Skip to content

Commit

Permalink
feat: wip
Browse files Browse the repository at this point in the history
  • Loading branch information
haoziqaq committed Dec 26, 2024
1 parent 2ba4de6 commit dadc1c5
Show file tree
Hide file tree
Showing 10 changed files with 75 additions and 39 deletions.
8 changes: 6 additions & 2 deletions packages/varlet-ui/src/checkbox-group/__tests__/index.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ test('test checkbox onClick & onChange', async () => {

await wrapper.find('.var-checkbox').trigger('click')
expect(onClick).toHaveBeenCalledTimes(1)
expect(onChange).lastCalledWith(true)
expect(onChange).lastCalledWith(true, false)

wrapper.unmount()
})
Expand Down Expand Up @@ -146,16 +146,20 @@ test('test checkbox readonly', async () => {
wrapper.unmount()
})

test('test checkbox indeterminate', () => {
test('test checkbox indeterminate', async () => {
const onChange = vi.fn()
const wrapper = mount(VarCheckbox, {
props: {
modelValue: false,
indeterminate: true,
onChange,
},
})

expect(wrapper.html()).toMatchSnapshot()

await wrapper.find('.var-checkbox').trigger('click')
expect(onChange).lastCalledWith(false, false)
wrapper.unmount()
})

Expand Down
11 changes: 8 additions & 3 deletions packages/varlet-ui/src/checkbox/Checkbox.vue
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,7 @@ export default defineComponent({
const { checkedValue, onChange } = props
value.value = changedValue
isIndeterminate.value = false
call(onChange, value.value)
call(onChange, value.value, isIndeterminate.value)
validateWithTrigger('onChange')
changedValue === checkedValue ? checkboxGroup?.onChecked(checkedValue) : checkboxGroup?.onUnchecked(checkedValue)
}
Expand All @@ -141,6 +139,13 @@ export default defineComponent({
return
}
if (isIndeterminate.value === true) {
isIndeterminate.value = false
call(props.onChange, value.value, isIndeterminate.value)
validateWithTrigger('onChange')
return
}
const maximum = checkboxGroup ? checkboxGroup.checkedCount.value >= Number(checkboxGroup.max.value) : false
if (!checked.value && maximum) {
Expand Down
2 changes: 1 addition & 1 deletion packages/varlet-ui/src/checkbox/docs/en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
| Event | Description | Arguments |
| --- | --- | --- |
| `click` | Triggered on Click | `e: Event` |
| `change` | Triggered on change | `value: any` |
| `change` | Triggered on change | `value: any, indeterminate: boolean` |

### Slots

Expand Down
2 changes: 1 addition & 1 deletion packages/varlet-ui/src/checkbox/docs/zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
| 事件名 | 说明 | 参数 |
| --- | --- | --- |
| `click` | 点击时触发 | `e: Event` |
| `change` | 状态变更时触发 | `value: any` |
| `change` | 状态变更时触发 | `value: any, indeterminate: boolean` |

### 插槽

Expand Down
2 changes: 1 addition & 1 deletion packages/varlet-ui/src/checkbox/props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export const props = {
},
rules: [Array, Function, Object] as PropType<any>,
onClick: defineListenerProp<(e: Event) => void>(),
onChange: defineListenerProp<(value: any) => void>(),
onChange: defineListenerProp<(value: any, indeterminate: boolean) => void>(),
'onUpdate:modelValue': defineListenerProp<(value: any) => void>(),
'onUpdate:indeterminate': defineListenerProp<(value: boolean) => void>(),
}
2 changes: 1 addition & 1 deletion packages/varlet-ui/src/menu-select/MenuChildren.vue
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
:option="option"
:ripple="option.ripple"
:disabled="option.disabled"
:highlight="highlightOptions.includes(option)"
:highlight="highlightOptions.some((_option) => _option.value === option.value)"
@key-arrow-x="handleArrowRight"
@mouseenter="handleMouseenter"
/>
Expand Down
83 changes: 54 additions & 29 deletions packages/varlet-ui/src/menu-select/MenuSelect.vue
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,11 @@ export default defineComponent({
components: { VarMenu, VarMenuOption, VarMenuChildren },
props,
setup(props) {
const show = useVModel(props, 'show')
const menu = ref<InstanceType<typeof VarMenu>>()
const menuOptionsRef = ref<HTMLElement>()
const menuChildren = ref<InstanceType<typeof VarMenuChildren>[]>()
const show = useVModel(props, 'show')
const enhancedOptions = computed(() => enhance(props.options))
const { menuOptions, length, bindMenuOptions } = useMenuOptions()
Expand All @@ -95,28 +96,26 @@ export default defineComponent({
optionProviders: () => menuOptions,
optionProvidersLength: () => length.value,
optionIsIndeterminate(optionProvider) {
const option = flattenOptions.value.find((option) => option.value === optionProvider.value.value)
if (!option) {
const enhancedOption = getEnhancedOption(optionProvider.value.value)
if (!enhancedOption) {
return false
}
const children = getOptionChildren(option) ?? []
const children = (enhancedOption._children ?? []).filter((option) => !option.disabled)
const selectedChildren = children.filter((option) => props.modelValue.includes(option.value))
return selectedChildren.length > 0 && selectedChildren.length < children.length
},
})
const flattenOptions = computed(() => flatten(props.options))
const highlightOptions = computed(() => {
const { multiple, modelValue } = props
if (multiple) {
return []
}
const selectedOption = flattenOptions.value.find((option) => option.value === modelValue)
const selectedOption = enhancedOptions.value.find((option) => option.value === modelValue)
const highlightOptions: MenuSelectOption[] = []
let parent = selectedOption?._parent
Expand All @@ -139,6 +138,14 @@ export default defineComponent({
useEventListener(() => window, 'keydown', handleKeydown)
function getEnhancedOption(value: any) {
return enhancedOptions.value.find((option) => option.value === value)
}
function getOptionProvider(value: any) {
return menuOptions.find((optionProvider) => optionProvider.value.value === value)
}
function getOptionChildren(option: MenuSelectOption) {
return option[props.childrenKey] as MenuSelectOption[] | undefined
}
Expand All @@ -148,51 +155,72 @@ export default defineComponent({
baseFlatten(options)
function baseFlatten(options: MenuSelectOption[], parent?: MenuSelectOption) {
function baseFlatten(options: MenuSelectOption[]) {
options.forEach((option) => {
flattenOptions.push(option)
const children = getOptionChildren(option)
if (children) {
baseFlatten(children)
}
})
}
return flattenOptions
}
function enhance(options: MenuSelectOption[]) {
function baseEnhance(options: MenuSelectOption[], parent?: MenuSelectOption) {
return options.map((option) => {
option = { ...option }
if (parent) {
option._parent = parent
}
flattenOptions.push(option)
const children = getOptionChildren(option)
if (children) {
baseFlatten(children, option)
const enhancedChildren = baseEnhance(children, option)
option[props.childrenKey] = enhancedChildren
option._children = flatten(enhancedChildren)
}
return option
})
}
return flattenOptions
return flatten(baseEnhance(options))
}
function onSelect(optionProvider: MenuOptionProvider) {
const { multiple, closeOnSelect } = props
const { value, selected } = optionProvider
const option = flattenOptions.value.find((option) => option.value === value.value)
const enhancedOption = getEnhancedOption(value.value)
if (option) {
const children = flatten(getOptionChildren(option) ?? [])
const relationChildrenValues = children.map((option) => option.value)
if (enhancedOption) {
const childrenValues = (enhancedOption._children ?? [])
.filter((option) => !option.disabled)
.map((option) => option.value)
if (multiple && selected.value) {
menuOptions.forEach((optionProvider) => {
if (relationChildrenValues.includes(optionProvider.value.value)) {
if (childrenValues.includes(optionProvider.value.value)) {
optionProvider.sync(true, false)
}
})
broadcastParentOption(option)
broadcastParentOption(enhancedOption)
}
if (multiple && !selected.value) {
menuOptions.forEach((optionProvider) => {
if (relationChildrenValues.includes(optionProvider.value.value)) {
if (childrenValues.includes(optionProvider.value.value)) {
optionProvider.sync(false, false)
}
})
broadcastParentOption(option)
broadcastParentOption(enhancedOption)
}
}
Expand All @@ -206,23 +234,20 @@ export default defineComponent({
}
}
function broadcastParentOption(option: MenuSelectOption) {
let parentOption = option._parent
function broadcastParentOption(enhancedOption: MenuSelectOption) {
let parentOption = enhancedOption._parent
while (parentOption) {
const parentOptionProvider = menuOptions.find(
(optionProvider) => optionProvider.value.value === parentOption!.value
)!
const parentOptionChildren = getOptionChildren(parentOption)!
const parentOptionProvider = getOptionProvider(parentOption.value)!
const parentOptionChildren = getOptionChildren(parentOption)!.filter((option) => !option.disabled)
const isAllChildrenUnselected = parentOptionChildren.every((option) => {
const optionProvider = menuOptions.find((optionProvider) => optionProvider.value.value === option.value)!
const optionProvider = getOptionProvider(option.value)!
return !optionProvider.selected.value
})
const isAllChildrenSelected = parentOptionChildren.every((option) => {
const optionProvider = menuOptions.find((optionProvider) => optionProvider.value.value === option.value)!
const optionProvider = getOptionProvider(option.value)!
return optionProvider.selected.value
})
Expand Down
1 change: 1 addition & 0 deletions packages/varlet-ui/src/menu-select/example/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ const cascadeOptions = ref([
{
label: '2-2-1',
value: 221,
disabled: true,
},
{
label: '2-2-2',
Expand Down
1 change: 1 addition & 0 deletions packages/varlet-ui/src/menu-select/props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export interface MenuSelectOption {
disabled?: boolean
ripple?: boolean
_parent?: MenuSelectOption
_children?: MenuSelectOption[]
[key: PropertyKey]: any
}

Expand Down
2 changes: 1 addition & 1 deletion packages/varlet-ui/types/checkbox.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export interface CheckboxProps extends BasicAttributes {
validateTrigger?: Array<CheckboxValidateTrigger>
rules?: CheckboxRules
onClick?: ListenerProp<(e: Event) => void>
onChange?: ListenerProp<(value: any) => void>
onChange?: ListenerProp<(value: any, indeterminate: boolean) => void>
'onUpdate:modelValue'?: ListenerProp<(value: any) => void>
'onUpdate:indeterminate'?: ListenerProp<(value: boolean) => void>
}
Expand Down

0 comments on commit dadc1c5

Please sign in to comment.