@colletdev/core 0.1.3

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 (119) hide show
  1. package/README.md +77 -0
  2. package/custom-elements.json +6037 -0
  3. package/generated/.gitattributes +2 -0
  4. package/generated/index.d.ts +120 -0
  5. package/generated/index.js +521 -0
  6. package/generated/styles.js +2845 -0
  7. package/package.json +56 -0
  8. package/src/elements/accordion.d.ts +20 -0
  9. package/src/elements/accordion.js +92 -0
  10. package/src/elements/activity_group.d.ts +19 -0
  11. package/src/elements/activity_group.js +27 -0
  12. package/src/elements/alert.d.ts +24 -0
  13. package/src/elements/alert.js +40 -0
  14. package/src/elements/autocomplete.d.ts +30 -0
  15. package/src/elements/autocomplete.js +671 -0
  16. package/src/elements/avatar.d.ts +18 -0
  17. package/src/elements/avatar.js +28 -0
  18. package/src/elements/backdrop.d.ts +14 -0
  19. package/src/elements/backdrop.js +28 -0
  20. package/src/elements/badge.d.ts +21 -0
  21. package/src/elements/badge.js +42 -0
  22. package/src/elements/breadcrumb.d.ts +17 -0
  23. package/src/elements/breadcrumb.js +41 -0
  24. package/src/elements/button.d.ts +24 -0
  25. package/src/elements/button.js +36 -0
  26. package/src/elements/card.d.ts +21 -0
  27. package/src/elements/card.js +67 -0
  28. package/src/elements/carousel.d.ts +23 -0
  29. package/src/elements/carousel.js +895 -0
  30. package/src/elements/chat_input.d.ts +22 -0
  31. package/src/elements/chat_input.js +78 -0
  32. package/src/elements/checkbox.d.ts +21 -0
  33. package/src/elements/checkbox.js +114 -0
  34. package/src/elements/code_block.d.ts +21 -0
  35. package/src/elements/code_block.js +27 -0
  36. package/src/elements/collapsible.d.ts +20 -0
  37. package/src/elements/collapsible.js +93 -0
  38. package/src/elements/date_picker.d.ts +30 -0
  39. package/src/elements/date_picker.js +528 -0
  40. package/src/elements/dialog.d.ts +20 -0
  41. package/src/elements/dialog.js +314 -0
  42. package/src/elements/drawer.d.ts +20 -0
  43. package/src/elements/drawer.js +318 -0
  44. package/src/elements/fab.d.ts +22 -0
  45. package/src/elements/fab.js +36 -0
  46. package/src/elements/file_upload.d.ts +26 -0
  47. package/src/elements/file_upload.js +59 -0
  48. package/src/elements/listbox.d.ts +19 -0
  49. package/src/elements/listbox.js +250 -0
  50. package/src/elements/menu.d.ts +20 -0
  51. package/src/elements/menu.js +224 -0
  52. package/src/elements/message_bubble.d.ts +23 -0
  53. package/src/elements/message_bubble.js +29 -0
  54. package/src/elements/message_group.d.ts +18 -0
  55. package/src/elements/message_group.js +28 -0
  56. package/src/elements/message_part.d.ts +35 -0
  57. package/src/elements/message_part.js +153 -0
  58. package/src/elements/pagination.d.ts +22 -0
  59. package/src/elements/pagination.js +36 -0
  60. package/src/elements/popover.d.ts +26 -0
  61. package/src/elements/popover.js +191 -0
  62. package/src/elements/profile_menu.d.ts +20 -0
  63. package/src/elements/profile_menu.js +213 -0
  64. package/src/elements/progress.d.ts +18 -0
  65. package/src/elements/progress.js +31 -0
  66. package/src/elements/radio_group.d.ts +22 -0
  67. package/src/elements/radio_group.js +70 -0
  68. package/src/elements/scrollbar.d.ts +19 -0
  69. package/src/elements/scrollbar.js +299 -0
  70. package/src/elements/search_bar.d.ts +27 -0
  71. package/src/elements/search_bar.js +98 -0
  72. package/src/elements/select.d.ts +26 -0
  73. package/src/elements/select.js +485 -0
  74. package/src/elements/sidebar.d.ts +21 -0
  75. package/src/elements/sidebar.js +322 -0
  76. package/src/elements/skeleton.d.ts +17 -0
  77. package/src/elements/skeleton.js +31 -0
  78. package/src/elements/slider.d.ts +28 -0
  79. package/src/elements/slider.js +93 -0
  80. package/src/elements/speed_dial.d.ts +23 -0
  81. package/src/elements/speed_dial.js +370 -0
  82. package/src/elements/spinner.d.ts +15 -0
  83. package/src/elements/spinner.js +28 -0
  84. package/src/elements/split_button.d.ts +23 -0
  85. package/src/elements/split_button.js +281 -0
  86. package/src/elements/stepper.d.ts +20 -0
  87. package/src/elements/stepper.js +31 -0
  88. package/src/elements/switch.d.ts +22 -0
  89. package/src/elements/switch.js +129 -0
  90. package/src/elements/table.d.ts +29 -0
  91. package/src/elements/table.js +371 -0
  92. package/src/elements/tabs.d.ts +19 -0
  93. package/src/elements/tabs.js +139 -0
  94. package/src/elements/text.d.ts +26 -0
  95. package/src/elements/text.js +32 -0
  96. package/src/elements/text_input.d.ts +36 -0
  97. package/src/elements/text_input.js +121 -0
  98. package/src/elements/thinking.d.ts +17 -0
  99. package/src/elements/thinking.js +28 -0
  100. package/src/elements/toast.d.ts +23 -0
  101. package/src/elements/toast.js +209 -0
  102. package/src/elements/toggle_group.d.ts +22 -0
  103. package/src/elements/toggle_group.js +176 -0
  104. package/src/elements/tooltip.d.ts +18 -0
  105. package/src/elements/tooltip.js +64 -0
  106. package/src/markdown.d.ts +24 -0
  107. package/src/markdown.js +66 -0
  108. package/src/runtime.d.ts +35 -0
  109. package/src/runtime.js +790 -0
  110. package/src/server.d.ts +69 -0
  111. package/src/server.js +176 -0
  112. package/src/streaming-markdown.js +43 -0
  113. package/src/vite-plugin.d.ts +46 -0
  114. package/src/vite-plugin.js +221 -0
  115. package/wasm/package.json +16 -0
  116. package/wasm/wasm_api.d.ts +72 -0
  117. package/wasm/wasm_api.js +593 -0
  118. package/wasm/wasm_api_bg.wasm +0 -0
  119. package/wasm/wasm_api_bg.wasm.d.ts +10 -0
