@botiverse/raft-ui 0.10.7 → 0.12.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/wip.mjs CHANGED
@@ -1,12 +1,11 @@
1
- import { D as DialogTitle, I as useThemeScopeProps, L as useTheme, M as defaultNativeButton, O as DialogTrigger, a as DrawerContent, c as DrawerHeader, d as DrawerTitle, f as DrawerTrigger, g as Dialog, i as DrawerClose, k as Button$1, n as DrawerActions, r as DrawerBody, s as DrawerFooter, t as Drawer, v as DialogClose, y as DialogContent, z as tv } from "./drawer-yZD16Ybl.mjs";
2
- import { Check, ChevronDown, LoaderCircle, Plus, Search, X } from "lucide-react";
1
+ import { An as DialogClose, Bn as DialogTrigger, Jn as useThemeScopeProps, On as Dialog, Vn as Button$1, Wn as defaultNativeButton, Yn as useTheme, Zn as tv, ct as MessageItemDelegatedAvatar, dt as MessageItemDelegatedByName, i as MessageListJumpPillGroup, jn as DialogContent, lt as MessageItemDelegatedBy, n as MessageListJumpPill, p as MessageQuotedPreviewAuthorDelegatedBy, r as MessageListJumpPillDismiss, t as MessageListJumpControls, ut as MessageItemDelegatedByButton, zn as DialogTitle } from "./message-list-CxawdwMF.mjs";
2
+ import { Check, ChevronDown, LoaderCircle, Plus, X } from "lucide-react";
3
3
  import { createContext, use, useCallback, useEffect, useId, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
4
4
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
5
5
  import { Button } from "@base-ui/react/button";
6
6
  import { mergeProps } from "@base-ui/react/merge-props";
7
7
  import { useRender } from "@base-ui/react/use-render";
8
8
  import { Combobox } from "@base-ui/react/combobox";
9
- import { Select } from "@base-ui/react/select";
10
9
  //#region src/lib/phone-media.ts
11
10
  /**
12
11
  * A phone: a touch screen narrower than the desktop layout. The complement, on
@@ -28,28 +27,17 @@ function getSnapshot() {
28
27
  function usePhoneMedia() {
29
28
  return useSyncExternalStore(subscribe, getSnapshot, () => false);
30
29
  }
31
- function resolveComboboxSelectMode({ phone, optionCount, sheetThreshold = 10, create = false, remote = false }) {
32
- if (!phone) return "field";
33
- if (create || remote) return "sheet";
34
- return optionCount > sheetThreshold ? "sheet" : "list";
35
- }
36
- /** Options people can pick, flat or grouped: disabled options don't count. */
37
- function countSelectableOptions(groups) {
38
- let count = 0;
39
- for (const group of groups) for (const item of group.items) if (!item.disabled) count += 1;
40
- return count;
41
- }
42
- /** The tallest the anchored list gets (`.r-combobox-select__list`, 16rem). */
43
- const LIST_MAX_HEIGHT = 256;
44
30
  /**
45
- * The side the anchored list opens on, chosen once when it opens so it never
46
- * flips while it is open (a phone's visual viewport keeps changing under it).
47
- * Below, unless the room below is short of the list and there is more above.
31
+ * The side a phone's list opens on, chosen once when it opens so it never flips
32
+ * while it is open (a phone's visual viewport keeps changing under it, as the
33
+ * keyboard and the address bar come and go). Below, unless the room below is
34
+ * short of the list and there is more above. `listHeight` is the list's full
35
+ * height and `maxHeight` its cap (`listMaxHeight`), both in pixels.
48
36
  */
49
- function preferredListSide(anchor, viewport, listHeight) {
37
+ function preferredListSide(anchor, viewport, listHeight, maxHeight) {
50
38
  const below = viewport.top + viewport.height - anchor.bottom;
51
39
  const above = anchor.top - viewport.top;
52
- return below >= Math.min(listHeight, LIST_MAX_HEIGHT) || below >= above ? "bottom" : "top";
40
+ return below >= Math.min(listHeight, maxHeight) || below >= above ? "bottom" : "top";
53
41
  }
54
42
  //#endregion
55
43
  //#region src/components/combobox-select/combobox-select.options.ts
@@ -79,10 +67,7 @@ const defaultMessages = {
79
67
  selected: "Selected options",
80
68
  chipDescription: "Press Backspace or Delete to remove",
81
69
  inputDescription: "From the start of the input, press Left Arrow to focus selected options",
82
- remove: (label) => `Remove ${label}`,
83
- search: "Search",
84
- done: "Done",
85
- close: "Close"
70
+ remove: (label) => `Remove ${label}`
86
71
  };
87
72
  const defaultRenderCreateLabel = (query) => `Create “${query}”`;
88
73
  function recordLabel(record, renderLabel) {
@@ -121,62 +106,27 @@ function renderSelectedChip({ record, index, tagLimit, strings, renderLabel, ren
121
106
  })]
122
107
  }, optionKey(record.value));
