@helixui/library 2.1.2-next.48 → 2.1.2-next.50
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/custom-elements.json +5 -5
- package/dist/components/hx-breadcrumb/hx-breadcrumb.d.ts.map +1 -1
- package/dist/components/hx-breadcrumb/index.js +1 -1
- package/dist/components/hx-checkbox/index.js +1 -1
- package/dist/components/hx-clinical-status/hx-clinical-status.d.ts +7 -0
- package/dist/components/hx-clinical-status/hx-clinical-status.d.ts.map +1 -1
- package/dist/components/hx-clinical-status/index.js +1 -1
- package/dist/components/hx-code-snippet/hx-code-snippet.d.ts +3 -2
- package/dist/components/hx-code-snippet/hx-code-snippet.d.ts.map +1 -1
- package/dist/components/hx-code-snippet/index.js +1 -1
- package/dist/components/hx-color-picker/hx-color-picker.d.ts +6 -10
- package/dist/components/hx-color-picker/hx-color-picker.d.ts.map +1 -1
- package/dist/components/hx-color-picker/hx-color-picker.styles.d.ts.map +1 -1
- package/dist/components/hx-color-picker/index.js +1 -1
- package/dist/components/hx-container/hx-container.styles.d.ts.map +1 -1
- package/dist/components/hx-container/index.js +1 -1
- package/dist/components/hx-link/hx-link.d.ts +2 -0
- package/dist/components/hx-link/hx-link.d.ts.map +1 -1
- package/dist/components/hx-link/index.js +1 -1
- package/dist/components/hx-patient-banner/hx-patient-banner.d.ts.map +1 -1
- package/dist/components/hx-progress-ring/index.js +1 -1
- package/dist/components/hx-select/hx-select.styles.d.ts.map +1 -1
- package/dist/components/hx-select/index.js +1 -1
- package/dist/components/hx-skeleton/hx-skeleton.d.ts +1 -1
- package/dist/components/hx-skeleton/index.js +1 -1
- package/dist/components/hx-spinner/index.js +1 -1
- package/dist/components/hx-style-scope/hx-style-scope.d.ts +2 -2
- package/dist/components/hx-style-scope/hx-style-scope.d.ts.map +1 -1
- package/dist/components/hx-text-input/index.js +1 -1
- package/dist/css/helix-all.css +9 -17
- package/dist/css/helix-core.css +5 -5
- package/dist/css/helix-feedback.css +3 -3
- package/dist/css/helix-forms.css +1 -3
- package/dist/css/helix-layout.css +0 -6
- package/dist/css/hx-color-picker.css +1 -1
- package/dist/css/hx-container.css +0 -6
- package/dist/css/hx-link.css +1 -1
- package/dist/css/hx-progress-ring.css +3 -3
- package/dist/css/hx-select.css +0 -2
- package/dist/css/hx-skeleton.css +1 -1
- package/dist/css/hx-spinner.css +3 -3
- package/dist/css/index.css +1 -1
- package/dist/css/manifest.json +2 -2
- package/dist/index.js +16 -15
- package/dist/index.js.map +1 -1
- package/dist/shared/{id-counter-JhvVCnjh.js → helix-element-CZvaIEQP.js} +19 -31
- package/dist/shared/helix-element-CZvaIEQP.js.map +1 -0
- package/dist/shared/{hx-breadcrumb-item-DzLyeL5Z.js → hx-breadcrumb-item-jLAKK038.js} +2 -2
- package/dist/shared/hx-breadcrumb-item-jLAKK038.js.map +1 -0
- package/dist/shared/{hx-checkbox-CTEZ9IFq.js → hx-checkbox-C82GjRXe.js} +6 -5
- package/dist/shared/{hx-checkbox-CTEZ9IFq.js.map → hx-checkbox-C82GjRXe.js.map} +1 -1
- package/dist/shared/{hx-clinical-status-m4soOOwg.js → hx-clinical-status-BjtT5c0M.js} +24 -23
- package/dist/shared/hx-clinical-status-BjtT5c0M.js.map +1 -0
- package/dist/shared/{hx-code-snippet-CoLYvX1Z.js → hx-code-snippet-DcVENSuC.js} +6 -5
- package/dist/shared/hx-code-snippet-DcVENSuC.js.map +1 -0
- package/dist/shared/{hx-color-picker-DhOaNe6-.js → hx-color-picker-C6EIuS9t.js} +47 -46
- package/dist/shared/hx-color-picker-C6EIuS9t.js.map +1 -0
- package/dist/shared/{hx-container-31QT9KV_.js → hx-container-BwWbMPTH.js} +5 -11
- package/dist/shared/hx-container-BwWbMPTH.js.map +1 -0
- package/dist/shared/{hx-link-B8IwUMSc.js → hx-link-CN7AvGOW.js} +29 -24
- package/dist/shared/hx-link-CN7AvGOW.js.map +1 -0
- package/dist/shared/hx-patient-banner-BKiN7nIE.js.map +1 -1
- package/dist/shared/{hx-progress-ring-BJeiDr3q.js → hx-progress-ring-Cs0WgWDJ.js} +4 -4
- package/dist/shared/hx-progress-ring-Cs0WgWDJ.js.map +1 -0
- package/dist/shared/{hx-select-B5wq9Swh.js → hx-select-CgcgsHU5.js} +3 -4
- package/dist/shared/hx-select-CgcgsHU5.js.map +1 -0
- package/dist/shared/{hx-skeleton-e5K9Qaxq.js → hx-skeleton-tiYvKO-t.js} +11 -11
- package/dist/shared/hx-skeleton-tiYvKO-t.js.map +1 -0
- package/dist/shared/{hx-spinner-Dyese1Tb.js → hx-spinner-D6nzuGmj.js} +8 -8
- package/dist/shared/hx-spinner-D6nzuGmj.js.map +1 -0
- package/dist/shared/hx-style-scope-CsQ2Phf_.js.map +1 -1
- package/dist/shared/{hx-text-input-Scyeefec.js → hx-text-input-Zuodg9s_.js} +3 -2
- package/dist/shared/{hx-text-input-Scyeefec.js.map → hx-text-input-Zuodg9s_.js.map} +1 -1
- package/dist/shared/id-counter-PTgF-zcG.js +15 -0
- package/dist/shared/id-counter-PTgF-zcG.js.map +1 -0
- package/package.json +2 -2
- package/dist/shared/hx-breadcrumb-item-DzLyeL5Z.js.map +0 -1
- package/dist/shared/hx-clinical-status-m4soOOwg.js.map +0 -1
- package/dist/shared/hx-code-snippet-CoLYvX1Z.js.map +0 -1
- package/dist/shared/hx-color-picker-DhOaNe6-.js.map +0 -1
- package/dist/shared/hx-container-31QT9KV_.js.map +0 -1
- package/dist/shared/hx-link-B8IwUMSc.js.map +0 -1
- package/dist/shared/hx-progress-ring-BJeiDr3q.js.map +0 -1
- package/dist/shared/hx-select-B5wq9Swh.js.map +0 -1
- package/dist/shared/hx-skeleton-e5K9Qaxq.js.map +0 -1
- package/dist/shared/hx-spinner-Dyese1Tb.js.map +0 -1
- package/dist/shared/id-counter-JhvVCnjh.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"hx-color-picker-DhOaNe6-.js","sources":["../../src/components/hx-color-picker/hx-color-picker.styles.ts","../../src/components/hx-color-picker/color-utils.ts","../../src/components/hx-color-picker/hx-color-picker.ts"],"sourcesContent":["import { css } from 'lit';\n\n// prettier-ignore\nexport const helixColorPickerStyles = css`: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}}`;\n","// ─── Color utility types ──────────────────────────────────────────────────────\n\nexport interface HSV {\n h: number; // 0-360\n s: number; // 0-100\n v: number; // 0-100\n a: number; // 0-1\n}\n\nexport interface RGB {\n r: number; // 0-255\n g: number; // 0-255\n b: number; // 0-255\n a: number; // 0-1\n}\n\nexport type ColorFormat = 'hex' | 'rgb' | 'hsl' | 'hsv';\n\n// ─── Color utilities ──────────────────────────────────────────────────────────\n\nexport function clamp(n: number, min: number, max: number): number {\n return Math.max(min, Math.min(max, n));\n}\n\nexport function hexToRgb(hex: string): RGB | null {\n let h = hex.trim().replace(/^#/, '');\n if (h.length === 3) h = h.replace(/(.)/g, '$1$1');\n if (h.length === 4) h = h.replace(/(.)/g, '$1$1');\n if (h.length === 6) h += 'ff';\n if (h.length !== 8) return null;\n const n = parseInt(h, 16);\n if (isNaN(n)) return null;\n return {\n r: (n >>> 24) & 0xff,\n g: (n >>> 16) & 0xff,\n b: (n >>> 8) & 0xff,\n a: (n & 0xff) / 255,\n };\n}\n\nfunction toHex2(n: number): string {\n return Math.round(clamp(n, 0, 255))\n .toString(16)\n .padStart(2, '0');\n}\n\nexport function rgbToHex(rgb: RGB, includeAlpha: boolean): string {\n const base = `#${toHex2(rgb.r)}${toHex2(rgb.g)}${toHex2(rgb.b)}`;\n if (includeAlpha && rgb.a < 1) return base + toHex2(rgb.a * 255);\n return base;\n}\n\nexport function rgbToHsv(rgb: RGB): HSV {\n const r = rgb.r / 255;\n const g = rgb.g / 255;\n const b = rgb.b / 255;\n const max = Math.max(r, g, b);\n const min = Math.min(r, g, b);\n const d = max - min;\n const s = max === 0 ? 0 : d / max;\n const v = max;\n let h = 0;\n if (d !== 0) {\n if (max === r) h = ((g - b) / d + (g < b ? 6 : 0)) / 6;\n else if (max === g) h = ((b - r) / d + 2) / 6;\n else h = ((r - g) / d + 4) / 6;\n }\n return { h: h * 360, s: s * 100, v: v * 100, a: rgb.a };\n}\n\nexport function hsvToRgb(hsv: HSV): RGB {\n const h = hsv.h / 360;\n const s = hsv.s / 100;\n const v = hsv.v / 100;\n const i = Math.floor(h * 6);\n const f = h * 6 - i;\n const p = v * (1 - s);\n const q = v * (1 - f * s);\n const t = v * (1 - (1 - f) * s);\n let r = 0;\n let g = 0;\n let b = 0;\n switch (i % 6) {\n case 0:\n r = v;\n g = t;\n b = p;\n break;\n case 1:\n r = q;\n g = v;\n b = p;\n break;\n case 2:\n r = p;\n g = v;\n b = t;\n break;\n case 3:\n r = p;\n g = q;\n b = v;\n break;\n case 4:\n r = t;\n g = p;\n b = v;\n break;\n case 5:\n r = v;\n g = p;\n b = q;\n break;\n }\n return { r: Math.round(r * 255), g: Math.round(g * 255), b: Math.round(b * 255), a: hsv.a };\n}\n\nexport function rgbToHsl(rgb: RGB): { h: number; s: number; l: number; a: number } {\n const r = rgb.r / 255;\n const g = rgb.g / 255;\n const b = rgb.b / 255;\n const max = Math.max(r, g, b);\n const min = Math.min(r, g, b);\n const l = (max + min) / 2;\n let h = 0;\n let s = 0;\n if (max !== min) {\n const d = max - min;\n s = l > 0.5 ? d / (2 - max - min) : d / (max + min);\n if (max === r) h = ((g - b) / d + (g < b ? 6 : 0)) / 6;\n else if (max === g) h = ((b - r) / d + 2) / 6;\n else h = ((r - g) / d + 4) / 6;\n }\n return { h: h * 360, s: s * 100, l: l * 100, a: rgb.a };\n}\n\n// P2-1: parseColor handles HSV/HSVA input strings for round-trip correctness\nexport function parseColor(value: string): HSV | null {\n if (!value) return null;\n\n if (value.startsWith('#')) {\n const rgb = hexToRgb(value);\n return rgb ? rgbToHsv(rgb) : null;\n }\n\n const rgbMatch = value.match(\n /rgba?\\(\\s*(\\d+)(?:\\s*,\\s*|\\s+)(\\d+)(?:\\s*,\\s*|\\s+)(\\d+)(?:\\s*(?:\\/|,)\\s*([\\d.]+))?\\s*\\)/,\n );\n if (rgbMatch) {\n const [, rm1, rm2, rm3, rm4] = rgbMatch;\n return rgbToHsv({\n r: parseInt(rm1 ?? '0', 10),\n g: parseInt(rm2 ?? '0', 10),\n b: parseInt(rm3 ?? '0', 10),\n a: rm4 !== undefined ? parseFloat(rm4) : 1,\n });\n }\n\n const hslMatch = value.match(\n /hsla?\\(\\s*([\\d.]+)(?:\\s*,\\s*|\\s+)([\\d.]+)%(?:\\s*,\\s*|\\s+)([\\d.]+)%(?:\\s*(?:\\/|,)\\s*([\\d.]+))?\\s*\\)/,\n );\n if (hslMatch) {\n const [, hm1, hm2, hm3, hm4] = hslMatch;\n const h = parseFloat(hm1 ?? '0');\n const s = parseFloat(hm2 ?? '0') / 100;\n const l = parseFloat(hm3 ?? '0') / 100;\n const a = hm4 !== undefined ? parseFloat(hm4) : 1;\n const c = (1 - Math.abs(2 * l - 1)) * s;\n const x = c * (1 - Math.abs(((h / 60) % 2) - 1));\n const m = l - c / 2;\n let r = 0;\n let g = 0;\n let b = 0;\n if (h < 60) {\n r = c;\n g = x;\n } else if (h < 120) {\n r = x;\n g = c;\n } else if (h < 180) {\n g = c;\n b = x;\n } else if (h < 240) {\n g = x;\n b = c;\n } else if (h < 300) {\n r = x;\n b = c;\n } else {\n r = c;\n b = x;\n }\n return rgbToHsv({\n r: Math.round((r + m) * 255),\n g: Math.round((g + m) * 255),\n b: Math.round((b + m) * 255),\n a,\n });\n }\n\n // P2-1: Support HSV/HSVA input strings (component's own output format)\n const hsvMatch = value.match(\n /hsva?\\(\\s*([\\d.]+)\\s*,\\s*([\\d.]+)%\\s*,\\s*([\\d.]+)%(?:\\s*,\\s*([\\d.]+))?\\s*\\)/,\n );\n if (hsvMatch) {\n const [, hm1, hm2, hm3, hm4] = hsvMatch;\n return {\n h: parseFloat(hm1 ?? '0'),\n s: parseFloat(hm2 ?? '0'),\n v: parseFloat(hm3 ?? '0'),\n a: hm4 !== undefined ? parseFloat(hm4) : 1,\n };\n }\n\n return null;\n}\n\nexport function formatColor(hsv: HSV, format: ColorFormat, includeAlpha: boolean): string {\n const rgb = hsvToRgb(hsv);\n switch (format) {\n case 'hex':\n return rgbToHex(rgb, includeAlpha);\n case 'rgb': {\n if (includeAlpha && hsv.a < 1) {\n return `rgb(${rgb.r} ${rgb.g} ${rgb.b} / ${Math.round(hsv.a * 100) / 100})`;\n }\n return `rgb(${rgb.r} ${rgb.g} ${rgb.b})`;\n }\n case 'hsl': {\n const hsl = rgbToHsl(rgb);\n if (includeAlpha && hsv.a < 1) {\n return `hsl(${Math.round(hsl.h)} ${Math.round(hsl.s)}% ${Math.round(hsl.l)}% / ${Math.round(hsv.a * 100) / 100})`;\n }\n return `hsl(${Math.round(hsl.h)} ${Math.round(hsl.s)}% ${Math.round(hsl.l)}%)`;\n }\n case 'hsv': {\n if (includeAlpha && hsv.a < 1) {\n return `hsva(${Math.round(hsv.h)}, ${Math.round(hsv.s)}%, ${Math.round(hsv.v)}%, ${Math.round(hsv.a * 100) / 100})`;\n }\n return `hsv(${Math.round(hsv.h)}, ${Math.round(hsv.s)}%, ${Math.round(hsv.v)}%)`;\n }\n }\n}\n","import { LitElement, html, nothing, type PropertyValues } from 'lit';\nimport '../../utilities/document-token-adoption.js';\nimport { customElement, property, query, state } from 'lit/decorators.js';\nimport { styleMap } from 'lit/directives/style-map.js';\nimport { helixColorPickerStyles } from './hx-color-picker.styles.js';\nimport {\n type ColorFormat,\n type HSV,\n clamp,\n hsvToRgb,\n parseColor,\n formatColor,\n} from './color-utils.js';\n\n// Re-export ColorFormat so existing consumers using this module path still work\nexport type { ColorFormat };\n\n// ─── Component ────────────────────────────────────────────────────────────────\n\n/**\n * A color picker control with gradient picker, hue/opacity sliders, swatches,\n * and formatted text input. Supports hex, rgb, hsl, and hsv output formats.\n *\n * @summary Color selection control with swatches, gradient picker, and formatted input.\n *\n * @tag hx-color-picker\n *\n * @slot trigger - Custom trigger element. Default: a color swatch button.\n *\n * @fires {CustomEvent<{value: string}>} hx-input - Dispatched while dragging sliders or grid.\n * @fires {CustomEvent<{value: string}>} hx-change - Dispatched when a color is committed.\n *\n * @csspart trigger - The trigger button element.\n * @csspart swatches - The swatch color buttons container.\n * @csspart grid - The 2D saturation/value gradient picker area.\n * @csspart slider - Shared slider container (also on hue-slider and opacity-slider).\n * @csspart hue-slider - The hue slider track.\n * @csspart opacity-slider - The alpha/opacity slider track.\n * @csspart input - The text input area.\n *\n * @cssprop [--hx-color-picker-z-index=1000] - z-index of the popover panel.\n * @cssprop [--hx-color-picker-width=260px] - Width of the picker panel.\n * @cssprop [--hx-color-picker-grid-height=160px] - Height of the gradient grid.\n * @cssprop [--hx-color-picker-thumb-border=#fff] - Border color of slider/grid thumbs.\n * @cssprop [--hx-color-picker-thumb-shadow=rgba(0,0,0,0.3)] - Shadow color of slider/grid thumbs.\n * @cssprop [--hx-color-picker-panel-shadow=rgba(0,0,0,0.15)] - Panel drop-shadow color.\n * @cssprop [--hx-color-picker-swatch-border=rgba(0,0,0,0.1)] - Swatch button border color.\n * @cssprop [--hx-color-picker-swatch-border-hover=rgba(0,0,0,0.3)] - Swatch button border on hover.\n *\n * @example\n * ```html\n * <hx-color-picker value=\"#3b82f6\" format=\"hex\"></hx-color-picker>\n * ```\n *\n * @example Drupal / Twig usage\n * The `swatches` property must be set via JavaScript (Drupal behavior) because arrays\n * cannot be serialized as HTML attributes:\n * ```js\n * // my-theme/js/color-picker-behavior.js\n * Drupal.behaviors.helixColorPicker = {\n * attach(context) {\n * context.querySelectorAll('hx-color-picker[data-swatches]').forEach((el) => {\n * el.swatches = JSON.parse(el.dataset.swatches);\n * });\n * },\n * };\n * ```\n * ```twig\n * <hx-color-picker\n * value=\"{{ color }}\"\n * data-swatches='{{ swatches | json_encode }}'\n * ></hx-color-picker>\n * ```\n */\n@customElement('hx-color-picker')\nexport class HelixColorPicker extends LitElement {\n static override styles = [helixColorPickerStyles];\n\n /**\n * Declares this element as form-associated so it participates in native form submission.\n * @internal\n */\n static formAssociated = true;\n\n /**\n * ElementInternals instance used for form participation and constraint validation.\n * @internal\n */\n private _internals: ElementInternals;\n\n constructor() {\n super();\n /** @internal */\n this._internals = this.attachInternals();\n // P1-1: Store bound references so connectedCallback/disconnectedCallback use the same object\n /** @internal */\n this._boundPointerMove = this._handlePointerMove.bind(this);\n /** @internal */\n this._boundPointerUp = this._handlePointerUp.bind(this);\n /** @internal */\n this._boundDocumentClick = this._handleDocumentClick.bind(this);\n }\n\n // ─── Public Properties ───────────────────────────────────────────────────\n\n /**\n * Current color value as a CSS color string.\n * @attr value\n */\n @property({ type: String, reflect: true })\n value = '#000000';\n\n /**\n * Output format for the color value.\n * @attr format\n */\n @property({ type: String, reflect: true })\n format: ColorFormat = 'hex';\n\n /**\n * Whether to show the alpha/opacity channel slider and include alpha in the output.\n * @attr opacity\n */\n @property({ type: Boolean, reflect: true })\n opacity = false;\n\n /**\n * Array of preset swatch color strings.\n * Set via JS property only — arrays cannot be serialized as HTML attributes.\n * In Drupal/Twig, use a behavior to read `data-swatches` and set this property.\n * See JSDoc example above.\n */\n @property({ attribute: false })\n swatches: string[] = [];\n\n /**\n * When true, hides the gradient grid and sliders, showing only swatches and the input.\n * Useful for compact preset-only color selection UIs.\n * @attr swatches-only\n */\n @property({ type: Boolean, reflect: true, attribute: 'swatches-only' })\n swatchesOnly = false;\n\n /**\n * Whether the control is disabled.\n * @attr disabled\n */\n @property({ type: Boolean, reflect: true })\n disabled = false;\n\n /**\n * Form field name for form participation.\n * @attr name\n */\n @property({ type: String, reflect: true })\n name = '';\n\n /**\n * When true the picker is shown inline instead of in a popover.\n * @attr inline\n */\n @property({ type: Boolean, reflect: true })\n inline = false;\n\n /**\n * When true, the picker requires a non-empty value for form submission.\n * @attr required\n */\n @property({ type: Boolean, reflect: true })\n required = false;\n\n /** Accessible label for the color gradient canvas. */\n @property({ type: String, attribute: 'label-gradient' })\n labelGradient = 'Color gradient';\n\n /** Accessible label for the hue slider. */\n @property({ type: String, attribute: 'label-hue' })\n labelHue = 'Hue';\n\n /** Accessible label for the opacity slider. */\n @property({ type: String, attribute: 'label-opacity' })\n labelOpacity = 'Opacity';\n\n /** Accessible label for the preset color swatches section. */\n @property({ type: String, attribute: 'label-swatches' })\n labelSwatches = 'Preset colors';\n\n /** Accessible label for the format-switch button. */\n @property({ type: String, attribute: 'label-switch-format' })\n labelSwitchFormat = 'Switch color format';\n\n /** Accessible label for the color value input. */\n @property({ type: String, attribute: 'label-color-value' })\n labelColorValue = 'Color value';\n\n /** Accessible label for the color picker dialog/panel. */\n @property({ type: String, attribute: 'label-picker' })\n labelPicker = 'Color picker';\n\n /**\n * Generates the accessible label for the trigger button.\n * @param color - current color value string\n */\n @property({ attribute: false })\n labelTrigger: (color: string) => string = (color) => `Choose color: ${color}`;\n\n // ─── Internal State ──────────────────────────────────────────────────────\n\n /**\n * Internal HSV representation of the current color, used to drive all picker UI elements.\n * @internal\n */\n @state() private _hsv: HSV = { h: 0, s: 0, v: 0, a: 1 };\n /**\n * Whether the color picker popover panel is currently open.\n * @internal\n */\n @state() private _open = false;\n /**\n * The formatted color string displayed in the text input, kept in sync with `_hsv` and `format`.\n * @internal\n */\n @state() private _inputValue = '#000000';\n\n // ─── Cached element references ───────────────────────────────────────────\n\n /** Cached reference to the gradient grid element. @internal */\n @query('[part=\"grid\"]') private _gridEl!: HTMLElement | null;\n /** Cached reference to the hue slider element. @internal */\n @query('[part=\"hue-slider\"]') private _hueSliderEl!: HTMLElement | null;\n /** Cached reference to the opacity slider element. @internal */\n @query('[part=\"opacity-slider\"]') private _opacitySliderEl!: HTMLElement | null;\n\n // ─── Dragging state (not reactive, managed manually) ─────────────────────\n\n /**\n * Whether the user is actively dragging within the gradient grid.\n * @internal\n */\n private _draggingGrid = false;\n /**\n * Whether the user is actively dragging the hue slider thumb.\n * @internal\n */\n private _draggingHue = false;\n /**\n * Whether the user is actively dragging the opacity slider thumb.\n * @internal\n */\n private _draggingOpacity = false;\n\n /**\n * Cached bounding rect from pointerdown; avoids repeated getBoundingClientRect on every pointermove.\n * @internal\n */\n private _dragRect: DOMRect | null = null;\n\n // P1-1: Stored bound references to prevent memory leaks\n /**\n * Stable bound reference to the pointermove handler, stored to allow correct listener removal.\n * @internal\n */\n private _boundPointerMove: (e: PointerEvent) => void;\n /**\n * Stable bound reference to the pointerup handler, stored to allow correct listener removal.\n * @internal\n */\n private _boundPointerUp: () => void;\n /**\n * Stable bound reference to the document click handler, stored to allow correct listener removal.\n * @internal\n */\n private _boundDocumentClick: (e: MouseEvent) => void;\n\n // ─── Lifecycle ───────────────────────────────────────────────────────────\n\n override connectedCallback(): void {\n super.connectedCallback();\n this._syncFromValue();\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n // P1-1: Remove using the same stored references added in connectedCallback\n // Guard for SSR — document is unavailable server-side\n if (typeof document !== 'undefined') {\n document.removeEventListener('click', this._boundDocumentClick, true);\n document.removeEventListener('pointermove', this._boundPointerMove);\n document.removeEventListener('pointerup', this._boundPointerUp);\n }\n }\n\n override willUpdate(changedProperties: PropertyValues<this>): void {\n if (changedProperties.has('value')) {\n this._syncFromValue();\n }\n if (changedProperties.has('required')) {\n this._updateValidity();\n }\n }\n\n // ─── Sync ────────────────────────────────────────────────────────────────\n\n /** @internal */\n private _syncFromValue(): void {\n const parsed = parseColor(this.value);\n if (parsed) {\n this._hsv = parsed;\n }\n this._inputValue = formatColor(this._hsv, this.format, this.opacity);\n this._internals.setFormValue(this.value);\n this._updateValidity();\n }\n\n /** @internal */\n formDisabledCallback(disabled: boolean): void {\n this.disabled = disabled;\n }\n\n /** @internal */\n formResetCallback(): void {\n this.value = '#000000';\n this._internals.setFormValue(null);\n }\n\n /** @internal */\n formStateRestoreCallback(\n state: string | File | FormData | null,\n _mode: 'restore' | 'autocomplete',\n ): void {\n if (typeof state === 'string') {\n this.value = state;\n }\n }\n\n /** Returns the ValidityState object. */\n get validity(): ValidityState {\n return this._internals.validity;\n }\n\n /** Returns the current validation message. */\n get validationMessage(): string {\n return this._internals.validationMessage;\n }\n\n /** Checks whether the picker satisfies its constraints. */\n checkValidity(): boolean {\n return this._internals.checkValidity();\n }\n\n /** Reports validity and shows the browser's constraint validation UI. */\n reportValidity(): boolean {\n return this._internals.reportValidity();\n }\n\n /** @internal */\n private _updateValidity(): void {\n if (this.required && !this.value) {\n this._internals.setValidity(\n { valueMissing: true },\n 'Please select a color.',\n this.shadowRoot?.querySelector<HTMLElement>('[part=\"trigger\"]') ??\n this.shadowRoot?.querySelector<HTMLElement>('[part=\"grid\"]') ??\n undefined,\n );\n } else {\n this._internals.setValidity({});\n }\n }\n\n /** @internal */\n private _commit(source: 'drag' | 'change'): void {\n const formatted = formatColor(this._hsv, this.format, this.opacity);\n this.value = formatted;\n this._inputValue = formatted;\n this._internals.setFormValue(formatted);\n const detail = { value: formatted };\n const opts: CustomEventInit<{ value: string }> = {\n bubbles: true,\n composed: true,\n detail,\n };\n if (source === 'drag') {\n this.dispatchEvent(new CustomEvent<{ value: string }>('hx-input', opts));\n } else {\n this.dispatchEvent(new CustomEvent<{ value: string }>('hx-change', opts));\n }\n }\n\n // ─── Panel open/close ────────────────────────────────────────────────────\n\n /** @internal */\n private _show(): void {\n if (this._open || this.inline) return;\n this._open = true;\n // Guard for SSR — document is unavailable server-side\n if (typeof document !== 'undefined') {\n document.addEventListener('click', this._boundDocumentClick, true);\n }\n // WCAG 2.4.3: move focus into the panel after it renders so keyboard/AT\n // users land on the first interactive element rather than staying on the trigger.\n void this.updateComplete.then(() => {\n const panel = this.shadowRoot?.querySelector<HTMLElement>('.panel');\n // Prefer the color value input; fall back to the panel itself (tabindex=\"-1\").\n const firstFocusable = panel?.querySelector<HTMLElement>('input, button') ?? panel;\n firstFocusable?.focus();\n });\n }\n\n /** @internal */\n private _hide(): void {\n if (!this._open) return;\n this._open = false;\n // Guard for SSR — document is unavailable server-side\n if (typeof document !== 'undefined') {\n document.removeEventListener('click', this._boundDocumentClick, true);\n }\n }\n\n /** @internal */\n private _handleDocumentClick(e: MouseEvent): void {\n if (!this._open) return;\n if (!e.composedPath().includes(this)) {\n this._hide();\n }\n }\n\n /** @internal */\n private _handleTriggerClick(e: MouseEvent): void {\n e.stopPropagation();\n if (this._open) {\n this._hide();\n } else {\n this._show();\n }\n }\n\n /** @internal */\n private _handlePanelKeydown(e: KeyboardEvent): void {\n if (e.key === 'Escape') {\n e.stopPropagation();\n this._hide();\n this.shadowRoot?.querySelector<HTMLElement>('[part=\"trigger\"]')?.focus();\n }\n }\n\n // ─── Gradient grid dragging ───────────────────────────────────────────────\n\n /** @internal */\n private _handleGridPointerDown(e: PointerEvent): void {\n if (this.disabled) return;\n e.preventDefault();\n this._draggingGrid = true;\n // Cache rect at pointerdown — element doesn't move during drag\n this._dragRect = this._gridEl?.getBoundingClientRect() ?? null;\n (e.currentTarget as HTMLElement).setPointerCapture(e.pointerId);\n // Guard for SSR — document is unavailable server-side\n if (typeof document !== 'undefined') {\n document.addEventListener('pointermove', this._boundPointerMove);\n document.addEventListener('pointerup', this._boundPointerUp);\n }\n this._updateGridFromPointer(e);\n }\n\n /** @internal */\n private _updateGridFromPointer(e: PointerEvent): void {\n const rect = this._dragRect ?? this._gridEl?.getBoundingClientRect();\n if (!rect) return;\n const x = clamp((e.clientX - rect.left) / rect.width, 0, 1);\n const y = clamp((e.clientY - rect.top) / rect.height, 0, 1);\n this._hsv = { ...this._hsv, s: x * 100, v: (1 - y) * 100 };\n this._commit('drag');\n this.requestUpdate();\n }\n\n // P0-1: Keyboard support for gradient grid — fixes WCAG 2.1 SC 2.1.1 failure\n /** @internal */\n private _handleGridKeydown(e: KeyboardEvent): void {\n let sDelta = 0;\n let vDelta = 0;\n if (e.key === 'ArrowLeft') sDelta = -1;\n else if (e.key === 'ArrowRight') sDelta = 1;\n else if (e.key === 'ArrowUp') vDelta = 1;\n else if (e.key === 'ArrowDown') vDelta = -1;\n else if (e.key === 'PageUp') vDelta = 10;\n else if (e.key === 'PageDown') vDelta = -10;\n else if (e.key === 'Home') {\n this._hsv = { ...this._hsv, s: 0, v: 100 };\n this._commit('change');\n return;\n } else if (e.key === 'End') {\n this._hsv = { ...this._hsv, s: 100, v: 0 };\n this._commit('change');\n return;\n }\n if (sDelta !== 0 || vDelta !== 0) {\n e.preventDefault();\n this._hsv = {\n ...this._hsv,\n s: clamp(this._hsv.s + sDelta, 0, 100),\n v: clamp(this._hsv.v + vDelta, 0, 100),\n };\n this._commit('change');\n }\n }\n\n // ─── Hue slider dragging ─────────────────────────────────────────────────\n\n /** @internal */\n private _handleHuePointerDown(e: PointerEvent): void {\n if (this.disabled) return;\n e.preventDefault();\n this._draggingHue = true;\n // Cache rect at pointerdown — element doesn't move during drag\n this._dragRect = this._hueSliderEl?.getBoundingClientRect() ?? null;\n (e.currentTarget as HTMLElement).setPointerCapture(e.pointerId);\n // Guard for SSR — document is unavailable server-side\n if (typeof document !== 'undefined') {\n document.addEventListener('pointermove', this._boundPointerMove);\n document.addEventListener('pointerup', this._boundPointerUp);\n }\n this._updateHueFromPointer(e);\n }\n\n /** @internal */\n private _updateHueFromPointer(e: PointerEvent): void {\n const rect = this._dragRect ?? this._hueSliderEl?.getBoundingClientRect();\n if (!rect) return;\n const pct = clamp((e.clientX - rect.left) / rect.width, 0, 1);\n this._hsv = { ...this._hsv, h: pct * 360 };\n this._commit('drag');\n this.requestUpdate();\n }\n\n // ─── Opacity slider dragging ──────────────────────────────────────────────\n\n /** @internal */\n private _handleOpacityPointerDown(e: PointerEvent): void {\n if (this.disabled) return;\n e.preventDefault();\n this._draggingOpacity = true;\n // Cache rect at pointerdown — element doesn't move during drag\n this._dragRect = this._opacitySliderEl?.getBoundingClientRect() ?? null;\n (e.currentTarget as HTMLElement).setPointerCapture(e.pointerId);\n // Guard for SSR — document is unavailable server-side\n if (typeof document !== 'undefined') {\n document.addEventListener('pointermove', this._boundPointerMove);\n document.addEventListener('pointerup', this._boundPointerUp);\n }\n this._updateOpacityFromPointer(e);\n }\n\n /** @internal */\n private _updateOpacityFromPointer(e: PointerEvent): void {\n const rect = this._dragRect ?? this._opacitySliderEl?.getBoundingClientRect();\n if (!rect) return;\n const pct = clamp((e.clientX - rect.left) / rect.width, 0, 1);\n this._hsv = { ...this._hsv, a: pct };\n this._commit('drag');\n this.requestUpdate();\n }\n\n // ─── Document-level pointer handlers ─────────────────────────────────────\n\n /** @internal */\n private _handlePointerMove(e: PointerEvent): void {\n if (this._draggingGrid) this._updateGridFromPointer(e);\n else if (this._draggingHue) this._updateHueFromPointer(e);\n else if (this._draggingOpacity) this._updateOpacityFromPointer(e);\n }\n\n /** @internal */\n private _handlePointerUp(): void {\n if (this._draggingGrid || this._draggingHue || this._draggingOpacity) {\n this._draggingGrid = false;\n this._draggingHue = false;\n this._draggingOpacity = false;\n this._dragRect = null;\n // Guard for SSR — document is unavailable server-side\n if (typeof document !== 'undefined') {\n document.removeEventListener('pointermove', this._boundPointerMove);\n document.removeEventListener('pointerup', this._boundPointerUp);\n }\n this._commit('change');\n }\n }\n\n // ─── Keyboard handling for sliders ───────────────────────────────────────\n\n /** @internal */\n private _handleHueKeydown(e: KeyboardEvent): void {\n let delta = 0;\n if (e.key === 'ArrowLeft' || e.key === 'ArrowDown') delta = -1;\n else if (e.key === 'ArrowRight' || e.key === 'ArrowUp') delta = 1;\n else if (e.key === 'PageDown') delta = -10;\n else if (e.key === 'PageUp') delta = 10;\n else if (e.key === 'Home') {\n this._hsv = { ...this._hsv, h: 0 };\n this._commit('change');\n return;\n } else if (e.key === 'End') {\n this._hsv = { ...this._hsv, h: 360 };\n this._commit('change');\n return;\n }\n if (delta !== 0) {\n e.preventDefault();\n this._hsv = { ...this._hsv, h: clamp(this._hsv.h + delta, 0, 360) };\n this._commit('change');\n }\n }\n\n /** @internal */\n private _handleOpacityKeydown(e: KeyboardEvent): void {\n let delta = 0;\n if (e.key === 'ArrowLeft' || e.key === 'ArrowDown') delta = -0.01;\n else if (e.key === 'ArrowRight' || e.key === 'ArrowUp') delta = 0.01;\n else if (e.key === 'PageDown') delta = -0.1;\n else if (e.key === 'PageUp') delta = 0.1;\n else if (e.key === 'Home') {\n this._hsv = { ...this._hsv, a: 0 };\n this._commit('change');\n return;\n } else if (e.key === 'End') {\n this._hsv = { ...this._hsv, a: 1 };\n this._commit('change');\n return;\n }\n if (delta !== 0) {\n e.preventDefault();\n this._hsv = { ...this._hsv, a: clamp(this._hsv.a + delta, 0, 1) };\n this._commit('change');\n }\n }\n\n // ─── Input ───────────────────────────────────────────────────────────────\n\n // P1-7: Bound to @input (was @change) for real-time color preview while typing\n /** @internal */\n private _handleInputChange(e: Event): void {\n const input = e.target as HTMLInputElement;\n const parsed = parseColor(input.value.trim());\n if (parsed) {\n this._hsv = parsed;\n this._commit('change');\n }\n this._inputValue = input.value;\n }\n\n /** @internal */\n private _handleInputBlur(e: FocusEvent): void {\n const input = e.target as HTMLInputElement;\n const parsed = parseColor(input.value.trim());\n if (parsed) {\n this._hsv = parsed;\n this._commit('change');\n } else {\n // Revert to current valid value\n this._inputValue = formatColor(this._hsv, this.format, this.opacity);\n }\n }\n\n /** @internal */\n private _handleFormatCycle(): void {\n const formats: ColorFormat[] = ['hex', 'rgb', 'hsl', 'hsv'];\n const idx = formats.indexOf(this.format);\n const next = formats[(idx + 1) % formats.length];\n if (next !== undefined) this.format = next;\n this._inputValue = formatColor(this._hsv, this.format, this.opacity);\n }\n\n // ─── Swatches ────────────────────────────────────────────────────────────\n\n /** @internal */\n private _handleSwatchClick(color: string): void {\n const parsed = parseColor(color);\n if (parsed) {\n this._hsv = parsed;\n this._commit('change');\n }\n }\n\n // ─── Computed values ──────────────────────────────────────────────────────\n\n /** @internal */\n private _hueColor(): string {\n return `hsl(${Math.round(this._hsv.h)}, 100%, 50%)`;\n }\n\n /** @internal */\n private _previewColor(): string {\n const rgb = hsvToRgb(this._hsv);\n if (this.opacity && this._hsv.a < 1) {\n return `rgb(${rgb.r} ${rgb.g} ${rgb.b} / ${Math.round(this._hsv.a * 100) / 100})`;\n }\n return `rgb(${rgb.r} ${rgb.g} ${rgb.b})`;\n }\n\n // ─── Render helpers ───────────────────────────────────────────────────────\n\n /** @internal */\n private _renderGrid() {\n const thumbX = `${this._hsv.s}%`;\n const thumbY = `${100 - this._hsv.v}%`;\n const hueColor = this._hueColor();\n\n // P0-1: Grid is now keyboard-operable — WCAG 2.1 SC 2.1.1 compliance\n // Arrow keys adjust saturation (left/right) and value (up/down)\n //\n // A11y note (WCAG 4.1.2 — 2D slider aria-valuenow limitation): The ARIA slider role\n // requires a single numeric aria-valuenow. This 2D control has two axes (saturation and\n // value), so aria-valuenow reports only saturation (the primary/horizontal axis) per\n // the ARIA 1.2 \"slider\" pattern. aria-valuetext compensates by announcing both axes\n // (\"Saturation X%, Value Y%\") for all assistive technologies that support it.\n return html`\n <div\n part=\"grid\"\n class=\"gradient-grid\"\n role=\"slider\"\n tabindex=\"0\"\n aria-label=${this.labelGradient}\n aria-valuemin=\"0\"\n aria-valuemax=\"100\"\n aria-valuenow=${Math.round(this._hsv.s)}\n aria-valuetext=\"Saturation ${Math.round(this._hsv.s)}%, Value ${Math.round(this._hsv.v)}%\"\n @pointerdown=${this._handleGridPointerDown}\n @keydown=${this._handleGridKeydown}\n >\n <div class=\"gradient-grid-bg\" style=${styleMap({ '--_hue-color': hueColor })}></div>\n <div\n class=\"gradient-thumb\"\n style=${styleMap({ '--_thumb-x': thumbX, '--_thumb-y': thumbY })}\n aria-hidden=\"true\"\n ></div>\n </div>\n `;\n }\n\n /** @internal */\n private _renderHueSlider() {\n const pct = `${(this._hsv.h / 360) * 100}%`;\n const hueColor = this._hueColor();\n\n // P1-8: part=\"slider hue-slider\" — exposes the documented shared \"slider\" CSS part\n // P1-4: aria-valuetext announces the hue angle with degree symbol\n return html`\n <div\n part=\"slider hue-slider\"\n class=\"slider-track hue-track\"\n role=\"slider\"\n tabindex=\"0\"\n aria-label=${this.labelHue}\n aria-valuemin=\"0\"\n aria-valuemax=\"360\"\n aria-valuenow=${Math.round(this._hsv.h)}\n aria-valuetext=\"${Math.round(this._hsv.h)}°\"\n @pointerdown=${this._handleHuePointerDown}\n @keydown=${this._handleHueKeydown}\n >\n <div\n class=\"slider-thumb\"\n style=${styleMap({ '--_slider-pct': pct, '--_thumb-color': hueColor })}\n aria-hidden=\"true\"\n ></div>\n </div>\n `;\n }\n\n /** @internal */\n private _renderOpacitySlider() {\n if (!this.opacity) return nothing;\n const pct = `${this._hsv.a * 100}%`;\n const rgb = hsvToRgb(this._hsv);\n const thumbColor = `rgb(${rgb.r} ${rgb.g} ${rgb.b} / ${Math.round(this._hsv.a * 100) / 100})`;\n const hueColor = this._hueColor();\n\n // P1-8: part=\"slider opacity-slider\" — exposes the documented shared \"slider\" CSS part\n // P1-4: aria-valuetext announces the opacity as a percentage\n return html`\n <div\n part=\"slider opacity-slider\"\n class=\"slider-track opacity-track\"\n role=\"slider\"\n tabindex=\"0\"\n aria-label=${this.labelOpacity}\n aria-valuemin=\"0\"\n aria-valuemax=\"100\"\n aria-valuenow=${Math.round(this._hsv.a * 100)}\n aria-valuetext=\"${Math.round(this._hsv.a * 100)}%\"\n style=${styleMap({ '--_hue-color': hueColor })}\n @pointerdown=${this._handleOpacityPointerDown}\n @keydown=${this._handleOpacityKeydown}\n >\n <div\n class=\"slider-thumb\"\n style=${styleMap({ '--_slider-pct': pct, '--_thumb-color': thumbColor })}\n aria-hidden=\"true\"\n ></div>\n </div>\n `;\n }\n\n /** @internal */\n private _renderSwatches() {\n if (!this.swatches?.length) return nothing;\n return html`\n <div part=\"swatches\" class=\"swatches\" role=\"group\" aria-label=${this.labelSwatches}>\n ${this.swatches.map(\n (color) => html`\n <button\n type=\"button\"\n class=\"swatch-btn\"\n style=${styleMap({ background: color })}\n aria-label=${color}\n title=${color}\n @click=${() => this._handleSwatchClick(color)}\n ></button>\n `,\n )}\n </div>\n `;\n }\n\n /** @internal */\n private _renderInput() {\n return html`\n <div part=\"input\" class=\"input-area\">\n <div\n class=\"input-preview\"\n style=${styleMap({ '--_preview-color': this._previewColor() })}\n aria-hidden=\"true\"\n ></div>\n <button\n type=\"button\"\n class=\"format-btn\"\n aria-label=${this.labelSwitchFormat}\n title=\"Switch format\"\n @click=${this._handleFormatCycle}\n >\n ${this.format}\n </button>\n <input\n type=\"text\"\n class=\"color-input\"\n .value=${this._inputValue}\n aria-label=${this.labelColorValue}\n autocomplete=\"off\"\n spellcheck=\"false\"\n @input=${this._handleInputChange}\n @blur=${this._handleInputBlur}\n />\n </div>\n `;\n }\n\n /** @internal */\n private _renderPanel() {\n // A11y fix (WCAG 4.1.2): use role=\"group\" instead of role=\"dialog\" + aria-modal=\"true\".\n // aria-modal=\"true\" requires a programmatic focus trap so screen readers restrict virtual\n // cursor navigation to the dialog. Without Tab-key trapping, aria-modal causes JAWS/NVDA\n // to hide all content outside the panel, stranding keyboard users who Tab out. role=\"group\"\n // with aria-label provides the same grouping semantics without the false modal contract.\n return html`\n <div\n class=\"panel\"\n role=\"group\"\n aria-label=${this.labelPicker}\n tabindex=\"-1\"\n @keydown=${this._handlePanelKeydown}\n >\n ${this.swatchesOnly\n ? nothing\n : html`${this._renderGrid()} ${this._renderHueSlider()} ${this._renderOpacitySlider()}`}\n ${this._renderSwatches()} ${this._renderInput()}\n </div>\n `;\n }\n\n // ─── Main render ─────────────────────────────────────────────────────────\n\n override render() {\n const previewColor = this._previewColor();\n\n if (this.inline) {\n return html`\n <div style=${styleMap({ '--_preview-color': previewColor })}>${this._renderPanel()}</div>\n `;\n }\n\n // P1-3: aria-label includes the current color value so AT users know the selected color\n return html`\n <button\n part=\"trigger\"\n type=\"button\"\n class=\"trigger\"\n aria-label=${this.labelTrigger(this._inputValue)}\n aria-expanded=${this._open ? 'true' : 'false'}\n ?disabled=${this.disabled}\n style=${styleMap({ '--_preview-color': previewColor })}\n @click=${this._handleTriggerClick}\n >\n <slot name=\"trigger\">\n <span class=\"trigger-swatch\" aria-hidden=\"true\"></span>\n <span class=\"trigger-label\">${this._inputValue}</span>\n </slot>\n </button>\n ${this._open ? this._renderPanel() : nothing}\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-color-picker': HelixColorPicker;\n }\n}\n"],"names":["helixColorPickerStyles","css","clamp","n","min","max","hexToRgb","hex","h","toHex2","rgbToHex","rgb","includeAlpha","base","rgbToHsv","r","g","b","d","s","v","hsvToRgb","hsv","i","f","p","q","t","rgbToHsl","l","parseColor","value","rgbMatch","rm1","rm2","rm3","rm4","hslMatch","hm1","hm2","hm3","hm4","a","c","x","m","hsvMatch","formatColor","format","hsl","HelixColorPicker","LitElement","color","changedProperties","parsed","disabled","state","_mode","_a","_b","source","formatted","opts","panel","firstFocusable","e","rect","y","sDelta","vDelta","pct","delta","input","formats","idx","next","thumbX","thumbY","hueColor","html","styleMap","nothing","thumbColor","previewColor","__decorateClass","property","query","customElement"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"hx-container-31QT9KV_.js","sources":["../../src/components/hx-container/hx-container.styles.ts","../../src/components/hx-container/hx-container.ts"],"sourcesContent":["import { css } from 'lit';\n\nexport const helixContainerStyles = css`\n :host {\n display: block;\n contain: layout style;\n width: 100%;\n background-color: var(--hx-container-bg, transparent);\n box-sizing: border-box;\n }\n\n /* ─── Vertical Padding Variants ─── */\n\n /* Defensive reset: ensures zero vertical padding even if a future base rule adds it */\n :host([padding='none']) {\n padding-top: 0;\n padding-bottom: 0;\n }\n\n :host([padding='sm']) {\n padding-top: var(--hx-space-6, 1.5rem);\n padding-bottom: var(--hx-space-6, 1.5rem);\n }\n\n :host([padding='md']) {\n padding-top: var(--hx-space-12, 3rem);\n padding-bottom: var(--hx-space-12, 3rem);\n }\n\n :host([padding='lg']) {\n padding-top: var(--hx-space-16, 4rem);\n padding-bottom: var(--hx-space-16, 4rem);\n }\n\n :host([padding='xl']) {\n padding-top: var(--hx-space-24, 6rem);\n padding-bottom: var(--hx-space-24, 6rem);\n }\n\n :host([padding='2xl']) {\n padding-top: var(--hx-space-32, 8rem);\n padding-bottom: var(--hx-space-32, 8rem);\n }\n\n /* ─── Inner Container ─── */\n\n .container__inner {\n margin-inline-start: auto;\n margin-inline-end: auto;\n padding-inline-start: var(--hx-container-gutter, var(--hx-space-6, 1.5rem));\n padding-inline-end: var(--hx-container-gutter, var(--hx-space-6, 1.5rem));\n box-sizing: border-box;\n width: 100%;\n }\n\n /* ─── Width Variants ─── */\n\n .container__inner--full {\n max-width: none;\n }\n\n .container__inner--content {\n max-width: var(--hx-container-max-width, var(--hx-container-content, 1152px));\n }\n\n .container__inner--narrow {\n max-width: var(--hx-container-max-width, var(--hx-container-narrow, 768px));\n }\n\n .container__inner--sm {\n max-width: var(--hx-container-max-width, var(--hx-container-sm, 640px));\n }\n\n .container__inner--md {\n max-width: var(--hx-container-max-width, var(--hx-container-md, 768px));\n }\n\n .container__inner--lg {\n max-width: var(--hx-container-max-width, var(--hx-container-lg, 1024px));\n }\n\n .container__inner--xl {\n max-width: var(--hx-container-max-width, var(--hx-container-xl, 1280px));\n }\n`;\n","import { LitElement, html } from 'lit';\nimport '../../utilities/document-token-adoption.js';\nimport { customElement, property } from 'lit/decorators.js';\nimport { classMap } from 'lit/directives/class-map.js';\nimport { helixContainerStyles } from './hx-container.styles.js';\n\n/**\n * A layout container that constrains content width and provides\n * consistent vertical spacing and horizontal gutters.\n *\n * Uses a two-layer model: the outer host spans full width (background,\n * vertical padding), while the inner wrapper constrains max-width,\n * centers content, and applies horizontal gutters.\n *\n * ## Accessibility\n *\n * `hx-container` is a purely visual layout primitive with no semantic meaning.\n * It carries no ARIA role and is intentionally transparent to assistive\n * technologies. Screen readers announce the container's children directly,\n * not the container itself.\n *\n * The inner wrapper always centers content horizontally (via `margin: auto`).\n * This is by design for page-layout use cases. If you need non-centered\n * alignment at a specific breakpoint, override `margin-left` and\n * `margin-right` on `::part(inner)` from your stylesheet.\n *\n * @summary Layout primitive for constraining content width with consistent spacing.\n *\n * @tag hx-container\n *\n * @slot - Default slot for container content.\n *\n * @csspart inner - The inner wrapper that constrains max-width and applies gutters.\n *\n * @cssprop [--hx-container-bg=transparent] - Background color on the outer wrapper.\n * @cssprop [--hx-container-gutter=var(--hx-space-6)] - Horizontal padding on the inner box.\n * @cssprop [--hx-container-max-width] - Override the max-width set by the width property.\n * @cssprop [--hx-container-content=72rem] - Max-width for the content width preset.\n * @cssprop [--hx-container-narrow=48rem] - Max-width for the narrow width preset.\n * @cssprop [--hx-container-sm=640px] - Max-width for the sm width preset.\n * @cssprop [--hx-container-md=768px] - Max-width for the md width preset.\n * @cssprop [--hx-container-lg=1024px] - Max-width for the lg width preset.\n * @cssprop [--hx-container-xl=1280px] - Max-width for the xl width preset.\n */\n@customElement('hx-container')\nexport class HelixContainer extends LitElement {\n static override styles = [helixContainerStyles];\n\n /**\n * Controls the max-width of the inner content wrapper.\n * @attr width\n * @example\n * // Width presets and their default max-width values:\n * // full → no max-width constraint\n * // content → 72rem (1152px)\n * // narrow → 48rem (768px) — override with --hx-container-narrow\n * // sm → 640px — override with --hx-container-sm\n * // md → 768px — override with --hx-container-md\n * // lg → 1024px — override with --hx-container-lg\n * // xl → 1280px — override with --hx-container-xl\n */\n @property({ type: String, reflect: true })\n width: 'full' | 'content' | 'narrow' | 'sm' | 'md' | 'lg' | 'xl' = 'content';\n\n /**\n * Vertical padding applied to the outer wrapper.\n * @attr padding\n */\n @property({ type: String, reflect: true })\n padding: 'none' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' = 'none';\n\n // ─── Render ───\n\n override render() {\n const classes = {\n container__inner: true,\n [`container__inner--${this.width}`]: true,\n };\n\n return html`\n <div part=\"inner\" class=${classMap(classes)}>\n <slot></slot>\n </div>\n `;\n }\n}\n\n/** Canonical type alias for the hx-container component. */\nexport type HxContainer = HelixContainer;\n\n/** @deprecated Use {@link HxContainer} instead. The `Wc` prefix was a legacy naming convention. */\nexport type WcContainer = HelixContainer;\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-container': HelixContainer;\n }\n}\n"],"names":["helixContainerStyles","css","HelixContainer","LitElement","classes","html","classMap","__decorateClass","property","customElement"],"mappings":";;;;AAEO,MAAMA,IAAuBC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;;;;AC2C7B,IAAMC,IAAN,cAA6BC,EAAW;AAAA,EAAxC,cAAA;AAAA,UAAA,GAAA,SAAA,GAiBL,KAAA,QAAmE,WAOnE,KAAA,UAAsD;AAAA,EAAA;AAAA;AAAA,EAI7C,SAAS;AAChB,UAAMC,IAAU;AAAA,MACd,kBAAkB;AAAA,MAClB,CAAC,qBAAqB,KAAK,KAAK,EAAE,GAAG;AAAA,IAAA;AAGvC,WAAOC;AAAA,gCACqBC,EAASF,CAAO,CAAC;AAAA;AAAA;AAAA;AAAA,EAI/C;AACF;AAxCaF,EACK,SAAS,CAACF,CAAoB;AAgB9CO,EAAA;AAAA,EADCC,EAAS,EAAE,MAAM,QAAQ,SAAS,IAAM;AAAA,GAhB9BN,EAiBX,WAAA,SAAA,CAAA;AAOAK,EAAA;AAAA,EADCC,EAAS,EAAE,MAAM,QAAQ,SAAS,IAAM;AAAA,GAvB9BN,EAwBX,WAAA,WAAA,CAAA;AAxBWA,IAANK,EAAA;AAAA,EADNE,EAAc,cAAc;AAAA,GAChBP,CAAA;"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"hx-link-B8IwUMSc.js","sources":["../../src/components/hx-link/hx-link.styles.ts","../../src/components/hx-link/hx-link.ts"],"sourcesContent":["import { css } from 'lit';\n\nexport const helixLinkStyles = css`\n :host {\n display: inline;\n }\n\n :host([disabled]) {\n cursor: not-allowed;\n }\n\n /* --- Base Link --- */\n\n .link {\n display: inline-flex;\n align-items: center;\n gap: var(--hx-space-1, 0.25rem);\n color: var(--hx-link-color, var(--hx-color-primary-500, #2563eb));\n font-family: var(--hx-link-font-family, var(--hx-font-family-sans, inherit));\n font-size: inherit;\n line-height: inherit;\n text-decoration: var(--hx-link-text-decoration, underline);\n text-underline-offset: var(--hx-link-underline-offset, 2px);\n cursor: pointer;\n outline: 0;\n transition:\n color var(--hx-transition-fast, 150ms ease),\n text-decoration-color var(--hx-transition-fast, 150ms ease);\n }\n\n .link:hover {\n color: var(--hx-link-color-hover, var(--hx-color-primary-700, #1d4ed8));\n text-decoration: var(--hx-link-text-decoration-hover, underline);\n }\n\n .link:active {\n color: var(--hx-link-color-active, var(--hx-color-primary-800, #1e40af));\n }\n\n .link:focus-visible {\n outline: var(--hx-focus-ring-width, 2px) solid\n var(\n --hx-link-focus-ring-color,\n var(--hx-focus-ring-color, var(--hx-color-primary-400, #60a5fa))\n );\n outline-offset: var(--hx-focus-ring-offset, 2px);\n border-radius: var(--hx-border-radius-sm, 0.125rem);\n }\n\n /* --- Variant: subtle --- */\n\n .link--subtle {\n color: var(--hx-link-color-subtle, var(--hx-color-neutral-600, #475569));\n text-decoration: none;\n }\n\n .link--subtle:hover {\n color: var(--hx-link-color-hover, var(--hx-color-primary-700, #1d4ed8));\n text-decoration: underline;\n }\n\n /* --- Variant: danger --- */\n\n .link--danger {\n color: var(--hx-link-color-danger, var(--hx-color-error-text, #b91c1c));\n }\n\n .link--danger:hover {\n color: var(--hx-link-color-danger-hover, var(--hx-color-error-700, #b91c1c));\n }\n\n /* --- Disabled --- */\n\n .link--disabled {\n color: var(--hx-link-color-disabled, var(--hx-color-neutral-400, #94a3b8));\n text-decoration: none;\n pointer-events: none;\n }\n\n /* --- External link icon --- */\n\n .link__external-icon {\n display: inline-flex;\n width: 0.75em;\n height: 0.75em;\n flex-shrink: 0;\n }\n\n @media (prefers-reduced-motion: reduce) {\n .link {\n transition: none;\n }\n }\n\n /* --- Visually hidden (sr-only) --- */\n\n .sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip-path: inset(50%);\n white-space: nowrap;\n border: 0;\n }\n`;\n","import { LitElement, html, nothing, svg } from 'lit';\nimport '../../utilities/document-token-adoption.js';\nimport { customElement, property } from 'lit/decorators.js';\nimport { classMap } from 'lit/directives/class-map.js';\nimport { ifDefined } from 'lit/directives/if-defined.js';\nimport { helixLinkStyles } from './hx-link.styles.js';\n\n/**\n * Variant options for the link component.\n */\nexport type LinkVariant = 'default' | 'subtle' | 'danger';\n\n/**\n * A semantic hyperlink component with accessibility-first design.\n * Renders a native `<a>` element for enabled state and a `<span>` for\n * disabled state with full keyboard and screen reader support.\n *\n * @summary Accessible hyperlink with external-link detection, disabled state,\n * and download support.\n *\n * @tag hx-link\n *\n * @slot - Default slot for link label text or content.\n *\n * @fires {CustomEvent<{originalEvent: MouseEvent}>} hx-click - Dispatched when\n * the link is clicked and is not disabled.\n *\n * @csspart link - The inner anchor or span element.\n * @csspart external-icon - The external link icon SVG (when target=\"_blank\").\n *\n * @cssprop [--hx-link-color=var(--hx-color-primary-500)] - Default link color.\n * @cssprop [--hx-link-color-hover=var(--hx-color-primary-700)] - Hover color.\n * @cssprop [--hx-link-color-active=var(--hx-color-primary-800)] - Active color.\n * @cssprop [--hx-link-color-disabled=var(--hx-color-neutral-400)] - Disabled color.\n * @cssprop [--hx-link-color-subtle=var(--hx-color-neutral-600)] - Subtle variant color.\n * @cssprop [--hx-link-color-danger=var(--hx-color-error-text)] - Danger variant color.\n * @cssprop [--hx-link-color-danger-hover=var(--hx-color-error-700)] - Danger variant hover color.\n * @cssprop [--hx-link-font-family=var(--hx-font-family-sans)] - Link font family.\n * @cssprop [--hx-link-text-decoration=underline] - Link text decoration.\n * @cssprop [--hx-link-text-decoration-hover=underline] - Hover text decoration.\n * @cssprop [--hx-link-underline-offset=2px] - Text underline offset.\n * @cssprop [--hx-link-focus-ring-color=var(--hx-focus-ring-color)] - Focus ring color.\n *\n * @note The `:visited` pseudo-class does not work inside Shadow DOM due to\n * browser privacy restrictions. This is a known platform limitation.\n */\n@customElement('hx-link')\nexport class HelixLink extends LitElement {\n static override styles = [helixLinkStyles];\n\n /**\n * The URL the link points to.\n * @attr href\n */\n @property({ type: String })\n href: string | undefined = undefined;\n\n /**\n * Where to display the linked URL (_self, _blank, etc.).\n * When set to \"_blank\", automatically adds rel=\"noopener noreferrer\"\n * and shows an external-link indicator.\n * @attr target\n */\n @property({ type: String })\n target: string | undefined = undefined;\n\n /**\n * Visual style variant of the link.\n * @attr variant\n */\n @property({ type: String, reflect: true })\n variant: 'default' | 'subtle' | 'danger' = 'default';\n\n /**\n * Whether the link is disabled. Renders a span instead of an anchor.\n * The disabled span is keyboard-focusable (tabindex=\"0\") and announces\n * as a disabled link to screen readers.\n * @attr disabled\n */\n @property({ type: Boolean, reflect: true })\n disabled = false;\n\n /**\n * Prompts the user to download the linked URL. When set to a string,\n * the value is used as the suggested filename.\n * @attr download\n */\n @property({ type: String })\n download: string | undefined = undefined;\n\n /**\n * Relationship between the current document and the linked URL.\n * Automatically set to \"noopener noreferrer\" when target=\"_blank\".\n * @attr rel\n */\n @property({ type: String })\n rel: string | undefined = undefined;\n\n // --- Event Handling ---\n\n /** @internal */\n private _handleClick(e: MouseEvent): void {\n if (this.disabled) {\n e.preventDefault();\n e.stopPropagation();\n return;\n }\n\n this.dispatchEvent(\n new CustomEvent<{ originalEvent: MouseEvent }>('hx-click', {\n bubbles: true,\n composed: true,\n detail: { originalEvent: e },\n }),\n );\n }\n\n // --- Render Helpers ---\n\n /** @internal */\n private _computeRel(): string | undefined {\n if (this.rel) return this.rel;\n if (this.target === '_blank') return 'noopener noreferrer';\n return undefined;\n }\n\n /** @internal */\n private _renderExternalIcon() {\n if (this.target !== '_blank') return nothing;\n\n return html`\n <svg\n class=\"link__external-icon\"\n part=\"external-icon\"\n aria-hidden=\"true\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n ${svg`<path d=\"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6\" /><polyline points=\"15 3 21 3 21 9\" /><line x1=\"10\" y1=\"14\" x2=\"21\" y2=\"3\" />`}\n </svg>\n <span class=\"sr-only\">(opens in new tab)</span>\n `;\n }\n\n // --- Render ---\n\n override render() {\n const classes = {\n link: true,\n [`link--${this.variant}`]: this.variant !== 'default',\n 'link--disabled': this.disabled,\n };\n\n if (this.disabled) {\n return html`\n <span\n part=\"link\"\n class=${classMap(classes)}\n role=\"link\"\n aria-disabled=\"true\"\n tabindex=\"0\"\n @click=${this._handleClick}\n >\n <slot></slot>\n </span>\n `;\n }\n\n return html`\n <a\n part=\"link\"\n class=${classMap(classes)}\n href=${ifDefined(this.href)}\n target=${ifDefined(this.target)}\n rel=${ifDefined(this._computeRel())}\n download=${ifDefined(this.download)}\n @click=${this._handleClick}\n >\n <slot></slot>\n ${this._renderExternalIcon()}\n </a>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-link': HelixLink;\n }\n}\n"],"names":["helixLinkStyles","css","HelixLink","LitElement","e","nothing","html","svg","classes","classMap","ifDefined","__decorateClass","property","customElement"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"hx-progress-ring-BJeiDr3q.js","sources":["../../src/components/hx-progress-ring/hx-progress-ring.styles.ts","../../src/components/hx-progress-ring/hx-progress-ring.ts"],"sourcesContent":["import { css } from 'lit';\n\nexport const helixProgressRingStyles = css`\n :host {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n }\n\n /* ─── Base Container ─── */\n\n .progress-ring {\n position: relative;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n }\n\n /* ─── SVG ─── */\n\n .progress-ring__svg {\n transform: rotate(-90deg);\n overflow: visible;\n }\n\n /* ─── Track ─── */\n\n .progress-ring__track {\n fill: none;\n stroke: var(--hx-progress-ring-track-color, var(--hx-color-neutral-200, #e2e8f0));\n }\n\n /* ─── Indicator ─── */\n\n .progress-ring__indicator {\n fill: none;\n stroke: var(--hx-progress-ring-indicator-color, var(--hx-color-primary-500, #2563eb));\n stroke-linecap: round;\n transition: stroke-dashoffset var(--hx-transition-base, 300ms ease);\n }\n\n /* ─── Variant Colors ─── */\n\n :host([variant='success']) .progress-ring__indicator {\n stroke: var(--hx-progress-ring-indicator-color, var(--hx-color-success-500, #16a34a));\n }\n\n :host([variant='warning']) .progress-ring__indicator {\n stroke: var(--hx-progress-ring-indicator-color, var(--hx-color-warning-500, #d97706));\n }\n\n :host([variant='danger']) .progress-ring__indicator {\n stroke: var(--hx-progress-ring-indicator-color, var(--hx-color-error-500, #dc2626));\n }\n\n /* ─── Indeterminate Animation ─── */\n\n :host([indeterminate]) .progress-ring__svg {\n animation: hx-progress-ring-rotate var(--hx-duration-spinner, 1400ms) linear infinite;\n }\n\n :host([indeterminate]) .progress-ring__indicator {\n animation: hx-progress-ring-dash var(--hx-duration-spinner, 1400ms) ease-in-out infinite;\n transition: none;\n stroke-dasharray: 1, 200;\n stroke-dashoffset: 0;\n }\n\n @keyframes hx-progress-ring-rotate {\n to {\n transform: rotate(270deg);\n }\n }\n\n /*\n * Indeterminate spinner keyframes — values are tuned for default strokeWidth=4\n * (radius ≈ 48, circumference ≈ 301). The gap value 200 is intentionally smaller\n * than the full circumference; the repeating pattern is a standard CSS spinner\n * technique that produces an arc of ~35% coverage. At non-default strokeWidths\n * the arc coverage will vary slightly but remains visually acceptable.\n */\n @keyframes hx-progress-ring-dash {\n 0% {\n stroke-dasharray: 1, 200;\n stroke-dashoffset: 0;\n }\n 50% {\n stroke-dasharray: 89, 200;\n stroke-dashoffset: -35;\n }\n 100% {\n stroke-dasharray: 89, 200;\n stroke-dashoffset: -124;\n }\n }\n\n @media (prefers-reduced-motion: reduce) {\n :host([indeterminate]) .progress-ring__svg {\n animation: none;\n }\n\n :host([indeterminate]) .progress-ring__indicator {\n animation: none;\n stroke-dasharray: 89, 200;\n stroke-dashoffset: -35;\n }\n\n .progress-ring__indicator {\n transition: none;\n }\n }\n\n /* ─── Size Variants ─── */\n\n :host([size='sm']) .progress-ring {\n width: var(--hx-size-8, 2rem);\n height: var(--hx-size-8, 2rem);\n }\n\n :host([size='md']) .progress-ring,\n .progress-ring {\n width: var(--hx-size-12, 3rem);\n height: var(--hx-size-12, 3rem);\n }\n\n :host([size='lg']) .progress-ring {\n width: var(--hx-size-16, 4rem);\n height: var(--hx-size-16, 4rem);\n }\n\n /* ─── Label (center slot wrapper) ─── */\n\n .progress-ring__label {\n position: absolute;\n display: flex;\n align-items: center;\n justify-content: center;\n inset: 0;\n font-size: var(--hx-font-size-xs, 0.75rem);\n font-family: var(--hx-font-family-sans, sans-serif);\n font-weight: var(--hx-font-weight-semibold, 600);\n color: var(--hx-progress-ring-label-color, var(--hx-color-neutral-900, #0f172a));\n pointer-events: none;\n }\n`;\n","import { LitElement, html, svg, TemplateResult, type PropertyValues } from 'lit';\nimport '../../utilities/document-token-adoption.js';\nimport { customElement, property } from 'lit/decorators.js';\nimport { helixProgressRingStyles } from './hx-progress-ring.styles.js';\nimport { devWarn } from '../../utils/dev-warn.js';\n\n/**\n * SVG-based circular progress indicator. Supports determinate and indeterminate modes,\n * multiple size variants, semantic color variants, and a center content slot.\n *\n * @summary Circular progress ring for indicating operation progress or loading state.\n *\n * @tag hx-progress-ring\n *\n * @slot - Default slot for center content (percentage text, icon, etc.).\n *\n * @csspart base - The SVG element.\n * @csspart track - The background circle track.\n * @csspart indicator - The progress arc indicator.\n * @csspart label - The center slot wrapper div.\n *\n * @cssprop [--hx-progress-ring-track-color=var(--hx-color-neutral-200)] - Track stroke color.\n * @cssprop [--hx-progress-ring-indicator-color=var(--hx-color-primary-500)] - Indicator stroke color.\n * @cssprop [--hx-progress-ring-label-color=var(--hx-color-neutral-900)] - Center label text color.\n */\n@customElement('hx-progress-ring')\nexport class HelixProgressRing extends LitElement {\n static override styles = [helixProgressRingStyles];\n\n // ─── Public Properties ───\n\n /**\n * Current progress value (0–max). When null, renders in indeterminate mode.\n * @attr value\n */\n @property({ type: Number, reflect: true })\n value: number | null = null;\n\n /**\n * Maximum value for the progress range. Defaults to 100. Used for aria-valuemax.\n * @attr max\n */\n @property({ type: Number, reflect: true })\n max = 100;\n\n /**\n * Size of the ring. Controls SVG diameter.\n * @attr hx-size\n */\n @property({ type: String, reflect: true, attribute: 'hx-size' })\n size: 'sm' | 'md' | 'lg' = 'md';\n\n /**\n * Stroke width of the ring circles in SVG user units.\n * @attr stroke-width\n */\n @property({ type: Number, attribute: 'stroke-width', reflect: true })\n strokeWidth = 4;\n\n /**\n * Semantic color variant.\n * @attr variant\n */\n @property({ type: String, reflect: true })\n variant: 'default' | 'success' | 'warning' | 'danger' = 'default';\n\n /**\n * Accessible label for the progressbar. Exposed as aria-label.\n * Set this attribute to satisfy WCAG 4.1.2. When absent, aria-busy reflects\n * indeterminate state and a console warning is emitted.\n * @attr label\n */\n @property({ type: String })\n label = '';\n\n // ─── Private Helpers ───\n\n /** @internal */\n private get _isIndeterminate(): boolean {\n return this.value === null;\n }\n\n /** @internal */\n private get _clampedValue(): number {\n if (this.value === null) return 0;\n return Math.min(this.max, Math.max(0, this.value));\n }\n\n /**\n * SVG viewBox is 100x100. Radius leaves room for the stroke.\n */\n /** @internal */\n private get _radius(): number {\n return (100 - this.strokeWidth) / 2;\n }\n\n /** @internal */\n private get _circumference(): number {\n return 2 * Math.PI * this._radius;\n }\n\n /** @internal */\n private get _strokeDashoffset(): number {\n return this._circumference * (1 - this._clampedValue / this.max);\n }\n\n /** @internal */\n private _labelWarned = false;\n\n // ─── Lifecycle ───\n\n override connectedCallback(): void {\n super.connectedCallback();\n // Backward compat: accept legacy `size` attribute. When present and `hx-size`\n // is not set, map the value and emit a deprecation warning.\n const legacySize = this.getAttribute('size');\n if (legacySize !== null && !this.hasAttribute('hx-size')) {\n devWarn('hx-progress-ring', 'The \"size\" attribute is deprecated. Use \"hx-size\" instead.');\n this.size = legacySize as 'sm' | 'md' | 'lg';\n }\n this.setAttribute('role', 'progressbar');\n this.setAttribute('aria-valuemin', '0');\n }\n\n protected override willUpdate(_changed: PropertyValues<this>): void {\n // Sync all dynamic ARIA attributes before render\n this.setAttribute('aria-valuemax', String(this.max));\n\n if (this._isIndeterminate) {\n this.setAttribute('indeterminate', '');\n this.setAttribute('aria-busy', 'true');\n this.removeAttribute('aria-valuenow');\n this.removeAttribute('aria-valuetext');\n } else {\n this.removeAttribute('indeterminate');\n this.removeAttribute('aria-busy');\n this.setAttribute('aria-valuenow', String(this._clampedValue));\n this.setAttribute('aria-valuetext', `${this._clampedValue}% complete`);\n }\n\n if (this.label) {\n this.setAttribute('aria-label', this.label);\n } else {\n this.removeAttribute('aria-label');\n if (!this._labelWarned) {\n this._labelWarned = true;\n devWarn(\n 'hx-progress-ring',\n 'Missing accessible label. Set the `label` attribute for WCAG 4.1.2 compliance.',\n );\n }\n }\n }\n\n // ─── Render ───\n\n override render(): TemplateResult {\n const cx = 50;\n const cy = 50;\n const r = this._radius;\n const circumference = this._circumference;\n\n return html`\n <div class=\"progress-ring\">\n <svg\n class=\"progress-ring__svg\"\n part=\"base\"\n viewBox=\"0 0 100 100\"\n aria-hidden=\"true\"\n focusable=\"false\"\n >\n ${svg`\n <circle\n class=\"progress-ring__track\"\n part=\"track\"\n cx=${cx}\n cy=${cy}\n r=${r}\n stroke-width=${this.strokeWidth}\n />\n <circle\n class=\"progress-ring__indicator\"\n part=\"indicator\"\n cx=${cx}\n cy=${cy}\n r=${r}\n stroke-width=${this.strokeWidth}\n stroke-dasharray=${\n this._isIndeterminate ? '1 200' : `${circumference} ${circumference}`\n }\n stroke-dashoffset=${this._isIndeterminate ? '0' : this._strokeDashoffset}\n />\n `}\n </svg>\n <div class=\"progress-ring__label\" part=\"label\">\n <slot></slot>\n </div>\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-progress-ring': HelixProgressRing;\n }\n}\n"],"names":["helixProgressRingStyles","css","HelixProgressRing","LitElement","legacySize","_changed","r","circumference","html","svg","__decorateClass","property","customElement"],"mappings":";;;AAEO,MAAMA,IAA0BC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;;;;ACwBhC,IAAMC,IAAN,cAAgCC,EAAW;AAAA,EAA3C,cAAA;AAAA,UAAA,GAAA,SAAA,GAUL,KAAA,QAAuB,MAOvB,KAAA,MAAM,KAON,KAAA,OAA2B,MAO3B,KAAA,cAAc,GAOd,KAAA,UAAwD,WASxD,KAAA,QAAQ,IAkCR,KAAQ,eAAe;AAAA,EAAA;AAAA;AAAA;AAAA,EA7BvB,IAAY,mBAA4B;AACtC,WAAO,KAAK,UAAU;AAAA,EACxB;AAAA;AAAA,EAGA,IAAY,gBAAwB;AAClC,WAAI,KAAK,UAAU,OAAa,IACzB,KAAK,IAAI,KAAK,KAAK,KAAK,IAAI,GAAG,KAAK,KAAK,CAAC;AAAA,EACnD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAY,UAAkB;AAC5B,YAAQ,MAAM,KAAK,eAAe;AAAA,EACpC;AAAA;AAAA,EAGA,IAAY,iBAAyB;AACnC,WAAO,IAAI,KAAK,KAAK,KAAK;AAAA,EAC5B;AAAA;AAAA,EAGA,IAAY,oBAA4B;AACtC,WAAO,KAAK,kBAAkB,IAAI,KAAK,gBAAgB,KAAK;AAAA,EAC9D;AAAA;AAAA,EAOS,oBAA0B;AACjC,UAAM,kBAAA;AAGN,UAAMC,IAAa,KAAK,aAAa,MAAM;AAC3C,IAAIA,MAAe,QAAQ,CAAC,KAAK,aAAa,SAAS,MAErD,KAAK,OAAOA,IAEd,KAAK,aAAa,QAAQ,aAAa,GACvC,KAAK,aAAa,iBAAiB,GAAG;AAAA,EACxC;AAAA,EAEmB,WAAWC,GAAsC;AAElE,SAAK,aAAa,iBAAiB,OAAO,KAAK,GAAG,CAAC,GAE/C,KAAK,oBACP,KAAK,aAAa,iBAAiB,EAAE,GACrC,KAAK,aAAa,aAAa,MAAM,GACrC,KAAK,gBAAgB,eAAe,GACpC,KAAK,gBAAgB,gBAAgB,MAErC,KAAK,gBAAgB,eAAe,GACpC,KAAK,gBAAgB,WAAW,GAChC,KAAK,aAAa,iBAAiB,OAAO,KAAK,aAAa,CAAC,GAC7D,KAAK,aAAa,kBAAkB,GAAG,KAAK,aAAa,YAAY,IAGnE,KAAK,QACP,KAAK,aAAa,cAAc,KAAK,KAAK,KAE1C,KAAK,gBAAgB,YAAY,GAC5B,KAAK,iBACR,KAAK,eAAe;AAAA,EAO1B;AAAA;AAAA,EAIS,SAAyB;AAGhC,UAAMC,IAAI,KAAK,SACTC,IAAgB,KAAK;AAE3B,WAAOC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,YASCC;AAAA;AAAA;AAAA;AAAA,mBAIO,EAAE;AAAA,mBACF,EAAE;AAAA,kBACHH,CAAC;AAAA,6BACU,KAAK,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA,mBAK1B,EAAE;AAAA,mBACF,EAAE;AAAA,kBACHA,CAAC;AAAA,6BACU,KAAK,WAAW;AAAA,iCAE7B,KAAK,mBAAmB,UAAU,GAAGC,CAAa,IAAIA,CAAa,EACrE;AAAA,kCACoB,KAAK,mBAAmB,MAAM,KAAK,iBAAiB;AAAA;AAAA,WAE3E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOT;AACF;AA9KaL,EACK,SAAS,CAACF,CAAuB;AASjDU,EAAA;AAAA,EADCC,EAAS,EAAE,MAAM,QAAQ,SAAS,IAAM;AAAA,GAT9BT,EAUX,WAAA,SAAA,CAAA;AAOAQ,EAAA;AAAA,EADCC,EAAS,EAAE,MAAM,QAAQ,SAAS,IAAM;AAAA,GAhB9BT,EAiBX,WAAA,OAAA,CAAA;AAOAQ,EAAA;AAAA,EADCC,EAAS,EAAE,MAAM,QAAQ,SAAS,IAAM,WAAW,WAAW;AAAA,GAvBpDT,EAwBX,WAAA,QAAA,CAAA;AAOAQ,EAAA;AAAA,EADCC,EAAS,EAAE,MAAM,QAAQ,WAAW,gBAAgB,SAAS,IAAM;AAAA,GA9BzDT,EA+BX,WAAA,eAAA,CAAA;AAOAQ,EAAA;AAAA,EADCC,EAAS,EAAE,MAAM,QAAQ,SAAS,IAAM;AAAA,GArC9BT,EAsCX,WAAA,WAAA,CAAA;AASAQ,EAAA;AAAA,EADCC,EAAS,EAAE,MAAM,OAAA,CAAQ;AAAA,GA9CfT,EA+CX,WAAA,SAAA,CAAA;AA/CWA,IAANQ,EAAA;AAAA,EADNE,EAAc,kBAAkB;AAAA,GACpBV,CAAA;"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"hx-select-B5wq9Swh.js","sources":["../../src/components/hx-select/hx-select.styles.ts","../../src/components/hx-select/hx-select.ts"],"sourcesContent":["import { css } from 'lit';\n\nexport const helixSelectStyles = css`\n /* ─── 3-tier token cascade: component → semantic → hardcoded fallback ─── */\n :host {\n display: block;\n\n /* Background & foreground */\n --_bg: var(--hx-select-bg, var(--hx-color-neutral-0, #ffffff));\n --_color: var(--hx-select-color, var(--hx-color-neutral-800, #212529));\n --_placeholder-color: var(--hx-select-placeholder-color, var(--hx-color-neutral-400, #adb5bd));\n\n /* Label */\n --_label-color: var(--hx-select-label-color, var(--hx-color-neutral-700, #343a40));\n\n /* Border */\n --_border-color: var(--hx-select-border-color, var(--hx-color-neutral-300, #ced4da));\n --_border-radius: var(--hx-select-border-radius, var(--hx-border-radius-md, 0.375rem));\n\n /* Focus ring */\n --_focus-ring-color: var(\n --hx-select-focus-ring-color,\n var(--hx-focus-ring-color, var(--hx-color-primary-400, #60a5fa))\n );\n\n /* Error */\n --_error-color: var(--hx-select-error-color, var(--hx-color-error-500, #dc3545));\n\n /* Chevron */\n --_chevron-color: var(--hx-select-chevron-color, var(--hx-color-neutral-500, #6c757d));\n --_chevron-size: var(--hx-select-chevron-size, 0.5rem);\n\n /* Listbox */\n --_listbox-bg: var(--hx-select-listbox-bg, var(--hx-color-neutral-0, #ffffff));\n --_option-hover-bg: var(--hx-select-option-hover-bg, var(--hx-color-primary-50, #eff6ff));\n --_option-selected-bg: var(\n --hx-select-option-selected-bg,\n var(--hx-color-primary-100, #dbeafe)\n );\n\n /* Typography */\n --_font-family: var(--hx-select-font-family, var(--hx-font-family-sans, sans-serif));\n }\n\n :host([disabled]) {\n opacity: var(--hx-opacity-disabled, 0.5);\n pointer-events: none;\n }\n\n * {\n box-sizing: border-box;\n }\n\n .field {\n display: flex;\n flex-direction: column;\n gap: var(--hx-space-1, 0.25rem);\n font-family: var(--_font-family);\n position: relative;\n }\n\n .field__label {\n display: flex;\n align-items: baseline;\n gap: var(--hx-space-1, 0.25rem);\n font-size: var(--hx-font-size-sm, 0.875rem);\n font-weight: var(--hx-font-weight-medium, 500);\n color: var(--_label-color);\n line-height: var(--hx-line-height-normal, 1.5);\n }\n\n .field__required-marker {\n color: var(--hx-select-error-color, var(--hx-color-error-text, #b91c1c));\n font-weight: var(--hx-font-weight-bold, 700);\n }\n\n .field__select-wrapper {\n position: relative;\n display: block;\n }\n\n .field__trigger {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--hx-space-2, 0.5rem);\n width: 100%;\n min-height: var(--hx-input-height-md, var(--hx-size-10, 2.5rem));\n border: var(--hx-border-width-thin, 1px) solid var(--_border-color);\n border-radius: var(--_border-radius);\n background-color: var(--_bg);\n color: var(--_color);\n font-family: inherit;\n font-size: var(--hx-font-size-md, 1rem);\n line-height: var(--hx-line-height-normal, 1.5);\n padding: var(--hx-space-2, 0.5rem) var(--hx-space-3, 0.75rem);\n cursor: pointer;\n text-align: start;\n transition:\n border-color var(--hx-transition-fast, 150ms ease),\n box-shadow var(--hx-transition-fast, 150ms ease);\n outline: none;\n }\n\n .field__trigger:focus,\n .field__trigger:focus-visible {\n border-color: var(--_focus-ring-color);\n box-shadow: 0 0 0 var(--hx-focus-ring-width, 2px)\n color-mix(\n in srgb,\n var(--_focus-ring-color) calc(var(--hx-focus-ring-opacity, 0.25) * 100%),\n transparent\n );\n }\n\n .field__trigger[aria-disabled='true'] {\n cursor: not-allowed;\n }\n\n .field__trigger--sm {\n min-height: var(--hx-input-height-sm, var(--hx-size-8, 2rem));\n font-size: var(--hx-font-size-sm, 0.875rem);\n padding: var(--hx-space-1, 0.25rem) var(--hx-space-3, 0.75rem);\n }\n\n .field__trigger--lg {\n min-height: var(--hx-input-height-lg, var(--hx-size-12, 3rem));\n font-size: var(--hx-font-size-lg, 1.125rem);\n padding: var(--hx-space-3, 0.75rem) var(--hx-space-4, 1rem);\n }\n\n .field__trigger-value {\n flex: 1;\n min-width: 0;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .field__trigger--placeholder .field__trigger-value {\n color: var(--_placeholder-color);\n }\n\n .field__chevron {\n flex-shrink: 0;\n width: calc(var(--_chevron-size) * 1.5);\n height: var(--_chevron-size);\n position: relative;\n color: var(--_chevron-color);\n pointer-events: none;\n transition: transform var(--hx-transition-fast, 150ms ease);\n }\n\n .field__chevron::after {\n content: '';\n position: absolute;\n top: 0;\n left: var(--hx-space-px, 2px);\n width: var(--_chevron-size);\n height: var(--_chevron-size);\n border-inline-end: var(--hx-border-width-thin, 1.5px) solid currentColor;\n border-bottom: var(--hx-border-width-thin, 1.5px) solid currentColor;\n transform: rotate(45deg);\n }\n\n .field--open .field__chevron {\n transform: rotate(180deg);\n }\n\n .field--error .field__trigger {\n border-color: var(--_error-color);\n }\n\n .field--error .field__trigger:focus,\n .field--error .field__trigger:focus-visible {\n border-color: var(--_error-color);\n box-shadow: 0 0 0 var(--hx-focus-ring-width, 2px)\n color-mix(\n in srgb,\n var(--_error-color) calc(var(--hx-focus-ring-opacity, 0.25) * 100%),\n transparent\n );\n }\n\n .field__listbox {\n position: absolute;\n top: calc(100% + var(--hx-space-1, 0.25rem));\n left: 0;\n right: 0;\n z-index: var(--hx-z-index-dropdown, 1000);\n background-color: var(--_listbox-bg);\n border: var(--hx-border-width-thin, 1px) solid var(--_border-color);\n border-radius: var(--_border-radius);\n box-shadow: var(\n --hx-select-listbox-shadow,\n 0 4px 16px var(--hx-overlay-neutral-12, rgba(13, 17, 23, 0.12))\n );\n max-height: var(--hx-select-listbox-max-height, 16rem);\n overflow: hidden;\n display: flex;\n flex-direction: column;\n }\n\n .field__listbox[hidden] {\n display: none;\n }\n\n .field__options {\n overflow-y: auto;\n flex: 1;\n padding: var(--hx-space-1, 0.25rem) 0;\n }\n\n .field__option {\n display: flex;\n align-items: center;\n gap: var(--hx-space-2, 0.5rem);\n padding: var(--hx-space-2, 0.5rem) var(--hx-space-3, 0.75rem);\n font-size: var(--hx-font-size-md, 1rem);\n color: var(--_color);\n cursor: pointer;\n user-select: none;\n -webkit-user-select: none;\n transition: background-color var(--hx-transition-fast, 150ms ease);\n }\n\n .field__option:hover {\n background-color: var(--_option-hover-bg);\n }\n\n .field__option--selected {\n background-color: var(--_option-selected-bg);\n font-weight: var(--hx-font-weight-medium, 500);\n }\n\n .field__option--focused {\n background-color: var(--_option-hover-bg);\n outline: var(--hx-focus-ring-width, 2px) solid\n var(--_focus-ring-color, var(--hx-color-primary-500));\n outline-offset: var(--hx-select-option-focus-ring-offset, -2px);\n }\n\n .field__option--focused.field__option--selected {\n background-color: var(--_option-selected-bg);\n }\n\n .field__option--disabled {\n opacity: var(--hx-opacity-disabled, 0.5);\n cursor: not-allowed;\n pointer-events: none;\n }\n\n .field__option-label {\n flex: 1;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .field__no-options {\n padding: var(--hx-space-3, 0.75rem);\n text-align: center;\n color: var(--_placeholder-color);\n font-size: var(--hx-font-size-sm, 0.875rem);\n }\n\n .field__select {\n position: absolute;\n width: 1px;\n height: 1px;\n overflow: hidden;\n opacity: 0;\n pointer-events: none;\n clip: rect(0, 0, 0, 0);\n }\n\n .field__help-text,\n .field__error {\n font-size: var(--hx-font-size-xs, 0.75rem);\n line-height: var(--hx-line-height-normal, 1.5);\n }\n\n .field__help-text {\n color: var(--hx-color-neutral-500, #6c757d);\n }\n\n .field__error {\n color: var(--hx-select-error-color, var(--hx-color-error-text, #b91c1c));\n }\n\n @media (prefers-reduced-motion: reduce) {\n .field__trigger,\n .field__chevron,\n .field__option {\n transition: none;\n }\n }\n`;\n","import { html, nothing, type PropertyValues } from 'lit';\nimport '../../utilities/document-token-adoption.js';\nimport { customElement, property, query, state } from 'lit/decorators.js';\nimport { classMap } from 'lit/directives/class-map.js';\nimport { ifDefined } from 'lit/directives/if-defined.js';\nimport { repeat } from 'lit/directives/repeat.js';\nimport { HelixElement, createIdCounter } from '../../base/index.js';\nimport { helixSelectStyles } from './hx-select.styles.js';\nimport { devWarn } from '../../utils/dev-warn.js';\n\n// Module-level counter for stable, SSR-safe IDs (avoids Math.random() hydration mismatch)\nconst _nextSelectId = createIdCounter('hx-select');\n\n// ─── Internal option model ───\n\ninterface SelectOption {\n value: string;\n label: string;\n disabled: boolean;\n}\n\n/**\n * A form-associated select component with custom styling, label, error, and\n * help text. Options are provided via slotted `<option>` (and `<optgroup>`)\n * elements in the light DOM. The component wraps a hidden native `<select>`\n * for form participation and provides a combobox trigger for consistent\n * cross-browser styling.\n *\n * @remarks Multi-select is intentionally not supported. This component\n * implements a single-value select (combobox) pattern only. For multi-value\n * selection use a separate multi-select component.\n *\n * @remarks The listbox panel uses `position: absolute` and may be clipped by\n * ancestor elements with `overflow: hidden` or `overflow: auto`. This is a\n * known limitation when embedding the component inside cards, tables, or\n * dialogs. Use the CSS custom property `--hx-select-listbox-shadow` or\n * restructure the containing layout to avoid clipping.\n *\n * @summary Form-associated custom select with label, error, and help text.\n *\n * @tag hx-select\n *\n * @slot - Default slot for `<option>` and `<optgroup>` elements.\n * @slot label - Custom label content (overrides the label property).\n * @slot error - Custom error content (overrides the error property).\n * @slot help-text - Custom help text content (overrides the helpText property).\n *\n * @fires {CustomEvent<{value: string}>} hx-change - Dispatched when the selected option changes.\n *\n * @csspart field - The outer field container.\n * @csspart label - The label element.\n * @csspart select-wrapper - The wrapper containing the trigger and listbox.\n * @csspart select - The hidden native select element (kept for form participation).\n * @csspart trigger - The button that opens/closes the dropdown.\n * @csspart listbox - The dropdown panel containing options.\n * @csspart option - Individual option items in the listbox.\n * @csspart help-text - The help text container.\n * @csspart error - The error message container.\n *\n * @cssprop [--hx-select-bg=var(--hx-color-neutral-0)] - Select background color.\n * @cssprop [--hx-select-color=var(--hx-color-neutral-800)] - Select text color.\n * @cssprop [--hx-select-border-color=var(--hx-color-neutral-300)] - Select border color.\n * @cssprop [--hx-select-border-radius=var(--hx-border-radius-md)] - Select border radius.\n * @cssprop [--hx-select-font-family=var(--hx-font-family-sans)] - Select font family.\n * @cssprop [--hx-select-focus-ring-color=var(--hx-focus-ring-color)] - Focus ring color.\n * @cssprop [--hx-select-error-color=var(--hx-color-error-500)] - Error state color.\n * @cssprop [--hx-select-label-color=var(--hx-color-neutral-700)] - Label text color.\n * @cssprop [--hx-select-chevron-color=var(--hx-color-neutral-500)] - Chevron indicator color.\n * @cssprop [--hx-select-chevron-size=0.5rem] - Chevron indicator size (width/height base unit).\n * @cssprop [--hx-select-listbox-bg=var(--hx-color-neutral-0)] - Listbox panel background color.\n * @cssprop [--hx-select-option-hover-bg=var(--hx-color-primary-50)] - Option hover background color.\n * @cssprop [--hx-select-option-selected-bg=var(--hx-color-primary-100)] - Selected option background color.\n * @cssprop [--hx-select-placeholder-color=var(--hx-color-neutral-400)] - Placeholder text color.\n */\n@customElement('hx-select')\nexport class HelixSelect extends HelixElement {\n static override styles = [helixSelectStyles];\n\n // ─── Form Association ───\n\n /** Marks this element as form-associated for ElementInternals support. @internal */\n static override formAssociated = true;\n\n // ─── Stable IDs ───\n\n /** @internal */\n private _selectId = _nextSelectId();\n /** @internal */\n private _listboxId = `${this._selectId}-listbox`;\n /** @internal */\n private _labelId = `${this._selectId}-label`;\n /** @internal */\n private _helpTextId = `${this._selectId}-help`;\n /** @internal */\n private _errorId = `${this._selectId}-error`;\n\n // ─── Public Properties ───\n\n /**\n * The visible label text for the select.\n * @attr label\n */\n @property({ type: String })\n label = '';\n\n /**\n * Placeholder text shown in the trigger when no option is selected.\n * @attr placeholder\n */\n @property({ type: String })\n placeholder = '';\n\n /**\n * The current value of the select.\n * @attr value\n */\n @property({ type: String, reflect: true })\n value = '';\n\n /**\n * Whether the select is required for form submission.\n * @attr required\n */\n @property({ type: Boolean, reflect: true })\n required = false;\n\n /**\n * Whether the select is disabled.\n * @attr disabled\n */\n @property({ type: Boolean, reflect: true })\n disabled = false;\n\n /**\n * The name used for form submission.\n * @attr name\n */\n @property({ type: String })\n name = '';\n\n /**\n * Error message to display. When set, the field enters an error state.\n * @attr error\n */\n @property({ type: String })\n error = '';\n\n /**\n * Help text displayed below the select for guidance.\n * @attr help-text\n */\n @property({ type: String, attribute: 'help-text' })\n helpText = '';\n\n /**\n * Size variant of the select trigger.\n * @attr hx-size\n */\n @property({ type: String, attribute: 'hx-size', reflect: true })\n size: 'sm' | 'md' | 'lg' = 'md';\n\n /**\n * Accessible name for screen readers, if different from the visible label.\n * @attr aria-label\n */\n @property({ type: String, attribute: 'aria-label' })\n override ariaLabel: string | null = null;\n\n /**\n * Controls whether the dropdown listbox is open.\n * @attr open\n */\n @property({ type: Boolean, reflect: true })\n open = false;\n\n /**\n * Validation message when no option is selected. Override for i18n.\n * @attr label-required\n */\n @property({ attribute: 'label-required' }) labelRequired = 'Please select an option.';\n\n /**\n * Label shown when no options are available. Override for i18n.\n * @attr label-no-options\n */\n @property({ attribute: 'label-no-options' }) labelNoOptions = 'No options found';\n\n // ─── Internal State ───\n\n /** Parsed option models derived from slotted `<option>` and `<optgroup>` elements. @internal */\n @state() private _options: SelectOption[] = [];\n /** Whether the named error slot contains projected content. @internal */\n @state() private _hasErrorSlot = false;\n /** Zero-based index of the keyboard-focused option in the listbox; -1 means none. @internal */\n @state() private _focusedOptionIndex = -1;\n\n // ─── Queries ───\n\n /** Reference to the hidden native select element used for form participation. @internal */\n @query('.field__select')\n private _select: HTMLSelectElement | undefined;\n\n /** Reference to the visible combobox trigger element that receives keyboard focus. @internal */\n @query('.field__trigger')\n private _trigger: HTMLElement | undefined;\n\n // ─── Computed helpers ───\n\n /** @internal */\n private get _displayValue(): string {\n if (!this.value) return '';\n const opt = this._options.find((o) => o.value === this.value);\n return opt ? opt.label : this.value;\n }\n\n // ─── Lifecycle ───\n\n override connectedCallback(): void {\n super.connectedCallback();\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n // Safety net: remove listener if component is removed while dropdown is open\n document.removeEventListener('click', this._handleOutsideClick);\n // Reset open state to prevent persisted open state on reconnect\n if (this.open) {\n this.open = false;\n this._focusedOptionIndex = -1;\n }\n }\n\n override updated(changedProperties: PropertyValues<this>): void {\n if (changedProperties.has('open')) {\n if (this.open) {\n document.addEventListener('click', this._handleOutsideClick);\n } else {\n document.removeEventListener('click', this._handleOutsideClick);\n }\n }\n if (changedProperties.has('value')) {\n this._syncNativeSelect();\n this._updateFormValue();\n this._updateValidity();\n }\n if (changedProperties.has('size')) {\n const validSizes: string[] = ['sm', 'md', 'lg'];\n if (!validSizes.includes(this.size)) {\n devWarn(\n 'hx-select',\n `Invalid size \"${this.size}\". Expected one of: ${validSizes.join(', ')}.`,\n );\n }\n }\n }\n\n // ─── Form Integration ───\n\n /** Returns the associated form element, if any. */\n get form(): HTMLFormElement | null {\n return this._internals.form;\n }\n\n /** Returns the validation message. */\n get validationMessage(): string {\n return this._internals.validationMessage;\n }\n\n /** Returns the ValidityState object. */\n get validity(): ValidityState {\n return this._internals.validity;\n }\n\n /** Checks whether the select satisfies its constraints. */\n checkValidity(): boolean {\n return this._internals.checkValidity();\n }\n\n /** Reports validity and shows the browser's constraint validation UI. */\n reportValidity(): boolean {\n return this._internals.reportValidity();\n }\n\n /** @internal */\n private _updateFormValue(): void {\n this._internals.setFormValue(this.value || null);\n }\n\n /** @internal */\n private _updateValidity(): void {\n if (this.required && !this.value) {\n this._internals.setValidity(\n { valueMissing: true },\n this.error || this.labelRequired,\n this._trigger ?? this._select,\n );\n } else {\n this._internals.setValidity({});\n }\n }\n\n // ─── Form Lifecycle Hooks ───\n\n protected override _onFormReset(): void {\n this.value = '';\n this._internals.setFormValue(null);\n }\n\n protected override _onFormStateRestore(\n state: File | string | FormData | null,\n _mode: 'restore' | 'autocomplete',\n ): void {\n if (typeof state === 'string') {\n this.value = state;\n }\n }\n\n protected override _onFormDisabled(disabled: boolean): void {\n this.disabled = disabled;\n }\n\n // ─── Native Select Sync ───\n\n /** @internal */\n private _syncNativeSelect(): void {\n if (!this._select) return;\n if (this.value) {\n this._select.value = this.value;\n }\n }\n\n // ─── Option Syncing from Slot ───\n\n /** @internal */\n private _parseOption(el: HTMLOptionElement): SelectOption {\n return { value: el.value, label: el.textContent?.trim() ?? el.value, disabled: el.disabled };\n }\n\n /**\n * Single-pass slot handler: reads options into _options for the custom\n * listbox AND clones them into the native <select> for form participation.\n * Handles both top-level <option> and <optgroup> children.\n */\n /** @internal */\n private _handleSlotChange(): void {\n const slot = this.shadowRoot?.querySelector<HTMLSlotElement>('slot:not([name])');\n if (!slot) return;\n\n const parsed: SelectOption[] = [];\n\n // Remove previously cloned options from native select\n if (this._select) {\n this._select.querySelectorAll('option[data-cloned]').forEach((opt) => opt.remove());\n }\n\n const cloneIntoSelect = (optEl: HTMLOptionElement): void => {\n if (!this._select) return;\n const clone = optEl.cloneNode(true) as HTMLOptionElement;\n clone.setAttribute('data-cloned', '');\n this._select.appendChild(clone);\n };\n\n for (const el of slot.assignedElements({ flatten: true })) {\n if (el instanceof HTMLOptionElement) {\n parsed.push(this._parseOption(el));\n cloneIntoSelect(el);\n } else if (el instanceof HTMLOptGroupElement) {\n for (const child of Array.from(el.children)) {\n if (child instanceof HTMLOptionElement) {\n parsed.push(this._parseOption(child));\n cloneIntoSelect(child);\n }\n }\n }\n }\n\n this._options = parsed;\n\n if (parsed.length === 0) {\n devWarn(\n 'hx-select',\n 'hx-select has no options — add <option> or <optgroup> elements as children.',\n );\n }\n\n if (this._select) {\n if (this.value) {\n this._select.value = this.value;\n } else if (!this.placeholder && parsed.length > 0) {\n this.value = this._select.value;\n this._updateFormValue();\n }\n }\n }\n\n // ─── Slot Change Handlers ───\n\n /** @internal */\n private _handleErrorSlotChange(e: Event): void {\n const slot = e.target as HTMLSlotElement;\n this._hasErrorSlot = slot.assignedNodes({ flatten: true }).length > 0;\n }\n\n // ─── Dropdown Control ───\n\n /** @internal */\n private _toggleDropdown(): void {\n if (!this.disabled) {\n this.open = !this.open;\n if (this.open) {\n // Pre-focus the currently selected option (or first enabled) when opening\n const selectedIndex = this._options.findIndex((o) => o.value === this.value);\n this._focusedOptionIndex = selectedIndex >= 0 ? selectedIndex : 0;\n } else {\n this._focusedOptionIndex = -1;\n }\n }\n }\n\n // ─── Keyboard Navigation ───\n\n /** @internal */\n private _handleKeydown(e: KeyboardEvent): void {\n if (this.disabled) return;\n\n const enabledIndices = this._options\n .map((o, i) => ({ o, i }))\n .filter(({ o }) => !o.disabled)\n .map(({ i }) => i);\n\n switch (e.key) {\n case 'ArrowDown': {\n e.preventDefault();\n if (!this.open) {\n this.open = true;\n this._focusedOptionIndex = enabledIndices.length > 0 ? (enabledIndices[0] ?? 0) : 0;\n break;\n }\n const nextDown = enabledIndices.find((i) => i > this._focusedOptionIndex);\n this._focusedOptionIndex =\n nextDown !== undefined ? nextDown : (enabledIndices[0] ?? this._focusedOptionIndex);\n break;\n }\n case 'ArrowUp': {\n e.preventDefault();\n if (!this.open) {\n this.open = true;\n const lastEnabled = enabledIndices[enabledIndices.length - 1];\n this._focusedOptionIndex = lastEnabled !== undefined ? lastEnabled : 0;\n break;\n }\n const prevUp = [...enabledIndices].reverse().find((i) => i < this._focusedOptionIndex);\n const lastEnabledUp = enabledIndices[enabledIndices.length - 1];\n this._focusedOptionIndex =\n prevUp !== undefined ? prevUp : (lastEnabledUp ?? this._focusedOptionIndex);\n break;\n }\n case 'Home': {\n e.preventDefault();\n if (!this.open) {\n this.open = true;\n }\n this._focusedOptionIndex = enabledIndices.length > 0 ? (enabledIndices[0] ?? 0) : 0;\n break;\n }\n case 'End': {\n e.preventDefault();\n if (!this.open) {\n this.open = true;\n }\n const lastEnabled = enabledIndices[enabledIndices.length - 1];\n this._focusedOptionIndex = lastEnabled !== undefined ? lastEnabled : 0;\n break;\n }\n case 'Enter':\n case ' ': {\n e.preventDefault();\n if (!this.open) {\n this.open = true;\n const selIdx = this._options.findIndex((o) => o.value === this.value);\n this._focusedOptionIndex = selIdx >= 0 ? selIdx : (enabledIndices[0] ?? 0);\n break;\n }\n if (this._focusedOptionIndex >= 0 && this._focusedOptionIndex < this._options.length) {\n const opt = this._options[this._focusedOptionIndex];\n if (opt) this._selectOption(opt);\n }\n break;\n }\n case 'Escape': {\n e.preventDefault();\n this.open = false;\n this._focusedOptionIndex = -1;\n this._trigger?.focus();\n break;\n }\n case 'Tab': {\n // Close the dropdown but allow Tab to move focus naturally\n if (this.open) {\n this.open = false;\n this._focusedOptionIndex = -1;\n }\n break;\n }\n default: {\n // Typeahead: single printable character jumps to first matching option\n if (!e.ctrlKey && !e.metaKey && !e.altKey && e.key.length === 1) {\n const char = e.key.toLowerCase();\n const startIndex = this.open ? this._focusedOptionIndex + 1 : 0;\n const matching = this._options\n .map((o, i) => ({ o, i }))\n .filter(({ o }) => !o.disabled && o.label.toLowerCase().startsWith(char));\n const afterCurrent = matching.find(({ i }) => i >= startIndex);\n const target = afterCurrent ?? matching[0];\n if (target) {\n if (!this.open) {\n this.open = true;\n }\n this._focusedOptionIndex = target.i;\n e.preventDefault();\n }\n }\n break;\n }\n }\n }\n\n // ─── Selection ───\n\n /** @internal */\n private _selectOption(option: SelectOption): void {\n if (option.disabled) return;\n this.value = option.value; // triggers updated() → sync + formValue + validity\n this._dispatchChange();\n this.open = false;\n this._focusedOptionIndex = -1;\n }\n\n // ─── Event Dispatchers ───\n\n /** @internal */\n private _dispatchChange(): void {\n this.dispatchEvent(\n new CustomEvent<{ value: string }>('hx-change', {\n bubbles: true,\n composed: true,\n detail: { value: this.value },\n }),\n );\n }\n\n /** @internal */\n private _handleNativeChange(e: Event): void {\n this.value = (e.target as HTMLSelectElement).value; // triggers updated()\n this._dispatchChange();\n }\n\n // ─── Outside Click Handler ───\n\n /** @internal */\n private _handleOutsideClick = (e: MouseEvent): void => {\n if (this.open && !e.composedPath().includes(this)) {\n this.open = false;\n }\n };\n\n // ─── Public Methods ───\n\n /** Moves focus to the visible trigger button. */\n override focus(options?: FocusOptions): void {\n this._trigger?.focus(options);\n }\n\n // ─── Render Helpers ───\n\n /** @internal */\n private _optionId(index: number): string {\n return `hx-select-option-${this._selectId}-${index}`;\n }\n\n /** @internal */\n private _renderOptions() {\n if (this._options.length === 0) {\n return html`<div class=\"field__no-options\">${this.labelNoOptions}</div>`;\n }\n\n return repeat(\n this._options,\n (opt) => opt.value,\n (opt, index) => {\n const isSelected = opt.value === this.value;\n const isFocused = index === this._focusedOptionIndex;\n\n return html`\n <div\n id=${this._optionId(index)}\n part=\"option\"\n role=\"option\"\n class=${classMap({\n field__option: true,\n 'field__option--selected': isSelected,\n 'field__option--focused': isFocused,\n 'field__option--disabled': opt.disabled,\n })}\n aria-selected=${isSelected ? 'true' : nothing}\n aria-disabled=${opt.disabled ? 'true' : nothing}\n @click=${() => this._selectOption(opt)}\n >\n <span class=\"field__option-label\">${opt.label}</span>\n </div>\n `;\n },\n );\n }\n\n // ─── Main Render ───\n\n override render() {\n const hasError = !!this.error || this._hasErrorSlot;\n\n const fieldClasses = {\n field: true,\n 'field--error': hasError,\n 'field--disabled': this.disabled,\n 'field--required': this.required,\n 'field--open': this.open,\n };\n\n const triggerClasses = {\n field__trigger: true,\n [`field__trigger--${this.size}`]: true,\n 'field__trigger--placeholder': !this.value,\n };\n\n const selectClasses = {\n field__select: true,\n [`field__select--${this.size}`]: true,\n };\n\n const describedBy =\n [\n hasError || this._hasErrorSlot ? this._errorId : null,\n this.helpText ? this._helpTextId : null,\n ]\n .filter(Boolean)\n .join(' ') || undefined;\n\n return html`\n <div part=\"field\" class=${classMap(fieldClasses)}>\n <!-- Label -->\n <slot name=\"label\">\n ${this.label\n ? html`<label\n part=\"label\"\n class=\"field__label\"\n id=${this._labelId}\n for=${this._selectId}\n >\n ${this.label}\n ${this.required\n ? html`<span class=\"field__required-marker\" aria-hidden=\"true\">*</span>`\n : nothing}\n </label>`\n : nothing}\n </slot>\n\n <!-- Select Wrapper: trigger + listbox -->\n <div part=\"select-wrapper\" class=\"field__select-wrapper\">\n <!-- Custom Trigger (combobox — div to avoid native role conflicts per APG) -->\n <div\n part=\"trigger\"\n id=${this._selectId}\n class=${classMap(triggerClasses)}\n role=\"combobox\"\n tabindex=${this.disabled ? '-1' : '0'}\n aria-expanded=${this.open ? 'true' : 'false'}\n aria-haspopup=\"listbox\"\n aria-controls=${this._listboxId}\n aria-activedescendant=${this.open && this._focusedOptionIndex >= 0\n ? this._optionId(this._focusedOptionIndex)\n : nothing}\n aria-invalid=${hasError ? 'true' : nothing}\n aria-describedby=${ifDefined(describedBy)}\n aria-required=${this.required ? 'true' : nothing}\n aria-disabled=${this.disabled ? 'true' : nothing}\n aria-labelledby=${ifDefined(this.label ? this._labelId : undefined)}\n aria-label=${ifDefined(this.ariaLabel ?? undefined)}\n @click=${this._toggleDropdown}\n @keydown=${this._handleKeydown}\n >\n <span class=\"field__trigger-value\"\n >${this._displayValue || this.placeholder || nothing}</span\n >\n <span class=\"field__chevron\" aria-hidden=\"true\"></span>\n </div>\n\n <!-- Custom Listbox Panel -->\n <div\n part=\"listbox\"\n role=\"listbox\"\n id=${this._listboxId}\n class=\"field__listbox\"\n aria-label=${ifDefined(this.label || this.ariaLabel || undefined)}\n ?hidden=${!this.open}\n >\n <div class=\"field__options\">${this._renderOptions()}</div>\n </div>\n\n <!-- Hidden native select (form participation + test compat) -->\n <select\n part=\"select\"\n class=${classMap(selectClasses)}\n tabindex=\"-1\"\n aria-hidden=\"true\"\n ?required=${this.required}\n ?disabled=${this.disabled}\n name=${ifDefined(this.name || undefined)}\n aria-label=${ifDefined(this.ariaLabel ?? undefined)}\n aria-invalid=${hasError ? 'true' : nothing}\n aria-describedby=${ifDefined(describedBy)}\n aria-required=${this.required ? 'true' : nothing}\n @change=${this._handleNativeChange}\n >\n ${this.placeholder\n ? html`<option value=\"\" disabled selected>${this.placeholder}</option>`\n : nothing}\n </select>\n </div>\n\n <!-- Hidden slot (options are read from here) -->\n <slot @slotchange=${this._handleSlotChange} style=\"display:none;\"></slot>\n\n <!-- Error -->\n <slot name=\"error\" @slotchange=${this._handleErrorSlotChange}>\n ${hasError\n ? html`<div part=\"error\" class=\"field__error\" id=${this._errorId} role=\"alert\">\n ${this.error}\n </div>`\n : nothing}\n </slot>\n\n <!-- Help Text -->\n ${this.helpText && !hasError\n ? html`\n <div part=\"help-text\" class=\"field__help-text\" id=${this._helpTextId}>\n <slot name=\"help-text\">${this.helpText}</slot>\n </div>\n `\n : nothing}\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-select': HelixSelect;\n }\n}\n\nexport type { HelixSelect as HxSelect };\n/** @deprecated Use HxSelect instead */\nexport type { HelixSelect as WcSelect };\n"],"names":["helixSelectStyles","css","_nextSelectId","createIdCounter","HelixSelect","HelixElement","opt","o","changedProperties","validSizes","devWarn","state","_mode","disabled","el","_a","slot","parsed","cloneIntoSelect","optEl","clone","child","selectedIndex","enabledIndices","i","nextDown","lastEnabled","prevUp","lastEnabledUp","selIdx","char","startIndex","matching","target","option","options","index","html","repeat","isSelected","isFocused","classMap","nothing","hasError","fieldClasses","triggerClasses","selectClasses","describedBy","ifDefined","__decorateClass","property","query","customElement"],"mappings":";;;;;;;;AAEO,MAAMA,IAAoBC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"hx-skeleton-e5K9Qaxq.js","sources":["../../src/components/hx-skeleton/hx-skeleton.styles.ts","../../src/components/hx-skeleton/hx-skeleton.ts"],"sourcesContent":["import { css } from 'lit';\n\nexport const helixSkeletonStyles = css`\n :host {\n display: block;\n }\n\n :host([loaded]) {\n display: none;\n }\n\n /* ─── Base ─── */\n\n .skeleton {\n display: block;\n background-color: var(--hx-skeleton-bg, var(--hx-color-neutral-200, #e2e8f0));\n overflow: hidden;\n position: relative;\n width: var(--_width, 100%);\n height: var(--_height, auto);\n }\n\n /* ─── Variant Shapes ─── */\n\n .skeleton--text {\n border-radius: var(--hx-skeleton-text-radius, var(--hx-border-radius-full, 9999px));\n height: var(--_height, 1em);\n }\n\n .skeleton--circle {\n border-radius: var(--hx-skeleton-circle-radius, 50%);\n aspect-ratio: var(--_circle-aspect-ratio, 1);\n width: var(--_width, 2.5rem);\n height: var(--_height, var(--_width, 2.5rem));\n }\n\n .skeleton--rect {\n border-radius: var(--hx-skeleton-rect-radius, var(--hx-border-radius-sm, 0.25rem));\n height: var(--_height, 1rem);\n }\n\n .skeleton--button {\n border-radius: var(--hx-skeleton-button-radius, var(--hx-border-radius-md, 0.375rem));\n height: var(--_height, 2.5rem);\n }\n\n .skeleton--paragraph {\n border-radius: var(--hx-skeleton-text-radius, var(--hx-border-radius-full, 9999px));\n height: var(--_height, auto);\n display: flex;\n flex-direction: column;\n gap: 0.5em;\n }\n\n /* ─── Shimmer Animation ─── */\n\n .skeleton--animated::after {\n content: '';\n position: absolute;\n inset: 0;\n background: linear-gradient(\n 90deg,\n transparent 0%,\n var(--hx-skeleton-shimmer-color, var(--hx-overlay-white-40, rgba(255, 255, 255, 0.4))) 50%,\n transparent 100%\n );\n background-size: var(--hx-skeleton-shimmer-width, 200%) 100%;\n animation: hx-skeleton-shimmer var(--hx-skeleton-duration, 1.5s) ease-in-out infinite;\n }\n\n @keyframes hx-skeleton-shimmer {\n from {\n background-position: 200% center;\n }\n to {\n background-position: -200% center;\n }\n }\n\n @media (prefers-reduced-motion: reduce) {\n .skeleton--animated::after {\n display: none;\n }\n }\n`;\n","import { LitElement, html, type PropertyValues } from 'lit';\nimport '../../utilities/document-token-adoption.js';\nimport { customElement, property } from 'lit/decorators.js';\nimport { classMap } from 'lit/directives/class-map.js';\nimport { styleMap } from 'lit/directives/style-map.js';\nimport { helixSkeletonStyles } from './hx-skeleton.styles.js';\n\n/**\n * An animated placeholder used to indicate loading content.\n * Purely decorative — hidden from assistive technology.\n * Supports a `loaded` state that announces content availability to screen readers.\n *\n * @summary Animated shimmer placeholder for loading states.\n *\n * @tag hx-skeleton\n *\n * @csspart base - The inner skeleton element.\n *\n * @cssprop [--hx-skeleton-bg=var(--hx-color-neutral-200)] - Skeleton background color.\n * @cssprop [--hx-skeleton-shimmer-color=rgba(255,255,255,0.4)] - Shimmer highlight color.\n * @cssprop [--hx-skeleton-shimmer-width=200%] - Shimmer sweep width (background-size X axis).\n * @cssprop [--hx-skeleton-duration=1.5s] - Shimmer animation duration.\n * @cssprop [--hx-skeleton-text-radius=var(--hx-border-radius-full)] - Border radius for text variant.\n * @cssprop [--hx-skeleton-rect-radius=var(--hx-border-radius-sm)] - Border radius for rect variant.\n * @cssprop [--hx-skeleton-button-radius=var(--hx-border-radius-md)] - Border radius for button variant.\n * @cssprop [--hx-skeleton-circle-radius=50%] - Border radius for circle variant.\n *\n * @fires hx-loaded - Dispatched when `loaded` transitions to `true`. Consumers should use\n * this event to update an external `aria-live` region announcing content availability.\n */\n@customElement('hx-skeleton')\nexport class HelixSkeleton extends LitElement {\n static override styles = [helixSkeletonStyles];\n\n /**\n * Shape variant of the skeleton placeholder.\n * @attr variant\n */\n @property({ type: String, reflect: true })\n variant: 'text' | 'circle' | 'rect' | 'button' | 'paragraph' = 'rect';\n\n /**\n * CSS width of the skeleton. Accepts any valid CSS width value.\n * @attr width\n */\n @property({ type: String })\n width = '100%';\n\n /**\n * CSS height of the skeleton. Accepts any valid CSS height value.\n * Defaults vary by variant when not set.\n * @attr height\n */\n @property({ type: String })\n height: string | undefined = undefined;\n\n /**\n * Whether the shimmer wave animation is active.\n * Set to false to display a static skeleton.\n * @attr animated\n */\n @property({ type: Boolean, reflect: true })\n animated = true;\n\n /**\n * When true, hides the skeleton and dispatches an `hx-loaded` event.\n * Consumers should pair this with an external `aria-live` region to\n * announce loading completion to assistive technology users.\n *\n * @example\n * ```html\n * <div aria-live=\"polite\" aria-atomic=\"true\" id=\"status\"></div>\n * <hx-skeleton id=\"sk\"></hx-skeleton>\n * <script>\n * document.getElementById('sk').addEventListener('hx-loaded', () => {\n * document.getElementById('status').textContent = 'Content has loaded.';\n * });\n * </script>\n * ```\n * @attr loaded\n */\n @property({ type: Boolean, reflect: true })\n loaded = false;\n\n // ─── Lifecycle ───\n\n override connectedCallback() {\n super.connectedCallback();\n // Hide the skeleton host from the accessibility tree entirely (P1-01).\n // Some AT + browser combinations traverse shadow hosts even when children\n // are aria-hidden. Setting on the host ensures full concealment.\n this.setAttribute('aria-hidden', 'true');\n }\n\n override updated(changedProperties: PropertyValues<this>) {\n super.updated(changedProperties);\n if (changedProperties.has('loaded') && this.loaded) {\n this.dispatchEvent(\n new CustomEvent<void>('hx-loaded', {\n bubbles: true,\n composed: true,\n }),\n );\n }\n }\n\n // ─── Render ───\n\n override render() {\n // When loaded, render nothing — the skeleton is replaced by real content.\n if (this.loaded) {\n return html``;\n }\n\n const classes = {\n skeleton: true,\n [`skeleton--${this.variant}`]: true,\n 'skeleton--animated': this.animated,\n };\n\n const styles: Record<string, string> = {\n '--_width': this.width,\n };\n if (this.height !== undefined) {\n styles['--_height'] = this.height;\n }\n\n return html`\n <span\n part=\"base\"\n class=${classMap(classes)}\n style=${styleMap(styles)}\n aria-hidden=\"true\"\n role=\"presentation\"\n ></span>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-skeleton': HelixSkeleton;\n }\n}\n"],"names":["helixSkeletonStyles","css","HelixSkeleton","LitElement","changedProperties","html","classes","styles","classMap","styleMap","__decorateClass","property","customElement"],"mappings":";;;;;AAEO,MAAMA,IAAsBC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;;;;AC6B5B,IAAMC,IAAN,cAA4BC,EAAW;AAAA,EAAvC,cAAA;AAAA,UAAA,GAAA,SAAA,GAQL,KAAA,UAA+D,QAO/D,KAAA,QAAQ,QAQR,KAAA,SAA6B,QAQ7B,KAAA,WAAW,IAoBX,KAAA,SAAS;AAAA,EAAA;AAAA;AAAA,EAIA,oBAAoB;AAC3B,UAAM,kBAAA,GAIN,KAAK,aAAa,eAAe,MAAM;AAAA,EACzC;AAAA,EAES,QAAQC,GAAyC;AACxD,UAAM,QAAQA,CAAiB,GAC3BA,EAAkB,IAAI,QAAQ,KAAK,KAAK,UAC1C,KAAK;AAAA,MACH,IAAI,YAAkB,aAAa;AAAA,QACjC,SAAS;AAAA,QACT,UAAU;AAAA,MAAA,CACX;AAAA,IAAA;AAAA,EAGP;AAAA;AAAA,EAIS,SAAS;AAEhB,QAAI,KAAK;AACP,aAAOC;AAGT,UAAMC,IAAU;AAAA,MACd,UAAU;AAAA,MACV,CAAC,aAAa,KAAK,OAAO,EAAE,GAAG;AAAA,MAC/B,sBAAsB,KAAK;AAAA,IAAA,GAGvBC,IAAiC;AAAA,MACrC,YAAY,KAAK;AAAA,IAAA;AAEnB,WAAI,KAAK,WAAW,WAClBA,EAAO,WAAW,IAAI,KAAK,SAGtBF;AAAA;AAAA;AAAA,gBAGKG,EAASF,CAAO,CAAC;AAAA,gBACjBG,EAASF,CAAM,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,EAK9B;AACF;AA1GaL,EACK,SAAS,CAACF,CAAmB;AAO7CU,EAAA;AAAA,EADCC,EAAS,EAAE,MAAM,QAAQ,SAAS,IAAM;AAAA,GAP9BT,EAQX,WAAA,WAAA,CAAA;AAOAQ,EAAA;AAAA,EADCC,EAAS,EAAE,MAAM,OAAA,CAAQ;AAAA,GAdfT,EAeX,WAAA,SAAA,CAAA;AAQAQ,EAAA;AAAA,EADCC,EAAS,EAAE,MAAM,OAAA,CAAQ;AAAA,GAtBfT,EAuBX,WAAA,UAAA,CAAA;AAQAQ,EAAA;AAAA,EADCC,EAAS,EAAE,MAAM,SAAS,SAAS,IAAM;AAAA,GA9B/BT,EA+BX,WAAA,YAAA,CAAA;AAoBAQ,EAAA;AAAA,EADCC,EAAS,EAAE,MAAM,SAAS,SAAS,IAAM;AAAA,GAlD/BT,EAmDX,WAAA,UAAA,CAAA;AAnDWA,IAANQ,EAAA;AAAA,EADNE,EAAc,aAAa;AAAA,GACfV,CAAA;"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"hx-spinner-Dyese1Tb.js","sources":["../../src/components/hx-spinner/hx-spinner.styles.ts","../../src/components/hx-spinner/hx-spinner.ts"],"sourcesContent":["import { css } from 'lit';\n\nexport const helixSpinnerStyles = css`\n :host {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n }\n\n .spinner {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: var(--_spinner-size);\n height: var(--_spinner-size);\n flex-shrink: 0;\n }\n\n .spinner__svg {\n width: 100%;\n height: 100%;\n animation: hx-spinner-rotate var(--hx-duration-spinner, 750ms) linear infinite;\n }\n\n .spinner__track {\n stroke: var(--_spinner-track-color);\n }\n\n .spinner__arc {\n stroke: var(--_spinner-color);\n /* SVG arc math: viewBox is 24×24, r=10, circumference = 2π × 10 ≈ 62.83.\n stroke-dasharray: 56 creates a visible arc of ~89% of circumference.\n stroke-dashoffset: 14 shifts the arc start to produce the ~75% visible gap aesthetic.\n Adjust both proportionally if r or viewBox dimensions change. */\n stroke-dasharray: 56;\n stroke-dashoffset: 14;\n animation: hx-spinner-dash var(--hx-duration-spinner, 750ms)\n var(--hx-easing-in-out, ease-in-out) infinite;\n transform-origin: center;\n }\n\n @keyframes hx-spinner-rotate {\n to {\n transform: rotate(360deg);\n }\n }\n\n @keyframes hx-spinner-dash {\n 0% {\n stroke-dashoffset: 50;\n }\n 50% {\n stroke-dashoffset: 14;\n }\n 100% {\n stroke-dashoffset: 50;\n }\n }\n\n @media (prefers-reduced-motion: reduce) {\n .spinner__svg {\n animation: none;\n }\n\n .spinner__arc {\n animation: none;\n /* Maintain the static partial arc at full opacity so the loading state remains\n clearly communicated without motion. A faded arc looks broken; full opacity\n alongside the track ring unambiguously signals \"in progress\". */\n stroke-dashoffset: 14;\n opacity: 1;\n }\n }\n\n /* ─── Size Variants ─── */\n\n :host([size='sm']) {\n --_spinner-size: var(--hx-size-4, 1rem);\n }\n\n :host([size='md']) {\n --_spinner-size: var(--hx-size-6, 1.5rem);\n }\n\n :host([size='lg']) {\n --_spinner-size: var(--hx-size-8, 2rem);\n }\n\n /* ─── Variant Colors ─── */\n\n :host([variant='default']) {\n --_spinner-color: var(--hx-spinner-color, var(--hx-color-neutral-600, #475569));\n --_spinner-track-color: var(--hx-spinner-track-color, var(--hx-color-neutral-200, #e2e8f0));\n }\n\n :host([variant='primary']) {\n --_spinner-color: var(--hx-spinner-color, var(--hx-color-primary-500, #2563eb));\n --_spinner-track-color: var(--hx-spinner-track-color, var(--hx-color-primary-100, #dbeafe));\n }\n\n :host([variant='inverted']) {\n --_spinner-color: var(--hx-spinner-color, var(--hx-color-neutral-0, #ffffff));\n /* Fallback for browsers without color-mix() support (Chrome < 111, Firefox < 113, Safari < 16.2).\n rgba(255, 255, 255, 0.3) approximates the intended 30% white track color. */\n --_spinner-track-color: var(\n --hx-spinner-track-color,\n var(--hx-overlay-white-30, rgba(255, 255, 255, 0.3))\n );\n }\n\n @supports (color: color-mix(in srgb, white 30%, transparent)) {\n :host([variant='inverted']) {\n --_spinner-track-color: var(\n --hx-spinner-track-color,\n color-mix(in srgb, var(--hx-color-neutral-0, #ffffff) 30%, transparent)\n );\n }\n }\n`;\n","import { LitElement, html } from 'lit';\nimport '../../utilities/document-token-adoption.js';\nimport { customElement, property } from 'lit/decorators.js';\nimport { styleMap } from 'lit/directives/style-map.js';\nimport { ifDefined } from 'lit/directives/if-defined.js';\nimport { devWarn } from '../../utils/dev-warn.js';\nimport { helixSpinnerStyles } from './hx-spinner.styles.js';\n\n/**\n * Token size values for the spinner. Use these for standard sizing.\n * The `size` property also accepts any valid CSS size string (e.g. \"3rem\", \"48px\")\n * for custom sizes — the type widens to `string` in that usage.\n */\nexport type SpinnerSize = 'sm' | 'md' | 'lg';\n\n/**\n * A circular loading indicator for inline and overlay loading states.\n * Purely visual — no slots. Announces loading state to screen readers via\n * `role=\"status\"` and an `aria-label` (customizable via the `label` prop).\n *\n * When used alongside visible loading text, set `decorative` to suppress\n * duplicate AT announcements.\n *\n * **WCAG 4.1.2 — `aria-busy` pattern for consumers:**\n * When this spinner indicates that a region of the page is loading, set\n * `aria-busy=\"true\"` on the container element that wraps the loading content\n * and remove it (or set `aria-busy=\"false\"`) once loading completes. This\n * communicates the loading state to assistive technologies at the region level,\n * complementing the spinner's own `role=\"status\"` announcement.\n *\n * ```html\n * <section aria-busy=\"true\" aria-label=\"Patient records\">\n * <hx-spinner label=\"Loading patient records\"></hx-spinner>\n * </section>\n * ```\n *\n * @summary Circular loading indicator component.\n *\n * @tag hx-spinner\n *\n * @csspart base - The SVG spinner element.\n *\n * @cssprop [--hx-spinner-color] - Spinner arc color. Defaults per variant.\n * @cssprop [--hx-spinner-track-color] - Spinner track color. Defaults per variant.\n * @cssprop [--hx-duration-spinner] - Duration of the rotation animation. Defaults to 750ms.\n */\n@customElement('hx-spinner')\nexport class HelixSpinner extends LitElement {\n static override styles = [helixSpinnerStyles];\n\n /**\n * Size of the spinner. Accepts `SpinnerSize` token values ('sm' | 'md' | 'lg'),\n * or any valid CSS size string (e.g. \"3rem\", \"48px\") for custom dimensions.\n *\n * The type is `SpinnerSize | string` which widens to `string` at the TypeScript\n * level — this is intentional to support CSS size overrides. Use `SpinnerSize`\n * values for standard sizing; custom strings bypass token-based scaling.\n * @attr hx-size\n */\n @property({ type: String, reflect: true, attribute: 'hx-size' })\n size: 'sm' | 'md' | 'lg' | (string & Record<never, never>) = 'md';\n\n /**\n * Visual variant of the spinner.\n * @attr variant\n */\n @property({ type: String, reflect: true })\n variant: 'default' | 'primary' | 'inverted' = 'default';\n\n /**\n * Accessible label announced to screen readers. Defaults to \"Loading\".\n * Reflected as an attribute for Drupal/Twig compatibility.\n * @attr label\n */\n @property({ type: String, reflect: true })\n label = 'Loading';\n\n /**\n * When true, the spinner is decorative and suppresses all ARIA announcements.\n * Use this when the spinner appears alongside visible loading text to prevent\n * duplicate announcements. Sets `role=\"presentation\"` and removes `aria-label`.\n * @attr decorative\n */\n @property({ type: Boolean, reflect: true })\n decorative = false;\n\n // ─── Lifecycle ───\n\n override connectedCallback(): void {\n super.connectedCallback();\n // Backward compat: accept legacy `size` attribute. When present and `hx-size`\n // is not set, map the value and emit a deprecation warning.\n const legacySize = this.getAttribute('size');\n if (legacySize !== null && !this.hasAttribute('hx-size')) {\n devWarn('hx-spinner', 'The \"size\" attribute is deprecated. Use \"hx-size\" instead.');\n this.size = legacySize;\n }\n }\n\n /** @internal */\n private _isTokenSize(): this is { size: SpinnerSize } {\n return this.size === 'sm' || this.size === 'md' || this.size === 'lg';\n }\n\n override render() {\n const customSizeStyle =\n !this._isTokenSize() && this.size ? styleMap({ '--_spinner-size': this.size }) : styleMap({});\n\n // Decorative spinners use role=\"presentation\" to suppress AT announcements.\n // Non-decorative spinners use role=\"status\" with aria-label for accessible naming.\n // Guard against empty label (aria-label=\"\" is a WCAG failure).\n const role = this.decorative ? 'presentation' : 'status';\n const ariaLabel = this.decorative ? undefined : this.label || undefined;\n\n return html`\n <div\n class=\"spinner\"\n part=\"base\"\n style=${customSizeStyle}\n role=${role}\n aria-label=${ifDefined(ariaLabel)}\n >\n <svg\n class=\"spinner__svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n aria-hidden=\"true\"\n focusable=\"false\"\n >\n <circle class=\"spinner__track\" cx=\"12\" cy=\"12\" r=\"10\" stroke-width=\"2.5\" fill=\"none\" />\n <path\n class=\"spinner__arc\"\n d=\"M12 2a10 10 0 0 1 10 10\"\n stroke-width=\"2.5\"\n stroke-linecap=\"round\"\n fill=\"none\"\n />\n </svg>\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-spinner': HelixSpinner;\n }\n}\n"],"names":["helixSpinnerStyles","css","HelixSpinner","LitElement","legacySize","customSizeStyle","styleMap","role","ariaLabel","html","ifDefined","__decorateClass","property","customElement"],"mappings":";;;;;AAEO,MAAMA,IAAqBC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;;;;AC6C3B,IAAMC,IAAN,cAA2BC,EAAW;AAAA,EAAtC,cAAA;AAAA,UAAA,GAAA,SAAA,GAaL,KAAA,OAA6D,MAO7D,KAAA,UAA8C,WAQ9C,KAAA,QAAQ,WASR,KAAA,aAAa;AAAA,EAAA;AAAA;AAAA,EAIJ,oBAA0B;AACjC,UAAM,kBAAA;AAGN,UAAMC,IAAa,KAAK,aAAa,MAAM;AAC3C,IAAIA,MAAe,QAAQ,CAAC,KAAK,aAAa,SAAS,MAErD,KAAK,OAAOA;AAAA,EAEhB;AAAA;AAAA,EAGQ,eAA8C;AACpD,WAAO,KAAK,SAAS,QAAQ,KAAK,SAAS,QAAQ,KAAK,SAAS;AAAA,EACnE;AAAA,EAES,SAAS;AAChB,UAAMC,IACJ,CAAC,KAAK,aAAA,KAAkB,KAAK,OAAOC,EAAS,EAAE,mBAAmB,KAAK,KAAA,CAAM,IAAIA,EAAS,CAAA,CAAE,GAKxFC,IAAO,KAAK,aAAa,iBAAiB,UAC1CC,IAAY,KAAK,aAAa,SAAY,KAAK,SAAS;AAE9D,WAAOC;AAAA;AAAA;AAAA;AAAA,gBAIKJ,CAAe;AAAA,eAChBE,CAAI;AAAA,qBACEG,EAAUF,CAAS,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAoBvC;AACF;AA9FaN,EACK,SAAS,CAACF,CAAkB;AAY5CW,EAAA;AAAA,EADCC,EAAS,EAAE,MAAM,QAAQ,SAAS,IAAM,WAAW,WAAW;AAAA,GAZpDV,EAaX,WAAA,QAAA,CAAA;AAOAS,EAAA;AAAA,EADCC,EAAS,EAAE,MAAM,QAAQ,SAAS,IAAM;AAAA,GAnB9BV,EAoBX,WAAA,WAAA,CAAA;AAQAS,EAAA;AAAA,EADCC,EAAS,EAAE,MAAM,QAAQ,SAAS,IAAM;AAAA,GA3B9BV,EA4BX,WAAA,SAAA,CAAA;AASAS,EAAA;AAAA,EADCC,EAAS,EAAE,MAAM,SAAS,SAAS,IAAM;AAAA,GApC/BV,EAqCX,WAAA,cAAA,CAAA;AArCWA,IAANS,EAAA;AAAA,EADNE,EAAc,YAAY;AAAA,GACdX,CAAA;"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"id-counter-JhvVCnjh.js","sources":["../../src/base/helix-element.ts","../../src/base/id-counter.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","/**\n * Module-level monotonic ID counter factory.\n *\n * Provides collision-free, deterministic, SSR-safe IDs for components that\n * need stable element IDs (for ARIA relationships, label associations, etc.)\n * without relying on Math.random() which causes hydration mismatches.\n *\n * @public\n */\n\nconst counters = new Map<string, number>();\n\n/**\n * Creates a monotonic ID generator for the given namespace.\n *\n * @param namespace - Component namespace (e.g. 'hx-text-input')\n * @returns A function that returns the next unique ID string\n * @public\n *\n * @example\n * ```ts\n * const nextId = createIdCounter('hx-text-input');\n * private _id = nextId(); // 'hx-text-input-0', 'hx-text-input-1', ...\n * ```\n */\nexport function createIdCounter(namespace: string): () => string {\n return () => {\n const current = counters.get(namespace) ?? 0;\n counters.set(namespace, current + 1);\n return `${namespace}-${current}`;\n };\n}\n\n/**\n * Resets the counter for the given namespace (or all namespaces if omitted).\n * Use in test `beforeEach()` for counter isolation between tests.\n *\n * @param namespace - Optional namespace to reset. If omitted, resets all counters.\n * @public\n */\nexport function resetIdCounter(namespace?: string): void {\n if (namespace !== undefined) {\n counters.delete(namespace);\n } else {\n counters.clear();\n }\n}\n"],"names":["_HelixElement","LitElement","__privateAdd","_internals","cached","__privateGet","internals","__privateSet","disabled","state","mode","_disabled","_state","_mode","HelixElement","counters","createIdCounter","namespace","current","resetIdCounter"],"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;AC7BP,MAAMe,wBAAe,IAAA;AAed,SAASC,EAAgBC,GAAiC;AAC/D,SAAO,MAAM;AACX,UAAMC,IAAUH,EAAS,IAAIE,CAAS,KAAK;AAC3C,WAAAF,EAAS,IAAIE,GAAWC,IAAU,CAAC,GAC5B,GAAGD,CAAS,IAAIC,CAAO;AAAA,EAChC;AACF;AASO,SAASC,EAAeF,GAA0B;AACvD,EAAIA,MAAc,SAChBF,EAAS,OAAOE,CAAS,IAEzBF,EAAS,MAAA;AAEb;"}
|