juxscript 1.1.4 → 1.1.6

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 (205) hide show
  1. package/index.d.ts +10 -10
  2. package/index.d.ts.map +1 -0
  3. package/lib/components/alert.d.ts +32 -0
  4. package/lib/components/alert.d.ts.map +1 -0
  5. package/lib/components/alert.js +153 -0
  6. package/lib/components/alert.ts +200 -0
  7. package/lib/components/app.d.ts +89 -0
  8. package/lib/components/app.d.ts.map +1 -0
  9. package/lib/components/app.js +175 -0
  10. package/lib/components/app.ts +247 -0
  11. package/lib/components/badge.d.ts +27 -0
  12. package/lib/components/badge.d.ts.map +1 -0
  13. package/lib/components/badge.js +70 -0
  14. package/lib/components/badge.ts +101 -0
  15. package/lib/components/base/BaseComponent.d.ts +142 -0
  16. package/lib/components/base/BaseComponent.d.ts.map +1 -0
  17. package/lib/components/base/BaseComponent.js +363 -0
  18. package/lib/components/base/BaseComponent.ts +421 -0
  19. package/lib/components/base/FormInput.d.ts +73 -0
  20. package/lib/components/base/FormInput.d.ts.map +1 -0
  21. package/lib/components/base/FormInput.js +163 -0
  22. package/lib/components/base/FormInput.ts +227 -0
  23. package/lib/components/button.d.ts +48 -0
  24. package/lib/components/button.d.ts.map +1 -0
  25. package/lib/components/button.js +121 -0
  26. package/lib/components/button.ts +178 -0
  27. package/lib/components/card.d.ts +34 -0
  28. package/lib/components/card.d.ts.map +1 -0
  29. package/lib/components/card.js +127 -0
  30. package/lib/components/card.ts +173 -0
  31. package/lib/components/chart.d.ts +45 -0
  32. package/lib/components/chart.d.ts.map +1 -0
  33. package/lib/components/chart.js +186 -0
  34. package/lib/components/chart.ts +231 -0
  35. package/lib/components/checkbox.d.ts +31 -0
  36. package/lib/components/checkbox.d.ts.map +1 -0
  37. package/lib/components/checkbox.js +185 -0
  38. package/lib/components/checkbox.ts +242 -0
  39. package/lib/components/code.d.ts +24 -0
  40. package/lib/components/code.d.ts.map +1 -0
  41. package/lib/components/code.js +88 -0
  42. package/lib/components/code.ts +123 -0
  43. package/lib/components/container.d.ts +42 -0
  44. package/lib/components/container.d.ts.map +1 -0
  45. package/lib/components/container.js +93 -0
  46. package/lib/components/container.ts +140 -0
  47. package/lib/components/data.d.ts +36 -0
  48. package/lib/components/data.d.ts.map +1 -0
  49. package/lib/components/data.js +110 -0
  50. package/lib/components/data.ts +135 -0
  51. package/lib/components/datepicker.d.ts +38 -0
  52. package/lib/components/datepicker.d.ts.map +1 -0
  53. package/lib/components/datepicker.js +177 -0
  54. package/lib/components/datepicker.ts +234 -0
  55. package/lib/components/dialog.d.ts +38 -0
  56. package/lib/components/dialog.d.ts.map +1 -0
  57. package/lib/components/dialog.js +126 -0
  58. package/lib/components/dialog.ts +172 -0
  59. package/lib/components/divider.d.ts +30 -0
  60. package/lib/components/divider.d.ts.map +1 -0
  61. package/lib/components/divider.js +69 -0
  62. package/lib/components/divider.ts +100 -0
  63. package/lib/components/dropdown.d.ts +39 -0
  64. package/lib/components/dropdown.d.ts.map +1 -0
  65. package/lib/components/dropdown.js +133 -0
  66. package/lib/components/dropdown.ts +186 -0
  67. package/lib/components/element.d.ts +50 -0
  68. package/lib/components/element.d.ts.map +1 -0
  69. package/lib/components/element.js +206 -0
  70. package/lib/components/element.ts +267 -0
  71. package/lib/components/fileupload.d.ts +40 -0
  72. package/lib/components/fileupload.d.ts.map +1 -0
  73. package/lib/components/fileupload.js +241 -0
  74. package/lib/components/fileupload.ts +309 -0
  75. package/lib/components/grid.d.ts +87 -0
  76. package/lib/components/grid.d.ts.map +1 -0
  77. package/lib/components/grid.js +205 -0
  78. package/lib/components/grid.ts +291 -0
  79. package/lib/components/guard.d.ts +41 -0
  80. package/lib/components/guard.d.ts.map +1 -0
  81. package/lib/components/guard.js +56 -0
  82. package/lib/components/guard.ts +92 -0
  83. package/lib/components/heading.d.ts +24 -0
  84. package/lib/components/heading.d.ts.map +1 -0
  85. package/lib/components/heading.js +67 -0
  86. package/lib/components/heading.ts +96 -0
  87. package/lib/components/helpers.d.ts +9 -0
  88. package/lib/components/helpers.d.ts.map +1 -0
  89. package/lib/components/helpers.js +30 -0
  90. package/lib/components/helpers.ts +41 -0
  91. package/lib/components/hero.d.ts +45 -0
  92. package/lib/components/hero.d.ts.map +1 -0
  93. package/lib/components/hero.js +165 -0
  94. package/lib/components/hero.ts +224 -0
  95. package/lib/components/icon.d.ts +35 -0
  96. package/lib/components/icon.d.ts.map +1 -0
  97. package/lib/components/icon.js +132 -0
  98. package/lib/components/icon.ts +178 -0
  99. package/lib/components/icons.d.ts +25 -0
  100. package/lib/components/icons.d.ts.map +1 -0
  101. package/lib/components/icons.js +440 -0
  102. package/lib/components/icons.ts +464 -0
  103. package/lib/components/include.d.ts +120 -0
  104. package/lib/components/include.d.ts.map +1 -0
  105. package/lib/components/include.js +350 -0
  106. package/lib/components/include.ts +410 -0
  107. package/lib/components/input.d.ts +83 -0
  108. package/lib/components/input.d.ts.map +1 -0
  109. package/lib/components/input.js +348 -0
  110. package/lib/components/input.ts +457 -0
  111. package/lib/components/list.d.ts +82 -0
  112. package/lib/components/list.d.ts.map +1 -0
  113. package/lib/components/list.js +311 -0
  114. package/lib/components/list.ts +419 -0
  115. package/lib/components/loading.d.ts +24 -0
  116. package/lib/components/loading.d.ts.map +1 -0
  117. package/lib/components/loading.js +73 -0
  118. package/lib/components/loading.ts +100 -0
  119. package/lib/components/menu.d.ts +37 -0
  120. package/lib/components/menu.d.ts.map +1 -0
  121. package/lib/components/menu.js +202 -0
  122. package/lib/components/menu.ts +275 -0
  123. package/lib/components/modal.d.ts +51 -0
  124. package/lib/components/modal.d.ts.map +1 -0
  125. package/lib/components/modal.js +227 -0
  126. package/lib/components/modal.ts +284 -0
  127. package/lib/components/nav.d.ts +45 -0
  128. package/lib/components/nav.d.ts.map +1 -0
  129. package/lib/components/nav.js +190 -0
  130. package/lib/components/nav.ts +257 -0
  131. package/lib/components/paragraph.d.ts +21 -0
  132. package/lib/components/paragraph.d.ts.map +1 -0
  133. package/lib/components/paragraph.js +70 -0
  134. package/lib/components/paragraph.ts +97 -0
  135. package/lib/components/progress.d.ts +39 -0
  136. package/lib/components/progress.d.ts.map +1 -0
  137. package/lib/components/progress.js +113 -0
  138. package/lib/components/progress.ts +159 -0
  139. package/lib/components/radio.d.ts +41 -0
  140. package/lib/components/radio.d.ts.map +1 -0
  141. package/lib/components/radio.js +203 -0
  142. package/lib/components/radio.ts +278 -0
  143. package/lib/components/req.d.ts +155 -0
  144. package/lib/components/req.d.ts.map +1 -0
  145. package/lib/components/req.js +253 -0
  146. package/lib/components/req.ts +303 -0
  147. package/lib/components/script.d.ts +14 -0
  148. package/lib/components/script.d.ts.map +1 -0
  149. package/lib/components/script.js +33 -0
  150. package/lib/components/script.ts +41 -0
  151. package/lib/components/select.d.ts +40 -0
  152. package/lib/components/select.d.ts.map +1 -0
  153. package/lib/components/select.js +183 -0
  154. package/lib/components/select.ts +252 -0
  155. package/lib/components/sidebar.d.ts +48 -0
  156. package/lib/components/sidebar.d.ts.map +1 -0
  157. package/lib/components/sidebar.js +207 -0
  158. package/lib/components/sidebar.ts +275 -0
  159. package/lib/components/style.d.ts +14 -0
  160. package/lib/components/style.d.ts.map +1 -0
  161. package/lib/components/style.js +33 -0
  162. package/lib/components/style.ts +41 -0
  163. package/lib/components/switch.d.ts +32 -0
  164. package/lib/components/switch.d.ts.map +1 -0
  165. package/lib/components/switch.js +186 -0
  166. package/lib/components/switch.ts +246 -0
  167. package/lib/components/table.d.ts +137 -0
  168. package/lib/components/table.d.ts.map +1 -0
  169. package/lib/components/table.js +1045 -0
  170. package/lib/components/table.ts +1249 -0
  171. package/lib/components/tabs.d.ts +36 -0
  172. package/lib/components/tabs.d.ts.map +1 -0
  173. package/lib/components/tabs.js +198 -0
  174. package/lib/components/tabs.ts +250 -0
  175. package/lib/components/theme-toggle.d.ts +44 -0
  176. package/lib/components/theme-toggle.d.ts.map +1 -0
  177. package/lib/components/theme-toggle.js +215 -0
  178. package/lib/components/theme-toggle.ts +293 -0
  179. package/lib/components/tooltip.d.ts +30 -0
  180. package/lib/components/tooltip.d.ts.map +1 -0
  181. package/lib/components/tooltip.js +109 -0
  182. package/lib/components/tooltip.ts +144 -0
  183. package/lib/components/view.d.ts +48 -0
  184. package/lib/components/view.d.ts.map +1 -0
  185. package/lib/components/view.js +149 -0
  186. package/lib/components/view.ts +190 -0
  187. package/lib/components/write.d.ts +107 -0
  188. package/lib/components/write.d.ts.map +1 -0
  189. package/lib/components/write.js +222 -0
  190. package/lib/components/write.ts +272 -0
  191. package/lib/layouts/default.css +260 -0
  192. package/lib/layouts/figma.css +334 -0
  193. package/lib/reactivity/state.d.ts +36 -0
  194. package/lib/reactivity/state.d.ts.map +1 -0
  195. package/lib/reactivity/state.js +67 -0
  196. package/lib/reactivity/state.ts +78 -0
  197. package/lib/utils/fetch.d.ts +176 -0
  198. package/lib/utils/fetch.d.ts.map +1 -0
  199. package/lib/utils/fetch.js +427 -0
  200. package/lib/utils/fetch.ts +553 -0
  201. package/machinery/compiler3.js +78 -0
  202. package/machinery/doc-generator.js +136 -0
  203. package/machinery/imports.js +155 -0
  204. package/machinery/ts-shim.js +46 -0
  205. package/package.json +9 -15
