@teamix-evo/ui 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +184 -184
- package/manifest.json +680 -492
- package/package.json +15 -9
- package/src/components/accordion/accordion.meta.md +5 -9
- package/src/components/accordion/accordion.stories.tsx +3 -3
- package/src/components/accordion/accordion.tsx +104 -8
- package/src/components/affix/affix.meta.md +21 -12
- package/src/components/affix/affix.stories.tsx +101 -26
- package/src/components/affix/affix.tsx +79 -9
- package/src/components/alert/alert.meta.md +52 -26
- package/src/components/alert/alert.stories.tsx +66 -21
- package/src/components/alert/alert.tsx +81 -34
- package/src/components/alert-dialog/alert-dialog.meta.md +48 -16
- package/src/components/alert-dialog/alert-dialog.stories.tsx +145 -3
- package/src/components/alert-dialog/alert-dialog.tsx +60 -13
- package/src/components/anchor/anchor.meta.md +10 -14
- package/src/components/anchor/anchor.stories.tsx +3 -3
- package/src/components/anchor/anchor.tsx +2 -2
- package/src/components/app/app.meta.md +10 -14
- package/src/components/app/app.stories.tsx +6 -6
- package/src/components/aspect-ratio/aspect-ratio.meta.md +4 -8
- package/src/components/aspect-ratio/aspect-ratio.stories.tsx +3 -3
- package/src/components/auto-complete/auto-complete.meta.md +19 -20
- package/src/components/auto-complete/auto-complete.stories.tsx +44 -3
- package/src/components/auto-complete/auto-complete.tsx +119 -71
- package/src/components/avatar/avatar.meta.md +9 -22
- package/src/components/avatar/avatar.stories.tsx +21 -3
- package/src/components/avatar/avatar.tsx +24 -23
- package/src/components/badge/badge.meta.md +14 -18
- package/src/components/badge/badge.stories.tsx +2 -2
- package/src/components/badge/badge.tsx +2 -2
- package/src/components/breadcrumb/breadcrumb.meta.md +29 -20
- package/src/components/breadcrumb/breadcrumb.stories.tsx +120 -5
- package/src/components/breadcrumb/breadcrumb.tsx +22 -8
- package/src/components/button/button.meta.md +261 -29
- package/src/components/button/button.stories.tsx +549 -41
- package/src/components/button/button.tsx +335 -33
- package/src/components/calendar/calendar.meta.md +19 -14
- package/src/components/calendar/calendar.stories.tsx +5 -5
- package/src/components/calendar/calendar.tsx +73 -8
- package/src/components/card/card.meta.md +31 -34
- package/src/components/card/card.stories.tsx +34 -3
- package/src/components/card/card.tsx +146 -63
- package/src/components/carousel/carousel.meta.md +10 -14
- package/src/components/carousel/carousel.stories.tsx +1 -1
- package/src/components/cascader/cascader.meta.md +43 -22
- package/src/components/cascader/cascader.stories.tsx +13 -2
- package/src/components/cascader/cascader.tsx +427 -84
- package/src/components/checkbox/checkbox.meta.md +74 -24
- package/src/components/checkbox/checkbox.stories.tsx +160 -2
- package/src/components/checkbox/checkbox.tsx +77 -9
- package/src/components/collapsible/collapsible.meta.md +7 -6
- package/src/components/collapsible/collapsible.stories.tsx +2 -2
- package/src/components/collapsible/collapsible.tsx +93 -6
- package/src/components/color-picker/color-picker.meta.md +16 -20
- package/src/components/color-picker/color-picker.stories.tsx +86 -7
- package/src/components/color-picker/color-picker.tsx +19 -9
- package/src/components/command/command.meta.md +7 -11
- package/src/components/command/command.stories.tsx +4 -4
- package/src/components/command/command.tsx +18 -7
- package/src/components/context-menu/context-menu.meta.md +5 -25
- package/src/components/context-menu/context-menu.stories.tsx +4 -4
- package/src/components/context-menu/context-menu.tsx +21 -8
- package/src/components/data-table/data-table.meta.md +14 -18
- package/src/components/data-table/data-table.stories.tsx +1 -1
- package/src/components/data-table/data-table.tsx +2 -2
- package/src/components/date-picker/date-picker.meta.md +90 -41
- package/src/components/date-picker/date-picker.stories.tsx +55 -5
- package/src/components/date-picker/date-picker.tsx +1489 -91
- package/src/components/descriptions/descriptions.meta.md +12 -16
- package/src/components/descriptions/descriptions.stories.tsx +2 -2
- package/src/components/descriptions/descriptions.tsx +22 -14
- package/src/components/dialog/dialog.meta.md +67 -17
- package/src/components/dialog/dialog.stories.tsx +182 -20
- package/src/components/dialog/dialog.tsx +67 -15
- package/src/components/dialog/imperative.tsx +252 -0
- package/src/components/drawer/drawer.meta.md +27 -39
- package/src/components/drawer/drawer.stories.tsx +29 -12
- package/src/components/drawer/drawer.tsx +22 -114
- package/src/components/dropdown-menu/dropdown-menu.meta.md +64 -24
- package/src/components/dropdown-menu/dropdown-menu.stories.tsx +81 -3
- package/src/components/dropdown-menu/dropdown-menu.tsx +24 -10
- package/src/components/ellipsis/ellipsis.meta.md +87 -0
- package/src/components/ellipsis/ellipsis.stories.tsx +72 -0
- package/src/components/ellipsis/ellipsis.tsx +153 -0
- package/src/components/empty/empty.meta.md +10 -14
- package/src/components/empty/empty.stories.tsx +3 -3
- package/src/components/empty/empty.tsx +10 -3
- package/src/components/field/field.meta.md +46 -25
- package/src/components/field/field.stories.tsx +380 -3
- package/src/components/field/field.tsx +263 -35
- package/src/components/filter-bar/filter-bar.meta.md +92 -0
- package/src/components/filter-bar/filter-bar.stories.tsx +1083 -0
- package/src/components/filter-bar/filter-bar.tsx +568 -0
- package/src/components/flex/flex.meta.md +59 -20
- package/src/components/flex/flex.stories.tsx +65 -10
- package/src/components/flex/flex.tsx +27 -4
- package/src/components/float-button/float-button.meta.md +10 -29
- package/src/components/float-button/float-button.stories.tsx +6 -6
- package/src/components/form/form.meta.md +31 -52
- package/src/components/form/form.stories.tsx +350 -3
- package/src/components/form/form.tsx +101 -35
- package/src/components/grid/grid.meta.md +4 -24
- package/src/components/grid/grid.stories.tsx +2 -2
- package/src/components/hover-card/hover-card.meta.md +9 -10
- package/src/components/hover-card/hover-card.stories.tsx +29 -4
- package/src/components/hover-card/hover-card.tsx +51 -13
- package/src/components/icon/DEVELOPMENT.md +809 -0
- package/src/components/icon/icon.meta.md +170 -0
- package/src/components/icon/icon.stories.tsx +344 -0
- package/src/components/icon/icon.tsx +248 -0
- package/src/components/image/image.meta.md +14 -18
- package/src/components/image/image.stories.tsx +3 -3
- package/src/components/image/image.tsx +2 -0
- package/src/components/input/demo/sizes.tsx +2 -2
- package/src/components/input/input.meta.md +44 -43
- package/src/components/input/input.stories.tsx +62 -35
- package/src/components/input/input.tsx +96 -101
- package/src/components/input-group/input-group.meta.md +53 -39
- package/src/components/input-group/input-group.stories.tsx +49 -16
- package/src/components/input-group/input-group.tsx +43 -8
- package/src/components/input-number/input-number.meta.md +68 -20
- package/src/components/input-number/input-number.stories.tsx +33 -6
- package/src/components/input-number/input-number.tsx +79 -20
- package/src/components/input-otp/input-otp.meta.md +8 -20
- package/src/components/input-otp/input-otp.stories.tsx +3 -3
- package/src/components/input-otp/input-otp.tsx +1 -1
- package/src/components/item/item.meta.md +8 -26
- package/src/components/item/item.stories.tsx +3 -3
- package/src/components/item/item.tsx +7 -6
- package/src/components/kbd/kbd.meta.md +7 -19
- package/src/components/kbd/kbd.stories.tsx +4 -4
- package/src/components/kbd/kbd.tsx +8 -4
- package/src/components/label/label.meta.md +21 -18
- package/src/components/label/label.stories.tsx +64 -6
- package/src/components/label/label.tsx +91 -19
- package/src/components/masonry/masonry.meta.md +8 -12
- package/src/components/masonry/masonry.stories.tsx +4 -4
- package/src/components/mentions/mentions.meta.md +42 -21
- package/src/components/mentions/mentions.stories.tsx +120 -6
- package/src/components/mentions/mentions.tsx +10 -5
- package/src/components/menubar/menubar.meta.md +4 -8
- package/src/components/menubar/menubar.stories.tsx +55 -3
- package/src/components/menubar/menubar.tsx +9 -9
- package/src/components/native-select/native-select.meta.md +7 -11
- package/src/components/native-select/native-select.stories.tsx +4 -4
- package/src/components/native-select/native-select.tsx +1 -1
- package/src/components/navigation-menu/navigation-menu.meta.md +4 -8
- package/src/components/navigation-menu/navigation-menu.stories.tsx +106 -3
- package/src/components/navigation-menu/navigation-menu.tsx +6 -3
- package/src/components/notification/notification.meta.md +41 -8
- package/src/components/notification/notification.stories.tsx +9 -9
- package/src/components/notification/notification.tsx +34 -19
- package/src/components/page-header/DEVELOPMENT.md +842 -0
- package/src/components/page-header/page-header.meta.md +208 -0
- package/src/components/page-header/page-header.stories.tsx +421 -0
- package/src/components/page-header/page-header.tsx +281 -0
- package/src/components/pagination/pagination.meta.md +122 -50
- package/src/components/pagination/pagination.stories.tsx +227 -11
- package/src/components/pagination/pagination.tsx +355 -63
- package/src/components/popconfirm/popconfirm.meta.md +19 -23
- package/src/components/popconfirm/popconfirm.stories.tsx +2 -2
- package/src/components/popconfirm/popconfirm.tsx +1 -1
- package/src/components/popover/popover.meta.md +64 -12
- package/src/components/popover/popover.stories.tsx +83 -7
- package/src/components/popover/popover.tsx +77 -28
- package/src/components/progress/progress.meta.md +43 -26
- package/src/components/progress/progress.stories.tsx +2 -2
- package/src/components/progress/progress.tsx +19 -11
- package/src/components/radio-group/radio-group.meta.md +78 -11
- package/src/components/radio-group/radio-group.stories.tsx +38 -2
- package/src/components/radio-group/radio-group.tsx +149 -18
- package/src/components/rate/rate.meta.md +41 -19
- package/src/components/rate/rate.stories.tsx +2 -2
- package/src/components/rate/rate.tsx +37 -10
- package/src/components/resizable/resizable.meta.md +4 -12
- package/src/components/resizable/resizable.stories.tsx +5 -5
- package/src/components/resizable/resizable.tsx +1 -1
- package/src/components/result/result.meta.md +10 -14
- package/src/components/result/result.stories.tsx +2 -2
- package/src/components/result/result.tsx +21 -12
- package/src/components/scroll-area/scroll-area.meta.md +4 -8
- package/src/components/scroll-area/scroll-area.stories.tsx +5 -5
- package/src/components/segmented/segmented.meta.md +15 -17
- package/src/components/segmented/segmented.stories.tsx +3 -3
- package/src/components/segmented/segmented.tsx +15 -7
- package/src/components/select/select.meta.md +199 -67
- package/src/components/select/select.stories.tsx +238 -63
- package/src/components/select/select.tsx +718 -171
- package/src/components/separator/separator.meta.md +10 -14
- package/src/components/separator/separator.stories.tsx +2 -2
- package/src/components/separator/separator.tsx +3 -7
- package/src/components/sheet/sheet.meta.md +26 -21
- package/src/components/sheet/sheet.stories.tsx +116 -10
- package/src/components/sheet/sheet.tsx +116 -29
- package/src/components/sidebar/sidebar.meta.md +28 -38
- package/src/components/sidebar/sidebar.stories.tsx +696 -29
- package/src/components/sidebar/sidebar.tsx +615 -142
- package/src/components/skeleton/skeleton.meta.md +7 -31
- package/src/components/skeleton/skeleton.stories.tsx +3 -3
- package/src/components/skeleton/skeleton.tsx +7 -7
- package/src/components/slider/slider.meta.md +60 -13
- package/src/components/slider/slider.stories.tsx +58 -6
- package/src/components/slider/slider.tsx +154 -13
- package/src/components/sonner/sonner.meta.md +54 -8
- package/src/components/sonner/sonner.stories.tsx +79 -11
- package/src/components/sonner/sonner.tsx +137 -8
- package/src/components/spinner/spinner.meta.md +57 -21
- package/src/components/spinner/spinner.stories.tsx +66 -14
- package/src/components/spinner/spinner.tsx +111 -9
- package/src/components/statistic/statistic.meta.md +14 -30
- package/src/components/statistic/statistic.stories.tsx +1 -1
- package/src/components/statistic/statistic.tsx +4 -5
- package/src/components/steps/steps.meta.md +20 -15
- package/src/components/steps/steps.stories.tsx +37 -2
- package/src/components/steps/steps.tsx +15 -12
- package/src/components/switch/switch.meta.md +56 -15
- package/src/components/switch/switch.stories.tsx +5 -5
- package/src/components/switch/switch.tsx +59 -13
- package/src/components/table/table.meta.md +3 -7
- package/src/components/table/table.stories.tsx +1 -1
- package/src/components/table/table.tsx +4 -4
- package/src/components/tabs/tabs.meta.md +40 -32
- package/src/components/tabs/tabs.stories.tsx +104 -26
- package/src/components/tabs/tabs.tsx +125 -54
- package/src/components/tag/tag.meta.md +104 -68
- package/src/components/tag/tag.stories.tsx +183 -15
- package/src/components/tag/tag.tsx +222 -21
- package/src/components/textarea/textarea.meta.md +42 -31
- package/src/components/textarea/textarea.stories.tsx +32 -6
- package/src/components/textarea/textarea.tsx +32 -8
- package/src/components/time-picker/time-picker.meta.md +119 -50
- package/src/components/time-picker/time-picker.stories.tsx +65 -33
- package/src/components/time-picker/time-picker.tsx +889 -101
- package/src/components/timeline/timeline.meta.md +16 -17
- package/src/components/timeline/timeline.stories.tsx +24 -4
- package/src/components/timeline/timeline.tsx +32 -12
- package/src/components/toggle/toggle.meta.md +8 -12
- package/src/components/toggle/toggle.stories.tsx +4 -4
- package/src/components/toggle/toggle.tsx +4 -3
- package/src/components/toggle-group/toggle-group.meta.md +10 -14
- package/src/components/toggle-group/toggle-group.stories.tsx +3 -3
- package/src/components/toggle-group/toggle-group.tsx +2 -2
- package/src/components/tooltip/tooltip.meta.md +63 -18
- package/src/components/tooltip/tooltip.stories.tsx +42 -5
- package/src/components/tooltip/tooltip.tsx +81 -21
- package/src/components/tour/tour.meta.md +16 -20
- package/src/components/tour/tour.stories.tsx +3 -3
- package/src/components/tour/tour.tsx +3 -3
- package/src/components/transfer/transfer.meta.md +18 -22
- package/src/components/transfer/transfer.stories.tsx +2 -2
- package/src/components/transfer/transfer.tsx +28 -21
- package/src/components/tree/tree.meta.md +67 -22
- package/src/components/tree/tree.stories.tsx +1 -1
- package/src/components/tree/tree.tsx +9 -8
- package/src/components/tree-select/tree-select.meta.md +59 -23
- package/src/components/tree-select/tree-select.stories.tsx +2 -2
- package/src/components/tree-select/tree-select.tsx +42 -7
- package/src/components/typography/typography.meta.md +61 -39
- package/src/components/typography/typography.stories.tsx +14 -9
- package/src/components/typography/typography.tsx +38 -25
- package/src/components/upload/upload.meta.md +61 -25
- package/src/components/upload/upload.stories.tsx +69 -3
- package/src/components/upload/upload.tsx +170 -37
- package/src/components/watermark/watermark.meta.md +15 -19
- package/src/components/watermark/watermark.stories.tsx +98 -8
- package/src/hooks/use-breakpoint.ts +117 -0
- package/src/hooks/use-debounce-callback.ts +52 -0
- package/src/hooks/use-mobile.ts +23 -0
- package/src/stories/theme-tokens.stories.tsx +747 -0
- package/src/utils/trigger-input.ts +53 -0
- package/src/components/button-group/button-group.meta.md +0 -101
- package/src/components/button-group/button-group.stories.tsx +0 -93
- package/src/components/button-group/button-group.tsx +0 -75
- package/src/components/combobox/combobox.meta.md +0 -102
- package/src/components/combobox/combobox.stories.tsx +0 -55
- package/src/components/combobox/combobox.tsx +0 -130
- package/src/components/input/demo/addon.tsx +0 -15
- package/src/components/input/demo/with-prefix-suffix.tsx +0 -19
- package/src/components/space/space.meta.md +0 -103
- package/src/components/space/space.stories.tsx +0 -108
- package/src/components/space/space.tsx +0 -106
|
@@ -3,7 +3,7 @@ id: color-picker
|
|
|
3
3
|
name: ColorPicker
|
|
4
4
|
displayName: 颜色选择
|
|
5
5
|
type: component
|
|
6
|
-
category:
|
|
6
|
+
category: data-entry
|
|
7
7
|
since: 0.1.0
|
|
8
8
|
package: '@teamix-evo/ui'
|
|
9
9
|
---
|
|
@@ -28,38 +28,34 @@ package: '@teamix-evo/ui'
|
|
|
28
28
|
## Props
|
|
29
29
|
|
|
30
30
|
<!-- auto:props:begin -->
|
|
31
|
-
|
|
32
|
-
|
|
|
33
|
-
|
|
|
34
|
-
| `
|
|
35
|
-
| `
|
|
36
|
-
| `
|
|
37
|
-
| `
|
|
38
|
-
| `
|
|
39
|
-
| `
|
|
40
|
-
| `
|
|
41
|
-
| `className` | `string` | – | – | 触发器 className。 |
|
|
42
|
-
|
|
31
|
+
| 名称 | 类型 | 默认值 | 必填 | 说明 |
|
|
32
|
+
| --- | --- | --- | --- | --- |
|
|
33
|
+
| `value` | `string` | – | – | 受控值 — `#RRGGBB` 或 `#RRGGBBAA`(开 `allowAlpha` 时)。 |
|
|
34
|
+
| `defaultValue` | `string` | `"#000000"` | – | uncontrolled 初值。 |
|
|
35
|
+
| `onChange` | `(value: string) => void` | – | – | 值变化回调。 |
|
|
36
|
+
| `allowAlpha` | `boolean` | `false` | – | 是否允许透明度(antd `format=hex8` 类似行为) — 启用后展示 alpha 滑块,value 变为 8 位 hex。 |
|
|
37
|
+
| `presets` | `string[]` | – | – | 预设色块(antd `presets` 并集) — 一组常用颜色快捷选择。 |
|
|
38
|
+
| `disabled` | `boolean` | – | – | 整体禁用。 |
|
|
39
|
+
| `size` | `'sm' \| 'md' \| 'default' \| 'lg'` | `"default"` | – | 触发器尺寸。 |
|
|
40
|
+
| `className` | `string` | – | – | 触发器 className。 |
|
|
43
41
|
<!-- auto:props:end -->
|
|
44
42
|
|
|
45
43
|
## 依赖
|
|
46
44
|
|
|
47
45
|
<!-- auto:deps:begin -->
|
|
48
|
-
|
|
49
46
|
### 同库依赖
|
|
50
47
|
|
|
51
48
|
> `teamix-evo ui add color-picker` 时,以下 entry 会被自动连带安装(无需手动 add)。
|
|
52
49
|
|
|
53
|
-
| Entry
|
|
54
|
-
|
|
|
55
|
-
| `cn`
|
|
56
|
-
| `input`
|
|
57
|
-
| `popover` | component | 可交互浮层 — Radix Popover + antd arrow
|
|
50
|
+
| Entry | 类型 | 描述 |
|
|
51
|
+
| --- | --- | --- |
|
|
52
|
+
| `cn` | util | Tailwind className 合并工具(clsx + tailwind-merge) |
|
|
53
|
+
| `input` | component | 单行文本输入 — clearable / showCount / size(sm 24 / md 32 / lg 36,与 Button 同档)/ error 四档内建能力。前缀/后缀/addon 等复合形态已拆出独立 InputGroup;多行已拆出独立 Textarea |
|
|
54
|
+
| `popover` | component | 可交互浮层 — Radix Popover + antd arrow 并集,使用 showArrow 控制尖角(与 Tooltip / HoverCard 命名统一) |
|
|
58
55
|
|
|
59
56
|
### npm 依赖
|
|
60
57
|
|
|
61
58
|
_无 — 本组件不依赖任何 npm 包。_
|
|
62
|
-
|
|
63
59
|
<!-- auto:deps:end -->
|
|
64
60
|
|
|
65
61
|
## AI 生成纪律
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
3
3
|
import { ColorPicker } from './color-picker';
|
|
4
4
|
|
|
5
5
|
const meta: Meta<typeof ColorPicker> = {
|
|
6
|
-
title: '
|
|
6
|
+
title: '数据录入 · Data Entry/ColorPicker',
|
|
7
7
|
component: ColorPicker,
|
|
8
8
|
tags: ['autodocs'],
|
|
9
9
|
parameters: {
|
|
10
10
|
docs: {
|
|
11
11
|
description: {
|
|
12
12
|
component:
|
|
13
|
-
'颜色选择
|
|
13
|
+
'颜色选择 —— 触发器色块 → Popover 面板,选取一个 `#RRGGBB` 或 `#RRGGBBAA` 颜色。基于原生 `<input type="color">` + Radix `Popover` + `Input` 组合,等价 antd `ColorPicker`(v5.5+):`value` / `defaultValue` / `onChange` 受控双轨、`allowAlpha` 透明度档(8 位 hex)、`presets` 预设色板、`size`(`sm`/`default`/`lg`)三档触发器、`disabled`。视觉走 OpenTrek semantic tokens,所有样式来自 `@teamix-evo/tokens`,无 mock。',
|
|
14
14
|
},
|
|
15
15
|
},
|
|
16
16
|
},
|
|
@@ -26,11 +26,27 @@ export default meta;
|
|
|
26
26
|
type Story = StoryObj<typeof ColorPicker>;
|
|
27
27
|
|
|
28
28
|
export const Playground: Story = {
|
|
29
|
+
parameters: {
|
|
30
|
+
docs: {
|
|
31
|
+
description: {
|
|
32
|
+
story:
|
|
33
|
+
'基础颜色选择 —— uncontrolled,内部维护当前色,点击触发器弹出原生 color input + hex 文本输入双通道。',
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
},
|
|
29
37
|
render: (args) => <ColorPicker {...args} defaultValue="#f43f5e" />,
|
|
30
38
|
};
|
|
31
39
|
|
|
32
40
|
export const Controlled: Story = {
|
|
33
|
-
parameters: {
|
|
41
|
+
parameters: {
|
|
42
|
+
controls: { disable: true },
|
|
43
|
+
docs: {
|
|
44
|
+
description: {
|
|
45
|
+
story:
|
|
46
|
+
'受控形态 —— `value` + `onChange` 由消费侧持有真值,常用于"主题色配置 + 实时预览"场景。',
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
},
|
|
34
50
|
render: () => {
|
|
35
51
|
const [c, setC] = React.useState('#3b82f6');
|
|
36
52
|
return (
|
|
@@ -43,7 +59,15 @@ export const Controlled: Story = {
|
|
|
43
59
|
};
|
|
44
60
|
|
|
45
61
|
export const WithPresets: Story = {
|
|
46
|
-
parameters: {
|
|
62
|
+
parameters: {
|
|
63
|
+
controls: { disable: true },
|
|
64
|
+
docs: {
|
|
65
|
+
description: {
|
|
66
|
+
story:
|
|
67
|
+
'预设色板 —— `presets` 数组渲染为面板底部色块,点击即写入 value。建议给 6~12 个品牌色,避免视觉混乱。',
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
},
|
|
47
71
|
render: () => (
|
|
48
72
|
<ColorPicker
|
|
49
73
|
defaultValue="#3b82f6"
|
|
@@ -64,12 +88,49 @@ export const WithPresets: Story = {
|
|
|
64
88
|
};
|
|
65
89
|
|
|
66
90
|
export const WithAlpha: Story = {
|
|
67
|
-
parameters: {
|
|
91
|
+
parameters: {
|
|
92
|
+
controls: { disable: true },
|
|
93
|
+
docs: {
|
|
94
|
+
description: {
|
|
95
|
+
story:
|
|
96
|
+
'透明度档 —— `allowAlpha` 启用后 value 自动变 8 位 hex,面板内多出 `Alpha` 滑块与百分比读数。',
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
},
|
|
68
100
|
render: () => <ColorPicker allowAlpha defaultValue="#3b82f680" />,
|
|
69
101
|
};
|
|
70
102
|
|
|
103
|
+
export const HexInput: Story = {
|
|
104
|
+
parameters: {
|
|
105
|
+
controls: { disable: true },
|
|
106
|
+
docs: {
|
|
107
|
+
description: {
|
|
108
|
+
story:
|
|
109
|
+
'自定义 hex 输入 —— 面板内嵌的 `Input` 接受手动 hex(`#RRGGBB` 或 `#RRGGBBAA`),不合法字符自动剥除,长度按 `allowAlpha` 截断。',
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
render: () => {
|
|
114
|
+
const [c, setC] = React.useState('#10b981');
|
|
115
|
+
return (
|
|
116
|
+
<div className="flex items-center gap-3">
|
|
117
|
+
<ColorPicker value={c} onChange={setC} allowAlpha />
|
|
118
|
+
<code className="rounded bg-muted px-2 py-1 text-xs">{c}</code>
|
|
119
|
+
</div>
|
|
120
|
+
);
|
|
121
|
+
},
|
|
122
|
+
};
|
|
123
|
+
|
|
71
124
|
export const Sizes: Story = {
|
|
72
|
-
parameters: {
|
|
125
|
+
parameters: {
|
|
126
|
+
controls: { disable: true },
|
|
127
|
+
docs: {
|
|
128
|
+
description: {
|
|
129
|
+
story:
|
|
130
|
+
'三档触发器尺寸 —— `sm` / `default` / `lg`,对齐其它表单控件高度档位。',
|
|
131
|
+
},
|
|
132
|
+
},
|
|
133
|
+
},
|
|
73
134
|
render: () => (
|
|
74
135
|
<div className="flex items-center gap-3">
|
|
75
136
|
<ColorPicker size="sm" defaultValue="#ef4444" />
|
|
@@ -78,3 +139,21 @@ export const Sizes: Story = {
|
|
|
78
139
|
</div>
|
|
79
140
|
),
|
|
80
141
|
};
|
|
142
|
+
|
|
143
|
+
export const Disabled: Story = {
|
|
144
|
+
parameters: {
|
|
145
|
+
controls: { disable: true },
|
|
146
|
+
docs: {
|
|
147
|
+
description: {
|
|
148
|
+
story:
|
|
149
|
+
'禁用态 —— 整组 `disabled`,点击不弹面板,触发器降透明度。仅用于只读语义,业务态锁定建议在 form 层处理。',
|
|
150
|
+
},
|
|
151
|
+
},
|
|
152
|
+
},
|
|
153
|
+
render: () => (
|
|
154
|
+
<div className="flex items-center gap-3">
|
|
155
|
+
<ColorPicker defaultValue="#3b82f6" disabled />
|
|
156
|
+
<ColorPicker defaultValue="#10b981" allowAlpha disabled />
|
|
157
|
+
</div>
|
|
158
|
+
),
|
|
159
|
+
};
|
|
@@ -27,7 +27,7 @@ export interface ColorPickerProps {
|
|
|
27
27
|
/** 整体禁用。 */
|
|
28
28
|
disabled?: boolean;
|
|
29
29
|
/** 触发器尺寸。 @default "default" */
|
|
30
|
-
size?: 'sm' | 'default' | 'lg';
|
|
30
|
+
size?: 'sm' | 'md' | 'default' | 'lg';
|
|
31
31
|
/** 触发器 className。 */
|
|
32
32
|
className?: string;
|
|
33
33
|
}
|
|
@@ -54,7 +54,7 @@ const ColorPicker = React.forwardRef<HTMLButtonElement, ColorPickerProps>(
|
|
|
54
54
|
allowAlpha = false,
|
|
55
55
|
presets,
|
|
56
56
|
disabled = false,
|
|
57
|
-
size = '
|
|
57
|
+
size = 'md',
|
|
58
58
|
className,
|
|
59
59
|
},
|
|
60
60
|
ref,
|
|
@@ -70,10 +70,12 @@ const ColorPicker = React.forwardRef<HTMLButtonElement, ColorPickerProps>(
|
|
|
70
70
|
};
|
|
71
71
|
|
|
72
72
|
const baseHex = current.slice(0, 7);
|
|
73
|
-
const alphaHex =
|
|
73
|
+
const alphaHex =
|
|
74
|
+
allowAlpha && current.length >= 9 ? current.slice(7, 9) : 'ff';
|
|
74
75
|
const alphaInt = parseInt(alphaHex, 16);
|
|
75
76
|
|
|
76
|
-
const swatchSize =
|
|
77
|
+
const swatchSize =
|
|
78
|
+
size === 'sm' ? 'size-7' : size === 'lg' ? 'size-11' : 'size-9';
|
|
77
79
|
|
|
78
80
|
return (
|
|
79
81
|
<Popover>
|
|
@@ -83,7 +85,7 @@ const ColorPicker = React.forwardRef<HTMLButtonElement, ColorPickerProps>(
|
|
|
83
85
|
type="button"
|
|
84
86
|
disabled={disabled}
|
|
85
87
|
className={cn(
|
|
86
|
-
'inline-flex items-center justify-center rounded-md border border-input bg-background shadow-sm transition-colors',
|
|
88
|
+
'inline-flex cursor-pointer items-center justify-center rounded-md border border-input bg-background shadow-sm transition-colors',
|
|
87
89
|
'focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring',
|
|
88
90
|
'disabled:cursor-not-allowed disabled:opacity-50',
|
|
89
91
|
swatchSize,
|
|
@@ -104,12 +106,18 @@ const ColorPicker = React.forwardRef<HTMLButtonElement, ColorPickerProps>(
|
|
|
104
106
|
type="color"
|
|
105
107
|
value={baseHex}
|
|
106
108
|
disabled={disabled}
|
|
107
|
-
onChange={(e) =>
|
|
109
|
+
onChange={(e) =>
|
|
110
|
+
update(
|
|
111
|
+
allowAlpha ? `${e.target.value}${alphaHex}` : e.target.value,
|
|
112
|
+
)
|
|
113
|
+
}
|
|
108
114
|
className="h-10 w-full cursor-pointer rounded-md border border-input bg-transparent"
|
|
109
115
|
/>
|
|
110
116
|
{allowAlpha ? (
|
|
111
117
|
<div className="flex items-center gap-2">
|
|
112
|
-
<span className="w-12 text-xs text-muted-foreground">
|
|
118
|
+
<span className="w-12 text-xs text-muted-foreground">
|
|
119
|
+
Alpha
|
|
120
|
+
</span>
|
|
113
121
|
<input
|
|
114
122
|
type="range"
|
|
115
123
|
min={0}
|
|
@@ -117,7 +125,9 @@ const ColorPicker = React.forwardRef<HTMLButtonElement, ColorPickerProps>(
|
|
|
117
125
|
value={alphaInt}
|
|
118
126
|
disabled={disabled}
|
|
119
127
|
onChange={(e) => {
|
|
120
|
-
const a = Number(e.target.value)
|
|
128
|
+
const a = Number(e.target.value)
|
|
129
|
+
.toString(16)
|
|
130
|
+
.padStart(2, '0');
|
|
121
131
|
update(`${baseHex}${a}`);
|
|
122
132
|
}}
|
|
123
133
|
className="flex-1"
|
|
@@ -142,7 +152,7 @@ const ColorPicker = React.forwardRef<HTMLButtonElement, ColorPickerProps>(
|
|
|
142
152
|
aria-label={p}
|
|
143
153
|
onClick={() => update(p)}
|
|
144
154
|
className={cn(
|
|
145
|
-
'size-6 rounded-sm border border-border ring-offset-background transition-all',
|
|
155
|
+
'size-6 cursor-pointer rounded-sm border border-border ring-offset-background transition-all',
|
|
146
156
|
'hover:scale-110 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring',
|
|
147
157
|
)}
|
|
148
158
|
style={{ backgroundColor: p }}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
id: command
|
|
3
3
|
name: Command
|
|
4
4
|
type: component
|
|
5
|
-
category:
|
|
5
|
+
category: feedback
|
|
6
6
|
since: 0.1.0
|
|
7
7
|
package: '@teamix-evo/ui'
|
|
8
8
|
displayName: 命令面板
|
|
@@ -10,8 +10,8 @@ displayName: 命令面板
|
|
|
10
10
|
|
|
11
11
|
# Command 命令面板
|
|
12
12
|
|
|
13
|
-
命令面板 — 基于 [`cmdk`](https://cmdk.paco.me/),提供"按 ⌘K 打开"的全局搜索 / 命令执行体验(Linear / Raycast / Vercel 风格)。
|
|
14
|
-
**shadcn-only**(antd 无对标)
|
|
13
|
+
命令面板 / 下拉底座 — 基于 [`cmdk`](https://cmdk.paco.me/),提供"按 ⌘K 打开"的全局搜索 / 命令执行体验(Linear / Raycast / Vercel 风格)。
|
|
14
|
+
**shadcn-only**(antd 无对标)。同时作为 `Combobox` / `Select` / `AutoComplete` 的同源下拉内核(ADR 0029),提供过滤 / 键盘导航 / a11y 能力。
|
|
15
15
|
|
|
16
16
|
## When to use
|
|
17
17
|
|
|
@@ -30,23 +30,20 @@ displayName: 命令面板
|
|
|
30
30
|
## Props
|
|
31
31
|
|
|
32
32
|
<!-- auto:props:begin -->
|
|
33
|
-
|
|
34
33
|
_(no props)_
|
|
35
|
-
|
|
36
34
|
<!-- auto:props:end -->
|
|
37
35
|
|
|
38
36
|
## 依赖
|
|
39
37
|
|
|
40
38
|
<!-- auto:deps:begin -->
|
|
41
|
-
|
|
42
39
|
### 同库依赖
|
|
43
40
|
|
|
44
41
|
> `teamix-evo ui add command` 时,以下 entry 会被自动连带安装(无需手动 add)。
|
|
45
42
|
|
|
46
|
-
| Entry
|
|
47
|
-
|
|
|
48
|
-
| `cn`
|
|
49
|
-
| `dialog` | component | 模态对话框 — Radix Dialog + antd Modal 并集(组合式 Header/Footer/Title/Description) |
|
|
43
|
+
| Entry | 类型 | 描述 |
|
|
44
|
+
| --- | --- | --- |
|
|
45
|
+
| `cn` | util | Tailwind className 合并工具(clsx + tailwind-merge) |
|
|
46
|
+
| `dialog` | component | 模态对话框 — Radix Dialog + antd Modal 并集(组合式 Header/Footer/Title/Description,size sm/md/lg/xl 绑定 layout-dialog tokens,圆角 radius-dialog 16px,无 border) |
|
|
50
47
|
|
|
51
48
|
### npm 依赖
|
|
52
49
|
|
|
@@ -55,7 +52,6 @@ _(no props)_
|
|
|
55
52
|
```bash
|
|
56
53
|
pnpm add cmdk@^1.0.0 lucide-react@^0.460.0
|
|
57
54
|
```
|
|
58
|
-
|
|
59
55
|
<!-- auto:deps:end -->
|
|
60
56
|
|
|
61
57
|
> 子组件:`Command`(Root 容器)/ `CommandDialog`(模态版,内部组合 Dialog)/ `CommandInput`(自带搜索图标)/ `CommandList`(可滚动列表)/ `CommandEmpty`(无匹配空态)/ `CommandGroup`(分组,带 heading)/ `CommandItem`(选项,支持 `onSelect`)/ `CommandSeparator` / `CommandShortcut`(右对齐快捷键)。
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from '@storybook/react';
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
2
|
import { Calendar, Mail, Settings, User } from 'lucide-react';
|
|
3
3
|
import {
|
|
4
4
|
Command,
|
|
@@ -12,14 +12,14 @@ import {
|
|
|
12
12
|
} from './command';
|
|
13
13
|
|
|
14
14
|
const meta: Meta<typeof Command> = {
|
|
15
|
-
title: '
|
|
15
|
+
title: '反馈 · Feedback/Command',
|
|
16
16
|
component: Command,
|
|
17
17
|
tags: ['autodocs'],
|
|
18
18
|
parameters: {
|
|
19
19
|
docs: {
|
|
20
20
|
description: {
|
|
21
21
|
component:
|
|
22
|
-
'命令面板 — 全局搜索 / 命令执行(Linear / Raycast / Vercel 风格)。基于 cmdk,提供键盘导航、模糊搜索、分组、空态、快捷键提示;模态版用 CommandDialog 监听 ⌘K
|
|
22
|
+
'命令面板 / 下拉底座 — 全局搜索 / 命令执行(Linear / Raycast / Vercel 风格)。基于 cmdk,提供键盘导航、模糊搜索、分组、空态、快捷键提示;模态版用 CommandDialog 监听 ⌘K 全局触发。同时作为 `Combobox` / `Select` / `AutoComplete` 的同源下拉内核(ADR 0029)。',
|
|
23
23
|
},
|
|
24
24
|
},
|
|
25
25
|
},
|
|
@@ -30,7 +30,7 @@ type Story = StoryObj<typeof Command>;
|
|
|
30
30
|
|
|
31
31
|
export const Inline: Story = {
|
|
32
32
|
render: () => (
|
|
33
|
-
<Command className="w-80 rounded-lg border">
|
|
33
|
+
<Command className="w-80 rounded-lg border border-border">
|
|
34
34
|
<CommandInput placeholder="输入命令或搜索..." />
|
|
35
35
|
<CommandList>
|
|
36
36
|
<CommandEmpty>无结果。</CommandEmpty>
|
|
@@ -3,7 +3,7 @@ import { Command as CommandPrimitive } from 'cmdk';
|
|
|
3
3
|
import { Search } from 'lucide-react';
|
|
4
4
|
|
|
5
5
|
import { cn } from '@/utils/cn';
|
|
6
|
-
import { Dialog, DialogContent } from '@/components/dialog/dialog';
|
|
6
|
+
import { Dialog, DialogContent, DialogTitle } from '@/components/dialog/dialog';
|
|
7
7
|
|
|
8
8
|
export interface CommandProps
|
|
9
9
|
extends React.ComponentPropsWithoutRef<typeof CommandPrimitive> {}
|
|
@@ -24,11 +24,19 @@ const Command = React.forwardRef<
|
|
|
24
24
|
Command.displayName = CommandPrimitive.displayName;
|
|
25
25
|
|
|
26
26
|
interface CommandDialogProps
|
|
27
|
-
extends React.ComponentPropsWithoutRef<typeof Dialog> {
|
|
27
|
+
extends React.ComponentPropsWithoutRef<typeof Dialog> {
|
|
28
|
+
/** 命令面板的可访问性标题(默认隐藏视觉)。 */
|
|
29
|
+
title?: string;
|
|
30
|
+
}
|
|
28
31
|
|
|
29
|
-
const CommandDialog = ({
|
|
32
|
+
const CommandDialog = ({
|
|
33
|
+
title = '命令面板',
|
|
34
|
+
children,
|
|
35
|
+
...props
|
|
36
|
+
}: CommandDialogProps) => (
|
|
30
37
|
<Dialog {...props}>
|
|
31
38
|
<DialogContent className="overflow-hidden p-0">
|
|
39
|
+
<DialogTitle className="sr-only">{title}</DialogTitle>
|
|
32
40
|
<Command className="[&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-group]]:px-2 [&_[cmdk-input-wrapper]_svg]:size-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:size-5">
|
|
33
41
|
{children}
|
|
34
42
|
</Command>
|
|
@@ -40,12 +48,15 @@ const CommandInput = React.forwardRef<
|
|
|
40
48
|
React.ElementRef<typeof CommandPrimitive.Input>,
|
|
41
49
|
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Input>
|
|
42
50
|
>(({ className, ...props }, ref) => (
|
|
43
|
-
<div
|
|
51
|
+
<div
|
|
52
|
+
className="flex items-center border-b border-b-border px-3"
|
|
53
|
+
cmdk-input-wrapper=""
|
|
54
|
+
>
|
|
44
55
|
<Search className="mr-2 size-4 shrink-0 opacity-50" />
|
|
45
56
|
<CommandPrimitive.Input
|
|
46
57
|
ref={ref}
|
|
47
58
|
className={cn(
|
|
48
|
-
'flex h-10 w-full rounded-md bg-transparent py-3 text-
|
|
59
|
+
'flex h-10 w-full rounded-md bg-transparent py-3 text-xs outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50',
|
|
49
60
|
className,
|
|
50
61
|
)}
|
|
51
62
|
{...props}
|
|
@@ -72,7 +83,7 @@ const CommandEmpty = React.forwardRef<
|
|
|
72
83
|
>((props, ref) => (
|
|
73
84
|
<CommandPrimitive.Empty
|
|
74
85
|
ref={ref}
|
|
75
|
-
className="py-6 text-center text-
|
|
86
|
+
className="py-6 text-center text-xs text-muted-foreground"
|
|
76
87
|
{...props}
|
|
77
88
|
/>
|
|
78
89
|
));
|
|
@@ -112,7 +123,7 @@ const CommandItem = React.forwardRef<
|
|
|
112
123
|
<CommandPrimitive.Item
|
|
113
124
|
ref={ref}
|
|
114
125
|
className={cn(
|
|
115
|
-
"relative flex cursor-
|
|
126
|
+
"relative flex cursor-pointer gap-2 select-none items-center rounded-sm px-2 py-1.5 text-xs outline-none data-[disabled=true]:pointer-events-none data-[selected='true']:bg-accent data-[selected=true]:text-accent-foreground data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
|
|
116
127
|
className,
|
|
117
128
|
)}
|
|
118
129
|
{...props}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
id: context-menu
|
|
3
3
|
name: ContextMenu
|
|
4
4
|
type: component
|
|
5
|
-
category:
|
|
5
|
+
category: deprecated
|
|
6
6
|
since: 0.1.0
|
|
7
7
|
package: '@teamix-evo/ui'
|
|
8
8
|
displayName: 右键菜单
|
|
@@ -30,25 +30,7 @@ shadcn 显式版,antd 用 Dropdown 模拟同样可达。
|
|
|
30
30
|
> 以下表格由 `pnpm --filter @teamix-evo/ui gen:meta` 自动生成。下表是 `ContextMenuContent` 的 props。
|
|
31
31
|
|
|
32
32
|
<!-- auto:props:begin -->
|
|
33
|
-
|
|
34
|
-
#### ContextMenuSubTrigger
|
|
35
|
-
|
|
36
|
-
| 名称 | 类型 | 默认值 | 必填 | 说明 |
|
|
37
|
-
| ------- | --------- | ------- | ---- | ------------------------------------------- |
|
|
38
|
-
| `inset` | `boolean` | `false` | – | 左侧留出 icon 宽度的缩进,对齐同级 icon 项。 |
|
|
39
|
-
|
|
40
|
-
#### ContextMenuItem
|
|
41
|
-
|
|
42
|
-
| 名称 | 类型 | 默认值 | 必填 | 说明 |
|
|
43
|
-
| ------- | --------- | ------- | ---- | ------------------------------------------- |
|
|
44
|
-
| `inset` | `boolean` | `false` | – | 左侧留出 icon 宽度的缩进,对齐同级 icon 项。 |
|
|
45
|
-
|
|
46
|
-
#### ContextMenuLabel
|
|
47
|
-
|
|
48
|
-
| 名称 | 类型 | 默认值 | 必填 | 说明 |
|
|
49
|
-
| ------- | --------- | ------- | ---- | ------------------------------------------- |
|
|
50
|
-
| `inset` | `boolean` | `false` | – | 左侧留出 icon 宽度的缩进,对齐同级 icon 项。 |
|
|
51
|
-
|
|
33
|
+
_(组件无 `<Name>Props` interface — props 详见 [`context-menu.tsx`](./context-menu.tsx))_
|
|
52
34
|
<!-- auto:props:end -->
|
|
53
35
|
|
|
54
36
|
## 依赖
|
|
@@ -56,14 +38,13 @@ shadcn 显式版,antd 用 Dropdown 模拟同样可达。
|
|
|
56
38
|
> 以下表格由 `pnpm --filter @teamix-evo/ui gen:meta` 自动生成,数据源是 [`manifest.json`](../../../manifest.json)。**手工编辑 marker 之间的内容会在下次生成时被覆盖**。
|
|
57
39
|
|
|
58
40
|
<!-- auto:deps:begin -->
|
|
59
|
-
|
|
60
41
|
### 同库依赖
|
|
61
42
|
|
|
62
43
|
> `teamix-evo ui add context-menu` 时,以下 entry 会被自动连带安装(无需手动 add)。
|
|
63
44
|
|
|
64
|
-
| Entry | 类型 | 描述
|
|
65
|
-
|
|
|
66
|
-
| `cn`
|
|
45
|
+
| Entry | 类型 | 描述 |
|
|
46
|
+
| --- | --- | --- |
|
|
47
|
+
| `cn` | util | Tailwind className 合并工具(clsx + tailwind-merge) |
|
|
67
48
|
|
|
68
49
|
### npm 依赖
|
|
69
50
|
|
|
@@ -72,7 +53,6 @@ shadcn 显式版,antd 用 Dropdown 模拟同样可达。
|
|
|
72
53
|
```bash
|
|
73
54
|
pnpm add @radix-ui/react-context-menu@^2.2.0 lucide-react@^0.460.0
|
|
74
55
|
```
|
|
75
|
-
|
|
76
56
|
<!-- auto:deps:end -->
|
|
77
57
|
|
|
78
58
|
## AI 生成纪律
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from '@storybook/react';
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
2
|
import {
|
|
3
3
|
ContextMenu,
|
|
4
4
|
ContextMenuTrigger,
|
|
@@ -9,14 +9,14 @@ import {
|
|
|
9
9
|
} from './context-menu';
|
|
10
10
|
|
|
11
11
|
const meta: Meta<typeof ContextMenuContent> = {
|
|
12
|
-
title: '
|
|
12
|
+
title: '废弃 · Deprecated/ContextMenu',
|
|
13
13
|
component: ContextMenuContent,
|
|
14
14
|
tags: ['autodocs'],
|
|
15
15
|
parameters: {
|
|
16
16
|
docs: {
|
|
17
17
|
description: {
|
|
18
18
|
component:
|
|
19
|
-
'右键菜单 — 右键触发的操作菜单,与 DropdownMenu 形态一致(Item / CheckboxItem / RadioItem / Sub),仅触发方式不同。Radix ContextMenu 实现,shadcn 显式版,antd 用 Dropdown 模拟同样可达。',
|
|
19
|
+
'⚠️ **已废弃** — 仅 Storybook 留档,不通过 manifest 对外发布。\n\n右键菜单 — 右键触发的操作菜单,与 DropdownMenu 形态一致(Item / CheckboxItem / RadioItem / Sub),仅触发方式不同。Radix ContextMenu 实现,shadcn 显式版,antd 用 Dropdown 模拟同样可达。',
|
|
20
20
|
},
|
|
21
21
|
},
|
|
22
22
|
},
|
|
@@ -28,7 +28,7 @@ type Story = StoryObj<typeof ContextMenuContent>;
|
|
|
28
28
|
export const Default: Story = {
|
|
29
29
|
render: () => (
|
|
30
30
|
<ContextMenu>
|
|
31
|
-
<ContextMenuTrigger className="flex h-32 w-72 items-center justify-center rounded-md border border-dashed text-sm text-muted-foreground">
|
|
31
|
+
<ContextMenuTrigger className="flex h-32 w-72 items-center justify-center rounded-md border border-border border-dashed text-sm text-muted-foreground">
|
|
32
32
|
在此处右键(或长按)打开菜单
|
|
33
33
|
</ContextMenuTrigger>
|
|
34
34
|
<ContextMenuContent className="w-56">
|
|
@@ -20,7 +20,7 @@ const ContextMenuSubTrigger = React.forwardRef<
|
|
|
20
20
|
<ContextMenuPrimitive.SubTrigger
|
|
21
21
|
ref={ref}
|
|
22
22
|
className={cn(
|
|
23
|
-
'flex cursor-
|
|
23
|
+
'flex cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-1.5 text-xs outline-none focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0',
|
|
24
24
|
inset && 'pl-8',
|
|
25
25
|
className,
|
|
26
26
|
)}
|
|
@@ -39,7 +39,7 @@ const ContextMenuSubContent = React.forwardRef<
|
|
|
39
39
|
<ContextMenuPrimitive.SubContent
|
|
40
40
|
ref={ref}
|
|
41
41
|
className={cn(
|
|
42
|
-
'z-50 min-w-menu overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95',
|
|
42
|
+
'z-50 min-w-menu overflow-hidden rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95',
|
|
43
43
|
className,
|
|
44
44
|
)}
|
|
45
45
|
{...props}
|
|
@@ -47,15 +47,28 @@ const ContextMenuSubContent = React.forwardRef<
|
|
|
47
47
|
));
|
|
48
48
|
ContextMenuSubContent.displayName = ContextMenuPrimitive.SubContent.displayName;
|
|
49
49
|
|
|
50
|
+
/**
|
|
51
|
+
* `onCloseAutoFocus` 默认 `preventDefault` — 阻止 Radix 关闭时把焦点程序化
|
|
52
|
+
* restore 回 trigger。
|
|
53
|
+
*
|
|
54
|
+
* 原因:Chromium/Safari 把"程序化 restore 的 focus"判定为非鼠标焦点 → 触发
|
|
55
|
+
* `:focus-visible` → trigger 如果是 button-like 元素会残留蓝色 ring(ContextMenu
|
|
56
|
+
* trigger 常是任意容器,常见场景不明显,但作为 popper 类一致默认策略)。
|
|
57
|
+
* 与 DropdownMenu / Popover 走同一默认,保证全库 popper 类鼠标体感一致。
|
|
58
|
+
*
|
|
59
|
+
* 取舍:键盘 Esc 关闭后焦点也不会 restore 回 trigger,而是落到 body。业务侧
|
|
60
|
+
* 需要保留 restore 行为时,显式传 `onCloseAutoFocus` 即可完全覆盖默认。
|
|
61
|
+
*/
|
|
50
62
|
const ContextMenuContent = React.forwardRef<
|
|
51
63
|
React.ElementRef<typeof ContextMenuPrimitive.Content>,
|
|
52
64
|
React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Content>
|
|
53
|
-
>(({ className, ...props }, ref) => (
|
|
65
|
+
>(({ className, onCloseAutoFocus, ...props }, ref) => (
|
|
54
66
|
<ContextMenuPrimitive.Portal>
|
|
55
67
|
<ContextMenuPrimitive.Content
|
|
56
68
|
ref={ref}
|
|
69
|
+
onCloseAutoFocus={onCloseAutoFocus ?? ((event) => event.preventDefault())}
|
|
57
70
|
className={cn(
|
|
58
|
-
'z-50 min-w-menu overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md animate-in fade-in-80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95',
|
|
71
|
+
'z-50 min-w-menu overflow-hidden rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-md animate-in fade-in-80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95',
|
|
59
72
|
className,
|
|
60
73
|
)}
|
|
61
74
|
{...props}
|
|
@@ -73,7 +86,7 @@ const ContextMenuItem = React.forwardRef<
|
|
|
73
86
|
<ContextMenuPrimitive.Item
|
|
74
87
|
ref={ref}
|
|
75
88
|
className={cn(
|
|
76
|
-
'relative flex cursor-
|
|
89
|
+
'relative flex cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-1.5 text-xs outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0',
|
|
77
90
|
inset && 'pl-8',
|
|
78
91
|
className,
|
|
79
92
|
)}
|
|
@@ -89,7 +102,7 @@ const ContextMenuCheckboxItem = React.forwardRef<
|
|
|
89
102
|
<ContextMenuPrimitive.CheckboxItem
|
|
90
103
|
ref={ref}
|
|
91
104
|
className={cn(
|
|
92
|
-
'relative flex cursor-
|
|
105
|
+
'relative flex cursor-pointer select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-xs outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
|
|
93
106
|
className,
|
|
94
107
|
)}
|
|
95
108
|
checked={checked}
|
|
@@ -113,7 +126,7 @@ const ContextMenuRadioItem = React.forwardRef<
|
|
|
113
126
|
<ContextMenuPrimitive.RadioItem
|
|
114
127
|
ref={ref}
|
|
115
128
|
className={cn(
|
|
116
|
-
'relative flex cursor-
|
|
129
|
+
'relative flex cursor-pointer select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-xs outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
|
|
117
130
|
className,
|
|
118
131
|
)}
|
|
119
132
|
{...props}
|
|
@@ -137,7 +150,7 @@ const ContextMenuLabel = React.forwardRef<
|
|
|
137
150
|
<ContextMenuPrimitive.Label
|
|
138
151
|
ref={ref}
|
|
139
152
|
className={cn(
|
|
140
|
-
'px-2 py-1.5 text-
|
|
153
|
+
'px-2 py-1.5 text-xs font-semibold text-foreground',
|
|
141
154
|
inset && 'pl-8',
|
|
142
155
|
className,
|
|
143
156
|
)}
|