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