@qijenchen/design-system 0.1.0-beta.3

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.
Files changed (119) hide show
  1. package/package.json +93 -0
  2. package/src/README.md +32 -0
  3. package/src/components/Accordion/accordion.tsx +104 -0
  4. package/src/components/Alert/alert.tsx +188 -0
  5. package/src/components/AppShell/_demo-helpers.tsx +198 -0
  6. package/src/components/AppShell/app-shell.tsx +364 -0
  7. package/src/components/AspectRatio/aspect-ratio.tsx +58 -0
  8. package/src/components/Avatar/avatar.tsx +368 -0
  9. package/src/components/Badge/badge.tsx +104 -0
  10. package/src/components/Breadcrumb/breadcrumb.tsx +609 -0
  11. package/src/components/BulkActionBar/bulk-action-bar.tsx +156 -0
  12. package/src/components/Button/button-group.tsx +96 -0
  13. package/src/components/Button/button.tsx +539 -0
  14. package/src/components/Calendar/calendar.tsx +411 -0
  15. package/src/components/Carousel/carousel.tsx +371 -0
  16. package/src/components/Chart/chart.tsx +376 -0
  17. package/src/components/Checkbox/checkbox-group.tsx +94 -0
  18. package/src/components/Checkbox/checkbox.tsx +237 -0
  19. package/src/components/Chip/chip.tsx +359 -0
  20. package/src/components/CircularProgress/circular-progress.tsx +204 -0
  21. package/src/components/Coachmark/coachmark.tsx +255 -0
  22. package/src/components/Combobox/combobox.tsx +826 -0
  23. package/src/components/Command/command.tsx +187 -0
  24. package/src/components/DataTable/active-editor-controller.ts +72 -0
  25. package/src/components/DataTable/cell-registry.tsx +520 -0
  26. package/src/components/DataTable/column-types.ts +180 -0
  27. package/src/components/DataTable/data-table-column-visibility-panel.tsx +261 -0
  28. package/src/components/DataTable/data-table-filter-panel.tsx +813 -0
  29. package/src/components/DataTable/data-table-interaction-layer.tsx +483 -0
  30. package/src/components/DataTable/data-table-sort-manager.tsx +210 -0
  31. package/src/components/DataTable/data-table.css +165 -0
  32. package/src/components/DataTable/data-table.tsx +2924 -0
  33. package/src/components/DataTable/filter-operators.ts +225 -0
  34. package/src/components/DataTable/filter-tree.ts +313 -0
  35. package/src/components/DataTable/lib/column-meta.ts +79 -0
  36. package/src/components/DateGrid/date-grid.tsx +209 -0
  37. package/src/components/DatePicker/date-picker.tsx +1114 -0
  38. package/src/components/DescriptionList/description-list.tsx +141 -0
  39. package/src/components/Dialog/dialog.tsx +267 -0
  40. package/src/components/DropdownMenu/dropdown-menu.tsx +475 -0
  41. package/src/components/Empty/empty.tsx +108 -0
  42. package/src/components/Field/field-context.ts +136 -0
  43. package/src/components/Field/field-types.ts +52 -0
  44. package/src/components/Field/field-wrapper.tsx +348 -0
  45. package/src/components/Field/field.tsx +535 -0
  46. package/src/components/FieldControlGroup/field-control-group.tsx +136 -0
  47. package/src/components/FileItem/file-item.tsx +322 -0
  48. package/src/components/FileUpload/file-upload.tsx +326 -0
  49. package/src/components/FileViewer/file-viewer-types.ts +76 -0
  50. package/src/components/FileViewer/file-viewer.tsx +1065 -0
  51. package/src/components/FileViewer/image-renderer.tsx +256 -0
  52. package/src/components/HoverCard/hover-card.tsx +79 -0
  53. package/src/components/Input/input.tsx +233 -0
  54. package/src/components/LinkInput/link-input.tsx +304 -0
  55. package/src/components/Menu/menu-item.tsx +334 -0
  56. package/src/components/NameCard/name-card.tsx +319 -0
  57. package/src/components/Notice/notice.tsx +196 -0
  58. package/src/components/NumberInput/number-input.tsx +203 -0
  59. package/src/components/OverflowIndicator/overflow-indicator.tsx +156 -0
  60. package/src/components/PeoplePicker/avatar-stack-overflow.ts +100 -0
  61. package/src/components/PeoplePicker/people-picker-helpers.ts +76 -0
  62. package/src/components/PeoplePicker/people-picker.tsx +455 -0
  63. package/src/components/PeoplePicker/person-display.tsx +358 -0
  64. package/src/components/Popover/popover.tsx +183 -0
  65. package/src/components/ProgressBar/progress-bar.tsx +157 -0
  66. package/src/components/README.md +58 -0
  67. package/src/components/RadioGroup/radio-group.tsx +261 -0
  68. package/src/components/Rating/rating.tsx +295 -0
  69. package/src/components/ScrollArea/scroll-area.tsx +110 -0
  70. package/src/components/SegmentedControl/segmented-control.tsx +304 -0
  71. package/src/components/Select/select.tsx +658 -0
  72. package/src/components/SelectMenu/select-menu.tsx +430 -0
  73. package/src/components/SelectionControl/selection-item.tsx +261 -0
  74. package/src/components/Separator/separator.tsx +48 -0
  75. package/src/components/Sheet/sheet.tsx +240 -0
  76. package/src/components/Sidebar/sidebar.tsx +1280 -0
  77. package/src/components/Skeleton/skeleton.tsx +35 -0
  78. package/src/components/Slider/slider.tsx +158 -0
  79. package/src/components/Steps/steps.tsx +850 -0
  80. package/src/components/Switch/switch.tsx +285 -0
  81. package/src/components/Tabs/tabs.tsx +515 -0
  82. package/src/components/Tag/tag.tsx +246 -0
  83. package/src/components/Textarea/textarea.tsx +280 -0
  84. package/src/components/TimePicker/time-columns.tsx +260 -0
  85. package/src/components/TimePicker/time-picker.tsx +419 -0
  86. package/src/components/Toast/toast.tsx +129 -0
  87. package/src/components/Tooltip/tooltip.tsx +68 -0
  88. package/src/components/TreeView/tree-view.tsx +1031 -0
  89. package/src/hooks/use-controllable.ts +40 -0
  90. package/src/hooks/use-is-narrow-viewport.ts +19 -0
  91. package/src/hooks/use-is-touch-device.ts +21 -0
  92. package/src/hooks/use-overflow-items.ts +256 -0
  93. package/src/index.ts +85 -0
  94. package/src/lib/README.md +82 -0
  95. package/src/lib/drag-visual.ts +272 -0
  96. package/src/lib/i18n/README.md +60 -0
  97. package/src/lib/i18n/i18n-context.tsx +129 -0
  98. package/src/lib/multi-select-ordering.ts +61 -0
  99. package/src/lib/utils.ts +93 -0
  100. package/src/patterns/README.md +67 -0
  101. package/src/patterns/element-anatomy/item-anatomy.tsx +744 -0
  102. package/src/patterns/header-canonical/chrome-header.tsx +175 -0
  103. package/src/patterns/header-canonical/header-canonical.css +27 -0
  104. package/src/patterns/horizontal-overflow/horizontal-overflow.tsx +217 -0
  105. package/src/patterns/overlay-surface/overlay-surface.tsx +191 -0
  106. package/src/patterns/resize-handle/resize-handle.tsx +188 -0
  107. package/src/stories-helpers/anatomy/anatomy-utils.tsx +64 -0
  108. package/src/tokens/README.md +53 -0
  109. package/src/tokens/color/primitives.css +429 -0
  110. package/src/tokens/color/semantic.css +539 -0
  111. package/src/tokens/elevation/overlay-geometry.ts +13 -0
  112. package/src/tokens/layoutSpace/layoutSpace.css +36 -0
  113. package/src/tokens/motion/motion.css +30 -0
  114. package/src/tokens/motion/motion.ts +17 -0
  115. package/src/tokens/opacity/opacity.css +23 -0
  116. package/src/tokens/radius/radius.css +19 -0
  117. package/src/tokens/typography/typography.css +118 -0
  118. package/src/tokens/uiSize/icon-size.ts +52 -0
  119. package/src/tokens/uiSize/uiSize.css +125 -0
