dalila 1.5.13 → 1.7.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 (137) hide show
  1. package/README.md +47 -0
  2. package/dist/componentes/ui/accordion/index.d.ts +2 -0
  3. package/dist/componentes/ui/accordion/index.js +114 -0
  4. package/dist/componentes/ui/calendar/index.d.ts +2 -0
  5. package/dist/componentes/ui/calendar/index.js +132 -0
  6. package/dist/componentes/ui/combobox/index.d.ts +2 -0
  7. package/dist/componentes/ui/combobox/index.js +161 -0
  8. package/dist/componentes/ui/dialog/index.d.ts +10 -0
  9. package/dist/componentes/ui/dialog/index.js +54 -0
  10. package/dist/componentes/ui/drawer/index.d.ts +2 -0
  11. package/dist/componentes/ui/drawer/index.js +41 -0
  12. package/dist/componentes/ui/dropdown/index.d.ts +2 -0
  13. package/dist/componentes/ui/dropdown/index.js +48 -0
  14. package/dist/componentes/ui/dropzone/index.d.ts +2 -0
  15. package/dist/componentes/ui/dropzone/index.js +92 -0
  16. package/dist/componentes/ui/env.d.ts +1 -0
  17. package/dist/componentes/ui/env.js +2 -0
  18. package/dist/componentes/ui/index.d.ts +13 -0
  19. package/dist/componentes/ui/index.js +12 -0
  20. package/dist/componentes/ui/popover/index.d.ts +2 -0
  21. package/dist/componentes/ui/popover/index.js +156 -0
  22. package/dist/componentes/ui/runtime.d.ts +20 -0
  23. package/dist/componentes/ui/runtime.js +421 -0
  24. package/dist/componentes/ui/tabs/index.d.ts +3 -0
  25. package/dist/componentes/ui/tabs/index.js +101 -0
  26. package/dist/componentes/ui/toast/index.d.ts +3 -0
  27. package/dist/componentes/ui/toast/index.js +115 -0
  28. package/dist/componentes/ui/ui-types.d.ts +175 -0
  29. package/dist/componentes/ui/ui-types.js +1 -0
  30. package/dist/componentes/ui/validate.d.ts +7 -0
  31. package/dist/componentes/ui/validate.js +71 -0
  32. package/dist/components/ui/accordion/index.d.ts +2 -0
  33. package/dist/components/ui/accordion/index.js +114 -0
  34. package/dist/components/ui/calendar/index.d.ts +2 -0
  35. package/dist/components/ui/calendar/index.js +132 -0
  36. package/dist/components/ui/combobox/index.d.ts +2 -0
  37. package/dist/components/ui/combobox/index.js +161 -0
  38. package/dist/components/ui/dialog/index.d.ts +10 -0
  39. package/dist/components/ui/dialog/index.js +54 -0
  40. package/dist/components/ui/drawer/index.d.ts +2 -0
  41. package/dist/components/ui/drawer/index.js +41 -0
  42. package/dist/components/ui/dropdown/index.d.ts +2 -0
  43. package/dist/components/ui/dropdown/index.js +48 -0
  44. package/dist/components/ui/dropzone/index.d.ts +2 -0
  45. package/dist/components/ui/dropzone/index.js +92 -0
  46. package/dist/components/ui/env.d.ts +1 -0
  47. package/dist/components/ui/env.js +2 -0
  48. package/dist/components/ui/index.d.ts +13 -0
  49. package/dist/components/ui/index.js +12 -0
  50. package/dist/components/ui/popover/index.d.ts +2 -0
  51. package/dist/components/ui/popover/index.js +156 -0
  52. package/dist/components/ui/runtime.d.ts +20 -0
  53. package/dist/components/ui/runtime.js +421 -0
  54. package/dist/components/ui/tabs/index.d.ts +3 -0
  55. package/dist/components/ui/tabs/index.js +101 -0
  56. package/dist/components/ui/toast/index.d.ts +3 -0
  57. package/dist/components/ui/toast/index.js +115 -0
  58. package/dist/components/ui/ui-types.d.ts +175 -0
  59. package/dist/components/ui/ui-types.js +1 -0
  60. package/dist/components/ui/validate.d.ts +7 -0
  61. package/dist/components/ui/validate.js +71 -0
  62. package/dist/form/form-types.d.ts +181 -0
  63. package/dist/form/form-types.js +4 -0
  64. package/dist/form/form.d.ts +71 -0
  65. package/dist/form/form.js +1073 -0
  66. package/dist/form/index.d.ts +2 -0
  67. package/dist/form/index.js +2 -0
  68. package/dist/index.d.ts +1 -0
  69. package/dist/index.js +1 -0
  70. package/dist/runtime/bind.js +567 -9
  71. package/dist/ui/accordion.d.ts +2 -0
  72. package/dist/ui/accordion.js +114 -0
  73. package/dist/ui/calendar.d.ts +2 -0
  74. package/dist/ui/calendar.js +132 -0
  75. package/dist/ui/combobox.d.ts +2 -0
  76. package/dist/ui/combobox.js +161 -0
  77. package/dist/ui/dialog.d.ts +10 -0
  78. package/dist/ui/dialog.js +54 -0
  79. package/dist/ui/drawer.d.ts +2 -0
  80. package/dist/ui/drawer.js +41 -0
  81. package/dist/ui/dropdown.d.ts +2 -0
  82. package/dist/ui/dropdown.js +48 -0
  83. package/dist/ui/dropzone.d.ts +2 -0
  84. package/dist/ui/dropzone.js +92 -0
  85. package/dist/ui/env.d.ts +1 -0
  86. package/dist/ui/env.js +2 -0
  87. package/dist/ui/index.d.ts +13 -0
  88. package/dist/ui/index.js +12 -0
  89. package/dist/ui/popover.d.ts +2 -0
  90. package/dist/ui/popover.js +156 -0
  91. package/dist/ui/runtime.d.ts +20 -0
  92. package/dist/ui/runtime.js +421 -0
  93. package/dist/ui/tabs.d.ts +3 -0
  94. package/dist/ui/tabs.js +101 -0
  95. package/dist/ui/toast.d.ts +3 -0
  96. package/dist/ui/toast.js +115 -0
  97. package/dist/ui/ui-types.d.ts +175 -0
  98. package/dist/ui/ui-types.js +1 -0
  99. package/dist/ui/validate.d.ts +7 -0
  100. package/dist/ui/validate.js +71 -0
  101. package/package.json +60 -2
  102. package/src/components/ui/accordion/accordion.css +90 -0
  103. package/src/components/ui/alert/alert.css +78 -0
  104. package/src/components/ui/avatar/avatar.css +45 -0
  105. package/src/components/ui/badge/badge.css +71 -0
  106. package/src/components/ui/breadcrumb/breadcrumb.css +41 -0
  107. package/src/components/ui/button/button.css +135 -0
  108. package/src/components/ui/calendar/calendar.css +96 -0
  109. package/src/components/ui/card/card.css +93 -0
  110. package/src/components/ui/checkbox/checkbox.css +57 -0
  111. package/src/components/ui/chip/chip.css +62 -0
  112. package/src/components/ui/collapsible/collapsible.css +61 -0
  113. package/src/components/ui/combobox/combobox.css +85 -0
  114. package/src/components/ui/dalila/dalila.css +42 -0
  115. package/src/components/ui/dalila-core/dalila-core.css +14 -0
  116. package/src/components/ui/dialog/dialog.css +125 -0
  117. package/src/components/ui/drawer/drawer.css +122 -0
  118. package/src/components/ui/dropdown/dropdown.css +87 -0
  119. package/src/components/ui/dropzone/dropzone.css +47 -0
  120. package/src/components/ui/empty-state/empty-state.css +33 -0
  121. package/src/components/ui/form/form.css +44 -0
  122. package/src/components/ui/input/input.css +106 -0
  123. package/src/components/ui/layout/layout.css +62 -0
  124. package/src/components/ui/pagination/pagination.css +55 -0
  125. package/src/components/ui/popover/popover.css +55 -0
  126. package/src/components/ui/radio/radio.css +56 -0
  127. package/src/components/ui/separator/separator.css +38 -0
  128. package/src/components/ui/skeleton/skeleton.css +57 -0
  129. package/src/components/ui/slider/slider.css +60 -0
  130. package/src/components/ui/spinner/spinner.css +38 -0
  131. package/src/components/ui/table/table.css +54 -0
  132. package/src/components/ui/tabs/tabs.css +74 -0
  133. package/src/components/ui/toast/toast.css +100 -0
  134. package/src/components/ui/toggle/toggle.css +90 -0
  135. package/src/components/ui/tokens/tokens.css +161 -0
  136. package/src/components/ui/tooltip/tooltip.css +53 -0
  137. package/src/components/ui/typography/typography.css +81 -0
