@kazee-ds/react 0.0.0-stage → 0.5.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.
Files changed (60) hide show
  1. package/dist/index.js +3436 -0
  2. package/dist/index.js.map +1 -0
  3. package/dist/types/Alert.d.ts +12 -0
  4. package/dist/types/Badge.d.ts +7 -0
  5. package/dist/types/Breadcrumb.d.ts +8 -0
  6. package/dist/types/Button.d.ts +53 -0
  7. package/dist/types/ButtonGroup.d.ts +18 -0
  8. package/dist/types/Card.d.ts +14 -0
  9. package/dist/types/Chart.d.ts +15 -0
  10. package/dist/types/Checkbox.d.ts +16 -0
  11. package/dist/types/Combobox.d.ts +27 -0
  12. package/dist/types/DataTable.d.ts +18 -0
  13. package/dist/types/DateRangePicker.d.ts +12 -0
  14. package/dist/types/Dialog.d.ts +29 -0
  15. package/dist/types/DropdownMenu.d.ts +25 -0
  16. package/dist/types/Empty.d.ts +10 -0
  17. package/dist/types/FieldComponent.d.ts +33 -0
  18. package/dist/types/Form.d.ts +17 -0
  19. package/dist/types/Input.d.ts +47 -0
  20. package/dist/types/Label.d.ts +8 -0
  21. package/dist/types/Listbox.d.ts +17 -0
  22. package/dist/types/NumberField.d.ts +24 -0
  23. package/dist/types/OverlayDirection.d.ts +5 -0
  24. package/dist/types/Pagination.d.ts +16 -0
  25. package/dist/types/Popover.d.ts +14 -0
  26. package/dist/types/RadioGroup.d.ts +20 -0
  27. package/dist/types/Select.d.ts +50 -0
  28. package/dist/types/SelectGroup.d.ts +13 -0
  29. package/dist/types/SelectionValidation.d.ts +8 -0
  30. package/dist/types/Separator.d.ts +6 -0
  31. package/dist/types/Sidebar.d.ts +13 -0
  32. package/dist/types/Skeleton.d.ts +7 -0
  33. package/dist/types/Spinner.d.ts +10 -0
  34. package/dist/types/Switch.d.ts +13 -0
  35. package/dist/types/Table.d.ts +5 -0
  36. package/dist/types/Tabs.d.ts +33 -0
  37. package/dist/types/Textarea.d.ts +24 -0
  38. package/dist/types/Toast.d.ts +26 -0
  39. package/dist/types/ToggleButton.d.ts +23 -0
  40. package/dist/types/ToggleButtonGroup.d.ts +30 -0
  41. package/dist/types/ToggleGroup.d.ts +33 -0
  42. package/dist/types/Tooltip.d.ts +16 -0
  43. package/dist/types/chart-model.d.ts +12 -0
  44. package/dist/types/dashboard-types.d.ts +27 -0
  45. package/dist/types/data-table-types.d.ts +13 -0
  46. package/dist/types/date-range-model.d.ts +69 -0
  47. package/dist/types/field.d.ts +9 -0
  48. package/dist/types/form-context.d.ts +3 -0
  49. package/dist/types/icons.d.ts +7 -0
  50. package/dist/types/index.d.ts +87 -0
  51. package/dist/types/listbox-selection.d.ts +8 -0
  52. package/dist/types/overlay-model.d.ts +14 -0
  53. package/dist/types/pagination-model.d.ts +5 -0
  54. package/dist/types/selection-options.d.ts +8 -0
  55. package/dist/types/tabs-indicator.d.ts +1 -0
  56. package/dist/types/toast-model.d.ts +64 -0
  57. package/dist/types/toggle-group-model.d.ts +9 -0
  58. package/dist/types/useDisclosure.d.ts +4 -0
  59. package/package.json +56 -3
  60. package/README.md +0 -3
