@uicraft/core 1.0.0 → 1.1.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.
package/package.json CHANGED
@@ -1,12 +1,14 @@
1
1
  {
2
2
  "name": "@uicraft/core",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "uicraft — beautifully designed UI components built with semantic CSS utility classes",
5
- "main": "uicraft.css",
5
+ "main": "uicraft.js",
6
6
  "style": "uicraft.css",
7
7
  "files": [
8
8
  "uicraft.css",
9
9
  "uicraft.min.css",
10
+ "uicraft.js",
11
+ "uicraft.min.js",
10
12
  "theme-manifest.json",
11
13
  "themes/"
12
14
  ],
package/uicraft.js ADDED
@@ -0,0 +1,882 @@
1
+ /*!
2
+ * uicraft.js v1.1.0
3
+ * https://getuicraft.com
4
+ * MIT License
5
+ */
6
+
7
+ // UCAccordion — expand/collapse with single and multi mode
8
+ var UCAccordion = {
9
+ init: function() {
10
+ var uid = 0;
11
+ document.querySelectorAll('[data-accordion-item]').forEach(function(item) {
12
+ uid++;
13
+ var trigger = item.querySelector('[data-accordion-trigger]');
14
+ var content = item.querySelector('[data-accordion-content]');
15
+ if (trigger && content) {
16
+ var tId = 'acc-trigger-' + uid;
17
+ var cId = 'acc-content-' + uid;
18
+ trigger.id = tId;
19
+ content.id = cId;
20
+ trigger.setAttribute('aria-controls', cId);
21
+ content.setAttribute('aria-labelledby', tId);
22
+ }
23
+ });
24
+
25
+ function openContent(content) {
26
+ content.classList.remove('uc-hidden');
27
+ content.classList.add('open');
28
+ content.style.maxHeight = content.scrollHeight + 16 + 'px';
29
+ }
30
+
31
+ function closeContent(content) {
32
+ content.style.maxHeight = '0px';
33
+ content.classList.remove('open');
34
+ content.addEventListener('transitionend', function handler() {
35
+ if (content.style.maxHeight === '0px') {
36
+ content.classList.add('uc-hidden');
37
+ }
38
+ content.removeEventListener('transitionend', handler);
39
+ });
40
+ }
41
+
42
+ document.querySelectorAll('[data-accordion-content]').forEach(function(content) {
43
+ if (!content.classList.contains('uc-hidden') && !content.classList.contains('hidden')) {
44
+ content.classList.add('open');
45
+ content.style.maxHeight = content.scrollHeight + 16 + 'px';
46
+ }
47
+ });
48
+
49
+ document.querySelectorAll('[data-accordion-trigger]').forEach(function(trigger) {
50
+ if (trigger.hasAttribute('data-accordion-init')) return;
51
+ trigger.setAttribute('data-accordion-init', 'true');
52
+
53
+ trigger.addEventListener('click', function() {
54
+ var item = trigger.closest('[data-accordion-item]');
55
+ var accordion = trigger.closest('[data-accordion]');
56
+ var mode = accordion.getAttribute('data-accordion');
57
+ var content = item.querySelector('[data-accordion-content]');
58
+ var icon = trigger.querySelector('[data-accordion-icon]');
59
+ var isOpen = !content.classList.contains('uc-hidden') && !content.classList.contains('hidden') && content.classList.contains('open');
60
+
61
+ if (mode === 'single') {
62
+ accordion.querySelectorAll('[data-accordion-item]').forEach(function(otherItem) {
63
+ var otherContent = otherItem.querySelector('[data-accordion-content]');
64
+ var otherTrigger = otherItem.querySelector('[data-accordion-trigger]');
65
+ var otherIcon = otherItem.querySelector('[data-accordion-trigger] [data-accordion-icon]');
66
+ if (otherItem !== item && !otherContent.classList.contains('uc-hidden') && !otherContent.classList.contains('hidden')) {
67
+ closeContent(otherContent);
68
+ if (otherIcon) otherIcon.classList.remove('uc-rotate-180');
69
+ if (otherTrigger) otherTrigger.setAttribute('aria-expanded', 'false');
70
+ }
71
+ });
72
+ }
73
+
74
+ if (isOpen) {
75
+ closeContent(content);
76
+ if (icon) icon.classList.remove('uc-rotate-180');
77
+ trigger.setAttribute('aria-expanded', 'false');
78
+ } else {
79
+ content.classList.remove('uc-hidden');
80
+ content.offsetHeight;
81
+ openContent(content);
82
+ if (icon) icon.classList.add('uc-rotate-180');
83
+ trigger.setAttribute('aria-expanded', 'true');
84
+ }
85
+ });
86
+ });
87
+ }
88
+ };
89
+
90
+ // UCCollapsible — expand/collapse content with optional animation
91
+ var UCCollapsible = {
92
+ init: function() {
93
+ // Initialize open collapsibles
94
+ document.querySelectorAll('[data-collapsible][data-collapsible-open]').forEach(function(collapsible) {
95
+ var content = collapsible.querySelector('[data-collapsible-content]');
96
+ var icon = collapsible.querySelector('[data-collapsible-icon]');
97
+ if (content) {
98
+ content.classList.remove('uc-hidden');
99
+ if (collapsible.hasAttribute('data-collapsible-animated')) {
100
+ content.style.maxHeight = content.scrollHeight + 'px';
101
+ }
102
+ }
103
+ if (icon) {
104
+ icon.classList.add('uc-rotate-180');
105
+ }
106
+ });
107
+
108
+ // Bind triggers with guard
109
+ document.querySelectorAll('[data-collapsible-trigger]').forEach(function(trigger) {
110
+ if (trigger.hasAttribute('data-collapsible-bound')) return;
111
+ trigger.setAttribute('data-collapsible-bound', 'true');
112
+
113
+ trigger.addEventListener('click', function() {
114
+ var collapsible = trigger.closest('[data-collapsible]');
115
+ var content = collapsible.querySelector(':scope > [data-collapsible-content]');
116
+ if (!content) {
117
+ content = collapsible.querySelector('[data-collapsible-content]');
118
+ }
119
+ var icon = collapsible.querySelector(':scope > * [data-collapsible-icon]') || collapsible.querySelector('[data-collapsible-icon]');
120
+ var isAnimated = collapsible.hasAttribute('data-collapsible-animated');
121
+ var labelCollapse = trigger.querySelector('[data-collapsible-label-collapse]');
122
+ var labelExpand = trigger.querySelector('[data-collapsible-label-expand]');
123
+ var isOpen;
124
+
125
+ if (isAnimated) {
126
+ isOpen = parseInt(content.style.maxHeight) > 0;
127
+ } else {
128
+ isOpen = !content.classList.contains('uc-hidden');
129
+ }
130
+
131
+ if (isOpen) {
132
+ if (isAnimated) {
133
+ content.style.maxHeight = '0';
134
+ } else {
135
+ content.classList.add('uc-hidden');
136
+ }
137
+ if (icon) icon.classList.remove('uc-rotate-180');
138
+ if (labelCollapse) labelCollapse.classList.add('uc-hidden');
139
+ if (labelExpand) labelExpand.classList.remove('uc-hidden');
140
+ collapsible.removeAttribute('data-collapsible-open');
141
+ } else {
142
+ if (isAnimated) {
143
+ content.style.maxHeight = content.scrollHeight + 'px';
144
+ } else {
145
+ content.classList.remove('uc-hidden');
146
+ }
147
+ if (icon) icon.classList.add('uc-rotate-180');
148
+ if (labelCollapse) labelCollapse.classList.remove('uc-hidden');
149
+ if (labelExpand) labelExpand.classList.add('uc-hidden');
150
+ collapsible.setAttribute('data-collapsible-open', '');
151
+ }
152
+ });
153
+ });
154
+ }
155
+ };
156
+
157
+ // UCCombobox — searchable single/multi-select with tags
158
+ var UCCombobox = {
159
+ init: function() {
160
+ var checkSvg = '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="uc-w-4 uc-h-4 uc-shrink-0 uc-text-accents-blue uc-combobox-icon"><path d="M20 6 9 17l-5-5"/></svg>';
161
+ var emptySpacer = '<span class="uc-w-4 uc-h-4 uc-shrink-0 uc-combobox-icon"></span>';
162
+ var xTagSvg = '<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="uc-w-3 uc-h-3"><path d="M18 6 6 18"/><path d="m6 6 12 12"/></svg>';
163
+
164
+ // Close on click outside
165
+ if (!document.body.hasAttribute('data-combobox-outside-init')) {
166
+ document.body.setAttribute('data-combobox-outside-init', 'true');
167
+ document.addEventListener('click', function(e) {
168
+ if (!e.target.closest('.uc-combobox-wrapper')) {
169
+ document.querySelectorAll('[data-combobox-content]').forEach(function(el) {
170
+ el.classList.remove('uc-open');
171
+ });
172
+ }
173
+ });
174
+ }
175
+
176
+ // Expose functions globally for inline onclick use
177
+ window.openCombobox = function(id) {
178
+ var el = document.getElementById(id);
179
+ if (el) el.classList.add('uc-open');
180
+ };
181
+
182
+ window.toggleCombobox = function(id) {
183
+ var el = document.getElementById(id);
184
+ if (el) el.classList.toggle('uc-open');
185
+ };
186
+
187
+ window.filterCombobox = function(input, id) {
188
+ var dropdown = document.getElementById(id);
189
+ var query = input.value.toLowerCase();
190
+ var items = dropdown.querySelectorAll('.uc-combobox-item');
191
+ var groups = dropdown.querySelectorAll('[data-combobox-group]');
192
+ var emptyEl = dropdown.querySelector('.uc-combobox-empty');
193
+ var totalVisible = 0;
194
+
195
+ if (groups.length > 0) {
196
+ groups.forEach(function(group) {
197
+ var groupItems = group.querySelectorAll('.uc-combobox-item');
198
+ var groupVisible = 0;
199
+ groupItems.forEach(function(item) {
200
+ if (item.textContent.toLowerCase().includes(query)) {
201
+ item.classList.remove('uc-hidden');
202
+ groupVisible++;
203
+ totalVisible++;
204
+ } else {
205
+ item.classList.add('uc-hidden');
206
+ }
207
+ });
208
+ group.style.display = groupVisible > 0 ? '' : 'none';
209
+ });
210
+ } else {
211
+ items.forEach(function(item) {
212
+ if (item.textContent.toLowerCase().includes(query)) {
213
+ item.classList.remove('uc-hidden');
214
+ totalVisible++;
215
+ } else {
216
+ item.classList.add('uc-hidden');
217
+ }
218
+ });
219
+ }
220
+
221
+ if (emptyEl) {
222
+ emptyEl.classList.toggle('uc-hidden', totalVisible > 0 || !query);
223
+ }
224
+ };
225
+
226
+ function setItemIcon(item, checked) {
227
+ var icon = item.querySelector('.uc-combobox-icon');
228
+ if (icon) icon.outerHTML = checked ? checkSvg : emptySpacer;
229
+ }
230
+
231
+ window.selectComboboxItem = function(item) {
232
+ var text = item.textContent.trim();
233
+ var wrapper = item.closest('.uc-combobox-wrapper');
234
+ var keepIcons = wrapper.hasAttribute('data-keep-icons');
235
+ var input = wrapper.querySelector('input');
236
+ var dropdown = item.closest('[data-combobox-content]');
237
+
238
+ input.value = text;
239
+
240
+ dropdown.querySelectorAll('.uc-combobox-item').forEach(function(i) {
241
+ i.classList.remove('uc-selected');
242
+ if (!keepIcons) setItemIcon(i, false);
243
+ });
244
+ item.classList.add('uc-selected');
245
+ if (!keepIcons) setItemIcon(item, true);
246
+
247
+ dropdown.classList.remove('uc-open');
248
+ };
249
+
250
+ window.selectComboboxButton = function(item, dropdownId) {
251
+ var text = item.textContent.trim();
252
+ var wrapper = item.closest('.uc-combobox-wrapper');
253
+ var label = wrapper.querySelector('.uc-combobox-button-label');
254
+ var dropdown = document.getElementById(dropdownId);
255
+
256
+ label.textContent = text;
257
+ label.classList.remove('uc-text-fg-disabled');
258
+
259
+ dropdown.querySelectorAll('.uc-combobox-item').forEach(function(i) {
260
+ i.classList.remove('uc-selected');
261
+ setItemIcon(i, false);
262
+ });
263
+ item.classList.add('uc-selected');
264
+ setItemIcon(item, true);
265
+
266
+ dropdown.classList.remove('uc-open');
267
+ };
268
+
269
+ window.toggleMultiComboboxItem = function(item) {
270
+ var isSelected = item.classList.toggle('uc-selected');
271
+ setItemIcon(item, isSelected);
272
+
273
+ var wrapper = item.closest('.uc-combobox-wrapper');
274
+ var tagContainer = wrapper.querySelector('.uc-combobox-tags');
275
+ var text = item.textContent.trim();
276
+
277
+ if (isSelected) {
278
+ var tag = document.createElement('span');
279
+ tag.className = 'uc-combobox-tag uc-inline-flex uc-items-center uc-gap-1 uc-rounded uc-bg-neutrals-subtle uc-px-2 uc-py-0.5 uc-text-xs uc-font-medium';
280
+ tag.setAttribute('data-tag-value', text);
281
+ tag.innerHTML = text + '<button type="button" onclick="event.stopPropagation(); removeComboboxTag(this)" class="uc-ml-0.5 uc-rounded-sm uc-hover:bg-neutrals-muted uc-transition-colors">' + xTagSvg + '</button>';
282
+ tagContainer.insertBefore(tag, tagContainer.querySelector('input'));
283
+ } else {
284
+ var existing = tagContainer.querySelector('[data-tag-value="' + text + '"]');
285
+ if (existing) existing.remove();
286
+ }
287
+
288
+ UCCombobox._updateMultiPlaceholder(wrapper);
289
+ };
290
+
291
+ window.removeComboboxTag = function(btn) {
292
+ var tag = btn.closest('.uc-combobox-tag');
293
+ if (!tag) return;
294
+ var value = tag.getAttribute('data-tag-value');
295
+ var wrapper = tag.closest('.uc-combobox-wrapper');
296
+ tag.remove();
297
+
298
+ var dropdown = wrapper.querySelector('[data-combobox-content]');
299
+ if (dropdown) {
300
+ dropdown.querySelectorAll('.uc-combobox-item').forEach(function(item) {
301
+ if (item.textContent.trim() === value) {
302
+ item.classList.remove('uc-selected');
303
+ setItemIcon(item, false);
304
+ }
305
+ });
306
+ }
307
+
308
+ UCCombobox._updateMultiPlaceholder(wrapper);
309
+ };
310
+ },
311
+
312
+ _updateMultiPlaceholder: function(wrapper) {
313
+ var input = wrapper.querySelector('input');
314
+ var tags = wrapper.querySelectorAll('.uc-combobox-tag');
315
+ if (input) {
316
+ input.placeholder = tags.length > 0 ? '' : 'Add framework...';
317
+ }
318
+ }
319
+ };
320
+
321
+ // UCResizable — drag-to-resize panels horizontally or vertically
322
+ var UCResizable = {
323
+ init: function() {
324
+ document.querySelectorAll('[data-resizable]').forEach(function(container) {
325
+ if (container.hasAttribute('data-resizable-init')) return;
326
+ container.setAttribute('data-resizable-init', 'true');
327
+
328
+ var direction = container.dataset.resizable;
329
+ var isHorizontal = direction === 'horizontal';
330
+ var minPct = parseFloat(container.dataset.min || '10');
331
+ var maxPct = parseFloat(container.dataset.max || '90');
332
+ var handles = container.querySelectorAll(':scope > .uc-resize-handle');
333
+
334
+ handles.forEach(function(handle) {
335
+ var isDown = false;
336
+ var startPos = 0;
337
+ var prevPanel = null;
338
+ var nextPanel = null;
339
+ var containerSize = 0;
340
+ var prevStart = 0;
341
+ var nextStart = 0;
342
+
343
+ handle.addEventListener('mousedown', function(e) {
344
+ e.preventDefault();
345
+ isDown = true;
346
+ prevPanel = handle.previousElementSibling;
347
+ nextPanel = handle.nextElementSibling;
348
+ if (!prevPanel || !nextPanel) return;
349
+
350
+ containerSize = isHorizontal ? container.offsetWidth : container.offsetHeight;
351
+ prevStart = isHorizontal ? prevPanel.offsetWidth : prevPanel.offsetHeight;
352
+ nextStart = isHorizontal ? nextPanel.offsetWidth : nextPanel.offsetHeight;
353
+ startPos = isHorizontal ? e.clientX : e.clientY;
354
+
355
+ document.body.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';
356
+ document.body.style.userSelect = 'none';
357
+ handle.style.background = 'hsl(var(--accents-blue) / 0.5)';
358
+ });
359
+
360
+ document.addEventListener('mousemove', function(e) {
361
+ if (!isDown || !prevPanel || !nextPanel) return;
362
+ var delta = (isHorizontal ? e.clientX : e.clientY) - startPos;
363
+ var newPrev = prevStart + delta;
364
+ var newNext = nextStart - delta;
365
+
366
+ var minSize = containerSize * (minPct / 100);
367
+ var maxSize = containerSize * (maxPct / 100);
368
+
369
+ if (newPrev < minSize) { newPrev = minSize; newNext = prevStart + nextStart - minSize; }
370
+ if (newNext < minSize) { newNext = minSize; newPrev = prevStart + nextStart - minSize; }
371
+ if (newPrev > maxSize) { newPrev = maxSize; newNext = prevStart + nextStart - maxSize; }
372
+ if (newNext > maxSize) { newNext = maxSize; newPrev = prevStart + nextStart - maxSize; }
373
+
374
+ var prevPct = (newPrev / containerSize * 100).toFixed(1);
375
+ var nextPct = (newNext / containerSize * 100).toFixed(1);
376
+
377
+ if (isHorizontal) {
378
+ prevPanel.style.width = prevPct + '%';
379
+ nextPanel.style.width = nextPct + '%';
380
+ } else {
381
+ prevPanel.style.height = prevPct + '%';
382
+ nextPanel.style.height = nextPct + '%';
383
+ }
384
+
385
+ prevPanel.style.flex = 'none';
386
+ nextPanel.style.flex = 'none';
387
+
388
+ var prevLabel = prevPanel.querySelector('.uc-size-label');
389
+ var nextLabel = nextPanel.querySelector('.uc-size-label');
390
+ if (prevLabel) prevLabel.textContent = Math.round(parseFloat(prevPct)) + '%';
391
+ if (nextLabel) nextLabel.textContent = Math.round(parseFloat(nextPct)) + '%';
392
+ });
393
+
394
+ document.addEventListener('mouseup', function() {
395
+ if (!isDown) return;
396
+ isDown = false;
397
+ document.body.style.cursor = '';
398
+ document.body.style.userSelect = '';
399
+ handle.style.background = '';
400
+ });
401
+ });
402
+ });
403
+ }
404
+ };
405
+
406
+ // UCCarousel — slide carousel with dots, prev/next navigation
407
+ var UCCarousel = {
408
+ init: function() {
409
+ document.querySelectorAll('[data-carousel]').forEach(function(el) {
410
+ if (el.hasAttribute('data-carousel-init')) return;
411
+ el.setAttribute('data-carousel-init', 'true');
412
+
413
+ var carousel = el;
414
+ var track = carousel.querySelector('[data-carousel-track]');
415
+ var prevBtn = carousel.querySelector('[data-carousel-prev]');
416
+ var nextBtn = carousel.querySelector('[data-carousel-next]');
417
+ var dotsContainer = carousel.querySelector('[data-carousel-dots]');
418
+ var total = parseInt(carousel.dataset.total || '0');
419
+ var visible = parseInt(carousel.dataset.visible || '1');
420
+ var maxIndex = total - visible;
421
+ var current = 0;
422
+
423
+ function update() {
424
+ if (visible === 1) {
425
+ track.style.transform = 'translateX(-' + (current * 100) + '%)';
426
+ } else {
427
+ var slide = track.children[0];
428
+ var gap = parseFloat(getComputedStyle(track).gap) || 0;
429
+ var offset = current * (slide.offsetWidth + gap);
430
+ track.style.transform = 'translateX(-' + offset + 'px)';
431
+ }
432
+
433
+ if (dotsContainer) {
434
+ dotsContainer.querySelectorAll('[data-dot]').forEach(function(dot) {
435
+ var idx = parseInt(dot.dataset.dot || '0');
436
+ dot.className = 'uc-w-2 uc-h-2 uc-rounded-full uc-transition-colors ' + (idx === current ? 'uc-bg-accents-blue' : 'uc-bg-neutrals-muted');
437
+ });
438
+ }
439
+
440
+ if (prevBtn) prevBtn.style.opacity = current === 0 ? '0.4' : '1';
441
+ if (nextBtn) nextBtn.style.opacity = current >= maxIndex ? '0.4' : '1';
442
+ }
443
+
444
+ if (prevBtn) {
445
+ prevBtn.addEventListener('click', function() {
446
+ if (current > 0) { current--; update(); }
447
+ });
448
+ }
449
+
450
+ if (nextBtn) {
451
+ nextBtn.addEventListener('click', function() {
452
+ if (current < maxIndex) { current++; update(); }
453
+ });
454
+ }
455
+
456
+ if (dotsContainer) {
457
+ dotsContainer.querySelectorAll('[data-dot]').forEach(function(dot) {
458
+ dot.addEventListener('click', function() {
459
+ current = Math.min(parseInt(dot.dataset.dot || '0'), maxIndex);
460
+ update();
461
+ });
462
+ });
463
+ }
464
+
465
+ update();
466
+ });
467
+ }
468
+ };
469
+
470
+ // UCDropdown — dropdown menu with checkbox and radio item support
471
+ var UCDropdown = {
472
+ init: function() {
473
+ if (document.body.hasAttribute('data-dropdowns-init')) return;
474
+ document.body.setAttribute('data-dropdowns-init', 'true');
475
+
476
+ document.addEventListener('click', function(e) {
477
+ if (!e.target.closest('[data-dropdown-trigger]') && !e.target.closest('.uc-dropdown-menu')) {
478
+ document.querySelectorAll('.uc-dropdown-menu').forEach(function(el) {
479
+ el.classList.remove('uc-open');
480
+ });
481
+ }
482
+ });
483
+
484
+ document.querySelectorAll('[data-dropdown-trigger]').forEach(function(trigger) {
485
+ if (trigger.hasAttribute('data-dropdown-bound')) return;
486
+ trigger.setAttribute('data-dropdown-bound', 'true');
487
+ trigger.addEventListener('click', function(e) {
488
+ e.stopPropagation();
489
+ var targetId = trigger.getAttribute('data-dropdown-trigger');
490
+ var content = document.getElementById(targetId);
491
+ if (!content) return;
492
+
493
+ document.querySelectorAll('.uc-dropdown-menu').forEach(function(el) {
494
+ if (el !== content) el.classList.remove('uc-open');
495
+ });
496
+
497
+ content.classList.toggle('uc-open');
498
+ });
499
+ });
500
+ }
501
+ };
502
+
503
+ // Checkbox toggle — called via onclick in HTML
504
+ function toggleCheckbox(el) {
505
+ var indicator = el.querySelector('.checkbox-indicator');
506
+ var isChecked = indicator.classList.contains('uc-bg-accents-blue');
507
+
508
+ if (isChecked) {
509
+ indicator.classList.remove('uc-bg-accents-blue', 'uc-text-constant-white', 'uc-border-transparent');
510
+ indicator.innerHTML = '';
511
+ } else {
512
+ indicator.classList.add('uc-bg-accents-blue', 'uc-text-constant-white', 'uc-border-transparent');
513
+ indicator.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" class="uc-w-3 uc-h-3"><path d="M20 6 9 17l-5-5"/></svg>';
514
+ }
515
+ }
516
+
517
+ // Radio select — called via onclick in HTML
518
+ function selectRadio(el) {
519
+ var parent = el.closest('.uc-dropdown-menu');
520
+ parent.querySelectorAll('.radio-indicator').forEach(function(r) {
521
+ r.classList.remove('uc-border-accents-blue');
522
+ r.classList.add('uc-border-input');
523
+ r.innerHTML = '';
524
+ });
525
+
526
+ var indicator = el.querySelector('.radio-indicator');
527
+ indicator.classList.remove('uc-border-input');
528
+ indicator.classList.add('uc-border-accents-blue');
529
+ indicator.innerHTML = '<div class="uc-w-2 uc-h-2 uc-rounded-full uc-bg-accents-blue"></div>';
530
+ }
531
+
532
+ // UCScrollView — drag-to-scroll and scroll indicators
533
+ var UCScrollView = {
534
+ init: function() {
535
+ // Drag-to-scroll for horizontal containers
536
+ document.querySelectorAll('.uc-drag-scroll').forEach(function(el) {
537
+ if (el.hasAttribute('data-drag-init')) return;
538
+ el.setAttribute('data-drag-init', 'true');
539
+
540
+ var isDown = false;
541
+ var startX = 0;
542
+ var scrollLeft = 0;
543
+
544
+ el.addEventListener('mousedown', function(e) {
545
+ isDown = true;
546
+ el.style.cursor = 'grabbing';
547
+ el.style.userSelect = 'none';
548
+ startX = e.pageX - el.offsetLeft;
549
+ scrollLeft = el.scrollLeft;
550
+ });
551
+
552
+ el.addEventListener('mouseleave', function() {
553
+ isDown = false;
554
+ el.style.cursor = 'grab';
555
+ el.style.userSelect = '';
556
+ });
557
+
558
+ el.addEventListener('mouseup', function() {
559
+ isDown = false;
560
+ el.style.cursor = 'grab';
561
+ el.style.userSelect = '';
562
+ });
563
+
564
+ el.addEventListener('mousemove', function(e) {
565
+ if (!isDown) return;
566
+ e.preventDefault();
567
+ var x = e.pageX - el.offsetLeft;
568
+ var walk = (x - startX) * 1.5;
569
+ el.scrollLeft = scrollLeft - walk;
570
+ });
571
+ });
572
+
573
+ // Scroll indicators — vertical
574
+ document.querySelectorAll('.uc-scroll-indicator').forEach(function(indicator) {
575
+ if (indicator.hasAttribute('data-indicator-init')) return;
576
+ indicator.setAttribute('data-indicator-init', 'true');
577
+
578
+ var scroll = indicator.querySelector('.uc-scroll, .uc-scroll-hidden, .uc-scroll-autohide');
579
+ if (!scroll) return;
580
+
581
+ scroll.addEventListener('scroll', function() {
582
+ var st = scroll.scrollTop;
583
+ var sh = scroll.scrollHeight;
584
+ var ch = scroll.clientHeight;
585
+ indicator.classList.toggle('uc-show-top', st > 8);
586
+ indicator.classList.toggle('uc-show-bottom', st < sh - ch - 8);
587
+ });
588
+ });
589
+
590
+ // Scroll indicators — horizontal
591
+ document.querySelectorAll('.uc-scroll-indicator-h').forEach(function(indicator) {
592
+ if (indicator.hasAttribute('data-indicator-h-init')) return;
593
+ indicator.setAttribute('data-indicator-h-init', 'true');
594
+
595
+ var scroll = indicator.querySelector('.uc-scroll, .uc-scroll-hidden, .uc-scroll-autohide, [class*="uc-overflow-x"]');
596
+ if (!scroll) return;
597
+
598
+ scroll.addEventListener('scroll', function() {
599
+ var sl = scroll.scrollLeft;
600
+ var sw = scroll.scrollWidth;
601
+ var cw = scroll.clientWidth;
602
+ indicator.classList.toggle('uc-show-left', sl > 8);
603
+ indicator.classList.toggle('uc-show-right', sl < sw - cw - 8);
604
+ });
605
+ });
606
+ }
607
+ };
608
+
609
+ // UCNumberInput — increment/decrement with min/max constraints
610
+ var UCNumberInput = {
611
+ init: function() {
612
+ document.querySelectorAll('[data-number-input]').forEach(function(wrapper) {
613
+ if (wrapper.hasAttribute('data-ni-bound')) return;
614
+ wrapper.setAttribute('data-ni-bound', 'true');
615
+
616
+ var input = wrapper.querySelector('[data-number-value]');
617
+ var decBtn = wrapper.querySelector('[data-action="decrement"]');
618
+ var incBtn = wrapper.querySelector('[data-action="increment"]');
619
+ if (!input) return;
620
+
621
+ function updateButtons() {
622
+ var val = parseInt(input.value) || 0;
623
+ var min = input.hasAttribute('min') ? parseInt(input.min) : -Infinity;
624
+ var max = input.hasAttribute('max') ? parseInt(input.max) : Infinity;
625
+ if (decBtn) decBtn.disabled = val <= min;
626
+ if (incBtn) incBtn.disabled = val >= max;
627
+ }
628
+
629
+ function step(delta) {
630
+ var val = parseInt(input.value) || 0;
631
+ var min = input.hasAttribute('min') ? parseInt(input.min) : -Infinity;
632
+ var max = input.hasAttribute('max') ? parseInt(input.max) : Infinity;
633
+ var next = Math.min(Math.max(val + delta, min), max);
634
+ input.value = next;
635
+ updateButtons();
636
+ }
637
+
638
+ if (decBtn) decBtn.addEventListener('click', function() { step(-1); });
639
+ if (incBtn) incBtn.addEventListener('click', function() { step(1); });
640
+
641
+ input.addEventListener('change', function() {
642
+ var min = input.hasAttribute('min') ? parseInt(input.min) : -Infinity;
643
+ var max = input.hasAttribute('max') ? parseInt(input.max) : Infinity;
644
+ var val = parseInt(input.value) || min;
645
+ input.value = Math.min(Math.max(val, min), max);
646
+ updateButtons();
647
+ });
648
+
649
+ updateButtons();
650
+ });
651
+ }
652
+ };
653
+
654
+ // UCPopover — toggle popover panels with outside-click close
655
+ var UCPopover = {
656
+ init: function() {
657
+ document.querySelectorAll('[data-popover-trigger]').forEach(function(btn) {
658
+ btn.onclick = function(e) {
659
+ e.stopPropagation();
660
+ var id = btn.getAttribute('data-popover-trigger');
661
+ var el = id ? document.getElementById(id) : null;
662
+ if (!el) return;
663
+
664
+ var isOpen = el.classList.contains('uc-open');
665
+
666
+ document.querySelectorAll('.uc-popover-content').forEach(function(p) {
667
+ p.classList.remove('uc-open');
668
+ });
669
+
670
+ if (!isOpen) el.classList.add('uc-open');
671
+ };
672
+ });
673
+
674
+ if (!document.body.hasAttribute('data-popover-outside-init')) {
675
+ document.body.setAttribute('data-popover-outside-init', 'true');
676
+ document.addEventListener('click', function(e) {
677
+ var target = e.target;
678
+ if (!target.closest('.uc-popover-content') && !target.closest('[data-popover-trigger]')) {
679
+ document.querySelectorAll('.uc-popover-content').forEach(function(p) {
680
+ p.classList.remove('uc-open');
681
+ });
682
+ }
683
+ });
684
+ }
685
+ }
686
+ };
687
+
688
+ // UCSelect — custom select dropdown with single selection
689
+ var UCSelect = {
690
+ init: function() {
691
+ if (document.body.hasAttribute('data-select-init')) return;
692
+ document.body.setAttribute('data-select-init', 'true');
693
+
694
+ document.addEventListener('click', function(e) {
695
+ if (!e.target.closest('.uc-select-wrapper')) {
696
+ document.querySelectorAll('.uc-select-dropdown').forEach(function(d) {
697
+ d.classList.remove('open');
698
+ });
699
+ }
700
+ });
701
+ }
702
+ };
703
+
704
+ // toggleSelect — called via onclick in HTML
705
+ function toggleSelect(id) {
706
+ var dropdown = document.getElementById(id);
707
+ document.querySelectorAll('.uc-select-dropdown').forEach(function(d) {
708
+ if (d.id !== id) d.classList.remove('open');
709
+ });
710
+ dropdown.classList.toggle('open');
711
+ }
712
+
713
+ // selectItem — called via onclick in HTML
714
+ function selectItem(id, triggerId, value) {
715
+ document.getElementById(triggerId).querySelector('span').textContent = value;
716
+ document.getElementById(triggerId).querySelector('span').classList.remove('placeholder');
717
+ var dropdown = document.getElementById(id);
718
+ dropdown.querySelectorAll('.uc-select-item').forEach(function(i) {
719
+ i.classList.remove('selected');
720
+ });
721
+ dropdown.querySelectorAll('.uc-select-item').forEach(function(i) {
722
+ if (i.textContent.trim() === value) i.classList.add('selected');
723
+ });
724
+ dropdown.classList.remove('open');
725
+ }
726
+
727
+ // UCToast — programmatic toast notifications
728
+ var UCToast = {
729
+ _count: 0,
730
+
731
+ show: function(type) {
732
+ var container = document.getElementById('toast-container');
733
+ if (!container) return;
734
+
735
+ var id = 'toast-' + (++UCToast._count);
736
+ var configs = {
737
+ default: { title: 'Scheduled: Catch up', desc: 'Friday, February 14, 2026 at 5:57 PM', icon: '', btn: 'Undo' },
738
+ success: { title: 'Success', desc: 'Your changes have been saved.', icon: '<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="uc-w-5 uc-h-5 uc-text-accents-blue"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/><path d="M22 4 12 14.01l-3-3"/></svg>', btn: '' },
739
+ error: { title: 'Error', desc: 'Something went wrong. Please try again.', icon: '<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="uc-w-5 uc-h-5 uc-text-accents-red"><circle cx="12" cy="12" r="10"/><line x1="12" x2="12" y1="8" y2="12"/><line x1="12" x2="12.01" y1="16" y2="16"/></svg>', btn: 'Retry' },
740
+ action: { title: 'Event created', desc: 'Sunday, December 03, 2023', icon: '', btn: 'Undo' }
741
+ };
742
+
743
+ var c = configs[type] || configs.default;
744
+ var toast = document.createElement('div');
745
+ toast.id = id;
746
+ toast.className = 'uc-flex uc-items-start uc-gap-3 uc-w-80 uc-p-4 uc-rounded-lg uc-border uc-border-border-default uc-bg-neutrals-surface uc-shadow-lg uc-mb-2';
747
+ toast.innerHTML =
748
+ (c.icon ? '<div class="uc-flex-shrink-0 uc-mt-0.5">' + c.icon + '</div>' : '') +
749
+ '<div class="uc-flex-1 uc-min-w-0">' +
750
+ '<p class="uc-text-sm uc-font-semibold">' + c.title + '</p>' +
751
+ '<p class="uc-text-xs uc-text-fg-disabled uc-mt-0.5">' + c.desc + '</p>' +
752
+ '</div>' +
753
+ (c.btn ? '<button onclick="this.parentElement.remove()" class="uc-flex-shrink-0 uc-inline-flex uc-items-center uc-justify-center uc-rounded-lg uc-text-xs uc-font-medium uc-h-7 uc-px-2 uc-border uc-border-border-strong uc-bg-neutrals-surface uc-hover:bg-neutrals-subtle uc-transition-colors">' + c.btn + '</button>' : '') +
754
+ '<button onclick="this.parentElement.remove()" class="uc-flex-shrink-0 uc-p-0.5 uc-text-fg-disabled uc-hover:text-fg-primary uc-transition-colors">' +
755
+ '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="uc-w-3.5 uc-h-3.5"><path d="M18 6 6 18"/><path d="m6 6 12 12"/></svg>' +
756
+ '</button>';
757
+
758
+ container.appendChild(toast);
759
+ setTimeout(function() {
760
+ var el = document.getElementById(id);
761
+ if (el) el.remove();
762
+ }, 4000);
763
+ },
764
+
765
+ init: function() {
766
+ // Expose showToast globally for onclick use
767
+ window.showToast = function(type) { UCToast.show(type); };
768
+ }
769
+ };
770
+
771
+ // UCDialog — modal dialog with focus trap and keyboard support
772
+ var UCDialog = {
773
+ init: function() {
774
+ // Expose functions globally for onclick use
775
+ window.openDialog = function(id) {
776
+ var el = document.getElementById(id);
777
+ if (!el) return;
778
+ el.classList.add('uc-open');
779
+ el.removeAttribute('aria-hidden');
780
+ var focusable = el.querySelector('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])');
781
+ if (focusable) focusable.focus();
782
+ el._keyHandler = function(e) {
783
+ if (e.key === 'Escape') { window.closeDialog(id); return; }
784
+ if (e.key !== 'Tab') return;
785
+ var all = el.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])');
786
+ var first = all[0];
787
+ var last = all[all.length - 1];
788
+ if (e.shiftKey && document.activeElement === first) { e.preventDefault(); last.focus(); }
789
+ else if (!e.shiftKey && document.activeElement === last) { e.preventDefault(); first.focus(); }
790
+ };
791
+ document.addEventListener('keydown', el._keyHandler);
792
+ };
793
+
794
+ window.closeDialog = function(id) {
795
+ var el = document.getElementById(id);
796
+ if (!el) return;
797
+ el.classList.remove('uc-open');
798
+ el.setAttribute('aria-hidden', 'true');
799
+ if (el._keyHandler) document.removeEventListener('keydown', el._keyHandler);
800
+ };
801
+ }
802
+ };
803
+
804
+ // UCTreeView — expandable/collapsible tree nodes
805
+ var UCTreeView = {
806
+ init: function() {
807
+ document.querySelectorAll('[data-tree]').forEach(function(tree) {
808
+ if (tree.hasAttribute('data-tree-bound')) return;
809
+ tree.setAttribute('data-tree-bound', 'true');
810
+
811
+ tree.querySelectorAll('[data-tree-branch]').forEach(function(branch) {
812
+ var toggle = branch.querySelector(':scope > .uc-tree-toggle');
813
+ if (!toggle) return;
814
+ toggle.addEventListener('click', function() {
815
+ branch.classList.toggle('open');
816
+ });
817
+ });
818
+ });
819
+ }
820
+ };
821
+
822
+ // UCSheet — slide-in panels from any edge
823
+ var UCSheet = {
824
+ init: function() {
825
+ // Expose functions globally for onclick use
826
+ window.openSheet = function(id) {
827
+ var overlay = document.getElementById('uc-sheet-overlay');
828
+ if (overlay) overlay.classList.add('uc-open');
829
+ var sheet = document.getElementById(id);
830
+ if (sheet) sheet.classList.add('uc-open');
831
+ };
832
+
833
+ window.closeSheet = function(id) {
834
+ var overlay = document.getElementById('uc-sheet-overlay');
835
+ if (overlay) overlay.classList.remove('uc-open');
836
+ var sheet = document.getElementById(id);
837
+ if (sheet) sheet.classList.remove('uc-open');
838
+ };
839
+
840
+ window.closeAllSheets = function() {
841
+ var overlay = document.getElementById('uc-sheet-overlay');
842
+ if (overlay) overlay.classList.remove('uc-open');
843
+ document.querySelectorAll('.uc-sheet-right,.uc-sheet-bottom,.uc-sheet-left').forEach(function(s) {
844
+ s.classList.remove('uc-open');
845
+ });
846
+ };
847
+ }
848
+ };
849
+
850
+ // Auto-initialize all components
851
+ (function() {
852
+ function initAll() {
853
+ UCAccordion.init();
854
+ UCCollapsible.init();
855
+ UCCombobox.init();
856
+ UCResizable.init();
857
+ UCCarousel.init();
858
+ UCDropdown.init();
859
+ UCScrollView.init();
860
+ UCNumberInput.init();
861
+ UCPopover.init();
862
+ UCSelect.init();
863
+ UCToast.init();
864
+ UCDialog.init();
865
+ UCTreeView.init();
866
+ UCSheet.init();
867
+ }
868
+
869
+ if (document.readyState === 'loading') {
870
+ document.addEventListener('DOMContentLoaded', initAll);
871
+ } else {
872
+ initAll();
873
+ }
874
+
875
+ document.addEventListener('astro:after-swap', function() {
876
+ document.body.removeAttribute('data-dropdowns-init');
877
+ document.body.removeAttribute('data-select-init');
878
+ document.body.removeAttribute('data-popover-outside-init');
879
+ document.body.removeAttribute('data-combobox-outside-init');
880
+ initAll();
881
+ });
882
+ })();
package/uicraft.min.js ADDED
@@ -0,0 +1,7 @@
1
+ /*!
2
+ * uicraft.js v1.1.0
3
+ * https://getuicraft.com
4
+ * MIT License
5
+ */
6
+
7
+ var UCAccordion={init:function(){var uid=0;document.querySelectorAll('[data-accordion-item]').forEach(function(item){uid++;var trigger=item.querySelector('[data-accordion-trigger]');var content=item.querySelector('[data-accordion-content]');if(trigger&&content){var tId='acc-trigger-'+uid;var cId='acc-content-'+uid;trigger.id=tId;content.id=cId;trigger.setAttribute('aria-controls',cId);content.setAttribute('aria-labelledby',tId);}});function openContent(content){content.classList.remove('uc-hidden');content.classList.add('open');content.style.maxHeight=content.scrollHeight+16+'px';}function closeContent(content){content.style.maxHeight='0px';content.classList.remove('open');content.addEventListener('transitionend',function handler(){if(content.style.maxHeight==='0px'){content.classList.add('uc-hidden');}content.removeEventListener('transitionend',handler);});}document.querySelectorAll('[data-accordion-content]').forEach(function(content){if(!content.classList.contains('uc-hidden')&&!content.classList.contains('hidden')){content.classList.add('open');content.style.maxHeight=content.scrollHeight+16+'px';}});document.querySelectorAll('[data-accordion-trigger]').forEach(function(trigger){if(trigger.hasAttribute('data-accordion-init'))return;trigger.setAttribute('data-accordion-init','true');trigger.addEventListener('click',function(){var item=trigger.closest('[data-accordion-item]');var accordion=trigger.closest('[data-accordion]');var mode=accordion.getAttribute('data-accordion');var content=item.querySelector('[data-accordion-content]');var icon=trigger.querySelector('[data-accordion-icon]');var isOpen=!content.classList.contains('uc-hidden')&&!content.classList.contains('hidden')&&content.classList.contains('open');if(mode==='single'){accordion.querySelectorAll('[data-accordion-item]').forEach(function(otherItem){var otherContent=otherItem.querySelector('[data-accordion-content]');var otherTrigger=otherItem.querySelector('[data-accordion-trigger]');var otherIcon=otherItem.querySelector('[data-accordion-trigger][data-accordion-icon]');if(otherItem!==item&&!otherContent.classList.contains('uc-hidden')&&!otherContent.classList.contains('hidden')){closeContent(otherContent);if(otherIcon)otherIcon.classList.remove('uc-rotate-180');if(otherTrigger)otherTrigger.setAttribute('aria-expanded','false');}});}if(isOpen){closeContent(content);if(icon)icon.classList.remove('uc-rotate-180');trigger.setAttribute('aria-expanded','false');}else{content.classList.remove('uc-hidden');content.offsetHeight;openContent(content);if(icon)icon.classList.add('uc-rotate-180');trigger.setAttribute('aria-expanded','true');}});});}};var UCCollapsible={init:function(){document.querySelectorAll('[data-collapsible][data-collapsible-open]').forEach(function(collapsible){var content=collapsible.querySelector('[data-collapsible-content]');var icon=collapsible.querySelector('[data-collapsible-icon]');if(content){content.classList.remove('uc-hidden');if(collapsible.hasAttribute('data-collapsible-animated')){content.style.maxHeight=content.scrollHeight+'px';}}if(icon){icon.classList.add('uc-rotate-180');}});document.querySelectorAll('[data-collapsible-trigger]').forEach(function(trigger){if(trigger.hasAttribute('data-collapsible-bound'))return;trigger.setAttribute('data-collapsible-bound','true');trigger.addEventListener('click',function(){var collapsible=trigger.closest('[data-collapsible]');var content=collapsible.querySelector(':scope>[data-collapsible-content]');if(!content){content=collapsible.querySelector('[data-collapsible-content]');}var icon=collapsible.querySelector(':scope>*[data-collapsible-icon]')||collapsible.querySelector('[data-collapsible-icon]');var isAnimated=collapsible.hasAttribute('data-collapsible-animated');var labelCollapse=trigger.querySelector('[data-collapsible-label-collapse]');var labelExpand=trigger.querySelector('[data-collapsible-label-expand]');var isOpen;if(isAnimated){isOpen=parseInt(content.style.maxHeight)>0;}else{isOpen=!content.classList.contains('uc-hidden');}if(isOpen){if(isAnimated){content.style.maxHeight='0';}else{content.classList.add('uc-hidden');}if(icon)icon.classList.remove('uc-rotate-180');if(labelCollapse)labelCollapse.classList.add('uc-hidden');if(labelExpand)labelExpand.classList.remove('uc-hidden');collapsible.removeAttribute('data-collapsible-open');}else{if(isAnimated){content.style.maxHeight=content.scrollHeight+'px';}else{content.classList.remove('uc-hidden');}if(icon)icon.classList.add('uc-rotate-180');if(labelCollapse)labelCollapse.classList.remove('uc-hidden');if(labelExpand)labelExpand.classList.add('uc-hidden');collapsible.setAttribute('data-collapsible-open','');}});});}};var UCCombobox={init:function(){var checkSvg='<svg xmlns="http:var emptySpacer='<span class="uc-w-4 uc-h-4 uc-shrink-0 uc-combobox-icon"></span>';var xTagSvg='<svg xmlns="http:if(!document.body.hasAttribute('data-combobox-outside-init')){document.body.setAttribute('data-combobox-outside-init','true');document.addEventListener('click',function(e){if(!e.target.closest('.uc-combobox-wrapper')){document.querySelectorAll('[data-combobox-content]').forEach(function(el){el.classList.remove('uc-open');});}});}window.openCombobox=function(id){var el=document.getElementById(id);if(el)el.classList.add('uc-open');};window.toggleCombobox=function(id){var el=document.getElementById(id);if(el)el.classList.toggle('uc-open');};window.filterCombobox=function(input,id){var dropdown=document.getElementById(id);var query=input.value.toLowerCase();var items=dropdown.querySelectorAll('.uc-combobox-item');var groups=dropdown.querySelectorAll('[data-combobox-group]');var emptyEl=dropdown.querySelector('.uc-combobox-empty');var totalVisible=0;if(groups.length>0){groups.forEach(function(group){var groupItems=group.querySelectorAll('.uc-combobox-item');var groupVisible=0;groupItems.forEach(function(item){if(item.textContent.toLowerCase().includes(query)){item.classList.remove('uc-hidden');groupVisible++;totalVisible++;}else{item.classList.add('uc-hidden');}});group.style.display=groupVisible>0?'':'none';});}else{items.forEach(function(item){if(item.textContent.toLowerCase().includes(query)){item.classList.remove('uc-hidden');totalVisible++;}else{item.classList.add('uc-hidden');}});}if(emptyEl){emptyEl.classList.toggle('uc-hidden',totalVisible>0||!query);}};function setItemIcon(item,checked){var icon=item.querySelector('.uc-combobox-icon');if(icon)icon.outerHTML=checked?checkSvg:emptySpacer;}window.selectComboboxItem=function(item){var text=item.textContent.trim();var wrapper=item.closest('.uc-combobox-wrapper');var keepIcons=wrapper.hasAttribute('data-keep-icons');var input=wrapper.querySelector('input');var dropdown=item.closest('[data-combobox-content]');input.value=text;dropdown.querySelectorAll('.uc-combobox-item').forEach(function(i){i.classList.remove('uc-selected');if(!keepIcons)setItemIcon(i,false);});item.classList.add('uc-selected');if(!keepIcons)setItemIcon(item,true);dropdown.classList.remove('uc-open');};window.selectComboboxButton=function(item,dropdownId){var text=item.textContent.trim();var wrapper=item.closest('.uc-combobox-wrapper');var label=wrapper.querySelector('.uc-combobox-button-label');var dropdown=document.getElementById(dropdownId);label.textContent=text;label.classList.remove('uc-text-fg-disabled');dropdown.querySelectorAll('.uc-combobox-item').forEach(function(i){i.classList.remove('uc-selected');setItemIcon(i,false);});item.classList.add('uc-selected');setItemIcon(item,true);dropdown.classList.remove('uc-open');};window.toggleMultiComboboxItem=function(item){var isSelected=item.classList.toggle('uc-selected');setItemIcon(item,isSelected);var wrapper=item.closest('.uc-combobox-wrapper');var tagContainer=wrapper.querySelector('.uc-combobox-tags');var text=item.textContent.trim();if(isSelected){var tag=document.createElement('span');tag.className='uc-combobox-tag uc-inline-flex uc-items-center uc-gap-1 uc-rounded uc-bg-neutrals-subtle uc-px-2 uc-py-0.5 uc-text-xs uc-font-medium';tag.setAttribute('data-tag-value',text);tag.innerHTML=text+'<button type="button" onclick="event.stopPropagation();removeComboboxTag(this)" class="uc-ml-0.5 uc-rounded-sm uc-hover:bg-neutrals-muted uc-transition-colors">'+xTagSvg+'</button>';tagContainer.insertBefore(tag,tagContainer.querySelector('input'));}else{var existing=tagContainer.querySelector('[data-tag-value="'+text+'"]');if(existing)existing.remove();}UCCombobox._updateMultiPlaceholder(wrapper);};window.removeComboboxTag=function(btn){var tag=btn.closest('.uc-combobox-tag');if(!tag)return;var value=tag.getAttribute('data-tag-value');var wrapper=tag.closest('.uc-combobox-wrapper');tag.remove();var dropdown=wrapper.querySelector('[data-combobox-content]');if(dropdown){dropdown.querySelectorAll('.uc-combobox-item').forEach(function(item){if(item.textContent.trim()===value){item.classList.remove('uc-selected');setItemIcon(item,false);}});}UCCombobox._updateMultiPlaceholder(wrapper);};},_updateMultiPlaceholder:function(wrapper){var input=wrapper.querySelector('input');var tags=wrapper.querySelectorAll('.uc-combobox-tag');if(input){input.placeholder=tags.length>0?'':'Add framework...';}}};var UCResizable={init:function(){document.querySelectorAll('[data-resizable]').forEach(function(container){if(container.hasAttribute('data-resizable-init'))return;container.setAttribute('data-resizable-init','true');var direction=container.dataset.resizable;var isHorizontal=direction==='horizontal';var minPct=parseFloat(container.dataset.min||'10');var maxPct=parseFloat(container.dataset.max||'90');var handles=container.querySelectorAll(':scope>.uc-resize-handle');handles.forEach(function(handle){var isDown=false;var startPos=0;var prevPanel=null;var nextPanel=null;var containerSize=0;var prevStart=0;var nextStart=0;handle.addEventListener('mousedown',function(e){e.preventDefault();isDown=true;prevPanel=handle.previousElementSibling;nextPanel=handle.nextElementSibling;if(!prevPanel||!nextPanel)return;containerSize=isHorizontal?container.offsetWidth:container.offsetHeight;prevStart=isHorizontal?prevPanel.offsetWidth:prevPanel.offsetHeight;nextStart=isHorizontal?nextPanel.offsetWidth:nextPanel.offsetHeight;startPos=isHorizontal?e.clientX:e.clientY;document.body.style.cursor=isHorizontal?'col-resize':'row-resize';document.body.style.userSelect='none';handle.style.background='hsl(var(--accents-blue)/0.5)';});document.addEventListener('mousemove',function(e){if(!isDown||!prevPanel||!nextPanel)return;var delta=(isHorizontal?e.clientX:e.clientY)-startPos;var newPrev=prevStart+delta;var newNext=nextStart-delta;var minSize=containerSize*(minPct/100);var maxSize=containerSize*(maxPct/100);if(newPrev<minSize){newPrev=minSize;newNext=prevStart+nextStart-minSize;}if(newNext<minSize){newNext=minSize;newPrev=prevStart+nextStart-minSize;}if(newPrev>maxSize){newPrev=maxSize;newNext=prevStart+nextStart-maxSize;}if(newNext>maxSize){newNext=maxSize;newPrev=prevStart+nextStart-maxSize;}var prevPct=(newPrev/containerSize*100).toFixed(1);var nextPct=(newNext/containerSize*100).toFixed(1);if(isHorizontal){prevPanel.style.width=prevPct+'%';nextPanel.style.width=nextPct+'%';}else{prevPanel.style.height=prevPct+'%';nextPanel.style.height=nextPct+'%';}prevPanel.style.flex='none';nextPanel.style.flex='none';var prevLabel=prevPanel.querySelector('.uc-size-label');var nextLabel=nextPanel.querySelector('.uc-size-label');if(prevLabel)prevLabel.textContent=Math.round(parseFloat(prevPct))+'%';if(nextLabel)nextLabel.textContent=Math.round(parseFloat(nextPct))+'%';});document.addEventListener('mouseup',function(){if(!isDown)return;isDown=false;document.body.style.cursor='';document.body.style.userSelect='';handle.style.background='';});});});}};var UCCarousel={init:function(){document.querySelectorAll('[data-carousel]').forEach(function(el){if(el.hasAttribute('data-carousel-init'))return;el.setAttribute('data-carousel-init','true');var carousel=el;var track=carousel.querySelector('[data-carousel-track]');var prevBtn=carousel.querySelector('[data-carousel-prev]');var nextBtn=carousel.querySelector('[data-carousel-next]');var dotsContainer=carousel.querySelector('[data-carousel-dots]');var total=parseInt(carousel.dataset.total||'0');var visible=parseInt(carousel.dataset.visible||'1');var maxIndex=total-visible;var current=0;function update(){if(visible===1){track.style.transform='translateX(-'+(current*100)+'%)';}else{var slide=track.children[0];var gap=parseFloat(getComputedStyle(track).gap)||0;var offset=current*(slide.offsetWidth+gap);track.style.transform='translateX(-'+offset+'px)';}if(dotsContainer){dotsContainer.querySelectorAll('[data-dot]').forEach(function(dot){var idx=parseInt(dot.dataset.dot||'0');dot.className='uc-w-2 uc-h-2 uc-rounded-full uc-transition-colors '+(idx===current?'uc-bg-accents-blue':'uc-bg-neutrals-muted');});}if(prevBtn)prevBtn.style.opacity=current===0?'0.4':'1';if(nextBtn)nextBtn.style.opacity=current>=maxIndex?'0.4':'1';}if(prevBtn){prevBtn.addEventListener('click',function(){if(current>0){current--;update();}});}if(nextBtn){nextBtn.addEventListener('click',function(){if(current<maxIndex){current++;update();}});}if(dotsContainer){dotsContainer.querySelectorAll('[data-dot]').forEach(function(dot){dot.addEventListener('click',function(){current=Math.min(parseInt(dot.dataset.dot||'0'),maxIndex);update();});});}update();});}};var UCDropdown={init:function(){if(document.body.hasAttribute('data-dropdowns-init'))return;document.body.setAttribute('data-dropdowns-init','true');document.addEventListener('click',function(e){if(!e.target.closest('[data-dropdown-trigger]')&&!e.target.closest('.uc-dropdown-menu')){document.querySelectorAll('.uc-dropdown-menu').forEach(function(el){el.classList.remove('uc-open');});}});document.querySelectorAll('[data-dropdown-trigger]').forEach(function(trigger){if(trigger.hasAttribute('data-dropdown-bound'))return;trigger.setAttribute('data-dropdown-bound','true');trigger.addEventListener('click',function(e){e.stopPropagation();var targetId=trigger.getAttribute('data-dropdown-trigger');var content=document.getElementById(targetId);if(!content)return;document.querySelectorAll('.uc-dropdown-menu').forEach(function(el){if(el!==content)el.classList.remove('uc-open');});content.classList.toggle('uc-open');});});}};function toggleCheckbox(el){var indicator=el.querySelector('.checkbox-indicator');var isChecked=indicator.classList.contains('uc-bg-accents-blue');if(isChecked){indicator.classList.remove('uc-bg-accents-blue','uc-text-constant-white','uc-border-transparent');indicator.innerHTML='';}else{indicator.classList.add('uc-bg-accents-blue','uc-text-constant-white','uc-border-transparent');indicator.innerHTML='<svg xmlns="http:}}function selectRadio(el){var parent=el.closest('.uc-dropdown-menu');parent.querySelectorAll('.radio-indicator').forEach(function(r){r.classList.remove('uc-border-accents-blue');r.classList.add('uc-border-input');r.innerHTML='';});var indicator=el.querySelector('.radio-indicator');indicator.classList.remove('uc-border-input');indicator.classList.add('uc-border-accents-blue');indicator.innerHTML='<div class="uc-w-2 uc-h-2 uc-rounded-full uc-bg-accents-blue"></div>';}var UCScrollView={init:function(){document.querySelectorAll('.uc-drag-scroll').forEach(function(el){if(el.hasAttribute('data-drag-init'))return;el.setAttribute('data-drag-init','true');var isDown=false;var startX=0;var scrollLeft=0;el.addEventListener('mousedown',function(e){isDown=true;el.style.cursor='grabbing';el.style.userSelect='none';startX=e.pageX-el.offsetLeft;scrollLeft=el.scrollLeft;});el.addEventListener('mouseleave',function(){isDown=false;el.style.cursor='grab';el.style.userSelect='';});el.addEventListener('mouseup',function(){isDown=false;el.style.cursor='grab';el.style.userSelect='';});el.addEventListener('mousemove',function(e){if(!isDown)return;e.preventDefault();var x=e.pageX-el.offsetLeft;var walk=(x-startX)*1.5;el.scrollLeft=scrollLeft-walk;});});document.querySelectorAll('.uc-scroll-indicator').forEach(function(indicator){if(indicator.hasAttribute('data-indicator-init'))return;indicator.setAttribute('data-indicator-init','true');var scroll=indicator.querySelector('.uc-scroll,.uc-scroll-hidden,.uc-scroll-autohide');if(!scroll)return;scroll.addEventListener('scroll',function(){var st=scroll.scrollTop;var sh=scroll.scrollHeight;var ch=scroll.clientHeight;indicator.classList.toggle('uc-show-top',st>8);indicator.classList.toggle('uc-show-bottom',st<sh-ch-8);});});document.querySelectorAll('.uc-scroll-indicator-h').forEach(function(indicator){if(indicator.hasAttribute('data-indicator-h-init'))return;indicator.setAttribute('data-indicator-h-init','true');var scroll=indicator.querySelector('.uc-scroll,.uc-scroll-hidden,.uc-scroll-autohide,[class*="uc-overflow-x"]');if(!scroll)return;scroll.addEventListener('scroll',function(){var sl=scroll.scrollLeft;var sw=scroll.scrollWidth;var cw=scroll.clientWidth;indicator.classList.toggle('uc-show-left',sl>8);indicator.classList.toggle('uc-show-right',sl<sw-cw-8);});});}};var UCNumberInput={init:function(){document.querySelectorAll('[data-number-input]').forEach(function(wrapper){if(wrapper.hasAttribute('data-ni-bound'))return;wrapper.setAttribute('data-ni-bound','true');var input=wrapper.querySelector('[data-number-value]');var decBtn=wrapper.querySelector('[data-action="decrement"]');var incBtn=wrapper.querySelector('[data-action="increment"]');if(!input)return;function updateButtons(){var val=parseInt(input.value)||0;var min=input.hasAttribute('min')?parseInt(input.min):-Infinity;var max=input.hasAttribute('max')?parseInt(input.max):Infinity;if(decBtn)decBtn.disabled=val<=min;if(incBtn)incBtn.disabled=val>=max;}function step(delta){var val=parseInt(input.value)||0;var min=input.hasAttribute('min')?parseInt(input.min):-Infinity;var max=input.hasAttribute('max')?parseInt(input.max):Infinity;var next=Math.min(Math.max(val+delta,min),max);input.value=next;updateButtons();}if(decBtn)decBtn.addEventListener('click',function(){step(-1);});if(incBtn)incBtn.addEventListener('click',function(){step(1);});input.addEventListener('change',function(){var min=input.hasAttribute('min')?parseInt(input.min):-Infinity;var max=input.hasAttribute('max')?parseInt(input.max):Infinity;var val=parseInt(input.value)||min;input.value=Math.min(Math.max(val,min),max);updateButtons();});updateButtons();});}};var UCPopover={init:function(){document.querySelectorAll('[data-popover-trigger]').forEach(function(btn){btn.onclick=function(e){e.stopPropagation();var id=btn.getAttribute('data-popover-trigger');var el=id?document.getElementById(id):null;if(!el)return;var isOpen=el.classList.contains('uc-open');document.querySelectorAll('.uc-popover-content').forEach(function(p){p.classList.remove('uc-open');});if(!isOpen)el.classList.add('uc-open');};});if(!document.body.hasAttribute('data-popover-outside-init')){document.body.setAttribute('data-popover-outside-init','true');document.addEventListener('click',function(e){var target=e.target;if(!target.closest('.uc-popover-content')&&!target.closest('[data-popover-trigger]')){document.querySelectorAll('.uc-popover-content').forEach(function(p){p.classList.remove('uc-open');});}});}}};var UCSelect={init:function(){if(document.body.hasAttribute('data-select-init'))return;document.body.setAttribute('data-select-init','true');document.addEventListener('click',function(e){if(!e.target.closest('.uc-select-wrapper')){document.querySelectorAll('.uc-select-dropdown').forEach(function(d){d.classList.remove('open');});}});}};function toggleSelect(id){var dropdown=document.getElementById(id);document.querySelectorAll('.uc-select-dropdown').forEach(function(d){if(d.id!==id)d.classList.remove('open');});dropdown.classList.toggle('open');}function selectItem(id,triggerId,value){document.getElementById(triggerId).querySelector('span').textContent=value;document.getElementById(triggerId).querySelector('span').classList.remove('placeholder');var dropdown=document.getElementById(id);dropdown.querySelectorAll('.uc-select-item').forEach(function(i){i.classList.remove('selected');});dropdown.querySelectorAll('.uc-select-item').forEach(function(i){if(i.textContent.trim()===value)i.classList.add('selected');});dropdown.classList.remove('open');}var UCToast={_count:0,show:function(type){var container=document.getElementById('toast-container');if(!container)return;var id='toast-'+(++UCToast._count);var configs={default:{title:'Scheduled:Catch up',desc:'Friday,February 14,2026 at 5:57 PM',icon:'',btn:'Undo'},success:{title:'Success',desc:'Your changes have been saved.',icon:'<svg xmlns="http:error:{title:'Error',desc:'Something went wrong. Please try again.',icon:'<svg xmlns="http:action:{title:'Event created',desc:'Sunday,December 03,2023',icon:'',btn:'Undo'}};var c=configs[type]||configs.default;var toast=document.createElement('div');toast.id=id;toast.className='uc-flex uc-items-start uc-gap-3 uc-w-80 uc-p-4 uc-rounded-lg uc-border uc-border-border-default uc-bg-neutrals-surface uc-shadow-lg uc-mb-2';toast.innerHTML=(c.icon?'<div class="uc-flex-shrink-0 uc-mt-0.5">'+c.icon+'</div>':'')+'<div class="uc-flex-1 uc-min-w-0">'+'<p class="uc-text-sm uc-font-semibold">'+c.title+'</p>'+'<p class="uc-text-xs uc-text-fg-disabled uc-mt-0.5">'+c.desc+'</p>'+'</div>'+(c.btn?'<button onclick="this.parentElement.remove()" class="uc-flex-shrink-0 uc-inline-flex uc-items-center uc-justify-center uc-rounded-lg uc-text-xs uc-font-medium uc-h-7 uc-px-2 uc-border uc-border-border-strong uc-bg-neutrals-surface uc-hover:bg-neutrals-subtle uc-transition-colors">'+c.btn+'</button>':'')+'<button onclick="this.parentElement.remove()" class="uc-flex-shrink-0 uc-p-0.5 uc-text-fg-disabled uc-hover:text-fg-primary uc-transition-colors">'+'<svg xmlns="http:'</button>';container.appendChild(toast);setTimeout(function(){var el=document.getElementById(id);if(el)el.remove();},4000);},init:function(){window.showToast=function(type){UCToast.show(type);};}};var UCDialog={init:function(){window.openDialog=function(id){var el=document.getElementById(id);if(!el)return;el.classList.add('uc-open');el.removeAttribute('aria-hidden');var focusable=el.querySelector('button,[href],input,select,textarea,[tabindex]:not([tabindex="-1"])');if(focusable)focusable.focus();el._keyHandler=function(e){if(e.key==='Escape'){window.closeDialog(id);return;}if(e.key!=='Tab')return;var all=el.querySelectorAll('button,[href],input,select,textarea,[tabindex]:not([tabindex="-1"])');var first=all[0];var last=all[all.length-1];if(e.shiftKey&&document.activeElement===first){e.preventDefault();last.focus();}else if(!e.shiftKey&&document.activeElement===last){e.preventDefault();first.focus();}};document.addEventListener('keydown',el._keyHandler);};window.closeDialog=function(id){var el=document.getElementById(id);if(!el)return;el.classList.remove('uc-open');el.setAttribute('aria-hidden','true');if(el._keyHandler)document.removeEventListener('keydown',el._keyHandler);};}};var UCTreeView={init:function(){document.querySelectorAll('[data-tree]').forEach(function(tree){if(tree.hasAttribute('data-tree-bound'))return;tree.setAttribute('data-tree-bound','true');tree.querySelectorAll('[data-tree-branch]').forEach(function(branch){var toggle=branch.querySelector(':scope>.uc-tree-toggle');if(!toggle)return;toggle.addEventListener('click',function(){branch.classList.toggle('open');});});});}};var UCSheet={init:function(){window.openSheet=function(id){var overlay=document.getElementById('uc-sheet-overlay');if(overlay)overlay.classList.add('uc-open');var sheet=document.getElementById(id);if(sheet)sheet.classList.add('uc-open');};window.closeSheet=function(id){var overlay=document.getElementById('uc-sheet-overlay');if(overlay)overlay.classList.remove('uc-open');var sheet=document.getElementById(id);if(sheet)sheet.classList.remove('uc-open');};window.closeAllSheets=function(){var overlay=document.getElementById('uc-sheet-overlay');if(overlay)overlay.classList.remove('uc-open');document.querySelectorAll('.uc-sheet-right,.uc-sheet-bottom,.uc-sheet-left').forEach(function(s){s.classList.remove('uc-open');});};}};(function(){function initAll(){UCAccordion.init();UCCollapsible.init();UCCombobox.init();UCResizable.init();UCCarousel.init();UCDropdown.init();UCScrollView.init();UCNumberInput.init();UCPopover.init();UCSelect.init();UCToast.init();UCDialog.init();UCTreeView.init();UCSheet.init();}if(document.readyState==='loading'){document.addEventListener('DOMContentLoaded',initAll);}else{initAll();}document.addEventListener('astro:after-swap',function(){document.body.removeAttribute('data-dropdowns-init');document.body.removeAttribute('data-select-init');document.body.removeAttribute('data-popover-outside-init');document.body.removeAttribute('data-combobox-outside-init');initAll();});})();