@sidecar-ai/native 0.1.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,1829 @@
1
+ // packages/native/src/index.ts
2
+ import { browserBridge, detectHostContext as detectSidecarHostContext } from "@sidecar-ai/client";
3
+
4
+ // packages/native/src/components/index.tsx
5
+ import * as React from "react";
6
+ var Button = React.forwardRef(function Button2({
7
+ block = false,
8
+ children,
9
+ color,
10
+ disabled,
11
+ disabledTone,
12
+ gutterSize,
13
+ iconSize,
14
+ inert = false,
15
+ intent,
16
+ loading = false,
17
+ opticallyAlign,
18
+ pill = true,
19
+ recipe = "auto",
20
+ selected = false,
21
+ size = "md",
22
+ type = "button",
23
+ uniform = false,
24
+ variant,
25
+ ...props
26
+ }, ref) {
27
+ const visual = normalizeButtonVisual({ color, intent, variant });
28
+ return React.createElement(
29
+ "button",
30
+ {
31
+ ref,
32
+ "aria-busy": loading || void 0,
33
+ "data-sc-block": block ? "" : void 0,
34
+ "data-sc-color": visual.color,
35
+ "data-sc-component": "button",
36
+ "data-sc-disabled-tone": disabledTone,
37
+ "data-sc-gutter-size": gutterSize,
38
+ "data-sc-icon-size": iconSize,
39
+ "data-sc-inert": inert ? "" : void 0,
40
+ "data-sc-intent": visual.color,
41
+ "data-sc-loading": loading ? "" : void 0,
42
+ "data-sc-optically-align": opticallyAlign,
43
+ "data-sc-pill": pill ? "" : void 0,
44
+ "data-sc-recipe": recipe,
45
+ "data-sc-selected": selected ? "" : void 0,
46
+ "data-sc-size": size,
47
+ "data-sc-uniform": uniform ? "" : void 0,
48
+ "data-sc-variant": visual.variant,
49
+ disabled: disabled || loading || void 0,
50
+ type,
51
+ ...props
52
+ },
53
+ loading ? React.createElement(LoadingIndicator, { "aria-hidden": true, size: "1em" }) : null,
54
+ React.createElement("span", { "data-sc-component": "button-label" }, children)
55
+ );
56
+ });
57
+ var ButtonLink = React.forwardRef(function ButtonLink2({
58
+ block = false,
59
+ children,
60
+ color,
61
+ disabledTone,
62
+ external,
63
+ gutterSize,
64
+ href,
65
+ iconSize,
66
+ inert = false,
67
+ intent,
68
+ loading = false,
69
+ opticallyAlign,
70
+ pill = true,
71
+ recipe = "auto",
72
+ rel,
73
+ selected = false,
74
+ size = "md",
75
+ target,
76
+ uniform = false,
77
+ variant,
78
+ ...props
79
+ }, ref) {
80
+ const visual = normalizeButtonVisual({ color, intent, variant });
81
+ const isExternal = external ?? Boolean(href && /^(?:[a-z][a-z0-9+.-]*:)?\/\//i.test(href));
82
+ return React.createElement(
83
+ "a",
84
+ {
85
+ ref,
86
+ "data-sc-block": block ? "" : void 0,
87
+ "data-sc-color": visual.color,
88
+ "data-sc-component": "button",
89
+ "data-sc-disabled-tone": disabledTone,
90
+ "data-sc-gutter-size": gutterSize,
91
+ "data-sc-icon-size": iconSize,
92
+ "data-sc-inert": inert ? "" : void 0,
93
+ "data-sc-loading": loading ? "" : void 0,
94
+ "data-sc-optically-align": opticallyAlign,
95
+ "data-sc-pill": pill ? "" : void 0,
96
+ "data-sc-recipe": recipe,
97
+ "data-sc-selected": selected ? "" : void 0,
98
+ "data-sc-size": size,
99
+ "data-sc-uniform": uniform ? "" : void 0,
100
+ "data-sc-variant": visual.variant,
101
+ href,
102
+ rel: isExternal && target === "_blank" ? mergeRel(rel, "noopener noreferrer") : rel,
103
+ target,
104
+ ...props
105
+ },
106
+ loading ? React.createElement(LoadingIndicator, { "aria-hidden": true, size: "1em" }) : null,
107
+ React.createElement("span", { "data-sc-component": "button-label" }, children)
108
+ );
109
+ });
110
+ function CopyButton({ children = "Copy", copyValue, onClick, ...restProps }) {
111
+ const [copied, setCopied] = React.useState(false);
112
+ React.useEffect(() => {
113
+ if (!copied) {
114
+ return;
115
+ }
116
+ const timeout = window.setTimeout(() => setCopied(false), 1400);
117
+ return () => window.clearTimeout(timeout);
118
+ }, [copied]);
119
+ return React.createElement(
120
+ Button,
121
+ {
122
+ ...restProps,
123
+ onClick: async (event) => {
124
+ onClick?.(event);
125
+ if (event.defaultPrevented) {
126
+ return;
127
+ }
128
+ const resolved = typeof copyValue === "function" ? copyValue() : copyValue;
129
+ await copyToClipboard(resolved);
130
+ setCopied(true);
131
+ }
132
+ },
133
+ typeof children === "function" ? children({ copied }) : children
134
+ );
135
+ }
136
+ var Text = React.forwardRef(function Text2({ tone = "default", recipe = "auto", ...props }, ref) {
137
+ return React.createElement("p", {
138
+ ref,
139
+ "data-sc-component": "text",
140
+ "data-sc-recipe": recipe,
141
+ "data-sc-tone": tone,
142
+ ...props
143
+ });
144
+ });
145
+ var Heading = React.forwardRef(function Heading2({ level = 2, recipe = "auto", ...props }, ref) {
146
+ return React.createElement(`h${level}`, {
147
+ ref,
148
+ "data-sc-component": "heading",
149
+ "data-sc-level": level,
150
+ "data-sc-recipe": recipe,
151
+ ...props
152
+ });
153
+ });
154
+ var Input = React.forwardRef(function Input2({
155
+ allowAutofillExtensions: _allowAutofillExtensions,
156
+ autoSelect = false,
157
+ block = false,
158
+ disabled = false,
159
+ endAdornment,
160
+ gutterSize,
161
+ id,
162
+ invalid,
163
+ onAutofill: _onAutofill,
164
+ opticallyAlign,
165
+ pill = false,
166
+ recipe = "auto",
167
+ size = "md",
168
+ startAdornment,
169
+ variant = "outline",
170
+ ...props
171
+ }, ref) {
172
+ const field = React.useContext(FieldContext);
173
+ const inputRef = React.useRef(null);
174
+ const mergedRef = useMergedRefs(ref, inputRef);
175
+ const inputId = id ?? field?.controlId;
176
+ const resolvedInvalid = invalid ?? field?.invalid ?? false;
177
+ React.useEffect(() => {
178
+ if (autoSelect) {
179
+ inputRef.current?.select();
180
+ }
181
+ }, [autoSelect]);
182
+ return React.createElement(
183
+ "span",
184
+ {
185
+ "data-sc-block": block ? "" : void 0,
186
+ "data-sc-component": "input-shell",
187
+ "data-sc-disabled": disabled ? "" : void 0,
188
+ "data-sc-gutter-size": gutterSize,
189
+ "data-sc-has-end-adornment": endAdornment ? "" : void 0,
190
+ "data-sc-has-start-adornment": startAdornment ? "" : void 0,
191
+ "data-sc-invalid": resolvedInvalid ? "" : void 0,
192
+ "data-sc-optically-align": opticallyAlign,
193
+ "data-sc-pill": pill ? "" : void 0,
194
+ "data-sc-recipe": recipe,
195
+ "data-sc-size": size,
196
+ "data-sc-variant": variant
197
+ },
198
+ startAdornment ? React.createElement("span", { "data-sc-component": "input-adornment" }, startAdornment) : null,
199
+ React.createElement("input", {
200
+ ref: mergedRef,
201
+ "aria-describedby": describedBy(props["aria-describedby"], field, resolvedInvalid),
202
+ "aria-invalid": resolvedInvalid || void 0,
203
+ disabled,
204
+ id: inputId,
205
+ "data-sc-component": "input",
206
+ ...props
207
+ }),
208
+ endAdornment ? React.createElement("span", { "data-sc-component": "input-adornment" }, endAdornment) : null
209
+ );
210
+ });
211
+ var TextField = Input;
212
+ var Textarea = React.forwardRef(function Textarea2({
213
+ allowAutofillExtensions: _allowAutofillExtensions,
214
+ autoResize = false,
215
+ autoSelect = false,
216
+ block = false,
217
+ disabled = false,
218
+ gutterSize,
219
+ id,
220
+ invalid,
221
+ maxRows: _maxRows,
222
+ onAutofill: _onAutofill,
223
+ opticallyAlign,
224
+ pill = false,
225
+ recipe = "auto",
226
+ rows = 3,
227
+ size = "md",
228
+ variant = "outline",
229
+ ...props
230
+ }, ref) {
231
+ const field = React.useContext(FieldContext);
232
+ const textareaRef = React.useRef(null);
233
+ const mergedRef = useMergedRefs(ref, textareaRef);
234
+ const inputId = id ?? field?.controlId;
235
+ const resolvedInvalid = invalid ?? field?.invalid ?? false;
236
+ React.useEffect(() => {
237
+ if (autoSelect) {
238
+ textareaRef.current?.select();
239
+ }
240
+ }, [autoSelect]);
241
+ React.useLayoutEffect(() => {
242
+ const node = textareaRef.current;
243
+ if (!node || !autoResize) {
244
+ return;
245
+ }
246
+ node.style.height = "auto";
247
+ node.style.height = `${node.scrollHeight}px`;
248
+ }, [autoResize, props.value, props.defaultValue]);
249
+ return React.createElement("textarea", {
250
+ ref: mergedRef,
251
+ "aria-describedby": describedBy(props["aria-describedby"], field, resolvedInvalid),
252
+ "aria-invalid": resolvedInvalid || void 0,
253
+ disabled,
254
+ id: inputId,
255
+ "data-sc-block": block ? "" : void 0,
256
+ "data-sc-component": "textarea",
257
+ "data-sc-disabled": disabled ? "" : void 0,
258
+ "data-sc-gutter-size": gutterSize,
259
+ "data-sc-invalid": resolvedInvalid ? "" : void 0,
260
+ "data-sc-optically-align": opticallyAlign,
261
+ "data-sc-pill": pill ? "" : void 0,
262
+ "data-sc-recipe": recipe,
263
+ "data-sc-size": size,
264
+ "data-sc-variant": variant,
265
+ rows,
266
+ ...props
267
+ });
268
+ });
269
+ function Checkbox({
270
+ checked,
271
+ className,
272
+ defaultChecked = false,
273
+ disabled = false,
274
+ id,
275
+ label,
276
+ name,
277
+ onBlur,
278
+ onCheckedChange,
279
+ onFocus,
280
+ orientation = "left",
281
+ recipe = "auto",
282
+ required = false,
283
+ value = "on"
284
+ }) {
285
+ const generatedId = React.useId();
286
+ const controlId = id ?? generatedId;
287
+ const [state, setState] = useControllableValue({
288
+ controlled: checked,
289
+ defaultValue: defaultChecked,
290
+ onChange: (next) => onCheckedChange?.(next === true)
291
+ });
292
+ const isChecked = state === true;
293
+ const isMixed = state === "indeterminate";
294
+ const button = React.createElement("button", {
295
+ "aria-checked": isMixed ? "mixed" : isChecked,
296
+ "aria-labelledby": label ? `${controlId}-label` : void 0,
297
+ disabled,
298
+ id: controlId,
299
+ onBlur,
300
+ onClick: () => {
301
+ if (!disabled) {
302
+ setState(!isChecked);
303
+ }
304
+ },
305
+ onFocus,
306
+ role: "checkbox",
307
+ type: "button",
308
+ "data-sc-checked": isChecked ? "" : void 0,
309
+ "data-sc-component": "checkbox",
310
+ "data-sc-disabled": disabled ? "" : void 0,
311
+ "data-sc-indeterminate": isMixed ? "" : void 0,
312
+ "data-sc-recipe": recipe
313
+ });
314
+ const labelNode = label ? React.createElement("span", { id: `${controlId}-label`, "data-sc-component": "checkbox-label-text" }, label) : null;
315
+ return React.createElement(
316
+ "label",
317
+ {
318
+ className,
319
+ "data-sc-component": "checkbox-label",
320
+ "data-sc-orientation": orientation,
321
+ "data-sc-recipe": recipe
322
+ },
323
+ orientation === "right" ? labelNode : button,
324
+ React.createElement("input", {
325
+ checked: isChecked,
326
+ disabled,
327
+ name,
328
+ readOnly: true,
329
+ required,
330
+ tabIndex: -1,
331
+ type: "checkbox",
332
+ value,
333
+ "data-sc-component": "visually-hidden-input"
334
+ }),
335
+ orientation === "right" ? button : labelNode
336
+ );
337
+ }
338
+ function Switch({
339
+ checked,
340
+ className,
341
+ defaultChecked = false,
342
+ disabled = false,
343
+ id,
344
+ label,
345
+ labelPosition = "end",
346
+ name,
347
+ onBlur,
348
+ onCheckedChange,
349
+ onFocus,
350
+ recipe = "auto",
351
+ required = false,
352
+ value = "on"
353
+ }) {
354
+ const generatedId = React.useId();
355
+ const controlId = id ?? generatedId;
356
+ const [state, setState] = useControllableValue({
357
+ controlled: checked,
358
+ defaultValue: defaultChecked,
359
+ onChange: onCheckedChange
360
+ });
361
+ const button = React.createElement(
362
+ "button",
363
+ {
364
+ "aria-checked": state,
365
+ "aria-labelledby": label ? `${controlId}-label` : void 0,
366
+ disabled,
367
+ id: controlId,
368
+ onBlur,
369
+ onClick: () => {
370
+ if (!disabled) {
371
+ setState(!state);
372
+ }
373
+ },
374
+ onFocus,
375
+ role: "switch",
376
+ type: "button",
377
+ "data-sc-checked": state ? "" : void 0,
378
+ "data-sc-component": "switch",
379
+ "data-sc-disabled": disabled ? "" : void 0,
380
+ "data-sc-recipe": recipe
381
+ },
382
+ React.createElement("span", { "data-sc-component": "switch-thumb" })
383
+ );
384
+ const labelNode = label ? React.createElement("span", { id: `${controlId}-label`, "data-sc-component": "switch-label-text" }, label) : null;
385
+ return React.createElement(
386
+ "label",
387
+ {
388
+ className,
389
+ "data-sc-component": "switch-label",
390
+ "data-sc-label-position": labelPosition,
391
+ "data-sc-recipe": recipe
392
+ },
393
+ labelPosition === "start" ? labelNode : button,
394
+ React.createElement("input", {
395
+ checked: state,
396
+ disabled,
397
+ name,
398
+ readOnly: true,
399
+ required,
400
+ tabIndex: -1,
401
+ type: "checkbox",
402
+ value,
403
+ "data-sc-component": "visually-hidden-input"
404
+ }),
405
+ labelPosition === "start" ? button : labelNode
406
+ );
407
+ }
408
+ var RadioGroupContext = React.createContext(null);
409
+ function RadioGroupRoot({
410
+ children,
411
+ className,
412
+ defaultValue,
413
+ direction = "row",
414
+ disabled = false,
415
+ name,
416
+ onChange,
417
+ recipe = "auto",
418
+ required = false,
419
+ value,
420
+ ...restProps
421
+ }) {
422
+ const [selected, setSelected] = useControllableValue({
423
+ controlled: value,
424
+ defaultValue,
425
+ onChange: (next) => {
426
+ if (next !== void 0) {
427
+ onChange?.(next);
428
+ }
429
+ }
430
+ });
431
+ return React.createElement(
432
+ RadioGroupContext.Provider,
433
+ {
434
+ value: {
435
+ disabled,
436
+ name,
437
+ onChange: setSelected,
438
+ recipe,
439
+ required,
440
+ value: selected
441
+ }
442
+ },
443
+ React.createElement(
444
+ "div",
445
+ {
446
+ ...restProps,
447
+ className,
448
+ role: "radiogroup",
449
+ "data-sc-component": "radio-group",
450
+ "data-sc-direction": direction,
451
+ "data-sc-disabled": disabled ? "" : void 0,
452
+ "data-sc-recipe": recipe
453
+ },
454
+ children
455
+ )
456
+ );
457
+ }
458
+ function RadioGroupItem({
459
+ block = false,
460
+ children,
461
+ className,
462
+ disabled = false,
463
+ required,
464
+ value
465
+ }) {
466
+ const context = useRequiredContext(RadioGroupContext, "RadioGroup.Item must be rendered inside RadioGroup");
467
+ const itemDisabled = context.disabled || disabled;
468
+ const checked = context.value === value;
469
+ return React.createElement(
470
+ "button",
471
+ {
472
+ "aria-checked": checked,
473
+ className,
474
+ disabled: itemDisabled,
475
+ onClick: () => {
476
+ if (!itemDisabled) {
477
+ context.onChange(value);
478
+ }
479
+ },
480
+ role: "radio",
481
+ type: "button",
482
+ "data-sc-block": block ? "" : void 0,
483
+ "data-sc-checked": checked ? "" : void 0,
484
+ "data-sc-component": "radio-item",
485
+ "data-sc-disabled": itemDisabled ? "" : void 0,
486
+ "data-sc-recipe": context.recipe
487
+ },
488
+ React.createElement("span", { "data-sc-component": "radio-indicator" }),
489
+ React.createElement("span", { "data-sc-component": "radio-label" }, children),
490
+ context.name ? React.createElement("input", {
491
+ checked,
492
+ disabled: itemDisabled,
493
+ name: context.name,
494
+ readOnly: true,
495
+ required: required ?? context.required,
496
+ tabIndex: -1,
497
+ type: "radio",
498
+ value,
499
+ "data-sc-component": "visually-hidden-input"
500
+ }) : null
501
+ );
502
+ }
503
+ var RadioGroup = Object.assign(RadioGroupRoot, {
504
+ Item: RadioGroupItem
505
+ });
506
+ var SegmentedControlContext = React.createContext(null);
507
+ function SegmentedControlRoot({
508
+ block = false,
509
+ children,
510
+ className,
511
+ defaultValue,
512
+ disabled = false,
513
+ gutterSize,
514
+ onChange,
515
+ onClick,
516
+ pill = false,
517
+ recipe = "auto",
518
+ size = "md",
519
+ value,
520
+ ...restProps
521
+ }) {
522
+ const [selected, setSelected] = useControllableValue({
523
+ controlled: value,
524
+ defaultValue,
525
+ onChange: (next) => {
526
+ if (next !== void 0) {
527
+ onChange?.(next);
528
+ }
529
+ }
530
+ });
531
+ return React.createElement(
532
+ SegmentedControlContext.Provider,
533
+ {
534
+ value: {
535
+ disabled,
536
+ onChange: setSelected,
537
+ onClick,
538
+ recipe,
539
+ selected
540
+ }
541
+ },
542
+ React.createElement(
543
+ "div",
544
+ {
545
+ ...restProps,
546
+ className,
547
+ role: "group",
548
+ "data-sc-block": block ? "" : void 0,
549
+ "data-sc-component": "segmented-control",
550
+ "data-sc-disabled": disabled ? "" : void 0,
551
+ "data-sc-gutter-size": gutterSize,
552
+ "data-sc-pill": pill ? "" : void 0,
553
+ "data-sc-recipe": recipe,
554
+ "data-sc-size": size
555
+ },
556
+ children
557
+ )
558
+ );
559
+ }
560
+ function SegmentedControlOption({
561
+ children,
562
+ disabled = false,
563
+ value,
564
+ ...restProps
565
+ }) {
566
+ const context = useRequiredContext(
567
+ SegmentedControlContext,
568
+ "SegmentedControl.Option must be rendered inside SegmentedControl"
569
+ );
570
+ const selected = context.selected === value;
571
+ const optionDisabled = context.disabled || disabled;
572
+ return React.createElement(
573
+ "button",
574
+ {
575
+ ...restProps,
576
+ "aria-pressed": selected,
577
+ disabled: optionDisabled,
578
+ onClick: () => {
579
+ context.onClick?.();
580
+ if (!optionDisabled) {
581
+ context.onChange(value);
582
+ }
583
+ },
584
+ type: "button",
585
+ "data-sc-component": "segmented-option",
586
+ "data-sc-disabled": optionDisabled ? "" : void 0,
587
+ "data-sc-recipe": context.recipe,
588
+ "data-sc-selected": selected ? "" : void 0
589
+ },
590
+ children
591
+ );
592
+ }
593
+ var SegmentedControl = Object.assign(SegmentedControlRoot, {
594
+ Option: SegmentedControlOption
595
+ });
596
+ function Select({
597
+ actions,
598
+ block = true,
599
+ clearable = false,
600
+ defaultOpen = false,
601
+ disabled = false,
602
+ dropdownIconType = "dropdown",
603
+ id,
604
+ loading = false,
605
+ loadingPlaceholder = "Loading...",
606
+ multiple,
607
+ name,
608
+ onChange,
609
+ OptionView,
610
+ options,
611
+ opticallyAlign,
612
+ pill = false,
613
+ placeholder = "Select...",
614
+ recipe = "auto",
615
+ required = false,
616
+ searchEmptyMessage = "No results",
617
+ searchPlaceholder = "Search...",
618
+ searchPredicate = defaultSearchPredicate,
619
+ size = "md",
620
+ TriggerStartIcon,
621
+ TriggerView,
622
+ triggerClassName,
623
+ value,
624
+ variant = "outline"
625
+ }) {
626
+ const [open, setOpen] = React.useState(defaultOpen);
627
+ const [search, setSearch] = React.useState("");
628
+ const allOptions = React.useMemo(() => flattenOptions(options), [options]);
629
+ const filteredOptions = React.useMemo(
630
+ () => allOptions.filter((option) => searchPredicate(option, search)),
631
+ [allOptions, search, searchPredicate]
632
+ );
633
+ const selectedOptions = React.useMemo(() => {
634
+ const values = Array.isArray(value) ? value : [value];
635
+ return allOptions.filter((option) => values.includes(option.value));
636
+ }, [allOptions, value]);
637
+ const selected = selectedOptions[0];
638
+ const triggerContent = renderSelectTriggerContent({
639
+ loading,
640
+ loadingPlaceholder,
641
+ multiple: Boolean(multiple),
642
+ placeholder,
643
+ selected,
644
+ selectedOptions,
645
+ TriggerView
646
+ });
647
+ const commitOption = (option) => {
648
+ if (option.disabled) {
649
+ return;
650
+ }
651
+ if (multiple) {
652
+ const current = selectedOptions.some((selectedOption) => selectedOption.value === option.value) ? selectedOptions.filter((selectedOption) => selectedOption.value !== option.value) : [...selectedOptions, option];
653
+ onChange(current);
654
+ return;
655
+ }
656
+ onChange(option);
657
+ setOpen(false);
658
+ };
659
+ return React.createElement(
660
+ "div",
661
+ {
662
+ "data-sc-block": block ? "" : void 0,
663
+ "data-sc-component": "select",
664
+ "data-sc-open": open ? "" : void 0,
665
+ "data-sc-recipe": recipe
666
+ },
667
+ React.createElement(SelectControl, {
668
+ block,
669
+ children: triggerContent,
670
+ className: triggerClassName,
671
+ disabled,
672
+ dropdownIconType,
673
+ id,
674
+ loading,
675
+ onClearClick: clearable && selectedOptions.length > 0 ? () => {
676
+ if (multiple) {
677
+ onChange([]);
678
+ } else {
679
+ onChange({ label: "", value: "" });
680
+ }
681
+ } : void 0,
682
+ onInteract: () => setOpen((next) => !next),
683
+ opticallyAlign,
684
+ pill,
685
+ recipe,
686
+ selected: selectedOptions.length > 0,
687
+ size,
688
+ StartIcon: TriggerStartIcon,
689
+ variant
690
+ }),
691
+ name ? renderHiddenSelectInputs({
692
+ disabled,
693
+ multiple: Boolean(multiple),
694
+ name,
695
+ required,
696
+ selectedOptions,
697
+ value
698
+ }) : null,
699
+ open ? React.createElement(
700
+ "div",
701
+ {
702
+ role: "listbox",
703
+ "aria-multiselectable": multiple || void 0,
704
+ "data-sc-component": "select-list",
705
+ "data-sc-recipe": recipe
706
+ },
707
+ React.createElement(Input, {
708
+ "aria-label": searchPlaceholder,
709
+ onChange: (event) => setSearch(event.currentTarget.value),
710
+ placeholder: searchPlaceholder,
711
+ recipe,
712
+ size: "sm",
713
+ value: search
714
+ }),
715
+ filteredOptions.length === 0 ? React.createElement("div", { "data-sc-component": "select-empty" }, searchEmptyMessage) : filteredOptions.map((option) => {
716
+ const selectedOption = selectedOptions.some((selectedCandidate) => selectedCandidate.value === option.value);
717
+ return React.createElement(
718
+ "button",
719
+ {
720
+ className: void 0,
721
+ disabled: option.disabled,
722
+ key: option.value,
723
+ onClick: () => commitOption(option),
724
+ role: "option",
725
+ type: "button",
726
+ "aria-selected": selectedOption,
727
+ "data-sc-component": "select-option",
728
+ "data-sc-disabled": option.disabled ? "" : void 0,
729
+ "data-sc-selected": selectedOption ? "" : void 0
730
+ },
731
+ OptionView ? React.createElement(OptionView, option) : React.createElement(
732
+ React.Fragment,
733
+ null,
734
+ React.createElement("span", { "data-sc-component": "select-option-label" }, option.label),
735
+ option.description ? React.createElement("span", { "data-sc-component": "select-option-description" }, option.description) : null
736
+ )
737
+ );
738
+ }),
739
+ actions?.length ? React.createElement(
740
+ "div",
741
+ { "data-sc-component": "select-actions" },
742
+ actions.map(
743
+ (action) => React.createElement(
744
+ "button",
745
+ {
746
+ className: action.className,
747
+ key: action.id,
748
+ onClick: () => action.onSelect(action.id),
749
+ type: "button",
750
+ "data-sc-component": "select-action"
751
+ },
752
+ action.Icon ? React.createElement(action.Icon, { "aria-hidden": true }) : null,
753
+ action.label
754
+ )
755
+ )
756
+ ) : null
757
+ ) : null
758
+ );
759
+ }
760
+ var SelectControl = React.forwardRef(function SelectControl2({
761
+ block = true,
762
+ children,
763
+ disabled = false,
764
+ dropdownIconType = "dropdown",
765
+ invalid = false,
766
+ loading = false,
767
+ onClearClick,
768
+ onInteract,
769
+ opticallyAlign,
770
+ pill = false,
771
+ recipe = "auto",
772
+ selected = false,
773
+ size = "md",
774
+ StartIcon,
775
+ tabIndex,
776
+ variant = "outline",
777
+ ...props
778
+ }, ref) {
779
+ return React.createElement(
780
+ "span",
781
+ {
782
+ ref,
783
+ role: "button",
784
+ tabIndex: disabled ? -1 : tabIndex ?? 0,
785
+ onClick: () => {
786
+ if (!disabled) {
787
+ onInteract?.();
788
+ }
789
+ },
790
+ onKeyDown: (event) => {
791
+ props.onKeyDown?.(event);
792
+ if (!disabled && !event.defaultPrevented && (event.key === "Enter" || event.key === " ")) {
793
+ event.preventDefault();
794
+ onInteract?.();
795
+ }
796
+ },
797
+ "data-sc-block": block ? "" : void 0,
798
+ "data-sc-component": "select-control",
799
+ "data-sc-disabled": disabled ? "" : void 0,
800
+ "data-sc-invalid": invalid ? "" : void 0,
801
+ "data-sc-optically-align": opticallyAlign,
802
+ "data-sc-pill": pill ? "" : void 0,
803
+ "data-sc-recipe": recipe,
804
+ "data-sc-selected": selected ? "" : void 0,
805
+ "data-sc-size": size,
806
+ "data-sc-variant": variant,
807
+ ...props
808
+ },
809
+ StartIcon ? React.createElement(StartIcon, { "aria-hidden": true }) : null,
810
+ React.createElement("span", { "data-sc-component": "select-control-value" }, children),
811
+ loading ? React.createElement(LoadingIndicator, { "aria-hidden": true, size: "1em" }) : null,
812
+ onClearClick ? React.createElement(
813
+ "button",
814
+ {
815
+ "aria-label": "Clear selection",
816
+ onClick: (event) => {
817
+ event.stopPropagation();
818
+ onClearClick();
819
+ },
820
+ type: "button",
821
+ "data-sc-component": "select-clear"
822
+ },
823
+ "\xD7"
824
+ ) : null,
825
+ dropdownIconType === "none" ? null : React.createElement("span", { "aria-hidden": true, "data-sc-component": "select-dropdown-icon" }, dropdownIconType === "chevronDown" ? "\u2304" : "\u25BE")
826
+ );
827
+ });
828
+ var Badge = React.forwardRef(function Badge2({
829
+ children,
830
+ color,
831
+ pill = false,
832
+ recipe = "auto",
833
+ size = "sm",
834
+ tone,
835
+ variant = "soft",
836
+ ...props
837
+ }, ref) {
838
+ const resolvedColor = color ?? toneToColor(tone) ?? "secondary";
839
+ return React.createElement(
840
+ "span",
841
+ {
842
+ ref,
843
+ "data-sc-color": resolvedColor,
844
+ "data-sc-component": "badge",
845
+ "data-sc-pill": pill ? "" : void 0,
846
+ "data-sc-recipe": recipe,
847
+ "data-sc-size": size,
848
+ "data-sc-tone": tone,
849
+ "data-sc-variant": variant,
850
+ ...props
851
+ },
852
+ children
853
+ );
854
+ });
855
+ var Alert = React.forwardRef(function Alert2({
856
+ actions,
857
+ actionsClassName,
858
+ actionsPlacement,
859
+ children,
860
+ color,
861
+ description,
862
+ indicator,
863
+ recipe = "auto",
864
+ role = "note",
865
+ title,
866
+ tone,
867
+ variant = "soft",
868
+ ...props
869
+ }, ref) {
870
+ const resolvedColor = color ?? toneToColor(tone) ?? "primary";
871
+ return React.createElement(
872
+ "div",
873
+ {
874
+ ref,
875
+ role,
876
+ "data-sc-actions-placement": actionsPlacement,
877
+ "data-sc-color": resolvedColor,
878
+ "data-sc-component": "alert",
879
+ "data-sc-recipe": recipe,
880
+ "data-sc-tone": tone,
881
+ "data-sc-variant": variant,
882
+ ...props
883
+ },
884
+ indicator === false ? null : React.createElement(
885
+ "span",
886
+ { "aria-hidden": true, "data-sc-component": "alert-indicator" },
887
+ indicator ?? "\u2022"
888
+ ),
889
+ React.createElement(
890
+ "div",
891
+ { "data-sc-component": "alert-content" },
892
+ title ? React.createElement("div", { "data-sc-component": "alert-title" }, title) : null,
893
+ description ? React.createElement("div", { "data-sc-component": "alert-description" }, description) : null,
894
+ children
895
+ ),
896
+ actions ? React.createElement(
897
+ "div",
898
+ { className: actionsClassName, "data-sc-component": "alert-actions" },
899
+ actions
900
+ ) : null
901
+ );
902
+ });
903
+ var Callout = Alert;
904
+ var Avatar = React.forwardRef(function Avatar2({
905
+ alt = "",
906
+ color = "secondary",
907
+ fallback,
908
+ Icon,
909
+ imageUrl,
910
+ name,
911
+ overflowCount,
912
+ recipe = "auto",
913
+ size = 28,
914
+ src,
915
+ variant = "soft",
916
+ ...props
917
+ }, ref) {
918
+ const url = imageUrl ?? src;
919
+ const label = overflowCount !== void 0 ? formatOverflow(overflowCount) : initialsFromName(name);
920
+ const interactive = Boolean(props.onClick || props.onPointerDown);
921
+ return React.createElement(
922
+ "span",
923
+ {
924
+ ref,
925
+ role: interactive ? "button" : void 0,
926
+ tabIndex: interactive ? 0 : void 0,
927
+ "data-sc-color": color,
928
+ "data-sc-component": "avatar",
929
+ "data-sc-interactive": interactive ? "" : void 0,
930
+ "data-sc-recipe": recipe,
931
+ "data-sc-variant": variant,
932
+ style: { "--sc-avatar-size": `${size}px`, ...props.style },
933
+ ...props
934
+ },
935
+ url ? React.createElement("img", { alt, src: url }) : null,
936
+ !url && Icon ? React.createElement(Icon, { "aria-hidden": true }) : null,
937
+ !url && !Icon ? fallback ?? label : null
938
+ );
939
+ });
940
+ function AvatarGroup({ children, className, recipe = "auto", size, stack = "start" }) {
941
+ return React.createElement(
942
+ "div",
943
+ {
944
+ className,
945
+ "data-sc-component": "avatar-group",
946
+ "data-sc-recipe": recipe,
947
+ "data-sc-stack": stack,
948
+ style: size ? { "--sc-avatar-size": `${size}px` } : void 0
949
+ },
950
+ children
951
+ );
952
+ }
953
+ var EmptyMessageContext = React.createContext("auto");
954
+ function EmptyMessageRoot({ children, className, fill = "static", recipe = "auto" }) {
955
+ return React.createElement(
956
+ EmptyMessageContext.Provider,
957
+ { value: recipe },
958
+ React.createElement(
959
+ "div",
960
+ {
961
+ className,
962
+ "data-sc-component": "empty-message",
963
+ "data-sc-fill": fill,
964
+ "data-sc-recipe": recipe
965
+ },
966
+ children
967
+ )
968
+ );
969
+ }
970
+ function EmptyMessageIcon({ children, className, color = "secondary", recipe, size = "sm" }) {
971
+ const inheritedRecipe = React.useContext(EmptyMessageContext);
972
+ return React.createElement(
973
+ "div",
974
+ {
975
+ className,
976
+ "data-sc-color": color,
977
+ "data-sc-component": "empty-message-icon",
978
+ "data-sc-recipe": recipe ?? inheritedRecipe,
979
+ "data-sc-size": size
980
+ },
981
+ children
982
+ );
983
+ }
984
+ function EmptyMessageTitle({ children, className, color = "secondary", recipe }) {
985
+ const inheritedRecipe = React.useContext(EmptyMessageContext);
986
+ return React.createElement(
987
+ "div",
988
+ {
989
+ className,
990
+ "data-sc-color": color,
991
+ "data-sc-component": "empty-message-title",
992
+ "data-sc-recipe": recipe ?? inheritedRecipe
993
+ },
994
+ children
995
+ );
996
+ }
997
+ function EmptyMessageDescription({
998
+ children,
999
+ className
1000
+ }) {
1001
+ return React.createElement("div", { className, "data-sc-component": "empty-message-description" }, children);
1002
+ }
1003
+ function EmptyMessageActionRow({
1004
+ children,
1005
+ className
1006
+ }) {
1007
+ return React.createElement("div", { className, "data-sc-component": "empty-message-actions" }, children);
1008
+ }
1009
+ var EmptyMessage = Object.assign(EmptyMessageRoot, {
1010
+ ActionRow: EmptyMessageActionRow,
1011
+ Description: EmptyMessageDescription,
1012
+ Icon: EmptyMessageIcon,
1013
+ Title: EmptyMessageTitle
1014
+ });
1015
+ var EmptyState = React.forwardRef(function EmptyState2({ action, children, recipe = "auto", title, ...props }, ref) {
1016
+ return React.createElement(
1017
+ "div",
1018
+ { ref, ...props },
1019
+ React.createElement(
1020
+ EmptyMessage,
1021
+ {
1022
+ recipe,
1023
+ children: [
1024
+ React.createElement(EmptyMessage.Title, { children: title, key: "title" }),
1025
+ children ? React.createElement(EmptyMessage.Description, { children, key: "description" }) : null,
1026
+ action ? React.createElement(EmptyMessage.ActionRow, { children: action, key: "action" }) : null
1027
+ ]
1028
+ }
1029
+ )
1030
+ );
1031
+ });
1032
+ function LoadingDots({ recipe = "auto", ...props }) {
1033
+ return React.createElement(
1034
+ "div",
1035
+ {
1036
+ "aria-hidden": true,
1037
+ "data-sc-component": "loading-dots",
1038
+ "data-sc-recipe": recipe,
1039
+ ...props
1040
+ },
1041
+ React.createElement("span", null),
1042
+ React.createElement("span", null),
1043
+ React.createElement("span", null)
1044
+ );
1045
+ }
1046
+ function LoadingIndicator({
1047
+ className,
1048
+ recipe = "auto",
1049
+ size = "1em",
1050
+ strokeWidth = 2,
1051
+ style,
1052
+ ...props
1053
+ }) {
1054
+ return React.createElement(
1055
+ "div",
1056
+ {
1057
+ className,
1058
+ "data-sc-component": "loading-indicator",
1059
+ "data-sc-recipe": recipe,
1060
+ style: { "--sc-indicator-size": typeof size === "number" ? `${size}px` : size, ...style },
1061
+ ...props
1062
+ },
1063
+ React.createElement(
1064
+ "svg",
1065
+ {
1066
+ viewBox: "0 0 24 24",
1067
+ "aria-hidden": true
1068
+ },
1069
+ React.createElement("circle", {
1070
+ cx: 12,
1071
+ cy: 12,
1072
+ r: 9,
1073
+ fill: "none",
1074
+ stroke: "currentColor",
1075
+ strokeLinecap: "round",
1076
+ strokeWidth
1077
+ })
1078
+ )
1079
+ );
1080
+ }
1081
+ function CircularProgress({
1082
+ className,
1083
+ done = false,
1084
+ progress,
1085
+ recipe = "auto",
1086
+ size = 28,
1087
+ strokeWidth = 2,
1088
+ style,
1089
+ trackActiveColor = "currentColor",
1090
+ trackColor = "color-mix(in srgb, currentColor 18%, transparent)",
1091
+ ...props
1092
+ }) {
1093
+ const value = done ? 100 : Math.max(0, Math.min(100, progress ?? 66));
1094
+ const radius = 10;
1095
+ const circumference = 2 * Math.PI * radius;
1096
+ const dashOffset = circumference - value / 100 * circumference;
1097
+ return React.createElement(
1098
+ "div",
1099
+ {
1100
+ className,
1101
+ role: "progressbar",
1102
+ "aria-valuemax": 100,
1103
+ "aria-valuemin": 0,
1104
+ "aria-valuenow": value,
1105
+ "data-sc-component": "circular-progress",
1106
+ "data-sc-recipe": recipe,
1107
+ style: { "--sc-progress-size": typeof size === "number" ? `${size}px` : size, ...style },
1108
+ ...props
1109
+ },
1110
+ React.createElement(
1111
+ "svg",
1112
+ { viewBox: "0 0 24 24", "aria-hidden": true },
1113
+ React.createElement("circle", {
1114
+ cx: 12,
1115
+ cy: 12,
1116
+ fill: "none",
1117
+ r: radius,
1118
+ stroke: trackColor,
1119
+ strokeWidth
1120
+ }),
1121
+ React.createElement("circle", {
1122
+ cx: 12,
1123
+ cy: 12,
1124
+ fill: "none",
1125
+ r: radius,
1126
+ stroke: trackActiveColor,
1127
+ strokeDasharray: circumference,
1128
+ strokeDashoffset: dashOffset,
1129
+ strokeLinecap: "round",
1130
+ strokeWidth,
1131
+ transform: "rotate(-90 12 12)"
1132
+ })
1133
+ )
1134
+ );
1135
+ }
1136
+ var Spinner = LoadingIndicator;
1137
+ var Progress = React.forwardRef(function Progress2({ recipe = "auto", ...props }, ref) {
1138
+ return React.createElement("progress", {
1139
+ ref,
1140
+ "data-sc-component": "progress",
1141
+ "data-sc-recipe": recipe,
1142
+ ...props
1143
+ });
1144
+ });
1145
+ function ShimmerText({ as: Tag = "span", children, className, recipe = "auto" }) {
1146
+ return React.createElement(
1147
+ Tag,
1148
+ {
1149
+ className,
1150
+ "data-sc-component": "shimmer-text",
1151
+ "data-sc-recipe": recipe
1152
+ },
1153
+ children
1154
+ );
1155
+ }
1156
+ var TextLink = React.forwardRef(function TextLink2({
1157
+ children,
1158
+ forceExternal,
1159
+ href,
1160
+ primary = false,
1161
+ recipe = "auto",
1162
+ rel,
1163
+ target,
1164
+ underline = true,
1165
+ ...props
1166
+ }, ref) {
1167
+ const external = forceExternal ?? Boolean(href && /^(?:[a-z][a-z0-9+.-]*:)?\/\//i.test(href));
1168
+ return React.createElement(
1169
+ "a",
1170
+ {
1171
+ ref,
1172
+ "data-sc-component": "text-link",
1173
+ "data-sc-primary": primary ? "" : void 0,
1174
+ "data-sc-recipe": recipe,
1175
+ "data-sc-underline": underline ? "" : void 0,
1176
+ href,
1177
+ rel: external && target === "_blank" ? mergeRel(rel, "noopener noreferrer") : rel,
1178
+ target,
1179
+ ...props
1180
+ },
1181
+ children
1182
+ );
1183
+ });
1184
+ var Image = React.forwardRef(function Image2({ forceRenderAfterLoadFail: _forceRenderAfterLoadFail, recipe = "auto", ...props }, ref) {
1185
+ return React.createElement("img", {
1186
+ ref,
1187
+ "data-sc-component": "image",
1188
+ "data-sc-recipe": recipe,
1189
+ ...props
1190
+ });
1191
+ });
1192
+ var Skeleton = React.forwardRef(function Skeleton2({ height, recipe = "auto", style, width, ...props }, ref) {
1193
+ return React.createElement("div", {
1194
+ ref,
1195
+ "aria-hidden": true,
1196
+ "data-sc-component": "skeleton",
1197
+ "data-sc-recipe": recipe,
1198
+ style: { width, height, ...style },
1199
+ ...props
1200
+ });
1201
+ });
1202
+ var FieldContext = React.createContext(null);
1203
+ function FormField({
1204
+ children,
1205
+ disabled = false,
1206
+ id,
1207
+ invalid = false,
1208
+ recipe = "auto",
1209
+ required = false,
1210
+ ...props
1211
+ }) {
1212
+ const generatedId = React.useId();
1213
+ const controlId = id ?? generatedId;
1214
+ const context = React.useMemo(
1215
+ () => ({
1216
+ controlId,
1217
+ descriptionId: `${controlId}-description`,
1218
+ disabled,
1219
+ errorId: `${controlId}-error`,
1220
+ invalid,
1221
+ required
1222
+ }),
1223
+ [controlId, disabled, invalid, required]
1224
+ );
1225
+ return React.createElement(
1226
+ FieldContext.Provider,
1227
+ { value: context },
1228
+ React.createElement(
1229
+ "div",
1230
+ {
1231
+ "data-sc-component": "form-field",
1232
+ "data-sc-disabled": disabled ? "" : void 0,
1233
+ "data-sc-invalid": invalid ? "" : void 0,
1234
+ "data-sc-recipe": recipe,
1235
+ ...props
1236
+ },
1237
+ children
1238
+ )
1239
+ );
1240
+ }
1241
+ var FieldLabel = React.forwardRef(function FieldLabel2({ children, htmlFor, recipe = "auto", ...props }, ref) {
1242
+ const field = React.useContext(FieldContext);
1243
+ return React.createElement(
1244
+ "label",
1245
+ {
1246
+ ref,
1247
+ htmlFor: htmlFor ?? field?.controlId,
1248
+ "data-sc-component": "field-label",
1249
+ "data-sc-recipe": recipe,
1250
+ ...props
1251
+ },
1252
+ children,
1253
+ field?.required ? React.createElement("span", { "aria-hidden": true, "data-sc-component": "field-required" }, "*") : null
1254
+ );
1255
+ });
1256
+ var FieldDescription = React.forwardRef(function FieldDescription2({ id, recipe = "auto", ...props }, ref) {
1257
+ const field = React.useContext(FieldContext);
1258
+ return React.createElement("p", {
1259
+ ref,
1260
+ id: id ?? field?.descriptionId,
1261
+ "data-sc-component": "field-description",
1262
+ "data-sc-recipe": recipe,
1263
+ ...props
1264
+ });
1265
+ });
1266
+ var FieldError = React.forwardRef(function FieldError2({ id, recipe = "auto", ...props }, ref) {
1267
+ const field = React.useContext(FieldContext);
1268
+ return React.createElement("p", {
1269
+ ref,
1270
+ id: id ?? field?.errorId,
1271
+ role: "alert",
1272
+ "data-sc-component": "field-error",
1273
+ "data-sc-recipe": recipe,
1274
+ ...props
1275
+ });
1276
+ });
1277
+ var Surface = React.forwardRef(function Surface2({ recipe = "auto", variant = "plain", ...props }, ref) {
1278
+ return React.createElement("div", {
1279
+ ref,
1280
+ "data-sc-component": "surface",
1281
+ "data-sc-recipe": recipe,
1282
+ "data-sc-variant": variant,
1283
+ ...props
1284
+ });
1285
+ });
1286
+ var Stack = React.forwardRef(function Stack2({ gap = "md", recipe = "auto", ...props }, ref) {
1287
+ return React.createElement("div", {
1288
+ ref,
1289
+ "data-sc-component": "stack",
1290
+ "data-sc-gap": gap,
1291
+ "data-sc-recipe": recipe,
1292
+ ...props
1293
+ });
1294
+ });
1295
+ var Inline = React.forwardRef(function Inline2({ align = "center", gap = "sm", recipe = "auto", wrap = true, ...props }, ref) {
1296
+ return React.createElement("div", {
1297
+ ref,
1298
+ "data-sc-align": align,
1299
+ "data-sc-component": "inline",
1300
+ "data-sc-gap": gap,
1301
+ "data-sc-recipe": recipe,
1302
+ "data-sc-wrap": wrap ? "" : void 0,
1303
+ ...props
1304
+ });
1305
+ });
1306
+ var Divider = React.forwardRef(function Divider2({ recipe = "auto", ...props }, ref) {
1307
+ return React.createElement("hr", {
1308
+ ref,
1309
+ "data-sc-component": "divider",
1310
+ "data-sc-recipe": recipe,
1311
+ ...props
1312
+ });
1313
+ });
1314
+ var Code = React.forwardRef(function Code2({ recipe = "auto", ...props }, ref) {
1315
+ return React.createElement("code", {
1316
+ ref,
1317
+ "data-sc-component": "code",
1318
+ "data-sc-recipe": recipe,
1319
+ ...props
1320
+ });
1321
+ });
1322
+ var Tabs = React.forwardRef(function Tabs2({ recipe = "auto", ...props }, ref) {
1323
+ return React.createElement("div", {
1324
+ ref,
1325
+ "data-sc-component": "tabs",
1326
+ "data-sc-recipe": recipe,
1327
+ ...props
1328
+ });
1329
+ });
1330
+ var Slider = React.forwardRef(function Slider2({ recipe = "auto", ...props }, ref) {
1331
+ return React.createElement("input", {
1332
+ ref,
1333
+ type: "range",
1334
+ "data-sc-component": "slider",
1335
+ "data-sc-recipe": recipe,
1336
+ ...props
1337
+ });
1338
+ });
1339
+ var Table = React.forwardRef(function Table2({ recipe = "auto", ...props }, ref) {
1340
+ return React.createElement("table", {
1341
+ ref,
1342
+ "data-sc-component": "table",
1343
+ "data-sc-recipe": recipe,
1344
+ ...props
1345
+ });
1346
+ });
1347
+ var KeyValue = React.forwardRef(function KeyValue2({ items, recipe = "auto", ...props }, ref) {
1348
+ return React.createElement(
1349
+ "dl",
1350
+ {
1351
+ ref,
1352
+ "data-sc-component": "key-value",
1353
+ "data-sc-recipe": recipe,
1354
+ ...props
1355
+ },
1356
+ items.map(
1357
+ (item, index) => React.createElement(
1358
+ "div",
1359
+ { "data-sc-component": "key-value-row", key: index },
1360
+ React.createElement("dt", null, item.key),
1361
+ React.createElement("dd", null, item.value)
1362
+ )
1363
+ )
1364
+ );
1365
+ });
1366
+ function createPrimitiveComponents(recipe) {
1367
+ return {
1368
+ Alert: pinRecipe(Alert, recipe),
1369
+ Avatar: pinRecipe(Avatar, recipe),
1370
+ AvatarGroup: pinRecipe(AvatarGroup, recipe),
1371
+ Badge: pinRecipe(Badge, recipe),
1372
+ Button: pinRecipe(Button, recipe),
1373
+ ButtonLink: pinRecipe(ButtonLink, recipe),
1374
+ Callout: pinRecipe(Callout, recipe),
1375
+ Checkbox: pinRecipe(Checkbox, recipe),
1376
+ CircularProgress: pinRecipe(CircularProgress, recipe),
1377
+ Code: pinRecipe(Code, recipe),
1378
+ CopyButton: pinRecipe(CopyButton, recipe),
1379
+ Divider: pinRecipe(Divider, recipe),
1380
+ EmptyMessage: pinRecipe(EmptyMessage, recipe),
1381
+ EmptyState: pinRecipe(EmptyState, recipe),
1382
+ FieldDescription: pinRecipe(FieldDescription, recipe),
1383
+ FieldError: pinRecipe(FieldError, recipe),
1384
+ FieldLabel: pinRecipe(FieldLabel, recipe),
1385
+ FormField: pinRecipe(FormField, recipe),
1386
+ Heading: pinRecipe(Heading, recipe),
1387
+ Image: pinRecipe(Image, recipe),
1388
+ Inline: pinRecipe(Inline, recipe),
1389
+ Input: pinRecipe(Input, recipe),
1390
+ KeyValue: pinRecipe(KeyValue, recipe),
1391
+ LoadingDots: pinRecipe(LoadingDots, recipe),
1392
+ LoadingIndicator: pinRecipe(LoadingIndicator, recipe),
1393
+ Progress: pinRecipe(Progress, recipe),
1394
+ RadioGroup: pinRecipe(RadioGroup, recipe),
1395
+ SegmentedControl: pinRecipe(SegmentedControl, recipe),
1396
+ Select: pinRecipe(Select, recipe),
1397
+ SelectControl: pinRecipe(SelectControl, recipe),
1398
+ ShimmerText: pinRecipe(ShimmerText, recipe),
1399
+ Skeleton: pinRecipe(Skeleton, recipe),
1400
+ Slider: pinRecipe(Slider, recipe),
1401
+ Spinner: pinRecipe(Spinner, recipe),
1402
+ Stack: pinRecipe(Stack, recipe),
1403
+ Surface: pinRecipe(Surface, recipe),
1404
+ Switch: pinRecipe(Switch, recipe),
1405
+ Table: pinRecipe(Table, recipe),
1406
+ Tabs: pinRecipe(Tabs, recipe),
1407
+ Text: pinRecipe(Text, recipe),
1408
+ Textarea: pinRecipe(Textarea, recipe),
1409
+ TextField: pinRecipe(TextField, recipe),
1410
+ TextLink: pinRecipe(TextLink, recipe)
1411
+ };
1412
+ }
1413
+ function normalizeButtonVisual({
1414
+ color,
1415
+ intent,
1416
+ variant
1417
+ }) {
1418
+ if (variant && isSemanticColor(variant)) {
1419
+ return { color: variant, variant: defaultVariantForColor(variant) };
1420
+ }
1421
+ if (variant === "ghost") {
1422
+ return { color: color ?? "secondary", variant: "ghost" };
1423
+ }
1424
+ if (intent === "ghost") {
1425
+ return { color: color ?? "secondary", variant: "ghost" };
1426
+ }
1427
+ const resolvedColor = color ?? (intent && isSemanticColor(intent) ? intent : "secondary");
1428
+ return { color: resolvedColor, variant: variant ?? defaultVariantForColor(resolvedColor) };
1429
+ }
1430
+ function defaultVariantForColor(color) {
1431
+ return color === "secondary" ? "soft" : "solid";
1432
+ }
1433
+ function isSemanticColor(value) {
1434
+ return ["primary", "secondary", "danger", "success", "warning", "caution", "discovery", "info"].includes(value);
1435
+ }
1436
+ function toneToColor(tone) {
1437
+ switch (tone) {
1438
+ case "success":
1439
+ return "success";
1440
+ case "warning":
1441
+ return "warning";
1442
+ case "danger":
1443
+ return "danger";
1444
+ case "default":
1445
+ case void 0:
1446
+ return void 0;
1447
+ }
1448
+ }
1449
+ function mergeRel(current, required) {
1450
+ return [.../* @__PURE__ */ new Set([...current?.split(/\s+/).filter(Boolean) ?? [], ...required.split(/\s+/)])].join(" ");
1451
+ }
1452
+ function useControllableValue({
1453
+ controlled,
1454
+ defaultValue,
1455
+ onChange
1456
+ }) {
1457
+ const [uncontrolled, setUncontrolled] = React.useState(defaultValue);
1458
+ const value = controlled ?? uncontrolled;
1459
+ const setValue = React.useCallback(
1460
+ (nextValue) => {
1461
+ if (controlled === void 0) {
1462
+ setUncontrolled(nextValue);
1463
+ }
1464
+ onChange?.(nextValue);
1465
+ },
1466
+ [controlled, onChange]
1467
+ );
1468
+ return [value, setValue];
1469
+ }
1470
+ function useRequiredContext(context, message) {
1471
+ const value = React.useContext(context);
1472
+ if (value === null) {
1473
+ throw new Error(message);
1474
+ }
1475
+ return value;
1476
+ }
1477
+ function useMergedRefs(...refs) {
1478
+ return React.useCallback(
1479
+ (node) => {
1480
+ for (const ref of refs) {
1481
+ if (!ref) {
1482
+ continue;
1483
+ }
1484
+ if (typeof ref === "function") {
1485
+ ref(node);
1486
+ } else {
1487
+ ref.current = node;
1488
+ }
1489
+ }
1490
+ },
1491
+ [refs]
1492
+ );
1493
+ }
1494
+ function describedBy(existing, field, invalid) {
1495
+ const ids = [existing, field?.descriptionId, invalid ? field?.errorId : void 0].filter(Boolean);
1496
+ return ids.length ? ids.join(" ") : void 0;
1497
+ }
1498
+ function flattenOptions(options) {
1499
+ return options.flatMap((entry) => isOptionGroup(entry) ? entry.options : [entry]);
1500
+ }
1501
+ function isOptionGroup(entry) {
1502
+ return Array.isArray(entry.options);
1503
+ }
1504
+ function defaultSearchPredicate(option, searchTerm) {
1505
+ if (!searchTerm) {
1506
+ return true;
1507
+ }
1508
+ return `${option.label} ${option.description ?? ""}`.toLowerCase().includes(searchTerm.toLowerCase());
1509
+ }
1510
+ function renderSelectTriggerContent({
1511
+ loading,
1512
+ loadingPlaceholder,
1513
+ multiple,
1514
+ placeholder,
1515
+ selected,
1516
+ selectedOptions,
1517
+ TriggerView
1518
+ }) {
1519
+ if (loading && selectedOptions.length === 0) {
1520
+ return loadingPlaceholder;
1521
+ }
1522
+ if (TriggerView) {
1523
+ const View = TriggerView;
1524
+ return multiple ? React.createElement(View, {
1525
+ selectedAll: false,
1526
+ values: selectedOptions
1527
+ }) : selected ? React.createElement(View, selected) : placeholder;
1528
+ }
1529
+ if (multiple) {
1530
+ return selectedOptions.length ? `${selectedOptions.length} selected` : placeholder;
1531
+ }
1532
+ return selected?.label || placeholder;
1533
+ }
1534
+ function renderHiddenSelectInputs({
1535
+ disabled,
1536
+ multiple,
1537
+ name,
1538
+ required,
1539
+ selectedOptions,
1540
+ value
1541
+ }) {
1542
+ if (multiple) {
1543
+ return selectedOptions.map(
1544
+ (option) => React.createElement("input", {
1545
+ disabled,
1546
+ key: option.value,
1547
+ name,
1548
+ readOnly: true,
1549
+ required,
1550
+ type: "hidden",
1551
+ value: option.value
1552
+ })
1553
+ );
1554
+ }
1555
+ return React.createElement("input", {
1556
+ disabled,
1557
+ name,
1558
+ readOnly: true,
1559
+ required,
1560
+ type: "hidden",
1561
+ value: Array.isArray(value) ? "" : value
1562
+ });
1563
+ }
1564
+ function initialsFromName(name) {
1565
+ if (!name) {
1566
+ return null;
1567
+ }
1568
+ const initials = name.trim().split(/\s+/).slice(0, 2).map((part) => part[0]?.toUpperCase()).join("");
1569
+ return initials || null;
1570
+ }
1571
+ function formatOverflow(count) {
1572
+ return count > 99 ? "99+" : `+${count}`;
1573
+ }
1574
+ async function copyToClipboard(value) {
1575
+ if (typeof navigator !== "undefined" && navigator.clipboard?.writeText) {
1576
+ await navigator.clipboard.writeText(typeof value === "string" ? value : Object.values(value).join("\n"));
1577
+ }
1578
+ }
1579
+ function pinRecipe(Component, recipe) {
1580
+ const ComponentWithRecipe = Component;
1581
+ const Wrapped = ((props) => React.createElement(ComponentWithRecipe, { ...props, recipe }));
1582
+ Object.assign(Wrapped, Component);
1583
+ return Wrapped;
1584
+ }
1585
+
1586
+ // packages/native/src/index.ts
1587
+ var host = {
1588
+ /** Detects the current host from browser globals. */
1589
+ current() {
1590
+ const context = detectSidecarHostContext();
1591
+ if (context.name === "chatgpt") {
1592
+ return "chatgpt";
1593
+ }
1594
+ if (context.name === "claude") {
1595
+ return "claude";
1596
+ }
1597
+ return "unknown";
1598
+ }
1599
+ };
1600
+ var capabilities = {
1601
+ /** Returns one stable support state for a known capability. */
1602
+ get(capability) {
1603
+ const standard = browserBridge.getHostCapabilities();
1604
+ const context = detectSidecarHostContext().raw;
1605
+ switch (capability) {
1606
+ case "display.fullscreen":
1607
+ return context?.availableDisplayModes?.includes("fullscreen") ? "supported" : "unsupported";
1608
+ case "display.pip":
1609
+ return context?.availableDisplayModes?.includes("pip") ? "supported" : "unsupported";
1610
+ case "files.select":
1611
+ return typeof document === "undefined" ? "unsupported" : "browser-fallback";
1612
+ case "files.download":
1613
+ return standard?.downloadFile ? "supported" : typeof document === "undefined" || typeof URL === "undefined" ? "unsupported" : "browser-fallback";
1614
+ case "links.openExternal":
1615
+ return standard?.openLinks ? "supported" : typeof window === "undefined" ? "unsupported" : "browser-fallback";
1616
+ }
1617
+ },
1618
+ /** Returns every known capability state as a plain object. */
1619
+ all() {
1620
+ return {
1621
+ "display.fullscreen": this.get("display.fullscreen"),
1622
+ "display.pip": this.get("display.pip"),
1623
+ "files.select": this.get("files.select"),
1624
+ "files.download": this.get("files.download"),
1625
+ "links.openExternal": this.get("links.openExternal")
1626
+ };
1627
+ }
1628
+ };
1629
+ var display = {
1630
+ /** Requests a widget display mode when the host supports it. */
1631
+ async request(mode) {
1632
+ try {
1633
+ const result = await browserBridge.requestDisplayMode(mode);
1634
+ return result.ok ? { ok: true, value: void 0 } : result;
1635
+ } catch (error) {
1636
+ return normalizeHostError(error);
1637
+ }
1638
+ }
1639
+ };
1640
+ var files = {
1641
+ /** Requests files from the host when supported. */
1642
+ async select(options = {}) {
1643
+ return selectFilesWithBrowserInput(options);
1644
+ },
1645
+ /** Downloads a Blob/string using the browser's native download behavior. */
1646
+ async download(data, options) {
1647
+ const hostResult = await downloadWithHost(data, options);
1648
+ if (hostResult.ok || hostResult.reason !== "unsupported") {
1649
+ return hostResult;
1650
+ }
1651
+ if (typeof document === "undefined" || typeof URL === "undefined") {
1652
+ return { ok: false, reason: "unsupported" };
1653
+ }
1654
+ const blob = data instanceof Blob ? data : new Blob([data], { type: options.mimeType ?? "application/octet-stream" });
1655
+ const url = URL.createObjectURL(blob);
1656
+ const anchor = document.createElement("a");
1657
+ anchor.href = url;
1658
+ anchor.download = options.filename;
1659
+ anchor.rel = "noopener noreferrer";
1660
+ try {
1661
+ document.body.append(anchor);
1662
+ anchor.click();
1663
+ return { ok: true, value: void 0 };
1664
+ } catch (error) {
1665
+ return normalizeHostError(error);
1666
+ } finally {
1667
+ anchor.remove();
1668
+ URL.revokeObjectURL(url);
1669
+ }
1670
+ }
1671
+ };
1672
+ var links = {
1673
+ /** Opens an external URL through the host bridge when possible. */
1674
+ async openExternal(url) {
1675
+ const hostResult = await browserBridge.openLink(url);
1676
+ if (hostResult.ok || hostResult.reason !== "unsupported") {
1677
+ return hostResult;
1678
+ }
1679
+ return openWithBrowserFallback(url);
1680
+ }
1681
+ };
1682
+ function isAllowedExternalUrl(value) {
1683
+ try {
1684
+ const url = new URL(value);
1685
+ return url.protocol === "https:" || url.protocol === "http:" || url.protocol === "mailto:";
1686
+ } catch {
1687
+ return false;
1688
+ }
1689
+ }
1690
+ async function downloadWithHost(data, options) {
1691
+ try {
1692
+ const contents = typeof data === "string" ? [{
1693
+ type: "resource",
1694
+ resource: {
1695
+ uri: fileUri(options.filename),
1696
+ mimeType: options.mimeType ?? "text/plain",
1697
+ text: data
1698
+ }
1699
+ }] : [{
1700
+ type: "resource",
1701
+ resource: {
1702
+ uri: fileUri(options.filename),
1703
+ mimeType: options.mimeType ?? (data instanceof Blob ? data.type : void 0) ?? "application/octet-stream",
1704
+ blob: await blobPartToBase64(data, options.mimeType)
1705
+ }
1706
+ }];
1707
+ return browserBridge.downloadFile(contents);
1708
+ } catch (error) {
1709
+ return normalizeHostError(error);
1710
+ }
1711
+ }
1712
+ function fileUri(filename) {
1713
+ return `file:///${encodeURIComponent(filename.replace(/^[/\\]+/, ""))}`;
1714
+ }
1715
+ async function blobPartToBase64(data, mimeType) {
1716
+ const blob = data instanceof Blob ? data : new Blob([data], { type: mimeType ?? "application/octet-stream" });
1717
+ const bytes = new Uint8Array(await blob.arrayBuffer());
1718
+ let binary = "";
1719
+ for (const byte of bytes) {
1720
+ binary += String.fromCharCode(byte);
1721
+ }
1722
+ return btoa(binary);
1723
+ }
1724
+ function selectFilesWithBrowserInput(options) {
1725
+ if (typeof document === "undefined") {
1726
+ return Promise.resolve({ ok: false, reason: "unsupported" });
1727
+ }
1728
+ return new Promise((resolve) => {
1729
+ const input = document.createElement("input");
1730
+ input.type = "file";
1731
+ input.accept = options.accept?.join(",") ?? "";
1732
+ input.multiple = Boolean(options.multiple);
1733
+ input.style.position = "fixed";
1734
+ input.style.left = "-9999px";
1735
+ input.addEventListener("change", () => {
1736
+ const selected = input.files ? Array.from(input.files) : [];
1737
+ input.remove();
1738
+ resolve({ ok: true, value: selected });
1739
+ }, { once: true });
1740
+ input.addEventListener("cancel", () => {
1741
+ input.remove();
1742
+ resolve({ ok: false, reason: "cancelled" });
1743
+ }, { once: true });
1744
+ document.body.append(input);
1745
+ input.click();
1746
+ });
1747
+ }
1748
+ function openWithBrowserFallback(url) {
1749
+ if (!isAllowedExternalUrl(url)) {
1750
+ return {
1751
+ ok: false,
1752
+ reason: "denied",
1753
+ message: "Only http, https, and mailto URLs can be opened externally."
1754
+ };
1755
+ }
1756
+ if (typeof window === "undefined") {
1757
+ return { ok: false, reason: "unsupported" };
1758
+ }
1759
+ const opened = window.open(url, "_blank", "noopener,noreferrer");
1760
+ return opened ? { ok: true, value: void 0 } : { ok: false, reason: "denied", message: "The host blocked the popup." };
1761
+ }
1762
+ function normalizeHostError(error) {
1763
+ if (isAbortError(error)) {
1764
+ return { ok: false, reason: "cancelled" };
1765
+ }
1766
+ if (error instanceof Error) {
1767
+ const message = error.message.toLowerCase();
1768
+ if (message.includes("denied") || message.includes("permission")) {
1769
+ return { ok: false, reason: "denied", message: error.message };
1770
+ }
1771
+ return { ok: false, reason: "failed", message: error.message };
1772
+ }
1773
+ return { ok: false, reason: "failed" };
1774
+ }
1775
+ function isAbortError(error) {
1776
+ return error instanceof DOMException && error.name === "AbortError";
1777
+ }
1778
+ export {
1779
+ Alert,
1780
+ Avatar,
1781
+ AvatarGroup,
1782
+ Badge,
1783
+ Button,
1784
+ ButtonLink,
1785
+ Callout,
1786
+ Checkbox,
1787
+ CircularProgress,
1788
+ Code,
1789
+ CopyButton,
1790
+ Divider,
1791
+ EmptyMessage,
1792
+ EmptyState,
1793
+ FieldDescription,
1794
+ FieldError,
1795
+ FieldLabel,
1796
+ FormField,
1797
+ Heading,
1798
+ Image,
1799
+ Inline,
1800
+ Input,
1801
+ KeyValue,
1802
+ LoadingDots,
1803
+ LoadingIndicator,
1804
+ Progress,
1805
+ RadioGroup,
1806
+ SegmentedControl,
1807
+ Select,
1808
+ SelectControl,
1809
+ ShimmerText,
1810
+ Skeleton,
1811
+ Slider,
1812
+ Spinner,
1813
+ Stack,
1814
+ Surface,
1815
+ Switch,
1816
+ Table,
1817
+ Tabs,
1818
+ Text,
1819
+ TextField,
1820
+ TextLink,
1821
+ Textarea,
1822
+ capabilities,
1823
+ createPrimitiveComponents,
1824
+ display,
1825
+ files,
1826
+ host,
1827
+ links
1828
+ };
1829
+ //# sourceMappingURL=index.js.map