@fragments-sdk/ui 0.8.6 → 0.8.8

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 (116) hide show
  1. package/fragments.json +1 -1
  2. package/package.json +2 -2
  3. package/src/assets/fragments-logo.tsx +9 -8
  4. package/src/blocks/AccountSettings.block.ts +1 -1
  5. package/src/blocks/ActivityFeed.block.ts +1 -1
  6. package/src/blocks/ChatInterface.block.ts +1 -1
  7. package/src/blocks/ChatMessages.block.ts +1 -1
  8. package/src/blocks/CheckoutForm.block.ts +1 -1
  9. package/src/blocks/CommandPalette.block.ts +34 -0
  10. package/src/blocks/ContactForm.block.ts +1 -1
  11. package/src/blocks/DashboardLayout.block.ts +1 -1
  12. package/src/blocks/DashboardPage.block.ts +1 -1
  13. package/src/blocks/DataTable.block.ts +1 -1
  14. package/src/blocks/EmptyState.block.ts +1 -1
  15. package/src/blocks/FAQSection.block.ts +1 -1
  16. package/src/blocks/FeatureGrid.block.ts +1 -1
  17. package/src/blocks/HeroSection.block.ts +1 -1
  18. package/src/blocks/LoginForm.block.ts +1 -1
  19. package/src/blocks/NavigationHeader.block.ts +1 -1
  20. package/src/blocks/PaginatedTable.block.ts +36 -0
  21. package/src/blocks/PricingComparison.block.ts +1 -1
  22. package/src/blocks/ProductCard.block.ts +1 -1
  23. package/src/blocks/RegistrationForm.block.ts +1 -1
  24. package/src/blocks/SettingsDrawer.block.ts +47 -0
  25. package/src/blocks/SettingsPanel.block.ts +1 -1
  26. package/src/blocks/ShoppingCart.block.ts +1 -1
  27. package/src/blocks/StatsCard.block.ts +1 -1
  28. package/src/blocks/ThinkingStates.block.ts +1 -1
  29. package/src/components/Accordion/Accordion.fragment.tsx +1 -1
  30. package/src/components/Alert/Alert.fragment.tsx +1 -1
  31. package/src/components/AppShell/AppShell.fragment.tsx +11 -11
  32. package/src/components/Avatar/Avatar.fragment.tsx +1 -1
  33. package/src/components/Badge/Badge.fragment.tsx +1 -1
  34. package/src/components/Box/Box.fragment.tsx +1 -1
  35. package/src/components/Breadcrumbs/Breadcrumbs.fragment.tsx +1 -1
  36. package/src/components/Button/Button.fragment.tsx +1 -1
  37. package/src/components/ButtonGroup/ButtonGroup.fragment.tsx +1 -1
  38. package/src/components/Card/Card.fragment.tsx +1 -1
  39. package/src/components/Chart/Chart.fragment.tsx +1 -1
  40. package/src/components/Checkbox/Checkbox.fragment.tsx +1 -1
  41. package/src/components/Chip/Chip.fragment.tsx +1 -1
  42. package/src/components/CodeBlock/CodeBlock.fragment.tsx +1 -1
  43. package/src/components/Collapsible/Collapsible.fragment.tsx +1 -1
  44. package/src/components/ColorPicker/ColorPicker.fragment.tsx +1 -1
  45. package/src/components/Combobox/Combobox.fragment.tsx +1 -1
  46. package/src/components/Command/Command.fragment.tsx +237 -0
  47. package/src/components/Command/Command.module.scss +153 -0
  48. package/src/components/Command/Command.test.tsx +363 -0
  49. package/src/components/Command/index.tsx +502 -0
  50. package/src/components/ConversationList/ConversationList.fragment.tsx +1 -1
  51. package/src/components/DatePicker/DatePicker.fragment.tsx +10 -9
  52. package/src/components/Dialog/Dialog.fragment.tsx +1 -1
  53. package/src/components/Drawer/Drawer.fragment.tsx +206 -0
  54. package/src/components/Drawer/Drawer.module.scss +215 -0
  55. package/src/components/Drawer/Drawer.test.tsx +227 -0
  56. package/src/components/Drawer/index.tsx +239 -0
  57. package/src/components/EmptyState/EmptyState.fragment.tsx +1 -1
  58. package/src/components/Field/Field.fragment.tsx +1 -1
  59. package/src/components/Fieldset/Fieldset.fragment.tsx +1 -1
  60. package/src/components/Form/Form.fragment.tsx +1 -1
  61. package/src/components/Grid/Grid.fragment.tsx +1 -1
  62. package/src/components/Header/Header.fragment.tsx +1 -1
  63. package/src/components/Icon/Icon.fragment.tsx +1 -1
  64. package/src/components/Image/Image.fragment.tsx +1 -1
  65. package/src/components/Input/Input.fragment.tsx +1 -1
  66. package/src/components/Link/Link.fragment.tsx +1 -1
  67. package/src/components/List/List.fragment.tsx +1 -1
  68. package/src/components/Listbox/Listbox.fragment.tsx +1 -1
  69. package/src/components/Loading/Loading.fragment.tsx +1 -1
  70. package/src/components/Markdown/Markdown.fragment.tsx +1 -1
  71. package/src/components/Menu/Menu.fragment.tsx +55 -5
  72. package/src/components/Menu/Menu.module.scss +21 -10
  73. package/src/components/Menu/Menu.test.tsx +126 -3
  74. package/src/components/Menu/index.tsx +85 -11
  75. package/src/components/Message/Message.fragment.tsx +1 -1
  76. package/src/components/Message/Message.module.scss +2 -1
  77. package/src/components/NavigationMenu/NavigationMenu.fragment.tsx +1 -1
  78. package/src/components/Pagination/Pagination.fragment.tsx +152 -0
  79. package/src/components/Pagination/Pagination.module.scss +109 -0
  80. package/src/components/Pagination/Pagination.test.tsx +171 -0
  81. package/src/components/Pagination/index.tsx +360 -0
  82. package/src/components/Popover/Popover.fragment.tsx +1 -1
  83. package/src/components/Progress/Progress.fragment.tsx +1 -1
  84. package/src/components/Prompt/Prompt.fragment.tsx +1 -1
  85. package/src/components/RadioGroup/RadioGroup.fragment.tsx +1 -1
  86. package/src/components/ScrollArea/ScrollArea.fragment.tsx +1 -1
  87. package/src/components/Select/Select.fragment.tsx +1 -1
  88. package/src/components/Separator/Separator.fragment.tsx +1 -1
  89. package/src/components/Sidebar/Sidebar.fragment.tsx +2 -2
  90. package/src/components/Skeleton/Skeleton.fragment.tsx +1 -1
  91. package/src/components/Slider/Slider.fragment.tsx +1 -1
  92. package/src/components/Stack/Stack.fragment.tsx +1 -1
  93. package/src/components/Table/Table.fragment.tsx +1 -1
  94. package/src/components/TableOfContents/TableOfContents.fragment.tsx +1 -1
  95. package/src/components/Tabs/Tabs.fragment.tsx +1 -1
  96. package/src/components/Text/Text.fragment.tsx +1 -1
  97. package/src/components/Textarea/Textarea.fragment.tsx +1 -1
  98. package/src/components/Theme/Theme.fragment.tsx +1 -1
  99. package/src/components/ThinkingIndicator/ThinkingIndicator.fragment.tsx +1 -1
  100. package/src/components/Toast/Toast.fragment.tsx +1 -1
  101. package/src/components/Toggle/Toggle.fragment.tsx +1 -1
  102. package/src/components/ToggleGroup/ToggleGroup.fragment.tsx +1 -1
  103. package/src/components/Tooltip/Tooltip.fragment.tsx +1 -1
  104. package/src/components/Tooltip/index.tsx +25 -1
  105. package/src/components/VisuallyHidden/VisuallyHidden.fragment.tsx +1 -1
  106. package/src/index.ts +34 -1
  107. package/src/styles/globals.scss +65 -7
  108. package/src/tokens/_computed.scss +1 -1
  109. package/src/tokens/_density.scss +1 -1
  110. package/src/tokens/_derive.scss +1 -1
  111. package/src/tokens/_index.scss +1 -1
  112. package/src/tokens/_mixins.scss +1 -1
  113. package/src/tokens/_palettes.scss +1 -1
  114. package/src/tokens/_radius.scss +1 -1
  115. package/src/tokens/_seeds.scss +1 -1
  116. package/src/tokens/_variables.scss +2 -2
