@moni-labs/moni-ui 0.4.13 → 0.4.14

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 (96) hide show
  1. package/custom-elements.json +91 -81
  2. package/dist/browser/moni-ui.iife.min.js +1537 -1384
  3. package/dist/browser/moni-ui.iife.min.js.br +0 -0
  4. package/dist/browser/moni-ui.iife.min.js.gz +0 -0
  5. package/dist/browser/moni-ui.iife.min.js.map +1 -1
  6. package/dist/browser/moni-ui.min.js +2703 -2481
  7. package/dist/browser/moni-ui.min.js.br +0 -0
  8. package/dist/browser/moni-ui.min.js.gz +0 -0
  9. package/dist/browser/moni-ui.min.js.map +1 -1
  10. package/dist/cdn/chunks/{class-map-DsL1Jr2T.js → class-map-QyT9W7rZ.js} +1 -1
  11. package/dist/cdn/chunks/{decorate-DxJYS4gw.js → decorate-B7wZvwrn.js} +629 -543
  12. package/dist/cdn/chunks/if-defined-5hr_ccFw.js +1 -0
  13. package/dist/cdn/chunks/{live-D52JqeKf.js → live-Hm1Di_ND.js} +1 -1
  14. package/dist/cdn/components/moni-app-bar.js +1 -1
  15. package/dist/cdn/components/moni-badge.js +1 -1
  16. package/dist/cdn/components/moni-bottom-sheet.js +1 -1
  17. package/dist/cdn/components/moni-button-group.js +1 -1
  18. package/dist/cdn/components/moni-button-segment.js +1 -1
  19. package/dist/cdn/components/moni-button.js +1 -1
  20. package/dist/cdn/components/moni-card.js +1 -1
  21. package/dist/cdn/components/moni-carousel.js +1 -1
  22. package/dist/cdn/components/moni-checkbox.js +1 -1
  23. package/dist/cdn/components/moni-chip.js +1 -1
  24. package/dist/cdn/components/moni-color-field.js +1 -1
  25. package/dist/cdn/components/moni-context-menu.js +1 -1
  26. package/dist/cdn/components/moni-dialog.js +1 -1
  27. package/dist/cdn/components/moni-divider.js +1 -1
  28. package/dist/cdn/components/moni-expansion.js +1 -1
  29. package/dist/cdn/components/moni-fab-menu.js +1 -1
  30. package/dist/cdn/components/moni-fab.js +1 -1
  31. package/dist/cdn/components/moni-file-field.js +1 -1
  32. package/dist/cdn/components/moni-icon.js +1 -1
  33. package/dist/cdn/components/moni-list-item.js +1 -1
  34. package/dist/cdn/components/moni-list.js +1 -1
  35. package/dist/cdn/components/moni-loading-indicator.js +1 -1
  36. package/dist/cdn/components/moni-menu-item.js +1 -1
  37. package/dist/cdn/components/moni-menu.js +1 -1
  38. package/dist/cdn/components/moni-morph-modal.js +3 -2
  39. package/dist/cdn/components/moni-nav-item.js +1 -1
  40. package/dist/cdn/components/moni-nav.js +1 -1
  41. package/dist/cdn/components/moni-progress.js +1 -1
  42. package/dist/cdn/components/moni-radio.js +1 -1
  43. package/dist/cdn/components/moni-ripple.js +1 -1
  44. package/dist/cdn/components/moni-segmented-button.js +1 -1
  45. package/dist/cdn/components/moni-select-option.js +1 -1
  46. package/dist/cdn/components/moni-select.js +512 -473
  47. package/dist/cdn/components/moni-shape.js +1 -1
  48. package/dist/cdn/components/moni-side-sheet.js +1 -1
  49. package/dist/cdn/components/moni-slider.js +1 -1
  50. package/dist/cdn/components/moni-snackbar.js +1 -1
  51. package/dist/cdn/components/moni-split-button.js +1 -1
  52. package/dist/cdn/components/moni-step.js +1 -1
  53. package/dist/cdn/components/moni-stepper.js +1 -1
  54. package/dist/cdn/components/moni-switch.js +1 -1
  55. package/dist/cdn/components/moni-tab.js +1 -1
  56. package/dist/cdn/components/moni-tabs.js +1 -1
  57. package/dist/cdn/components/moni-text-field.js +122 -95
  58. package/dist/cdn/components/moni-textarea.js +52 -52
  59. package/dist/cdn/components/moni-time-picker.js +1 -1
  60. package/dist/cdn/components/moni-toolbar.js +1 -1
  61. package/dist/cdn/components/moni-tooltip.js +1 -1
  62. package/dist/cdn/components/moni-typography.js +1 -1
  63. package/dist/cdn/importmap.json +98 -98
  64. package/dist/components/_base/field-styles.d.ts.map +1 -1
  65. package/dist/components/_base/field-styles.js +662 -576
  66. package/dist/components/moni-morph-modal.d.ts +10 -0
  67. package/dist/components/moni-morph-modal.d.ts.map +1 -1
  68. package/dist/components/moni-morph-modal.js +323 -217
  69. package/dist/components/moni-select.d.ts +16 -16
  70. package/dist/components/moni-select.d.ts.map +1 -1
  71. package/dist/components/moni-select.js +797 -727
  72. package/dist/components/moni-text-field.d.ts +15 -15
  73. package/dist/components/moni-text-field.d.ts.map +1 -1
  74. package/dist/components/moni-text-field.js +224 -180
  75. package/dist/components/moni-textarea.d.ts +13 -13
  76. package/dist/components/moni-textarea.d.ts.map +1 -1
  77. package/dist/components/moni-textarea.js +127 -122
  78. package/docs/api.json +97 -88
  79. package/docs/assets/moni-morph-modal/autoHeight--false.png +0 -0
  80. package/docs/assets/moni-morph-modal/autoHeight--true.png +0 -0
  81. package/docs/components/morph-modal.md +16 -7
  82. package/docs/components/select.md +74 -74
  83. package/docs/components/text-field.md +75 -66
  84. package/docs/components/textarea.md +51 -51
  85. package/docs/llms.txt +3 -3
  86. package/package.json +1 -1
  87. package/src/components/_base/field-styles.ts +723 -637
  88. package/src/components/moni-morph-modal.test.ts +490 -413
  89. package/src/components/moni-morph-modal.ts +2274 -2162
  90. package/src/components/moni-select.test.ts +489 -466
  91. package/src/components/moni-select.ts +1963 -1815
  92. package/src/components/moni-text-field.test.ts +366 -342
  93. package/src/components/moni-text-field.ts +717 -645
  94. package/src/components/moni-textarea.test.ts +201 -197
  95. package/src/components/moni-textarea.ts +476 -460
  96. package/dist/cdn/chunks/if-defined-DdzvcoI7.js +0 -1
@@ -10,15 +10,15 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
10
10
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
11
11
  return c > 3 && r && Object.defineProperty(target, key, r), r;
12
12
  };
13
- import { html, css, nothing } from 'lit';
14
- import { customElement, property, state, query } from 'lit/decorators.js';
15
- import { ifDefined } from 'lit/directives/if-defined.js';
16
- import { classMap } from 'lit/directives/class-map.js';
17
- import { MoniElement, sharedStyles, fieldStyles } from './_base/index.js';
18
- import { emitMoniEvent } from '../utils/event-emitter.js';
19
- import './moni-icon.js';
20
- import './moni-progress.js';
21
- import './moni-select-option.js';
13
+ import { html, css, nothing } from "lit";
14
+ import { customElement, property, state, query } from "lit/decorators.js";
15
+ import { ifDefined } from "lit/directives/if-defined.js";
16
+ import { classMap } from "lit/directives/class-map.js";
17
+ import { MoniElement, sharedStyles, fieldStyles } from "./_base/index.js";
18
+ import { emitMoniEvent } from "../utils/event-emitter.js";
19
+ import "./moni-icon.js";
20
+ import "./moni-progress.js";
21
+ import "./moni-select-option.js";
22
22
  /**
23
23
  * Componente Material Design 3 Select (Menú Desplegable).
24
24
  *
@@ -82,30 +82,30 @@ let MoniSelect = class MoniSelect extends MoniElement {
82
82
  * Nombre del campo select, usado para el envío del formulario.
83
83
  * @type {string}
84
84
  */
85
- this.name = '';
85
+ this.name = "";
86
86
  /**
87
87
  * Texto de la etiqueta flotante.
88
88
  * @type {string}
89
89
  */
90
- this.label = '';
90
+ this.label = "";
91
91
  /**
92
92
  * Variante visual del campo select.
93
93
  * @type {'filled' | 'outlined'}
94
94
  * @default 'filled'
95
95
  */
96
- this.variant = 'filled';
96
+ this.variant = "filled";
97
97
  /**
98
98
  * Define las dimensiones del campo select.
99
99
  * @type {'small' | 'medium' | 'large' | 'extra'}
100
100
  * @default 'medium'
101
101
  */
102
- this.size = 'medium';
102
+ this.size = "medium";
103
103
  /**
104
104
  * Forma (radio de borde) del campo.
105
105
  * @type {'round' | 'small-round' | 'square' | 'no-round'}
106
106
  * @default 'no-round'
107
107
  */
108
- this.shape = 'no-round';
108
+ this.shape = "no-round";
109
109
  /**
110
110
  * Deshabilita el campo select.
111
111
  * @type {boolean}
@@ -128,13 +128,13 @@ let MoniSelect = class MoniSelect extends MoniElement {
128
128
  * Texto de ayuda mostrado debajo del campo.
129
129
  * @type {string}
130
130
  */
131
- this.helper = '';
131
+ this.helper = "";
132
132
  /**
133
133
  * Texto de error mostrado debajo del campo cuando `error` es true.
134
134
  * Reemplaza al texto de ayuda.
135
135
  * @type {string}
136
136
  */
137
- this.errorText = '';
137
+ this.errorText = "";
138
138
  /**
139
139
  * Si es verdadero, establece el campo en un estado de error.
140
140
  * @type {boolean}
@@ -144,18 +144,18 @@ let MoniSelect = class MoniSelect extends MoniElement {
144
144
  * El valor actual del select.
145
145
  * @type {string}
146
146
  */
147
- this.value = '';
147
+ this.value = "";
148
148
  /**
149
149
  * Nombre del icono principal (leading icon, Material Symbols).
150
150
  * @type {string}
151
151
  */
152
- this.icon = '';
152
+ this.icon = "";
153
153
  /**
154
154
  * Nombre del icono final (trailing icon, Material Symbols) que indica el estado del menú desplegable.
155
155
  * @type {string}
156
156
  * @default 'arrow_drop_down'
157
157
  */
158
- this.trailingIcon = 'arrow_drop_down';
158
+ this.trailingIcon = "arrow_drop_down";
159
159
  /**
160
160
  * Habilita un campo de búsqueda en la parte superior del menú desplegable para filtrar opciones.
161
161
  * @type {boolean}
@@ -175,7 +175,7 @@ let MoniSelect = class MoniSelect extends MoniElement {
175
175
  * Texto de marcador de posición (placeholder) mostrado cuando no hay ningún valor seleccionado.
176
176
  * @type {string}
177
177
  */
178
- this.placeholder = '';
178
+ this.placeholder = "";
179
179
  /**
180
180
  * Estrategia de posicionamiento para el menú desplegable.
181
181
  *
@@ -187,13 +187,13 @@ let MoniSelect = class MoniSelect extends MoniElement {
187
187
  * @type {'absolute' | 'fixed' | 'body'}
188
188
  * @default 'absolute'
189
189
  */
190
- this.positioning = 'absolute';
190
+ this.positioning = "absolute";
191
191
  /**
192
192
  * Ubicación preferida del menú desplegable con respecto al disparador (trigger).
193
193
  * @type {'top' | 'bottom' | 'left' | 'right' | 'auto'}
194
194
  * @default 'auto'
195
195
  */