123
108
  }
124
- /** An option of the phone's anchored list: the same content as the field's list. */
125
- function renderSelectOption({ record, selected, loading, renderLabel, renderOption }) {
126
- const content = record.option === void 0 ? record.label : renderOption?.(record.option, { selected }) ?? recordLabel(record, renderLabel);
127
- return /* @__PURE__ */ jsxs(Select.Item, {
128
- value: record,
129
- label: record.label,
130
- disabled: record.disabled || loading,
131
- className: "r-combobox-select__option",
132
- children: [/* @__PURE__ */ jsx(Select.ItemText, {
133
- className: "r-combobox-select__text",
134
- children: content
135
- }), /* @__PURE__ */ jsx(Select.ItemIndicator, {
136
- className: "r-combobox-select__indicator",
137
- children: /* @__PURE__ */ jsx(Check, { "aria-hidden": true })
138
- })]
139
- }, optionKey(record.value));
140
- }
141
- /** Change details for the phone's own changes: the clear button outside any Base UI root, the sheet's search emptied as it closes. */
142
- function syntheticDetails(reason, event) {
143
- let canceled = false;
144
- return {
145
- reason,
146
- event,
147
- trigger: void 0,
148
- cancel() {
149
- canceled = true;
150
- },
151
- allowPropagation() {},
152
- get isCanceled() {
153
- return canceled;
154
- },
155
- get isPropagationAllowed() {
156
- return false;
157
- }
158
- };
159
- }
160
- function assignRef(ref, value) {
161
- if (typeof ref === "function") ref(value);
162
- else if (ref) ref.current = value;
163
- }
164
- /** The text that names a field: its `aria-labelledby` elements, else its `<label>`. */
165
- function readFieldLabel(element, labelledBy) {
166
- if (!element) return "";
167
- const doc = element.ownerDocument;
168
- const fromIds = (labelledBy ?? "").split(/\s+/).filter(Boolean).map((labelId) => doc.getElementById(labelId)?.textContent?.trim() ?? "").filter(Boolean).join(" ");
169
- if (fromIds) return fromIds;
170
- return [...element.labels ?? []].map((label) => label.textContent?.trim() ?? "").filter(Boolean).join(" ");
171
- }
172
- /** The phone's anchored list keeps the side it opened on: it never flips while open. */
109
+ /**
110
+ * On a phone the list keeps the side it opened on: it never flips while it is
111
+ * open, as the keyboard or the address bar change the visual viewport under it.
112
+ */
173
113
  const PHONE_LIST_COLLISION = {
174
114
  side: "none",
175
115
  align: "shift",
176
116
  fallbackAxisSide: "none"
177
117
  };
178
- /** The side the phone's anchored list opens on, from the room around the field. */
179
- function measureListSide(anchor, groups) {
118
+ /** A CSS length in pixels, as the document resolves it (rem, vh, calc()). */
119
+ function resolveLength(doc, length) {
120
+ const probe = doc.createElement("div");
121
+ probe.style.cssText = "position:absolute;visibility:hidden;pointer-events:none;width:0";
122
+ probe.style.height = length;
123
+ doc.body.append(probe);
124
+ const height = probe.getBoundingClientRect().height;
125
+ probe.remove();
126
+ return height;
127
+ }
128
+ /** The side the phone's list opens on, from the room around the field and the list's cap. */
129
+ function measureListSide(anchor, groups, maxHeight) {
180
130
  const view = anchor?.ownerDocument.defaultView;
181
131
  if (!anchor || !view) return "bottom";
182
132
  const visual = view.visualViewport;
@@ -187,7 +137,7 @@ function measureListSide(anchor, groups) {
187
137
  } : {
188
138
  top: 0,
189
139
  height: view.innerHeight
190
- }, rows * 36 + 12);
140
+ }, rows * 36 + 12, resolveLength(anchor.ownerDocument, maxHeight));
191
141
  }
