basecoat-css 0.3.2 → 0.3.4

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/dist/basecoat.css CHANGED
@@ -146,10 +146,6 @@
146
146
  border-radius: var(--scrollbar-radius);
147
147
  }
148
148
  }
149
- /* Alpine.js */
150
- [x-cloak] {
151
- display: none !important;
152
- }
153
149
  }
154
150
 
155
151
  /* Alert */
@@ -158,7 +154,8 @@
158
154
  .alert-destructive {
159
155
  @apply relative w-full rounded-lg border px-4 py-3 text-sm grid has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] grid-cols-[0_1fr] has-[>svg]:gap-x-3 gap-y-0.5 items-start [&>svg]:size-4 [&>svg]:translate-y-0.5 [&>svg]:text-current;
160
156
 
161
- h2 {
157
+ h2,
158
+ h3 {
162
159
  @apply col-start-2 line-clamp-1 min-h-4 font-medium tracking-tight;
163
160
  }
164
161
  section {
@@ -181,6 +178,30 @@
181
178
  }
182
179
  }
183
180
 
181
+ /* Badge */
182
+ @layer components {
183
+ .badge,
184
+ .badge-primary,
185
+ .badge-secondary,
186
+ .badge-destructive,
187
+ .badge-outline {
188
+ @apply inline-flex items-center justify-center rounded-full border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden;
189
+ }
190
+ .badge,
191
+ .badge-primary {
192
+ @apply border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90;
193
+ }
194
+ .badge-secondary {
195
+ @apply border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90;
196
+ }
197
+ .badge-destructive {
198
+ @apply border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60;
199
+ }
200
+ .badge-outline {
201
+ @apply text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground;
202
+ }
203
+ }
204
+
184
205
  /* Button */
185
206
  @layer components {
186
207
  .btn,
@@ -359,27 +380,44 @@
359
380
  }
360
381
  }
361
382
 
