dalila 1.8.2 → 1.8.4

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 (89) hide show
  1. package/dist/cli/routes-generator.js +1 -2
  2. package/dist/components/ui/dialog/index.d.ts +0 -8
  3. package/dist/components/ui/dialog/index.js +2 -41
  4. package/dist/components/ui/dialog/internal.d.ts +5 -0
  5. package/dist/{componentes/ui/dialog/index.js → components/ui/dialog/internal.js} +1 -23
  6. package/dist/components/ui/drawer/index.js +2 -2
  7. package/dist/components/ui/index.d.ts +1 -1
  8. package/dist/components/ui/index.js +1 -1
  9. package/dist/core/index.d.ts +1 -1
  10. package/dist/core/index.js +1 -1
  11. package/dist/core/query.js +9 -7
  12. package/dist/core/resource.d.ts +23 -171
  13. package/dist/core/resource.js +178 -15
  14. package/dist/form/index.d.ts +1 -1
  15. package/dist/form/index.js +1 -1
  16. package/dist/router/index.d.ts +1 -1
  17. package/dist/router/index.js +1 -1
  18. package/dist/runtime/bind.d.ts +10 -0
  19. package/dist/runtime/bind.js +382 -53
  20. package/package.json +1 -1
  21. package/dist/componentes/ui/accordion/index.d.ts +0 -2
  22. package/dist/componentes/ui/accordion/index.js +0 -114
  23. package/dist/componentes/ui/calendar/index.d.ts +0 -2
  24. package/dist/componentes/ui/calendar/index.js +0 -132
  25. package/dist/componentes/ui/combobox/index.d.ts +0 -2
  26. package/dist/componentes/ui/combobox/index.js +0 -161
  27. package/dist/componentes/ui/dialog/index.d.ts +0 -10
  28. package/dist/componentes/ui/drawer/index.d.ts +0 -2
  29. package/dist/componentes/ui/drawer/index.js +0 -41
  30. package/dist/componentes/ui/dropdown/index.d.ts +0 -2
  31. package/dist/componentes/ui/dropdown/index.js +0 -48
  32. package/dist/componentes/ui/dropzone/index.d.ts +0 -2
  33. package/dist/componentes/ui/dropzone/index.js +0 -92
  34. package/dist/componentes/ui/env.d.ts +0 -1
  35. package/dist/componentes/ui/env.js +0 -2
  36. package/dist/componentes/ui/index.d.ts +0 -13
  37. package/dist/componentes/ui/index.js +0 -12
  38. package/dist/componentes/ui/popover/index.d.ts +0 -2
  39. package/dist/componentes/ui/popover/index.js +0 -156
  40. package/dist/componentes/ui/runtime.d.ts +0 -20
  41. package/dist/componentes/ui/runtime.js +0 -421
  42. package/dist/componentes/ui/tabs/index.d.ts +0 -3
  43. package/dist/componentes/ui/tabs/index.js +0 -101
  44. package/dist/componentes/ui/toast/index.d.ts +0 -3
  45. package/dist/componentes/ui/toast/index.js +0 -115
  46. package/dist/componentes/ui/ui-types.d.ts +0 -175
  47. package/dist/componentes/ui/ui-types.js +0 -1
  48. package/dist/componentes/ui/validate.d.ts +0 -7
  49. package/dist/componentes/ui/validate.js +0 -71
  50. package/dist/core/store.d.ts +0 -130
  51. package/dist/core/store.js +0 -234
  52. package/dist/core/virtual.d.ts +0 -26
  53. package/dist/core/virtual.js +0 -277
  54. package/dist/core/watch-testing.d.ts +0 -13
  55. package/dist/core/watch-testing.js +0 -16
  56. package/dist/router/route.d.ts +0 -23
  57. package/dist/router/route.js +0 -48
  58. package/dist/simple.d.ts +0 -11
  59. package/dist/simple.js +0 -11
  60. package/dist/ui/accordion.d.ts +0 -2
  61. package/dist/ui/accordion.js +0 -114
  62. package/dist/ui/calendar.d.ts +0 -2
  63. package/dist/ui/calendar.js +0 -132
  64. package/dist/ui/combobox.d.ts +0 -2
  65. package/dist/ui/combobox.js +0 -161
  66. package/dist/ui/dialog.d.ts +0 -10
  67. package/dist/ui/dialog.js +0 -54
  68. package/dist/ui/drawer.d.ts +0 -2
  69. package/dist/ui/drawer.js +0 -41
  70. package/dist/ui/dropdown.d.ts +0 -2
  71. package/dist/ui/dropdown.js +0 -48
  72. package/dist/ui/dropzone.d.ts +0 -2
  73. package/dist/ui/dropzone.js +0 -92
  74. package/dist/ui/env.d.ts +0 -1
  75. package/dist/ui/env.js +0 -2
  76. package/dist/ui/index.d.ts +0 -13
  77. package/dist/ui/index.js +0 -12
  78. package/dist/ui/popover.d.ts +0 -2
  79. package/dist/ui/popover.js +0 -156
  80. package/dist/ui/runtime.d.ts +0 -20
  81. package/dist/ui/runtime.js +0 -421
  82. package/dist/ui/tabs.d.ts +0 -3
  83. package/dist/ui/tabs.js +0 -101
  84. package/dist/ui/toast.d.ts +0 -3
  85. package/dist/ui/toast.js +0 -115
  86. package/dist/ui/ui-types.d.ts +0 -175
  87. package/dist/ui/ui-types.js +0 -1
  88. package/dist/ui/validate.d.ts +0 -7
  89. package/dist/ui/validate.js +0 -71
