@kazee-ds/react 0.7.0 → 0.10.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/README.md CHANGED
@@ -1,8 +1,10 @@
1
1
  # @kazee-ds/react
2
2
 
3
+ Workspace additions: full-control Combobox anchoring, bounded popovers, Select-compatible sizing and opt-in focus/nonempty-selection policies. These additions are unpublished; see [Combobox and option-list documentation](https://gitlab.com/kazee.indonesia/kazee-design-system/-/blob/main/docs/select-and-combobox.md).
4
+
3
5
  Accessible Kazee React components, including Toast, built on React Aria Components. Requires React/React DOM 19+ and ESM.
4
6
 
5
- Version **0.7.0** adds Avatar/AvatarGroup, expanded Badge, sized/icon Switch, interactive/compact Card, dense controls, input clearing and composable date/time families. Existing compact APIs remain supported. Verify registry availability before installing; use matching local packed artifacts for checkout testing. See [component expansion](https://gitlab.com/kazee.indonesia/kazee-design-system/-/blob/main/docs/component-expansion.md) and [release status](https://gitlab.com/kazee.indonesia/kazee-design-system/-/blob/main/docs/versions.md).
7
+ Version **0.10.0** adds Combobox sizing, focus/search and nonempty-selection policies, full-control popovers, and compact and compound Dialog header/footer dividers and builds on controlled selectable Card actions, Avatar/AvatarGroup, expanded Badge, sized/icon Switch, interactive/compact Card, dense controls, input clearing and composable date/time families. Existing compact APIs remain supported. Verify registry availability before installing; use matching local packed artifacts for checkout testing. See [component expansion](https://gitlab.com/kazee.indonesia/kazee-design-system/-/blob/main/docs/component-expansion.md) and [release status](https://gitlab.com/kazee.indonesia/kazee-design-system/-/blob/main/docs/versions.md).
6
8
 
7
9
 
8
10
  Version 0.5.3 ignores Toast shortcut events with missing or non-string keys. Normal shortcuts and scoped Escape dismissal remain available.
@@ -12,7 +14,7 @@ Version 0.5.3 ignores Toast shortcut events with missing or non-string keys. Nor
12
14
  Public npm installation requires no read token or login. Preserve the application's package manager and lockfile.
13
15
 
14
16
  ```sh
15
- npm install --save-exact @kazee-ds/react@0.7.0 @kazee-ds/styles@0.7.0
17
+ npm install --save-exact @kazee-ds/react@0.10.0 @kazee-ds/styles@0.10.0
16
18
  ```
17
19
 
18
20
  ## Use
package/dist/index.js CHANGED
@@ -6,8 +6,8 @@ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
6
6
  import { ToggleButton as ToggleButton$1 } from "react-aria-components/ToggleButton";
7
7
  import { ToggleButtonGroup as ToggleButtonGroup$1 } from "react-aria-components/ToggleButtonGroup";
8
8
  import { I18nProvider, useLocale } from "react-aria-components/I18nProvider";
9
- import { Button as Button$2, Label as Label$1, ListBox as ListBox$1, ListBoxItem, Popover as Popover$1, Select as Select$1, SelectStateContext, SelectValue } from "react-aria-components/Select";
10
- import { Popover as Popover$2 } from "react-aria-components/Popover";
9
+ import { Popover as Popover$1 } from "react-aria-components/Popover";
10
+ import { Button as Button$2, Label as Label$1, ListBox as ListBox$1, ListBoxItem, Select as Select$1, SelectStateContext, SelectValue } from "react-aria-components/Select";
11
11
  import { ListBox as ListBox$2, ListBoxItem as ListBoxItem$1, ListBoxSection } from "react-aria-components/ListBox";
12
12
  import { Text } from "react-aria-components/Text";
13
13
  import { Header, Header as Header$1 } from "react-aria-components/Header";
@@ -26,7 +26,7 @@ import { Modal, ModalOverlay } from "react-aria-components/Modal";
26
26
  import { Tooltip as Tooltip$1, TooltipTrigger } from "react-aria-components/Tooltip";
27
27
  import { Menu, MenuItem, MenuSection, MenuTrigger, SubmenuTrigger } from "react-aria-components/Menu";
28
28
  import { Separator as Separator$1 } from "react-aria-components/Separator";
29
- import { Button as Button$5, ComboBox, ComboBoxStateContext, Input as Input$3, Label as Label$6, ListBox as ListBox$3, ListBoxItem as ListBoxItem$2, Popover as Popover$3 } from "react-aria-components/ComboBox";
29
+ import { Button as Button$5, ComboBox, ComboBoxStateContext, Input as Input$3, Label as Label$6, ListBox as ListBox$3, ListBoxItem as ListBoxItem$2 } from "react-aria-components/ComboBox";
30
30
  import { CalendarCell, CalendarGrid, CalendarGridBody, CalendarGridHeader, CalendarHeaderCell, RangeCalendar as RangeCalendar$1, RangeCalendarStateContext } from "react-aria-components/RangeCalendar";
31
31
  import { CalendarDate, GregorianCalendar, endOfMonth, getLocalTimeZone, now, parseAbsolute, parseDate, parseDateTime, parseTime, parseZonedDateTime, startOfMonth, startOfWeek, toCalendarDateTime, toZoned, today } from "@internationalized/date";
32
32
  import { Calendar as Calendar$1, CalendarCell as CalendarCell$1, CalendarGrid as CalendarGrid$1, CalendarGridBody as CalendarGridBody$1, CalendarGridHeader as CalendarGridHeader$1, CalendarHeaderCell as CalendarHeaderCell$1, CalendarStateContext } from "react-aria-components/Calendar";
@@ -188,6 +188,40 @@ function Root$1(props) {
188
188
  }
189
189
  var ToggleButtonGroup = /* @__PURE__ */ Object.assign(Root$1, { Separator: ButtonGroupSeparator });
190
190
  //#endregion
191
+ //#region src/selection-popover.tsx
192
+ /** Positioning must receive the cap: its available-space inline style wins over CSS. */
193
+ function SelectionPopover({ maxHeight, ...props }) {
194
+ const [remHeight, setRemHeight] = useState(256);
195
+ useLayoutEffect(() => {
196
+ if (maxHeight !== void 0 && Number.isFinite(maxHeight) && maxHeight > 0) return;
197
+ const root = document.documentElement;
198
+ const update = () => setRemHeight((parseFloat(getComputedStyle(root).fontSize) || 16) * 16);
199
+ update();
200
+ const resize = new ResizeObserver(update);
201
+ resize.observe(root);
202
+ const mutation = new MutationObserver(update);
203
+ mutation.observe(root, {
204
+ attributes: true,
205
+ attributeFilter: [
206
+ "style",
207
+ "class",
208
+ "data-theme"
209
+ ]
210
+ });
211
+ window.addEventListener("resize", update);
212
+ return () => {
213
+ resize.disconnect();
214
+ mutation.disconnect();
215
+ window.removeEventListener("resize", update);
216
+ };
217
+ }, [maxHeight]);
218
+ const limit = maxHeight !== void 0 && Number.isFinite(maxHeight) && maxHeight > 0 ? maxHeight : remHeight;
219
+ return /* @__PURE__ */ jsx(Popover$1, {
220
+ ...props,
221
+ maxHeight: limit
222
+ });
223
+ }
224
+ //#endregion
191
225
  //#region src/label-context.ts
192
226
  /** Item labels use Text slots rather than introducing native label elements. */
193
227
  var ItemLabelContext = createContext(false);
@@ -424,7 +458,7 @@ function SelectClearButton({ className, children, "aria-label": label = "Hapus p
424
458
  }
425
459
  function SelectPopover({ className, ...props }) {
426
460
  const { classNames } = useContext(SelectPartsContext);
427
- return /* @__PURE__ */ jsx(Popover$2, {
461
+ return /* @__PURE__ */ jsx(SelectionPopover, {
428
462
  ...props,
429
463
  className: partClass(partClass("select__popover", classNames?.popover), className)
430
464
  });
@@ -689,7 +723,8 @@ function SelectCompact(props) {
689
723
  children: /* @__PURE__ */ jsx(CloseIcon, { className: partClass("selection__close-icon", props.classNames?.clearIcon) })
690
724
  })]
691
725
  }),
692
- /* @__PURE__ */ jsx(Popover$1, {
726
+ /* @__PURE__ */ jsx(SelectionPopover, {
727
+ maxHeight: props.maxHeight,
693
728
  className: partClass("select__popover", props.classNames?.popover),
694
729
  children: /* @__PURE__ */ jsx(ListBox$1, {
695
730
  className: partClass("select__list", props.classNames?.list),
@@ -1725,7 +1760,7 @@ var NumberField = /* @__PURE__ */ Object.assign(NumberFieldRoot, {
1725
1760
  //#region src/Card.tsx
1726
1761
  /** Native primary action is a sibling of content, so nested controls remain valid HTML. */
1727
1762
  var CardTitleIdContext = createContext(void 0);
1728
- function CardAction({ href, target, rel, onPress, isDisabled, actionLabel, actionLabelledBy, actionClassName, renderLink }) {
1763
+ function CardAction({ href, target, rel, onPress, isDisabled, isSelected, actionLabel, actionLabelledBy, actionClassName, renderLink }) {
1729
1764
  if (!href && !onPress) return null;
1730
1765
  if (href) {
1731
1766
  const props = {
@@ -1754,18 +1789,20 @@ function CardAction({ href, target, rel, onPress, isDisabled, actionLabel, actio
1754
1789
  className: partClass("card__action", actionClassName),
1755
1790
  "aria-label": actionLabel,
1756
1791
  "aria-labelledby": actionLabelledBy,
1792
+ "aria-pressed": isSelected,
1757
1793
  disabled: isDisabled,
1758
1794
  onClick: () => onPress?.()
1759
1795
  };
1760
1796
  return /* @__PURE__ */ jsx("button", { ...props });
1761
1797
  }
1762
- function CompactCard({ title, description, headingLevel = 3, actions, header, titleExtras, footer, children, className, classNames, density, href, target, rel, onPress, isDisabled, actionLabel, actionLabelledBy, actionClassName, renderLink, headerAlign, dividedHeader, flushFooter, ...props }) {
1798
+ function CompactCard({ title, description, headingLevel = 3, actions, header, titleExtras, footer, children, className, classNames, density, href, target, rel, onPress, isDisabled, isSelected, actionLabel, actionLabelledBy, actionClassName, renderLink, headerAlign, dividedHeader, flushFooter, ...props }) {
1763
1799
  const Heading = `h${headingLevel}`;
1764
1800
  return /* @__PURE__ */ jsxs("div", {
1765
1801
  ...props,
1766
1802
  "data-density": density,
1767
1803
  "data-interactive": !!(href || onPress) || void 0,
1768
1804
  "data-disabled": isDisabled || void 0,
1805
+ "data-selected": isSelected || void 0,
1769
1806
  className: partClass(partClass("card", classNames?.root), className),
1770
1807
  children: [
1771
1808
  /* @__PURE__ */ jsx(CardAction, {
@@ -1774,6 +1811,7 @@ function CompactCard({ title, description, headingLevel = 3, actions, header, ti
1774
1811
  rel,
1775
1812
  onPress,
1776
1813
  isDisabled,
1814
+ isSelected,
1777
1815
  renderLink,
1778
1816
  actionClassName: partClass(classNames?.action ?? "", actionClassName),
1779
1817
  actionLabelledBy: actionLabelledBy ?? props["aria-labelledby"],
@@ -1815,7 +1853,7 @@ function CompactCard({ title, description, headingLevel = 3, actions, header, ti
1815
1853
  ]
1816
1854
  });
1817
1855
  }
1818
- function CardRoot({ className, classNames, children, density, href, target, rel, onPress, isDisabled, actionLabel, actionLabelledBy, actionClassName, renderLink, ...props }) {
1856
+ function CardRoot({ className, classNames, children, density, href, target, rel, onPress, isDisabled, isSelected, actionLabel, actionLabelledBy, actionClassName, renderLink, ...props }) {
1819
1857
  const titleId = useId();
1820
1858
  const label = actionLabel ?? props["aria-label"];
1821
1859
  return /* @__PURE__ */ jsx(CardTitleIdContext.Provider, {
@@ -1825,6 +1863,7 @@ function CardRoot({ className, classNames, children, density, href, target, rel,
1825
1863
  "data-density": density,
1826
1864
  "data-interactive": !!(href || onPress) || void 0,
1827
1865
  "data-disabled": isDisabled || void 0,
1866
+ "data-selected": isSelected || void 0,
1828
1867
  className: partClass(partClass("card", classNames?.root), className),
1829
1868
  children: [/* @__PURE__ */ jsx(CardAction, {
1830
1869
  href,
@@ -1832,6 +1871,7 @@ function CardRoot({ className, classNames, children, density, href, target, rel,
1832
1871
  rel,
1833
1872
  onPress,
1834
1873
  isDisabled,
1874
+ isSelected,
1835
1875
  renderLink,
1836
1876
  actionClassName: partClass(classNames?.action ?? "", actionClassName),
1837
1877
  actionLabel: label,
@@ -2723,9 +2763,18 @@ function DialogContent(props) {
2723
2763
  base: "dialog__content"
2724
2764
  });
2725
2765
  }
2726
- var OverlayHeader = divPart("overlay__header");
2766
+ function dividedPart(base) {
2767
+ return function Part({ divided, className, ...props }) {
2768
+ return /* @__PURE__ */ jsx("div", {
2769
+ ...props,
2770
+ className: partClass(base, className),
2771
+ "data-divided": divided || void 0
2772
+ });
2773
+ };
2774
+ }
2775
+ var OverlayHeader = dividedPart("overlay__header");
2727
2776
  var OverlayBody = divPart("overlay__body");
2728
- var OverlayFooter = divPart("overlay__footer");
2777
+ var OverlayFooter = dividedPart("overlay__footer");
2729
2778
  function OverlayHeading({ level = 2, slot = "title", ...props }) {
2730
2779
  return /* @__PURE__ */ jsx(Heading, {
2731
2780
  ...props,
@@ -2754,7 +2803,7 @@ function DialogCloseButton({ slot = "close", ...props }) {
2754
2803
  });
2755
2804
  }
2756
2805
  var PopoverTrigger = DialogTriggerPart;
2757
- var PopoverContent = ariaPart(Popover$2, "popover__panel");
2806
+ var PopoverContent = ariaPart(Popover$1, "popover__panel");
2758
2807
  function PopoverDialog(props) {
2759
2808
  return /* @__PURE__ */ jsx(DescribedDialog, {
2760
2809
  ...props,
@@ -2785,7 +2834,7 @@ function DropdownRoot({ open, defaultOpen, ...props }) {
2785
2834
  });
2786
2835
  }
2787
2836
  var DropdownTrigger = DialogTriggerPart;
2788
- var DropdownPopover = ariaPart(Popover$2, "menu__panel");
2837
+ var DropdownPopover = ariaPart(Popover$1, "menu__panel");
2789
2838
  function DropdownList(props) {
2790
2839
  return /* @__PURE__ */ jsx(Menu, {
2791
2840
  ...props,
@@ -3570,6 +3619,7 @@ function CompactDialog(props) {
3570
3619
  /* @__PURE__ */ jsxs("div", {
3571
3620
  className: partClass("overlay__header", classNames?.header),
3572
3621
  "data-close-button": showCloseButton || void 0,
3622
+ "data-divided": props.dividedHeader || void 0,
3573
3623
  children: [
3574
3624
  /* @__PURE__ */ jsx(Heading, {
3575
3625
  level: 2,
@@ -3596,6 +3646,7 @@ function CompactDialog(props) {
3596
3646
  }),
3597
3647
  (footer || showFooterClose) && /* @__PURE__ */ jsxs("div", {
3598
3648
  className: partClass("overlay__footer", classNames?.footer),
3649
+ "data-divided": props.dividedFooter || void 0,
3599
3650
  children: [footer, showFooterClose && /* @__PURE__ */ jsx(Button$1, {
3600
3651
  className: partClass("button button--secondary", classNames?.footerClose),
3601
3652
  onPress: () => change(false),
@@ -3720,7 +3771,7 @@ function CompactDropdownMenu(props) {
3720
3771
  shouldCloseOnSelect: closeOnSelect,
3721
3772
  children: content(item)
3722
3773
  }, item.id);
3723
- return item.children?.length ? /* @__PURE__ */ jsxs(SubmenuTrigger, { children: [row, /* @__PURE__ */ jsx(Popover$2, {
3774
+ return item.children?.length ? /* @__PURE__ */ jsxs(SubmenuTrigger, { children: [row, /* @__PURE__ */ jsx(Popover$1, {
3724
3775
  className: partClass("menu__panel", classNames?.panel),
3725
3776
  offset: 4,
3726
3777
  containerPadding: 16,
@@ -3749,7 +3800,7 @@ function CompactDropdownMenu(props) {
3749
3800
  "aria-label": triggerLabel,
3750
3801
  isDisabled: isDisabled || !items.length,
3751
3802
  children: props.triggerContent ?? triggerLabel
3752
- }), /* @__PURE__ */ jsx(Popover$2, {
3803
+ }), /* @__PURE__ */ jsx(Popover$1, {
3753
3804
  className: partClass("menu__panel", classNames?.panel),
3754
3805
  placement: popoverPlacement,
3755
3806
  offset: 8,
@@ -3789,7 +3840,7 @@ function CompactPopover({ className, style, classNames, triggerLabel, title, des
3789
3840
  className: partClass("button button--secondary", classNames?.trigger),
3790
3841
  isDisabled,
3791
3842
  children: triggerLabel
3792
- }), /* @__PURE__ */ jsx(Popover$2, {
3843
+ }), /* @__PURE__ */ jsx(Popover$1, {
3793
3844
  className: partClass(partClass(partClass("popover__panel", classNames?.panel), classNames?.root), className),
3794
3845
  style,
3795
3846
  isNonModal: true,
@@ -3926,27 +3977,121 @@ function Spinner({ size = "md", color = "current", label, id, className, style,
3926
3977
  }
3927
3978
  //#endregion
3928
3979
  //#region src/combobox-composition.tsx
3929
- var ComboboxDisabledContext = createContext(false);
3930
- function ComboboxComposition({ className, onChange, ...props }) {
3931
- return /* @__PURE__ */ jsx(ComboboxDisabledContext.Provider, {
3932
- value: !!props.isDisabled,
3980
+ var ComboboxPolicyContext = createContext({
3981
+ disabled: false,
3982
+ selectOnFocus: false,
3983
+ disallowEmptySelection: false,
3984
+ menuTrigger: "input",
3985
+ maxHeight: void 0,
3986
+ manageReset: false,
3987
+ controlled: false,
3988
+ resetting: { current: false },
3989
+ resetLocal: () => {}
3990
+ });
3991
+ function useComboState() {
3992
+ return useContext(ComboBoxStateContext);
3993
+ }
3994
+ function ComboboxComposition({ className, onChange, size = "md", variant = "primary", hideLabel, fullWidth = true, selectOnFocus = false, disallowEmptySelection = false, maxHeight, ...props }) {
3995
+ const [local, setLocal] = useState(props.defaultValue ?? null);
3996
+ const resetting = useRef(false);
3997
+ const resetLocal = useCallback(() => setLocal(props.defaultValue ?? null), [props.defaultValue]);
3998
+ const value = props.value !== void 0 ? props.value : local;
3999
+ return /* @__PURE__ */ jsx(ComboboxPolicyContext.Provider, {
4000
+ value: {
4001
+ disabled: !!props.isDisabled,
4002
+ selectOnFocus,
4003
+ disallowEmptySelection,
4004
+ menuTrigger: props.menuTrigger ?? "input",
4005
+ maxHeight,
4006
+ manageReset: props.inputValue === void 0,
4007
+ controlled: props.value !== void 0,
4008
+ resetting,
4009
+ resetLocal
4010
+ },
3933
4011
  children: /* @__PURE__ */ jsx(ComboBox, {
3934
4012
  ...props,
3935
- onChange: (key) => onChange?.(key == null ? null : String(key)),
3936
- className: partClass("select combobox", className)
4013
+ ...disallowEmptySelection ? { value } : {},
4014
+ onChange: (key) => {
4015
+ if (resetting.current) return;
4016
+ if (disallowEmptySelection && key == null) return;
4017
+ const next = key == null ? null : String(key);
4018
+ setLocal(next);
4019
+ onChange?.(next);
4020
+ },
4021
+ onInputChange: (text) => {
4022
+ if (!resetting.current) props.onInputChange?.(text);
4023
+ },
4024
+ className: partClass(`select combobox select--${size} select--${variant}${hideLabel ? " select--label-hidden" : ""}${!fullWidth ? " select--fit" : ""}`, className)
3937
4025
  })
3938
4026
  });
3939
4027
  }
3940
4028
  function ComboboxInputGroup({ className, ...props }) {
3941
- return /* @__PURE__ */ jsx("div", {
4029
+ const state = useComboState();
4030
+ return /* @__PURE__ */ jsx(Group, {
3942
4031
  ...props,
3943
- className: partClass("combobox__control", className)
4032
+ className: partClass("combobox__control", className),
4033
+ onKeyDownCapture: (event) => {
4034
+ props.onKeyDownCapture?.(event);
4035
+ if (!event.defaultPrevented && event.key === "Escape" && state?.isOpen && !event.nativeEvent.isComposing) {
4036
+ event.preventDefault();
4037
+ event.stopPropagation();
4038
+ state.revert();
4039
+ }
4040
+ }
3944
4041
  });
3945
4042
  }
3946
4043
  function ComboboxInput({ className, ...props }) {
4044
+ const policy = useContext(ComboboxPolicyContext);
4045
+ const state = useComboState();
4046
+ const inputRef = useRef(null);
4047
+ const selectClick = useRef(false);
4048
+ const forwardedRef = props.ref;
4049
+ const captureRef = useCallback((node) => {
4050
+ inputRef.current = node;
4051
+ if (typeof forwardedRef === "function") return forwardedRef(node);
4052
+ if (forwardedRef) forwardedRef.current = node;
4053
+ }, [forwardedRef]);
4054
+ useEffect(() => {
4055
+ const form = inputRef.current?.form;
4056
+ if (!form || !policy.manageReset || !state) return;
4057
+ const onReset = (event) => {
4058
+ const value = state.value;
4059
+ const text = state.inputValue;
4060
+ policy.resetting.current = true;
4061
+ queueMicrotask(() => {
4062
+ if (event.defaultPrevented || policy.controlled) {
4063
+ state.setValue(value);
4064
+ state.setInputValue(text);
4065
+ } else policy.resetLocal();
4066
+ policy.resetting.current = false;
4067
+ });
4068
+ };
4069
+ form.addEventListener("reset", onReset, true);
4070
+ return () => form.removeEventListener("reset", onReset, true);
4071
+ }, [policy, state]);
3947
4072
  return /* @__PURE__ */ jsx(Input$3, {
3948
4073
  ...props,
3949
- className: partClass("combobox__input", className)
4074
+ ref: captureRef,
4075
+ className: partClass("combobox__input", className),
4076
+ onFocus: (event) => {
4077
+ props.onFocus?.(event);
4078
+ if (policy.selectOnFocus && !policy.disabled) event.currentTarget.select();
4079
+ },
4080
+ onPointerDown: (event) => {
4081
+ props.onPointerDown?.(event);
4082
+ selectClick.current = policy.selectOnFocus && document.activeElement !== event.currentTarget;
4083
+ if (selectClick.current && !event.defaultPrevented && !policy.disabled) {
4084
+ event.preventDefault();
4085
+ event.currentTarget.focus();
4086
+ event.currentTarget.select();
4087
+ }
4088
+ },
4089
+ onClick: (event) => {
4090
+ props.onClick?.(event);
4091
+ if (selectClick.current && !event.defaultPrevented && !policy.disabled) event.currentTarget.select();
4092
+ selectClick.current = false;
4093
+ if (!event.defaultPrevented && !policy.disabled && policy.menuTrigger === "focus" && !state?.isOpen) state?.open(null, "focus");
4094
+ }
3950
4095
  });
3951
4096
  }
3952
4097
  function ComboboxTrigger({ className, children, ...props }) {
@@ -3958,14 +4103,17 @@ function ComboboxTrigger({ className, children, ...props }) {
3958
4103
  });
3959
4104
  }
3960
4105
  function ComboboxPopover({ className, ...props }) {
3961
- return /* @__PURE__ */ jsx(Popover$3, {
4106
+ const policy = useContext(ComboboxPolicyContext);
4107
+ return /* @__PURE__ */ jsx(SelectionPopover, {
4108
+ maxHeight: policy.maxHeight,
3962
4109
  ...props,
3963
4110
  className: partClass("select__popover combobox__popover", className)
3964
4111
  });
3965
4112
  }
3966
4113
  function ComboboxClearButton({ className, children, "aria-label": label = "Hapus pilihan", ...props }) {
3967
4114
  const state = useContext(ComboBoxStateContext);
3968
- const disabled = useContext(ComboboxDisabledContext);
4115
+ const { disabled, disallowEmptySelection } = useContext(ComboboxPolicyContext);
4116
+ if (disallowEmptySelection) return null;
3969
4117
  return /* @__PURE__ */ jsx("button", {
3970
4118
  ...props,
3971
4119
  type: "button",
@@ -4010,16 +4158,27 @@ function CompactCombobox(props) {
4010
4158
  props.onChange?.(next);
4011
4159
  setDraft(null);
4012
4160
  }
4013
- const content = /* @__PURE__ */ jsxs(ComboBox, {
4161
+ const content = /* @__PURE__ */ jsxs(ComboboxComposition, {
4014
4162
  className: partClass(partClass("select combobox", props.classNames?.root), props.className),
4015
4163
  style: props.style,
4164
+ size: props.size,
4165
+ variant: props.variant,
4166
+ hideLabel: props.hideLabel,
4167
+ fullWidth: props.fullWidth,
4168
+ maxHeight: props.maxHeight,
4169
+ menuTrigger: props.menuTrigger,
4170
+ selectOnFocus: props.selectOnFocus,
4171
+ disallowEmptySelection: props.disallowEmptySelection,
4172
+ onOpenChange: (open) => {
4173
+ if (!open) setDraft(null);
4174
+ },
4016
4175
  value: id,
4017
4176
  onChange: change,
4018
4177
  inputValue: text,
4019
4178
  onInputChange: (text) => {
4020
4179
  if (resetting.current) return;
4021
4180
  setDraft(text);
4022
- if (text === "" && id) {
4181
+ if (text === "" && id && !props.disallowEmptySelection) {
4023
4182
  setLocal(null);
4024
4183
  props.onChange?.(null);
4025
4184
  }
@@ -4041,7 +4200,7 @@ function CompactCombobox(props) {
4041
4200
  children: [" ", "*"]
4042
4201
  })]
4043
4202
  }),
4044
- /* @__PURE__ */ jsxs("div", {
4203
+ /* @__PURE__ */ jsxs(ComboboxInputGroup, {
4045
4204
  className: partClass("combobox__control", props.classNames?.control),
4046
4205
  "data-invalid": invalid || void 0,
4047
4206
  "data-disabled": props.isDisabled || void 0,
@@ -4051,13 +4210,13 @@ function CompactCombobox(props) {
4051
4210
  "aria-hidden": "true",
4052
4211
  children: props.startContent
4053
4212
  }),
4054
- /* @__PURE__ */ jsx(Input$3, {
4213
+ /* @__PURE__ */ jsx(ComboboxInput, {
4055
4214
  ref: input,
4056
4215
  className: partClass("combobox__input", props.classNames?.input),
4057
4216
  placeholder: props.placeholder,
4058
4217
  "aria-describedby": describedBy
4059
4218
  }),
4060
- props.isClearable && /* @__PURE__ */ jsx("button", {
4219
+ props.isClearable && !props.disallowEmptySelection && /* @__PURE__ */ jsx("button", {
4061
4220
  type: "button",
4062
4221
  className: partClass("combobox__clear", props.classNames?.clearButton),
4063
4222
  "data-empty": !id && !text || void 0,
@@ -4078,7 +4237,7 @@ function CompactCombobox(props) {
4078
4237
  })
4079
4238
  ]
4080
4239
  }),
4081
- /* @__PURE__ */ jsx(Popover$3, {
4240
+ /* @__PURE__ */ jsx(ComboboxPopover, {
4082
4241
  className: partClass("select__popover combobox__popover", props.classNames?.popover),
4083
4242
  children: /* @__PURE__ */ jsx(ListBox$3, {
4084
4243
  className: partClass("select__list", props.classNames?.list),
@@ -4256,7 +4415,7 @@ function DateRangeIndicator({ className, children, ...props }) {
4256
4415
  }
4257
4416
  function DateRangePopover({ className, children, ...props }) {
4258
4417
  const range = useRange();
4259
- return /* @__PURE__ */ jsx(Popover$2, {
4418
+ return /* @__PURE__ */ jsx(Popover$1, {
4260
4419
  placement: "bottom start",
4261
4420
  offset: 8,
4262
4421
  dir: range.dir,
@@ -5238,7 +5397,7 @@ function DateRangePickerRoot(props) {
5238
5397
  children: panel
5239
5398
  })
5240
5399
  })
5241
- }) : /* @__PURE__ */ jsx(Popover$2, {
5400
+ }) : /* @__PURE__ */ jsx(Popover$1, {
5242
5401
  className: partClass("date-range__panel", props.classNames?.panel),
5243
5402
  placement: "bottom start",
5244
5403
  offset: 8,
@@ -6864,7 +7023,7 @@ function TemporalPickerContent({ children, className, ...props }) {
6864
7023
  }
6865
7024
  function TemporalPickerPopover({ children, className, ...props }) {
6866
7025
  const c = usePicker();
6867
- return /* @__PURE__ */ jsx(Popover$2, {
7026
+ return /* @__PURE__ */ jsx(Popover$1, {
6868
7027
  className: partClass("date-range__panel temporal-picker__panel", className),
6869
7028
  placement: "bottom start",
6870
7029
  offset: 8,