@@ -0,0 +1,227 @@
1
+ import { BaseComponent } from './base/BaseComponent.js';
2
+ // Event definitions
3
+ const TRIGGER_EVENTS = [];
4
+ const CALLBACK_EVENTS = ['open', 'close'];
5
+ export class Modal extends BaseComponent {
6
+ constructor(id, options = {}) {
7
+ super(id, {
8
+ title: options.title ?? '',
9
+ content: options.content ?? '',
10
+ showCloseButton: options.showCloseButton ?? true,
11
+ closeOnBackdropClick: options.closeOnBackdropClick ?? true,
12
+ size: options.size ?? 'medium',
13
+ open: false,
14
+ style: options.style ?? '',
15
+ class: options.class ?? ''
16
+ });
17
+ this._overlay = null;
18
+ }
19
+ getTriggerEvents() {
20
+ return TRIGGER_EVENTS;
21
+ }
22
+ getCallbackEvents() {
23
+ return CALLBACK_EVENTS;
24
+ }
25
+ /* ═════════════════════════════════════════════════════════════════
26
+ * FLUENT API
27
+ * ═════════════════════════════════════════════════════════════════ */
28
+ // ✅ Inherited from BaseComponent:
29
+ // - style(), class()
30
+ // - bind(), sync(), renderTo()
31
+ // - addClass(), removeClass(), toggleClass()
32
+ // - visible(), show(), hide()
33
+ // - attr(), attrs(), removeAttr()
34
+ title(value) {
35
+ this.state.title = value;
36
+ if (this._overlay) {
37
+ const modal = this._overlay.querySelector('.jux-modal');
38
+ const header = modal?.querySelector('.jux-modal-header');
39
+ if (header) {
40
+ header.textContent = value;
41
+ }
42
+ }
43
+ return this;
44
+ }
45
+ content(value) {
46
+ this.state.content = value;
47
+ if (this._overlay) {
48
+ const body = this._overlay.querySelector('.jux-modal-body');
49
+ if (body) {
50
+ body.innerHTML = value;
51
+ }
52
+ }
53
+ return this;
54
+ }
55
+ showCloseButton(value) {
56
+ this.state.showCloseButton = value;
57
+ return this;
58
+ }
59
+ closeOnBackdropClick(value) {
60
+ this.state.closeOnBackdropClick = value;
61
+ return this;
62
+ }
63
+ size(value) {
64
+ this.state.size = value;
65
+ if (this._overlay) {
66
+ const modal = this._overlay.querySelector('.jux-modal');
67
+ if (modal) {
68
+ modal.className = modal.className.replace(/jux-modal-(small|medium|large)/, `jux-modal-${value}`);
69
+ }
70
+ }
71
+ return this;
72
+ }
73
+ open() {
74
+ this.state.open = true;
75
+ if (this._overlay) {
76
+ this._overlay.style.display = 'flex';
77
+ }
78
+ // 🎯 Fire the open callback event
79
+ this._triggerCallback('open');
80
+ return this;
81
+ }
82
+ close() {
83
+ this.state.open = false;
84
+ if (this._overlay) {
85
+ this._overlay.style.display = 'none';
86
+ }
87
+ // 🎯 Fire the close callback event
88
+ this._triggerCallback('close');
89
+ return this;
90
+ }
91
+ /**
92
+ * Get the modal body element ID for rendering child components
93
+ * @returns The ID of the modal body element (e.g., 'mymodal-body')
94
+ *
95
+ * Usage:
96
+ * const modal = jux.modal('files-modal', { title: 'Files' }).render('body').open();
97
+ * jux.table('files-table', {...}).render(modal.bodyId());
98
+ */
99
+ bodyId() {
100
+ return `${this._id}-body`;
101
+ }
102
+ /**
103
+ * Get the modal body element (only available after render)
104
+ * @returns The modal body element or null if not rendered
105
+ */
106
+ getBodyElement() {
107
+ return document.getElementById(this.bodyId());
108
+ }
109
+ /* ═════════════════════════════════════════════════════════════════
110
+ * RENDER
111
+ * ═════════════════════════════════════════════════════════════════ */
112
+ render(targetId) {
113
+ const container = this._setupContainer(targetId);
114
+ const { open, title, content, size, closeOnBackdropClick: closeOnBackdrop, showCloseButton: showClose, style, class: className } = this.state;
115
+ const hasOpenSync = this._syncBindings.some(b => b.property === 'open');
116
+ const overlay = document.createElement('div');
117
+ overlay.className = 'jux-modal-overlay';
118
+ overlay.id = this._id;
119
+ overlay.style.display = open ? 'flex' : 'none';
120
+ if (className)
121
+ overlay.className += ` ${className}`;
122
+ if (style)
123
+ overlay.setAttribute('style', style);
124
+ this._overlay = overlay;
125
+ const modal = document.createElement('div');
126
+ modal.className = `jux-modal jux-modal-${size}`;
127
+ if (showClose) {
128
+ const closeButton = document.createElement('button');
129
+ closeButton.className = 'jux-modal-close';
130
+ closeButton.innerHTML = '×';
131
+ modal.appendChild(closeButton);
132
+ }
133
+ if (title) {
134
+ const header = document.createElement('div');
135
+ header.className = 'jux-modal-header';
136
+ header.textContent = title;
137
+ modal.appendChild(header);
138
+ }
139
+ const body = document.createElement('div');
140
+ body.className = 'jux-modal-body';
141
+ body.id = this.bodyId(); // Set predictable ID for child component rendering
142
+ body.innerHTML = content;
143
+ modal.appendChild(body);
144
+ overlay.appendChild(modal);
145
+ if (!hasOpenSync) {
146
+ if (showClose) {
147
+ const closeButton = modal.querySelector('.jux-modal-close');
148
+ closeButton?.addEventListener('click', () => {
149
+ this.state.open = false;
150
+ overlay.style.display = 'none';
151
+ });
152
+ }
153
+ if (closeOnBackdrop) {
154
+ overlay.addEventListener('click', (e) => {
155
+ if (e.target === overlay) {
156
+ this.state.open = false;
157
+ overlay.style.display = 'none';
158
+ }
159
+ });
160
+ }
161
+ }
162
+ this._wireStandardEvents(overlay);
163
+ this._syncBindings.forEach(({ property, stateObj, toState, toComponent }) => {
164
+ if (property === 'open') {
165
+ const transformToState = toState || ((v) => Boolean(v));
166
+ const transformToComponent = toComponent || ((v) => Boolean(v));
167
+ let isUpdating = false;
168
+ stateObj.subscribe((val) => {
169
+ if (isUpdating)
170
+ return;
171
+ const transformed = transformToComponent(val);
172
+ this.state.open = transformed;
173
+ overlay.style.display = transformed ? 'flex' : 'none';
174
+ });
175
+ if (showClose) {
176
+ const closeButton = modal.querySelector('.jux-modal-close');
177
+ closeButton?.addEventListener('click', () => {
178
+ if (isUpdating)
179
+ return;
180
+ isUpdating = true;
181
+ this.state.open = false;
182
+ overlay.style.display = 'none';
183
+ stateObj.set(transformToState(false));
184
+ setTimeout(() => { isUpdating = false; }, 0);
185
+ });
186
+ }
187
+ if (closeOnBackdrop) {
188
+ overlay.addEventListener('click', (e) => {
189
+ if (e.target === overlay) {
190
+ if (isUpdating)
191
+ return;
192
+ isUpdating = true;
193
+ this.state.open = false;
194
+ overlay.style.display = 'none';
195
+ stateObj.set(transformToState(false));
196
+ setTimeout(() => { isUpdating = false; }, 0);
197
+ }
198
+ });
199
+ }
200
+ }
201
+ else if (property === 'content') {
202
+ const transform = toComponent || ((v) => String(v));
203
+ stateObj.subscribe((val) => {
204
+ const transformed = transform(val);
205
+ body.innerHTML = transformed;
206
+ this.state.content = transformed;
207
+ });
208
+ }
209
+ else if (property === 'title') {
210
+ const transform = toComponent || ((v) => String(v));
211
+ stateObj.subscribe((val) => {
212
+ const transformed = transform(val);
213
+ const header = modal.querySelector('.jux-modal-header');
214
+ if (header) {
215
+ header.textContent = transformed;
216
+ }
217
+ this.state.title = transformed;
218
+ });
219
+ }
220
+ });
221
+ container.appendChild(overlay);
222
+ return this;
223
+ }
224
+ }
225
+ export function modal(id, options = {}) {
226
+ return new Modal(id, options);
227
+ }
@@ -0,0 +1,284 @@
1
+ import { BaseComponent } from './base/BaseComponent.js';
2
+
3
+ // Event definitions
4
+ const TRIGGER_EVENTS = [] as const;
5
+ const CALLBACK_EVENTS = ['open', 'close'] as const;
6
+
7
+ export interface ModalOptions {
8
+ title?: string;
9
+ content?: string;
10
+ showCloseButton?: boolean;
11
+ closeOnBackdropClick?: boolean;
12
+ size?: 'small' | 'medium' | 'large';
13
+ style?: string;
14
+ class?: string;
15
+ }
16
+
17
+ type ModalState = {
18
+ title: string;
19
+ content: string;
20
+ showCloseButton: boolean;
21
+ closeOnBackdropClick: boolean;
22
+ size: string;
23
+ open: boolean;
24
+ style: string;
25
+ class: string;
26
+ };
27
+
28
+ export class Modal extends BaseComponent<ModalState> {
29
+ private _overlay: HTMLElement | null = null;
30
+
31
+ constructor(id: string, options: ModalOptions = {}) {
32
+ super(id, {
33
+ title: options.title ?? '',
34
+ content: options.content ?? '',
35
+ showCloseButton: options.showCloseButton ?? true,
36
+ closeOnBackdropClick: options.closeOnBackdropClick ?? true,
37
+ size: options.size ?? 'medium',
38
+ open: false,
39
+ style: options.style ?? '',
40
+ class: options.class ?? ''
41
+ });
42
+ }
43
+
44
+ protected getTriggerEvents(): readonly string[] {
45
+ return TRIGGER_EVENTS;
46
+ }
47
+
48
+ protected getCallbackEvents(): readonly string[] {
49
+ return CALLBACK_EVENTS;
50
+ }
51
+
52
+ /* ═════════════════════════════════════════════════════════════════
53
+ * FLUENT API
54
+ * ═════════════════════════════════════════════════════════════════ */
55
+
56
+ // ✅ Inherited from BaseComponent:
57
+ // - style(), class()
58
+ // - bind(), sync(), renderTo()
59
+ // - addClass(), removeClass(), toggleClass()
60
+ // - visible(), show(), hide()
61
+ // - attr(), attrs(), removeAttr()
62
+
63
+ title(value: string): this {
64
+ this.state.title = value;
65
+ if (this._overlay) {
66
+ const modal = this._overlay.querySelector('.jux-modal');
67
+ const header = modal?.querySelector('.jux-modal-header');
68
+ if (header) {
69
+ header.textContent = value;
70
+ }
71
+ }
72
+ return this;
73
+ }
74
+
75
+ content(value: string): this {
76
+ this.state.content = value;
77
+ if (this._overlay) {
78
+ const body = this._overlay.querySelector('.jux-modal-body');
79
+ if (body) {
80
+ body.innerHTML = value;
81
+ }
82
+ }
83
+ return this;
84
+ }
85
+
86
+ showCloseButton(value: boolean): this {
87
+ this.state.showCloseButton = value;
88
+ return this;
89
+ }
90
+
91
+ closeOnBackdropClick(value: boolean): this {
92
+ this.state.closeOnBackdropClick = value;
93
+ return this;
94
+ }
95
+
96
+ size(value: 'small' | 'medium' | 'large'): this {
97
+ this.state.size = value;
98
+ if (this._overlay) {
99
+ const modal = this._overlay.querySelector('.jux-modal');
100
+ if (modal) {
101
+ modal.className = modal.className.replace(/jux-modal-(small|medium|large)/, `jux-modal-${value}`);
102
+ }
103
+ }
104
+ return this;
105
+ }
106
+
107
+ open(): this {
108
+ this.state.open = true;
109
+ if (this._overlay) {
110
+ this._overlay.style.display = 'flex';
111
+ }
112
+ // 🎯 Fire the open callback event
113
+ this._triggerCallback('open');
114
+ return this;
115
+ }
116
+
117
+ close(): this {
118
+ this.state.open = false;
119
+ if (this._overlay) {
120
+ this._overlay.style.display = 'none';
121
+ }
122
+ // 🎯 Fire the close callback event
123
+ this._triggerCallback('close');
124
+ return this;
125
+ }
126
+
127
+ /**
128
+ * Get the modal body element ID for rendering child components
129
+ * @returns The ID of the modal body element (e.g., 'mymodal-body')
130
+ *
131
+ * Usage:
132
+ * const modal = jux.modal('files-modal', { title: 'Files' }).render('body').open();
133
+ * jux.table('files-table', {...}).render(modal.bodyId());
134
+ */
135
+ bodyId(): string {
136
+ return `${this._id}-body`;
137
+ }
138
+
139
+ /**
140
+ * Get the modal body element (only available after render)
141
+ * @returns The modal body element or null if not rendered
142
+ */
143
+ getBodyElement(): HTMLElement | null {
144
+ return document.getElementById(this.bodyId());
145
+ }
146
+
147
+ /* ═════════════════════════════════════════════════════════════════
148
+ * RENDER
149
+ * ═════════════════════════════════════════════════════════════════ */
150
+
151
+ render(targetId?: string): this {
152
+ const container = this._setupContainer(targetId);
153
+
154
+ const { open, title, content, size, closeOnBackdropClick: closeOnBackdrop, showCloseButton: showClose, style, class: className } = this.state;
155
+ const hasOpenSync = this._syncBindings.some(b => b.property === 'open');
156
+
157
+ const overlay = document.createElement('div');
158
+ overlay.className = 'jux-modal-overlay';
159
+ overlay.id = this._id;
160
+ overlay.style.display = open ? 'flex' : 'none';
161
+ if (className) overlay.className += ` ${className}`;
162
+ if (style) overlay.setAttribute('style', style);
163
+ this._overlay = overlay;
164
+
165
+ const modal = document.createElement('div');
166
+ modal.className = `jux-modal jux-modal-${size}`;
167
+
168
+ if (showClose) {
169
+ const closeButton = document.createElement('button');
170
+ closeButton.className = 'jux-modal-close';
171
+ closeButton.innerHTML = '×';
172
+ modal.appendChild(closeButton);
173
+ }
174
+
175
+ if (title) {
176
+ const header = document.createElement('div');
177
+ header.className = 'jux-modal-header';
178
+ header.textContent = title;
179
+ modal.appendChild(header);
180
+ }
181
+
182
+ const body = document.createElement('div');
183
+ body.className = 'jux-modal-body';
184
+ body.id = this.bodyId(); // Set predictable ID for child component rendering
185
+ body.innerHTML = content;
186
+ modal.appendChild(body);
187
+
188
+ overlay.appendChild(modal);
189
+
190
+ if (!hasOpenSync) {
191
+ if (showClose) {
192
+ const closeButton = modal.querySelector('.jux-modal-close');
193
+ closeButton?.addEventListener('click', () => {
194
+ this.state.open = false;
195
+ overlay.style.display = 'none';
196
+ });
197
+ }
198
+
199
+ if (closeOnBackdrop) {
200
+ overlay.addEventListener('click', (e) => {
201
+ if (e.target === overlay) {
202
+ this.state.open = false;
203
+ overlay.style.display = 'none';
204
+ }
205
+ });
206
+ }
207
+ }
208
+
209
+ this._wireStandardEvents(overlay);
210
+
211
+ this._syncBindings.forEach(({ property, stateObj, toState, toComponent }) => {
212
+ if (property === 'open') {
213
+ const transformToState = toState || ((v: any) => Boolean(v));
214
+ const transformToComponent = toComponent || ((v: any) => Boolean(v));
215
+
216
+ let isUpdating = false;
217
+
218
+ stateObj.subscribe((val: any) => {
219
+ if (isUpdating) return;
220
+ const transformed = transformToComponent(val);
221
+ this.state.open = transformed;
222
+ overlay.style.display = transformed ? 'flex' : 'none';
223
+ });
224
+
225
+ if (showClose) {
226
+ const closeButton = modal.querySelector('.jux-modal-close');
227
+ closeButton?.addEventListener('click', () => {
228
+ if (isUpdating) return;
229
+ isUpdating = true;
230
+
231
+ this.state.open = false;
232
+ overlay.style.display = 'none';
233
+ stateObj.set(transformToState(false));
234
+
235
+ setTimeout(() => { isUpdating = false; }, 0);
236
+ });
237
+ }
238
+
239
+ if (closeOnBackdrop) {
240
+ overlay.addEventListener('click', (e) => {
241
+ if (e.target === overlay) {
242
+ if (isUpdating) return;
243
+ isUpdating = true;
244
+
245
+ this.state.open = false;
246
+ overlay.style.display = 'none';
247
+ stateObj.set(transformToState(false));
248
+
249
+ setTimeout(() => { isUpdating = false; }, 0);
250
+ }
251
+ });
252
+ }
253
+ }
254
+ else if (property === 'content') {
255
+ const transform = toComponent || ((v: any) => String(v));
256
+
257
+ stateObj.subscribe((val: any) => {
258
+ const transformed = transform(val);
259
+ body.innerHTML = transformed;
260
+ this.state.content = transformed;
261
+ });
262
+ }
263
+ else if (property === 'title') {
264
+ const transform = toComponent || ((v: any) => String(v));
265
+
266
+ stateObj.subscribe((val: any) => {
267
+ const transformed = transform(val);
268
+ const header = modal.querySelector('.jux-modal-header');
269
+ if (header) {
270
+ header.textContent = transformed;
271
+ }
272
+ this.state.title = transformed;
273
+ });
274
+ }
275
+ });
276
+
277
+ container.appendChild(overlay);
278
+ return this;
279
+ }
280
+ }
281
+
282
+ export function modal(id: string, options: ModalOptions = {}): Modal {
283
+ return new Modal(id, options);
284
+ }
@@ -0,0 +1,45 @@
1
+ import { BaseComponent } from './base/BaseComponent.js';
2
+ export interface NavItem {
3
+ label: string;
4
+ href: string;
5
+ active?: boolean;
6
+ itemClass?: string;
7
+ }
8
+ export interface NavBrand {
9
+ text?: string;
10
+ href?: string;
11
+ icon?: string;
12
+ }
13
+ export interface NavOptions {
14
+ items?: NavItem[];
15
+ brand?: NavBrand;
16
+ variant?: 'default' | 'pills' | 'tabs';
17
+ sticky?: boolean;
18
+ style?: string;
19
+ class?: string;
20
+ }
21
+ type NavState = {
22
+ items: NavItem[];
23
+ brand?: NavBrand;
24
+ variant: string;
25
+ sticky: boolean;
26
+ style: string;
27
+ class: string;
28
+ };
29
+ export declare class Nav extends BaseComponent<NavState> {
30
+ private _nav;
31
+ constructor(id: string, options?: NavOptions);
32
+ protected getTriggerEvents(): readonly string[];
33
+ protected getCallbackEvents(): readonly string[];
34
+ private _setActiveStates;
35
+ items(value: NavItem[]): this;
36
+ addItem(item: NavItem): this;
37
+ itemClass(className: string): this;
38
+ brand(value: NavBrand): this;
39
+ variant(value: string): this;
40
+ sticky(value: boolean): this;
41
+ render(targetId?: string): this;
42
+ }
43
+ export declare function nav(id: string, options?: NavOptions): Nav;
44
+ export {};
45
+ //# sourceMappingURL=nav.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nav.d.ts","sourceRoot":"","sources":["nav.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAQxD,MAAM,WAAW,OAAO;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,UAAU;IACzB,KAAK,CAAC,EAAE,OAAO,EAAE,CAAC;IAClB,KAAK,CAAC,EAAE,QAAQ,CAAC;IACjB,OAAO,CAAC,EAAE,SAAS,GAAG,OAAO,GAAG,MAAM,CAAC;IACvC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,KAAK,QAAQ,GAAG;IACd,KAAK,EAAE,OAAO,EAAE,CAAC;IACjB,KAAK,CAAC,EAAE,QAAQ,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,qBAAa,GAAI,SAAQ,aAAa,CAAC,QAAQ,CAAC;IAC9C,OAAO,CAAC,IAAI,CAA4B;gBAE5B,EAAE,EAAE,MAAM,EAAE,OAAO,GAAE,UAAe;IAahD,SAAS,CAAC,gBAAgB,IAAI,SAAS,MAAM,EAAE;IAI/C,SAAS,CAAC,iBAAiB,IAAI,SAAS,MAAM,EAAE;IAIhD,OAAO,CAAC,gBAAgB;IAaxB,KAAK,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,IAAI;IAM7B,OAAO,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI;IAM5B,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAQlC,KAAK,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI;IAK5B,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAK5B,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IAS5B,MAAM,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI;CAyIhC;AAED,wBAAgB,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,GAAE,UAAe,GAAG,GAAG,CAE7D"}