@teamix-evo/ui 0.1.1 → 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 +20 -10
- package/src/components/accordion/accordion.meta.md +5 -4
- package/src/components/accordion/accordion.stories.tsx +14 -9
- package/src/components/accordion/accordion.tsx +104 -8
- package/src/components/affix/affix.meta.md +20 -2
- package/src/components/affix/affix.stories.tsx +102 -25
- package/src/components/affix/affix.tsx +79 -9
- package/src/components/alert/alert.meta.md +44 -13
- 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 +61 -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 +8 -3
- package/src/components/anchor/anchor.stories.tsx +3 -3
- package/src/components/anchor/anchor.tsx +2 -2
- package/src/components/app/app.meta.md +9 -4
- package/src/components/app/app.stories.tsx +9 -7
- package/src/components/aspect-ratio/aspect-ratio.meta.md +4 -3
- package/src/components/aspect-ratio/aspect-ratio.stories.tsx +3 -3
- package/src/components/auto-complete/auto-complete.meta.md +14 -6
- package/src/components/auto-complete/auto-complete.stories.tsx +47 -4
- package/src/components/auto-complete/auto-complete.tsx +119 -71
- package/src/components/avatar/avatar.meta.md +6 -7
- package/src/components/avatar/avatar.stories.tsx +21 -3
- package/src/components/avatar/avatar.tsx +24 -23
- package/src/components/badge/badge.meta.md +10 -9
- package/src/components/badge/badge.stories.tsx +2 -2
- package/src/components/badge/badge.tsx +9 -15
- package/src/components/breadcrumb/breadcrumb.meta.md +27 -7
- package/src/components/breadcrumb/breadcrumb.stories.tsx +127 -4
- package/src/components/breadcrumb/breadcrumb.tsx +22 -8
- package/src/components/button/button.meta.md +258 -21
- package/src/components/button/button.stories.tsx +549 -41
- package/src/components/button/button.tsx +335 -33
- package/src/components/button/demo/as-child.tsx +24 -0
- package/src/components/button/demo/basic.tsx +8 -0
- package/src/components/button/demo/block.tsx +16 -0
- package/src/components/button/demo/loading.tsx +19 -0
- package/src/components/button/demo/shapes.tsx +18 -0
- package/src/components/button/demo/sizes.tsx +19 -0
- package/src/components/button/demo/variants.tsx +19 -0
- package/src/components/button/demo/with-icon.tsx +20 -0
- package/src/components/calendar/calendar.meta.md +13 -3
- package/src/components/calendar/calendar.stories.tsx +6 -6
- package/src/components/calendar/calendar.tsx +73 -8
- package/src/components/card/card.meta.md +27 -5
- package/src/components/card/card.stories.tsx +42 -3
- package/src/components/card/card.tsx +146 -63
- package/src/components/carousel/carousel.meta.md +4 -3
- package/src/components/carousel/carousel.stories.tsx +11 -6
- package/src/components/cascader/cascader.meta.md +47 -17
- package/src/components/cascader/cascader.stories.tsx +22 -10
- package/src/components/cascader/cascader.tsx +428 -85
- package/src/components/checkbox/checkbox.meta.md +75 -7
- package/src/components/checkbox/checkbox.stories.tsx +161 -3
- package/src/components/checkbox/checkbox.tsx +77 -9
- package/src/components/collapsible/collapsible.meta.md +14 -6
- package/src/components/collapsible/collapsible.stories.tsx +10 -2
- package/src/components/collapsible/collapsible.tsx +93 -6
- package/src/components/color-picker/color-picker.meta.md +12 -7
- package/src/components/color-picker/color-picker.stories.tsx +86 -7
- package/src/components/color-picker/color-picker.tsx +20 -9
- package/src/components/command/command.meta.md +29 -13
- package/src/components/command/command.stories.tsx +4 -4
- package/src/components/command/command.tsx +19 -8
- package/src/components/context-menu/context-menu.meta.md +11 -8
- package/src/components/context-menu/context-menu.stories.tsx +11 -3
- package/src/components/context-menu/context-menu.tsx +21 -8
- package/src/components/data-table/data-table.meta.md +6 -5
- package/src/components/data-table/data-table.stories.tsx +13 -6
- package/src/components/data-table/data-table.tsx +2 -2
- package/src/components/date-picker/date-picker.meta.md +88 -19
- 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 +10 -5
- package/src/components/descriptions/descriptions.stories.tsx +3 -3
- package/src/components/descriptions/descriptions.tsx +22 -14
- package/src/components/dialog/dialog.meta.md +76 -13
- 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 +33 -34
- package/src/components/drawer/drawer.stories.tsx +29 -12
- package/src/components/drawer/drawer.tsx +22 -113
- package/src/components/dropdown-menu/dropdown-menu.meta.md +78 -10
- package/src/components/dropdown-menu/dropdown-menu.stories.tsx +88 -2
- 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 +9 -4
- package/src/components/empty/empty.stories.tsx +4 -4
- package/src/components/empty/empty.tsx +10 -3
- package/src/components/field/field.meta.md +47 -9
- package/src/components/field/field.stories.tsx +385 -5
- 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 +54 -6
- package/src/components/flex/flex.stories.tsx +107 -20
- package/src/components/flex/flex.tsx +27 -4
- package/src/components/float-button/float-button.meta.md +8 -3
- package/src/components/float-button/float-button.stories.tsx +9 -7
- package/src/components/float-button/float-button.tsx +1 -1
- package/src/components/form/form.meta.md +39 -17
- package/src/components/form/form.stories.tsx +350 -3
- package/src/components/form/form.tsx +101 -35
- package/src/components/grid/grid.meta.md +7 -2
- package/src/components/grid/grid.stories.tsx +6 -4
- package/src/components/hover-card/hover-card.meta.md +20 -9
- package/src/components/hover-card/hover-card.stories.tsx +34 -5
- 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 +9 -4
- package/src/components/image/image.stories.tsx +3 -3
- package/src/components/image/image.tsx +6 -4
- package/src/components/input/demo/basic.tsx +12 -0
- package/src/components/input/demo/clearable.tsx +21 -0
- package/src/components/input/demo/show-count.tsx +18 -0
- package/src/components/input/demo/sizes.tsx +15 -0
- package/src/components/input/input.meta.md +39 -33
- package/src/components/input/input.stories.tsx +62 -35
- package/src/components/input/input.tsx +97 -98
- package/src/components/input-group/input-group.meta.md +54 -22
- package/src/components/input-group/input-group.stories.tsx +49 -16
- package/src/components/input-group/input-group.tsx +44 -8
- package/src/components/input-number/input-number.meta.md +64 -7
- package/src/components/input-number/input-number.stories.tsx +46 -8
- package/src/components/input-number/input-number.tsx +99 -26
- package/src/components/input-otp/input-otp.meta.md +4 -3
- 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 -3
- package/src/components/item/item.stories.tsx +8 -5
- package/src/components/item/item.tsx +7 -6
- package/src/components/kbd/kbd.meta.md +13 -4
- package/src/components/kbd/kbd.stories.tsx +4 -4
- package/src/components/kbd/kbd.tsx +10 -5
- package/src/components/label/label.meta.md +18 -10
- 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 -3
- package/src/components/masonry/masonry.stories.tsx +7 -5
- package/src/components/masonry/masonry.tsx +1 -0
- package/src/components/mentions/mentions.meta.md +36 -6
- package/src/components/mentions/mentions.stories.tsx +120 -6
- package/src/components/mentions/mentions.tsx +11 -5
- package/src/components/menubar/menubar.meta.md +30 -12
- package/src/components/menubar/menubar.stories.tsx +62 -2
- package/src/components/menubar/menubar.tsx +9 -9
- package/src/components/native-select/native-select.meta.md +8 -3
- package/src/components/native-select/native-select.stories.tsx +8 -5
- package/src/components/native-select/native-select.tsx +1 -1
- package/src/components/navigation-menu/navigation-menu.meta.md +19 -9
- package/src/components/navigation-menu/navigation-menu.stories.tsx +112 -9
- package/src/components/navigation-menu/navigation-menu.tsx +8 -4
- package/src/components/notification/notification.meta.md +52 -10
- package/src/components/notification/notification.stories.tsx +11 -9
- package/src/components/notification/notification.tsx +36 -21
- 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 +140 -37
- package/src/components/pagination/pagination.stories.tsx +232 -10
- package/src/components/pagination/pagination.tsx +355 -63
- package/src/components/popconfirm/popconfirm.meta.md +9 -4
- package/src/components/popconfirm/popconfirm.stories.tsx +3 -4
- package/src/components/popconfirm/popconfirm.tsx +2 -2
- package/src/components/popover/popover.meta.md +62 -5
- package/src/components/popover/popover.stories.tsx +83 -7
- package/src/components/popover/popover.tsx +77 -28
- package/src/components/progress/progress.meta.md +38 -6
- package/src/components/progress/progress.stories.tsx +3 -3
- package/src/components/progress/progress.tsx +24 -16
- package/src/components/radio-group/radio-group.meta.md +79 -7
- package/src/components/radio-group/radio-group.stories.tsx +39 -3
- package/src/components/radio-group/radio-group.tsx +149 -18
- package/src/components/rate/rate.meta.md +35 -4
- package/src/components/rate/rate.stories.tsx +13 -5
- package/src/components/rate/rate.tsx +37 -10
- package/src/components/resizable/resizable.meta.md +7 -4
- package/src/components/resizable/resizable.stories.tsx +6 -6
- package/src/components/resizable/resizable.tsx +1 -1
- package/src/components/result/result.meta.md +7 -2
- package/src/components/result/result.stories.tsx +4 -8
- package/src/components/result/result.tsx +24 -15
- package/src/components/scroll-area/scroll-area.meta.md +4 -3
- package/src/components/scroll-area/scroll-area.stories.tsx +12 -4
- package/src/components/scroll-area/scroll-area.tsx +3 -3
- package/src/components/segmented/segmented.meta.md +7 -4
- package/src/components/segmented/segmented.stories.tsx +37 -8
- package/src/components/segmented/segmented.tsx +15 -7
- package/src/components/select/select.meta.md +197 -52
- package/src/components/select/select.stories.tsx +238 -63
- package/src/components/select/select.tsx +718 -171
- package/src/components/separator/separator.meta.md +4 -3
- package/src/components/separator/separator.stories.tsx +3 -3
- package/src/components/separator/separator.tsx +3 -7
- package/src/components/sheet/sheet.meta.md +32 -16
- package/src/components/sheet/sheet.stories.tsx +116 -10
- package/src/components/sheet/sheet.tsx +116 -29
- package/src/components/sidebar/sidebar.meta.md +37 -18
- package/src/components/sidebar/sidebar.stories.tsx +701 -29
- package/src/components/sidebar/sidebar.tsx +615 -142
- package/src/components/skeleton/skeleton.meta.md +4 -5
- package/src/components/skeleton/skeleton.stories.tsx +4 -4
- package/src/components/skeleton/skeleton.tsx +7 -7
- package/src/components/slider/slider.meta.md +57 -5
- package/src/components/slider/slider.stories.tsx +58 -6
- package/src/components/slider/slider.tsx +154 -13
- package/src/components/sonner/sonner.meta.md +58 -7
- package/src/components/sonner/sonner.stories.tsx +78 -5
- package/src/components/sonner/sonner.tsx +137 -8
- package/src/components/spinner/spinner.meta.md +62 -13
- package/src/components/spinner/spinner.stories.tsx +66 -14
- package/src/components/spinner/spinner.tsx +111 -9
- package/src/components/statistic/statistic.meta.md +7 -2
- package/src/components/statistic/statistic.stories.tsx +3 -7
- package/src/components/statistic/statistic.tsx +5 -6
- package/src/components/steps/steps.meta.md +18 -4
- package/src/components/steps/steps.stories.tsx +43 -3
- package/src/components/steps/steps.tsx +15 -12
- package/src/components/switch/switch.meta.md +51 -5
- package/src/components/switch/switch.stories.tsx +6 -6
- package/src/components/switch/switch.tsx +109 -41
- package/src/components/table/table.meta.md +17 -6
- package/src/components/table/table.stories.tsx +10 -5
- package/src/components/table/table.tsx +4 -4
- package/src/components/tabs/tabs.meta.md +38 -25
- package/src/components/tabs/tabs.stories.tsx +111 -25
- package/src/components/tabs/tabs.tsx +125 -54
- package/src/components/tag/tag.meta.md +105 -40
- package/src/components/tag/tag.stories.tsx +189 -16
- package/src/components/tag/tag.tsx +222 -21
- package/src/components/textarea/textarea.meta.md +35 -19
- package/src/components/textarea/textarea.stories.tsx +32 -6
- package/src/components/textarea/textarea.tsx +33 -9
- package/src/components/time-picker/time-picker.meta.md +124 -32
- package/src/components/time-picker/time-picker.stories.tsx +85 -15
- package/src/components/time-picker/time-picker.tsx +913 -61
- package/src/components/timeline/timeline.meta.md +14 -6
- package/src/components/timeline/timeline.stories.tsx +37 -7
- package/src/components/timeline/timeline.tsx +35 -14
- package/src/components/toggle/toggle.meta.md +5 -4
- 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 +5 -4
- 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 +55 -5
- package/src/components/tooltip/tooltip.stories.tsx +42 -5
- package/src/components/tooltip/tooltip.tsx +81 -21
- package/src/components/tour/tour.meta.md +9 -4
- package/src/components/tour/tour.stories.tsx +3 -3
- package/src/components/tour/tour.tsx +4 -4
- package/src/components/transfer/transfer.meta.md +11 -6
- package/src/components/transfer/transfer.stories.tsx +4 -8
- package/src/components/transfer/transfer.tsx +28 -21
- package/src/components/tree/tree.meta.md +63 -5
- package/src/components/tree/tree.stories.tsx +31 -12
- package/src/components/tree/tree.tsx +9 -8
- package/src/components/tree-select/tree-select.meta.md +59 -8
- package/src/components/tree-select/tree-select.stories.tsx +3 -3
- package/src/components/tree-select/tree-select.tsx +42 -7
- package/src/components/typography/typography.meta.md +61 -14
- package/src/components/typography/typography.stories.tsx +12 -11
- package/src/components/typography/typography.tsx +43 -28
- package/src/components/upload/upload.meta.md +49 -4
- package/src/components/upload/upload.stories.tsx +72 -12
- package/src/components/upload/upload.tsx +170 -37
- package/src/components/watermark/watermark.meta.md +7 -2
- package/src/components/watermark/watermark.stories.tsx +101 -9
- package/src/components/watermark/watermark.tsx +1 -0
- 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 -92
- package/src/components/button-group/button-group.stories.tsx +0 -90
- package/src/components/button-group/button-group.tsx +0 -75
- package/src/components/combobox/combobox.meta.md +0 -93
- package/src/components/combobox/combobox.stories.tsx +0 -55
- package/src/components/combobox/combobox.tsx +0 -130
- package/src/components/space/space.meta.md +0 -94
- package/src/components/space/space.stories.tsx +0 -94
- package/src/components/space/space.tsx +0 -106
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from '@storybook/react';
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
2
|
import { Masonry } from './masonry';
|
|
3
3
|
|
|
4
4
|
const meta: Meta<typeof Masonry> = {
|
|
5
|
-
title: '
|
|
5
|
+
title: '废弃 · Deprecated/Masonry',
|
|
6
6
|
component: Masonry,
|
|
7
7
|
tags: ['autodocs'],
|
|
8
8
|
parameters: {
|
|
9
9
|
docs: {
|
|
10
10
|
description: {
|
|
11
11
|
component:
|
|
12
|
-
'瀑布流 — CSS column-count + break-inside: avoid 的 0 JS 实现(图片墙 / 资讯卡片流 / Dashboard 卡片墙)。等价 antd `Masonry`(v6.0 新)。响应式建议外层 className
|
|
12
|
+
'⚠️ **已废弃** — 仅 Storybook 留档,不通过 manifest 对外发布。\n\n瀑布流 — CSS column-count + break-inside: avoid 的 0 JS 实现(图片墙 / 资讯卡片流 / Dashboard 卡片墙)。等价 antd `Masonry`(v6.0 新)。响应式建议外层 className 控制。',
|
|
13
13
|
},
|
|
14
14
|
},
|
|
15
15
|
},
|
|
@@ -35,7 +35,7 @@ export const Playground: Story = {
|
|
|
35
35
|
{cards.map((c) => (
|
|
36
36
|
<div
|
|
37
37
|
key={c.id}
|
|
38
|
-
className="flex items-center justify-center rounded-md border bg-card text-sm"
|
|
38
|
+
className="flex items-center justify-center rounded-md border border-border bg-card text-sm"
|
|
39
39
|
style={{ height: c.h }}
|
|
40
40
|
>
|
|
41
41
|
{c.text}({c.h}px)
|
|
@@ -55,7 +55,9 @@ export const ColorfulPhotos: Story = {
|
|
|
55
55
|
className="rounded-md bg-muted text-center text-xs text-muted-foreground"
|
|
56
56
|
style={{
|
|
57
57
|
height: c.h,
|
|
58
|
-
background: `linear-gradient(135deg, hsl(${
|
|
58
|
+
background: `linear-gradient(135deg, hsl(${
|
|
59
|
+
(c.id * 30) % 360
|
|
60
|
+
}, 60%, 70%), hsl(${(c.id * 30 + 60) % 360}, 60%, 50%))`,
|
|
59
61
|
}}
|
|
60
62
|
>
|
|
61
63
|
<span className="block py-2 text-white/90">photo {c.id + 1}</span>
|
|
@@ -44,6 +44,7 @@ const Masonry = React.forwardRef<HTMLDivElement, MasonryProps>(
|
|
|
44
44
|
{items.map((child, i) => (
|
|
45
45
|
<div
|
|
46
46
|
key={i}
|
|
47
|
+
// eslint-disable-next-line teamix-evo/no-arbitrary-tw-value -- runtime CSS var driven by `gap` prop; consumes per-instance var, not tokenizable.
|
|
47
48
|
className="mb-[var(--masonry-gap)] break-inside-avoid"
|
|
48
49
|
style={{ ['--masonry-gap' as string]: `${gap}px` }}
|
|
49
50
|
>
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
---
|
|
2
2
|
id: mentions
|
|
3
3
|
name: Mentions
|
|
4
|
+
displayName: 提及
|
|
4
5
|
type: component
|
|
5
|
-
category:
|
|
6
|
+
category: deprecated
|
|
6
7
|
since: 0.1.0
|
|
7
|
-
package:
|
|
8
|
+
package: '@teamix-evo/ui'
|
|
8
9
|
---
|
|
9
10
|
|
|
10
|
-
# Mentions
|
|
11
|
+
# Mentions 提及
|
|
11
12
|
|
|
12
13
|
@提及 — antd 独有补足。在 Textarea 中输入 `@`(或自定义 `prefix`)即弹出候选下拉,选中后插入 `@name `。键盘 ↑↓ 切换、Enter / Tab 选中、Esc 关闭。**异步候选**用 `onSearch(query)` 由消费方刷新 `options`。
|
|
13
14
|
|
|
@@ -21,6 +22,8 @@ package: "@teamix-evo/ui"
|
|
|
21
22
|
- 全字段候选(下拉选单)→ `Select` / `Combobox`
|
|
22
23
|
- 仅是搜索输入 → `Input` + 业务侧自渲染建议列表
|
|
23
24
|
|
|
25
|
+
## Props
|
|
26
|
+
|
|
24
27
|
<!-- auto:props:begin -->
|
|
25
28
|
| 名称 | 类型 | 默认值 | 必填 | 说明 |
|
|
26
29
|
| --- | --- | --- | --- | --- |
|
|
@@ -36,6 +39,8 @@ package: "@teamix-evo/ui"
|
|
|
36
39
|
| `disabled` | `boolean` | – | – | 禁用。 |
|
|
37
40
|
<!-- auto:props:end -->
|
|
38
41
|
|
|
42
|
+
## 依赖
|
|
43
|
+
|
|
39
44
|
<!-- auto:deps:begin -->
|
|
40
45
|
### 同库依赖
|
|
41
46
|
|
|
@@ -44,7 +49,7 @@ package: "@teamix-evo/ui"
|
|
|
44
49
|
| Entry | 类型 | 描述 |
|
|
45
50
|
| --- | --- | --- |
|
|
46
51
|
| `cn` | util | Tailwind className 合并工具(clsx + tailwind-merge) |
|
|
47
|
-
| `
|
|
52
|
+
| `input` | component | 文本输入合集 — Input(单行 + prefix/suffix/clearable/showCount/addonBefore/addonAfter/size)+ Textarea(多行 + autoSize)+ InputGroup 系列(InputGroupAddon / InputGroupInput / InputGroupTextarea)三件合一,size 与 Button 同档(sm 24 / md 32 / lg 36) |
|
|
48
53
|
|
|
49
54
|
### npm 依赖
|
|
50
55
|
|
|
@@ -73,7 +78,7 @@ const users = [
|
|
|
73
78
|
];
|
|
74
79
|
|
|
75
80
|
// 静态候选
|
|
76
|
-
<Mentions options={users} placeholder="输入 @ 提及同事..."
|
|
81
|
+
<Mentions options={users} placeholder="输入 @ 提及同事..." />;
|
|
77
82
|
|
|
78
83
|
// 异步候选
|
|
79
84
|
const [opts, setOpts] = React.useState(users);
|
|
@@ -83,7 +88,32 @@ const [opts, setOpts] = React.useState(users);
|
|
|
83
88
|
const list = await fetchUsers(q);
|
|
84
89
|
setOpts(list);
|
|
85
90
|
}}
|
|
86
|
-
|
|
91
|
+
/>;
|
|
87
92
|
|
|
88
93
|
// 双触发符:@ + # — 当前组件支持单 prefix,如需多触发请实例化两个 Mentions
|
|
89
94
|
```
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## Mentions 形态 — 旧库无此组件
|
|
99
|
+
|
|
100
|
+
> 旧库(hybridcloud)不含 Mentions;本组件为**新库独有**,对齐 antd `Mentions` API 形态。
|
|
101
|
+
> 基于内置 Textarea + 自绘候选列表(无 portal);用 `prefix` 触发、`onSearch` 异步刷新、`onSelect` 埋点。
|
|
102
|
+
|
|
103
|
+
### antd Mentions 对齐表
|
|
104
|
+
|
|
105
|
+
| antd prop | 新库 prop | 备注 |
|
|
106
|
+
| ------------------- | ------------------ | --------------------------------------- |
|
|
107
|
+
| `options` | `options` | 结构一致 `{ value, label?, disabled? }` |
|
|
108
|
+
| `prefix` | `prefix` | 触发符,单字符 |
|
|
109
|
+
| `split` | `split` | 选中后尾随分隔,默认空格 |
|
|
110
|
+
| `onSearch` | `onSearch` | 异步刷新回调 |
|
|
111
|
+
| `onSelect` | `onSelect` | 选中回调 |
|
|
112
|
+
| `value / onChange` | `value / onChange` | 受控模式 |
|
|
113
|
+
| `defaultValue` | `defaultValue` | 非受控初值 |
|
|
114
|
+
| `disabled` | `disabled` | 整组禁用 |
|
|
115
|
+
| `rows` | `rows` | Textarea 行数(默认 3) |
|
|
116
|
+
| `placement` | 不支持 | 固定 bottom-left(级联层级场景不需调整) |
|
|
117
|
+
| `getPopupContainer` | 不支持 | 无 portal,列表就在组件内 relative 定位 |
|
|
118
|
+
| `filterOption` | 内置 includes | 如需自定义过滤逻辑,请在 onSearch 中做 |
|
|
119
|
+
| `validateSearch` | 不支持 | 低频 |
|
|
@@ -1,22 +1,24 @@
|
|
|
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 { Mentions } from './mentions';
|
|
4
4
|
|
|
5
5
|
const meta: Meta<typeof Mentions> = {
|
|
6
|
-
title: '
|
|
6
|
+
title: '废弃 · Deprecated/Mentions',
|
|
7
7
|
component: Mentions,
|
|
8
8
|
tags: ['autodocs'],
|
|
9
9
|
parameters: {
|
|
10
10
|
docs: {
|
|
11
11
|
description: {
|
|
12
12
|
component:
|
|
13
|
-
'
|
|
13
|
+
'⚠️ **已废弃** — 仅 Storybook 留档,不通过 manifest 对外发布。\n\n提及输入 —— 在多行文本中输入触发符(`@` / `#` / `/` 等)即弹出候选下拉,选中后插入 `@name<split>`,用于评论 @ 同事、# 话题、/ 命令等场景。基于 `Textarea` + 自定义 portal-less 候选层,等价 antd `Mentions`:`options` 候选、`prefix` 触发符、`split` 分隔、`onSearch` 异步刷新、`onSelect` 选中回调。键盘 ↑↓ 切换、Enter / Tab 选中、Esc 关闭;email 类 `a@b` 不会误触(触发符前必须为空白或行首)。视觉走 OpenTrek semantic tokens,所有样式来自 `@teamix-evo/tokens`,无 mock。',
|
|
14
14
|
},
|
|
15
15
|
},
|
|
16
16
|
},
|
|
17
17
|
argTypes: {
|
|
18
18
|
prefix: { control: 'text' },
|
|
19
19
|
placeholder: { control: 'text' },
|
|
20
|
+
rows: { control: { type: 'number', min: 1, max: 10 } },
|
|
21
|
+
disabled: { control: 'boolean' },
|
|
20
22
|
},
|
|
21
23
|
};
|
|
22
24
|
|
|
@@ -31,11 +33,27 @@ const users = [
|
|
|
31
33
|
];
|
|
32
34
|
|
|
33
35
|
export const Playground: Story = {
|
|
34
|
-
args: { placeholder: '输入 @ 提及同事...', options: users },
|
|
36
|
+
args: { placeholder: '输入 @ 提及同事...', options: users, rows: 3 },
|
|
37
|
+
parameters: {
|
|
38
|
+
docs: {
|
|
39
|
+
description: {
|
|
40
|
+
story:
|
|
41
|
+
'基础 @提及 —— 输入 `@` 触发,候选从 `options` 中按 query 过滤;键盘 ↑↓ + Enter 选中,Esc 关闭。',
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
},
|
|
35
45
|
};
|
|
36
46
|
|
|
37
47
|
export const HashtagPrefix: Story = {
|
|
38
|
-
parameters: {
|
|
48
|
+
parameters: {
|
|
49
|
+
controls: { disable: true },
|
|
50
|
+
docs: {
|
|
51
|
+
description: {
|
|
52
|
+
story:
|
|
53
|
+
'自定义前缀 —— `prefix="#"` 用于话题标签场景。`prefix` 必须是单字符,多字符会与正文混淆。',
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
},
|
|
39
57
|
render: () => (
|
|
40
58
|
<Mentions
|
|
41
59
|
options={[
|
|
@@ -49,8 +67,35 @@ export const HashtagPrefix: Story = {
|
|
|
49
67
|
),
|
|
50
68
|
};
|
|
51
69
|
|
|
70
|
+
export const Multiline: Story = {
|
|
71
|
+
parameters: {
|
|
72
|
+
controls: { disable: true },
|
|
73
|
+
docs: {
|
|
74
|
+
description: {
|
|
75
|
+
story:
|
|
76
|
+
'多行场景 —— `rows={6}` 给到更长的输入区域。Enter 在候选打开时被消费(选中候选);候选关闭时回归原生换行 —— 这是预期行为。',
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
render: () => (
|
|
81
|
+
<Mentions
|
|
82
|
+
options={users}
|
|
83
|
+
rows={6}
|
|
84
|
+
placeholder={'多行评论:\n第一行...\n第二行 @ 提及同事...\n回车在候选打开时是"选中",关闭时是"换行"。'}
|
|
85
|
+
/>
|
|
86
|
+
),
|
|
87
|
+
};
|
|
88
|
+
|
|
52
89
|
export const AsyncSearch: Story = {
|
|
53
|
-
parameters: {
|
|
90
|
+
parameters: {
|
|
91
|
+
controls: { disable: true },
|
|
92
|
+
docs: {
|
|
93
|
+
description: {
|
|
94
|
+
story:
|
|
95
|
+
'异步候选 —— `onSearch(query, prefix)` 由消费侧拉接口刷新 `options`(组件不内置网络层)。下方实时显示当前候选数。',
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
},
|
|
54
99
|
render: () => {
|
|
55
100
|
const [opts, setOpts] = React.useState(users);
|
|
56
101
|
return (
|
|
@@ -73,3 +118,72 @@ export const AsyncSearch: Story = {
|
|
|
73
118
|
);
|
|
74
119
|
},
|
|
75
120
|
};
|
|
121
|
+
|
|
122
|
+
export const WithOnSelect: Story = {
|
|
123
|
+
parameters: {
|
|
124
|
+
controls: { disable: true },
|
|
125
|
+
docs: {
|
|
126
|
+
description: {
|
|
127
|
+
story:
|
|
128
|
+
'onSelect 回调 —— 在选中候选时记录最后一次选择。注意:`onSelect` 与 `onChange` 互不替代 —— 文本写入由 `onChange` 已经处理,`onSelect` 仅做埋点 / 业务联动。',
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
},
|
|
132
|
+
render: () => {
|
|
133
|
+
const [picked, setPicked] = React.useState<string | null>(null);
|
|
134
|
+
return (
|
|
135
|
+
<div className="flex flex-col gap-2">
|
|
136
|
+
<Mentions
|
|
137
|
+
options={users}
|
|
138
|
+
placeholder="选一个 @ 试试..."
|
|
139
|
+
onSelect={(opt, prefix) => setPicked(`${prefix}${opt.value}`)}
|
|
140
|
+
/>
|
|
141
|
+
<div className="text-xs text-muted-foreground">
|
|
142
|
+
上次选中:{' '}
|
|
143
|
+
<code className="rounded bg-muted px-1">{picked ?? '(无)'}</code>
|
|
144
|
+
</div>
|
|
145
|
+
</div>
|
|
146
|
+
);
|
|
147
|
+
},
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
export const DisabledOption: Story = {
|
|
151
|
+
parameters: {
|
|
152
|
+
controls: { disable: true },
|
|
153
|
+
docs: {
|
|
154
|
+
description: {
|
|
155
|
+
story:
|
|
156
|
+
'禁用候选项 —— 单个 option 的 `disabled` 会让它在下拉中变灰且不可选中(键盘跳过、点击无效)。',
|
|
157
|
+
},
|
|
158
|
+
},
|
|
159
|
+
},
|
|
160
|
+
render: () => (
|
|
161
|
+
<Mentions
|
|
162
|
+
options={[
|
|
163
|
+
{ value: 'alice', label: 'Alice (在线)' },
|
|
164
|
+
{ value: 'bob', label: 'Bob (离线)', disabled: true },
|
|
165
|
+
{ value: 'carol', label: 'Carol (在线)' },
|
|
166
|
+
]}
|
|
167
|
+
placeholder="@ 试试,Bob 不可选..."
|
|
168
|
+
/>
|
|
169
|
+
),
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
export const Disabled: Story = {
|
|
173
|
+
parameters: {
|
|
174
|
+
controls: { disable: true },
|
|
175
|
+
docs: {
|
|
176
|
+
description: {
|
|
177
|
+
story:
|
|
178
|
+
'整组禁用 —— `disabled` 透传 Textarea,既不可输入也不弹出候选。',
|
|
179
|
+
},
|
|
180
|
+
},
|
|
181
|
+
},
|
|
182
|
+
render: () => (
|
|
183
|
+
<Mentions
|
|
184
|
+
options={users}
|
|
185
|
+
defaultValue="@alice 这个评论已经被锁定..."
|
|
186
|
+
disabled
|
|
187
|
+
/>
|
|
188
|
+
),
|
|
189
|
+
};
|
|
@@ -68,10 +68,11 @@ function getTriggerContext(
|
|
|
68
68
|
// Walk backwards from caret until we hit a whitespace, newline, or `prefix`.
|
|
69
69
|
for (let i = caret - 1; i >= 0; i--) {
|
|
70
70
|
const ch = value[i];
|
|
71
|
+
if (ch === undefined) return null;
|
|
71
72
|
if (ch === prefix) {
|
|
72
73
|
// The char immediately before prefix must be start-of-string / whitespace / newline,
|
|
73
74
|
// otherwise we'd trigger on emails like a@b.
|
|
74
|
-
const prev = i === 0 ? '' : value[i - 1];
|
|
75
|
+
const prev = i === 0 ? '' : value[i - 1] ?? '';
|
|
75
76
|
if (prev === '' || /\s/.test(prev)) {
|
|
76
77
|
return { start: i, query: value.slice(i + 1, caret) };
|
|
77
78
|
}
|
|
@@ -106,7 +107,10 @@ const Mentions = React.forwardRef<HTMLTextAreaElement, MentionsProps>(
|
|
|
106
107
|
const current = isControlled ? value! : internal;
|
|
107
108
|
|
|
108
109
|
const innerRef = React.useRef<HTMLTextAreaElement | null>(null);
|
|
109
|
-
React.useImperativeHandle(
|
|
110
|
+
React.useImperativeHandle(
|
|
111
|
+
ref,
|
|
112
|
+
() => innerRef.current as HTMLTextAreaElement,
|
|
113
|
+
);
|
|
110
114
|
|
|
111
115
|
const [ctx, setCtx] = React.useState<TriggerCtx | null>(null);
|
|
112
116
|
const [activeIdx, setActiveIdx] = React.useState(0);
|
|
@@ -142,7 +146,7 @@ const Mentions = React.forwardRef<HTMLTextAreaElement, MentionsProps>(
|
|
|
142
146
|
const el = innerRef.current;
|
|
143
147
|
const before = current.slice(0, ctx.start);
|
|
144
148
|
const after = current.slice(
|
|
145
|
-
|
|
149
|
+
el?.selectionStart ?? ctx.start + 1 + ctx.query.length,
|
|
146
150
|
);
|
|
147
151
|
const inserted = `${prefix}${opt.value}${split}`;
|
|
148
152
|
const next = `${before}${inserted}${after}`;
|
|
@@ -205,7 +209,7 @@ const Mentions = React.forwardRef<HTMLTextAreaElement, MentionsProps>(
|
|
|
205
209
|
{ctx && filtered.length > 0 ? (
|
|
206
210
|
<ul
|
|
207
211
|
role="listbox"
|
|
208
|
-
className="absolute left-0 top-full z-50 mt-1 max-h-60 w-56 overflow-auto rounded-md border bg-popover p-1 text-
|
|
212
|
+
className="absolute left-0 top-full z-50 mt-1 max-h-60 w-56 overflow-auto rounded-md border border-border bg-popover p-1 text-xs text-popover-foreground shadow-md"
|
|
209
213
|
>
|
|
210
214
|
{filtered.map((opt, i) => (
|
|
211
215
|
<li
|
|
@@ -219,7 +223,9 @@ const Mentions = React.forwardRef<HTMLTextAreaElement, MentionsProps>(
|
|
|
219
223
|
onMouseEnter={() => setActiveIdx(i)}
|
|
220
224
|
className={cn(
|
|
221
225
|
'cursor-pointer rounded-sm px-2 py-1.5',
|
|
222
|
-
i === activeIdx &&
|
|
226
|
+
i === activeIdx &&
|
|
227
|
+
!opt.disabled &&
|
|
228
|
+
'bg-accent text-accent-foreground',
|
|
223
229
|
opt.disabled && 'cursor-not-allowed opacity-50',
|
|
224
230
|
)}
|
|
225
231
|
>
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
---
|
|
2
2
|
id: menubar
|
|
3
3
|
name: Menubar
|
|
4
|
+
displayName: 菜单栏
|
|
4
5
|
type: component
|
|
5
|
-
category:
|
|
6
|
+
category: deprecated
|
|
6
7
|
since: 0.1.0
|
|
7
|
-
package:
|
|
8
|
+
package: '@teamix-evo/ui'
|
|
8
9
|
---
|
|
9
10
|
|
|
10
|
-
# Menubar
|
|
11
|
+
# Menubar 菜单栏
|
|
11
12
|
|
|
12
13
|
应用顶部菜单栏 — Radix Menubar(典型 macOS 风格,文件 / 编辑 / 视图 / 帮助)。
|
|
13
14
|
**与 DropdownMenu 区别**:Menubar 是**横排多个一级菜单**,鼠标 hover 切换;DropdownMenu 是单个独立下拉。
|
|
@@ -66,17 +67,28 @@ pnpm add @radix-ui/react-menubar@^1.1.0 lucide-react@^0.460.0
|
|
|
66
67
|
|
|
67
68
|
```tsx
|
|
68
69
|
import {
|
|
69
|
-
Menubar,
|
|
70
|
-
|
|
71
|
-
|
|
70
|
+
Menubar,
|
|
71
|
+
MenubarMenu,
|
|
72
|
+
MenubarTrigger,
|
|
73
|
+
MenubarContent,
|
|
74
|
+
MenubarItem,
|
|
75
|
+
MenubarSeparator,
|
|
76
|
+
MenubarShortcut,
|
|
77
|
+
MenubarSub,
|
|
78
|
+
MenubarSubTrigger,
|
|
79
|
+
MenubarSubContent,
|
|
72
80
|
} from '@/components/ui/menubar';
|
|
73
81
|
|
|
74
82
|
<Menubar>
|
|
75
83
|
<MenubarMenu>
|
|
76
84
|
<MenubarTrigger>文件</MenubarTrigger>
|
|
77
85
|
<MenubarContent>
|
|
78
|
-
<MenubarItem
|
|
79
|
-
|
|
86
|
+
<MenubarItem>
|
|
87
|
+
新建文件 <MenubarShortcut>⌘N</MenubarShortcut>
|
|
88
|
+
</MenubarItem>
|
|
89
|
+
<MenubarItem>
|
|
90
|
+
打开 <MenubarShortcut>⌘O</MenubarShortcut>
|
|
91
|
+
</MenubarItem>
|
|
80
92
|
<MenubarSeparator />
|
|
81
93
|
<MenubarSub>
|
|
82
94
|
<MenubarSubTrigger>分享</MenubarSubTrigger>
|
|
@@ -86,15 +98,21 @@ import {
|
|
|
86
98
|
</MenubarSubContent>
|
|
87
99
|
</MenubarSub>
|
|
88
100
|
<MenubarSeparator />
|
|
89
|
-
<MenubarItem
|
|
101
|
+
<MenubarItem>
|
|
102
|
+
退出 <MenubarShortcut>⌘Q</MenubarShortcut>
|
|
103
|
+
</MenubarItem>
|
|
90
104
|
</MenubarContent>
|
|
91
105
|
</MenubarMenu>
|
|
92
106
|
<MenubarMenu>
|
|
93
107
|
<MenubarTrigger>编辑</MenubarTrigger>
|
|
94
108
|
<MenubarContent>
|
|
95
|
-
<MenubarItem
|
|
96
|
-
|
|
109
|
+
<MenubarItem>
|
|
110
|
+
撤销 <MenubarShortcut>⌘Z</MenubarShortcut>
|
|
111
|
+
</MenubarItem>
|
|
112
|
+
<MenubarItem>
|
|
113
|
+
重做 <MenubarShortcut>⇧⌘Z</MenubarShortcut>
|
|
114
|
+
</MenubarItem>
|
|
97
115
|
</MenubarContent>
|
|
98
116
|
</MenubarMenu>
|
|
99
|
-
</Menubar
|
|
117
|
+
</Menubar>;
|
|
100
118
|
```
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
3
|
import {
|
|
3
4
|
Menubar,
|
|
4
5
|
MenubarMenu,
|
|
@@ -10,12 +11,23 @@ import {
|
|
|
10
11
|
MenubarSub,
|
|
11
12
|
MenubarSubTrigger,
|
|
12
13
|
MenubarSubContent,
|
|
14
|
+
MenubarCheckboxItem,
|
|
15
|
+
MenubarRadioGroup,
|
|
16
|
+
MenubarRadioItem,
|
|
13
17
|
} from './menubar';
|
|
14
18
|
|
|
15
19
|
const meta: Meta<typeof Menubar> = {
|
|
16
|
-
title: '
|
|
20
|
+
title: '废弃 · Deprecated/Menubar',
|
|
17
21
|
component: Menubar,
|
|
18
22
|
tags: ['autodocs'],
|
|
23
|
+
parameters: {
|
|
24
|
+
docs: {
|
|
25
|
+
description: {
|
|
26
|
+
component:
|
|
27
|
+
'⚠️ **已废弃** — 仅 Storybook 留档,不通过 manifest 对外发布。\n\nMenubar 菜单栏 —— 在桌面应用或编辑器顶部带出 macOS 风格的“文件 / 编辑 / 视图 / 帮助”多一级菜单。Radix `Menubar` 内核 + shadcn 原子,**shadcn 专有、antd 未提供对应原子**,对齐 shadcn 的 `MenubarMenu` / `MenubarTrigger` / `MenubarContent` / `MenubarShortcut` / `MenubarSub` / `MenubarCheckboxItem` / `MenubarRadioItem`。视觉走 OpenTrek semantic tokens,所有样式来自 `@teamix-evo/tokens`,无 mock。',
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
},
|
|
19
31
|
};
|
|
20
32
|
|
|
21
33
|
export default meta;
|
|
@@ -79,3 +91,51 @@ export const Default: Story = {
|
|
|
79
91
|
</Menubar>
|
|
80
92
|
),
|
|
81
93
|
};
|
|
94
|
+
|
|
95
|
+
export const WithCheckboxAndRadio: Story = {
|
|
96
|
+
parameters: { controls: { disable: true } },
|
|
97
|
+
render: () => {
|
|
98
|
+
const [showStatus, setShowStatus] = React.useState(true);
|
|
99
|
+
const [showActivity, setShowActivity] = React.useState(false);
|
|
100
|
+
const [profile, setProfile] = React.useState('benoit');
|
|
101
|
+
return (
|
|
102
|
+
<Menubar>
|
|
103
|
+
<MenubarMenu>
|
|
104
|
+
<MenubarTrigger>视图</MenubarTrigger>
|
|
105
|
+
<MenubarContent>
|
|
106
|
+
<MenubarCheckboxItem checked={showStatus} onCheckedChange={setShowStatus}>
|
|
107
|
+
状态栏
|
|
108
|
+
</MenubarCheckboxItem>
|
|
109
|
+
<MenubarCheckboxItem checked={showActivity} onCheckedChange={setShowActivity}>
|
|
110
|
+
活动栏
|
|
111
|
+
</MenubarCheckboxItem>
|
|
112
|
+
<MenubarSeparator />
|
|
113
|
+
<MenubarRadioGroup value={profile} onValueChange={setProfile}>
|
|
114
|
+
<MenubarRadioItem value="benoit">Benoit</MenubarRadioItem>
|
|
115
|
+
<MenubarRadioItem value="colm">Colm</MenubarRadioItem>
|
|
116
|
+
<MenubarRadioItem value="hubert">Hubert</MenubarRadioItem>
|
|
117
|
+
</MenubarRadioGroup>
|
|
118
|
+
</MenubarContent>
|
|
119
|
+
</MenubarMenu>
|
|
120
|
+
</Menubar>
|
|
121
|
+
);
|
|
122
|
+
},
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
export const DisabledItems: Story = {
|
|
126
|
+
parameters: { controls: { disable: true } },
|
|
127
|
+
render: () => (
|
|
128
|
+
<Menubar>
|
|
129
|
+
<MenubarMenu>
|
|
130
|
+
<MenubarTrigger>文件</MenubarTrigger>
|
|
131
|
+
<MenubarContent>
|
|
132
|
+
<MenubarItem>新建</MenubarItem>
|
|
133
|
+
<MenubarItem disabled>从模板新建(即将上线)</MenubarItem>
|
|
134
|
+
<MenubarSeparator />
|
|
135
|
+
<MenubarItem>保存</MenubarItem>
|
|
136
|
+
<MenubarItem disabled>发布到云端(未设置)</MenubarItem>
|
|
137
|
+
</MenubarContent>
|
|
138
|
+
</MenubarMenu>
|
|
139
|
+
</Menubar>
|
|
140
|
+
),
|
|
141
|
+
};
|
|
@@ -21,7 +21,7 @@ const Menubar = React.forwardRef<
|
|
|
21
21
|
<MenubarPrimitive.Root
|
|
22
22
|
ref={ref}
|
|
23
23
|
className={cn(
|
|
24
|
-
'flex h-9 items-center gap-1 rounded-md border bg-background p-1 shadow-sm',
|
|
24
|
+
'flex h-9 items-center gap-1 rounded-md border border-border bg-background p-1 shadow-sm',
|
|
25
25
|
className,
|
|
26
26
|
)}
|
|
27
27
|
{...props}
|
|
@@ -36,7 +36,7 @@ const MenubarTrigger = React.forwardRef<
|
|
|
36
36
|
<MenubarPrimitive.Trigger
|
|
37
37
|
ref={ref}
|
|
38
38
|
className={cn(
|
|
39
|
-
'flex cursor-
|
|
39
|
+
'flex cursor-pointer select-none items-center rounded-sm px-3 py-1 text-xs font-medium outline-none focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground',
|
|
40
40
|
className,
|
|
41
41
|
)}
|
|
42
42
|
{...props}
|
|
@@ -53,7 +53,7 @@ const MenubarSubTrigger = React.forwardRef<
|
|
|
53
53
|
<MenubarPrimitive.SubTrigger
|
|
54
54
|
ref={ref}
|
|
55
55
|
className={cn(
|
|
56
|
-
'flex cursor-
|
|
56
|
+
'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',
|
|
57
57
|
inset && 'pl-8',
|
|
58
58
|
className,
|
|
59
59
|
)}
|
|
@@ -72,7 +72,7 @@ const MenubarSubContent = React.forwardRef<
|
|
|
72
72
|
<MenubarPrimitive.SubContent
|
|
73
73
|
ref={ref}
|
|
74
74
|
className={cn(
|
|
75
|
-
'z-50 min-w-
|
|
75
|
+
'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',
|
|
76
76
|
className,
|
|
77
77
|
)}
|
|
78
78
|
{...props}
|
|
@@ -95,7 +95,7 @@ const MenubarContent = React.forwardRef<
|
|
|
95
95
|
alignOffset={alignOffset}
|
|
96
96
|
sideOffset={sideOffset}
|
|
97
97
|
className={cn(
|
|
98
|
-
'z-50 min-w-
|
|
98
|
+
'z-50 min-w-menu-md overflow-hidden rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95',
|
|
99
99
|
className,
|
|
100
100
|
)}
|
|
101
101
|
{...props}
|
|
@@ -114,7 +114,7 @@ const MenubarItem = React.forwardRef<
|
|
|
114
114
|
<MenubarPrimitive.Item
|
|
115
115
|
ref={ref}
|
|
116
116
|
className={cn(
|
|
117
|
-
'relative flex cursor-
|
|
117
|
+
'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',
|
|
118
118
|
inset && 'pl-8',
|
|
119
119
|
className,
|
|
120
120
|
)}
|
|
@@ -130,7 +130,7 @@ const MenubarCheckboxItem = React.forwardRef<
|
|
|
130
130
|
<MenubarPrimitive.CheckboxItem
|
|
131
131
|
ref={ref}
|
|
132
132
|
className={cn(
|
|
133
|
-
'relative flex cursor-
|
|
133
|
+
'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',
|
|
134
134
|
className,
|
|
135
135
|
)}
|
|
136
136
|
checked={checked}
|
|
@@ -153,7 +153,7 @@ const MenubarRadioItem = React.forwardRef<
|
|
|
153
153
|
<MenubarPrimitive.RadioItem
|
|
154
154
|
ref={ref}
|
|
155
155
|
className={cn(
|
|
156
|
-
'relative flex cursor-
|
|
156
|
+
'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',
|
|
157
157
|
className,
|
|
158
158
|
)}
|
|
159
159
|
{...props}
|
|
@@ -177,7 +177,7 @@ const MenubarLabel = React.forwardRef<
|
|
|
177
177
|
<MenubarPrimitive.Label
|
|
178
178
|
ref={ref}
|
|
179
179
|
className={cn(
|
|
180
|
-
'px-2 py-1.5 text-
|
|
180
|
+
'px-2 py-1.5 text-xs font-semibold',
|
|
181
181
|
inset && 'pl-8',
|
|
182
182
|
className,
|
|
183
183
|
)}
|
|
@@ -2,12 +2,13 @@
|
|
|
2
2
|
id: native-select
|
|
3
3
|
name: NativeSelect
|
|
4
4
|
type: component
|
|
5
|
-
category:
|
|
5
|
+
category: deprecated
|
|
6
6
|
since: 0.1.0
|
|
7
|
-
package:
|
|
7
|
+
package: '@teamix-evo/ui'
|
|
8
|
+
displayName: 原生下拉
|
|
8
9
|
---
|
|
9
10
|
|
|
10
|
-
# NativeSelect
|
|
11
|
+
# NativeSelect 原生下拉
|
|
11
12
|
|
|
12
13
|
原生下拉选择 — shadcn 2025-10 新增。**原生 `<select>` 元素**的样式封装,零 JS 开销,移动端弹起系统 picker,直接参与 form `submit`。与 `Select`(Radix)互为补充,分别面向"原生友好"与"可定制项 UI"两种诉求。
|
|
13
14
|
|
|
@@ -23,12 +24,16 @@ package: "@teamix-evo/ui"
|
|
|
23
24
|
- 需要搜索 / 虚拟列表 / 自定义选项渲染 → `Select`(Radix)/ `Combobox`
|
|
24
25
|
- 多选 → `Select multiple`(原生 multi 体验差)→ 用 Radix 版
|
|
25
26
|
|
|
27
|
+
## Props
|
|
28
|
+
|
|
26
29
|
<!-- auto:props:begin -->
|
|
27
30
|
| 名称 | 类型 | 默认值 | 必填 | 说明 |
|
|
28
31
|
| --- | --- | --- | --- | --- |
|
|
29
32
|
| `wrapperClassName` | `string` | – | – | 容器额外 className(给外层 wrapper,而非 `<select>` 本身)。 |
|
|
30
33
|
<!-- auto:props:end -->
|
|
31
34
|
|
|
35
|
+
## 依赖
|
|
36
|
+
|
|
32
37
|
<!-- auto:deps:begin -->
|
|
33
38
|
### 同库依赖
|
|
34
39
|
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from '@storybook/react';
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
2
|
import { NativeSelect } from './native-select';
|
|
3
3
|
|
|
4
4
|
const meta: Meta<typeof NativeSelect> = {
|
|
5
|
-
title: '
|
|
5
|
+
title: '废弃 · Deprecated/NativeSelect',
|
|
6
6
|
component: NativeSelect,
|
|
7
7
|
tags: ['autodocs'],
|
|
8
8
|
parameters: {
|
|
9
9
|
docs: {
|
|
10
10
|
description: {
|
|
11
11
|
component:
|
|
12
|
-
'原生下拉选择 — 原生 `<select>`
|
|
12
|
+
'⚠️ **已废弃** — 仅 Storybook 留档,不通过 manifest 对外发布。\n\n原生下拉选择 — 原生 `<select>` 元素的样式封装,零 JS 开销,移动端弹起系统 picker,直接参与 form submit。与 Radix `Select` 互为补充:NativeSelect 面向原生 / 移动端友好,Radix Select 面向自定义项 UI / 受控复杂表单。shadcn 2025-10 新增。',
|
|
13
13
|
},
|
|
14
14
|
},
|
|
15
15
|
},
|
|
@@ -63,7 +63,7 @@ export const InForm: Story = {
|
|
|
63
63
|
onSubmit={(e) => {
|
|
64
64
|
e.preventDefault();
|
|
65
65
|
const fd = new FormData(e.currentTarget);
|
|
66
|
-
|
|
66
|
+
|
|
67
67
|
alert(`提交: sort=${fd.get('sort')}`);
|
|
68
68
|
}}
|
|
69
69
|
className="flex items-center gap-2"
|
|
@@ -72,7 +72,10 @@ export const InForm: Story = {
|
|
|
72
72
|
<option value="date">按日期</option>
|
|
73
73
|
<option value="name">按名称</option>
|
|
74
74
|
</NativeSelect>
|
|
75
|
-
<button
|
|
75
|
+
<button
|
|
76
|
+
type="submit"
|
|
77
|
+
className="rounded-md border border-border px-3 py-1 text-sm hover:bg-accent"
|
|
78
|
+
>
|
|
76
79
|
提交
|
|
77
80
|
</button>
|
|
78
81
|
</form>
|