192
142
  /** Options-driven composition. The stable compound Combobox API stays unchanged. */
193
143
  function isItemEqualToValue(a, b) {
@@ -199,7 +149,7 @@ function itemToStringLabel(record) {
199
149
  function itemToStringValue(record) {
200
150
  return String(record.value);
201
151
  }
202
- function ComboboxSelect({ options, multiple, value, defaultValue, onValueChange, labelField = "label", valueField = "value", disabledField = "disabled", fallbackOption, filterable = true, filter, remote = false, onSearch, loading = false, create = false, creatable, onCreate, clearable = false, showArrow = true, clearFilterAfterSelect = true, onClear, maxTagCount, size = "md", status, placeholder = "Select an option", renderLabel, renderOption, renderTag, renderCreateLabel = defaultRenderCreateLabel, emptyContent = "No options found", loadingContent = "Loading…", messages, sheetThreshold = 10, sheetTitle, inputProps, portalProps, positionerProps, popupProps, className, style, id: idProp, ref, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, "aria-describedby": ariaDescribedBy, "aria-invalid": ariaInvalid, inputValue, defaultInputValue, onInputValueChange, disabled, readOnly, autoHighlight = true, ...rootProps }) {
152
+ function ComboboxSelect({ options, multiple, value, defaultValue, onValueChange, labelField = "label", valueField = "value", disabledField = "disabled", fallbackOption, filterable = true, filter, remote = false, onSearch, loading = false, create = false, creatable, onCreate, clearable = false, showArrow = true, clearFilterAfterSelect = true, onClear, maxTagCount, size = "md", status, placeholder = "Select an option", renderLabel, renderOption, renderTag, renderCreateLabel = defaultRenderCreateLabel, emptyContent = "No options found", loadingContent = "Loading…", messages, listMaxHeight, inputProps, portalProps, positionerProps, popupProps, className, style, id: idProp, ref, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, "aria-describedby": ariaDescribedBy, "aria-invalid": ariaInvalid, inputValue, defaultInputValue, onInputValueChange, disabled, readOnly, autoHighlight = true, onOpenChange, ...rootProps }) {
203
153
  const generatedId = useId();
204
154
  const id = idProp ?? generatedId;
205
155
  const { resolvedMode } = useTheme();
@@ -288,15 +238,18 @@ function ComboboxSelect({ options, multiple, value, defaultValue, onValueChange,
288
238
  const css = `r-combobox-select r-combobox-select--${size}${resolvedMode === "dark" ? " r-combobox-select--dark" : ""}`;
289
239
  const tagLimit = maxTagCount === void 0 ? Infinity : Math.max(0, Math.floor(maxTagCount));
290
240
  const inputClassName = ["r-combobox-select__input", typeof inputProps?.className === "string" ? inputProps.className : null].filter(Boolean).join(" ");
241
+ const phone = usePhoneMedia();
291
242
  const controlClassName = [
292
243
  css,
293
244
  "r-combobox-select__control has-focus-visible:shadow-focus",
245
+ phone ? "r-combobox-select__control--phone" : null,
294
246
  className
295
247
  ].filter(Boolean).join(" ");
296
248
  const positionerClassName = ["r-combobox-select__positioner", typeof positionerProps?.className === "string" ? positionerProps.className : null].filter(Boolean).join(" ");
297
249
  const popupClassName = [
298
250
  css,
299
251
  "r-combobox-select__popup",
252
+ phone ? "r-combobox-select__popup--anchored" : null,
300
253
  typeof popupProps?.className === "string" ? popupProps.className : null
301
254
  ].filter(Boolean).join(" ");
302
255
  const inputRef = ref ?? inputProps?.ref;
@@ -468,293 +421,30 @@ function ComboboxSelect({ options, multiple, value, defaultValue, onValueChange,
468
421
  ]
469
422
  });
470
423
  const valueChange = handleValueChange;
471
- const mode = resolveComboboxSelectMode({
472
- phone: usePhoneMedia(),
473
- optionCount: countSelectableOptions(normalized.groups),
474
- sheetThreshold,
475
- create: Boolean(create || creatable),
476
- remote
477
- });
424
+ const listHeight = typeof listMaxHeight === "number" ? `${listMaxHeight}px` : listMaxHeight;
478
425
  const fieldRef = useRef(null);
479
- const triggerRef = useRef(null);
480
- const searchInputRef = useRef(null);
481
- const [uncontrolledPhoneOpen, setUncontrolledPhoneOpen] = useState(Boolean(rootProps.defaultOpen));
482
- const phoneOpen = rootProps.open ?? uncontrolledPhoneOpen;
483
426
  const [listSide, setListSide] = useState("bottom");
484
- const [fieldLabel, setFieldLabel] = useState("");
485
- const sheetNamed = sheetTitle != null || Boolean(inputLabel);
486
- useLayoutEffect(() => {
487
- if (mode !== "sheet" || !phoneOpen || sheetNamed) return;
488
- setFieldLabel(readFieldLabel(triggerRef.current, inputLabelledBy));
489
- }, [
490
- mode,
491
- phoneOpen,
492
- sheetNamed,
493
- inputLabelledBy
494
- ]);
495
- const setSearchInput = useCallback((element) => {
496
- searchInputRef.current = element;
497
- assignRef(inputRef, element);
498
- }, [inputRef]);
499
- const onOpenChangeProp = rootProps.onOpenChange;
500
- const openProp = rootProps.open;
501
427
  const groups = normalized.groups;
502
- const handlePhoneOpenChange = useCallback((next, details) => {
503
- onOpenChangeProp?.(next, details);
504
- if (details.isCanceled) return;
505
- if (next && mode === "list") setListSide(measureListSide(fieldRef.current, groups));
506
- if (!next && mode === "sheet") handleInputValueChange("", syntheticDetails("input-clear", details.event));
507
- if (openProp === void 0) setUncontrolledPhoneOpen(next);
428
+ const handleOpenChange = useCallback((next, details) => {
429
+ onOpenChange?.(next, details);
430
+ if (next && phone && !details.isCanceled) setListSide(measureListSide(fieldRef.current, groups, listHeight ?? "16rem"));
508
431
  }, [
509
- onOpenChangeProp,
510
- openProp,
511
- mode,
432
+ onOpenChange,
433
+ phone,
512
434
  groups,
513
- handleInputValueChange
435
+ listHeight
514
436
  ]);
515
- const handleSheetValueChange = useCallback((next, details) => {
516
- handleValueChange(next, details);
517
- if (!multiple && !details.isCanceled) handlePhoneOpenChange(false, details);
518
- }, [
519
- handleValueChange,
520
- multiple,
521
- handlePhoneOpenChange
522
- ]);
523
- const handlePhoneClear = useCallback((event) => {
524
- handleValueChange(multiple ? [] : null, syntheticDetails("clear-press", event.nativeEvent));
525
- }, [handleValueChange, multiple]);
526
- const focusSearchInput = useCallback(() => searchInputRef.current, []);
527
- if (mode !== "field") {
528
- const placeholderText = /* @__PURE__ */ jsx("span", {
529
- className: "r-combobox-select__placeholder",
530
- children: placeholder
531
- });
532
- const phoneValue = multiple ? selected.length ? /* @__PURE__ */ jsxs("span", {
533
- className: "r-combobox-select__chips",
534
- children: [selected.slice(0, tagLimit).map((record) => /* @__PURE__ */ jsx("span", {
535
- className: "r-combobox-select__chip",
536
- children: /* @__PURE__ */ jsx("span", {
537
- className: "r-combobox-select__text",
538
- children: record.option === void 0 ? record.label : renderTag?.(record.option) ?? recordLabel(record, renderLabel)
539
- })
540
- }, optionKey(record.value))), overflow]
541
- }) : placeholderText : selected[0] ? /* @__PURE__ */ jsx("span", {
542
- className: "r-combobox-select__value",
543
- children: selected[0].label
544
- }) : placeholderText;
545
- const phoneClear = clearable && selected.length > 0 && !disabled && !readOnly ? /* @__PURE__ */ jsx("button", {
546
- type: "button",
547
- className: "r-combobox-select__action r-combobox-select__clear",
548
- "aria-label": strings.clear,
549
- onClick: handlePhoneClear,
550
- children: /* @__PURE__ */ jsx(X, { "aria-hidden": true })
551
- }) : null;
552
- const phoneActions = /* @__PURE__ */ jsxs("span", {
553
- className: "r-combobox-select__actions",
554
- children: [
555
- loadingIndicator,
556
- phoneClear,
557
- showArrow ? /* @__PURE__ */ jsx("span", {
558
- className: "r-combobox-select__action r-combobox-select__arrow",
559
- "aria-hidden": true,
560
- children: /* @__PURE__ */ jsx(ChevronDown, {})
561
- }) : null
562
- ]
563
- });
564
- const phoneControlClassName = [
565
- css,
566
- "r-combobox-select__control r-combobox-select__control--trigger has-focus-visible:shadow-focus",
567
- className
568
- ].filter(Boolean).join(" ");
569
- const triggerProps = {
570
- ref: triggerRef,
571
- id,
572
- "data-slot": "combobox-select-trigger",
573
- className: "r-combobox-select__trigger",
574
- "aria-label": inputLabel,
575
- "aria-labelledby": inputLabelledBy,
576
- "aria-describedby": inputDescribedBy,
577
- "aria-invalid": inputInvalid
578
- };
579
- const field = (trigger) => /* @__PURE__ */ jsxs("div", {
580
- ref: fieldRef,
581
- "data-slot": "combobox-select",
582
- "data-status": status,
583
- "data-disabled": disabled || void 0,
584
- "data-readonly": readOnly || void 0,
585
- "data-popup-open": phoneOpen || void 0,
586
- className: phoneControlClassName,
587
- style,
588
- children: [trigger, phoneActions]
589
- });
590
- if (mode === "list") {
591
- const anchoredPopupClassName = `${popupClassName} r-combobox-select__popup--anchored`;
592
- const hasOptions = normalized.groups.some((group) => group.items.length > 0);
593
- return /* @__PURE__ */ jsxs(Select.Root, {
594
- multiple,
595
- value: controlValue,
596
- onValueChange: valueChange,
597
- open: phoneOpen,
598
- onOpenChange: handlePhoneOpenChange,
599
- onOpenChangeComplete: rootProps.onOpenChangeComplete,
600
- modal: false,
601
- name: rootProps.name,
602
- form: rootProps.form,
603
- required: rootProps.required,
604
- autoComplete: rootProps.autoComplete,
605
- disabled,
606
- readOnly,
607
- itemToStringLabel,
608
- itemToStringValue,
609
- isItemEqualToValue,
610
- children: [field(/* @__PURE__ */ jsx(Select.Trigger, {
611
- ...triggerProps,
612
- children: phoneValue
613
- })), /* @__PURE__ */ jsx(Select.Portal, {
614
- ...scopedPortalProps,
615
- children: /* @__PURE__ */ jsx(Select.Positioner, {
616
- anchor: fieldRef,
617
- side: listSide,
618
- align: "start",
619
- sideOffset: 4,
620
- alignItemWithTrigger: false,
621
- collisionAvoidance: PHONE_LIST_COLLISION,
622
- className: positionerClassName,
623
- children: /* @__PURE__ */ jsxs(Select.Popup, {
624
- "data-slot": "combobox-select-popup",
625
- className: anchoredPopupClassName,
626
- children: [
627
- loading ? /* @__PURE__ */ jsx("div", {
628
- role: "status",
629
- className: "r-combobox-select__message",
630
- children: loadingContent
631
- }) : null,
632
- /* @__PURE__ */ jsx(Select.List, {
633
- className: "r-combobox-select__list",
634
- "aria-busy": loading,
635
- children: normalized.groups.map((group) => /* @__PURE__ */ jsxs(Select.Group, { children: [group.label == null ? null : /* @__PURE__ */ jsx(Select.GroupLabel, {
636
- className: "r-combobox-select__group-label",
637
- children: group.label
638
- }), group.items.map((record) => renderSelectOption({
639
- record,
640
- selected: selected.some((item) => item.value === record.value),
641
- loading,
642
- renderLabel,
643
- renderOption
644
- }))] }, group.key))
645
- }),
646
- !hasOptions ? emptyMessage : null
647
- ]
648
- })
649
- })
650
- })]
651
- });
652
- }
653
- const titleId = `${id}-sheet-title`;
654
- const sheetCss = `r-combobox-select r-combobox-select--md${resolvedMode === "dark" ? " r-combobox-select--dark" : ""} r-combobox-select__sheet`;
655
- const hiddenInputs = rootProps.name ? selectedKeys.map((key) => /* @__PURE__ */ jsx("input", {
656
- type: "hidden",
657
- name: rootProps.name,
658
- form: rootProps.form,
659
- value: String(key),
660
- disabled
661
- }, optionKey(key))) : null;
662
- return /* @__PURE__ */ jsxs(Drawer, {
663
- open: phoneOpen,
664
- onOpenChange: handlePhoneOpenChange,
665
- onOpenChangeComplete: rootProps.onOpenChangeComplete,
666
- children: [
667
- field(/* @__PURE__ */ jsx(DrawerTrigger, {
668
- ...triggerProps,
669
- disabled,
670
- role: "combobox",
671
- "aria-haspopup": "dialog",
672
- "aria-expanded": phoneOpen,
673
- "aria-readonly": readOnly || void 0,
674
- "aria-required": rootProps.required || void 0,
675
- children: phoneValue
676
- })),
677
- hiddenInputs,
678
- /* @__PURE__ */ jsx(DrawerContent, {
679
- portalProps,
680
- "data-slot": "combobox-select-sheet",
681
- className: "r-combobox-select__sheet-popup",
682
- initialFocus: create || creatable ? focusSearchInput : void 0,
683
- children: /* @__PURE__ */ jsxs("div", {
684
- className: sheetCss,
685
- children: [
686
- /* @__PURE__ */ jsxs(DrawerHeader, {
687
- className: "r-combobox-select__sheet-header",
688
- children: [/* @__PURE__ */ jsx(DrawerTitle, {
689
- id: titleId,
690
- className: "r-combobox-select__sheet-title",
691
- children: sheetTitle ?? inputLabel ?? (fieldLabel || placeholder)
692
- }), /* @__PURE__ */ jsx(DrawerClose, { "aria-label": strings.close })]
693
- }),
694
- /* @__PURE__ */ jsxs(Combobox.Root, {
695
- inline: true,
696
- multiple,
697
- disabled,
698
- readOnly,
699
- items,
700
- value: controlValue,
701
- onValueChange: handleSheetValueChange,
702
- inputValue,
703
- defaultInputValue,
704
- onInputValueChange: handleInputValueChange,
705
- filter: filterOptions,
706
- itemToStringLabel,
707
- itemToStringValue,
708
- isItemEqualToValue,
709
- autoHighlight,
710
- children: [/* @__PURE__ */ jsx("div", {
711
- className: "r-combobox-select__sheet-search",
712
- children: /* @__PURE__ */ jsxs(Combobox.InputGroup, {
713
- className: "r-combobox-select__control has-focus-visible:shadow-focus",
714
- children: [
715
- /* @__PURE__ */ jsx(Search, {
716
- className: "r-combobox-select__search-icon",
717
- "aria-hidden": true
718
- }),
719
- /* @__PURE__ */ jsx(Combobox.Input, {
720
- ...inputProps,
721
- ref: setSearchInput,
722
- id: `${id}-search`,
723
- "data-slot": "combobox-select-input",
724
- className: inputClassName,
725
- "aria-labelledby": titleId,
726
- placeholder: strings.search,
727
- readOnly: inputReadOnly,
728
- enterKeyHint: "search"
729
- }),
730
- loadingIndicator
731
- ]
732
- })
733
- }), /* @__PURE__ */ jsxs(DrawerBody, {
734
- className: "r-combobox-select__sheet-body",
735
- children: [
736
- /* @__PURE__ */ jsx(Combobox.Status, { children: loadingMessage }),
737
- /* @__PURE__ */ jsx(Combobox.List, {
738
- className: "r-combobox-select__list",
739
- "aria-busy": loading,
740
- children: renderGroup
741
- }),
742
- /* @__PURE__ */ jsx(Combobox.Empty, { children: emptyMessage })
743
- ]
744
- })]
745
- }),
746
- multiple ? /* @__PURE__ */ jsx(DrawerFooter, { children: /* @__PURE__ */ jsx(DrawerActions, { children: /* @__PURE__ */ jsx(DrawerClose, {
747
- render: /* @__PURE__ */ jsx(Button$1, { size: "lg" }),
748
- children: strings.done
749
- }) }) }) : null
750
- ]
751
- })
752
- })
753
- ]
437
+ const popupPropsStyle = popupProps?.style;
438
+ const popupStyle = useMemo(() => {
439
+ if (listHeight === void 0) return popupPropsStyle;
440
+ return (state) => ({
441
+ ...typeof popupPropsStyle === "function" ? popupPropsStyle(state) : popupPropsStyle,
442
+ "--combobox-select-list-max-height": listHeight
754
443
  });
755
- }
444
+ }, [listHeight, popupPropsStyle]);
756
445
  return /* @__PURE__ */ jsxs(Combobox.Root, {
757
446
  ...rootProps,
447
+ onOpenChange: handleOpenChange,
758
448
  id,
759
449
  multiple,
760
450
  disabled,
@@ -771,6 +461,7 @@ function ComboboxSelect({ options, multiple, value, defaultValue, onValueChange,
771
461
  isItemEqualToValue,
772
462
  autoHighlight,
773
463
  children: [/* @__PURE__ */ jsxs(Combobox.InputGroup, {
464
+ ref: fieldRef,
774
465
  "data-slot": "combobox-select",
775
466
  "data-status": status,
776
467
  className: controlClassName,
@@ -781,12 +472,17 @@ function ComboboxSelect({ options, multiple, value, defaultValue, onValueChange,
781
472
  children: /* @__PURE__ */ jsx(Combobox.Positioner, {
782
473
  sideOffset: 4,
783
474
  align: "start",
475
+ ...phone ? {
476
+ side: listSide,
477
+ collisionAvoidance: PHONE_LIST_COLLISION
478
+ } : null,
784
479
  ...positionerProps,
785
480
  className: positionerClassName,
786
481
  children: /* @__PURE__ */ jsxs(Combobox.Popup, {
787
482
  initialFocus: false,
788
483
  finalFocus: false,
789
484
  ...popupProps,
485
+ style: popupStyle,
790
486
  "data-slot": "combobox-select-popup",
791
487
  className: popupClassName,
792
488
  children: [
@@ -1410,4 +1106,4 @@ function useCommentMarginFits(element, { minWidth = 784 } = {}) {
1410
1106
  return desktop && element !== null && width >= minWidth;
1411
1107
  }
1412
1108
  //#endregion
1413
- export { Dialog as AnnouncementDialog, AnnouncementDialogAction, AnnouncementDialogBody, DialogClose as AnnouncementDialogClose, AnnouncementDialogContent, AnnouncementDialogFooter, AnnouncementDialogHeader, AnnouncementDialogLabel, AnnouncementDialogPicture, AnnouncementDialogSecondaryAction, AnnouncementDialogText, AnnouncementDialogTitle, DialogTrigger as AnnouncementDialogTrigger, COMMENT_HIGHLIGHT, COMMENT_HIGHLIGHT_ACTIVE, ComboboxSelect, CommentCard, CommentCardMeta, CommentCardQuote, CommentCardTrigger, CommentEntry, CommentEntryAuthor, CommentEntryBody, CommentEntryHeader, CommentEntryTime, CommentMargin, CommentMarginItem, CommentMarker, resolveCommentMarginLayout, setCommentHighlights, useCommentMarginFits };
1109
+ export { Dialog as AnnouncementDialog, AnnouncementDialogAction, AnnouncementDialogBody, DialogClose as AnnouncementDialogClose, AnnouncementDialogContent, AnnouncementDialogFooter, AnnouncementDialogHeader, AnnouncementDialogLabel, AnnouncementDialogPicture, AnnouncementDialogSecondaryAction, AnnouncementDialogText, AnnouncementDialogTitle, DialogTrigger as AnnouncementDialogTrigger, COMMENT_HIGHLIGHT, COMMENT_HIGHLIGHT_ACTIVE, ComboboxSelect, CommentCard, CommentCardMeta, CommentCardQuote, CommentCardTrigger, CommentEntry, CommentEntryAuthor, CommentEntryBody, CommentEntryHeader, CommentEntryTime, CommentMargin, CommentMarginItem, CommentMarker, MessageItemDelegatedAvatar, MessageItemDelegatedBy, MessageItemDelegatedByButton, MessageItemDelegatedByName, MessageListJumpControls, MessageListJumpPill, MessageListJumpPillDismiss, MessageListJumpPillGroup, MessageQuotedPreviewAuthorDelegatedBy, resolveCommentMarginLayout, setCommentHighlights, useCommentMarginFits };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@botiverse/raft-ui",
3
- "version": "0.10.7",
3
+ "version": "0.12.0",
4
4
  "description": "React components and CSS foundations for the Raft Design System.",
5
5
  "keywords": [
6
6
  "agent-skills",