@helixui/library 2.1.2-next.47 → 2.1.2-next.49

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 (87) hide show
  1. package/custom-elements.json +5 -5
  2. package/dist/components/hx-breadcrumb/hx-breadcrumb.d.ts.map +1 -1
  3. package/dist/components/hx-breadcrumb/index.js +1 -1
  4. package/dist/components/hx-checkbox/index.js +1 -1
  5. package/dist/components/hx-clinical-status/hx-clinical-status.d.ts +7 -0
  6. package/dist/components/hx-clinical-status/hx-clinical-status.d.ts.map +1 -1
  7. package/dist/components/hx-clinical-status/index.js +1 -1
  8. package/dist/components/hx-code-snippet/hx-code-snippet.d.ts +3 -2
  9. package/dist/components/hx-code-snippet/hx-code-snippet.d.ts.map +1 -1
  10. package/dist/components/hx-code-snippet/index.js +1 -1
  11. package/dist/components/hx-color-picker/hx-color-picker.d.ts +6 -10
  12. package/dist/components/hx-color-picker/hx-color-picker.d.ts.map +1 -1
  13. package/dist/components/hx-color-picker/hx-color-picker.styles.d.ts.map +1 -1
  14. package/dist/components/hx-color-picker/index.js +1 -1
  15. package/dist/components/hx-container/hx-container.styles.d.ts.map +1 -1
  16. package/dist/components/hx-container/index.js +1 -1
  17. package/dist/components/hx-link/hx-link.d.ts +2 -0
  18. package/dist/components/hx-link/hx-link.d.ts.map +1 -1
  19. package/dist/components/hx-link/index.js +1 -1
  20. package/dist/components/hx-patient-banner/hx-patient-banner.d.ts.map +1 -1
  21. package/dist/components/hx-progress-ring/index.js +1 -1
  22. package/dist/components/hx-select/hx-select.styles.d.ts.map +1 -1
  23. package/dist/components/hx-select/index.js +1 -1
  24. package/dist/components/hx-skeleton/hx-skeleton.d.ts +1 -1
  25. package/dist/components/hx-skeleton/index.js +1 -1
  26. package/dist/components/hx-spinner/index.js +1 -1
  27. package/dist/components/hx-style-scope/hx-style-scope.d.ts +2 -2
  28. package/dist/components/hx-style-scope/hx-style-scope.d.ts.map +1 -1
  29. package/dist/components/hx-text-input/index.js +1 -1
  30. package/dist/css/helix-all.css +9 -17
  31. package/dist/css/helix-core.css +5 -5
  32. package/dist/css/helix-feedback.css +3 -3
  33. package/dist/css/helix-forms.css +1 -3
  34. package/dist/css/helix-layout.css +0 -6
  35. package/dist/css/hx-color-picker.css +1 -1
  36. package/dist/css/hx-container.css +0 -6
  37. package/dist/css/hx-link.css +1 -1
  38. package/dist/css/hx-progress-ring.css +3 -3
  39. package/dist/css/hx-select.css +0 -2
  40. package/dist/css/hx-skeleton.css +1 -1
  41. package/dist/css/hx-spinner.css +3 -3
  42. package/dist/css/index.css +1 -1
  43. package/dist/css/manifest.json +2 -2
  44. package/dist/index.js +16 -15
  45. package/dist/index.js.map +1 -1
  46. package/dist/shared/{id-counter-JhvVCnjh.js → helix-element-CZvaIEQP.js} +19 -31
  47. package/dist/shared/helix-element-CZvaIEQP.js.map +1 -0
  48. package/dist/shared/{hx-breadcrumb-item-DzLyeL5Z.js → hx-breadcrumb-item-jLAKK038.js} +2 -2
  49. package/dist/shared/hx-breadcrumb-item-jLAKK038.js.map +1 -0
  50. package/dist/shared/{hx-checkbox-CTEZ9IFq.js → hx-checkbox-C82GjRXe.js} +6 -5
  51. package/dist/shared/{hx-checkbox-CTEZ9IFq.js.map → hx-checkbox-C82GjRXe.js.map} +1 -1
  52. package/dist/shared/{hx-clinical-status-m4soOOwg.js → hx-clinical-status-BjtT5c0M.js} +24 -23
  53. package/dist/shared/hx-clinical-status-BjtT5c0M.js.map +1 -0
  54. package/dist/shared/{hx-code-snippet-CoLYvX1Z.js → hx-code-snippet-DcVENSuC.js} +6 -5
  55. package/dist/shared/hx-code-snippet-DcVENSuC.js.map +1 -0
  56. package/dist/shared/{hx-color-picker-DhOaNe6-.js → hx-color-picker-C6EIuS9t.js} +47 -46
  57. package/dist/shared/hx-color-picker-C6EIuS9t.js.map +1 -0
  58. package/dist/shared/{hx-container-31QT9KV_.js → hx-container-BwWbMPTH.js} +5 -11
  59. package/dist/shared/hx-container-BwWbMPTH.js.map +1 -0
  60. package/dist/shared/{hx-link-B8IwUMSc.js → hx-link-CN7AvGOW.js} +29 -24
  61. package/dist/shared/hx-link-CN7AvGOW.js.map +1 -0
  62. package/dist/shared/hx-patient-banner-BKiN7nIE.js.map +1 -1
  63. package/dist/shared/{hx-progress-ring-BJeiDr3q.js → hx-progress-ring-Cs0WgWDJ.js} +4 -4
  64. package/dist/shared/hx-progress-ring-Cs0WgWDJ.js.map +1 -0
  65. package/dist/shared/{hx-select-B5wq9Swh.js → hx-select-CgcgsHU5.js} +3 -4
  66. package/dist/shared/hx-select-CgcgsHU5.js.map +1 -0
  67. package/dist/shared/{hx-skeleton-e5K9Qaxq.js → hx-skeleton-tiYvKO-t.js} +11 -11
  68. package/dist/shared/hx-skeleton-tiYvKO-t.js.map +1 -0
  69. package/dist/shared/{hx-spinner-Dyese1Tb.js → hx-spinner-D6nzuGmj.js} +8 -8
  70. package/dist/shared/hx-spinner-D6nzuGmj.js.map +1 -0
  71. package/dist/shared/hx-style-scope-CsQ2Phf_.js.map +1 -1
  72. package/dist/shared/{hx-text-input-Scyeefec.js → hx-text-input-Zuodg9s_.js} +3 -2
  73. package/dist/shared/{hx-text-input-Scyeefec.js.map → hx-text-input-Zuodg9s_.js.map} +1 -1
  74. package/dist/shared/id-counter-PTgF-zcG.js +15 -0
  75. package/dist/shared/id-counter-PTgF-zcG.js.map +1 -0
  76. package/package.json +2 -2
  77. package/dist/shared/hx-breadcrumb-item-DzLyeL5Z.js.map +0 -1
  78. package/dist/shared/hx-clinical-status-m4soOOwg.js.map +0 -1
  79. package/dist/shared/hx-code-snippet-CoLYvX1Z.js.map +0 -1
  80. package/dist/shared/hx-color-picker-DhOaNe6-.js.map +0 -1
  81. package/dist/shared/hx-container-31QT9KV_.js.map +0 -1
  82. package/dist/shared/hx-link-B8IwUMSc.js.map +0 -1
  83. package/dist/shared/hx-progress-ring-BJeiDr3q.js.map +0 -1
  84. package/dist/shared/hx-select-B5wq9Swh.js.map +0 -1
  85. package/dist/shared/hx-skeleton-e5K9Qaxq.js.map +0 -1
  86. package/dist/shared/hx-spinner-Dyese1Tb.js.map +0 -1
  87. package/dist/shared/id-counter-JhvVCnjh.js.map +0 -1
@@ -1,2 +1,2 @@
1
1
  /* hx-color-picker — extracted from Shadow DOM styles */