196
- this.placement = 'auto';
196
+ this.placement = "auto";
197
197
  /**
198
198
  * Restricción de ancho del menú desplegable.
199
199
  * - `'trigger'`: Coincide con el ancho del campo de entrada.
@@ -202,7 +202,7 @@ let MoniSelect = class MoniSelect extends MoniElement {
202
202
  * @type {string}
203
203
  * @default 'trigger'
204
204
  */
205
- this.dropdownWidth = 'trigger';
205
+ this.dropdownWidth = "trigger";
206
206
  /**
207
207
  * Límite manual opcional para la altura del menú.
208
208
  *
@@ -213,14 +213,14 @@ let MoniSelect = class MoniSelect extends MoniElement {
213
213
  *
214
214
  * @default ''
215
215
  */
216
- this.dropdownMaxHeight = '';
216
+ this.dropdownMaxHeight = "";
217
217
  this._open = false;
218
- this._searchQuery = '';
219
- this._actualPlacement = 'bottom';
218
+ this._searchQuery = "";
219
+ this._actualPlacement = "bottom";
220
220
  this._parsedOptions = [];
221
221
  this._activeIndex = -1;
222
- this._menuStyle = '';
223
- this._menuMaxHeight = '75vh';
222
+ this._menuStyle = "";
223
+ this._menuMaxHeight = "75vh";
224
224
  this._useInlineCategories = false;
225
225
  this._drilldownPath = [];
226
226
  /**
@@ -273,12 +273,12 @@ let MoniSelect = class MoniSelect extends MoniElement {
273
273
  * mensaje y a dónde llevar el foco.
274
274
  */
275
275
  /**
276
- * API de validación equivalente a la de un control nativo.
277
- *
278
- * Los elementos form-associated participan en la validación del formulario,
279
- * pero no reciben estos miembros automáticamente: hay que exponerlos para que
280
- * un `moni-select` se pueda interrogar igual que un `<input>`.
281
- */
276
+ * API de validación equivalente a la de un control nativo.
277
+ *
278
+ * Los elementos form-associated participan en la validación del formulario,
279
+ * pero no reciben estos miembros automáticamente: hay que exponerlos para que
280
+ * un `moni-select` se pueda interrogar igual que un `<input>`.
281
+ */
282
282
  get validity() {
283
283
  return this._internals.validity;
284
284
  }
