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,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/index.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;
@@ -0,0 +1,101 @@
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
+ }
@@ -0,0 +1,3 @@
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;
@@ -0,0 +1,115 @@
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
+ }