@kazee-ds/react 0.6.0 → 0.8.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 CHANGED
@@ -27,8 +27,11 @@ import { Tooltip as Tooltip$1, TooltipTrigger } from "react-aria-components/Tool
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
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";
30
- import { CalendarCell, CalendarGrid, CalendarGridBody, CalendarGridHeader, CalendarHeaderCell, CalendarHeading, RangeCalendar, RangeCalendarStateContext } from "react-aria-components/RangeCalendar";
31
- import { GregorianCalendar, endOfMonth, getLocalTimeZone, parseDate, startOfMonth, startOfWeek, today } from "@internationalized/date";
30
+ import { CalendarCell, CalendarGrid, CalendarGridBody, CalendarGridHeader, CalendarHeaderCell, RangeCalendar as RangeCalendar$1, RangeCalendarStateContext } from "react-aria-components/RangeCalendar";
31
+ import { CalendarDate, GregorianCalendar, endOfMonth, getLocalTimeZone, now, parseAbsolute, parseDate, parseDateTime, parseTime, parseZonedDateTime, startOfMonth, startOfWeek, toCalendarDateTime, toZoned, today } from "@internationalized/date";
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";
33
+ import { DateField as DateField$1, DateInput, DateSegment } from "react-aria-components/DateField";
34
+ import { TimeField as TimeField$1 } from "react-aria-components/TimeField";
32
35
  //#region src/Button.tsx
33
36
  function PendingLabelAnchor() {
34
37
  const context = useContext(ProgressBarContext);
@@ -80,7 +83,7 @@ function ButtonGroupSeparator({ className, style, classNames } = {}) {
80
83
  "aria-hidden": "true"
81
84
  });
82
85
  }
