feat(split): supports setting the pixel value size (#5712)

* feat(n-split): supports setting the pixel value size

* feat: add docs

* fix: type

* feat: add docs

---------

Co-authored-by: 07akioni <07akioni2@gmail.com>
This commit is contained in:
jahnli 2024-03-11 18:18:52 +08:00 committed by GitHub
parent 966533e09c
commit b7f726dd58
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 62 additions and 27 deletions

View File

@ -44,6 +44,7 @@
- `n-date-picker` adds `default-calendar-start-time` props when `type` is `'date'`/`'datetime'` or `'week'`, closes [#4493](https://github.com/tusen-ai/naive-ui/issues/4493).
- `n-tree-select` adds `get-children` prop.
- `n-split` supports setting the pixel value size.
## 2.38.0

View File

@ -43,6 +43,7 @@
- `n-date-picker``type``'date'`、`'datetime'` 或 `'week'` 时新增 `default-calendar-start-time` 属性,关闭 [#4493](https://github.com/tusen-ai/naive-ui/issues/4493)
- `n-tree-select` 新增 `get-children` 属性
- `n-split` 支持设置像素值大小
## 2.38.0

View File

@ -21,19 +21,19 @@ controlled.vue
| Name | Type | Default | Description | Version |
| --- | --- | --- | --- | --- |
| default-size | `number` | `0.5` | Default split size, 0~1 is a percentage. | 2.36.0 |
| size | `number` | `undefined` | Split is the controlled split size, with 0~1 representing the percentage. | 2.38.0 |
| disabled | `boolean` | `false` | Whether to disable the split. | 2.36.0 |
| default-size | `string \| number` | `0.5` | Default split size, 0~1 is a percentage or pixel value. | 2.36.0 |
| direction | `'horizontal' \| 'vertical'` | `'horizontal'` | The direction of the split. | 2.36.0 |
| min | `number` | `0` | The minimum threshold for splitting, 0~1 is a percentage. | 2.36.0 |
| max | `number` | `1` | The maximum split threshold, 0~1 is a percentage. | 2.36.0 |
| disabled | `boolean` | `false` | Whether to disable the split. | 2.36.0 |
| max | `string \| number` | `1` | The maximum split threshold, 0~1 is a percentage or pixel value. | 2.36.0 |
| min | `string \| number` | `0` | The minimum threshold for splitting, 0~1 is a percentage or pixel value. | 2.36.0 |
| panel1-class | `string` | `undefined` | The class name of the first panel. | NEXT_VERSION |
| panel1-style | `Object \| string` | `undefined` | The Style of the first panel | NEXT_VERSION |
| panel2-class | `string` | `undefined` | The class name of the second panel. | NEXT_VERSION |
| panel2-style | `Object \| string` | `undefined` | The Style of the second panel | NEXT_VERSION |
| resize-trigger-size | `number` | `3` | Size of the resize trigger. | 2.36.0 |
| size | `string \| number` | `undefined` | Split is the controlled split size, with 0~1 representing the percentage or pixel value. | 2.38.0 |
| watch-props | `Array<'defaultSize'>` | `undefined` | Default prop names that needed to be watched. Components will be updated after the prop is changed. Note: the `watch-props` itself is not reactive. | 2.38.0 |
| on-update:size | `(value: number) => void` | `undefined` | Callback fired on size changes. | 2.38.0 |
| on-update:size | `(value: string \| number) => void` | `undefined` | Callback fired on `size` changes. | 2.38.0 |
### Split Slots

View File

@ -21,19 +21,19 @@ controlled.vue
| 名称 | 类型 | 默认值 | 说明 | 版本 |
| --- | --- | --- | --- | --- |
| default-size | `number` | `0.5` | Split 的默认分割大小0~1 代表百分比 | 2.36.0 |
| size | `number` | `undefined` | Split 的受控分割大小0~1 代表百分比 | 2.38.0 |
| disabled | `boolean` | `false` | 是否禁用 | 2.36.0 |
| default-size | `string \| number` | `0.5` | Split 的默认分割大小0~1 代表百分比或像素值 | 2.36.0 |
| direction | `'horizontal' \| 'vertical'` | `'horizontal'` | Split 的分割方向 | 2.36.0 |
| min | `number` | `0` | Split 的分割最小阈值0~1 代表百分比 | 2.36.0 |
| max | `number` | `1` | Split 的分割最大阈值0~1 代表百分比 | 2.36.0 |
| disabled | `boolean` | `false` | 是否禁用 | 2.36.0 |
| max | `string \| number` | `1` | Split 的分割最大阈值0~1 代表百分比或像素值 | 2.36.0 |
| min | `string \| number` | `0` | Split 的分割最小阈值0~1 代表百分比或像素值 | 2.36.0 |
| panel1-class | `string` | `undefined` | 第一个面板的类名 | NEXT_VERSION |
| panel1-style | `Object \| string` | `undefined` | 第一个面板的样式 | NEXT_VERSION |
| panel2-class | `string` | `undefined` | 第二个面板的类名 | NEXT_VERSION |
| panel2-style | `Object \| string` | `undefined` | 第二个面板的样式 | NEXT_VERSION |
| resize-trigger-size | `number` | `3` | Split 的分隔条大小 | 2.36.0 |
| size | `string \| number` | `undefined` | Split 的受控分割大小0~1 代表百分比或像素值 | 2.38.0 |
| watch-props | `Array<'defaultSize'>` | `undefined` | 需要检测变更的默认属性,检测后组件状态会更新。注意:`watch-props` 本身不是响应式的 | 2.38.0 |
| on-update:size | `(value: number) => void` | `undefined` | 组件 size 属性变化时触发的回调 | 2.38.0 |
| on-update:size | `(value: string \| number) => void` | `undefined` | 组件 `size` 属性变化时触发的回调 | 2.38.0 |
### Split Slots

View File

@ -29,7 +29,7 @@ export const splitProps = {
},
disabled: Boolean,
defaultSize: {
type: Number,
type: [String, Number] as PropType<string | number>,
default: 0.5
},
'onUpdate:size': [Function, Array] as PropType<
@ -38,13 +38,13 @@ export const splitProps = {
onUpdateSize: [Function, Array] as PropType<
SplitOnUpdateSize | SplitOnUpdateSize[]
>,
size: Number,
size: [String, Number] as PropType<string | number>,
min: {
type: Number,
type: [String, Number] as PropType<string | number>,
default: 0
},
max: {
type: Number,
type: [String, Number] as PropType<string | number>,
default: 1
},
panel1Class: String,
@ -92,17 +92,32 @@ export default defineComponent({
watchEffect(() => (uncontrolledSizeRef.value = props.defaultSize))
}
// use to update controlled or uncontrolled values
const doUpdateSize = (size: number): void => {
const doUpdateSize = (size: number, containerSize: number): void => {
const sizeValue =
typeof props.size === 'string' ? `${size * containerSize}px` : size
const _onUpdateSize = props['onUpdate:size']
if (props.onUpdateSize) call(props.onUpdateSize, size)
if (_onUpdateSize) call(_onUpdateSize, size)
if (props.onUpdateSize) call(props.onUpdateSize, sizeValue)
if (_onUpdateSize) call(_onUpdateSize, sizeValue)
uncontrolledSizeRef.value = size
}
const mergedSizeRef = useMergedState(controlledSizeRef, uncontrolledSizeRef)
const isPixel = computed(() => typeof mergedSizeRef.value === 'string')
const firstPaneStyle = computed(() => {
const size = mergedSizeRef.value * 100
return {
flex: `0 0 calc(${size}% - ${(props.resizeTriggerSize * size) / 100}px)`
const sizeValue = mergedSizeRef.value
if (isPixel.value) {
const size = parseFloat(sizeValue as string)
return {
flex: `0 0 ${size}px`
}
} else if (typeof sizeValue === 'number') {
const size = sizeValue * 100
return {
flex: `0 0 calc(${size}% - ${
(props.resizeTriggerSize * size) / 100
}px)`
}
}
})
@ -158,28 +173,46 @@ export default defineComponent({
offset = elRect.top - e.clientY
}
}
updateSize(e)
}
const parseSizeValue = (
value: string | number,
parentSize: number
): number => {
if (typeof value === 'string' && value.endsWith('px')) {
return parseFloat(value) / parentSize
} else {
const numericValue = value as number
return numericValue >= 0 && numericValue <= 1
? numericValue
: numericValue / 100
}
}
const updateSize = (event: MouseEvent): void => {
const parentRect =
resizeTriggerElRef.value?.parentElement?.getBoundingClientRect()
if (!parentRect) return
const newSize =
props.direction === 'horizontal'
? (event.clientX - parentRect.left - offset) /
(parentRect.width - props.resizeTriggerSize)
: (event.clientY - parentRect.top + offset) /
(parentRect.height - props.resizeTriggerSize)
const containerSize =
props.direction === 'horizontal' ? parentRect.width : parentRect.height
const min = parseSizeValue(props.min, containerSize)
const max = parseSizeValue(props.max, containerSize)
let nextSize = newSize
if (props.min) {
nextSize = Math.max(newSize, props.min)
nextSize = Math.max(newSize, min)
}
if (props.max) {
nextSize = Math.min(nextSize, props.max)
nextSize = Math.min(nextSize, max)
}
doUpdateSize(nextSize)
doUpdateSize(nextSize, containerSize)
}
const themeClassHandle = inlineThemeDisabled

View File

@ -1 +1 @@
export type SplitOnUpdateSize = (size: number) => void
export type SplitOnUpdateSize = (size: string | number) => void