@@ -295,7 +295,7 @@ let MoniSelect = class MoniSelect extends MoniElement {
295
295
  if (!this._internals?.setValidity)
296
296
  return;
297
297
  if (this.required && !this.value) {
298
- this._internals.setValidity({ valueMissing: true }, 'Selecciona una opción.', this._input ?? undefined);
298
+ this._internals.setValidity({ valueMissing: true }, "Selecciona una opción.", this._input ?? undefined);
299
299
  return;
300
300
  }
301
301
  this._internals.setValidity({});
@@ -303,339 +303,343 @@ let MoniSelect = class MoniSelect extends MoniElement {
303
303
  static { this.styles = [
304
304
  sharedStyles,
305
305
  fieldStyles,
306
- css `
307
- :host {
308
- position: relative;
309
- display: block;
310
- }
311
-
312
- .field {
313
- cursor: pointer;
314
- }
315
-
316
- input[type='text'] {
317
- cursor: pointer;
318
- width: 100%;
319
- }
320
-
321
- input[type='text'][readonly] {
322
- caret-color: transparent;
323
- user-select: none;
324
- }
325
-
326
- /* Dropdown menu overlay */
327
- .dropdown-menu {
328
- position: absolute;
329
- top: 100%;
330
- left: 0;
331
- right: 0;
332
- z-index: 100;
333
- background-color: var(--surface-container);
334
- box-shadow: var(--elevate3);
335
- border-radius: 0.5rem;
336
- margin-top: 4px;
337
- padding: 4px 0;
338
- list-style: none;
339
- opacity: 0;
340
- visibility: hidden;
341
- transform: scale(0.95) translateY(-8px);
342
- transform-origin: top;
343
- transition:
344
- opacity var(--speed3) cubic-bezier(0.2, 0.8, 0.2, 1),
345
- transform var(--speed3) cubic-bezier(0.34, 1.56, 0.64, 1),
346
- visibility var(--speed3);
347
- }
348
-
349
- .dropdown-menu.open {
350
- opacity: 1;
351
- visibility: visible;
352
- transform: scale(1) translateY(0);
353
- }
354
-
355
- /* positioning="body" promotes the menu to the browser's top layer.
356
- Reset the Popover UA box while retaining Shadow DOM styles. */
357
- .dropdown-menu[popover] {
358
- margin: 0;
359
- border: 0;
360
- }
361
-
362
- .dropdown-menu.placement-top {
363
- top: auto;
364
- bottom: 100%;
365
- margin-top: 0;
366
- margin-bottom: 4px;
367
- transform-origin: bottom;
368
- transform: scale(0.95) translateY(8px);
369
- }
370
-
371
- .dropdown-menu.placement-top.open {
372
- transform: scale(1) translateY(0);
373
- }
374
-
375
- .dropdown-menu.placement-left {
376
- top: 0;
377
- left: auto;
378
- right: 100%;
379
- margin-top: 0;
380
- margin-right: 4px;
381
- transform-origin: right center;
382
- transform: scale(0.95) translateX(8px);
383
- }
384
-
385
- .dropdown-menu.placement-left.open {
386
- transform: scale(1) translateX(0);
387
- }
388
-
389
- .dropdown-menu.placement-right {
390
- top: 0;
391
- left: 100%;
392
- right: auto;
393
- margin-top: 0;
394
- margin-left: 4px;
395
- transform-origin: left center;
396
- transform: scale(0.95) translateX(-8px);
397
- }
398
-
399
- .dropdown-menu.placement-right.open {
400
- transform: scale(1) translateX(0);
401
- }
402
-
403
- .dropdown-menu.open.scrollable {
404
- overflow-x: hidden;
405
- overflow-y: auto;
406
- overscroll-behavior: contain;
407
- }
408
-
409
- /* Desktop category flyouts need visible overflow. If the root list no
410
- longer fits, the component switches to the inline drilldown layout. */
411
- .dropdown-menu.open:not(.scrollable) {
412
- overflow: visible;
413
- }
414
-
415
- /* Bottom sheet drawer styles */
416
- .sheet-backdrop {
417
- position: fixed;
418
- inset: 0;
419
- z-index: 1000;
420
- background-color: rgba(0, 0, 0, 0.4);
421
- opacity: 0;
422
- visibility: hidden;
423
- transition: opacity var(--speed3) cubic-bezier(0.2, 0.8, 0.2, 1), visibility var(--speed3);
424
- display: flex;
425
- flex-direction: column;
426
- justify-content: flex-end;
427
- }
428
-
429
- .sheet-backdrop.open {
430
- opacity: 1;
431
- visibility: visible;
432
- }
433
-
434
- .sheet-drawer {
435
- background-color: var(--surface-container);
436
- border-radius: 1.75rem 1.75rem 0 0;
437
- box-shadow: var(--elevate3);
438
- max-height: 70vh;
439
- display: flex;
440
- flex-direction: column;
441
- transform: translateY(100%);
442
- transition: transform var(--speed3) cubic-bezier(0.16, 1, 0.3, 1);
443
- padding: 16px 0;
444
- }
445
-
446
- .sheet-drawer.open {
447
- transform: translateY(0);
448
- }
449
-
450
- .sheet-handle {
451
- width: 40px;
452
- height: 4px;
453
- background-color: var(--outline-variant);
454
- border-radius: 2px;
455
- margin: 0 auto 16px;
456
- }
457
-
458
- .sheet-title {
459
- padding: 0 24px 8px;
460
- font-size: 1.125rem;
461
- font-weight: 700;
462
- color: var(--on-surface);
463
- }
464
-
465
- .sheet-search-wrapper {
466
- padding: 0 16px 12px;
467
- }
468
-
469
- .sheet-search-input {
470
- width: 100%;
471
- box-sizing: border-box;
472
- padding: 10px 16px;
473
- border: 1px solid var(--outline);
474
- border-radius: 9999px;
475
- background: var(--surface-container-high);
476
- color: var(--on-surface);
477
- font-size: 1rem;
478
- outline: none;
479
- }
480
-
481
- .sheet-search-input:focus {
482
- border-color: var(--primary);
483
- }
484
-
485
- .sheet-options-list {
486
- list-style: none;
487
- padding: 0;
488
- margin: 0;
489
- overflow-y: auto;
490
- flex: 1;
491
- }
492
-
493
- /* Animated Drilldown Slide Layout */
494
- .drilldown-wrapper {
495
- width: 100%;
496
- overflow: hidden;
497
- position: relative;
498
- transition: height var(--speed3) cubic-bezier(0.2, 0.8, 0.2, 1);
499
- }
500
-
501
- .drilldown-track {
502
- display: flex;
503
- width: 200%;
504
- transition: transform var(--speed3) cubic-bezier(0.2, 0.8, 0.2, 1);
505
- }
506
-
507
- .drilldown-track.slide-active {
508
- transform: translateX(-50%);
509
- }
510
-
511
- .drilldown-panel {
512
- width: 50%;
513
- box-sizing: border-box;
514
- list-style: none;
515
- padding: 0;
516
- margin: 0;
517
- flex-shrink: 0;
518
- }
519
-
520
- .drilldown-panel.panel-active {
521
- max-height: none;
522
- }
523
-
524
- .drilldown-panel.panel-inactive {
525
- max-height: 0;
526
- overflow: hidden;
527
- }
528
-
529
- /* Group / Subcategory header (Browsing mode - acts as a hover trigger for submenus) */
530
- .group-header {
531
- padding: 8px 16px;
532
- font-size: 0.875rem;
533
- font-weight: 500;
534
- color: var(--on-surface);
535
- cursor: pointer;
536
- display: flex;
537
- align-items: center;
538
- position: relative;
539
- user-select: none;
540
- transition: background-color var(--speed2) ease, color var(--speed2) ease;
541
- }
542
-
543
- .group-header:hover,
544
- .group-header.active {
545
- background-color: var(--surface-container-high);
546
- color: var(--primary);
547
- }
548
-
549
- /* Inline header (Searching mode & Sheet mode - flat layout) */
550
- .group-header-flat {
551
- padding: 6px 16px;
552
- font-size: 0.75rem;
553
- font-weight: 700;
554
- text-transform: uppercase;
555
- color: var(--primary);
556
- letter-spacing: 0.05em;
557
- background-color: var(--surface-container-low);
558
- user-select: none;
559
- }
560
-
561
- /* Hierarchical sub-menu with premium flyout animation */
562
- .submenu {
563
- display: block;
564
- opacity: 0;
565
- visibility: hidden;
566
- position: absolute;
567
- top: 0;
568
- /* Intermediate flyouts must keep overflow visible so deeper
569
- subcategories are never clipped. Oversized trees switch to the
570
- scrollable inline drilldown layout before rendering. */
571
- overflow: visible;
572
- background-color: var(--surface-container-highest);
573
- box-shadow: var(--elevate3);
574
- border-radius: 0.5rem;
575
- padding: 4px 0;
576
- list-style: none;
577
- min-width: 160px;
578
- z-index: 110;
579
- transition:
580
- opacity var(--speed2) cubic-bezier(0.2, 0.8, 0.2, 1),
581
- transform var(--speed2) cubic-bezier(0.34, 1.56, 0.64, 1),
582
- visibility var(--speed2);
583
- }
584
-
585
- .submenu.open-right {
586
- left: 100%;
587
- margin-left: 2px;
588
- transform: scale(0.9) translateX(-10px);
589
- transform-origin: top left;
590
- }
591
-
592
- .submenu.open-left {
593
- right: 100%;
594
- margin-right: 2px;
595
- transform: scale(0.9) translateX(10px);
596
- transform-origin: top right;
597
- }
598
-
599
- .group-header:hover > .submenu.active,
600
- .group-header.active > .submenu.active {
601
- opacity: 1;
602
- visibility: visible;
603
- transform: scale(1) translateX(0);
604
- }
605
-
606
- .option-item {
607
- cursor: pointer;
608
- padding: 8px 16px;
609
- font-size: 0.875rem;
610
- color: var(--on-surface);
611
- display: flex;
612
- align-items: center;
613
- transition: background-color var(--speed2) ease;
614
- }
615
-
616
- .option-item:hover,
617
- .option-item.active-nav {
618
- background-color: var(--surface-container-high);
619
- }
620
-
621
- .option-item.selected {
622
- background-color: var(--tertiary-container);
623
- color: var(--on-tertiary-container);
624
- font-weight: 500;
625
- }
626
-
627
- .option-item.disabled {
628
- opacity: 0.5;
629
- pointer-events: none;
630
- }
631
-
632
- .no-options {
633
- padding: 12px 16px;
634
- font-size: 0.875rem;
635
- color: var(--outline);
636
- text-align: center;
637
- }
638
- `
306
+ css `
307
+ :host {
308
+ position: relative;
309
+ display: block;
310
+ }
311
+
312
+ .field {
313
+ cursor: pointer;
314
+ }
315
+
316
+ input[type="text"] {
317
+ cursor: pointer;
318
+ width: 100%;
319
+ }
320
+
321
+ input[type="text"][readonly] {
322
+ caret-color: transparent;
323
+ user-select: none;
324
+ }
325
+
326
+ /* Dropdown menu overlay */
327
+ .dropdown-menu {
328
+ position: absolute;
329
+ top: 100%;
330
+ left: 0;
331
+ right: 0;
332
+ z-index: 100;
333
+ background-color: var(--surface-container);
334
+ box-shadow: var(--elevate3);
335
+ border-radius: 0.5rem;
336
+ margin-top: 4px;
337
+ padding: 4px 0;
338
+ list-style: none;
339
+ opacity: 0;
340
+ visibility: hidden;
341
+ transform: scale(0.95) translateY(-8px);
342
+ transform-origin: top;
343
+ transition:
344
+ opacity var(--speed3) cubic-bezier(0.2, 0.8, 0.2, 1),
345
+ transform var(--speed3) cubic-bezier(0.34, 1.56, 0.64, 1),
346
+ visibility var(--speed3);
347
+ }
348
+
349
+ .dropdown-menu.open {
350
+ opacity: 1;
351
+ visibility: visible;
352
+ transform: scale(1) translateY(0);
353
+ }
354
+
355
+ /* positioning="body" promotes the menu to the browser's top layer.
356
+ Reset the Popover UA box while retaining Shadow DOM styles. */
357
+ .dropdown-menu[popover] {
358
+ margin: 0;
359
+ border: 0;
360
+ }
361
+
362
+ .dropdown-menu.placement-top {
363
+ top: auto;
364
+ bottom: 100%;
365
+ margin-top: 0;
366
+ margin-bottom: 4px;
367
+ transform-origin: bottom;
368
+ transform: scale(0.95) translateY(8px);
369
+ }
370
+
371
+ .dropdown-menu.placement-top.open {
372
+ transform: scale(1) translateY(0);
373
+ }
374
+
375
+ .dropdown-menu.placement-left {
376
+ top: 0;
377
+ left: auto;
378
+ right: 100%;
379
+ margin-top: 0;
380
+ margin-right: 4px;
381
+ transform-origin: right center;
382
+ transform: scale(0.95) translateX(8px);
383
+ }
384
+
385
+ .dropdown-menu.placement-left.open {
386
+ transform: scale(1) translateX(0);
387
+ }
388
+
389
+ .dropdown-menu.placement-right {
390
+ top: 0;
391
+ left: 100%;
392
+ right: auto;
393
+ margin-top: 0;
394
+ margin-left: 4px;
395
+ transform-origin: left center;
396
+ transform: scale(0.95) translateX(-8px);
397
+ }
398
+
399
+ .dropdown-menu.placement-right.open {
400
+ transform: scale(1) translateX(0);
401
+ }
402
+
403
+ .dropdown-menu.open.scrollable {
404
+ overflow-x: hidden;
405
+ overflow-y: auto;
406
+ overscroll-behavior: contain;
407
+ }
408
+
409
+ /* Desktop category flyouts need visible overflow. If the root list no
410
+ longer fits, the component switches to the inline drilldown layout. */
411
+ .dropdown-menu.open:not(.scrollable) {
412
+ overflow: visible;
413
+ }
414
+
415
+ /* Bottom sheet drawer styles */
416
+ .sheet-backdrop {
417
+ position: fixed;
418
+ inset: 0;
419
+ z-index: 1000;
420
+ background-color: rgba(0, 0, 0, 0.4);
421
+ opacity: 0;
422
+ visibility: hidden;
423
+ transition:
424
+ opacity var(--speed3) cubic-bezier(0.2, 0.8, 0.2, 1),
425
+ visibility var(--speed3);
426
+ display: flex;
427
+ flex-direction: column;
428
+ justify-content: flex-end;
429
+ }
430
+
431
+ .sheet-backdrop.open {
432
+ opacity: 1;
433
+ visibility: visible;
434
+ }
435
+
436
+ .sheet-drawer {
437
+ background-color: var(--surface-container);
438
+ border-radius: 1.75rem 1.75rem 0 0;
439
+ box-shadow: var(--elevate3);
440
+ max-height: 70vh;
441
+ display: flex;
442
+ flex-direction: column;
443
+ transform: translateY(100%);
444
+ transition: transform var(--speed3) cubic-bezier(0.16, 1, 0.3, 1);
445
+ padding: 16px 0;
446
+ }
447
+
448
+ .sheet-drawer.open {
449
+ transform: translateY(0);
450
+ }
451
+
452
+ .sheet-handle {
453
+ width: 40px;
454
+ height: 4px;
455
+ background-color: var(--outline-variant);
456
+ border-radius: 2px;
457
+ margin: 0 auto 16px;
458
+ }
459
+
460
+ .sheet-title {
461
+ padding: 0 24px 8px;
462
+ font-size: 1.125rem;
463
+ font-weight: 700;
464
+ color: var(--on-surface);
465
+ }
466
+
467
+ .sheet-search-wrapper {
468
+ padding: 0 16px 12px;
469
+ }
470
+
471
+ .sheet-search-input {
472
+ width: 100%;
473
+ box-sizing: border-box;
474
+ padding: 10px 16px;
475
+ border: 1px solid var(--outline);
476
+ border-radius: 9999px;
477
+ background: var(--surface-container-high);
478
+ color: var(--on-surface);
479
+ font-size: 1rem;
480
+ outline: none;
481
+ }
482
+
483
+ .sheet-search-input:focus {
484
+ border-color: var(--primary);
485
+ }
486
+
487
+ .sheet-options-list {
488
+ list-style: none;
489
+ padding: 0;
490
+ margin: 0;
491
+ overflow-y: auto;
492
+ flex: 1;
493
+ }
494
+
495
+ /* Animated Drilldown Slide Layout */
496
+ .drilldown-wrapper {
497
+ width: 100%;
498
+ overflow: hidden;
499
+ position: relative;
500
+ transition: height var(--speed3) cubic-bezier(0.2, 0.8, 0.2, 1);
501
+ }
502
+
503
+ .drilldown-track {
504
+ display: flex;
505
+ width: 200%;
506
+ transition: transform var(--speed3) cubic-bezier(0.2, 0.8, 0.2, 1);
507
+ }
508
+
509
+ .drilldown-track.slide-active {
510
+ transform: translateX(-50%);
511
+ }
512
+
513
+ .drilldown-panel {
514
+ width: 50%;
515
+ box-sizing: border-box;
516
+ list-style: none;
517
+ padding: 0;
518
+ margin: 0;
519
+ flex-shrink: 0;
520
+ }
521
+
522
+ .drilldown-panel.panel-active {
523
+ max-height: none;
524
+ }
525
+
526
+ .drilldown-panel.panel-inactive {
527
+ max-height: 0;
528
+ overflow: hidden;
529
+ }
530
+
531
+ /* Group / Subcategory header (Browsing mode - acts as a hover trigger for submenus) */
532
+ .group-header {
533
+ padding: 8px 16px;
534
+ font-size: 0.875rem;
535
+ font-weight: 500;
536
+ color: var(--on-surface);
537
+ cursor: pointer;
538
+ display: flex;
539
+ align-items: center;
540
+ position: relative;
541
+ user-select: none;
542
+ transition:
543
+ background-color var(--speed2) ease,
544
+ color var(--speed2) ease;
545
+ }
546
+
547
+ .group-header:hover,
548
+ .group-header.active {
549
+ background-color: var(--surface-container-high);
550
+ color: var(--primary);
551
+ }
552
+
553
+ /* Inline header (Searching mode & Sheet mode - flat layout) */
554
+ .group-header-flat {
555
+ padding: 6px 16px;
556
+ font-size: 0.75rem;
557
+ font-weight: 700;
558
+ text-transform: uppercase;
559
+ color: var(--primary);
560
+ letter-spacing: 0.05em;
561
+ background-color: var(--surface-container-low);
562
+ user-select: none;
563
+ }
564
+
565
+ /* Hierarchical sub-menu with premium flyout animation */
566
+ .submenu {
567
+ display: block;
568
+ opacity: 0;
569
+ visibility: hidden;
570
+ position: absolute;
571
+ top: 0;
572
+ /* Intermediate flyouts must keep overflow visible so deeper
573
+ subcategories are never clipped. Oversized trees switch to the
574
+ scrollable inline drilldown layout before rendering. */
575
+ overflow: visible;
576
+ background-color: var(--surface-container-highest);
577
+ box-shadow: var(--elevate3);
578
+ border-radius: 0.5rem;
579
+ padding: 4px 0;
580
+ list-style: none;
581
+ min-width: 160px;
582
+ z-index: 110;
583
+ transition:
584
+ opacity var(--speed2) cubic-bezier(0.2, 0.8, 0.2, 1),
585
+ transform var(--speed2) cubic-bezier(0.34, 1.56, 0.64, 1),
586
+ visibility var(--speed2);
587
+ }
588
+
589
+ .submenu.open-right {
590
+ left: 100%;
591
+ margin-left: 2px;
592
+ transform: scale(0.9) translateX(-10px);
593
+ transform-origin: top left;
594
+ }
595
+
596
+ .submenu.open-left {
597
+ right: 100%;
598
+ margin-right: 2px;
599
+ transform: scale(0.9) translateX(10px);
600
+ transform-origin: top right;
601
+ }
602
+
603
+ .group-header:hover > .submenu.active,
604
+ .group-header.active > .submenu.active {
605
+ opacity: 1;
606
+ visibility: visible;
607
+ transform: scale(1) translateX(0);
608
+ }
609
+
610
+ .option-item {
611
+ cursor: pointer;
612
+ padding: 8px 16px;
613
+ font-size: 0.875rem;
614
+ color: var(--on-surface);
615
+ display: flex;
616
+ align-items: center;
617
+ transition: background-color var(--speed2) ease;
618
+ }
619
+
620
+ .option-item:hover,
621
+ .option-item.active-nav {
622
+ background-color: var(--surface-container-high);
623
+ }
624
+
625
+ .option-item.selected {
626
+ background-color: var(--tertiary-container);
627
+ color: var(--on-tertiary-container);
628
+ font-weight: 500;
629
+ }
630
+
631
+ .option-item.disabled {
632
+ opacity: 0.5;
633
+ pointer-events: none;
634
+ }
635
+
636
+ .no-options {
637
+ padding: 12px 16px;
638
+ font-size: 0.875rem;
639
+ color: var(--outline);
640
+ text-align: center;
641
+ }
642
+ `,
639
643
  ]; }
640
644
  /**
641
645
  * Hook del ciclo de vida (Lit).
@@ -645,12 +649,12 @@ let MoniSelect = class MoniSelect extends MoniElement {
645
649
  */
646
650
  connectedCallback() {
647
651
  super.connectedCallback();
648
- document.addEventListener('click', this._handleOutsideClick);
649
- document.addEventListener('moni-select-open', this._handlePeerOpen);
650
- window.addEventListener('scroll', this._handleScroll, { capture: true });
651
- window.addEventListener('resize', this._handleResize);
652
- window.visualViewport?.addEventListener('scroll', this._handleScroll);
653
- window.visualViewport?.addEventListener('resize', this._handleResize);
652
+ document.addEventListener("click", this._handleOutsideClick);
653
+ document.addEventListener("moni-select-open", this._handlePeerOpen);
654
+ window.addEventListener("scroll", this._handleScroll, { capture: true });
655
+ window.addEventListener("resize", this._handleResize);
656
+ window.visualViewport?.addEventListener("scroll", this._handleScroll);
657
+ window.visualViewport?.addEventListener("resize", this._handleResize);
654
658
  }
655
659
  /**
656
660
  * Hook del ciclo de vida (Lit).
@@ -660,12 +664,12 @@ let MoniSelect = class MoniSelect extends MoniElement {
660
664
  disconnectedCallback() {
661
665
  this._hideBodyPopover();
662
666
  super.disconnectedCallback();
663
- document.removeEventListener('click', this._handleOutsideClick);
664
- document.removeEventListener('moni-select-open', this._handlePeerOpen);
665
- window.removeEventListener('scroll', this._handleScroll, { capture: true });
666
- window.removeEventListener('resize', this._handleResize);
667
- window.visualViewport?.removeEventListener('scroll', this._handleScroll);
668
- window.visualViewport?.removeEventListener('resize', this._handleResize);
667
+ document.removeEventListener("click", this._handleOutsideClick);
668
+ document.removeEventListener("moni-select-open", this._handlePeerOpen);
669
+ window.removeEventListener("scroll", this._handleScroll, { capture: true });
670
+ window.removeEventListener("resize", this._handleResize);
671
+ window.visualViewport?.removeEventListener("scroll", this._handleScroll);
672
+ window.visualViewport?.removeEventListener("resize", this._handleResize);
669
673
  }
670
674
  /**
671
675
  * Hook de actualización reactiva (Lit).
@@ -675,27 +679,27 @@ let MoniSelect = class MoniSelect extends MoniElement {
675
679
  */
676
680
  updated(changedProperties) {
677
681
  super.updated(changedProperties);
678
- if (changedProperties.has('value')) {
682
+ if (changedProperties.has("value")) {
679
683
  this._internals?.setFormValue?.(this.value);
680
684
  }
681
685
  this._syncValidity();
682
- if (changedProperties.has('_open') ||
683
- changedProperties.has('_drilldownPath') ||
684
- changedProperties.has('_searchQuery') ||
685
- changedProperties.has('_useInlineCategories') ||
686
- changedProperties.has('_parsedOptions')) {
686
+ if (changedProperties.has("_open") ||
687
+ changedProperties.has("_drilldownPath") ||
688
+ changedProperties.has("_searchQuery") ||
689
+ changedProperties.has("_useInlineCategories") ||
690
+ changedProperties.has("_parsedOptions")) {
687
691
  this._updateWrapperHeight();
688
692
  }
689
693
  if (this._open &&
690
- (changedProperties.has('positioning') ||
691
- changedProperties.has('placement') ||
692
- changedProperties.has('dropdownWidth') ||
693
- changedProperties.has('dropdownMaxHeight'))) {
694
+ (changedProperties.has("positioning") ||
695
+ changedProperties.has("placement") ||
696
+ changedProperties.has("dropdownWidth") ||
697
+ changedProperties.has("dropdownMaxHeight"))) {
694
698
  this._updateMenuPosition();
695
699
  }
696
- if (changedProperties.has('_open') ||
697
- changedProperties.has('positioning') ||
698
- changedProperties.has('sheet')) {
700
+ if (changedProperties.has("_open") ||
701
+ changedProperties.has("positioning") ||
702
+ changedProperties.has("sheet")) {
699
703
  this._syncBodyPopover();
700
704
  }
701
705
  }
@@ -706,21 +710,21 @@ let MoniSelect = class MoniSelect extends MoniElement {
706
710
  * imperativamente al `wrapper` para disparar una transición CSS suave en la altura del dropdown.
707
711
  */
708
712
  _updateWrapperHeight() {
709
- const wrapper = this.shadowRoot?.querySelector('.drilldown-wrapper');
713
+ const wrapper = this.shadowRoot?.querySelector(".drilldown-wrapper");
710
714
  if (!wrapper)
711
715
  return;
712
716
  if (!this._open || this.sheet) {
713
- wrapper.style.height = '';
717
+ wrapper.style.height = "";
714
718
  return;
715
719
  }
716
720
  // Wait for Lit render and styles to apply
717
721
  requestAnimationFrame(() => {
718
- const activePanel = this.shadowRoot?.querySelector('.drilldown-panel.panel-active');
722
+ const activePanel = this.shadowRoot?.querySelector(".drilldown-panel.panel-active");
719
723
  if (activePanel) {
720
724
  wrapper.style.height = `${activePanel.scrollHeight}px`;
721
725
  }
722
726
  else {
723
- wrapper.style.height = '';
727
+ wrapper.style.height = "";
724
728
  }
725
729
  });
726
730
  }
@@ -731,11 +735,11 @@ let MoniSelect = class MoniSelect extends MoniElement {
731
735
  */
732
736
  _syncBodyPopover() {
733
737
  const menu = this._menu;
734
- if (!menu || typeof menu.showPopover !== 'function')
738
+ if (!menu || typeof menu.showPopover !== "function")
735
739
  return;
736
- const shouldBeOpen = this._open && !this.sheet && this.positioning === 'body';
740
+ const shouldBeOpen = this._open && !this.sheet && this.positioning === "body";
737
741
  try {
738
- const isOpen = menu.matches(':popover-open');
742
+ const isOpen = menu.matches(":popover-open");
739
743
  if (shouldBeOpen && !isOpen) {
740
744
  menu.showPopover();
741
745
  }
@@ -749,10 +753,10 @@ let MoniSelect = class MoniSelect extends MoniElement {
749
753
  }
750
754
  _hideBodyPopover() {
751
755
  const menu = this._menu;
752
- if (!menu || typeof menu.hidePopover !== 'function')
756
+ if (!menu || typeof menu.hidePopover !== "function")
753
757
  return;
754
758
  try {
755
- if (menu.matches(':popover-open'))
759
+ if (menu.matches(":popover-open"))
756
760
  menu.hidePopover();
757
761
  }
758
762
  catch {
@@ -776,7 +780,14 @@ let MoniSelect = class MoniSelect extends MoniElement {
776
780
  const left = viewport?.offsetLeft ?? 0;
777
781
  const height = viewport?.height ?? window.innerHeight;
778
782
  const width = viewport?.width ?? window.innerWidth;
779
- return { top, left, height, width, bottom: top + height, right: left + width };
783
+ return {
784
+ top,
785
+ left,
786
+ height,
787
+ width,
788
+ bottom: top + height,
789
+ right: left + width,
790
+ };
780
791
  }
781
792
  /**
782
793
  * Calcula el espacio vertical en una dirección. Además del espacio físico,
@@ -787,7 +798,7 @@ let MoniSelect = class MoniSelect extends MoniElement {
787
798
  const viewport = this._getViewportMetrics();
788
799
  const gap = 8;
789
800
  const viewportCap = viewport.height * 0.75;
790
- if (direction === 'bottom') {
801
+ if (direction === "bottom") {
791
802
  const physicalSpace = viewport.bottom - rect.bottom - gap;
792
803
  const triggerOffset = rect.bottom - viewport.top + gap;
793
804
  return Math.max(0, Math.floor(Math.min(viewportCap, physicalSpace, viewportCap - triggerOffset)));
@@ -799,12 +810,12 @@ let MoniSelect = class MoniSelect extends MoniElement {
799
810
  _normalizeManualMaxHeight() {
800
811
  const raw = this.dropdownMaxHeight.trim();
801
812
  if (!raw)
802
- return '';
813
+ return "";
803
814
  const normalized = /^\d+(?:\.\d+)?$/.test(raw) ? `${raw}px` : raw;
804
- if (typeof CSS !== 'undefined' &&
805
- typeof CSS.supports === 'function' &&
806
- !CSS.supports('max-height', normalized)) {
807
- return '';
815
+ if (typeof CSS !== "undefined" &&
816
+ typeof CSS.supports === "function" &&
817
+ !CSS.supports("max-height", normalized)) {
818
+ return "";
808
819
  }
809
820
  return normalized;
810
821
  }
@@ -815,9 +826,9 @@ let MoniSelect = class MoniSelect extends MoniElement {
815
826
  return null;
816
827
  const amount = Number(match[1]);
817
828
  const unit = match[2].toLowerCase();
818
- if (unit === 'px')
829
+ if (unit === "px")
819
830
  return amount;
820
- if (unit === 'rem') {
831
+ if (unit === "rem") {
821
832
  const rootSize = Number.parseFloat(getComputedStyle(document.documentElement).fontSize) || 16;
822
833
  return amount * rootSize;
823
834
  }
@@ -825,7 +836,7 @@ let MoniSelect = class MoniSelect extends MoniElement {
825
836
  }
826
837
  _getMenuHeightConstraint(rect, placement = this._actualPlacement) {
827
838
  const viewport = this._getViewportMetrics();
828
- const automatic = placement === 'top' || placement === 'bottom'
839
+ const automatic = placement === "top" || placement === "bottom"
829
840
  ? this._getDirectionalAvailableHeight(placement, rect)
830
841
  : Math.max(0, Math.floor(Math.min(viewport.height * 0.75, viewport.height - 16)));
831
842
  const manualCss = this._normalizeManualMaxHeight();
@@ -835,7 +846,7 @@ let MoniSelect = class MoniSelect extends MoniElement {
835
846
  const px = manualPx === null ? automatic : Math.min(automatic, manualPx);
836
847
  return {
837
848
  css: manualCss ? `min(${automatic}px, ${manualCss})` : `${automatic}px`,
838
- px: Math.max(0, px)
849
+ px: Math.max(0, px),
839
850
  };
840
851
  }
841
852
  _estimateDesiredMenuHeight() {
@@ -855,18 +866,19 @@ let MoniSelect = class MoniSelect extends MoniElement {
855
866
  /** Profundidad máxima de flyouts necesaria para representar el árbol. */
856
867
  _getGroupDepth(nodes) {
857
868
  return nodes.reduce((depth, node) => {
858
- if (node.type === 'option')
869
+ if (node.type === "option")
859
870
  return depth;
860
871
  return Math.max(depth, 1 + this._getGroupDepth(node.children));
861
872
  }, 0);
862
873
  }
863
874
  /** Detecta cualquier nivel cuya lista directa necesitaría scroll propio. */
864
875
  _hasOversizedGroupPanel(nodes, maxHeight) {
865
- return nodes.some(node => {
866
- if (node.type === 'option')
876
+ return nodes.some((node) => {
877
+ if (node.type === "option")
867
878
  return false;
868
879
  const panelHeight = node.children.length * 40 + 8;
869
- return panelHeight > maxHeight || this._hasOversizedGroupPanel(node.children, maxHeight);
880
+ return (panelHeight > maxHeight ||
881
+ this._hasOversizedGroupPanel(node.children, maxHeight));
870
882
  });
871
883
  }
872
884
  /**
@@ -879,7 +891,7 @@ let MoniSelect = class MoniSelect extends MoniElement {
879
891
  const viewport = this._getViewportMetrics();
880
892
  let boundaryLeft = viewport.left;
881
893
  let boundaryRight = viewport.right;
882
- if (this.positioning !== 'body') {
894
+ if (this.positioning !== "body") {
883
895
  let current = this;
884
896
  while (current) {
885
897
  const parent = current.parentNode instanceof ShadowRoot
@@ -900,42 +912,41 @@ let MoniSelect = class MoniSelect extends MoniElement {
900
912
  }
901
913
  _determineActualPlacement() {
902
914
  if (this.sheet) {
903
- this._actualPlacement = 'bottom';
915
+ this._actualPlacement = "bottom";
904
916
  return;
905
917
  }
906
918
  const rect = this.getBoundingClientRect();
907
919
  const viewport = this._getViewportMetrics();
908
- const spaceBelow = this._getDirectionalAvailableHeight('bottom', rect);
909
- const spaceAbove = this._getDirectionalAvailableHeight('top', rect);
920
+ const spaceBelow = this._getDirectionalAvailableHeight("bottom", rect);
921
+ const spaceAbove = this._getDirectionalAvailableHeight("top", rect);
910
922
  const spaceRight = viewport.right - rect.right;
911
923
  const spaceLeft = rect.left - viewport.left;
912
924
  const menuHeight = this._estimateDesiredMenuHeight();
913
925
  const menuWidth = 180;
914
926
  let preferred = this.placement;
915
- if (preferred === 'auto') {
916
- preferred = spaceBelow >= menuHeight
917
- ? 'bottom'
918
- : (spaceAbove > spaceBelow ? 'top' : 'bottom');
927
+ if (preferred === "auto") {
928
+ preferred =
929
+ spaceBelow >= menuHeight
930
+ ? "bottom"
931
+ : spaceAbove > spaceBelow
932
+ ? "top"
933
+ : "bottom";
919
934
  }
920
- if (preferred === 'top') {
921
- this._actualPlacement = spaceAbove < menuHeight && spaceBelow > spaceAbove
922
- ? 'bottom'
923
- : 'top';
935
+ if (preferred === "top") {
936
+ this._actualPlacement =
937
+ spaceAbove < menuHeight && spaceBelow > spaceAbove ? "bottom" : "top";
924
938
  }
925
- else if (preferred === 'bottom') {
926
- this._actualPlacement = spaceBelow < menuHeight && spaceAbove > spaceBelow
927
- ? 'top'
928
- : 'bottom';
939
+ else if (preferred === "bottom") {
940
+ this._actualPlacement =
941
+ spaceBelow < menuHeight && spaceAbove > spaceBelow ? "top" : "bottom";
929
942
  }
930
- else if (preferred === 'left') {
931
- this._actualPlacement = spaceLeft < menuWidth && spaceRight > spaceLeft
932
- ? 'right'
933
- : 'left';
943
+ else if (preferred === "left") {
944
+ this._actualPlacement =
945
+ spaceLeft < menuWidth && spaceRight > spaceLeft ? "right" : "left";
934
946
  }
935
- else if (preferred === 'right') {
936
- this._actualPlacement = spaceRight < menuWidth && spaceLeft > spaceRight
937
- ? 'left'
938
- : 'right';
947
+ else if (preferred === "right") {
948
+ this._actualPlacement =
949
+ spaceRight < menuWidth && spaceLeft > spaceRight ? "left" : "right";
939
950
  }
940
951
  }
941
952
  /**
@@ -952,70 +963,71 @@ let MoniSelect = class MoniSelect extends MoniElement {
952
963
  const viewport = this._getViewportMetrics();
953
964
  const constraint = this._getMenuHeightConstraint(rect);
954
965
  this._menuMaxHeight = constraint.css;
955
- const hasGroups = this._parsedOptions.some(node => node.type === 'group');
966
+ const hasGroups = this._parsedOptions.some((node) => node.type === "group");
956
967
  const estimatedRootHeight = this._parsedOptions.length * 40 + 8;
957
968
  const groupDepth = this._getGroupDepth(this._parsedOptions);
958
969
  const requiredFlyoutWidth = groupDepth * 160;
959
970
  const availableFlyoutWidth = this._getAvailableFlyoutWidth(rect);
960
971
  const lacksFlyoutSpace = viewport.width < 600 ||
961
972
  (hasGroups && availableFlyoutWidth < requiredFlyoutWidth);
962
- const needsVerticalDrilldown = hasGroups && (estimatedRootHeight > constraint.px ||
963
- this._hasOversizedGroupPanel(this._parsedOptions, constraint.px));
973
+ const needsVerticalDrilldown = hasGroups &&
974
+ (estimatedRootHeight > constraint.px ||
975
+ this._hasOversizedGroupPanel(this._parsedOptions, constraint.px));
964
976
  this._useInlineCategories = lacksFlyoutSpace || needsVerticalDrilldown;
965
- if (this.positioning !== 'fixed' && this.positioning !== 'body') {
966
- this._menuStyle = '';
977
+ if (this.positioning !== "fixed" && this.positioning !== "body") {
978
+ this._menuStyle = "";
967
979
  return;
968
980
  }
969
- let widthStyle = '';
970
- if (this.dropdownWidth === 'trigger') {
981
+ let widthStyle = "";
982
+ if (this.dropdownWidth === "trigger") {
971
983
  widthStyle = `width: ${rect.width}px;`;
972
984
  }
973
- else if (this.dropdownWidth === 'auto') {
974
- widthStyle = 'width: auto; min-width: 160px; max-width: 320px;';
985
+ else if (this.dropdownWidth === "auto") {
986
+ widthStyle = "width: auto; min-width: 160px; max-width: 320px;";
975
987
  }
976
988
  else {
977
989
  widthStyle = `width: ${this.dropdownWidth};`;
978
990
  }
979
- if (this._actualPlacement === 'top') {
980
- this._menuStyle = `
981
- position: fixed;
982
- bottom: ${window.innerHeight - rect.top}px;
983
- left: ${rect.left}px;
984
- ${widthStyle}
985
- top: auto;
986
- right: auto;
991
+ if (this._actualPlacement === "top") {
992
+ this._menuStyle = `
993
+ position: fixed;
994
+ bottom: ${window.innerHeight - rect.top}px;
995
+ left: ${rect.left}px;
996
+ ${widthStyle}
997
+ top: auto;
998
+ right: auto;
987
999
  `;
988
1000
  }
989
- else if (this._actualPlacement === 'bottom') {
990
- this._menuStyle = `
991
- position: fixed;
992
- top: ${rect.bottom}px;
993
- left: ${rect.left}px;
994
- ${widthStyle}
995
- bottom: auto;
996
- right: auto;
1001
+ else if (this._actualPlacement === "bottom") {
1002
+ this._menuStyle = `
1003
+ position: fixed;
1004
+ top: ${rect.bottom}px;
1005
+ left: ${rect.left}px;
1006
+ ${widthStyle}
1007
+ bottom: auto;
1008
+ right: auto;
997
1009
  `;
998
1010
  }
999
1011
  else {
1000
1012
  const sideTop = Math.max(viewport.top + 8, Math.min(rect.top, viewport.bottom - constraint.px - 8));
1001
- if (this._actualPlacement === 'left') {
1002
- this._menuStyle = `
1003
- position: fixed;
1004
- top: ${sideTop}px;
1005
- right: ${window.innerWidth - rect.left + 4}px;
1006
- ${widthStyle}
1007
- left: auto;
1008
- bottom: auto;
1013
+ if (this._actualPlacement === "left") {
1014
+ this._menuStyle = `
1015
+ position: fixed;
1016
+ top: ${sideTop}px;
1017
+ right: ${window.innerWidth - rect.left + 4}px;
1018
+ ${widthStyle}
1019
+ left: auto;
1020
+ bottom: auto;
1009
1021
  `;
1010
1022
  }
1011
1023
  else {
1012
- this._menuStyle = `
1013
- position: fixed;
1014
- top: ${sideTop}px;
1015
- left: ${rect.right + 4}px;
1016
- ${widthStyle}
1017
- right: auto;
1018
- bottom: auto;
1024
+ this._menuStyle = `
1025
+ position: fixed;
1026
+ top: ${sideTop}px;
1027
+ left: ${rect.right + 4}px;
1028
+ ${widthStyle}
1029
+ right: auto;
1030
+ bottom: auto;
1019
1031
  `;
1020
1032
  }
1021
1033
  }
@@ -1026,13 +1038,13 @@ let MoniSelect = class MoniSelect extends MoniElement {
1026
1038
  */
1027
1039
  _getMenuStyle() {
1028
1040
  const constraintStyle = `max-height: ${this._menuMaxHeight}; --_select-menu-max-height: ${this._menuMaxHeight};`;
1029
- if (this.positioning === 'fixed' || this.positioning === 'body') {
1041
+ if (this.positioning === "fixed" || this.positioning === "body") {
1030
1042
  return `${this._menuStyle} ${constraintStyle}`;
1031
1043
  }
1032
- if (this.dropdownWidth === 'auto') {
1044
+ if (this.dropdownWidth === "auto") {
1033
1045
  return `width: max-content; min-width: 160px; max-width: 320px; ${constraintStyle}`;
1034
1046
  }
1035
- else if (this.dropdownWidth !== 'trigger') {
1047
+ else if (this.dropdownWidth !== "trigger") {
1036
1048
  return `width: ${this.dropdownWidth}; ${constraintStyle}`;
1037
1049
  }
1038
1050
  return constraintStyle;
@@ -1055,9 +1067,9 @@ let MoniSelect = class MoniSelect extends MoniElement {
1055
1067
  const assigned = this._slot.assignedElements({ flatten: true });
1056
1068
  const tree = [];
1057
1069
  const findOrCreateGroup = (nodes, label) => {
1058
- let group = nodes.find(n => n.type === 'group' && n.label === label);
1070
+ let group = nodes.find((n) => n.type === "group" && n.label === label);
1059
1071
  if (!group) {
1060
- group = { type: 'group', label, children: [] };
1072
+ group = { type: "group", label, children: [] };
1061
1073
  nodes.push(group);
1062
1074
  }
1063
1075
  return group;
@@ -1065,9 +1077,9 @@ let MoniSelect = class MoniSelect extends MoniElement {
1065
1077
  const insertOption = (targetTree, opt, groupPath) => {
1066
1078
  let currentLevel = targetTree;
1067
1079
  if (groupPath.length > 0) {
1068
- opt.group = groupPath.join(' / ');
1080
+ opt.group = groupPath.join(" / ");
1069
1081
  }
1070
- groupPath.forEach(part => {
1082
+ groupPath.forEach((part) => {
1071
1083
  const group = findOrCreateGroup(currentLevel, part);
1072
1084
  currentLevel = group.children;
1073
1085
  });
@@ -1075,26 +1087,34 @@ let MoniSelect = class MoniSelect extends MoniElement {
1075
1087
  };
1076
1088
  const parseElement = (el, parentGroupPath) => {
1077
1089
  const tag = el.tagName.toLowerCase();
1078
- if (tag === 'option' || tag === 'moni-select-option') {
1090
+ if (tag === "option" || tag === "moni-select-option") {
1079
1091
  const opt = {
1080
- type: 'option',
1081
- value: el.getAttribute('value') || '',
1082
- label: el.textContent?.trim() || el.getAttribute('label') || el.getAttribute('value') || '',
1083
- disabled: el.hasAttribute('disabled'),
1084
- element: el
1092
+ type: "option",
1093
+ value: el.getAttribute("value") || "",
1094
+ label: el.textContent?.trim() ||
1095
+ el.getAttribute("label") ||
1096
+ el.getAttribute("value") ||
1097
+ "",
1098
+ disabled: el.hasAttribute("disabled"),
1099
+ element: el,
1085
1100
  };
1086
- const groupAttr = el.getAttribute('group');
1087
- const localPath = groupAttr ? groupAttr.split('/').map(s => s.trim()).filter(Boolean) : [];
1101
+ const groupAttr = el.getAttribute("group");
1102
+ const localPath = groupAttr
1103
+ ? groupAttr
1104
+ .split("/")
1105
+ .map((s) => s.trim())
1106
+ .filter(Boolean)
1107
+ : [];
1088
1108
  const finalPath = [...parentGroupPath, ...localPath];
1089
1109
  insertOption(tree, opt, finalPath);
1090
1110
  }
1091
- else if (tag === 'optgroup') {
1092
- const label = el.getAttribute('label') || '';
1111
+ else if (tag === "optgroup") {
1112
+ const label = el.getAttribute("label") || "";
1093
1113
  const localPath = [...parentGroupPath, label];
1094
- Array.from(el.children).forEach(child => parseElement(child, localPath));
1114
+ Array.from(el.children).forEach((child) => parseElement(child, localPath));
1095
1115
  }
1096
1116
  };
1097
- assigned.forEach(el => parseElement(el, []));
1117
+ assigned.forEach((el) => parseElement(el, []));
1098
1118
  this._parsedOptions = tree;
1099
1119
  this.requestUpdate();
1100
1120
  }
@@ -1142,10 +1162,10 @@ let MoniSelect = class MoniSelect extends MoniElement {
1142
1162
  this._activeIndex = -1;
1143
1163
  this._drilldownPath = [];
1144
1164
  // La búsqueda siempre comienza limpia, aunque exista un valor seleccionado.
1145
- this._searchQuery = '';
1165
+ this._searchQuery = "";
1146
1166
  // El evento global permite que cualquier otro select abierto se cierre,
1147
1167
  // incluso cuando la apertura vino del teclado o del icono trailing.
1148
- emitMoniEvent(this, 'moni-select-open', { detail: { item: this } });
1168
+ emitMoniEvent(this, "moni-select-open", { detail: { item: this } });
1149
1169
  this._updateMenuPosition();
1150
1170
  if (this.searchable) {
1151
1171
  // Esperamos un tick para que el input o sheet esté renderizado antes de enfocarlo.
@@ -1156,7 +1176,7 @@ let MoniSelect = class MoniSelect extends MoniElement {
1156
1176
  this._input.focus();
1157
1177
  }
1158
1178
  else if (this.sheet) {
1159
- const sheetInput = this.shadowRoot?.querySelector('.sheet-search-input');
1179
+ const sheetInput = this.shadowRoot?.querySelector(".sheet-search-input");
1160
1180
  sheetInput?.focus();
1161
1181
  }
1162
1182
  }, 50);
@@ -1170,11 +1190,11 @@ let MoniSelect = class MoniSelect extends MoniElement {
1170
1190
  if (!this._open)
1171
1191
  return;
1172
1192
  this._open = false;
1173
- this._searchQuery = '';
1193
+ this._searchQuery = "";
1174
1194
  this._hideBodyPopover();
1175
1195
  }
1176
1196
  _findOptionByValue(value) {
1177
- return this._getFlatOptions(this._parsedOptions).find(opt => opt.value === value);
1197
+ return this._getFlatOptions(this._parsedOptions).find((opt) => opt.value === value);
1178
1198
  }
1179
1199
  /**
1180
1200
  * Evento de input (tecleo) en la barra de búsqueda.
@@ -1191,13 +1211,15 @@ let MoniSelect = class MoniSelect extends MoniElement {
1191
1211
  this._openDropdown();
1192
1212
  this._searchQuery = query;
1193
1213
  this._activeIndex = -1;
1194
- if (this.clearable && query.trim() === '') {
1195
- this.value = '';
1196
- emitMoniEvent(this, 'moni-change', { detail: { value: this.value, originalEvent: e } });
1214
+ if (this.clearable && query.trim() === "") {
1215
+ this.value = "";
1216
+ emitMoniEvent(this, "moni-change", {
1217
+ detail: { value: this.value, originalEvent: e },
1218
+ });
1197
1219
  return;
1198
1220
  }
1199
1221
  const flat = this._getFlatOptions(this._parsedOptions);
1200
- const exactMatch = flat.find(opt => opt.label.toLowerCase() === query.trim().toLowerCase());
1222
+ const exactMatch = flat.find((opt) => opt.label.toLowerCase() === query.trim().toLowerCase());
1201
1223
  if (exactMatch && !exactMatch.disabled) {
1202
1224
  this._selectOption(exactMatch);
1203
1225
  }
@@ -1212,9 +1234,9 @@ let MoniSelect = class MoniSelect extends MoniElement {
1212
1234
  return;
1213
1235
  this.value = option.value;
1214
1236
  this._closeDropdown();
1215
- this.dispatchEvent(new Event('input', { bubbles: true, composed: true }));
1216
- this.dispatchEvent(new Event('change', { bubbles: true, composed: true }));
1217
- emitMoniEvent(this, 'moni-change', { detail: { value: this.value } });
1237
+ this.dispatchEvent(new Event("input", { bubbles: true, composed: true }));
1238
+ this.dispatchEvent(new Event("change", { bubbles: true, composed: true }));
1239
+ emitMoniEvent(this, "moni-change", { detail: { value: this.value } });
1218
1240
  }
1219
1241
  /**
1220
1242
  * Maneja el Hover sobre categorías en modo Desktop (Submenús emergentes).
@@ -1224,7 +1246,7 @@ let MoniSelect = class MoniSelect extends MoniElement {
1224
1246
  */
1225
1247
  _onSubmenuMouseEnter(e) {
1226
1248
  const headerEl = e.currentTarget;
1227
- const submenu = headerEl.querySelector(':scope > .submenu');
1249
+ const submenu = headerEl.querySelector(":scope > .submenu");
1228
1250
  if (!submenu)
1229
1251
  return;
1230
1252
  const rect = headerEl.getBoundingClientRect();
@@ -1232,12 +1254,12 @@ let MoniSelect = class MoniSelect extends MoniElement {
1232
1254
  const spaceOnLeft = rect.left;
1233
1255
  const submenuWidth = 160;
1234
1256
  if (spaceOnRight < submenuWidth && spaceOnLeft > spaceOnRight) {
1235
- submenu.classList.remove('open-right');
1236
- submenu.classList.add('open-left');
1257
+ submenu.classList.remove("open-right");
1258
+ submenu.classList.add("open-left");
1237
1259
  }
1238
1260
  else {
1239
- submenu.classList.remove('open-left');
1240
- submenu.classList.add('open-right');
1261
+ submenu.classList.remove("open-left");
1262
+ submenu.classList.add("open-right");
1241
1263
  }
1242
1264
  }
1243
1265
  /**
@@ -1249,7 +1271,7 @@ let MoniSelect = class MoniSelect extends MoniElement {
1249
1271
  return;
1250
1272
  // Obtenemos solo las opciones que están visualmente disponibles en la jerarquía actual
1251
1273
  const visible = this._getVisibleOptions();
1252
- if (e.key === 'ArrowDown') {
1274
+ if (e.key === "ArrowDown") {
1253
1275
  e.preventDefault();
1254
1276
  if (!this._open) {
1255
1277
  // Si está cerrado, ArrowDown lo abre (comportamiento estándar nativo)
@@ -1261,15 +1283,16 @@ let MoniSelect = class MoniSelect extends MoniElement {
1261
1283
  this._scrollToActive();
1262
1284
  }
1263
1285
  }
1264
- else if (e.key === 'ArrowUp') {
1286
+ else if (e.key === "ArrowUp") {
1265
1287
  e.preventDefault();
1266
1288
  if (this._open && visible.length > 0) {
1267
1289
  // Navegamos circularmente hacia arriba (+visible.length evita valores negativos en JS)
1268
- this._activeIndex = (this._activeIndex - 1 + visible.length) % visible.length;
1290
+ this._activeIndex =
1291
+ (this._activeIndex - 1 + visible.length) % visible.length;
1269
1292
  this._scrollToActive();
1270
1293
  }
1271
1294
  }
1272
- else if (e.key === 'Enter') {
1295
+ else if (e.key === "Enter") {
1273
1296
  e.preventDefault();
1274
1297
  if (this._open) {
1275
1298
  // Si está abierto y hay una opción resaltada, simulamos el click para seleccionarla
@@ -1282,7 +1305,7 @@ let MoniSelect = class MoniSelect extends MoniElement {
1282
1305
  this._openDropdown();
1283
1306
  }
1284
1307
  }
1285
- else if (e.key === 'Escape') {
1308
+ else if (e.key === "Escape") {
1286
1309
  e.preventDefault();
1287
1310
  // Escapa el menú sin hacer ninguna selección
1288
1311
  this._closeDropdown();
@@ -1294,9 +1317,9 @@ let MoniSelect = class MoniSelect extends MoniElement {
1294
1317
  _scrollToActive() {
1295
1318
  // Se requiere setTimeout para darle tiempo a Lit a renderizar la clase 'active-nav'
1296
1319
  setTimeout(() => {
1297
- const activeEl = this.shadowRoot?.querySelector('.option-item.active-nav');
1320
+ const activeEl = this.shadowRoot?.querySelector(".option-item.active-nav");
1298
1321
  if (activeEl) {
1299
- activeEl.scrollIntoView({ block: 'nearest' });
1322
+ activeEl.scrollIntoView({ block: "nearest" });
1300
1323
  }
1301
1324
  }, 0);
1302
1325
  }
@@ -1307,7 +1330,7 @@ let MoniSelect = class MoniSelect extends MoniElement {
1307
1330
  _getFlatOptions(nodes) {
1308
1331
  const flat = [];
1309
1332
  const traverse = (n) => {
1310
- if (n.type === 'option') {
1333
+ if (n.type === "option") {
1311
1334
  flat.push(n);
1312
1335
  }
1313
1336
  else {
@@ -1322,7 +1345,8 @@ let MoniSelect = class MoniSelect extends MoniElement {
1322
1345
  if (!this._searchQuery)
1323
1346
  return flat;
1324
1347
  const query = this._searchQuery.toLowerCase();
1325
- return flat.filter(opt => opt.label.toLowerCase().includes(query) || opt.value.toLowerCase().includes(query));
1348
+ return flat.filter((opt) => opt.label.toLowerCase().includes(query) ||
1349
+ opt.value.toLowerCase().includes(query));
1326
1350
  }
1327
1351
  _getVisibleOptions() {
1328
1352
  const filtered = this._getFilteredOptions();
@@ -1331,9 +1355,9 @@ let MoniSelect = class MoniSelect extends MoniElement {
1331
1355
  if (this.sheet || this._useInlineCategories) {
1332
1356
  if (this._drilldownPath.length > 0) {
1333
1357
  const activeGroup = this._drilldownPath[this._drilldownPath.length - 1];
1334
- return activeGroup.children.filter(n => n.type === 'option');
1358
+ return activeGroup.children.filter((n) => n.type === "option");
1335
1359
  }
1336
- return this._parsedOptions.filter(n => n.type === 'option');
1360
+ return this._parsedOptions.filter((n) => n.type === "option");
1337
1361
  }
1338
1362
  return filtered;
1339
1363
  }
@@ -1346,26 +1370,35 @@ let MoniSelect = class MoniSelect extends MoniElement {
1346
1370
  */
1347
1371
  _renderRootList() {
1348
1372
  let visibleIndex = 0;
1349
- return this._parsedOptions.map(node => {
1350
- if (node.type === 'option') {
1373
+ return this._parsedOptions.map((node) => {
1374
+ if (node.type === "option") {
1351
1375
  const currentIdx = visibleIndex++;
1352
1376
  const isSelected = node.value === this.value;
1353
1377
  const isActiveNav = this._drilldownPath.length === 0 && currentIdx === this._activeIndex;
1354
- return html `
1355
- <li
1356
- class="option-item ${isSelected ? 'selected' : ''} ${isActiveNav ? 'active-nav' : ''} ${node.disabled ? 'disabled' : ''}"
1357
- @click=${() => this._selectOption(node)}
1358
- >
1359
- ${node.label}
1360
- </li>
1361
- `;
1378
+ return html `
1379
+ <li
1380
+ class="option-item ${isSelected ? "selected" : ""} ${isActiveNav ? "active-nav" : ""} ${node.disabled ? "disabled" : ""}"
1381
+ @click=${() => this._selectOption(node)}
1382
+ >
1383
+ ${node.label}
1384
+ </li>
1385
+ `;
1362
1386
  }
1363
- return html `
1364
- <li class="group-header" @click=${(e) => { e.stopPropagation(); this._drilldownPath = [...this._drilldownPath, node]; }}>
1365
- <span>${node.label}</span>
1366
- <moni-icon name="chevron_right" style="margin-inline-start: auto; font-size: 1.125rem;"></moni-icon>
1367
- </li>
1368
- `;
1387
+ return html `
1388
+ <li
1389
+ class="group-header"
1390
+ @click=${(e) => {
1391
+ e.stopPropagation();
1392
+ this._drilldownPath = [...this._drilldownPath, node];
1393
+ }}
1394
+ >
1395
+ <span>${node.label}</span>
1396
+ <moni-icon
1397
+ name="chevron_right"
1398
+ style="margin-inline-start: auto; font-size: 1.125rem;"
1399
+ ></moni-icon>
1400
+ </li>
1401
+ `;
1369
1402
  });
1370
1403
  }
1371
1404
  /**
@@ -1380,63 +1413,84 @@ let MoniSelect = class MoniSelect extends MoniElement {
1380
1413
  return nothing;
1381
1414
  const activeGroup = this._drilldownPath[this._drilldownPath.length - 1];
1382
1415
  let visibleIndex = 0;
1383
- return html `
1384
- <li class="group-header" @click=${(e) => { e.stopPropagation(); this._drilldownPath = this._drilldownPath.slice(0, -1); }}>
1385
- <moni-icon name="arrow_back" style="font-size: 1.25rem; margin-inline-end: 8px;"></moni-icon>
1386
- <span>Regresar</span>
1387
- </li>
1388
- <li class="group-header-flat">${activeGroup.label}</li>
1389
- ${activeGroup.children.map(node => {
1390
- if (node.type === 'option') {
1416
+ return html `
1417
+ <li
1418
+ class="group-header"
1419
+ @click=${(e) => {
1420
+ e.stopPropagation();
1421
+ this._drilldownPath = this._drilldownPath.slice(0, -1);
1422
+ }}
1423
+ >
1424
+ <moni-icon
1425
+ name="arrow_back"
1426
+ style="font-size: 1.25rem; margin-inline-end: 8px;"
1427
+ ></moni-icon>
1428
+ <span>Regresar</span>
1429
+ </li>
1430
+ <li class="group-header-flat">${activeGroup.label}</li>
1431
+ ${activeGroup.children.map((node) => {
1432
+ if (node.type === "option") {
1391
1433
  const currentIdx = visibleIndex++;
1392
1434
  const isSelected = node.value === this.value;
1393
1435
  const isActiveNav = this._drilldownPath.length > 0 && currentIdx === this._activeIndex;
1394
- return html `
1395
- <li
1396
- class="option-item ${isSelected ? 'selected' : ''} ${isActiveNav ? 'active-nav' : ''} ${node.disabled ? 'disabled' : ''}"
1397
- @click=${() => this._selectOption(node)}
1398
- >
1399
- ${node.label}
1400
- </li>
1401
- `;
1436
+ return html `
1437
+ <li
1438
+ class="option-item ${isSelected ? "selected" : ""} ${isActiveNav ? "active-nav" : ""} ${node.disabled ? "disabled" : ""}"
1439
+ @click=${() => this._selectOption(node)}
1440
+ >
1441
+ ${node.label}
1442
+ </li>
1443
+ `;
1402
1444
  }
1403
- return html `
1404
- <li class="group-header" @click=${(e) => { e.stopPropagation(); this._drilldownPath = [...this._drilldownPath, node]; }}>
1405
- <span>${node.label}</span>
1406
- <moni-icon name="chevron_right" style="margin-inline-start: auto; font-size: 1.125rem;"></moni-icon>
1407
- </li>
1408
- `;
1409
- })}
1410
- `;
1445
+ return html `
1446
+ <li
1447
+ class="group-header"
1448
+ @click=${(e) => {
1449
+ e.stopPropagation();
1450
+ this._drilldownPath = [...this._drilldownPath, node];
1451
+ }}
1452
+ >
1453
+ <span>${node.label}</span>
1454
+ <moni-icon
1455
+ name="chevron_right"
1456
+ style="margin-inline-start: auto; font-size: 1.125rem;"
1457
+ ></moni-icon>
1458
+ </li>
1459
+ `;
1460
+ })}
1461
+ `;
1411
1462
  }
1412
1463
  _renderDesktopNode(node, flatIndexRef) {
1413
- if (node.type === 'option') {
1464
+ if (node.type === "option") {
1414
1465
  const currentIdx = flatIndexRef.value++;
1415
1466
  const isSelected = node.value === this.value;
1416
1467
  const isActiveNav = currentIdx === this._activeIndex;
1417
- return html `
1418
- <li
1419
- class="option-item ${isSelected ? 'selected' : ''} ${isActiveNav ? 'active-nav' : ''} ${node.disabled ? 'disabled' : ''}"
1420
- @click=${() => this._selectOption(node)}
1421
- >
1422
- ${node.label}
1423
- </li>
1424
- `;
1468
+ return html `
1469
+ <li
1470
+ class="option-item ${isSelected ? "selected" : ""} ${isActiveNav ? "active-nav" : ""} ${node.disabled ? "disabled" : ""}"
1471
+ @click=${() => this._selectOption(node)}
1472
+ >
1473
+ ${node.label}
1474
+ </li>
1475
+ `;
1425
1476
  }
1426
- return html `
1427
- <li
1428
- class="group-header"
1429
- @mouseenter=${this._onSubmenuMouseEnter}
1430
- @click=${(e) => e.stopPropagation()}
1431
- >
1432
- <span>${node.label}</span>
1433
- <moni-icon name="chevron_right" style="margin-inline-start: auto; font-size: 1.125rem;"></moni-icon>
1434
-
1435
- <ul class="submenu active open-right">
1436
- ${node.children.map(child => this._renderDesktopNode(child, flatIndexRef))}
1437
- </ul>
1438
- </li>
1439
- `;
1477
+ return html `
1478
+ <li
1479
+ class="group-header"
1480
+ @mouseenter=${this._onSubmenuMouseEnter}
1481
+ @click=${(e) => e.stopPropagation()}
1482
+ >
1483
+ <span>${node.label}</span>
1484
+ <moni-icon
1485
+ name="chevron_right"
1486
+ style="margin-inline-start: auto; font-size: 1.125rem;"
1487
+ ></moni-icon>
1488
+
1489
+ <ul class="submenu active open-right">
1490
+ ${node.children.map((child) => this._renderDesktopNode(child, flatIndexRef))}
1491
+ </ul>
1492
+ </li>
1493
+ `;
1440
1494
  }
1441
1495
  /**
1442
1496
  * Orquestador principal de renderizado de la lista de opciones.
@@ -1452,48 +1506,54 @@ let MoniSelect = class MoniSelect extends MoniElement {
1452
1506
  }
1453
1507
  if (this._searchQuery) {
1454
1508
  const groups = {};
1455
- filtered.forEach(opt => {
1456
- const gName = opt.group || '';
1509
+ filtered.forEach((opt) => {
1510
+ const gName = opt.group || "";
1457
1511
  if (!groups[gName])
1458
1512
  groups[gName] = [];
1459
1513
  groups[gName].push(opt);
1460
1514
  });
1461
1515
  let flatIndex = 0;
1462
- return Object.entries(groups).map(([groupName, groupOpts]) => html `
1463
- ${groupName ? html `<li class="group-header-flat">${groupName}</li>` : nothing}
1464
- ${groupOpts.map(opt => {
1516
+ return Object.entries(groups).map(([groupName, groupOpts]) => html `
1517
+ ${groupName ? html `<li class="group-header-flat">${groupName}</li>` : nothing}
1518
+ ${groupOpts.map((opt) => {
1465
1519
  const currentIdx = flatIndex++;
1466
1520
  const isSelected = opt.value === this.value;
1467
1521
  const isActiveNav = currentIdx === this._activeIndex;
1468
- return html `
1469
- <li
1470
- class="option-item ${isSelected ? 'selected' : ''} ${isActiveNav ? 'active-nav' : ''} ${opt.disabled ? 'disabled' : ''}"
1471
- @click=${() => this._selectOption(opt)}
1472
- >
1473
- ${opt.label}
1474
- </li>
1475
- `;
1476
- })}
1477
- `);
1522
+ return html `
1523
+ <li
1524
+ class="option-item ${isSelected ? "selected" : ""} ${isActiveNav ? "active-nav" : ""} ${opt.disabled ? "disabled" : ""}"
1525
+ @click=${() => this._selectOption(opt)}
1526
+ >
1527
+ ${opt.label}
1528
+ </li>
1529
+ `;
1530
+ })}
1531
+ `);
1478
1532
  }
1479
1533
  if (this.sheet || this._useInlineCategories) {
1480
1534
  const isRootActive = this._drilldownPath.length === 0;
1481
1535
  const isSubActive = !isRootActive;
1482
- return html `
1483
- <div class="drilldown-wrapper">
1484
- <div class="drilldown-track ${this._drilldownPath.length > 0 ? 'slide-active' : ''}">
1485
- <ul class="drilldown-panel ${isRootActive ? 'panel-active' : 'panel-inactive'}">
1486
- ${this._renderRootList()}
1487
- </ul>
1488
- <ul class="drilldown-panel ${isSubActive ? 'panel-active' : 'panel-inactive'}">
1489
- ${this._renderSubcategoryList()}
1490
- </ul>
1491
- </div>
1492
- </div>
1493
- `;
1536
+ return html `
1537
+ <div class="drilldown-wrapper">
1538
+ <div
1539
+ class="drilldown-track ${this._drilldownPath.length > 0 ? "slide-active" : ""}"
1540
+ >
1541
+ <ul
1542
+ class="drilldown-panel ${isRootActive ? "panel-active" : "panel-inactive"}"
1543
+ >
1544
+ ${this._renderRootList()}
1545
+ </ul>
1546
+ <ul
1547
+ class="drilldown-panel ${isSubActive ? "panel-active" : "panel-inactive"}"
1548
+ >
1549
+ ${this._renderSubcategoryList()}
1550
+ </ul>
1551
+ </div>
1552
+ </div>
1553
+ `;
1494
1554
  }
1495
1555
  const flatIndexRef = { value: 0 };
1496
- return this._parsedOptions.map(node => this._renderDesktopNode(node, flatIndexRef));
1556
+ return this._parsedOptions.map((node) => this._renderDesktopNode(node, flatIndexRef));
1497
1557
  }
1498
1558
  /**
1499
1559
  * Ensambla el Shadow DOM del campo select, coordinando dos modos de interfaz de usuario distintos.
@@ -1531,125 +1591,135 @@ let MoniSelect = class MoniSelect extends MoniElement {
1531
1591
  const selectedOpt = this._findOptionByValue(this.value);
1532
1592
  const displayValue = this._open && this.searchable && !this.sheet
1533
1593
  ? this._searchQuery
1534
- : (selectedOpt ? selectedOpt.label : '');
1594
+ : selectedOpt
1595
+ ? selectedOpt.label
1596
+ : "";
1535
1597
  const isActive = Boolean(displayValue || this.placeholder);
1536
1598
  const fieldClasses = {
1537
1599
  field: true,
1538
1600
  label: Boolean(this.label),
1539
- fill: this.variant === 'filled',
1540
- border: this.variant === 'outlined',
1541
- small: this.size === 'small',
1542
- large: this.size === 'large',
1543
- extra: this.size === 'extra',
1601
+ fill: this.variant === "filled",
1602
+ border: this.variant === "outlined",
1603
+ small: this.size === "small",
1604
+ large: this.size === "large",
1605
+ extra: this.size === "extra",
1544
1606
  prefix: hasLeading,
1545
1607
  suffix: true,
1546
1608
  invalid: this.error,
1547
- round: this.shape === 'round',
1548
- 'small-round': this.shape === 'small-round',
1549
- square: this.shape === 'no-round'
1609
+ round: this.shape === "round",
1610
+ "small-round": this.shape === "small-round",
1611
+ square: this.shape === "no-round",
1550
1612
  };
1551
1613
  const leading = this.icon
1552
- ? html `<i class="leading-icon" part="leading-icon"
1553
- ><moni-icon name="${this.icon}"></moni-icon
1554
- ></i>`
1614
+ ? html `<i class="leading-icon" part="leading-icon"
1615
+ ><moni-icon name="${this.icon}"></moni-icon
1616
+ ></i>`
1555
1617
  : nothing;
1556
1618
  const trailing = this.loading
1557
- ? html `<i class="trailing-icon" part="trailing-icon"
1558
- ><moni-progress
1559
- variant="circular"
1560
- indeterminate
1561
- size="small"
1562
- style="inline-size: 1.25rem; block-size: 1.25rem; color: currentColor;"
1563
- ></moni-progress
1564
- ></i>`
1565
- : html `<i class="trailing-icon" part="trailing-icon" @click=${this._toggleDropdown}
1566
- ><moni-icon name="${this.trailingIcon}"></moni-icon
1567
- ></i>`;
1568
- const hasGroups = this._parsedOptions.some(node => node.type === 'group');
1619
+ ? html `<i class="trailing-icon" part="trailing-icon"
1620
+ ><moni-progress
1621
+ variant="circular"
1622
+ indeterminate
1623
+ size="small"
1624
+ style="inline-size: 1.25rem; block-size: 1.25rem; color: currentColor;"
1625
+ ></moni-progress
1626
+ ></i>`
1627
+ : html `<i
1628
+ class="trailing-icon"
1629
+ part="trailing-icon"
1630
+ @click=${this._toggleDropdown}
1631
+ ><moni-icon name="${this.trailingIcon}"></moni-icon
1632
+ ></i>`;
1633
+ const hasGroups = this._parsedOptions.some((node) => node.type === "group");
1569
1634
  const usesFlyoutSubmenus = hasGroups && !this._searchQuery && !this._useInlineCategories;
1570
1635
  const menuClasses = {
1571
- 'dropdown-menu': true,
1636
+ "dropdown-menu": true,
1572
1637
  open: this._open,
1573
1638
  scrollable: !usesFlyoutSubmenus,
1574
1639
  searching: Boolean(this._searchQuery),
1575
- 'inline-categories': this._useInlineCategories,
1576
- 'placement-top': this._actualPlacement === 'top',
1577
- 'placement-bottom': this._actualPlacement === 'bottom',
1578
- 'placement-left': this._actualPlacement === 'left',
1579
- 'placement-right': this._actualPlacement === 'right'
1640
+ "inline-categories": this._useInlineCategories,
1641
+ "placement-top": this._actualPlacement === "top",
1642
+ "placement-bottom": this._actualPlacement === "bottom",
1643
+ "placement-left": this._actualPlacement === "left",
1644
+ "placement-right": this._actualPlacement === "right",
1580
1645
  };
1581
- return html `<div class=${classMap(fieldClasses)} part="field">
1582
- ${leading}
1583
- <input
1584
- id="input"
1585
- type="text"
1586
- part="input"
1587
- .value=${displayValue}
1588
- ?readonly=${!this.searchable || this.sheet}
1589
- ?disabled=${this.disabled}
1590
- inputmode=${ifDefined(!this.searchable || this.sheet ? 'none' : undefined)}
1591
- placeholder=${this.placeholder || ''}
1592
- class=${isActive ? 'active' : ''}
1593
- @click=${this._onInputClick}
1594
- @input=${this._onSearchInput}
1595
- @keydown=${this._onKeyDown}
1596
- />
1597
- ${this.label
1598
- ? html `<label
1599
- for="input"
1600
- part="label"
1601
- class=${classMap({ active: isActive })}
1602
- >${this.label}</label
1603
- >`
1604
- : nothing}
1605
- ${trailing}
1606
-
1607
- ${this.sheet
1608
- ? html `
1609
- <div class="sheet-backdrop ${this._open ? 'open' : ''}" @click=${this._closeDropdown}>
1610
- <div class="sheet-drawer ${this._open ? 'open' : ''}" @click=${(e) => e.stopPropagation()}>
1611
- <div class="sheet-handle"></div>
1612
- ${this.label ? html `<div class="sheet-title">${this.label}</div>` : nothing}
1613
- ${this.searchable
1614
- ? html `
1615
- <div class="sheet-search-wrapper">
1616
- <input
1617
- type="text"
1618
- class="sheet-search-input"
1619
- .value=${this._searchQuery}
1620
- placeholder="Buscar..."
1621
- @input=${this._onSearchInput}
1622
- />
1623
- </div>
1624
- `
1625
- : nothing}
1626
- <ul class="sheet-options-list">
1627
- ${this._renderOptionsList(filtered)}
1628
- </ul>
1629
- </div>
1630
- </div>
1631
- `
1632
- : html `
1633
- <ul
1634
- class=${classMap(menuClasses)}
1635
- part="menu"
1636
- popover=${this.positioning === 'body' ? 'manual' : nothing}
1637
- style=${this._getMenuStyle()}
1638
- >
1639
- ${this._renderOptionsList(filtered)}
1640
- </ul>
1641
- `}
1642
-
1643
- <slot style="display: none;" @slotchange=${this._onSlotChange}></slot>
1644
-
1645
- ${this.error
1646
- ? html `<output part="helper" class="invalid"
1647
- >${this.errorText || this.helper}</output
1648
- >`
1646
+ return html `<div class=${classMap(fieldClasses)} part="field">
1647
+ ${leading}
1648
+ <input
1649
+ id="input"
1650
+ type="text"
1651
+ part="input"
1652
+ .value=${displayValue}
1653
+ ?readonly=${!this.searchable || this.sheet}
1654
+ ?disabled=${this.disabled}
1655
+ inputmode=${ifDefined(!this.searchable || this.sheet ? "none" : undefined)}
1656
+ placeholder=${this.placeholder || ""}
1657
+ class=${isActive ? "active" : ""}
1658
+ @click=${this._onInputClick}
1659
+ @input=${this._onSearchInput}
1660
+ @keydown=${this._onKeyDown}
1661
+ />
1662
+ ${this.label
1663
+ ? html `<label
1664
+ for="input"
1665
+ part="label"
1666
+ class=${classMap({ active: isActive })}
1667
+ >${this.label}</label
1668
+ >`
1669
+ : nothing}
1670
+ ${trailing}
1671
+ ${this.sheet
1672
+ ? html `
1673
+ <div
1674
+ class="sheet-backdrop ${this._open ? "open" : ""}"
1675
+ @click=${this._closeDropdown}
1676
+ >
1677
+ <div
1678
+ class="sheet-drawer ${this._open ? "open" : ""}"
1679
+ @click=${(e) => e.stopPropagation()}
1680
+ >
1681
+ <div class="sheet-handle"></div>
1682
+ ${this.label ? html `<div class="sheet-title">${this.label}</div>` : nothing}
1683
+ ${this.searchable
1684
+ ? html `
1685
+ <div class="sheet-search-wrapper">
1686
+ <input
1687
+ type="text"
1688
+ class="sheet-search-input"
1689
+ .value=${this._searchQuery}
1690
+ placeholder="Buscar..."
1691
+ @input=${this._onSearchInput}
1692
+ />
1693
+ </div>
1694
+ `
1695
+ : nothing}
1696
+ <ul class="sheet-options-list">
1697
+ ${this._renderOptionsList(filtered)}
1698
+ </ul>
1699
+ </div>
1700
+ </div>
1701
+ `
1702
+ : html `
1703
+ <ul
1704
+ class=${classMap(menuClasses)}
1705
+ part="menu"
1706
+ popover=${this.positioning === "body" ? "manual" : nothing}
1707
+ style=${this._getMenuStyle()}
1708
+ >
1709
+ ${this._renderOptionsList(filtered)}
1710
+ </ul>
1711
+ `}
1712
+
1713
+ <slot style="display: none;" @slotchange=${this._onSlotChange}></slot>
1714
+
1715
+ ${this.error
1716
+ ? html `<output part="helper" class="invalid"
1717
+ >${this.errorText || this.helper}</output
1718
+ >`
1649
1719
  : this.helper
1650
1720
  ? html `<output part="helper">${this.helper}</output>`
1651
- : nothing}
1652
- </div>`;
1721
+ : nothing}
1722
+ </div>`;
1653
1723
  }
1654
1724
  };
1655
1725
  __decorate([
@@ -1680,7 +1750,7 @@ __decorate([
1680
1750
  property({ reflect: true })
1681
1751
  ], MoniSelect.prototype, "helper", void 0);
1682
1752
  __decorate([
1683
- property({ reflect: true, attribute: 'error-text' })
1753
+ property({ reflect: true, attribute: "error-text" })
1684
1754
  ], MoniSelect.prototype, "errorText", void 0);
1685
1755
  __decorate([
1686
1756
  property({ type: Boolean, reflect: true })
@@ -1692,7 +1762,7 @@ __decorate([
1692
1762
  property({ reflect: true })
1693
1763
  ], MoniSelect.prototype, "icon", void 0);
1694
1764
  __decorate([
1695
- property({ reflect: true, attribute: 'trailing-icon' })
1765
+ property({ reflect: true, attribute: "trailing-icon" })
1696
1766
  ], MoniSelect.prototype, "trailingIcon", void 0);
1697
1767
  __decorate([
1698
1768
  property({ type: Boolean, reflect: true })
@@ -1713,10 +1783,10 @@ __decorate([
1713
1783
  property({ reflect: true })
1714
1784
  ], MoniSelect.prototype, "placement", void 0);
1715
1785
  __decorate([
1716
- property({ reflect: true, attribute: 'dropdown-width' })
1786
+ property({ reflect: true, attribute: "dropdown-width" })
1717
1787
  ], MoniSelect.prototype, "dropdownWidth", void 0);
1718
1788
  __decorate([
1719
- property({ reflect: true, attribute: 'dropdown-max-height' })
1789
+ property({ reflect: true, attribute: "dropdown-max-height" })
1720
1790
  ], MoniSelect.prototype, "dropdownMaxHeight", void 0);
1721
1791
  __decorate([
1722
1792
  state()
@@ -1746,16 +1816,16 @@ __decorate([
1746
1816
  state()
1747
1817
  ], MoniSelect.prototype, "_drilldownPath", void 0);
1748
1818
  __decorate([
1749
- query('slot')
1819
+ query("slot")
1750
1820
  ], MoniSelect.prototype, "_slot", void 0);
1751
1821
  __decorate([
1752
- query('input')
1822
+ query("input")
1753
1823
  ], MoniSelect.prototype, "_input", void 0);
1754
1824
  __decorate([
1755
- query('.dropdown-menu')
1825
+ query(".dropdown-menu")
1756
1826
  ], MoniSelect.prototype, "_menu", void 0);
1757
1827
  MoniSelect = __decorate([
1758
- customElement('moni-select')
1828
+ customElement("moni-select")
1759
1829
  ], MoniSelect);
1760
1830
  export { MoniSelect };
1761
1831
  export default MoniSelect;