@@ -0,0 +1,13 @@
1
+ export * from "./ui-types.js";
2
+ export { createDialog, _attachDialogBehavior } from "./dialog.js";
3
+ export { createDrawer } from "./drawer.js";
4
+ export { createToast, toastIcon } from "./toast.js";
5
+ export { createTabs, tabBindings } from "./tabs.js";
6
+ export { createDropdown } from "./dropdown.js";
7
+ export { createCombobox } from "./combobox.js";
8
+ export { createAccordion } from "./accordion.js";
9
+ export { createCalendar } from "./calendar.js";
10
+ export { createDropzone } from "./dropzone.js";
11
+ export { createPopover } from "./popover.js";
12
+ export { mountUI } from "./runtime.js";
13
+ export type { MountUIOptions } from "./runtime.js";
@@ -0,0 +1,12 @@
1
+ export * from "./ui-types.js";
2
+ export { createDialog, _attachDialogBehavior } from "./dialog.js";
3
+ export { createDrawer } from "./drawer.js";
4
+ export { createToast, toastIcon } from "./toast.js";
5
+ export { createTabs, tabBindings } from "./tabs.js";
6
+ export { createDropdown } from "./dropdown.js";
7
+ export { createCombobox } from "./combobox.js";
8
+ export { createAccordion } from "./accordion.js";
9
+ export { createCalendar } from "./calendar.js";
10
+ export { createDropzone } from "./dropzone.js";
11
+ export { createPopover } from "./popover.js";
12
+ export { mountUI } from "./runtime.js";
@@ -0,0 +1,2 @@
1
+ import type { Popover, PopoverOptions } from "./ui-types.js";
2
+ export declare function createPopover(options?: PopoverOptions): Popover;
@@ -0,0 +1,156 @@
1
+ import { signal } from "../core/signal.js";
2
+ import { getCurrentScope } from "../core/scope.js";
3
+ import { validatePopoverOptions } from "./validate.js";
4
+ import { isBrowser } from "./env.js";
5
+ let popoverUid = 0;
6
+ function computePosition(trigger, popoverEl, placement, gap, viewportPadding) {
7
+ const triggerRect = trigger.getBoundingClientRect();
8
+ const popRect = popoverEl.getBoundingClientRect();
9
+ const vw = isBrowser ? window.innerWidth : 1024;
10
+ const vh = isBrowser ? window.innerHeight : 768;
11
+ // ── Flip when not enough space ──
12
+ let effective = placement;
13
+ if (effective.startsWith("bottom") && triggerRect.bottom + gap + popRect.height > vh - viewportPadding) {
14
+ if (triggerRect.top - gap - popRect.height >= viewportPadding) {
15
+ effective = effective.replace("bottom", "top");
16
+ }
17
+ }
18
+ else if (effective.startsWith("top") && triggerRect.top - gap - popRect.height < viewportPadding) {
19
+ if (triggerRect.bottom + gap + popRect.height <= vh - viewportPadding) {
20
+ effective = effective.replace("top", "bottom");
21
+ }
22
+ }
23
+ else if (effective === "left" && triggerRect.left - gap - popRect.width < viewportPadding) {
24
+ if (triggerRect.right + gap + popRect.width <= vw - viewportPadding) {
25
+ effective = "right";
26
+ }
27
+ }
28
+ else if (effective === "right" && triggerRect.right + gap + popRect.width > vw - viewportPadding) {
29
+ if (triggerRect.left - gap - popRect.width >= viewportPadding) {
30
+ effective = "left";
31
+ }
32
+ }
33
+ let top = 0;
34
+ let left = 0;
35
+ switch (effective) {
36
+ case "bottom":
37
+ top = triggerRect.bottom + gap;
38
+ left = triggerRect.left + (triggerRect.width - popRect.width) / 2;
39
+ break;
40
+ case "bottom-start":
41
+ top = triggerRect.bottom + gap;
42
+ left = triggerRect.left;
43
+ break;
44
+ case "top":
45
+ top = triggerRect.top - popRect.height - gap;
46
+ left = triggerRect.left + (triggerRect.width - popRect.width) / 2;
47
+ break;
48
+ case "top-start":
49
+ top = triggerRect.top - popRect.height - gap;
50
+ left = triggerRect.left;
51
+ break;
52
+ case "left":
53
+ top = triggerRect.top + (triggerRect.height - popRect.height) / 2;
54
+ left = triggerRect.left - popRect.width - gap;
55
+ break;
56
+ case "right":
57
+ top = triggerRect.top + (triggerRect.height - popRect.height) / 2;
58
+ left = triggerRect.right + gap;
59
+ break;
60
+ }
61
+ // Viewport clamping
62
+ const maxLeft = vw - popRect.width - viewportPadding;
63
+ left = Math.min(Math.max(viewportPadding, left), Math.max(viewportPadding, maxLeft));
64
+ const maxTop = vh - popRect.height - viewportPadding;
65
+ top = Math.min(Math.max(viewportPadding, top), Math.max(viewportPadding, maxTop));
66
+ return { top, left };
67
+ }
68
+ export function createPopover(options = {}) {
69
+ validatePopoverOptions(options);
70
+ const { placement: initialPlacement = "bottom", gap = 8, viewportPadding = 12, } = options;
71
+ const open = signal(false);
72
+ const placement = signal(initialPlacement);
73
+ const show = () => open.set(true);
74
+ const hide = () => open.set(false);
75
+ const toggle = () => open.update((v) => !v);
76
+ const position = (trigger, popoverEl) => {
77
+ const { top, left } = computePosition(trigger, popoverEl, placement(), gap, viewportPadding);
78
+ popoverEl.style.position = "fixed";
79
+ popoverEl.style.top = `${top}px`;
80
+ popoverEl.style.left = `${left}px`;
81
+ };
82
+ const _attachTo = (trigger, popoverEl) => {
83
+ const scope = getCurrentScope();
84
+ // Ensure popover attribute for native API
85
+ if (!popoverEl.hasAttribute("popover")) {
86
+ popoverEl.setAttribute("popover", "manual");
87
+ }
88
+ const reposition = () => {
89
+ try {
90
+ if (!popoverEl.matches(":popover-open"))
91
+ return;
92
+ }
93
+ catch {
94
+ return;
95
+ }
96
+ position(trigger, popoverEl);
97
+ };
98
+ // Sync open signal → native popover
99
+ const unsub = open.on((isOpen) => {
100
+ try {
101
+ const isNativeOpen = popoverEl.matches(":popover-open");
102
+ if (isOpen && !isNativeOpen) {
103
+ popoverEl.showPopover();
104
+ reposition();
105
+ }
106
+ else if (!isOpen && isNativeOpen) {
107
+ popoverEl.hidePopover();
108
+ }
109
+ }
110
+ catch {
111
+ // Popover API not supported or element not connected
112
+ }
113
+ });
114
+ // Sync native toggle → signal
115
+ const onToggle = (ev) => {
116
+ const state = ev.newState;
117
+ if (state === "open") {
118
+ if (!open.peek())
119
+ open.set(true);
120
+ reposition();
121
+ }
122
+ else {
123
+ if (open.peek())
124
+ open.set(false);
125
+ }
126
+ };
127
+ popoverEl.addEventListener("toggle", onToggle);
128
+ // Reposition on scroll/resize
129
+ if (isBrowser) {
130
+ window.addEventListener("resize", reposition);
131
+ window.addEventListener("scroll", reposition, { passive: true });
132
+ }
133
+ // ARIA
134
+ const popoverId = popoverEl.id || `d-popover-${++popoverUid}`;
135
+ if (!popoverEl.id)
136
+ popoverEl.id = popoverId;
137
+ trigger.setAttribute("aria-controls", popoverId);
138
+ trigger.setAttribute("aria-expanded", "false");
139
+ trigger.setAttribute("aria-haspopup", "true");
140
+ const unsubAria = open.on((isOpen) => {
141
+ trigger.setAttribute("aria-expanded", String(isOpen));
142
+ });
143
+ if (scope) {
144
+ scope.onCleanup(() => {
145
+ unsub();
146
+ unsubAria();
147
+ popoverEl.removeEventListener("toggle", onToggle);
148
+ if (isBrowser) {
149
+ window.removeEventListener("resize", reposition);
150
+ window.removeEventListener("scroll", reposition);
151
+ }
152
+ });
153
+ }
154
+ };
155
+ return { open, show, hide, toggle, placement, position, _attachTo };
156
+ }
@@ -0,0 +1,20 @@
1
+ import { type Signal } from "../core/signal.js";
2
+ import { type BindContext } from "../runtime/bind.js";
3
+ import type { Calendar, Combobox, Dialog, Drawer, Dropdown, Dropzone, PopoverMount, TabsMount, Toast } from "./ui-types.js";
4
+ export interface MountUIOptions {
5
+ context?: BindContext;
6
+ events?: string[];
7
+ theme?: boolean;
8
+ sliderValue?: Signal<string>;
9
+ dialogs?: Record<string, Dialog>;
10
+ drawers?: Record<string, Drawer>;
11
+ dropdowns?: Record<string, Dropdown>;
12
+ combos?: Record<string, Combobox>;
13
+ tabs?: Record<string, TabsMount>;
14
+ toasts?: Record<string, Toast>;
15
+ popovers?: Record<string, PopoverMount>;
16
+ dropzones?: Record<string, Dropzone>;
17
+ calendars?: Record<string, Calendar>;
18
+ accordions?: Record<string, import("./ui-types.js").Accordion>;
19
+ }
20
+ export declare function mountUI(root: Element, options: MountUIOptions): () => void;
@@ -0,0 +1,421 @@
1
+ import { computed, signal } from "../core/signal.js";
2
+ import { createScope, withScope } from "../core/scope.js";
3
+ import { bind } from "../runtime/bind.js";
4
+ import { tabBindings } from "./tabs.js";
5
+ import { isBrowser } from "./env.js";
6
+ // ── Constants ───────────────────────────────────────────────────────
7
+ const DEFAULT_EVENTS = [
8
+ "click", "input", "change", "submit",
9
+ "keydown", "keyup", "focus",
10
+ "dragover", "dragleave", "drop",
11
+ ];
12
+ const DEFAULT_TOAST_VARIANTS = ["success", "error", "warning", "info"];
13
+ // ── Tag Aliases ─────────────────────────────────────────────────────
14
+ const TAG_ALIASES = {
15
+ "d-h1": "h1", "d-h2": "h2", "d-h3": "h3", "d-h4": "h4", "d-h5": "h5", "d-h6": "h6",
16
+ "d-text": "p", "d-link": "a", "d-code-inline": "span", "d-kbd": "span",
17
+ "d-field": "label", "d-field-label": "span", "d-field-hint": "span", "d-field-error": "span",
18
+ "d-input": "input", "d-button-group": "div", "d-select": "select", "d-textarea": "textarea",
19
+ "d-checkbox": "label", "d-radio-group": "div", "d-radio": "label",
20
+ "d-slider": "input", "d-toggle": "label", "d-toggle-track": "span",
21
+ "d-form": "form", "d-form-row": "div", "d-form-section-title": "h3", "d-form-actions": "div",
22
+ "d-card": "div", "d-card-section": "div", "d-card-header": "div", "d-card-title": "h3",
23
+ "d-card-description": "p", "d-card-body": "div", "d-card-footer": "div",
24
+ "d-badge": "span", "d-chip": "span", "d-chip-remove": "button",
25
+ "d-avatar": "div", "d-avatar-group": "div",
26
+ "d-alert": "div", "d-alert-title": "strong", "d-alert-text": "p",
27
+ "d-tooltip-trigger": "button",
28
+ "d-accordion": "div", "d-accordion-item": "details", "d-accordion-body": "div",
29
+ "d-collapsible": "details", "d-collapsible-body": "div",
30
+ "d-table-wrapper": "div", "d-table": "table",
31
+ "d-pagination": "nav", "d-page": "button", "d-page-ellipsis": "span",
32
+ "d-breadcrumb": "ol", "d-breadcrumb-item": "li",
33
+ "d-separator": "hr", "d-separator-label": "div",
34
+ "d-skeleton": "div", "d-loading": "div", "d-spinner": "span",
35
+ "d-empty": "div", "d-empty-icon": "div", "d-empty-title": "h3", "d-empty-text": "p",
36
+ "d-stack": "div", "d-flex": "div", "d-grid": "div",
37
+ "d-dialog": "dialog", "d-dialog-header": "div", "d-dialog-title": "h3",
38
+ "d-dialog-body": "div", "d-dialog-footer": "div", "d-dialog-close": "button",
39
+ "d-drawer": "dialog", "d-drawer-header": "div", "d-drawer-title": "h3",
40
+ "d-drawer-body": "div", "d-drawer-footer": "div",
41
+ "d-sheet": "dialog", "d-button": "button",
42
+ "d-toast-container": "div", "d-toast": "div", "d-toast-icon": "div",
43
+ "d-toast-body": "div", "d-toast-title": "div", "d-toast-text": "p", "d-toast-close": "button",
44
+ "d-popover-trigger": "button",
45
+ "d-dropdown": "div", "d-menu": "div", "d-menu-label": "div",
46
+ "d-menu-item": "button", "d-menu-separator": "div",
47
+ "d-combobox": "div", "d-combobox-input": "input", "d-combobox-trigger": "button",
48
+ "d-combobox-list": "ul", "d-combobox-option": "li",
49
+ "d-tabs": "div", "d-tab-list": "div", "d-tab": "button", "d-tab-panel": "div",
50
+ "d-calendar": "div", "d-calendar-header": "div", "d-calendar-nav": "button",
51
+ "d-calendar-title": "span", "d-calendar-grid": "div",
52
+ "d-calendar-dow": "span", "d-calendar-day": "button",
53
+ "d-dropzone": "div", "d-dropzone-icon": "div", "d-dropzone-text": "p", "d-dropzone-hint": "p",
54
+ "d-popover": "div", "d-popover-title": "p", "d-popover-text": "p",
55
+ };
56
+ const TAG_DEFAULT_CLASS = {
57
+ "d-h1": "d-h1", "d-h2": "d-h2", "d-h3": "d-h3", "d-h4": "d-h4", "d-h5": "d-h5", "d-h6": "d-h6",
58
+ "d-text": "d-text", "d-link": "d-link", "d-code-inline": "d-code", "d-kbd": "d-kbd",
59
+ "d-field": "d-field", "d-field-label": "d-field-label", "d-field-hint": "d-field-hint", "d-field-error": "d-field-error",
60
+ "d-input": "d-input", "d-button-group": "d-btn-group", "d-select": "d-select", "d-textarea": "d-textarea",
61
+ "d-checkbox": "d-checkbox", "d-radio-group": "d-radio-group", "d-radio": "d-radio",
62
+ "d-slider": "d-slider", "d-toggle": "d-toggle", "d-toggle-track": "d-toggle-track",
63
+ "d-form": "d-form", "d-form-row": "d-form-row", "d-form-section-title": "d-form-section-title", "d-form-actions": "d-form-actions",
64
+ "d-card": "d-card", "d-card-section": "d-card-section", "d-card-header": "d-card-header", "d-card-title": "d-card-title",
65
+ "d-card-description": "d-card-description", "d-card-body": "d-card-body", "d-card-footer": "d-card-footer",
66
+ "d-badge": "d-badge", "d-chip": "d-chip", "d-chip-remove": "d-chip-remove",
67
+ "d-avatar": "d-avatar", "d-avatar-group": "d-avatar-group",
68
+ "d-alert": "d-alert", "d-alert-title": "d-alert-title", "d-alert-text": "d-alert-text",
69
+ "d-tooltip-trigger": "d-btn d-tooltip",
70
+ "d-accordion": "d-accordion", "d-accordion-item": "d-accordion-item", "d-accordion-body": "d-accordion-body",
71
+ "d-collapsible": "d-collapsible", "d-collapsible-body": "d-collapsible-body",
72
+ "d-table-wrapper": "d-table-wrapper", "d-table": "d-table",
73
+ "d-pagination": "d-pagination", "d-page": "d-page", "d-page-ellipsis": "d-page-ellipsis",
74
+ "d-breadcrumb": "d-breadcrumb", "d-breadcrumb-item": "d-breadcrumb-item",
75
+ "d-separator": "d-separator", "d-separator-label": "d-separator-label",
76
+ "d-skeleton": "d-skeleton", "d-loading": "d-loading", "d-spinner": "d-spinner",
77
+ "d-empty": "d-empty", "d-empty-icon": "d-empty-icon", "d-empty-title": "d-empty-title", "d-empty-text": "d-empty-text",
78
+ "d-stack": "d-stack", "d-flex": "d-flex", "d-grid": "d-grid",
79
+ "d-button": "d-btn",
80
+ "d-toast-container": "d-toast-container", "d-toast": "d-toast", "d-toast-icon": "d-toast-icon",
81
+ "d-toast-body": "d-toast-body", "d-toast-title": "d-toast-title", "d-toast-text": "d-toast-text", "d-toast-close": "d-toast-close",
82
+ "d-popover-trigger": "d-btn d-btn-primary",
83
+ "d-dialog": "d-dialog", "d-dialog-header": "d-dialog-header", "d-dialog-title": "d-dialog-title",
84
+ "d-dialog-body": "d-dialog-body", "d-dialog-footer": "d-dialog-footer", "d-dialog-close": "d-dialog-close",
85
+ "d-drawer": "d-drawer", "d-sheet": "d-drawer d-sheet",
86
+ "d-drawer-header": "d-drawer-header", "d-drawer-title": "d-drawer-title",
87
+ "d-drawer-body": "d-drawer-body", "d-drawer-footer": "d-drawer-footer",
88
+ "d-dropdown": "d-dropdown", "d-menu": "d-menu", "d-menu-label": "d-menu-label",
89
+ "d-menu-item": "d-menu-item", "d-menu-separator": "d-menu-separator",
90
+ "d-combobox": "d-combobox", "d-combobox-input": "d-input d-combobox-input",
91
+ "d-combobox-trigger": "d-combobox-trigger", "d-combobox-list": "d-combobox-list", "d-combobox-option": "d-combobox-option",
92
+ "d-tabs": "d-tabs", "d-tab-list": "d-tab-list", "d-tab": "d-tab", "d-tab-panel": "d-tab-panel",
93
+ "d-calendar": "d-calendar", "d-calendar-header": "d-calendar-header", "d-calendar-nav": "d-calendar-nav",
94
+ "d-calendar-title": "d-calendar-title", "d-calendar-grid": "d-calendar-grid", "d-calendar-dow": "d-calendar-dow", "d-calendar-day": "d-calendar-day",
95
+ "d-dropzone": "d-dropzone", "d-dropzone-icon": "d-dropzone-icon", "d-dropzone-text": "d-dropzone-text", "d-dropzone-hint": "d-dropzone-hint",
96
+ "d-popover": "d-popover", "d-popover-title": "d-popover-title", "d-popover-text": "d-popover-text",
97
+ };
98
+ const TAG_UPGRADE_RULES = {
99
+ "d-button": { attrs: { variant: "d-btn-{}", size: "d-btn-{}" }, flags: { icon: "d-btn-icon" }, defaultType: "button" },
100
+ "d-text": { attrs: { tone: "d-text-{}", size: "d-text-{}" } },
101
+ "d-link": { attrs: { tone: "d-link-{}" } },
102
+ "d-radio-group": { attrs: { variant: "d-radio-group-{}" } },
103
+ "d-toggle": { attrs: { size: "d-toggle-{}" } },
104
+ "d-form-actions": { attrs: { align: "d-form-actions-{}" } },
105
+ "d-card": { attrs: { variant: "d-card-{}" } },
106
+ "d-badge": { attrs: { variant: "d-badge-{}" }, flags: { dot: "d-badge-dot" } },
107
+ "d-chip": { attrs: { variant: "d-chip-{}" } },
108
+ "d-avatar": { attrs: { size: "d-avatar-{}", shape: "d-avatar-{}" } },
109
+ "d-alert": { attrs: { variant: "d-alert-{}" } },
110
+ "d-tooltip-trigger": { attrs: { place: "d-tooltip-{}" }, defaultType: "button" },
111
+ "d-skeleton": { attrs: { kind: "d-skeleton-{}" } },
112
+ "d-spinner": { attrs: { size: "d-spinner-{}" } },
113
+ "d-stack": { attrs: { gap: "d-stack-{}" } },
114
+ "d-flex": { flags: { wrap: "d-flex-wrap" } },
115
+ "d-grid": { attrs: { cols: "d-grid-{}" } },
116
+ "d-tab-list": { attrs: { variant: "d-tab-list-{}" } },
117
+ "d-menu-item": { attrs: { variant: "d-menu-item-{}" }, defaultType: "button" },
118
+ "d-chip-remove": { defaultType: "button" },
119
+ "d-page": { defaultType: "button" },
120
+ "d-toast-close": { defaultType: "button" },
121
+ "d-popover-trigger": { defaultType: "button" },
122
+ "d-dialog-close": { defaultType: "button" },
123
+ "d-combobox-trigger": { defaultType: "button" },
124
+ "d-tab": { defaultType: "button" },
125
+ "d-calendar-nav": { defaultType: "button" },
126
+ "d-calendar-day": { defaultType: "button" },
127
+ "d-combobox-input": { defaultType: "text" },
128
+ };
129
+ // ── Tag upgrade engine ──────────────────────────────────────────────
130
+ function upgradeDalilaTags(root) {
131
+ if (!isBrowser)
132
+ return root;
133
+ let currentRoot = root;
134
+ for (const [sourceTag, targetTag] of Object.entries(TAG_ALIASES)) {
135
+ const nodes = [];
136
+ if (currentRoot.matches(sourceTag))
137
+ nodes.push(currentRoot);
138
+ nodes.push(...Array.from(currentRoot.querySelectorAll(sourceTag)));
139
+ for (const node of nodes) {
140
+ const replacement = currentRoot.ownerDocument.createElement(targetTag);
141
+ for (const attr of Array.from(node.attributes)) {
142
+ replacement.setAttribute(attr.name, attr.value);
143
+ }
144
+ replacement.setAttribute("data-d-tag", sourceTag);
145
+ const defaultClass = TAG_DEFAULT_CLASS[sourceTag];
146
+ if (defaultClass) {
147
+ const current = replacement.getAttribute("class");
148
+ replacement.setAttribute("class", current ? `${defaultClass} ${current}` : defaultClass);
149
+ }
150
+ const rule = TAG_UPGRADE_RULES[sourceTag];
151
+ if (rule) {
152
+ // Default type attribute
153
+ if (rule.defaultType && !replacement.hasAttribute("type")) {
154
+ replacement.setAttribute("type", rule.defaultType);
155
+ }
156
+ // Attribute → class mappings
157
+ if (rule.attrs) {
158
+ for (const [attr, template] of Object.entries(rule.attrs)) {
159
+ const val = replacement.getAttribute(attr);
160
+ if (val) {
161
+ replacement.classList.add(template.replace("{}", val));
162
+ replacement.removeAttribute(attr);
163
+ }
164
+ }
165
+ }
166
+ // Boolean flag → class mappings
167
+ if (rule.flags) {
168
+ for (const [attr, className] of Object.entries(rule.flags)) {
169
+ if (replacement.hasAttribute(attr)) {
170
+ replacement.classList.add(className);
171
+ replacement.removeAttribute(attr);
172
+ }
173
+ }
174
+ }
175
+ }
176
+ while (node.firstChild)
177
+ replacement.appendChild(node.firstChild);
178
+ node.replaceWith(replacement);
179
+ if (node === currentRoot) {
180
+ currentRoot = replacement;
181
+ }
182
+ }
183
+ }
184
+ return currentRoot;
185
+ }
186
+ // ── Element discovery ───────────────────────────────────────────────
187
+ function findByUI(root, name, fallbackTag) {
188
+ // 0. Root itself
189
+ if (root instanceof HTMLElement) {
190
+ if (root.getAttribute("d-ui") === name)
191
+ return root;
192
+ if (fallbackTag && root.getAttribute("data-d-tag") === fallbackTag)
193
+ return root;
194
+ }
195
+ // 1. d-ui attribute
196
+ let el = root.querySelector(`[d-ui="${name}"]`);
197
+ if (el)
198
+ return el;
199
+ // 2. ID match
200
+ el = root.ownerDocument.getElementById(name);
201
+ if (el && root.contains(el))
202
+ return el;
203
+ // 3. Fallback: first matching data-d-tag
204
+ if (fallbackTag) {
205
+ el = root.querySelector(`[data-d-tag="${fallbackTag}"]`);
206
+ if (el)
207
+ return el;
208
+ }
209
+ return null;
210
+ }
211
+ function findPopoverTrigger(root, id) {
212
+ if (id)
213
+ return root.ownerDocument.getElementById(id);
214
+ return (root.querySelector(`[d-ui="popover-trigger"]`) ??
215
+ root.querySelector(`[data-d-tag="d-popover-trigger"]`) ??
216
+ null);
217
+ }
218
+ function findPopoverPanel(root, id) {
219
+ if (id)
220
+ return root.ownerDocument.getElementById(id);
221
+ return (root.querySelector(`[d-ui="popover"]`) ??
222
+ root.querySelector(`[data-d-tag="d-popover"]`) ??
223
+ root.querySelector(`[popover]`) ??
224
+ null);
225
+ }
226
+ // ── Context binding generators ──────────────────────────────────────
227
+ function capitalize(s) {
228
+ return s.charAt(0).toUpperCase() + s.slice(1);
229
+ }
230
+ function addDialogBindings(ctx, key, dialog) {
231
+ ctx[`${key}Show`] = dialog.show;
232
+ ctx[`${key}Close`] = dialog.close;
233
+ ctx[`${key}Open`] = dialog.open;
234
+ }
235
+ function addDropdownBindings(ctx, key, dd) {
236
+ ctx[`${key}Class`] = computed(() => dd.open() ? "d-dropdown open" : "d-dropdown");
237
+ ctx[`${key}Toggle`] = dd.toggle;
238
+ ctx[`${key}Select`] = dd.select;
239
+ }
240
+ function addComboBindings(ctx, key, combo) {
241
+ ctx[`${key}Class`] = computed(() => combo.open() ? "d-combobox open" : "d-combobox");
242
+ ctx[`${key}Items`] = computed(() => {
243
+ const items = combo.filtered();
244
+ const hi = combo.highlightedIndex();
245
+ const sel = combo.value();
246
+ return items.map((opt, i) => ({
247
+ value: opt.value,
248
+ label: opt.label,
249
+ optionClass: "d-combobox-option" + (opt.value === sel ? " selected" : "") + (i === hi ? " highlighted" : ""),
250
+ }));
251
+ });
252
+ ctx[`${key}Label`] = combo.label;
253
+ ctx[`${key}Input`] = combo.handleInput;
254
+ ctx[`${key}Show`] = combo.show;
255
+ ctx[`${key}Trigger`] = (ev) => {
256
+ ev.stopPropagation();
257
+ combo.toggle();
258
+ };
259
+ ctx[`${key}Select`] = combo.handleSelect;
260
+ ctx[`${key}Keydown`] = combo.handleKeydown;
261
+ }
262
+ function addTabsBindings(ctx, key, mount) {
263
+ ctx[`${key}Click`] = mount.api.handleClick;
264
+ for (const [bindKey, tabId] of mount.bindings) {
265
+ const b = tabBindings(mount.api, tabId);
266
+ ctx[`${bindKey}Class`] = b.tabClass;
267
+ ctx[`${bindKey}Visible`] = b.visible;
268
+ }
269
+ }
270
+ function addToastBindings(ctx, key, toast) {
271
+ let cycle = 0;
272
+ ctx[`${key}ContainerClass`] = toast.containerClass;
273
+ ctx[`${key}Items`] = toast.items;
274
+ ctx[`show${capitalize(key)}`] = () => {
275
+ const variant = DEFAULT_TOAST_VARIANTS[cycle++ % DEFAULT_TOAST_VARIANTS.length];
276
+ toast.show(variant, variant.charAt(0).toUpperCase() + variant.slice(1), `This is a ${variant} toast notification.`);
277
+ };
278
+ ctx[`dismiss${capitalize(key)}`] = (ev) => {
279
+ const target = ev.currentTarget;
280
+ const id = target.dataset.id;
281
+ if (id)
282
+ toast.dismiss(id);
283
+ };
284
+ }
285
+ function addCalendarBindings(ctx, key, cal) {
286
+ ctx[`${key}Title`] = cal.title;
287
+ ctx[`${key}Days`] = computed(() => cal.days().map((day) => ({
288
+ date: day.date,
289
+ dayClass: ["d-calendar-day", day.month !== "current" ? "other-month" : "", day.isToday ? "today" : "", day.isSelected ? "selected" : ""]
290
+ .filter(Boolean)
291
+ .join(" "),
292
+ dateStr: day.fullDate.toISOString(),
293
+ isDisabled: day.disabled || day.month !== "current",
294
+ })));
295
+ ctx[`${key}Prev`] = cal.prev;
296
+ ctx[`${key}Next`] = cal.next;
297
+ ctx[`${key}DayClick`] = cal.handleDayClick;
298
+ }
299
+ function addDropzoneBindings(ctx, key, dz) {
300
+ ctx[`${key}Class`] = computed(() => dz.dragging() ? "d-dropzone dragover" : "d-dropzone");
301
+ ctx[`${key}Click`] = dz.handleClick;
302
+ ctx[`${key}Dragover`] = dz.handleDragover;
303
+ ctx[`${key}Dragleave`] = dz.handleDragleave;
304
+ ctx[`${key}Drop`] = dz.handleDrop;
305
+ }
306
+ // ── mountUI ─────────────────────────────────────────────────────────
307
+ export function mountUI(root, options) {
308
+ if (!isBrowser)
309
+ return () => { };
310
+ const mountedRoot = upgradeDalilaTags(root);
311
+ const sliderValue = options.sliderValue ?? signal("50");
312
+ const ctx = { ...(options.context ?? {}) };
313
+ const cleanups = [];
314
+ const scope = createScope();
315
+ // Theme toggle
316
+ if (options.theme !== false) {
317
+ ctx.onThemeToggle = (ev) => {
318
+ const target = ev.target;
319
+ mountedRoot.ownerDocument.documentElement.setAttribute("data-theme", target.checked ? "dark" : "");
320
+ };
321
+ }
322
+ // Slider
323
+ ctx.sliderValue = sliderValue;
324
+ ctx.onSliderInput = (ev) => {
325
+ const target = ev.target;
326
+ sliderValue.set(target.value);
327
+ };
328
+ // ── Phase 1: Generate context bindings ──
329
+ for (const [key, dialog] of Object.entries(options.dialogs ?? {})) {
330
+ addDialogBindings(ctx, key, dialog);
331
+ }
332
+ for (const [key, drawer] of Object.entries(options.drawers ?? {})) {
333
+ addDialogBindings(ctx, key, drawer);
334
+ }
335
+ for (const [key, dd] of Object.entries(options.dropdowns ?? {})) {
336
+ addDropdownBindings(ctx, key, dd);
337
+ }
338
+ for (const [key, combo] of Object.entries(options.combos ?? {})) {
339
+ addComboBindings(ctx, key, combo);
340
+ }
341
+ for (const [key, mount] of Object.entries(options.tabs ?? {})) {
342
+ addTabsBindings(ctx, key, mount);
343
+ }
344
+ for (const [key, toast] of Object.entries(options.toasts ?? {})) {
345
+ addToastBindings(ctx, key, toast);
346
+ }
347
+ for (const [key, cal] of Object.entries(options.calendars ?? {})) {
348
+ addCalendarBindings(ctx, key, cal);
349
+ }
350
+ for (const [key, dz] of Object.entries(options.dropzones ?? {})) {
351
+ addDropzoneBindings(ctx, key, dz);
352
+ }
353
+ // ── Phase 2: Bind + attach to DOM ──
354
+ withScope(scope, () => {
355
+ cleanups.push(bind(mountedRoot, ctx, {
356
+ events: options.events ?? DEFAULT_EVENTS,
357
+ }));
358
+ // Attach dialogs
359
+ for (const [key, dialog] of Object.entries(options.dialogs ?? {})) {
360
+ const el = findByUI(mountedRoot, key, "d-dialog");
361
+ if (el)
362
+ dialog._attachTo(el);
363
+ }
364
+ // Attach drawers
365
+ for (const [key, drawer] of Object.entries(options.drawers ?? {})) {
366
+ const el = findByUI(mountedRoot, key, "d-drawer");
367
+ if (el)
368
+ drawer._attachTo(el);
369
+ }
370
+ // Attach dropdowns
371
+ for (const [key, dd] of Object.entries(options.dropdowns ?? {})) {
372
+ const el = findByUI(mountedRoot, key, "d-dropdown");
373
+ if (el)
374
+ dd._attachTo(el);
375
+ }
376
+ // Attach combos
377
+ for (const [key, combo] of Object.entries(options.combos ?? {})) {
378
+ const el = findByUI(mountedRoot, key, "d-combobox");
379
+ if (el)
380
+ combo._attachTo(el);
381
+ }
382
+ // Attach tabs
383
+ for (const [key, mount] of Object.entries(options.tabs ?? {})) {
384
+ const el = findByUI(mountedRoot, key, "d-tabs");
385
+ if (el)
386
+ mount.api._attachTo(el);
387
+ }
388
+ // Attach dropzones
389
+ for (const [key, dz] of Object.entries(options.dropzones ?? {})) {
390
+ const el = findByUI(mountedRoot, key, "d-dropzone");
391
+ if (el)
392
+ dz._attachTo(el);
393
+ }
394
+ // Attach accordions
395
+ for (const [key, acc] of Object.entries(options.accordions ?? {})) {
396
+ const el = findByUI(mountedRoot, key, "d-accordion");
397
+ if (el)
398
+ acc._attachTo(el);
399
+ }
400
+ });
401
+ // Attach popovers (outside scope — manages its own listeners)
402
+ for (const [key, mount] of Object.entries(options.popovers ?? {})) {
403
+ const triggerEl = findPopoverTrigger(mountedRoot, mount.triggerId) ??
404
+ findByUI(mountedRoot, `${key}-trigger`);
405
+ const panelEl = findPopoverPanel(mountedRoot, mount.panelId) ??
406
+ findByUI(mountedRoot, key, "d-popover");
407
+ if (triggerEl && panelEl) {
408
+ withScope(scope, () => {
409
+ mount.api._attachTo(triggerEl, panelEl);
410
+ });
411
+ }
412
+ }
413
+ return () => {
414
+ while (cleanups.length > 0) {
415
+ const cleanup = cleanups.pop();
416
+ if (cleanup)
417
+ cleanup();
418
+ }
419
+ scope.dispose();
420
+ };
421
+ }
@@ -0,0 +1,3 @@
1
+ import type { Tabs, TabBindings, TabsOptions } from "./ui-types.js";
2
+ export declare function createTabs(options?: TabsOptions): Tabs;
3
+ export declare function tabBindings(tabs: Tabs, tabId: string): TabBindings;