@@ -0,0 +1,502 @@
1
+ 'use client';
2
+
3
+ import * as React from 'react';
4
+ import styles from './Command.module.scss';
5
+ import '../../styles/globals.scss';
6
+
7
+ // ============================================
8
+ // Types
9
+ // ============================================
10
+
11
+ export interface CommandProps extends React.HTMLAttributes<HTMLDivElement> {
12
+ children: React.ReactNode;
13
+ /** Controlled search value */
14
+ search?: string;
15
+ /** Default search value */
16
+ defaultSearch?: string;
17
+ /** Called when search input changes */
18
+ onSearchChange?: (search: string) => void;
19
+ /** Custom filter function. Return 0 to hide, >0 to show (higher = better match).
20
+ Default: case-insensitive substring match on value + keywords */
21
+ filter?: (value: string, search: string, keywords?: string[]) => number;
22
+ /** Whether to loop keyboard navigation. Default: true */
23
+ loop?: boolean;
24
+ }
25
+
26
+ export interface CommandInputProps extends React.InputHTMLAttributes<HTMLInputElement> {
27
+ className?: string;
28
+ }
29
+
30
+ export interface CommandListProps extends React.HTMLAttributes<HTMLDivElement> {
31
+ children: React.ReactNode;
32
+ }
33
+
34
+ export interface CommandItemProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onSelect'> {
35
+ children: React.ReactNode;
36
+ /** Value used for filtering (falls back to text content) */
37
+ value?: string;
38
+ /** Extra keywords for filtering */
39
+ keywords?: string[];
40
+ /** Whether this item is disabled */
41
+ disabled?: boolean;
42
+ /** Called when item is selected (Enter or click) */
43
+ onItemSelect?: () => void;
44
+ }
45
+
46
+ export interface CommandGroupProps extends React.HTMLAttributes<HTMLDivElement> {
47
+ children: React.ReactNode;
48
+ /** Group heading text */
49
+ heading?: string;
50
+ }
51
+
52
+ export interface CommandEmptyProps extends React.HTMLAttributes<HTMLDivElement> {
53
+ children: React.ReactNode;
54
+ }
55
+
56
+ export interface CommandSeparatorProps extends React.HTMLAttributes<HTMLDivElement> {}
57
+
58
+ // ============================================
59
+ // Default filter
60
+ // ============================================
61
+
62
+ function defaultFilter(value: string, search: string, keywords?: string[]): number {
63
+ if (!search) return 1;
64
+ const searchLower = search.toLowerCase();
65
+ const valueLower = value.toLowerCase();
66
+
67
+ if (valueLower.includes(searchLower)) return 1;
68
+
69
+ if (keywords) {
70
+ for (const keyword of keywords) {
71
+ if (keyword.toLowerCase().includes(searchLower)) return 1;
72
+ }
73
+ }
74
+
75
+ return 0;
76
+ }
77
+
78
+ // ============================================
79
+ // Context
80
+ // ============================================
81
+
82
+ interface ItemRegistration {
83
+ value: string;
84
+ keywords?: string[];
85
+ }
86
+
87
+ interface CommandContextValue {
88
+ search: string;
89
+ setSearch: (search: string) => void;
90
+ filter: (value: string, search: string, keywords?: string[]) => number;
91
+ scores: Map<string, number>;
92
+ registerItem: (id: string, registration: ItemRegistration) => void;
93
+ unregisterItem: (id: string) => void;
94
+ activeId: string | null;
95
+ setActiveId: (id: string | null) => void;
96
+ loop: boolean;
97
+ listRef: React.RefObject<HTMLDivElement | null>;
98
+ visibleCount: number;
99
+ }
100
+
101
+ const CommandContext = React.createContext<CommandContextValue | null>(null);
102
+
103
+ function useCommandContext() {
104
+ const ctx = React.useContext(CommandContext);
105
+ if (!ctx) throw new Error('Command sub-components must be used within <Command>');
106
+ return ctx;
107
+ }
108
+
109
+ // ============================================
110
+ // Search Icon
111
+ // ============================================
112
+
113
+ function SearchIcon() {
114
+ return (
115
+ <svg
116
+ xmlns="http://www.w3.org/2000/svg"
117
+ width="16"
118
+ height="16"
119
+ viewBox="0 0 24 24"
120
+ fill="none"
121
+ stroke="currentColor"
122
+ strokeWidth="2"
123
+ strokeLinecap="round"
124
+ strokeLinejoin="round"
125
+ aria-hidden="true"
126
+ >
127
+ <circle cx="11" cy="11" r="8" />
128
+ <line x1="21" y1="21" x2="16.65" y2="16.65" />
129
+ </svg>
130
+ );
131
+ }
132
+
133
+ // ============================================
134
+ // Components
135
+ // ============================================
136
+
137
+ function CommandRoot({
138
+ children,
139
+ search: controlledSearch,
140
+ defaultSearch = '',
141
+ onSearchChange,
142
+ filter = defaultFilter,
143
+ loop = true,
144
+ className,
145
+ ...htmlProps
146
+ }: CommandProps) {
147
+ const [uncontrolledSearch, setUncontrolledSearch] = React.useState(defaultSearch);
148
+ const isControlled = controlledSearch !== undefined;
149
+ const search = isControlled ? controlledSearch : uncontrolledSearch;
150
+
151
+ const [items, setItems] = React.useState<Map<string, ItemRegistration>>(new Map());
152
+ const [activeId, setActiveId] = React.useState<string | null>(null);
153
+ const listRef = React.useRef<HTMLDivElement | null>(null);
154
+
155
+ const setSearch = React.useCallback(
156
+ (value: string) => {
157
+ if (!isControlled) {
158
+ setUncontrolledSearch(value);
159
+ }
160
+ onSearchChange?.(value);
161
+ },
162
+ [isControlled, onSearchChange]
163
+ );
164
+
165
+ const registerItem = React.useCallback((id: string, registration: ItemRegistration) => {
166
+ setItems((prev) => {
167
+ const next = new Map(prev);
168
+ next.set(id, registration);
169
+ return next;
170
+ });
171
+ }, []);
172
+
173
+ const unregisterItem = React.useCallback((id: string) => {
174
+ setItems((prev) => {
175
+ const next = new Map(prev);
176
+ next.delete(id);
177
+ return next;
178
+ });
179
+ }, []);
180
+
181
+ // Compute scores for all items
182
+ const scores = React.useMemo(() => {
183
+ const result = new Map<string, number>();
184
+ for (const [id, registration] of items) {
185
+ const score = filter(registration.value, search, registration.keywords);
186
+ result.set(id, score);
187
+ }
188
+ return result;
189
+ }, [items, search, filter]);
190
+
191
+ const visibleCount = React.useMemo(() => {
192
+ let count = 0;
193
+ for (const score of scores.values()) {
194
+ if (score > 0) count++;
195
+ }
196
+ return count;
197
+ }, [scores]);
198
+
199
+ // Reset active when search changes
200
+ React.useEffect(() => {
201
+ setActiveId(null);
202
+ }, [search]);
203
+
204
+ const contextValue = React.useMemo<CommandContextValue>(
205
+ () => ({
206
+ search,
207
+ setSearch,
208
+ filter,
209
+ scores,
210
+ registerItem,
211
+ unregisterItem,
212
+ activeId,
213
+ setActiveId,
214
+ loop,
215
+ listRef,
216
+ visibleCount,
217
+ }),
218
+ [search, setSearch, filter, scores, registerItem, unregisterItem, activeId, loop, visibleCount]
219
+ );
220
+
221
+ return (
222
+ <CommandContext.Provider value={contextValue}>
223
+ <div
224
+ {...htmlProps}
225
+ className={[styles.command, className].filter(Boolean).join(' ')}
226
+ role="search"
227
+ >
228
+ {children}
229
+ </div>
230
+ </CommandContext.Provider>
231
+ );
232
+ }
233
+
234
+ function CommandInput({ className, ...htmlProps }: CommandInputProps) {
235
+ const { search, setSearch, listRef, setActiveId, activeId, loop } = useCommandContext();
236
+ const inputRef = React.useRef<HTMLInputElement>(null);
237
+
238
+ const getEnabledItems = React.useCallback(() => {
239
+ const list = listRef.current;
240
+ if (!list) return [];
241
+ return Array.from(
242
+ list.querySelectorAll<HTMLElement>('[data-command-item]:not([data-disabled="true"])')
243
+ ).filter((el) => el.style.display !== 'none');
244
+ }, [listRef]);
245
+
246
+ const handleKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {
247
+ htmlProps.onKeyDown?.(event);
248
+ if (event.defaultPrevented) return;
249
+
250
+ const items = getEnabledItems();
251
+ if (items.length === 0) return;
252
+
253
+ const currentIndex = activeId
254
+ ? items.findIndex((item) => item.id === activeId)
255
+ : -1;
256
+
257
+ switch (event.key) {
258
+ case 'ArrowDown': {
259
+ event.preventDefault();
260
+ if (currentIndex < 0) {
261
+ setActiveId(items[0].id);
262
+ } else if (currentIndex < items.length - 1) {
263
+ setActiveId(items[currentIndex + 1].id);
264
+ } else if (loop) {
265
+ setActiveId(items[0].id);
266
+ }
267
+ break;
268
+ }
269
+ case 'ArrowUp': {
270
+ event.preventDefault();
271
+ if (currentIndex < 0) {
272
+ setActiveId(items[items.length - 1].id);
273
+ } else if (currentIndex > 0) {
274
+ setActiveId(items[currentIndex - 1].id);
275
+ } else if (loop) {
276
+ setActiveId(items[items.length - 1].id);
277
+ }
278
+ break;
279
+ }
280
+ case 'Home': {
281
+ event.preventDefault();
282
+ setActiveId(items[0].id);
283
+ break;
284
+ }
285
+ case 'End': {
286
+ event.preventDefault();
287
+ setActiveId(items[items.length - 1].id);
288
+ break;
289
+ }
290
+ case 'Enter': {
291
+ event.preventDefault();
292
+ if (activeId) {
293
+ const activeItem = items.find((item) => item.id === activeId);
294
+ if (activeItem) {
295
+ activeItem.click();
296
+ }
297
+ }
298
+ break;
299
+ }
300
+ }
301
+ };
302
+
303
+ return (
304
+ <div className={styles.inputWrapper}>
305
+ <SearchIcon />
306
+ <input
307
+ ref={inputRef}
308
+ type="text"
309
+ role="combobox"
310
+ aria-expanded={true}
311
+ aria-controls="command-list"
312
+ aria-autocomplete="list"
313
+ aria-activedescendant={activeId ?? undefined}
314
+ autoComplete="off"
315
+ autoCorrect="off"
316
+ spellCheck={false}
317
+ value={search}
318
+ onChange={(e) => setSearch(e.target.value)}
319
+ onKeyDown={handleKeyDown}
320
+ className={[styles.input, className].filter(Boolean).join(' ')}
321
+ {...htmlProps}
322
+ />
323
+ </div>
324
+ );
325
+ }
326
+
327
+ function CommandList({ children, className, ...htmlProps }: CommandListProps) {
328
+ const { listRef } = useCommandContext();
329
+
330
+ return (
331
+ <div
332
+ ref={listRef}
333
+ id="command-list"
334
+ role="listbox"
335
+ className={[styles.list, className].filter(Boolean).join(' ')}
336
+ {...htmlProps}
337
+ >
338
+ {children}
339
+ </div>
340
+ );
341
+ }
342
+
343
+ function CommandItem({
344
+ children,
345
+ value: valueProp,
346
+ keywords,
347
+ disabled = false,
348
+ onItemSelect,
349
+ className,
350
+ ...htmlProps
351
+ }: CommandItemProps) {
352
+ const { scores, registerItem, unregisterItem, activeId, setActiveId } = useCommandContext();
353
+ const generatedId = React.useId();
354
+ const itemId = (htmlProps.id as string | undefined) ?? `command-item-${generatedId}`;
355
+ const itemRef = React.useRef<HTMLDivElement>(null);
356
+
357
+ // Extract text content for filtering if no value prop
358
+ const textValue = React.useMemo(() => {
359
+ if (valueProp) return valueProp;
360
+ if (typeof children === 'string') return children;
361
+ return '';
362
+ }, [valueProp, children]);
363
+
364
+ // Register with context
365
+ React.useEffect(() => {
366
+ registerItem(itemId, { value: textValue, keywords });
367
+ return () => unregisterItem(itemId);
368
+ }, [itemId, textValue, keywords, registerItem, unregisterItem]);
369
+
370
+ const score = scores.get(itemId) ?? 1;
371
+ const isVisible = score > 0;
372
+ const isActive = activeId === itemId;
373
+
374
+ // Scroll active item into view
375
+ React.useEffect(() => {
376
+ if (isActive && itemRef.current) {
377
+ itemRef.current.scrollIntoView({ block: 'nearest' });
378
+ }
379
+ }, [isActive]);
380
+
381
+ const handleClick = () => {
382
+ if (disabled) return;
383
+ onItemSelect?.();
384
+ };
385
+
386
+ const handleMouseEnter = () => {
387
+ if (!disabled) {
388
+ setActiveId(itemId);
389
+ }
390
+ };
391
+
392
+ return (
393
+ <div
394
+ ref={itemRef}
395
+ {...htmlProps}
396
+ id={itemId}
397
+ role="option"
398
+ aria-selected={isActive}
399
+ aria-disabled={disabled}
400
+ data-command-item=""
401
+ data-active={isActive || undefined}
402
+ data-disabled={disabled || undefined}
403
+ onClick={handleClick}
404
+ onMouseEnter={handleMouseEnter}
405
+ className={[
406
+ styles.item,
407
+ isActive && styles.itemActive,
408
+ disabled && styles.itemDisabled,
409
+ className,
410
+ ]
411
+ .filter(Boolean)
412
+ .join(' ')}
413
+ style={{ display: isVisible ? undefined : 'none' }}
414
+ >
415
+ {children}
416
+ </div>
417
+ );
418
+ }
419
+
420
+ function CommandGroup({ children, heading, className, ...htmlProps }: CommandGroupProps) {
421
+ const labelId = React.useId();
422
+ const groupRef = React.useRef<HTMLDivElement>(null);
423
+ const { scores } = useCommandContext();
424
+ const [hasVisibleChildren, setHasVisibleChildren] = React.useState(true);
425
+
426
+ // Check if any children are visible after each score update
427
+ React.useEffect(() => {
428
+ if (!groupRef.current) return;
429
+ const items = groupRef.current.querySelectorAll<HTMLElement>('[data-command-item]');
430
+ const anyVisible = Array.from(items).some((item) => item.style.display !== 'none');
431
+ setHasVisibleChildren(anyVisible);
432
+ }, [scores]);
433
+
434
+ return (
435
+ <div
436
+ ref={groupRef}
437
+ {...htmlProps}
438
+ role="group"
439
+ aria-labelledby={heading ? labelId : undefined}
440
+ className={[styles.group, className].filter(Boolean).join(' ')}
441
+ style={{ display: hasVisibleChildren ? undefined : 'none' }}
442
+ >
443
+ {heading && (
444
+ <div id={labelId} className={styles.groupHeading}>
445
+ {heading}
446
+ </div>
447
+ )}
448
+ {children}
449
+ </div>
450
+ );
451
+ }
452
+
453
+ function CommandEmpty({ children, className, ...htmlProps }: CommandEmptyProps) {
454
+ const { visibleCount } = useCommandContext();
455
+
456
+ if (visibleCount > 0) return null;
457
+
458
+ return (
459
+ <div
460
+ {...htmlProps}
461
+ role="option"
462
+ aria-disabled="true"
463
+ aria-selected="false"
464
+ className={[styles.empty, className].filter(Boolean).join(' ')}
465
+ >
466
+ {children}
467
+ </div>
468
+ );
469
+ }
470
+
471
+ function CommandSeparator({ className, ...htmlProps }: CommandSeparatorProps) {
472
+ return (
473
+ <div
474
+ {...htmlProps}
475
+ role="separator"
476
+ className={[styles.separator, className].filter(Boolean).join(' ')}
477
+ />
478
+ );
479
+ }
480
+
481
+ // ============================================
482
+ // Export compound component
483
+ // ============================================
484
+
485
+ export const Command = Object.assign(CommandRoot, {
486
+ Input: CommandInput,
487
+ List: CommandList,
488
+ Item: CommandItem,
489
+ Group: CommandGroup,
490
+ Empty: CommandEmpty,
491
+ Separator: CommandSeparator,
492
+ });
493
+
494
+ export {
495
+ CommandRoot,
496
+ CommandInput,
497
+ CommandList,
498
+ CommandItem,
499
+ CommandGroup,
500
+ CommandEmpty,
501
+ CommandSeparator,
502
+ };
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { defineFragment } from '@fragments/core';
2
+ import { defineFragment } from '@fragments-sdk/cli/core';
3
3
  import { ConversationList } from '.';
