@colletdev/react 0.1.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 (110) hide show
  1. package/README.md +67 -0
  2. package/dist/generated/accordion.d.ts +17 -0
  3. package/dist/generated/accordion.js +56 -0
  4. package/dist/generated/activity-group.d.ts +14 -0
  5. package/dist/generated/activity-group.js +26 -0
  6. package/dist/generated/alert.d.ts +22 -0
  7. package/dist/generated/alert.js +55 -0
  8. package/dist/generated/autocomplete.d.ts +46 -0
  9. package/dist/generated/autocomplete.js +144 -0
  10. package/dist/generated/avatar.d.ts +13 -0
  11. package/dist/generated/avatar.js +24 -0
  12. package/dist/generated/backdrop.d.ts +9 -0
  13. package/dist/generated/backdrop.js +16 -0
  14. package/dist/generated/badge.d.ts +17 -0
  15. package/dist/generated/badge.js +40 -0
  16. package/dist/generated/breadcrumb.d.ts +14 -0
  17. package/dist/generated/breadcrumb.js +41 -0
  18. package/dist/generated/button.d.ts +21 -0
  19. package/dist/generated/button.js +46 -0
  20. package/dist/generated/card.d.ts +20 -0
  21. package/dist/generated/card.js +54 -0
  22. package/dist/generated/carousel.d.ts +28 -0
  23. package/dist/generated/carousel.js +62 -0
  24. package/dist/generated/chat-input.d.ts +27 -0
  25. package/dist/generated/chat-input.js +92 -0
  26. package/dist/generated/checkbox.d.ts +28 -0
  27. package/dist/generated/checkbox.js +93 -0
  28. package/dist/generated/code-block.d.ts +17 -0
  29. package/dist/generated/code-block.js +32 -0
  30. package/dist/generated/collapsible.d.ts +26 -0
  31. package/dist/generated/collapsible.js +36 -0
  32. package/dist/generated/date-picker.d.ts +39 -0
  33. package/dist/generated/date-picker.js +124 -0
  34. package/dist/generated/dialog.d.ts +28 -0
  35. package/dist/generated/dialog.js +59 -0
  36. package/dist/generated/drawer.d.ts +28 -0
  37. package/dist/generated/drawer.js +59 -0
  38. package/dist/generated/fab.d.ts +19 -0
  39. package/dist/generated/fab.js +42 -0
  40. package/dist/generated/file-upload.d.ts +22 -0
  41. package/dist/generated/file-upload.js +59 -0
  42. package/dist/generated/index.d.ts +56 -0
  43. package/dist/generated/index.js +58 -0
  44. package/dist/generated/listbox.d.ts +19 -0
  45. package/dist/generated/listbox.js +93 -0
  46. package/dist/generated/menu.d.ts +26 -0
  47. package/dist/generated/menu.js +86 -0
  48. package/dist/generated/message-bubble.d.ts +18 -0
  49. package/dist/generated/message-bubble.js +41 -0
  50. package/dist/generated/message-group.d.ts +14 -0
  51. package/dist/generated/message-group.js +42 -0
  52. package/dist/generated/message-part.d.ts +20 -0
  53. package/dist/generated/message-part.js +36 -0
  54. package/dist/generated/pagination.d.ts +17 -0
  55. package/dist/generated/pagination.js +59 -0
  56. package/dist/generated/popover.d.ts +27 -0
  57. package/dist/generated/popover.js +65 -0
  58. package/dist/generated/profile-menu.d.ts +23 -0
  59. package/dist/generated/profile-menu.js +56 -0
  60. package/dist/generated/progress.d.ts +14 -0
  61. package/dist/generated/progress.js +33 -0
  62. package/dist/generated/radio-group.d.ts +24 -0
  63. package/dist/generated/radio-group.js +110 -0
  64. package/dist/generated/scrollbar.d.ts +14 -0
  65. package/dist/generated/scrollbar.js +33 -0
  66. package/dist/generated/search-bar.d.ts +33 -0
  67. package/dist/generated/search-bar.js +118 -0
  68. package/dist/generated/select.d.ts +36 -0
  69. package/dist/generated/select.js +136 -0
  70. package/dist/generated/serialize.d.ts +2 -0
  71. package/dist/generated/serialize.js +13 -0
  72. package/dist/generated/sidebar.d.ts +25 -0
  73. package/dist/generated/sidebar.js +55 -0
  74. package/dist/generated/skeleton.d.ts +12 -0
  75. package/dist/generated/skeleton.js +31 -0
  76. package/dist/generated/slider.d.ts +34 -0
  77. package/dist/generated/slider.js +140 -0
  78. package/dist/generated/speed-dial.d.ts +29 -0
  79. package/dist/generated/speed-dial.js +63 -0
  80. package/dist/generated/spinner.d.ts +10 -0
  81. package/dist/generated/spinner.js +18 -0
  82. package/dist/generated/split-button.d.ts +27 -0
  83. package/dist/generated/split-button.js +63 -0
  84. package/dist/generated/stepper.d.ts +17 -0
  85. package/dist/generated/stepper.js +56 -0
  86. package/dist/generated/switch.d.ts +29 -0
  87. package/dist/generated/switch.js +92 -0
  88. package/dist/generated/table.d.ts +31 -0
  89. package/dist/generated/table.js +187 -0
  90. package/dist/generated/tabs.d.ts +20 -0
  91. package/dist/generated/tabs.js +54 -0
  92. package/dist/generated/text-input.d.ts +48 -0
  93. package/dist/generated/text-input.js +165 -0
  94. package/dist/generated/text.d.ts +21 -0
  95. package/dist/generated/text.js +74 -0
  96. package/dist/generated/thinking.d.ts +12 -0
  97. package/dist/generated/thinking.js +22 -0
  98. package/dist/generated/toast.d.ts +24 -0
  99. package/dist/generated/toast.js +60 -0
  100. package/dist/generated/toggle-group.d.ts +21 -0
  101. package/dist/generated/toggle-group.js +70 -0
  102. package/dist/generated/tooltip.d.ts +18 -0
  103. package/dist/generated/tooltip.js +42 -0
  104. package/dist/generated/types.d.ts +300 -0
  105. package/dist/generated/types.js +6 -0
  106. package/dist/generated/use-markdown-stream.d.ts +45 -0
  107. package/dist/generated/use-markdown-stream.js +48 -0
  108. package/dist/generated/use-markdown.d.ts +20 -0
  109. package/dist/generated/use-markdown.js +49 -0
  110. package/package.json +38 -0