362
- /* Badge */
363
- @layer components {
364
- .badge,
365
- .badge-primary,
366
- .badge-secondary,
367
- .badge-destructive,
368
- .badge-outline {
369
- @apply inline-flex items-center justify-center rounded-md border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden;
370
- }
371
- .badge,
372
- .badge-primary {
373
- @apply border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90;
374
- }
375
- .badge-secondary {
376
- @apply border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90;
383
+ /* Button Group */
384
+ .button-group {
385
+ @apply inline-flex w-fit items-stretch isolate;
386
+
387
+ > *:focus-visible,
388
+ > :is(.dropdown-menu, .popover, .select) > button:focus-visible {
389
+ @apply relative z-10;
377
390
  }
378
- .badge-destructive {
379
- @apply border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60;
391
+
392
+ > hr[role='separator'] {
393
+ @apply w-0 h-auto self-stretch border border-input shrink-0 m-0;
380
394
  }
381
- .badge-outline {
382
- @apply text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground;
395
+
396
+ &:not([data-orientation='vertical']) {
397
+ > *:not(:first-child),
398
+ > :is(.dropdown-menu, .popover, .select):not(:first-child) > button {
399
+ @apply rounded-l-none border-l-0;
400
+ }
401
+ > *:not(:last-child),
402
+ > :is(.dropdown-menu, .popover, .select):not(:last-child) > button {
403
+ @apply rounded-r-none;
404
+ }
405
+ }
406
+ &[data-orientation='vertical'] {
407
+ @apply flex-col;
408
+
409
+ > hr[role='separator'] {
410
+ @apply w-auto h-px;
411
+ }
412
+
413
+ > *:not(:first-child),
414
+ > :is(.dropdown-menu, .popover, .select):not(:first-child) > button {
415
+ @apply rounded-t-none border-t-0;
416
+ }
417
+ > *:not(:last-child),
418
+ > :is(.dropdown-menu, .popover, .select):not(:last-child) > button {
419
+ @apply rounded-b-none;
420
+ }
383
421
  }
384
422
  }
385
423
 
@@ -410,7 +448,7 @@
410
448
 
411
449
  /* Checkbox */
412
450
  @layer components {
413
- .form input[type='checkbox']:not([role='switch']),
451
+ :is(.form, .field) input[type='checkbox']:not([role='switch']),
414
452
  .input[type='checkbox']:not([role='switch']) {
415
453
  @apply appearance-none border-input dark:bg-input/30 checked:bg-primary dark:checked:bg-primary checked:border-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive size-4 shrink-0 rounded-[4px] border shadow-xs transition-shadow outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50;
416
454
 
@@ -442,6 +480,115 @@
442
480
  }
443
481
  }
444
482
 
483
+ /* Command */
484
+ @layer components {
485
+ .command-dialog {
486
+ @apply inset-y-0 opacity-0 transition-all transition-discrete;
487
+
488
+ &:is([open],:popover-open) {
489
+ @apply opacity-100;
490
+
491
+ &::backdrop {
492
+ @apply opacity-100;
493
+ }
494
+ > * {
495
+ @apply scale-100;
496
+ }
497
+
498
+ @starting-style {
499
+ @apply opacity-0;
500
+
501
+ &::backdrop {
502
+ @apply opacity-0;
503
+ }
504
+ > * {
505
+ @apply scale-95;
506
+ }
507
+ }
508
+ }
509
+ &::backdrop {
510
+ @apply bg-black/50 opacity-0 transition-all transition-discrete;
511
+ }
512
+ > * {
513
+ @apply bg-background fixed top-[50%] left-[50%] z-50 flex flex-col w-full max-w-[calc(100%_-_2rem)] -translate-x-1/2 -translate-y-1/2 overflow-hidden rounded-lg border shadow-lg sm:max-w-lg max-h-[min(640px,calc(100%_-_2rem))];
514
+ @apply transition-all scale-95;
515
+
516
+ > button,
517
+ > form[method='dialog'] {
518
+ @apply absolute top-4 right-4;
519
+ }
520
+ > button,
521
+ > form[method='dialog'] > button {
522
+ @apply ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4;
523
+ }
524
+ }
525
+
526
+ .command {
527
+ > header input {
528
+ @apply h-12;
529
+ }
530
+ [role='menu'] {
531
+ @apply px-2;
532
+
533
+ [role='menuitem'] {
534
+ @apply py-3 px-2 [&_svg]:size-5;
535
+ }
536
+ [role='heading'] {
537
+ @apply px-2 py-1.5 font-medium text-muted-foreground;
538
+ }
539
+ }
540
+ }
541
+ }
542
+
543
+ .command {
544
+ > header {
545
+ @apply flex items-center border-b px-3 gap-2;
546
+
547
+ svg {
548
+ @apply size-4 shrink-0 opacity-50;
549
+ }
550
+ input {
551
+ @apply placeholder:text-muted-foreground flex h-10 w-full rounded-md bg-transparent py-3 text-sm outline-hidden disabled:cursor-not-allowed disabled:opacity-50;
552
+ }
553
+ }
554
+ [role='menu'] {
555
+ @apply max-h-[300px] overflow-y-auto overflow-x-hidden p-1;
556
+
557
+ [role='menuitem'] {
558
+ @apply aria-hidden:hidden relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none aria-disabled:opacity-50 aria-disabled:pointer-events-none disabled:opacity-50 disabled:pointer-events-none w-full truncate [&_svg:not([class*='text-'])]:text-muted-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4;
559
+
560
+ &.active {
561
+ @apply bg-accent text-accent-foreground;
562
+ }
563
+ }
564
+ [role='heading'] {
565
+ @apply text-muted-foreground flex px-2 py-1.5 text-xs font-medium;
566
+ }
567
+ [role='group']:not(:has([role='menuitem']:not([aria-hidden='true']))) {
568
+ @apply hidden;
569
+ }
570
+ [role='separator'] {
571
+ @apply border-border -mx-1 my-1;
572
+ }
573
+ &:not(:has([data-value]:not([aria-hidden='true'])))::before {
574
+ @apply flex items-center justify-center py-6 px-3 text-sm truncate -m-1;
575
+ }
576
+ &[data-empty]:not(:has([data-value]:not([aria-hidden='true'])))::before {
577
+ @apply content-[attr(data-empty)];
578
+ }
579
+ &:not([data-empty]):not(:has([data-value]:not([aria-hidden='true'])))::before {
580
+ @apply content-['No_results_found'];
581
+ }
582
+ }
583
+ &:not([data-command-initialized]) [role='menuitem'] {
584
+ @apply hover:bg-accent hover:text-accent-foreground;
585
+ }
586
+ &:has(> header input:not(:placeholder-shown)) [role='separator'] {
587
+ @apply hidden;
588
+ }
589
+ }
590
+ }
591
+
445
592
  /* Dialog */
446
593
  @layer components {
447
594
  .dialog {
@@ -453,7 +600,7 @@
453
600
  &::backdrop {
454
601
  @apply opacity-100;
455
602
  }
456
- > article {
603
+ > * {
457
604
  @apply scale-100;
458
605
  }
459
606
 
@@ -463,7 +610,7 @@
463
610
  &::backdrop {
464
611
  @apply opacity-0;
465
612
  }
466
- > article {
613
+ > * {
467
614
  @apply scale-95;
468
615
  }
469
616
  }
@@ -471,7 +618,7 @@
471
618
  &::backdrop {
472
619
  @apply bg-black/50 opacity-0 transition-all transition-discrete;
473
620
  }
474
- > article {
621
+ > * {
475
622
  @apply bg-background fixed top-[50%] left-[50%] z-50 flex flex-col w-full max-w-[calc(100%_-_2rem)] -translate-x-1/2 -translate-y-1/2 gap-4 rounded-lg border p-6 shadow-lg sm:max-w-lg max-h-[calc(100%_-_2rem)];
476
623
  @apply transition-all scale-95;
477
624
 
@@ -542,21 +689,65 @@
542
689
  }
543
690
  }
544
691
 
692
+ /* Field */
693
+ @layer components {
694
+ .fieldset {
695
+ @apply flex flex-col gap-6;
696
+
697
+ > legend {
698
+ @apply text-base font-medium mb-3;
699
+ }
700
+ }
701
+ .field {
702
+ @apply flex flex-col w-full gap-3 data-[invalid=true]:text-destructive [&>*]:w-full [&>.sr-only]:w-auto;
703
+
704
+ h2,
705
+ h3 {
706
+ @apply flex w-fit items-center gap-2 text-sm leading-snug font-medium;
707
+ }
708
+ [role="alert"] {
709
+ @apply text-sm text-destructive font-normal;
710
+
711
+ ul {
712
+ @apply ml-4 flex list-disc flex-col gap-1;
713
+ }
714
+ }
715
+ section {
716
+ @apply flex flex-1 flex-col gap-1.5 leading-snug;
717
+ }
718
+
719
+ &[data-orientation='horizontal'] {
720
+ @apply flex-row items-center [&>label]:flex-auto has-[>section]:items-start has-[>section]:[&>[type=checkbox],[type=radio]]:mt-px [&_p]:text-balance;
721
+ }
722
+ }
723
+ .fieldset legend + p,
724
+ .field > p,
725
+ .field section > p {
726
+ @apply text-muted-foreground text-sm leading-normal font-normal [&>a:hover]:text-primary [&>a]:underline [&>a]:underline-offset-4;
727
+ }
728
+ .fieldset legend + p {
729
+ @apply -mt-1.5;
730
+ }
731
+ .field > p {
732
+ @apply last:mt-0 nth-last-2:-mt-1;
733
+ }
734
+ }
735
+
545
736
  /* Input */
546
737
  @layer components {
547
- .form input[type='text'],
548
- .form input[type='email'],
549
- .form input[type='password'],
550
- .form input[type='number'],
551
- .form input[type='file'],
552
- .form input[type='tel'],
553
- .form input[type='url'],
554
- .form input[type='search'],
555
- .form input[type='date'],
556
- .form input[type='datetime-local'],
557
- .form input[type='month'],
558
- .form input[type='week'],
559
- .form input[type='time'],
738
+ :is(.form, .field) input[type='text'],
739
+ :is(.form, .field) input[type='email'],
740
+ :is(.form, .field) input[type='password'],
741
+ :is(.form, .field) input[type='number'],
742
+ :is(.form, .field) input[type='file'],
743
+ :is(.form, .field) input[type='tel'],
744
+ :is(.form, .field) input[type='url'],
745
+ :is(.form, .field) input[type='search'],
746
+ :is(.form, .field) input[type='date'],
747
+ :is(.form, .field) input[type='datetime-local'],
748
+ :is(.form, .field) input[type='month'],
749
+ :is(.form, .field) input[type='week'],
750
+ :is(.form, .field) input[type='time'],
560
751
  .input[type='text'],
561
752
  .input[type='email'],
562
753
  .input[type='password'],
@@ -576,9 +767,16 @@
576
767
  }
577
768
  }
578
769
 
770
+ /* Kbd */
771
+ @layer components {
772
+ .kbd {
773
+ @apply bg-muted text-muted-foreground pointer-events-none inline-flex h-5 w-fit min-w-5 items-center justify-center gap-1 rounded-sm px-1 font-sans text-xs font-medium select-none [&_svg:not([class*='size-'])]:size-3;
774
+ }
775
+ }
776
+
579
777
  /* Label */
580
778
  @layer components {
581
- .form label,
779
+ :is(.form, .field) label,
582
780
  .label {
583
781
  @apply flex items-center gap-2 text-sm leading-none font-medium select-none peer-disabled:pointer-events-none peer-disabled:opacity-50;
584
782
 
@@ -663,7 +861,7 @@
663
861
 
664
862
  /* Radio */
665
863
  @layer components {
666
- .form input[type='radio'],
864
+ :is(.form, .field) input[type='radio'],
667
865
  .input[type='radio'] {
668
866
  @apply appearance-none border-input text-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 aspect-square size-4 shrink-0 rounded-full border shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 relative;
669
867
 
@@ -675,7 +873,7 @@
675
873
 
676
874
  /* Range */
677
875
  @layer components {
678
- .form input[type='range'],
876
+ :is(.form, .field) input[type='range'],
679
877
  .input[type='range'] {
680
878
  @apply appearance-none flex items-center p-0 outline-none;
681
879
  --slider-value: 20%;
@@ -724,7 +922,7 @@
724
922
 
725
923
  /* Select */
726
924
  @layer components {
727
- .form select,
925
+ :is(.form, .field) select,
728
926
  select.select {
729
927
  @apply appearance-none border-input focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 dark:hover:bg-input/50 flex w-fit items-center justify-between gap-2 rounded-md border bg-transparent pl-3 pr-9 py-2 text-sm whitespace-nowrap shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 h-9;
730
928
  @apply bg-[image:var(--chevron-down-icon-50)] bg-no-repeat bg-position-[center_right_0.75rem] bg-size-[1rem];
@@ -780,6 +978,9 @@
780
978
  @apply content-['No_results_found'];
781
979
  }
782
980
  }
981
+ [data-popover]:has(> header input:not(:placeholder-shown)) [role='separator'] {
982
+ @apply hidden;
983
+ }
783
984
  &:not([data-select-initialized]) [data-popover] [role='option'] {
784
985
  @apply hover:bg-accent hover:text-accent-foreground;
785
986
  }
@@ -908,7 +1109,7 @@
908
1109
 
909
1110
  /* Switch */
910
1111
  @layer components {
911
- .form input[type='checkbox'][role='switch'],
1112
+ :is(.form, .field) input[type='checkbox'][role='switch'],
912
1113
  .input[type='checkbox'][role='switch'] {
913
1114
  @apply appearance-none focus-visible:border-ring focus-visible:ring-ring/50 inline-flex h-[1.15rem] w-8 shrink-0 items-center rounded-full border border-transparent shadow-xs transition-all outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50;
914
1115
  @apply bg-input dark:bg-input/80 checked:bg-primary dark:checked:bg-primary;
@@ -970,7 +1171,7 @@
970
1171
 
971
1172
  /* Textarea */
972
1173
  @layer components {
973
- .form textarea,
1174
+ :is(.form, .field) textarea,
974
1175
  .textarea {
975
1176
  @apply border-input placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 flex field-sizing-content min-h-16 w-full rounded-md border bg-transparent px-3 py-2 text-base shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 md:text-sm;
976
1177
  }
package/dist/js/all.js CHANGED
@@ -97,6 +97,155 @@
97
97
  startObserver();
98
98
  });
99
99
  })();
100
+ (() => {
101
+ const initCommand = (container) => {
102
+ const input = container.querySelector('header input');
103
+ const menu = container.querySelector('[role="menu"]');
104
+
105
+ if (!input || !menu) {
106
+ const missing = [];
107
+ if (!input) missing.push('input');
108
+ if (!menu) missing.push('menu');
109
+ console.error(`Command component initialization failed. Missing element(s): ${missing.join(', ')}`, container);
110
+ return;
111
+ }
112
+
113
+ const allMenuItems = Array.from(menu.querySelectorAll('[role="menuitem"]'));
114
+ const menuItems = allMenuItems.filter(item =>
115
+ !item.hasAttribute('disabled') &&
116
+ item.getAttribute('aria-disabled') !== 'true'
117
+ );
118
+ let visibleMenuItems = [...menuItems];
119
+ let activeIndex = -1;
120
+
121
+ const setActiveItem = (index) => {
122
+ if (activeIndex > -1 && menuItems[activeIndex]) {
123
+ menuItems[activeIndex].classList.remove('active');
124
+ }
125
+
126
+ activeIndex = index;
127
+
128
+ if (activeIndex > -1) {
129
+ const activeItem = menuItems[activeIndex];
130
+ activeItem.classList.add('active');
131
+ if (activeItem.id) {
132
+ input.setAttribute('aria-activedescendant', activeItem.id);
133
+ } else {
134
+ input.removeAttribute('aria-activedescendant');
135
+ }
136
+ } else {
137
+ input.removeAttribute('aria-activedescendant');
138
+ }
139
+ };
140
+
141
+ const filterMenuItems = () => {
142
+ const searchTerm = input.value.trim().toLowerCase();
143
+
144
+ setActiveItem(-1);
145
+
146
+ visibleMenuItems = [];
147
+ allMenuItems.forEach(item => {
148
+ const itemText = (item.dataset.label || item.textContent).trim().toLowerCase();
149
+ const keywords = (item.dataset.keywords || '').toLowerCase();
150
+ const matches = itemText.includes(searchTerm) || keywords.includes(searchTerm);
151
+ item.setAttribute('aria-hidden', String(!matches));
152
+ if (matches && menuItems.includes(item)) {
153
+ visibleMenuItems.push(item);
154
+ }
155
+ });
156
+
157
+ if (visibleMenuItems.length > 0) {
158
+ setActiveItem(menuItems.indexOf(visibleMenuItems[0]));
159
+ visibleMenuItems[0].scrollIntoView({ block: 'nearest' });
160
+ }
161
+ };
162
+
163
+ input.addEventListener('input', filterMenuItems);
164
+
165
+ const handleKeyNavigation = (event) => {
166
+ if (!['ArrowDown', 'ArrowUp', 'Enter', 'Home', 'End'].includes(event.key)) {
167
+ return;
168
+ }
169
+
170
+ if (event.key === 'Enter') {
171
+ event.preventDefault();
172
+ if (activeIndex > -1) {
173
+ menuItems[activeIndex]?.click();
174
+ }
175
+ return;
176
+ }
177
+
178
+ if (visibleMenuItems.length === 0) return;
179
+
180
+ event.preventDefault();
181
+
182
+ const currentVisibleIndex = activeIndex > -1 ? visibleMenuItems.indexOf(menuItems[activeIndex]) : -1;
183
+ let nextVisibleIndex = currentVisibleIndex;
184
+
185
+ switch (event.key) {
186
+ case 'ArrowDown':
187
+ if (currentVisibleIndex < visibleMenuItems.length - 1) {
188
+ nextVisibleIndex = currentVisibleIndex + 1;
189
+ }
190
+ break;
191
+ case 'ArrowUp':
192
+ if (currentVisibleIndex > 0) {
193
+ nextVisibleIndex = currentVisibleIndex - 1;
194
+ } else if (currentVisibleIndex === -1) {
195
+ nextVisibleIndex = 0;
196
+ }
197
+ break;
198
+ case 'Home':
199
+ nextVisibleIndex = 0;
200
+ break;
201
+ case 'End':
202
+ nextVisibleIndex = visibleMenuItems.length - 1;
203
+ break;
204
+ }
205
+
206
+ if (nextVisibleIndex !== currentVisibleIndex) {
207
+ const newActiveItem = visibleMenuItems[nextVisibleIndex];
208
+ setActiveItem(menuItems.indexOf(newActiveItem));
209
+ newActiveItem.scrollIntoView({ block: 'nearest', behavior: 'smooth' });
210
+ }
211
+ };
212
+
213
+ menu.addEventListener('mousemove', (event) => {
214
+ const menuItem = event.target.closest('[role="menuitem"]');
215
+ if (menuItem && visibleMenuItems.includes(menuItem)) {
216
+ const index = menuItems.indexOf(menuItem);
217
+ if (index !== activeIndex) {
218
+ setActiveItem(index);
219
+ }
220
+ }
221
+ });
222
+
223
+ menu.addEventListener('click', (event) => {
224
+ const clickedItem = event.target.closest('[role="menuitem"]');
225
+ if (clickedItem && visibleMenuItems.includes(clickedItem)) {
226
+ const dialog = container.closest('dialog.command-dialog');
227
+ if (dialog && !clickedItem.hasAttribute('data-keep-command-open')) {
228
+ dialog.close();
229
+ }
230
+ }
231
+ });
232
+
233
+ input.addEventListener('keydown', handleKeyNavigation);
234
+
235
+ if (visibleMenuItems.length > 0) {
236
+ setActiveItem(menuItems.indexOf(visibleMenuItems[0]));
237
+ visibleMenuItems[0].scrollIntoView({ block: 'nearest' });
238
+ }
239
+
240
+ container.dataset.commandInitialized = true;
241
+ container.dispatchEvent(new CustomEvent('basecoat:initialized'));
242
+ };
243
+
244
+ if (window.basecoat) {
245
+ window.basecoat.register('command', '.command:not([data-command-initialized])', initCommand);
246
+ }
247
+ })();
248
+
100
249
  (() => {
101
250
  const initDropdownMenu = (dropdownMenuComponent) => {
102
251
  const trigger = dropdownMenuComponent.querySelector(':scope > button');
@@ -360,7 +509,8 @@
360
509
  return;
361
510
  }
362
511
 
363
- const options = Array.from(listbox.querySelectorAll('[role="option"]'));
512
+ const allOptions = Array.from(listbox.querySelectorAll('[role="option"]'));
513
+ const options = allOptions.filter(opt => opt.getAttribute('aria-disabled') !== 'true');
364
514
  let visibleOptions = [...options];
365
515
  let activeIndex = -1;
366
516
 
@@ -413,7 +563,7 @@
413
563
  const resetFilter = () => {
414
564
  filter.value = '';
415
565
  visibleOptions = [...options];
416
- options.forEach(opt => opt.setAttribute('aria-hidden', 'false'));
566
+ allOptions.forEach(opt => opt.setAttribute('aria-hidden', 'false'));
417
567
  };
418
568
 
419
569
  if (hasTransition()) {
@@ -454,11 +604,11 @@
454
604
  setActiveOption(-1);
455
605
 
456
606
  visibleOptions = [];
457
- options.forEach(option => {
607
+ allOptions.forEach(option => {
458
608
  const optionText = (option.dataset.label || option.textContent).trim().toLowerCase();
459
609
  const matches = optionText.includes(searchTerm);
460
610
  option.setAttribute('aria-hidden', String(!matches));
461
- if (matches) {
611
+ if (matches && options.includes(option)) {
462
612
  visibleOptions.push(option);
463
613
  }
464
614
  });