4
4
  import { Message } from '../Message';
5
5
 
@@ -1,5 +1,5 @@
1
1
  import React, { useState } from 'react';
2
- import { defineFragment } from '@fragments/core';
2
+ import { defineFragment } from '@fragments-sdk/cli/core';
3
3
  import { DatePicker } from '.';
4
4
  import type { DateRange } from '.';
5
5
  import { subDays } from 'date-fns';
@@ -87,17 +87,18 @@ export default defineFragment({
87
87
  required: true,
88
88
  },
89
89
  mode: {
90
- type: "'single' | 'range'",
90
+ type: 'enum',
91
+ values: ['single', 'range'],
91
92
  description: 'Selection mode',
92
93
  default: "'single'",
93
94
  },
94
95
  selected: {
95
- type: 'Date | null',
96
- description: 'Controlled date (single mode)',
96
+ type: 'custom',
97
+ description: 'Controlled date (single mode). Type: Date | null',
97
98
  },
98
99
  selectedRange: {
99
- type: 'DateRange | null',
100
- description: 'Controlled range (range mode)',
100
+ type: 'custom',
101
+ description: 'Controlled range (range mode). Type: DateRange | null',
101
102
  },
102
103
  onSelect: {
103
104
  type: 'function',
@@ -118,8 +119,8 @@ export default defineFragment({
118
119
  default: 'false',
119
120
  },
120
121
  disabledDates: {
121
- type: 'Matcher | Matcher[]',
122
- description: 'Dates to disable (react-day-picker Matcher)',
122
+ type: 'custom',
123
+ description: 'Dates to disable (react-day-picker Matcher | Matcher[])',
123
124
  },
124
125
  placeholder: {
125
126
  type: 'string',
@@ -130,7 +131,7 @@ export default defineFragment({
130
131
  relations: [
131
132
  { component: 'Select', relationship: 'alternative', note: 'Use Select for choosing from a list of options' },
132
133
  { component: 'Input', relationship: 'sibling', note: 'Use Input for free-form text date entry' },
133
- { component: 'Popover', relationship: 'uses', note: 'DatePicker uses Popover for the calendar dropdown' },
134
+ { component: 'Popover', relationship: 'composition', note: 'DatePicker uses Popover for the calendar dropdown' },
134
135
  ],
135
136
 
136
137
  contract: {
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { defineFragment } from '@fragments/core';
2
+ import { defineFragment } from '@fragments-sdk/cli/core';
3
3
  import { Dialog } from '.';
4
4
  import { Button } from '../Button';
5
5