@@ -0,0 +1,528 @@
1
+ // Custom behavior for <cx-date-picker> — calendar panel, date selection, keyboard nav.
2
+ //
3
+ // The Rust component renders:
4
+ // <div part="base" data-date-picker="{id}">
5
+ // <input data-date-picker-input role="combobox" aria-haspopup="dialog">
6
+ // <button data-date-picker-trigger aria-label="Choose date">
7
+ // <button data-date-picker-step-up> / <button data-date-picker-step-down>
8
+ // <div data-floating data-date-picker-panel role="dialog">
9
+ // <button data-date-picker-prev> / <button data-date-picker-next>
10
+ // <div data-date-picker-heading aria-live="polite">
11
+ // <div role="grid" data-date-picker-grid>
12
+ // <button role="gridcell" data-date="YYYY-MM-DD">
13
+ // <button data-date-picker-today>
14
+ //
15
+ // This Custom Element wires up:
16
+ // - Toggle calendar panel via trigger button or input click
17
+ // - Day selection via click on gridcell
18
+ // - Month navigation (prev/next buttons)
19
+ // - Today button shortcut
20
+ // - Day stepping via up/down buttons
21
+ // - Full keyboard nav (arrows ±1/7 days, Page ±month, Home/End, Escape)
22
+ // - Click outside / focus exit to close
23
+ //
24
+ // Source: crates/wasm-api/src/date_picker.rs
25
+
26
+ let _sheet;
27
+ function getSheet() {
28
+ if (!_sheet) {
29
+ _sheet = new CSSStyleSheet();
30
+ _sheet.replaceSync([
31
+ // Calendar panel uses position:fixed (set by JS) to escape scroll container clipping.
32
+ '[data-floating] {',
33
+ ' z-index: 50;',
34
+ '}',
35
+ // Hover for day cells
36
+ 'button[role="gridcell"]:not([aria-disabled="true"]):hover {',
37
+ ' background-color: var(--color-secondary);',
38
+ ' cursor: pointer;',
39
+ '}',
40
+ // Focus for day cells
41
+ 'button[role="gridcell"]:focus-visible {',
42
+ ' outline: 2px solid var(--color-ring);',
43
+ ' outline-offset: -2px;',
44
+ ' border-radius: 0.25rem;',
45
+ '}',
46
+ ].join('\n'));
47
+ }
48
+ return _sheet;
49
+ }
50
+
51
+ // ── Date helpers ──
52
+
53
+ function todayStr() {
54
+ const d = new Date();
55
+ return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;
56
+ }
57
+
58
+ function addDays(isoDate, n) {
59
+ const d = new Date(isoDate + 'T12:00:00');
60
+ d.setDate(d.getDate() + n);
61
+ return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;
62
+ }
63
+
64
+ function addMonths(isoDate, n) {
65
+ const d = new Date(isoDate + 'T12:00:00');
66
+ d.setMonth(d.getMonth() + n);
67
+ return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;
68
+ }
69
+
70
+ function getMonthYear(isoDate) {
71
+ return isoDate.substring(0, 7); // "YYYY-MM"
72
+ }
73
+
74
+ export function defineCxDatePicker(wasmFn, baseClass) {
75
+ class CxDatePicker extends baseClass {
76
+ static observedAttributes = ['id', 'label', 'variant', 'shape', 'size', 'selected', 'min', 'max', 'disabled-dates', 'format', 'first-day', 'placeholder', 'helper-text', 'error', 'disabled', 'required', 'readonly', 'name', 'on-change'];
77
+ static _booleanAttrs = new Set(['disabled', 'required', 'readonly']);
78
+
79
+ #outsideClick = null;
80
+
81
+ connectedCallback() {
82
+ if (!this._isInitialized) {
83
+ this._markInitialized();
84
+ const shadow = this._shadow;
85
+
86
+ const sheet = getSheet();
87
+ if (!shadow.adoptedStyleSheets.includes(sheet)) {
88
+ shadow.adoptedStyleSheets = [...shadow.adoptedStyleSheets, sheet];
89
+ }
90
+
91
+ // ── Click handler ──
92
+ shadow.addEventListener('click', (e) => {
93
+ // Calendar trigger button
94
+ if (e.target.closest('[data-date-picker-trigger]')) {
95
+ if (!this._props.disabled && !this._props.readonly) {
96
+ this.#toggle();
97
+ }
98
+ return;
99
+ }
100
+
101
+ // Day cell click
102
+ const cell = e.target.closest('button[role="gridcell"]');
103
+ if (cell && !cell.hasAttribute('aria-disabled')) {
104
+ const date = cell.getAttribute('data-date');
105
+ if (date) this.#selectDate(date);
106
+ return;
107
+ }
108
+
109
+ // Previous month
110
+ if (e.target.closest('[data-date-picker-prev]')) {
111
+ this.#navigateMonth(-1);
112
+ return;
113
+ }
114
+
115
+ // Next month
116
+ if (e.target.closest('[data-date-picker-next]')) {
117
+ this.#navigateMonth(1);
118
+ return;
119
+ }
120
+
121
+ // Today button
122
+ if (e.target.closest('[data-date-picker-today]')) {
123
+ this.#selectDate(todayStr());
124
+ return;
125
+ }
126
+
127
+ // Step up (+1 day)
128
+ if (e.target.closest('[data-date-picker-step-up]')) {
129
+ this.#stepDay(1);
130
+ return;
131
+ }
132
+
133
+ // Step down (-1 day)
134
+ if (e.target.closest('[data-date-picker-step-down]')) {
135
+ this.#stepDay(-1);
136
+ return;
137
+ }
138
+
139
+ // Input click → open panel
140
+ const input = e.target.closest('[data-date-picker-input]');
141
+ if (input && !this.#isOpen() && !this._props.disabled && !this._props.readonly) {
142
+ this.#open();
143
+ }
144
+ });
145
+
146
+ // ── Keyboard handler ──
147
+ shadow.addEventListener('keydown', (e) => this.#handleKey(e));
148
+
149
+ // ── Input typing ──
150
+ shadow.addEventListener('input', (e) => {
151
+ if (e.target.matches('[data-date-picker-input]')) {
152
+ this._setFormValue(e.target.value);
153
+ this._emit('cx-input', { value: e.target.value });
154
+ }
155
+ });
156
+
157
+ // ── Click outside → close ──
158
+ this.#outsideClick = (e) => {
159
+ if (this.#isOpen() && !this.contains(e.target) && !this._shadow.contains(e.target)) {
160
+ this.#close();
161
+ }
162
+ };
163
+ document.addEventListener('mousedown', this.#outsideClick);
164
+
165
+ // ── Focus exit → close ──
166
+ // Must check both light DOM and shadow DOM — Node.contains() doesn't cross shadow boundaries.
167
+ shadow.addEventListener('focusout', () => {
168
+ setTimeout(() => {
169
+ if (this.#isOpen()) {
170
+ const active = shadow.activeElement || document.activeElement;
171
+ if (!this.contains(active) && !this._shadow.contains(active) && active !== this) {
172
+ this.#close();
173
+ }
174
+ }
175
+ }, 0);
176
+ });
177
+
178
+ // Forward focus events from inner interactive elements
179
+ shadow.addEventListener('focusin', (e) => {
180
+ this._emit('cx-focus', { relatedTarget: e.relatedTarget });
181
+ });
182
+ shadow.addEventListener('focusout', (e) => {
183
+ this._emit('cx-blur', { relatedTarget: e.relatedTarget });
184
+ });
185
+
186
+ // Forward keyboard events from inner interactive elements
187
+ shadow.addEventListener('keydown', (e) => {
188
+ this._emit('cx-keydown', { key: e.key, code: e.code, shiftKey: e.shiftKey, ctrlKey: e.ctrlKey, altKey: e.altKey, metaKey: e.metaKey });
189
+ });
190
+ shadow.addEventListener('keyup', (e) => {
191
+ this._emit('cx-keyup', { key: e.key, code: e.code, shiftKey: e.shiftKey, ctrlKey: e.ctrlKey, altKey: e.altKey, metaKey: e.metaKey });
192
+ });
193
+ } // end _isInitialized guard
194
+ super.connectedCallback();
195
+ }
196
+
197
+ disconnectedCallback() {
198
+ if (this.#outsideClick) {
199
+ document.removeEventListener('mousedown', this.#outsideClick);
200
+ this.#outsideClick = null;
201
+ }
202
+ super.disconnectedCallback();
203
+ }
204
+
205
+ // ── DOM accessors ──
206
+
207
+ #getInput() {
208
+ return this._shadow.querySelector('[data-date-picker-input]');
209
+ }
210
+
211
+ #getPanel() {
212
+ return this._shadow.querySelector('[data-date-picker-panel]');
213
+ }
214
+
215
+ #getTrigger() {
216
+ return this._shadow.querySelector('[data-date-picker-trigger]');
217
+ }
218
+
219
+ // ── Panel state ──
220
+
221
+ #isOpen() {
222
+ const panel = this.#getPanel();
223
+ return panel ? panel.hasAttribute('data-open') : false;
224
+ }
225
+
226
+ #open() {
227
+ const panel = this.#getPanel();
228
+ const input = this.#getInput();
229
+ const trigger = this._shadow.querySelector('button[data-floating-trigger]') || input;
230
+ if (!panel || this.#isOpen()) return;
231
+
232
+ // Position with fixed coordinates — escapes overflow:auto/scroll clipping.
233
+ if (trigger) this._positionFloatingFixed(trigger, panel);
234
+
235
+ panel.setAttribute('data-open', '');
236
+ panel.classList.remove('hidden');
237
+ panel.style.display = 'block';
238
+ panel.style.pointerEvents = 'auto';
239
+ panel.style.opacity = '1';
240
+
241
+ if (input) input.setAttribute('aria-expanded', 'true');
242
+
243
+ // Focus the active gridcell
244
+ requestAnimationFrame(() => {
245
+ const active = panel.querySelector('button[role="gridcell"][tabindex="0"]');
246
+ if (active) active.focus();
247
+ });
248
+ }
249
+
250
+ #close() {
251
+ const panel = this.#getPanel();
252
+ const input = this.#getInput();
253
+ if (!panel) return;
254
+
255
+ panel.removeAttribute('data-open');
256
+ panel.classList.add('hidden');
257
+ panel.style.display = '';
258
+ panel.style.pointerEvents = '';
259
+ panel.style.opacity = '';
260
+ this._resetFloatingFixed(panel);
261
+
262
+ if (input) {
263
+ input.setAttribute('aria-expanded', 'false');
264
+ input.focus();
265
+ }
266
+ }
267
+
268
+ #toggle() {
269
+ if (this.#isOpen()) this.#close();
270
+ else this.#open();
271
+ }
272
+
273
+ // ── Date selection ──
274
+
275
+ #selectDate(isoDate) {
276
+ this._props.selected = isoDate;
277
+
278
+ // Update input value
279
+ const input = this.#getInput();
280
+ if (input) {
281
+ input.value = isoDate;
282
+ this._setFormValue(isoDate);
283
+ }
284
+
285
+ this._emit('cx-change', { value: isoDate });
286
+ this.#close();
287
+
288
+ // Re-render to show updated calendar state
289
+ this._scheduleRender();
290
+ }
291
+
292
+ // ── Day stepping ──
293
+
294
+ #stepDay(delta) {
295
+ const current = this._props.selected;
296
+ if (!current) return;
297
+ const newDate = addDays(current, delta);
298
+ this._props.selected = newDate;
299
+
300
+ const input = this.#getInput();
301
+ if (input) {
302
+ input.value = newDate;
303
+ this._setFormValue(newDate);
304
+ }
305
+
306
+ this._emit('cx-change', { value: newDate });
307
+ this._scheduleRender();
308
+ }
309
+
310
+ // ── Month navigation ──
311
+
312
+ #navigateMonth(delta) {
313
+ // Find current viewing month from heading or selected date
314
+ const heading = this._shadow.querySelector('[data-date-picker-heading]');
315
+ const grid = this._shadow.querySelector('[data-date-picker-grid]');
316
+ if (!grid) return;
317
+
318
+ // Find a date in the current month from the grid
319
+ const firstCell = grid.querySelector('button[role="gridcell"]:not([aria-disabled="true"])');
320
+ if (!firstCell) return;
321
+
322
+ const currentDate = firstCell.getAttribute('data-date');
323
+ if (!currentDate) return;
324
+
325
+ const newMonthDate = addMonths(currentDate, delta);
326
+ const newMonth = getMonthYear(newMonthDate);
327
+
328
+ // Re-render with the new viewing month by updating a prop
329
+ // The WASM will render the correct month when we set selected or use viewing
330
+ this._props._viewing = newMonth;
331
+ this._scheduleRender();
332
+
333
+ // After re-render, focus first active cell
334
+ requestAnimationFrame(() => {
335
+ requestAnimationFrame(() => {
336
+ const panel = this.#getPanel();
337
+ if (panel && this.#isOpen()) {
338
+ // Restore open state after re-render
339
+ panel.setAttribute('data-open', '');
340
+ panel.classList.remove('hidden');
341
+ panel.style.display = 'block';
342
+ panel.style.pointerEvents = 'auto';
343
+ panel.style.opacity = '1';
344
+
345
+ const active = panel.querySelector('button[role="gridcell"][tabindex="0"]');
346
+ if (active) active.focus();
347
+ }
348
+ });
349
+ });
350
+ }
351
+
352
+ // ── Keyboard navigation ──
353
+
354
+ #handleKey(e) {
355
+ const input = this.#getInput();
356
+
357
+ // Input keyboard
358
+ if (e.target === input || e.target?.matches?.('[data-date-picker-input]')) {
359
+ if (e.key === 'ArrowDown' && !this.#isOpen()) {
360
+ e.preventDefault();
361
+ this.#open();
362
+ return;
363
+ }
364
+ if (e.key === 'Escape' && this.#isOpen()) {
365
+ e.preventDefault();
366
+ this.#close();
367
+ return;
368
+ }
369
+ if (e.key === 'Enter') {
370
+ // Try to parse typed date
371
+ const val = input?.value?.trim();
372
+ if (val && /^\d{4}-\d{2}-\d{2}$/.test(val)) {
373
+ e.preventDefault();
374
+ this.#selectDate(val);
375
+ }
376
+ return;
377
+ }
378
+ return;
379
+ }
380
+
381
+ // Grid cell keyboard
382
+ const cell = e.target?.closest?.('button[role="gridcell"]');
383
+ if (!cell) {
384
+ // Escape from anywhere in panel
385
+ if (e.key === 'Escape' && this.#isOpen()) {
386
+ e.preventDefault();
387
+ this.#close();
388
+ }
389
+ return;
390
+ }
391
+
392
+ const date = cell.getAttribute('data-date');
393
+ if (!date) return;
394
+
395
+ let targetDate = null;
396
+
397
+ switch (e.key) {
398
+ case 'ArrowRight':
399
+ e.preventDefault();
400
+ targetDate = addDays(date, 1);
401
+ break;
402
+ case 'ArrowLeft':
403
+ e.preventDefault();
404
+ targetDate = addDays(date, -1);
405
+ break;
406
+ case 'ArrowDown':
407
+ e.preventDefault();
408
+ targetDate = addDays(date, 7);
409
+ break;
410
+ case 'ArrowUp':
411
+ e.preventDefault();
412
+ targetDate = addDays(date, -7);
413
+ break;
414
+ case 'PageDown':
415
+ e.preventDefault();
416
+ targetDate = addMonths(date, e.shiftKey ? 12 : 1);
417
+ break;
418
+ case 'PageUp':
419
+ e.preventDefault();
420
+ targetDate = addMonths(date, e.shiftKey ? -12 : -1);
421
+ break;
422
+ case 'Home':
423
+ e.preventDefault();
424
+ targetDate = date.substring(0, 8) + '01';
425
+ break;
426
+ case 'End': {
427
+ e.preventDefault();
428
+ const d = new Date(date + 'T12:00:00');
429
+ d.setMonth(d.getMonth() + 1, 0);
430
+ targetDate = `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;
431
+ break;
432
+ }
433
+ case 'Enter':
434
+ case ' ':
435
+ e.preventDefault();
436
+ if (!cell.hasAttribute('aria-disabled')) {
437
+ this.#selectDate(date);
438
+ }
439
+ return;
440
+ case 'Escape':
441
+ e.preventDefault();
442
+ this.#close();
443
+ return;
444
+ case 'Tab':
445
+ this.#close();
446
+ return;
447
+ }
448
+
449
+ if (targetDate) {
450
+ // Try to find the target cell in current grid
451
+ const target = this._shadow.querySelector(`button[data-date="${targetDate}"]`);
452
+ if (target && !target.hasAttribute('aria-disabled')) {
453
+ // Same month — just move focus
454
+ this.#setGridFocus(target);
455
+ } else {
456
+ // Different month — navigate and focus after re-render
457
+ const targetMonth = getMonthYear(targetDate);
458
+ this._props._viewing = targetMonth;
459
+ this._props._focus_date = targetDate;
460
+ this._scheduleRender();
461
+
462
+ requestAnimationFrame(() => {
463
+ requestAnimationFrame(() => {
464
+ const panel = this.#getPanel();
465
+ if (panel) {
466
+ panel.setAttribute('data-open', '');
467
+ panel.classList.remove('hidden');
468
+ panel.style.display = 'block';
469
+ panel.style.pointerEvents = 'auto';
470
+ panel.style.opacity = '1';
471
+
472
+ const tc = this._shadow.querySelector(`button[data-date="${targetDate}"]`);
473
+ if (tc) this.#setGridFocus(tc);
474
+ }
475
+ });
476
+ });
477
+ }
478
+ }
479
+ }
480
+
481
+ #setGridFocus(cell) {
482
+ // Reset all cells to tabindex -1
483
+ this._shadow.querySelectorAll('button[role="gridcell"]').forEach(c => {
484
+ c.setAttribute('tabindex', '-1');
485
+ });
486
+ cell.setAttribute('tabindex', '0');
487
+ cell.focus();
488
+ }
489
+
490
+ // ── Public imperative API ──
491
+ open() { this.#open(); }
492
+ close() { this.#close(); }
493
+ focus() { const el = this._shadow.querySelector('button[data-floating-trigger]'); if (el) el.focus(); else super.focus(); }
494
+
495
+ // ── Render ──
496
+
497
+ _doRender() {
498
+ try {
499
+ const wasOpen = this.#isOpen();
500
+
501
+ const result = wasmFn(this._props);
502
+ this._injectHtml(result);
503
+
504
+ const sheet = getSheet();
505
+ if (!this._shadow.adoptedStyleSheets.includes(sheet)) {
506
+ this._shadow.adoptedStyleSheets = [...this._shadow.adoptedStyleSheets, sheet];
507
+ }
508
+
509
+ // Sync form value
510
+ const input = this.#getInput();
511
+ if (input) {
512
+ if (this._props.selected) input.value = this._props.selected;
513
+ this._setFormValue(input.value || '');
514
+ }
515
+
516
+ // Restore open state
517
+ if (wasOpen) {
518
+ this.#open();
519
+ }
520
+ } catch (e) {
521
+ console.error('[cx-date-picker]', e);
522
+ }
523
+ }
524
+ }
525
+
526
+ customElements.define('cx-date-picker', CxDatePicker);
527
+ return CxDatePicker;
528
+ }
@@ -0,0 +1,20 @@
1
+ // Auto-generated by scripts/generate-elements.mjs — DO NOT EDIT
2
+ // Source: crates/wasm-api/src/dialog.rs
3
+
4
+ export interface CxDialogAttributes {
5
+ id?: string;
6
+ title?: string;
7
+ variant?: 'standard' | 'alert';
8
+ description?: string;
9
+ body?: string;
10
+ footer?: string;
11
+ size?: 'sm' | 'md' | 'lg' | 'xl' | 'full';
12
+ closeButton?: string;
13
+ drawer?: string;
14
+ }
15
+
16
+ declare global {
17
+ interface HTMLElementTagNameMap {
18
+ 'cx-dialog': HTMLElement & CxDialogAttributes;
19
+ }
20
+ }