@@ -0,0 +1,60 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { forwardRef, useEffect, useImperativeHandle, useRef } from 'react';
3
+ export const Toast = forwardRef((props, forwardedRef) => {
4
+ const ref = useRef(null);
5
+ useImperativeHandle(forwardedRef, () => ref.current);
6
+ const onDismissRef = useRef(props.onDismiss);
7
+ onDismissRef.current = props.onDismiss;
8
+ useEffect(() => {
9
+ const el = ref.current;
10
+ if (!el)
11
+ return;
12
+ const handler = (e) => onDismissRef.current?.(e);
13
+ el.addEventListener('cx-dismiss', handler);
14
+ return () => el.removeEventListener('cx-dismiss', handler);
15
+ }, []);
16
+ useEffect(() => {
17
+ const el = ref.current;
18
+ if (!el)
19
+ return;
20
+ if (props.title != null) {
21
+ el.setAttribute('title', String(props.title));
22
+ }
23
+ else {
24
+ el.removeAttribute('title');
25
+ }
26
+ }, [props.title]);
27
+ useEffect(() => {
28
+ const el = ref.current;
29
+ if (!el)
30
+ return;
31
+ if (props.duration != null) {
32
+ el.setAttribute('duration', String(props.duration));
33
+ }
34
+ else {
35
+ el.removeAttribute('duration');
36
+ }
37
+ }, [props.duration]);
38
+ // Build attribute object
39
+ const attrs = {};
40
+ if (props.id != null)
41
+ attrs['id'] = typeof props.id === 'object' ? JSON.stringify(props.id) : String(props.id);
42
+ if (props.description != null)
43
+ attrs['description'] = typeof props.description === 'object' ? JSON.stringify(props.description) : String(props.description);
44
+ if (props.variant != null)
45
+ attrs['variant'] = typeof props.variant === 'object' ? JSON.stringify(props.variant) : String(props.variant);
46
+ if (props.intent != null)
47
+ attrs['intent'] = typeof props.intent === 'object' ? JSON.stringify(props.intent) : String(props.intent);
48
+ if (props.size != null)
49
+ attrs['size'] = typeof props.size === 'object' ? JSON.stringify(props.size) : String(props.size);
50
+ if (props.showIcon)
51
+ attrs['show-icon'] = '';
52
+ if (props.icon != null)
53
+ attrs['icon'] = typeof props.icon === 'object' ? JSON.stringify(props.icon) : String(props.icon);
54
+ if (props.dismissible)
55
+ attrs['dismissible'] = '';
56
+ if (props.dismissLabel != null)
57
+ attrs['dismiss-label'] = typeof props.dismissLabel === 'object' ? JSON.stringify(props.dismissLabel) : String(props.dismissLabel);
58
+ return (_jsx("cx-toast", { ref: ref, ...attrs, className: props.className, style: props.style, children: props.action && _jsx("div", { slot: "action", style: { display: 'contents' }, children: props.action }) }));
59
+ });
60
+ Toast.displayName = 'Toast';
@@ -0,0 +1,21 @@
1
+ import type React from 'react';
2
+ import type { ToggleDetail, ToggleItem } from './types.js';
3
+ export interface ToggleGroupProps {
4
+ id?: string;
5
+ label?: string;
6
+ items?: ToggleItem[] | string;
7
+ variant?: 'outline' | 'ghost' | 'filled';
8
+ shape?: 'sharp' | 'rounded' | 'pill';
9
+ mode?: 'single' | 'multiple';
10
+ orientation?: 'horizontal' | 'vertical';
11
+ intent?: 'neutral' | 'primary' | 'info' | 'success' | 'warning' | 'danger';
12
+ size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
13
+ disabled?: boolean;
14
+ /** Controlled pressed item IDs. Pass a single ID or an array; arrays are serialized to the comma-separated format expected by the Custom Element. */
15
+ value?: string | string[];
16
+ onInput?: (event: CustomEvent) => void;
17
+ onChange?: (event: CustomEvent<ToggleDetail>) => void;
18
+ className?: string;
19
+ style?: React.CSSProperties;
20
+ }
21
+ export declare const ToggleGroup: React.ForwardRefExoticComponent<ToggleGroupProps & React.RefAttributes<HTMLElement>>;
@@ -0,0 +1,70 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { forwardRef, useEffect, useImperativeHandle, useRef } from 'react';
3
+ export const ToggleGroup = forwardRef((props, forwardedRef) => {
4
+ const ref = useRef(null);
5
+ useImperativeHandle(forwardedRef, () => ref.current);
6
+ const onInputRef = useRef(props.onInput);
7
+ onInputRef.current = props.onInput;
8
+ const onChangeRef = useRef(props.onChange);
9
+ onChangeRef.current = props.onChange;
10
+ useEffect(() => {
11
+ const el = ref.current;
12
+ if (!el)
13
+ return;
14
+ const handler = (e) => onInputRef.current?.(e);
15
+ el.addEventListener('cx-input', handler);
16
+ return () => el.removeEventListener('cx-input', handler);
17
+ }, []);
18
+ useEffect(() => {
19
+ const el = ref.current;
20
+ if (!el)
21
+ return;
22
+ const handler = (e) => onChangeRef.current?.(e);
23
+ el.addEventListener('cx-change', handler);
24
+ return () => el.removeEventListener('cx-change', handler);
25
+ }, []);
26
+ useEffect(() => {
27
+ const el = ref.current;
28
+ if (!el)
29
+ return;
30
+ if (props.value != null) {
31
+ el.setAttribute('value', String(props.value));
32
+ }
33
+ else {
34
+ el.removeAttribute('value');
35
+ }
36
+ }, [props.value]);
37
+ useEffect(() => {
38
+ const el = ref.current;
39
+ if (!el)
40
+ return;
41
+ if (props.items != null) {
42
+ el.setAttribute('items', typeof props.items === 'object' ? JSON.stringify(props.items) : String(props.items));
43
+ }
44
+ else {
45
+ el.removeAttribute('items');
46
+ }
47
+ }, [props.items]);
48
+ // Build attribute object
49
+ const attrs = {};
50
+ if (props.id != null)
51
+ attrs['id'] = typeof props.id === 'object' ? JSON.stringify(props.id) : String(props.id);
52
+ if (props.label != null)
53
+ attrs['label'] = typeof props.label === 'object' ? JSON.stringify(props.label) : String(props.label);
54
+ if (props.variant != null)
55
+ attrs['variant'] = typeof props.variant === 'object' ? JSON.stringify(props.variant) : String(props.variant);
56
+ if (props.shape != null)
57
+ attrs['shape'] = typeof props.shape === 'object' ? JSON.stringify(props.shape) : String(props.shape);
58
+ if (props.mode != null)
59
+ attrs['mode'] = typeof props.mode === 'object' ? JSON.stringify(props.mode) : String(props.mode);
60
+ if (props.orientation != null)
61
+ attrs['orientation'] = typeof props.orientation === 'object' ? JSON.stringify(props.orientation) : String(props.orientation);
62
+ if (props.intent != null)
63
+ attrs['intent'] = typeof props.intent === 'object' ? JSON.stringify(props.intent) : String(props.intent);
64
+ if (props.size != null)
65
+ attrs['size'] = typeof props.size === 'object' ? JSON.stringify(props.size) : String(props.size);
66
+ if (props.disabled)
67
+ attrs['disabled'] = '';
68
+ return (_jsx("cx-toggle-group", { ref: ref, ...attrs, className: props.className, style: props.style }));
69
+ });
70
+ ToggleGroup.displayName = 'ToggleGroup';
@@ -0,0 +1,18 @@
1
+ import type React from 'react';
2
+ export interface TooltipProps {
3
+ id?: string;
4
+ /** Tooltip text shown on hover/focus. Also serves as the accessible name. */
5
+ content?: string;
6
+ triggerHtml?: string;
7
+ position?: 'top' | 'bottom' | 'left' | 'right';
8
+ arrow?: boolean;
9
+ openDelay?: number;
10
+ closeDelay?: number;
11
+ /** The element that triggers the tooltip on hover/focus. Accepts ReactNode. You can also pass this as `children`. */
12
+ trigger?: React.ReactNode;
13
+ /** Alias for `trigger` prop. Wraps children in the trigger slot. */
14
+ children?: React.ReactNode;
15
+ className?: string;
16
+ style?: React.CSSProperties;
17
+ }
18
+ export declare const Tooltip: React.ForwardRefExoticComponent<TooltipProps & React.RefAttributes<HTMLElement>>;
@@ -0,0 +1,42 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { forwardRef, useEffect, useImperativeHandle, useRef } from 'react';
3
+ export const Tooltip = forwardRef((props, forwardedRef) => {
4
+ const ref = useRef(null);
5
+ useImperativeHandle(forwardedRef, () => ref.current);
6
+ useEffect(() => {
7
+ const el = ref.current;
8
+ if (!el)
9
+ return;
10
+ if (props.openDelay != null) {
11
+ el.setAttribute('open-delay', String(props.openDelay));
12
+ }
13
+ else {
14
+ el.removeAttribute('open-delay');
15
+ }
16
+ }, [props.openDelay]);
17
+ useEffect(() => {
18
+ const el = ref.current;
19
+ if (!el)
20
+ return;
21
+ if (props.closeDelay != null) {
22
+ el.setAttribute('close-delay', String(props.closeDelay));
23
+ }
24
+ else {
25
+ el.removeAttribute('close-delay');
26
+ }
27
+ }, [props.closeDelay]);
28
+ // Build attribute object
29
+ const attrs = {};
30
+ if (props.id != null)
31
+ attrs['id'] = typeof props.id === 'object' ? JSON.stringify(props.id) : String(props.id);
32
+ if (props.content != null)
33
+ attrs['content'] = typeof props.content === 'object' ? JSON.stringify(props.content) : String(props.content);
34
+ if (props.triggerHtml != null)
35
+ attrs['trigger-html'] = typeof props.triggerHtml === 'object' ? JSON.stringify(props.triggerHtml) : String(props.triggerHtml);
36
+ if (props.position != null)
37
+ attrs['position'] = typeof props.position === 'object' ? JSON.stringify(props.position) : String(props.position);
38
+ if (props.arrow)
39
+ attrs['arrow'] = '';
40
+ return (_jsx("cx-tooltip", { ref: ref, ...attrs, className: props.className, style: props.style, children: (props.trigger || props.children) && _jsx("div", { slot: "trigger", style: { display: 'contents' }, children: props.trigger || props.children }) }));
41
+ });
42
+ Tooltip.displayName = 'Tooltip';
@@ -0,0 +1,300 @@
1
+ import type { ReactNode } from 'react';
2
+ export interface SelectOption {
3
+ value: string;
4
+ label: string;
5
+ icon?: string;
6
+ description?: string;
7
+ disabled?: boolean;
8
+ }
9
+ export interface OptionGroup {
10
+ label: string;
11
+ options: SelectOption[];
12
+ }
13
+ export interface TabItem {
14
+ value: string;
15
+ label: string;
16
+ content?: string | ReactNode;
17
+ icon?: string;
18
+ disabled?: boolean;
19
+ }
20
+ export interface TableColumn {
21
+ id: string;
22
+ header: string;
23
+ sortable?: boolean;
24
+ width?: string;
25
+ align?: 'left' | 'center' | 'right';
26
+ visible?: boolean;
27
+ pinned?: 'left' | 'right';
28
+ resizable?: boolean;
29
+ sr_only?: boolean;
30
+ min_width?: string;
31
+ max_width?: string;
32
+ }
33
+ export interface TableCell {
34
+ text?: string;
35
+ html?: string | ReactNode;
36
+ number?: number;
37
+ }
38
+ export interface TableRow {
39
+ id: string;
40
+ cells: TableCell[] | Record<string, string | TableCell>;
41
+ disabled?: boolean;
42
+ detail?: string | ReactNode;
43
+ expanded?: boolean;
44
+ }
45
+ export interface SortState {
46
+ column_id: string;
47
+ direction: 'asc' | 'desc' | 'ascending' | 'descending';
48
+ }
49
+ export interface PaginationConfig {
50
+ current_page: number;
51
+ page_size: number;
52
+ total_items: number;
53
+ page_size_options?: number[];
54
+ }
55
+ export interface FooterRow {
56
+ cells: Record<string, string | TableCell>;
57
+ }
58
+ export interface EmptyStateConfig {
59
+ title?: string;
60
+ icon?: string;
61
+ description?: string;
62
+ }
63
+ export interface AccordionItem {
64
+ id: string;
65
+ trigger_label: string;
66
+ panel_content: string | ReactNode;
67
+ icon?: string;
68
+ description?: string;
69
+ disabled?: boolean;
70
+ }
71
+ export interface MenuRadioItem {
72
+ value: string;
73
+ label: string;
74
+ icon?: string;
75
+ disabled?: boolean;
76
+ }
77
+ export interface MenuEntry {
78
+ type: 'item' | 'checkbox' | 'radio-group' | 'separator' | 'label';
79
+ id?: string;
80
+ label?: string;
81
+ icon?: string;
82
+ shortcut?: string;
83
+ disabled?: boolean;
84
+ danger?: boolean;
85
+ intent?: string;
86
+ checked?: boolean;
87
+ value?: string;
88
+ items?: MenuRadioItem[];
89
+ }
90
+ export interface SidebarNavItem {
91
+ id: string;
92
+ label: string;
93
+ href?: string;
94
+ icon?: string;
95
+ badge?: string;
96
+ active?: boolean;
97
+ disabled?: boolean;
98
+ }
99
+ export interface SidebarGroup {
100
+ label?: string;
101
+ icon?: string;
102
+ items: SidebarNavItem[];
103
+ collapsible?: boolean;
104
+ expanded?: boolean;
105
+ }
106
+ export interface BreadcrumbItem {
107
+ label: string;
108
+ href?: string;
109
+ icon?: string;
110
+ current?: boolean;
111
+ ellipsis?: boolean;
112
+ }
113
+ export interface RadioOption {
114
+ value: string;
115
+ label: string;
116
+ description?: string;
117
+ disabled?: boolean;
118
+ icon?: string;
119
+ }
120
+ export interface ToggleItem {
121
+ id: string;
122
+ label: string;
123
+ icon?: string;
124
+ icon_only?: boolean;
125
+ pressed?: boolean;
126
+ disabled?: boolean;
127
+ }
128
+ export interface SplitMenuEntry {
129
+ type: 'item' | 'separator';
130
+ id?: string;
131
+ label?: string;
132
+ icon?: string;
133
+ shortcut?: string;
134
+ intent?: string;
135
+ disabled?: boolean;
136
+ }
137
+ export interface CarouselSlide {
138
+ image_url?: string;
139
+ title: string;
140
+ badge?: string;
141
+ badge_color?: string;
142
+ subtitle?: string;
143
+ href?: string;
144
+ }
145
+ export interface CarouselDetail {
146
+ index: number;
147
+ total: number;
148
+ }
149
+ export interface SpeedDialAction {
150
+ id: string;
151
+ icon: string;
152
+ label: string;
153
+ intent?: string;
154
+ disabled?: boolean;
155
+ handler?: string;
156
+ }
157
+ /** A part config for MessageGroup — connections are auto-computed from array position. */
158
+ export interface MessageGroupPart {
159
+ /** Unique part ID. Auto-generated as `{groupId}-part-{index}` if omitted. */
160
+ id?: string;
161
+ /** Part kind. */
162
+ kind: 'text' | 'tool-call' | 'tool-result' | 'thinking' | 'code-block' | 'error';
163
+ /** Override auto-computed connection (standalone/first/middle/last). Usually omit this. */
164
+ connection?: 'standalone' | 'first' | 'middle' | 'last';
165
+ /** Text/code/error content. */
166
+ content?: string;
167
+ /** Pre-rendered HTML content. */
168
+ html_content?: string;
169
+ /** Tool/function name (for tool-call and tool-result kinds). */
170
+ tool_name?: string;
171
+ /** Tool arguments JSON string (for tool-call kind). */
172
+ tool_arguments?: string;
173
+ /** Tool execution status. */
174
+ tool_status?: 'pending' | 'success' | 'error';
175
+ /** Whether tool result is collapsible. */
176
+ collapsible?: boolean;
177
+ /** Label for thinking indicator. */
178
+ thinking_label?: string;
179
+ /** Code language hint (for code-block kind). */
180
+ language?: string;
181
+ /** Size override for this part (inherits group size if omitted). */
182
+ size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
183
+ }
184
+ /** Step configuration for Stepper component. */
185
+ export interface StepperStep {
186
+ /** Unique step ID. */
187
+ id: string;
188
+ /** Step label text. */
189
+ label: string;
190
+ /** Optional description text below the label. */
191
+ description?: string;
192
+ /** Override auto-computed status (pending/active/completed/error/loading). */
193
+ status?: 'pending' | 'active' | 'completed' | 'error' | 'loading';
194
+ /** Whether this step is disabled (non-interactive). */
195
+ disabled?: boolean;
196
+ /** Whether this step is optional. */
197
+ optional?: boolean;
198
+ }
199
+ /** Detail for `cx-input` on TextInput, ChatInput, Autocomplete. */
200
+ export interface InputDetail {
201
+ value: string;
202
+ }
203
+ /** Detail for `cx-change` on Select, Autocomplete, Listbox, RadioGroup, Tabs. */
204
+ export interface SelectDetail {
205
+ value: string;
206
+ }
207
+ /** Detail for `cx-input`/`cx-change` on Checkbox, Switch. */
208
+ export interface CheckedDetail {
209
+ checked: boolean;
210
+ }
211
+ /** Detail for `cx-input` on Slider. */
212
+ export interface SliderDetail {
213
+ value: number;
214
+ }
215
+ /** Detail for `cx-change` on ToggleGroup. */
216
+ export interface ToggleDetail {
217
+ pressed: string[];
218
+ }
219
+ /** Detail for `cx-change` on Accordion. */
220
+ export interface AccordionDetail {
221
+ expanded: string[];
222
+ }
223
+ /** Detail for `cx-change` on Collapsible. */
224
+ export interface CollapsibleDetail {
225
+ open: boolean;
226
+ }
227
+ /** Detail for `cx-action` on Menu. */
228
+ export interface MenuActionDetail {
229
+ id: string;
230
+ label?: string;
231
+ }
232
+ /** Detail for `cx-change` on Menu (checkbox/radio state changes). */
233
+ export interface MenuChangeDetail {
234
+ id: string;
235
+ checked?: boolean;
236
+ value?: string;
237
+ }
238
+ /** Detail for `cx-sort` on Table. */
239
+ export interface SortDetail {
240
+ column_id: string;
241
+ direction: 'asc' | 'desc' | 'none';
242
+ }
243
+ /** Detail for `cx-select` on Table. */
244
+ export interface TableSelectDetail {
245
+ selected: string[];
246
+ /** The row that triggered the selection change (undefined for select-all). */
247
+ row_id?: string;
248
+ }
249
+ /** Detail for `cx-expand` on Table. */
250
+ export interface TableExpandDetail {
251
+ row_id: string;
252
+ expanded: boolean;
253
+ }
254
+ /** Detail for `cx-page` on Table, Pagination. */
255
+ export interface PageDetail {
256
+ page: number;
257
+ page_size?: number;
258
+ }
259
+ /** Detail for `cx-navigate` on Breadcrumb, Sidebar. */
260
+ export interface NavigateDetail {
261
+ href: string;
262
+ label: string;
263
+ }
264
+ /** Detail for `cx-click` on Button, Card. */
265
+ export interface ClickDetail {
266
+ /** Original mouse event coordinates, if applicable. */
267
+ x?: number;
268
+ y?: number;
269
+ }
270
+ /** Detail for `cx-change` on FileUpload. */
271
+ export interface FileChangeDetail {
272
+ files: FileInfo[];
273
+ }
274
+ /** Metadata for a selected file. */
275
+ export interface FileInfo {
276
+ name: string;
277
+ size: number;
278
+ type: string;
279
+ }
280
+ /** Detail for `cx-close` on Dialog, Drawer. */
281
+ export interface CloseDetail {
282
+ reason?: 'escape' | 'backdrop' | 'close-button';
283
+ }
284
+ /** Detail for `cx-dismiss` on Alert, Toast. */
285
+ export interface DismissDetail {
286
+ reason?: 'user' | 'timeout';
287
+ }
288
+ /** Detail for `cx-focus` / `cx-blur` on form/interactive components. */
289
+ export interface FocusDetail {
290
+ relatedTarget: EventTarget | null;
291
+ }
292
+ /** Detail for `cx-keydown` / `cx-keyup` on form/interactive components. */
293
+ export interface KeyboardDetail {
294
+ key: string;
295
+ code: string;
296
+ shiftKey: boolean;
297
+ ctrlKey: boolean;
298
+ altKey: boolean;
299
+ metaKey: boolean;
300
+ }
@@ -0,0 +1,6 @@
1
+ // Shared TypeScript interfaces for structured component props.
2
+ // These mirror the Rust config structs in crates/wasm-api/src/*.rs.
3
+ // Consumers import these from '@collet/react' for typed component APIs.
4
+ // Content fields that accept HTML can also accept React.ReactNode —
5
+ // wrappers serialize JSX via renderToStaticMarkup before passing to WASM.
6
+ export {};
@@ -0,0 +1,45 @@
1
+ /** Ref type for the streaming message part element. */
2
+ export interface MarkdownStreamRef {
3
+ /** React ref to attach to the MessagePart component. */
4
+ ref: React.RefObject<HTMLElement | null>;
5
+ /**
6
+ * Initialize the streaming parser.
7
+ * Clears content and shows a blinking cursor.
8
+ */
9
+ startStream: () => Promise<void>;
10
+ /**
11
+ * Feed markdown tokens into the streaming parser.
12
+ * Tokens are rAF-batched for performance.
13
+ */
14
+ appendTokens: (text: string) => void;
15
+ /**
16
+ * End the stream. Flushes remaining tokens, removes cursor,
17
+ * then runs a final WASM sanitization pass.
18
+ */
19
+ endStream: () => Promise<void>;
20
+ }
21
+ /**
22
+ * Hook for streaming markdown into a MessagePart element.
23
+ *
24
+ * @example
25
+ * ```tsx
26
+ * import { MessagePart, useMarkdownStream } from '@collet/react';
27
+ *
28
+ * function StreamingMessage() {
29
+ * const { ref, startStream, appendTokens, endStream } = useMarkdownStream();
30
+ *
31
+ * async function handleSSE() {
32
+ * await startStream();
33
+ * const source = new EventSource('/api/chat');
34
+ * source.onmessage = (e) => appendTokens(e.data);
35
+ * source.addEventListener('done', async () => {
36
+ * source.close();
37
+ * await endStream();
38
+ * });
39
+ * }
40
+ *
41
+ * return <MessagePart ref={ref} stream />;
42
+ * }
43
+ * ```
44
+ */
45
+ export declare function useMarkdownStream(): MarkdownStreamRef;
@@ -0,0 +1,48 @@
1
+ // useMarkdownStream — React hook for streaming markdown rendering.
2
+ //
3
+ // Provides ref + imperative methods for feeding tokens from SSE/WebSocket
4
+ // into a cx-message-part element's streaming parser.
5
+ import { useRef, useCallback } from 'react';
6
+ /**
7
+ * Hook for streaming markdown into a MessagePart element.
8
+ *
9
+ * @example
10
+ * ```tsx
11
+ * import { MessagePart, useMarkdownStream } from '@collet/react';
12
+ *
13
+ * function StreamingMessage() {
14
+ * const { ref, startStream, appendTokens, endStream } = useMarkdownStream();
15
+ *
16
+ * async function handleSSE() {
17
+ * await startStream();
18
+ * const source = new EventSource('/api/chat');
19
+ * source.onmessage = (e) => appendTokens(e.data);
20
+ * source.addEventListener('done', async () => {
21
+ * source.close();
22
+ * await endStream();
23
+ * });
24
+ * }
25
+ *
26
+ * return <MessagePart ref={ref} stream />;
27
+ * }
28
+ * ```
29
+ */
30
+ export function useMarkdownStream() {
31
+ const ref = useRef(null);
32
+ const startStream = useCallback(async () => {
33
+ const el = ref.current;
34
+ if (el?.startStream)
35
+ await el.startStream();
36
+ }, []);
37
+ const appendTokens = useCallback((text) => {
38
+ const el = ref.current;
39
+ if (el?.appendTokens)
40
+ el.appendTokens(text);
41
+ }, []);
42
+ const endStream = useCallback(async () => {
43
+ const el = ref.current;
44
+ if (el?.endStream)
45
+ await el.endStream();
46
+ }, []);
47
+ return { ref, startStream, appendTokens, endStream };
48
+ }
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Render GFM markdown to sanitized HTML.
3
+ *
4
+ * Returns empty string while WASM is loading, then the rendered HTML.
5
+ * Re-renders automatically when the input changes.
6
+ *
7
+ * @param content - GFM markdown string
8
+ * @returns Sanitized HTML string (or empty string while loading)
9
+ *
10
+ * @example
11
+ * ```tsx
12
+ * import { useMarkdown } from '@colletdev/react';
13
+ *
14
+ * function Message({ markdown }: { markdown: string }) {
15
+ * const html = useMarkdown(markdown);
16
+ * return <div dangerouslySetInnerHTML={{ __html: html }} />;
17
+ * }
18
+ * ```
19
+ */
20
+ export declare function useMarkdown(content: string): string;
@@ -0,0 +1,49 @@
1
+ // useMarkdown — React hook for static markdown rendering via WASM.
2
+ //
3
+ // Converts GFM markdown to XSS-safe HTML using the WASM renderer.
4
+ // Re-renders when the input string changes.
5
+ import { useState, useEffect } from 'react';
6
+ /**
7
+ * Render GFM markdown to sanitized HTML.
8
+ *
9
+ * Returns empty string while WASM is loading, then the rendered HTML.
10
+ * Re-renders automatically when the input changes.
11
+ *
12
+ * @param content - GFM markdown string
13
+ * @returns Sanitized HTML string (or empty string while loading)
14
+ *
15
+ * @example
16
+ * ```tsx
17
+ * import { useMarkdown } from '@colletdev/react';
18
+ *
19
+ * function Message({ markdown }: { markdown: string }) {
20
+ * const html = useMarkdown(markdown);
21
+ * return <div dangerouslySetInnerHTML={{ __html: html }} />;
22
+ * }
23
+ * ```
24
+ */
25
+ export function useMarkdown(content) {
26
+ const [html, setHtml] = useState('');
27
+ useEffect(() => {
28
+ let cancelled = false;
29
+ async function render() {
30
+ try {
31
+ const { renderMarkdown } = await import('@colletdev/core/markdown');
32
+ const result = await renderMarkdown(content);
33
+ if (!cancelled)
34
+ setHtml(result);
35
+ }
36
+ catch {
37
+ // WASM not loaded — return empty
38
+ }
39
+ }
40
+ if (content) {
41
+ render();
42
+ }
43
+ else {
44
+ setHtml('');
45
+ }
46
+ return () => { cancelled = true; };
47
+ }, [content]);
48
+ return html;
49
+ }