2
- :host{display:inline-block;position:relative;font-family:var(--hx-font-family-sans, sans-serif);font-size:var(--hx-font-size-sm, .875rem)}:host([disabled]){pointer-events:none;opacity:var(--hx-opacity-disabled, .4)}.trigger{display:inline-flex;align-items:center;gap:var(--hx-space-2, .5rem);padding:var(--hx-space-1, .25rem);border:var(--hx-border-width-thin, 1px) solid var(--hx-color-neutral-300, #d1d5db);border-radius:var(--hx-border-radius-md, .375rem);background:var(--hx-color-neutral-0, #fff);cursor:pointer;transition:border-color var(--hx-transition-fast, .15s ease)}.trigger:hover:not([disabled]){border-color:var(--hx-color-primary-500, #3b82f6)}:is(.trigger,.gradient-grid,.slider-track,.swatch-btn,.format-btn):focus-visible{outline:var(--hx-focus-ring-width, 2px) solid var(--hx-focus-ring-color, var(--hx-color-primary-500));outline-offset:var(--hx-focus-ring-offset, 2px)}.trigger-swatch{width:1.5rem;height:1.5rem;border-radius:var(--hx-border-radius-sm, .25rem);border:var(--hx-border-width-thin, 1px) solid var(--hx-color-picker-swatch-border, var(--hx-overlay-black-10, rgba(0, 0, 0, .1)));background:var(--_preview-color, #000);display:block;flex-shrink:0}.trigger-label{font-size:var(--hx-font-size-sm, .875rem);color:var(--hx-color-neutral-700, #374151);font-family:var(--hx-font-family-mono, monospace);white-space:nowrap}.panel{position:absolute;z-index:var(--hx-color-picker-z-index, 1000);top:calc(100% + 4px);left:0;background:var(--hx-color-neutral-0, #fff);border:var(--hx-border-width-thin, 1px) solid var(--hx-color-neutral-200, #e5e7eb);border-radius:var(--hx-border-radius-lg, .5rem);box-shadow:0 8px 24px var(--hx-color-picker-panel-shadow, var(--hx-overlay-black-15, rgba(0, 0, 0, .15)));padding:var(--hx-space-4, 1rem);width:var(--hx-color-picker-width, 260px);display:flex;flex-direction:column;gap:var(--hx-space-3, .75rem);outline:none}:host([inline]) .panel{position:static;box-shadow:none;border:var(--hx-border-width-thin, 1px) solid var(--hx-color-neutral-200, #e5e7eb);border-radius:var(--hx-border-radius-lg, .5rem)}.gradient-grid{position:relative;width:100%;height:var(--hx-color-picker-grid-height, 160px);border-radius:var(--hx-border-radius-sm, .25rem);cursor:crosshair;overflow:hidden;touch-action:none;flex-shrink:0}.gradient-grid-bg{position:absolute;inset:0;background:linear-gradient(to bottom,transparent,#000),linear-gradient(to right,#fff,var(--_hue-color, hsl(0, 100%, 50%)));pointer-events:none}.gradient-thumb{position:absolute;width:12px;height:12px;border-radius:50%;border:none;box-shadow:0 0 0 2px var(--hx-color-picker-thumb-border, var(--hx-color-neutral-0, #fff)),0 0 0 3px var(--hx-color-picker-thumb-shadow, var(--hx-overlay-black-30, rgba(0, 0, 0, .3)));transform:translate(-50%,-50%);pointer-events:none;top:var(--_thumb-y, 0%);left:var(--_thumb-x, 100%)}.slider-track{position:relative;width:100%;height:12px;border-radius:6px;cursor:pointer;touch-action:none;flex-shrink:0}.hue-track{background:linear-gradient(to right,red,#ff8000,#ff0,#80ff00,#0f0,#00ff80,#0ff,#0080ff,#00f,#7f00ff,#f0f,#ff0080,red)}.opacity-track{background-image:linear-gradient(to right,transparent,var(--_hue-color, hsl(0, 100%, 50%))),repeating-conic-gradient(#ccc 0% 25%,#fff 0% 50%) 0 0 / 12px 12px}.slider-thumb{position:absolute;top:50%;width:16px;height:16px;border-radius:50%;border:none;box-shadow:0 0 0 2px var(--hx-color-picker-thumb-border, var(--hx-color-neutral-0, #fff)),0 0 0 3px var(--hx-color-picker-thumb-shadow, var(--hx-overlay-black-30, rgba(0, 0, 0, .3)));transform:translate(-50%,-50%);pointer-events:none;left:var(--_slider-pct, 0%);background:var(--_thumb-color, hsl(0, 100%, 50%))}.swatches{display:flex;flex-wrap:wrap;gap:var(--hx-space-1, .25rem)}.swatch-btn{width:20px;height:20px;border-radius:var(--hx-border-radius-sm, .25rem);border:var(--hx-border-width-thin, 1px) solid var(--hx-color-picker-swatch-border, var(--hx-overlay-black-10, rgba(0, 0, 0, .1)));cursor:pointer;padding:0;flex-shrink:0;transition:transform var(--hx-transition-fast, .15s ease)}.swatch-btn:hover{transform:scale(1.15);border-color:var( --hx-color-picker-swatch-border-hover, var(--hx-overlay-black-30, rgba(0, 0, 0, .3)) )}.input-area{display:flex;align-items:center;gap:var(--hx-space-2, .5rem)}.format-btn{flex-shrink:0;padding:var(--hx-space-1, .25rem) var(--hx-space-2, .5rem);background:var(--hx-color-neutral-100, #f3f4f6);border:var(--hx-border-width-thin, 1px) solid var(--hx-color-neutral-300, #d1d5db);border-radius:var(--hx-border-radius-sm, .25rem);cursor:pointer;font-size:var(--hx-font-size-xs, .75rem);color:var(--hx-color-neutral-600, #4b5563);text-transform:uppercase;font-weight:var(--hx-font-weight-semibold, 600);letter-spacing:.05em}.color-input{flex:1;min-width:0;padding:var(--hx-space-1, .25rem) var(--hx-space-2, .5rem);border:var(--hx-border-width-thin, 1px) solid var(--hx-color-neutral-300, #d1d5db);border-radius:var(--hx-border-radius-sm, .25rem);font-family:var(--hx-font-family-mono, monospace);font-size:var(--hx-font-size-sm, .875rem);color:var(--hx-color-neutral-900, #111827);background:var(--hx-color-neutral-0, #fff);outline:none}.color-input:focus{border-color:var(--hx-focus-ring-color, var(--hx-color-primary-500));box-shadow:0 0 0 2px color-mix(in srgb,var(--hx-focus-ring-color, var(--hx-color-primary-500)) 20%,transparent)}.input-preview{width:24px;height:24px;border-radius:var(--hx-border-radius-sm, .25rem);border:var(--hx-border-width-thin, 1px) solid var(--hx-color-picker-swatch-border, var(--hx-overlay-black-10, rgba(0, 0, 0, .1)));background:var(--_preview-color, #000);flex-shrink:0}@media(prefers-reduced-motion:reduce){.trigger,.swatch-btn{transition:none}}
2
+ :host{display:inline-block;position:relative;font-family:var(--hx-font-family-sans, sans-serif);font-size:var(--hx-font-size-sm, .875rem)}:host([disabled]){pointer-events:none;opacity:var(--hx-opacity-disabled, .4)}.trigger{display:inline-flex;align-items:center;gap:var(--hx-space-2, .5rem);padding:var(--hx-space-1, .25rem);border:var(--hx-border-width-thin, 1px) solid var(--hx-color-neutral-300, #d1d5db);border-radius:var(--hx-border-radius-md, .375rem);background:var(--hx-color-neutral-0, #fff);cursor:pointer;transition:border-color var(--hx-transition-fast, .15s ease)}.trigger:hover:not([disabled]){border-color:var(--hx-color-primary-500, #3b82f6)}:is(.trigger,.gradient-grid,.slider-track,.swatch-btn,.format-btn):focus-visible{outline:var(--hx-focus-ring-width, 2px) solid var(--hx-focus-ring-color, var(--hx-color-primary-500));outline-offset:var(--hx-focus-ring-offset, 2px)}.trigger-swatch{width:1.5rem;height:1.5rem;border-radius:var(--hx-border-radius-sm, .25rem);border:var(--hx-border-width-thin, 1px) solid var(--hx-color-picker-swatch-border, var(--hx-overlay-black-10, rgba(0, 0, 0, .1)));background:var(--_preview-color, #000);display:block;flex-shrink:0}.trigger-label{font-size:var(--hx-font-size-sm, .875rem);color:var(--hx-color-neutral-700, #374151);font-family:var(--hx-font-family-mono, monospace);white-space:nowrap}.panel{position:absolute;z-index:var(--hx-color-picker-z-index, 1000);top:calc(100% + 4px);left:0;background:var(--hx-color-neutral-0, #fff);border:var(--hx-border-width-thin, 1px) solid var(--hx-color-neutral-200, #e5e7eb);border-radius:var(--hx-border-radius-lg, .5rem);box-shadow:0 8px 24px var(--hx-color-picker-panel-shadow, var(--hx-overlay-black-15, rgba(0, 0, 0, .15)));padding:var(--hx-space-4, 1rem);width:var(--hx-color-picker-width, 260px);display:flex;flex-direction:column;gap:var(--hx-space-3, .75rem);outline:none}:host([inline]) .panel{position:static;box-shadow:none;border:var(--hx-border-width-thin, 1px) solid var(--hx-color-neutral-200, #e5e7eb);border-radius:var(--hx-border-radius-lg, .5rem)}.gradient-grid{position:relative;width:100%;height:var(--hx-color-picker-grid-height, 160px);border-radius:var(--hx-border-radius-sm, .25rem);cursor:crosshair;overflow:hidden;touch-action:none;flex-shrink:0}.gradient-grid-bg{position:absolute;inset:0;background:linear-gradient(to bottom,transparent,#000),linear-gradient(to right,#fff,var(--_hue-color, hsl(0, 100%, 50%)));pointer-events:none}.gradient-thumb{position:absolute;width:12px;height:12px;border-radius:50%;border:none;box-shadow:0 0 0 2px var(--hx-color-picker-thumb-border, var(--hx-color-neutral-0, #fff)),0 0 0 3px var(--hx-color-picker-thumb-shadow, var(--hx-overlay-black-30, rgba(0, 0, 0, .3)));transform:translate(-50%,-50%);pointer-events:none;top:var(--_thumb-y, 0%);left:var(--_thumb-x, 100%)}.slider-track{position:relative;width:100%;height:12px;border-radius:6px;cursor:pointer;touch-action:none;flex-shrink:0}.hue-track{background:linear-gradient(to right,red,#ff8000,#ff0,#80ff00,#0f0,#00ff80,#0ff,#0080ff,#00f,#7f00ff,#f0f,#ff0080,red)}.opacity-track{background-image:linear-gradient(to right,transparent,var(--_hue-color, hsl(0, 100%, 50%))),repeating-conic-gradient(#ccc 0% 25%,#fff 0% 50%) 0 0 / 12px 12px}.slider-thumb{position:absolute;top:50%;width:16px;height:16px;border-radius:50%;border:none;box-shadow:0 0 0 2px var(--hx-color-picker-thumb-border, var(--hx-color-neutral-0, #fff)),0 0 0 3px var(--hx-color-picker-thumb-shadow, var(--hx-overlay-black-30, rgba(0, 0, 0, .3)));transform:translate(-50%,-50%);pointer-events:none;left:var(--_slider-pct, 0%);background:var(--_thumb-color, hsl(0, 100%, 50%))}.swatches{display:flex;flex-wrap:wrap;gap:var(--hx-space-1, .25rem)}.swatch-btn{width:20px;height:20px;border-radius:var(--hx-border-radius-sm, .25rem);border:var(--hx-border-width-thin, 1px) solid var(--hx-color-picker-swatch-border, var(--hx-overlay-black-10, rgba(0, 0, 0, .1)));cursor:pointer;padding:0;flex-shrink:0;transition:transform var(--hx-transition-fast, .15s ease)}.swatch-btn:hover{transform:scale(1.15);border-color:var( --hx-color-picker-swatch-border-hover, var(--hx-overlay-black-30, rgba(0, 0, 0, .3)) )}.input-area{display:flex;align-items:center;gap:var(--hx-space-2, .5rem)}.format-btn{flex-shrink:0;padding:var(--hx-space-1, .25rem) var(--hx-space-2, .5rem);background:var(--hx-color-neutral-100, #f3f4f6);border:var(--hx-border-width-thin, 1px) solid var(--hx-color-neutral-300, #d1d5db);border-radius:var(--hx-border-radius-sm, .25rem);cursor:pointer;font-size:var(--hx-font-size-xs, .75rem);color:var(--hx-color-neutral-600, #4b5563);text-transform:uppercase;font-weight:var(--hx-font-weight-semibold, 600);letter-spacing:.05em}.color-input{flex:1;min-width:0;padding:var(--hx-space-1, .25rem) var(--hx-space-2, .5rem);border:var(--hx-border-width-thin, 1px) solid var(--hx-color-neutral-300, #d1d5db);border-radius:var(--hx-border-radius-sm, .25rem);font-family:var(--hx-font-family-mono, monospace);font-size:var(--hx-font-size-sm, .875rem);color:var(--hx-color-neutral-900, #111827);background:var(--hx-color-neutral-0, #fff);outline:none}.color-input:focus-visible{border-color:var(--hx-focus-ring-color, var(--hx-color-primary-500));box-shadow:0 0 0 2px color-mix(in srgb,var(--hx-focus-ring-color, var(--hx-color-primary-500)) 20%,transparent)}.input-preview{width:24px;height:24px;border-radius:var(--hx-border-radius-sm, .25rem);border:var(--hx-border-width-thin, 1px) solid var(--hx-color-picker-swatch-border, var(--hx-overlay-black-10, rgba(0, 0, 0, .1)));background:var(--_preview-color, #000);flex-shrink:0}@media(prefers-reduced-motion:reduce){.trigger,.swatch-btn{transition:none}}
@@ -9,12 +9,6 @@
9
9
 
10
10
  /* ─── Vertical Padding Variants ─── */
11
11
 
12
- /* Defensive reset: ensures zero vertical padding even if a future base rule adds it */
13
- :host([padding='none']) {
14
- padding-top: 0;
15
- padding-bottom: 0;
16
- }
17
-
18
12
  :host([padding='sm']) {
19
13
  padding-top: var(--hx-space-6, 1.5rem);
20
14
  padding-bottom: var(--hx-space-6, 1.5rem);
@@ -72,7 +72,7 @@
72
72
  .link--disabled {
73
73
  color: var(--hx-link-color-disabled, var(--hx-color-neutral-400, #94a3b8));
74
74
  text-decoration: none;
75
- pointer-events: none;
75
+ cursor: not-allowed;
76
76
  }
77
77
 
78
78
  /* --- External link icon --- */
@@ -110,18 +110,18 @@
110
110
 
111
111
  /* ─── Size Variants ─── */
112
112
 
113
- :host([size='sm']) .progress-ring {
113
+ :host([hx-size='sm']) .progress-ring {
114
114
  width: var(--hx-size-8, 2rem);
115
115
  height: var(--hx-size-8, 2rem);
116
116
  }
117
117
 
118
- :host([size='md']) .progress-ring,
118
+ :host([hx-size='md']) .progress-ring,
119
119
  .progress-ring {
120
120
  width: var(--hx-size-12, 3rem);
121
121
  height: var(--hx-size-12, 3rem);
122
122
  }
123
123
 
124
- :host([size='lg']) .progress-ring {
124
+ :host([hx-size='lg']) .progress-ring {
125
125
  width: var(--hx-size-16, 4rem);
126
126
  height: var(--hx-size-16, 4rem);
127
127
  }
@@ -100,7 +100,6 @@
100
100
  outline: none;
101
101
  }
102
102
 
103
- .field__trigger:focus,
104
103
  .field__trigger:focus-visible {
105
104
  border-color: var(--_focus-ring-color);
106
105
  box-shadow: 0 0 0 var(--hx-focus-ring-width, 2px)
@@ -169,7 +168,6 @@
169
168
  border-color: var(--_error-color);
170
169
  }
171
170
 
172
- .field--error .field__trigger:focus,
173
171
  .field--error .field__trigger:focus-visible {
174
172
  border-color: var(--_error-color);
175
173
  box-shadow: 0 0 0 var(--hx-focus-ring-width, 2px)
@@ -26,7 +26,7 @@
26
26
  }
27
27
 
28
28
  .skeleton--circle {
29
- border-radius: var(--hx-skeleton-circle-radius, 50%);
29
+ border-radius: var(--hx-skeleton-border-radius-circle, 50%);
30
30
  aspect-ratio: var(--_circle-aspect-ratio, 1);
31
31
  width: var(--_width, 2.5rem);
32
32
  height: var(--_height, var(--_width, 2.5rem));
@@ -72,15 +72,15 @@
72
72
 
73
73
  /* ─── Size Variants ─── */
74
74
 
75
- :host([size='sm']) {
75
+ :host([hx-size='sm']) {
76
76
  --_spinner-size: var(--hx-size-4, 1rem);
77
77
  }
78
78
 
79
- :host([size='md']) {
79
+ :host([hx-size='md']) {
80
80
  --_spinner-size: var(--hx-size-6, 1.5rem);
81
81
  }
82
82
 
83
- :host([size='lg']) {
83
+ :host([hx-size='lg']) {
84
84
  --_spinner-size: var(--hx-size-8, 2rem);
85
85
  }
86
86
 
@@ -1,4 +1,4 @@
1
- /* index.css — generated 2026-04-12T13:32:35.231Z */
1
+ /* index.css — generated 2026-04-12T21:14:10.898Z */
2
2
  /* Imports all per-component CSS files for Drupal asset pipeline */
3
3
 
4
4
  @import './hx-accordion.css';
@@ -1,5 +1,5 @@
1
1
  {
2
- "generated": "2026-04-12T13:32:35.231Z",
2
+ "generated": "2026-04-12T21:14:10.897Z",
3
3
  "components": [
4
4
  {
5
5
  "name": "hx-accordion",
@@ -1720,8 +1720,8 @@
1720
1720
  "--hx-color-neutral-200",
1721
1721
  "--hx-overlay-white-40",
1722
1722
  "--hx-skeleton-bg",
1723
+ "--hx-skeleton-border-radius-circle",
1723
1724
  "--hx-skeleton-button-radius",
1724
- "--hx-skeleton-circle-radius",
1725
1725
  "--hx-skeleton-duration",
1726
1726
  "--hx-skeleton-rect-radius",
1727
1727
  "--hx-skeleton-shimmer-color",
package/dist/index.js CHANGED
@@ -5,18 +5,18 @@ import { H as g } from "./shared/hx-alert-CHOjTBds.js";
5
5
  import { H as v } from "./shared/hx-avatar-an-WsuLl.js";
6
6
  import { H as y } from "./shared/hx-badge-RPzd-t5l.js";
7
7
  import { H as E } from "./shared/hx-banner-B-WEDiq7.js";
8
- import { H as P, a as k } from "./shared/hx-breadcrumb-item-DzLyeL5Z.js";
8
+ import { H as P, a as k } from "./shared/hx-breadcrumb-item-jLAKK038.js";
9
9
  import { H as A } from "./shared/hx-button-DoN8jjQT.js";
10
10
  import { H as L } from "./shared/hx-button-group-BXlMQTt_.js";
11
11
  import { H as N } from "./shared/hx-card-BgXZXDuc.js";
12
12
  import { H as G, a as U } from "./shared/hx-carousel-item-Dwt9Pphz.js";
13
- import { H as V } from "./shared/hx-checkbox-CTEZ9IFq.js";
13
+ import { H as V } from "./shared/hx-checkbox-C82GjRXe.js";
14
14
  import { H as W } from "./shared/hx-checkbox-group-DThZeN5d.js";
15
- import { H as Y } from "./shared/hx-clinical-status-m4soOOwg.js";
16
- import { H as q } from "./shared/hx-code-snippet-CoLYvX1Z.js";
17
- import { H as J } from "./shared/hx-color-picker-DhOaNe6-.js";
15
+ import { H as Y } from "./shared/hx-clinical-status-BjtT5c0M.js";
16
+ import { H as q } from "./shared/hx-code-snippet-DcVENSuC.js";
17
+ import { H as J } from "./shared/hx-color-picker-C6EIuS9t.js";
18
18
  import { H as Q } from "./shared/hx-combobox-BJ4lQocO.js";
19
- import { H as ee } from "./shared/hx-container-31QT9KV_.js";
19
+ import { H as ee } from "./shared/hx-container-BwWbMPTH.js";
20
20
  import { H as te } from "./shared/hx-copy-button-BoM0WsMd.js";
21
21
  import { H as ae } from "./shared/hx-counter-CP42cSVK.js";
22
22
  import { H as se } from "./shared/hx-data-table-D5Ne-goy.js";
@@ -35,7 +35,7 @@ import { H as ke } from "./shared/hx-help-text-Bmb80bP4.js";
35
35
  import { H as Ae } from "./shared/hx-icon-BKHs3OLu.js";
36
36
  import { H as Le } from "./shared/hx-icon-button-CJuy9xbw.js";
37
37
  import { H as Ne } from "./shared/hx-image-ztiXumZB.js";
38
- import { H as Ge } from "./shared/hx-link-B8IwUMSc.js";
38
+ import { H as Ge } from "./shared/hx-link-CN7AvGOW.js";
39
39
  import { H as $e, a as Ve } from "./shared/hx-list-CoTDMp19.js";
40
40
  import { H as We, a as Xe, b as Ye } from "./shared/hx-menu-divider-DRT8yHRZ.js";
41
41
  import { H as qe } from "./shared/hx-meter-BvSJoqDp.js";
@@ -48,15 +48,15 @@ import { H as so } from "./shared/hx-phi-field-BiJH3V-k.js";
48
48
  import { H as Ho } from "./shared/hx-popover-D63RXn5H.js";
49
49
  import { H as po } from "./shared/hx-popup-BQWMhvMO.js";
50
50
  import { H as mo } from "./shared/hx-progress-bar-Cm0VihTN.js";
51
- import { H as co } from "./shared/hx-progress-ring-BJeiDr3q.js";
51
+ import { H as co } from "./shared/hx-progress-ring-Cs0WgWDJ.js";
52
52
  import { H as uo } from "./shared/hx-prose-Ml_L2zje.js";
53
53
  import { H as bo, a as So } from "./shared/hx-radio-f8c5ggHG.js";
54
54
  import { H as go } from "./shared/hx-rating-qRJZXskm.js";
55
- import { H as vo } from "./shared/hx-select-B5wq9Swh.js";
55
+ import { H as vo } from "./shared/hx-select-CgcgsHU5.js";
56
56
  import { H as yo, a as Do } from "./shared/hx-nav-item-CJN4VDrf.js";
57
- import { H as Bo } from "./shared/hx-skeleton-e5K9Qaxq.js";
57
+ import { H as Bo } from "./shared/hx-skeleton-tiYvKO-t.js";
58
58
  import { H as ko } from "./shared/hx-slider-BvXtvxmN.js";
59
- import { H as Ao } from "./shared/hx-spinner-Dyese1Tb.js";
59
+ import { H as Ao } from "./shared/hx-spinner-D6nzuGmj.js";
60
60
  import { H as Lo } from "./shared/hx-split-button-CPndTJlC.js";
61
61
  import { H as No } from "./shared/hx-split-panel-Dx72NaET.js";
62
62
  import { H as Go } from "./shared/hx-stack-B76_1O6g.js";
@@ -70,7 +70,7 @@ import { H as ot, a as tt, b as rt, c as at, d as it, e as st, f as xt } from ".
70
70
  import { H as lt, a as pt, b as nt } from "./shared/hx-tab-panel-J58zOSjq.js";
71
71
  import { H as ft } from "./shared/hx-tag-F0ZcYj9b.js";
72
72
  import { H as dt } from "./shared/hx-text-DcWBqZwx.js";
73
- import { F as ut, H as Tt } from "./shared/hx-text-input-Scyeefec.js";
73
+ import { F as ut, H as Tt } from "./shared/hx-text-input-Zuodg9s_.js";
74
74
  import { H as St } from "./shared/hx-textarea-BfSJJtA1.js";
75
75
  import { H as gt } from "./shared/hx-theme-pc1V7dyL.js";
76
76
  import { H as vt } from "./shared/hx-time-picker-CZvmihHD.js";
@@ -80,7 +80,8 @@ import { H as wt } from "./shared/hx-tooltip-Ny4i1Idj.js";
80
80
  import { H as Ft } from "./shared/hx-top-nav-CC4FW2Hp.js";
81
81
  import { H as Mt, a as Nt } from "./shared/hx-tree-item-CPQ9dJiK.js";
82
82
  import { H as Gt } from "./shared/hx-visually-hidden-vKX8QjeX.js";
83
- import { H as $t, c as Vt, r as Ot } from "./shared/id-counter-JhvVCnjh.js";
83
+ import { H as $t } from "./shared/helix-element-CZvaIEQP.js";
84
+ import { c as Ot, r as Wt } from "./shared/id-counter-PTgF-zcG.js";
84
85
  function n(t, e) {
85
86
  const o = Array.isArray(t) ? t : [t], r = Array.isArray(e) ? e : [e];
86
87
  return [...o, ...r];
@@ -262,10 +263,10 @@ export {
262
263
  Nt as HelixTreeView,
263
264
  Gt as HelixVisuallyHidden,
264
265
  Ko as HxStyleScope,
265
- Vt as createIdCounter,
266
+ Ot as createIdCounter,
266
267
  d as ensureDocumentTokens,
267
268
  n as mergeTokenStyles,
268
- Ot as resetIdCounter,
269
+ Wt as resetIdCounter,
269
270
  Et as toast
270
271
  };
271
272
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/base/styles.ts","../src/controllers/helix-audit-controller.ts"],"sourcesContent":["import { type CSSResultOrNative } from 'lit';\n\n/**\n * Merges token CSS custom properties into component styles.\n *\n * Accepts either a single style or an array for each argument and returns\n * a flat merged array suitable for use as `static override styles`.\n *\n * @deprecated Use document-level adopted stylesheets instead. Import\n * `'@helixui/library'` (which auto-adopts tokens) or call\n * `ensureDocumentTokens()` directly. Per-component token merging is no\n * longer necessary because tokens are now adopted at the document level\n * and cascade into Shadow DOM via CSS inheritance.\n *\n * @param componentStyles - The component's own styles\n * @param tokenStyles - Additional token CSS to merge in\n * @returns Merged styles array\n * @public\n *\n * @example\n * ```ts\n * // Preferred: tokens are auto-adopted at the document level\n * import '@helixui/library';\n *\n * // Legacy usage (deprecated):\n * static override styles = mergeTokenStyles(myStyles, extraStyles);\n * ```\n */\nexport function mergeTokenStyles(\n componentStyles: CSSResultOrNative | CSSResultOrNative[],\n tokenStyles: CSSResultOrNative | CSSResultOrNative[],\n): CSSResultOrNative[] {\n const base = Array.isArray(componentStyles) ? componentStyles : [componentStyles];\n const tokens = Array.isArray(tokenStyles) ? tokenStyles : [tokenStyles];\n return [...base, ...tokens];\n}\n","/**\n * @module HelixAuditController\n *\n * A Lit ReactiveController that captures `hx-*` CustomEvents on the host\n * element and re-dispatches them as enriched `hx-audit` events that bubble to\n * the document level. Designed for HIPAA audit-trail infrastructure in\n * enterprise healthcare deployments.\n *\n * @example\n * ```ts\n * import { HelixAuditController } from '../controllers/helix-audit-controller.js';\n *\n * class MyElement extends LitElement {\n * private _audit = new HelixAuditController(this, {\n * userId: 'user-123',\n * patientContextId: 'patient-456',\n * encounterId: 'encounter-789',\n * });\n * }\n * ```\n *\n * At the application boundary, wire a single document-level listener to forward\n * events to your HIPAA audit log infrastructure:\n *\n * ```ts\n * document.addEventListener('hx-audit', (e) => {\n * const detail = (e as CustomEvent<AuditEventDetail>).detail;\n * auditLogService.record(detail);\n * });\n * ```\n */\nimport type { ReactiveController, ReactiveControllerHost } from 'lit';\n\n/**\n * The structured payload carried in every `hx-audit` CustomEvent.\n */\nexport interface AuditEventDetail {\n /** Stable correlation ID generated once per controller instance. */\n sessionId: string;\n /** ISO-8601 timestamp at the moment of capture. */\n timestamp: string;\n /** Lowercase tag name of the host element (e.g. `\"hx-button\"`). */\n tagName: string;\n /** The original `hx-*` event type that triggered this audit record. */\n sourceEventType: string;\n /** The original event's `detail` payload, preserved verbatim. */\n sourceEventDetail: unknown;\n /** Optional user identifier for the authenticated session. */\n userId?: string;\n /** Optional patient context identifier for clinical audit trails. */\n patientContextId?: string;\n /** Optional encounter/visit identifier for clinical audit trails. */\n encounterId?: string;\n /** Additional caller-supplied key/value metadata. */\n [key: string]: unknown;\n}\n\n/**\n * Options accepted by `HelixAuditController` at construction time and via\n * `updateMetadata()`.\n */\nexport interface AuditControllerOptions {\n /** Authenticated user identifier. */\n userId?: string;\n /** Patient context identifier. */\n patientContextId?: string;\n /** Clinical encounter / visit identifier. */\n encounterId?: string;\n /** Arbitrary additional metadata to merge into every audit record. */\n metadata?: Record<string, unknown>;\n}\n\n/**\n * All `hx-*` event types defined in the HELiX component library that should\n * be captured for audit. When a new event is added to the library, adding it\n * here ensures automatic audit coverage with zero other changes required.\n *\n * The DOM event model does not support wildcard subscriptions, so we maintain\n * this explicit list and attach/detach one listener per type — a single bound\n * handler object is reused across all registrations for memory efficiency.\n */\nconst HX_EVENT_TYPES = [\n 'hx-click',\n 'hx-input',\n 'hx-change',\n 'hx-open',\n 'hx-close',\n 'hx-select',\n 'hx-submit',\n 'hx-reset',\n 'hx-sort',\n 'hx-filter',\n 'hx-page-change',\n 'hx-tab-change',\n 'hx-expand',\n 'hx-collapse',\n 'hx-copy',\n 'hx-upload',\n 'hx-remove',\n 'hx-rate',\n 'hx-toggle',\n 'hx-dismiss',\n 'hx-phi-access',\n] as const;\n\n/**\n * Generates a unique session correlation ID. Uses `crypto.randomUUID()` when\n * available and falls back to a timestamp-seeded pseudo-random string for\n * environments that do not expose the Web Crypto API (e.g. SSR, jsdom without\n * the crypto polyfill).\n */\nfunction generateSessionId(): string {\n if (typeof crypto !== 'undefined' && typeof (crypto as Crypto).randomUUID === 'function') {\n return (crypto as Crypto).randomUUID();\n }\n // Fallback: formatted as a UUID v4 lookalike so downstream parsers that\n // expect that shape don't break.\n const t = Date.now().toString(16).padStart(12, '0');\n const r1 = Math.random().toString(16).slice(2, 10).padStart(8, '0');\n const r2 = Math.random().toString(16).slice(2, 14).padStart(12, '0');\n return `${t.slice(0, 8)}-${t.slice(8)}-4${r1.slice(0, 3)}-${r2.slice(0, 4)}-${r2.slice(4)}`;\n}\n\n/**\n * Attaches to a Lit `ReactiveControllerHost` (any `LitElement`) and silently\n * captures all `hx-*` events, enriching them with session, timestamp, and\n * optional clinical metadata before re-dispatching as `hx-audit` events.\n *\n * Because all HELiX component events are dispatched with\n * `bubbles: true, composed: true`, they propagate from inside the shadow DOM\n * up to the host element — where this controller's listeners are registered —\n * and then continue bubbling to `document`, making the `hx-audit` event\n * observable anywhere in the page without requiring a global listener.\n */\nexport class HelixAuditController implements ReactiveController {\n private readonly _host: ReactiveControllerHost & EventTarget;\n private readonly _sessionId: string;\n private _options: AuditControllerOptions;\n\n /**\n * A single `EventListenerObject` reused across all event-type registrations.\n * Using the object form (rather than a bound function) avoids creating a new\n * closure per event type while still keeping `this` bound correctly.\n */\n private readonly _listener: EventListenerObject;\n\n constructor(host: ReactiveControllerHost & EventTarget, options: AuditControllerOptions = {}) {\n this._host = host;\n this._sessionId = generateSessionId();\n this._options = options;\n this._listener = { handleEvent: this._onHxEvent.bind(this) };\n this._host.addController(this);\n }\n\n /**\n * Updates the metadata attached to future audit records. Useful when the\n * authenticated user, patient context, or encounter changes after the\n * component is connected (e.g. patient context switch within a session).\n */\n updateMetadata(options: AuditControllerOptions): void {\n this._options = { ...this._options, ...options };\n }\n\n hostConnected(): void {\n for (const type of HX_EVENT_TYPES) {\n this._host.addEventListener(type, this._listener);\n }\n }\n\n hostDisconnected(): void {\n for (const type of HX_EVENT_TYPES) {\n this._host.removeEventListener(type, this._listener);\n }\n }\n\n private _onHxEvent(event: Event): void {\n // Guard: only process events whose type starts with 'hx-'.\n if (!event.type.startsWith('hx-')) return;\n // Guard: prevent recursion — never audit the audit event itself.\n if (event.type === 'hx-audit') return;\n\n const sourceDetail = event instanceof CustomEvent ? event.detail : undefined;\n\n const tagName = this._host instanceof Element ? this._host.tagName.toLowerCase() : 'unknown';\n\n const { userId, patientContextId, encounterId, metadata } = this._options;\n\n const detail: AuditEventDetail = {\n sessionId: this._sessionId,\n timestamp: new Date().toISOString(),\n tagName,\n sourceEventType: event.type,\n sourceEventDetail: sourceDetail,\n ...(userId !== undefined ? { userId } : {}),\n ...(patientContextId !== undefined ? { patientContextId } : {}),\n ...(encounterId !== undefined ? { encounterId } : {}),\n ...metadata,\n };\n\n this._host.dispatchEvent(\n new CustomEvent<AuditEventDetail>('hx-audit', {\n bubbles: true,\n composed: true,\n detail,\n }),\n );\n }\n}\n"],"names":["mergeTokenStyles","componentStyles","tokenStyles","base","tokens","HX_EVENT_TYPES","generateSessionId","r1","r2","HelixAuditController","host","options","type","event","sourceDetail","tagName","userId","patientContextId","encounterId","metadata","detail"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BO,SAASA,EACdC,GACAC,GACqB;AACrB,QAAMC,IAAO,MAAM,QAAQF,CAAe,IAAIA,IAAkB,CAACA,CAAe,GAC1EG,IAAS,MAAM,QAAQF,CAAW,IAAIA,IAAc,CAACA,CAAW;AACtE,SAAO,CAAC,GAAGC,GAAM,GAAGC,CAAM;AAC5B;AC8CA,MAAMC,IAAiB;AAAA,EACrB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAQA,SAASC,IAA4B;AACnC,MAAI,OAAO,SAAW,OAAe,OAAQ,OAAkB,cAAe;AAC5E,WAAQ,OAAkB,WAAA;AAI5B,QAAM,IAAI,KAAK,MAAM,SAAS,EAAE,EAAE,SAAS,IAAI,GAAG,GAC5CC,IAAK,KAAK,OAAA,EAAS,SAAS,EAAE,EAAE,MAAM,GAAG,EAAE,EAAE,SAAS,GAAG,GAAG,GAC5DC,IAAK,KAAK,OAAA,EAAS,SAAS,EAAE,EAAE,MAAM,GAAG,EAAE,EAAE,SAAS,IAAI,GAAG;AACnE,SAAO,GAAG,EAAE,MAAM,GAAG,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,KAAKD,EAAG,MAAM,GAAG,CAAC,CAAC,IAAIC,EAAG,MAAM,GAAG,CAAC,CAAC,IAAIA,EAAG,MAAM,CAAC,CAAC;AAC3F;AAaO,MAAMC,EAAmD;AAAA,EAY9D,YAAYC,GAA4CC,IAAkC,IAAI;AAC5F,SAAK,QAAQD,GACb,KAAK,aAAaJ,EAAA,GAClB,KAAK,WAAWK,GAChB,KAAK,YAAY,EAAE,aAAa,KAAK,WAAW,KAAK,IAAI,EAAA,GACzD,KAAK,MAAM,cAAc,IAAI;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,eAAeA,GAAuC;AACpD,SAAK,WAAW,EAAE,GAAG,KAAK,UAAU,GAAGA,EAAA;AAAA,EACzC;AAAA,EAEA,gBAAsB;AACpB,eAAWC,KAAQP;AACjB,WAAK,MAAM,iBAAiBO,GAAM,KAAK,SAAS;AAAA,EAEpD;AAAA,EAEA,mBAAyB;AACvB,eAAWA,KAAQP;AACjB,WAAK,MAAM,oBAAoBO,GAAM,KAAK,SAAS;AAAA,EAEvD;AAAA,EAEQ,WAAWC,GAAoB;AAIrC,QAFI,CAACA,EAAM,KAAK,WAAW,KAAK,KAE5BA,EAAM,SAAS,WAAY;AAE/B,UAAMC,IAAeD,aAAiB,cAAcA,EAAM,SAAS,QAE7DE,IAAU,KAAK,iBAAiB,UAAU,KAAK,MAAM,QAAQ,gBAAgB,WAE7E,EAAE,QAAAC,GAAQ,kBAAAC,GAAkB,aAAAC,GAAa,UAAAC,EAAA,IAAa,KAAK,UAE3DC,IAA2B;AAAA,MAC/B,WAAW,KAAK;AAAA,MAChB,YAAW,oBAAI,KAAA,GAAO,YAAA;AAAA,MACtB,SAAAL;AAAA,MACA,iBAAiBF,EAAM;AAAA,MACvB,mBAAmBC;AAAA,MACnB,GAAIE,MAAW,SAAY,EAAE,QAAAA,EAAA,IAAW,CAAA;AAAA,MACxC,GAAIC,MAAqB,SAAY,EAAE,kBAAAA,EAAA,IAAqB,CAAA;AAAA,MAC5D,GAAIC,MAAgB,SAAY,EAAE,aAAAA,EAAA,IAAgB,CAAA;AAAA,MAClD,GAAGC;AAAA,IAAA;AAGL,SAAK,MAAM;AAAA,MACT,IAAI,YAA8B,YAAY;AAAA,QAC5C,SAAS;AAAA,QACT,UAAU;AAAA,QACV,QAAAC;AAAA,MAAA,CACD;AAAA,IAAA;AAAA,EAEL;AACF;"}
1
+ {"version":3,"file":"index.js","sources":["../src/base/styles.ts","../src/controllers/helix-audit-controller.ts"],"sourcesContent":["import { type CSSResultOrNative } from 'lit';\n\n/**\n * Merges token CSS custom properties into component styles.\n *\n * Accepts either a single style or an array for each argument and returns\n * a flat merged array suitable for use as `static override styles`.\n *\n * @deprecated Use document-level adopted stylesheets instead. Import\n * `'@helixui/library'` (which auto-adopts tokens) or call\n * `ensureDocumentTokens()` directly. Per-component token merging is no\n * longer necessary because tokens are now adopted at the document level\n * and cascade into Shadow DOM via CSS inheritance.\n *\n * @param componentStyles - The component's own styles\n * @param tokenStyles - Additional token CSS to merge in\n * @returns Merged styles array\n * @public\n *\n * @example\n * ```ts\n * // Preferred: tokens are auto-adopted at the document level\n * import '@helixui/library';\n *\n * // Legacy usage (deprecated):\n * static override styles = mergeTokenStyles(myStyles, extraStyles);\n * ```\n */\nexport function mergeTokenStyles(\n componentStyles: CSSResultOrNative | CSSResultOrNative[],\n tokenStyles: CSSResultOrNative | CSSResultOrNative[],\n): CSSResultOrNative[] {\n const base = Array.isArray(componentStyles) ? componentStyles : [componentStyles];\n const tokens = Array.isArray(tokenStyles) ? tokenStyles : [tokenStyles];\n return [...base, ...tokens];\n}\n","/**\n * @module HelixAuditController\n *\n * A Lit ReactiveController that captures `hx-*` CustomEvents on the host\n * element and re-dispatches them as enriched `hx-audit` events that bubble to\n * the document level. Designed for HIPAA audit-trail infrastructure in\n * enterprise healthcare deployments.\n *\n * @example\n * ```ts\n * import { HelixAuditController } from '../controllers/helix-audit-controller.js';\n *\n * class MyElement extends LitElement {\n * private _audit = new HelixAuditController(this, {\n * userId: 'user-123',\n * patientContextId: 'patient-456',\n * encounterId: 'encounter-789',\n * });\n * }\n * ```\n *\n * At the application boundary, wire a single document-level listener to forward\n * events to your HIPAA audit log infrastructure:\n *\n * ```ts\n * document.addEventListener('hx-audit', (e) => {\n * const detail = (e as CustomEvent<AuditEventDetail>).detail;\n * auditLogService.record(detail);\n * });\n * ```\n */\nimport type { ReactiveController, ReactiveControllerHost } from 'lit';\n\n/**\n * The structured payload carried in every `hx-audit` CustomEvent.\n */\nexport interface AuditEventDetail {\n /** Stable correlation ID generated once per controller instance. */\n sessionId: string;\n /** ISO-8601 timestamp at the moment of capture. */\n timestamp: string;\n /** Lowercase tag name of the host element (e.g. `\"hx-button\"`). */\n tagName: string;\n /** The original `hx-*` event type that triggered this audit record. */\n sourceEventType: string;\n /** The original event's `detail` payload, preserved verbatim. */\n sourceEventDetail: unknown;\n /** Optional user identifier for the authenticated session. */\n userId?: string;\n /** Optional patient context identifier for clinical audit trails. */\n patientContextId?: string;\n /** Optional encounter/visit identifier for clinical audit trails. */\n encounterId?: string;\n /** Additional caller-supplied key/value metadata. */\n [key: string]: unknown;\n}\n\n/**\n * Options accepted by `HelixAuditController` at construction time and via\n * `updateMetadata()`.\n */\nexport interface AuditControllerOptions {\n /** Authenticated user identifier. */\n userId?: string;\n /** Patient context identifier. */\n patientContextId?: string;\n /** Clinical encounter / visit identifier. */\n encounterId?: string;\n /** Arbitrary additional metadata to merge into every audit record. */\n metadata?: Record<string, unknown>;\n}\n\n/**\n * All `hx-*` event types defined in the HELiX component library that should\n * be captured for audit. When a new event is added to the library, adding it\n * here ensures automatic audit coverage with zero other changes required.\n *\n * The DOM event model does not support wildcard subscriptions, so we maintain\n * this explicit list and attach/detach one listener per type — a single bound\n * handler object is reused across all registrations for memory efficiency.\n */\nconst HX_EVENT_TYPES = [\n 'hx-click',\n 'hx-input',\n 'hx-change',\n 'hx-open',\n 'hx-close',\n 'hx-select',\n 'hx-submit',\n 'hx-reset',\n 'hx-sort',\n 'hx-filter',\n 'hx-page-change',\n 'hx-tab-change',\n 'hx-expand',\n 'hx-collapse',\n 'hx-copy',\n 'hx-upload',\n 'hx-remove',\n 'hx-rate',\n 'hx-toggle',\n 'hx-dismiss',\n 'hx-phi-access',\n] as const;\n\n/**\n * Generates a unique session correlation ID. Uses `crypto.randomUUID()` when\n * available and falls back to a timestamp-seeded pseudo-random string for\n * environments that do not expose the Web Crypto API (e.g. SSR, jsdom without\n * the crypto polyfill).\n */\nfunction generateSessionId(): string {\n if (typeof crypto !== 'undefined' && typeof (crypto as Crypto).randomUUID === 'function') {\n return (crypto as Crypto).randomUUID();\n }\n // Fallback: formatted as a UUID v4 lookalike so downstream parsers that\n // expect that shape don't break.\n const t = Date.now().toString(16).padStart(12, '0');\n const r1 = Math.random().toString(16).slice(2, 10).padStart(8, '0');\n const r2 = Math.random().toString(16).slice(2, 14).padStart(12, '0');\n return `${t.slice(0, 8)}-${t.slice(8)}-4${r1.slice(0, 3)}-${r2.slice(0, 4)}-${r2.slice(4)}`;\n}\n\n/**\n * Attaches to a Lit `ReactiveControllerHost` (any `LitElement`) and silently\n * captures all `hx-*` events, enriching them with session, timestamp, and\n * optional clinical metadata before re-dispatching as `hx-audit` events.\n *\n * Because all HELiX component events are dispatched with\n * `bubbles: true, composed: true`, they propagate from inside the shadow DOM\n * up to the host element — where this controller's listeners are registered —\n * and then continue bubbling to `document`, making the `hx-audit` event\n * observable anywhere in the page without requiring a global listener.\n */\nexport class HelixAuditController implements ReactiveController {\n private readonly _host: ReactiveControllerHost & EventTarget;\n private readonly _sessionId: string;\n private _options: AuditControllerOptions;\n\n /**\n * A single `EventListenerObject` reused across all event-type registrations.\n * Using the object form (rather than a bound function) avoids creating a new\n * closure per event type while still keeping `this` bound correctly.\n */\n private readonly _listener: EventListenerObject;\n\n constructor(host: ReactiveControllerHost & EventTarget, options: AuditControllerOptions = {}) {\n this._host = host;\n this._sessionId = generateSessionId();\n this._options = options;\n this._listener = { handleEvent: this._onHxEvent.bind(this) };\n this._host.addController(this);\n }\n\n /**\n * Updates the metadata attached to future audit records. Useful when the\n * authenticated user, patient context, or encounter changes after the\n * component is connected (e.g. patient context switch within a session).\n */\n updateMetadata(options: AuditControllerOptions): void {\n this._options = { ...this._options, ...options };\n }\n\n hostConnected(): void {\n for (const type of HX_EVENT_TYPES) {\n this._host.addEventListener(type, this._listener);\n }\n }\n\n hostDisconnected(): void {\n for (const type of HX_EVENT_TYPES) {\n this._host.removeEventListener(type, this._listener);\n }\n }\n\n private _onHxEvent(event: Event): void {\n // Guard: only process events whose type starts with 'hx-'.\n if (!event.type.startsWith('hx-')) return;\n // Guard: prevent recursion — never audit the audit event itself.\n if (event.type === 'hx-audit') return;\n\n const sourceDetail = event instanceof CustomEvent ? event.detail : undefined;\n\n const tagName = this._host instanceof Element ? this._host.tagName.toLowerCase() : 'unknown';\n\n const { userId, patientContextId, encounterId, metadata } = this._options;\n\n const detail: AuditEventDetail = {\n sessionId: this._sessionId,\n timestamp: new Date().toISOString(),\n tagName,\n sourceEventType: event.type,\n sourceEventDetail: sourceDetail,\n ...(userId !== undefined ? { userId } : {}),\n ...(patientContextId !== undefined ? { patientContextId } : {}),\n ...(encounterId !== undefined ? { encounterId } : {}),\n ...metadata,\n };\n\n this._host.dispatchEvent(\n new CustomEvent<AuditEventDetail>('hx-audit', {\n bubbles: true,\n composed: true,\n detail,\n }),\n );\n }\n}\n"],"names":["mergeTokenStyles","componentStyles","tokenStyles","base","tokens","HX_EVENT_TYPES","generateSessionId","r1","r2","HelixAuditController","host","options","type","event","sourceDetail","tagName","userId","patientContextId","encounterId","metadata","detail"],"mappings":"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"}
@@ -1,14 +1,14 @@
1
- var c = (s) => {
1
+ var a = (s) => {
2
2
  throw TypeError(s);
3
3
  };
4
- var l = (s, e, t) => e.has(s) || c("Cannot " + t);
5
- var n = (s, e, t) => (l(s, e, "read from private field"), t ? t.call(s) : e.get(s)), d = (s, e, t) => e.has(s) ? c("Cannot add the same private member more than once") : e instanceof WeakSet ? e.add(s) : e.set(s, t), u = (s, e, t, r) => (l(s, e, "write to private field"), r ? r.call(s, t) : e.set(s, t), t);
4
+ var c = (s, o, t) => o.has(s) || a("Cannot " + t);
5
+ var i = (s, o, t) => (c(s, o, "read from private field"), t ? t.call(s) : o.get(s)), l = (s, o, t) => o.has(s) ? a("Cannot add the same private member more than once") : o instanceof WeakSet ? o.add(s) : o.set(s, t), d = (s, o, t, e) => (c(s, o, "write to private field"), e ? e.call(s, t) : o.set(s, t), t);
6
6
  import { LitElement as h } from "lit";
7
- var o;
8
- const a = class a extends h {
7
+ var r;
8
+ const n = class n extends h {
9
9
  constructor() {
10
10
  super(...arguments);
11
- d(this, o);
11
+ l(this, r);
12
12
  }
13
13
  /**
14
14
  * Lazy accessor for `ElementInternals`. Calls `attachInternals()` on first
@@ -25,11 +25,11 @@ const a = class a extends h {
25
25
  throw new Error(
26
26
  `[HelixElement] _internals accessed on <${this.tagName.toLowerCase()}> but static formAssociated is not set to true on ${this.constructor.name}.`
27
27
  );
28
- const t = n(this, o);
28
+ const t = i(this, r);
29
29
  if (t !== void 0)
30
30
  return t;
31
- const r = this.attachInternals();
32
- return u(this, o, r), r;
31
+ const e = this.attachInternals();
32
+ return d(this, r, e), e;
33
33
  }
34
34
  // ─── Browser Form Callbacks (delegate to hook methods) ───
35
35
  /**
@@ -57,8 +57,8 @@ const a = class a extends h {
57
57
  * Delegates to `_onFormStateRestore`. Override that method in subclasses.
58
58
  * @internal
59
59
  */
60
- formStateRestoreCallback(t, r) {
61
- this._onFormStateRestore(t, r);
60
+ formStateRestoreCallback(t, e) {
61
+ this._onFormStateRestore(t, e);
62
62
  }
63
63
  // ─── Hook Methods (override in subclasses) ───
64
64
  /**
@@ -83,7 +83,7 @@ const a = class a extends h {
83
83
  * @param _mode - `'restore'` for bfcache navigation, `'autocomplete'` for autofill
84
84
  * @internal
85
85
  */
86
- _onFormStateRestore(t, r) {
86
+ _onFormStateRestore(t, e) {
87
87
  }
88
88
  // ─── Convenience Getters ───
89
89
  /**
@@ -96,7 +96,7 @@ const a = class a extends h {
96
96
  * @internal
97
97
  */
98
98
  get form() {
99
- const t = n(this, o);
99
+ const t = i(this, r);
100
100
  return !this.constructor.formAssociated || t === void 0 ? null : t.form;
101
101
  }
102
102
  /**
@@ -109,7 +109,7 @@ const a = class a extends h {
109
109
  * @internal
110
110
  */
111
111
  get validity() {
112
- const t = n(this, o);
112
+ const t = i(this, r);
113
113
  return !this.constructor.formAssociated || t === void 0 ? null : t.validity;
114
114
  }
115
115
  /**
@@ -119,25 +119,13 @@ const a = class a extends h {
119
119
  * @internal
120
120
  */
121
121
  get validationMessage() {
122
- const t = n(this, o);
122
+ const t = i(this, r);
123
123
  return !this.constructor.formAssociated || t === void 0 ? "" : t.validationMessage;
124
124
  }
125
125
  };
126
- o = new WeakMap(), a.formAssociated = !1;
127
- let f = a;
128
- const i = /* @__PURE__ */ new Map();
129
- function v(s) {
130
- return () => {
131
- const e = i.get(s) ?? 0;
132
- return i.set(s, e + 1), `${s}-${e}`;
133
- };
134
- }
135
- function b(s) {
136
- s !== void 0 ? i.delete(s) : i.clear();
137
- }
126
+ r = new WeakMap(), n.formAssociated = !1;
127
+ let m = n;
138
128
  export {
139
- f as H,
140
- v as c,
141
- b as r
129
+ m as H
142
130
  };
143
- //# sourceMappingURL=id-counter-JhvVCnjh.js.map
131
+ //# sourceMappingURL=helix-element-CZvaIEQP.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helix-element-CZvaIEQP.js","sources":["../../src/base/helix-element.ts"],"sourcesContent":["import { LitElement } from 'lit';\n\n/**\n * `HelixElement` extends `LitElement` with shared infrastructure for all HELiX\n * components: lazy `ElementInternals` access, form lifecycle hook delegation,\n * and convenience validity getters.\n *\n * Form association is opt-in via `static formAssociated = true` on the subclass.\n * When set, `HelixElement` provides a lazy `_internals` accessor that calls\n * `attachInternals()` on first access — eliminating constructor boilerplate.\n *\n * Form components should also override the `_onForm*` hook methods rather than\n * re-declaring the raw browser callbacks (`formResetCallback`, etc.).\n *\n * @example Non-form component — no configuration required:\n * ```ts\n * class HxCard extends HelixElement {\n * // no formAssociated needed\n * }\n * ```\n *\n * @example Form-associated component:\n * ```ts\n * class HxTextInput extends HelixElement {\n * static override formAssociated = true;\n *\n * override _onFormReset(): void {\n * this.value = '';\n * this._internals.setFormValue('');\n * }\n *\n * override _onFormDisabled(disabled: boolean): void {\n * this.disabled = disabled;\n * }\n * }\n * ```\n *\n * @public\n */\nexport class HelixElement extends LitElement {\n /**\n * Set to `true` on the subclass to enable ElementInternals form association.\n *\n * IMPORTANT: This MUST be redeclared as `static override formAssociated = true`\n * on each form-associated subclass. The browser's form association mechanism\n * inspects `formAssociated` on the *registered* custom element class, not\n * on ancestor classes.\n *\n * @internal\n */\n static formAssociated = false;\n\n #internals: ElementInternals | undefined;\n\n /**\n * Lazy accessor for `ElementInternals`. Calls `attachInternals()` on first\n * access and caches the result.\n *\n * Only valid when `static formAssociated = true` is declared on the subclass.\n * Accessing this on a non-form-associated component throws a descriptive error.\n *\n * @throws {Error} If accessed on a component where `formAssociated` is `false`\n * @internal\n */\n get _internals(): ElementInternals {\n if (!(this.constructor as typeof HelixElement).formAssociated) {\n throw new Error(\n `[HelixElement] _internals accessed on <${this.tagName.toLowerCase()}> but ` +\n `static formAssociated is not set to true on ${this.constructor.name}.`,\n );\n }\n const cached = this.#internals;\n if (cached !== undefined) {\n return cached;\n }\n const internals = this.attachInternals();\n this.#internals = internals;\n return internals;\n }\n\n // ─── Browser Form Callbacks (delegate to hook methods) ───\n\n /**\n * Called by the browser when the element's form-associated disabled state\n * changes (e.g., a parent `<fieldset disabled>` is toggled).\n *\n * Delegates to `_onFormDisabled`. Override that method in subclasses.\n * @internal\n */\n formDisabledCallback(disabled: boolean): void {\n this._onFormDisabled(disabled);\n }\n\n /**\n * Called by the browser when the owning form is reset.\n *\n * Delegates to `_onFormReset`. Override that method in subclasses.\n * @internal\n */\n formResetCallback(): void {\n this._onFormReset();\n }\n\n /**\n * Called by the browser to restore form state (e.g., back/forward cache).\n *\n * Delegates to `_onFormStateRestore`. Override that method in subclasses.\n * @internal\n */\n formStateRestoreCallback(\n state: File | string | FormData | null,\n mode: 'restore' | 'autocomplete',\n ): void {\n this._onFormStateRestore(state, mode);\n }\n\n // ─── Hook Methods (override in subclasses) ───\n\n /**\n * Override in subclass to react to the element being disabled or enabled\n * via a parent `<fieldset>`.\n *\n * @param _disabled - `true` when the element is being disabled\n * @internal\n */\n protected _onFormDisabled(_disabled: boolean): void {}\n\n /**\n * Override in subclass to reset component state when the owning form resets.\n * @internal\n */\n protected _onFormReset(): void {}\n\n /**\n * Override in subclass to restore component state from saved form state.\n *\n * @param _state - The saved state value, or `null` if none\n * @param _mode - `'restore'` for bfcache navigation, `'autocomplete'` for autofill\n * @internal\n */\n protected _onFormStateRestore(\n _state: File | string | FormData | null,\n _mode: 'restore' | 'autocomplete',\n ): void {}\n\n // ─── Convenience Getters ───\n\n /**\n * The associated form element, or `null` if not form-associated or not yet\n * connected to a form.\n *\n * Form-associated subclasses that need a guaranteed non-null return type\n * should redeclare this getter and delegate to `this._internals.form`.\n *\n * @internal\n */\n get form(): HTMLFormElement | null {\n const internals = this.#internals;\n if (!(this.constructor as typeof HelixElement).formAssociated || internals === undefined) {\n return null;\n }\n return internals.form;\n }\n\n /**\n * The current `ValidityState` for this element, or `null` if not\n * form-associated.\n *\n * Form-associated subclasses that need a guaranteed `ValidityState` return\n * should redeclare this getter and delegate to `this._internals.validity`.\n *\n * @internal\n */\n get validity(): ValidityState | null {\n const internals = this.#internals;\n if (!(this.constructor as typeof HelixElement).formAssociated || internals === undefined) {\n return null;\n }\n return internals.validity;\n }\n\n /**\n * The current validation message, or an empty string if not form-associated\n * or if the element is valid.\n *\n * @internal\n */\n get validationMessage(): string {\n const internals = this.#internals;\n if (!(this.constructor as typeof HelixElement).formAssociated || internals === undefined) {\n return '';\n }\n return internals.validationMessage;\n }\n}\n"],"names":["_HelixElement","LitElement","__privateAdd","_internals","cached","__privateGet","internals","__privateSet","disabled","state","mode","_disabled","_state","_mode","HelixElement"],"mappings":";;;;;;;AAuCO,MAAMA,IAAN,MAAMA,UAAqBC,EAAW;AAAA,EAAtC;AAAA;AAaL,IAAAC,EAAA,MAAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,IAAI,aAA+B;AACjC,QAAI,CAAE,KAAK,YAAoC;AAC7C,YAAM,IAAI;AAAA,QACR,0CAA0C,KAAK,QAAQ,YAAA,CAAa,qDACnB,KAAK,YAAY,IAAI;AAAA,MAAA;AAG1E,UAAMC,IAASC,EAAA,MAAKF;AACpB,QAAIC,MAAW;AACb,aAAOA;AAET,UAAME,IAAY,KAAK,gBAAA;AACvB,WAAAC,EAAA,MAAKJ,GAAaG,IACXA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,qBAAqBE,GAAyB;AAC5C,SAAK,gBAAgBA,CAAQ;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,oBAA0B;AACxB,SAAK,aAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,yBACEC,GACAC,GACM;AACN,SAAK,oBAAoBD,GAAOC,CAAI;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWU,gBAAgBC,GAA0B;AAAA,EAAC;AAAA;AAAA;AAAA;AAAA;AAAA,EAM3C,eAAqB;AAAA,EAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAStB,oBACRC,GACAC,GACM;AAAA,EAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaT,IAAI,OAA+B;AACjC,UAAMP,IAAYD,EAAA,MAAKF;AACvB,WAAI,CAAE,KAAK,YAAoC,kBAAkBG,MAAc,SACtE,OAEFA,EAAU;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,IAAI,WAAiC;AACnC,UAAMA,IAAYD,EAAA,MAAKF;AACvB,WAAI,CAAE,KAAK,YAAoC,kBAAkBG,MAAc,SACtE,OAEFA,EAAU;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,IAAI,oBAA4B;AAC9B,UAAMA,IAAYD,EAAA,MAAKF;AACvB,WAAI,CAAE,KAAK,YAAoC,kBAAkBG,MAAc,SACtE,KAEFA,EAAU;AAAA,EACnB;AACF;AA9IEH,IAAA,eAFAH,EAAO,iBAAiB;AAXnB,IAAMc,IAANd;"}
@@ -165,7 +165,7 @@ let o = class extends u {
165
165
  }
166
166
  // ─── Lifecycle ───
167
167
  connectedCallback() {
168
- super.connectedCallback(), this.addEventListener("click", this._boundEllipsisClick), this.addEventListener("keydown", this._boundEllipsisKeydown);
168
+ super.connectedCallback(), this.hasAttribute("role") || this.setAttribute("role", "list"), this.addEventListener("click", this._boundEllipsisClick), this.addEventListener("keydown", this._boundEllipsisKeydown);
169
169
  }
170
170
  disconnectedCallback() {
171
171
  super.disconnectedCallback(), this.removeEventListener("click", this._boundEllipsisClick), this.removeEventListener("keydown", this._boundEllipsisKeydown), this._removeJsonLd();
@@ -334,4 +334,4 @@ export {
334
334
  o as H,
335
335
  c as a
336
336
  };
337
- //# sourceMappingURL=hx-breadcrumb-item-DzLyeL5Z.js.map
337
+ //# sourceMappingURL=hx-breadcrumb-item-jLAKK038.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hx-breadcrumb-item-jLAKK038.js","sources":["../../src/components/hx-breadcrumb/hx-breadcrumb.styles.ts","../../src/components/hx-breadcrumb/hx-breadcrumb.ts","../../src/components/hx-breadcrumb/hx-breadcrumb-item.styles.ts","../../src/components/hx-breadcrumb/hx-breadcrumb-item.ts"],"sourcesContent":["import { css } from 'lit';\n\nexport const helixBreadcrumbStyles = css`\n :host {\n display: block;\n font-family: var(\n --hx-breadcrumb-font-family,\n var(--hx-font-family-sans, system-ui, sans-serif)\n );\n font-size: var(--hx-breadcrumb-font-size, var(--hx-font-size-sm, 0.875rem));\n }\n\n [part='nav'] {\n /* nav landmark — no additional styling needed */\n }\n\n [part='list'] {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n list-style: none;\n margin: 0;\n padding: 0;\n gap: 0;\n }\n\n /* Hide middle items when collapsed via maxItems */\n ::slotted([data-bc-hidden]) {\n display: none;\n }\n\n /* Visually hide the separator slot — used only to read text content.\n * display:none is intentional: the slot contains no interactive or focusable\n * content. If a future change adds focusable elements to this slot, switch to\n * visibility:hidden + position:absolute to preserve focus reachability. */\n .separator-slot {\n display: none;\n }\n`;\n","import { LitElement, html, type PropertyValues } from 'lit';\nimport '../../utilities/document-token-adoption.js';\nimport { customElement, property } from 'lit/decorators.js';\nimport { helixBreadcrumbStyles } from './hx-breadcrumb.styles.js';\n\n/** Typed schema.org ListItem entry for JSON-LD BreadcrumbList structured data. */\ninterface JsonLdListItem {\n '@type': string;\n position: number;\n name: string;\n item?: string;\n}\n\n/**\n * Hierarchical page path navigation showing current location in site structure.\n *\n * @summary Navigation breadcrumb showing the page hierarchy. Works with Drupal's breadcrumb system.\n *\n * @tag hx-breadcrumb\n *\n * @slot - Default slot for hx-breadcrumb-item children.\n * @slot separator - Optional separator element. Its text content overrides the `separator` property.\n *\n * @csspart nav - The nav landmark element.\n * @csspart list - The ordered list containing items.\n *\n * @cssprop [--hx-breadcrumb-separator-content='/'] - Separator character between items.\n * NOTE: If overriding this custom property directly in CSS (rather than via the `separator`\n * attribute), the value MUST be quoted: `--hx-breadcrumb-separator-content: \">\"`. An unquoted\n * value is invalid for the CSS `content` property and will silently render nothing.\n * @cssprop [--hx-breadcrumb-separator-color=var(--hx-color-neutral-400)] - Separator color.\n * @cssprop [--hx-breadcrumb-separator-gap=var(--hx-space-1)] - Horizontal gap around separators.\n * @cssprop [--hx-breadcrumb-font-size=var(--hx-font-size-sm)] - Font size.\n * @cssprop [--hx-breadcrumb-link-color=var(--hx-color-primary-600)] - Link color.\n * @cssprop [--hx-breadcrumb-link-hover-color=var(--hx-color-primary-700)] - Link hover color.\n * @cssprop [--hx-breadcrumb-text-color=var(--hx-color-neutral-700)] - Current page text color.\n * @cssprop [--hx-breadcrumb-item-max-width] - Max-width for item text truncation (e.g. `12rem`).\n */\n@customElement('hx-breadcrumb')\nexport class HelixBreadcrumb extends LitElement {\n static override styles = [helixBreadcrumbStyles];\n\n /**\n * Per-instance counter used to generate stable, deterministic IDs for the\n * injected JSON-LD script tags. Deterministic IDs (vs Math.random()) allow\n * SSR frameworks to match server-rendered script tags during hydration.\n * @internal\n */\n private static _instanceCounter = 0;\n\n /**\n * The separator character displayed between breadcrumb items.\n * @attr separator\n */\n @property({ type: String })\n separator = '/';\n\n /**\n * The accessible label for the nav landmark.\n * @attr label\n */\n @property({ type: String })\n label = 'Breadcrumb';\n\n /**\n * Maximum number of items to show before collapsing middle items with an ellipsis.\n * Set to 0 (default) to show all items. The ellipsis is a keyboard-accessible\n * button; activating it expands the full breadcrumb by setting maxItems to 0.\n * @attr max-items\n */\n @property({ type: Number, attribute: 'max-items' })\n maxItems = 0;\n\n /**\n * Accessible label for the expand ellipsis button. Override for i18n.\n * @attr label-ellipsis\n */\n @property({ attribute: 'label-ellipsis' }) labelEllipsis = 'Show all breadcrumb items';\n\n /**\n * When true, injects a JSON-LD BreadcrumbList structured data script into the document head.\n *\n * NOTE: Drupal manages `<head>` content via its own render pipeline. Injecting a\n * `<script>` directly via `document.head.appendChild()` in a Drupal context:\n * 1. Bypasses Drupal's deduplication and `hook_html_head_alter()` hook.\n * 2. Is not cacheable by Drupal's page cache.\n * 3. Will be wiped on BigPipe partial page replacements.\n *\n * For Drupal integrations, leave `json-ld` false and use the structured data\n * Twig template instead (see `hx-breadcrumb.twig` in the component directory).\n *\n * @attr json-ld\n */\n @property({ type: Boolean, attribute: 'json-ld' })\n jsonLd = false;\n\n /** @internal */\n private _ellipsisItem: Element | null = null;\n /** @internal */\n private _jsonLdScript: HTMLScriptElement | null = null;\n /** @internal */\n private readonly _boundEllipsisClick = (e: Event) => this._handleEllipsisClick(e);\n /** @internal */\n private readonly _boundEllipsisKeydown = (e: Event) => this._handleEllipsisKeydown(e);\n\n /**\n * Tracks which items had their `current` attribute set by this component\n * (as opposed to set by a consumer/Drupal template). This lets us re-evaluate\n * positional current-page detection on each slotchange without incorrectly\n * treating a previously component-set `current` attribute as a consumer-set\n * explicit override.\n * @internal\n */\n private readonly _managedCurrentItems = new WeakSet<Element>();\n\n /**\n * Stable per-instance ID used to tag the injected script element so that\n * multiple hx-breadcrumb instances on the same page don't produce conflicting\n * or duplicate structured-data blocks. Each instance owns exactly one script\n * tag identified by this ID; any stale tag from a previous render cycle is\n * removed before a new one is inserted.\n *\n * Uses a static counter (not Math.random()) so IDs are deterministic across\n * server and client renders, enabling SSR hydration matching.\n * @internal\n */\n private readonly _jsonLdId = `hx-breadcrumb-ld-${++HelixBreadcrumb._instanceCounter}`;\n\n // ─── Item Helpers ───\n\n /**\n * Returns only real breadcrumb items, excluding the managed ellipsis element.\n * @internal\n */\n private _getBreadcrumbItems(slot: HTMLSlotElement): Element[] {\n return slot\n .assignedElements({ flatten: true })\n .filter(\n (el) =>\n el.tagName.toLowerCase() === 'hx-breadcrumb-item' &&\n !el.classList.contains('hx-bc-ellipsis'),\n );\n }\n\n /**\n * Applies aria/state attributes to the item list.\n *\n * Current-page detection: if any item has an explicit `current` attribute\n * (e.g. set by a Drupal Twig template), that item is treated as the current\n * page. Otherwise the last item is the current page (default behaviour).\n *\n * This separation allows Drupal to control current-page marking without\n * relying on item order.\n * @internal\n */\n private _applyItemAttributes(items: Element[]): void {\n // Detect consumer-set 'current' attributes. An item has an explicit consumer\n // current if it has the 'current' attribute AND the component did not set it\n // (tracked via _managedCurrentItems). This prevents component-managed state\n // from being misread as a consumer override on subsequent slotchange events.\n const hasExplicitCurrent = items.some(\n (el) => el.hasAttribute('current') && !this._managedCurrentItems.has(el),\n );\n\n items.forEach((item, i) => {\n const el = item as HTMLElement;\n const isLast = i === items.length - 1;\n\n // Separator hiding: always positional — last item has no trailing separator.\n if (isLast) {\n el.setAttribute('data-bc-last', '');\n } else {\n el.removeAttribute('data-bc-last');\n }\n\n // Current-page marker: explicit consumer attribute wins over positional last.\n // The item component renders aria-current=\"page\" on its inner element\n // based on this attribute (see hx-breadcrumb-item.ts).\n if (!hasExplicitCurrent) {\n if (isLast) {\n el.setAttribute('current', '');\n this._managedCurrentItems.add(el);\n } else {\n el.removeAttribute('current');\n this._managedCurrentItems.delete(el);\n }\n }\n // When hasExplicitCurrent is true, leave 'current' attributes as-is so\n // consumer or Drupal template markup is not overridden.\n });\n }\n\n // ─── Slot Handling ───\n\n /** @internal */\n private _handleSlotChange(e: Event): void {\n if (!(e.target instanceof HTMLSlotElement)) return;\n const items = this._getBreadcrumbItems(e.target);\n\n // Handle collapse behaviour\n if (this.maxItems > 0 && items.length > this.maxItems) {\n this._applyCollapse(items);\n } else {\n this._removeCollapse(items);\n }\n\n this._applyItemAttributes(items);\n\n if (this.jsonLd) {\n this._updateJsonLd(items);\n }\n }\n\n /** @internal */\n private _handleSeparatorSlotChange(e: Event): void {\n if (!(e.target instanceof HTMLSlotElement)) return;\n const assigned = e.target.assignedElements({ flatten: true });\n if (assigned.length > 0) {\n const text = (assigned[0] as HTMLElement).textContent?.trim() ?? '';\n this.style.setProperty('--hx-breadcrumb-separator-content', JSON.stringify(text));\n }\n }\n\n // ─── Collapse ───\n\n /** @internal */\n private _applyCollapse(items: Element[]): void {\n // Show only first and last; hide all middle items\n items.forEach((item, i) => {\n const el = item as HTMLElement;\n if (i === 0 || i === items.length - 1) {\n el.removeAttribute('data-bc-hidden');\n } else {\n el.setAttribute('data-bc-hidden', '');\n }\n });\n\n // Create the ellipsis element once (guard for SSR — document is unavailable server-side)\n if (!this._ellipsisItem && typeof document !== 'undefined') {\n const ellipsis = document.createElement('hx-breadcrumb-item');\n ellipsis.classList.add('hx-bc-ellipsis');\n\n // Keyboard-accessible expand button. Events handled via host-level delegation\n // in _handleEllipsisClick / _handleEllipsisKeydown.\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.textContent = '…';\n btn.setAttribute('aria-label', this.labelEllipsis);\n ellipsis.appendChild(btn);\n\n this._ellipsisItem = ellipsis;\n }\n\n // Insert ellipsis after first item only if not already correctly placed\n const firstItem = items[0];\n if (!firstItem || !this._ellipsisItem) return;\n if (this._ellipsisItem.previousElementSibling !== firstItem) {\n firstItem.after(this._ellipsisItem);\n }\n }\n\n /** @internal */\n private _removeCollapse(items: Element[]): void {\n items.forEach((item) => {\n (item as HTMLElement).removeAttribute('data-bc-hidden');\n });\n\n if (this._ellipsisItem?.isConnected) {\n this._ellipsisItem.remove();\n }\n }\n\n /** @internal */\n private _handleEllipsisClick(e: Event): void {\n if ((e.target as Element)?.closest?.('.hx-bc-ellipsis')) {\n this._expandBreadcrumb();\n }\n }\n\n /** @internal */\n private _handleEllipsisKeydown(e: Event): void {\n if (!(e instanceof KeyboardEvent)) return;\n if (e.key === 'Enter' || e.key === ' ') {\n if ((e.target as Element)?.closest?.('.hx-bc-ellipsis')) {\n e.preventDefault();\n this._expandBreadcrumb();\n }\n }\n }\n\n /**\n * Expands a collapsed breadcrumb by resetting maxItems to 0.\n * Called by the ellipsis expand button (click or Enter/Space).\n * @internal\n */\n private _expandBreadcrumb(): void {\n this.maxItems = 0;\n // updated() will detect the maxItems change and call _removeCollapse.\n }\n\n // ─── JSON-LD ───\n\n /**\n * JSON-LD ListItem entry with typed fields to avoid Record<string, unknown>.\n * @internal\n */\n private _buildListItem(item: Element, position: number): JsonLdListItem {\n const href = (item as HTMLElement).getAttribute('href');\n const name = (item as HTMLElement).textContent?.trim() ?? '';\n const entry: JsonLdListItem = {\n '@type': 'ListItem',\n position,\n name,\n };\n if (href) entry.item = href;\n return entry;\n }\n\n /** @internal */\n private _updateJsonLd(items: Element[]): void {\n const schema = {\n '@context': 'https://schema.org',\n '@type': 'BreadcrumbList',\n itemListElement: items.map((item, i) => this._buildListItem(item, i + 1)),\n };\n\n // Guard for SSR — document is unavailable server-side\n if (typeof document === 'undefined') return;\n\n if (!this._jsonLdScript) {\n // Dedup guard: remove any stale script with this instance's ID before\n // creating a fresh one. This handles the edge case where the element was\n // reconnected to the DOM after being disconnected without the script\n // reference being re-established.\n document.getElementById(this._jsonLdId)?.remove();\n\n this._jsonLdScript = document.createElement('script');\n this._jsonLdScript.type = 'application/ld+json';\n this._jsonLdScript.id = this._jsonLdId;\n this._jsonLdScript.setAttribute('data-hx-breadcrumb', '');\n document.head.appendChild(this._jsonLdScript);\n }\n\n this._jsonLdScript.textContent = JSON.stringify(schema);\n }\n\n /** @internal */\n private _removeJsonLd(): void {\n this._jsonLdScript?.remove();\n this._jsonLdScript = null;\n }\n\n // ─── Lifecycle ───\n\n override connectedCallback(): void {\n super.connectedCallback();\n // Expose role=\"list\" on the host element so that axe-core's flat-tree\n // traversal sees a valid list ancestor for the hx-breadcrumb-item\n // children that carry role=\"listitem\". The shadow-DOM <ol> owns the\n // visual list structure, but the composed accessibility tree requires\n // the ARIA role on the host to satisfy the aria-required-parent rule.\n if (!this.hasAttribute('role')) {\n this.setAttribute('role', 'list');\n }\n this.addEventListener('click', this._boundEllipsisClick);\n this.addEventListener('keydown', this._boundEllipsisKeydown);\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n this.removeEventListener('click', this._boundEllipsisClick);\n this.removeEventListener('keydown', this._boundEllipsisKeydown);\n this._removeJsonLd();\n }\n\n override updated(changedProperties: PropertyValues<this>): void {\n super.updated(changedProperties);\n\n if (changedProperties.has('separator')) {\n // JSON.stringify wraps the string in quotes so the value is valid\n // for use in the CSS `content` property (e.g. '/' becomes '\"/\"').\n this.style.setProperty('--hx-breadcrumb-separator-content', JSON.stringify(this.separator));\n }\n\n if (changedProperties.has('maxItems')) {\n // Re-evaluate collapse state when maxItems changes programmatically\n // (e.g. when the expand button resets maxItems to 0).\n const slot = this.shadowRoot?.querySelector<HTMLSlotElement>('slot:not([name])');\n if (slot) {\n const items = this._getBreadcrumbItems(slot);\n if (this.maxItems > 0 && items.length > this.maxItems) {\n this._applyCollapse(items);\n } else {\n this._removeCollapse(items);\n }\n this._applyItemAttributes(items);\n }\n }\n\n if (changedProperties.has('jsonLd')) {\n if (this.jsonLd) {\n // json-ld toggled on after initial render — inject script immediately.\n const slot = this.shadowRoot?.querySelector<HTMLSlotElement>('slot:not([name])');\n if (slot) {\n this._updateJsonLd(this._getBreadcrumbItems(slot));\n }\n } else {\n // json-ld toggled off — remove existing script.\n this._removeJsonLd();\n }\n }\n }\n\n // ─── Render ───\n\n override render() {\n return html`\n <nav part=\"nav\" aria-label=${this.label}>\n <ol part=\"list\">\n <slot @slotchange=${this._handleSlotChange}></slot>\n </ol>\n </nav>\n <slot\n name=\"separator\"\n class=\"separator-slot\"\n @slotchange=${this._handleSeparatorSlotChange}\n ></slot>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-breadcrumb': HelixBreadcrumb;\n }\n}\n","import { css } from 'lit';\n\nexport const helixBreadcrumbItemStyles = css`\n :host {\n display: inline-flex;\n align-items: center;\n }\n\n /*\n * display: contents removes [part='item'] from the box model entirely.\n * This is intentional — the wrapper exists only for slot selection purposes.\n * Consumers using ::part(item) CANNOT apply box-model properties (padding,\n * margin, background, border) to this part. Use ::part(link) or ::part(text)\n * for visual styling of breadcrumb item content.\n */\n [part='item'] {\n display: contents;\n }\n\n [part='link'] {\n color: var(--hx-breadcrumb-link-color, var(--hx-color-primary-600));\n text-decoration: none;\n cursor: pointer;\n font-family: inherit;\n font-size: inherit;\n max-width: var(--hx-breadcrumb-item-max-width);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n [part='link']:hover {\n color: var(--hx-breadcrumb-link-hover-color, var(--hx-color-primary-700));\n text-decoration: underline;\n }\n\n [part='link']:focus-visible {\n outline: var(--hx-focus-ring-width, 2px) solid\n var(\n --hx-breadcrumb-link-focus-ring-color,\n var(--hx-focus-ring-color, var(--hx-color-primary-500))\n );\n outline-offset: var(--hx-focus-ring-offset, 2px);\n border-radius: var(--hx-border-radius-sm, 0.125rem);\n }\n\n [part='text'] {\n color: var(--hx-breadcrumb-text-color, var(--hx-color-neutral-700));\n font-family: inherit;\n font-size: inherit;\n max-width: var(--hx-breadcrumb-item-max-width);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .separator {\n margin-inline: var(--hx-breadcrumb-separator-gap, var(--hx-space-1, 0.25rem));\n color: var(--hx-breadcrumb-separator-color, var(--hx-color-neutral-400));\n user-select: none;\n }\n\n .separator::before {\n content: var(--hx-breadcrumb-separator-content, '/');\n }\n\n /* Normalize buttons slotted into breadcrumb items (e.g. the expand-ellipsis button). */\n ::slotted(button) {\n background: none;\n border: none;\n cursor: pointer;\n font: inherit;\n color: inherit;\n padding: 0;\n }\n`;\n","import { LitElement, html, nothing } from 'lit';\nimport '../../utilities/document-token-adoption.js';\nimport { customElement, property } from 'lit/decorators.js';\nimport { helixBreadcrumbItemStyles } from './hx-breadcrumb-item.styles.js';\n\n/**\n * A single breadcrumb navigation item.\n *\n * @summary A navigation item within an hx-breadcrumb component. Renders as a link when `href` is\n * provided, or as static text for the current page item. The current page item is determined by\n * the `current` attribute (set explicitly or automatically by the parent `hx-breadcrumb`).\n *\n * @tag hx-breadcrumb-item\n *\n * @slot - The link or page text content. Accepts text, HTML, or icon elements.\n *\n * @csspart item - Wrapper around the link or text content.\n * @csspart link - The anchor element when href is provided (non-current items only).\n * @csspart text - The span element for the current page or items without href.\n * @csspart separator - The separator element rendered after non-last items.\n *\n * @cssprop [--hx-breadcrumb-link-color=var(--hx-color-primary-600)] - Link text color.\n * @cssprop [--hx-breadcrumb-link-hover-color=var(--hx-color-primary-700)] - Link hover text color.\n * @cssprop [--hx-breadcrumb-text-color=var(--hx-color-neutral-700)] - Current page text color.\n * @cssprop [--hx-breadcrumb-separator-content='/'] - Separator character displayed after non-last items.\n * @cssprop [--hx-breadcrumb-separator-color=var(--hx-color-neutral-400)] - Separator color.\n * @cssprop [--hx-breadcrumb-separator-gap=var(--hx-space-1)] - Horizontal margin around separator.\n * @cssprop [--hx-breadcrumb-item-max-width] - Optional max-width for text truncation.\n * @cssprop [--hx-breadcrumb-link-focus-ring-color=var(--hx-focus-ring-color, var(--hx-color-primary-500))] - Focus ring color for breadcrumb links.\n */\n@customElement('hx-breadcrumb-item')\nexport class HelixBreadcrumbItem extends LitElement {\n static override styles = [helixBreadcrumbItemStyles];\n\n override connectedCallback(): void {\n super.connectedCallback();\n // Only apply role=\"listitem\" when this item is a direct child of an\n // hx-breadcrumb element. Setting the role unconditionally when used\n // standalone (outside a list context) creates an invalid ARIA hierarchy\n // because listitem requires a list ancestor.\n //\n // hx-breadcrumb sets role=\"list\" on its host element so that axe-core's\n // flat-tree traversal (used by @axe-core/playwright) sees a valid list\n // ancestor for these listitems. The shadow-DOM <ol> owns the visual\n // structure; the host role satisfies the ARIA required-parent rule in\n // the composed/flat accessibility tree.\n //\n // IMPORTANT: If programmatically creating an ellipsis element, set aria-hidden\n // BEFORE inserting into the DOM. connectedCallback fires on insertion and sets\n // role=\"listitem\"; setting aria-hidden after would momentarily expose an\n // un-hidden listitem to the accessibility tree.\n if (this.closest('hx-breadcrumb') !== null) {\n this.setAttribute('role', 'listitem');\n } else {\n this.removeAttribute('role');\n }\n }\n\n /**\n * The URL for this breadcrumb link. Omit for the current page item.\n * When `current` is true, this attribute is ignored and the item always\n * renders as static text per WAI-ARIA APG breadcrumb guidance.\n * @attr href\n */\n @property({ type: String, reflect: true })\n href: string | undefined = undefined;\n\n /**\n * Whether this is the last item in the breadcrumb trail. Set by the parent\n * hx-breadcrumb component via the `data-bc-last` boolean attribute. When\n * present the trailing separator is hidden.\n *\n * @attr data-bc-last\n * @internal\n */\n @property({ type: Boolean, attribute: 'data-bc-last', reflect: true })\n dataBcLast = false;\n\n /**\n * Marks this item as the current page. When set, the item always renders as\n * static text (never a navigable link) and `aria-current=\"page\"` is placed on\n * the inner text element per WAI-ARIA APG breadcrumb guidance, yielding the\n * canonical AT announcement (\"current page, Patient Records\").\n *\n * Can be set explicitly by consumers (e.g. Drupal Twig templates) to override\n * the default positional last-item detection in `hx-breadcrumb`. When any item\n * in the breadcrumb has an explicit `current` attribute, the parent will not\n * override it.\n *\n * @attr current\n */\n @property({ type: Boolean, reflect: true })\n current = false;\n\n override render() {\n // Per WAI-ARIA APG, the current page item MUST NOT be a navigable link.\n // aria-current=\"page\" is placed on the inner element (not the listitem host)\n // for canonical AT announcement (\"current page, Patient Records\" vs\n // \"current page, list item\").\n return html`\n <span part=\"item\">\n ${this.current\n ? html`<span part=\"text\" aria-current=\"page\"><slot></slot></span>`\n : this.href\n ? html`<a part=\"link\" href=${this.href}><slot></slot></a>`\n : html`<span part=\"text\"><slot></slot></span>`}\n </span>\n ${!this.dataBcLast\n ? html`<span class=\"separator\" part=\"separator\" aria-hidden=\"true\"></span>`\n : nothing}\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-breadcrumb-item': HelixBreadcrumbItem;\n }\n}\n"],"names":["helixBreadcrumbStyles","css","HelixBreadcrumb","LitElement","e","slot","el","items","hasExplicitCurrent","item","isLast","assigned","text","_a","ellipsis","btn","firstItem","_b","position","href","name","entry","schema","i","changedProperties","html","__decorateClass","property","customElement","helixBreadcrumbItemStyles","HelixBreadcrumbItem","nothing"],"mappings":"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"}
@@ -1,12 +1,13 @@
1
1
  import { css as k, nothing as s, html as d } from "lit";
2
2
  import "./document-token-adoption-DuYNKd4k.js";
3
- import { property as c, query as v, state as p, customElement as m } from "lit/decorators.js";
3
+ import { property as c, query as m, state as p, customElement as v } from "lit/decorators.js";
4
4
  import { classMap as _ } from "lit/directives/class-map.js";
5
5
  import { ifDefined as l } from "lit/directives/if-defined.js";
6
6
  import { live as b } from "lit/directives/live.js";
7
7
  import { F as u } from "./FormMixin-Bjvw20G5.js";
8
8
  import { m as f } from "./aria-delegation-CBP9eQ0M.js";
9
- import { c as g, H as y } from "./id-counter-JhvVCnjh.js";
9
+ import { c as g } from "./id-counter-PTgF-zcG.js";
10
+ import { H as y } from "./helix-element-CZvaIEQP.js";
10
11
  const z = k`
11
12
  :host {
12
13
  display: block;
@@ -425,7 +426,7 @@ o([
425
426
  c({ type: String, attribute: "hx-size", reflect: !0 })
426
427
  ], r.prototype, "size", 2);
427
428
  o([
428
- v(".checkbox__input")
429
+ m(".checkbox__input")
429
430
  ], r.prototype, "_inputEl", 2);
430
431
  o([
431
432
  p()
@@ -434,9 +435,9 @@ o([
434
435
  p()
435
436
  ], r.prototype, "_announcedError", 2);
436
437
  r = o([
437
- m("hx-checkbox")
438
+ v("hx-checkbox")
438
439
  ], r);
439
440
  export {
440
441
  r as H
441
442
  };
442
- //# sourceMappingURL=hx-checkbox-CTEZ9IFq.js.map
443
+ //# sourceMappingURL=hx-checkbox-C82GjRXe.js.map