package/dist/ui/tabs.js DELETED
@@ -1,101 +0,0 @@
1
- import { signal, computed } from "../core/signal.js";
2
- import { getCurrentScope } from "../core/scope.js";
3
- export function createTabs(options = {}) {
4
- const { initial = "", orientation = "horizontal" } = options;
5
- const active = signal(initial);
6
- const select = (tabId) => active.set(tabId);
7
- const isActive = (tabId) => active() === tabId;
8
- const handleClick = (ev) => {
9
- const target = ev.target.closest("[data-tab]");
10
- if (target && target.dataset.tab) {
11
- select(target.dataset.tab);
12
- }
13
- };
14
- const _attachTo = (el) => {
15
- const scope = getCurrentScope();
16
- // ARIA setup
17
- const tabList = el.querySelector("[data-d-tag='d-tab-list'], .d-tab-list");
18
- if (tabList) {
19
- tabList.setAttribute("role", "tablist");
20
- tabList.setAttribute("aria-orientation", orientation);
21
- }
22
- const tabButtons = el.querySelectorAll("[data-tab]");
23
- const panels = el.querySelectorAll("[data-d-tag='d-tab-panel'], .d-tab-panel");
24
- tabButtons.forEach((btn, i) => {
25
- btn.setAttribute("role", "tab");
26
- const tabId = btn.dataset.tab;
27
- const btnId = btn.id || `d-tab-${tabId}`;
28
- if (!btn.id)
29
- btn.id = btnId;
30
- if (panels[i]) {
31
- const panelId = panels[i].id || `d-tabpanel-${tabId}`;
32
- if (!panels[i].id)
33
- panels[i].id = panelId;
34
- panels[i].setAttribute("role", "tabpanel");
35
- panels[i].setAttribute("aria-labelledby", btnId);
36
- btn.setAttribute("aria-controls", panelId);
37
- }
38
- });
39
- const syncAria = (activeId) => {
40
- tabButtons.forEach((btn, i) => {
41
- const isAct = btn.dataset.tab === activeId;
42
- btn.setAttribute("aria-selected", String(isAct));
43
- btn.setAttribute("tabindex", isAct ? "0" : "-1");
44
- if (panels[i])
45
- panels[i].setAttribute("aria-hidden", String(!isAct));
46
- });
47
- };
48
- // Apply initial state
49
- syncAria(active());
50
- const unsub = active.on(syncAria);
51
- // Keyboard navigation
52
- const prevKey = orientation === "vertical" ? "ArrowUp" : "ArrowLeft";
53
- const nextKey = orientation === "vertical" ? "ArrowDown" : "ArrowRight";
54
- const onKeydown = (ev) => {
55
- const tabs = Array.from(tabButtons);
56
- const currentIndex = tabs.findIndex((btn) => btn.dataset.tab === active());
57
- let nextIndex = -1;
58
- switch (ev.key) {
59
- case nextKey:
60
- ev.preventDefault();
61
- nextIndex = currentIndex < tabs.length - 1 ? currentIndex + 1 : 0;
62
- break;
63
- case prevKey:
64
- ev.preventDefault();
65
- nextIndex = currentIndex > 0 ? currentIndex - 1 : tabs.length - 1;
66
- break;
67
- case "Home":
68
- ev.preventDefault();
69
- nextIndex = 0;
70
- break;
71
- case "End":
72
- ev.preventDefault();
73
- nextIndex = tabs.length - 1;
74
- break;
75
- default:
76
- return;
77
- }
78
- const nextTab = tabs[nextIndex];
79
- if (nextTab?.dataset.tab) {
80
- select(nextTab.dataset.tab);
81
- nextTab.focus();
82
- }
83
- };
84
- if (tabList)
85
- tabList.addEventListener("keydown", onKeydown);
86
- if (scope) {
87
- scope.onCleanup(() => {
88
- unsub();
89
- if (tabList)
90
- tabList.removeEventListener("keydown", onKeydown);
91
- });
92
- }
93
- };
94
- return { active, select, isActive, handleClick, _attachTo };
95
- }
96
- export function tabBindings(tabs, tabId) {
97
- const tabClass = computed(() => tabs.active() === tabId ? "d-tab active" : "d-tab");
98
- const selected = computed(() => tabs.active() === tabId ? "true" : "false");
99
- const visible = computed(() => tabs.active() === tabId);
100
- return { tabClass, selected, visible };
101
- }
@@ -1,3 +0,0 @@
1
- import type { Toast, ToastOptions, ToastVariant } from "./ui-types.js";
2
- export declare function createToast(options?: ToastOptions): Toast;
3
- export declare function toastIcon(variant: () => ToastVariant | "idle"): DocumentFragment;
package/dist/ui/toast.js DELETED
@@ -1,115 +0,0 @@
1
- import { signal } from "../core/signal.js";
2
- import { getCurrentScope } from "../core/scope.js";
3
- import { match } from "../core/match.js";
4
- import { html } from "../core/html.js";
5
- import { validateToastOptions } from "./validate.js";
6
- import { isBrowser } from "./env.js";
7
- const VARIANT_CLASSES = {
8
- success: "d-toast d-toast-success",
9
- error: "d-toast d-toast-error",
10
- warning: "d-toast d-toast-warning",
11
- info: "d-toast d-toast-info",
12
- };
13
- const VARIANT_ICONS = {
14
- success: "\u2705",
15
- error: "\u274C",
16
- warning: "\u26A0\uFE0F",
17
- info: "\u2139\uFE0F",
18
- };
19
- const POSITION_CLASSES = {
20
- "top-right": "d-toast-container d-toast-top-right",
21
- "top-left": "d-toast-container d-toast-top-left",
22
- "bottom-right": "d-toast-container d-toast-bottom-right",
23
- "bottom-left": "d-toast-container d-toast-bottom-left",
24
- "top-center": "d-toast-container d-toast-top-center",
25
- "bottom-center": "d-toast-container d-toast-bottom-center",
26
- };
27
- let toastUid = 0;
28
- export function createToast(options = {}) {
29
- validateToastOptions(options);
30
- const { position = "top-right", duration: defaultDuration = 4000, maxToasts = 5, } = options;
31
- const items = signal([]);
32
- const activeVariant = signal("idle");
33
- const containerClass = signal(POSITION_CLASSES[position] ?? POSITION_CLASSES["top-right"]);
34
- const scope = getCurrentScope();
35
- const timers = new Map();
36
- const dismiss = (id) => {
37
- const timer = timers.get(id);
38
- if (timer) {
39
- clearTimeout(timer);
40
- timers.delete(id);
41
- }
42
- items.update((list) => list.filter((t) => t.id !== id));
43
- if (items().length === 0)
44
- activeVariant.set("idle");
45
- };
46
- const clear = () => {
47
- timers.forEach((t) => clearTimeout(t));
48
- timers.clear();
49
- items.set([]);
50
- activeVariant.set("idle");
51
- };
52
- const show = (variant, title, text, duration) => {
53
- const id = `toast-${++toastUid}`;
54
- const item = {
55
- id,
56
- variant,
57
- title,
58
- text,
59
- variantClass: VARIANT_CLASSES[variant],
60
- icon: VARIANT_ICONS[variant],
61
- };
62
- items.update((list) => {
63
- const next = [...list, item];
64
- // Enforce max toasts — remove oldest
65
- while (next.length > maxToasts) {
66
- const oldest = next.shift();
67
- const timer = timers.get(oldest.id);
68
- if (timer) {
69
- clearTimeout(timer);
70
- timers.delete(oldest.id);
71
- }
72
- }
73
- return next;
74
- });
75
- activeVariant.set(variant);
76
- const ms = duration ?? defaultDuration;
77
- if (ms > 0) {
78
- const timer = setTimeout(() => dismiss(id), ms);
79
- timers.set(id, timer);
80
- }
81
- return id;
82
- };
83
- const success = (title, text) => show("success", title, text);
84
- const error = (title, text) => show("error", title, text);
85
- const warning = (title, text) => show("warning", title, text);
86
- const info = (title, text) => show("info", title, text);
87
- if (scope) {
88
- scope.onCleanup(() => {
89
- timers.forEach((t) => clearTimeout(t));
90
- timers.clear();
91
- });
92
- }
93
- return {
94
- items,
95
- activeVariant,
96
- containerClass,
97
- show,
98
- success,
99
- error,
100
- warning,
101
- info,
102
- dismiss,
103
- clear,
104
- };
105
- }
106
- export function toastIcon(variant) {
107
- return match(variant, {
108
- success: () => html `<span class="d-toast-icon">\u2705</span>`,
109
- error: () => html `<span class="d-toast-icon">\u274C</span>`,
110
- warning: () => html `<span class="d-toast-icon">\u26A0\uFE0F</span>`,
111
- info: () => html `<span class="d-toast-icon">\u2139\uFE0F</span>`,
112
- idle: () => isBrowser ? document.createComment("no toast") : null,
113
- _: () => isBrowser ? document.createComment("no toast") : null,
114
- });
115
- }
@@ -1,175 +0,0 @@
1
- import type { Signal } from "../core/signal.js";
2
- export interface DialogOptions {
3
- closeOnBackdrop?: boolean;
4
- closeOnEscape?: boolean;
5
- }
6
- export interface Dialog {
7
- open: Signal<boolean>;
8
- show(): void;
9
- close(): void;
10
- toggle(): void;
11
- _attachTo(el: HTMLDialogElement): void;
12
- }
13
- export type DrawerSide = "right" | "left" | "bottom";
14
- export interface DrawerOptions extends DialogOptions {
15
- side?: DrawerSide;
16
- }
17
- export interface Drawer extends Dialog {
18
- side: Signal<DrawerSide>;
19
- }
20
- export type ToastVariant = "success" | "error" | "warning" | "info";
21
- export type ToastPosition = "top-right" | "top-left" | "bottom-right" | "bottom-left" | "top-center" | "bottom-center";
22
- export interface ToastItem {
23
- id: string;
24
- variant: ToastVariant;
25
- title: string;
26
- text?: string;
27
- variantClass: string;
28
- icon: string;
29
- }
30
- export interface ToastOptions {
31
- position?: ToastPosition;
32
- duration?: number;
33
- maxToasts?: number;
34
- }
35
- export interface Toast {
36
- items: Signal<ToastItem[]>;
37
- activeVariant: Signal<ToastVariant | "idle">;
38
- containerClass: Signal<string>;
39
- show(variant: ToastVariant, title: string, text?: string, duration?: number): string;
40
- success(title: string, text?: string): string;
41
- error(title: string, text?: string): string;
42
- warning(title: string, text?: string): string;
43
- info(title: string, text?: string): string;
44
- dismiss(id: string): void;
45
- clear(): void;
46
- }
47
- export interface TabsOptions {
48
- initial?: string;
49
- orientation?: "horizontal" | "vertical";
50
- }
51
- export interface Tabs {
52
- active: Signal<string>;
53
- select(tabId: string): void;
54
- isActive(tabId: string): boolean;
55
- handleClick(ev: Event): void;
56
- _attachTo(el: HTMLElement): void;
57
- }
58
- export interface TabBindings {
59
- tabClass: Signal<string>;
60
- selected: Signal<string>;
61
- visible: Signal<boolean>;
62
- }
63
- export interface DropdownOptions {
64
- closeOnSelect?: boolean;
65
- }
66
- export interface Dropdown {
67
- open: Signal<boolean>;
68
- toggle(ev?: Event): void;
69
- close(): void;
70
- select(ev?: Event): void;
71
- _attachTo(el: HTMLElement): void;
72
- }
73
- export interface ComboboxOption {
74
- value: string;
75
- label: string;
76
- }
77
- export interface ComboboxOptions {
78
- options: ComboboxOption[];
79
- placeholder?: string;
80
- name?: string;
81
- }
82
- export interface Combobox {
83
- open: Signal<boolean>;
84
- query: Signal<string>;
85
- value: Signal<string>;
86
- label: Signal<string>;
87
- filtered: Signal<ComboboxOption[]>;
88
- highlightedIndex: Signal<number>;
89
- show(): void;
90
- close(): void;
91
- toggle(): void;
92
- handleInput(ev: Event): void;
93
- handleSelect(ev: Event): void;
94
- handleKeydown(ev: KeyboardEvent): void;
95
- _attachTo(el: HTMLElement): void;
96
- }
97
- export interface AccordionOptions {
98
- single?: boolean;
99
- initial?: string[];
100
- }
101
- export interface Accordion {
102
- openItems: Signal<Set<string>>;
103
- toggle(itemId: string): void;
104
- open(itemId: string): void;
105
- close(itemId: string): void;
106
- isOpen(itemId: string): Signal<boolean>;
107
- _attachTo(el: HTMLElement): void;
108
- }
109
- export interface CalendarDay {
110
- date: number;
111
- month: "prev" | "current" | "next";
112
- fullDate: Date;
113
- isToday: boolean;
114
- isSelected: boolean;
115
- disabled: boolean;
116
- }
117
- export interface CalendarOptions {
118
- initial?: Date;
119
- min?: Date;
120
- max?: Date;
121
- dayLabels?: string[];
122
- monthLabels?: string[];
123
- }
124
- export interface Calendar {
125
- year: Signal<number>;
126
- month: Signal<number>;
127
- selected: Signal<Date | null>;
128
- title: Signal<string>;
129
- days: Signal<CalendarDay[]>;
130
- dayLabels: string[];
131
- prev(): void;
132
- next(): void;
133
- select(date: Date): void;
134
- handleDayClick(ev: Event): void;
135
- }
136
- export interface DropzoneOptions {
137
- accept?: string;
138
- multiple?: boolean;
139
- maxFiles?: number;
140
- maxSize?: number;
141
- }
142
- export interface Dropzone {
143
- dragging: Signal<boolean>;
144
- files: Signal<File[]>;
145
- browse(): void;
146
- handleClick(): void;
147
- handleDragover(ev: DragEvent): void;
148
- handleDragleave(): void;
149
- handleDrop(ev: DragEvent): void;
150
- _attachTo(el: HTMLElement): void;
151
- }
152
- export type PopoverPlacement = "top" | "bottom" | "left" | "right" | "top-start" | "bottom-start";
153
- export interface PopoverOptions {
154
- placement?: PopoverPlacement;
155
- gap?: number;
156
- viewportPadding?: number;
157
- }
158
- export interface Popover {
159
- open: Signal<boolean>;
160
- placement: Signal<PopoverPlacement>;
161
- show(): void;
162
- hide(): void;
163
- toggle(): void;
164
- position(trigger: HTMLElement, popoverEl: HTMLElement): void;
165
- _attachTo(trigger: HTMLElement, popoverEl: HTMLElement): void;
166
- }
167
- export interface TabsMount {
168
- api: Tabs;
169
- bindings: [string, string][];
170
- }
171
- export interface PopoverMount {
172
- api: Popover;
173
- triggerId?: string;
174
- panelId?: string;
175
- }
@@ -1 +0,0 @@
1
- export {};
@@ -1,7 +0,0 @@
1
- export declare function validateDialogOptions(opts: Record<string, unknown>): void;
2
- export declare function validateDrawerOptions(opts: Record<string, unknown>): void;
3
- export declare function validateToastOptions(opts: Record<string, unknown>): void;
4
- export declare function validatePopoverOptions(opts: Record<string, unknown>): void;
5
- export declare function validateDropzoneOptions(opts: Record<string, unknown>): void;
6
- export declare function validateCalendarOptions(opts: Record<string, unknown>): void;
7
- export declare function validateComboboxOptions(opts: Record<string, unknown>): void;
@@ -1,71 +0,0 @@
1
- // ── Prop Validation ─────────────────────────────────────────────────
2
- const VALID_TOAST_POSITIONS = new Set([
3
- "top-right", "top-left", "bottom-right", "bottom-left", "top-center", "bottom-center",
4
- ]);
5
- const VALID_POPOVER_PLACEMENTS = new Set([
6
- "top", "bottom", "left", "right", "top-start", "bottom-start",
7
- ]);
8
- const VALID_DRAWER_SIDES = new Set(["right", "left", "bottom"]);
9
- function warn(component, message) {
10
- console.warn(`[Dalila] ${component}: ${message}`);
11
- }
12
- function warnInvalidType(component, prop, expected, got) {
13
- warn(component, `"${prop}" expected ${expected}, got ${typeof got} (${String(got)})`);
14
- }
15
- export function validateDialogOptions(opts) {
16
- if (opts.closeOnBackdrop !== undefined && typeof opts.closeOnBackdrop !== "boolean") {
17
- warnInvalidType("createDialog", "closeOnBackdrop", "boolean", opts.closeOnBackdrop);
18
- }
19
- if (opts.closeOnEscape !== undefined && typeof opts.closeOnEscape !== "boolean") {
20
- warnInvalidType("createDialog", "closeOnEscape", "boolean", opts.closeOnEscape);
21
- }
22
- }
23
- export function validateDrawerOptions(opts) {
24
- validateDialogOptions(opts);
25
- if (opts.side !== undefined && !VALID_DRAWER_SIDES.has(opts.side)) {
26
- warn("createDrawer", `"side" must be one of "right"|"left"|"bottom", got "${String(opts.side)}"`);
27
- }
28
- }
29
- export function validateToastOptions(opts) {
30
- if (opts.position !== undefined && !VALID_TOAST_POSITIONS.has(opts.position)) {
31
- warn("createToast", `"position" must be a valid ToastPosition, got "${String(opts.position)}"`);
32
- }
33
- if (opts.duration !== undefined && (typeof opts.duration !== "number" || opts.duration < 0)) {
34
- warn("createToast", `"duration" must be a number >= 0, got ${String(opts.duration)}`);
35
- }
36
- if (opts.maxToasts !== undefined && (typeof opts.maxToasts !== "number" || opts.maxToasts <= 0)) {
37
- warn("createToast", `"maxToasts" must be a number > 0, got ${String(opts.maxToasts)}`);
38
- }
39
- }
40
- export function validatePopoverOptions(opts) {
41
- if (opts.placement !== undefined && !VALID_POPOVER_PLACEMENTS.has(opts.placement)) {
42
- warn("createPopover", `"placement" must be a valid PopoverPlacement, got "${String(opts.placement)}"`);
43
- }
44
- if (opts.gap !== undefined && (typeof opts.gap !== "number" || opts.gap < 0)) {
45
- warn("createPopover", `"gap" must be a number >= 0, got ${String(opts.gap)}`);
46
- }
47
- if (opts.viewportPadding !== undefined && (typeof opts.viewportPadding !== "number" || opts.viewportPadding < 0)) {
48
- warn("createPopover", `"viewportPadding" must be a number >= 0, got ${String(opts.viewportPadding)}`);
49
- }
50
- }
51
- export function validateDropzoneOptions(opts) {
52
- if (opts.maxFiles !== undefined && (typeof opts.maxFiles !== "number" || opts.maxFiles <= 0)) {
53
- warn("createDropzone", `"maxFiles" must be a number > 0, got ${String(opts.maxFiles)}`);
54
- }
55
- if (opts.maxSize !== undefined && (typeof opts.maxSize !== "number" || opts.maxSize <= 0)) {
56
- warn("createDropzone", `"maxSize" must be a number > 0, got ${String(opts.maxSize)}`);
57
- }
58
- }
59
- export function validateCalendarOptions(opts) {
60
- const min = opts.min;
61
- const max = opts.max;
62
- if (min && max && min > max) {
63
- warn("createCalendar", `"min" must be before "max"`);
64
- }
65
- }
66
- export function validateComboboxOptions(opts) {
67
- const options = opts.options;
68
- if (!Array.isArray(options) || options.length === 0) {
69
- warn("createCombobox", `"options" must be a non-empty array`);
70
- }
71
- }