From aaaf3cbc19d9c74dcf8bd738c53f29716c1d02c2 Mon Sep 17 00:00:00 2001 From: baiwusanyu-c <740132583@qq.com> Date: Tue, 14 Jan 2025 14:25:50 +0800 Subject: [PATCH 1/7] fix: Properly adjust the disabled backgrpund of the KMenu component --- components/Menu/src/item.svelte | 5 +++-- preset/src/shortcuts/src/menu.ts | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/components/Menu/src/item.svelte b/components/Menu/src/item.svelte index 42059a55..f76cbc1e 100644 --- a/components/Menu/src/item.svelte +++ b/components/Menu/src/item.svelte @@ -474,8 +474,9 @@ }; if (it.disabled || it.disabledParent) { basicCls = { - [`${prefixCls}-disabled`]: true, - [`${prefixCls}-disabled__dark`]: isDark(it) + [`${prefixCls}-disabled`]: level !== 1, + [`${prefixCls}-disabled__dark`]: isDark(it), + [`${prefixCls}-disabled-l1`]: level === 1 }; if (hasSub(it)) { it.children = it.children!.map((item) => { diff --git a/preset/src/shortcuts/src/menu.ts b/preset/src/shortcuts/src/menu.ts index d2f9bd42..13194d84 100644 --- a/preset/src/shortcuts/src/menu.ts +++ b/preset/src/shortcuts/src/menu.ts @@ -46,7 +46,8 @@ export const menuShortcuts: Record = { 'fcc pr h-40px leading-40px list-inside ps-16px p-ie-16px m-is-4px m-ie-4px my-4px ' + 'rounded-8px', 'k-menu-item-active': 'active:(ikun:20:bg-ikun-main)', - 'k-menu-item-disabled': 'k-bg-disabled k-cur-disabled', + 'k-menu-item-disabled': 'k-bg-disabled k-cur-disabled text-ikun-info', + 'k-menu-item-disabled-l1': 'k-cur-disabled text-ikun-info', 'k-menu-item-horizontal-not-top': 'k-menu-item-horizontal fbc', 'k-menu-item-horizontal-group': 'k-menu-w k-menu-transition ' + From c71fb4617c957fb77036295c21528050ec24a69c Mon Sep 17 00:00:00 2001 From: baiwusanyu-c <740132583@qq.com> Date: Tue, 14 Jan 2025 14:37:42 +0800 Subject: [PATCH 2/7] docs: init KMenu document --- .../components/demo-block/src/index.vue | 5 + docs/.vitepress/config.ts | 4 + docs/components/KMenu.md | 131 ++++++++++++++++++ docs/example/menu/horizontal.svelte | 56 ++++++++ 4 files changed, 196 insertions(+) create mode 100644 docs/components/KMenu.md create mode 100644 docs/example/menu/horizontal.svelte diff --git a/docs/.vitepress/components/demo-block/src/index.vue b/docs/.vitepress/components/demo-block/src/index.vue index 1fcd5511..90126a0a 100644 --- a/docs/.vitepress/components/demo-block/src/index.vue +++ b/docs/.vitepress/components/demo-block/src/index.vue @@ -123,6 +123,11 @@ const handleCopy = () => { padding: 0; } +.vp-doc ul.k-menu{ + padding: 0; + margin: 0; +} + .vp-doc li.k-timeline-item{ margin-top: 0; } diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts index 549853ef..eb4b5815 100644 --- a/docs/.vitepress/config.ts +++ b/docs/.vitepress/config.ts @@ -212,6 +212,10 @@ const components = [ text: 'Dropdown', link: '/components/KDropdown' }, + { + text: 'Menu', + link: '/components/KMenu' + }, { text: 'Segmented', link: '/components/KSegmented' diff --git a/docs/components/KMenu.md b/docs/components/KMenu.md new file mode 100644 index 00000000..dd8905b6 --- /dev/null +++ b/docs/components/KMenu.md @@ -0,0 +1,131 @@ +--- +title: KMenu +lang: en-US +--- + +# KMenu + +A versatile menu for navigation. + +## Install + +::: code-group + +```bash [pnpm] +pnpm add @ikun-ui/menu +``` + +```bash [yarn] +yarn add @ikun-ui/menu +``` + +```bash [npm] +npm install @ikun-ui/menu +``` + +::: + +## Basic usage + +Horizontal top navigation menu. + + + +## Prefix icon and suffix icon input + +Set the prefix through the `icon` attribute + + + +## Disabled input + +Disable the input through the `disabled` attribute + + + +## Clearable + +Make the Input clearable with the `clearable` attribute. + + + +## Password input + +Enable the password input box and pass the `type` as `password`. + + + +## Prepend and append input + +Use the `append` or `prepend` attribute to enable a button + + + +## Search input + +Quickly implement a search box + +::: tip +When search is `true` and you press `enter` or click the `prepend` button or click the `append` button, the event will be triggered. +In this case, the `triggerPrepend` event, `triggerPrepend` event and `enter` event will not be triggered. +::: + + + +## Sizes + +Add `size` attribute to change the size of Input. It supports `sm`, `md` and `lg`. + + + +## Textarea + +Setting the `autosize` prop for a textarea type of Input makes the height to automatically adjust based on the content. +An options object can be provided to `autosize` to specify the minimum and maximum number of lines the textarea can automatically adjust. + + + +## Input Props + +| Name | Type | Default | Description | +| ------------------- | ------------------------------------------------ | ------- | ------------------------------------------------------------------------------ | +| size | `sm \| md \|lg` | `md` | size of Input. | +| type | `text \| password` | `text` | Determine whether it is a password input | +| value | `string` | `-` | Binding value | +| iconPrefix | `string` | `-` | The class name of the prefix icon, following the unocss standard | +| iconSuffix | `string` | `-` | The class name of the suffix icon, following the unocss standard | +| append | `string` | `-` | The class name of the append button icon, following the unocss standard | +| prepend | `string` | `-` | The class name of the prepend button icon, following the unocss standard | +| placeholder | `string` | `false` | Input's placeholder | +| disabled | `boolean` | `false` | Disable the Input | +| clearable | `boolean` | `false` | whether to show clear button, only works when type is not 'textarea' | +| search | `boolean` | `false` | Enable `search` callback | +| useCompositionInput | `boolean` | `false` | Bind value will be updated after the composition input ends | +| rows | `number` | `3` | number of rows of `textarea`, only works when type is 'textarea' | +| autosize | `boolean \| { minRows: number: maxRows:number }` | `false` | whether `textarea` has an adaptive height, only works when type is 'textarea'. | +| cls | `string` | `-` | Additional class | +| attrs | `Record` | `{}` | Additional attributes | + +## Input Events + +| Name | Description | Type | +| ---------------- | ---------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------- | +| input | Event fired on input | `(value: string)=> void` | +| enter | Event fired when `enter` is pressed | `(e: Event)=> void` | +| keydown | Event fired when `keyboard` is pressed | `(e: Event)=> void` | +| change | Event fired when the `value` is changes | `(e: Event)=> void` | +| compositionstart | The compositionstart event is fired when a text composition system | `(e: CompositionEvent)=> void` | +| compositionend | The compositionend event is fired when a text composition system | `(e: CompositionEvent)=> void` | +| compositionInput | Event fired when enable `useCompositionInput` | `(e: CompositionEvent)=> void` | +| triggerPrepend | Event fired on prepend button | `(value: HTMLInputElement.value)=> void` | +| triggerAppend | Event fired on append button | `(value: HTMLInputElement.value)=> void` | +| search | When search is true and you press `enter` or click the `prepend` button or click the `append` button, the event will be triggered. | `(value: HTMLInputElement.value)=> void` | + +## Input Slots + +| Name | Description | +| ------- | ------------------------------- | +| prefix | Customize input prefix content | +| suffix | Customize input suffix content | +| append | Customize input append content | +| prepend | Customize input prepend content | diff --git a/docs/example/menu/horizontal.svelte b/docs/example/menu/horizontal.svelte new file mode 100644 index 00000000..a6aca5a8 --- /dev/null +++ b/docs/example/menu/horizontal.svelte @@ -0,0 +1,56 @@ + + + + + From 6c64b84e33ac48d90db0c33a997b5f093a910c3f Mon Sep 17 00:00:00 2001 From: baiwusanyu-c <740132583@qq.com> Date: Fri, 17 Jan 2025 17:21:09 +0800 Subject: [PATCH 3/7] feat: KMenu component added mutiple props --- components/Menu/src/item.svelte | 58 +++++++++++++++++++++++++---- docs/example/menu/horizontal.svelte | 12 +++++- 2 files changed, 61 insertions(+), 9 deletions(-) diff --git a/components/Menu/src/item.svelte b/components/Menu/src/item.svelte index f76cbc1e..9179fe21 100644 --- a/components/Menu/src/item.svelte +++ b/components/Menu/src/item.svelte @@ -121,9 +121,7 @@ } function handleSelectedRecursion( - e: - | CustomEvent<{ selected: boolean; uid: string }> - | { detail: { selected: boolean; uid: string } }, + e: CustomEvent<{ selected: boolean; uid: string; isLeaf: boolean; item: SubMenuType }>, index: number ) { const { selected, uid } = e.detail; @@ -138,6 +136,19 @@ it.selected = !!it.selectedDeps.size; + // 重置当前点击层所在树的其他项选择状态 + if (!ctxProps.multiple && it.selected && itemsList[index]) { + itemsList = cancelSelected(itemsList, it); + } + + // 到第一层时如果是单选,则遍历取消其他项的选择状态 + if (!ctxProps.multiple && level === 1 && e.detail.isLeaf && itemsList[index]) { + itemsList = cancelSelected(itemsList, it); + } + if (!ctxProps.multiple && level === 1 && e.detail.isLeaf && !itemsList[index]) { + itemsList = cancelSelected(itemsList, e.detail.item); + } + if (itemsList[index]) { itemsList[index] = it; } else { @@ -145,19 +156,47 @@ } dispatch('selectedRecursion', { selected: it.selected, - uid: it.uid + uid: it.uid, + isLeaf: e.detail.isLeaf, + item: it }); } else { dispatch('selectedRecursion', e.detail); } } + function cancelSelected(list: SubMenuType[], it: SubMenuType) { + return list.map((value) => { + if (!ctxProps.multiple && value.uid !== it.uid && !isGroup(it)) { + value.selected = false; + value.selectedDeps && value.selectedDeps.clear(); + menuCtx.syncUids(value.uid!, 'selected', 'delete'); + menuCtx.syncSelectedItems(value, 'delete'); + if (hasSub(value)) { + value.children = cancelSelected(value.children!, it); + } + } + return value; + }); + } + function setOpenAndSelectStatus(it: SubMenuType, list = itemsList, parentOpen?: boolean) { return list.map((value) => { if (value.uid === it.uid && !isGroup(it)) { // set selected - if (ctxProps.selectable) { - value.selected = !value.selected; + const resolveSelected = !value.selected; + if (ctxProps.selectable && !hasSub(it)) { + // 重置当前点击层其他项选择状态 + if (!ctxProps.multiple && resolveSelected && !hasSub(it)) { + list = cancelSelected(list, it); + + if (moreItem.children && moreItem.children.length > 0) { + moreItem.children = cancelSelected(moreItem.children, it); + moreItem.selected = false; + moreItem.selectedDeps && moreItem.selectedDeps.clear(); + } + } + value.selected = resolveSelected; } // set open @@ -182,7 +221,9 @@ */ dispatch('selectedRecursion', { selected: value.selected, - uid: value.uid + uid: value.uid, + isLeaf: !hasSub(value), + item: value }); } } @@ -1072,3 +1113,6 @@ {/if} + + + diff --git a/docs/example/menu/horizontal.svelte b/docs/example/menu/horizontal.svelte index a6aca5a8..a244afbb 100644 --- a/docs/example/menu/horizontal.svelte +++ b/docs/example/menu/horizontal.svelte @@ -20,8 +20,16 @@ uid: 'SubMenu Item 1', label: 'Item 1', children: [ - { label: 'Option 1', uid: 'setting:1', disabled: true }, - { label: 'Option 2', uid: 'setting:2' } + { label: 'Option 1', uid: 'setting:1-g', disabled: true }, + { label: 'Option 3', uid: 'setting:3-g' }, + { + label: 'Option 2', + uid: 'setting:2-g', + children: [ + { label: 'Option 2 - c1', uid: 'etting:2c1' }, + { label: 'Option 2 - c2', uid: 'etting:2c2' } + ] + } ] }, { From 808cef285993644be2143efd32ed330dc88b7b70 Mon Sep 17 00:00:00 2001 From: baiwusanyu-c <740132583@qq.com> Date: Fri, 17 Jan 2025 18:25:05 +0800 Subject: [PATCH 4/7] fix: KMenu component in non-horizontal mode single selection does not take effect --- components/Menu/src/item.svelte | 27 ++++++++++++++++----------- docs/example/menu/horizontal.svelte | 12 +++--------- 2 files changed, 19 insertions(+), 20 deletions(-) diff --git a/components/Menu/src/item.svelte b/components/Menu/src/item.svelte index 9179fe21..5ef0bd20 100644 --- a/components/Menu/src/item.svelte +++ b/components/Menu/src/item.svelte @@ -137,16 +137,21 @@ it.selected = !!it.selectedDeps.size; // 重置当前点击层所在树的其他项选择状态 - if (!ctxProps.multiple && it.selected && itemsList[index]) { - itemsList = cancelSelected(itemsList, it); - } - - // 到第一层时如果是单选,则遍历取消其他项的选择状态 - if (!ctxProps.multiple && level === 1 && e.detail.isLeaf && itemsList[index]) { - itemsList = cancelSelected(itemsList, it); - } - if (!ctxProps.multiple && level === 1 && e.detail.isLeaf && !itemsList[index]) { - itemsList = cancelSelected(itemsList, e.detail.item); + if (!ctxProps.multiple && e.detail.isLeaf) { + if (it.selected && itemsList[index]) { + itemsList = cancelSelected(itemsList, it); + if (hasSub(it)) { + it.children = cancelSelected(it.children!, e.detail.item); + } + } + if (level === 1) { + // 到第一层时如果是单选,则遍历取消其他项的选择状态 + if (itemsList[index]) { + itemsList = cancelSelected(itemsList, it); + } else { + itemsList = cancelSelected(itemsList, e.detail.item); + } + } } if (itemsList[index]) { @@ -187,7 +192,7 @@ const resolveSelected = !value.selected; if (ctxProps.selectable && !hasSub(it)) { // 重置当前点击层其他项选择状态 - if (!ctxProps.multiple && resolveSelected && !hasSub(it)) { + if (!ctxProps.multiple && resolveSelected) { list = cancelSelected(list, it); if (moreItem.children && moreItem.children.length > 0) { diff --git a/docs/example/menu/horizontal.svelte b/docs/example/menu/horizontal.svelte index a244afbb..1b35e762 100644 --- a/docs/example/menu/horizontal.svelte +++ b/docs/example/menu/horizontal.svelte @@ -37,8 +37,8 @@ label: 'Item 2', uid: 'SubMenu Item 2', children: [ - { label: 'Option 3', uid: 'setting:3' }, - { label: 'Option 4', uid: 'setting:4' } + { label: 'Option 3 Item 2', uid: 'setting:3' }, + { label: 'Option 4 Item 2', uid: 'setting:4' } ] } ] @@ -53,12 +53,6 @@ }; - + From b196ebfa4c06bc346aff595403c393358913a48b Mon Sep 17 00:00:00 2001 From: baiwusanyu-c <740132583@qq.com> Date: Mon, 20 Jan 2025 10:45:59 +0800 Subject: [PATCH 5/7] style: KMenu component spacing style optimization --- components/Menu/src/item.svelte | 7 +++---- .../components/demo-block/src/index.vue | 6 ++++++ preset/src/shortcuts/src/menu.ts | 18 ++++++++++-------- 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/components/Menu/src/item.svelte b/components/Menu/src/item.svelte index 5ef0bd20..f4e98c09 100644 --- a/components/Menu/src/item.svelte +++ b/components/Menu/src/item.svelte @@ -246,7 +246,7 @@ return value; }); } - async function handleSelect(it: SubMenuType, e: MouseEvent) { + async function handleSelect(it: SubMenuType, e: MouseEvent, index: number) { if (it.disabled || it.disabledParent) return; itemsList = setOpenAndSelectStatus(it); if (menuCtx) { @@ -276,6 +276,7 @@ } else { menuCtx.onDeSelect(params); } + popoverRef[index] && popoverRef[index].updateShow && popoverRef[index].updateShow(false); } else if (hasSub(it) || isGroup(it)) { dispatchTitleClick(it, e, uidPath); } @@ -950,7 +951,7 @@ {#if it.type !== 'divider'}
  • handleSelect(it, e)} + on:click={(e) => handleSelect(it, e, index)} aria-hidden="true" style:padding-left={`${getIndent(it, ctxProps.inlineCollapsed)}`} class={cnames(it)} @@ -1119,5 +1120,3 @@ {/if} - - diff --git a/docs/.vitepress/components/demo-block/src/index.vue b/docs/.vitepress/components/demo-block/src/index.vue index 90126a0a..d28d1e7f 100644 --- a/docs/.vitepress/components/demo-block/src/index.vue +++ b/docs/.vitepress/components/demo-block/src/index.vue @@ -128,6 +128,12 @@ const handleCopy = () => { margin: 0; } +.vp-doc ul.k-menu-horizontal.k-menu-sub-horizontal, +.vp-doc ul.k-menu-vertical.k-menu-sub-vertical{ + padding-top: 2px; + padding-bottom: 2px; +} + .vp-doc li.k-timeline-item{ margin-top: 0; } diff --git a/preset/src/shortcuts/src/menu.ts b/preset/src/shortcuts/src/menu.ts index 13194d84..f998845a 100644 --- a/preset/src/shortcuts/src/menu.ts +++ b/preset/src/shortcuts/src/menu.ts @@ -30,20 +30,22 @@ export const menuShortcuts: Record = { 'k-menu-item-child': 'justify-between', - 'k-menu-vertical': 'bdr-1 b-e-solid border-ikun-bd-base overflow-hidden', - 'k-menu-item-popover-trigger-vertical': 'box-border my-4px', - 'k-menu-item-vertical': 'k-menu-item-inline my-0', + 'k-menu-vertical': + 'bdr-1 b-e-solid border-ikun-bd-base overflow-hidden [&.k-menu-sub-vertical]:py-[2px]', + 'k-menu-item-popover-trigger-vertical': 'box-border', + 'k-menu-item-vertical': 'k-menu-item-inline my-[2px]', 'k-menu-item-vertical-group': 'k-menu-w k-menu-transition ' + 'flex items-center pr h-40px leading-40px list-inside ps-16px p-ie-16px m-is-4px m-ie-4px ' + 'rounded-8px ikun:50:text-black', - 'k-menu-horizontal': 'bdb-1 b-solid border-ikun-bd-base flex [&.k-menu-sub-horizontal]:block', - 'k-menu-item-popover-trigger-horizontal': 'box-border my-4px', + 'k-menu-horizontal': + 'bdb-1 b-solid border-ikun-bd-base flex [&.k-menu-sub-horizontal]:block [&.k-menu-sub-horizontal]:py-[2px]', + 'k-menu-item-popover-trigger-horizontal': 'box-border', 'k-menu-item-popover-content': 'p-0 box-border', 'k-menu-item-horizontal': 'cursor-pointer k-menu-w k-menu-transition ' + - 'fcc pr h-40px leading-40px list-inside ps-16px p-ie-16px m-is-4px m-ie-4px my-4px ' + + 'fcc pr h-40px leading-40px list-inside ps-16px p-ie-16px m-is-4px m-ie-4px my-2px ' + 'rounded-8px', 'k-menu-item-active': 'active:(ikun:20:bg-ikun-main)', 'k-menu-item-disabled': 'k-bg-disabled k-cur-disabled text-ikun-info', @@ -59,11 +61,11 @@ export const menuShortcuts: Record = { 'k-menu-inline': 'bdr-1 b-e-solid border-ikun-bd-base overflow-hidden', 'k-menu-item-inline': 'cursor-pointer k-menu-w k-menu-transition ' + - 'flex items-center pr h-40px leading-40px list-inside ps-16px p-ie-16px m-is-4px m-ie-4px my-4px ' + + 'flex items-center pr h-40px leading-40px list-inside ps-16px p-ie-16px m-is-4px m-ie-4px my-2px ' + 'rounded-8px', 'k-menu-item-inline-group': 'k-menu-w k-menu-transition ' + - 'flex items-center pr h-40px leading-40px list-inside ps-16px p-ie-16px m-is-4px m-ie-4px my-4px ' + + 'flex items-center pr h-40px leading-40px list-inside ps-16px p-ie-16px m-is-4px m-ie-4px my-2px ' + 'rounded-8px ikun:50:text-black', // dark From 624d663cd713d5af559ead14e6f219b0c6b823a9 Mon Sep 17 00:00:00 2001 From: baiwusanyu-c <740132583@qq.com> Date: Mon, 20 Jan 2025 11:22:54 +0800 Subject: [PATCH 6/7] fix: KMenu component single-select mode does not close the popover when clicked --- components/Menu/src/index.svelte | 2 +- components/Menu/src/item.svelte | 10 ++++++++-- docs/example/menu/horizontal.svelte | 21 ++++++++++++++------- 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/components/Menu/src/index.svelte b/components/Menu/src/index.svelte index 000a7dd1..26d0e211 100644 --- a/components/Menu/src/index.svelte +++ b/components/Menu/src/index.svelte @@ -15,7 +15,7 @@ export let selectedUids: KMenuProps['selectedUids'] = []; export let openUids: KMenuProps['openUids'] = []; export let show: KMenuProps['show'] = true; - export let multiple: KMenuProps['multiple'] = true; + export let multiple: KMenuProps['multiple'] = false; export let selectable: KMenuProps['selectable'] = true; export let inlineCollapsed: KMenuProps['inlineCollapsed'] = false; export let ctxKey: KMenuProps['ctxKey'] = ''; diff --git a/components/Menu/src/item.svelte b/components/Menu/src/item.svelte index f4e98c09..a33f3e98 100644 --- a/components/Menu/src/item.svelte +++ b/components/Menu/src/item.svelte @@ -168,6 +168,7 @@ } else { dispatch('selectedRecursion', e.detail); } + onSubItemSelect(index); } function cancelSelected(list: SubMenuType[], it: SubMenuType) { @@ -246,7 +247,7 @@ return value; }); } - async function handleSelect(it: SubMenuType, e: MouseEvent, index: number) { + async function handleSelect(it: SubMenuType, e: MouseEvent) { if (it.disabled || it.disabledParent) return; itemsList = setOpenAndSelectStatus(it); if (menuCtx) { @@ -276,7 +277,6 @@ } else { menuCtx.onDeSelect(params); } - popoverRef[index] && popoverRef[index].updateShow && popoverRef[index].updateShow(false); } else if (hasSub(it) || isGroup(it)) { dispatchTitleClick(it, e, uidPath); } @@ -677,6 +677,12 @@ if (it.disabled || it.disabledParent || e.detail) return; itemsList = clearVerticalOpenStatus(it); } + + function onSubItemSelect(index: number) { + if (level == 1 && !ctxProps.multiple) { + popoverRef[index] && popoverRef[index].updateShow && popoverRef[index].updateShow(false); + } + } {#each itemsList as it, index (it.uid)} diff --git a/docs/example/menu/horizontal.svelte b/docs/example/menu/horizontal.svelte index 1b35e762..7f0af883 100644 --- a/docs/example/menu/horizontal.svelte +++ b/docs/example/menu/horizontal.svelte @@ -21,13 +21,13 @@ label: 'Item 1', children: [ { label: 'Option 1', uid: 'setting:1-g', disabled: true }, - { label: 'Option 3', uid: 'setting:3-g' }, + { label: 'Option 2', uid: 'setting:2-g' }, { - label: 'Option 2', - uid: 'setting:2-g', + label: 'Option 3', + uid: 'setting:3-g', children: [ - { label: 'Option 2 - c1', uid: 'etting:2c1' }, - { label: 'Option 2 - c2', uid: 'etting:2c2' } + { label: 'Option 3 - c1', uid: 'etting:3c1' }, + { label: 'Option 3 - c2', uid: 'etting:3c2' } ] } ] @@ -37,8 +37,15 @@ label: 'Item 2', uid: 'SubMenu Item 2', children: [ - { label: 'Option 3 Item 2', uid: 'setting:3' }, - { label: 'Option 4 Item 2', uid: 'setting:4' } + { + label: 'Option 4', + uid: 'setting:3', + children: [ + { label: 'Option 4 - c1', uid: 'etting:4c1' }, + { label: 'Option 4 - c2', uid: 'etting:4c2' } + ] + }, + { label: 'Option 5 Item 2', uid: 'setting:5' } ] } ] From 50e6eb02f21474684b4bb877c72dc73642be259b Mon Sep 17 00:00:00 2001 From: baiwusanyu-c <740132583@qq.com> Date: Mon, 20 Jan 2025 18:30:25 +0800 Subject: [PATCH 7/7] docs: added KMenu component English document --- .../__test__/__snapshots__/menu.spec.ts.snap | 6 +- .../Menu/__test__/fixture/open-change.svelte | 3 + .../Menu/__test__/fixture/select.svelte | 3 + components/Menu/src/item.svelte | 13 +- components/Menu/src/types.d.ts | 116 ++++--- components/Menu/src/utils.ts | 8 + docs/components/KMenu.md | 282 +++++++++++++----- docs/example/menu/collapsed.svelte | 79 +++++ docs/example/menu/custom.svelte | 76 +++++ docs/example/menu/horizontal.svelte | 7 +- docs/example/menu/inline.svelte | 70 +++++ docs/example/menu/item-slot.svelte | 79 +++++ docs/example/menu/theme.svelte | 76 +++++ docs/example/menu/type.svelte | 90 ++++++ docs/example/menu/vertical.svelte | 70 +++++ 15 files changed, 825 insertions(+), 153 deletions(-) create mode 100644 docs/example/menu/collapsed.svelte create mode 100644 docs/example/menu/custom.svelte create mode 100644 docs/example/menu/inline.svelte create mode 100644 docs/example/menu/item-slot.svelte create mode 100644 docs/example/menu/theme.svelte create mode 100644 docs/example/menu/type.svelte create mode 100644 docs/example/menu/vertical.svelte diff --git a/components/Menu/__test__/__snapshots__/menu.spec.ts.snap b/components/Menu/__test__/__snapshots__/menu.spec.ts.snap index 5efd329b..323d118a 100644 --- a/components/Menu/__test__/__snapshots__/menu.spec.ts.snap +++ b/components/Menu/__test__/__snapshots__/menu.spec.ts.snap @@ -126,15 +126,15 @@ exports[`Test: KMenuItems > props: items - children & inline 1`] = `"
    props: items - children & vertical 1`] = `"
    "`; -exports[`Test: KMenuItems > props: items - danger & horizontal 1`] = `"
    1
    [["SubMenu","asda","setting:1","setting:3333"]]
    "`; +exports[`Test: KMenuItems > props: items - danger & horizontal 1`] = `"
    1
    [["SubMenu","asda","setting:1","setting:3333"]]
    "`; exports[`Test: KMenuItems > props: items - danger & inline 1`] = `"
    1
    [["SubMenu","asda","setting:1","setting:3333"]]
    "`; exports[`Test: KMenuItems > props: items - danger & vertical 1`] = `"
    1
    [["SubMenu","asda","setting:1","setting:3333"]]
    "`; -exports[`Test: KMenuItems > props: items - disabled & horizontal 1`] = `"
    1
    [["SubMenu","asda","setting:1","setting:3333"]]
    "`; +exports[`Test: KMenuItems > props: items - disabled & horizontal 1`] = `"
    1
    [["SubMenu","asda","setting:1","setting:3333"]]
    "`; -exports[`Test: KMenuItems > props: items - disabled & horizontal 2`] = `"
    1
    [["SubMenu","asda","setting:1","setting:3333"]]
    "`; +exports[`Test: KMenuItems > props: items - disabled & horizontal 2`] = `"
    1
    [["SubMenu","asda","setting:1","setting:3333"]]
    "`; exports[`Test: KMenuItems > props: items - disabled & inline 1`] = `"
    1
    [["SubMenu","asda","setting:1","setting:3333"]]
    "`; diff --git a/components/Menu/__test__/fixture/open-change.svelte b/components/Menu/__test__/fixture/open-change.svelte index a9b7b10e..ef67e123 100644 --- a/components/Menu/__test__/fixture/open-change.svelte +++ b/components/Menu/__test__/fixture/open-change.svelte @@ -84,6 +84,7 @@ mode="vertical" id="open_change_test_vertical" on:openChange={handleClick} + multiple={true} triggerSubMenuAction="click" ctxKey="11" > @@ -92,6 +93,7 @@ diff --git a/components/Menu/__test__/fixture/select.svelte b/components/Menu/__test__/fixture/select.svelte index 9fef55cf..7d808519 100644 --- a/components/Menu/__test__/fixture/select.svelte +++ b/components/Menu/__test__/fixture/select.svelte @@ -84,6 +84,7 @@ mode="vertical" id="select_test_vertical" on:deSelect={handleClick} + multiple={true} on:select={handleClick} triggerSubMenuAction="click" ctxKey="11" @@ -95,6 +96,7 @@ id="select_test_inline" triggerSubMenuAction="click" on:deSelect={handleClick} + multiple={true} on:select={handleClick} ctxKey="22" > @@ -105,6 +107,7 @@ id="select_test_horizontal" triggerSubMenuAction="click" on:deSelect={handleClick} + multiple={true} on:select={handleClick} ctxKey="22" > diff --git a/components/Menu/src/item.svelte b/components/Menu/src/item.svelte index a33f3e98..e8968981 100644 --- a/components/Menu/src/item.svelte +++ b/components/Menu/src/item.svelte @@ -137,6 +137,7 @@ it.selected = !!it.selectedDeps.size; // 重置当前点击层所在树的其他项选择状态 + // Reset the selection status of other items in the tree where the current clicked layer is located if (!ctxProps.multiple && e.detail.isLeaf) { if (it.selected && itemsList[index]) { itemsList = cancelSelected(itemsList, it); @@ -146,6 +147,8 @@ } if (level === 1) { // 到第一层时如果是单选,则遍历取消其他项的选择状态 + // If it is a single selection at the first level, + // traverse and cancel the selection status of other items if (itemsList[index]) { itemsList = cancelSelected(itemsList, it); } else { @@ -168,7 +171,7 @@ } else { dispatch('selectedRecursion', e.detail); } - onSubItemSelect(index); + e.detail.isLeaf && onSubItemSelect(index); } function cancelSelected(list: SubMenuType[], it: SubMenuType) { @@ -193,6 +196,7 @@ const resolveSelected = !value.selected; if (ctxProps.selectable && !hasSub(it)) { // 重置当前点击层其他项选择状态 + // Reset the selection status of other items in the current click layer if (!ctxProps.multiple && resolveSelected) { list = cancelSelected(list, it); @@ -628,9 +632,11 @@ const resolveDisabledTooltip = (it: SubMenuType, isInlineCollapsed?: boolean) => { // 有子节点的不显示 + // Nodes with child nodes are not displayed if ((it.children && it.children.length > 0 && it.type !== 'group') || !isInlineCollapsed) { return true; // 收起时且非水平模式 + // When folded and not in horizontal mode } else { return false; } @@ -639,15 +645,19 @@ const resolveTitle = (it: SubMenuType, isInlineCollapsed?: boolean, isTooltip?: boolean) => { let res = ''; // 有子节点的不显示 + // Nodes with child nodes are not displayed if (it.children && it.children.length > 0 && it.type !== 'group') { res = ''; // 收起时且非水平模式 + // Nodes with child nodes are not displayed } else if (isInlineCollapsed && ctxProps.mode !== 'horizontal') { res = it.title || it.label || ''; if (!isTooltip) { res = ''; } // 收起时或水平模式无默认值,只展示 title + // When collapsed or in horizontal mode, + // there is no default value and only the title is displayed. } else if (!isInlineCollapsed || ctxProps.mode === 'horizontal') { res = it.title || ''; } @@ -1125,4 +1135,3 @@
    {/if} - diff --git a/components/Menu/src/types.d.ts b/components/Menu/src/types.d.ts index e6353202..59af9d0f 100644 --- a/components/Menu/src/types.d.ts +++ b/components/Menu/src/types.d.ts @@ -57,77 +57,81 @@ export type KMenuInstance = { export type KMenuProps = { /** - * 上下文 key, - * 用于组件内部逻辑,应该是一个全局唯一值 KMenuItem 与 KMenu 公用一个相同值 + * @zh 上下文 key, 用于组件内部逻辑,应该是一个全局唯一值,KMenuItem 与 KMenu 公用一个相同值 + * @en Context key, used for component internal logic, + * should be a globally unique value, KMenuItem and KMenu share the same value */ ctxKey?: string; /** - * 展开图标 - * 展开图标 horizontal(more menu 展示) + * @zh 展开图标 + * @en expand icon * @default 'i-carbon-chevron-down' */ expandIcon?: string; /** - * inline 模式的菜单缩进宽度 + * @zh inline 模式的菜单缩进宽度 + * @en Menu indent width in inline mode * @default 24 */ inlineIndent?: number; /** - * inline 或 vertical 时菜单是否收起状态 (指显示图标的mini模式和展开到常规模式) + * @zh inline 或 vertical 时菜单是否收起状态 (指显示图标的mini模式和展开到常规模式) + * @en Whether the menu is collapsed in inline or vertical mode * @default false */ inlineCollapsed?: boolean; /** - * 菜单类型,现在支持垂直、水平、和内嵌模式三种 inline - * 菜单类型,现在支持垂直、水平、和内嵌模式三种 vertical - * 菜单类型,现在支持垂直、水平、和内嵌模式三种 horizontal - * `vertical` 和 `inline` 的区别在于 `vertical` 子菜单以 popover 形式出现 + * @zh 菜单渲染模式 + * @en Menu rendering mode * @default `vertical` */ mode?: `vertical` | `horizontal` | `inline`; /** - * 当前展开的 SubMenu 菜单项 key 数组 inline - * 当前展开的 SubMenu 菜单项 key 数组 vertical - * 当前展开的 SubMenu 菜单项 key 数组 horizontal + * @zh 默认打开的菜单 uid 数组 + * @en Default open menu uid array * @default `[]` */ openUids?: string[]; /** - * 当前选中的菜单项 key 数组(子菜单只高亮,不展开) inline - * 当前选中的菜单项 key 数组(子菜单只高亮,不展开) vertical - * 当前选中的菜单项 key 数组(子菜单只高亮,不展开) horizontal + * @zh 默认选中的的菜单 uid 数组 + * @en Default select menu uid array * @default `[]` */ selectedUids?: string[]; /** - * 是否允许选中(为 false, 点击不高亮,不触发 select事件) inline - * 是否允许选中(为 false, 点击不高亮,不触发 select事件) vertical - * 是否允许选中(为 false, 点击不高亮,不触发 select事件) horizontal - * @default false + * @zh 菜单可否被选中,设置为false将不会触发 Select 相关事件 + * @en Whether the menu can be selected. + * Setting it to false will not trigger `select` related events + * @default true */ selectable?: boolean; /** - * 用户鼠标离开子菜单后关闭延时,单位:毫秒(非 inline 模式, hover触发) + * @zh 用户鼠标离开子菜单后关闭延时,单位:毫秒(非 inline 模式, hover触发) + * @en The closing delay after the user leaves the submenu, unit: milliseconds * @default 100ms */ subMenuCloseDelay?: number; /** - * 用户鼠标进入子菜单后开启延时,单位:毫秒(非 inline 模式, hover触发) + * @zh 用户鼠标进入子菜单后开启延时,单位:毫秒(非 inline 模式, hover触发) + * @en The delay after the user mouse enters the submenu, unit: milliseconds * @default 0 */ subMenuOpenDelay?: number; /** - * TODO: 主题 + * @zh 主题 + * @en Theme style * @default 'light' */ theme?: 'light' | 'dark'; /** - * 是否允许多选 - * @default 'true' + * @zh 是否允许多选 + * @en Whether to allow multiple selections + * @default 'false' */ multiple?: boolean; /** - * SubMenu 展开/关闭的触发行为(非 inline 模式) + * @zh Sub Menu 展开/关闭的触发行为(非 inline 模式) + * @en Sub menu expand/close trigger behavior * @default 'hover' */ triggerSubMenuAction?: 'hover' | 'click'; @@ -139,24 +143,6 @@ export type KMenuProps = { show: boolean; }; -// onClick 点击 MenuItem 调用此函数 inline -// onOpenChange SubMenu 展开/关闭的回调 inline -// onSelect 被选中时调用(点击子菜单标题不触发) inline -// onDeSelect 被选中时调用(点击子菜单标题不触发) inline - -// onClick 点击 MenuItem 调用此函数 vertical -// onOpenChange SubMenu 展开/关闭的回调 vertical -// onSelect 被选中时调用(点击子菜单标题不触发) vertical -// onDeSelect 被选中时调用(点击子菜单标题不触发) inline - -// onClick 点击 MenuItem 调用此函数 horizontal -// onOpenChange SubMenu 展开/关闭的回调 horizontal -// onSelect 被选中时调用(点击子菜单标题不触发) horizontal -// onDeSelect 被选中时调用(点击子菜单标题不触发) inline - -// onTitleClick 点击子菜单标题 -// titleClick?: (item: SubMenuType, e: MouseEvent, uidPath: string[]) => void; - export type KMenuItemProps = { /** * @internal @@ -169,29 +155,36 @@ export type KMenuItemProps = { }; export type SubMenuType = { /** - * 展示错误状态样式 + * @zh 展示错误状态样式 + * @en Display error state style * @default false */ danger?: boolean; /** - * 展示為分組或分割綫 + * @zh 展示為分組或分割綫 + * @en Render as groups or dividers */ type?: 'group' | 'divider'; /** - * 菜单图标 + * @zh 菜单图标 + * @en Menu Icon */ icon?: string; /** - * 菜单项标题 + * @zh 菜单标题 + * @en Menu Label */ label?: string; /** - * item 的唯一标志 + * @zh item 的唯一标志, 在整个菜单树种应该是个唯一值 + * @en The unique value of the menu item. + * It should be a unique value in the entire menu tree. */ uid?: string; /** - * 是否禁用 - * 优先级高于 danger, 子节点也禁用 + * @zh 是否禁用 优先级高于 danger, 子节点也禁用 + * @en Indicates whether it is disabled. Its priority is higher than danger, + * and its child nodes are also disabled. * @default false */ disabled?: boolean; @@ -201,15 +194,18 @@ export type SubMenuType = { */ theme?: 'light' | 'dark'; /** - * 浮标题 + * @zh 悬浮标题 + * @en title */ title?: string; /** - * 子菜单的菜单项 + * @zh 子菜单的菜单项 + * @en Menu items in submenus */ children?: SubMenuType[]; /** - * 子菜单样式 + * @zh 子菜单 popover 的样式 + * @en Submenu popover style */ popupClassName?: string; /** @@ -230,15 +226,3 @@ export type SubMenuType = { selectedDeps?: Set; [property: string]: any; }; - -// Items Slots slots label 分组标题 vertical -// Items Slots slots label 分组标题 horizontal -// Items Slots slots label 分组标题 inline -// Items Slots slots icon 菜单图标 vertical -// Items Slots slots icon 菜单图标 horizontal -// Items Slots slots icon 菜单图标 inline -// Items Slots slots expandIcon 菜单图标 vertical -// Items Slots slots expandIcon 菜单图标 horizontal -// Items Slots slots expandIcon 菜单图标 inline - -// TODO: 🎯 dark mode diff --git a/components/Menu/src/utils.ts b/components/Menu/src/utils.ts index 388f5c1d..49997f4f 100644 --- a/components/Menu/src/utils.ts +++ b/components/Menu/src/utils.ts @@ -83,19 +83,25 @@ export function transitionOut(node: HTMLElement) { export function getUidPath(uid: string, list: SubMenuType[], path: string[] = []) { // 遍历树结构数组中的每个节点 + // Traverse each node in the tree structure array for (const node of list) { // 如果当前节点的 uid 与给定的 uid 匹配,返回当前路径 + // If the current node's uid matches the given uid, return the current path if (node.uid === uid) { return path.concat(uid); } // 如果当前节点包含子节点,则递归搜索子节点 + // If the current node has child nodes, recursively search for the child nodes if (node.children && node.children.length > 0) { // 在路径中添加当前节点的 uid + // Add the current node's uid to the path const newPath = path.concat(node.uid!); // 递归搜索子节点 + // Recursive search for child nodes const result = getUidPath(uid, node.children!, newPath) as null | string[]; // 如果找到了目标节点,则返回结果 + // If the target node is found, the result is returned if (result) { return result; } @@ -103,5 +109,7 @@ export function getUidPath(uid: string, list: SubMenuType[], path: string[] = [] } // 如果在当前节点及其子节点中未找到目标节点,则返回空 + // If the target node is not found in the current node and its child nodes, + // it returns null. return null; } diff --git a/docs/components/KMenu.md b/docs/components/KMenu.md index dd8905b6..db20df2e 100644 --- a/docs/components/KMenu.md +++ b/docs/components/KMenu.md @@ -31,101 +31,223 @@ Horizontal top navigation menu. -## Prefix icon and suffix icon input +## Vertical mode -Set the prefix through the `icon` attribute +Vertical menu - + -## Disabled input +## Inline mode -Disable the input through the `disabled` attribute +Vertical menu with inline submenus. - + -## Clearable +## Collapsed inline menu -Make the Input clearable with the `clearable` attribute. +Inline menu could be collapsed. - + -## Password input +## Theme -Enable the password input box and pass the `type` as `password`. +There are two built-in themes: `light` and `dark`. The default value is `light`. +When `theme` is specified, it takes precedence over unocss's dark theme. - + -## Prepend and append input +## Switch the menu type -Use the `append` or `prepend` attribute to enable a button +Show the dynamic switching mode (between `inline` and `vertical`). - + -## Search input +## Custom Render -Quickly implement a search box +Implement custom rendering through various slots -::: tip -When search is `true` and you press `enter` or click the `prepend` button or click the `append` button, the event will be triggered. -In this case, the `triggerPrepend` event, `triggerPrepend` event and `enter` event will not be triggered. -::: + + +Implement custom rendering through various slots + + + +## Menu Props + +| Name | Type | Default | Description | +| -------------------- | ----------------------------------- | ----------------------- | -------------------------------------------------------------------------------------------------------------------------------- | +| ctxKey | `string` | `-` | Context key, used for component internal logic, should be a globally unique value, `KMenuItem` and `KMenu` share the same value. | +| expandIcon | `string` | `i-carbon-chevron-down` | Expand Icon,following the unocss standard | +| inlineIndent | `number` | `24` | Menu indent width in inline mode | +| inlineCollapsed | `boolean` | `false` | Whether the menu is collapsed in inline or vertical mode | +| mode | `vertical \| horizontal \| inline` | `vertical` | Menu rendering mode | +| openUids | `string[]` | `[]` | Default open menu uid array | +| selectedUids | `string[]` | `[]` | Default select menu uid array | +| selectable | `boolean` | `true` | Whether the menu can be selected. Setting it to false will not trigger `select` related events | +| subMenuCloseDelay | `number` | `100` | The closing delay after the user leaves the submenu, unit: milliseconds | +| subMenuOpenDelay | `number` | `0` | The delay after the user mouse enters the submenu, unit: milliseconds | +| theme | `light \| dark` | `-` | Theme style | +| multiple | `boolean` | `false` | Whether to allow multiple selections | +| triggerSubMenuAction | `hover \| click` | `hover` | Sub menu expand/close trigger behavior | +| cls | `string` | `-` | Additional class | +| attrs | `Record` | `{}` | Additional attributes | + +## Menu Events + +| Name | Description | Type | +| ---------- | ------------------------------------------------------------------------------- | -------------------------------------- | +| click | Triggered when the menu item is clicked | `(e: CustomEvent)=> void` | +| openChange | Sub menu expand/close callback, the parameter is the currently opened uid array | `(e: CustomEvent)=> void` | +| select | Triggered when the menu item is seleced | `(e: CustomEvent)=> void` | +| deSelect | Fired when the menu item is deselected | `(e: CustomEvent)=> void` | + +#### ClickEvtPa + +```typescript +export type ClickEvtPa = { + // The clicked item object + item: SubMenuType; + // The uid of the item object clicked + uid: string; + // An array of uid paths starting from the root menu object to the clicked item + uidPath: string[]; + e: MouseEvent; +}; +``` + +#### SelectEvtPa + +```typescript +export type SelectEvtPa = { + // The selected/deSelected item object + item: SubMenuType; + // The uid of the item object selected/deSelected + uid: string; + // An array of uid paths starting from the root menu object to the selected/deSelected item + uidPath: string[]; + // An array of uids selected in multi-select mode + selectedUids: string[]; + // An array of items selected in multi-select mode + selectedItems: SubMenuType[]; + // An array of uid paths selected in multi-select mode + selectedUidPaths: string[][]; + e: MouseEvent; +}; +``` + +## MenuItem Props + +| Name | Type | Default | Description | +| ------ | ------------------------ | ------- | -------------------------------------------------------------------------------------------------------------------------------- | +| ctxKey | `string` | `-` | Context key, used for component internal logic, should be a globally unique value, `KMenuItem` and `KMenu` share the same value. | +| items | `SubMenuType[]` | `-` | Menu configuration object | +| cls | `string` | `-` | Additional class | +| attrs | `Record` | `{}` | Additional attributes | + +#### SubMenuType + +```typescript +export type SubMenuType = { + /** + * @en Display error state style + * @default false + */ + danger?: boolean; + /** + * @en Render as groups or dividers + */ + type?: 'group' | 'divider'; + /** + * @en Menu Icon + */ + icon?: string; + /** + * @en Menu Label + */ + label?: string; + /** + * @en The unique value of the menu item. + * It should be a unique value in the entire menu tree. + */ + uid?: string; + /** + * @en Indicates whether it is disabled. Its priority is higher than danger, + * and its child nodes are also disabled. + * @default false + */ + disabled?: boolean; + /** + * @en title + */ + title?: string; + /** + * @en Menu items in submenus + */ + children?: SubMenuType[]; + /** + * @en Submenu popover style + */ + popupClassName?: string; +}; +``` + +## MenuItem Events + +| Name | Description | Type | +| ---------- | ------------------------------------------- | ------------------------------------------ | +| titleClick | Triggered when the submenu title is clicked | `(e: CustomEvent)=> void` | - - -## Sizes - -Add `size` attribute to change the size of Input. It supports `sm`, `md` and `lg`. - - - -## Textarea - -Setting the `autosize` prop for a textarea type of Input makes the height to automatically adjust based on the content. -An options object can be provided to `autosize` to specify the minimum and maximum number of lines the textarea can automatically adjust. - - - -## Input Props - -| Name | Type | Default | Description | -| ------------------- | ------------------------------------------------ | ------- | ------------------------------------------------------------------------------ | -| size | `sm \| md \|lg` | `md` | size of Input. | -| type | `text \| password` | `text` | Determine whether it is a password input | -| value | `string` | `-` | Binding value | -| iconPrefix | `string` | `-` | The class name of the prefix icon, following the unocss standard | -| iconSuffix | `string` | `-` | The class name of the suffix icon, following the unocss standard | -| append | `string` | `-` | The class name of the append button icon, following the unocss standard | -| prepend | `string` | `-` | The class name of the prepend button icon, following the unocss standard | -| placeholder | `string` | `false` | Input's placeholder | -| disabled | `boolean` | `false` | Disable the Input | -| clearable | `boolean` | `false` | whether to show clear button, only works when type is not 'textarea' | -| search | `boolean` | `false` | Enable `search` callback | -| useCompositionInput | `boolean` | `false` | Bind value will be updated after the composition input ends | -| rows | `number` | `3` | number of rows of `textarea`, only works when type is 'textarea' | -| autosize | `boolean \| { minRows: number: maxRows:number }` | `false` | whether `textarea` has an adaptive height, only works when type is 'textarea'. | -| cls | `string` | `-` | Additional class | -| attrs | `Record` | `{}` | Additional attributes | - -## Input Events - -| Name | Description | Type | -| ---------------- | ---------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------- | -| input | Event fired on input | `(value: string)=> void` | -| enter | Event fired when `enter` is pressed | `(e: Event)=> void` | -| keydown | Event fired when `keyboard` is pressed | `(e: Event)=> void` | -| change | Event fired when the `value` is changes | `(e: Event)=> void` | -| compositionstart | The compositionstart event is fired when a text composition system | `(e: CompositionEvent)=> void` | -| compositionend | The compositionend event is fired when a text composition system | `(e: CompositionEvent)=> void` | -| compositionInput | Event fired when enable `useCompositionInput` | `(e: CompositionEvent)=> void` | -| triggerPrepend | Event fired on prepend button | `(value: HTMLInputElement.value)=> void` | -| triggerAppend | Event fired on append button | `(value: HTMLInputElement.value)=> void` | -| search | When search is true and you press `enter` or click the `prepend` button or click the `append` button, the event will be triggered. | `(value: HTMLInputElement.value)=> void` | - -## Input Slots - -| Name | Description | -| ------- | ------------------------------- | -| prefix | Customize input prefix content | -| suffix | Customize input suffix content | -| append | Customize input append content | -| prepend | Customize input prepend content | +#### TitleClickEvtPa + +```typescript +type TitleClickEvtPa = { + // The clicked item object + item: SubMenuType; + e: MouseEvent; +}; +``` + +## MenuItem Slots + +| Name | Description | +| ---------- | --------------------------------------------------------------------------------------------------- | +| label | Customize menu item's `label` content | +| icon | Customize menu item's `icon` content | +| expandIcon | Customize menu item's `expandIcon` content | +| item | Customize menu item content, When setting the item slot, the other three slots will not take effect | + +#### label slot params + +```typescript +// render item object +type item = SubMenuType; +// render item class +type cls = string; +``` + +#### icon slot params + +```typescript +// render item object +type item = SubMenuType; +// render item class +type cls = string; +``` + +#### expandIcon slot params + +```typescript +// render item object +type item = SubMenuType; +// render item class +type cls = string; +``` + +#### item slot params + +```typescript +// render item object +type item = SubMenuType; +// render item class +type cls = string; +``` diff --git a/docs/example/menu/collapsed.svelte b/docs/example/menu/collapsed.svelte new file mode 100644 index 00000000..c710323d --- /dev/null +++ b/docs/example/menu/collapsed.svelte @@ -0,0 +1,79 @@ + + + + +
    + + + +
    diff --git a/docs/example/menu/custom.svelte b/docs/example/menu/custom.svelte new file mode 100644 index 00000000..cb392482 --- /dev/null +++ b/docs/example/menu/custom.svelte @@ -0,0 +1,76 @@ + + +
    + + + + 🤣 {item.label} + + 🎯 + 👇 + + +
    diff --git a/docs/example/menu/horizontal.svelte b/docs/example/menu/horizontal.svelte index 7f0af883..1d608e41 100644 --- a/docs/example/menu/horizontal.svelte +++ b/docs/example/menu/horizontal.svelte @@ -4,16 +4,19 @@ const items: SubMenuType[] = [ { label: 'Navigation One', - uid: 'mail' + uid: 'mail', + icon: 'i-carbon-email' }, { label: 'Navigation Two', uid: 'app', - disabled: true + disabled: true, + icon: 'i-carbon-apps' }, { label: 'Navigation Three - Submenu', uid: 'SubMenu', + icon: 'i-carbon-cloud-satellite-config', children: [ { type: 'group', diff --git a/docs/example/menu/inline.svelte b/docs/example/menu/inline.svelte new file mode 100644 index 00000000..1d09c98f --- /dev/null +++ b/docs/example/menu/inline.svelte @@ -0,0 +1,70 @@ + + +
    + + + +
    diff --git a/docs/example/menu/item-slot.svelte b/docs/example/menu/item-slot.svelte new file mode 100644 index 00000000..4d38930c --- /dev/null +++ b/docs/example/menu/item-slot.svelte @@ -0,0 +1,79 @@ + + +
    + + +
    + + 🤟🏼 {item.label} + + {#if item.children && item.children.length > 0 && item.type !== 'group'} + 🏀 + {/if} +
    +
    +
    +
    diff --git a/docs/example/menu/theme.svelte b/docs/example/menu/theme.svelte new file mode 100644 index 00000000..f26671ef --- /dev/null +++ b/docs/example/menu/theme.svelte @@ -0,0 +1,76 @@ + + + + {theme} + {theme} + +
    + + + +
    diff --git a/docs/example/menu/type.svelte b/docs/example/menu/type.svelte new file mode 100644 index 00000000..1837a0ce --- /dev/null +++ b/docs/example/menu/type.svelte @@ -0,0 +1,90 @@ + + +
    + + change style + + change style +
    + +
    + + + +
    diff --git a/docs/example/menu/vertical.svelte b/docs/example/menu/vertical.svelte new file mode 100644 index 00000000..a3b61363 --- /dev/null +++ b/docs/example/menu/vertical.svelte @@ -0,0 +1,70 @@ + + +
    + + + +