@refraction-ui/react 0.18.4 → 0.19.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.
Files changed (86) hide show
  1. package/dist/index.cjs +3416 -2768
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.js +3382 -2735
  4. package/dist/index.js.map +1 -1
  5. package/dist/internal/analytics/index.d.cts +6 -0
  6. package/dist/internal/analytics/index.d.ts +6 -0
  7. package/dist/internal/calendar/index.d.cts +5 -3
  8. package/dist/internal/calendar/index.d.ts +5 -3
  9. package/dist/internal/call-controls/index.d.ts +1 -3
  10. package/dist/internal/conversation/index.d.cts +2 -0
  11. package/dist/internal/conversation/index.d.ts +2 -0
  12. package/dist/internal/date-picker/index.d.cts +2 -0
  13. package/dist/internal/date-picker/index.d.ts +2 -0
  14. package/dist/internal/device-frame/index.d.cts +1 -3
  15. package/dist/internal/device-frame/index.d.ts +1 -3
  16. package/dist/internal/emoji-picker/index.d.cts +1 -3
  17. package/dist/internal/emoji-picker/index.d.ts +1 -3
  18. package/dist/internal/file-tree/index.d.cts +125 -0
  19. package/dist/internal/file-tree/index.d.ts +125 -0
  20. package/dist/internal/footer/index.d.cts +2 -0
  21. package/dist/internal/footer/index.d.ts +2 -0
  22. package/dist/internal/logger/index.d.cts +4 -0
  23. package/dist/internal/logger/index.d.ts +4 -0
  24. package/dist/internal/presence-indicator/index.d.cts +1 -3
  25. package/dist/internal/presence-indicator/index.d.ts +1 -3
  26. package/dist/internal/react-app-shell/index.d.cts +7 -51
  27. package/dist/internal/react-app-shell/index.d.ts +7 -51
  28. package/dist/internal/react-avatar-group/index.d.cts +1 -21
  29. package/dist/internal/react-avatar-group/index.d.ts +1 -21
  30. package/dist/internal/react-calendar/index.d.cts +2 -27
  31. package/dist/internal/react-calendar/index.d.ts +2 -27
  32. package/dist/internal/react-charts/index.d.cts +20 -10
  33. package/dist/internal/react-charts/index.d.ts +20 -10
  34. package/dist/internal/react-command/index.d.cts +1 -1
  35. package/dist/internal/react-command/index.d.ts +1 -1
  36. package/dist/internal/react-conversation/index.d.cts +2 -6
  37. package/dist/internal/react-conversation/index.d.ts +2 -6
  38. package/dist/internal/react-cookie-consent/index.d.cts +1 -6
  39. package/dist/internal/react-cookie-consent/index.d.ts +1 -6
  40. package/dist/internal/react-device-frame/index.d.cts +1 -25
  41. package/dist/internal/react-device-frame/index.d.ts +1 -25
  42. package/dist/internal/react-dropdown-menu/index.d.cts +1 -1
  43. package/dist/internal/react-dropdown-menu/index.d.ts +1 -1
  44. package/dist/internal/react-emoji-picker/index.d.cts +1 -5
  45. package/dist/internal/react-emoji-picker/index.d.ts +1 -5
  46. package/dist/internal/react-file-tree/index.d.cts +30 -3
  47. package/dist/internal/react-file-tree/index.d.ts +30 -3
  48. package/dist/internal/react-file-upload/index.d.cts +1 -6
  49. package/dist/internal/react-file-upload/index.d.ts +1 -6
  50. package/dist/internal/react-inline-editor/index.d.cts +1 -6
  51. package/dist/internal/react-inline-editor/index.d.ts +1 -6
  52. package/dist/internal/react-keyboard-shortcut/index.d.cts +1 -1
  53. package/dist/internal/react-keyboard-shortcut/index.d.ts +1 -1
  54. package/dist/internal/react-language-selector/index.d.cts +2 -13
  55. package/dist/internal/react-language-selector/index.d.ts +2 -13
  56. package/dist/internal/react-location-selector/index.d.cts +1 -3
  57. package/dist/internal/react-location-selector/index.d.ts +1 -3
  58. package/dist/internal/react-pagination/index.d.ts +22 -1
  59. package/dist/internal/react-presence-indicator/index.d.cts +1 -21
  60. package/dist/internal/react-presence-indicator/index.d.ts +1 -21
  61. package/dist/internal/react-radio/index.d.ts +2 -17
  62. package/dist/internal/react-reaction-bar/index.d.cts +1 -21
  63. package/dist/internal/react-reaction-bar/index.d.ts +1 -21
  64. package/dist/internal/react-search-bar/index.d.cts +1 -12
  65. package/dist/internal/react-search-bar/index.d.ts +1 -12
  66. package/dist/internal/react-slider/index.d.cts +22 -1
  67. package/dist/internal/react-slider/index.d.ts +22 -1
  68. package/dist/internal/react-status-indicator/index.d.cts +1 -5
  69. package/dist/internal/react-status-indicator/index.d.ts +1 -5
  70. package/dist/internal/react-tabs/index.d.cts +2 -8
  71. package/dist/internal/react-tabs/index.d.ts +2 -8
  72. package/dist/internal/react-thread-view/index.d.cts +1 -21
  73. package/dist/internal/react-thread-view/index.d.ts +1 -21
  74. package/dist/internal/react-version-selector/index.d.cts +2 -12
  75. package/dist/internal/react-version-selector/index.d.ts +2 -12
  76. package/dist/internal/reaction-bar/index.d.cts +1 -3
  77. package/dist/internal/reaction-bar/index.d.ts +1 -3
  78. package/dist/internal/status-indicator/index.d.cts +1 -3
  79. package/dist/internal/status-indicator/index.d.ts +1 -3
  80. package/dist/internal/thread-view/index.d.cts +3 -5
  81. package/dist/internal/thread-view/index.d.ts +3 -5
  82. package/dist/internal/toast/index.d.cts +7 -1
  83. package/dist/internal/toast/index.d.ts +7 -1
  84. package/dist/internal/voice-pill/index.d.cts +2 -2
  85. package/dist/internal/voice-pill/index.d.ts +2 -2
  86. package/package.json +1 -1
