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,309 @@
1
+ import { FormInput, FormInputState } from './base/FormInput.js';
2
+ import { renderIcon } from './icons.js';
3
+
4
+ // Event definitions
5
+ const TRIGGER_EVENTS = [] as const;
6
+ const CALLBACK_EVENTS = ['change', 'filesSelected', 'clear'] as const;
7
+
8
+ export interface FileUploadOptions {
9
+ label?: string;
10
+ accept?: string;
11
+ multiple?: boolean;
12
+ disabled?: boolean;
13
+ name?: string;
14
+ icon?: string;
15
+ required?: boolean;
16
+ style?: string;
17
+ class?: string;
18
+ onValidate?: (files: File[]) => boolean | string;
19
+ }
20
+
21
+ interface FileUploadState extends FormInputState {
22
+ files: File[];
23
+ accept: string;
24
+ multiple: boolean;
25
+ icon: string;
26
+ }
27
+
28
+ export class FileUpload extends FormInput<FileUploadState> {
29
+ private _fileListElement: HTMLElement | null = null;
30
+
31
+ constructor(id: string, options: FileUploadOptions = {}) {
32
+ super(id, {
33
+ files: [],
34
+ accept: options.accept ?? '',
35
+ multiple: options.multiple ?? false,
36
+ icon: options.icon ?? 'upload',
37
+ label: options.label ?? '',
38
+ required: options.required ?? false,
39
+ disabled: options.disabled ?? false,
40
+ name: options.name ?? id,
41
+ style: options.style ?? '',
42
+ class: options.class ?? '',
43
+ errorMessage: undefined
44
+ });
45
+
46
+ if (options.onValidate) {
47
+ this._onValidate = options.onValidate;
48
+ }
49
+ }
50
+
51
+ protected getTriggerEvents(): readonly string[] {
52
+ return TRIGGER_EVENTS;
53
+ }
54
+
55
+ protected getCallbackEvents(): readonly string[] {
56
+ return CALLBACK_EVENTS;
57
+ }
58
+
59
+ /* ═════════════════════════════════════════════════════════════════
60
+ * FLUENT API
61
+ * ═════════════════════════════════════════════════════════════════ */
62
+
63
+ // ✅ Inherited from FormInput/BaseComponent:
64
+ // - label(), required(), name(), onValidate()
65
+ // - validate(), isValid()
66
+ // - style(), class()
67
+ // - bind(), sync(), renderTo()
68
+ // - disabled(), enable(), disable()
69
+
70
+ accept(value: string): this {
71
+ this.state.accept = value;
72
+ return this;
73
+ }
74
+
75
+ multiple(value: boolean): this {
76
+ this.state.multiple = value;
77
+ return this;
78
+ }
79
+
80
+ icon(value: string): this {
81
+ this.state.icon = value;
82
+ return this;
83
+ }
84
+
85
+ clear(): this {
86
+ this.state.files = [];
87
+ if (this._inputElement) {
88
+ (this._inputElement as HTMLInputElement).value = '';
89
+ }
90
+ if (this._fileListElement) {
91
+ this._updateFileList([]);
92
+ }
93
+ // 🎯 Fire the clear callback event
94
+ this._triggerCallback('clear');
95
+ return this;
96
+ }
97
+
98
+ /* ═════════════════════════════════════════════════════════════════
99
+ * FORM INPUT IMPLEMENTATION
100
+ * ═════════════════════════════════════════════════════════════════ */
101
+
102
+ getValue(): File[] {
103
+ return this.state.files;
104
+ }
105
+
106
+ setValue(files: File[]): this {
107
+ this.state.files = files;
108
+ if (this._fileListElement) {
109
+ this._updateFileList(files);
110
+ }
111
+ return this;
112
+ }
113
+
114
+ getFiles(): File[] {
115
+ return this.getValue();
116
+ }
117
+
118
+ protected _validateValue(files: File[]): boolean | string {
119
+ const { required } = this.state;
120
+
121
+ if (required && files.length === 0) {
122
+ return 'Please select at least one file';
123
+ }
124
+
125
+ if (this._onValidate) {
126
+ const result = this._onValidate(files);
127
+ if (result !== true) {
128
+ return result || 'Invalid files';
129
+ }
130
+ }
131
+
132
+ return true;
133
+ }
134
+
135
+ protected _buildInputElement(): HTMLElement {
136
+ const { accept, multiple, required, disabled, name } = this.state;
137
+
138
+ const input = document.createElement('input');
139
+ input.type = 'file';
140
+ input.className = 'jux-fileupload-input';
141
+ input.id = `${this._id}-input`;
142
+ input.name = name;
143
+ input.required = required;
144
+ input.disabled = disabled;
145
+
146
+ if (accept) input.accept = accept;
147
+ if (multiple) input.multiple = multiple;
148
+
149
+ return input;
150
+ }
151
+
152
+ /* ═════════════════════════════════════════════════════════════════
153
+ * RENDER
154
+ * ═════════════════════════════════════════════════════════════════ */
155
+
156
+ render(targetId?: string): this {
157
+ const container = this._setupContainer(targetId);
158
+
159
+ const { icon, style, class: className } = this.state;
160
+
161
+ // Build wrapper
162
+ const wrapper = document.createElement('div');
163
+ wrapper.className = 'jux-input jux-fileupload';
164
+ wrapper.id = this._id;
165
+ if (className) wrapper.className += ` ${className}`;
166
+ if (style) wrapper.setAttribute('style', style);
167
+
168
+ // Label
169
+ if (this.state.label) {
170
+ wrapper.appendChild(this._renderLabel());
171
+ }
172
+
173
+ // Hidden file input
174
+ const inputEl = this._buildInputElement() as HTMLInputElement;
175
+ this._inputElement = inputEl;
176
+ wrapper.appendChild(inputEl);
177
+
178
+ // Button container
179
+ const buttonContainer = document.createElement('div');
180
+ buttonContainer.className = 'jux-fileupload-button-container';
181
+
182
+ if (icon) {
183
+ const iconEl = document.createElement('span');
184
+ iconEl.className = 'jux-fileupload-icon';
185
+ iconEl.appendChild(renderIcon(icon));
186
+ buttonContainer.appendChild(iconEl);
187
+ }
188
+
189
+ const button = document.createElement('button');
190
+ button.type = 'button';
191
+ button.className = 'jux-fileupload-button';
192
+ button.textContent = 'Choose File(s)';
193
+ button.disabled = this.state.disabled;
194
+
195
+ buttonContainer.appendChild(button);
196
+ wrapper.appendChild(buttonContainer);
197
+
198
+ // File list
199
+ const fileList = document.createElement('div');
200
+ fileList.className = 'jux-fileupload-list';
201
+ this._fileListElement = fileList;
202
+ wrapper.appendChild(fileList);
203
+
204
+ // Error element
205
+ wrapper.appendChild(this._renderError());
206
+
207
+ // Button click triggers file input
208
+ button.addEventListener('click', () => inputEl.click());
209
+
210
+ // Wire events
211
+ this._wireStandardEvents(wrapper);
212
+
213
+ // Wire file-specific sync
214
+ const filesSync = this._syncBindings.find(b => b.property === 'files' || b.property === 'value');
215
+
216
+ if (filesSync) {
217
+ const { stateObj, toState, toComponent } = filesSync;
218
+
219
+ const transformToState = toState || ((v: File[]) => v);
220
+ const transformToComponent = toComponent || ((v: any) => v);
221
+
222
+ let isUpdating = false;
223
+
224
+ // State → Component
225
+ stateObj.subscribe((val: any) => {
226
+ if (isUpdating) return;
227
+ const transformed = transformToComponent(val);
228
+ this.setValue(transformed);
229
+ });
230
+
231
+ // Component → State
232
+ inputEl.addEventListener('change', () => {
233
+ if (isUpdating) return;
234
+ isUpdating = true;
235
+
236
+ const files = Array.from(inputEl.files || []);
237
+ this.state.files = files;
238
+ this._updateFileList(files);
239
+ this._clearError();
240
+
241
+ const transformed = transformToState(files);
242
+ stateObj.set(transformed);
243
+
244
+ // 🎯 Fire the callback events
245
+ this._triggerCallback('change', files);
246
+ this._triggerCallback('filesSelected', files);
247
+
248
+ setTimeout(() => { isUpdating = false; }, 0);
249
+ });
250
+ } else {
251
+ // Default behavior without sync
252
+ inputEl.addEventListener('change', () => {
253
+ const files = Array.from(inputEl.files || []);
254
+ this.state.files = files;
255
+ this._updateFileList(files);
256
+ this._clearError();
257
+
258
+ // 🎯 Fire the callback events
259
+ this._triggerCallback('change', files);
260
+ this._triggerCallback('filesSelected', files);
261
+ });
262
+ }
263
+
264
+ // Always add blur validation
265
+ inputEl.addEventListener('blur', () => {
266
+ this.validate();
267
+ });
268
+
269
+ // Sync label changes
270
+ const labelSync = this._syncBindings.find(b => b.property === 'label');
271
+ if (labelSync) {
272
+ const transform = labelSync.toComponent || ((v: any) => String(v));
273
+ labelSync.stateObj.subscribe((val: any) => {
274
+ this.label(transform(val));
275
+ });
276
+ }
277
+
278
+ container.appendChild(wrapper);
279
+ return this;
280
+ }
281
+
282
+ private _updateFileList(files: File[]): void {
283
+ if (!this._fileListElement) return;
284
+
285
+ this._fileListElement.innerHTML = '';
286
+
287
+ if (files.length === 0) {
288
+ this._fileListElement.textContent = 'No files selected';
289
+ return;
290
+ }
291
+
292
+ files.forEach(file => {
293
+ const fileItem = document.createElement('div');
294
+ fileItem.className = 'jux-fileupload-item';
295
+ fileItem.textContent = `${file.name} (${this._formatFileSize(file.size)})`;
296
+ this._fileListElement!.appendChild(fileItem);
297
+ });
298
+ }
299
+
300
+ private _formatFileSize(bytes: number): string {
301
+ if (bytes < 1024) return `${bytes} B`;
302
+ if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
303
+ return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
304
+ }
305
+ }
306
+
307
+ export function fileupload(id: string, options: FileUploadOptions = {}): FileUpload {
308
+ return new FileUpload(id, options);
309
+ }
@@ -0,0 +1,87 @@
1
+ import { BaseComponent } from './base/BaseComponent.js';
2
+ export interface GridRowConfig {
3
+ height?: string;
4
+ style?: string;
5
+ class?: string;
6
+ }
7
+ export interface GridColumnConfig {
8
+ width?: string;
9
+ style?: string;
10
+ class?: string;
11
+ }
12
+ export interface GridItemConfig {
13
+ target: string;
14
+ text?: string;
15
+ html?: string;
16
+ component?: any;
17
+ }
18
+ export interface GridCreateConfig {
19
+ columns?: GridColumnConfig[] | number;
20
+ rows?: GridRowConfig[] | number;
21
+ items?: GridItemConfig[];
22
+ }
23
+ export interface GridOptions {
24
+ columns?: GridColumnConfig[] | number;
25
+ rows?: GridRowConfig[] | number;
26
+ width?: string;
27
+ height?: string;
28
+ gap?: string;
29
+ style?: string;
30
+ class?: string;
31
+ }
32
+ type GridState = {
33
+ rows: GridRowConfig[];
34
+ columns: GridColumnConfig[];
35
+ boundary: {
36
+ width: string;
37
+ height: string;
38
+ };
39
+ gap: string;
40
+ cells: Map<string, HTMLElement>;
41
+ style: string;
42
+ class: string;
43
+ gridder: boolean;
44
+ };
45
+ export declare class Grid extends BaseComponent<GridState> {
46
+ constructor(id: string, options?: GridOptions);
47
+ protected getTriggerEvents(): readonly string[];
48
+ protected getCallbackEvents(): readonly string[];
49
+ width(value: string): this;
50
+ height(value: string): this;
51
+ gap(value: string): this;
52
+ /**
53
+ * Define rows (SETTER)
54
+ * @param config - Number (creates N equal rows) or Array of row configs
55
+ */
56
+ rows(config: GridRowConfig[] | number): this;
57
+ /**
58
+ * Define columns (SETTER)
59
+ * @param config - Number (creates N equal columns) or Array of column configs
60
+ */
61
+ columns(config: GridColumnConfig[] | number): this;
62
+ /**
63
+ * Get the cell ID for a specific coordinate
64
+ */
65
+ getCellId(row: number, col: number): string;
66
+ /**
67
+ * Get the DOM element for a specific cell
68
+ */
69
+ getCell(row: number, col: number): HTMLElement | undefined;
70
+ /**
71
+ * ✅ Enable blueprint/wireframe visualization
72
+ * Shows grid structure, cell coordinates, and geometric borders
73
+ */
74
+ gridder(value?: boolean): this;
75
+ /**
76
+ * Pattern B: The Static Orchestration
77
+ * Creates the grid and populates it with items in one operation
78
+ */
79
+ create(config: GridCreateConfig): this;
80
+ render(targetId?: string): this;
81
+ }
82
+ /**
83
+ * Factory function
84
+ */
85
+ export declare function grid(id: string, options?: GridOptions): Grid;
86
+ export {};
87
+ //# sourceMappingURL=grid.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grid.d.ts","sourceRoot":"","sources":["grid.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,205 @@
1
+ import { BaseComponent } from './base/BaseComponent.js';
2
+ // Event definitions - Grid is layout-only, no interactive events
3
+ const TRIGGER_EVENTS = [];
4
+ const CALLBACK_EVENTS = [];
5
+ export class Grid extends BaseComponent {
6
+ constructor(id, options = {}) {
7
+ // Normalize columns/rows to config arrays
8
+ const columnsConfig = normalizeTrackConfig(options.columns || 1);
9
+ const rowsConfig = normalizeTrackConfig(options.rows || 1);
10
+ super(id, {
11
+ rows: rowsConfig,
12
+ columns: columnsConfig,
13
+ boundary: {
14
+ width: options.width ?? '', // ✅ CHANGE: Empty = inherit parent
15
+ height: options.height ?? '' // ✅ CHANGE: Empty = inherit parent
16
+ },
17
+ gap: options.gap ?? '0',
18
+ cells: new Map(),
19
+ style: options.style ?? '',
20
+ class: options.class ?? '',
21
+ gridder: false
22
+ });
23
+ }
24
+ getTriggerEvents() {
25
+ return TRIGGER_EVENTS;
26
+ }
27
+ getCallbackEvents() {
28
+ return CALLBACK_EVENTS;
29
+ }
30
+ /* ═════════════════════════════════════════════════════════════════
31
+ * PROPS ACCESSOR - Inherited from BaseComponent
32
+ * ═════════════════════════════════════════════════════════════════ */
33
+ // ✅ Already available via BaseComponent.props getter
34
+ // Access: grid.props.rows, grid.props.columns, grid.props.gap, etc.
35
+ /* ═════════════════════════════════════════════════════════════════
36
+ * FLUENT API - The Blueprint (Setters)
37
+ * ═════════════════════════════════════════════════════════════════ */
38
+ width(value) {
39
+ this.state.boundary.width = value;
40
+ return this;
41
+ }
42
+ height(value) {
43
+ this.state.boundary.height = value;
44
+ return this;
45
+ }
46
+ gap(value) {
47
+ this.state.gap = value;
48
+ return this;
49
+ }
50
+ /**
51
+ * Define rows (SETTER)
52
+ * @param config - Number (creates N equal rows) or Array of row configs
53
+ */
54
+ rows(config) {
55
+ this.state.rows = normalizeTrackConfig(config);
56
+ return this;
57
+ }
58
+ /**
59
+ * Define columns (SETTER)
60
+ * @param config - Number (creates N equal columns) or Array of column configs
61
+ */
62
+ columns(config) {
63
+ this.state.columns = normalizeTrackConfig(config);
64
+ return this;
65
+ }
66
+ /**
67
+ * Get the cell ID for a specific coordinate
68
+ */
69
+ getCellId(row, col) {
70
+ return `${this._id}-${row}-${col}`;
71
+ }
72
+ /**
73
+ * Get the DOM element for a specific cell
74
+ */
75
+ getCell(row, col) {
76
+ const cellId = this.getCellId(row, col);
77
+ return this.state.cells.get(cellId);
78
+ }
79
+ /**
80
+ * ✅ Enable blueprint/wireframe visualization
81
+ * Shows grid structure, cell coordinates, and geometric borders
82
+ */
83
+ gridder(value = true) {
84
+ this.state.gridder = value;
85
+ return this;
86
+ }
87
+ /* ═════════════════════════════════════════════════════════════════
88
+ * ORCHESTRATION - The Execution
89
+ * ═════════════════════════════════════════════════════════════════ */
90
+ /**
91
+ * Pattern B: The Static Orchestration
92
+ * Creates the grid and populates it with items in one operation
93
+ */
94
+ create(config) {
95
+ // Apply configuration
96
+ if (config.columns) {
97
+ this.columns(config.columns);
98
+ }
99
+ if (config.rows) {
100
+ this.rows(config.rows);
101
+ }
102
+ // Render the grid structure
103
+ this.render();
104
+ // Populate items
105
+ if (config.items) {
106
+ config.items.forEach(item => {
107
+ const targetId = item.target.replace(/^#/, '');
108
+ const cell = document.getElementById(targetId);
109
+ if (!cell) {
110
+ console.warn(`[Grid] Cell not found: ${item.target}`);
111
+ return;
112
+ }
113
+ if (item.component) {
114
+ // Render Jux component
115
+ item.component.render(`#${targetId}`);
116
+ }
117
+ else if (item.html) {
118
+ cell.innerHTML = item.html;
119
+ }
120
+ else if (item.text) {
121
+ cell.textContent = item.text;
122
+ }
123
+ });
124
+ }
125
+ return this;
126
+ }
127
+ /* ═════════════════════════════════════════════════════════════════
128
+ * RENDER
129
+ * ═════════════════════════════════════════════════════════════════ */
130
+ render(targetId) {
131
+ const container = this._setupContainer(targetId);
132
+ const { rows, columns, boundary, gap, style, class: className, gridder } = this.state;
133
+ // Build grid container
134
+ const grid = document.createElement('div');
135
+ grid.className = 'jux-grid';
136
+ grid.id = this._id;
137
+ if (gridder)
138
+ grid.classList.add('jux-grid-gridder');
139
+ if (className)
140
+ grid.className += ` ${className}`;
141
+ // Apply grid styles
142
+ const gridTemplateRows = rows.map(r => r.height || '1fr').join(' ');
143
+ const gridTemplateColumns = columns.map(c => c.width || '1fr').join(' ');
144
+ const gridStyle = `
145
+ display: grid;
146
+ grid-template-rows: ${gridTemplateRows};
147
+ grid-template-columns: ${gridTemplateColumns};
148
+ gap: ${gap};
149
+ ${boundary.width ? `width: ${boundary.width};` : ''} /* ✅ CHANGE: Only apply if set */
150
+ ${boundary.height ? `height: ${boundary.height};` : ''} /* ✅ CHANGE: Only apply if set */
151
+ ${style}
152
+ `;
153
+ grid.setAttribute('style', gridStyle.trim());
154
+ // Generate cells with coordinate-based IDs
155
+ this.state.cells.clear();
156
+ rows.forEach((row, rowIndex) => {
157
+ columns.forEach((col, colIndex) => {
158
+ const cell = document.createElement('div');
159
+ const cellId = this.getCellId(rowIndex, colIndex);
160
+ cell.id = cellId;
161
+ cell.className = 'jux-grid-cell';
162
+ cell.setAttribute('data-row', String(rowIndex));
163
+ cell.setAttribute('data-col', String(colIndex));
164
+ // ✅ CHANGE: Use title attribute instead of DOM element
165
+ if (gridder) {
166
+ cell.setAttribute('title', `Cell [${rowIndex},${colIndex}] — #${cellId}`);
167
+ }
168
+ // Apply row-specific styles
169
+ if (row.style) {
170
+ cell.setAttribute('style', (cell.getAttribute('style') || '') + row.style);
171
+ }
172
+ if (row.class) {
173
+ cell.className += ` ${row.class}`;
174
+ }
175
+ // Apply column-specific styles
176
+ if (col.style) {
177
+ cell.setAttribute('style', (cell.getAttribute('style') || '') + col.style);
178
+ }
179
+ if (col.class) {
180
+ cell.className += ` ${col.class}`;
181
+ }
182
+ this.state.cells.set(cellId, cell);
183
+ grid.appendChild(cell);
184
+ });
185
+ });
186
+ this._wireStandardEvents(grid);
187
+ container.appendChild(grid);
188
+ return this;
189
+ }
190
+ }
191
+ /**
192
+ * Normalize track configuration to array format
193
+ */
194
+ function normalizeTrackConfig(config) {
195
+ if (typeof config === 'number') {
196
+ return Array(config).fill({});
197
+ }
198
+ return config;
199
+ }
200
+ /**
201
+ * Factory function
202
+ */
203
+ export function grid(id, options = {}) {
204
+ return new Grid(id, options);
205
+ }