package/dist/index.js ADDED
@@ -0,0 +1,3436 @@
1
+ "use client";
2
+ import { Button as Button$1, ButtonContext } from "react-aria-components/Button";
3
+ import { Children, Fragment, cloneElement, createContext, forwardRef, isValidElement, useContext, useEffect, useId, useImperativeHandle, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
4
+ import { ProgressBarContext } from "react-aria-components/ProgressBar";
5
+ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
6
+ import { ToggleButton as ToggleButton$1 } from "react-aria-components/ToggleButton";
7
+ import { ToggleButtonGroup as ToggleButtonGroup$1 } from "react-aria-components/ToggleButtonGroup";
8
+ import { I18nProvider, useLocale } from "react-aria-components/I18nProvider";
9
+ import { Button as Button$2, Label as Label$1, ListBox, ListBoxItem, Popover as Popover$1, Select as Select$1, SelectValue } from "react-aria-components/Select";
10
+ import { FieldError, Input as Input$1, Label as Label$2, Text, TextArea, TextField } from "react-aria-components/TextField";
11
+ import { Label as Label$3 } from "react-aria-components/Label";
12
+ import { Checkbox as Checkbox$1 } from "react-aria-components/Checkbox";
13
+ import { Label as Label$4, Radio, RadioGroup as RadioGroup$1 } from "react-aria-components/RadioGroup";
14
+ import { FieldError as FieldError$1, SwitchButton, SwitchField, Text as Text$1 } from "react-aria-components/Switch";
15
+ import { ListBox as ListBox$1, ListBoxItem as ListBoxItem$1 } from "react-aria-components/ListBox";
16
+ import { Button as Button$3, FieldError as FieldError$2, Group, Input as Input$2, Label as Label$5, NumberField as NumberField$1, Text as Text$2 } from "react-aria-components/NumberField";
17
+ import { Tab, TabList, TabPanel, Tabs as Tabs$1 } from "react-aria-components/Tabs";
18
+ import { Dialog as Dialog$1, DialogTrigger, Heading } from "react-aria-components/Dialog";
19
+ import { Modal, ModalOverlay } from "react-aria-components/Modal";
20
+ import { Menu, MenuItem, MenuSection, MenuTrigger, SubmenuTrigger } from "react-aria-components/Menu";
21
+ import { Header } from "react-aria-components/Header";
22
+ import { Separator as Separator$1 } from "react-aria-components/Separator";
23
+ import { Popover as Popover$2 } from "react-aria-components/Popover";
24
+ import { Tooltip as Tooltip$1, TooltipTrigger } from "react-aria-components/Tooltip";
25
+ import { Button as Button$4, ComboBox, Input as Input$3, Label as Label$6, ListBox as ListBox$2, ListBoxItem as ListBoxItem$2, Popover as Popover$3 } from "react-aria-components/ComboBox";
26
+ import { CalendarCell, CalendarGrid, CalendarGridBody, CalendarGridHeader, CalendarHeaderCell, CalendarHeading, RangeCalendar, RangeCalendarStateContext } from "react-aria-components/RangeCalendar";
27
+ import { GregorianCalendar, endOfMonth, getLocalTimeZone, parseDate, startOfMonth, startOfWeek, today } from "@internationalized/date";
28
+ import { Button as Button$5, I18nProvider as I18nProvider$1, Text as Text$3, UNSTABLE_Toast, UNSTABLE_ToastContent, UNSTABLE_ToastList, UNSTABLE_ToastQueue, UNSTABLE_ToastRegion } from "react-aria-components";
29
+ //#region src/Button.tsx
30
+ function PendingLabelAnchor() {
31
+ const context = useContext(ProgressBarContext);
32
+ const id = context && "id" in context ? context.id : void 0;
33
+ return id ? /* @__PURE__ */ jsx("span", {
34
+ id,
35
+ hidden: true,
36
+ "aria-hidden": "true"
37
+ }) : null;
38
+ }
39
+ function Button({ variant = "primary", size = "md", isIconOnly = false, isPending = false, isDisabled = false, fullWidth = false, type = "button", children, ...props }) {
40
+ const className = [
41
+ "button",
42
+ `button--${variant}`,
43
+ size !== "md" && `button--${size}`,
44
+ isIconOnly && "button--icon-only",
45
+ fullWidth && !isIconOnly && "button--full-width"
46
+ ].filter(Boolean).join(" ");
47
+ return /* @__PURE__ */ jsx(Button$1, {
48
+ ...props,
49
+ type: isPending ? "button" : type,
50
+ className,
51
+ isDisabled,
52
+ isPending,
53
+ children: (state) => /* @__PURE__ */ jsxs(Fragment$1, { children: [typeof children === "function" ? children({
54
+ isPending: state.isPending,
55
+ isDisabled: state.isDisabled,
56
+ isHovered: state.isHovered,
57
+ isPressed: state.isPressed,
58
+ isFocused: state.isFocused,
59
+ isFocusVisible: state.isFocusVisible
60
+ }) : children, isPending && /* @__PURE__ */ jsx(PendingLabelAnchor, {})] })
61
+ });
62
+ }
63
+ //#endregion
64
+ //#region src/ButtonGroup.tsx
65
+ function ButtonGroupSeparator() {
66
+ return /* @__PURE__ */ jsx("span", {
67
+ className: "button-group__separator",
68
+ "aria-hidden": "true"
69
+ });
70
+ }
71
+ function Root$1({ children, label, variant, size, isDisabled, fullWidth, orientation = "horizontal", dir }) {
72
+ function defaults(nodes) {
73
+ return Children.map(nodes, (child) => {
74
+ if (!isValidElement(child)) return child;
75
+ if (child.type === Fragment) return cloneElement(child, {}, defaults(child.props.children));
76
+ if (child.type !== Button) return child;
77
+ const button = child;
78
+ return cloneElement(button, {
79
+ variant: button.props.variant ?? variant,
80
+ size: button.props.size ?? size,
81
+ isDisabled: button.props.isDisabled ?? isDisabled
82
+ });
83
+ });
84
+ }
85
+ return /* @__PURE__ */ jsx("div", {
86
+ role: "group",
87
+ "aria-label": label,
88
+ dir,
89
+ "data-orientation": orientation,
90
+ className: `button-group${fullWidth ? " button-group--full-width" : ""}`,
91
+ children: defaults(children)
92
+ });
93
+ }
94
+ var ButtonGroup = /* @__PURE__ */ Object.assign(Root$1, { Separator: ButtonGroupSeparator });
95
+ //#endregion
96
+ //#region src/ToggleButton.tsx
97
+ var ToggleButtonSizeContext = createContext("md");
98
+ function ToggleButton({ children, variant = "default", size, isIconOnly, ...props }) {
99
+ const inheritedSize = useContext(ToggleButtonSizeContext);
100
+ const resolvedSize = size ?? inheritedSize;
101
+ return /* @__PURE__ */ jsx(ToggleButton$1, {
102
+ ...props,
103
+ className: [
104
+ "button",
105
+ "toggle-button",
106
+ `toggle-button--${variant}`,
107
+ resolvedSize !== "md" && `button--${resolvedSize}`,
108
+ isIconOnly && "button--icon-only"
109
+ ].filter(Boolean).join(" "),
110
+ children: ({ isSelected, isPressed, isHovered, isFocused, isFocusVisible, isDisabled }) => typeof children === "function" ? children({
111
+ isSelected,
112
+ isPressed,
113
+ isHovered,
114
+ isFocused,
115
+ isFocusVisible,
116
+ isDisabled
117
+ }) : children
118
+ });
119
+ }
120
+ //#endregion
121
+ //#region src/OverlayDirection.tsx
122
+ function OverlayDirection({ dir, children }) {
123
+ return dir ? /* @__PURE__ */ jsx(I18nProvider, {
124
+ locale: dir === "rtl" ? "ar-EG" : "en-US",
125
+ children
126
+ }) : children;
127
+ }
128
+ //#endregion
129
+ //#region src/ToggleButtonGroup.tsx
130
+ var keys = (value) => Array.isArray(value) ? value : value ? [value] : [];
131
+ function Root(props) {
132
+ return /* @__PURE__ */ jsx(OverlayDirection, {
133
+ dir: props.dir,
134
+ children: /* @__PURE__ */ jsx(ToggleButtonSizeContext.Provider, {
135
+ value: props.size ?? "md",
136
+ children: /* @__PURE__ */ jsx(ToggleButtonGroup$1, {
137
+ "aria-label": props.label,
138
+ dir: props.dir,
139
+ className: [
140
+ "button-group",
141
+ "toggle-button-group",
142
+ props.isDetached && "button-group--detached",
143
+ props.fullWidth && "button-group--full-width"
144
+ ].filter(Boolean).join(" "),
145
+ orientation: props.orientation ?? "horizontal",
146
+ selectionMode: props.selectionMode ?? "single",
147
+ selectedKeys: props.value === void 0 ? void 0 : keys(props.value),
148
+ defaultSelectedKeys: keys(props.defaultValue),
149
+ onSelectionChange: (selected) => {
150
+ if (props.isDisabled) return;
151
+ const next = Array.from(selected, String);
152
+ if (props.selectionMode === "multiple") props.onChange?.(next);
153
+ else props.onChange?.(next[0] ?? null);
154
+ },
155
+ isDisabled: props.isDisabled,
156
+ disallowEmptySelection: props.disallowEmptySelection,
157
+ children: props.children
158
+ })
159
+ })
160
+ });
161
+ }
162
+ var ToggleButtonGroup = /* @__PURE__ */ Object.assign(Root, { Separator: ButtonGroupSeparator });
163
+ //#endregion
164
+ //#region src/icons.tsx
165
+ function ChevronIcon({ className }) {
166
+ return /* @__PURE__ */ jsx("svg", {
167
+ className,
168
+ viewBox: "0 0 16 16",
169
+ fill: "none",
170
+ stroke: "currentColor",
171
+ strokeWidth: "1.5",
172
+ strokeLinecap: "round",
173
+ strokeLinejoin: "round",
174
+ "aria-hidden": "true",
175
+ children: /* @__PURE__ */ jsx("path", { d: "M4 6l4 4 4-4" })
176
+ });
177
+ }
178
+ function CheckIcon({ className }) {
179
+ return /* @__PURE__ */ jsx("svg", {
180
+ className,
181
+ viewBox: "0 0 16 16",
182
+ fill: "none",
183
+ stroke: "currentColor",
184
+ strokeWidth: "1.5",
185
+ strokeLinecap: "round",
186
+ strokeLinejoin: "round",
187
+ "aria-hidden": "true",
188
+ children: /* @__PURE__ */ jsx("path", { d: "M3.5 8.5l3 3 6-6.5" })
189
+ });
190
+ }
191
+ function CloseIcon({ className }) {
192
+ return /* @__PURE__ */ jsx("svg", {
193
+ className,
194
+ viewBox: "0 0 16 16",
195
+ fill: "none",
196
+ stroke: "currentColor",
197
+ strokeWidth: "1.5",
198
+ strokeLinecap: "round",
199
+ strokeLinejoin: "round",
200
+ "aria-hidden": "true",
201
+ children: /* @__PURE__ */ jsx("path", { d: "M4 4l8 8M12 4l-8 8" })
202
+ });
203
+ }
204
+ //#endregion
205
+ //#region src/field.tsx
206
+ function useFeedback({ description, errorMessage, isInvalid }) {
207
+ const id = useId();
208
+ const descriptionId = `${id}-description`;
209
+ const errorId = `${id}-error`;
210
+ const showError = !!(isInvalid && errorMessage);
211
+ return {
212
+ describedBy: [description && descriptionId, showError && errorId].filter(Boolean).join(" ") || void 0,
213
+ feedback: /* @__PURE__ */ jsxs(Fragment$1, { children: [description && /* @__PURE__ */ jsx("span", {
214
+ id: descriptionId,
215
+ className: "input__description",
216
+ children: description
217
+ }), showError && /* @__PURE__ */ jsx("span", {
218
+ id: errorId,
219
+ className: "input__error",
220
+ children: errorMessage
221
+ })] })
222
+ };
223
+ }
224
+ //#endregion
225
+ //#region src/SelectionValidation.tsx
226
+ function SelectionValidation({ hasValue, required, disabled, onInvalid, onReset, onResetStart }) {
227
+ const ref = useRef(null);
228
+ useEffect(() => {
229
+ const form = ref.current?.form;
230
+ const reset = (event) => {
231
+ onResetStart();
232
+ setTimeout(() => onReset(event.defaultPrevented), 0);
233
+ };
234
+ form?.addEventListener("reset", reset, true);
235
+ return () => form?.removeEventListener("reset", reset, true);
236
+ }, [onReset, onResetStart]);
237
+ return /* @__PURE__ */ jsx("input", {
238
+ ref,
239
+ className: "selection__validation",
240
+ type: "text",
241
+ tabIndex: -1,
242
+ "aria-hidden": "true",
243
+ autoComplete: "off",
244
+ required,
245
+ disabled,
246
+ value: hasValue ? "selected" : "",
247
+ onChange: () => {},
248
+ onInvalid: (event) => {
249
+ event.preventDefault();
250
+ onInvalid();
251
+ }
252
+ });
253
+ }
254
+ //#endregion
255
+ //#region src/selection-options.ts
256
+ function selectionIds(value, options, multiple) {
257
+ const requested = new Set(Array.isArray(value) ? value : typeof value === "string" ? [value] : []);
258
+ const ids = [...new Set(options.filter((o) => o.id !== "" && requested.has(o.id)).map((o) => o.id))];
259
+ return multiple ? ids : ids.slice(0, 1);
260
+ }
261
+ function filterOptions(options, query) {
262
+ const fold = (text) => text.normalize("NFD").replace(/\p{M}/gu, "").toLowerCase();
263
+ const search = fold(query.trim());
264
+ return options.filter((o) => fold(`${o.label} ${o.description ?? ""}`).includes(search));
265
+ }
266
+ //#endregion
267
+ //#region src/Select.tsx
268
+ function Select(props) {
269
+ const { label, options, placeholder, isDisabled, isRequired, isClearable, clearLabel = "Hapus pilihan", dir } = props;
270
+ const multiple = props.selectionMode === "multiple";
271
+ const [local, setLocal] = useState(props.defaultValue);
272
+ const [tried, setTried] = useState(false);
273
+ const resetting = useRef(false);
274
+ const trigger = useRef(null);
275
+ const ids = selectionIds(props.value !== void 0 ? props.value : local, options, multiple);
276
+ const selected = options.filter((o) => ids.includes(o.id));
277
+ const invalid = props.isInvalid || tried && isRequired && ids.length === 0;
278
+ const { describedBy, feedback } = useFeedback({
279
+ description: props.description,
280
+ isInvalid: invalid,
281
+ errorMessage: props.errorMessage ?? (isRequired && ids.length === 0 ? props.requiredMessage ?? "Pilihan wajib diisi." : void 0)
282
+ });
283
+ function update(value) {
284
+ if (isDisabled || resetting.current) return;
285
+ const next = selectionIds(value, options, multiple);
286
+ setLocal(multiple ? next : next[0] ?? null);
287
+ if (props.selectionMode === "multiple") props.onChange?.(next);
288
+ else if (next[0] !== void 0) props.onChange?.(next[0]);
289
+ }
290
+ function clear() {
291
+ if (isDisabled || resetting.current) return;
292
+ setLocal(multiple ? [] : null);
293
+ if (props.selectionMode === "multiple") props.onChange?.([]);
294
+ props.onClear?.();
295
+ trigger.current?.focus();
296
+ }
297
+ const select = /* @__PURE__ */ jsxs(Select$1, {
298
+ className: [
299
+ "select",
300
+ `select--${props.size ?? "md"}`,
301
+ `select--${props.variant ?? "primary"}`,
302
+ props.hideLabel && "select--label-hidden",
303
+ props.fullWidth === false && "select--fit"
304
+ ].filter(Boolean).join(" "),
305
+ "data-multiple": multiple || void 0,
306
+ selectionMode: multiple ? "multiple" : "single",
307
+ value: multiple ? ids : ids[0] ?? null,
308
+ onChange: update,
309
+ placeholder,
310
+ isDisabled,
311
+ isRequired,
312
+ isInvalid: !!invalid,
313
+ validationBehavior: "aria",
314
+ "aria-describedby": describedBy,
315
+ children: [
316
+ /* @__PURE__ */ jsxs(Label$1, {
317
+ className: "select__label",
318
+ children: [label, isRequired && /* @__PURE__ */ jsxs("span", {
319
+ className: "selection__required",
320
+ "aria-hidden": "true",
321
+ children: [" ", "*"]
322
+ })]
323
+ }),
324
+ /* @__PURE__ */ jsxs("div", {
325
+ className: "select__control",
326
+ "data-clearable": isClearable || void 0,
327
+ children: [/* @__PURE__ */ jsxs(Button$2, {
328
+ ref: trigger,
329
+ className: "select__trigger",
330
+ "aria-describedby": describedBy,
331
+ children: [
332
+ props.startContent && /* @__PURE__ */ jsx("span", {
333
+ className: "selection__leading",
334
+ "aria-hidden": "true",
335
+ children: props.startContent
336
+ }),
337
+ /* @__PURE__ */ jsx(SelectValue, {
338
+ className: "select__value",
339
+ children: () => selected.length ? props.renderValue?.(selected) ?? selected.map((o) => o.label).join(", ") : placeholder
340
+ }),
341
+ /* @__PURE__ */ jsx(ChevronIcon, { className: "select__icon" })
342
+ ]
343
+ }), isClearable && /* @__PURE__ */ jsx("button", {
344
+ type: "button",
345
+ className: "selection__clear",
346
+ "data-empty": ids.length === 0 || void 0,
347
+ "aria-hidden": ids.length === 0 || void 0,
348
+ tabIndex: ids.length === 0 ? -1 : void 0,
349
+ "aria-label": clearLabel,
350
+ disabled: isDisabled || ids.length === 0,
351
+ onClick: clear,
352
+ children: /* @__PURE__ */ jsx(CloseIcon, { className: "selection__close-icon" })
353
+ })]
354
+ }),
355
+ /* @__PURE__ */ jsx(Popover$1, {
356
+ className: "select__popover",
357
+ children: /* @__PURE__ */ jsx(ListBox, {
358
+ className: "select__list",
359
+ children: options.map((option) => /* @__PURE__ */ jsxs(ListBoxItem, {
360
+ onPress: props.onAction ? () => props.onAction(option.id) : void 0,
361
+ id: option.id,
362
+ textValue: option.label,
363
+ isDisabled: option.isDisabled,
364
+ className: "select__item",
365
+ children: [/* @__PURE__ */ jsx("span", {
366
+ className: "select__item-label",
367
+ children: props.renderOption?.(option) ?? /* @__PURE__ */ jsxs(Fragment$1, { children: [option.label, option.description && /* @__PURE__ */ jsx("span", {
368
+ className: "selection__description",
369
+ children: option.description
370
+ })] })
371
+ }), /* @__PURE__ */ jsx(CheckIcon, { className: "select__check" })]
372
+ }, option.id))
373
+ })
374
+ }),
375
+ feedback,
376
+ props.name && (multiple ? ids : [ids[0] ?? ""]).map((id, i) => /* @__PURE__ */ jsx("input", {
377
+ type: "hidden",
378
+ name: props.name,
379
+ value: id,
380
+ disabled: isDisabled
381
+ }, i)),
382
+ /* @__PURE__ */ jsx(SelectionValidation, {
383
+ hasValue: ids.length > 0,
384
+ required: isRequired,
385
+ disabled: isDisabled,
386
+ onInvalid: () => {
387
+ setTried(true);
388
+ trigger.current?.focus();
389
+ },
390
+ onResetStart: () => {
391
+ resetting.current = true;
392
+ },
393
+ onReset: (cancelled) => {
394
+ resetting.current = false;
395
+ if (!cancelled) {
396
+ setTried(false);
397
+ if (props.value === void 0) setLocal(props.defaultValue);
398
+ }
399
+ }
400
+ })
401
+ ]
402
+ });
403
+ return dir ? /* @__PURE__ */ jsx(I18nProvider, {
404
+ locale: dir === "rtl" ? "ar-EG" : "en-US",
405
+ children: select
406
+ }) : select;
407
+ }
408
+ //#endregion
409
+ //#region src/SelectGroup.tsx
410
+ /** Joins direct Select children. Each child retains its own value and accessible label. */
411
+ function SelectGroup({ label, children, size, variant, fullWidth = true, isDisabled, dir }) {
412
+ function defaults(nodes) {
413
+ return Children.map(nodes, (child) => {
414
+ if (!isValidElement(child)) return child;
415
+ if (child.type === Fragment) return cloneElement(child, {}, defaults(child.props.children));
416
+ if (child.type !== Select) return child;
417
+ const select = child;
418
+ return cloneElement(select, {
419
+ size: select.props.size ?? size,
420
+ variant: select.props.variant ?? variant,
421
+ hideLabel: select.props.hideLabel ?? true,
422
+ fullWidth: select.props.fullWidth ?? fullWidth,
423
+ isDisabled: !!isDisabled || select.props.isDisabled,
424
+ dir: select.props.dir ?? dir
425
+ });
426
+ });
427
+ }
428
+ return /* @__PURE__ */ jsxs("fieldset", {
429
+ className: ["select-group", !fullWidth && "select-group--fit"].filter(Boolean).join(" "),
430
+ disabled: isDisabled,
431
+ dir,
432
+ children: [/* @__PURE__ */ jsx("legend", {
433
+ className: "select-group__legend",
434
+ children: label
435
+ }), /* @__PURE__ */ jsx("div", {
436
+ className: "select-group__controls",
437
+ children: defaults(children)
438
+ })]
439
+ });
440
+ }
441
+ //#endregion
442
+ //#region src/Input.tsx
443
+ var Input = /* @__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 }, ref) {
444
+ const control = useRef(null);
445
+ useImperativeHandle(ref, () => control.current);
446
+ const hasAdornment = prefix != null || suffix != null;
447
+ const input = /* @__PURE__ */ jsx(Input$1, {
448
+ ref: control,
449
+ className: "input__control",
450
+ placeholder,
451
+ required: isRequired,
452
+ minLength,
453
+ pattern,
454
+ inputMode,
455
+ enterKeyHint,
456
+ autoFocus,
457
+ spellCheck,
458
+ form,
459
+ onFocus,
460
+ onBlur,
461
+ onKeyDown,
462
+ onKeyUp
463
+ });
464
+ return /* @__PURE__ */ jsxs(TextField, {
465
+ className: `input input--${size} input--${variant}${fullWidth ? "" : " input--fit"}`,
466
+ value,
467
+ defaultValue,
468
+ onChange,
469
+ isInvalid,
470
+ isDisabled,
471
+ isReadOnly,
472
+ isRequired,
473
+ validationBehavior: "aria",
474
+ type,
475
+ name,
476
+ id,
477
+ autoComplete,
478
+ maxLength,
479
+ dir,
480
+ children: [
481
+ /* @__PURE__ */ jsx(Label$2, {
482
+ className: "input__label",
483
+ children: label
484
+ }),
485
+ /* @__PURE__ */ jsx("fieldset", {
486
+ className: "input__boundary",
487
+ role: "presentation",
488
+ disabled: isDisabled,
489
+ children: /* @__PURE__ */ jsxs("div", {
490
+ className: hasAdornment ? "input__group" : "input__plain",
491
+ "data-invalid": isInvalid || void 0,
492
+ "data-readonly": isReadOnly || void 0,
493
+ onPointerDown: (event) => {
494
+ if (!isDisabled && !event.target.closest("input,button,a,select,textarea,[tabindex],[contenteditable]")) {
495
+ event.preventDefault();
496
+ control.current?.focus();
497
+ }
498
+ },
499
+ children: [
500
+ prefix != null && /* @__PURE__ */ jsx("span", {
501
+ className: "input__prefix",
502
+ children: prefix
503
+ }),
504
+ input,
505
+ suffix != null && /* @__PURE__ */ jsx("span", {
506
+ className: "input__suffix",
507
+ children: suffix
508
+ })
509
+ ]
510
+ })
511
+ }),
512
+ description && /* @__PURE__ */ jsx(Text, {
513
+ slot: "description",
514
+ className: "input__description",
515
+ children: description
516
+ }),
517
+ isInvalid && errorMessage && /* @__PURE__ */ jsx(FieldError, {
518
+ className: "input__error",
519
+ children: errorMessage
520
+ })
521
+ ]
522
+ });
523
+ });
524
+ //#endregion
525
+ //#region src/Textarea.tsx
526
+ function Textarea({ label, value, defaultValue, onChange, description, errorMessage, isInvalid = false, isDisabled = false, isReadOnly = false, isRequired = false, placeholder, rows = 3, resize = "vertical", name, id, autoComplete, maxLength, dir }) {
527
+ return /* @__PURE__ */ jsxs(TextField, {
528
+ className: "input textarea",
529
+ "data-resize": resize,
530
+ value,
531
+ defaultValue,
532
+ onChange,
533
+ isInvalid,
534
+ isDisabled,
535
+ isReadOnly,
536
+ isRequired,
537
+ validationBehavior: "aria",
538
+ name,
539
+ id,
540
+ autoComplete,
541
+ maxLength,
542
+ dir,
543
+ children: [
544
+ /* @__PURE__ */ jsx(Label$2, {
545
+ className: "input__label",
546
+ children: label
547
+ }),
548
+ /* @__PURE__ */ jsx(TextArea, {
549
+ className: "input__control textarea__control",
550
+ rows,
551
+ placeholder,
552
+ required: isRequired
553
+ }),
554
+ description && /* @__PURE__ */ jsx(Text, {
555
+ slot: "description",
556
+ className: "input__description",
557
+ children: description
558
+ }),
559
+ isInvalid && errorMessage && /* @__PURE__ */ jsx(FieldError, {
560
+ className: "input__error",
561
+ children: errorMessage
562
+ })
563
+ ]
564
+ });
565
+ }
566
+ //#endregion
567
+ //#region src/Label.tsx
568
+ /** Associates visible text with a separately rendered control. */
569
+ function Label({ children, htmlFor, id }) {
570
+ return /* @__PURE__ */ jsx(Label$3, {
571
+ className: "label",
572
+ htmlFor,
573
+ id,
574
+ children
575
+ });
576
+ }
577
+ //#endregion
578
+ //#region src/Checkbox.tsx
579
+ function Checkbox({ label, description, errorMessage, isInvalid = false, isSelected, defaultSelected, onChange, isDisabled = false, isRequired = false, isIndeterminate = false, name, value = "on", id, dir }) {
580
+ const { describedBy, feedback } = useFeedback({
581
+ description,
582
+ errorMessage,
583
+ isInvalid
584
+ });
585
+ return /* @__PURE__ */ jsxs("div", {
586
+ className: "input",
587
+ dir,
588
+ children: [/* @__PURE__ */ jsx(Checkbox$1, {
589
+ className: "choice",
590
+ isSelected,
591
+ defaultSelected,
592
+ onChange,
593
+ isDisabled,
594
+ isRequired,
595
+ isInvalid,
596
+ isIndeterminate,
597
+ validationBehavior: "aria",
598
+ name,
599
+ value,
600
+ id,
601
+ "aria-describedby": describedBy,
602
+ "aria-invalid": isInvalid || void 0,
603
+ children: ({ isSelected: selected, isDisabled: disabled, isFocusVisible }) => /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs("span", {
604
+ "aria-hidden": "true",
605
+ className: "checkbox__control",
606
+ "data-state": isIndeterminate ? "indeterminate" : selected ? "checked" : "unchecked",
607
+ "data-disabled": disabled || void 0,
608
+ "data-invalid": isInvalid || void 0,
609
+ "data-focus-visible": isFocusVisible || void 0,
610
+ children: [/* @__PURE__ */ jsx(CheckIcon, { className: "checkbox__check" }), /* @__PURE__ */ jsx("span", { className: "checkbox__dash" })]
611
+ }), /* @__PURE__ */ jsx("span", {
612
+ className: "choice__label",
613
+ children: label
614
+ })] })
615
+ }), feedback]
616
+ });
617
+ }
618
+ //#endregion
619
+ //#region src/RadioGroup.tsx
620
+ function RadioGroup({ label, options, value, defaultValue, onChange, description, errorMessage, isInvalid = false, isDisabled = false, isRequired = false, name, id, orientation = "vertical", dir }) {
621
+ const { describedBy, feedback } = useFeedback({
622
+ description,
623
+ errorMessage,
624
+ isInvalid
625
+ });
626
+ const group = /* @__PURE__ */ jsxs(RadioGroup$1, {
627
+ className: "input radio-group",
628
+ value,
629
+ defaultValue,
630
+ onChange,
631
+ isDisabled,
632
+ isRequired,
633
+ isInvalid,
634
+ validationBehavior: "aria",
635
+ name,
636
+ id,
637
+ orientation,
638
+ dir,
639
+ "aria-describedby": describedBy,
640
+ children: [
641
+ /* @__PURE__ */ jsx(Label$4, {
642
+ className: "label",
643
+ children: label
644
+ }),
645
+ /* @__PURE__ */ jsx("div", {
646
+ className: "radio-group__items",
647
+ "data-orientation": orientation,
648
+ children: options.map((option) => /* @__PURE__ */ jsx(Radio, {
649
+ value: option.id,
650
+ isDisabled: option.isDisabled,
651
+ className: "choice",
652
+ children: ({ isSelected, isDisabled: disabled, isFocusVisible }) => /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("span", {
653
+ "aria-hidden": "true",
654
+ className: "radio__control",
655
+ "data-state": isSelected ? "checked" : "unchecked",
656
+ "data-disabled": disabled || void 0,
657
+ "data-invalid": isInvalid || void 0,
658
+ "data-focus-visible": isFocusVisible || void 0,
659
+ children: /* @__PURE__ */ jsx("span", { className: "radio__dot" })
660
+ }), /* @__PURE__ */ jsx("span", {
661
+ className: "choice__label",
662
+ children: option.label
663
+ })] })
664
+ }, option.id))
665
+ }),
666
+ feedback
667
+ ]
668
+ });
669
+ return dir ? /* @__PURE__ */ jsx(I18nProvider, {
670
+ locale: dir === "rtl" ? "ar-EG" : "en-US",
671
+ children: group
672
+ }) : group;
673
+ }
674
+ //#endregion
675
+ //#region src/Switch.tsx
676
+ function Switch({ label, description, errorMessage, isInvalid = false, isSelected, defaultSelected, onChange, isDisabled = false, name, value = "on", id, dir }) {
677
+ return /* @__PURE__ */ jsxs(SwitchField, {
678
+ className: "input",
679
+ dir,
680
+ isSelected,
681
+ defaultSelected,
682
+ onChange,
683
+ isDisabled,
684
+ isInvalid,
685
+ validationBehavior: "aria",
686
+ name,
687
+ value,
688
+ id,
689
+ children: [
690
+ /* @__PURE__ */ jsx(SwitchButton, {
691
+ className: "choice",
692
+ children: ({ isSelected: selected, isDisabled: disabled, isFocusVisible }) => /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("span", {
693
+ "aria-hidden": "true",
694
+ className: "switch__control",
695
+ "data-state": selected ? "checked" : "unchecked",
696
+ "data-disabled": disabled || void 0,
697
+ "data-invalid": isInvalid || void 0,
698
+ "data-focus-visible": isFocusVisible || void 0,
699
+ children: /* @__PURE__ */ jsx("span", { className: "switch__thumb" })
700
+ }), /* @__PURE__ */ jsx("span", {
701
+ className: "choice__label",
702
+ children: label
703
+ })] })
704
+ }),
705
+ description && /* @__PURE__ */ jsx(Text$1, {
706
+ slot: "description",
707
+ className: "input__description",
708
+ children: description
709
+ }),
710
+ isInvalid && errorMessage && /* @__PURE__ */ jsx(FieldError$1, {
711
+ className: "input__error",
712
+ children: errorMessage
713
+ })
714
+ ]
715
+ });
716
+ }
717
+ //#endregion
718
+ //#region src/form-context.ts
719
+ var FormErrorsContext = /* @__PURE__ */ createContext({});
720
+ //#endregion
721
+ //#region src/FieldComponent.tsx
722
+ function Field({ label, name, children, id, description, errorMessage, isInvalid = false, isDisabled = false, isReadOnly = false, isRequired = false, dir }) {
723
+ const errors = useContext(FormErrorsContext);
724
+ const error = Object.hasOwn(errors, name) && typeof errors[name] === "string" ? errors[name] || void 0 : void 0;
725
+ const invalid = isInvalid || !!error;
726
+ const message = isInvalid && errorMessage || error || void 0;
727
+ const generated = useId();
728
+ const controlId = id ?? generated;
729
+ const { describedBy, feedback } = useFeedback({
730
+ description,
731
+ isInvalid: invalid,
732
+ errorMessage: message
733
+ });
734
+ return /* @__PURE__ */ jsxs("div", {
735
+ className: "input field",
736
+ dir,
737
+ children: [
738
+ /* @__PURE__ */ jsx(Label, {
739
+ htmlFor: controlId,
740
+ children: label
741
+ }),
742
+ children({
743
+ controlProps: {
744
+ id: controlId,
745
+ name,
746
+ className: "input__control field__control",
747
+ disabled: isDisabled,
748
+ readOnly: isReadOnly,
749
+ required: isRequired,
750
+ "aria-required": isRequired || void 0,
751
+ "aria-invalid": invalid || void 0,
752
+ "aria-describedby": describedBy
753
+ },
754
+ isInvalid: invalid,
755
+ errorMessage: message
756
+ }),
757
+ feedback
758
+ ]
759
+ });
760
+ }
761
+ //#endregion
762
+ //#region src/Form.tsx
763
+ function Form({ children, validationErrors = {}, onSubmit, onReset, noValidate = false, id, "aria-label": ariaLabel, "aria-labelledby": labelledBy, dir }) {
764
+ function submit(event) {
765
+ event.preventDefault();
766
+ const form = event.currentTarget;
767
+ if (!noValidate && !form.checkValidity()) {
768
+ form.reportValidity();
769
+ return;
770
+ }
771
+ for (const element of form.querySelectorAll("[aria-invalid=\"true\"]")) {
772
+ const selector = "input:not([type=\"hidden\"]), textarea, select, button, [role=\"listbox\"]";
773
+ const invalid = (element.matches(selector) ? [element] : [...element.querySelectorAll(selector)]).find((control) => !control.matches(":disabled, [aria-disabled=\"true\"]"));
774
+ if (invalid) {
775
+ invalid.focus();
776
+ return;
777
+ }
778
+ }
779
+ onSubmit?.(new FormData(form, event.nativeEvent.submitter), event);
780
+ }
781
+ return /* @__PURE__ */ jsx(FormErrorsContext.Provider, {
782
+ value: validationErrors,
783
+ children: /* @__PURE__ */ jsx("form", {
784
+ className: "form",
785
+ id,
786
+ dir,
787
+ "aria-label": ariaLabel,
788
+ "aria-labelledby": labelledBy,
789
+ noValidate,
790
+ onSubmit: submit,
791
+ onReset,
792
+ children
793
+ })
794
+ });
795
+ }
796
+ //#endregion
797
+ //#region src/listbox-selection.ts
798
+ /** Stable option order, unique enabled IDs, and at most one ID in single mode. */
799
+ function listboxSelection(value, options, mode) {
800
+ const requested = new Set(value);
801
+ const seen = /* @__PURE__ */ new Set();
802
+ const result = [];
803
+ for (const option of options) if (option.id && !option.isDisabled && requested.has(option.id) && !seen.has(option.id)) {
804
+ seen.add(option.id);
805
+ result.push(option.id);
806
+ if (mode === "single") break;
807
+ }
808
+ return result;
809
+ }
810
+ //#endregion
811
+ //#region src/Listbox.tsx
812
+ function Listbox({ label, options, value, defaultValue = [], onChange, selectionMode = "single", isDisabled = false, description, errorMessage, isInvalid = false, name, id, dir, emptyMessage = "Tidak ada pilihan." }) {
813
+ const [local, setLocal] = useState(defaultValue);
814
+ const selected = listboxSelection(value ?? local, options, selectionMode);
815
+ const nodeRef = useRef(null);
816
+ const tabIndexBeforeDisable = useRef(void 0);
817
+ function listRef(node) {
818
+ if (!node) return;
819
+ if (nodeRef.current !== node) tabIndexBeforeDisable.current = void 0;
820
+ nodeRef.current = node;
821
+ if (isInvalid) node.setAttribute("aria-invalid", "true");
822
+ else node.removeAttribute("aria-invalid");
823
+ if (isDisabled) {
824
+ node.setAttribute("aria-disabled", "true");
825
+ if (tabIndexBeforeDisable.current === void 0) tabIndexBeforeDisable.current = node.getAttribute("tabindex");
826
+ node.tabIndex = -1;
827
+ } else {
828
+ node.removeAttribute("aria-disabled");
829
+ if (tabIndexBeforeDisable.current !== void 0) {
830
+ if (tabIndexBeforeDisable.current === null) node.removeAttribute("tabindex");
831
+ else node.setAttribute("tabindex", tabIndexBeforeDisable.current);
832
+ tabIndexBeforeDisable.current = void 0;
833
+ }
834
+ }
835
+ }
836
+ const generated = useId();
837
+ const labelId = `${id ?? generated}-label`;
838
+ const { describedBy, feedback } = useFeedback({
839
+ description,
840
+ errorMessage,
841
+ isInvalid
842
+ });
843
+ function change(keys) {
844
+ if (isDisabled || keys === "all") return;
845
+ const next = listboxSelection([...keys].map(String), options, selectionMode);
846
+ if (next.length === selected.length && next.every((key, index) => key === selected[index])) return;
847
+ setLocal(next);
848
+ onChange?.(next);
849
+ }
850
+ const list = /* @__PURE__ */ jsxs("div", {
851
+ className: "input listbox",
852
+ dir,
853
+ children: [
854
+ /* @__PURE__ */ jsx("span", {
855
+ id: labelId,
856
+ className: "label",
857
+ children: label
858
+ }),
859
+ /* @__PURE__ */ jsx(ListBox$1, {
860
+ ref: listRef,
861
+ id,
862
+ className: "listbox__list",
863
+ "aria-labelledby": labelId,
864
+ "aria-describedby": describedBy,
865
+ "aria-invalid": isInvalid || void 0,
866
+ "aria-disabled": isDisabled || void 0,
867
+ selectionMode,
868
+ selectionBehavior: selectionMode === "single" ? "replace" : "toggle",
869
+ disallowEmptySelection: selectionMode === "single",
870
+ selectedKeys: selected,
871
+ onSelectionChange: change,
872
+ disabledKeys: options.filter((option) => isDisabled || option.isDisabled).map((option) => option.id),
873
+ renderEmptyState: () => /* @__PURE__ */ jsx("span", {
874
+ className: "listbox__empty",
875
+ children: emptyMessage
876
+ }),
877
+ children: options.map((option) => /* @__PURE__ */ jsxs(ListBoxItem$1, {
878
+ id: option.id,
879
+ textValue: option.label,
880
+ isDisabled: isDisabled || option.isDisabled,
881
+ className: "listbox__item",
882
+ children: [/* @__PURE__ */ jsx("span", {
883
+ className: "listbox__text",
884
+ children: option.label
885
+ }), /* @__PURE__ */ jsx(CheckIcon, { className: "listbox__check" })]
886
+ }, option.id))
887
+ }),
888
+ feedback,
889
+ name && selected.map((key) => /* @__PURE__ */ jsx("input", {
890
+ type: "hidden",
891
+ name,
892
+ value: key,
893
+ disabled: isDisabled
894
+ }, key))
895
+ ]
896
+ });
897
+ return dir ? /* @__PURE__ */ jsx(I18nProvider, {
898
+ locale: dir === "rtl" ? "ar-EG" : "en-US",
899
+ children: list
900
+ }) : list;
901
+ }
902
+ //#endregion
903
+ //#region src/NumberField.tsx
904
+ function finite(value) {
905
+ return typeof value === "number" && Number.isFinite(value) ? value : null;
906
+ }
907
+ function NumberField({ label, value, defaultValue = null, onChange, min, max, step = 1, locale = "id-ID", formatOptions, description, errorMessage, isInvalid = false, isDisabled = false, isReadOnly = false, isRequired = false, name, id, dir, incrementLabel, decrementLabel }) {
908
+ const buttonId = useId();
909
+ const inputRef = useRef(null);
910
+ const [local, setLocal] = useState(() => finite(defaultValue));
911
+ const selected = finite(value === void 0 ? local : value);
912
+ function change(next) {
913
+ if (isDisabled || isReadOnly) return;
914
+ const number = finite(next);
915
+ setLocal(number);
916
+ onChange?.(number);
917
+ }
918
+ return /* @__PURE__ */ jsx(I18nProvider, {
919
+ locale,
920
+ children: /* @__PURE__ */ jsx(NumberField$1, {
921
+ className: "input number-field",
922
+ id,
923
+ dir,
924
+ value: selected ?? NaN,
925
+ onChange: change,
926
+ minValue: min,
927
+ maxValue: max,
928
+ step,
929
+ formatOptions,
930
+ isDisabled,
931
+ isReadOnly,
932
+ isRequired,
933
+ isInvalid,
934
+ validationBehavior: "aria",
935
+ isWheelDisabled: true,
936
+ children: ({ state }) => {
937
+ const empty = state.inputValue.trim() === "";
938
+ function startEmpty() {
939
+ const start = Math.min(max ?? Infinity, Math.max(min ?? -Infinity, min ?? 0));
940
+ state.setNumberValue(start);
941
+ inputRef.current?.focus();
942
+ }
943
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [
944
+ /* @__PURE__ */ jsx(Label$5, {
945
+ className: "label",
946
+ children: label
947
+ }),
948
+ /* @__PURE__ */ jsx(Group, {
949
+ className: "number-field__group",
950
+ onKeyDownCapture: (event) => {
951
+ if (isDisabled || isReadOnly || !empty || ![
952
+ "ArrowUp",
953
+ "ArrowDown",
954
+ "PageUp",
955
+ "PageDown"
956
+ ].includes(event.key)) return;
957
+ event.preventDefault();
958
+ event.stopPropagation();
959
+ startEmpty();
960
+ },
961
+ children: /* @__PURE__ */ jsx(ButtonContext.Consumer, { children: (buttonContext) => /* @__PURE__ */ jsxs(ButtonContext.Provider, {
962
+ value: empty ? null : buttonContext,
963
+ children: [
964
+ /* @__PURE__ */ jsxs(Button$3, {
965
+ slot: empty ? void 0 : "decrement",
966
+ onPress: empty ? startEmpty : void 0,
967
+ isDisabled: empty ? isDisabled || isReadOnly : void 0,
968
+ preventFocusOnPress: true,
969
+ className: "number-field__step",
970
+ "aria-label": decrementLabel ?? `Kurangi ${label}`,
971
+ "aria-labelledby": `${buttonId}-decrement`,
972
+ excludeFromTabOrder: true,
973
+ children: [/* @__PURE__ */ jsx("span", {
974
+ id: `${buttonId}-decrement`,
975
+ hidden: true,
976
+ children: decrementLabel ?? `Kurangi ${label}`
977
+ }), "−"]
978
+ }),
979
+ /* @__PURE__ */ jsx(Input$2, {
980
+ ref: inputRef,
981
+ className: "number-field__control",
982
+ required: isRequired
983
+ }),
984
+ /* @__PURE__ */ jsxs(Button$3, {
985
+ slot: empty ? void 0 : "increment",
986
+ onPress: empty ? startEmpty : void 0,
987
+ isDisabled: empty ? isDisabled || isReadOnly : void 0,
988
+ preventFocusOnPress: true,
989
+ className: "number-field__step",
990
+ "aria-label": incrementLabel ?? `Tambah ${label}`,
991
+ "aria-labelledby": `${buttonId}-increment`,
992
+ excludeFromTabOrder: true,
993
+ children: [/* @__PURE__ */ jsx("span", {
994
+ id: `${buttonId}-increment`,
995
+ hidden: true,
996
+ children: incrementLabel ?? `Tambah ${label}`
997
+ }), "+"]
998
+ })
999
+ ]
1000
+ }) })
1001
+ }),
1002
+ description && /* @__PURE__ */ jsx(Text$2, {
1003
+ slot: "description",
1004
+ className: "input__description",
1005
+ children: description
1006
+ }),
1007
+ isInvalid && errorMessage && /* @__PURE__ */ jsx(FieldError$2, {
1008
+ className: "input__error",
1009
+ children: errorMessage
1010
+ }),
1011
+ name && /* @__PURE__ */ jsx("input", {
1012
+ type: "hidden",
1013
+ name,
1014
+ value: selected === null ? "" : String(selected),
1015
+ disabled: isDisabled
1016
+ })
1017
+ ] });
1018
+ }
1019
+ })
1020
+ });
1021
+ }
1022
+ //#endregion
1023
+ //#region src/Card.tsx
1024
+ /** A content container; place links and buttons inside rather than making it clickable. */
1025
+ function Card({ title, description, headingLevel = 3, actions, header, titleExtras, footer, children, className, ...props }) {
1026
+ const Heading = `h${headingLevel}`;
1027
+ return /* @__PURE__ */ jsxs("div", {
1028
+ ...props,
1029
+ className: ["card", className].filter(Boolean).join(" "),
1030
+ children: [
1031
+ (title || description || actions || header || titleExtras) && /* @__PURE__ */ jsxs("div", {
1032
+ className: "card__header",
1033
+ children: [(title || description || header || titleExtras) && /* @__PURE__ */ jsx("div", {
1034
+ className: "card__heading",
1035
+ children: header ?? /* @__PURE__ */ jsxs(Fragment$1, { children: [titleExtras ? /* @__PURE__ */ jsxs("div", {
1036
+ className: "card__title-row",
1037
+ children: [title && /* @__PURE__ */ jsx(Heading, {
1038
+ className: "card__title",
1039
+ children: title
1040
+ }), titleExtras]
1041
+ }) : title && /* @__PURE__ */ jsx(Heading, {
1042
+ className: "card__title",
1043
+ children: title
1044
+ }), description && /* @__PURE__ */ jsx("p", {
1045
+ className: "card__description",
1046
+ children: description
1047
+ })] })
1048
+ }), actions && /* @__PURE__ */ jsx("div", {
1049
+ className: "card__actions",
1050
+ children: actions
1051
+ })]
1052
+ }),
1053
+ /* @__PURE__ */ jsx("div", {
1054
+ className: "card__content",
1055
+ children
1056
+ }),
1057
+ footer && /* @__PURE__ */ jsx("div", {
1058
+ className: "card__footer",
1059
+ children: footer
1060
+ })
1061
+ ]
1062
+ });
1063
+ }
1064
+ //#endregion
1065
+ //#region src/Badge.tsx
1066
+ /** Static status text. Dynamic announcements belong in an application-owned live region. */
1067
+ function Badge({ tone = "neutral", className, ...props }) {
1068
+ return /* @__PURE__ */ jsx("span", {
1069
+ ...props,
1070
+ className: ["badge", className].filter(Boolean).join(" "),
1071
+ "data-tone": tone
1072
+ });
1073
+ }
1074
+ //#endregion
1075
+ //#region src/Skeleton.tsx
1076
+ /** Decorative placeholder. Set aria-busy and loading text on the surrounding content. */
1077
+ function Skeleton({ shape = "rectangle", animated = true, className, ...props }) {
1078
+ return /* @__PURE__ */ jsx("span", {
1079
+ ...props,
1080
+ className: ["skeleton", className].filter(Boolean).join(" "),
1081
+ "data-shape": shape,
1082
+ "data-animated": animated ? "true" : void 0,
1083
+ "aria-hidden": "true"
1084
+ });
1085
+ }
1086
+ //#endregion
1087
+ //#region src/Separator.tsx
1088
+ function Separator({ orientation = "horizontal", decorative = true, className, ...props }) {
1089
+ return /* @__PURE__ */ jsx("div", {
1090
+ ...props,
1091
+ className: ["separator", className].filter(Boolean).join(" "),
1092
+ "data-orientation": orientation,
1093
+ role: decorative ? "presentation" : "separator",
1094
+ "aria-hidden": decorative ? "true" : void 0,
1095
+ "aria-orientation": decorative ? void 0 : orientation
1096
+ });
1097
+ }
1098
+ //#endregion
1099
+ //#region src/tabs-indicator.ts
1100
+ function mountTabsIndicator(container) {
1101
+ const list = container.querySelector("[role=\"tablist\"]");
1102
+ if (!list) return () => {};
1103
+ let frame = 0, disposed = false, previous = null, armed = false;
1104
+ const prev = container.querySelector("[data-tabs-scroll=\"prev\"]");
1105
+ const next = container.querySelector("[data-tabs-scroll=\"next\"]");
1106
+ const vertical = () => list.getAttribute("aria-orientation") === "vertical";
1107
+ const reduced = () => window.matchMedia?.("(prefers-reduced-motion: reduce)").matches ?? false;
1108
+ function measure() {
1109
+ if (disposed) return;
1110
+ const selected = list.querySelector("[role=\"tab\"][aria-selected=\"true\"]");
1111
+ const rect = list.getBoundingClientRect();
1112
+ if (selected && rect.width > 0 && rect.height > 0) {
1113
+ const tab = selected.getBoundingClientRect();
1114
+ const border = getComputedStyle(list);
1115
+ list.style.setProperty("--tabs-indicator-x", `${tab.left - rect.left + list.scrollLeft - (parseFloat(border.borderLeftWidth) || 0)}px`);
1116
+ list.style.setProperty("--tabs-indicator-y", `${tab.top - rect.top + list.scrollTop - (parseFloat(border.borderTopWidth) || 0)}px`);
1117
+ list.style.setProperty("--tabs-indicator-width", `${tab.width}px`);
1118
+ list.style.setProperty("--tabs-indicator-height", `${tab.height}px`);
1119
+ list.dataset.indicatorReady = "true";
1120
+ if (!armed) {
1121
+ armed = true;
1122
+ requestAnimationFrame(() => {
1123
+ if (!disposed) list.dataset.indicatorAnimated = "true";
1124
+ });
1125
+ }
1126
+ if (selected !== previous && previous && typeof list.scrollBy === "function") {
1127
+ const delta = vertical() ? tab.top < rect.top ? tab.top - rect.top : tab.bottom > rect.bottom ? tab.bottom - rect.bottom : 0 : tab.left < rect.left ? tab.left - rect.left : tab.right > rect.right ? tab.right - rect.right : 0;
1128
+ if (delta) list.scrollBy({
1129
+ [vertical() ? "top" : "left"]: delta,
1130
+ behavior: reduced() ? "instant" : "smooth"
1131
+ });
1132
+ }
1133
+ } else list.dataset.indicatorReady = "false";
1134
+ previous = selected;
1135
+ const max = vertical() ? list.scrollHeight - list.clientHeight : list.scrollWidth - list.clientWidth;
1136
+ const position = Math.abs(vertical() ? list.scrollTop : list.scrollLeft);
1137
+ list.dataset.overflow = String(max > 1);
1138
+ if (prev) {
1139
+ prev.hidden = max <= 1;
1140
+ prev.disabled = position <= 1;
1141
+ }
1142
+ if (next) {
1143
+ next.hidden = max <= 1;
1144
+ next.disabled = position >= max - 1;
1145
+ }
1146
+ }
1147
+ function schedule() {
1148
+ if (disposed) return;
1149
+ cancelAnimationFrame(frame);
1150
+ frame = requestAnimationFrame(measure);
1151
+ }
1152
+ function scroll(direction) {
1153
+ if (typeof list.scrollBy !== "function") return;
1154
+ const rtl = !vertical() && getComputedStyle(list).direction === "rtl";
1155
+ const amount = (vertical() ? list.clientHeight : list.clientWidth) * .7 * direction * (rtl ? -1 : 1);
1156
+ list.scrollBy({
1157
+ [vertical() ? "top" : "left"]: amount,
1158
+ behavior: reduced() ? "instant" : "smooth"
1159
+ });
1160
+ }
1161
+ const backward = () => scroll(-1), forward = () => scroll(1);
1162
+ prev?.addEventListener("click", backward);
1163
+ next?.addEventListener("click", forward);
1164
+ list.addEventListener("scroll", schedule, { passive: true });
1165
+ window.addEventListener("resize", schedule);
1166
+ const observer = new MutationObserver(schedule);
1167
+ observer.observe(list, {
1168
+ subtree: true,
1169
+ childList: true,
1170
+ characterData: true,
1171
+ attributes: true,
1172
+ attributeFilter: [
1173
+ "aria-selected",
1174
+ "aria-orientation",
1175
+ "aria-disabled",
1176
+ "disabled"
1177
+ ]
1178
+ });
1179
+ const resize = typeof ResizeObserver === "undefined" ? void 0 : new ResizeObserver(schedule);
1180
+ resize?.observe(list);
1181
+ for (const tab of list.querySelectorAll("[role=\"tab\"]")) resize?.observe(tab);
1182
+ document.fonts?.ready.then(schedule);
1183
+ schedule();
1184
+ return () => {
1185
+ disposed = true;
1186
+ cancelAnimationFrame(frame);
1187
+ observer.disconnect();
1188
+ resize?.disconnect();
1189
+ prev?.removeEventListener("click", backward);
1190
+ next?.removeEventListener("click", forward);
1191
+ list.removeEventListener("scroll", schedule);
1192
+ window.removeEventListener("resize", schedule);
1193
+ };
1194
+ }
1195
+ //#endregion
1196
+ //#region src/Tabs.tsx
1197
+ function Tabs({ 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 }) {
1198
+ const container = useRef(null);
1199
+ const hasToolbar = !!(extras || actions);
1200
+ useEffect(() => container.current ? mountTabsIndicator(container.current) : void 0, [items.length, hasToolbar]);
1201
+ const [local, setLocal] = useState(defaultValue);
1202
+ const selected = items.find((item) => item.id === (value ?? local) && !item.isDisabled)?.id ?? items.find((item) => !item.isDisabled)?.id;
1203
+ const list = items.length > 0 ? /* @__PURE__ */ jsxs("div", {
1204
+ className: "tabs__list-container",
1205
+ ref: container,
1206
+ children: [
1207
+ /* @__PURE__ */ jsx("button", {
1208
+ type: "button",
1209
+ className: "tabs__scroll-button tabs__scroll-button--prev",
1210
+ "data-tabs-scroll": "prev",
1211
+ hidden: true,
1212
+ "aria-label": previousLabel,
1213
+ children: /* @__PURE__ */ jsx("svg", {
1214
+ viewBox: "0 0 24 24",
1215
+ "aria-hidden": "true",
1216
+ children: /* @__PURE__ */ jsx("path", { d: "m14 6-6 6 6 6" })
1217
+ })
1218
+ }),
1219
+ /* @__PURE__ */ jsx(TabList, {
1220
+ className: "tabs__list",
1221
+ "aria-label": label,
1222
+ children: items.map((item, index) => /* @__PURE__ */ jsxs(Tab, {
1223
+ className: "tabs__trigger",
1224
+ id: item.id,
1225
+ isDisabled: item.isDisabled,
1226
+ children: [
1227
+ showSeparators && index > 0 && /* @__PURE__ */ jsx("span", {
1228
+ className: "tabs__separator",
1229
+ "aria-hidden": "true"
1230
+ }),
1231
+ renderIcon && /* @__PURE__ */ jsx("span", {
1232
+ className: "tabs__icon",
1233
+ "aria-hidden": "true",
1234
+ children: renderIcon(item)
1235
+ }),
1236
+ /* @__PURE__ */ jsx("span", {
1237
+ className: "tabs__label",
1238
+ children: item.label
1239
+ })
1240
+ ]
1241
+ }, item.id))
1242
+ }),
1243
+ /* @__PURE__ */ jsx("button", {
1244
+ type: "button",
1245
+ className: "tabs__scroll-button tabs__scroll-button--next",
1246
+ "data-tabs-scroll": "next",
1247
+ hidden: true,
1248
+ "aria-label": nextLabel,
1249
+ children: /* @__PURE__ */ jsx("svg", {
1250
+ viewBox: "0 0 24 24",
1251
+ "aria-hidden": "true",
1252
+ children: /* @__PURE__ */ jsx("path", { d: "m10 6 6 6-6 6" })
1253
+ })
1254
+ })
1255
+ ]
1256
+ }) : null;
1257
+ const content = /* @__PURE__ */ jsxs(Tabs$1, {
1258
+ className: [
1259
+ "tabs",
1260
+ `tabs--${variant === "default" ? "primary" : variant}`,
1261
+ `tabs--align-${align}`,
1262
+ fullWidth && "tabs--full-width",
1263
+ inset === "none" && "tabs--flush",
1264
+ size !== "md" && `tabs--${size}`
1265
+ ].filter(Boolean).join(" "),
1266
+ id,
1267
+ orientation,
1268
+ dir,
1269
+ selectedKey: selected ?? "",
1270
+ keyboardActivation: activationMode,
1271
+ disabledKeys: items.filter((item) => item.isDisabled).map((item) => item.id),
1272
+ onSelectionChange: (key) => {
1273
+ const next = String(key);
1274
+ if (next !== selected && items.some((item) => item.id === next && !item.isDisabled)) {
1275
+ setLocal(next);
1276
+ onChange?.(next);
1277
+ }
1278
+ },
1279
+ children: [extras || actions ? /* @__PURE__ */ jsxs("div", {
1280
+ className: "tabs__toolbar",
1281
+ children: [/* @__PURE__ */ jsxs("div", {
1282
+ className: "tabs__navigation",
1283
+ children: [list, extras && /* @__PURE__ */ jsx("div", {
1284
+ className: "tabs__extras",
1285
+ children: extras
1286
+ })]
1287
+ }), actions && /* @__PURE__ */ jsx("div", {
1288
+ className: "tabs__actions",
1289
+ children: actions
1290
+ })]
1291
+ }) : list, items.map((item) => /* @__PURE__ */ jsx(TabPanel, {
1292
+ id: item.id,
1293
+ className: "tabs__panel",
1294
+ children: renderPanel(item)
1295
+ }, item.id))]
1296
+ });
1297
+ return dir ? /* @__PURE__ */ jsx(I18nProvider, {
1298
+ locale: dir === "rtl" ? "ar-EG" : "en-US",
1299
+ children: content
1300
+ }) : content;
1301
+ }
1302
+ //#endregion
1303
+ //#region src/pagination-model.ts
1304
+ function paginationModel(totalItems, pageSize, value, siblingCount = 1) {
1305
+ const count = Math.max(1, Math.ceil((Number.isFinite(totalItems) ? Math.min(Number.MAX_SAFE_INTEGER, Math.max(0, Math.floor(totalItems))) : 0) / (Number.isFinite(pageSize) ? Math.max(1, Math.floor(pageSize)) : 10)));
1306
+ const current = Math.min(count, Math.max(1, Number.isFinite(value) ? Math.floor(value) : 1));
1307
+ const siblings = Number.isFinite(siblingCount) ? Math.min(2, Math.max(0, Math.floor(siblingCount))) : 1;
1308
+ const pages = /* @__PURE__ */ new Set([
1309
+ 1,
1310
+ count,
1311
+ current
1312
+ ]);
1313
+ for (let offset = 1; offset <= siblings; offset++) {
1314
+ if (current - offset > 1) pages.add(current - offset);
1315
+ if (current + offset < count) pages.add(current + offset);
1316
+ }
1317
+ const ordered = [...pages].sort((a, b) => a - b);
1318
+ const entries = [];
1319
+ ordered.forEach((page, index) => {
1320
+ if (index && page - ordered[index - 1] > 1) entries.push(`gap-${page}`);
1321
+ entries.push(page);
1322
+ });
1323
+ return {
1324
+ current,
1325
+ count,
1326
+ entries
1327
+ };
1328
+ }
1329
+ //#endregion
1330
+ //#region src/Pagination.tsx
1331
+ function Pagination({ totalItems, pageSize = 10, value, defaultValue = 1, onChange, isDisabled = false, siblingCount = 1, label = "Navigasi halaman", previousLabel = "Sebelumnya", nextLabel = "Berikutnya", pageLabel = "Halaman", dir, id }) {
1332
+ const [local, setLocal] = useState(defaultValue);
1333
+ const { current, count, entries } = paginationModel(totalItems, pageSize, value ?? local, siblingCount);
1334
+ function change(next) {
1335
+ if (isDisabled || next === current || next < 1 || next > count) return;
1336
+ setLocal(next);
1337
+ onChange?.(next);
1338
+ }
1339
+ return /* @__PURE__ */ jsxs("nav", {
1340
+ className: "pagination",
1341
+ "aria-label": label,
1342
+ dir,
1343
+ id,
1344
+ children: [
1345
+ /* @__PURE__ */ jsx("button", {
1346
+ type: "button",
1347
+ className: "pagination__button",
1348
+ disabled: isDisabled || current === 1,
1349
+ onClick: () => change(current - 1),
1350
+ children: previousLabel
1351
+ }),
1352
+ entries.map((entry) => typeof entry === "string" ? /* @__PURE__ */ jsx("span", {
1353
+ className: "pagination__gap",
1354
+ "aria-hidden": "true",
1355
+ children: "..."
1356
+ }, entry) : /* @__PURE__ */ jsx("button", {
1357
+ type: "button",
1358
+ className: "pagination__button",
1359
+ "aria-label": `${pageLabel} ${entry}`,
1360
+ "aria-current": entry === current ? "page" : void 0,
1361
+ disabled: isDisabled,
1362
+ onClick: () => change(entry),
1363
+ children: entry
1364
+ }, entry)),
1365
+ /* @__PURE__ */ jsx("button", {
1366
+ type: "button",
1367
+ className: "pagination__button",
1368
+ disabled: isDisabled || current === count,
1369
+ onClick: () => change(current + 1),
1370
+ children: nextLabel
1371
+ }),
1372
+ /* @__PURE__ */ jsxs("span", {
1373
+ className: "pagination__summary",
1374
+ "aria-live": "polite",
1375
+ children: [
1376
+ current,
1377
+ " / ",
1378
+ count
1379
+ ]
1380
+ })
1381
+ ]
1382
+ });
1383
+ }
1384
+ //#endregion
1385
+ //#region src/Table.tsx
1386
+ function Table({ caption, children, className, ...props }) {
1387
+ return /* @__PURE__ */ jsx("div", {
1388
+ className: "table__scroll",
1389
+ role: "region",
1390
+ "aria-label": caption,
1391
+ tabIndex: 0,
1392
+ children: /* @__PURE__ */ jsxs("table", {
1393
+ ...props,
1394
+ className: ["table", className].filter(Boolean).join(" "),
1395
+ children: [/* @__PURE__ */ jsx("caption", {
1396
+ className: "table__caption",
1397
+ children: caption
1398
+ }), children]
1399
+ })
1400
+ });
1401
+ }
1402
+ //#endregion
1403
+ //#region src/DataTable.tsx
1404
+ function DataTable({ caption, columns, rows, sort = null, onSortChange, isLoading = false, isDisabled = false, emptyMessage = "Tidak ada data.", loadingMessage = "Memuat data...", errorMessage, renderCell, dir, id }) {
1405
+ function requestSort(column) {
1406
+ if (isLoading || isDisabled || !column.sortable) return;
1407
+ onSortChange?.({
1408
+ columnId: column.id,
1409
+ direction: sort?.columnId === column.id && sort.direction === "ascending" ? "descending" : "ascending"
1410
+ });
1411
+ }
1412
+ return /* @__PURE__ */ jsxs("div", {
1413
+ className: "data-table",
1414
+ dir,
1415
+ id,
1416
+ children: [
1417
+ /* @__PURE__ */ jsxs(Table, {
1418
+ caption,
1419
+ "aria-busy": isLoading || void 0,
1420
+ children: [/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsx("tr", { children: columns.map((column) => /* @__PURE__ */ jsx("th", {
1421
+ scope: "col",
1422
+ "aria-sort": column.sortable ? sort?.columnId === column.id ? sort.direction : "none" : void 0,
1423
+ children: column.sortable ? /* @__PURE__ */ jsxs("button", {
1424
+ type: "button",
1425
+ className: "table__sort",
1426
+ disabled: isLoading || isDisabled,
1427
+ onClick: () => requestSort(column),
1428
+ children: [column.label, /* @__PURE__ */ jsx("span", {
1429
+ "aria-hidden": "true",
1430
+ children: sort?.columnId === column.id ? sort.direction === "ascending" ? "↑" : "↓" : "↕"
1431
+ })]
1432
+ }) : column.label
1433
+ }, column.id)) }) }), /* @__PURE__ */ jsx("tbody", { children: rows.length ? rows.map((row) => /* @__PURE__ */ jsx("tr", { children: columns.map((column) => /* @__PURE__ */ jsx("td", { children: renderCell ? renderCell(row, column) : row.cells[column.id] ?? "" }, column.id)) }, row.id)) : /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx("td", {
1434
+ colSpan: Math.max(1, columns.length),
1435
+ className: "table__empty",
1436
+ children: isLoading ? loadingMessage : errorMessage || emptyMessage
1437
+ }) }) })]
1438
+ }),
1439
+ isLoading && /* @__PURE__ */ jsx("p", {
1440
+ className: "data-table__status",
1441
+ role: "status",
1442
+ children: loadingMessage
1443
+ }),
1444
+ errorMessage && !isLoading && /* @__PURE__ */ jsx("p", {
1445
+ className: "input__error",
1446
+ role: "alert",
1447
+ children: errorMessage
1448
+ })
1449
+ ]
1450
+ });
1451
+ }
1452
+ //#endregion
1453
+ //#region src/Alert.tsx
1454
+ function Alert({ title, description, tone = "info", announcement = "off", children, actions, id }) {
1455
+ return /* @__PURE__ */ jsxs("div", {
1456
+ id,
1457
+ className: "alert",
1458
+ "data-tone": tone,
1459
+ role: announcement === "polite" ? "status" : announcement === "assertive" ? "alert" : void 0,
1460
+ children: [
1461
+ /* @__PURE__ */ jsx("p", {
1462
+ className: "alert__title",
1463
+ children: title
1464
+ }),
1465
+ description && /* @__PURE__ */ jsx("p", {
1466
+ className: "alert__description",
1467
+ children: description
1468
+ }),
1469
+ children,
1470
+ actions && /* @__PURE__ */ jsx("div", {
1471
+ className: "alert__actions",
1472
+ children: actions
1473
+ })
1474
+ ]
1475
+ });
1476
+ }
1477
+ //#endregion
1478
+ //#region src/Empty.tsx
1479
+ function Empty({ title, description, headingLevel = 3, actions, children, id }) {
1480
+ const Heading = `h${headingLevel}`;
1481
+ return /* @__PURE__ */ jsxs("div", {
1482
+ id,
1483
+ className: "empty",
1484
+ children: [
1485
+ /* @__PURE__ */ jsx(Heading, {
1486
+ className: "empty__title",
1487
+ children: title
1488
+ }),
1489
+ description && /* @__PURE__ */ jsx("p", {
1490
+ className: "empty__description",
1491
+ children: description
1492
+ }),
1493
+ children,
1494
+ actions && /* @__PURE__ */ jsx("div", {
1495
+ className: "empty__actions",
1496
+ children: actions
1497
+ })
1498
+ ]
1499
+ });
1500
+ }
1501
+ //#endregion
1502
+ //#region src/Breadcrumb.tsx
1503
+ function Breadcrumb({ items, label = "Jejak halaman", dir, id }) {
1504
+ return /* @__PURE__ */ jsx("nav", {
1505
+ id,
1506
+ className: "breadcrumb",
1507
+ "aria-label": label,
1508
+ dir,
1509
+ children: /* @__PURE__ */ jsx("ol", { children: items.map((item, index) => /* @__PURE__ */ jsxs("li", { children: [index > 0 && /* @__PURE__ */ jsx("span", {
1510
+ className: "breadcrumb__separator",
1511
+ "aria-hidden": "true",
1512
+ children: "/"
1513
+ }), index === items.length - 1 ? /* @__PURE__ */ jsx("span", {
1514
+ "aria-current": "page",
1515
+ children: item.label
1516
+ }) : item.href ? /* @__PURE__ */ jsx("a", {
1517
+ href: item.href,
1518
+ children: item.label
1519
+ }) : /* @__PURE__ */ jsx("span", { children: item.label })] }, index)) })
1520
+ });
1521
+ }
1522
+ //#endregion
1523
+ //#region src/useDisclosure.ts
1524
+ function useDisclosure(open, defaultOpen = false, onOpenChange) {
1525
+ const [local, setLocal] = useState(defaultOpen);
1526
+ const visible = open ?? local;
1527
+ function change(next) {
1528
+ if (next === visible) return;
1529
+ setLocal(next);
1530
+ onOpenChange?.(next);
1531
+ }
1532
+ return {
1533
+ visible,
1534
+ change
1535
+ };
1536
+ }
1537
+ //#endregion
1538
+ //#region src/Sidebar.tsx
1539
+ function Sidebar({ label, items, currentId, open, defaultOpen = true, onOpenChange, toggleLabel = "Menu navigasi", dir, id }) {
1540
+ const generated = useId(), navId = `${id ?? generated}-nav`;
1541
+ const { visible, change } = useDisclosure(open, defaultOpen, onOpenChange);
1542
+ return /* @__PURE__ */ jsxs("aside", {
1543
+ id,
1544
+ className: "sidebar",
1545
+ dir,
1546
+ children: [/* @__PURE__ */ jsxs("div", {
1547
+ className: "sidebar__header",
1548
+ children: [/* @__PURE__ */ jsx("span", {
1549
+ className: "sidebar__title",
1550
+ children: label
1551
+ }), /* @__PURE__ */ jsx("button", {
1552
+ type: "button",
1553
+ className: "sidebar__toggle",
1554
+ "aria-label": toggleLabel,
1555
+ "aria-expanded": visible,
1556
+ "aria-controls": navId,
1557
+ onClick: () => change(!visible),
1558
+ children: /* @__PURE__ */ jsx("span", {
1559
+ "aria-hidden": "true",
1560
+ children: visible ? "−" : "+"
1561
+ })
1562
+ })]
1563
+ }), /* @__PURE__ */ jsx("nav", {
1564
+ id: navId,
1565
+ "aria-label": label,
1566
+ hidden: !visible,
1567
+ children: /* @__PURE__ */ jsx("ul", { children: items.map((item) => /* @__PURE__ */ jsx("li", { children: item.isDisabled ? /* @__PURE__ */ jsx("span", {
1568
+ className: "sidebar__link",
1569
+ "aria-disabled": "true",
1570
+ children: item.label
1571
+ }) : /* @__PURE__ */ jsx("a", {
1572
+ className: "sidebar__link",
1573
+ href: item.href,
1574
+ "aria-current": item.id === currentId ? "page" : void 0,
1575
+ children: item.label
1576
+ }) }, item.id)) })
1577
+ })]
1578
+ });
1579
+ }
1580
+ //#endregion
1581
+ //#region src/chart-model.ts
1582
+ function chartModel(data) {
1583
+ const valid = data.filter((item) => Number.isFinite(item.value));
1584
+ const scale = valid.reduce((max, item) => Math.max(max, Math.abs(item.value)), 1);
1585
+ const min = valid.reduce((min, item) => Math.min(min, item.value / scale), 0);
1586
+ const span = valid.reduce((max, item) => Math.max(max, item.value / scale), 0) - min || 1, step = 560 / Math.max(1, valid.length);
1587
+ const y = (value) => 180 - (value / scale - min) / span * 160;
1588
+ return {
1589
+ items: valid.map((item, index) => ({
1590
+ ...item,
1591
+ x: 20 + step * (index + .5),
1592
+ y: y(item.value)
1593
+ })),
1594
+ baseline: y(0),
1595
+ barWidth: Math.min(40, step * .7)
1596
+ };
1597
+ }
1598
+ //#endregion
1599
+ //#region src/Chart.tsx
1600
+ function Chart({ label, data, type = "bar", description, locale = "id-ID", formatOptions, categoryLabel = "Kategori", valueLabel = "Nilai", emptyMessage = "Belum ada data grafik.", id, dir }) {
1601
+ const generated = useId(), labelId = `${id ?? generated}-label`, model = chartModel(data), format = new Intl.NumberFormat(locale, formatOptions);
1602
+ return /* @__PURE__ */ jsxs("figure", {
1603
+ id,
1604
+ className: "chart",
1605
+ dir,
1606
+ "aria-labelledby": labelId,
1607
+ children: [
1608
+ /* @__PURE__ */ jsx("figcaption", {
1609
+ id: labelId,
1610
+ className: "chart__title",
1611
+ children: label
1612
+ }),
1613
+ description && /* @__PURE__ */ jsx("p", {
1614
+ className: "chart__description",
1615
+ children: description
1616
+ }),
1617
+ model.items.length ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs("svg", {
1618
+ className: "chart__plot",
1619
+ viewBox: "0 0 600 210",
1620
+ "aria-hidden": "true",
1621
+ focusable: "false",
1622
+ children: [
1623
+ /* @__PURE__ */ jsx("line", {
1624
+ className: "chart__axis",
1625
+ x1: "20",
1626
+ x2: "580",
1627
+ y1: model.baseline,
1628
+ y2: model.baseline
1629
+ }),
1630
+ type === "line" ? /* @__PURE__ */ jsx("polyline", {
1631
+ className: "chart__line",
1632
+ points: model.items.map((item) => `${item.x},${item.y}`).join(" ")
1633
+ }) : null,
1634
+ model.items.map((item) => /* @__PURE__ */ jsxs("g", { children: [type === "bar" ? /* @__PURE__ */ jsx("rect", {
1635
+ className: "chart__bar",
1636
+ x: item.x - model.barWidth / 2,
1637
+ y: Math.min(item.y, model.baseline),
1638
+ width: model.barWidth,
1639
+ height: Math.abs(item.y - model.baseline)
1640
+ }) : /* @__PURE__ */ jsx("circle", {
1641
+ className: "chart__bar",
1642
+ cx: item.x,
1643
+ cy: item.y,
1644
+ r: "4"
1645
+ }), model.items.length <= 12 && /* @__PURE__ */ jsx("text", {
1646
+ className: "chart__label",
1647
+ x: item.x,
1648
+ y: "202",
1649
+ textAnchor: "middle",
1650
+ children: item.label.slice(0, 12)
1651
+ })] }, item.id))
1652
+ ]
1653
+ }), /* @__PURE__ */ jsxs(Table, {
1654
+ caption: label,
1655
+ children: [/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [/* @__PURE__ */ jsx("th", {
1656
+ scope: "col",
1657
+ children: categoryLabel
1658
+ }), /* @__PURE__ */ jsx("th", {
1659
+ scope: "col",
1660
+ children: valueLabel
1661
+ })] }) }), /* @__PURE__ */ jsx("tbody", { children: model.items.map((item) => /* @__PURE__ */ jsxs("tr", { children: [/* @__PURE__ */ jsx("th", {
1662
+ scope: "row",
1663
+ children: item.label
1664
+ }), /* @__PURE__ */ jsx("td", { children: format.format(item.value) })] }, item.id)) })]
1665
+ })] }) : /* @__PURE__ */ jsx(Empty, { title: emptyMessage })
1666
+ ]
1667
+ });
1668
+ }
1669
+ //#endregion
1670
+ //#region src/Dialog.tsx
1671
+ function Dialog(props) {
1672
+ const { triggerLabel, title, description, children, footer, isDisabled = false, closeLabel = "Tutup", dir, size = "md", placement = "center", scroll = "outside", backdrop = "opaque", isDismissable = true, isKeyboardDismissDisabled = false, showCloseButton = true, showFooterClose = true } = props;
1673
+ const { visible, change } = useDisclosure(props.open, props.defaultOpen ?? false, props.onOpenChange);
1674
+ const descriptionId = useId();
1675
+ return /* @__PURE__ */ jsx(OverlayDirection, {
1676
+ dir,
1677
+ children: /* @__PURE__ */ jsxs(DialogTrigger, {
1678
+ isOpen: visible,
1679
+ onOpenChange: change,
1680
+ children: [/* @__PURE__ */ jsx(Button$1, {
1681
+ className: `button button--${props.triggerVariant ?? "secondary"}${props.triggerIconOnly ? " button--icon-only" : ""}`,
1682
+ "aria-label": triggerLabel,
1683
+ isDisabled,
1684
+ children: props.triggerContent ?? triggerLabel
1685
+ }), /* @__PURE__ */ jsx(ModalOverlay, {
1686
+ className: "dialog__backdrop dialog__viewport",
1687
+ "data-size": size,
1688
+ "data-placement": placement,
1689
+ "data-scroll": scroll,
1690
+ "data-backdrop": backdrop,
1691
+ isDismissable,
1692
+ isKeyboardDismissDisabled,
1693
+ children: /* @__PURE__ */ jsx(Modal, {
1694
+ className: "dialog__panel",
1695
+ dir,
1696
+ children: /* @__PURE__ */ jsxs(Dialog$1, {
1697
+ className: "dialog__content",
1698
+ "aria-describedby": description ? descriptionId : void 0,
1699
+ children: [
1700
+ /* @__PURE__ */ jsxs("div", {
1701
+ className: "overlay__header",
1702
+ "data-close-button": showCloseButton || void 0,
1703
+ children: [
1704
+ /* @__PURE__ */ jsx(Heading, {
1705
+ level: 2,
1706
+ slot: "title",
1707
+ className: "overlay__title",
1708
+ children: title
1709
+ }),
1710
+ description && /* @__PURE__ */ jsx("p", {
1711
+ id: descriptionId,
1712
+ className: "overlay__description",
1713
+ children: description
1714
+ }),
1715
+ showCloseButton && /* @__PURE__ */ jsx(Button$1, {
1716
+ className: "dialog__close",
1717
+ "aria-label": props.closeIconLabel ?? `${closeLabel} dialog`,
1718
+ onPress: () => change(false),
1719
+ children: /* @__PURE__ */ jsx(CloseIcon, {})
1720
+ })
1721
+ ]
1722
+ }),
1723
+ /* @__PURE__ */ jsx("div", {
1724
+ className: "overlay__body",
1725
+ children
1726
+ }),
1727
+ (footer || showFooterClose) && /* @__PURE__ */ jsxs("div", {
1728
+ className: "overlay__footer",
1729
+ children: [footer, showFooterClose && /* @__PURE__ */ jsx(Button$1, {
1730
+ className: "button button--secondary",
1731
+ onPress: () => change(false),
1732
+ children: closeLabel
1733
+ })]
1734
+ })
1735
+ ]
1736
+ })
1737
+ })
1738
+ })]
1739
+ })
1740
+ });
1741
+ }
1742
+ //#endregion
1743
+ //#region src/overlay-model.ts
1744
+ function menuGroups(items) {
1745
+ const groups = [];
1746
+ for (const item of items) {
1747
+ const previous = groups.at(-1);
1748
+ if (!previous || previous.label !== item.section || item.separatorBefore) groups.push({
1749
+ key: item.id,
1750
+ label: item.section,
1751
+ items: [item]
1752
+ });
1753
+ else previous.items.push(item);
1754
+ }
1755
+ return groups;
1756
+ }
1757
+ function menuLeaves(items, disabled = false) {
1758
+ return items.flatMap((item) => item.children?.length ? menuLeaves(item.children, disabled || !!item.isDisabled) : [{
1759
+ ...item,
1760
+ isDisabled: disabled || item.isDisabled
1761
+ }]);
1762
+ }
1763
+ function menuSelection(keys, items, mode) {
1764
+ const wanted = new Set(keys);
1765
+ const result = menuLeaves(items).filter((item) => wanted.has(item.id)).map((item) => item.id);
1766
+ return mode === "none" ? [] : mode === "single" ? result.slice(0, 1) : result;
1767
+ }
1768
+ //#endregion
1769
+ //#region src/DropdownMenu.tsx
1770
+ function DropdownMenu(props) {
1771
+ const { triggerLabel, items, isDisabled = false, dir, selectionMode = "none", placement = "bottom-start" } = props;
1772
+ const { visible, change } = useDisclosure(props.open, props.defaultOpen ?? false, props.onOpenChange);
1773
+ const [local, setLocal] = useState(props.defaultSelectedKeys ?? []);
1774
+ const selected = menuSelection(props.selectedKeys ?? local, items, selectionMode);
1775
+ const [side, align] = placement.split("-");
1776
+ const popoverPlacement = `${side} ${side === "left" || side === "right" ? align === "start" ? "top" : "bottom" : align}`;
1777
+ const closeOnSelect = props.closeOnSelect ?? selectionMode !== "multiple";
1778
+ const leaves = menuLeaves(items, isDisabled);
1779
+ function action(id) {
1780
+ const item = leaves.find((item) => item.id === id);
1781
+ if (item && !item.isDisabled) props.onAction?.(id);
1782
+ }
1783
+ function select(keys, level) {
1784
+ if (isDisabled || selectionMode === "none") return;
1785
+ const levelIds = new Set(level.filter((item) => !item.children?.length).map((item) => item.id));
1786
+ const next = menuSelection(selectionMode === "multiple" ? [...selected.filter((id) => !levelIds.has(id)), ...keys] : keys, items, selectionMode);
1787
+ setLocal(next);
1788
+ props.onSelectionChange?.(next);
1789
+ }
1790
+ function content(item) {
1791
+ const icon = props.renderIcon?.(item);
1792
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [
1793
+ selectionMode !== "none" && !item.children?.length && /* @__PURE__ */ jsx(CheckIcon, { className: "menu__check" }),
1794
+ icon && /* @__PURE__ */ jsx("span", {
1795
+ className: "menu__icon",
1796
+ "aria-hidden": "true",
1797
+ children: icon
1798
+ }),
1799
+ /* @__PURE__ */ jsxs("span", {
1800
+ className: "menu__text",
1801
+ children: [/* @__PURE__ */ jsx("span", { children: item.label }), item.description && /* @__PURE__ */ jsx("span", {
1802
+ className: "menu__description",
1803
+ children: item.description
1804
+ })]
1805
+ }),
1806
+ item.shortcut && /* @__PURE__ */ jsx("kbd", {
1807
+ className: "menu__shortcut",
1808
+ "aria-hidden": "true",
1809
+ children: item.shortcut
1810
+ }),
1811
+ !!item.children?.length && /* @__PURE__ */ jsx(ChevronIcon, { className: "menu__arrow" })
1812
+ ] });
1813
+ }
1814
+ function renderMenu(level, label, blocked = false) {
1815
+ return /* @__PURE__ */ jsx(Menu, {
1816
+ className: "menu__list",
1817
+ "aria-label": label,
1818
+ selectionMode,
1819
+ selectedKeys: selected,
1820
+ onSelectionChange: (keys) => select(keys === "all" ? level.filter((i) => !i.isDisabled && !i.children?.length).map((i) => i.id) : Array.from(keys, String), level),
1821
+ disallowEmptySelection: selectionMode === "single",
1822
+ shouldCloseOnSelect: closeOnSelect,
1823
+ onAction: (key) => action(String(key)),
1824
+ children: menuGroups(level).flatMap((group, index) => {
1825
+ const rows = group.items.map((item) => {
1826
+ const disabled = isDisabled || blocked || !!item.isDisabled;
1827
+ const row = /* @__PURE__ */ jsx(MenuItem, {
1828
+ id: item.id,
1829
+ textValue: item.label,
1830
+ className: "menu__item",
1831
+ isDisabled: disabled,
1832
+ "data-tone": item.tone ?? "default",
1833
+ shouldCloseOnSelect: closeOnSelect,
1834
+ children: content(item)
1835
+ }, item.id);
1836
+ return item.children?.length ? /* @__PURE__ */ jsxs(SubmenuTrigger, { children: [row, /* @__PURE__ */ jsx(Popover$2, {
1837
+ className: "menu__panel",
1838
+ offset: 4,
1839
+ containerPadding: 16,
1840
+ dir,
1841
+ children: renderMenu(item.children, item.label, disabled)
1842
+ })] }, item.id) : row;
1843
+ });
1844
+ return [index > 0 ? /* @__PURE__ */ jsx(Separator$1, { className: "menu__separator" }, `${group.key}-separator`) : null, /* @__PURE__ */ jsxs(MenuSection, {
1845
+ "aria-label": group.label,
1846
+ children: [group.label && /* @__PURE__ */ jsx(Header, {
1847
+ className: "menu__heading",
1848
+ children: group.label
1849
+ }), rows]
1850
+ }, group.key)];
1851
+ })
1852
+ });
1853
+ }
1854
+ return /* @__PURE__ */ jsx(OverlayDirection, {
1855
+ dir,
1856
+ children: /* @__PURE__ */ jsxs(MenuTrigger, {
1857
+ isOpen: visible,
1858
+ onOpenChange: change,
1859
+ children: [/* @__PURE__ */ jsx(Button$1, {
1860
+ className: `button button--${props.triggerVariant ?? "secondary"}${props.triggerIconOnly ? " button--icon-only" : ""}`,
1861
+ "aria-label": triggerLabel,
1862
+ isDisabled: isDisabled || !items.length,
1863
+ children: props.triggerContent ?? triggerLabel
1864
+ }), /* @__PURE__ */ jsx(Popover$2, {
1865
+ className: "menu__panel",
1866
+ placement: popoverPlacement,
1867
+ offset: 8,
1868
+ containerPadding: 16,
1869
+ dir,
1870
+ children: renderMenu(items, triggerLabel)
1871
+ })]
1872
+ })
1873
+ });
1874
+ }
1875
+ //#endregion
1876
+ //#region src/Popover.tsx
1877
+ function Popover({ triggerLabel, title, description, children, open, defaultOpen = false, onOpenChange, isDisabled = false, closeLabel = "Tutup", dir }) {
1878
+ const { visible, change } = useDisclosure(open, defaultOpen, onOpenChange), descriptionId = useId();
1879
+ return /* @__PURE__ */ jsx(OverlayDirection, {
1880
+ dir,
1881
+ children: /* @__PURE__ */ jsxs(DialogTrigger, {
1882
+ isOpen: visible,
1883
+ onOpenChange: change,
1884
+ children: [/* @__PURE__ */ jsx(Button$1, {
1885
+ className: "button button--secondary",
1886
+ isDisabled,
1887
+ children: triggerLabel
1888
+ }), /* @__PURE__ */ jsx(Popover$2, {
1889
+ className: "popover__panel",
1890
+ isNonModal: true,
1891
+ placement: "bottom start",
1892
+ offset: 8,
1893
+ containerPadding: 16,
1894
+ dir,
1895
+ children: /* @__PURE__ */ jsxs(Dialog$1, {
1896
+ className: "popover__content",
1897
+ "aria-describedby": description ? descriptionId : void 0,
1898
+ children: [
1899
+ /* @__PURE__ */ jsx(Heading, {
1900
+ level: 2,
1901
+ slot: "title",
1902
+ className: "overlay__title",
1903
+ children: title
1904
+ }),
1905
+ description && /* @__PURE__ */ jsx("p", {
1906
+ id: descriptionId,
1907
+ className: "overlay__description",
1908
+ children: description
1909
+ }),
1910
+ /* @__PURE__ */ jsx("div", {
1911
+ className: "overlay__body",
1912
+ children
1913
+ }),
1914
+ /* @__PURE__ */ jsx("div", {
1915
+ className: "overlay__footer",
1916
+ children: /* @__PURE__ */ jsx(Button$1, {
1917
+ className: "button button--secondary",
1918
+ onPress: () => change(false),
1919
+ children: closeLabel
1920
+ })
1921
+ })
1922
+ ]
1923
+ })
1924
+ })]
1925
+ })
1926
+ });
1927
+ }
1928
+ //#endregion
1929
+ //#region src/Tooltip.tsx
1930
+ function Tooltip({ triggerLabel, text, triggerContent, triggerIconOnly = false, triggerVariant = "secondary", triggerSize = "md", open, defaultOpen = false, onOpenChange, isDisabled = false, dir }) {
1931
+ const { visible, change } = useDisclosure(open, defaultOpen, onOpenChange);
1932
+ return /* @__PURE__ */ jsx(OverlayDirection, {
1933
+ dir,
1934
+ children: /* @__PURE__ */ jsxs(TooltipTrigger, {
1935
+ isOpen: visible,
1936
+ onOpenChange: change,
1937
+ delay: 300,
1938
+ closeDelay: 0,
1939
+ isDisabled,
1940
+ children: [/* @__PURE__ */ jsx(Button$1, {
1941
+ className: [
1942
+ "button",
1943
+ `button--${triggerVariant}`,
1944
+ triggerSize !== "md" && `button--${triggerSize}`,
1945
+ triggerIconOnly && "button--icon-only"
1946
+ ].filter(Boolean).join(" "),
1947
+ "aria-label": triggerLabel,
1948
+ isDisabled,
1949
+ children: triggerContent ?? triggerLabel
1950
+ }), /* @__PURE__ */ jsx(Tooltip$1, {
1951
+ className: "tooltip__panel",
1952
+ placement: "top",
1953
+ offset: 8,
1954
+ containerPadding: 16,
1955
+ dir,
1956
+ children: text
1957
+ })]
1958
+ })
1959
+ });
1960
+ }
1961
+ //#endregion
1962
+ //#region src/Spinner.tsx
1963
+ /** Decorative by default. Use label for a standalone loading status; omit it inside a labeled Button. */
1964
+ function Spinner({ size = "md", color = "current", label, id }) {
1965
+ return /* @__PURE__ */ jsxs("span", {
1966
+ id,
1967
+ className: `spinner spinner--${size}`,
1968
+ "data-color": color,
1969
+ role: label ? "status" : void 0,
1970
+ "aria-label": label || void 0,
1971
+ "aria-hidden": !label || void 0,
1972
+ children: [/* @__PURE__ */ jsxs("svg", {
1973
+ viewBox: "0 0 20 20",
1974
+ fill: "none",
1975
+ "aria-hidden": "true",
1976
+ focusable: "false",
1977
+ children: [/* @__PURE__ */ jsx("circle", {
1978
+ className: "spinner__track",
1979
+ cx: "10",
1980
+ cy: "10",
1981
+ r: "8"
1982
+ }), /* @__PURE__ */ jsx("circle", {
1983
+ className: "spinner__arc",
1984
+ cx: "10",
1985
+ cy: "10",
1986
+ r: "8",
1987
+ pathLength: "100",
1988
+ strokeDasharray: "36 64"
1989
+ })]
1990
+ }), label && /* @__PURE__ */ jsx("span", {
1991
+ className: "spinner__label",
1992
+ children: label
1993
+ })]
1994
+ });
1995
+ }
1996
+ //#endregion
1997
+ //#region src/Combobox.tsx
1998
+ /** Searchable single selection. Draft text is never submitted as a value. */
1999
+ function Combobox(props) {
2000
+ const [local, setLocal] = useState(props.defaultValue ?? null);
2001
+ const [draft, setDraft] = useState(null);
2002
+ const [tried, setTried] = useState(false);
2003
+ const resetting = useRef(false);
2004
+ const input = useRef(null);
2005
+ const id = selectionIds(props.value !== void 0 ? props.value : local, props.options, false)[0] ?? null;
2006
+ const selected = props.options.find((o) => o.id === id);
2007
+ const [previous, setPrevious] = useState(selected);
2008
+ if (previous !== selected) {
2009
+ setPrevious(selected);
2010
+ setDraft(null);
2011
+ }
2012
+ const text = draft ?? selected?.label ?? "";
2013
+ const invalid = props.isInvalid || tried && props.isRequired && !id;
2014
+ const { describedBy, feedback } = useFeedback({
2015
+ description: props.description,
2016
+ isInvalid: invalid,
2017
+ errorMessage: props.errorMessage ?? (props.isRequired && !id ? props.requiredMessage ?? "Pilihan wajib diisi." : void 0)
2018
+ });
2019
+ function change(value) {
2020
+ if (props.isDisabled || resetting.current) return;
2021
+ const next = selectionIds(value, props.options, false)[0] ?? null;
2022
+ setLocal(next);
2023
+ props.onChange?.(next);
2024
+ setDraft(null);
2025
+ }
2026
+ const content = /* @__PURE__ */ jsxs(ComboBox, {
2027
+ className: "select combobox",
2028
+ value: id,
2029
+ onChange: change,
2030
+ inputValue: text,
2031
+ onInputChange: (text) => {
2032
+ if (resetting.current) return;
2033
+ setDraft(text);
2034
+ if (text === "" && id) {
2035
+ setLocal(null);
2036
+ props.onChange?.(null);
2037
+ }
2038
+ },
2039
+ defaultItems: props.options,
2040
+ defaultFilter: (label, query) => filterOptions(props.options, query).some((option) => option.label === label),
2041
+ allowsEmptyCollection: true,
2042
+ allowsCustomValue: false,
2043
+ isDisabled: props.isDisabled,
2044
+ isRequired: props.isRequired,
2045
+ isInvalid: !!invalid,
2046
+ validationBehavior: "aria",
2047
+ children: [
2048
+ /* @__PURE__ */ jsxs(Label$6, {
2049
+ className: "select__label",
2050
+ children: [props.label, props.isRequired && /* @__PURE__ */ jsxs("span", {
2051
+ className: "selection__required",
2052
+ "aria-hidden": "true",
2053
+ children: [" ", "*"]
2054
+ })]
2055
+ }),
2056
+ /* @__PURE__ */ jsxs("div", {
2057
+ className: "combobox__control",
2058
+ "data-invalid": invalid || void 0,
2059
+ "data-disabled": props.isDisabled || void 0,
2060
+ children: [
2061
+ props.startContent && /* @__PURE__ */ jsx("span", {
2062
+ className: "selection__leading",
2063
+ "aria-hidden": "true",
2064
+ children: props.startContent
2065
+ }),
2066
+ /* @__PURE__ */ jsx(Input$3, {
2067
+ ref: input,
2068
+ className: "combobox__input",
2069
+ placeholder: props.placeholder,
2070
+ "aria-describedby": describedBy
2071
+ }),
2072
+ props.isClearable && /* @__PURE__ */ jsx("button", {
2073
+ type: "button",
2074
+ className: "combobox__clear",
2075
+ "data-empty": !id && !text || void 0,
2076
+ "aria-hidden": !id && !text || void 0,
2077
+ tabIndex: !id && !text ? -1 : void 0,
2078
+ disabled: props.isDisabled || !id && !text,
2079
+ "aria-label": props.clearLabel ?? "Hapus pilihan",
2080
+ onClick: () => {
2081
+ change(null);
2082
+ input.current?.focus();
2083
+ },
2084
+ children: /* @__PURE__ */ jsx(CloseIcon, { className: "selection__close-icon" })
2085
+ }),
2086
+ /* @__PURE__ */ jsx(Button$4, {
2087
+ className: "combobox__toggle",
2088
+ "aria-label": props.toggleLabel ?? "Buka pilihan",
2089
+ children: /* @__PURE__ */ jsx(ChevronIcon, { className: "select__icon" })
2090
+ })
2091
+ ]
2092
+ }),
2093
+ /* @__PURE__ */ jsx(Popover$3, {
2094
+ className: "select__popover combobox__popover",
2095
+ children: /* @__PURE__ */ jsx(ListBox$2, {
2096
+ className: "select__list",
2097
+ renderEmptyState: () => /* @__PURE__ */ jsx("span", {
2098
+ className: "selection__empty",
2099
+ children: props.emptyMessage ?? "Tidak ada pilihan."
2100
+ }),
2101
+ children: (option) => /* @__PURE__ */ jsxs(ListBoxItem$2, {
2102
+ id: option.id,
2103
+ textValue: option.label,
2104
+ isDisabled: option.isDisabled,
2105
+ className: "select__item",
2106
+ children: [/* @__PURE__ */ jsx("span", {
2107
+ className: "select__item-label",
2108
+ children: props.renderOption?.(option) ?? /* @__PURE__ */ jsxs(Fragment$1, { children: [option.label, option.description && /* @__PURE__ */ jsx("span", {
2109
+ className: "selection__description",
2110
+ children: option.description
2111
+ })] })
2112
+ }), /* @__PURE__ */ jsx(CheckIcon, { className: "select__check" })]
2113
+ })
2114
+ })
2115
+ }),
2116
+ feedback,
2117
+ props.name && /* @__PURE__ */ jsx("input", {
2118
+ type: "hidden",
2119
+ name: props.name,
2120
+ value: id ?? "",
2121
+ disabled: props.isDisabled
2122
+ }),
2123
+ /* @__PURE__ */ jsx(SelectionValidation, {
2124
+ hasValue: !!id,
2125
+ required: props.isRequired,
2126
+ disabled: props.isDisabled,
2127
+ onInvalid: () => {
2128
+ setTried(true);
2129
+ input.current?.focus();
2130
+ },
2131
+ onResetStart: () => {
2132
+ resetting.current = true;
2133
+ },
2134
+ onReset: (cancelled) => {
2135
+ resetting.current = false;
2136
+ if (!cancelled) {
2137
+ setTried(false);
2138
+ setDraft(null);
2139
+ if (props.value === void 0) setLocal(props.defaultValue ?? null);
2140
+ }
2141
+ }
2142
+ })
2143
+ ]
2144
+ });
2145
+ return props.dir ? /* @__PURE__ */ jsx(I18nProvider, {
2146
+ locale: props.dir === "rtl" ? "ar-EG" : "en-US",
2147
+ children: content
2148
+ }) : content;
2149
+ }
2150
+ //#endregion
2151
+ //#region src/toggle-group-model.ts
2152
+ /** Normalize IDs without discarding existing disabled selections. */
2153
+ function toggleIds(value, items, multiple) {
2154
+ const wanted = new Set(Array.isArray(value) ? value : typeof value === "string" ? [value] : []);
2155
+ const result = [...new Set(items.filter((item) => item.id !== "" && wanted.has(item.id)).map((item) => item.id))];
2156
+ return multiple ? result : result.slice(0, 1);
2157
+ }
2158
+ //#endregion
2159
+ //#region src/ToggleGroup.tsx
2160
+ function ToggleGroup(props) {
2161
+ const multiple = props.selectionMode === "multiple";
2162
+ const [local, setLocal] = useState(props.defaultValue);
2163
+ const ids = toggleIds(props.value !== void 0 ? props.value : local, props.items, multiple);
2164
+ function update(keys) {
2165
+ if (props.isDisabled) return;
2166
+ const requested = new Set(Array.from(keys, String));
2167
+ for (const item of props.items.filter((item) => item.isDisabled)) if (multiple && ids.includes(item.id)) requested.add(item.id);
2168
+ else if (!ids.includes(item.id)) requested.delete(item.id);
2169
+ const next = toggleIds([...requested], props.items, multiple);
2170
+ if (next.length === ids.length && next.every((id, index) => id === ids[index])) return;
2171
+ if (props.disallowEmptySelection && ids.length && !next.length) return;
2172
+ const value = multiple ? next : next[0] ?? null;
2173
+ setLocal(value);
2174
+ if (props.selectionMode === "multiple") props.onChange?.(next);
2175
+ else props.onChange?.(next[0] ?? null);
2176
+ }
2177
+ return /* @__PURE__ */ jsx(OverlayDirection, {
2178
+ dir: props.dir,
2179
+ children: /* @__PURE__ */ jsx(ToggleButtonGroup$1, {
2180
+ className: "toggle-group",
2181
+ "aria-label": props.label,
2182
+ dir: props.dir,
2183
+ selectionMode: multiple ? "multiple" : "single",
2184
+ selectedKeys: ids,
2185
+ onSelectionChange: update,
2186
+ disallowEmptySelection: props.disallowEmptySelection,
2187
+ isDisabled: props.isDisabled,
2188
+ orientation: props.orientation ?? "horizontal",
2189
+ "data-variant": props.variant ?? "outline",
2190
+ "data-size": props.size ?? "md",
2191
+ "data-icon-only": props.isIconOnly || void 0,
2192
+ children: props.items.map((item) => /* @__PURE__ */ jsxs(ToggleButton$1, {
2193
+ id: item.id,
2194
+ className: "toggle-group__item",
2195
+ "aria-label": item.label,
2196
+ isDisabled: props.isDisabled || item.isDisabled,
2197
+ children: [props.renderIcon && /* @__PURE__ */ jsx("span", {
2198
+ className: "toggle-group__icon",
2199
+ "aria-hidden": "true",
2200
+ children: props.renderIcon(item)
2201
+ }), !props.isIconOnly && /* @__PURE__ */ jsx("span", { children: item.label })]
2202
+ }, item.id))
2203
+ })
2204
+ });
2205
+ }
2206
+ //#endregion
2207
+ //#region src/date-range-model.ts
2208
+ function dateRangeLabels(locale = "id-ID") {
2209
+ return locale.startsWith("id") ? {
2210
+ title: "Pilih rentang tanggal",
2211
+ start: "Tanggal mulai",
2212
+ end: "Tanggal akhir",
2213
+ apply: "Terapkan",
2214
+ cancel: "Batal",
2215
+ clear: "Kosongkan",
2216
+ previousMonth: "Bulan sebelumnya",
2217
+ nextMonth: "Bulan berikutnya",
2218
+ presets: "Pilihan cepat",
2219
+ placeholder: "Pilih tanggal",
2220
+ incomplete: "Lengkapi tanggal mulai dan akhir.",
2221
+ order: "Tanggal akhir harus setelah atau sama dengan tanggal mulai.",
2222
+ bounds: "Tanggal berada di luar batas yang diizinkan.",
2223
+ unavailable: "Rentang memuat tanggal yang tidak tersedia.",
2224
+ length: "Durasi rentang tidak sesuai batas yang diizinkan.",
2225
+ required: "Rentang tanggal wajib diisi."
2226
+ } : {
2227
+ title: "Select date range",
2228
+ start: "Start date",
2229
+ end: "End date",
2230
+ apply: "Apply",
2231
+ cancel: "Cancel",
2232
+ clear: "Clear",
2233
+ previousMonth: "Previous month",
2234
+ nextMonth: "Next month",
2235
+ presets: "Quick selections",
2236
+ placeholder: "Choose dates",
2237
+ incomplete: "Enter both start and end dates.",
2238
+ order: "End date must be on or after start date.",
2239
+ bounds: "Dates are outside the allowed limits.",
2240
+ unavailable: "The range includes an unavailable date.",
2241
+ length: "The range duration is outside the allowed limits.",
2242
+ required: "A date range is required."
2243
+ };
2244
+ }
2245
+ function validDate(value) {
2246
+ if (!/^(?!0000)\d{4}-\d{2}-\d{2}$/.test(value)) return false;
2247
+ try {
2248
+ return parseDate(value).toString() === value;
2249
+ } catch {
2250
+ return false;
2251
+ }
2252
+ }
2253
+ function asDate(value) {
2254
+ return value && validDate(value) ? parseDate(value) : void 0;
2255
+ }
2256
+ function currentDate() {
2257
+ return today(getLocalTimeZone()).toString();
2258
+ }
2259
+ function rangeError(value, constraints = {}) {
2260
+ if (!value) return null;
2261
+ if (!validDate(value.start) || !validDate(value.end)) return "incomplete";
2262
+ if (value.end < value.start) return "order";
2263
+ if (constraints.minDate && value.start < constraints.minDate || constraints.maxDate && value.end > constraints.maxDate) return "bounds";
2264
+ const start = parseDate(value.start), end = parseDate(value.end);
2265
+ const days = end.calendar.toJulianDay(end) - start.calendar.toJulianDay(start) + 1;
2266
+ if (constraints.minDays && days < constraints.minDays || constraints.maxDays && days > constraints.maxDays) return "length";
2267
+ if (constraints.isDateUnavailable) for (let day = start; day.compare(end) <= 0; day = day.add({ days: 1 })) {
2268
+ if (constraints.isDateUnavailable(day.toString())) return "unavailable";
2269
+ if (day.compare(end) === 0) break;
2270
+ }
2271
+ return null;
2272
+ }
2273
+ function rangeText(value, locale = "id-ID") {
2274
+ if (!value || !validDate(value.start) || !validDate(value.end)) return "";
2275
+ const formatter = new Intl.DateTimeFormat(locale, {
2276
+ day: "numeric",
2277
+ month: "short",
2278
+ year: "numeric",
2279
+ timeZone: "UTC",
2280
+ calendar: "gregory"
2281
+ });
2282
+ const date = (s) => parseDate(s).toDate("UTC");
2283
+ return value.start === value.end ? formatter.format(date(value.start)) : `${formatter.format(date(value.start))} – ${formatter.format(date(value.end))}`;
2284
+ }
2285
+ function createDateRangePresets(referenceDate = currentDate(), locale = "id-ID", weekStartsOn = 1) {
2286
+ const day = parseDate(referenceDate), week = startOfWeek(day, locale, weekStartsOn === 1 ? "mon" : "sun");
2287
+ const id = locale.startsWith("id");
2288
+ return [
2289
+ {
2290
+ id: "this-week",
2291
+ label: id ? "Minggu ini" : "This Week",
2292
+ start: week,
2293
+ end: week.add({ days: 6 })
2294
+ },
2295
+ {
2296
+ id: "last-week",
2297
+ label: id ? "Minggu lalu" : "Last Week",
2298
+ start: week.subtract({ days: 7 }),
2299
+ end: week.subtract({ days: 1 })
2300
+ },
2301
+ {
2302
+ id: "last-7-days",
2303
+ label: id ? "7 hari terakhir" : "Last 7 Days",
2304
+ start: day.subtract({ days: 6 }),
2305
+ end: day
2306
+ },
2307
+ {
2308
+ id: "last-30-days",
2309
+ label: id ? "30 hari terakhir" : "Last 30 Days",
2310
+ start: day.subtract({ days: 29 }),
2311
+ end: day
2312
+ },
2313
+ {
2314
+ id: "this-month",
2315
+ label: id ? "Bulan ini" : "Current Month",
2316
+ start: startOfMonth(day),
2317
+ end: endOfMonth(day)
2318
+ },
2319
+ {
2320
+ id: "next-month",
2321
+ label: id ? "Bulan depan" : "Next Month",
2322
+ start: startOfMonth(day.add({ months: 1 })),
2323
+ end: endOfMonth(day.add({ months: 1 }))
2324
+ }
2325
+ ].map(({ id, label, start, end }) => ({
2326
+ id,
2327
+ label,
2328
+ value: {
2329
+ start: start.toString(),
2330
+ end: end.toString()
2331
+ }
2332
+ }));
2333
+ }
2334
+ //#endregion
2335
+ //#region src/DateRangePicker.tsx
2336
+ var empty = () => ({
2337
+ start: "",
2338
+ end: ""
2339
+ });
2340
+ function CalendarContent({ onPending, dir, children }) {
2341
+ const state = useContext(RangeCalendarStateContext);
2342
+ const { direction } = useLocale();
2343
+ const pending = !!state?.anchorDate;
2344
+ useEffect(() => onPending(pending), [pending, onPending]);
2345
+ return /* @__PURE__ */ jsx("div", {
2346
+ onKeyDownCapture: (event) => {
2347
+ if (!state || !dir || dir === direction || event.altKey || event.ctrlKey || event.metaKey || event.shiftKey || !["ArrowLeft", "ArrowRight"].includes(event.key) || !event.target.closest(".date-range__day")) return;
2348
+ event.preventDefault();
2349
+ event.stopPropagation();
2350
+ if (event.key === "ArrowRight" === (dir === "rtl")) state.focusPreviousDay();
2351
+ else state.focusNextDay();
2352
+ },
2353
+ children
2354
+ });
2355
+ }
2356
+ function DateRangePicker(props) {
2357
+ 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;
2358
+ const labels = {
2359
+ ...dateRangeLabels(locale),
2360
+ ...props.labels
2361
+ };
2362
+ const [local, setLocal] = useState(props.defaultValue ?? null);
2363
+ const committed = props.value !== void 0 ? props.value : local;
2364
+ const start = committed?.start ?? "", end = committed?.end ?? "";
2365
+ const [draft, setDraft] = useState({
2366
+ start,
2367
+ end
2368
+ });
2369
+ const initialFocus = () => {
2370
+ const date = asDate(start) ?? asDate(props.referenceDate) ?? asDate(currentDate());
2371
+ const min = asDate(props.minDate), max = asDate(props.maxDate);
2372
+ return min && date.compare(min) < 0 ? min : max && date.compare(max) > 0 ? max : date;
2373
+ };
2374
+ const [focused, setFocused] = useState(initialFocus);
2375
+ const [formError, setFormError] = useState(false);
2376
+ const [pending, setPending] = useState(false), [calendarKey, setCalendarKey] = useState(0);
2377
+ const trigger = useRef(null);
2378
+ const id = useId();
2379
+ const disclosure = useDisclosure(props.open, props.defaultOpen, props.onOpenChange);
2380
+ const visible = disclosure.visible && !isDisabled;
2381
+ useEffect(() => setDraft({
2382
+ start,
2383
+ end
2384
+ }), [start, end]);
2385
+ function replaceDraft(next) {
2386
+ setDraft(next);
2387
+ setPending(false);
2388
+ setCalendarKey((k) => k + 1);
2389
+ }
2390
+ function resetDraft() {
2391
+ replaceDraft({
2392
+ start,
2393
+ end
2394
+ });
2395
+ setFocused(initialFocus());
2396
+ }
2397
+ function changeOpen(next) {
2398
+ if (isDisabled && next) return;
2399
+ resetDraft();
2400
+ disclosure.change(next);
2401
+ }
2402
+ const nullableDraft = draft.start || draft.end ? draft : null;
2403
+ const errorCode = pending ? "incomplete" : rangeError(nullableDraft, props) ?? (isRequired && !nullableDraft ? "required" : null);
2404
+ const error = errorCode ? labels[errorCode] : void 0;
2405
+ const committedError = rangeError(committed, props);
2406
+ const outerError = props.isInvalid || committedError || formError;
2407
+ const matchingPreset = presets.find((p) => p.value.start === start && p.value.end === end);
2408
+ const text = committed ? props.formatRange?.(committed, locale) ?? matchingPreset?.label ?? rangeText(committed, locale) : labels.placeholder;
2409
+ const feedbackId = outerError ? `${id}-error` : props.description ? `${id}-description` : void 0;
2410
+ function apply() {
2411
+ if (isDisabled || isReadOnly || errorCode) return;
2412
+ const next = nullableDraft ? { ...nullableDraft } : null;
2413
+ setLocal(next);
2414
+ setFormError(false);
2415
+ props.onChange?.(next);
2416
+ props.onApply?.(next);
2417
+ disclosure.change(false);
2418
+ }
2419
+ function edit(part, value) {
2420
+ if (isDisabled || isReadOnly) return;
2421
+ replaceDraft({
2422
+ ...draft,
2423
+ [part]: value
2424
+ });
2425
+ if (asDate(value)) setFocused(asDate(value));
2426
+ }
2427
+ const calendarValue = asDate(draft.start) && asDate(draft.end) && draft.start <= draft.end ? {
2428
+ start: asDate(draft.start),
2429
+ end: asDate(draft.end)
2430
+ } : null;
2431
+ const panel = /* @__PURE__ */ jsxs("div", {
2432
+ className: "date-range__content",
2433
+ "data-readonly": isReadOnly || void 0,
2434
+ children: [
2435
+ /* @__PURE__ */ jsxs("header", {
2436
+ className: "date-range__intro",
2437
+ children: [/* @__PURE__ */ jsx("h2", {
2438
+ id: `${id}-title`,
2439
+ children: labels.title
2440
+ }), /* @__PURE__ */ jsx("p", {
2441
+ className: "date-range__summary",
2442
+ "aria-live": "polite",
2443
+ children: pending ? labels.incomplete : rangeText(nullableDraft, locale) || labels.incomplete
2444
+ })]
2445
+ }),
2446
+ /* @__PURE__ */ jsxs("div", {
2447
+ className: "date-range__body",
2448
+ children: [presets.length > 0 && /* @__PURE__ */ jsx("div", {
2449
+ className: "date-range__presets",
2450
+ role: "group",
2451
+ "aria-label": labels.presets,
2452
+ children: presets.map((p) => /* @__PURE__ */ jsx("button", {
2453
+ type: "button",
2454
+ className: "date-range__preset",
2455
+ disabled: isDisabled || isReadOnly || !!rangeError(p.value, props),
2456
+ "aria-pressed": !pending && draft.start === p.value.start && draft.end === p.value.end,
2457
+ onClick: () => {
2458
+ replaceDraft({ ...p.value });
2459
+ setFocused(asDate(p.value.start));
2460
+ },
2461
+ children: p.label
2462
+ }, p.id))
2463
+ }), /* @__PURE__ */ jsxs("div", {
2464
+ className: "date-range__main",
2465
+ children: [
2466
+ showInputs && /* @__PURE__ */ jsx("div", {
2467
+ className: "date-range__inputs",
2468
+ children: ["start", "end"].map((part) => /* @__PURE__ */ jsxs("label", {
2469
+ className: "date-range__field",
2470
+ children: [/* @__PURE__ */ jsx("span", { children: labels[part] }), /* @__PURE__ */ jsx("input", {
2471
+ type: "date",
2472
+ form: "",
2473
+ value: draft[part],
2474
+ min: props.minDate,
2475
+ max: props.maxDate,
2476
+ disabled: isDisabled,
2477
+ readOnly: isReadOnly,
2478
+ "aria-invalid": !!errorCode,
2479
+ "aria-describedby": error ? `${id}-draft-error` : void 0,
2480
+ onChange: (e) => edit(part, e.target.value)
2481
+ })]
2482
+ }, part))
2483
+ }),
2484
+ props.showMonthYearPicker && /* @__PURE__ */ jsxs("div", {
2485
+ className: "date-range__jump",
2486
+ children: [/* @__PURE__ */ jsxs("label", { children: [/* @__PURE__ */ jsx("span", { children: locale.startsWith("id") ? "Bulan" : "Month" }), /* @__PURE__ */ jsx("select", {
2487
+ form: "",
2488
+ disabled: isDisabled,
2489
+ "aria-label": locale.startsWith("id") ? "Bulan" : "Month",
2490
+ value: focused.month,
2491
+ onChange: (e) => setFocused(focused.set({ month: Number(e.target.value) })),
2492
+ children: Array.from({ length: 12 }, (_, i) => /* @__PURE__ */ jsx("option", {
2493
+ value: i + 1,
2494
+ children: new Intl.DateTimeFormat(locale, {
2495
+ month: "long",
2496
+ timeZone: "UTC",
2497
+ calendar: "gregory"
2498
+ }).format(focused.set({
2499
+ month: i + 1,
2500
+ day: 1
2501
+ }).toDate("UTC"))
2502
+ }, i))
2503
+ })] }), /* @__PURE__ */ jsxs("label", { children: [/* @__PURE__ */ jsx("span", { children: locale.startsWith("id") ? "Tahun" : "Year" }), /* @__PURE__ */ jsx("input", {
2504
+ type: "number",
2505
+ form: "",
2506
+ disabled: isDisabled,
2507
+ min: asDate(props.minDate)?.year ?? 1,
2508
+ max: asDate(props.maxDate)?.year ?? 9999,
2509
+ defaultValue: focused.year,
2510
+ onBlur: (e) => {
2511
+ const year = Number(e.target.value);
2512
+ if (Number.isInteger(year) && year >= 1 && year <= 9999) setFocused(focused.set({ year }));
2513
+ else e.target.value = String(focused.year);
2514
+ }
2515
+ }, focused.year)] })]
2516
+ }),
2517
+ /* @__PURE__ */ jsx(RangeCalendar, {
2518
+ dir,
2519
+ className: "date-range__calendar",
2520
+ "aria-label": labels.title,
2521
+ value: calendarValue,
2522
+ focusedValue: focused,
2523
+ onFocusChange: setFocused,
2524
+ createCalendar: () => new GregorianCalendar(),
2525
+ onChange: (v) => {
2526
+ if (v) setDraft({
2527
+ start: v.start.toString(),
2528
+ end: v.end.toString()
2529
+ });
2530
+ },
2531
+ visibleDuration: { months: visibleMonths },
2532
+ firstDayOfWeek: weekStartsOn === 1 ? "mon" : "sun",
2533
+ pageBehavior: "single",
2534
+ minValue: asDate(props.minDate),
2535
+ maxValue: asDate(props.maxDate),
2536
+ isDisabled,
2537
+ isReadOnly,
2538
+ isDateUnavailable: props.isDateUnavailable ? (d) => props.isDateUnavailable(d.toString()) : void 0,
2539
+ children: /* @__PURE__ */ jsxs(CalendarContent, {
2540
+ onPending: setPending,
2541
+ dir,
2542
+ children: [/* @__PURE__ */ jsxs("div", {
2543
+ className: "date-range__navigation",
2544
+ children: [/* @__PURE__ */ jsx(Button$1, {
2545
+ slot: "previous",
2546
+ className: "date-range__nav date-range__nav--previous",
2547
+ "aria-label": labels.previousMonth,
2548
+ children: /* @__PURE__ */ jsx(ChevronIcon, {})
2549
+ }), /* @__PURE__ */ jsx(Button$1, {
2550
+ slot: "next",
2551
+ className: "date-range__nav date-range__nav--next",
2552
+ "aria-label": labels.nextMonth,
2553
+ children: /* @__PURE__ */ jsx(ChevronIcon, {})
2554
+ })]
2555
+ }), /* @__PURE__ */ jsx("div", {
2556
+ className: "date-range__months",
2557
+ children: Array.from({ length: visibleMonths }, (_, i) => /* @__PURE__ */ jsxs("div", {
2558
+ className: "date-range__month",
2559
+ children: [/* @__PURE__ */ jsx(CalendarHeading, {
2560
+ offset: { months: i },
2561
+ className: "date-range__heading"
2562
+ }), /* @__PURE__ */ jsxs(CalendarGrid, {
2563
+ offset: { months: i },
2564
+ className: "date-range__grid",
2565
+ weekdayStyle: "short",
2566
+ children: [/* @__PURE__ */ jsx(CalendarGridHeader, { children: (day) => /* @__PURE__ */ jsx(CalendarHeaderCell, {
2567
+ className: "date-range__weekday",
2568
+ children: day
2569
+ }) }), /* @__PURE__ */ jsx(CalendarGridBody, { children: (date) => /* @__PURE__ */ jsx(CalendarCell, {
2570
+ date,
2571
+ className: "date-range__day"
2572
+ }) })]
2573
+ })]
2574
+ }, i))
2575
+ })]
2576
+ })
2577
+ }, calendarKey),
2578
+ /* @__PURE__ */ jsx("div", {
2579
+ className: "date-range__validation",
2580
+ "aria-live": "polite",
2581
+ children: error && /* @__PURE__ */ jsx("p", {
2582
+ id: `${id}-draft-error`,
2583
+ role: "alert",
2584
+ children: error
2585
+ })
2586
+ })
2587
+ ]
2588
+ })]
2589
+ }),
2590
+ /* @__PURE__ */ jsxs("footer", {
2591
+ className: "date-range__footer",
2592
+ children: [/* @__PURE__ */ jsx("button", {
2593
+ type: "button",
2594
+ className: "button button--ghost button--sm",
2595
+ disabled: isDisabled || isReadOnly,
2596
+ onClick: () => replaceDraft(empty()),
2597
+ children: labels.clear
2598
+ }), /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("button", {
2599
+ type: "button",
2600
+ className: "button button--secondary button--sm",
2601
+ onClick: () => changeOpen(false),
2602
+ children: labels.cancel
2603
+ }), /* @__PURE__ */ jsx("button", {
2604
+ type: "button",
2605
+ className: "button button--primary button--sm",
2606
+ disabled: isDisabled || isReadOnly || !!errorCode,
2607
+ onClick: apply,
2608
+ children: labels.apply
2609
+ })] })]
2610
+ })
2611
+ ]
2612
+ });
2613
+ return /* @__PURE__ */ jsx(I18nProvider, {
2614
+ locale: new Intl.Locale(locale, {
2615
+ calendar: "gregory",
2616
+ ...dir ? { script: dir === "rtl" ? "Arab" : "Latn" } : {}
2617
+ }).toString(),
2618
+ children: /* @__PURE__ */ jsxs("div", {
2619
+ className: [
2620
+ "date-range",
2621
+ `date-range--${size}`,
2622
+ `date-range--${variant}`,
2623
+ !fullWidth && "date-range--fit",
2624
+ hideLabel && "date-range--label-hidden",
2625
+ props.triggerDisplay === "icon" && "date-range--icon-trigger"
2626
+ ].filter(Boolean).join(" "),
2627
+ dir,
2628
+ "data-disabled": isDisabled || void 0,
2629
+ children: [
2630
+ /* @__PURE__ */ jsxs("span", {
2631
+ id: `${id}-label`,
2632
+ className: "date-range__label",
2633
+ children: [label, isRequired && /* @__PURE__ */ jsx("span", {
2634
+ "aria-hidden": "true",
2635
+ children: " *"
2636
+ })]
2637
+ }),
2638
+ display === "inline" ? /* @__PURE__ */ jsx("section", {
2639
+ className: "date-range__panel date-range__inline",
2640
+ "aria-labelledby": `${id}-title`,
2641
+ dir,
2642
+ children: panel
2643
+ }) : /* @__PURE__ */ jsxs(DialogTrigger, {
2644
+ isOpen: visible,
2645
+ onOpenChange: changeOpen,
2646
+ children: [/* @__PURE__ */ jsxs(Button$1, {
2647
+ ref: trigger,
2648
+ className: "date-range__trigger",
2649
+ isDisabled,
2650
+ "aria-labelledby": `${id}-label ${id}-value`,
2651
+ "aria-describedby": feedbackId,
2652
+ "aria-invalid": !!outerError,
2653
+ children: [
2654
+ /* @__PURE__ */ jsxs("svg", {
2655
+ className: "date-range__icon",
2656
+ "aria-hidden": "true",
2657
+ viewBox: "0 0 24 24",
2658
+ fill: "none",
2659
+ stroke: "currentColor",
2660
+ strokeWidth: "1.8",
2661
+ strokeLinecap: "round",
2662
+ children: [/* @__PURE__ */ jsx("rect", {
2663
+ x: "3",
2664
+ y: "5",
2665
+ width: "18",
2666
+ height: "16",
2667
+ rx: "2"
2668
+ }), /* @__PURE__ */ jsx("path", { d: "M7 3v4m10-4v4M3 10h18" })]
2669
+ }),
2670
+ /* @__PURE__ */ jsx("span", {
2671
+ id: `${id}-value`,
2672
+ className: "date-range__value",
2673
+ "data-placeholder": !committed || void 0,
2674
+ children: text
2675
+ }),
2676
+ /* @__PURE__ */ jsx(ChevronIcon, { className: "date-range__chevron" })
2677
+ ]
2678
+ }), /* @__PURE__ */ jsx(Popover$2, {
2679
+ className: "date-range__panel",
2680
+ placement: "bottom start",
2681
+ offset: 8,
2682
+ containerPadding: 16,
2683
+ dir,
2684
+ children: /* @__PURE__ */ jsx(Dialog$1, {
2685
+ className: "date-range__dialog",
2686
+ "aria-labelledby": `${id}-title`,
2687
+ children: panel
2688
+ })
2689
+ })]
2690
+ }),
2691
+ props.description && /* @__PURE__ */ jsx("span", {
2692
+ id: `${id}-description`,
2693
+ className: "input__description",
2694
+ children: props.description
2695
+ }),
2696
+ outerError && /* @__PURE__ */ jsx("span", {
2697
+ id: `${id}-error`,
2698
+ className: "input__error",
2699
+ role: "alert",
2700
+ children: props.errorMessage ?? (committedError ? labels[committedError] : labels.required)
2701
+ }),
2702
+ props.name && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("input", {
2703
+ type: "hidden",
2704
+ name: `${props.name}.start`,
2705
+ value: start,
2706
+ disabled: isDisabled
2707
+ }), /* @__PURE__ */ jsx("input", {
2708
+ type: "hidden",
2709
+ name: `${props.name}.end`,
2710
+ value: end,
2711
+ disabled: isDisabled
2712
+ })] }),
2713
+ /* @__PURE__ */ jsx(SelectionValidation, {
2714
+ hasValue: !!committed && !committedError,
2715
+ required: isRequired || !!committedError,
2716
+ disabled: isDisabled,
2717
+ onInvalid: () => {
2718
+ setFormError(true);
2719
+ trigger.current?.focus();
2720
+ },
2721
+ onResetStart: () => {},
2722
+ onReset: (cancelled) => {
2723
+ if (!cancelled) {
2724
+ if (props.value === void 0) setLocal(props.defaultValue ?? null);
2725
+ setFormError(false);
2726
+ changeOpen(false);
2727
+ }
2728
+ }
2729
+ })
2730
+ ]
2731
+ })
2732
+ });
2733
+ }
2734
+ //#endregion
2735
+ //#region src/toast-model.ts
2736
+ var EMPTY = Object.freeze([]);
2737
+ var messageOptions = (message) => typeof message === "string" ? { title: message } : message;
2738
+ var milliseconds = (value, fallback) => Number.isFinite(value) && value >= 0 ? value : fallback;
2739
+ /** Complete required notifications/cleanup before reporting user callback failures. */
2740
+ var complete = (operations) => {
2741
+ const errors = [];
2742
+ for (const operation of operations) try {
2743
+ operation();
2744
+ } catch (error) {
2745
+ errors.push(error);
2746
+ }
2747
+ if (errors.length === 1) throw errors[0];
2748
+ if (errors.length > 1) throw new AggregateError(errors, "Toast lifecycle callbacks failed.");
2749
+ };
2750
+ /** Create per application/provider; no browser globals or timers are used until attached. */
2751
+ function createToastManager(options = {}) {
2752
+ const maxVisible = Math.max(1, Math.floor(options.maxVisible ?? 3));
2753
+ const maxPending = Math.max(0, Math.floor(options.maxPending ?? 50));
2754
+ const duration = milliseconds(options.duration ?? 5e3, 5e3);
2755
+ const exitDuration = milliseconds(options.exitDuration ?? 200, 200);
2756
+ const records = /* @__PURE__ */ new Map();
2757
+ const visible = [];
2758
+ const pending = [];
2759
+ const listeners = /* @__PURE__ */ new Set();
2760
+ const pauses = /* @__PURE__ */ new Map();
2761
+ let snapshot = EMPTY;
2762
+ let attached = false;
2763
+ let disposed = false;
2764
+ let sequence = 0;
2765
+ let generation = 0;
2766
+ const paused = () => !attached || pauses.size > 0;
2767
+ const freeze = (entry) => Object.freeze({
2768
+ ...entry,
2769
+ action: entry.action ? Object.freeze({ ...entry.action }) : void 0,
2770
+ cancel: entry.cancel ? Object.freeze({ ...entry.cancel }) : void 0
2771
+ });
2772
+ const publish = () => {
2773
+ const next = visible.map((id) => records.get(id).entry);
2774
+ if (next.length === snapshot.length && next.every((entry, index) => entry === snapshot[index])) return;
2775
+ snapshot = Object.freeze(next);
2776
+ complete([...listeners]);
2777
+ };
2778
+ const stop = (record) => {
2779
+ if (record.timer !== void 0) clearTimeout(record.timer);
2780
+ record.timer = void 0;
2781
+ if (record.startedAt !== null) {
2782
+ const elapsed = Math.max(0, Date.now() - record.startedAt);
2783
+ if (record.entry.state === "closing") record.exitRemaining = Math.max(0, record.exitRemaining - elapsed);
2784
+ else record.entry = freeze({
2785
+ ...record.entry,
2786
+ remaining: Math.max(0, record.entry.remaining - elapsed)
2787
+ });
2788
+ }
2789
+ record.startedAt = null;
2790
+ };
2791
+ const promote = () => {
2792
+ while (visible.length < maxVisible && pending.length) {
2793
+ const id = pending.shift();
2794
+ const record = records.get(id);
2795
+ visible.push(id);
2796
+ record.entry = freeze({
2797
+ ...record.entry,
2798
+ visibleAt: Date.now(),
2799
+ paused: paused()
2800
+ });
2801
+ start(record);
2802
+ }
2803
+ };
2804
+ const remove = (id) => {
2805
+ const record = records.get(id);
2806
+ if (!record) return;
2807
+ stop(record);
2808
+ records.delete(id);
2809
+ const index = visible.indexOf(id);
2810
+ if (index >= 0) visible.splice(index, 1);
2811
+ const waiting = pending.indexOf(id);
2812
+ if (waiting >= 0) pending.splice(waiting, 1);
2813
+ promote();
2814
+ publish();
2815
+ };
2816
+ const start = (record) => {
2817
+ if (!attached || record.entry.visibleAt === null || record.timer !== void 0) return;
2818
+ const closing = record.entry.state === "closing";
2819
+ if (!closing && (paused() || record.entry.isLoading || record.entry.duration === 0)) return;
2820
+ record.startedAt = Date.now();
2821
+ record.timer = setTimeout(() => {
2822
+ record.timer = void 0;
2823
+ record.startedAt = null;
2824
+ if (closing) remove(record.entry.id);
2825
+ else manager.dismiss(record.entry.id, "timeout");
2826
+ }, closing ? record.exitRemaining : record.entry.remaining);
2827
+ };
2828
+ const refreshPause = () => {
2829
+ for (const id of visible) {
2830
+ const record = records.get(id);
2831
+ stop(record);
2832
+ record.entry = freeze({
2833
+ ...record.entry,
2834
+ paused: paused() || record.entry.state === "closing"
2835
+ });
2836
+ start(record);
2837
+ }
2838
+ publish();
2839
+ };
2840
+ const update = (id, changes, invalidate, onGeneration) => {
2841
+ const record = records.get(id);
2842
+ if (!record || record.entry.state === "closing" || disposed) return false;
2843
+ stop(record);
2844
+ const before = record.entry;
2845
+ const settled = before.isLoading && changes.isLoading === false;
2846
+ const nextDuration = changes.duration !== void 0 ? milliseconds(changes.duration, duration) : settled ? duration : before.duration;
2847
+ record.entry = freeze({
2848
+ ...before,
2849
+ ...changes,
2850
+ id,
2851
+ tone: changes.tone ?? before.tone,
2852
+ duration: nextDuration,
2853
+ isLoading: changes.isLoading ?? before.isLoading,
2854
+ remaining: changes.duration !== void 0 || settled ? nextDuration : before.remaining,
2855
+ generation: invalidate ? ++generation : before.generation
2856
+ });
2857
+ onGeneration?.(record.entry.generation);
2858
+ start(record);
2859
+ publish();
2860
+ return true;
2861
+ };
2862
+ const add = (value, onGeneration) => {
2863
+ if (disposed) return null;
2864
+ if (value.id !== void 0 && records.has(value.id)) return update(value.id, value, true, onGeneration) ? value.id : null;
2865
+ if (visible.length >= maxVisible && pending.length >= maxPending) return null;
2866
+ let id = value.id;
2867
+ if (id === void 0) do
2868
+ id = `toast-${++sequence}`;
2869
+ while (records.has(id));
2870
+ const entry = freeze({
2871
+ ...value,
2872
+ id,
2873
+ tone: value.tone ?? "neutral",
2874
+ duration: milliseconds(value.duration ?? duration, duration),
2875
+ isLoading: value.isLoading ?? false,
2876
+ generation: ++generation,
2877
+ state: "open",
2878
+ createdAt: Date.now(),
2879
+ visibleAt: visible.length < maxVisible ? Date.now() : null,
2880
+ remaining: milliseconds(value.duration ?? duration, duration),
2881
+ paused: paused()
2882
+ });
2883
+ const record = {
2884
+ entry,
2885
+ startedAt: null,
2886
+ exitRemaining: exitDuration
2887
+ };
2888
+ records.set(id, record);
2889
+ if (visible.length < maxVisible) {
2890
+ visible.push(id);
2891
+ start(record);
2892
+ } else pending.push(id);
2893
+ onGeneration?.(entry.generation);
2894
+ publish();
2895
+ return id;
2896
+ };
2897
+ const manager = {
2898
+ add,
2899
+ update: (id, changes) => update(id, changes, true),
2900
+ dismiss(id, reason = "dismiss") {
2901
+ const record = records.get(id);
2902
+ if (!record || record.entry.state === "closing") return;
2903
+ stop(record);
2904
+ record.entry = freeze({
2905
+ ...record.entry,
2906
+ state: "closing",
2907
+ paused: true,
2908
+ remaining: reason === "timeout" ? 0 : record.entry.remaining
2909
+ });
2910
+ complete([() => {
2911
+ if (record.entry.visibleAt === null) remove(id);
2912
+ else {
2913
+ start(record);
2914
+ publish();
2915
+ }
2916
+ }, () => record.entry.onClose?.(reason)]);
2917
+ },
2918
+ clear(reason = "clear") {
2919
+ complete([...pending, ...visible].map((id) => () => manager.dismiss(id, reason)));
2920
+ },
2921
+ pause(reason) {
2922
+ if (disposed) return;
2923
+ pauses.set(reason, (pauses.get(reason) ?? 0) + 1);
2924
+ if (pauses.size === 1 && pauses.get(reason) === 1) refreshPause();
2925
+ },
2926
+ resume(reason) {
2927
+ const count = pauses.get(reason);
2928
+ if (!count || disposed) return;
2929
+ if (count === 1) pauses.delete(reason);
2930
+ else pauses.set(reason, count - 1);
2931
+ if (!pauses.size) refreshPause();
2932
+ },
2933
+ attach() {
2934
+ if (disposed) throw new Error("Cannot attach a disposed ToastManager.");
2935
+ if (attached) throw new Error("A ToastManager may attach to only one provider.");
2936
+ attached = true;
2937
+ try {
2938
+ refreshPause();
2939
+ } catch (error) {
2940
+ attached = false;
2941
+ complete([() => {
2942
+ throw error;
2943
+ }, refreshPause]);
2944
+ }
2945
+ let detached = false;
2946
+ return () => {
2947
+ if (detached || disposed) return;
2948
+ detached = true;
2949
+ attached = false;
2950
+ refreshPause();
2951
+ };
2952
+ },
2953
+ dispose() {
2954
+ if (disposed) return;
2955
+ disposed = true;
2956
+ attached = false;
2957
+ const closing = [...records.values()].filter((record) => record.entry.state === "open");
2958
+ for (const record of records.values()) stop(record);
2959
+ records.clear();
2960
+ visible.length = 0;
2961
+ pending.length = 0;
2962
+ pauses.clear();
2963
+ complete([
2964
+ publish,
2965
+ () => listeners.clear(),
2966
+ ...closing.map((record) => () => record.entry.onClose?.("unmount"))
2967
+ ]);
2968
+ },
2969
+ subscribe(listener) {
2970
+ if (!disposed) listeners.add(listener);
2971
+ return () => {
2972
+ listeners.delete(listener);
2973
+ };
2974
+ },
2975
+ getSnapshot: () => snapshot,
2976
+ getServerSnapshot: () => EMPTY,
2977
+ promise(task, messages, promiseOptions = {}) {
2978
+ let expected;
2979
+ const id = add({
2980
+ ...promiseOptions,
2981
+ ...messageOptions(messages.loading),
2982
+ isLoading: true
2983
+ }, (value) => {
2984
+ expected = value;
2985
+ });
2986
+ const settle = (message, tone) => {
2987
+ if (id === null || records.get(id)?.entry.generation !== expected || records.get(id)?.entry.state !== "open") return;
2988
+ const content = typeof message === "function" ? message() : message;
2989
+ if (records.get(id)?.entry.generation !== expected || records.get(id)?.entry.state !== "open") return;
2990
+ update(id, {
2991
+ tone,
2992
+ duration: promiseOptions.duration ?? duration,
2993
+ ...messageOptions(content),
2994
+ isLoading: false
2995
+ }, false);
2996
+ };
2997
+ return {
2998
+ id,
2999
+ promise: task.then((value) => {
3000
+ const message = messages.success;
3001
+ settle(typeof message === "function" ? () => message(value) : message, "success");
3002
+ return value;
3003
+ }, (error) => {
3004
+ const message = messages.error;
3005
+ settle(typeof message === "function" ? () => message(error) : message, "danger");
3006
+ throw error;
3007
+ })
3008
+ };
3009
+ }
3010
+ };
3011
+ return manager;
3012
+ }
3013
+ //#endregion
3014
+ //#region src/Toast.tsx
3015
+ /** Keeps upstream accessibility/focus behavior while Kazee owns every timer and queue decision. */
3016
+ var QueueAdapter = class extends UNSTABLE_ToastQueue {
3017
+ manager;
3018
+ regionPaused = false;
3019
+ constructor(manager) {
3020
+ super();
3021
+ this.manager = manager;
3022
+ this.refresh();
3023
+ }
3024
+ refresh() {
3025
+ this.visibleToasts = this.manager.getSnapshot().map((content) => ({
3026
+ key: content.id,
3027
+ content
3028
+ }));
3029
+ }
3030
+ subscribe(listener) {
3031
+ return this.manager.subscribe(() => {
3032
+ this.refresh();
3033
+ listener();
3034
+ });
3035
+ }
3036
+ add(content) {
3037
+ return this.manager.add(content) ?? "";
3038
+ }
3039
+ close(key) {
3040
+ this.manager.dismiss(key);
3041
+ }
3042
+ clear() {
3043
+ this.manager.clear();
3044
+ }
3045
+ pauseAll() {
3046
+ if (!this.regionPaused) {
3047
+ this.regionPaused = true;
3048
+ this.manager.pause("region");
3049
+ }
3050
+ }
3051
+ resumeAll() {
3052
+ if (this.regionPaused) {
3053
+ this.regionPaused = false;
3054
+ this.manager.resume("region");
3055
+ }
3056
+ }
3057
+ };
3058
+ var ToastContext = createContext(null);
3059
+ function ToastProvider({ children, manager: suppliedManager, placement = "bottom-end", label = "Notifikasi / Notifications", closeLabel = "Tutup notifikasi / Close notification", hotkey = ["Alt", "t"], dir = "ltr", showProgress = false, swipeThreshold = 50, renderToast }) {
3060
+ const [ownedManager] = useState(() => createToastManager());
3061
+ const manager = suppliedManager ?? ownedManager;
3062
+ const queue = useMemo(() => new QueueAdapter(manager), [manager]);
3063
+ const region = useRef(null);
3064
+ const entries = useSyncExternalStore(manager.subscribe, manager.getSnapshot, manager.getServerSnapshot);
3065
+ const positions = useRef(/* @__PURE__ */ new Map());
3066
+ useLayoutEffect(() => {
3067
+ const nodes = region.current?.querySelectorAll(".toast");
3068
+ const previous = positions.current;
3069
+ const next = /* @__PURE__ */ new Map();
3070
+ const animations = [];
3071
+ const regionTop = region.current?.getBoundingClientRect().top ?? 0;
3072
+ const reducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
3073
+ for (const node of nodes ?? []) {
3074
+ const id = node.dataset.toastId;
3075
+ if (!id) continue;
3076
+ const top = node.offsetTop + regionTop;
3077
+ next.set(id, top);
3078
+ const before = previous.get(id);
3079
+ if (before !== void 0 && before !== top && node.dataset.state === "open" && !reducedMotion && node.animate) {
3080
+ const style = getComputedStyle(node);
3081
+ const token = style.getPropertyValue("--ds-motion-duration-normal").trim();
3082
+ const duration = token.endsWith("ms") ? parseFloat(token) : parseFloat(token) * 1e3;
3083
+ animations.push(node.animate([{ translate: `0 ${before - top}px` }, { translate: "0 0" }], {
3084
+ duration: Number.isFinite(duration) ? duration : 160,
3085
+ easing: style.getPropertyValue("--ds-motion-ease-standard").trim() || "ease-out"
3086
+ }));
3087
+ }
3088
+ }
3089
+ positions.current = next;
3090
+ return () => {
3091
+ for (const animation of animations) animation.cancel();
3092
+ };
3093
+ }, [entries]);
3094
+ const lastFocused = useRef(null);
3095
+ const lifetime = useRef({ generation: 0 });
3096
+ const hotkeySignature = hotkey.join("+");
3097
+ useEffect(() => {
3098
+ const keys = hotkeySignature ? hotkeySignature.split("+") : [];
3099
+ const detach = manager.attach();
3100
+ let documentPaused = false;
3101
+ let windowPaused = false;
3102
+ const visibility = () => {
3103
+ if (document.hidden && !documentPaused) {
3104
+ documentPaused = true;
3105
+ manager.pause("document");
3106
+ } else if (!document.hidden && documentPaused) {
3107
+ documentPaused = false;
3108
+ manager.resume("document");
3109
+ }
3110
+ };
3111
+ const blur = () => {
3112
+ if (!windowPaused) {
3113
+ windowPaused = true;
3114
+ manager.pause("window");
3115
+ }
3116
+ };
3117
+ const focus = () => {
3118
+ if (windowPaused) {
3119
+ windowPaused = false;
3120
+ manager.resume("window");
3121
+ }
3122
+ };
3123
+ visibility();
3124
+ const keydown = (event) => {
3125
+ if (event.defaultPrevented) return;
3126
+ if (event.key === "Escape" && region.current?.contains(event.target)) {
3127
+ const target = event.target;
3128
+ if (target.closest("input,textarea,select,[contenteditable=\"true\"]")) return;
3129
+ const focused = target.closest(".toast[data-state=\"open\"]");
3130
+ const latest = [...manager.getSnapshot()].reverse().find((entry) => entry.state === "open");
3131
+ const id = focused?.dataset.toastId ?? latest?.id;
3132
+ if (id) {
3133
+ event.preventDefault();
3134
+ event.stopPropagation();
3135
+ manager.dismiss(id);
3136
+ }
3137
+ return;
3138
+ }
3139
+ if (!keys.length) return;
3140
+ const key = keys[keys.length - 1].toLowerCase();
3141
+ const modifiers = keys.slice(0, -1).map((value) => value.toLowerCase());
3142
+ if (event.key.toLowerCase() === key && event.altKey === modifiers.includes("alt") && event.ctrlKey === modifiers.includes("control") && event.metaKey === modifiers.includes("meta") && event.shiftKey === modifiers.includes("shift")) {
3143
+ const target = region.current?.querySelector(".toast[data-state=\"open\"]");
3144
+ if (target) {
3145
+ event.preventDefault();
3146
+ target.focus();
3147
+ }
3148
+ }
3149
+ };
3150
+ const focusIn = (event) => {
3151
+ if (region.current?.contains(event.target) && !region.current.contains(event.relatedTarget)) lastFocused.current = event.relatedTarget;
3152
+ };
3153
+ document.addEventListener("focusin", focusIn);
3154
+ document.addEventListener("visibilitychange", visibility);
3155
+ document.addEventListener("keydown", keydown);
3156
+ window.addEventListener("blur", blur);
3157
+ window.addEventListener("focus", focus);
3158
+ return () => {
3159
+ document.removeEventListener("focusin", focusIn);
3160
+ document.removeEventListener("visibilitychange", visibility);
3161
+ document.removeEventListener("keydown", keydown);
3162
+ window.removeEventListener("blur", blur);
3163
+ window.removeEventListener("focus", focus);
3164
+ detach();
3165
+ if (documentPaused) manager.resume("document");
3166
+ if (windowPaused) manager.resume("window");
3167
+ queue.resumeAll();
3168
+ };
3169
+ }, [
3170
+ manager,
3171
+ hotkeySignature,
3172
+ queue
3173
+ ]);
3174
+ useEffect(() => {
3175
+ const lifecycle = lifetime.current;
3176
+ const token = ++lifecycle.generation;
3177
+ return () => {
3178
+ queueMicrotask(() => {
3179
+ if (lifecycle.generation === token) ownedManager.dispose();
3180
+ });
3181
+ };
3182
+ }, [ownedManager]);
3183
+ const context = {
3184
+ manager,
3185
+ closeLabel,
3186
+ placement,
3187
+ dir,
3188
+ showProgress,
3189
+ swipeThreshold,
3190
+ restoreFocus: () => {
3191
+ const next = region.current?.querySelector(".toast[data-state=\"open\"]");
3192
+ if (next) next.focus();
3193
+ else if (lastFocused.current?.isConnected) lastFocused.current.focus();
3194
+ }
3195
+ };
3196
+ return /* @__PURE__ */ jsxs(ToastContext.Provider, {
3197
+ value: context,
3198
+ children: [children, /* @__PURE__ */ jsx(I18nProvider$1, {
3199
+ locale: dir === "rtl" ? "ar" : "en",
3200
+ children: /* @__PURE__ */ jsx(UNSTABLE_ToastRegion, {
3201
+ queue,
3202
+ ref: region,
3203
+ className: "toast-region",
3204
+ "data-placement": placement,
3205
+ "aria-label": label,
3206
+ "aria-keyshortcuts": hotkey.length ? hotkey.join("+") : void 0,
3207
+ children: /* @__PURE__ */ jsx(UNSTABLE_ToastList, {
3208
+ className: "toast-list",
3209
+ children: ({ toast }) => /* @__PURE__ */ jsx(Fragment$1, { children: renderToast ? renderToast(toast.content) : /* @__PURE__ */ jsx(Toast, { entry: toast.content }) })
3210
+ })
3211
+ })
3212
+ })]
3213
+ });
3214
+ }
3215
+ function useToast() {
3216
+ const context = useContext(ToastContext);
3217
+ if (!context) throw new Error("useToast must be used within a ToastProvider.");
3218
+ return context.manager;
3219
+ }
3220
+ function Indicator({ entry }) {
3221
+ return /* @__PURE__ */ jsx("svg", {
3222
+ viewBox: "0 0 24 24",
3223
+ width: "20",
3224
+ height: "20",
3225
+ fill: "none",
3226
+ stroke: "currentColor",
3227
+ strokeWidth: "1.8",
3228
+ "aria-hidden": "true",
3229
+ children: entry.isLoading ? /* @__PURE__ */ jsx("circle", {
3230
+ cx: "12",
3231
+ cy: "12",
3232
+ r: "8",
3233
+ strokeDasharray: "36 14"
3234
+ }) : entry.tone === "success" ? /* @__PURE__ */ jsx("path", { d: "m5 12 4 4L19 6" }) : entry.tone === "warning" || entry.tone === "danger" ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("path", { d: "m12 3 10 18H2L12 3Z" }), /* @__PURE__ */ jsx("path", { d: "M12 9v5m0 3v1" })] }) : /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("circle", {
3235
+ cx: "12",
3236
+ cy: "12",
3237
+ r: "9"
3238
+ }), /* @__PURE__ */ jsx("path", { d: "M12 10v7m0-11v1" })] })
3239
+ });
3240
+ }
3241
+ function Toast({ entry, indicator, children, className }) {
3242
+ const actionDescriptionId = useId();
3243
+ const cancelDescriptionId = useId();
3244
+ const context = useContext(ToastContext);
3245
+ if (!context) throw new Error("Toast must be used within a ToastProvider region.");
3246
+ const { manager, closeLabel, placement, dir, showProgress, swipeThreshold, restoreFocus } = context;
3247
+ const ref = useRef(null);
3248
+ const drag = useRef(null);
3249
+ const [offset, setOffset] = useState(0);
3250
+ const [swipe, setSwipe] = useState();
3251
+ const closing = entry.state === "closing";
3252
+ const direction = (placement.endsWith("start") ? -1 : 1) * (dir === "rtl" ? -1 : 1);
3253
+ useEffect(() => {
3254
+ if (closing && ref.current?.contains(document.activeElement)) restoreFocus?.();
3255
+ }, [closing, restoreFocus]);
3256
+ const action = (item, reason) => {
3257
+ item.onAction();
3258
+ if (item.dismiss !== false) manager.dismiss(entry.id, reason);
3259
+ };
3260
+ const finishSwipe = (commit) => {
3261
+ const current = drag.current;
3262
+ drag.current = null;
3263
+ if (!current) return;
3264
+ if (current && !current.cancelled) manager.resume("swipe");
3265
+ if (commit && !current.cancelled && current.offset * direction >= swipeThreshold) {
3266
+ setSwipe("end");
3267
+ setOffset(current.offset);
3268
+ manager.dismiss(entry.id, "swipe");
3269
+ } else {
3270
+ setSwipe("cancel");
3271
+ setOffset(0);
3272
+ }
3273
+ };
3274
+ useEffect(() => {
3275
+ const node = ref.current;
3276
+ if (!node) return;
3277
+ const handlers = {
3278
+ pointerdown: (event) => {
3279
+ if (closing || drag.current || event.button !== 0 || event.target.closest("button,a,input,textarea,select,[role=\"button\"],[contenteditable=\"true\"]")) return;
3280
+ if (event.pointerType === "mouse") event.preventDefault();
3281
+ drag.current = {
3282
+ x: event.clientX,
3283
+ y: event.clientY,
3284
+ id: event.pointerId,
3285
+ cancelled: false,
3286
+ offset: 0
3287
+ };
3288
+ ref.current?.setPointerCapture?.(event.pointerId);
3289
+ manager.pause("swipe");
3290
+ },
3291
+ selectstart: (event) => {
3292
+ if (drag.current && !drag.current.cancelled) event.preventDefault();
3293
+ },
3294
+ dragstart: (event) => {
3295
+ if (drag.current && !drag.current.cancelled) event.preventDefault();
3296
+ },
3297
+ pointermove: (event) => {
3298
+ const current = drag.current;
3299
+ if (!current || current.id !== event.pointerId || current.cancelled) return;
3300
+ const x = event.clientX - current.x;
3301
+ const y = event.clientY - current.y;
3302
+ if (Math.abs(y) > Math.abs(x) && Math.abs(y) > 8) {
3303
+ current.cancelled = true;
3304
+ setOffset(0);
3305
+ manager.resume("swipe");
3306
+ return;
3307
+ }
3308
+ if (Math.abs(x) > 8) {
3309
+ current.offset = Math.max(0, x * direction) * direction;
3310
+ setSwipe("move");
3311
+ setOffset(current.offset);
3312
+ }
3313
+ },
3314
+ pointerup: () => finishSwipe(true),
3315
+ pointercancel: () => finishSwipe(false),
3316
+ lostpointercapture: () => {
3317
+ if (drag.current) finishSwipe(false);
3318
+ }
3319
+ };
3320
+ for (const [name, handler] of Object.entries(handlers)) node.addEventListener(name, handler);
3321
+ return () => {
3322
+ for (const [name, handler] of Object.entries(handlers)) node.removeEventListener(name, handler);
3323
+ };
3324
+ });
3325
+ useEffect(() => () => {
3326
+ if (drag.current) {
3327
+ const active = !drag.current.cancelled;
3328
+ drag.current = null;
3329
+ if (active) manager.resume("swipe");
3330
+ }
3331
+ }, [manager]);
3332
+ return /* @__PURE__ */ jsxs(UNSTABLE_Toast, {
3333
+ toast: {
3334
+ key: entry.id,
3335
+ content: entry
3336
+ },
3337
+ ref,
3338
+ className: `toast${className ? ` ${className}` : ""}`,
3339
+ "data-toast-id": entry.id,
3340
+ "data-tone": entry.tone,
3341
+ "data-loading": entry.isLoading || void 0,
3342
+ "data-state": entry.state,
3343
+ "data-placement": placement,
3344
+ "data-paused": entry.paused || void 0,
3345
+ "data-swipe": swipe,
3346
+ inert: closing || void 0,
3347
+ "aria-hidden": closing || void 0,
3348
+ style: {
3349
+ "--toast-swipe-x": `${offset}px`,
3350
+ touchAction: "pan-y"
3351
+ },
3352
+ children: [
3353
+ /* @__PURE__ */ jsx("span", {
3354
+ className: "toast__indicator",
3355
+ "aria-hidden": "true",
3356
+ children: indicator ?? /* @__PURE__ */ jsx(Indicator, { entry })
3357
+ }),
3358
+ /* @__PURE__ */ jsxs(UNSTABLE_ToastContent, {
3359
+ className: "toast__body",
3360
+ role: "status",
3361
+ "aria-live": "polite",
3362
+ children: [
3363
+ /* @__PURE__ */ jsx(Text$3, {
3364
+ slot: "title",
3365
+ className: "toast__title",
3366
+ children: entry.title
3367
+ }),
3368
+ entry.description && /* @__PURE__ */ jsx(Text$3, {
3369
+ slot: "description",
3370
+ className: "toast__description",
3371
+ children: entry.description
3372
+ }),
3373
+ children,
3374
+ (entry.action || entry.cancel) && /* @__PURE__ */ jsxs("div", {
3375
+ className: "toast__actions",
3376
+ children: [
3377
+ entry.action && /* @__PURE__ */ jsx("span", {
3378
+ id: actionDescriptionId,
3379
+ hidden: true,
3380
+ children: entry.action.altText
3381
+ }),
3382
+ entry.cancel && /* @__PURE__ */ jsx("span", {
3383
+ id: cancelDescriptionId,
3384
+ hidden: true,
3385
+ children: entry.cancel.altText
3386
+ }),
3387
+ entry.action && /* @__PURE__ */ jsx(Button$5, {
3388
+ className: "toast__action",
3389
+ "aria-describedby": actionDescriptionId,
3390
+ isDisabled: closing,
3391
+ onPress: () => action(entry.action, "action"),
3392
+ children: entry.action.label
3393
+ }),
3394
+ entry.cancel && /* @__PURE__ */ jsx(Button$5, {
3395
+ className: "toast__action",
3396
+ "data-cancel": true,
3397
+ "aria-describedby": cancelDescriptionId,
3398
+ isDisabled: closing,
3399
+ onPress: () => action(entry.cancel, "cancel"),
3400
+ children: entry.cancel.label
3401
+ })
3402
+ ]
3403
+ })
3404
+ ]
3405
+ }),
3406
+ /* @__PURE__ */ jsx(Button$5, {
3407
+ slot: "close",
3408
+ className: "toast__close",
3409
+ "aria-label": closeLabel,
3410
+ isDisabled: closing,
3411
+ children: /* @__PURE__ */ jsx("svg", {
3412
+ viewBox: "0 0 24 24",
3413
+ width: "16",
3414
+ height: "16",
3415
+ fill: "none",
3416
+ stroke: "currentColor",
3417
+ strokeWidth: "2",
3418
+ "aria-hidden": "true",
3419
+ children: /* @__PURE__ */ jsx("path", { d: "m6 6 12 12M6 18 18 6" })
3420
+ })
3421
+ }),
3422
+ showProgress && entry.duration > 0 && !entry.isLoading && /* @__PURE__ */ jsx("span", {
3423
+ className: "toast__progress",
3424
+ "aria-hidden": "true",
3425
+ style: {
3426
+ "--toast-progress": entry.remaining / entry.duration,
3427
+ "--toast-remaining": `${entry.remaining}ms`
3428
+ }
3429
+ }, `${entry.generation}-${entry.remaining}-${entry.paused}`)
3430
+ ]
3431
+ });
3432
+ }
3433
+ //#endregion
3434
+ export { Alert, Badge, Breadcrumb, Button, ButtonGroup, ButtonGroupSeparator, Card, Chart, Checkbox, Combobox, DataTable, DateRangePicker, Dialog, DropdownMenu, Empty, Field, Form, Input, Label, Listbox, NumberField, Pagination, Popover, RadioGroup, Select, SelectGroup, Separator, Sidebar, Skeleton, Spinner, Switch, Table, Tabs, Textarea, Toast, ToastProvider, ToggleButton, ToggleButtonGroup, ToggleGroup, Tooltip, createDateRangePresets, createToastManager, rangeText as formatDateRange, useToast };
3435
+
3436
+ //# sourceMappingURL=index.js.map