@botiverse/raft-ui 0.11.0 → 0.13.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 { Bn as DialogTitle, Gn as defaultNativeButton, Hn as Button$1, Mn as DialogContent, Qn as tv, Rt as useOverflowTitle, Vn as DialogTrigger, Xn as useTheme, Yn as useThemeScopeProps, ct as MessageItemDelegatedAvatar, dt as MessageItemDelegatedByName, i as MessageListJumpPillGroup, jn as DialogClose, kn as Dialog, lt as MessageItemDelegatedBy, n as MessageListJumpPill, p as MessageQuotedPreviewAuthorDelegatedBy, r as MessageListJumpPillDismiss, t as MessageListJumpControls, ut as MessageItemDelegatedByButton } from "./message-list-DP03T8gF.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,25 +67,24 @@ 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}”`;
73
+ /** An option's or a chip's text, with its whole value as the title when it is cut off. */
74
+ function OverflowText({ children }) {
75
+ return /* @__PURE__ */ jsx("span", {
76
+ ref: useOverflowTitle(),
77
+ className: "r-combobox-select__text",
78
+ children
79
+ });
80
+ }
88
81
  function recordLabel(record, renderLabel) {
89
82
  return record.option === void 0 ? record.label : renderLabel?.(record.option) ?? record.label;
90
83
  }
91
84
  function renderOptionContent({ record, selected, renderLabel, renderOption, renderCreateLabel }) {
92
- if (record.createQuery !== void 0) return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Plus, { "aria-hidden": true }), /* @__PURE__ */ jsx("span", {
93
- className: "r-combobox-select__text",
94
- children: renderCreateLabel(record.label)
95
- })] });
85
+ if (record.createQuery !== void 0) return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Plus, { "aria-hidden": true }), /* @__PURE__ */ jsx(OverflowText, { children: renderCreateLabel(record.label) })] });
96
86
  const content = record.option === void 0 ? record.label : renderOption?.(record.option, { selected }) ?? recordLabel(record, renderLabel);
97
- return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("span", {
98
- className: "r-combobox-select__text",
99
- children: content
100
- }), /* @__PURE__ */ jsx(Combobox.ItemIndicator, {
87
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(OverflowText, { children: content }), /* @__PURE__ */ jsx(Combobox.ItemIndicator, {
101
88
  className: "r-combobox-select__indicator",
102
89
  children: /* @__PURE__ */ jsx(Check, { "aria-hidden": true })
103
90
  })] });
@@ -111,72 +98,34 @@ function renderSelectedChip({ record, index, tagLimit, strings, renderLabel, ren
111
98
  "data-overflow": overflow || void 0,
112
99
  "aria-label": record.label,
113
100
  "aria-description": strings.chipDescription,
114
- children: [/* @__PURE__ */ jsx("span", {
115
- className: "r-combobox-select__text",
116
- children: content
117
- }), /* @__PURE__ */ jsx(Combobox.ChipRemove, {
101
+ children: [/* @__PURE__ */ jsx(OverflowText, { children: content }), /* @__PURE__ */ jsx(Combobox.ChipRemove, {
118
102
  className: "r-combobox-select__remove",
119
103
  "aria-label": strings.remove(record.label),
120
104
  children: /* @__PURE__ */ jsx(X, { "aria-hidden": true })
121
105
  })]
122
106
  }, optionKey(record.value));
123
107
  }
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. */
108
+ /**
109
+ * On a phone the list keeps the side it opened on: it never flips while it is
110
+ * open, as the keyboard or the address bar change the visual viewport under it.
111
+ */
173
112
  const PHONE_LIST_COLLISION = {
174
113
  side: "none",
175
114
  align: "shift",
176
115
  fallbackAxisSide: "none"
177
116
  };
178
- /** The side the phone's anchored list opens on, from the room around the field. */
179
- function measureListSide(anchor, groups) {
117
+ /** A CSS length in pixels, as the document resolves it (rem, vh, calc()). */
118
+ function resolveLength(doc, length) {
119
+ const probe = doc.createElement("div");
120
+ probe.style.cssText = "position:absolute;visibility:hidden;pointer-events:none;width:0";
121
+ probe.style.height = length;
122
+ doc.body.append(probe);
123
+ const height = probe.getBoundingClientRect().height;
124
+ probe.remove();
125
+ return height;
126
+ }
127
+ /** The side the phone's list opens on, from the room around the field and the list's cap. */
128
+ function measureListSide(anchor, groups, maxHeight) {
180
129
  const view = anchor?.ownerDocument.defaultView;
181
130
  if (!anchor || !view) return "bottom";
182
131
  const visual = view.visualViewport;
@@ -187,7 +136,7 @@ function measureListSide(anchor, groups) {
187
136
  } : {
188
137
  top: 0,
189
138
  height: view.innerHeight
190
- }, rows * 36 + 12);
139
+ }, rows * 36 + 12, resolveLength(anchor.ownerDocument, maxHeight));
191
140
  }
