From db4d588f240eeb07543a82f5d1906a2b8556a139 Mon Sep 17 00:00:00 2001
From: baiwusanyu-c <740132583@qq.com>
Date: Mon, 15 Apr 2024 16:56:00 +0800
Subject: [PATCH 01/39] wip: init KMenu component
---
components/Menu/__test__/menu.spec.ts | 32 ++++++++++++++++++
components/Menu/package.json | 47 +++++++++++++++++++++++++++
components/Menu/src/index.svelte | 19 +++++++++++
components/Menu/src/index.ts | 5 +++
components/Menu/src/types.d.ts | 6 ++++
components/Menu/tsconfig.json | 11 +++++++
components/index.ts | 1 +
package.json | 5 +--
pnpm-lock.yaml | 45 +++++++++++++++++++++----
preset/src/shortcuts/index.ts | 6 ++++
preset/src/shortcuts/src/menu.ts | 3 ++
11 files changed, 172 insertions(+), 8 deletions(-)
create mode 100644 components/Menu/__test__/menu.spec.ts
create mode 100644 components/Menu/package.json
create mode 100644 components/Menu/src/index.svelte
create mode 100644 components/Menu/src/index.ts
create mode 100644 components/Menu/src/types.d.ts
create mode 100644 components/Menu/tsconfig.json
create mode 100644 preset/src/shortcuts/src/menu.ts
diff --git a/components/Menu/__test__/menu.spec.ts b/components/Menu/__test__/menu.spec.ts
new file mode 100644
index 00000000..52352fac
--- /dev/null
+++ b/components/Menu/__test__/menu.spec.ts
@@ -0,0 +1,32 @@
+import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest';
+import KMenu from '../src';
+
+let host;
+
+const initHost = () => {
+ host = globalThis.document.createElement('div');
+ host.setAttribute('id', 'host');
+ globalThis.document.body.appendChild(host);
+};
+beforeEach(() => {
+ initHost();
+ vi.useFakeTimers();
+});
+afterEach(() => {
+ host.remove();
+ vi.useRealTimers();
+});
+
+describe('Test: KMenu', () => {
+ test('props: cls', async () => {
+ const instance = new KMenu({
+ target: host,
+ props: {
+ cls: 'k-menu--test'
+ }
+ });
+ expect(instance).toBeTruthy();
+ expect(host!.innerHTML.includes('k-menu--test')).toBeTruthy();
+ expect(host.innerHTML).matchSnapshot();
+ });
+});
diff --git a/components/Menu/package.json b/components/Menu/package.json
new file mode 100644
index 00000000..34c658ac
--- /dev/null
+++ b/components/Menu/package.json
@@ -0,0 +1,47 @@
+{
+ "name": "@ikun-ui/menu",
+ "version": "0.2.6",
+ "type": "module",
+ "main": "src/index.ts",
+ "types": "src/index.d.ts",
+ "svelte": "src/index.ts",
+ "keywords": [
+ "svelte",
+ "svelte3",
+ "web component",
+ "component",
+ "react",
+ "vue",
+ "svelte-kit",
+ "dx"
+ ],
+ "files": [
+ "dist",
+ "package.json"
+ ],
+ "scripts": {
+ "build": "svelte-package -i src",
+ "publish:pre": "node ../../scripts/pre-publish.js",
+ "publish:npm": "pnpm run publish:pre && pnpm publish --no-git-checks --access public"
+ },
+ "publishConfig": {
+ "access": "public",
+ "main": "dist/index.js",
+ "module": "dist/index.js",
+ "svelte": "dist/index.js",
+ "types": "dist/index.d.ts"
+ },
+ "dependencies": {
+ "@ikun-ui/icon": "workspace:*",
+ "@ikun-ui/utils": "workspace:*",
+ "baiwusanyu-utils": "^1.0.18",
+ "clsx": "^2.0.0",
+ "svelte": "^4.2.7"
+ },
+ "devDependencies": {
+ "@sveltejs/package": "^2.3.1",
+ "@tsconfig/svelte": "^5.0.4",
+ "tslib": "^2.6.2",
+ "typescript": "^5.4.4"
+ }
+}
diff --git a/components/Menu/src/index.svelte b/components/Menu/src/index.svelte
new file mode 100644
index 00000000..8a0701f3
--- /dev/null
+++ b/components/Menu/src/index.svelte
@@ -0,0 +1,19 @@
+
+
+
diff --git a/components/Menu/src/index.ts b/components/Menu/src/index.ts
new file mode 100644
index 00000000..ef6362b4
--- /dev/null
+++ b/components/Menu/src/index.ts
@@ -0,0 +1,5 @@
+///
+import Menu from './index.svelte';
+export { Menu as KMenu };
+
+export default Menu;
diff --git a/components/Menu/src/types.d.ts b/components/Menu/src/types.d.ts
new file mode 100644
index 00000000..86f469e0
--- /dev/null
+++ b/components/Menu/src/types.d.ts
@@ -0,0 +1,6 @@
+///
+import type { ClassValue } from 'clsx';
+export type KMenuProps = {
+ cls: ClassValue;
+ attrs: Record;
+};
diff --git a/components/Menu/tsconfig.json b/components/Menu/tsconfig.json
new file mode 100644
index 00000000..fe0d7c4f
--- /dev/null
+++ b/components/Menu/tsconfig.json
@@ -0,0 +1,11 @@
+{
+ "extends": "@tsconfig/svelte/tsconfig.json",
+
+ "compilerOptions": {
+ "noImplicitAny": true,
+ "strict": true,
+ "declaration": true
+ },
+ "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.svelte"],
+ "exclude": ["node_modules/*", "**/*.spec.ts"]
+}
diff --git a/components/index.ts b/components/index.ts
index 7763c2f5..d0cb94e2 100644
--- a/components/index.ts
+++ b/components/index.ts
@@ -68,3 +68,4 @@ export * from '@ikun-ui/timeline';
export * from '@ikun-ui/calendar';
export * from '@ikun-ui/indicators';
export * from '@ikun-ui/tour';
+export * from '@ikun-ui/menu';
diff --git a/package.json b/package.json
index bc500cbf..490e40e1 100644
--- a/package.json
+++ b/package.json
@@ -69,7 +69,7 @@
"clean:deps": "node scripts/clean-deps.js && node scripts/clean-root-deps.js",
"prepare": "npx simple-git-hooks",
"update:deps": "npx taze -w -r major && pnpm run init",
- "create:new:comp": "node scripts/new-component.js tour"
+ "create:new:comp": "node scripts/new-component.js menu"
},
"peerDependencies": {
"baiwusanyu-utils": "^1.0.18",
@@ -151,7 +151,8 @@
"baiwusanyu-utils": "^1.0.18",
"clsx": "^2.1.0",
"dayjs": "^1.11.10",
- "@ikun-ui/indicators": "workspace:*"
+ "@ikun-ui/indicators": "workspace:*",
+ "@ikun-ui/menu": "workspace:*"
},
"devDependencies": {
"@sveltejs/adapter-auto": "^3.2.0",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 96018301..58481b75 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -134,6 +134,9 @@ importers:
'@ikun-ui/mask':
specifier: workspace:*
version: link:components/Mask
+ '@ikun-ui/menu':
+ specifier: workspace:*
+ version: link:components/Menu
'@ikun-ui/message':
specifier: workspace:*
version: link:components/Message
@@ -1759,6 +1762,37 @@ importers:
specifier: ^5.4.4
version: 5.4.4
+ components/Menu:
+ dependencies:
+ '@ikun-ui/icon':
+ specifier: workspace:*
+ version: link:../Icon
+ '@ikun-ui/utils':
+ specifier: workspace:*
+ version: link:../../utils
+ baiwusanyu-utils:
+ specifier: ^1.0.18
+ version: 1.0.18(ansi-colors@4.1.3)(moment@2.29.4)
+ clsx:
+ specifier: ^2.0.0
+ version: 2.1.0
+ svelte:
+ specifier: ^4.2.7
+ version: 4.2.12
+ devDependencies:
+ '@sveltejs/package':
+ specifier: ^2.3.1
+ version: 2.3.1(svelte@4.2.12)(typescript@5.4.4)
+ '@tsconfig/svelte':
+ specifier: ^5.0.4
+ version: 5.0.4
+ tslib:
+ specifier: ^2.6.2
+ version: 2.6.2
+ typescript:
+ specifier: ^5.4.4
+ version: 5.4.4
+
components/Message:
dependencies:
'@ikun-ui/notify':
@@ -4661,7 +4695,7 @@ packages:
globby: 11.1.0
is-glob: 4.0.3
minimatch: 9.0.3
- semver: 7.5.4
+ semver: 7.6.0
ts-api-utils: 1.0.3(typescript@5.4.3)
typescript: 5.4.3
transitivePeerDependencies:
@@ -4703,7 +4737,7 @@ packages:
'@typescript-eslint/types': 7.3.1
'@typescript-eslint/typescript-estree': 7.3.1(typescript@5.4.3)
eslint: 8.57.0
- semver: 7.5.4
+ semver: 7.6.0
transitivePeerDependencies:
- supports-color
- typescript
@@ -7372,7 +7406,7 @@ packages:
dev: true
/lru-cache@5.1.1:
- resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==, tarball: https://r2.cnpmjs.org/lru-cache/-/lru-cache-5.1.1.tgz}
+ resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==}
dependencies:
yallist: 3.1.1
dev: true
@@ -7413,7 +7447,6 @@ packages:
engines: {node: '>=12'}
dependencies:
'@jridgewell/sourcemap-codec': 1.4.15
- dev: true
/mark.js@8.11.1:
resolution: {integrity: sha1-GA8fnr74sOY45BZq1S24eb6y/8U=}
@@ -7964,7 +7997,7 @@ packages:
/periscopic@3.1.0:
resolution: {integrity: sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==}
dependencies:
- '@types/estree': 1.0.3
+ '@types/estree': 1.0.5
estree-walker: 3.0.3
is-reference: 3.0.2
@@ -8992,7 +9025,7 @@ packages:
estree-walker: 3.0.3
is-reference: 3.0.2
locate-character: 3.0.0
- magic-string: 0.30.8
+ magic-string: 0.30.9
periscopic: 3.1.0
/symbol-tree@3.2.4:
diff --git a/preset/src/shortcuts/index.ts b/preset/src/shortcuts/index.ts
index b6abdff1..02fc7ac4 100644
--- a/preset/src/shortcuts/index.ts
+++ b/preset/src/shortcuts/index.ts
@@ -1,3 +1,4 @@
+import { menuShortcuts } from './src/menu';
import { indicatorsShortcuts } from './src/indicators';
import { tourShortcuts } from './src/tour';
import { calendarShortcuts } from './src/calendar';
@@ -71,6 +72,8 @@ export const defaultShortcuts = [
commonShortcuts,
// don't remove
// anchor defaultShortcuts
+ // menu
+ menuShortcuts,
// indicators
indicatorsShortcuts,
// tour
@@ -196,6 +199,7 @@ export const defaultShortcuts = [
export function getSafeList() {
// don't remove
// anchor shortcuts
+ const menuList = Object.keys(menuShortcuts);
const indicatorsList = Object.keys(indicatorsShortcuts);
const tourList = Object.keys(tourShortcuts);
const calendarList = Object.keys(calendarShortcuts);
@@ -261,6 +265,7 @@ export function getSafeList() {
let res = iconList
// don't remove
// anchor list
+ .concat(menuList)
.concat(indicatorsList)
.concat(tourList)
.concat(calendarList)
@@ -400,3 +405,4 @@ export { timelineShortcuts } from './src/timeline';
export { calendarShortcuts } from './src/calendar';
export { indicatorsShortcuts } from './src/indicators';
export { tourShortcuts } from './src/tour';
+export { menuShortcuts } from './src/menu';
diff --git a/preset/src/shortcuts/src/menu.ts b/preset/src/shortcuts/src/menu.ts
new file mode 100644
index 00000000..624f842e
--- /dev/null
+++ b/preset/src/shortcuts/src/menu.ts
@@ -0,0 +1,3 @@
+export const menuShortcuts: Record = {
+ 'k-menu': ''
+};
From 2e6cf3d8df4b1c2813cf8f7979048b1a4bd336f2 Mon Sep 17 00:00:00 2001
From: baiwusanyu-c <740132583@qq.com>
Date: Mon, 15 Apr 2024 18:14:10 +0800
Subject: [PATCH 02/39] wip: KMEnu api design
---
components/Menu/src/types.d.ts | 155 +++++++++++++++++++++++++++++++++
1 file changed, 155 insertions(+)
diff --git a/components/Menu/src/types.d.ts b/components/Menu/src/types.d.ts
index 86f469e0..f3f089af 100644
--- a/components/Menu/src/types.d.ts
+++ b/components/Menu/src/types.d.ts
@@ -1,6 +1,161 @@
///
import type { ClassValue } from 'clsx';
export type KMenuProps = {
+ /**
+ * TODO: 展开图标
+ */
+ expandIcon?: string
+ /**
+ * TODO: inline 模式的菜单缩进宽度
+ * @default 24
+ */
+ inlineIndent?: number
+ /**
+ * TODO: inline 时菜单是否收起状态 (指显示图标的mini模式和展开到常规模式)
+ * @default 24
+ */
+ inlineCollapsed?: number
+ /**
+ * TODO: 菜单内容
+ */
+ items?: KItemType[]
+ /**
+ * TODO: 菜单类型,现在支持垂直、水平、和内嵌模式三种
+ * `vertical` 和 `inline` 的区别在于 `vertical` 子菜单以 popover 形式出现
+ * @default `vertical`
+ */
+ mode?: `vertical` | `horizontal` | `inline`
+ /**
+ * TODO: 当前展开的 SubMenu 菜单项 key 数组
+ * @default `[]`
+ */
+ openUids?: string[]
+ /**
+ * TODO: 用于自定义 Menu 水平空间不足时的省略收缩的图标
+ */
+ overflowedIndicator?: string
+ /**
+ * TODO: 当前选中的菜单项 key 数组
+ * @default `[]`
+ */
+ selectedUids?: string[]
+ /**
+ * TODO: 是否允许选中(为 false, 仅不触发 select事件)
+ * @default false
+ */
+ selectable?: boolean
+ /**
+ * TODO: 用户鼠标离开子菜单后关闭延时,单位:毫秒
+ * @default 100ms
+ */
+ subMenuCloseDelay?: boolean
+ /**
+ * TODO: 用户鼠标进入子菜单后开启延时,单位:毫秒
+ * @default 0
+ */
+ subMenuOpenDelay?: number
+ /**
+ * TODO: 主题
+ * @default 'light'
+ */
+ theme?: 'light' | 'dark'
+ /**
+ * TODO: SubMenu 展开/关闭的触发行为(非 inline 模式)
+ * @default 'hover'
+ */
+ triggerSubMenuAction?: 'hover' | 'click'
cls: ClassValue;
attrs: Record;
};
+
+// TODO: onClick 点击 MenuItem 调用此函数(点击子菜单标题不触发)
+// TODO: onOpenChange SubMenu 展开/关闭的回调
+// TODO: onSelect 被选中时调用(点击子菜单标题不触发)
+
+// TODO: slots overflowedIndicator 用于自定义 Menu 水平空间不足时的省略收缩的图标
+// TODO: slots expandIcon 展开图标
+
+export type KItemType = KMenuItemType | DividerItem | SubMenuType | GroupItem
+
+export type KMenuItemType = {
+ /**
+ * TODO: 菜单图标
+ */
+ icon?: string
+ /**
+ * TODO: 菜单项标题
+ */
+ label?: string
+ /**
+ * TODO: item 的唯一标志
+ */
+ uid?: string
+ /**
+ * TODO: 设置收缩时展示的悬浮标题(无子菜单情况下生效,不传时默认为 label)
+ */
+ title?: string
+ /**
+ * TODO: 是否禁用
+ * @default false
+ */
+ disabled: boolean
+ /**
+ * TODO: 展示错误状态样式
+ * @default false
+ */
+ danger: boolean
+}
+
+export type SubMenuType = {
+ /**
+ * TODO: 菜单图标
+ */
+ icon?: string
+ /**
+ * TODO: 菜单项标题
+ */
+ label?: string
+ /**
+ * TODO: item 的唯一标志
+ */
+ uid?: string
+ /**
+ * TODO: 是否禁用
+ * @default false
+ */
+ disabled: boolean
+ /**
+ * TODO: 设置子菜单的主题,默认从 Menu 上继承
+ * @default 'light'
+ */
+ theme?: 'light' | 'dark'
+ /**
+ * TODO: 子菜单的菜单项
+ */
+ children?: KItemType[]
+ /**
+ * TODO: 子菜单样式,mode="inline" 时无效
+ */
+ popupClassName?: string
+};
+
+// TODO: onTitleClick 点击子菜单标题
+
+export type GroupItem = {
+ type?: 'group', // Must have
+ /**
+ * TODO: 分组标题
+ */
+ label: string
+ /**
+ * TODO: 分组的菜单项
+ */
+ children: KMenuItemType[],
+};
+
+export type DividerItem = {
+ type?: 'divider', // Must have
+};
+
+// TODO: Items Slots slots label 分组标题
+// TODO: Items Slots slots icon 菜单图标
From 747e77604c2d68ed4db82beff6caf58fc1015bc4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E7=99=BD=E9=9B=BE=E4=B8=89=E8=AF=AD?=
<32354856+baiwusanyu-c@users.noreply.github.com>
Date: Mon, 15 Apr 2024 21:39:58 +0800
Subject: [PATCH 03/39] wip: temp commit
---
components/Menu/src/index.svelte | 21 ++++++++++++++-----
components/Menu/src/index.ts | 8 ++++++++
components/Menu/src/types.d.ts | 35 ++++++++++++++++++++------------
3 files changed, 46 insertions(+), 18 deletions(-)
diff --git a/components/Menu/src/index.svelte b/components/Menu/src/index.svelte
index 8a0701f3..02a266c0 100644
--- a/components/Menu/src/index.svelte
+++ b/components/Menu/src/index.svelte
@@ -2,18 +2,29 @@
import { getPrefixCls } from '@ikun-ui/utils';
import { clsx } from 'clsx';
import type { KMenuProps } from './types';
-
+ export let triggerSubMenuAction: KMenuProps['triggerSubMenuAction'] = 'hover';
+ export let subMenuCloseDelay: KMenuProps['subMenuCloseDelay'] = 100;
+ export let subMenuOpenDelay: KMenuProps['subMenuOpenDelay'] = 0;
+ export let items: KMenuProps['items'] = [];
+ export let expandIcon: KMenuProps['expandIcon'] = 'i-carbon-chevron-down';
+ export let overflowedIndicator: KMenuProps['overflowedIndicator'] = 'i-carbon-overflow-menu-horizontal';
+ export let mode: KMenuProps['mode'] = 'vertical';
export let cls: KMenuProps['cls'] = undefined;
export let attrs: KMenuProps['attrs'] = {};
const prefixCls = getPrefixCls('menu');
$: cnames = clsx(
prefixCls,
- {
- [`${prefixCls}--base`]: true
- },
cls
);
-
+
+ {#if mode !== 'horizontal'}
+ {#each items as item, index (item.uid)}
+
+ {item.uid}
+
+ {/each}
+ {/if}
+
diff --git a/components/Menu/src/index.ts b/components/Menu/src/index.ts
index ef6362b4..a0df1de6 100644
--- a/components/Menu/src/index.ts
+++ b/components/Menu/src/index.ts
@@ -3,3 +3,11 @@ import Menu from './index.svelte';
export { Menu as KMenu };
export default Menu;
+
+export type {
+ KMenuProps,
+ DividerItem,
+ GroupItem,
+ SubMenuType,
+ KMenuItemType
+} from './types'
diff --git a/components/Menu/src/types.d.ts b/components/Menu/src/types.d.ts
index f3f089af..670f947c 100644
--- a/components/Menu/src/types.d.ts
+++ b/components/Menu/src/types.d.ts
@@ -2,7 +2,8 @@
import type { ClassValue } from 'clsx';
export type KMenuProps = {
/**
- * TODO: 展开图标
+ * TODO: 🎯 展开图标
+ * @default 'i-carbon-chevron-down'
*/
expandIcon?: string
/**
@@ -16,11 +17,11 @@ export type KMenuProps = {
*/
inlineCollapsed?: number
/**
- * TODO: 菜单内容
+ * TODO: 🎯 菜单内容
*/
- items?: KItemType[]
+ items: KItemType[]
/**
- * TODO: 菜单类型,现在支持垂直、水平、和内嵌模式三种
+ * TODO: 🎯 菜单类型,现在支持垂直、水平、和内嵌模式三种
* `vertical` 和 `inline` 的区别在于 `vertical` 子菜单以 popover 形式出现
* @default `vertical`
*/
@@ -31,7 +32,7 @@ export type KMenuProps = {
*/
openUids?: string[]
/**
- * TODO: 用于自定义 Menu 水平空间不足时的省略收缩的图标
+ * TODO: 🎯 用于自定义 Menu 水平空间不足时的省略收缩的图标
*/
overflowedIndicator?: string
/**
@@ -45,12 +46,12 @@ export type KMenuProps = {
*/
selectable?: boolean
/**
- * TODO: 用户鼠标离开子菜单后关闭延时,单位:毫秒
+ * TODO: 🎯 用户鼠标离开子菜单后关闭延时,单位:毫秒
* @default 100ms
*/
subMenuCloseDelay?: boolean
/**
- * TODO: 用户鼠标进入子菜单后开启延时,单位:毫秒
+ * TODO: 🎯 用户鼠标进入子菜单后开启延时,单位:毫秒
* @default 0
*/
subMenuOpenDelay?: number
@@ -60,7 +61,7 @@ export type KMenuProps = {
*/
theme?: 'light' | 'dark'
/**
- * TODO: SubMenu 展开/关闭的触发行为(非 inline 模式)
+ * TODO: 🎯 SubMenu 展开/关闭的触发行为(非 inline 模式)
* @default 'hover'
*/
triggerSubMenuAction?: 'hover' | 'click'
@@ -98,12 +99,12 @@ export type KMenuItemType = {
* TODO: 是否禁用
* @default false
*/
- disabled: boolean
+ disabled?: boolean
/**
* TODO: 展示错误状态样式
* @default false
*/
- danger: boolean
+ danger?: boolean
}
export type SubMenuType = {
@@ -123,7 +124,7 @@ export type SubMenuType = {
* TODO: 是否禁用
* @default false
*/
- disabled: boolean
+ disabled?: boolean
/**
* TODO: 设置子菜单的主题,默认从 Menu 上继承
* @default 'light'
@@ -146,15 +147,23 @@ export type GroupItem = {
/**
* TODO: 分组标题
*/
- label: string
+ label?: string
+ /**
+ * TODO: item 的唯一标志
+ */
+ uid?: string
/**
* TODO: 分组的菜单项
*/
- children: KMenuItemType[],
+ children?: KItemType[],
};
export type DividerItem = {
type?: 'divider', // Must have
+ /**
+ * TODO: item 的唯一标志
+ */
+ uid?: string
};
// TODO: Items Slots slots label 分组标题
From c7b1f034ba2bbd91b547b91198e02bc2c2b0158c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E7=99=BD=E9=9B=BE=E4=B8=89=E8=AF=AD?=
<32354856+baiwusanyu-c@users.noreply.github.com>
Date: Mon, 15 Apr 2024 23:39:42 +0800
Subject: [PATCH 04/39] wip: temp commit
---
components/Menu/src/index.svelte | 12 +++----
components/Menu/src/index.ts | 3 +-
components/Menu/src/item.svelte | 15 +++++++++
components/Menu/src/types.d.ts | 55 +++-----------------------------
4 files changed, 27 insertions(+), 58 deletions(-)
create mode 100644 components/Menu/src/item.svelte
diff --git a/components/Menu/src/index.svelte b/components/Menu/src/index.svelte
index 02a266c0..a7b3503d 100644
--- a/components/Menu/src/index.svelte
+++ b/components/Menu/src/index.svelte
@@ -1,7 +1,8 @@
+
+{#each items as item (item.uid)}
+
+ {#if item.type === 'divider'}
+
+
+
+ {/if}
+
+{/each}
diff --git a/components/Menu/src/types.d.ts b/components/Menu/src/types.d.ts
index 670f947c..4b6a48ee 100644
--- a/components/Menu/src/types.d.ts
+++ b/components/Menu/src/types.d.ts
@@ -76,38 +76,15 @@ export type KMenuProps = {
// TODO: slots overflowedIndicator 用于自定义 Menu 水平空间不足时的省略收缩的图标
// TODO: slots expandIcon 展开图标
-export type KItemType = KMenuItemType | DividerItem | SubMenuType | GroupItem
+export type KItemType = KMenuItemType
-export type KMenuItemType = {
- /**
- * TODO: 菜单图标
- */
- icon?: string
- /**
- * TODO: 菜单项标题
- */
- label?: string
- /**
- * TODO: item 的唯一标志
- */
- uid?: string
- /**
- * TODO: 设置收缩时展示的悬浮标题(无子菜单情况下生效,不传时默认为 label)
- */
- title?: string
- /**
- * TODO: 是否禁用
- * @default false
- */
- disabled?: boolean
+export type SubMenuType = {
/**
* TODO: 展示错误状态样式
* @default false
*/
- danger?: boolean
-}
-
-export type SubMenuType = {
+ danger?: boolean,
+ type?: 'group' | 'divider',
/**
* TODO: 菜单图标
*/
@@ -142,29 +119,5 @@ export type SubMenuType = {
// TODO: onTitleClick 点击子菜单标题
-export type GroupItem = {
- type?: 'group', // Must have
- /**
- * TODO: 分组标题
- */
- label?: string
- /**
- * TODO: item 的唯一标志
- */
- uid?: string
- /**
- * TODO: 分组的菜单项
- */
- children?: KItemType[],
-};
-
-export type DividerItem = {
- type?: 'divider', // Must have
- /**
- * TODO: item 的唯一标志
- */
- uid?: string
-};
-
// TODO: Items Slots slots label 分组标题
// TODO: Items Slots slots icon 菜单图标
From 8a4f7f9c25ef142d4a06c264509c125e086471f1 Mon Sep 17 00:00:00 2001
From: baiwusanyu-c <740132583@qq.com>
Date: Tue, 16 Apr 2024 11:18:37 +0800
Subject: [PATCH 05/39] wip: recursive slots and dynamic context
---
components/Menu/src/index.svelte | 54 +++++++++++++++---------
components/Menu/src/index.ts | 12 +++---
components/Menu/src/item.svelte | 59 ++++++++++++++++++++++-----
components/Menu/src/types.d.ts | 70 +++++++++++++++++++++-----------
components/Menu/src/utils.ts | 14 +++++++
utils/src/index.ts | 3 +-
utils/src/symbol-key.ts | 1 +
7 files changed, 153 insertions(+), 60 deletions(-)
create mode 100644 components/Menu/src/utils.ts
diff --git a/components/Menu/src/index.svelte b/components/Menu/src/index.svelte
index a7b3503d..e5f008ce 100644
--- a/components/Menu/src/index.svelte
+++ b/components/Menu/src/index.svelte
@@ -1,30 +1,46 @@
- {#if mode !== 'horizontal'}
-
- {/if}
+
diff --git a/components/Menu/src/index.ts b/components/Menu/src/index.ts
index 0ac11645..acb9e54b 100644
--- a/components/Menu/src/index.ts
+++ b/components/Menu/src/index.ts
@@ -6,9 +6,9 @@ export { MenuItem as KMenuItem };
export default Menu;
export type {
- KMenuProps,
- DividerItem,
- GroupItem,
- SubMenuType,
- KMenuItemType
-} from './types'
+ KMenuInstanceOption,
+ KMenuItemProps,
+ KMenuInstance,
+ KMenuProps,
+ SubMenuType
+} from './types';
diff --git a/components/Menu/src/item.svelte b/components/Menu/src/item.svelte
index b4ef87e2..ad037486 100644
--- a/components/Menu/src/item.svelte
+++ b/components/Menu/src/item.svelte
@@ -1,15 +1,54 @@
-{#each items as item (item.uid)}
-
- {#if item.type === 'divider'}
-
+{#each items as it (it.uid)}
+
+
+
+
+ {it.label}
+
+
-
- {/if}
-
+
+ {#if it.children && it.children.length}
+
+
+
+
+
+ {item.label}
+
+
+
+
+
+
+ {/if}
+
{/each}
+
diff --git a/components/Menu/src/types.d.ts b/components/Menu/src/types.d.ts
index 4b6a48ee..f608325f 100644
--- a/components/Menu/src/types.d.ts
+++ b/components/Menu/src/types.d.ts
@@ -1,70 +1,89 @@
///
import type { ClassValue } from 'clsx';
+export type KMenuInstanceOption = {
+ expandIcon?: string;
+ inlineIndent?: number;
+ inlineCollapsed?: number;
+ mode?: `vertical` | `horizontal` | `inline`;
+ openUids?: string[];
+ overflowedIndicator?: string;
+ selectedUids?: string[];
+ selectable?: boolean;
+ subMenuCloseDelay?: number;
+ subMenuOpenDelay?: number;
+ theme?: 'light' | 'dark';
+ triggerSubMenuAction?: 'hover' | 'click';
+}
+export type KMenuInstance = {
+ __propHandleEvtMap: Array<(props: Record) => void>
+ __dynamicProps: KMenuInstanceOption,
+}
+
export type KMenuProps = {
/**
* TODO: 🎯 展开图标
* @default 'i-carbon-chevron-down'
*/
- expandIcon?: string
+ expandIcon?: string;
/**
* TODO: inline 模式的菜单缩进宽度
* @default 24
*/
- inlineIndent?: number
+ inlineIndent?: number;
/**
* TODO: inline 时菜单是否收起状态 (指显示图标的mini模式和展开到常规模式)
* @default 24
*/
- inlineCollapsed?: number
+ inlineCollapsed?: number;
/**
* TODO: 🎯 菜单内容
*/
- items: KItemType[]
+ // items: KItemType[]
/**
* TODO: 🎯 菜单类型,现在支持垂直、水平、和内嵌模式三种
* `vertical` 和 `inline` 的区别在于 `vertical` 子菜单以 popover 形式出现
* @default `vertical`
*/
- mode?: `vertical` | `horizontal` | `inline`
+ mode?: `vertical` | `horizontal` | `inline`;
/**
* TODO: 当前展开的 SubMenu 菜单项 key 数组
* @default `[]`
*/
- openUids?: string[]
+ openUids?: string[];
/**
* TODO: 🎯 用于自定义 Menu 水平空间不足时的省略收缩的图标
*/
- overflowedIndicator?: string
+ overflowedIndicator?: string;
/**
* TODO: 当前选中的菜单项 key 数组
* @default `[]`
*/
- selectedUids?: string[]
+ selectedUids?: string[];
/**
* TODO: 是否允许选中(为 false, 仅不触发 select事件)
* @default false
*/
- selectable?: boolean
+ selectable?: boolean;
/**
* TODO: 🎯 用户鼠标离开子菜单后关闭延时,单位:毫秒
* @default 100ms
*/
- subMenuCloseDelay?: boolean
+ subMenuCloseDelay?: number;
/**
* TODO: 🎯 用户鼠标进入子菜单后开启延时,单位:毫秒
* @default 0
*/
- subMenuOpenDelay?: number
+ subMenuOpenDelay?: number;
/**
* TODO: 主题
* @default 'light'
*/
- theme?: 'light' | 'dark'
+ theme?: 'light' | 'dark';
/**
* TODO: 🎯 SubMenu 展开/关闭的触发行为(非 inline 模式)
* @default 'hover'
*/
- triggerSubMenuAction?: 'hover' | 'click'
+ triggerSubMenuAction?: 'hover' | 'click';
cls: ClassValue;
attrs: Record;
};
@@ -76,45 +95,48 @@ export type KMenuProps = {
// TODO: slots overflowedIndicator 用于自定义 Menu 水平空间不足时的省略收缩的图标
// TODO: slots expandIcon 展开图标
-export type KItemType = KMenuItemType
-
+export type KMenuItemProps = {
+ items: SubMenuType[]
+ cls: ClassValue;
+ attrs: Record;
+}
export type SubMenuType = {
/**
* TODO: 展示错误状态样式
* @default false
*/
- danger?: boolean,
- type?: 'group' | 'divider',
+ danger?: boolean;
+ type?: 'group' | 'divider';
/**
* TODO: 菜单图标
*/
- icon?: string
+ icon?: string;
/**
* TODO: 菜单项标题
*/
- label?: string
+ label?: string;
/**
* TODO: item 的唯一标志
*/
- uid?: string
+ uid?: string;
/**
* TODO: 是否禁用
* @default false
*/
- disabled?: boolean
+ disabled?: boolean;
/**
* TODO: 设置子菜单的主题,默认从 Menu 上继承
* @default 'light'
*/
- theme?: 'light' | 'dark'
+ theme?: 'light' | 'dark';
/**
* TODO: 子菜单的菜单项
*/
- children?: KItemType[]
+ children?: KItemType[];
/**
* TODO: 子菜单样式,mode="inline" 时无效
*/
- popupClassName?: string
+ popupClassName?: string;
};
// TODO: onTitleClick 点击子菜单标题
diff --git a/components/Menu/src/utils.ts b/components/Menu/src/utils.ts
new file mode 100644
index 00000000..7a2469b1
--- /dev/null
+++ b/components/Menu/src/utils.ts
@@ -0,0 +1,14 @@
+import type { KMenuInstance, KMenuInstanceOption } from "./types";
+
+
+export const createKMenu = (options: KMenuInstanceOption):KMenuInstance => {
+ return {
+ /**
+ * @internal
+ */
+ __propHandleEvtMap: [],
+ __dynamicProps: {
+ ...options
+ }
+ }
+}
diff --git a/utils/src/index.ts b/utils/src/index.ts
index 0b708508..8c1567ec 100644
--- a/utils/src/index.ts
+++ b/utils/src/index.ts
@@ -15,6 +15,7 @@ export {
tabsKey,
dropDownKey,
descriptionsKey,
- segmentedKey
+ segmentedKey,
+ menuKey,
} from './symbol-key';
export * from './dom';
diff --git a/utils/src/symbol-key.ts b/utils/src/symbol-key.ts
index 8cdc87bf..b67c2edd 100644
--- a/utils/src/symbol-key.ts
+++ b/utils/src/symbol-key.ts
@@ -20,3 +20,4 @@ export const dropDownKey = KSymbolKey('dropDown');
export const tabsKey = KSymbolKey('tabs');
export const descriptionsKey = KSymbolKey('descriptions');
export const segmentedKey = KSymbolKey('segmented');
+export const menuKey = KSymbolKey('menu');
From 8292b95d106a76deb29bed13d152cf35f23a86c3 Mon Sep 17 00:00:00 2001
From: baiwusanyu-c <740132583@qq.com>
Date: Tue, 16 Apr 2024 18:33:44 +0800
Subject: [PATCH 06/39] wip: initial drawing of menu component inline mode
---
components/Menu/package.json | 1 +
components/Menu/src/index.svelte | 18 ++-
components/Menu/src/item.svelte | 190 ++++++++++++++++++++++++-----
components/Menu/src/types.d.ts | 24 ++--
preset/src/rules/index.ts | 2 +
preset/src/rules/src/menu.ts | 7 ++
preset/src/shortcuts/src/common.ts | 1 +
preset/src/shortcuts/src/menu.ts | 33 ++++-
8 files changed, 234 insertions(+), 42 deletions(-)
create mode 100644 preset/src/rules/src/menu.ts
diff --git a/components/Menu/package.json b/components/Menu/package.json
index 34c658ac..bddd7f1e 100644
--- a/components/Menu/package.json
+++ b/components/Menu/package.json
@@ -34,6 +34,7 @@
"dependencies": {
"@ikun-ui/icon": "workspace:*",
"@ikun-ui/utils": "workspace:*",
+ "@ikun-ui/divider": "workspace:*",
"baiwusanyu-utils": "^1.0.18",
"clsx": "^2.0.0",
"svelte": "^4.2.7"
diff --git a/components/Menu/src/index.svelte b/components/Menu/src/index.svelte
index e5f008ce..30568432 100644
--- a/components/Menu/src/index.svelte
+++ b/components/Menu/src/index.svelte
@@ -7,7 +7,7 @@
export let triggerSubMenuAction: KMenuProps['triggerSubMenuAction'] = 'hover';
export let subMenuCloseDelay: KMenuProps['subMenuCloseDelay'] = 100;
export let subMenuOpenDelay: KMenuProps['subMenuOpenDelay'] = 0;
- // export let items: KMenuProps['items'] = [];
+ export let inlineIndent: KMenuProps['inlineIndent'] = 24
export let expandIcon: KMenuProps['expandIcon'] = 'i-carbon-chevron-down';
export let overflowedIndicator: KMenuProps['overflowedIndicator'] =
'i-carbon-overflow-menu-horizontal';
@@ -22,6 +22,9 @@
expandIcon,
overflowedIndicator,
mode,
+ inlineIndent,
+ cls,
+ attrs,
})
setContext(menuKey, menuInst);
$: {
@@ -33,14 +36,21 @@
expandIcon,
overflowedIndicator,
mode,
+ inlineIndent,
+ cls,
+ attrs,
});
});
}
const prefixCls = getPrefixCls('menu');
- $: cnames = clsx(prefixCls, cls);
+ $: cnames = clsx(
+ prefixCls,
+ `${prefixCls}-${mode}`,
+ cls
+ );
-
+
diff --git a/components/Menu/src/item.svelte b/components/Menu/src/item.svelte
index ad037486..a9f8b39e 100644
--- a/components/Menu/src/item.svelte
+++ b/components/Menu/src/item.svelte
@@ -1,54 +1,186 @@
-{#each items as it (it.uid)}
-
-
-
-
- {it.label}
-
-
-
-
- {#if it.children && it.children.length}
-
-
-
-
-
- {item.label}
-
-
+{#each itemsList as it (it.uid)}
+ {#if it.type !== 'divider'}
+ handleSelect(it)}
+ aria-hidden="true"
+ style:padding-left={`${(ctxProps.inlineIndent || 24 ) * getLevel(it, level)}px`}
+ class={cnames(it)}
+ {...$$restProps}
+ {...attrs}>
+
+
+
+ {#if it.icon}
+
+
+ {/if}
+
+ {it.label}
+
+ {#if hasSub(it) && !isGroup(it)}
+
+
+
-
-
+ {/if}
+
+
+
+
+
+ {#if (hasSub(it) && it.open) || isGroup(it)}
+
+
+
+
+
+
+
+
+ {#if item.icon}
+
+
+ {/if}
+
+ self {item.label}
+
+
+ {#if hasSub(item) && !isGroup(item)}
+
+
+
+
+ {/if}
+
+
+
+
+
+
{/if}
-
+ {:else}
+
+ {/if}
{/each}
diff --git a/components/Menu/src/types.d.ts b/components/Menu/src/types.d.ts
index f608325f..2c299914 100644
--- a/components/Menu/src/types.d.ts
+++ b/components/Menu/src/types.d.ts
@@ -3,7 +3,7 @@ import type { ClassValue } from 'clsx';
export type KMenuInstanceOption = {
expandIcon?: string;
inlineIndent?: number;
- inlineCollapsed?: number;
+ inlineCollapsed?: boolean;
mode?: `vertical` | `horizontal` | `inline`;
openUids?: string[];
overflowedIndicator?: string;
@@ -13,6 +13,8 @@ export type KMenuInstanceOption = {
subMenuOpenDelay?: number;
theme?: 'light' | 'dark';
triggerSubMenuAction?: 'hover' | 'click';
+ cls?: ClassValue;
+ attrs?: Record;
}
export type KMenuInstance = {
__propHandleEvtMap: Array<(props: Record) => void>
@@ -32,13 +34,9 @@ export type KMenuProps = {
inlineIndent?: number;
/**
* TODO: inline 时菜单是否收起状态 (指显示图标的mini模式和展开到常规模式)
- * @default 24
- */
- inlineCollapsed?: number;
- /**
- * TODO: 🎯 菜单内容
+ * @default false
*/
- // items: KItemType[]
+ inlineCollapsed?: boolean;
/**
* TODO: 🎯 菜单类型,现在支持垂直、水平、和内嵌模式三种
* `vertical` 和 `inline` 的区别在于 `vertical` 子菜单以 popover 形式出现
@@ -96,6 +94,10 @@ export type KMenuProps = {
// TODO: slots expandIcon 展开图标
export type KMenuItemProps = {
+ /**
+ * @internal
+ */
+ level: number
items: SubMenuType[]
cls: ClassValue;
attrs: Record;
@@ -132,14 +134,20 @@ export type SubMenuType = {
/**
* TODO: 子菜单的菜单项
*/
- children?: KItemType[];
+ children?: SubMenuType[];
/**
* TODO: 子菜单样式,mode="inline" 时无效
*/
popupClassName?: string;
+ [property: string]: any
};
// TODO: onTitleClick 点击子菜单标题
// TODO: Items Slots slots label 分组标题
// TODO: Items Slots slots icon 菜单图标
+
+
+// TODO: 高度动画
+// TODO: 缩略文字
+// TODO: 背景色随着层级加深
diff --git a/preset/src/rules/index.ts b/preset/src/rules/index.ts
index 41fd9015..456907d8 100644
--- a/preset/src/rules/index.ts
+++ b/preset/src/rules/index.ts
@@ -18,6 +18,7 @@ import { carouselRules } from './src/carousel';
import { skeletonRules } from './src/skeleton';
import { colorPickerRules } from './src/color-picker';
import { timelineRules } from './src/timeline';
+import { menuRules } from './src/menu';
import { baseRules } from './src/base';
declare type dynamicRulesFunc = (...args: any[]) => Array any)>;
@@ -34,6 +35,7 @@ export const defaultRules = {
...carouselRules,
...skeletonRules,
...colorPickerRules,
+ ...menuRules,
...timelineRules,
...baseRules,
...getColCls(),
diff --git a/preset/src/rules/src/menu.ts b/preset/src/rules/src/menu.ts
new file mode 100644
index 00000000..488b3940
--- /dev/null
+++ b/preset/src/rules/src/menu.ts
@@ -0,0 +1,7 @@
+export const menuRules = {
+ 'k-menu-w': { width: 'calc(100% - 8px)' },
+ 'k-menu-transition-c': { transition: 'color 0.3s' },
+ 'k-menu-transition-o': { transition: 'opacity 0.3s cubic-bezier(0.645, 0.045, 0.355, 1),margin 0.3s,color 0.3s' },
+ 'k-menu-transition-w': { transition: 'width 0.3s cubic-bezier(0.2, 0, 0, 1) 0s' },
+ 'k-menu-transition': { transition: 'border-color 0.3s,background 0.3s,padding 0.3s cubic-bezier(0.645, 0.045, 0.355, 1)' },
+};
diff --git a/preset/src/shortcuts/src/common.ts b/preset/src/shortcuts/src/common.ts
index 36540024..44f00c14 100644
--- a/preset/src/shortcuts/src/common.ts
+++ b/preset/src/shortcuts/src/common.ts
@@ -29,6 +29,7 @@ export const commonShortcuts: UserShortcuts = {
infcc: 'inline-flex justify-center items-center',
'bd-1': 'border-t-1 border-l-1 border-b-1 border-r-1',
'bdt-1': 'border-t-1 border-l-0 border-b-0 border-r-0',
+ 'bdr-1': 'border-t-0 border-l-0 border-b-0 border-r-1',
'bdl-1': 'border-l-1 border-t-0 border-b-0 border-r-0',
'bdb-1': 'border-l-0 border-t-0 border-b-1 border-r-0',
'bdlb-1': 'border-l-1 border-t-0 border-b-1 border-r-0',
diff --git a/preset/src/shortcuts/src/menu.ts b/preset/src/shortcuts/src/menu.ts
index 624f842e..bd91ca5a 100644
--- a/preset/src/shortcuts/src/menu.ts
+++ b/preset/src/shortcuts/src/menu.ts
@@ -1,3 +1,34 @@
export const menuShortcuts: Record = {
- 'k-menu': ''
+ 'k-menu': 'bg-white text-ikun-tx-base p-0 m-0 box-border text-14px leading-0 list-none outline-none focus:outline-none k-menu-transition-w',
+ 'k-menu-item': 'box-border',
+ 'k-menu-item-icon': 'inline-flex text-inherit items-center leading-0',
+ 'k-menu-title-content': 'box-border k-menu-transition-c',
+ 'k-menu-title-content-i': 'm-is-10px k-menu-transition-o opacity-[1]',
+ 'k-menu-item-divider': 'my-0',
+
+
+
+ 'k-menu-sub': 'border-none',
+
+
+ 'k-menu-horizontal': '',
+ 'k-menu-item-horizontal': '',
+
+
+
+
+
+ 'k-menu-item-selected': 'ikun:20:bg-ikun-main text-ikun-main hover:(ikun:20:bg-ikun-main)',
+ 'k-menu-item-hover-ih': 'hover:(ikun:6:bg-ikun-black)',
+ 'k-menu-item-vh-child': 'justify-between',
+
+ 'k-menu-inline': 'bdr-1 b-e-solid border-ikun-bd-base',
+ 'k-menu-vertical': 'bdr-1 b-e-solid border-ikun-bd-base',
+ 'k-menu-item-vertical': '',
+ 'k-menu-item-inline': 'cursor-pointer k-menu-w k-menu-transition ' +
+ 'flex items-center pr h-40px leading-40px list-style-position truncate ps-16px p-ie-16px m-is-4px m-ie-4px m-bs-4px m-be-4px ' +
+ 'rounded-8px active:(ikun:20:bg-ikun-main)',
+ 'k-menu-item-inline-group': 'k-menu-w k-menu-transition ' +
+ 'flex items-center pr h-40px leading-40px list-style-position truncate ps-16px p-ie-16px m-is-4px m-ie-4px m-bs-4px m-be-4px ' +
+ 'rounded-8px ikun:50:text-black',
};
From f1f00c5abcb1ee3b20ed365977992bf0c04b8a05 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E7=99=BD=E9=9B=BE=E4=B8=89=E8=AF=AD?=
<32354856+baiwusanyu-c@users.noreply.github.com>
Date: Tue, 16 Apr 2024 22:34:59 +0800
Subject: [PATCH 07/39] wip: KMenu component completes submenu expansion
animation
---
components/Menu/src/index.svelte | 29 ++---
components/Menu/src/index.ts | 10 +-
components/Menu/src/item.svelte | 205 +++++++++++++------------------
components/Menu/src/types.d.ts | 23 ++--
components/Menu/src/utils.ts | 55 +++++++--
preset/src/rules/src/menu.ts | 15 ++-
preset/src/shortcuts/src/menu.ts | 20 ++-
utils/src/index.ts | 2 +-
8 files changed, 182 insertions(+), 177 deletions(-)
diff --git a/components/Menu/src/index.svelte b/components/Menu/src/index.svelte
index 30568432..022c1158 100644
--- a/components/Menu/src/index.svelte
+++ b/components/Menu/src/index.svelte
@@ -3,18 +3,21 @@
import { clsx } from 'clsx';
import type { KMenuProps } from './types';
import { setContext } from 'svelte';
- import { createKMenu } from "./utils";
+ import { createKMenu, transitionIn, transitionOut } from './utils';
export let triggerSubMenuAction: KMenuProps['triggerSubMenuAction'] = 'hover';
export let subMenuCloseDelay: KMenuProps['subMenuCloseDelay'] = 100;
export let subMenuOpenDelay: KMenuProps['subMenuOpenDelay'] = 0;
- export let inlineIndent: KMenuProps['inlineIndent'] = 24
+ export let inlineIndent: KMenuProps['inlineIndent'] = 24;
export let expandIcon: KMenuProps['expandIcon'] = 'i-carbon-chevron-down';
export let overflowedIndicator: KMenuProps['overflowedIndicator'] =
'i-carbon-overflow-menu-horizontal';
export let mode: KMenuProps['mode'] = 'vertical';
export let cls: KMenuProps['cls'] = undefined;
export let attrs: KMenuProps['attrs'] = {};
-
+ export let show: KMenuProps['show'] = true;
+ /**
+ * @internal
+ */
const menuInst = createKMenu({
triggerSubMenuAction,
subMenuCloseDelay,
@@ -24,8 +27,8 @@
mode,
inlineIndent,
cls,
- attrs,
- })
+ attrs
+ });
setContext(menuKey, menuInst);
$: {
menuInst.__propHandleEvtMap.forEach((cb) => {
@@ -38,19 +41,17 @@
mode,
inlineIndent,
cls,
- attrs,
+ attrs
});
});
}
const prefixCls = getPrefixCls('menu');
- $: cnames = clsx(
- prefixCls,
- `${prefixCls}-${mode}`,
- cls
- );
+ $: cnames = clsx(prefixCls, `${prefixCls}-${mode}`, cls);
-
+{#if show}
+
+{/if}
diff --git a/components/Menu/src/index.ts b/components/Menu/src/index.ts
index acb9e54b..f63e955e 100644
--- a/components/Menu/src/index.ts
+++ b/components/Menu/src/index.ts
@@ -6,9 +6,9 @@ export { MenuItem as KMenuItem };
export default Menu;
export type {
- KMenuInstanceOption,
- KMenuItemProps,
- KMenuInstance,
- KMenuProps,
- SubMenuType
+ KMenuInstanceOption,
+ KMenuItemProps,
+ KMenuInstance,
+ KMenuProps,
+ SubMenuType
} from './types';
diff --git a/components/Menu/src/item.svelte b/components/Menu/src/item.svelte
index a9f8b39e..6d2d4a1e 100644
--- a/components/Menu/src/item.svelte
+++ b/components/Menu/src/item.svelte
@@ -1,76 +1,61 @@
{#each itemsList as it (it.uid)}
@@ -111,19 +102,16 @@
handleSelect(it)}
aria-hidden="true"
- style:padding-left={`${(ctxProps.inlineIndent || 24 ) * getLevel(it, level)}px`}
+ style:padding-left={`${(ctxProps.inlineIndent || 24) * getLevel(it, level)}px`}
class={cnames(it)}
{...$$restProps}
- {...attrs}>
+ {...attrs}
+ >
{#if it.icon}
-
-
+
{/if}
{it.label}
@@ -131,56 +119,35 @@
{#if hasSub(it) && !isGroup(it)}
-
-
+
{/if}
-
-
-
- {#if (hasSub(it) && it.open) || isGroup(it)}
-
-
-
-
-
-
-
-
- {#if item.icon}
-
-
- {/if}
-
- self {item.label}
-
-
- {#if hasSub(item) && !isGroup(item)}
-
-
-
-
- {/if}
-
-
-
-
-
-
- {/if}
- {:else}
+
+
+
+
+
+
+
+ {#if item.icon}
+
+ {/if}
+
+ self {item.label}
+
+
+ {#if hasSub(item) && !isGroup(item)}
+
+
+
+ {/if}
+
+
+
+
+ {:else}
{/if}
{/each}
-
diff --git a/components/Menu/src/types.d.ts b/components/Menu/src/types.d.ts
index 2c299914..fa64d3df 100644
--- a/components/Menu/src/types.d.ts
+++ b/components/Menu/src/types.d.ts
@@ -15,11 +15,11 @@ export type KMenuInstanceOption = {
triggerSubMenuAction?: 'hover' | 'click';
cls?: ClassValue;
attrs?: Record
;
-}
+};
export type KMenuInstance = {
- __propHandleEvtMap: Array<(props: Record) => void>
- __dynamicProps: KMenuInstanceOption,
-}
+ __propHandleEvtMap: Array<(props: Record) => void>;
+ __dynamicProps: KMenuInstanceOption;
+};
export type KMenuProps = {
/**
@@ -82,6 +82,10 @@ export type KMenuProps = {
* @default 'hover'
*/
triggerSubMenuAction?: 'hover' | 'click';
+ /**
+ * @internal
+ */
+ show: boolean;
cls: ClassValue;
attrs: Record;
};
@@ -97,11 +101,11 @@ export type KMenuItemProps = {
/**
* @internal
*/
- level: number
- items: SubMenuType[]
+ level: number;
+ items: SubMenuType[];
cls: ClassValue;
attrs: Record;
-}
+};
export type SubMenuType = {
/**
* TODO: 展示错误状态样式
@@ -139,7 +143,7 @@ export type SubMenuType = {
* TODO: 子菜单样式,mode="inline" 时无效
*/
popupClassName?: string;
- [property: string]: any
+ [property: string]: any;
};
// TODO: onTitleClick 点击子菜单标题
@@ -147,7 +151,6 @@ export type SubMenuType = {
// TODO: Items Slots slots label 分组标题
// TODO: Items Slots slots icon 菜单图标
-
-// TODO: 高度动画
// TODO: 缩略文字
// TODO: 背景色随着层级加深
+// TODO: 菜单样式
diff --git a/components/Menu/src/utils.ts b/components/Menu/src/utils.ts
index 7a2469b1..2aa786a6 100644
--- a/components/Menu/src/utils.ts
+++ b/components/Menu/src/utils.ts
@@ -1,14 +1,47 @@
-import type { KMenuInstance, KMenuInstanceOption } from "./types";
+import type { KMenuInstance, KMenuInstanceOption } from './types';
+export const createKMenu = (options: KMenuInstanceOption): KMenuInstance => {
+ return {
+ /**
+ * @internal
+ */
+ __propHandleEvtMap: [],
+ __dynamicProps: {
+ ...options
+ }
+ };
+};
-export const createKMenu = (options: KMenuInstanceOption):KMenuInstance => {
- return {
- /**
- * @internal
- */
- __propHandleEvtMap: [],
- __dynamicProps: {
- ...options
- }
- }
+export function transitionIn(node: HTMLElement) {
+ return {
+ duration: 300,
+ tick: (t: number) => {
+ if (t === 0) {
+ node.style.overflow = 'hidden';
+ node.style.transition = 'height 0.3s';
+ node.style.height = '0';
+ } else if (t === 100) {
+ node.style.removeProperty('height');
+ } else {
+ node.style.height = node.scrollHeight + 'px';
+ }
+ }
+ };
+}
+
+export function transitionOut(node: HTMLElement) {
+ return {
+ duration: 300,
+ tick: (t: number) => {
+ if (t === 0) {
+ node.style.overflow = 'hidden';
+ node.style.transition = 'height 0.3s';
+ node.style.height = node.scrollHeight + 'px';
+ } else if (t === 100) {
+ node.style.removeProperty('height');
+ } else {
+ node.style.height = '0';
+ }
+ }
+ };
}
diff --git a/preset/src/rules/src/menu.ts b/preset/src/rules/src/menu.ts
index 488b3940..86ec9cd6 100644
--- a/preset/src/rules/src/menu.ts
+++ b/preset/src/rules/src/menu.ts
@@ -1,7 +1,12 @@
export const menuRules = {
- 'k-menu-w': { width: 'calc(100% - 8px)' },
- 'k-menu-transition-c': { transition: 'color 0.3s' },
- 'k-menu-transition-o': { transition: 'opacity 0.3s cubic-bezier(0.645, 0.045, 0.355, 1),margin 0.3s,color 0.3s' },
- 'k-menu-transition-w': { transition: 'width 0.3s cubic-bezier(0.2, 0, 0, 1) 0s' },
- 'k-menu-transition': { transition: 'border-color 0.3s,background 0.3s,padding 0.3s cubic-bezier(0.645, 0.045, 0.355, 1)' },
+ 'k-menu-w': { width: 'calc(100% - 8px)' },
+ 'k-menu-transition-c': { transition: 'color 0.3s' },
+ 'k-menu-transition-o': {
+ transition: 'opacity 0.3s cubic-bezier(0.645, 0.045, 0.355, 1),margin 0.3s,color 0.3s'
+ },
+ 'k-menu-transition-w': { transition: 'width 0.3s cubic-bezier(0.2, 0, 0, 1) 0s' },
+ 'k-menu-transition': {
+ transition:
+ 'border-color 0.3s,background 0.3s,padding 0.3s cubic-bezier(0.645, 0.045, 0.355, 1)'
+ }
};
diff --git a/preset/src/shortcuts/src/menu.ts b/preset/src/shortcuts/src/menu.ts
index bd91ca5a..36c525ed 100644
--- a/preset/src/shortcuts/src/menu.ts
+++ b/preset/src/shortcuts/src/menu.ts
@@ -1,23 +1,17 @@
export const menuShortcuts: Record = {
- 'k-menu': 'bg-white text-ikun-tx-base p-0 m-0 box-border text-14px leading-0 list-none outline-none focus:outline-none k-menu-transition-w',
- 'k-menu-item': 'box-border',
+ 'k-menu':
+ 'bg-white text-ikun-tx-base p-0 m-0 box-border text-14px leading-0 list-none outline-none focus:outline-none k-menu-transition-w',
+ 'k-menu-item': 'box-border select-none',
'k-menu-item-icon': 'inline-flex text-inherit items-center leading-0',
'k-menu-title-content': 'box-border k-menu-transition-c',
'k-menu-title-content-i': 'm-is-10px k-menu-transition-o opacity-[1]',
'k-menu-item-divider': 'my-0',
-
-
'k-menu-sub': 'border-none',
-
'k-menu-horizontal': '',
'k-menu-item-horizontal': '',
-
-
-
-
'k-menu-item-selected': 'ikun:20:bg-ikun-main text-ikun-main hover:(ikun:20:bg-ikun-main)',
'k-menu-item-hover-ih': 'hover:(ikun:6:bg-ikun-black)',
'k-menu-item-vh-child': 'justify-between',
@@ -25,10 +19,12 @@ export const menuShortcuts: Record = {
'k-menu-inline': 'bdr-1 b-e-solid border-ikun-bd-base',
'k-menu-vertical': 'bdr-1 b-e-solid border-ikun-bd-base',
'k-menu-item-vertical': '',
- 'k-menu-item-inline': 'cursor-pointer k-menu-w k-menu-transition ' +
+ 'k-menu-item-inline':
+ 'cursor-pointer k-menu-w k-menu-transition ' +
'flex items-center pr h-40px leading-40px list-style-position truncate ps-16px p-ie-16px m-is-4px m-ie-4px m-bs-4px m-be-4px ' +
'rounded-8px active:(ikun:20:bg-ikun-main)',
- 'k-menu-item-inline-group': 'k-menu-w k-menu-transition ' +
+ 'k-menu-item-inline-group':
+ 'k-menu-w k-menu-transition ' +
'flex items-center pr h-40px leading-40px list-style-position truncate ps-16px p-ie-16px m-is-4px m-ie-4px m-bs-4px m-be-4px ' +
- 'rounded-8px ikun:50:text-black',
+ 'rounded-8px ikun:50:text-black'
};
diff --git a/utils/src/index.ts b/utils/src/index.ts
index 8c1567ec..7d2a5ee1 100644
--- a/utils/src/index.ts
+++ b/utils/src/index.ts
@@ -16,6 +16,6 @@ export {
dropDownKey,
descriptionsKey,
segmentedKey,
- menuKey,
+ menuKey
} from './symbol-key';
export * from './dom';
From 2ba32332d99cde9f4f418f75b388e2a3eafb44cd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E7=99=BD=E9=9B=BE=E4=B8=89=E8=AF=AD?=
<32354856+baiwusanyu-c@users.noreply.github.com>
Date: Tue, 16 Apr 2024 23:35:28 +0800
Subject: [PATCH 08/39] wip: KMenu component completes submenu expansion
animation
---
components/Menu/src/item.svelte | 38 +++++++++++++++++---------------
components/Menu/src/types.d.ts | 1 -
preset/src/shortcuts/src/menu.ts | 10 ++++-----
3 files changed, 25 insertions(+), 24 deletions(-)
diff --git a/components/Menu/src/item.svelte b/components/Menu/src/item.svelte
index 6d2d4a1e..05adb2c3 100644
--- a/components/Menu/src/item.svelte
+++ b/components/Menu/src/item.svelte
@@ -108,18 +108,19 @@
{...attrs}
>
-
-
- {#if it.icon}
-
- {/if}
-
- {it.label}
-
+
+ {#if it.icon}
+
+ {/if}
+
+ {it.label}
{#if hasSub(it) && !isGroup(it)}
-
+
{/if}
@@ -129,18 +130,19 @@
-
-
- {#if item.icon}
-
- {/if}
-
- self {item.label}
-
+
+ {#if item.icon}
+
+ {/if}
+
+ self {item.label}
{#if hasSub(item) && !isGroup(item)}
-
+
{/if}
diff --git a/components/Menu/src/types.d.ts b/components/Menu/src/types.d.ts
index fa64d3df..1a4cff35 100644
--- a/components/Menu/src/types.d.ts
+++ b/components/Menu/src/types.d.ts
@@ -151,6 +151,5 @@ export type SubMenuType = {
// TODO: Items Slots slots label 分组标题
// TODO: Items Slots slots icon 菜单图标
-// TODO: 缩略文字
// TODO: 背景色随着层级加深
// TODO: 菜单样式
diff --git a/preset/src/shortcuts/src/menu.ts b/preset/src/shortcuts/src/menu.ts
index 36c525ed..207a0b7f 100644
--- a/preset/src/shortcuts/src/menu.ts
+++ b/preset/src/shortcuts/src/menu.ts
@@ -2,9 +2,9 @@ export const menuShortcuts: Record = {
'k-menu':
'bg-white text-ikun-tx-base p-0 m-0 box-border text-14px leading-0 list-none outline-none focus:outline-none k-menu-transition-w',
'k-menu-item': 'box-border select-none',
- 'k-menu-item-icon': 'inline-flex text-inherit items-center leading-0',
- 'k-menu-title-content': 'box-border k-menu-transition-c',
- 'k-menu-title-content-i': 'm-is-10px k-menu-transition-o opacity-[1]',
+ 'k-menu-item-icon': 'inline-flex text-inherit items-center leading-0 min-w-14px',
+ 'k-menu-title-content': 'truncate box-border k-menu-transition-c',
+ 'k-menu-title-content-i': 'm-is-6px m-ie-6px k-menu-transition-o opacity-[1] truncate',
'k-menu-item-divider': 'my-0',
'k-menu-sub': 'border-none',
@@ -21,10 +21,10 @@ export const menuShortcuts: Record = {
'k-menu-item-vertical': '',
'k-menu-item-inline':
'cursor-pointer k-menu-w k-menu-transition ' +
- 'flex items-center pr h-40px leading-40px list-style-position truncate ps-16px p-ie-16px m-is-4px m-ie-4px m-bs-4px m-be-4px ' +
+ 'flex items-center pr h-40px leading-40px list-style-position ps-16px p-ie-16px m-is-4px m-ie-4px m-bs-4px m-be-4px ' +
'rounded-8px active:(ikun:20:bg-ikun-main)',
'k-menu-item-inline-group':
'k-menu-w k-menu-transition ' +
- 'flex items-center pr h-40px leading-40px list-style-position truncate ps-16px p-ie-16px m-is-4px m-ie-4px m-bs-4px m-be-4px ' +
+ 'flex items-center pr h-40px leading-40px list-style-position ps-16px p-ie-16px m-is-4px m-ie-4px m-bs-4px m-be-4px ' +
'rounded-8px ikun:50:text-black'
};
From ea22ff81a2c1d04473e7cde60eb4c666e05515d6 Mon Sep 17 00:00:00 2001
From: baiwusanyu-c <740132583@qq.com>
Date: Wed, 17 Apr 2024 09:20:22 +0800
Subject: [PATCH 09/39] wip: fix expend animation
---
components/Menu/src/index.svelte | 4 ----
components/Menu/src/types.d.ts | 10 ++--------
components/Menu/src/utils.ts | 11 +++++------
3 files changed, 7 insertions(+), 18 deletions(-)
diff --git a/components/Menu/src/index.svelte b/components/Menu/src/index.svelte
index 022c1158..014dc5ce 100644
--- a/components/Menu/src/index.svelte
+++ b/components/Menu/src/index.svelte
@@ -9,8 +9,6 @@
export let subMenuOpenDelay: KMenuProps['subMenuOpenDelay'] = 0;
export let inlineIndent: KMenuProps['inlineIndent'] = 24;
export let expandIcon: KMenuProps['expandIcon'] = 'i-carbon-chevron-down';
- export let overflowedIndicator: KMenuProps['overflowedIndicator'] =
- 'i-carbon-overflow-menu-horizontal';
export let mode: KMenuProps['mode'] = 'vertical';
export let cls: KMenuProps['cls'] = undefined;
export let attrs: KMenuProps['attrs'] = {};
@@ -23,7 +21,6 @@
subMenuCloseDelay,
subMenuOpenDelay,
expandIcon,
- overflowedIndicator,
mode,
inlineIndent,
cls,
@@ -37,7 +34,6 @@
subMenuCloseDelay,
subMenuOpenDelay,
expandIcon,
- overflowedIndicator,
mode,
inlineIndent,
cls,
diff --git a/components/Menu/src/types.d.ts b/components/Menu/src/types.d.ts
index 1a4cff35..c37c971d 100644
--- a/components/Menu/src/types.d.ts
+++ b/components/Menu/src/types.d.ts
@@ -6,7 +6,6 @@ export type KMenuInstanceOption = {
inlineCollapsed?: boolean;
mode?: `vertical` | `horizontal` | `inline`;
openUids?: string[];
- overflowedIndicator?: string;
selectedUids?: string[];
selectable?: boolean;
subMenuCloseDelay?: number;
@@ -23,12 +22,12 @@ export type KMenuInstance = {
export type KMenuProps = {
/**
- * TODO: 🎯 展开图标
+ * TODO: 👀 展开图标
* @default 'i-carbon-chevron-down'
*/
expandIcon?: string;
/**
- * TODO: inline 模式的菜单缩进宽度
+ * TODO: 👀 inline 模式的菜单缩进宽度
* @default 24
*/
inlineIndent?: number;
@@ -48,10 +47,6 @@ export type KMenuProps = {
* @default `[]`
*/
openUids?: string[];
- /**
- * TODO: 🎯 用于自定义 Menu 水平空间不足时的省略收缩的图标
- */
- overflowedIndicator?: string;
/**
* TODO: 当前选中的菜单项 key 数组
* @default `[]`
@@ -94,7 +89,6 @@ export type KMenuProps = {
// TODO: onOpenChange SubMenu 展开/关闭的回调
// TODO: onSelect 被选中时调用(点击子菜单标题不触发)
-// TODO: slots overflowedIndicator 用于自定义 Menu 水平空间不足时的省略收缩的图标
// TODO: slots expandIcon 展开图标
export type KMenuItemProps = {
diff --git a/components/Menu/src/utils.ts b/components/Menu/src/utils.ts
index 2aa786a6..e582f738 100644
--- a/components/Menu/src/utils.ts
+++ b/components/Menu/src/utils.ts
@@ -20,7 +20,7 @@ export function transitionIn(node: HTMLElement) {
node.style.overflow = 'hidden';
node.style.transition = 'height 0.3s';
node.style.height = '0';
- } else if (t === 100) {
+ } else if (t === 1) {
node.style.removeProperty('height');
} else {
node.style.height = node.scrollHeight + 'px';
@@ -30,14 +30,13 @@ export function transitionIn(node: HTMLElement) {
}
export function transitionOut(node: HTMLElement) {
+ const orgHeight = node.scrollHeight
return {
duration: 300,
tick: (t: number) => {
- if (t === 0) {
- node.style.overflow = 'hidden';
- node.style.transition = 'height 0.3s';
- node.style.height = node.scrollHeight + 'px';
- } else if (t === 100) {
+ if (t <= 1 && t >= 0.9) {
+ node.style.height = orgHeight + 'px';
+ } else if (t === 0) {
node.style.removeProperty('height');
} else {
node.style.height = '0';
From f6255544d1eef2ffe59fdb29b1d758d488dc6b56 Mon Sep 17 00:00:00 2001
From: baiwusanyu-c <740132583@qq.com>
Date: Wed, 17 Apr 2024 10:37:10 +0800
Subject: [PATCH 10/39] wip: complete the selected style of the KMenu component
submenu
---
components/Menu/src/item.svelte | 49 ++++++++++++++++++++++++++++----
components/Menu/src/types.d.ts | 29 +++++++++++++++----
preset/src/shortcuts/src/menu.ts | 3 +-
3 files changed, 70 insertions(+), 11 deletions(-)
diff --git a/components/Menu/src/item.svelte b/components/Menu/src/item.svelte
index 05adb2c3..9c64240d 100644
--- a/components/Menu/src/item.svelte
+++ b/components/Menu/src/item.svelte
@@ -1,5 +1,5 @@
-{#each itemsList as it (it.uid)}
+{#each itemsList as it, index (it.uid)}
{#if it.type !== 'divider'}
handleSelect(it)}
@@ -127,7 +163,10 @@
-
+ handleSelectedRecursion(e, index)}
+ items={it.children}
+ level={getLevel(it, level) + 1}>
diff --git a/components/Menu/src/types.d.ts b/components/Menu/src/types.d.ts
index c37c971d..6eeeca44 100644
--- a/components/Menu/src/types.d.ts
+++ b/components/Menu/src/types.d.ts
@@ -106,17 +106,20 @@ export type SubMenuType = {
* @default false
*/
danger?: boolean;
+ /**
+ * TODO: 👀 展示為分組或分割綫
+ */
type?: 'group' | 'divider';
/**
- * TODO: 菜单图标
+ * TODO: 👀 菜单图标
*/
icon?: string;
/**
- * TODO: 菜单项标题
+ * TODO: 👀 菜单项标题
*/
label?: string;
/**
- * TODO: item 的唯一标志
+ * TODO: 👀 item 的唯一标志
*/
uid?: string;
/**
@@ -130,13 +133,29 @@ export type SubMenuType = {
*/
theme?: 'light' | 'dark';
/**
- * TODO: 子菜单的菜单项
+ * TODO: 设置收缩时展示的悬浮标题(无子菜单情况下生效,不传时默认为 label)
+ */
+ title?: string
+ /**
+ * TODO: 👀 子菜单的菜单项
*/
children?: SubMenuType[];
/**
* TODO: 子菜单样式,mode="inline" 时无效
*/
popupClassName?: string;
+ /**
+ * @internal
+ */
+ selected?: boolean
+ /**
+ * @internal
+ */
+ open?: boolean
+ /**
+ * @internal
+ */
+ selectedDeps: Set
[property: string]: any;
};
@@ -146,4 +165,4 @@ export type SubMenuType = {
// TODO: Items Slots slots icon 菜单图标
// TODO: 背景色随着层级加深
-// TODO: 菜单样式
+
diff --git a/preset/src/shortcuts/src/menu.ts b/preset/src/shortcuts/src/menu.ts
index 207a0b7f..26c20317 100644
--- a/preset/src/shortcuts/src/menu.ts
+++ b/preset/src/shortcuts/src/menu.ts
@@ -3,7 +3,7 @@ export const menuShortcuts: Record = {
'bg-white text-ikun-tx-base p-0 m-0 box-border text-14px leading-0 list-none outline-none focus:outline-none k-menu-transition-w',
'k-menu-item': 'box-border select-none',
'k-menu-item-icon': 'inline-flex text-inherit items-center leading-0 min-w-14px',
- 'k-menu-title-content': 'truncate box-border k-menu-transition-c',
+ 'k-menu-title-content': 'truncate box-border k-menu-transition-c select-none',
'k-menu-title-content-i': 'm-is-6px m-ie-6px k-menu-transition-o opacity-[1] truncate',
'k-menu-item-divider': 'my-0',
@@ -13,6 +13,7 @@ export const menuShortcuts: Record = {
'k-menu-item-horizontal': '',
'k-menu-item-selected': 'ikun:20:bg-ikun-main text-ikun-main hover:(ikun:20:bg-ikun-main)',
+ 'k-menu-item-selected-ih': 'text-ikun-main',
'k-menu-item-hover-ih': 'hover:(ikun:6:bg-ikun-black)',
'k-menu-item-vh-child': 'justify-between',
From 9f39ad660d3cefb60b3fbe9b11b40ad9fa95cbf9 Mon Sep 17 00:00:00 2001
From: baiwusanyu-c <740132583@qq.com>
Date: Wed, 17 Apr 2024 10:58:13 +0800
Subject: [PATCH 11/39] wip: KMenu component completes incremental changes in
submenu background color
---
components/Menu/src/index.svelte | 2 --
components/Menu/src/item.svelte | 11 +++++++++--
components/Menu/src/types.d.ts | 4 +---
preset/src/shortcuts/src/menu.ts | 5 ++++-
4 files changed, 14 insertions(+), 8 deletions(-)
diff --git a/components/Menu/src/index.svelte b/components/Menu/src/index.svelte
index 014dc5ce..c2917811 100644
--- a/components/Menu/src/index.svelte
+++ b/components/Menu/src/index.svelte
@@ -23,7 +23,6 @@
expandIcon,
mode,
inlineIndent,
- cls,
attrs
});
setContext(menuKey, menuInst);
@@ -36,7 +35,6 @@
expandIcon,
mode,
inlineIndent,
- cls,
attrs
});
});
diff --git a/components/Menu/src/item.svelte b/components/Menu/src/item.svelte
index 9c64240d..2c19eb5b 100644
--- a/components/Menu/src/item.svelte
+++ b/components/Menu/src/item.svelte
@@ -130,7 +130,14 @@
});
};
const dividerCls = clsx(`${prefixCls}-divider`);
- $: subMenuCls = clsx(`${menuPrefixCls}-sub`, ctxProps.cls);
+ const subMenuCls = (isGroup: boolean) => {
+ return clsx(
+ `${menuPrefixCls}-sub`,
+ {
+ [`${menuPrefixCls}-sub-bg`]: !isGroup
+ }
+ );
+ }
{#each itemsList as it, index (it.uid)}
@@ -162,7 +169,7 @@
-
+
handleSelectedRecursion(e, index)}
items={it.children}
diff --git a/components/Menu/src/types.d.ts b/components/Menu/src/types.d.ts
index 6eeeca44..a7b72501 100644
--- a/components/Menu/src/types.d.ts
+++ b/components/Menu/src/types.d.ts
@@ -12,7 +12,6 @@ export type KMenuInstanceOption = {
subMenuOpenDelay?: number;
theme?: 'light' | 'dark';
triggerSubMenuAction?: 'hover' | 'click';
- cls?: ClassValue;
attrs?: Record;
};
export type KMenuInstance = {
@@ -155,7 +154,7 @@ export type SubMenuType = {
/**
* @internal
*/
- selectedDeps: Set
+ selectedDeps?: Set
[property: string]: any;
};
@@ -164,5 +163,4 @@ export type SubMenuType = {
// TODO: Items Slots slots label 分组标题
// TODO: Items Slots slots icon 菜单图标
-// TODO: 背景色随着层级加深
diff --git a/preset/src/shortcuts/src/menu.ts b/preset/src/shortcuts/src/menu.ts
index 26c20317..29c5e6b9 100644
--- a/preset/src/shortcuts/src/menu.ts
+++ b/preset/src/shortcuts/src/menu.ts
@@ -1,13 +1,16 @@
export const menuShortcuts: Record = {
'k-menu':
'bg-white text-ikun-tx-base p-0 m-0 box-border text-14px leading-0 list-none outline-none focus:outline-none k-menu-transition-w',
+
+
'k-menu-item': 'box-border select-none',
'k-menu-item-icon': 'inline-flex text-inherit items-center leading-0 min-w-14px',
'k-menu-title-content': 'truncate box-border k-menu-transition-c select-none',
'k-menu-title-content-i': 'm-is-6px m-ie-6px k-menu-transition-o opacity-[1] truncate',
'k-menu-item-divider': 'my-0',
- 'k-menu-sub': 'border-none',
+ 'k-menu-sub': 'border-none bg-transparent',
+ 'k-menu-sub-bg': 'ikun:2:bg-black',
'k-menu-horizontal': '',
'k-menu-item-horizontal': '',
From f05ed4404daaa09d4d7e60cd8ba22cda61b238d9 Mon Sep 17 00:00:00 2001
From: baiwusanyu-c <740132583@qq.com>
Date: Wed, 17 Apr 2024 11:45:00 +0800
Subject: [PATCH 12/39] wip: KMenu component completes inline mode default
submenu expansion
---
components/Menu/src/index.svelte | 11 +++++++-
components/Menu/src/item.svelte | 34 ++++++++++++++--------
components/Menu/src/types.d.ts | 48 +++++++++++++++++++++-----------
components/Menu/src/utils.ts | 2 --
4 files changed, 64 insertions(+), 31 deletions(-)
diff --git a/components/Menu/src/index.svelte b/components/Menu/src/index.svelte
index c2917811..56727401 100644
--- a/components/Menu/src/index.svelte
+++ b/components/Menu/src/index.svelte
@@ -12,6 +12,8 @@
export let mode: KMenuProps['mode'] = 'vertical';
export let cls: KMenuProps['cls'] = undefined;
export let attrs: KMenuProps['attrs'] = {};
+ export let selectedUids: KMenuProps['selectedUids'] = [];
+ export let openUids: KMenuProps['openUids'] = [];
export let show: KMenuProps['show'] = true;
/**
* @internal
@@ -23,6 +25,8 @@
expandIcon,
mode,
inlineIndent,
+ openUids,
+ selectedUids,
attrs
});
setContext(menuKey, menuInst);
@@ -35,6 +39,8 @@
expandIcon,
mode,
inlineIndent,
+ openUids,
+ selectedUids,
attrs
});
});
@@ -45,7 +51,10 @@
{#if show}
-
+
{/if}
diff --git a/components/Menu/src/item.svelte b/components/Menu/src/item.svelte
index 2c19eb5b..86c1a731 100644
--- a/components/Menu/src/item.svelte
+++ b/components/Menu/src/item.svelte
@@ -21,20 +21,36 @@
return lv;
};
+ let itemsList = items;
+ $: {
+ itemsList = items;
+ // itemsList = initOpenSelectedStatus()
+ }
+ function initOpenSelectedStatus(list = itemsList) {
+ return list.map((value) => {
+ const defaultSelected = ctxProps.selectedUids?.includes(value.uid || '')
+ const defaultOpen = ctxProps.openUids?.includes(value.uid || '')
+ value.selected = defaultSelected
+ value.open = defaultOpen
+ if (hasSub(value)) {
+ value.children = initOpenSelectedStatus(value.children!);
+ }
+ return value;
+ });
+ }
const menuCtx = getContext(menuKey) as KMenuInstance;
let ctxProps: KMenuInstanceOption = {};
function updatedCtxProps(props: Record) {
ctxProps = { ...props };
+ itemsList = initOpenSelectedStatus()
}
if (menuCtx) {
ctxProps = { ...menuCtx.__dynamicProps };
+ itemsList = initOpenSelectedStatus()
+ console.log(itemsList)
menuCtx.__propHandleEvtMap.push(updatedCtxProps);
}
- let itemsList = items;
- $: {
- itemsList = items;
- }
function handleSelectedRecursion(e: CustomEvent, index: number){
const { selected, uid } = e.detail
@@ -66,12 +82,10 @@
if (value.uid === it.uid && !isGroup(it)) {
// set selected
value.selected = !value.selected;
- value.selected = ctxProps.selectedUids?.includes(value.uid || '') || value.selected;
// set open
if (hasSub(it)) {
value.open = !value.open;
value.selected = false
- value.open = ctxProps.openUids?.includes(value.uid || '') || value.open;
}
/**
* @internal
@@ -100,15 +114,13 @@
[`${prefixCls}-${ctxProps.mode}-group`]: isGroup(it),
[`${prefixCls}-${ctxProps.mode}`]: !isGroup(it),
[`${prefixCls}-selected`]:
- !isGroup(it) && !hasSub(it) && isNotHorizontal() && (ctxProps.selectedUids?.includes(it.uid || '') ||
- it.selected),
+ !isGroup(it) && !hasSub(it) && isNotHorizontal() && (it.selected),
[`${prefixCls}-selected-ih`]:
- !isGroup(it) && hasSub(it) && isNotHorizontal() && (ctxProps.selectedUids?.includes(it.uid || '') ||
- it.selected),
+ !isGroup(it) && hasSub(it) && isNotHorizontal() && (it.selected),
[`${prefixCls}-hover-ih`]:
!isGroup(it) &&
isNotHorizontal() &&
- !(ctxProps.selectedUids?.includes(it.uid || '') || it.selected),
+ !(it.selected),
[`${prefixCls}-vh-child`]: !isGroup(it) && isNotHorizontal() && hasSub(it)
},
cls
diff --git a/components/Menu/src/types.d.ts b/components/Menu/src/types.d.ts
index a7b72501..95525647 100644
--- a/components/Menu/src/types.d.ts
+++ b/components/Menu/src/types.d.ts
@@ -42,27 +42,31 @@ export type KMenuProps = {
*/
mode?: `vertical` | `horizontal` | `inline`;
/**
- * TODO: 当前展开的 SubMenu 菜单项 key 数组
+ * TODO: 👀 当前展开的 SubMenu 菜单项 key 数组 inline
+ * TODO: 当前展开的 SubMenu 菜单项 key 数组 vertical
+ * TODO: 当前展开的 SubMenu 菜单项 key 数组 horizontal
* @default `[]`
*/
openUids?: string[];
/**
- * TODO: 当前选中的菜单项 key 数组
+ * TODO: 🎯 当前选中的菜单项 key 数组(子菜单只高亮,不展开)
* @default `[]`
*/
selectedUids?: string[];
/**
- * TODO: 是否允许选中(为 false, 仅不触发 select事件)
+ * TODO: 🎯 是否允许选中(为 false, 点击不高亮,不触发 select事件) inline
+ * TODO: 是否允许选中(为 false, 点击不高亮,不触发 select事件) vertical
+ * TODO: 是否允许选中(为 false, 点击不高亮,不触发 select事件) horizontal
* @default false
*/
selectable?: boolean;
/**
- * TODO: 🎯 用户鼠标离开子菜单后关闭延时,单位:毫秒
+ * TODO: 用户鼠标离开子菜单后关闭延时,单位:毫秒(非 inline 模式, hover触发)
* @default 100ms
*/
subMenuCloseDelay?: number;
/**
- * TODO: 🎯 用户鼠标进入子菜单后开启延时,单位:毫秒
+ * TODO: 用户鼠标进入子菜单后开启延时,单位:毫秒(非 inline 模式, hover触发)
* @default 0
*/
subMenuOpenDelay?: number;
@@ -72,23 +76,31 @@ export type KMenuProps = {
*/
theme?: 'light' | 'dark';
/**
- * TODO: 🎯 SubMenu 展开/关闭的触发行为(非 inline 模式)
+ * TODO: SubMenu 展开/关闭的触发行为(非 inline 模式)
* @default 'hover'
*/
triggerSubMenuAction?: 'hover' | 'click';
+ cls: ClassValue;
+ attrs: Record;
/**
* @internal
*/
show: boolean;
- cls: ClassValue;
- attrs: Record;
};
-// TODO: onClick 点击 MenuItem 调用此函数(点击子菜单标题不触发)
-// TODO: onOpenChange SubMenu 展开/关闭的回调
-// TODO: onSelect 被选中时调用(点击子菜单标题不触发)
+// TODO: 🎯 onClick 点击 MenuItem 调用此函数(点击子菜单标题不触发) inline
+// TODO: 🎯 onOpenChange SubMenu 展开/关闭的回调 inline
+// TODO: 🎯 onSelect 被选中时调用(点击子菜单标题不触发) inline
+// TODO: onClick 点击 MenuItem 调用此函数(点击子菜单标题不触发) vertical
+// TODO: onOpenChange SubMenu 展开/关闭的回调 vertical
+// TODO: onSelect 被选中时调用(点击子菜单标题不触发) vertical
+// TODO: onClick 点击 MenuItem 调用此函数(点击子菜单标题不触发) horizontal
+// TODO: onOpenChange SubMenu 展开/关闭的回调 horizontal
+// TODO: onSelect 被选中时调用(点击子菜单标题不触发) horizontal
-// TODO: slots expandIcon 展开图标
+// TODO: slots expandIcon 展开图标 vertical
+// TODO: slots expandIcon 展开图标 horizontal
+// TODO: 🎯slots expandIcon 展开图标 inline
export type KMenuItemProps = {
/**
@@ -114,7 +126,7 @@ export type SubMenuType = {
*/
icon?: string;
/**
- * TODO: 👀 菜单项标题
+ * TODO: 菜单项标题
*/
label?: string;
/**
@@ -160,7 +172,9 @@ export type SubMenuType = {
// TODO: onTitleClick 点击子菜单标题
-// TODO: Items Slots slots label 分组标题
-// TODO: Items Slots slots icon 菜单图标
-
-
+// TODO: Items Slots slots label 分组标题 vertical
+// TODO: Items Slots slots label 分组标题 horizontal
+// TODO: 🎯Items Slots slots label 分组标题 inline
+// TODO: Items Slots slots icon 菜单图标 vertical
+// TODO: Items Slots slots icon 菜单图标 horizontal
+// TODO: 🎯Items Slots slots icon 菜单图标 inline
diff --git a/components/Menu/src/utils.ts b/components/Menu/src/utils.ts
index e582f738..1705337b 100644
--- a/components/Menu/src/utils.ts
+++ b/components/Menu/src/utils.ts
@@ -17,8 +17,6 @@ export function transitionIn(node: HTMLElement) {
duration: 300,
tick: (t: number) => {
if (t === 0) {
- node.style.overflow = 'hidden';
- node.style.transition = 'height 0.3s';
node.style.height = '0';
} else if (t === 1) {
node.style.removeProperty('height');
From a760a5a7d65ac2d31a6c97473ee4fa9e749aa2f0 Mon Sep 17 00:00:00 2001
From: baiwusanyu-c <740132583@qq.com>
Date: Wed, 17 Apr 2024 15:36:08 +0800
Subject: [PATCH 13/39] wip: KMenu component completes inline mode default
submenu select item
---
components/Menu/src/index.svelte | 9 ++++--
components/Menu/src/item.svelte | 55 +++++++++++++++++++++++++-------
components/Menu/src/types.d.ts | 7 +++-
components/Menu/src/utils.ts | 3 +-
4 files changed, 58 insertions(+), 16 deletions(-)
diff --git a/components/Menu/src/index.svelte b/components/Menu/src/index.svelte
index 56727401..0d72dd0a 100644
--- a/components/Menu/src/index.svelte
+++ b/components/Menu/src/index.svelte
@@ -1,8 +1,8 @@
{#if show}
-
+
{/if}
diff --git a/components/Menu/src/item.svelte b/components/Menu/src/item.svelte
index dedce8e5..f4ec44fd 100644
--- a/components/Menu/src/item.svelte
+++ b/components/Menu/src/item.svelte
@@ -1,12 +1,13 @@
{#each itemsList as it, index (it.uid)}
- {#if it.type !== 'divider'}
- - handleSelect(it, e)}
- aria-hidden="true"
- style:padding-left={`${(ctxProps.inlineIndent || 24) * getLevel(it, level)}px`}
- class={cnames(it)}
- {...$$restProps}
- {...attrs}
- >
-
-
-
- {#if it.icon}
-
- {/if}
-
- {it.label}
-
+ {#if ctxProps.mode === 'inline'}
+ {#if it.type !== 'divider'}
+
- handleSelect(it, e)}
+ aria-hidden="true"
+ style:padding-left={`${getIndent(it)}`}
+ class={cnames(it)}
+ {...$$restProps}
+ {...attrs}
+ >
+
+
+
+ {#if it.icon}
+
+ {/if}
+
+ {it.label}
+
- {#if hasSub(it) && !isGroup(it)}
-
-
-
- {/if}
-
-
-
-
- handleSelectedRecursion(e, index)}
- items={it.children}
- level={getLevel(it, level) + 1}>
-
-
+ {#if hasSub(it) && !isGroup(it)}
+
+
+
+ {/if}
+
+
+
+
+ handleSelectedRecursion(e, index)}
+ items={it.children}
+ level={getLevel(it, level) + 1}
+ >
+
+
-
- {#if item.icon}
-
- {/if}
-
- {item.label}
-
+
+ {#if item.icon}
+
+ {/if}
+
+ {item.label}
+
+ {#if hasSub(item) && !isGroup(item)}
+
+
+
+ {/if}
+
+
+
+
+ {:else}
+
+ {/if}
+ {/if}
+
+ {#if ctxProps.mode === 'vertical'}
+
+
+ {#if it.type !== 'divider'}
+ - handleSelect(it, e)}
+ aria-hidden="true"
+ style:padding-left={`${getIndent(it)}`}
+ class={cnames(it)}
+ {...$$restProps}
+ {...attrs}
+ >
+
+
+
+ {#if it.icon}
+
+ {/if}
+
+ {it.label}
+
- {#if hasSub(item) && !isGroup(item)}
-
-
+ {#if hasSub(it) && !isGroup(it)}
+
+
+
+ {/if}
+
+
+ {#if isGroup(it)}
+ {#each (it.children || []) as child, childIndex (child.uid)}
+ handleSelectedRecursion(e, childIndex)}
+ items={[child]}
+ level={getLevel(child, level) + 1}
+ >
+ {/each}
+
+ {/if}
+ {:else}
+
+ {/if}
+
+
+
+ handleSelectedRecursion(e, index)}
+ items={it.children}
+ level={getLevel(it, level) + 1}
+ >
+
+
+
+
+ {#if item.icon}
+
+ {/if}
+
+ {item.label} self
+
+ {#if hasSub(item) && !isGroup(item)}
+
+
+
+ {/if}
- {/if}
-
-
-
-
- {:else}
-
+
+
+
+
+
{/if}
{/each}
diff --git a/components/Menu/src/types.d.ts b/components/Menu/src/types.d.ts
index 80f00c07..e72e8e10 100644
--- a/components/Menu/src/types.d.ts
+++ b/components/Menu/src/types.d.ts
@@ -10,46 +10,45 @@ export type KMenuInstanceOption = {
selectable?: boolean;
subMenuCloseDelay?: number;
subMenuOpenDelay?: number;
- multiple?: boolean
+ multiple?: boolean;
theme?: 'light' | 'dark';
triggerSubMenuAction?: 'hover' | 'click';
attrs?: Record;
};
export type ClickEvtPa = {
- item: SubMenuType
- uid: string,
- uidPath: string[]
- e: MouseEvent
-}
+ item: SubMenuType;
+ uid: string;
+ uidPath: string[];
+ e: MouseEvent;
+};
export type SelectEvtPa = {
- item: SubMenuType
- uid: string
- uidPath: string[]
- selectedUids: string[]
- selectedItems: SubMenuType[]
- selectedUidPaths: string[][]
- e: MouseEvent
-}
+ item: SubMenuType;
+ uid: string;
+ uidPath: string[];
+ selectedUids: string[];
+ selectedItems: SubMenuType[];
+ selectedUidPaths: string[][];
+ e: MouseEvent;
+};
export type KMenuInstance = {
__propHandleEvtMap: Array<(props: Record) => void>;
__dynamicProps: KMenuInstanceOption;
- __org_items?: SubMenuType[]
- __selectedUids? : Set,
- __openUids? : Set
- __selectedItems? : Map
- syncSelectedItems: (
- item: SubMenuType,
- opType: 'set' | 'delete' = 'set') =>void
+ __org_items?: SubMenuType[];
+ __selectedUids?: Set;
+ __openUids?: Set;
+ __selectedItems?: Map;
+ syncSelectedItems: (item: SubMenuType, opType: 'set' | 'delete' = 'set') => void;
syncUids: (
uid: string | string[],
type: 'open' | 'selected',
- opType: 'add' | 'delete' = 'add') =>void
- onOpenChange: (openUids: string[]) => void
- onSelect: (param: SelectEvtPa) => void
- onClick: (param: ClickEvtPa) => void
+ opType: 'add' | 'delete' = 'add'
+ ) => void;
+ onOpenChange: (openUids: string[]) => void;
+ onSelect: (param: SelectEvtPa) => void;
+ onClick: (param: ClickEvtPa) => void;
};
export type KMenuProps = {
@@ -116,7 +115,7 @@ export type KMenuProps = {
* TODO: 是否允许多选
* @default 'true'
*/
- multiple?: boolean
+ multiple?: boolean;
/**
* TODO: SubMenu 展开/关闭的触发行为(非 inline 模式)
* @default 'hover'
@@ -188,7 +187,7 @@ export type SubMenuType = {
/**
* TODO: 设置收缩时展示的悬浮标题(无子菜单情况下生效,不传时默认为 label)
*/
- title?: string
+ title?: string;
/**
* TODO: 👀 子菜单的菜单项
*/
@@ -197,18 +196,19 @@ export type SubMenuType = {
* TODO: 子菜单样式,mode="inline" 时无效
*/
popupClassName?: string;
+
/**
* @internal
*/
- selected?: boolean
+ selected?: boolean;
/**
* @internal
*/
- open?: boolean
+ open?: boolean;
/**
* @internal
*/
- selectedDeps?: Set
+ selectedDeps?: Set;
[property: string]: any;
};
@@ -220,3 +220,8 @@ export type SubMenuType = {
// TODO: Items Slots slots icon 菜单图标 vertical
// TODO: Items Slots slots icon 菜单图标 horizontal
// TODO: 👀 Items Slots slots icon 菜单图标 inline
+
+// TODO: onSelect 选择子菜单时,再次选择被错误的取消
+// TODO: 非 inline 模式只允許一個子菜單
+// TODO: popover 对齐
+// TODO: 处理group
diff --git a/components/Menu/src/utils.ts b/components/Menu/src/utils.ts
index 4654c809..46eef5c6 100644
--- a/components/Menu/src/utils.ts
+++ b/components/Menu/src/utils.ts
@@ -1,10 +1,10 @@
-import type {KMenuInstance, KMenuInstanceOption, SubMenuType} from './types';
-import { isArray, isString } from "baiwusanyu-utils";
+import type { KMenuInstance, KMenuInstanceOption, SubMenuType } from './types';
+import { isArray, isString } from 'baiwusanyu-utils';
export const createKMenu = (
options: KMenuInstanceOption,
onOpenChange: KMenuInstance['onOpenChange'],
onSelect: KMenuInstance['onSelect'],
- onClick: KMenuInstance['onClick'],
+ onClick: KMenuInstance['onClick']
): KMenuInstance => {
return {
/**
@@ -17,36 +17,30 @@ export const createKMenu = (
__openUids: new Set(options.openUids),
__selectedUids: new Set(options.selectedUids),
__selectedItems: new Map(),
- syncUids(
- uid: string | string[],
- type: 'open' | 'selected',
- opType: 'add' | 'delete' = 'add'){
- let uids = uid
- if(isString(uid)){
- uids = [uid as string]
+ syncUids(uid: string | string[], type: 'open' | 'selected', opType: 'add' | 'delete' = 'add') {
+ let uids = uid;
+ if (isString(uid)) {
+ uids = [uid as string];
}
- if(isArray(uids)){
- (uids as string[]).forEach(id => {
- type === 'open' ? this.__openUids![opType](id) : this.__selectedUids![opType](id)
+ if (isArray(uids)) {
+ (uids as string[]).forEach((id) => {
+ type === 'open' ? this.__openUids![opType](id) : this.__selectedUids![opType](id);
});
}
},
- syncSelectedItems(
- item: SubMenuType,
- opType: 'set' | 'delete' = 'set'
- ){
- const { uid } = item
- if(opType === 'set'){
- this.__selectedItems?.set(uid!, item)
+ syncSelectedItems(item: SubMenuType, opType: 'set' | 'delete' = 'set') {
+ const { uid } = item;
+ if (opType === 'set') {
+ this.__selectedItems?.set(uid!, item);
}
- if(opType === 'delete'){
- this.__selectedItems?.delete(uid!)
+ if (opType === 'delete') {
+ this.__selectedItems?.delete(uid!);
}
},
onOpenChange,
onSelect,
- onClick,
+ onClick
};
};
@@ -66,7 +60,7 @@ export function transitionIn(node: HTMLElement) {
}
export function transitionOut(node: HTMLElement) {
- const orgHeight = node.scrollHeight
+ const orgHeight = node.scrollHeight;
return {
duration: 300,
tick: (t: number) => {
@@ -81,7 +75,7 @@ export function transitionOut(node: HTMLElement) {
};
}
-export function getUidPath(uid: string, list: SubMenuType[], path: string[] = []){
+export function getUidPath(uid: string, list: SubMenuType[], path: string[] = []) {
// 遍历树结构数组中的每个节点
for (const node of list) {
// 如果当前节点的 uid 与给定的 uid 匹配,返回当前路径
diff --git a/preset/src/shortcuts/src/menu.ts b/preset/src/shortcuts/src/menu.ts
index 640ed0af..509106fe 100644
--- a/preset/src/shortcuts/src/menu.ts
+++ b/preset/src/shortcuts/src/menu.ts
@@ -2,7 +2,6 @@ export const menuShortcuts: Record = {
'k-menu':
'bg-white text-ikun-tx-base p-0 m-0 box-border text-14px leading-0 list-none outline-none focus:outline-none k-menu-transition-w',
-
'k-menu-item': 'box-border select-none',
'k-menu-item-icon-root': 'truncate fsc',
'k-menu-item-icon': 'inline-flex text-inherit items-center leading-0 min-w-14px',
@@ -23,13 +22,19 @@ export const menuShortcuts: Record = {
'k-menu-inline': 'bdr-1 b-e-solid border-ikun-bd-base',
'k-menu-vertical': 'bdr-1 b-e-solid border-ikun-bd-base',
- 'k-menu-item-vertical': '',
+
+ 'k-menu-item-vertical': 'k-menu-item-inline',
+ '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 m-bs-4px m-be-4px ' +
+ 'rounded-8px ikun:50:text-black',
+
'k-menu-item-inline':
'cursor-pointer k-menu-w k-menu-transition ' +
- 'flex items-center pr h-40px leading-40px list-style-position ps-16px p-ie-16px m-is-4px m-ie-4px m-bs-4px m-be-4px ' +
+ 'flex items-center pr h-40px leading-40px list-inside ps-16px p-ie-16px m-is-4px m-ie-4px m-bs-4px m-be-4px ' +
'rounded-8px active:(ikun:20:bg-ikun-main)',
'k-menu-item-inline-group':
'k-menu-w k-menu-transition ' +
- 'flex items-center pr h-40px leading-40px list-style-position ps-16px p-ie-16px m-is-4px m-ie-4px m-bs-4px m-be-4px ' +
+ 'flex items-center pr h-40px leading-40px list-inside ps-16px p-ie-16px m-is-4px m-ie-4px m-bs-4px m-be-4px ' +
'rounded-8px ikun:50:text-black'
};
From 456687209dacd9c7a4474171482b71a44b1400a9 Mon Sep 17 00:00:00 2001
From: baiwusanyu-c <740132583@qq.com>
Date: Sun, 21 Apr 2024 15:11:11 +0800
Subject: [PATCH 23/39] wip: KMenu component completes vertical mode group item
render
---
components/Menu/src/item.svelte | 48 +++++++++++++++++++++------------
components/Menu/src/types.d.ts | 2 +-
2 files changed, 32 insertions(+), 18 deletions(-)
diff --git a/components/Menu/src/item.svelte b/components/Menu/src/item.svelte
index f4ec44fd..bd1c24d8 100644
--- a/components/Menu/src/item.svelte
+++ b/components/Menu/src/item.svelte
@@ -32,7 +32,7 @@
}
function initOpenSelectedStatus(list = itemsList) {
- const res: SubMenuType[] = [];
+ let res: SubMenuType[] = [];
let deps: string[] = [];
list.forEach((value) => {
const defaultSelected = menuCtx.__selectedUids?.has(value.uid || '');
@@ -44,7 +44,7 @@
deps.push(value.uid!);
}
- if (hasSub(value)) {
+ if (hasSub(value) && ctxProps.mode === 'inline') {
const recRes = initOpenSelectedStatus(value.children!);
value.children = recRes.children;
if (!isGroup(value)) {
@@ -60,8 +60,31 @@
deps = recRes.deps;
}
}
+
+ if(hasSub(value) && ctxProps.mode === 'vertical'){
+ const recRes = initOpenSelectedStatus(value.children!);
+ if (!isGroup(value)) {
+ value.children = recRes.children;
+ !value.selectedDeps && (value.selectedDeps = new Set());
+ recRes.deps.forEach((d) => {
+ value.selectedDeps!.add(d);
+ });
+ value.selected = !!value.selectedDeps.size;
+ if (value.selected) {
+ deps.push(value.uid!);
+ }
+ } else {
+ const { children } = value
+ value.children = []
+ res.push({ ...value });
+ res = res.concat(children!)
+ deps = recRes.deps;
+ return
+ }
+ }
res.push({ ...value });
});
+
return {
children: res,
deps
@@ -97,6 +120,8 @@
| { detail: { selected: boolean; uid: string } },
index: number
) {
+
+ debugger
const { selected, uid } = e.detail;
const it = itemsList[index];
if (!isGroup(it)) {
@@ -120,6 +145,7 @@
}
function setOpenAndSelectStatus(it: SubMenuType, list = itemsList) {
+ debugger
return list.map((value) => {
if (value.uid === it.uid && !isGroup(it)) {
// set selected
@@ -228,7 +254,7 @@
};
const popoverContentCls = clsx(`${prefixCls}-popover-content p-0 box-border`);
- const popoverTriggerCls = clsx(`${prefixCls}-popover-trigger !block`);
+ const popoverTriggerCls = clsx(`${prefixCls}-popover-trigger`);
$:getIndent = (it: SubMenuType) => {
if(ctxProps.mode !== 'inline') {
return `${ctxProps.inlineIndent}px`
@@ -236,7 +262,6 @@
return `${(ctxProps.inlineIndent || 24) * getLevel(it, level)}px`
}
- let groupChildIndex = 0
{#each itemsList as it, index (it.uid)}
@@ -342,17 +367,6 @@
{/if}
- {#if isGroup(it)}
- {#each (it.children || []) as child, childIndex (child.uid)}
- handleSelectedRecursion(e, childIndex)}
- items={[child]}
- level={getLevel(child, level) + 1}
- >
- {/each}
-
- {/if}
{:else}
{/if}
@@ -361,7 +375,7 @@
{item.label} self
- {#if hasSub(item) && !isGroup(item)}
+ {#if hasSub(item)}
diff --git a/components/Menu/src/types.d.ts b/components/Menu/src/types.d.ts
index e72e8e10..4644908c 100644
--- a/components/Menu/src/types.d.ts
+++ b/components/Menu/src/types.d.ts
@@ -224,4 +224,4 @@ export type SubMenuType = {
// TODO: onSelect 选择子菜单时,再次选择被错误的取消
// TODO: 非 inline 模式只允許一個子菜單
// TODO: popover 对齐
-// TODO: 处理group
+// TODO: 处理group 样式
From 7633e4024760c20160eb3a1546a1817badb2ee8e Mon Sep 17 00:00:00 2001
From: baiwusanyu-c <740132583@qq.com>
Date: Sun, 21 Apr 2024 17:16:11 +0800
Subject: [PATCH 24/39] wip: optimize the grouping style of KMenu component in
vertical mode
---
components/Menu/src/index.svelte | 13 ++++++++-----
components/Menu/src/item.svelte | 26 +++++++++++++++++---------
components/Menu/src/types.d.ts | 15 +++++++++++++--
components/Popover/src/index.svelte | 4 +++-
components/Popover/src/index.ts | 2 +-
components/Popover/src/types.d.ts | 5 +++++
preset/src/shortcuts/src/menu.ts | 11 ++++++-----
7 files changed, 53 insertions(+), 23 deletions(-)
diff --git a/components/Menu/src/index.svelte b/components/Menu/src/index.svelte
index 2c101a18..b300a6ab 100644
--- a/components/Menu/src/index.svelte
+++ b/components/Menu/src/index.svelte
@@ -8,7 +8,7 @@
export let subMenuCloseDelay: KMenuProps['subMenuCloseDelay'] = 100;
export let subMenuOpenDelay: KMenuProps['subMenuOpenDelay'] = 0;
export let inlineIndent: KMenuProps['inlineIndent'] = 24;
- export let expandIcon: KMenuProps['expandIcon'] = 'i-carbon-chevron-down';
+ export let expandIcon: KMenuProps['expandIcon'] = '';
export let mode: KMenuProps['mode'] = 'vertical';
export let cls: KMenuProps['cls'] = undefined;
export let attrs: KMenuProps['attrs'] = {};
@@ -17,6 +17,7 @@
export let show: KMenuProps['show'] = true;
export let multiple: KMenuProps['multiple'] = true;
export let selectable: KMenuProps['selectable'] = true;
+ export let ctxKey: KMenuProps['ctxKey'] = '';
const dispatch = createEventDispatcher();
function onOpenChange(openUids: string[]) {
dispatch('openChange', openUids);
@@ -44,14 +45,15 @@
selectedUids,
multiple,
selectable,
- attrs
+ attrs,
+ ctxKey,
},
onOpenChange,
onSelect,
onClick
);
- if (!getContext(menuKey)) {
- setContext(menuKey, menuInst);
+ if (!getContext(ctxKey || menuKey)) {
+ setContext(ctxKey || menuKey, menuInst);
}
$: {
menuInst.__propHandleEvtMap.forEach((cb) => {
@@ -66,7 +68,8 @@
multiple,
selectedUids,
selectable,
- attrs
+ attrs,
+ ctxKey,
});
});
}
diff --git a/components/Menu/src/item.svelte b/components/Menu/src/item.svelte
index bd1c24d8..756fe2f9 100644
--- a/components/Menu/src/item.svelte
+++ b/components/Menu/src/item.svelte
@@ -8,10 +8,12 @@
import { KMenu } from '@ikun-ui/menu';
import { getUidPath } from './utils';
import { KPopover } from '@ikun-ui/popover';
+ import type { OffsetsFunction, OffsetsFnPa } from '@ikun-ui/popover';
export let items: KMenuItemProps['items'] = [];
export let cls: KMenuItemProps['cls'] = undefined;
export let attrs: KMenuItemProps['attrs'] = {};
export let level: KMenuItemProps['level'] = 1;
+ export let ctxKey: KMenuItemProps['ctxKey'] = '';
const dispatch = createEventDispatcher();
const hasSub = (it: SubMenuType) => !!(it.children && it.children.length);
const isNotHorizontal = () => ctxProps.mode !== 'horizontal';
@@ -31,13 +33,14 @@
}
}
- function initOpenSelectedStatus(list = itemsList) {
+ function initOpenSelectedStatus(list = itemsList, inGroup: boolean = false) {
let res: SubMenuType[] = [];
let deps: string[] = [];
list.forEach((value) => {
const defaultSelected = menuCtx.__selectedUids?.has(value.uid || '');
const defaultOpen = menuCtx.__openUids?.has(value.uid || '');
value.selected = defaultSelected;
+ value.inGroup = inGroup
menuCtx.syncSelectedItems(value, value.selected ? 'set' : 'delete');
value.open = defaultOpen;
if (defaultSelected) {
@@ -62,7 +65,7 @@
}
if(hasSub(value) && ctxProps.mode === 'vertical'){
- const recRes = initOpenSelectedStatus(value.children!);
+ const recRes = initOpenSelectedStatus(value.children!, isGroup(value));
if (!isGroup(value)) {
value.children = recRes.children;
!value.selectedDeps && (value.selectedDeps = new Set());
@@ -121,7 +124,6 @@
index: number
) {
- debugger
const { selected, uid } = e.detail;
const it = itemsList[index];
if (!isGroup(it)) {
@@ -145,7 +147,6 @@
}
function setOpenAndSelectStatus(it: SubMenuType, list = itemsList) {
- debugger
return list.map((value) => {
if (value.uid === it.uid && !isGroup(it)) {
// set selected
@@ -231,7 +232,7 @@
const iconCls = clsx(`${prefixCls}-icon`);
const iconRootCls = clsx(`${prefixCls}-icon-root`);
- const expendIconCls = (it: SubMenuType) => {
+ $: expendIconCls = (it: SubMenuType) => {
if (ctxProps.mode === 'vertical') {
return resolvedExpandIcon;
}
@@ -254,14 +255,18 @@
};
const popoverContentCls = clsx(`${prefixCls}-popover-content p-0 box-border`);
- const popoverTriggerCls = clsx(`${prefixCls}-popover-trigger`);
+ const popoverTriggerCls = clsx(`${prefixCls}-popover-trigger-v`);
$:getIndent = (it: SubMenuType) => {
if(ctxProps.mode !== 'inline') {
- return `${ctxProps.inlineIndent}px`
+ return `${it.inGroup ? (ctxProps.inlineIndent || 24) * 2 : ctxProps.inlineIndent}px`
}
return `${(ctxProps.inlineIndent || 24) * getLevel(it, level)}px`
}
+ const setPopoverOffset: OffsetsFunction = ({popper, placement, reference}: OffsetsFnPa) => {
+ return [popper.height / 2 - reference.height / 2, 4]
+ }
+
{#each itemsList as it, index (it.uid)}
@@ -295,6 +300,7 @@
@@ -333,8 +339,9 @@
{#if ctxProps.mode === 'vertical'}
@@ -391,7 +399,7 @@
{/if}
- {item.label} self
+ {item.label}
{#if hasSub(item)}
diff --git a/components/Menu/src/types.d.ts b/components/Menu/src/types.d.ts
index 4644908c..e6cd5a73 100644
--- a/components/Menu/src/types.d.ts
+++ b/components/Menu/src/types.d.ts
@@ -14,6 +14,7 @@ export type KMenuInstanceOption = {
theme?: 'light' | 'dark';
triggerSubMenuAction?: 'hover' | 'click';
attrs?: Record;
+ ctxKey?: string
};
export type ClickEvtPa = {
@@ -52,6 +53,10 @@ export type KMenuInstance = {
};
export type KMenuProps = {
+ /**
+ * TODO: 👀 上下文 key
+ */
+ ctxKey?: string
/**
* TODO: 👀 展开图标
* @default 'i-carbon-chevron-down'
@@ -148,6 +153,10 @@ export type KMenuItemProps = {
* @internal
*/
level: number;
+ /**
+ * TODO: 👀 上下文 key
+ */
+ ctxKey?: string
items: SubMenuType[];
cls: ClassValue;
attrs: Record;
@@ -196,7 +205,10 @@ export type SubMenuType = {
* TODO: 子菜单样式,mode="inline" 时无效
*/
popupClassName?: string;
-
+ /**
+ * @internal
+ */
+ inGroup?: boolean;
/**
* @internal
*/
@@ -224,4 +236,3 @@ export type SubMenuType = {
// TODO: onSelect 选择子菜单时,再次选择被错误的取消
// TODO: 非 inline 模式只允許一個子菜單
// TODO: popover 对齐
-// TODO: 处理group 样式
diff --git a/components/Popover/src/index.svelte b/components/Popover/src/index.svelte
index 9b078e75..85407abf 100644
--- a/components/Popover/src/index.svelte
+++ b/components/Popover/src/index.svelte
@@ -21,6 +21,7 @@
* @internal
*/
export let width: KPopoverProps['width'] = 'fit-content';
+ export let offset: KPopoverProps['offset'] = [0, 8];
$: curPlacement = placement;
let arrowRef: null | HTMLElement = null;
const dispatch = createEventDispatcher();
@@ -31,7 +32,8 @@
{
name: 'offset',
options: {
- offset: [0, 8]
+ // TODO: feature props
+ offset,
}
},
{
diff --git a/components/Popover/src/index.ts b/components/Popover/src/index.ts
index b3a835ca..dd606c24 100644
--- a/components/Popover/src/index.ts
+++ b/components/Popover/src/index.ts
@@ -5,4 +5,4 @@ export default Popover;
export { Popover as KPopover };
-export type { KPopoverProps } from './types';
+export type { KPopoverProps, OffsetsFunction, OffsetsFnPa } from './types';
diff --git a/components/Popover/src/types.d.ts b/components/Popover/src/types.d.ts
index 47c1af5b..7a9897f3 100644
--- a/components/Popover/src/types.d.ts
+++ b/components/Popover/src/types.d.ts
@@ -8,6 +8,7 @@ export type KPopoverProps = {
trigger: IKunTrigger;
disabled: boolean;
arrow: boolean;
+ offset: OffsetsFunction | [?number, ?number];
cls: ClassValue;
clsTrigger: ClassValue;
mouseEnterDelay: number;
@@ -15,3 +16,7 @@ export type KPopoverProps = {
width: string | null | undefined;
attrs: Record;
};
+
+export type OffsetsFunction = (data: OffsetsFnPa) => [?number, ?number];
+
+export type OffsetsFnPa = { popper: DOMRect, reference: DOMRect, placement: IKunPlacement }
diff --git a/preset/src/shortcuts/src/menu.ts b/preset/src/shortcuts/src/menu.ts
index 509106fe..e4a8a809 100644
--- a/preset/src/shortcuts/src/menu.ts
+++ b/preset/src/shortcuts/src/menu.ts
@@ -7,7 +7,7 @@ export const menuShortcuts: Record = {
'k-menu-item-icon': 'inline-flex text-inherit items-center leading-0 min-w-14px',
'k-menu-title-content': 'truncate box-border k-menu-transition-c select-none',
'k-menu-title-content-i': 'm-is-6px m-ie-6px k-menu-transition-o opacity-[1] truncate',
- 'k-menu-item-divider': 'my-0',
+ 'k-menu-item-divider': 'my-0 w-full',
'k-menu-sub': 'border-none bg-transparent',
'k-menu-sub-bg': 'ikun:2:bg-black',
@@ -23,18 +23,19 @@ export const menuShortcuts: Record = {
'k-menu-inline': 'bdr-1 b-e-solid border-ikun-bd-base',
'k-menu-vertical': 'bdr-1 b-e-solid border-ikun-bd-base',
- 'k-menu-item-vertical': 'k-menu-item-inline',
+ 'k-menu-item-popover-trigger-v': 'box-border my-4px',
+ 'k-menu-item-vertical': 'k-menu-item-inline my-0',
'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 m-bs-4px m-be-4px ' +
+ '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-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 m-bs-4px m-be-4px ' +
+ 'flex items-center pr h-40px leading-40px list-inside ps-16px p-ie-16px m-is-4px m-ie-4px my-4px ' +
'rounded-8px active:(ikun:20:bg-ikun-main)',
'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 m-bs-4px m-be-4px ' +
+ 'flex items-center pr h-40px leading-40px list-inside ps-16px p-ie-16px m-is-4px m-ie-4px my-4px ' +
'rounded-8px ikun:50:text-black'
};
From 06305bfbb14201c9d2224ff99a1d21a2e58fc112 Mon Sep 17 00:00:00 2001
From: baiwusanyu-c <740132583@qq.com>
Date: Sun, 21 Apr 2024 17:50:48 +0800
Subject: [PATCH 25/39] wip: temp commit
---
components/Menu/src/item.svelte | 19 +++++++------------
components/Menu/src/types.d.ts | 1 -
2 files changed, 7 insertions(+), 13 deletions(-)
diff --git a/components/Menu/src/item.svelte b/components/Menu/src/item.svelte
index 756fe2f9..48d5698c 100644
--- a/components/Menu/src/item.svelte
+++ b/components/Menu/src/item.svelte
@@ -5,7 +5,7 @@
import { getPrefixCls, menuKey } from '@ikun-ui/utils';
import { clsx } from 'clsx';
import { KDivider } from '@ikun-ui/divider';
- import { KMenu } from '@ikun-ui/menu';
+ import KMenu from './index';
import { getUidPath } from './utils';
import { KPopover } from '@ikun-ui/popover';
import type { OffsetsFunction, OffsetsFnPa } from '@ikun-ui/popover';
@@ -96,21 +96,15 @@
const menuCtx = getContext(menuKey) as KMenuInstance;
let ctxProps: KMenuInstanceOption = {};
- let resolvedExpandIcon = 'i-carbon-chevron-down';
- function setExpandIcon() {
- resolvedExpandIcon =
- ctxProps.mode === 'vertical' ? `${ctxProps.expandIcon} -rotate-90` : ctxProps.expandIcon!;
- }
+
function updatedCtxProps(props: Record) {
ctxProps = { ...props };
menuCtx.syncUids(ctxProps.openUids || [], 'open');
menuCtx.syncUids(ctxProps.selectedUids || [], 'selected');
itemsList = initOpenSelectedStatus().children;
- setExpandIcon();
}
if (menuCtx) {
ctxProps = { ...menuCtx.__dynamicProps };
- setExpandIcon();
menuCtx.__propHandleEvtMap.push(updatedCtxProps);
if (level === 1) {
menuCtx.__org_items = items;
@@ -233,12 +227,13 @@
const iconRootCls = clsx(`${prefixCls}-icon-root`);
$: expendIconCls = (it: SubMenuType) => {
+ const icon = (ctxProps.expandIcon || 'i-carbon-chevron-down ');
if (ctxProps.mode === 'vertical') {
- return resolvedExpandIcon;
+ return `${icon} -rotate-90`
}
return it.open
- ? `${resolvedExpandIcon} rotate-180 k-icon-transition`
- : `${resolvedExpandIcon} k-icon-transition`;
+ ? `${icon} rotate-180 k-icon-transition`
+ : `${icon} k-icon-transition`;
};
const titleContentCls = (hasIcon: boolean) => {
@@ -263,7 +258,7 @@
return `${(ctxProps.inlineIndent || 24) * getLevel(it, level)}px`
}
- const setPopoverOffset: OffsetsFunction = ({popper, placement, reference}: OffsetsFnPa) => {
+ const setPopoverOffset: OffsetsFunction = ({popper, reference}: OffsetsFnPa) => {
return [popper.height / 2 - reference.height / 2, 4]
}
diff --git a/components/Menu/src/types.d.ts b/components/Menu/src/types.d.ts
index e6cd5a73..2c216bf3 100644
--- a/components/Menu/src/types.d.ts
+++ b/components/Menu/src/types.d.ts
@@ -235,4 +235,3 @@ export type SubMenuType = {
// TODO: onSelect 选择子菜单时,再次选择被错误的取消
// TODO: 非 inline 模式只允許一個子菜單
-// TODO: popover 对齐
From b0b0c1b287745a68cc4b7cd2b00c842ddf361625 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E7=99=BD=E9=9B=BE=E4=B8=89=E8=AF=AD?=
<32354856+baiwusanyu-c@users.noreply.github.com>
Date: Sun, 21 Apr 2024 22:16:09 +0800
Subject: [PATCH 26/39] wip: fix gorup item render error
---
components/Menu/src/item.svelte | 11 +++++++----
components/Menu/src/types.d.ts | 8 ++++----
2 files changed, 11 insertions(+), 8 deletions(-)
diff --git a/components/Menu/src/item.svelte b/components/Menu/src/item.svelte
index 48d5698c..f933bd9e 100644
--- a/components/Menu/src/item.svelte
+++ b/components/Menu/src/item.svelte
@@ -9,6 +9,7 @@
import { getUidPath } from './utils';
import { KPopover } from '@ikun-ui/popover';
import type { OffsetsFunction, OffsetsFnPa } from '@ikun-ui/popover';
+ import {jsonClone} from "baiwusanyu-utils";
export let items: KMenuItemProps['items'] = [];
export let cls: KMenuItemProps['cls'] = undefined;
export let attrs: KMenuItemProps['attrs'] = {};
@@ -20,14 +21,14 @@
const isGroup = (it: SubMenuType) => it.type === 'group';
const getLevel = (it: SubMenuType, lv: number) => {
if (isGroup(it)) {
- return lv - 1;
+ return Math.max(lv - 1, 1);
}
return lv;
};
- let itemsList = items;
+ let itemsList = level === 1 ? jsonClone(items) : items;
$: {
- itemsList = items;
+ itemsList = level === 1 ? jsonClone(items) : items;
if (level === 1) {
itemsList = initOpenSelectedStatus().children;
}
@@ -94,7 +95,7 @@
};
}
- const menuCtx = getContext(menuKey) as KMenuInstance;
+ const menuCtx = getContext(ctxKey || menuKey) as KMenuInstance;
let ctxProps: KMenuInstanceOption = {};
function updatedCtxProps(props: Record) {
@@ -301,6 +302,7 @@
>
handleSelectedRecursion(e, index)}
items={it.children}
level={getLevel(it, level) + 1}
@@ -382,6 +384,7 @@
>
handleSelectedRecursion(e, index)}
items={it.children}
level={getLevel(it, level) + 1}
diff --git a/components/Menu/src/types.d.ts b/components/Menu/src/types.d.ts
index 2c216bf3..4cce9315 100644
--- a/components/Menu/src/types.d.ts
+++ b/components/Menu/src/types.d.ts
@@ -95,7 +95,7 @@ export type KMenuProps = {
*/
selectedUids?: string[];
/**
- * TODO: 👀是否允许选中(为 false, 点击不高亮,不触发 select事件) inline
+ * TODO: 👀 是否允许选中(为 false, 点击不高亮,不触发 select事件) inline
* TODO: 是否允许选中(为 false, 点击不高亮,不触发 select事件) vertical
* TODO: 是否允许选中(为 false, 点击不高亮,不触发 select事件) horizontal
* @default false
@@ -122,7 +122,7 @@ export type KMenuProps = {
*/
multiple?: boolean;
/**
- * TODO: SubMenu 展开/关闭的触发行为(非 inline 模式)
+ * TODO: 👀 SubMenu 展开/关闭的触发行为(非 inline 模式)
* @default 'hover'
*/
triggerSubMenuAction?: 'hover' | 'click';
@@ -194,7 +194,7 @@ export type SubMenuType = {
*/
theme?: 'light' | 'dark';
/**
- * TODO: 设置收缩时展示的悬浮标题(无子菜单情况下生效,不传时默认为 label)
+ * TODO: 🎯设置收缩时展示的悬浮标题(无子菜单情况下生效,不传时默认为 label)
*/
title?: string;
/**
@@ -234,4 +234,4 @@ export type SubMenuType = {
// TODO: 👀 Items Slots slots icon 菜单图标 inline
// TODO: onSelect 选择子菜单时,再次选择被错误的取消
-// TODO: 非 inline 模式只允許一個子菜單
+// TODO: 🎯 测试非inline 模式下 ‘👀’ 的功能
From 72ad9fb14ef56f5637e0bf50152016bb7d2aa104 Mon Sep 17 00:00:00 2001
From: baiwusanyu-c <740132583@qq.com>
Date: Mon, 22 Apr 2024 11:05:19 +0800
Subject: [PATCH 27/39] wip: KMenu component completes vertical mode
subMenuCloseDelay and subMenuOpneDelay props
---
components/Menu/src/item.svelte | 2 ++
components/Menu/src/types.d.ts | 28 +++++++++++++++-------------
2 files changed, 17 insertions(+), 13 deletions(-)
diff --git a/components/Menu/src/item.svelte b/components/Menu/src/item.svelte
index f933bd9e..a54c5af9 100644
--- a/components/Menu/src/item.svelte
+++ b/components/Menu/src/item.svelte
@@ -339,6 +339,8 @@
width="100%"
placement="right"
offset={setPopoverOffset}
+ mouseEnterDelay={ctxProps.subMenuOpenDelay}
+ mouseLeaveDelay={ctxProps.subMenuCloseDelay}
trigger={ctxProps.triggerSubMenuAction}
cls={popoverContentCls}
clsTrigger={popoverTriggerCls}
diff --git a/components/Menu/src/types.d.ts b/components/Menu/src/types.d.ts
index 4cce9315..af84bc88 100644
--- a/components/Menu/src/types.d.ts
+++ b/components/Menu/src/types.d.ts
@@ -82,32 +82,32 @@ export type KMenuProps = {
mode?: `vertical` | `horizontal` | `inline`;
/**
* TODO: 👀 当前展开的 SubMenu 菜单项 key 数组 inline
- * TODO: 当前展开的 SubMenu 菜单项 key 数组 vertical
+ * TODO: 🎯 当前展开的 SubMenu 菜单项 key 数组 vertical
* TODO: 当前展开的 SubMenu 菜单项 key 数组 horizontal
* @default `[]`
*/
openUids?: string[];
/**
* TODO: 👀 当前选中的菜单项 key 数组(子菜单只高亮,不展开) inline
- * TODO: 当前选中的菜单项 key 数组(子菜单只高亮,不展开) vertical
+ * TODO: 👀 当前选中的菜单项 key 数组(子菜单只高亮,不展开) vertical
* TODO: 当前选中的菜单项 key 数组(子菜单只高亮,不展开) horizontal
* @default `[]`
*/
selectedUids?: string[];
/**
* TODO: 👀 是否允许选中(为 false, 点击不高亮,不触发 select事件) inline
- * TODO: 是否允许选中(为 false, 点击不高亮,不触发 select事件) vertical
+ * TODO: 👀 是否允许选中(为 false, 点击不高亮,不触发 select事件) vertical
* TODO: 是否允许选中(为 false, 点击不高亮,不触发 select事件) horizontal
* @default false
*/
selectable?: boolean;
/**
- * TODO: 用户鼠标离开子菜单后关闭延时,单位:毫秒(非 inline 模式, hover触发)
+ * TODO: 👀 用户鼠标离开子菜单后关闭延时,单位:毫秒(非 inline 模式, hover触发)
* @default 100ms
*/
subMenuCloseDelay?: number;
/**
- * TODO: 用户鼠标进入子菜单后开启延时,单位:毫秒(非 inline 模式, hover触发)
+ * TODO: 👀 用户鼠标进入子菜单后开启延时,单位:毫秒(非 inline 模式, hover触发)
* @default 0
*/
subMenuOpenDelay?: number;
@@ -137,14 +137,16 @@ export type KMenuProps = {
// TODO: 👀 onClick 点击 MenuItem 调用此函数(点击子菜单标题不触发) inline
// TODO: 👀 onOpenChange SubMenu 展开/关闭的回调 inline
// TODO: 👀 onSelect 被选中时调用(点击子菜单标题不触发) inline
-// TODO: onClick 点击 MenuItem 调用此函数(点击子菜单标题不触发) vertical
-// TODO: onOpenChange SubMenu 展开/关闭的回调 vertical
-// TODO: onSelect 被选中时调用(点击子菜单标题不触发) vertical
+
+// TODO: 👀 onClick 点击 MenuItem 调用此函数(点击子菜单标题不触发) vertical
+// TODO: 👀 onOpenChange SubMenu 展开/关闭的回调 vertical
+// TODO: 👀 onSelect 被选中时调用(点击子菜单标题不触发) vertical
+
// TODO: onClick 点击 MenuItem 调用此函数(点击子菜单标题不触发) horizontal
// TODO: onOpenChange SubMenu 展开/关闭的回调 horizontal
// TODO: onSelect 被选中时调用(点击子菜单标题不触发) horizontal
-// TODO: slots expandIcon 展开图标 vertical
+// TODO: 👀 slots expandIcon 展开图标 vertical
// TODO: slots expandIcon 展开图标 horizontal
// TODO: 👀 slots expandIcon 展开图标 inline
@@ -226,12 +228,12 @@ export type SubMenuType = {
// TODO: onTitleClick 点击子菜单标题
-// TODO: Items Slots slots label 分组标题 vertical
+// TODO: 🎯Items Slots slots label 分组标题 vertical
// TODO: Items Slots slots label 分组标题 horizontal
// TODO: 🎯Items Slots slots label 分组标题 inline
-// TODO: Items Slots slots icon 菜单图标 vertical
+// TODO: 👀 Items Slots slots icon 菜单图标 vertical
// TODO: Items Slots slots icon 菜单图标 horizontal
// TODO: 👀 Items Slots slots icon 菜单图标 inline
-// TODO: onSelect 选择子菜单时,再次选择被错误的取消
-// TODO: 🎯 测试非inline 模式下 ‘👀’ 的功能
+// TODO: 🎯 onSelect 选择子菜单时,选择和取消的预期行为是什么
+// TODO: 🎯 onOpenChange 选择和取消的预期行为是什么
From 81854d48702bc177090abe9b44dceb5f0d8c8bcb Mon Sep 17 00:00:00 2001
From: baiwusanyu-c <740132583@qq.com>
Date: Mon, 22 Apr 2024 13:39:08 +0800
Subject: [PATCH 28/39] wip: KMenu component completes vertical and inline mode
onDeSelect event
---
components/Menu/src/index.svelte | 11 ++++--
components/Menu/src/item.svelte | 60 +++++++++++++++-----------------
components/Menu/src/types.d.ts | 13 +++----
components/Menu/src/utils.ts | 6 ++--
4 files changed, 47 insertions(+), 43 deletions(-)
diff --git a/components/Menu/src/index.svelte b/components/Menu/src/index.svelte
index b300a6ab..4456d399 100644
--- a/components/Menu/src/index.svelte
+++ b/components/Menu/src/index.svelte
@@ -30,6 +30,10 @@
function onClick(data: ClickEvtPa) {
dispatch('click', data);
}
+
+ function onDeSelect(data: SelectEvtPa) {
+ dispatch('deSelect', data);
+ }
/**
* @internal
*/
@@ -46,11 +50,12 @@
multiple,
selectable,
attrs,
- ctxKey,
+ ctxKey
},
onOpenChange,
onSelect,
- onClick
+ onClick,
+ onDeSelect
);
if (!getContext(ctxKey || menuKey)) {
setContext(ctxKey || menuKey, menuInst);
@@ -69,7 +74,7 @@
selectedUids,
selectable,
attrs,
- ctxKey,
+ ctxKey
});
});
}
diff --git a/components/Menu/src/item.svelte b/components/Menu/src/item.svelte
index a54c5af9..6a2f30ca 100644
--- a/components/Menu/src/item.svelte
+++ b/components/Menu/src/item.svelte
@@ -8,8 +8,8 @@
import KMenu from './index';
import { getUidPath } from './utils';
import { KPopover } from '@ikun-ui/popover';
- import type { OffsetsFunction, OffsetsFnPa } from '@ikun-ui/popover';
- import {jsonClone} from "baiwusanyu-utils";
+ import type { OffsetsFunction, OffsetsFnPa } from '@ikun-ui/popover';
+ import { jsonClone } from 'baiwusanyu-utils';
export let items: KMenuItemProps['items'] = [];
export let cls: KMenuItemProps['cls'] = undefined;
export let attrs: KMenuItemProps['attrs'] = {};
@@ -41,7 +41,7 @@
const defaultSelected = menuCtx.__selectedUids?.has(value.uid || '');
const defaultOpen = menuCtx.__openUids?.has(value.uid || '');
value.selected = defaultSelected;
- value.inGroup = inGroup
+ value.inGroup = inGroup;
menuCtx.syncSelectedItems(value, value.selected ? 'set' : 'delete');
value.open = defaultOpen;
if (defaultSelected) {
@@ -65,7 +65,7 @@
}
}
- if(hasSub(value) && ctxProps.mode === 'vertical'){
+ if (hasSub(value) && ctxProps.mode === 'vertical') {
const recRes = initOpenSelectedStatus(value.children!, isGroup(value));
if (!isGroup(value)) {
value.children = recRes.children;
@@ -78,12 +78,12 @@
deps.push(value.uid!);
}
} else {
- const { children } = value
- value.children = []
+ const { children } = value;
+ value.children = [];
res.push({ ...value });
- res = res.concat(children!)
+ res = res.concat(children!);
deps = recRes.deps;
- return
+ return;
}
}
res.push({ ...value });
@@ -118,7 +118,6 @@
| { detail: { selected: boolean; uid: string } },
index: number
) {
-
const { selected, uid } = e.detail;
const it = itemsList[index];
if (!isGroup(it)) {
@@ -191,7 +190,7 @@
if (!hasSub(it) && !isGroup(it) && ctxProps.selectable) {
menuCtx.syncUids(it.uid!, 'selected', it.selected ? 'add' : 'delete');
menuCtx.syncSelectedItems(it, it.selected ? 'set' : 'delete');
- menuCtx.onSelect({
+ const params = {
item: it,
uid: it.uid!,
uidPath,
@@ -201,7 +200,12 @@
(uid) => getUidPath(uid, menuCtx.__org_items!) || []
),
e
- });
+ };
+ if (it.selected) {
+ menuCtx.onSelect(params);
+ } else {
+ menuCtx.onDeSelect(params);
+ }
}
}
}
@@ -228,13 +232,11 @@
const iconRootCls = clsx(`${prefixCls}-icon-root`);
$: expendIconCls = (it: SubMenuType) => {
- const icon = (ctxProps.expandIcon || 'i-carbon-chevron-down ');
+ const icon = ctxProps.expandIcon || 'i-carbon-chevron-down ';
if (ctxProps.mode === 'vertical') {
- return `${icon} -rotate-90`
+ return `${icon} -rotate-90`;
}
- return it.open
- ? `${icon} rotate-180 k-icon-transition`
- : `${icon} k-icon-transition`;
+ return it.open ? `${icon} rotate-180 k-icon-transition` : `${icon} k-icon-transition`;
};
const titleContentCls = (hasIcon: boolean) => {
@@ -252,17 +254,16 @@
const popoverContentCls = clsx(`${prefixCls}-popover-content p-0 box-border`);
const popoverTriggerCls = clsx(`${prefixCls}-popover-trigger-v`);
- $:getIndent = (it: SubMenuType) => {
- if(ctxProps.mode !== 'inline') {
- return `${it.inGroup ? (ctxProps.inlineIndent || 24) * 2 : ctxProps.inlineIndent}px`
+ $: getIndent = (it: SubMenuType) => {
+ if (ctxProps.mode !== 'inline') {
+ return `${it.inGroup ? (ctxProps.inlineIndent || 24) * 2 : ctxProps.inlineIndent}px`;
}
- return `${(ctxProps.inlineIndent || 24) * getLevel(it, level)}px`
- }
-
- const setPopoverOffset: OffsetsFunction = ({popper, reference}: OffsetsFnPa) => {
- return [popper.height / 2 - reference.height / 2, 4]
- }
+ return `${(ctxProps.inlineIndent || 24) * getLevel(it, level)}px`;
+ };
+ const setPopoverOffset: OffsetsFunction = ({ popper, reference }: OffsetsFnPa) => {
+ return [popper.height / 2 - reference.height / 2, 4];
+ };
{#each itemsList as it, index (it.uid)}
@@ -344,7 +345,7 @@
trigger={ctxProps.triggerSubMenuAction}
cls={popoverContentCls}
clsTrigger={popoverTriggerCls}
- disabled={!((hasSub(it)) || isGroup(it))}
+ disabled={!(hasSub(it) || isGroup(it))}
>
{#if it.type !== 'divider'}
@@ -378,12 +379,7 @@
{/if}
-
+
;
- ctxKey?: string
+ ctxKey?: string;
};
export type ClickEvtPa = {
@@ -49,6 +49,7 @@ export type KMenuInstance = {
) => void;
onOpenChange: (openUids: string[]) => void;
onSelect: (param: SelectEvtPa) => void;
+ onDeSelect: (param: SelectEvtPa) => void;
onClick: (param: ClickEvtPa) => void;
};
@@ -56,7 +57,7 @@ export type KMenuProps = {
/**
* TODO: 👀 上下文 key
*/
- ctxKey?: string
+ ctxKey?: string;
/**
* TODO: 👀 展开图标
* @default 'i-carbon-chevron-down'
@@ -137,14 +138,17 @@ export type KMenuProps = {
// TODO: 👀 onClick 点击 MenuItem 调用此函数(点击子菜单标题不触发) inline
// TODO: 👀 onOpenChange SubMenu 展开/关闭的回调 inline
// TODO: 👀 onSelect 被选中时调用(点击子菜单标题不触发) inline
+// TODO: 👀 onDeSelect 被选中时调用(点击子菜单标题不触发) inline
// TODO: 👀 onClick 点击 MenuItem 调用此函数(点击子菜单标题不触发) vertical
// TODO: 👀 onOpenChange SubMenu 展开/关闭的回调 vertical
// TODO: 👀 onSelect 被选中时调用(点击子菜单标题不触发) vertical
+// TODO: 👀 onDeSelect 被选中时调用(点击子菜单标题不触发) inline
// TODO: onClick 点击 MenuItem 调用此函数(点击子菜单标题不触发) horizontal
// TODO: onOpenChange SubMenu 展开/关闭的回调 horizontal
// TODO: onSelect 被选中时调用(点击子菜单标题不触发) horizontal
+// TODO: onDeSelect 被选中时调用(点击子菜单标题不触发) inline
// TODO: 👀 slots expandIcon 展开图标 vertical
// TODO: slots expandIcon 展开图标 horizontal
@@ -158,7 +162,7 @@ export type KMenuItemProps = {
/**
* TODO: 👀 上下文 key
*/
- ctxKey?: string
+ ctxKey?: string;
items: SubMenuType[];
cls: ClassValue;
attrs: Record;
@@ -234,6 +238,3 @@ export type SubMenuType = {
// TODO: 👀 Items Slots slots icon 菜单图标 vertical
// TODO: Items Slots slots icon 菜单图标 horizontal
// TODO: 👀 Items Slots slots icon 菜单图标 inline
-
-// TODO: 🎯 onSelect 选择子菜单时,选择和取消的预期行为是什么
-// TODO: 🎯 onOpenChange 选择和取消的预期行为是什么
diff --git a/components/Menu/src/utils.ts b/components/Menu/src/utils.ts
index 46eef5c6..892c8d5d 100644
--- a/components/Menu/src/utils.ts
+++ b/components/Menu/src/utils.ts
@@ -4,7 +4,8 @@ export const createKMenu = (
options: KMenuInstanceOption,
onOpenChange: KMenuInstance['onOpenChange'],
onSelect: KMenuInstance['onSelect'],
- onClick: KMenuInstance['onClick']
+ onClick: KMenuInstance['onClick'],
+ onDeSelect: KMenuInstance['onDeSelect']
): KMenuInstance => {
return {
/**
@@ -40,7 +41,8 @@ export const createKMenu = (
},
onOpenChange,
onSelect,
- onClick
+ onClick,
+ onDeSelect
};
};
From c5f8bcc67547843c776a6f124fe8adda07317421 Mon Sep 17 00:00:00 2001
From: baiwusanyu-c <740132583@qq.com>
Date: Mon, 22 Apr 2024 17:47:37 +0800
Subject: [PATCH 29/39] wip: KMenu component vertical mode openUids props temp
commit
---
components/Menu/src/item.svelte | 41 ++++++++++++++++++++++++++++-
components/Menu/src/types.d.ts | 4 +++
components/Popover/src/index.svelte | 21 ++++++++++-----
3 files changed, 59 insertions(+), 7 deletions(-)
diff --git a/components/Menu/src/item.svelte b/components/Menu/src/item.svelte
index 6a2f30ca..d0077bea 100644
--- a/components/Menu/src/item.svelte
+++ b/components/Menu/src/item.svelte
@@ -1,5 +1,5 @@
{#each itemsList as it, index (it.uid)}
@@ -461,4 +489,85 @@
{/if}
+
+ {#if ctxProps.mode === 'horizontal'}
+
+
+ {#if it.type !== 'divider'}
+ handleSelect(it, e)}
+ aria-hidden="true"
+ style:padding-left={`${getIndent(it)}`}
+ class={cnames(it)}
+ {...$$restProps}
+ {...attrs}
+ >
+
+
+
+ {#if it.icon}
+
+ {/if}
+
+ {it.label}
+
+
+ {#if hasSub(it) && !isGroup(it) && level !== 1}
+
+
+
+ {/if}
+
+
+ {:else}
+
+ {/if}
+
+
+
+ handleSelectedRecursion(e, index)}
+ items={it.children}
+ level={getLevel(it, level) + 1}
+ >
+
+
+
+
+ {#if item.icon}
+
+ {/if}
+
+ {item.label}
+
+ {#if hasSub(item)}
+
+
+
+ {/if}
+
+
+
+
+
+
+ {/if}
{/each}
diff --git a/components/Menu/src/types.d.ts b/components/Menu/src/types.d.ts
index 96f1f89c..16afd36e 100644
--- a/components/Menu/src/types.d.ts
+++ b/components/Menu/src/types.d.ts
@@ -60,6 +60,7 @@ export type KMenuProps = {
ctxKey?: string;
/**
* TODO: 👀 展开图标
+ * TODO: 展开图标 horizontal(more menu 展示)
* @default 'i-carbon-chevron-down'
*/
expandIcon?: string;
@@ -233,8 +234,11 @@ export type SubMenuType = {
// TODO: onTitleClick 点击子菜单标题
// TODO: 🎯Items Slots slots label 分组标题 vertical
-// TODO: Items Slots slots label 分组标题 horizontal
+// TODO: 🎯Items Slots slots label 分组标题 horizontal
// TODO: 🎯Items Slots slots label 分组标题 inline
// TODO: 👀 Items Slots slots icon 菜单图标 vertical
// TODO: Items Slots slots icon 菜单图标 horizontal
// TODO: 👀 Items Slots slots icon 菜单图标 inline
+
+// 🎯 TODO horizontal 缩略适配
+// 🎯 TODO 所有 👀 功能
diff --git a/preset/src/shortcuts/src/common.ts b/preset/src/shortcuts/src/common.ts
index 44f00c14..f8dc7fe4 100644
--- a/preset/src/shortcuts/src/common.ts
+++ b/preset/src/shortcuts/src/common.ts
@@ -40,6 +40,7 @@ export const commonShortcuts: UserShortcuts = {
'n-bdl-1': 'border-l-0 border-t-1 border-b-1 border-r-1',
'bd-2': 'border-t-2 border-l-2 border-b-2 border-r-2',
'bdl-2': 'border-l-2 border-t-0 border-b-0 border-r-0',
+ 'bdb-2': 'border-l-0 border-t-0 border-b-2 border-r-0',
'bdtr-2': 'border-l-0 border-t-2 border-b-0 border-r-2',
'bd-3': 'border-t-3 border-l-3 border-b-3 border-r-3'
};
diff --git a/preset/src/shortcuts/src/menu.ts b/preset/src/shortcuts/src/menu.ts
index e4a8a809..2cc9ddcb 100644
--- a/preset/src/shortcuts/src/menu.ts
+++ b/preset/src/shortcuts/src/menu.ts
@@ -12,24 +12,40 @@ export const menuShortcuts: Record = {
'k-menu-sub': 'border-none bg-transparent',
'k-menu-sub-bg': 'ikun:2:bg-black',
- 'k-menu-horizontal': '',
- 'k-menu-item-horizontal': '',
-
'k-menu-item-selected': 'ikun:20:bg-ikun-main text-ikun-main hover:(ikun:20:bg-ikun-main)',
- 'k-menu-item-selected-ih': 'text-ikun-main',
- 'k-menu-item-hover-ih': 'hover:(ikun:6:bg-ikun-black)',
- 'k-menu-item-vh-child': 'justify-between',
+ 'k-menu-item-selected-group': 'text-ikun-main',
+ 'k-menu-item-hover': 'hover:(ikun:6:bg-ikun-black)',
- 'k-menu-inline': 'bdr-1 b-e-solid border-ikun-bd-base',
- 'k-menu-vertical': 'bdr-1 b-e-solid border-ikun-bd-base',
+ 'k-menu-item-selected-after':
+ 'after:(content-empty pa bottom-0 bdb-2 border-solid b-b-ikun-main w-full left-0 animate-ikun-scale)',
+ 'k-menu-item-selected-h': 'text-ikun-main k-menu-item-selected-after',
+ 'k-menu-item-selected-group-h': 'text-ikun-main k-menu-item-selected-after',
+ 'k-menu-item-hover-h': 'hover:(k-menu-item-selected-after)',
- 'k-menu-item-popover-trigger-v': 'box-border my-4px',
+ 'k-menu-item-child': 'justify-between',
+
+ 'k-menu-vertical': 'bdr-1 b-e-solid border-ikun-bd-base',
+ 'k-menu-item-popover-trigger-vertical': 'box-border my-4px',
'k-menu-item-vertical': 'k-menu-item-inline my-0',
'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-e-solid border-ikun-bd-base flex [&.k-menu-sub-horizontal]:block',
+ 'k-menu-item-popover-trigger-horizontal': 'box-border my-4px',
+ 'k-menu-item-popover-content': 'p-0 box-border',
+ 'k-menu-item-horizontal':
+ '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 ' +
+ 'rounded-8px my-0',
+ 'k-menu-item-horizontal-not-top': 'k-menu-item-horizontal active:(ikun:20:bg-ikun-main)',
+ 'k-menu-item-horizontal-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-inline': 'bdr-1 b-e-solid border-ikun-bd-base',
'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 ' +
diff --git a/preset/src/theme/index.ts b/preset/src/theme/index.ts
index cffdbd44..fea255cb 100644
--- a/preset/src/theme/index.ts
+++ b/preset/src/theme/index.ts
@@ -123,6 +123,16 @@ const getAnimation = (themeColor: string) => {
'ikun-skeleton-loading': `{
0% { background-position: 100% 50%;}
100% { background-position: 0 50%; }
+ }`,
+ 'ikun-scale': `{
+ from {
+ transform: scale(0);
+ opacity: 0;
+ }
+ to {
+ transform: scale(1);
+ opacity: 1;
+ }
}`
},
durations: {
@@ -134,7 +144,8 @@ const getAnimation = (themeColor: string) => {
'ikun-checking-main': '.3s',
'ikun-checking': '.3s',
'ikun-switching': '.3s',
- 'ikun-skeleton-loading': '1.4s'
+ 'ikun-skeleton-loading': '1.4s',
+ 'ikun-scale': '.3s'
},
timingFns: {
'ikun-clicking--success': 'linear',
@@ -146,7 +157,8 @@ const getAnimation = (themeColor: string) => {
'ikun-clicking': 'linear',
'ikun-checking': 'linear',
'ikun-switching': 'linear',
- 'ikun-skeleton-loading': 'ease'
+ 'ikun-skeleton-loading': 'ease',
+ 'ikun-scale': 'forwards'
},
counts: {
'ikun-skeleton-loading': 'infinite'
From a1a40a42f731c2159c6e45062ceb8e693770c969 Mon Sep 17 00:00:00 2001
From: baiwusanyu-c <740132583@qq.com>
Date: Tue, 23 Apr 2024 18:00:45 +0800
Subject: [PATCH 32/39] wip: optimization the styling of the KMenu component in
horizontal mode
---
components/Menu/src/index.svelte | 1 -
components/Menu/src/item.svelte | 18 +++++++++++++-----
components/Menu/src/types.d.ts | 8 ++++----
preset/src/shortcuts/src/menu.ts | 10 ++++++----
4 files changed, 23 insertions(+), 14 deletions(-)
diff --git a/components/Menu/src/index.svelte b/components/Menu/src/index.svelte
index 4456d399..040d1bf0 100644
--- a/components/Menu/src/index.svelte
+++ b/components/Menu/src/index.svelte
@@ -87,7 +87,6 @@
{
return clsx(`${menuPrefixCls}-sub`, `${menuPrefixCls}-sub-${ctxProps.mode}`, {
[`${menuPrefixCls}-sub-bg`]: !isGroup
@@ -316,7 +319,12 @@
};
const popoverContentCls = clsx(`${prefixCls}-popover-content`);
- const popoverTriggerCls = clsx(`${prefixCls}-popover-trigger-${ctxProps.mode}`);
+ const popoverTriggerCls = (isDivider: boolean = false) => {
+ return clsx({
+ [`${prefixCls}-popover-trigger-${ctxProps.mode}`]: !isDivider && isNotHorizontalTop(),
+ [`${prefixCls}-popover-trigger-${ctxProps.mode}-divider`]: isDivider && !isNotHorizontalTop()
+ });
+ };
$: getIndent = (it: SubMenuType) => {
if (ctxProps.mode === 'horizontal' && level === 1) return '16px';
if (ctxProps.mode !== 'inline') {
@@ -422,7 +430,7 @@
mouseLeaveDelay={ctxProps.subMenuCloseDelay}
trigger={ctxProps.triggerSubMenuAction}
cls={popoverContentCls}
- clsTrigger={popoverTriggerCls}
+ clsTrigger={popoverTriggerCls(false)}
disabled={!(hasSub(it) || isGroup(it))}
>
@@ -503,7 +511,7 @@
mouseLeaveDelay={ctxProps.subMenuCloseDelay}
trigger={ctxProps.triggerSubMenuAction}
cls={popoverContentCls}
- clsTrigger={popoverTriggerCls}
+ clsTrigger={popoverTriggerCls(it.type === 'divider')}
disabled={!(hasSub(it) || isGroup(it))}
>
@@ -534,7 +542,7 @@
{:else}
-
+
{/if}
diff --git a/components/Menu/src/types.d.ts b/components/Menu/src/types.d.ts
index 16afd36e..f5ec36f4 100644
--- a/components/Menu/src/types.d.ts
+++ b/components/Menu/src/types.d.ts
@@ -76,8 +76,8 @@ export type KMenuProps = {
inlineCollapsed?: boolean;
/**
* TODO: 👀 菜单类型,现在支持垂直、水平、和内嵌模式三种 inline
- * TODO: 🎯 菜单类型,现在支持垂直、水平、和内嵌模式三种 vertical
- * TODO: 菜单类型,现在支持垂直、水平、和内嵌模式三种 horizontal
+ * TODO: 👀 菜单类型,现在支持垂直、水平、和内嵌模式三种 vertical
+ * TODO: 🎯 菜单类型,现在支持垂直、水平、和内嵌模式三种 horizontal
* `vertical` 和 `inline` 的区别在于 `vertical` 子菜单以 popover 形式出现
* @default `vertical`
*/
@@ -237,8 +237,8 @@ export type SubMenuType = {
// TODO: 🎯Items Slots slots label 分组标题 horizontal
// TODO: 🎯Items Slots slots label 分组标题 inline
// TODO: 👀 Items Slots slots icon 菜单图标 vertical
-// TODO: Items Slots slots icon 菜单图标 horizontal
+// TODO: 👀 Items Slots slots icon 菜单图标 horizontal
// TODO: 👀 Items Slots slots icon 菜单图标 inline
// 🎯 TODO horizontal 缩略适配
-// 🎯 TODO 所有 👀 功能
+// 🎯 TODO 所有 👀 功能 分(exclude Items Slots slots icon 菜单图标 inline)
diff --git a/preset/src/shortcuts/src/menu.ts b/preset/src/shortcuts/src/menu.ts
index 2cc9ddcb..3105a7e2 100644
--- a/preset/src/shortcuts/src/menu.ts
+++ b/preset/src/shortcuts/src/menu.ts
@@ -17,14 +17,14 @@ export const menuShortcuts: Record
= {
'k-menu-item-hover': 'hover:(ikun:6:bg-ikun-black)',
'k-menu-item-selected-after':
- 'after:(content-empty pa bottom-0 bdb-2 border-solid b-b-ikun-main w-full left-0 animate-ikun-scale)',
+ 'after:(content-empty pa -bottom-1px bdb-2 border-solid b-b-ikun-main w-full left-0 animate-ikun-scale)',
'k-menu-item-selected-h': 'text-ikun-main k-menu-item-selected-after',
'k-menu-item-selected-group-h': 'text-ikun-main k-menu-item-selected-after',
'k-menu-item-hover-h': 'hover:(k-menu-item-selected-after)',
'k-menu-item-child': 'justify-between',
- 'k-menu-vertical': 'bdr-1 b-e-solid border-ikun-bd-base',
+ '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-item-vertical-group':
@@ -32,7 +32,7 @@ export const menuShortcuts: Record = {
'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-e-solid border-ikun-bd-base flex [&.k-menu-sub-horizontal]:block',
+ '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-item-popover-content': 'p-0 box-border',
'k-menu-item-horizontal':
@@ -44,8 +44,10 @@ export const menuShortcuts: Record = {
'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-item-popover-trigger-horizontal-divider': 'fcc',
+ 'k-menu-item-divider-horizontal': 'h-32px',
- 'k-menu-inline': 'bdr-1 b-e-solid border-ikun-bd-base',
+ '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 ' +
From 65dc2cb3e1f543bf2447a90fe5dd3ee59bbe3db6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E7=99=BD=E9=9B=BE=E4=B8=89=E8=AF=AD?=
<32354856+baiwusanyu-c@users.noreply.github.com>
Date: Tue, 23 Apr 2024 22:08:46 +0800
Subject: [PATCH 33/39] wip: complete KMenu component temp commit
---
components/Menu/package.json | 1 +
components/Menu/src/item.svelte | 53 +++++++++++++++++++++++++++-----
components/Menu/src/types.d.ts | 17 +++++-----
pnpm-lock.yaml | 3 ++
preset/src/shortcuts/src/menu.ts | 4 +--
5 files changed, 59 insertions(+), 19 deletions(-)
diff --git a/components/Menu/package.json b/components/Menu/package.json
index fac95ad4..4264c119 100644
--- a/components/Menu/package.json
+++ b/components/Menu/package.json
@@ -37,6 +37,7 @@
"@ikun-ui/divider": "workspace:*",
"@ikun-ui/popover": "workspace:*",
"baiwusanyu-utils": "^1.0.18",
+ "esm-env": "^1.0.0",
"clsx": "^2.0.0",
"svelte": "^4.2.7"
},
diff --git a/components/Menu/src/item.svelte b/components/Menu/src/item.svelte
index 48cc1d79..c7921e07 100644
--- a/components/Menu/src/item.svelte
+++ b/components/Menu/src/item.svelte
@@ -1,5 +1,5 @@
{#if show}
-
+
{/if}
diff --git a/components/Menu/src/item.svelte b/components/Menu/src/item.svelte
index 08fbaca2..6030bea3 100644
--- a/components/Menu/src/item.svelte
+++ b/components/Menu/src/item.svelte
@@ -224,6 +224,9 @@
}
}
+
+
+
let popoverRef: any = [];
let subMenuRef: any = [];
let isDirty = true;
@@ -254,10 +257,12 @@
let parentDom: HTMLElement | null = null
let itemEls: HTMLElement[] | null = null
+ let prevParentDomWidth = -1
+ let ops = Array(items.length).fill(level === 1 ? '0' : '1');
if(BROWSER){
parentDom = document.querySelector('#bwsy');
if(parentDom){
- itemEls = (parentDom.querySelectorAll('[data-popover-trigger=""]'))
+ itemEls = Array.from((parentDom.querySelectorAll('[data-popover-trigger=""]')))
}
}
let moreItems: Array<{
@@ -268,53 +273,66 @@
function adjustLayout() {
if(parentDom && level === 1){
const parentWidth = parentDom.offsetWidth;
+ let toS = false
+ let init = false
+ if(prevParentDomWidth === -1){
+ init = true
+ prevParentDomWidth = parentWidth
+ }
+
+ if(prevParentDomWidth < parentWidth){
+ toS = false
+ }
+
+ if(prevParentDomWidth > parentWidth){
+ toS = true
+ }
+ prevParentDomWidth = parentWidth
+
let totalWidth = 0;
- let childrenToMove: Array<{
- item: SubMenuType,
- width: number,
- index: number
- }> = [];
itemEls!.forEach((child: any, index: number) => {
const offsetWidth = (child as HTMLElement).offsetWidth;
totalWidth += offsetWidth
- if (totalWidth > parentWidth) {
+ if (totalWidth > parentWidth && (toS || init)) {
(child as HTMLElement).style.opacity = '0';
(child as HTMLElement).style.height = '0';
(child as HTMLElement).style.overflowY = 'hidden';
(child as HTMLElement).style.position = 'absolute';
(child as HTMLElement).style.pointerEvents = 'none';
- (child as HTMLElement).style.width = 'auto';
- childrenToMove.push({
+ (child as HTMLElement).style.width = '0';
+ const has = moreItems.some(it => it.index === index)
+ !has && moreItems.push({
index,
item: itemsList[index],
width:offsetWidth
});
+ init && (moreItems = moreItems.sort((a, b) => {return b.index - a.index}))
+ } else {
+ ops[index] = '1'
}
});
- if (childrenToMove.length > 0) {
- // 将超出宽度的子节点从 Arr1 移到 Arr2
- moreItems = moreItems.concat(childrenToMove);
- } else {
- let spaceAvailable = parentWidth - totalWidth;
- const moreItemsLen = moreItems.length
- const lastItem = moreItems[moreItemsLen - 1]
- if(lastItem){
- const lastItemWidth = lastItem.width
- console.log(spaceAvailable, lastItemWidth)
- if (moreItems.length > 0 && spaceAvailable >= lastItemWidth) {
- const index = (moreItems.pop()!).index
- const dom = itemEls![index]
- if(dom){
- (dom as HTMLElement).style.opacity = '1';
- (dom as HTMLElement).style.width = '100';
- (dom as HTMLElement).style.removeProperty('height');
- (dom as HTMLElement).style.removeProperty('overflow-y');
- (dom as HTMLElement).style.removeProperty('position');
- (dom as HTMLElement).style.removeProperty('pointer-events');
- }
- }
- }
+ if(toS === false && !init){
+ let spaceAvailable = Math.abs(totalWidth - parentWidth);
+ const moreItemsLen = moreItems.length
+ const lastItem = moreItems[moreItemsLen - 1]
+ if(lastItem){
+ const lastItemWidth = lastItem.width
+ if (moreItems.length > 0 && spaceAvailable >= lastItemWidth) {
+ const index = (moreItems.pop()!).index
+ console.log(index)
+ const dom = itemEls![index]
+ if(dom){
+ (dom as HTMLElement).style.opacity = '1';
+ (dom as HTMLElement).style.width = '100';
+ (dom as HTMLElement).style.removeProperty('height');
+ (dom as HTMLElement).style.removeProperty('overflow-y');
+ (dom as HTMLElement).style.removeProperty('position');
+ (dom as HTMLElement).style.removeProperty('pointer-events');
+ (dom as HTMLElement).style.removeProperty('width');
+ }
+ }
+ }
}
}
@@ -327,11 +345,12 @@
showPopoverManual();
}
if (BROWSER && level === 1 && ctxProps.mode == 'horizontal') {
- window.addEventListener('resize', adjustLayout);
- await tick()
adjustLayout();
+ await tick()
+ window.addEventListener('resize', adjustLayout);
// showPopoverManual();
}
+ menuCtx.removeBorderStyleBg()
});
@@ -341,6 +360,9 @@
}
})
+
+
+
const menuPrefixCls = getPrefixCls('menu');
const prefixCls = getPrefixCls('menu-item');
$: cnames = (it: SubMenuType) => {
@@ -583,6 +605,7 @@
width="100%"
order={index}
arrow={false}
+ opacity={ops[index]}
placement={level === 1 ? 'bottom' : 'right'}
on:animateStart={showSubMenuPopover}
offset={setPopoverOffset}
diff --git a/components/Menu/src/types.d.ts b/components/Menu/src/types.d.ts
index d89c6fb0..ee624135 100644
--- a/components/Menu/src/types.d.ts
+++ b/components/Menu/src/types.d.ts
@@ -51,6 +51,7 @@ export type KMenuInstance = {
onSelect: (param: SelectEvtPa) => void;
onDeSelect: (param: SelectEvtPa) => void;
onClick: (param: ClickEvtPa) => void;
+ removeBorderStyleBg: () => void
};
export type KMenuProps = {
@@ -241,6 +242,6 @@ export type SubMenuType = {
// TODO: 👀 Items Slots slots icon 菜单图标 inline
// 🎯 TODO horizontal 缩略适配
-// 🎯 TODO horizontal 缩略颤抖
-// 🎯 TODO horizontal 缩略与默认打开冲突
-// 🎯 TODO horizontal 获取父节点
+// -- 🎯 TODO 缩略重构
+// -- 🎯 TODO horizontal 缩略与默认打开冲突
+// -- 🎯 TODO horizontal 获取父节点
diff --git a/components/Menu/src/utils.ts b/components/Menu/src/utils.ts
index 892c8d5d..45726f85 100644
--- a/components/Menu/src/utils.ts
+++ b/components/Menu/src/utils.ts
@@ -5,7 +5,8 @@ export const createKMenu = (
onOpenChange: KMenuInstance['onOpenChange'],
onSelect: KMenuInstance['onSelect'],
onClick: KMenuInstance['onClick'],
- onDeSelect: KMenuInstance['onDeSelect']
+ onDeSelect: KMenuInstance['onDeSelect'],
+ removeBorderStyleBg: KMenuInstance['removeBorderStyleBg'],
): KMenuInstance => {
return {
/**
@@ -42,7 +43,8 @@ export const createKMenu = (
onOpenChange,
onSelect,
onClick,
- onDeSelect
+ onDeSelect,
+ removeBorderStyleBg
};
};
diff --git a/components/Popover/src/index.svelte b/components/Popover/src/index.svelte
index f922c9a5..12142cce 100644
--- a/components/Popover/src/index.svelte
+++ b/components/Popover/src/index.svelte
@@ -23,6 +23,7 @@
export let width: KPopoverProps['width'] = 'fit-content';
export let order: undefined | number = undefined;
export let offset: KPopoverProps['offset'] = [0, 8];
+ export let opacity: string = ''
export let fallbackPlacements: KPopoverProps['fallbackPlacements'] = [
'top',
'right',
@@ -214,6 +215,7 @@
class={triggerCls}
style:width
style:order={order}
+ style:opacity={opacity}
data-popover-trigger
on:mouseenter={handleMouseenter}
on:mouseleave={handleMouseleave}
From 275cd8de244c06cf07af3ef82a84782f43b79f4d Mon Sep 17 00:00:00 2001
From: baiwusanyu-c <740132583@qq.com>
Date: Thu, 25 Apr 2024 15:39:59 +0800
Subject: [PATCH 36/39] wip: horizontal mode is turned on by default and is
compatible with
---
components/Menu/src/index.svelte | 32 ++++---
components/Menu/src/item.svelte | 126 ++++++++++++++--------------
components/Menu/src/types.d.ts | 8 +-
components/Menu/src/utils.ts | 4 +-
components/Popover/src/index.svelte | 8 +-
preset/src/shortcuts/src/common.ts | 4 +-
preset/src/shortcuts/src/menu.ts | 2 +-
7 files changed, 100 insertions(+), 84 deletions(-)
diff --git a/components/Menu/src/index.svelte b/components/Menu/src/index.svelte
index 3adad328..31298925 100644
--- a/components/Menu/src/index.svelte
+++ b/components/Menu/src/index.svelte
@@ -35,9 +35,16 @@
dispatch('deSelect', data);
}
- let bdBg = 'transparent'
- function removeBorderStyleBg(){
- bdBg = ''
+ let bdBg = 'transparent';
+ function removeBorderStyleBg() {
+ bdBg = '';
+ }
+
+ let menuRef: null | HTMLElement = null;
+ function getParentDom() {
+ if (menuRef) {
+ return menuRef.parentElement;
+ }
}
/**
* @internal
@@ -61,7 +68,8 @@
onSelect,
onClick,
onDeSelect,
- removeBorderStyleBg
+ removeBorderStyleBg,
+ getParentDom
);
if (!getContext(ctxKey || menuKey)) {
setContext(ctxKey || menuKey, menuInst);
@@ -90,15 +98,15 @@
{#if show}
-
+
diff --git a/components/Menu/src/item.svelte b/components/Menu/src/item.svelte
index 6030bea3..9a0aae95 100644
--- a/components/Menu/src/item.svelte
+++ b/components/Menu/src/item.svelte
@@ -1,5 +1,5 @@