83
- function Root$1({ children, label, variant, size, isDisabled, fullWidth, orientation = "horizontal", dir, className, style, classNames }) {
86
+ function Root$2({ children, label, variant, size, isDisabled, fullWidth, orientation = "horizontal", dir, className, style, classNames }) {
84
87
  function defaults(nodes) {
85
88
  return Children.map(nodes, (child) => {
86
89
  if (!isValidElement(child)) return child;
@@ -104,12 +107,14 @@ function Root$1({ children, label, variant, size, isDisabled, fullWidth, orienta
104
107
  children: defaults(children)
105
108
  });
106
109
  }
107
- var ButtonGroup = /* @__PURE__ */ Object.assign(Root$1, { Separator: ButtonGroupSeparator });
110
+ var ButtonGroup = /* @__PURE__ */ Object.assign(Root$2, { Separator: ButtonGroupSeparator });
108
111
  //#endregion
109
112
  //#region src/ToggleButton.tsx
110
113
  var ToggleButtonSizeContext = createContext("md");
111
- function ToggleButton({ children, variant = "default", size, isIconOnly, className: consumerClassName, classNames, style, ...props }) {
114
+ var ToggleButtonVariantContext = createContext("default");
115
+ function ToggleButton({ children, variant, size, isIconOnly, className: consumerClassName, classNames, style, ...props }) {
112
116
  const inheritedSize = useContext(ToggleButtonSizeContext);
117
+ const inheritedVariant = useContext(ToggleButtonVariantContext);
113
118
  const resolvedSize = size ?? inheritedSize;
114
119
  return /* @__PURE__ */ jsx(ToggleButton$1, {
115
120
  ...props,
@@ -119,7 +124,7 @@ function ToggleButton({ children, variant = "default", size, isIconOnly, classNa
119
124
  classNames?.root,
120
125
  consumerClassName,
121
126
  "toggle-button",
122
- `toggle-button--${variant}`,
127
+ `toggle-button--${variant ?? inheritedVariant}`,
123
128
  resolvedSize !== "md" && `button--${resolvedSize}`,
124
129
  isIconOnly && "button--icon-only"
125
130
  ].filter(Boolean).join(" "),
@@ -144,41 +149,44 @@ function OverlayDirection({ dir, children }) {
144
149
  //#endregion
145
150
  //#region src/ToggleButtonGroup.tsx
146
151
  var keys = (value) => Array.isArray(value) ? value : value ? [value] : [];
147
- function Root(props) {
152
+ function Root$1(props) {
148
153
  return /* @__PURE__ */ jsx(OverlayDirection, {
149
154
  dir: props.dir,
150
155
  children: /* @__PURE__ */ jsx(ToggleButtonSizeContext.Provider, {
151
156
  value: props.size ?? "md",
152
- children: /* @__PURE__ */ jsx(ToggleButtonGroup$1, {
153
- "aria-label": props.label,
154
- dir: props.dir,
155
- className: [
156
- "button-group",
157
- props.classNames?.root,
158
- props.className,
159
- "toggle-button-group",
160
- props.isDetached && "button-group--detached",
161
- props.fullWidth && "button-group--full-width"
162
- ].filter(Boolean).join(" "),
163
- style: props.style,
164
- orientation: props.orientation ?? "horizontal",
165
- selectionMode: props.selectionMode ?? "single",
166
- selectedKeys: props.value === void 0 ? void 0 : keys(props.value),
167
- defaultSelectedKeys: keys(props.defaultValue),
168
- onSelectionChange: (selected) => {
169
- if (props.isDisabled) return;
170
- const next = Array.from(selected, String);
171
- if (props.selectionMode === "multiple") props.onChange?.(next);
172
- else props.onChange?.(next[0] ?? null);
173
- },
174
- isDisabled: props.isDisabled,
175
- disallowEmptySelection: props.disallowEmptySelection,
176
- children: props.children
157
+ children: /* @__PURE__ */ jsx(ToggleButtonVariantContext.Provider, {
158
+ value: props.variant ?? "default",
159
+ children: /* @__PURE__ */ jsx(ToggleButtonGroup$1, {
160
+ "aria-label": props.label,
161
+ dir: props.dir,
162
+ className: [
163
+ "button-group",
164
+ props.classNames?.root,
165
+ props.className,
166
+ "toggle-button-group",
167
+ (props.isDetached ?? props.variant === "chip") && "button-group--detached",
168
+ props.fullWidth && "button-group--full-width"
169
+ ].filter(Boolean).join(" "),
170
+ style: props.style,
171
+ orientation: props.orientation ?? "horizontal",
172
+ selectionMode: props.selectionMode ?? "single",
173
+ selectedKeys: props.value === void 0 ? void 0 : keys(props.value),
174
+ defaultSelectedKeys: keys(props.defaultValue),
175
+ onSelectionChange: (selected) => {
176
+ if (props.isDisabled) return;
177
+ const next = Array.from(selected, String);
178
+ if (props.selectionMode === "multiple") props.onChange?.(next);
179
+ else props.onChange?.(next[0] ?? null);
180
+ },
181
+ isDisabled: props.isDisabled,
182
+ disallowEmptySelection: props.disallowEmptySelection,
183
+ children: props.children
184
+ })
177
185
  })
178
186
  })
179
187
  });
180
188
  }
181
- var ToggleButtonGroup = /* @__PURE__ */ Object.assign(Root, { Separator: ButtonGroupSeparator });
189
+ var ToggleButtonGroup = /* @__PURE__ */ Object.assign(Root$1, { Separator: ButtonGroupSeparator });
182
190
  //#endregion
183
191
  //#region src/label-context.ts
184
192
  /** Item labels use Text slots rather than introducing native label elements. */
@@ -227,6 +235,64 @@ function CloseIcon({ className }) {
227
235
  });
228
236
  }
229
237
  //#endregion
238
+ //#region src/input-clear.tsx
239
+ var InputClearContext = createContext(null);
240
+ function useClearableInput({ value, defaultValue = "", onChange, isDisabled, isReadOnly }, element) {
241
+ const [local, setLocal] = useState(defaultValue);
242
+ const current = value === void 0 ? local : value;
243
+ const update = (next) => {
244
+ if (!isDisabled && !isReadOnly) {
245
+ if (value === void 0) setLocal(next);
246
+ onChange?.(next);
247
+ }
248
+ };
249
+ useEffect(() => {
250
+ const form = (element.current instanceof HTMLInputElement || element.current instanceof HTMLTextAreaElement ? element.current : element.current?.querySelector("input,textarea"))?.form;
251
+ const reset = (event) => {
252
+ queueMicrotask(() => {
253
+ if (!event.defaultPrevented && value === void 0) setLocal(defaultValue);
254
+ });
255
+ };
256
+ form?.addEventListener("reset", reset);
257
+ return () => form?.removeEventListener("reset", reset);
258
+ }, [
259
+ element,
260
+ value,
261
+ defaultValue
262
+ ]);
263
+ return {
264
+ value: current,
265
+ update,
266
+ context: {
267
+ value: current,
268
+ disabled: isDisabled,
269
+ readOnly: isReadOnly,
270
+ clear: () => {
271
+ if (isDisabled || isReadOnly) return;
272
+ update("");
273
+ (element.current instanceof HTMLInputElement || element.current instanceof HTMLTextAreaElement ? element.current : element.current?.querySelector("input,textarea"))?.focus();
274
+ }
275
+ }
276
+ };
277
+ }
278
+ function InputClearButton({ className, children, onClick, ...props }) {
279
+ const context = useContext(InputClearContext);
280
+ if (!context) throw new Error("Input.ClearButton requires Input.Root.");
281
+ if (!context.value || context.readOnly) return null;
282
+ return /* @__PURE__ */ jsx("button", {
283
+ "aria-label": "Hapus input / Clear input",
284
+ ...props,
285
+ type: "button",
286
+ className: partClass("input__clear", className),
287
+ disabled: context.disabled || props.disabled,
288
+ onClick: (event) => {
289
+ onClick?.(event);
290
+ if (!event.defaultPrevented) context.clear();
291
+ },
292
+ children: children ?? /* @__PURE__ */ jsx(CloseIcon, {})
293
+ });
294
+ }
295
+ //#endregion
230
296
  //#region src/control-composition.tsx
231
297
  var SelectPartsContext = createContext({
232
298
  clearButtons: 0,
@@ -418,10 +484,24 @@ function FieldError({ className, ...props }) {
418
484
  className: partClass(partClass("input__error", fieldClasses.error), className)
419
485
  });
420
486
  }
421
- function InputRoot({ className, ...props }) {
422
- return /* @__PURE__ */ jsx(TextField, {
423
- ...props,
424
- className: partClass("input", className)
487
+ function InputRoot({ className, size = "md", variant = "primary", hideLabel = false, value, defaultValue, onChange, ...props }) {
488
+ const root = useRef(null);
489
+ const clearable = useClearableInput({
490
+ value,
491
+ defaultValue,
492
+ onChange,
493
+ isDisabled: props.isDisabled,
494
+ isReadOnly: props.isReadOnly
495
+ }, root);
496
+ return /* @__PURE__ */ jsx(InputClearContext.Provider, {
497
+ value: clearable.context,
498
+ children: /* @__PURE__ */ jsx(TextField, {
499
+ ...props,
500
+ ref: root,
501
+ value: clearable.value,
502
+ onChange: clearable.update,
503
+ className: partClass(`input input--${size} input--${variant}${hideLabel ? " input--label-hidden" : ""}`, className)
504
+ })
425
505
  });
426
506
  }
427
507
  var InputControlRefContext = createContext(void 0);
@@ -717,10 +797,17 @@ function SelectGroup({ label, children, size, variant, fullWidth = true, isDisab
717
797
  }
718
798
  //#endregion
719
799
  //#region src/Input.tsx
720
- var CompactInput = /* @__PURE__ */ forwardRef(function Input({ label, value, defaultValue, onChange, description, errorMessage, isInvalid = false, isDisabled = false, isReadOnly = false, isRequired = false, placeholder, type = "text", size = "md", variant = "primary", fullWidth = true, prefix, suffix, name, id, autoComplete, maxLength, minLength, pattern, inputMode, enterKeyHint, autoFocus, spellCheck, form, onFocus, onBlur, onKeyDown, onKeyUp, dir, className, style, classNames }, ref) {
800
+ var CompactInput = /* @__PURE__ */ forwardRef(function Input({ label, value, defaultValue, onChange, description, errorMessage, isInvalid = false, isDisabled = false, isReadOnly = false, isRequired = false, placeholder, type = "text", size = "md", variant = "primary", fullWidth = true, hideLabel = false, isClearable = false, clearLabel, prefix, suffix, name, id, autoComplete, maxLength, minLength, pattern, inputMode, enterKeyHint, autoFocus, spellCheck, form, onFocus, onBlur, onKeyDown, onKeyUp, dir, className, style, classNames }, ref) {
721
801
  const control = useRef(null);
802
+ const clearable = useClearableInput({
803
+ value,
804
+ defaultValue,
805
+ onChange,
806
+ isDisabled,
807
+ isReadOnly
808
+ }, control);
722
809
  useImperativeHandle(ref, () => control.current);
723
- const hasAdornment = prefix != null || suffix != null;
810
+ const hasAdornment = prefix != null || suffix != null || isClearable;
724
811
  const input = /* @__PURE__ */ jsx(Input$1, {
725
812
  ref: control,
726
813
  className: partClass(partClass("input__control", classNames?.input), classNames?.control),
@@ -738,65 +825,71 @@ var CompactInput = /* @__PURE__ */ forwardRef(function Input({ label, value, def
738
825
  onKeyDown,
739
826
  onKeyUp
740
827
  });
741
- return /* @__PURE__ */ jsxs(TextField, {
742
- className: partClass(partClass(`input input--${size} input--${variant}${fullWidth ? "" : " input--fit"}`, classNames?.root), className),
743
- style,
744
- value,
745
- defaultValue,
746
- onChange,
747
- isInvalid,
748
- isDisabled,
749
- isReadOnly,
750
- isRequired,
751
- validationBehavior: "aria",
752
- type,
753
- name,
754
- id,
755
- autoComplete,
756
- maxLength,
757
- dir,
758
- children: [
759
- /* @__PURE__ */ jsx(Label$2, {
760
- className: partClass("input__label", classNames?.label),
761
- children: label
762
- }),
763
- /* @__PURE__ */ jsx("fieldset", {
764
- className: partClass("input__boundary", classNames?.boundary),
765
- role: "presentation",
766
- disabled: isDisabled,
767
- children: /* @__PURE__ */ jsxs("div", {
768
- className: partClass(hasAdornment ? "input__group" : "input__plain", classNames?.group),
769
- "data-invalid": isInvalid || void 0,
770
- "data-readonly": isReadOnly || void 0,
771
- onPointerDown: (event) => {
772
- if (!isDisabled && !event.target.closest("input,button,a,select,textarea,[tabindex],[contenteditable]")) {
773
- event.preventDefault();
774
- control.current?.focus();
775
- }
776
- },
777
- children: [
778
- prefix != null && /* @__PURE__ */ jsx("span", {
779
- className: partClass("input__prefix", classNames?.prefix),
780
- children: prefix
781
- }),
782
- input,
783
- suffix != null && /* @__PURE__ */ jsx("span", {
784
- className: partClass("input__suffix", classNames?.suffix),
785
- children: suffix
786
- })
787
- ]
828
+ return /* @__PURE__ */ jsx(InputClearContext.Provider, {
829
+ value: clearable.context,
830
+ children: /* @__PURE__ */ jsxs(TextField, {
831
+ className: partClass(partClass(`input input--${size} input--${variant}${fullWidth ? "" : " input--fit"}${hideLabel ? " input--label-hidden" : ""}`, classNames?.root), className),
832
+ style,
833
+ value: clearable.value,
834
+ onChange: clearable.update,
835
+ isInvalid,
836
+ isDisabled,
837
+ isReadOnly,
838
+ isRequired,
839
+ validationBehavior: "aria",
840
+ type,
841
+ name,
842
+ id,
843
+ autoComplete,
844
+ maxLength,
845
+ dir,
846
+ children: [
847
+ /* @__PURE__ */ jsx(Label$2, {
848
+ className: partClass("input__label", classNames?.label),
849
+ children: label
850
+ }),
851
+ /* @__PURE__ */ jsx("fieldset", {
852
+ className: partClass("input__boundary", classNames?.boundary),
853
+ role: "presentation",
854
+ disabled: isDisabled,
855
+ children: /* @__PURE__ */ jsxs("div", {
856
+ className: partClass(hasAdornment ? "input__group" : "input__plain", classNames?.group),
857
+ "data-invalid": isInvalid || void 0,
858
+ "data-readonly": isReadOnly || void 0,
859
+ onPointerDown: (event) => {
860
+ if (!isDisabled && !event.target.closest("input,button,a,select,textarea,[tabindex],[contenteditable]")) {
861
+ event.preventDefault();
862
+ control.current?.focus();
863
+ }
864
+ },
865
+ children: [
866
+ prefix != null && /* @__PURE__ */ jsx("span", {
867
+ className: partClass("input__prefix", classNames?.prefix),
868
+ children: prefix
869
+ }),
870
+ input,
871
+ isClearable && /* @__PURE__ */ jsx(InputClearButton, {
872
+ "aria-label": clearLabel ?? "Hapus input / Clear input",
873
+ className: classNames?.clearButton
874
+ }),
875
+ suffix != null && /* @__PURE__ */ jsx("span", {
876
+ className: partClass("input__suffix", classNames?.suffix),
877
+ children: suffix
878
+ })
879
+ ]
880
+ })
881
+ }),
882
+ description && /* @__PURE__ */ jsx(Text$1, {
883
+ slot: "description",
884
+ className: partClass("input__description", classNames?.description),
885
+ children: description
886
+ }),
887
+ isInvalid && errorMessage && /* @__PURE__ */ jsx(FieldError$2, {
888
+ className: partClass("input__error", classNames?.error),
889
+ children: errorMessage
788
890
  })
789
- }),
790
- description && /* @__PURE__ */ jsx(Text$1, {
791
- slot: "description",
792
- className: partClass("input__description", classNames?.description),
793
- children: description
794
- }),
795
- isInvalid && errorMessage && /* @__PURE__ */ jsx(FieldError$2, {
796
- className: partClass("input__error", classNames?.error),
797
- children: errorMessage
798
- })
799
- ]
891
+ ]
892
+ })
800
893
  });
801
894
  });
802
895
  var Input = /* @__PURE__ */ Object.assign(/* @__PURE__ */ forwardRef(function InputWithComposition(props, ref) {
@@ -813,7 +906,8 @@ var Input = /* @__PURE__ */ Object.assign(/* @__PURE__ */ forwardRef(function In
813
906
  Control: InputControl,
814
907
  Group: InputGroup,
815
908
  Prefix: InputPrefix,
816
- Suffix: InputSuffix
909
+ Suffix: InputSuffix,
910
+ ClearButton: InputClearButton
817
911
  });
818
912
  //#endregion
819
913
  //#region src/Textarea.tsx
@@ -894,6 +988,36 @@ function Label({ children, htmlFor, id, className, style, classNames }) {
894
988
  });
895
989
  }
896
990
  //#endregion
991
+ //#region src/switch-visual.tsx
992
+ var SwitchVisualContext = createContext({});
993
+ function SwitchGroup({ size, tone, variant, isDisabled, orientation = "vertical", className, ...props }) {
994
+ const { label, ...native } = props;
995
+ return /* @__PURE__ */ jsx(SwitchVisualContext.Provider, {
996
+ value: {
997
+ size,
998
+ tone,
999
+ variant,
1000
+ isDisabled
1001
+ },
1002
+ children: /* @__PURE__ */ jsx("div", {
1003
+ ...native,
1004
+ role: "group",
1005
+ "aria-label": label ?? props["aria-label"],
1006
+ className: partClass("switch-group", className),
1007
+ "data-orientation": orientation
1008
+ })
1009
+ });
1010
+ }
1011
+ function useSwitchVisual(props) {
1012
+ const inherited = useContext(SwitchVisualContext);
1013
+ return {
1014
+ size: props.size ?? inherited.size ?? "md",
1015
+ tone: props.tone ?? inherited.tone ?? "primary",
1016
+ variant: props.variant ?? inherited.variant ?? "default",
1017
+ disabled: inherited.isDisabled
1018
+ };
1019
+ }
1020
+ //#endregion
897
1021
  //#region src/choice-composition.tsx
898
1022
  var ChoiceStateContext = createContext({
899
1023
  isSelected: false,
@@ -939,24 +1063,43 @@ function ChoiceContent({ className, ...props }) {
939
1063
  className: partClass("choice__label", className)
940
1064
  });
941
1065
  }
942
- function SwitchComposition({ className, children, ...props }) {
943
- return /* @__PURE__ */ jsx(SwitchField, {
944
- ...props,
945
- className: partClass("input", className),
946
- children: (fieldState) => /* @__PURE__ */ jsx(SwitchButton, {
947
- className: "choice",
948
- children: (state) => /* @__PURE__ */ jsx(ChoiceStateContext.Provider, {
949
- value: state,
950
- children: typeof children === "function" ? children(fieldState) : children
1066
+ function SwitchComposition({ className, children, size, tone, variant, ...props }) {
1067
+ const visual = useSwitchVisual({
1068
+ size,
1069
+ tone,
1070
+ variant
1071
+ });
1072
+ return /* @__PURE__ */ jsx(SwitchVisualContext.Provider, {
1073
+ value: visual,
1074
+ children: /* @__PURE__ */ jsx(SwitchField, {
1075
+ ...props,
1076
+ isDisabled: props.isDisabled ?? visual.disabled,
1077
+ className: partClass("input", className),
1078
+ children: (fieldState) => /* @__PURE__ */ jsx(SwitchButton, {
1079
+ className: "choice",
1080
+ children: (state) => /* @__PURE__ */ jsx(ChoiceStateContext.Provider, {
1081
+ value: state,
1082
+ children: /* @__PURE__ */ jsx(ItemLabelContext.Provider, {
1083
+ value: true,
1084
+ children: typeof children === "function" ? children({
1085
+ ...fieldState,
1086
+ ...state
1087
+ }) : children
1088
+ })
1089
+ })
951
1090
  })
952
1091
  })
953
1092
  });
954
1093
  }
955
1094
  function SwitchControl({ className, ...props }) {
956
1095
  const state = useContext(ChoiceStateContext);
1096
+ const visual = useSwitchVisual({});
957
1097
  return /* @__PURE__ */ jsx("span", {
958
1098
  ...props,
959
1099
  className: partClass("switch__control", className),
1100
+ "data-size": visual.size,
1101
+ "data-tone": visual.tone,
1102
+ "data-variant": visual.variant,
960
1103
  "aria-hidden": "true",
961
1104
  "data-state": state.isSelected ? "checked" : "unchecked",
962
1105
  "data-disabled": state.isDisabled || void 0,
@@ -971,6 +1114,13 @@ function SwitchThumb({ className, ...props }) {
971
1114
  "aria-hidden": "true"
972
1115
  });
973
1116
  }
1117
+ function SwitchIcon({ className, ...props }) {
1118
+ return /* @__PURE__ */ jsx("span", {
1119
+ ...props,
1120
+ className: partClass("switch__icon", className),
1121
+ "aria-hidden": "true"
1122
+ });
1123
+ }
974
1124
  function RadioGroupComposition({ className, ...props }) {
975
1125
  return /* @__PURE__ */ jsx(RadioGroup$1, {
976
1126
  ...props,
@@ -1129,7 +1279,12 @@ var RadioGroup = /* @__PURE__ */ Object.assign(RadioGroupRoot, {
1129
1279
  });
1130
1280
  //#endregion
1131
1281
  //#region src/Switch.tsx
1132
- function CompactSwitch({ label, description, errorMessage, isInvalid = false, isSelected, defaultSelected, onChange, isDisabled = false, name, value = "on", id, dir, className, style, classNames }) {
1282
+ function CompactSwitch({ label, description, errorMessage, isInvalid = false, isSelected, defaultSelected, onChange, isDisabled, isReadOnly = false, isRequired = false, validate, validationBehavior = "aria", size, tone, variant, name, value = "on", id, dir, className, style, classNames }) {
1283
+ const visual = useSwitchVisual({
1284
+ size,
1285
+ tone,
1286
+ variant
1287
+ });
1133
1288
  return /* @__PURE__ */ jsxs(SwitchField, {
1134
1289
  className: partClass(partClass("input", classNames?.root), className),
1135
1290
  style,
@@ -1137,9 +1292,12 @@ function CompactSwitch({ label, description, errorMessage, isInvalid = false, is
1137
1292
  isSelected,
1138
1293
  defaultSelected,
1139
1294
  onChange,
1140
- isDisabled,
1295
+ isDisabled: isDisabled ?? visual.disabled,
1296
+ isReadOnly,
1297
+ isRequired,
1298
+ validate,
1141
1299
  isInvalid,
1142
- validationBehavior: "aria",
1300
+ validationBehavior,
1143
1301
  name,
1144
1302
  value,
1145
1303
  id,
@@ -1149,6 +1307,9 @@ function CompactSwitch({ label, description, errorMessage, isInvalid = false, is
1149
1307
  children: ({ isSelected: selected, isDisabled: disabled, isFocusVisible }) => /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("span", {
1150
1308
  "aria-hidden": "true",
1151
1309
  className: partClass("switch__control", classNames?.control),
1310
+ "data-size": visual.size,
1311
+ "data-tone": visual.tone,
1312
+ "data-variant": visual.variant,
1152
1313
  "data-state": selected ? "checked" : "unchecked",
1153
1314
  "data-disabled": disabled || void 0,
1154
1315
  "data-invalid": isInvalid || void 0,
@@ -1179,6 +1340,7 @@ var Switch = /* @__PURE__ */ Object.assign(SwitchRoot, {
1179
1340
  Root: SwitchComposition,
1180
1341
  Control: SwitchControl,
1181
1342
  Thumb: SwitchThumb,
1343
+ Icon: SwitchIcon,
1182
1344
  Content: ChoiceContent
1183
1345
  });
1184
1346
  //#endregion
@@ -1561,14 +1723,68 @@ var NumberField = /* @__PURE__ */ Object.assign(NumberFieldRoot, {
1561
1723
  });
1562
1724
  //#endregion
1563
1725
  //#region src/Card.tsx
1564
- /** A content container; place links and buttons inside rather than making it clickable. */
1565
- function CompactCard({ title, description, headingLevel = 3, actions, header, titleExtras, footer, children, className, classNames, ...props }) {
1726
+ /** Native primary action is a sibling of content, so nested controls remain valid HTML. */
1727
+ var CardTitleIdContext = createContext(void 0);
1728
+ function CardAction({ href, target, rel, onPress, isDisabled, isSelected, actionLabel, actionLabelledBy, actionClassName, renderLink }) {
1729
+ if (!href && !onPress) return null;
1730
+ if (href) {
1731
+ const props = {
1732
+ className: partClass("card__action", actionClassName),
1733
+ href: isDisabled ? void 0 : href,
1734
+ target,
1735
+ rel: rel ?? (target === "_blank" ? "noopener noreferrer" : void 0),
1736
+ "aria-label": actionLabel,
1737
+ "aria-disabled": isDisabled || void 0,
1738
+ "aria-labelledby": actionLabelledBy,
1739
+ role: isDisabled ? "link" : void 0,
1740
+ tabIndex: isDisabled ? -1 : void 0,
1741
+ onClick: (event) => {
1742
+ if (isDisabled) event.preventDefault();
1743
+ else onPress?.();
1744
+ }
1745
+ };
1746
+ return renderLink ? renderLink(props) : /* @__PURE__ */ jsx("a", {
1747
+ ...props,
1748
+ "aria-label": actionLabel,
1749
+ "aria-labelledby": actionLabelledBy
1750
+ });
1751
+ }
1752
+ const props = {
1753
+ type: "button",
1754
+ className: partClass("card__action", actionClassName),
1755
+ "aria-label": actionLabel,
1756
+ "aria-labelledby": actionLabelledBy,
1757
+ "aria-pressed": isSelected,
1758
+ disabled: isDisabled,
1759
+ onClick: () => onPress?.()
1760
+ };
1761
+ return /* @__PURE__ */ jsx("button", { ...props });
1762
+ }
1763
+ 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 }) {
1566
1764
  const Heading = `h${headingLevel}`;
1567
1765
  return /* @__PURE__ */ jsxs("div", {
1568
1766
  ...props,
1767
+ "data-density": density,
1768
+ "data-interactive": !!(href || onPress) || void 0,
1769
+ "data-disabled": isDisabled || void 0,
1770
+ "data-selected": isSelected || void 0,
1569
1771
  className: partClass(partClass("card", classNames?.root), className),
1570
1772
  children: [
1773
+ /* @__PURE__ */ jsx(CardAction, {
1774
+ href,
1775
+ target,
1776
+ rel,
1777
+ onPress,
1778
+ isDisabled,
1779
+ isSelected,
1780
+ renderLink,
1781
+ actionClassName: partClass(classNames?.action ?? "", actionClassName),
1782
+ actionLabelledBy: actionLabelledBy ?? props["aria-labelledby"],
1783
+ actionLabel: actionLabel ?? title ?? props["aria-label"]
1784
+ }),
1571
1785
  (title || description || actions || header || titleExtras) && /* @__PURE__ */ jsxs("div", {
1786
+ "data-align": headerAlign,
1787
+ "data-divided": dividedHeader || void 0,
1572
1788
  className: partClass("card__header", classNames?.header),
1573
1789
  children: [(title || description || header || titleExtras) && /* @__PURE__ */ jsx("div", {
1574
1790
  className: partClass("card__heading", classNames?.heading),
@@ -1595,21 +1811,45 @@ function CompactCard({ title, description, headingLevel = 3, actions, header, ti
1595
1811
  children
1596
1812
  }),
1597
1813
  footer && /* @__PURE__ */ jsx("div", {
1814
+ "data-flush": flushFooter || void 0,
1598
1815
  className: partClass("card__footer", classNames?.footer),
1599
1816
  children: footer
1600
1817
  })
1601
1818
  ]
1602
1819
  });
1603
1820
  }
1604
- function CardRoot({ className, ...props }) {
1605
- return /* @__PURE__ */ jsx("div", {
1606
- ...props,
1607
- className: partClass("card", className)
1821
+ function CardRoot({ className, classNames, children, density, href, target, rel, onPress, isDisabled, isSelected, actionLabel, actionLabelledBy, actionClassName, renderLink, ...props }) {
1822
+ const titleId = useId();
1823
+ const label = actionLabel ?? props["aria-label"];
1824
+ return /* @__PURE__ */ jsx(CardTitleIdContext.Provider, {
1825
+ value: titleId,
1826
+ children: /* @__PURE__ */ jsxs("div", {
1827
+ ...props,
1828
+ "data-density": density,
1829
+ "data-interactive": !!(href || onPress) || void 0,
1830
+ "data-disabled": isDisabled || void 0,
1831
+ "data-selected": isSelected || void 0,
1832
+ className: partClass(partClass("card", classNames?.root), className),
1833
+ children: [/* @__PURE__ */ jsx(CardAction, {
1834
+ href,
1835
+ target,
1836
+ rel,
1837
+ onPress,
1838
+ isDisabled,
1839
+ isSelected,
1840
+ renderLink,
1841
+ actionClassName: partClass(classNames?.action ?? "", actionClassName),
1842
+ actionLabel: label,
1843
+ actionLabelledBy: actionLabelledBy ?? props["aria-labelledby"] ?? (label ? void 0 : titleId)
1844
+ }), children]
1845
+ })
1608
1846
  });
1609
1847
  }
1610
- function CardHeader({ className, ...props }) {
1848
+ function CardHeader({ className, align, divided, ...props }) {
1611
1849
  return /* @__PURE__ */ jsx("div", {
1612
1850
  ...props,
1851
+ "data-align": align,
1852
+ "data-divided": divided || void 0,
1613
1853
  className: partClass("card__header", className)
1614
1854
  });
1615
1855
  }
@@ -1626,8 +1866,10 @@ function CardTitleRow({ className, ...props }) {
1626
1866
  });
1627
1867
  }
1628
1868
  function CardTitle({ className, headingLevel = 3, ...props }) {
1869
+ const titleId = useContext(CardTitleIdContext);
1629
1870
  const Heading = `h${headingLevel}`;
1630
1871
  return /* @__PURE__ */ jsx(Heading, {
1872
+ id: titleId,
1631
1873
  ...props,
1632
1874
  className: partClass("card__title", className)
1633
1875
  });
@@ -1650,9 +1892,10 @@ function CardContent({ className, ...props }) {
1650
1892
  className: partClass("card__content", className)
1651
1893
  });
1652
1894
  }
1653
- function CardFooter({ className, ...props }) {
1895
+ function CardFooter({ className, flush, ...props }) {
1654
1896
  return /* @__PURE__ */ jsx("div", {
1655
1897
  ...props,
1898
+ "data-flush": flush || void 0,
1656
1899
  className: partClass("card__footer", className)
1657
1900
  });
1658
1901
  }
@@ -1668,15 +1911,261 @@ var Card = /* @__PURE__ */ Object.assign(CompactCard, {
1668
1911
  Footer: CardFooter
1669
1912
  });
1670
1913
  //#endregion
1914
+ //#region src/visual-slot.tsx
1915
+ /** Decorate one child while preserving its handlers and ref. */
1916
+ function visualSlot(children, props) {
1917
+ const child = Children.only(children);
1918
+ const merged = {
1919
+ ...child.props,
1920
+ ...props
1921
+ };
1922
+ merged.className = [props.className, child.props.className].filter(Boolean).join(" ");
1923
+ merged.style = {
1924
+ ...props.style,
1925
+ ...child.props.style
1926
+ };
1927
+ for (const key of Object.keys(props)) if (/^on[A-Z]/.test(key) && typeof child.props[key] === "function" && typeof props[key] === "function") merged[key] = (...args) => {
1928
+ child.props[key](...args);
1929
+ props[key](...args);
1930
+ };
1931
+ if (child.props.ref && props.ref) merged.ref = (node) => {
1932
+ const cleanups = [];
1933
+ for (const ref of [child.props.ref, props.ref]) if (typeof ref === "function") {
1934
+ const cleanup = ref(node);
1935
+ cleanups.push(typeof cleanup === "function" ? cleanup : () => {
1936
+ ref(null);
1937
+ });
1938
+ } else if (ref) {
1939
+ ref.current = node;
1940
+ cleanups.push(() => {
1941
+ ref.current = null;
1942
+ });
1943
+ }
1944
+ return () => {
1945
+ for (const cleanup of cleanups) cleanup();
1946
+ };
1947
+ };
1948
+ return cloneElement(child, merged);
1949
+ }
1950
+ //#endregion
1671
1951
  //#region src/Badge.tsx
1672
- /** Static status text. Dynamic announcements belong in an application-owned live region. */
1673
- function Badge({ tone = "neutral", className, classNames, ...props }) {
1674
- return /* @__PURE__ */ jsx("span", {
1952
+ var AnchorContext = createContext(false);
1953
+ /** Static status text; wrap in Badge.Anchor to position it relative to another element. */
1954
+ function BadgeRoot({ tone = "neutral", size = "md", variant = "default", placement = "top-right", asChild, children, className, classNames, ...props }) {
1955
+ const anchored = useContext(AnchorContext);
1956
+ const attributes = {
1675
1957
  ...props,
1676
1958
  className: partClass(partClass("badge", classNames?.root), className),
1959
+ "data-tone": tone,
1960
+ "data-size": size,
1961
+ "data-variant": variant,
1962
+ "data-placement": anchored ? placement : void 0,
1963
+ "data-anchored": anchored || void 0,
1964
+ "data-dot": anchored && children == null || void 0
1965
+ };
1966
+ return asChild ? visualSlot(children, attributes) : /* @__PURE__ */ jsx("span", {
1967
+ ...attributes,
1968
+ children: classNames?.label ? /* @__PURE__ */ jsx("span", {
1969
+ className: partClass("badge__label", classNames.label),
1970
+ children
1971
+ }) : children
1972
+ });
1973
+ }
1974
+ function BadgeAnchor({ className, ...props }) {
1975
+ return /* @__PURE__ */ jsx(AnchorContext.Provider, {
1976
+ value: true,
1977
+ children: /* @__PURE__ */ jsx("span", {
1978
+ ...props,
1979
+ className: partClass("badge-anchor badge__anchor", className)
1980
+ })
1981
+ });
1982
+ }
1983
+ function BadgeLabel({ className, ...props }) {
1984
+ return /* @__PURE__ */ jsx("span", {
1985
+ ...props,
1986
+ className: partClass("badge__label", className)
1987
+ });
1988
+ }
1989
+ var Badge = /* @__PURE__ */ Object.assign(BadgeRoot, {
1990
+ Root: BadgeRoot,
1991
+ Anchor: BadgeAnchor,
1992
+ Label: BadgeLabel
1993
+ });
1994
+ //#endregion
1995
+ //#region src/Avatar.tsx
1996
+ var AvatarGroupContext = createContext({});
1997
+ var AvatarContext = createContext(null);
1998
+ function AvatarRoot({ size, tone, variant, radius = "full", asChild, children, className, classNames, ...props }) {
1999
+ const group = useContext(AvatarGroupContext);
2000
+ const [status, setStatus] = useState("idle");
2001
+ const actualSize = size ?? group.size ?? "md";
2002
+ const attributes = {
2003
+ ...props,
2004
+ className: partClass(partClass("avatar", classNames?.root), className),
2005
+ "data-size": actualSize,
2006
+ "data-tone": tone ?? group.tone ?? "neutral",
2007
+ "data-variant": variant ?? group.variant ?? "default",
2008
+ "data-radius": radius,
2009
+ "data-image-status": status
2010
+ };
2011
+ return /* @__PURE__ */ jsx(AvatarContext.Provider, {
2012
+ value: {
2013
+ status,
2014
+ setStatus,
2015
+ size: actualSize,
2016
+ classNames
2017
+ },
2018
+ children: asChild ? visualSlot(children, attributes) : /* @__PURE__ */ jsx("span", {
2019
+ ...attributes,
2020
+ children
2021
+ })
2022
+ });
2023
+ }
2024
+ function AvatarImage(props) {
2025
+ return /* @__PURE__ */ jsx(AvatarImageLoader, { ...props }, `${props.src ?? ""}|${props.srcSet ?? ""}|${props.sizes ?? ""}`);
2026
+ }
2027
+ function AvatarImageLoader({ src, srcSet, sizes, alt, asChild, children, className, onLoad, onError, onLoadingStatusChange, ref, ...props }) {
2028
+ const context = useContext(AvatarContext);
2029
+ const setStatus = context?.setStatus;
2030
+ const imageRef = useRef(null);
2031
+ const [result, setResult] = useState({
2032
+ source: "",
2033
+ status: "idle"
2034
+ });
2035
+ const source = `${src ?? ""}|${srcSet ?? ""}|${sizes ?? ""}`;
2036
+ const status = result.source === source ? result.status : src || srcSet ? "loading" : "error";
2037
+ const statusCallback = useRef(onLoadingStatusChange);
2038
+ useEffect(() => {
2039
+ statusCallback.current = onLoadingStatusChange;
2040
+ });
2041
+ useEffect(() => {
2042
+ setStatus?.(status);
2043
+ statusCallback.current?.(status);
2044
+ }, [status, setStatus]);
2045
+ useEffect(() => () => setStatus?.("idle"), [setStatus]);
2046
+ useEffect(() => {
2047
+ if (imageRef.current?.complete && imageRef.current.naturalWidth > 0) setResult({
2048
+ source,
2049
+ status: "loaded"
2050
+ });
2051
+ }, [source]);
2052
+ const attributes = {
2053
+ ...props,
2054
+ src,
2055
+ srcSet,
2056
+ sizes,
2057
+ className: partClass(partClass("avatar__image", context?.classNames?.image), className),
2058
+ "data-status": status,
2059
+ "aria-hidden": status !== "loaded" || void 0,
2060
+ ref: (node) => {
2061
+ imageRef.current = node;
2062
+ if (typeof ref === "function") return ref(node);
2063
+ else if (ref) ref.current = node;
2064
+ },
2065
+ onLoad: (event) => {
2066
+ if (event.currentTarget !== imageRef.current) return;
2067
+ setResult({
2068
+ source,
2069
+ status: "loaded"
2070
+ });
2071
+ onLoad?.(event);
2072
+ },
2073
+ onError: (event) => {
2074
+ if (event.currentTarget !== imageRef.current) return;
2075
+ setResult({
2076
+ source,
2077
+ status: "error"
2078
+ });
2079
+ onError?.(event);
2080
+ }
2081
+ };
2082
+ return asChild ? visualSlot(children, {
2083
+ ...attributes,
2084
+ ...alt !== void 0 ? { alt } : {}
2085
+ }) : /* @__PURE__ */ jsx("img", {
2086
+ ...attributes,
2087
+ alt: alt ?? ""
2088
+ }, source);
2089
+ }
2090
+ function AvatarFallback({ delayMs = 0, tone, className, ...props }) {
2091
+ const context = useContext(AvatarContext);
2092
+ const [ready, setReady] = useState(delayMs <= 0);
2093
+ useEffect(() => {
2094
+ setReady(delayMs <= 0);
2095
+ if (delayMs <= 0) return;
2096
+ const timer = setTimeout(() => setReady(true), delayMs);
2097
+ return () => clearTimeout(timer);
2098
+ }, [delayMs, context?.status]);
2099
+ if (context?.status === "loaded" || !ready) return null;
2100
+ return /* @__PURE__ */ jsx("span", {
2101
+ ...props,
2102
+ className: partClass(partClass("avatar__fallback", context?.classNames?.fallback), className),
1677
2103
  "data-tone": tone
1678
2104
  });
1679
2105
  }
2106
+ function AvatarBadge({ size, tone = "primary", placement = "bottom-right", className, children, ...props }) {
2107
+ const context = useContext(AvatarContext);
2108
+ return /* @__PURE__ */ jsx("span", {
2109
+ ...props,
2110
+ className: partClass(partClass("avatar__badge", context?.classNames?.badge), className),
2111
+ "data-size": size ?? context?.size ?? "md",
2112
+ "data-tone": tone,
2113
+ "data-placement": placement,
2114
+ "data-dot": children == null || void 0,
2115
+ children
2116
+ });
2117
+ }
2118
+ var Avatar = /* @__PURE__ */ Object.assign(AvatarRoot, {
2119
+ Root: AvatarRoot,
2120
+ Image: AvatarImage,
2121
+ Fallback: AvatarFallback,
2122
+ Badge: AvatarBadge
2123
+ });
2124
+ //#endregion
2125
+ //#region src/AvatarGroup.tsx
2126
+ function flatten(children, prefix = "") {
2127
+ return Children.toArray(children).flatMap((child, index) => {
2128
+ const key = `${prefix}/${isValidElement(child) ? child.key ?? index : index}`;
2129
+ return isValidElement(child) && child.type === Fragment ? flatten(child.props.children, key) : isValidElement(child) ? [cloneElement(child, { key })] : [];
2130
+ });
2131
+ }
2132
+ function AvatarGroupCount({ className, ...props }) {
2133
+ return /* @__PURE__ */ jsx(Avatar, {
2134
+ ...props,
2135
+ className: partClass("avatar-group__count", className),
2136
+ children: /* @__PURE__ */ jsx(Avatar.Fallback, { children: props.children })
2137
+ });
2138
+ }
2139
+ function AvatarGroupRoot({ size = "md", tone = "neutral", variant = "default", max, isGrid = false, overlap = "clip", className, classNames, children, ...props }) {
2140
+ const items = flatten(children);
2141
+ const counts = items.filter((item) => isValidElement(item) && item.type === AvatarGroupCount);
2142
+ const avatars = items.filter((item) => !counts.includes(item));
2143
+ const limit = max === void 0 || !Number.isFinite(max) ? avatars.length : Math.max(0, Math.floor(max));
2144
+ const hidden = Math.max(0, avatars.length - limit);
2145
+ return /* @__PURE__ */ jsx(AvatarGroupContext.Provider, {
2146
+ value: {
2147
+ size,
2148
+ tone,
2149
+ variant
2150
+ },
2151
+ children: /* @__PURE__ */ jsxs("div", {
2152
+ ...props,
2153
+ className: partClass(partClass("avatar-group", classNames?.root), className),
2154
+ "data-size": size,
2155
+ "data-grid": isGrid || void 0,
2156
+ "data-overlap": overlap,
2157
+ children: [avatars.slice(0, limit), counts.length ? counts : hidden > 0 ? /* @__PURE__ */ jsxs(AvatarGroupCount, {
2158
+ className: classNames?.count,
2159
+ "aria-label": `${hidden} more`,
2160
+ children: ["+", hidden]
2161
+ }) : null]
2162
+ })
2163
+ });
2164
+ }
2165
+ var AvatarGroup = /* @__PURE__ */ Object.assign(AvatarGroupRoot, {
2166
+ Root: AvatarGroupRoot,
2167
+ Count: AvatarGroupCount
2168
+ });
1680
2169
  //#endregion
1681
2170
  //#region src/Skeleton.tsx
1682
2171
  /** Decorative placeholder. Set aria-busy and loading text on the surrounding content. */
@@ -1800,7 +2289,7 @@ function mountTabsIndicator(container) {
1800
2289
  }
1801
2290
  //#endregion
1802
2291
  //#region src/Tabs.tsx
1803
- function CompactTabs({ className, style, classNames, label, variant = "primary", size = "md", orientation = "horizontal", align = "center", fullWidth = false, inset = "default", showSeparators = false, renderIcon, previousLabel = "Tab sebelumnya / Previous tabs", nextLabel = "Tab berikutnya / Next tabs", extras, actions, items, value, defaultValue, onChange, renderPanel, activationMode = "manual", dir, id }) {
2292
+ function CompactTabs({ className, style, classNames, label, variant = "primary", size = "md", indicatorShadow = true, orientation = "horizontal", align = "center", fullWidth = false, inset = "default", showSeparators = false, renderIcon, previousLabel = "Tab sebelumnya / Previous tabs", nextLabel = "Tab berikutnya / Next tabs", extras, actions, items, value, defaultValue, onChange, renderPanel, activationMode = "manual", dir, id }) {
1804
2293
  const container = useRef(null);
1805
2294
  const hasToolbar = !!(extras || actions);
1806
2295
  useEffect(() => container.current ? mountTabsIndicator(container.current) : void 0, [items.length, hasToolbar]);
@@ -1861,6 +2350,7 @@ function CompactTabs({ className, style, classNames, label, variant = "primary",
1861
2350
  ]
1862
2351
  }) : null;
1863
2352
  const content = /* @__PURE__ */ jsxs(Tabs$1, {
2353
+ "data-indicator-shadow": indicatorShadow,
1864
2354
  className: [
1865
2355
  "tabs",
1866
2356
  classNames?.root,
@@ -1908,9 +2398,10 @@ function CompactTabs({ className, style, classNames, label, variant = "primary",
1908
2398
  children: content
1909
2399
  }) : content;
1910
2400
  }
1911
- function TabsRoot({ className, classNames, value, defaultValue, onChange, variant = "primary", size = "md", align = "center", fullWidth, ...props }) {
2401
+ function TabsRoot({ className, classNames, value, defaultValue, onChange, variant = "primary", size = "md", align = "center", fullWidth, indicatorShadow = true, ...props }) {
1912
2402
  return /* @__PURE__ */ jsx(Tabs$1, {
1913
2403
  ...props,
2404
+ "data-indicator-shadow": indicatorShadow,
1914
2405
  selectedKey: value,
1915
2406
  defaultSelectedKey: defaultValue,
1916
2407
  onSelectionChange: onChange ? (key) => onChange(String(key)) : void 0,
@@ -3259,7 +3750,7 @@ function CompactDropdownMenu(props) {
3259
3750
  onOpenChange: change,
3260
3751
  children: [/* @__PURE__ */ jsx(Button$1, {
3261
3752
  style,
3262
- className: partClass(partClass(partClass(`button button--${props.triggerVariant ?? "secondary"}${props.triggerIconOnly ? " button--icon-only" : ""}`, classNames?.trigger), classNames?.root), className),
3753
+ className: partClass(partClass(partClass(`button button--${props.triggerVariant ?? "secondary"} button--${props.triggerSize ?? "md"}${props.triggerIconOnly ? " button--icon-only" : ""}`, classNames?.trigger), classNames?.root), className),
3263
3754
  "aria-label": triggerLabel,
3264
3755
  isDisabled: isDisabled || !items.length,
3265
3756
  children: props.triggerContent ?? triggerLabel
@@ -3861,38 +4352,355 @@ function DateRangeCancelButton({ className, onClick, children, ...props }) {
3861
4352
  });
3862
4353
  }
3863
4354
  //#endregion
3864
- //#region src/date-range-model.ts
3865
- function dateRangeLabels(locale = "id-ID") {
3866
- return locale.startsWith("id") ? {
3867
- title: "Pilih rentang tanggal",
3868
- start: "Tanggal mulai",
3869
- end: "Tanggal akhir",
3870
- apply: "Terapkan",
3871
- cancel: "Batal",
3872
- clear: "Kosongkan",
3873
- previousMonth: "Bulan sebelumnya",
3874
- nextMonth: "Bulan berikutnya",
3875
- presets: "Pilihan cepat",
3876
- placeholder: "Pilih tanggal",
3877
- incomplete: "Lengkapi tanggal mulai dan akhir.",
3878
- order: "Tanggal akhir harus setelah atau sama dengan tanggal mulai.",
3879
- bounds: "Tanggal berada di luar batas yang diizinkan.",
3880
- unavailable: "Rentang memuat tanggal yang tidak tersedia.",
3881
- length: "Durasi rentang tidak sesuai batas yang diizinkan.",
3882
- required: "Rentang tanggal wajib diisi."
3883
- } : {
3884
- title: "Select date range",
3885
- start: "Start date",
3886
- end: "End date",
3887
- apply: "Apply",
3888
- cancel: "Cancel",
3889
- clear: "Clear",
3890
- previousMonth: "Previous month",
3891
- nextMonth: "Next month",
3892
- presets: "Quick selections",
3893
- placeholder: "Choose dates",
3894
- incomplete: "Enter both start and end dates.",
3895
- order: "End date must be on or after start date.",
4355
+ //#region src/Calendar.tsx
4356
+ function date(value) {
4357
+ try {
4358
+ return value ? parseDate(value) : void 0;
4359
+ } catch {
4360
+ return;
4361
+ }
4362
+ }
4363
+ function monthName(year, month, locale) {
4364
+ return new Intl.DateTimeFormat(locale, {
4365
+ month: "long",
4366
+ timeZone: "UTC",
4367
+ calendar: "gregory"
4368
+ }).format(new CalendarDate(year, month, 1).toDate("UTC"));
4369
+ }
4370
+ function MonthPicker({ value, year = today("UTC").year, onChange, locale = "id-ID", minDate, maxDate, isDisabled, className, ...props }) {
4371
+ return /* @__PURE__ */ jsx("div", {
4372
+ ...props,
4373
+ className: partClass("calendar__choices", className),
4374
+ role: "group",
4375
+ "aria-label": locale.startsWith("id") ? "Pilih bulan" : "Choose month",
4376
+ children: Array.from({ length: 12 }, (_, i) => i + 1).map((month) => {
4377
+ const start = new CalendarDate(year, month, 1);
4378
+ const end = start.add({ months: 1 }).subtract({ days: 1 });
4379
+ return /* @__PURE__ */ jsx("button", {
4380
+ type: "button",
4381
+ disabled: isDisabled || !!(date(minDate) && end.compare(date(minDate)) < 0) || !!(date(maxDate) && start.compare(date(maxDate)) > 0),
4382
+ "aria-pressed": value === month,
4383
+ onClick: () => onChange?.(month),
4384
+ children: monthName(year, month, locale)
4385
+ }, month);
4386
+ })
4387
+ });
4388
+ }
4389
+ function YearPicker({ value = today("UTC").year, onChange, locale = "id-ID", minDate, maxDate, isDisabled, className, ...props }) {
4390
+ const min = date(minDate)?.year ?? 1, max = date(maxDate)?.year ?? 9999;
4391
+ const [page, setPage] = useState(Math.max(min, Math.min(max, Math.floor((value - 1) / 12) * 12 + 1)));
4392
+ return /* @__PURE__ */ jsxs("div", {
4393
+ ...props,
4394
+ className: partClass("calendar__years", className),
4395
+ children: [/* @__PURE__ */ jsxs("div", {
4396
+ className: "calendar__year-navigation",
4397
+ children: [
4398
+ /* @__PURE__ */ jsx("button", {
4399
+ type: "button",
4400
+ "aria-label": locale.startsWith("id") ? "Tahun sebelumnya" : "Previous years",
4401
+ disabled: isDisabled || page <= min,
4402
+ onClick: () => setPage(Math.max(min, page - 12)),
4403
+ children: "‹"
4404
+ }),
4405
+ /* @__PURE__ */ jsxs("span", { children: [
4406
+ page,
4407
+ "–",
4408
+ Math.min(page + 11, max)
4409
+ ] }),
4410
+ /* @__PURE__ */ jsx("button", {
4411
+ type: "button",
4412
+ "aria-label": locale.startsWith("id") ? "Tahun berikutnya" : "Next years",
4413
+ disabled: isDisabled || page + 11 >= max,
4414
+ onClick: () => setPage(Math.max(min, Math.min(max - 11, page + 12))),
4415
+ children: "›"
4416
+ })
4417
+ ]
4418
+ }), /* @__PURE__ */ jsx("div", {
4419
+ className: "calendar__choices",
4420
+ role: "group",
4421
+ "aria-label": locale.startsWith("id") ? "Pilih tahun" : "Choose year",
4422
+ children: Array.from({ length: 12 }, (_, i) => page + i).filter((year) => year <= 9999).map((year) => /* @__PURE__ */ jsx("button", {
4423
+ type: "button",
4424
+ disabled: isDisabled || year < min || year > max,
4425
+ "aria-pressed": value === year,
4426
+ onClick: () => onChange?.(year),
4427
+ children: year
4428
+ }, year))
4429
+ })]
4430
+ });
4431
+ }
4432
+ function MonthYearNavigation({ value, onChange, locale = "id-ID", minDate, maxDate, isDisabled, className, ...props }) {
4433
+ const current = date(value) ?? today("UTC");
4434
+ const [view, setView] = useState(null);
4435
+ const header = useRef(null), lastToggle = useRef("month"), previousView = useRef(null);
4436
+ useEffect(() => {
4437
+ if (view) (header.current?.querySelector(".calendar__view [aria-pressed=\"true\"]:not(:disabled)") ?? header.current?.querySelector(".calendar__view button:not(:disabled)"))?.focus();
4438
+ else if (previousView.current) header.current?.querySelectorAll(".date-range__heading > button")[lastToggle.current === "month" ? 0 : 1]?.focus();
4439
+ previousView.current = view;
4440
+ }, [view]);
4441
+ useEffect(() => {
4442
+ if (!view) return;
4443
+ const grid = header.current?.closest(".date-range__month")?.querySelector(".date-range__grid");
4444
+ if (!grid) return;
4445
+ const inert = grid.hasAttribute("inert"), hidden = grid.getAttribute("aria-hidden");
4446
+ grid.inert = true;
4447
+ grid.setAttribute("inert", "");
4448
+ grid.setAttribute("aria-hidden", "true");
4449
+ return () => {
4450
+ grid.inert = inert;
4451
+ if (!inert) grid.removeAttribute("inert");
4452
+ if (hidden === null) grid.removeAttribute("aria-hidden");
4453
+ else grid.setAttribute("aria-hidden", hidden);
4454
+ };
4455
+ }, [view]);
4456
+ const navigate = (year, month) => {
4457
+ let next = new CalendarDate(year, month, 1);
4458
+ const min = date(minDate), max = date(maxDate);
4459
+ if (min && next.compare(min) < 0) next = min;
4460
+ if (max && next.compare(max) > 0) next = max;
4461
+ onChange(next.toString());
4462
+ };
4463
+ return /* @__PURE__ */ jsxs("div", {
4464
+ ...props,
4465
+ ref: header,
4466
+ className: partClass("calendar__header", className),
4467
+ children: [/* @__PURE__ */ jsxs("div", {
4468
+ className: "date-range__heading",
4469
+ children: [/* @__PURE__ */ jsx("button", {
4470
+ type: "button",
4471
+ disabled: isDisabled,
4472
+ "aria-expanded": view === "month",
4473
+ onClick: () => {
4474
+ lastToggle.current = "month";
4475
+ setView(view === "month" ? null : "month");
4476
+ },
4477
+ children: monthName(current.year, current.month, locale)
4478
+ }), /* @__PURE__ */ jsx("button", {
4479
+ type: "button",
4480
+ disabled: isDisabled,
4481
+ "aria-expanded": view === "year",
4482
+ onClick: () => {
4483
+ lastToggle.current = "year";
4484
+ setView(view === "year" ? null : "year");
4485
+ },
4486
+ children: current.year
4487
+ })]
4488
+ }), view && /* @__PURE__ */ jsxs("div", {
4489
+ className: "calendar__view",
4490
+ role: "group",
4491
+ "aria-label": view === "year" ? locale.startsWith("id") ? "Pilih tahun" : "Choose year" : locale.startsWith("id") ? "Pilih bulan" : "Choose month",
4492
+ onKeyDownCapture: (e) => {
4493
+ if (e.key === "Escape") {
4494
+ e.stopPropagation();
4495
+ setView(null);
4496
+ }
4497
+ },
4498
+ children: [view === "month" ? /* @__PURE__ */ jsx(MonthPicker, {
4499
+ value: current.month,
4500
+ year: current.year,
4501
+ locale,
4502
+ minDate,
4503
+ maxDate,
4504
+ isDisabled,
4505
+ onChange: (month) => {
4506
+ navigate(current.year, month);
4507
+ setView(null);
4508
+ }
4509
+ }) : /* @__PURE__ */ jsx(YearPicker, {
4510
+ value: current.year,
4511
+ locale,
4512
+ minDate,
4513
+ maxDate,
4514
+ isDisabled,
4515
+ onChange: (year) => {
4516
+ navigate(year, current.month);
4517
+ setView("month");
4518
+ }
4519
+ }), /* @__PURE__ */ jsx("button", {
4520
+ type: "button",
4521
+ className: "calendar__back",
4522
+ onClick: () => setView(null),
4523
+ children: locale.startsWith("id") ? "Kembali" : "Back"
4524
+ })]
4525
+ })]
4526
+ });
4527
+ }
4528
+ /** Reads actual visibleRange rather than assuming the focused day is the first panel. */
4529
+ function CalendarViewHeader({ offset = 0, onNavigate, ...props }) {
4530
+ const single = useContext(CalendarStateContext);
4531
+ const visible = (useContext(RangeCalendarStateContext) ?? single)?.visibleRange.start ?? today("UTC");
4532
+ return /* @__PURE__ */ jsx(MonthYearNavigation, {
4533
+ ...props,
4534
+ value: visible.add({ months: offset }).toString(),
4535
+ onChange: (value) => onNavigate(parseDate(value).subtract({ months: offset }))
4536
+ });
4537
+ }
4538
+ function CalendarBody({ props, onNavigate }) {
4539
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs("div", {
4540
+ className: "date-range__navigation",
4541
+ children: [/* @__PURE__ */ jsx(Button$1, {
4542
+ slot: "previous",
4543
+ className: "date-range__nav",
4544
+ "aria-label": props.locale?.startsWith("id") ? "Bulan sebelumnya" : "Previous month",
4545
+ children: "‹"
4546
+ }), /* @__PURE__ */ jsx(Button$1, {
4547
+ slot: "next",
4548
+ className: "date-range__nav",
4549
+ "aria-label": props.locale?.startsWith("id") ? "Bulan berikutnya" : "Next month",
4550
+ children: "›"
4551
+ })]
4552
+ }), /* @__PURE__ */ jsx("div", {
4553
+ className: "date-range__months",
4554
+ children: Array.from({ length: props.visibleMonths ?? 1 }, (_, i) => /* @__PURE__ */ jsxs("div", {
4555
+ className: partClass("date-range__month", props.classNames?.month),
4556
+ children: [/* @__PURE__ */ jsx(CalendarViewHeader, {
4557
+ offset: i,
4558
+ onNavigate,
4559
+ locale: props.locale,
4560
+ minDate: props.minDate,
4561
+ maxDate: props.maxDate,
4562
+ isDisabled: props.isDisabled,
4563
+ className: props.classNames?.header
4564
+ }), /* @__PURE__ */ jsxs(CalendarGrid$1, {
4565
+ offset: { months: i },
4566
+ className: partClass("date-range__grid", props.classNames?.grid),
4567
+ weekdayStyle: "short",
4568
+ children: [/* @__PURE__ */ jsx(CalendarGridHeader$1, { children: (day) => /* @__PURE__ */ jsx(CalendarHeaderCell$1, {
4569
+ className: "date-range__weekday",
4570
+ children: day
4571
+ }) }), /* @__PURE__ */ jsx(CalendarGridBody$1, { children: (day) => /* @__PURE__ */ jsx(CalendarCell$1, {
4572
+ date: day,
4573
+ className: partClass("date-range__day", props.classNames?.day)
4574
+ }) })]
4575
+ })]
4576
+ }, i))
4577
+ })] });
4578
+ }
4579
+ function Calendar(props) {
4580
+ const [local, setLocal] = useState(props.defaultValue ?? null);
4581
+ const value = props.value === void 0 ? local : props.value;
4582
+ useEffect(() => {
4583
+ const next = date(value);
4584
+ if (next) setFocused(next);
4585
+ }, [value]);
4586
+ const [focused, setFocused] = useState(() => date(value) ?? date(props.referenceDate) ?? date(props.minDate) ?? today("UTC"));
4587
+ return /* @__PURE__ */ jsx(I18nProvider, {
4588
+ locale: props.locale ?? "id-ID",
4589
+ children: /* @__PURE__ */ jsx(Calendar$1, {
4590
+ className: partClass(partClass("date-range__calendar calendar", props.classNames?.root), props.className),
4591
+ style: props.style,
4592
+ "aria-label": props.label ?? "Calendar",
4593
+ dir: props.dir,
4594
+ value: date(value) ?? null,
4595
+ focusedValue: focused,
4596
+ onFocusChange: setFocused,
4597
+ createCalendar: () => new GregorianCalendar(),
4598
+ visibleDuration: { months: props.visibleMonths ?? 1 },
4599
+ pageBehavior: "single",
4600
+ firstDayOfWeek: props.weekStartsOn === 0 ? "sun" : "mon",
4601
+ minValue: date(props.minDate),
4602
+ maxValue: date(props.maxDate),
4603
+ isDisabled: props.isDisabled,
4604
+ isReadOnly: props.isReadOnly,
4605
+ isDateUnavailable: (v) => props.isDateUnavailable?.(v.toString()) ?? false,
4606
+ onChange: (v) => {
4607
+ const next = v?.toString() ?? null;
4608
+ setLocal(next);
4609
+ props.onChange?.(next);
4610
+ },
4611
+ children: /* @__PURE__ */ jsx(CalendarBody, {
4612
+ props,
4613
+ onNavigate: setFocused
4614
+ })
4615
+ })
4616
+ });
4617
+ }
4618
+ function RangeCalendar(props) {
4619
+ const [local, setLocal] = useState(props.defaultValue ?? null);
4620
+ const value = props.value === void 0 ? local : props.value;
4621
+ const selectedStart = value?.start;
4622
+ useEffect(() => {
4623
+ const next = date(selectedStart);
4624
+ if (next) setFocused(next);
4625
+ }, [selectedStart]);
4626
+ const [focused, setFocused] = useState(() => date(value?.start) ?? date(props.referenceDate) ?? date(props.minDate) ?? today("UTC"));
4627
+ const selected = date(value?.start) && date(value?.end) ? {
4628
+ start: date(value?.start),
4629
+ end: date(value?.end)
4630
+ } : null;
4631
+ return /* @__PURE__ */ jsx(I18nProvider, {
4632
+ locale: props.locale ?? "id-ID",
4633
+ children: /* @__PURE__ */ jsx(RangeCalendar$1, {
4634
+ className: partClass(partClass("date-range__calendar calendar", props.classNames?.root), props.className),
4635
+ style: props.style,
4636
+ "aria-label": props.label ?? "Calendar",
4637
+ dir: props.dir,
4638
+ value: selected,
4639
+ focusedValue: focused,
4640
+ onFocusChange: setFocused,
4641
+ createCalendar: () => new GregorianCalendar(),
4642
+ visibleDuration: { months: props.visibleMonths ?? 2 },
4643
+ pageBehavior: "single",
4644
+ firstDayOfWeek: props.weekStartsOn === 0 ? "sun" : "mon",
4645
+ minValue: date(props.minDate),
4646
+ maxValue: date(props.maxDate),
4647
+ isDisabled: props.isDisabled,
4648
+ isReadOnly: props.isReadOnly,
4649
+ isDateUnavailable: (v) => props.isDateUnavailable?.(v.toString()) ?? false,
4650
+ onChange: (v) => {
4651
+ const next = v ? {
4652
+ start: v.start.toString(),
4653
+ end: v.end.toString()
4654
+ } : null;
4655
+ setLocal(next);
4656
+ props.onChange?.(next);
4657
+ },
4658
+ children: /* @__PURE__ */ jsx(CalendarBody, {
4659
+ props: {
4660
+ ...props,
4661
+ visibleMonths: props.visibleMonths ?? 2,
4662
+ value: null,
4663
+ defaultValue: null,
4664
+ onChange: void 0
4665
+ },
4666
+ onNavigate: setFocused
4667
+ })
4668
+ })
4669
+ });
4670
+ }
4671
+ //#endregion
4672
+ //#region src/date-range-model.ts
4673
+ function dateRangeLabels(locale = "id-ID") {
4674
+ return locale.startsWith("id") ? {
4675
+ title: "Pilih rentang tanggal",
4676
+ start: "Tanggal mulai",
4677
+ end: "Tanggal akhir",
4678
+ apply: "Terapkan",
4679
+ cancel: "Batal",
4680
+ clear: "Kosongkan",
4681
+ previousMonth: "Bulan sebelumnya",
4682
+ nextMonth: "Bulan berikutnya",
4683
+ presets: "Pilihan cepat",
4684
+ placeholder: "Pilih tanggal",
4685
+ incomplete: "Lengkapi tanggal mulai dan akhir.",
4686
+ order: "Tanggal akhir harus setelah atau sama dengan tanggal mulai.",
4687
+ bounds: "Tanggal berada di luar batas yang diizinkan.",
4688
+ unavailable: "Rentang memuat tanggal yang tidak tersedia.",
4689
+ length: "Durasi rentang tidak sesuai batas yang diizinkan.",
4690
+ required: "Rentang tanggal wajib diisi."
4691
+ } : {
4692
+ title: "Select date range",
4693
+ start: "Start date",
4694
+ end: "End date",
4695
+ apply: "Apply",
4696
+ cancel: "Cancel",
4697
+ clear: "Clear",
4698
+ previousMonth: "Previous month",
4699
+ nextMonth: "Next month",
4700
+ presets: "Quick selections",
4701
+ placeholder: "Choose dates",
4702
+ incomplete: "Enter both start and end dates.",
4703
+ order: "End date must be on or after start date.",
3896
4704
  bounds: "Dates are outside the allowed limits.",
3897
4705
  unavailable: "The range includes an unavailable date.",
3898
4706
  length: "The range duration is outside the allowed limits.",
@@ -4011,7 +4819,7 @@ function CalendarContent({ onPending, dir, children }) {
4011
4819
  });
4012
4820
  }
4013
4821
  function DateRangePickerRoot(props) {
4014
- const { label, locale = "id-ID", dir, size = "md", variant = "primary", fullWidth = true, hideLabel = false, visibleMonths = 2, weekStartsOn = 1, display = "popover", showInputs = true, presets = [], isDisabled = false, isReadOnly = false, isRequired = false } = props;
4822
+ const { label, locale = "id-ID", dir, size = "md", variant = "primary", fullWidth = true, hideLabel = false, visibleMonths = 2, weekStartsOn = 1, display = "auto", showInputs = true, presets = [], isDisabled = false, isReadOnly = false, isRequired = false } = props;
4015
4823
  const labels = {
4016
4824
  ...dateRangeLabels(locale),
4017
4825
  ...props.labels
@@ -4032,6 +4840,15 @@ function DateRangePickerRoot(props) {
4032
4840
  const [formError, setFormError] = useState(false);
4033
4841
  const [pending, setPending] = useState(false), [calendarKey, setCalendarKey] = useState(0);
4034
4842
  const trigger = useRef(null);
4843
+ const [mobile, setMobile] = useState(false);
4844
+ useEffect(() => {
4845
+ const query = window.matchMedia("(max-width: 640px)");
4846
+ const change = () => setMobile(query.matches);
4847
+ change();
4848
+ query.addEventListener("change", change);
4849
+ return () => query.removeEventListener("change", change);
4850
+ }, []);
4851
+ const isDialog = display === "dialog" || display === "auto" && mobile;
4035
4852
  const id = useId();
4036
4853
  const disclosure = useDisclosure(props.open, props.defaultOpen, props.onOpenChange);
4037
4854
  const visible = disclosure.visible && !isDisabled;
@@ -4044,6 +4861,23 @@ function DateRangePickerRoot(props) {
4044
4861
  setPending(false);
4045
4862
  setCalendarKey((k) => k + 1);
4046
4863
  }
4864
+ function updateDraft(next) {
4865
+ if (isDisabled || isReadOnly) return;
4866
+ setDraft(next);
4867
+ const value = next.start || next.end ? next : null;
4868
+ if (props.commitMode === "immediate" && !rangeError(value, props)) {
4869
+ setLocal(value);
4870
+ setFormError(false);
4871
+ props.onChange?.(value);
4872
+ }
4873
+ }
4874
+ function clearDraft() {
4875
+ replaceDraft(empty());
4876
+ if (props.commitMode === "immediate" && !isDisabled && !isReadOnly) {
4877
+ setLocal(null);
4878
+ props.onChange?.(null);
4879
+ }
4880
+ }
4047
4881
  function resetDraft() {
4048
4882
  replaceDraft({
4049
4883
  start,
@@ -4079,13 +4913,17 @@ function DateRangePickerRoot(props) {
4079
4913
  ...draft,
4080
4914
  [part]: value
4081
4915
  });
4916
+ updateDraft({
4917
+ ...draft,
4918
+ [part]: value
4919
+ });
4082
4920
  if (asDate(value)) setFocused(asDate(value));
4083
4921
  }
4084
4922
  const calendarValue = asDate(draft.start) && asDate(draft.end) && draft.start <= draft.end ? {
4085
4923
  start: asDate(draft.start),
4086
4924
  end: asDate(draft.end)
4087
4925
  } : null;
4088
- const calendar = /* @__PURE__ */ jsx(RangeCalendar, {
4926
+ const calendar = /* @__PURE__ */ jsx(RangeCalendar$1, {
4089
4927
  dir,
4090
4928
  className: partClass("date-range__calendar", props.classNames?.calendar),
4091
4929
  "aria-label": labels.title,
@@ -4094,7 +4932,7 @@ function DateRangePickerRoot(props) {
4094
4932
  onFocusChange: setFocused,
4095
4933
  createCalendar: () => new GregorianCalendar(),
4096
4934
  onChange: (v) => {
4097
- if (v) setDraft({
4935
+ if (v) updateDraft({
4098
4936
  start: v.start.toString(),
4099
4937
  end: v.end.toString()
4100
4938
  });
@@ -4127,9 +4965,14 @@ function DateRangePickerRoot(props) {
4127
4965
  className: partClass("date-range__months", props.classNames?.months),
4128
4966
  children: Array.from({ length: visibleMonths }, (_, i) => /* @__PURE__ */ jsxs("div", {
4129
4967
  className: partClass("date-range__month", props.classNames?.month),
4130
- children: [/* @__PURE__ */ jsx(CalendarHeading, {
4131
- offset: { months: i },
4132
- className: partClass("date-range__heading", props.classNames?.heading)
4968
+ children: [/* @__PURE__ */ jsx(CalendarViewHeader, {
4969
+ offset: i,
4970
+ onNavigate: setFocused,
4971
+ locale,
4972
+ minDate: props.minDate,
4973
+ maxDate: props.maxDate,
4974
+ isDisabled,
4975
+ className: props.classNames?.heading
4133
4976
  }), /* @__PURE__ */ jsxs(CalendarGrid, {
4134
4977
  offset: { months: i },
4135
4978
  className: partClass("date-range__grid", props.classNames?.grid),
@@ -4175,6 +5018,7 @@ function DateRangePickerRoot(props) {
4175
5018
  "aria-pressed": !pending && draft.start === p.value.start && draft.end === p.value.end,
4176
5019
  onClick: () => {
4177
5020
  replaceDraft({ ...p.value });
5021
+ updateDraft({ ...p.value });
4178
5022
  setFocused(asDate(p.value.start));
4179
5023
  },
4180
5024
  children: p.label
@@ -4253,26 +5097,46 @@ function DateRangePickerRoot(props) {
4253
5097
  ]
4254
5098
  })]
4255
5099
  }),
4256
- /* @__PURE__ */ jsxs("footer", {
5100
+ props.showActions !== false && /* @__PURE__ */ jsxs("footer", {
4257
5101
  className: partClass("date-range__footer", props.classNames?.footer),
4258
5102
  children: [/* @__PURE__ */ jsx("button", {
4259
5103
  type: "button",
4260
5104
  className: partClass("button button--ghost button--sm", props.classNames?.clearButton),
4261
5105
  disabled: isDisabled || isReadOnly,
4262
- onClick: () => replaceDraft(empty()),
5106
+ onClick: clearDraft,
4263
5107
  children: labels.clear
4264
- }), /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("button", {
4265
- type: "button",
4266
- className: partClass("button button--secondary button--sm", props.classNames?.cancelButton),
4267
- onClick: () => changeOpen(false),
4268
- children: labels.cancel
4269
- }), /* @__PURE__ */ jsx("button", {
4270
- type: "button",
4271
- className: partClass("button button--primary button--sm", props.classNames?.applyButton),
4272
- disabled: isDisabled || isReadOnly || !!errorCode,
4273
- onClick: apply,
4274
- children: labels.apply
4275
- })] })]
5108
+ }), /* @__PURE__ */ jsxs("div", { children: [
5109
+ /* @__PURE__ */ jsx("button", {
5110
+ type: "button",
5111
+ className: "button button--ghost button--sm",
5112
+ disabled: isDisabled || isReadOnly || !!rangeError({
5113
+ start: currentDate(),
5114
+ end: currentDate()
5115
+ }, props),
5116
+ onClick: () => {
5117
+ const next = {
5118
+ start: currentDate(),
5119
+ end: currentDate()
5120
+ };
5121
+ replaceDraft(next);
5122
+ updateDraft(next);
5123
+ },
5124
+ children: locale.startsWith("id") ? "Hari ini" : "Today"
5125
+ }),
5126
+ /* @__PURE__ */ jsx("button", {
5127
+ type: "button",
5128
+ className: partClass("button button--secondary button--sm", props.classNames?.cancelButton),
5129
+ onClick: () => changeOpen(false),
5130
+ children: labels.cancel
5131
+ }),
5132
+ props.commitMode !== "immediate" && /* @__PURE__ */ jsx("button", {
5133
+ type: "button",
5134
+ className: partClass("button button--primary button--sm", props.classNames?.applyButton),
5135
+ disabled: isDisabled || isReadOnly || !!errorCode,
5136
+ onClick: apply,
5137
+ children: labels.apply
5138
+ })
5139
+ ] })]
4276
5140
  })
4277
5141
  ]
4278
5142
  });
@@ -4299,7 +5163,7 @@ function DateRangePickerRoot(props) {
4299
5163
  panel,
4300
5164
  edit,
4301
5165
  apply,
4302
- clear: () => replaceDraft(empty()),
5166
+ clear: clearDraft,
4303
5167
  cancel: () => changeOpen(false)
4304
5168
  },
4305
5169
  children: /* @__PURE__ */ jsxs("div", {
@@ -4369,7 +5233,17 @@ function DateRangePickerRoot(props) {
4369
5233
  }),
4370
5234
  /* @__PURE__ */ jsx(ChevronIcon, { className: partClass("date-range__chevron", props.classNames?.chevron) })
4371
5235
  ]
4372
- }), /* @__PURE__ */ jsx(Popover$2, {
5236
+ }), isDialog ? /* @__PURE__ */ jsx(ModalOverlay, {
5237
+ className: "temporal-picker__overlay",
5238
+ children: /* @__PURE__ */ jsx(Modal, {
5239
+ className: "date-range__panel temporal-picker__modal",
5240
+ children: /* @__PURE__ */ jsx(Dialog$1, {
5241
+ "aria-labelledby": `${id}-title`,
5242
+ className: "date-range__dialog",
5243
+ children: panel
5244
+ })
5245
+ })
5246
+ }) : /* @__PURE__ */ jsx(Popover$2, {
4373
5247
  className: partClass("date-range__panel", props.classNames?.panel),
4374
5248
  placement: "bottom start",
4375
5249
  offset: 8,
@@ -5272,6 +6146,1030 @@ function ToastRenderer({ composed = false, style, classNames, entry, indicator,
5272
6146
  });
5273
6147
  }
5274
6148
  //#endregion
5275
- export { Alert, AlertActions, AlertContent, AlertDescription, AlertIndicator, AlertTitle, Badge, Breadcrumb, BreadcrumbCurrent, BreadcrumbItemPart, BreadcrumbLink, BreadcrumbList, BreadcrumbRoot, BreadcrumbSeparator, Button, ButtonGroup, ButtonGroupSeparator, Card, CardActions, CardContent, CardDescription, CardFooter, CardHeader, CardHeading, CardRoot, CardTitle, CardTitleRow, Chart, ChartDescription, ChartPlot, ChartRoot, ChartTitle, Checkbox, Combobox, DataTable, DataTableColumn as DataTableColumnPart, DataTableEmpty, DataTableError, DataTableRoot, DataTableSortButton, DataTableStatus, DateRangePicker, Description, Dialog, DialogBackdrop as DialogBackdropPart, DialogCloseButton, DialogContent, DialogPanel, DialogRoot, DialogTriggerPart, DropdownHeading, DropdownItem, DropdownItemIndicator, DropdownList, DropdownMenu, DropdownPopover, DropdownRoot, DropdownSection, DropdownSeparator, DropdownSubmenuIndicator, DropdownSubmenuTrigger, DropdownTrigger, Empty, EmptyActions, EmptyDescription, EmptyRoot, EmptyTitle, Field, FieldError, Form, Header, Input, Label, ListBox, Listbox, NumberField, OverlayBody, OverlayDescription, OverlayFooter, OverlayHeader, OverlayHeading, Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationNext, PaginationPageButton, PaginationPrevious, PaginationRoot, PaginationSummary, Popover, PopoverCloseButton, PopoverContent, PopoverDialog, PopoverTrigger, RadioGroup, Select, SelectGroup, Separator, Sidebar, SidebarHeader, SidebarItem, SidebarLink, SidebarList, SidebarNavigation, SidebarRoot, SidebarTitle, SidebarToggle, Skeleton, Spinner, Switch, Table, TableBody, TableCaption, TableCell, TableColumn, TableFooter, TableHeader, TableRoot, TableRow, TableScrollContainer, Tabs, TabsIndicator, TabsList, TabsListContainer, TabsPanel, TabsRoot, TabsSeparator, TabsTab, Textarea, Toast, ToastActionButton, ToastActions, ToastBody, ToastCloseButton, ToastDescription, ToastIndicator, ToastProgress, ToastProvider, ToastRoot, ToastTitle, ToggleButton, ToggleButtonGroup, ToggleGroup, Tooltip, TooltipContent, TooltipRoot, TooltipTriggerPart, createDateRangePresets, createToastManager, rangeText as formatDateRange, useToast };
6149
+ //#region src/temporal-model.ts
6150
+ /** Wall time is resolved explicitly; DST gaps/overlaps reject by default. */
6151
+ function toZonedValue(value, timeZone = "UTC", disambiguation = "reject") {
6152
+ return toZoned(parseDateTime(value), timeZone, disambiguation).toString();
6153
+ }
6154
+ function toLocalValue(value, timeZone = "UTC", seconds = false) {
6155
+ if (!value) return "";
6156
+ const zoned = value.includes("[") ? parseZonedDateTime(value) : parseAbsolute(value, timeZone);
6157
+ const display = parseAbsolute(zoned.toAbsoluteString(), timeZone);
6158
+ return toCalendarDateTime(display).toString().slice(0, seconds ? 19 : 16);
6159
+ }
6160
+ function orderedValue(value, kind) {
6161
+ if (kind === "datetime") return (value.includes("[") ? parseZonedDateTime(value) : parseAbsolute(value, "UTC")).toDate().getTime();
6162
+ if (kind === "time") {
6163
+ const t = parseTime(value);
6164
+ return t.hour * 3600 + t.minute * 60 + t.second;
6165
+ }
6166
+ return parseDate(value).toDate("UTC").getTime();
6167
+ }
6168
+ function step(value) {
6169
+ if (value !== void 0 && (!Number.isInteger(value) || value <= 0)) throw new RangeError("Time steps must be positive integers.");
6170
+ return value ?? 1;
6171
+ }
6172
+ function temporalError(value, options) {
6173
+ if (!value) return options.isRequired ? "required" : null;
6174
+ let date = "", time = "";
6175
+ try {
6176
+ if (options.kind === "date") {
6177
+ if (!/^(?!0000)\d{4}-\d{2}-\d{2}$/.test(value) || parseDate(value).toString() !== value) return "invalid";
6178
+ date = value;
6179
+ } else if (options.kind === "time") {
6180
+ if (!/^\d{2}:\d{2}(:\d{2})?$/.test(value)) return "invalid";
6181
+ parseTime(value);
6182
+ time = value;
6183
+ } else {
6184
+ orderedValue(value, "datetime");
6185
+ const local = toLocalValue(value, options.timeZone, true);
6186
+ date = local.slice(0, 10);
6187
+ time = local.slice(11);
6188
+ }
6189
+ if (date && (options.minDate && date < options.minDate || options.maxDate && date > options.maxDate)) return "bounds";
6190
+ if (time && (options.minTime && orderedValue(time, "time") < orderedValue(options.minTime, "time") || options.maxTime && orderedValue(time, "time") > orderedValue(options.maxTime, "time"))) return "bounds";
6191
+ if (options.kind === "datetime" && (options.minDateTime && orderedValue(value, "datetime") < orderedValue(options.minDateTime, "datetime") || options.maxDateTime && orderedValue(value, "datetime") > orderedValue(options.maxDateTime, "datetime"))) return "bounds";
6192
+ if (date && options.isDateUnavailable?.(date)) return "unavailable";
6193
+ if (time && options.isTimeUnavailable?.(time)) return "unavailable";
6194
+ if (time) {
6195
+ const t = parseTime(time);
6196
+ if (t.hour % step(options.hourStep) || t.minute % step(options.minuteStep) || t.second % step(options.secondStep)) return "step";
6197
+ }
6198
+ return null;
6199
+ } catch {
6200
+ return "invalid";
6201
+ }
6202
+ }
6203
+ function temporalRangeError(value, options) {
6204
+ if (!value || !value.start && !value.end) return options.isRequired ? "required" : null;
6205
+ if (!value.start || !value.end) return "incomplete";
6206
+ const error = temporalError(value.start, options) ?? temporalError(value.end, options);
6207
+ if (error) return error;
6208
+ if (orderedValue(value.start, options.kind) > orderedValue(value.end, options.kind)) return "order";
6209
+ if (options.kind !== "time" && options.isDateUnavailable) {
6210
+ const first = parseDate(options.kind === "date" ? value.start : toLocalValue(value.start, options.timeZone).slice(0, 10));
6211
+ const last = parseDate(options.kind === "date" ? value.end : toLocalValue(value.end, options.timeZone).slice(0, 10));
6212
+ for (let day = first.add({ days: 1 }); day.compare(last) < 0; day = day.add({ days: 1 })) if (options.isDateUnavailable(day.toString())) return "unavailable";
6213
+ }
6214
+ return null;
6215
+ }
6216
+ /** Project instant boundaries into the selected display zone for disabled calendar/time options. */
6217
+ function temporalDisplayBounds(options, selectedDate) {
6218
+ let minDate = options.minDate, maxDate = options.maxDate, minTime = options.minTime, maxTime = options.maxTime;
6219
+ if (options.kind === "datetime") try {
6220
+ const min = options.minDateTime ? toLocalValue(options.minDateTime, options.timeZone, true) : "", max = options.maxDateTime ? toLocalValue(options.maxDateTime, options.timeZone, true) : "";
6221
+ if (min) {
6222
+ const day = min.slice(0, 10);
6223
+ if (!minDate || day > minDate) minDate = day;
6224
+ if (selectedDate === day && (!minTime || orderedValue(min.slice(11), "time") > orderedValue(minTime, "time"))) minTime = min.slice(11);
6225
+ }
6226
+ if (max) {
6227
+ const day = max.slice(0, 10);
6228
+ if (!maxDate || day < maxDate) maxDate = day;
6229
+ if (selectedDate === day && (!maxTime || orderedValue(max.slice(11), "time") < orderedValue(maxTime, "time"))) maxTime = max.slice(11);
6230
+ }
6231
+ } catch {}
6232
+ return {
6233
+ minDate,
6234
+ maxDate,
6235
+ minTime,
6236
+ maxTime
6237
+ };
6238
+ }
6239
+ /** Minute-granularity list; seconds are edited with TimeField/TimeClock to avoid 86k DOM options. */
6240
+ function timeChoices(options) {
6241
+ const hours = step(options.hourStep), minutes = options.granularity === "hour" ? 60 : step(options.minuteStep ?? 30);
6242
+ const values = [];
6243
+ for (let hour = 0; hour < 24; hour += hours) for (let minute = 0; minute < 60; minute += minutes) {
6244
+ const value = `${String(hour).padStart(2, "0")}:${String(minute).padStart(2, "0")}`;
6245
+ if (!temporalError(value, options)) values.push(value);
6246
+ }
6247
+ return values;
6248
+ }
6249
+ /** User edits zero units hidden by the configured field granularity. */
6250
+ function normalizeTime(value, granularity = "minute") {
6251
+ const time = parseTime(value);
6252
+ return time.set({
6253
+ minute: granularity === "hour" ? 0 : time.minute,
6254
+ second: granularity === "second" ? time.second : 0,
6255
+ millisecond: 0
6256
+ }).toString().slice(0, granularity === "second" ? 8 : 5);
6257
+ }
6258
+ function normalizeWallDateTime(value, granularity = "minute") {
6259
+ const date = parseDateTime(value);
6260
+ return date.toString().slice(0, 10) + "T" + normalizeTime(date.toString().slice(11), granularity);
6261
+ }
6262
+ /** Keep the selected unit and choose the nearest complete valid time for the other units. */
6263
+ function resolveTimeUnit(value, part, selected, options) {
6264
+ let initial;
6265
+ try {
6266
+ initial = parseTime(value || options.minTime || "00:00");
6267
+ } catch {
6268
+ initial = parseTime("00:00");
6269
+ }
6270
+ const desired = initial.set({ [part]: selected });
6271
+ let best = null, distance = Infinity;
6272
+ const hours = step(options.hourStep), minutes = step(options.minuteStep), seconds = step(options.secondStep);
6273
+ for (let hour = 0; hour < 24; hour += hours) {
6274
+ if (part === "hour" && hour !== selected) continue;
6275
+ for (let minute = 0; minute < 60; minute += options.granularity === "hour" ? 60 : minutes) {
6276
+ if (part === "minute" && minute !== selected) continue;
6277
+ for (let second = 0; second < 60; second += options.granularity === "second" ? seconds : 60) {
6278
+ if (part === "second" && second !== selected) continue;
6279
+ const next = normalizeTime(`${String(hour).padStart(2, "0")}:${String(minute).padStart(2, "0")}:${String(second).padStart(2, "0")}`, options.granularity);
6280
+ if (temporalError(next, {
6281
+ ...options,
6282
+ kind: "time"
6283
+ })) continue;
6284
+ const delta = Math.abs(orderedValue(next, "time") - (desired.hour * 3600 + desired.minute * 60 + desired.second));
6285
+ if (delta < distance) {
6286
+ best = next;
6287
+ distance = delta;
6288
+ }
6289
+ }
6290
+ }
6291
+ }
6292
+ return best;
6293
+ }
6294
+ function temporalMessages(locale = "id-ID") {
6295
+ return locale.startsWith("id") ? {
6296
+ invalid: "Nilai tanggal atau waktu tidak valid.",
6297
+ required: "Nilai wajib diisi.",
6298
+ incomplete: "Lengkapi nilai mulai dan akhir.",
6299
+ order: "Nilai akhir harus setelah atau sama dengan nilai mulai.",
6300
+ bounds: "Nilai berada di luar batas yang diizinkan.",
6301
+ unavailable: "Nilai tidak tersedia.",
6302
+ step: "Nilai tidak sesuai interval yang diizinkan."
6303
+ } : {
6304
+ invalid: "Invalid date or time.",
6305
+ required: "A value is required.",
6306
+ incomplete: "Enter both start and end values.",
6307
+ order: "End must be on or after start.",
6308
+ bounds: "Value is outside the allowed limits.",
6309
+ unavailable: "Value is unavailable.",
6310
+ step: "Value does not match the allowed interval."
6311
+ };
6312
+ }
6313
+ //#endregion
6314
+ //#region src/TemporalField.tsx
6315
+ function parsed(value, kind, zone) {
6316
+ try {
6317
+ return value ? kind === "time" ? parseTime(value) : kind === "date" ? parseDate(value) : parseDateTime(toLocalValue(value, zone, true)) : null;
6318
+ } catch {
6319
+ return null;
6320
+ }
6321
+ }
6322
+ function TemporalField({ kind, ...props }) {
6323
+ const [local, setLocal] = useState(props.defaultValue ?? null), [editError, setEditError] = useState(null);
6324
+ const value = props.value === void 0 ? local : props.value;
6325
+ const id = useId();
6326
+ const error = editError ?? temporalError(value, {
6327
+ ...props,
6328
+ kind
6329
+ });
6330
+ useEffect(() => {
6331
+ setEditError(null);
6332
+ }, [value]);
6333
+ function change(v) {
6334
+ if (props.isDisabled || props.isReadOnly) return;
6335
+ let next;
6336
+ try {
6337
+ next = v ? kind === "datetime" ? toZonedValue(normalizeWallDateTime(v.toString(), props.granularity), props.timeZone, props.disambiguation) : kind === "time" ? normalizeTime(v.toString(), props.granularity) : v.toString().slice(0, 10) : null;
6338
+ } catch {
6339
+ const message = temporalMessages(props.locale).invalid;
6340
+ setEditError(message);
6341
+ props.onError?.(message);
6342
+ return;
6343
+ }
6344
+ setEditError(null);
6345
+ setLocal(next);
6346
+ props.onChange?.(next);
6347
+ props.onError?.(temporalError(next, {
6348
+ ...props,
6349
+ kind
6350
+ }));
6351
+ }
6352
+ const fieldContent = /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Label$3, {
6353
+ className: partClass(props.hideLabel ? "temporal__sr-only" : "input__label", props.classNames?.label),
6354
+ children: props.label
6355
+ }), /* @__PURE__ */ jsx(DateInput, {
6356
+ className: partClass("temporal-field__input input__control", props.classNames?.input),
6357
+ children: (segment) => /* @__PURE__ */ jsx(DateSegment, {
6358
+ segment,
6359
+ className: partClass("temporal-field__segment", props.classNames?.segment)
6360
+ })
6361
+ })] });
6362
+ const shared = {
6363
+ id: props.id ?? id,
6364
+ isDisabled: props.isDisabled,
6365
+ isReadOnly: props.isReadOnly,
6366
+ isRequired: props.isRequired,
6367
+ isInvalid: props.isInvalid || !!error,
6368
+ validationBehavior: "aria",
6369
+ "aria-describedby": [props.description ? `${id}-description` : void 0, props.isInvalid || error ? `${id}-error` : void 0].filter(Boolean).join(" ") || void 0
6370
+ };
6371
+ return /* @__PURE__ */ jsx(I18nProvider, {
6372
+ locale: props.locale ?? "id-ID",
6373
+ children: /* @__PURE__ */ jsxs("div", {
6374
+ className: partClass(partClass("input temporal-field", props.classNames?.root), props.className),
6375
+ style: props.style,
6376
+ dir: props.dir,
6377
+ children: [
6378
+ kind === "time" ? /* @__PURE__ */ jsx(TimeField$1, {
6379
+ ...shared,
6380
+ value: parsed(value, kind, props.timeZone),
6381
+ onChange: change,
6382
+ granularity: props.granularity ?? "minute",
6383
+ hourCycle: props.hourCycle,
6384
+ children: fieldContent
6385
+ }) : /* @__PURE__ */ jsx(DateField$1, {
6386
+ ...shared,
6387
+ value: parsed(value, kind, props.timeZone),
6388
+ onChange: change,
6389
+ granularity: kind === "date" ? "day" : props.granularity ?? "minute",
6390
+ hourCycle: props.hourCycle,
6391
+ children: fieldContent
6392
+ }),
6393
+ props.description && /* @__PURE__ */ jsx("span", {
6394
+ id: `${id}-description`,
6395
+ className: partClass("input__description", props.classNames?.description),
6396
+ children: props.description
6397
+ }),
6398
+ (props.isInvalid || error) && /* @__PURE__ */ jsx("span", {
6399
+ id: `${id}-error`,
6400
+ className: partClass("input__error", props.classNames?.error),
6401
+ role: "alert",
6402
+ children: props.errorMessage ?? (error && error in temporalMessages(props.locale) ? temporalMessages(props.locale)[error] : error ?? temporalMessages(props.locale).invalid)
6403
+ }),
6404
+ props.name && /* @__PURE__ */ jsx("input", {
6405
+ type: "hidden",
6406
+ name: props.name,
6407
+ value: value ?? "",
6408
+ disabled: props.isDisabled
6409
+ }),
6410
+ /* @__PURE__ */ jsx(SelectionValidation, {
6411
+ hasValue: !!value && !error,
6412
+ required: props.isRequired || !!error,
6413
+ disabled: props.isDisabled || props.formValidation === false,
6414
+ onInvalid: () => props.onError?.(error ?? "required"),
6415
+ onResetStart: () => {},
6416
+ onReset: (cancelled) => {
6417
+ if (!cancelled && props.value === void 0) {
6418
+ setLocal(props.defaultValue ?? null);
6419
+ setEditError(null);
6420
+ }
6421
+ }
6422
+ })
6423
+ ]
6424
+ })
6425
+ });
6426
+ }
6427
+ function DateField(props) {
6428
+ return /* @__PURE__ */ jsx(TemporalField, {
6429
+ ...props,
6430
+ kind: "date"
6431
+ });
6432
+ }
6433
+ function TimeField(props) {
6434
+ return /* @__PURE__ */ jsx(TemporalField, {
6435
+ ...props,
6436
+ kind: "time"
6437
+ });
6438
+ }
6439
+ function DateTimeField(props) {
6440
+ return /* @__PURE__ */ jsx(TemporalField, {
6441
+ ...props,
6442
+ kind: "datetime"
6443
+ });
6444
+ }
6445
+ function TemporalRangeField({ kind, ...props }) {
6446
+ const groupId = useId();
6447
+ const [local, setLocal] = useState(props.defaultValue ?? null);
6448
+ const value = props.value === void 0 ? local : props.value;
6449
+ const error = temporalRangeError(value, {
6450
+ ...props,
6451
+ kind
6452
+ });
6453
+ const fields = /* @__PURE__ */ jsx("div", {
6454
+ className: "temporal-picker__fields",
6455
+ children: ["start", "end"].map((part) => /* @__PURE__ */ createElement(TemporalField, {
6456
+ ...props,
6457
+ id: props.id ? `${props.id}-${part}` : void 0,
6458
+ className: void 0,
6459
+ style: void 0,
6460
+ classNames: {
6461
+ ...props.classNames,
6462
+ root: void 0
6463
+ },
6464
+ kind,
6465
+ key: part,
6466
+ value: value?.[part] ?? null,
6467
+ defaultValue: void 0,
6468
+ formValidation: false,
6469
+ name: props.name ? `${props.name}.${part}` : void 0,
6470
+ label: `${props.label} ${part === "start" ? props.locale?.startsWith("id") ? "Mulai" : "Start" : props.locale?.startsWith("id") ? "Akhir" : "End"}`,
6471
+ onChange: (next) => {
6472
+ const result = {
6473
+ ...value ?? {
6474
+ start: "",
6475
+ end: ""
6476
+ },
6477
+ [part]: next ?? ""
6478
+ };
6479
+ setLocal(result);
6480
+ props.onChange?.(result);
6481
+ }
6482
+ }))
6483
+ });
6484
+ return /* @__PURE__ */ jsxs("div", {
6485
+ id: props.id ?? groupId,
6486
+ role: "group",
6487
+ "aria-label": props.label,
6488
+ "aria-describedby": error ? `${groupId}-error` : void 0,
6489
+ className: partClass(partClass("temporal-range-field", props.classNames?.root), props.className),
6490
+ style: props.style,
6491
+ children: [
6492
+ fields,
6493
+ error && /* @__PURE__ */ jsx("span", {
6494
+ id: `${groupId}-error`,
6495
+ role: "alert",
6496
+ className: "input__error",
6497
+ children: props.errorMessage ?? temporalMessages(props.locale)[error]
6498
+ }),
6499
+ /* @__PURE__ */ jsx(SelectionValidation, {
6500
+ hasValue: !!value && !error,
6501
+ required: props.isRequired || !!error,
6502
+ disabled: props.isDisabled || props.formValidation === false,
6503
+ onInvalid: () => props.onError?.(error ?? "required"),
6504
+ onResetStart: () => {},
6505
+ onReset: (cancelled) => {
6506
+ if (!cancelled && props.value === void 0) setLocal(props.defaultValue ?? null);
6507
+ }
6508
+ })
6509
+ ]
6510
+ });
6511
+ }
6512
+ function DateRangeField(props) {
6513
+ return /* @__PURE__ */ jsx(TemporalRangeField, {
6514
+ ...props,
6515
+ kind: "date"
6516
+ });
6517
+ }
6518
+ function TimeRangeField(props) {
6519
+ return /* @__PURE__ */ jsx(TemporalRangeField, {
6520
+ ...props,
6521
+ kind: "time"
6522
+ });
6523
+ }
6524
+ function DateTimeRangeField(props) {
6525
+ return /* @__PURE__ */ jsx(TemporalRangeField, {
6526
+ ...props,
6527
+ kind: "datetime"
6528
+ });
6529
+ }
6530
+ //#endregion
6531
+ //#region src/TimeControls.tsx
6532
+ function format(value, locale, hourCycle) {
6533
+ const time = parseTime(value);
6534
+ const date = new Date(Date.UTC(2e3, 0, 1, time.hour, time.minute, time.second));
6535
+ return new Intl.DateTimeFormat(locale, {
6536
+ hour: "2-digit",
6537
+ minute: "2-digit",
6538
+ hourCycle: hourCycle === 12 ? "h12" : "h23",
6539
+ timeZone: "UTC"
6540
+ }).format(date);
6541
+ }
6542
+ function TimeList({ value, defaultValue, onChange, label = "Time", locale = "id-ID", hourCycle, isDisabled, isReadOnly, className, minTime, maxTime, hourStep, minuteStep, secondStep, granularity, isTimeUnavailable, ...props }) {
6543
+ const [local, setLocal] = useState(defaultValue ?? "");
6544
+ const actual = value === void 0 ? local : value ?? "";
6545
+ const options = {
6546
+ kind: "time",
6547
+ minTime,
6548
+ maxTime,
6549
+ hourStep,
6550
+ minuteStep,
6551
+ secondStep,
6552
+ granularity,
6553
+ isTimeUnavailable
6554
+ };
6555
+ return /* @__PURE__ */ jsx("div", {
6556
+ ...props,
6557
+ className: partClass("time-list", className),
6558
+ children: /* @__PURE__ */ jsxs("select", {
6559
+ "aria-label": label,
6560
+ size: 6,
6561
+ value: actual,
6562
+ disabled: isDisabled,
6563
+ "aria-readonly": isReadOnly || void 0,
6564
+ onChange: (event) => {
6565
+ if (isReadOnly) {
6566
+ event.currentTarget.value = actual;
6567
+ return;
6568
+ }
6569
+ setLocal(event.target.value);
6570
+ onChange?.(event.target.value);
6571
+ },
6572
+ children: [/* @__PURE__ */ jsx("option", {
6573
+ value: "",
6574
+ disabled: true,
6575
+ children: locale.startsWith("id") ? "Pilih waktu" : "Choose time"
6576
+ }), timeChoices(options).map((time) => /* @__PURE__ */ jsx("option", {
6577
+ value: time,
6578
+ children: format(time, locale, hourCycle)
6579
+ }, time))]
6580
+ })
6581
+ });
6582
+ }
6583
+ function TimeClock({ value, defaultValue, onChange, label = "Time", locale = "id-ID", hourCycle = 24, isDisabled, isReadOnly, className, minTime, maxTime, hourStep = 1, minuteStep = 1, secondStep = 1, granularity = "minute", isTimeUnavailable, ...props }) {
6584
+ const [local, setLocal] = useState(defaultValue ?? minTime ?? "00:00");
6585
+ const actual = value === void 0 ? local : value || minTime || "00:00";
6586
+ let time;
6587
+ try {
6588
+ time = parseTime(actual);
6589
+ } catch {
6590
+ time = parseTime("00:00");
6591
+ }
6592
+ const id = locale.startsWith("id");
6593
+ const parts = granularity === "hour" ? ["hour"] : granularity === "second" ? [
6594
+ "hour",
6595
+ "minute",
6596
+ "second"
6597
+ ] : ["hour", "minute"];
6598
+ return /* @__PURE__ */ jsx("div", {
6599
+ ...props,
6600
+ role: "group",
6601
+ "aria-label": label,
6602
+ className: partClass("time-clock", className),
6603
+ children: parts.map((part) => {
6604
+ const step = part === "hour" ? hourStep : part === "minute" ? minuteStep : secondStep;
6605
+ const count = part === "hour" ? 24 : 60;
6606
+ const values = Array.from({ length: Math.ceil(count / Math.max(1, step)) }, (_, i) => i * Math.max(1, step)).filter((n) => n < count);
6607
+ return /* @__PURE__ */ jsxs("label", { children: [/* @__PURE__ */ jsx("span", { children: part === "hour" ? id ? "Jam" : "Hours" : part === "minute" ? id ? "Menit" : "Minutes" : id ? "Detik" : "Seconds" }), /* @__PURE__ */ jsx("select", {
6608
+ value: time[part],
6609
+ disabled: isDisabled,
6610
+ "aria-readonly": isReadOnly || void 0,
6611
+ onChange: (event) => {
6612
+ if (isReadOnly) {
6613
+ event.currentTarget.value = String(time[part]);
6614
+ return;
6615
+ }
6616
+ const next = resolveTimeUnit(time.toString(), part, Number(event.target.value), {
6617
+ kind: "time",
6618
+ minTime,
6619
+ maxTime,
6620
+ hourStep,
6621
+ minuteStep,
6622
+ secondStep,
6623
+ granularity,
6624
+ isTimeUnavailable
6625
+ });
6626
+ if (!next) return;
6627
+ setLocal(next);
6628
+ onChange?.(next);
6629
+ },
6630
+ children: values.map((n) => /* @__PURE__ */ jsx("option", {
6631
+ value: n,
6632
+ children: part === "hour" && hourCycle === 12 ? `${n % 12 || 12} ${n < 12 ? "AM" : "PM"}` : String(n).padStart(2, "0")
6633
+ }, n))
6634
+ })] }, part);
6635
+ })
6636
+ });
6637
+ }
6638
+ //#endregion
6639
+ //#region src/TemporalPicker.tsx
6640
+ var PickerContext = createContext(null);
6641
+ function usePicker() {
6642
+ const context = useContext(PickerContext);
6643
+ if (!context) throw new Error("Picker parts must be inside their picker Root.");
6644
+ return context;
6645
+ }
6646
+ function labels(locale = "id-ID") {
6647
+ return locale.startsWith("id") ? {
6648
+ apply: "Terapkan",
6649
+ cancel: "Batal",
6650
+ clear: "Kosongkan",
6651
+ today: "Hari ini",
6652
+ now: "Sekarang",
6653
+ start: "Mulai",
6654
+ end: "Akhir",
6655
+ choose: "Pilih tanggal atau waktu"
6656
+ } : {
6657
+ apply: "Apply",
6658
+ cancel: "Cancel",
6659
+ clear: "Clear",
6660
+ today: "Today",
6661
+ now: "Now",
6662
+ start: "Start",
6663
+ end: "End",
6664
+ choose: "Choose date or time"
6665
+ };
6666
+ }
6667
+ function localValue(value, kind, options) {
6668
+ try {
6669
+ return kind === "datetime" ? toLocalValue(value, options.timeZone, options.granularity === "second") : value;
6670
+ } catch {
6671
+ return "";
6672
+ }
6673
+ }
6674
+ function datePart(value, kind, options) {
6675
+ return localValue(value, kind, options).slice(0, 10);
6676
+ }
6677
+ function combineDate(date, time, options) {
6678
+ try {
6679
+ return toZonedValue(`${date}T${time || "00:00"}`, options.timeZone, options.disambiguation);
6680
+ } catch {
6681
+ return "";
6682
+ }
6683
+ }
6684
+ function displayText(value, kind, options) {
6685
+ if (!value) return labels(options.locale).choose;
6686
+ if (options.formatValue) return options.formatValue(value, options.locale ?? "id-ID");
6687
+ const one = (v) => {
6688
+ if (!v) return "—";
6689
+ try {
6690
+ if (kind === "time") return new Intl.DateTimeFormat(options.locale ?? "id-ID", {
6691
+ hour: "2-digit",
6692
+ minute: "2-digit",
6693
+ second: options.granularity === "second" ? "2-digit" : void 0,
6694
+ hourCycle: options.hourCycle === 12 ? "h12" : "h23",
6695
+ timeZone: "UTC"
6696
+ }).format(/* @__PURE__ */ new Date(`2000-01-01T${v}Z`));
6697
+ if (kind === "date") return new Intl.DateTimeFormat(options.locale ?? "id-ID", {
6698
+ day: "numeric",
6699
+ month: "short",
6700
+ year: "numeric",
6701
+ timeZone: "UTC"
6702
+ }).format(/* @__PURE__ */ new Date(`${v}T12:00:00Z`));
6703
+ return `${localValue(v, kind, options).replace("T", " ")} ${options.timeZone ?? "UTC"}`;
6704
+ } catch {
6705
+ return v;
6706
+ }
6707
+ };
6708
+ return typeof value === "string" ? one(value) : `${one(value.start)} – ${one(value.end)}`;
6709
+ }
6710
+ function TemporalPickerField({ part = "start", ...props }) {
6711
+ const context = usePicker(), o = context.options, l = labels(o.locale);
6712
+ const Field = context.kind === "date" ? DateField : context.kind === "time" ? TimeField : DateTimeField;
6713
+ const value = typeof context.draft === "string" ? context.draft : context.draft?.[part] ?? null;
6714
+ return /* @__PURE__ */ jsx(Field, {
6715
+ ...o,
6716
+ ...props,
6717
+ className: partClass(o.classNames?.field ?? "", props.className),
6718
+ style: props.style,
6719
+ classNames: void 0,
6720
+ label: props.label ?? (context.range ? `${o.label} ${l[part]}` : o.label),
6721
+ value,
6722
+ name: void 0,
6723
+ formValidation: false,
6724
+ isRequired: false,
6725
+ onError: (error) => context.inputError(part, error),
6726
+ onChange: (next) => context.edit(context.range ? {
6727
+ ...typeof context.draft === "object" && context.draft ? context.draft : {
6728
+ start: "",
6729
+ end: ""
6730
+ },
6731
+ [part]: next ?? ""
6732
+ } : next, part)
6733
+ });
6734
+ }
6735
+ function TemporalPickerCalendar(props) {
6736
+ const c = usePicker(), o = c.options;
6737
+ const selected = typeof c.draft === "string" ? c.draft : "";
6738
+ const onSingle = (value) => {
6739
+ if (c.kind === "date") c.edit(value);
6740
+ else {
6741
+ const next = value ? combineDate(value, localValue(selected, c.kind, o).slice(11), o) : null;
6742
+ if (value && !next) {
6743
+ c.inputError("date", "invalid");
6744
+ return;
6745
+ }
6746
+ c.edit(next);
6747
+ }
6748
+ };
6749
+ const bounds = temporalDisplayBounds({
6750
+ ...o,
6751
+ kind: c.kind
6752
+ });
6753
+ const range = typeof c.draft === "object" && c.draft ? c.draft : {
6754
+ start: "",
6755
+ end: ""
6756
+ };
6757
+ return /* @__PURE__ */ jsx("div", {
6758
+ ...props,
6759
+ className: partClass("temporal-picker__calendar", props.className),
6760
+ children: c.kind !== "time" && (c.range ? /* @__PURE__ */ jsx(RangeCalendar, {
6761
+ ...o,
6762
+ minDate: bounds.minDate,
6763
+ maxDate: bounds.maxDate,
6764
+ style: void 0,
6765
+ className: void 0,
6766
+ classNames: void 0,
6767
+ value: {
6768
+ start: datePart(range.start, c.kind, o),
6769
+ end: datePart(range.end, c.kind, o)
6770
+ },
6771
+ onChange: (v) => {
6772
+ if (!v || c.kind === "date") {
6773
+ c.edit(v);
6774
+ return;
6775
+ }
6776
+ const start = v.start ? combineDate(v.start, localValue(range.start, c.kind, o).slice(11), o) : "", end = v.end ? combineDate(v.end, localValue(range.end, c.kind, o).slice(11), o) : "";
6777
+ if (v.start && !start || v.end && !end) {
6778
+ c.inputError("date", "invalid");
6779
+ return;
6780
+ }
6781
+ c.edit({
6782
+ start,
6783
+ end
6784
+ });
6785
+ }
6786
+ }) : /* @__PURE__ */ jsx(Calendar, {
6787
+ ...o,
6788
+ minDate: bounds.minDate,
6789
+ maxDate: bounds.maxDate,
6790
+ style: void 0,
6791
+ className: void 0,
6792
+ classNames: void 0,
6793
+ value: datePart(selected, c.kind, o),
6794
+ onChange: onSingle
6795
+ }))
6796
+ });
6797
+ }
6798
+ function TemporalPickerTime({ part = "start", ...props }) {
6799
+ const c = usePicker(), o = c.options, l = labels(o.locale);
6800
+ const wall = localValue(typeof c.draft === "string" ? c.draft : c.draft?.[part] ?? "", c.kind, o);
6801
+ const time = c.kind === "time" ? wall : wall.slice(11);
6802
+ const bounds = temporalDisplayBounds({
6803
+ ...o,
6804
+ kind: c.kind
6805
+ }, wall.slice(0, 10));
6806
+ const Control = o.timePresentation === "clock" ? TimeClock : TimeList;
6807
+ return /* @__PURE__ */ jsx("div", {
6808
+ ...props,
6809
+ className: partClass("temporal-picker__time", props.className),
6810
+ children: /* @__PURE__ */ jsx(Control, {
6811
+ locale: o.locale,
6812
+ hourCycle: o.hourCycle,
6813
+ minTime: bounds.minTime,
6814
+ maxTime: bounds.maxTime,
6815
+ hourStep: o.hourStep,
6816
+ minuteStep: o.minuteStep,
6817
+ secondStep: o.secondStep,
6818
+ granularity: o.granularity,
6819
+ isTimeUnavailable: o.isTimeUnavailable,
6820
+ isDisabled: o.isDisabled,
6821
+ isReadOnly: o.isReadOnly,
6822
+ label: c.range ? `${o.label} ${l[part]}` : o.label,
6823
+ value: time,
6824
+ onChange: (next) => {
6825
+ const result = c.kind === "time" ? next : combineDate(wall.slice(0, 10) || o.referenceDate || today(o.timeZone ?? "UTC").toString(), next, o);
6826
+ if (!result) {
6827
+ c.inputError(part, "invalid");
6828
+ return;
6829
+ }
6830
+ c.edit(c.range ? {
6831
+ ...typeof c.draft === "object" && c.draft ? c.draft : {
6832
+ start: "",
6833
+ end: ""
6834
+ },
6835
+ [part]: result
6836
+ } : result, part);
6837
+ }
6838
+ })
6839
+ });
6840
+ }
6841
+ function TemporalPickerValue({ children, className, ...props }) {
6842
+ const c = usePicker();
6843
+ return /* @__PURE__ */ jsx("span", {
6844
+ ...props,
6845
+ id: `${c.id}-value`,
6846
+ className: partClass("date-range__value", className),
6847
+ children: children ?? c.text
6848
+ });
6849
+ }
6850
+ function TemporalPickerTrigger({ children, className, ...props }) {
6851
+ const c = usePicker();
6852
+ return /* @__PURE__ */ jsx(Button$1, {
6853
+ ...props,
6854
+ isDisabled: c.options.isDisabled,
6855
+ className: partClass("date-range__trigger", className),
6856
+ "aria-labelledby": `${c.id}-label ${c.id}-value`,
6857
+ "aria-invalid": c.invalid || void 0,
6858
+ "aria-describedby": c.describedBy,
6859
+ children: children ?? /* @__PURE__ */ jsx(TemporalPickerValue, {})
6860
+ });
6861
+ }
6862
+ function TemporalPickerContent({ children, className, ...props }) {
6863
+ const c = usePicker();
6864
+ return /* @__PURE__ */ jsx("div", {
6865
+ ...props,
6866
+ className,
6867
+ children: children ?? c.panel
6868
+ });
6869
+ }
6870
+ function TemporalPickerPopover({ children, className, ...props }) {
6871
+ const c = usePicker();
6872
+ return /* @__PURE__ */ jsx(Popover$2, {
6873
+ className: partClass("date-range__panel temporal-picker__panel", className),
6874
+ placement: "bottom start",
6875
+ offset: 8,
6876
+ children: /* @__PURE__ */ jsx(Dialog$1, {
6877
+ "aria-labelledby": `${c.id}-label`,
6878
+ className: "date-range__dialog",
6879
+ children: /* @__PURE__ */ jsx("div", {
6880
+ ...props,
6881
+ children: children ?? c.panel
6882
+ })
6883
+ })
6884
+ });
6885
+ }
6886
+ function action(type) {
6887
+ return function PickerAction({ children, className, onClick, ...props }) {
6888
+ const c = usePicker();
6889
+ return /* @__PURE__ */ jsx("button", {
6890
+ type: "button",
6891
+ ...props,
6892
+ className: partClass(`button button--${type === "apply" ? "primary" : "ghost"} button--sm`, className),
6893
+ disabled: props.disabled || type !== "cancel" && (c.options.isDisabled || c.options.isReadOnly) || type === "apply" && !!c.error,
6894
+ onClick: (e) => {
6895
+ onClick?.(e);
6896
+ if (!e.defaultPrevented) c[type]();
6897
+ },
6898
+ children: children ?? labels(c.options.locale)[type]
6899
+ });
6900
+ };
6901
+ }
6902
+ var TemporalPickerApplyButton = /* @__PURE__ */ action("apply");
6903
+ var TemporalPickerCancelButton = /* @__PURE__ */ action("cancel");
6904
+ var TemporalPickerClearButton = /* @__PURE__ */ action("clear");
6905
+ function Root({ kind, range, ...props }) {
6906
+ const [local, setLocal] = useState(props.defaultValue ?? null);
6907
+ const committed = props.value === void 0 ? local : props.value;
6908
+ const [draft, setDraft] = useState(committed), [inputErrors, setInputErrors] = useState({}), [formError, setFormError] = useState(false), [mobile, setMobile] = useState(false);
6909
+ const id = useId(), trigger = useRef(null);
6910
+ const disclosure = useDisclosure(props.open, props.defaultOpen, props.onOpenChange);
6911
+ const l = labels(props.locale);
6912
+ const committedKey = JSON.stringify(committed), lastCommitted = useRef(committedKey);
6913
+ useEffect(() => {
6914
+ if (lastCommitted.current === committedKey) return;
6915
+ lastCommitted.current = committedKey;
6916
+ setDraft(committed);
6917
+ setInputErrors({});
6918
+ }, [committed, committedKey]);
6919
+ useEffect(() => {
6920
+ const media = window.matchMedia("(max-width: 640px)");
6921
+ const update = () => setMobile(media.matches);
6922
+ update();
6923
+ media.addEventListener("change", update);
6924
+ return () => media.removeEventListener("change", update);
6925
+ }, []);
6926
+ const constraints = {
6927
+ ...props,
6928
+ kind
6929
+ };
6930
+ const validate = (value) => range ? temporalRangeError(typeof value === "object" ? value : null, constraints) : temporalError(typeof value === "string" ? value : null, constraints);
6931
+ const code = Object.values(inputErrors).find(Boolean) ?? validate(draft);
6932
+ const error = code ? code in temporalMessages(props.locale) ? temporalMessages(props.locale)[code] : code : null;
6933
+ const committedError = validate(committed);
6934
+ const errorCallback = useRef(props.onError);
6935
+ useEffect(() => {
6936
+ errorCallback.current = props.onError;
6937
+ }, [props.onError]);
6938
+ useEffect(() => {
6939
+ errorCallback.current?.(error);
6940
+ }, [error]);
6941
+ function changeOpen(next) {
6942
+ if (props.isDisabled && next) return;
6943
+ setDraft(committed);
6944
+ setInputErrors({});
6945
+ disclosure.change(next);
6946
+ }
6947
+ function commit(value, close) {
6948
+ if (props.isDisabled || props.isReadOnly || validate(value)) return;
6949
+ setLocal(value);
6950
+ setFormError(false);
6951
+ props.onChange?.(value);
6952
+ if (close) {
6953
+ props.onApply?.(value);
6954
+ disclosure.change(false);
6955
+ }
6956
+ }
6957
+ function edit(value, part) {
6958
+ if (props.isDisabled || props.isReadOnly) return;
6959
+ setDraft(value);
6960
+ const remaining = part ? {
6961
+ ...inputErrors,
6962
+ [part]: null
6963
+ } : {};
6964
+ setInputErrors(remaining);
6965
+ if (props.commitMode === "immediate" && !Object.values(remaining).some(Boolean)) commit(value, false);
6966
+ }
6967
+ function clear() {
6968
+ if (props.isDisabled || props.isReadOnly) return;
6969
+ setDraft(null);
6970
+ setInputErrors({});
6971
+ if (props.commitMode === "immediate") {
6972
+ setLocal(null);
6973
+ props.onChange?.(null);
6974
+ }
6975
+ }
6976
+ const context = {
6977
+ options: props,
6978
+ kind,
6979
+ range,
6980
+ draft,
6981
+ error,
6982
+ id,
6983
+ invalid: props.isInvalid || !!committedError || formError,
6984
+ describedBy: [props.description ? `${id}-description` : void 0, props.isInvalid || committedError || formError ? `${id}-error` : void 0].filter(Boolean).join(" ") || void 0,
6985
+ text: displayText(committed, kind, props),
6986
+ edit,
6987
+ inputError: (part, error) => setInputErrors((current) => current[part] === error ? current : {
6988
+ ...current,
6989
+ [part]: error
6990
+ }),
6991
+ apply: () => {
6992
+ if (!error) commit(draft, true);
6993
+ },
6994
+ cancel: () => changeOpen(false),
6995
+ clear,
6996
+ panel: null
6997
+ };
6998
+ const current = kind === "date" ? today(props.timeZone ?? "UTC").toString() : kind === "time" ? now(props.timeZone ?? "UTC").toString().slice(11, props.granularity === "second" ? 19 : 16) : now(props.timeZone ?? "UTC").toString();
6999
+ const panel = /* @__PURE__ */ jsxs("div", {
7000
+ className: partClass("temporal-picker__content", props.classNames?.content),
7001
+ children: [
7002
+ /* @__PURE__ */ jsx("h2", {
7003
+ className: "temporal-picker__title",
7004
+ children: props.label
7005
+ }),
7006
+ !!props.presets?.length && /* @__PURE__ */ jsx("div", {
7007
+ className: "temporal-picker__presets",
7008
+ children: props.presets.map((p) => /* @__PURE__ */ jsx("button", {
7009
+ type: "button",
7010
+ className: partClass("date-range__preset", props.classNames?.preset),
7011
+ disabled: props.isDisabled || props.isReadOnly || !!validate(p.value),
7012
+ onClick: () => edit(p.value),
7013
+ children: p.label
7014
+ }, p.id))
7015
+ }),
7016
+ props.showInputs !== false && /* @__PURE__ */ jsxs("div", {
7017
+ className: "temporal-picker__fields",
7018
+ children: [/* @__PURE__ */ jsx(TemporalPickerField, {}), range && /* @__PURE__ */ jsx(TemporalPickerField, { part: "end" })]
7019
+ }),
7020
+ /* @__PURE__ */ jsxs("div", {
7021
+ className: "temporal-picker__views",
7022
+ children: [
7023
+ kind !== "time" && /* @__PURE__ */ jsx(TemporalPickerCalendar, { className: props.classNames?.calendar }),
7024
+ " ",
7025
+ kind !== "date" && /* @__PURE__ */ jsxs("div", {
7026
+ className: "temporal-picker__times",
7027
+ children: [/* @__PURE__ */ jsx(TemporalPickerTime, { className: props.classNames?.time }), range && /* @__PURE__ */ jsx(TemporalPickerTime, {
7028
+ part: "end",
7029
+ className: props.classNames?.time
7030
+ })]
7031
+ })
7032
+ ]
7033
+ }),
7034
+ error && /* @__PURE__ */ jsx("span", {
7035
+ className: "input__error",
7036
+ role: "alert",
7037
+ children: error
7038
+ }),
7039
+ /* @__PURE__ */ jsx("button", {
7040
+ type: "button",
7041
+ className: "button button--ghost button--sm",
7042
+ disabled: props.isDisabled || props.isReadOnly || !!temporalError(current, constraints),
7043
+ onClick: () => edit(range ? {
7044
+ start: current,
7045
+ end: current
7046
+ } : current),
7047
+ children: kind === "date" ? l.today : l.now
7048
+ }),
7049
+ props.showActions !== false && /* @__PURE__ */ jsxs("footer", {
7050
+ className: partClass("date-range__footer", props.classNames?.footer),
7051
+ children: [/* @__PURE__ */ jsx(TemporalPickerClearButton, { className: props.classNames?.clearButton }), /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx(TemporalPickerCancelButton, { className: props.classNames?.cancelButton }), props.commitMode !== "immediate" && /* @__PURE__ */ jsx(TemporalPickerApplyButton, { className: props.classNames?.applyButton })] })]
7052
+ })
7053
+ ]
7054
+ });
7055
+ context.panel = panel;
7056
+ const dialog = props.display === "dialog" || props.display !== "inline" && props.display !== "popover" && mobile;
7057
+ return /* @__PURE__ */ jsx(PickerContext.Provider, {
7058
+ value: context,
7059
+ children: /* @__PURE__ */ jsxs("div", {
7060
+ className: partClass(partClass(`date-range temporal-picker date-range--${props.size ?? "md"}`, props.classNames?.root), props.className),
7061
+ style: props.style,
7062
+ dir: props.dir,
7063
+ children: [
7064
+ /* @__PURE__ */ jsx("span", {
7065
+ id: `${id}-label`,
7066
+ className: partClass(props.hideLabel ? "temporal__sr-only" : "date-range__label", props.classNames?.label),
7067
+ children: props.label
7068
+ }),
7069
+ props.display === "inline" ? /* @__PURE__ */ jsx("section", {
7070
+ className: partClass("date-range__panel date-range__inline", props.classNames?.panel),
7071
+ "aria-labelledby": `${id}-label`,
7072
+ children: props.children ?? panel
7073
+ }) : /* @__PURE__ */ jsx(DialogTrigger, {
7074
+ isOpen: disclosure.visible && !props.isDisabled,
7075
+ onOpenChange: changeOpen,
7076
+ children: props.children ?? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Button$1, {
7077
+ ref: trigger,
7078
+ className: partClass("date-range__trigger", props.classNames?.trigger),
7079
+ isDisabled: props.isDisabled,
7080
+ "aria-labelledby": `${id}-label ${id}-value`,
7081
+ "aria-invalid": context.invalid || void 0,
7082
+ "aria-describedby": context.describedBy,
7083
+ children: /* @__PURE__ */ jsx(TemporalPickerValue, { className: props.classNames?.value })
7084
+ }), dialog ? /* @__PURE__ */ jsx(ModalOverlay, {
7085
+ className: "temporal-picker__overlay",
7086
+ children: /* @__PURE__ */ jsx(Modal, {
7087
+ className: "date-range__panel temporal-picker__modal",
7088
+ children: /* @__PURE__ */ jsx(Dialog$1, {
7089
+ "aria-labelledby": `${id}-label`,
7090
+ children: panel
7091
+ })
7092
+ })
7093
+ }) : /* @__PURE__ */ jsx(TemporalPickerPopover, { className: props.classNames?.panel })] })
7094
+ }),
7095
+ props.description && /* @__PURE__ */ jsx("span", {
7096
+ id: `${id}-description`,
7097
+ className: partClass("input__description", props.classNames?.description),
7098
+ children: props.description
7099
+ }),
7100
+ (props.isInvalid || committedError || formError) && /* @__PURE__ */ jsx("span", {
7101
+ id: `${id}-error`,
7102
+ role: "alert",
7103
+ className: partClass("input__error", props.classNames?.error),
7104
+ children: props.errorMessage ?? temporalMessages(props.locale)[committedError ?? (props.isInvalid ? "invalid" : "required")]
7105
+ }),
7106
+ props.name && (range ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("input", {
7107
+ type: "hidden",
7108
+ name: `${props.name}.start`,
7109
+ value: typeof committed === "object" && committed ? committed.start : "",
7110
+ disabled: props.isDisabled
7111
+ }), /* @__PURE__ */ jsx("input", {
7112
+ type: "hidden",
7113
+ name: `${props.name}.end`,
7114
+ value: typeof committed === "object" && committed ? committed.end : "",
7115
+ disabled: props.isDisabled
7116
+ })] }) : /* @__PURE__ */ jsx("input", {
7117
+ type: "hidden",
7118
+ name: props.name,
7119
+ value: typeof committed === "string" ? committed : "",
7120
+ disabled: props.isDisabled
7121
+ })),
7122
+ /* @__PURE__ */ jsx(SelectionValidation, {
7123
+ hasValue: !!committed && !committedError,
7124
+ required: props.isRequired || !!committedError,
7125
+ disabled: props.isDisabled,
7126
+ onInvalid: () => {
7127
+ setFormError(true);
7128
+ trigger.current?.focus();
7129
+ },
7130
+ onResetStart: () => {},
7131
+ onReset: (cancelled) => {
7132
+ if (!cancelled) {
7133
+ if (props.value === void 0) setLocal(props.defaultValue ?? null);
7134
+ setDraft(props.value === void 0 ? props.defaultValue ?? null : committed);
7135
+ setInputErrors({});
7136
+ setFormError(false);
7137
+ disclosure.change(false);
7138
+ }
7139
+ }
7140
+ })
7141
+ ]
7142
+ })
7143
+ });
7144
+ }
7145
+ function picker(kind, range) {
7146
+ const Component = (props) => /* @__PURE__ */ jsx(Root, {
7147
+ ...props,
7148
+ kind,
7149
+ range
7150
+ });
7151
+ return Object.assign(Component, {
7152
+ Root: Component,
7153
+ Trigger: TemporalPickerTrigger,
7154
+ Value: TemporalPickerValue,
7155
+ Popover: TemporalPickerPopover,
7156
+ Content: TemporalPickerContent,
7157
+ Field: TemporalPickerField,
7158
+ Calendar: TemporalPickerCalendar,
7159
+ Time: TemporalPickerTime,
7160
+ MonthPicker,
7161
+ YearPicker,
7162
+ ApplyButton: TemporalPickerApplyButton,
7163
+ CancelButton: TemporalPickerCancelButton,
7164
+ ClearButton: TemporalPickerClearButton
7165
+ });
7166
+ }
7167
+ var DatePicker = /* @__PURE__ */ picker("date", false);
7168
+ var TimePicker = /* @__PURE__ */ picker("time", false);
7169
+ var TimeRangePicker = /* @__PURE__ */ picker("time", true);
7170
+ var DateTimePicker = /* @__PURE__ */ picker("datetime", false);
7171
+ var DateTimeRangePicker = /* @__PURE__ */ picker("datetime", true);
7172
+ //#endregion
7173
+ export { Alert, AlertActions, AlertContent, AlertDescription, AlertIndicator, AlertTitle, Avatar, AvatarBadge, AvatarFallback, AvatarGroup, AvatarGroupCount, AvatarGroupRoot, AvatarImage, AvatarRoot, Badge, Breadcrumb, BreadcrumbCurrent, BreadcrumbItemPart, BreadcrumbLink, BreadcrumbList, BreadcrumbRoot, BreadcrumbSeparator, Button, ButtonGroup, ButtonGroupSeparator, Calendar, Card, CardActions, CardContent, CardDescription, CardFooter, CardHeader, CardHeading, CardRoot, CardTitle, CardTitleRow, Chart, ChartDescription, ChartPlot, ChartRoot, ChartTitle, Checkbox, Combobox, DataTable, DataTableColumn as DataTableColumnPart, DataTableEmpty, DataTableError, DataTableRoot, DataTableSortButton, DataTableStatus, DateField, DatePicker, DateRangeField, DateRangePicker, DateTimeField, DateTimePicker, DateTimeRangeField, DateTimeRangePicker, Description, Dialog, DialogBackdrop as DialogBackdropPart, DialogCloseButton, DialogContent, DialogPanel, DialogRoot, DialogTriggerPart, DropdownHeading, DropdownItem, DropdownItemIndicator, DropdownList, DropdownMenu, DropdownPopover, DropdownRoot, DropdownSection, DropdownSeparator, DropdownSubmenuIndicator, DropdownSubmenuTrigger, DropdownTrigger, Empty, EmptyActions, EmptyDescription, EmptyRoot, EmptyTitle, Field, FieldError, Form, Header, Input, InputClearButton, Label, ListBox, Listbox, MonthPicker, MonthYearNavigation, NumberField, OverlayBody, OverlayDescription, OverlayFooter, OverlayHeader, OverlayHeading, Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationNext, PaginationPageButton, PaginationPrevious, PaginationRoot, PaginationSummary, Popover, PopoverCloseButton, PopoverContent, PopoverDialog, PopoverTrigger, RadioGroup, RangeCalendar, Select, SelectGroup, Separator, Sidebar, SidebarHeader, SidebarItem, SidebarLink, SidebarList, SidebarNavigation, SidebarRoot, SidebarTitle, SidebarToggle, Skeleton, Spinner, Switch, SwitchGroup, Table, TableBody, TableCaption, TableCell, TableColumn, TableFooter, TableHeader, TableRoot, TableRow, TableScrollContainer, Tabs, TabsIndicator, TabsList, TabsListContainer, TabsPanel, TabsRoot, TabsSeparator, TabsTab, Textarea, TimeClock, TimeField, TimeList, TimePicker, TimeRangeField, TimeRangePicker, Toast, ToastActionButton, ToastActions, ToastBody, ToastCloseButton, ToastDescription, ToastIndicator, ToastProgress, ToastProvider, ToastRoot, ToastTitle, ToggleButton, ToggleButtonGroup, ToggleGroup, Tooltip, TooltipContent, TooltipRoot, TooltipTriggerPart, YearPicker, createDateRangePresets, createToastManager, rangeText as formatDateRange, useToast };
5276
7174
 
5277
7175
  //# sourceMappingURL=index.js.map