192
141
  /** Options-driven composition. The stable compound Combobox API stays unchanged. */
193
142
  function isItemEqualToValue(a, b) {
@@ -199,7 +148,7 @@ function itemToStringLabel(record) {
199
148
  function itemToStringValue(record) {
200
149
  return String(record.value);
201
150
  }
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 }) {
151
+ 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
152
  const generatedId = useId();
204
153
  const id = idProp ?? generatedId;
205
154
  const { resolvedMode } = useTheme();
@@ -288,15 +237,18 @@ function ComboboxSelect({ options, multiple, value, defaultValue, onValueChange,
288
237
  const css = `r-combobox-select r-combobox-select--${size}${resolvedMode === "dark" ? " r-combobox-select--dark" : ""}`;
289
238
  const tagLimit = maxTagCount === void 0 ? Infinity : Math.max(0, Math.floor(maxTagCount));
290
239
  const inputClassName = ["r-combobox-select__input", typeof inputProps?.className === "string" ? inputProps.className : null].filter(Boolean).join(" ");
240
+ const phone = usePhoneMedia();
291
241
  const controlClassName = [
292
242
  css,
293
243
  "r-combobox-select__control has-focus-visible:shadow-focus",
244
+ phone ? "r-combobox-select__control--phone" : null,
294
245
  className
295
246
  ].filter(Boolean).join(" ");
296
247
  const positionerClassName = ["r-combobox-select__positioner", typeof positionerProps?.className === "string" ? positionerProps.className : null].filter(Boolean).join(" ");
297
248
  const popupClassName = [
298
249
  css,
299
250
  "r-combobox-select__popup",
251
+ phone ? "r-combobox-select__popup--anchored" : null,
300
252
  typeof popupProps?.className === "string" ? popupProps.className : null
301
253
  ].filter(Boolean).join(" ");
302
254
  const inputRef = ref ?? inputProps?.ref;
@@ -468,293 +420,30 @@ function ComboboxSelect({ options, multiple, value, defaultValue, onValueChange,
468
420
  ]
469
421
  });
470
422
  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
- });
423
+ const listHeight = typeof listMaxHeight === "number" ? `${listMaxHeight}px` : listMaxHeight;
478
424
  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
425
  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
426
  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);
427
+ const handleOpenChange = useCallback((next, details) => {
428
+ onOpenChange?.(next, details);
429
+ if (next && phone && !details.isCanceled) setListSide(measureListSide(fieldRef.current, groups, listHeight ?? "16rem"));
508
430
  }, [
509
- onOpenChangeProp,
510
- openProp,
511
- mode,
431
+ onOpenChange,
432
+ phone,
512
433
  groups,
513
- handleInputValueChange
514
- ]);
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
434
+ listHeight
522
435
  ]);
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]
436
+ const popupPropsStyle = popupProps?.style;
437
+ const popupStyle = useMemo(() => {
438
+ if (listHeight === void 0) return popupPropsStyle;
439
+ return (state) => ({
440
+ ...typeof popupPropsStyle === "function" ? popupPropsStyle(state) : popupPropsStyle,
441
+ "--combobox-select-list-max-height": listHeight
589
442
  });
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
- ]
754
- });
755
- }
443
+ }, [listHeight, popupPropsStyle]);
756
444
  return /* @__PURE__ */ jsxs(Combobox.Root, {
757
445
  ...rootProps,
446
+ onOpenChange: handleOpenChange,
758
447
  id,
759
448
  multiple,
760
449
  disabled,
@@ -771,6 +460,7 @@ function ComboboxSelect({ options, multiple, value, defaultValue, onValueChange,
771
460
  isItemEqualToValue,
772
461
  autoHighlight,
773
462
  children: [/* @__PURE__ */ jsxs(Combobox.InputGroup, {
463
+ ref: fieldRef,
774
464
  "data-slot": "combobox-select",
775
465
  "data-status": status,
776
466
  className: controlClassName,
@@ -781,12 +471,18 @@ function ComboboxSelect({ options, multiple, value, defaultValue, onValueChange,
781
471
  children: /* @__PURE__ */ jsx(Combobox.Positioner, {
782
472
  sideOffset: 4,
783
473
  align: "start",
474
+ collisionPadding: 8,
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: [
@@ -938,7 +634,7 @@ const comment = tv({
938
634
  cardTrigger: [
939
635
  "absolute -inset-px z-10 cursor-pointer",
940
636
  "rounded-container border-0 bg-transparent p-0",
941
- "hover:bg-fill-pressed active:bg-fill-pressed",
637
+ "hover:bg-fill-row-hover active:bg-fill-pressed",
942
638
  "outline-none focus-visible:shadow-focus"
943
639
  ],
944
640
  cardQuote: ["sr-only"],
@@ -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.11.0",
3
+ "version": "0.13.0",
4
4
  "description": "React components and CSS foundations for the Raft Design System.",
5
5
  "keywords": [
6
6
  "agent-skills",