@@ -0,0 +1,187 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import { type DialogProps } from "@radix-ui/react-dialog"
5
+ import { Command as CommandPrimitive } from "cmdk"
6
+ import { Search } from "lucide-react"
7
+
8
+ import { cn } from "@/lib/utils"
9
+ import { Dialog, DialogContent } from "@/design-system/components/Dialog/dialog"
10
+ import { ScrollArea } from "@/design-system/components/ScrollArea/scroll-area"
11
+
12
+ const Command = React.forwardRef<
13
+ React.ElementRef<typeof CommandPrimitive>,
14
+ React.ComponentPropsWithoutRef<typeof CommandPrimitive>
15
+ >(({ className, ...props }, ref) => (
16
+ <CommandPrimitive
17
+ ref={ref}
18
+ className={cn(
19
+ "flex h-full w-full flex-col overflow-hidden rounded-md bg-surface-raised text-foreground",
20
+ className
21
+ )}
22
+ {...props}
23
+ />
24
+ ))
25
+ Command.displayName = CommandPrimitive.displayName
26
+
27
+ const CommandDialog = ({ children, ...props }: DialogProps) => {
28
+ // M2 verified 2026-04-25(cmdk/dist/index.js source):cmdk 於 DOM 上 emit
29
+ // `cmdk-group-heading=""` / `cmdk-group=""` / `cmdk-input-wrapper=""` / `cmdk-input=""` /
30
+ // `cmdk-item=""` attributes,下列 `[&_[cmdk-*]]:` attribute selectors 皆有對應真實 DOM。
31
+ return (
32
+ <Dialog {...props}>
33
+ <DialogContent className="overflow-hidden p-0 shadow-[var(--elevation-200)]">
34
+ <Command className="[&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-fg-muted [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-group]]:px-2 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5">
35
+ {children}
36
+ </Command>
37
+ </DialogContent>
38
+ </Dialog>
39
+ )
40
+ }
41
+
42
+ const CommandInput = React.forwardRef<
43
+ React.ElementRef<typeof CommandPrimitive.Input>,
44
+ React.ComponentPropsWithoutRef<typeof CommandPrimitive.Input>
45
+ >(({ className, ...props }, ref) => (
46
+ <div className="flex items-center border-b px-3" cmdk-input-wrapper="">
47
+ <Search className="mr-2 h-4 w-4 shrink-0 text-fg-muted" />
48
+ <CommandPrimitive.Input
49
+ ref={ref}
50
+ className={cn(
51
+ "flex h-11 w-full rounded-md bg-transparent py-3 text-body outline-none placeholder:text-fg-muted disabled:cursor-not-allowed disabled:text-fg-disabled disabled:placeholder:text-fg-disabled",
52
+ className
53
+ )}
54
+ {...props}
55
+ />
56
+ </div>
57
+ ))
58
+
59
+ CommandInput.displayName = CommandPrimitive.Input.displayName
60
+
61
+ /**
62
+ * CommandList — cmdk primitive 外包 ScrollArea 跨 OS scrollbar 一致。
63
+ *
64
+ * Verified against cmdk/dist/index.js(2026-04-25):cmdk selected-item auto-scroll
65
+ * 用標準 `Element.scrollIntoView({block:"nearest"})`,browser 向上找 nearest
66
+ * scrollable ancestor → 命中 ScrollArea.Viewport(`overflow:hidden scroll`)→ 自動
67
+ * 捲入 selected ✓。不需 MutationObserver sync。
68
+ *
69
+ * `cmdk-list-sizer` ResizeObserver 只量 offsetHeight 設 CSS var `--cmdk-list-height`
70
+ * (純測量,非 scroll logic),wrap 不影響。
71
+ *
72
+ * 跨 DS 一致:DataTable / Sheet / Sidebar / DropdownMenu / Command 皆走 ScrollArea。
73
+ */
74
+ const CommandList = React.forwardRef<
75
+ React.ElementRef<typeof CommandPrimitive.List>,
76
+ React.ComponentPropsWithoutRef<typeof CommandPrimitive.List>
77
+ >(({ className, ...props }, ref) => (
78
+ <ScrollArea className="max-h-[var(--menu-max-height,300px)]">
79
+ <CommandPrimitive.List ref={ref} className={cn("overflow-x-hidden", className)} {...props} />
80
+ </ScrollArea>
81
+ ))
82
+
83
+ CommandList.displayName = CommandPrimitive.List.displayName
84
+
85
+ const CommandEmpty = React.forwardRef<
86
+ React.ElementRef<typeof CommandPrimitive.Empty>,
87
+ React.ComponentPropsWithoutRef<typeof CommandPrimitive.Empty>
88
+ >(({ className, ...props }, ref) => (
89
+ <CommandPrimitive.Empty
90
+ ref={ref}
91
+ className={className}
92
+ {...props}
93
+ />
94
+ ))
95
+
96
+ CommandEmpty.displayName = CommandPrimitive.Empty.displayName
97
+
98
+ const CommandGroup = React.forwardRef<
99
+ React.ElementRef<typeof CommandPrimitive.Group>,
100
+ React.ComponentPropsWithoutRef<typeof CommandPrimitive.Group>
101
+ >(({ className, ...props }, ref) => (
102
+ <CommandPrimitive.Group
103
+ ref={ref}
104
+ className={cn(
105
+ "overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-caption [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-fg-muted",
106
+ className
107
+ )}
108
+ {...props}
109
+ />
110
+ ))
111
+
112
+ CommandGroup.displayName = CommandPrimitive.Group.displayName
113
+
114
+ const CommandSeparator = React.forwardRef<
115
+ React.ElementRef<typeof CommandPrimitive.Separator>,
116
+ React.ComponentPropsWithoutRef<typeof CommandPrimitive.Separator>
117
+ >(({ className, ...props }, ref) => (
118
+ <CommandPrimitive.Separator
119
+ ref={ref}
120
+ className={cn("h-px bg-divider", className)}
121
+ {...props}
122
+ />
123
+ ))
124
+ CommandSeparator.displayName = CommandPrimitive.Separator.displayName
125
+
126
+ const CommandItem = React.forwardRef<
127
+ React.ElementRef<typeof CommandPrimitive.Item>,
128
+ React.ComponentPropsWithoutRef<typeof CommandPrimitive.Item>
129
+ >(({ className, ...props }, ref) => (
130
+ <CommandPrimitive.Item
131
+ ref={ref}
132
+ className={cn(
133
+ "relative flex cursor-default gap-2 select-none items-center rounded-md px-2 py-1.5 text-body outline-none data-[disabled=true]:pointer-events-none data-[selected='true']:bg-neutral-hover data-[selected=true]:text-foreground data-[disabled=true]:text-fg-disabled [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
134
+ className
135
+ )}
136
+ {...props}
137
+ />
138
+ ))
139
+
140
+ CommandItem.displayName = CommandPrimitive.Item.displayName
141
+
142
+ const CommandShortcut = ({
143
+ className,
144
+ ...props
145
+ }: React.HTMLAttributes<HTMLSpanElement>) => {
146
+ return (
147
+ <span
148
+ className={cn(
149
+ "ml-auto text-caption tracking-shortcut text-fg-muted",
150
+ className
151
+ )}
152
+ {...props}
153
+ />
154
+ )
155
+ }
156
+ CommandShortcut.displayName = "CommandShortcut"
157
+
158
+ // Story auto-compile metadata — Phase 1 mechanical migration(2026-04-24)
159
+ // Phase 2 fill needed: purpose descriptions + when rationale + world-class refs
160
+ export const commandMeta = {
161
+ component: 'Command',
162
+ family: null, // non-family composite / overlay / layout
163
+ variants: {
164
+
165
+ },
166
+ sizes: {
167
+
168
+ },
169
+ states: ['default', 'hover', 'active', 'focus-visible', 'disabled'],
170
+ tokens: {
171
+ bg: ['bg-neutral-hover', 'bg-surface-raised', 'bg-transparent'],
172
+ fg: ['text-fg-disabled', 'text-fg-muted', 'text-foreground'],
173
+ ring: [],
174
+ },
175
+ } as const
176
+
177
+ export {
178
+ Command,
179
+ CommandDialog,
180
+ CommandInput,
181
+ CommandList,
182
+ CommandEmpty,
183
+ CommandGroup,
184
+ CommandItem,
185
+ CommandShortcut,
186
+ CommandSeparator,
187
+ }
@@ -0,0 +1,72 @@
1
+ /**
2
+ * ActiveEditorController — Slice C **types-only retire**(Issue 11,2026-05-10)
3
+ *
4
+ * **Status: types-only**(class runtime retired,types kept for future RFC reference)。
5
+ *
6
+ * History:Slice C scaffold 原本 spec 為 active editor lifecycle SSOT(startEdit / commit /
7
+ * cancel / Tab route / IME guard / unmount policy)。Phase 7 commit `c5eb054` shipped
8
+ * lightweight alternative — lifted draft state in DataTable + `onDraft` prop per-keystroke
9
+ * propagation,distributed lifecycle ownership 不再集中於此 class。
10
+ *
11
+ * **Lifecycle ownership migration(Phase 7 distributed)**:
12
+ * | RFC Contract | Original class method | New owner(Phase 7) |
13
+ * |---|---|---|
14
+ * | Contract 3 commit/cancel | `controller.commit()` | per-cell `onCommit` / `onCommitLive` callback in cell-registry |
15
+ * | Contract 4 Tab navigation | `controller.routeKeyDown` | `data-table.tsx:2605 handleEditTab`(onKeyDownCapture per portal cell) |
16
+ * | Contract 6 unmount preserve draft | `controller.onAnchorUnmount` | `data-table.tsx editingDraft` lifted state + `onDraft` prop(Phase 7) |
17
+ * | Contract 10 IME guard | `controller.onCompositionStart/End` | Field family per-control IME guard(field-controls.spec.md)+ `data-table.tsx:2609 isComposing` early-return |
18
+ * | Esc cancel | `controller.cancel()` | per-cell Field `onCancel` callback + Radix Popover outside-click |
19
+ *
20
+ * Verify(grep `src/`):**zero runtime consumer** of the class — only `experimentalActiveEditorController`
21
+ * prop name string referenced(this is a flag,not a class import)。Class is dead code as of
22
+ * commit 561945b(2026-05-10)。
23
+ *
24
+ * **Why retire to types-only(not delete file)**:type exports(`CellId` / `EditorReason` /
25
+ * `CommitResult` / `ActiveEditorState` / `ActiveEditorPolicy`)可能仍對 future RFC reference 有用
26
+ * (e.g., RFC 重啟集中式 controller 重構)。Class runtime 已 dead → 刪;types schema 保留 + 加
27
+ * deprecation 註記。
28
+ *
29
+ * RFC amendment:see `datatable-spreadsheet-rfc.md` Slice C / Contract 3 / 6 distributed
30
+ * ownership note(2026-05-10 post-Issue-11 backfill)。
31
+ *
32
+ * **Ship checklist verify**(M31 codex Round 1 ship checklist):
33
+ * 1. ✅ grep confirms class has zero runtime consumer
34
+ * 2. ✅ RFC Slice C / Contract 3 / 6 backfill distributed ownership
35
+ * 3. ✅ Keyboard invariants(Enter / Esc / Tab/Shift+Tab commit-and-move + skip non-editable)
36
+ * — visual-audit-comprehensive 17/17 PASS this turn(scenarios 11-17 cover Enter/Esc/Arrow/Tab)
37
+ * 4. ✅ IME composition — Field per-control built-in + `data-table.tsx:2609 isComposing` guard
38
+ * 5. ✅ Virtualizer scroll-out / scroll-back draft preservation — Phase 7 commit c5eb054 ships
39
+ * `onDraft` prop + lifted state(spec'd in commit body)
40
+ * 6. ✅ Outside-click + nested popover — Radix Popover idiom + Field family
41
+ * 7. ✅ Visual audit ALL PASS this turn
42
+ */
43
+
44
+ export type CellId = string
45
+
46
+ // code-quality-allow: dead-export — public type contract for active-editor controller pattern,reserved for consumer policy implementations(per file header policy hand-off canonical)
47
+ export type EditorReason = 'click' | 'tab' | 'shift-tab' | 'enter' | 'f2' | 'double-click' | 'printable'
48
+
49
+ // code-quality-allow: dead-export — public type contract,same rationale
50
+ export type CommitResult =
51
+ | { ok: true; value: unknown }
52
+ | { ok: false; error: string }
53
+
54
+ export interface ActiveEditorState {
55
+ cellId: CellId | null
56
+ draft: unknown
57
+ originalValue: unknown
58
+ isComposing: boolean
59
+ pendingCommitFromUnmount: boolean
60
+ }
61
+
62
+ // code-quality-allow: dead-export — public type contract,policy interface for cell-edit lifecycle consumer
63
+ export interface ActiveEditorPolicy {
64
+ canEditCell(cellId: CellId): boolean
65
+ cellClickEntersEdit(cellId: CellId): boolean
66
+ findNextEditable(fromCellId: CellId, direction: 'next' | 'prev'): CellId | null
67
+ validate(cellId: CellId, draft: unknown): CommitResult
68
+ onCommitChange(cellId: CellId, value: unknown): void
69
+ }
70
+
71
+ // Class runtime retired(Phase 7 distributed ownership)— see file-level JSDoc。
72
+ // 若 future RFC 重啟集中式 lifecycle controller,可從此 types 重新建構 class impl。