@@ -166,6 +166,8 @@ interface HttpSinkOptions {
166
166
  maxBatchBytes?: number;
167
167
  /** Soft per-event byte cap (Segment ≈ 32KB). Default 32_000. */
168
168
  maxEventBytes?: number;
169
+ /** Clock for the batch `sentAt` stamp. Default: ambient `new Date()` — inject for deterministic tests. */
170
+ now?: () => Date;
169
171
  }
170
172
  /** `createAnalytics` configuration. */
171
173
  interface AnalyticsConfig {
@@ -200,6 +202,10 @@ interface AnalyticsConfig {
200
202
  batchSize?: number;
201
203
  /** Auto-flush interval in ms (prod). Default 10_000. */
202
204
  flushIntervalMs?: number;
205
+ /** Clock for default event timestamps. Default: ambient `new Date()` — inject for deterministic tests/SSR. */
206
+ now?: () => Date;
207
+ /** RNG for sample-rate decisions. Default: ambient `Math.random` — inject for deterministic tests. */
208
+ random?: () => number;
203
209
  }
204
210
  /** Options accepted by every top-level call. */
205
211
  interface CallOptions {
@@ -166,6 +166,8 @@ interface HttpSinkOptions {
166
166
  maxBatchBytes?: number;
167
167
  /** Soft per-event byte cap (Segment ≈ 32KB). Default 32_000. */
168
168
  maxEventBytes?: number;
169
+ /** Clock for the batch `sentAt` stamp. Default: ambient `new Date()` — inject for deterministic tests. */
170
+ now?: () => Date;
169
171
  }
170
172
  /** `createAnalytics` configuration. */
171
173
  interface AnalyticsConfig {
@@ -200,6 +202,10 @@ interface AnalyticsConfig {
200
202
  batchSize?: number;
201
203
  /** Auto-flush interval in ms (prod). Default 10_000. */
202
204
  flushIntervalMs?: number;
205
+ /** Clock for default event timestamps. Default: ambient `new Date()` — inject for deterministic tests/SSR. */
206
+ now?: () => Date;
207
+ /** RNG for sample-rate decisions. Default: ambient `Math.random` — inject for deterministic tests. */
208
+ random?: () => number;
203
209
  }
204
210
  /** Options accepted by every top-level call. */
205
211
  interface CallOptions {
@@ -17,6 +17,8 @@ interface CalendarProps {
17
17
  maxDate?: Date;
18
18
  /** Specific dates to disable */
19
19
  disabledDates?: Date[];
20
+ /** Reference "today" for isToday/aria-current. Default: ambient `new Date()` — inject to avoid SSR/CSR hydration mismatch. */
21
+ today?: Date;
20
22
  }
21
23
  interface CalendarDay {
22
24
  /** The date this cell represents */
@@ -48,9 +50,9 @@ interface CalendarAPI {
48
50
  /** Select a date */
49
51
  select(date: Date): void;
50
52
  /** ARIA attributes for the calendar grid */
51
- ariaProps: Partial<AccessibilityProps> & Record<string, unknown>;
53
+ ariaProps: Partial<AccessibilityProps> & Record<string, string | number | boolean>;
52
54
  /** Get ARIA attributes for a specific day cell */
53
- getDayAriaProps(day: CalendarDay): Partial<AccessibilityProps> & Record<string, unknown>;
55
+ getDayAriaProps(day: CalendarDay): Partial<AccessibilityProps> & Record<string, string | number | boolean>;
54
56
  /** Generated IDs */
55
57
  ids: {
56
58
  grid: string;
@@ -65,7 +67,7 @@ declare const calendarVariants: (props?: ({
65
67
  className?: string;
66
68
  }) | undefined) => string;
67
69
  declare const dayVariants: (props?: ({
68
- state?: "default" | "selected" | "today" | "disabled" | "outside" | undefined;
70
+ state?: "today" | "default" | "selected" | "disabled" | "outside" | undefined;
69
71
  } & {
70
72
  className?: string;
71
73
  }) | undefined) => string;
@@ -17,6 +17,8 @@ interface CalendarProps {
17
17
  maxDate?: Date;
18
18
  /** Specific dates to disable */
19
19
  disabledDates?: Date[];
20
+ /** Reference "today" for isToday/aria-current. Default: ambient `new Date()` — inject to avoid SSR/CSR hydration mismatch. */
21
+ today?: Date;
20
22
  }
21
23
  interface CalendarDay {
22
24
  /** The date this cell represents */
@@ -48,9 +50,9 @@ interface CalendarAPI {
48
50
  /** Select a date */
49
51
  select(date: Date): void;
50
52
  /** ARIA attributes for the calendar grid */
51
- ariaProps: Partial<AccessibilityProps> & Record<string, unknown>;
53
+ ariaProps: Partial<AccessibilityProps> & Record<string, string | number | boolean>;
52
54
  /** Get ARIA attributes for a specific day cell */
53
- getDayAriaProps(day: CalendarDay): Partial<AccessibilityProps> & Record<string, unknown>;
55
+ getDayAriaProps(day: CalendarDay): Partial<AccessibilityProps> & Record<string, string | number | boolean>;
54
56
  /** Generated IDs */
55
57
  ids: {
56
58
  grid: string;
@@ -65,7 +67,7 @@ declare const calendarVariants: (props?: ({
65
67
  className?: string;
66
68
  }) | undefined) => string;
67
69
  declare const dayVariants: (props?: ({
68
- state?: "default" | "selected" | "today" | "disabled" | "outside" | undefined;
70
+ state?: "today" | "default" | "selected" | "disabled" | "outside" | undefined;
69
71
  } & {
70
72
  className?: string;
71
73
  }) | undefined) => string;
@@ -1,5 +1,3 @@
1
- import { AccessibilityProps } from '../shared/index.js';
2
-
3
1
  /** Visual/semantic tone of a call control button. */
4
2
  type CallControlTone = 'default' | 'active' | 'destructive';
5
3
  /**
@@ -29,7 +27,7 @@ interface CallControlsProps {
29
27
  }
30
28
  interface CallControlsAPI {
31
29
  /** ARIA attributes to spread on the toolbar element (`role="toolbar"`). */
32
- ariaProps: Partial<AccessibilityProps>;
30
+ ariaProps: Record<string, string | number | boolean>;
33
31
  /** Data attributes for styling hooks. */
34
32
  dataAttributes: Record<string, string>;
35
33
  }
@@ -157,6 +157,8 @@ interface ConversationConfig {
157
157
  generateTitle?: (firstMessage: string) => string;
158
158
  /** Threading mode (default 'inline') */
159
159
  threadingMode?: ThreadingMode;
160
+ /** Clock for conversation/message timestamps. Default: ambient `new Date()` — inject for deterministic SSR/tests. */
161
+ now?: () => Date;
160
162
  }
161
163
  /** Options for a single `sendMessage`. */
162
164
  interface SendOptions {
@@ -157,6 +157,8 @@ interface ConversationConfig {
157
157
  generateTitle?: (firstMessage: string) => string;
158
158
  /** Threading mode (default 'inline') */
159
159
  threadingMode?: ThreadingMode;
160
+ /** Clock for conversation/message timestamps. Default: ambient `new Date()` — inject for deterministic SSR/tests. */
161
+ now?: () => Date;
160
162
  }
161
163
  /** Options for a single `sendMessage`. */
162
164
  interface SendOptions {
@@ -24,6 +24,8 @@ interface DatePickerProps {
24
24
  onOpenChange?: (open: boolean) => void;
25
25
  /** The currently displayed month (controlled) */
26
26
  currentMonth?: Date;
27
+ /** Reference "today" for isToday/aria-current and time defaults. Default: ambient `new Date()` — inject to avoid SSR/CSR hydration mismatch. */
28
+ today?: Date;
27
29
  }
28
30
  interface DatePickerState {
29
31
  open: boolean;
@@ -24,6 +24,8 @@ interface DatePickerProps {
24
24
  onOpenChange?: (open: boolean) => void;
25
25
  /** The currently displayed month (controlled) */
26
26
  currentMonth?: Date;
27
+ /** Reference "today" for isToday/aria-current and time defaults. Default: ambient `new Date()` — inject to avoid SSR/CSR hydration mismatch. */
28
+ today?: Date;
27
29
  }
28
30
  interface DatePickerState {
29
31
  open: boolean;
@@ -1,5 +1,3 @@
1
- import { AccessibilityProps } from '../shared/index.cjs';
2
-
3
1
  type DeviceType = 'iphone' | 'ipad' | 'android-phone' | 'android-tablet';
4
2
  type DeviceOrientation = 'portrait' | 'landscape';
5
3
  interface DeviceFrameProps {
@@ -24,7 +22,7 @@ interface DeviceFrameAPI {
24
22
  /** Computed dimensions for the device */
25
23
  dimensions: DeviceDimensions;
26
24
  /** ARIA attributes for the device frame */
27
- ariaProps: Partial<AccessibilityProps> & Record<string, unknown>;
25
+ ariaProps: Record<string, string | number | boolean>;
28
26
  /** Data attributes for styling hooks */
29
27
  dataAttributes: Record<string, string>;
30
28
  }
@@ -1,5 +1,3 @@
1
- import { AccessibilityProps } from '../shared/index.js';
2
-
3
1
  type DeviceType = 'iphone' | 'ipad' | 'android-phone' | 'android-tablet';
4
2
  type DeviceOrientation = 'portrait' | 'landscape';
5
3
  interface DeviceFrameProps {
@@ -24,7 +22,7 @@ interface DeviceFrameAPI {
24
22
  /** Computed dimensions for the device */
25
23
  dimensions: DeviceDimensions;
26
24
  /** ARIA attributes for the device frame */
27
- ariaProps: Partial<AccessibilityProps> & Record<string, unknown>;
25
+ ariaProps: Record<string, string | number | boolean>;
28
26
  /** Data attributes for styling hooks */
29
27
  dataAttributes: Record<string, string>;
30
28
  }
@@ -1,5 +1,3 @@
1
- import { AccessibilityProps } from '../shared/index.cjs';
2
-
3
1
  type EmojiCategory = 'smileys' | 'people' | 'nature' | 'food' | 'travel' | 'activities' | 'objects' | 'symbols' | 'flags';
4
2
  interface EmojiEntry {
5
3
  /** The rendered glyph (native codepoints). */
@@ -77,7 +75,7 @@ interface EmojiPickerAPI {
77
75
  emoji: string;
78
76
  }[];
79
77
  /** ARIA props for the picker container */
80
- ariaProps: Partial<AccessibilityProps> & Record<string, unknown>;
78
+ ariaProps: Record<string, string | number | boolean>;
81
79
  /** ARIA props for the search input */
82
80
  searchInputProps: Record<string, unknown>;
83
81
  /** Get ARIA props for an emoji button */
@@ -1,5 +1,3 @@
1
- import { AccessibilityProps } from '../shared/index.js';
2
-
3
1
  type EmojiCategory = 'smileys' | 'people' | 'nature' | 'food' | 'travel' | 'activities' | 'objects' | 'symbols' | 'flags';
4
2
  interface EmojiEntry {
5
3
  /** The rendered glyph (native codepoints). */
@@ -77,7 +75,7 @@ interface EmojiPickerAPI {
77
75
  emoji: string;
78
76
  }[];
79
77
  /** ARIA props for the picker container */
80
- ariaProps: Partial<AccessibilityProps> & Record<string, unknown>;
78
+ ariaProps: Record<string, string | number | boolean>;
81
79
  /** ARIA props for the search input */
82
80
  searchInputProps: Record<string, unknown>;
83
81
  /** Get ARIA props for an emoji button */
@@ -0,0 +1,125 @@
1
+ /**
2
+ * @refraction-ui/file-tree — headless tree view.
3
+ *
4
+ * Owns the *behavior* of a hierarchical tree: the node model, expand/collapse
5
+ * state, single selection, roving focus, and WAI-ARIA treeview keyboard
6
+ * semantics. It has NO UI opinion — adapters render the nested markup and
7
+ * spread the ARIA objects.
8
+ */
9
+ /** A node in the tree. Parents carry `children`; leaves do not. */
10
+ interface FileTreeNode {
11
+ /** Unique, stable id (used for expansion/selection/focus). */
12
+ id: string;
13
+ /** Display label. */
14
+ label: string;
15
+ /** Child nodes — presence (even empty is not allowed: omit for leaves) marks a parent. */
16
+ children?: FileTreeNode[];
17
+ /** Disabled nodes cannot be selected, toggled, or focused via click. */
18
+ disabled?: boolean;
19
+ }
20
+ /** Options for {@link createFileTree}. */
21
+ interface FileTreeConfig {
22
+ /** Root-level nodes. */
23
+ nodes?: FileTreeNode[];
24
+ /** Controlled expanded node ids. Pair with `onExpandedChange`. */
25
+ expandedIds?: string[];
26
+ /** Uncontrolled initial expanded node ids. */
27
+ defaultExpandedIds?: string[];
28
+ /** Controlled selected node id (`null` = none). Pair with `onSelectionChange`. */
29
+ selectedId?: string | null;
30
+ /** Uncontrolled initial selected node id. */
31
+ defaultSelectedId?: string | null;
32
+ /** Called whenever the expanded set changes. */
33
+ onExpandedChange?: (ids: string[]) => void;
34
+ /** Called whenever the selection changes. */
35
+ onSelectionChange?: (id: string | null) => void;
36
+ /** Accessible label for the tree (default `'File tree'`). */
37
+ 'aria-label'?: string;
38
+ }
39
+ /** Snapshot of the store. Returned by `getState()`; treat as immutable. */
40
+ interface FileTreeState {
41
+ nodes: FileTreeNode[];
42
+ expandedIds: string[];
43
+ selectedId: string | null;
44
+ /** Node holding the roving-tabindex focus (null = the first visible item). */
45
+ focusedId: string | null;
46
+ }
47
+ /** A row of the flattened, currently-visible tree (DFS order). */
48
+ interface VisibleTreeItem {
49
+ node: FileTreeNode;
50
+ /** Id of the parent node, or null for root-level items. */
51
+ parentId: string | null;
52
+ /** 1-based nesting depth (ARIA `aria-level`). */
53
+ depth: number;
54
+ hasChildren: boolean;
55
+ isExpanded: boolean;
56
+ isSelected: boolean;
57
+ isFocused: boolean;
58
+ }
59
+ /** The framework-agnostic store. React/Astro adapters wrap this. */
60
+ interface FileTreeAPI {
61
+ /** Current immutable snapshot */
62
+ getState(): FileTreeState;
63
+ /** Subscribe to changes; returns an unsubscribe fn (suits useSyncExternalStore) */
64
+ subscribe(listener: () => void): () => void;
65
+ /** Flattened visible rows in DFS order (children of collapsed parents omitted) */
66
+ getVisibleItems(): VisibleTreeItem[];
67
+ isExpanded(id: string): boolean;
68
+ /** Toggle a parent's expanded state (no-op for leaves/disabled nodes) */
69
+ toggle(id: string): void;
70
+ expand(id: string): void;
71
+ collapse(id: string): void;
72
+ /** Select a node (`null` clears). No-op for unknown/disabled nodes. */
73
+ select(id: string | null): void;
74
+ /** Move the roving focus to a node */
75
+ focus(id: string | null): void;
76
+ /**
77
+ * WAI-ARIA treeview keyboard semantics, applied to the focused item:
78
+ * ArrowDown/Up move, ArrowRight expands or descends, ArrowLeft collapses or
79
+ * ascends, Home/End jump, Enter/Space selects.
80
+ */
81
+ handleKey(key: string): void;
82
+ /** Replace the node model (adapters sync the prop) */
83
+ setNodes(nodes: FileTreeNode[]): void;
84
+ /** Sync a controlled expanded set */
85
+ setExpandedIds(ids: string[]): void;
86
+ /** Sync a controlled selection */
87
+ setSelectedId(id: string | null): void;
88
+ /** Update callbacks/options after creation */
89
+ setOptions(options: {
90
+ onExpandedChange?: (ids: string[]) => void;
91
+ onSelectionChange?: (id: string | null) => void;
92
+ 'aria-label'?: string;
93
+ }): void;
94
+ /** ARIA attributes for the tree container (`role="tree"`). */
95
+ getTreeAria(): Record<string, string | number | boolean>;
96
+ /** ARIA attributes for one visible row (`role="treeitem"`). */
97
+ getItemAria(item: VisibleTreeItem): Record<string, string | number | boolean>;
98
+ }
99
+ /**
100
+ * createFileTree — headless tree store with expand/collapse, single
101
+ * selection, roving focus, and treeview keyboard semantics. Supports
102
+ * controlled (`expandedIds` / `selectedId`) and uncontrolled
103
+ * (`defaultExpandedIds` / `defaultSelectedId`) usage.
104
+ */
105
+ declare function createFileTree(config?: FileTreeConfig): FileTreeAPI;
106
+
107
+ /** Tree container. */
108
+ declare const fileTreeVariants: (props?: ({
109
+ [x: string]: string | undefined;
110
+ } & {
111
+ className?: string;
112
+ }) | undefined) => string;
113
+ /**
114
+ * A single tree row (treeitem). The `selected` variant carries the
115
+ * selected-row treatment so adapters never inline these classes.
116
+ */
117
+ declare const fileTreeItemVariants: (props?: ({
118
+ selected?: "true" | "false" | undefined;
119
+ } & {
120
+ className?: string;
121
+ }) | undefined) => string;
122
+ /** Expand/collapse glyph or file marker preceding the label. */
123
+ declare const fileTreeGlyphClass = "w-4 shrink-0 text-center text-muted-foreground";
124
+
125
+ export { type FileTreeAPI, type FileTreeConfig, type FileTreeNode, type FileTreeState, type VisibleTreeItem, createFileTree, fileTreeGlyphClass, fileTreeItemVariants, fileTreeVariants };
@@ -0,0 +1,125 @@
1
+ /**
2
+ * @refraction-ui/file-tree — headless tree view.
3
+ *
4
+ * Owns the *behavior* of a hierarchical tree: the node model, expand/collapse
5
+ * state, single selection, roving focus, and WAI-ARIA treeview keyboard
6
+ * semantics. It has NO UI opinion — adapters render the nested markup and
7
+ * spread the ARIA objects.
8
+ */
9
+ /** A node in the tree. Parents carry `children`; leaves do not. */
10
+ interface FileTreeNode {
11
+ /** Unique, stable id (used for expansion/selection/focus). */
12
+ id: string;
13
+ /** Display label. */
14
+ label: string;
15
+ /** Child nodes — presence (even empty is not allowed: omit for leaves) marks a parent. */
16
+ children?: FileTreeNode[];
17
+ /** Disabled nodes cannot be selected, toggled, or focused via click. */
18
+ disabled?: boolean;
19
+ }
20
+ /** Options for {@link createFileTree}. */
21
+ interface FileTreeConfig {
22
+ /** Root-level nodes. */
23
+ nodes?: FileTreeNode[];
24
+ /** Controlled expanded node ids. Pair with `onExpandedChange`. */
25
+ expandedIds?: string[];
26
+ /** Uncontrolled initial expanded node ids. */
27
+ defaultExpandedIds?: string[];
28
+ /** Controlled selected node id (`null` = none). Pair with `onSelectionChange`. */
29
+ selectedId?: string | null;
30
+ /** Uncontrolled initial selected node id. */
31
+ defaultSelectedId?: string | null;
32
+ /** Called whenever the expanded set changes. */
33
+ onExpandedChange?: (ids: string[]) => void;
34
+ /** Called whenever the selection changes. */
35
+ onSelectionChange?: (id: string | null) => void;
36
+ /** Accessible label for the tree (default `'File tree'`). */
37
+ 'aria-label'?: string;
38
+ }
39
+ /** Snapshot of the store. Returned by `getState()`; treat as immutable. */
40
+ interface FileTreeState {
41
+ nodes: FileTreeNode[];
42
+ expandedIds: string[];
43
+ selectedId: string | null;
44
+ /** Node holding the roving-tabindex focus (null = the first visible item). */
45
+ focusedId: string | null;
46
+ }
47
+ /** A row of the flattened, currently-visible tree (DFS order). */
48
+ interface VisibleTreeItem {
49
+ node: FileTreeNode;
50
+ /** Id of the parent node, or null for root-level items. */
51
+ parentId: string | null;
52
+ /** 1-based nesting depth (ARIA `aria-level`). */
53
+ depth: number;
54
+ hasChildren: boolean;
55
+ isExpanded: boolean;
56
+ isSelected: boolean;
57
+ isFocused: boolean;
58
+ }
59
+ /** The framework-agnostic store. React/Astro adapters wrap this. */
60
+ interface FileTreeAPI {
61
+ /** Current immutable snapshot */
62
+ getState(): FileTreeState;
63
+ /** Subscribe to changes; returns an unsubscribe fn (suits useSyncExternalStore) */
64
+ subscribe(listener: () => void): () => void;
65
+ /** Flattened visible rows in DFS order (children of collapsed parents omitted) */
66
+ getVisibleItems(): VisibleTreeItem[];
67
+ isExpanded(id: string): boolean;
68
+ /** Toggle a parent's expanded state (no-op for leaves/disabled nodes) */
69
+ toggle(id: string): void;
70
+ expand(id: string): void;
71
+ collapse(id: string): void;
72
+ /** Select a node (`null` clears). No-op for unknown/disabled nodes. */
73
+ select(id: string | null): void;
74
+ /** Move the roving focus to a node */
75
+ focus(id: string | null): void;
76
+ /**
77
+ * WAI-ARIA treeview keyboard semantics, applied to the focused item:
78
+ * ArrowDown/Up move, ArrowRight expands or descends, ArrowLeft collapses or
79
+ * ascends, Home/End jump, Enter/Space selects.
80
+ */
81
+ handleKey(key: string): void;
82
+ /** Replace the node model (adapters sync the prop) */
83
+ setNodes(nodes: FileTreeNode[]): void;
84
+ /** Sync a controlled expanded set */
85
+ setExpandedIds(ids: string[]): void;
86
+ /** Sync a controlled selection */
87
+ setSelectedId(id: string | null): void;
88
+ /** Update callbacks/options after creation */
89
+ setOptions(options: {
90
+ onExpandedChange?: (ids: string[]) => void;
91
+ onSelectionChange?: (id: string | null) => void;
92
+ 'aria-label'?: string;
93
+ }): void;
94
+ /** ARIA attributes for the tree container (`role="tree"`). */
95
+ getTreeAria(): Record<string, string | number | boolean>;
96
+ /** ARIA attributes for one visible row (`role="treeitem"`). */
97
+ getItemAria(item: VisibleTreeItem): Record<string, string | number | boolean>;
98
+ }
99
+ /**
100
+ * createFileTree — headless tree store with expand/collapse, single
101
+ * selection, roving focus, and treeview keyboard semantics. Supports
102
+ * controlled (`expandedIds` / `selectedId`) and uncontrolled
103
+ * (`defaultExpandedIds` / `defaultSelectedId`) usage.
104
+ */
105
+ declare function createFileTree(config?: FileTreeConfig): FileTreeAPI;
106
+
107
+ /** Tree container. */
108
+ declare const fileTreeVariants: (props?: ({
109
+ [x: string]: string | undefined;
110
+ } & {
111
+ className?: string;
112
+ }) | undefined) => string;
113
+ /**
114
+ * A single tree row (treeitem). The `selected` variant carries the
115
+ * selected-row treatment so adapters never inline these classes.
116
+ */
117
+ declare const fileTreeItemVariants: (props?: ({
118
+ selected?: "true" | "false" | undefined;
119
+ } & {
120
+ className?: string;
121
+ }) | undefined) => string;
122
+ /** Expand/collapse glyph or file marker preceding the label. */
123
+ declare const fileTreeGlyphClass = "w-4 shrink-0 text-center text-muted-foreground";
124
+
125
+ export { type FileTreeAPI, type FileTreeConfig, type FileTreeNode, type FileTreeState, type VisibleTreeItem, createFileTree, fileTreeGlyphClass, fileTreeItemVariants, fileTreeVariants };
@@ -14,6 +14,8 @@ interface FooterProps {
14
14
  copyright?: string;
15
15
  socialLinks?: SocialLink[];
16
16
  columns?: FooterColumn[];
17
+ /** Year for the default copyrightText. Default: ambient current year — inject to avoid year-boundary SSR/CSR mismatch. */
18
+ year?: number;
17
19
  }
18
20
  interface FooterAPI {
19
21
  ariaProps: Record<string, string>;
@@ -14,6 +14,8 @@ interface FooterProps {
14
14
  copyright?: string;
15
15
  socialLinks?: SocialLink[];
16
16
  columns?: FooterColumn[];
17
+ /** Year for the default copyrightText. Default: ambient current year — inject to avoid year-boundary SSR/CSR mismatch. */
18
+ year?: number;
17
19
  }
18
20
  interface FooterAPI {
19
21
  ariaProps: Record<string, string>;
@@ -74,6 +74,10 @@ interface TelemetryConfig {
74
74
  * PII / secrets, e.g. `['password', 'token', 'authorization']`.
75
75
  */
76
76
  redactKeys?: string[];
77
+ /** Clock for record timestamps and span timing (ms epoch). Default: ambient `Date.now()` — inject for deterministic tests. */
78
+ now?: () => number;
79
+ /** RNG for sample-rate decisions. Default: ambient `Math.random` — inject for deterministic tests. */
80
+ random?: () => number;
77
81
  }
78
82
  /** A logger bound to a context. Child loggers inherit + extend that context. */
79
83
  interface Logger {
@@ -74,6 +74,10 @@ interface TelemetryConfig {
74
74
  * PII / secrets, e.g. `['password', 'token', 'authorization']`.
75
75
  */
76
76
  redactKeys?: string[];
77
+ /** Clock for record timestamps and span timing (ms epoch). Default: ambient `Date.now()` — inject for deterministic tests. */
78
+ now?: () => number;
79
+ /** RNG for sample-rate decisions. Default: ambient `Math.random` — inject for deterministic tests. */
80
+ random?: () => number;
77
81
  }
78
82
  /** A logger bound to a context. Child loggers inherit + extend that context. */
79
83
  interface Logger {
@@ -1,5 +1,3 @@
1
- import { AccessibilityProps } from '../shared/index.cjs';
2
-
3
1
  type PresenceStatus = 'online' | 'offline' | 'away' | 'busy' | 'dnd';
4
2
  interface PresenceProps {
5
3
  /** The presence status to display */
@@ -11,7 +9,7 @@ interface PresenceProps {
11
9
  }
12
10
  interface PresenceAPI {
13
11
  /** ARIA attributes for the indicator */
14
- ariaProps: Partial<AccessibilityProps> & Record<string, unknown>;
12
+ ariaProps: Record<string, string | number | boolean>;
15
13
  /** CSS color for the status dot */
16
14
  color: string;
17
15
  /** Human-readable label for the status */
@@ -1,5 +1,3 @@
1
- import { AccessibilityProps } from '../shared/index.js';
2
-
3
1
  type PresenceStatus = 'online' | 'offline' | 'away' | 'busy' | 'dnd';
4
2
  interface PresenceProps {
5
3
  /** The presence status to display */
@@ -11,7 +9,7 @@ interface PresenceProps {
11
9
  }
12
10
  interface PresenceAPI {
13
11
  /** ARIA attributes for the indicator */
14
- ariaProps: Partial<AccessibilityProps> & Record<string, unknown>;
12
+ ariaProps: Record<string, string | number | boolean>;
15
13
  /** CSS color for the status dot */
16
14
  color: string;
17
15
  /** Human-readable label for the status */
@@ -12,82 +12,38 @@ interface AppShellProps {
12
12
  children?: React.ReactNode;
13
13
  className?: string;
14
14
  }
15
- declare function AppShellRoot({ config, children, className }: AppShellProps): React.FunctionComponentElement<React.ProviderProps<AppShellContextValue | null>>;
16
- declare namespace AppShellRoot {
17
- var displayName: string;
18
- }
19
15
  interface AppShellSidebarProps {
20
16
  children?: React.ReactNode;
21
17
  className?: string;
22
18
  }
23
- declare function Sidebar({ children, className }: AppShellSidebarProps): React.DetailedReactHTMLElement<{
24
- className: string;
25
- 'data-collapsed': string | undefined;
26
- 'data-open': string | undefined;
27
- }, HTMLElement>;
28
- declare namespace Sidebar {
29
- var displayName: string;
30
- }
31
19
  interface AppShellMainProps {
32
20
  children?: React.ReactNode;
33
21
  className?: string;
34
22
  }
35
- declare function Main({ children, className }: AppShellMainProps): React.DetailedReactHTMLElement<{
36
- className: string;
37
- }, HTMLElement>;
38
- declare namespace Main {
39
- var displayName: string;
40
- }
41
23
  interface AppShellHeaderProps {
42
24
  children?: React.ReactNode;
43
25
  className?: string;
44
26
  }
45
- declare function Header({ children, className }: AppShellHeaderProps): React.DetailedReactHTMLElement<{
46
- className: string;
47
- }, HTMLElement>;
48
- declare namespace Header {
49
- var displayName: string;
50
- }
51
27
  interface AppShellContentProps {
52
28
  children?: React.ReactNode;
53
29
  className?: string;
54
30
  /** Tailwind max-width class suffix, e.g. '6xl' -> max-w-6xl */
55
31
  maxWidth?: string;
56
32
  }
57
- declare function Content({ children, className, maxWidth }: AppShellContentProps): React.DetailedReactHTMLElement<{
58
- className: string;
59
- }, HTMLElement>;
60
- declare namespace Content {
61
- var displayName: string;
62
- }
63
33
  interface AppShellMobileNavProps {
64
34
  children?: React.ReactNode;
65
35
  className?: string;
66
36
  }
67
- declare function MobileNav({ children, className }: AppShellMobileNavProps): React.DetailedReactHTMLElement<{
68
- className: string;
69
- }, HTMLElement> | null;
70
- declare namespace MobileNav {
71
- var displayName: string;
72
- }
73
37
  interface AppShellOverlayProps {
74
38
  className?: string;
75
39
  }
76
- declare function Overlay({ className }: AppShellOverlayProps): React.DetailedReactHTMLElement<{
77
- className: string;
78
- onClick: () => void;
79
- 'data-shell-overlay': string;
80
- }, HTMLElement> | null;
81
- declare namespace Overlay {
82
- var displayName: string;
83
- }
84
- declare const AppShell: typeof AppShellRoot & {
85
- Sidebar: typeof Sidebar;
86
- Main: typeof Main;
87
- Header: typeof Header;
88
- Content: typeof Content;
89
- MobileNav: typeof MobileNav;
90
- Overlay: typeof Overlay;
40
+ declare const AppShell: React.ForwardRefExoticComponent<AppShellProps & React.RefAttributes<HTMLDivElement>> & {
41
+ Sidebar: React.ForwardRefExoticComponent<AppShellSidebarProps & React.RefAttributes<HTMLElement>>;
42
+ Main: React.ForwardRefExoticComponent<AppShellMainProps & React.RefAttributes<HTMLDivElement>>;
43
+ Header: React.ForwardRefExoticComponent<AppShellHeaderProps & React.RefAttributes<HTMLElement>>;
44
+ Content: React.ForwardRefExoticComponent<AppShellContentProps & React.RefAttributes<HTMLElement>>;
45
+ MobileNav: React.ForwardRefExoticComponent<AppShellMobileNavProps & React.RefAttributes<HTMLElement>>;
46
+ Overlay: React.ForwardRefExoticComponent<AppShellOverlayProps & React.RefAttributes<HTMLDivElement>>;
91
47
  };
92
48
 
93
49
  interface PageShellContextValue {