@helixui/library 0.3.1 → 0.3.3
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 +2076 -1606
- package/dist/components/hx-action-bar/hx-action-bar.d.ts +3 -1
- package/dist/components/hx-action-bar/hx-action-bar.d.ts.map +1 -1
- package/dist/components/hx-action-bar/index.js +1 -1
- package/dist/components/hx-badge/hx-badge.d.ts +8 -0
- package/dist/components/hx-badge/hx-badge.d.ts.map +1 -1
- package/dist/components/hx-badge/hx-badge.styles.d.ts.map +1 -1
- package/dist/components/hx-badge/index.d.ts +1 -0
- package/dist/components/hx-badge/index.d.ts.map +1 -1
- package/dist/components/hx-badge/index.js +1 -1
- package/dist/components/hx-breadcrumb/hx-breadcrumb-item.styles.d.ts.map +1 -1
- package/dist/components/hx-breadcrumb/hx-breadcrumb.d.ts +0 -25
- 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-button/hx-button.styles.d.ts.map +1 -1
- package/dist/components/hx-button/index.js +1 -1
- package/dist/components/hx-button-group/hx-button-group.d.ts +3 -1
- package/dist/components/hx-button-group/hx-button-group.d.ts.map +1 -1
- package/dist/components/hx-button-group/index.js +1 -1
- package/dist/components/hx-checkbox-group/hx-checkbox-group.d.ts +3 -1
- package/dist/components/hx-checkbox-group/hx-checkbox-group.d.ts.map +1 -1
- package/dist/components/hx-checkbox-group/index.js +1 -1
- package/dist/components/hx-container/hx-container.d.ts +12 -0
- package/dist/components/hx-container/hx-container.d.ts.map +1 -1
- package/dist/components/hx-container/hx-container.styles.d.ts.map +1 -1
- package/dist/components/hx-container/index.d.ts +1 -0
- package/dist/components/hx-container/index.d.ts.map +1 -1
- package/dist/components/hx-container/index.js +1 -1
- package/dist/components/hx-copy-button/hx-copy-button.d.ts +7 -0
- package/dist/components/hx-copy-button/hx-copy-button.d.ts.map +1 -1
- package/dist/components/hx-drawer/hx-drawer.d.ts +1 -1
- package/dist/components/hx-drawer/index.js +1 -1
- package/dist/components/hx-icon-button/hx-icon-button.d.ts +87 -0
- package/dist/components/hx-icon-button/hx-icon-button.d.ts.map +1 -0
- package/dist/components/hx-icon-button/hx-icon-button.styles.d.ts +2 -0
- package/dist/components/hx-icon-button/hx-icon-button.styles.d.ts.map +1 -0
- package/dist/components/hx-icon-button/index.d.ts +2 -0
- package/dist/components/hx-icon-button/index.d.ts.map +1 -0
- package/dist/components/hx-icon-button/index.js +5 -0
- package/dist/components/hx-icon-button/index.js.map +1 -0
- package/dist/components/hx-image/index.js +1 -1
- package/dist/components/hx-number-input/hx-number-input.d.ts +2 -2
- package/dist/components/hx-number-input/hx-number-input.d.ts.map +1 -1
- package/dist/components/hx-pagination/hx-pagination.d.ts +2 -0
- package/dist/components/hx-pagination/hx-pagination.d.ts.map +1 -1
- package/dist/components/hx-pagination/index.d.ts +1 -0
- package/dist/components/hx-pagination/index.d.ts.map +1 -1
- package/dist/components/hx-prose/index.js +1 -1
- package/dist/components/hx-radio-group/hx-radio-group.d.ts +31 -10
- package/dist/components/hx-radio-group/hx-radio-group.d.ts.map +1 -1
- package/dist/components/hx-radio-group/hx-radio.styles.d.ts.map +1 -1
- package/dist/components/hx-radio-group/index.js +1 -1
- package/dist/components/hx-slider/hx-slider.d.ts +6 -4
- package/dist/components/hx-slider/hx-slider.d.ts.map +1 -1
- package/dist/components/hx-slider/index.js +1 -1
- package/dist/components/hx-spinner/hx-spinner.d.ts +12 -6
- package/dist/components/hx-spinner/hx-spinner.d.ts.map +1 -1
- package/dist/components/hx-spinner/index.d.ts +1 -0
- package/dist/components/hx-spinner/index.d.ts.map +1 -1
- package/dist/components/hx-stack/hx-stack.d.ts +20 -0
- package/dist/components/hx-stack/hx-stack.d.ts.map +1 -1
- package/dist/components/hx-stack/index.js +1 -1
- package/dist/components/hx-status-indicator/hx-status-indicator.d.ts +2 -2
- package/dist/components/hx-status-indicator/hx-status-indicator.d.ts.map +1 -1
- package/dist/components/hx-steps/hx-step.d.ts +8 -0
- package/dist/components/hx-steps/hx-step.d.ts.map +1 -1
- package/dist/components/hx-structured-list/index.js +1 -1
- package/dist/components/hx-switch/hx-switch.d.ts +2 -2
- package/dist/components/hx-switch/hx-switch.d.ts.map +1 -1
- package/dist/components/hx-tabs/hx-tabs.d.ts +1 -1
- package/dist/components/hx-tabs/hx-tabs.d.ts.map +1 -1
- package/dist/components/hx-tag/index.d.ts +3 -0
- package/dist/components/hx-tag/index.d.ts.map +1 -1
- package/dist/components/hx-text/hx-text.d.ts +0 -2
- package/dist/components/hx-text/hx-text.d.ts.map +1 -1
- package/dist/components/hx-textarea/hx-textarea.d.ts +7 -0
- package/dist/components/hx-textarea/hx-textarea.d.ts.map +1 -1
- package/dist/components/hx-textarea/index.js +1 -1
- package/dist/components/hx-theme/hx-theme.d.ts +4 -0
- package/dist/components/hx-theme/hx-theme.d.ts.map +1 -1
- package/dist/components/hx-theme/index.d.ts +3 -1
- package/dist/components/hx-theme/index.d.ts.map +1 -1
- package/dist/components/hx-toggle-button/hx-toggle-button.d.ts +2 -2
- package/dist/components/hx-toggle-button/hx-toggle-button.d.ts.map +1 -1
- package/dist/components/hx-toggle-button/index.js +1 -1
- package/dist/components/hx-tree-view/hx-tree-item.d.ts +29 -10
- package/dist/components/hx-tree-view/hx-tree-item.d.ts.map +1 -1
- package/dist/components/hx-tree-view/hx-tree-item.styles.d.ts.map +1 -1
- package/dist/components/hx-tree-view/hx-tree-view.d.ts +22 -2
- package/dist/components/hx-tree-view/hx-tree-view.d.ts.map +1 -1
- package/dist/components/hx-tree-view/hx-tree-view.styles.d.ts.map +1 -1
- package/dist/components/hx-tree-view/index.d.ts +6 -1
- package/dist/components/hx-tree-view/index.d.ts.map +1 -1
- package/dist/components/hx-tree-view/index.js +1 -1
- package/dist/index.d.ts +13 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +107 -105
- package/dist/index.js.map +1 -1
- package/dist/shared/{hx-action-bar-D43v5rA2.js → hx-action-bar-B4i9tBCP.js} +71 -61
- package/dist/shared/hx-action-bar-B4i9tBCP.js.map +1 -0
- package/dist/shared/{hx-badge-DYB1Pnym.js → hx-badge-CjT0d8NK.js} +9 -2
- package/dist/shared/hx-badge-CjT0d8NK.js.map +1 -0
- package/dist/shared/{hx-breadcrumb-item-TKRcrMYc.js → hx-breadcrumb-item-DtSxRZ_W.js} +25 -18
- package/dist/shared/hx-breadcrumb-item-DtSxRZ_W.js.map +1 -0
- package/dist/shared/{hx-button-SAbf4_jC.js → hx-button-CtiJsmOg.js} +31 -29
- package/dist/shared/hx-button-CtiJsmOg.js.map +1 -0
- package/dist/shared/{hx-button-group-DET_Pkxt.js → hx-button-group-BMV5qFs4.js} +19 -13
- package/dist/shared/{hx-button-group-DET_Pkxt.js.map → hx-button-group-BMV5qFs4.js.map} +1 -1
- package/dist/shared/{hx-checkbox-group-CIIijwmc.js → hx-checkbox-group-DTS9iT4b.js} +26 -20
- package/dist/shared/hx-checkbox-group-DTS9iT4b.js.map +1 -0
- package/dist/shared/{hx-container-BXZBaOGG.js → hx-container-DLUKnTi9.js} +9 -8
- package/dist/shared/hx-container-DLUKnTi9.js.map +1 -0
- package/dist/shared/hx-copy-button-BXL1xkxb.js.map +1 -1
- package/dist/shared/{hx-drawer-CenIAGuR.js → hx-drawer-bTF0nbrg.js} +2 -2
- package/dist/shared/hx-drawer-bTF0nbrg.js.map +1 -0
- package/dist/shared/hx-icon-button-C_fsUJW4.js +257 -0
- package/dist/shared/hx-icon-button-C_fsUJW4.js.map +1 -0
- package/dist/shared/{hx-image-CzkOEeO4.js → hx-image-xyb_tHCR.js} +2 -2
- package/dist/shared/hx-image-xyb_tHCR.js.map +1 -0
- package/dist/shared/hx-number-input-CS6_w1lT.js.map +1 -1
- package/dist/shared/hx-pagination-DNFgXQm3.js.map +1 -1
- package/dist/shared/{hx-prose-BUkZ8rB3.js → hx-prose-DZh2KrMb.js} +10 -7
- package/dist/shared/{hx-prose-BUkZ8rB3.js.map → hx-prose-DZh2KrMb.js.map} +1 -1
- package/dist/shared/{hx-radio-reSaVmIB.js → hx-radio-CGtFKls2.js} +42 -14
- package/dist/shared/hx-radio-CGtFKls2.js.map +1 -0
- package/dist/shared/{hx-slider-CzHOl3Ur.js → hx-slider-Duzmuid9.js} +12 -8
- package/dist/shared/hx-slider-Duzmuid9.js.map +1 -0
- package/dist/shared/hx-spinner-BOApJ-g9.js.map +1 -1
- package/dist/shared/{hx-stack-C3xUwi6-.js → hx-stack-CfoW7jU7.js} +21 -1
- package/dist/shared/{hx-stack-C3xUwi6-.js.map → hx-stack-CfoW7jU7.js.map} +1 -1
- package/dist/shared/hx-status-indicator-oYWOkWlD.js.map +1 -1
- package/dist/shared/hx-step-nMT0fHEn.js.map +1 -1
- package/dist/shared/{hx-structured-list-DKborM60.js → hx-structured-list-CMja1VXz.js} +5 -5
- package/dist/shared/{hx-structured-list-DKborM60.js.map → hx-structured-list-CMja1VXz.js.map} +1 -1
- package/dist/shared/hx-switch-BPvIcDpM.js.map +1 -1
- package/dist/shared/hx-tab-panel-C7h5lRpw.js.map +1 -1
- package/dist/shared/hx-text-NjKoQATI.js.map +1 -1
- package/dist/shared/{hx-textarea-BLcReynr.js → hx-textarea-B_nmxzhC.js} +12 -8
- package/dist/shared/hx-textarea-B_nmxzhC.js.map +1 -0
- package/dist/shared/hx-theme-6GDoUG8j.js.map +1 -1
- package/dist/shared/{hx-toggle-button---Z4zvmn.js → hx-toggle-button--xCXWRJW.js} +3 -3
- package/dist/shared/{hx-toggle-button---Z4zvmn.js.map → hx-toggle-button--xCXWRJW.js.map} +1 -1
- package/dist/shared/{hx-tree-item-CIo3ek2M.js → hx-tree-item-Cesh_du5.js} +170 -148
- package/dist/shared/hx-tree-item-Cesh_du5.js.map +1 -0
- package/package.json +7 -1
- package/dist/shared/hx-action-bar-D43v5rA2.js.map +0 -1
- package/dist/shared/hx-badge-DYB1Pnym.js.map +0 -1
- package/dist/shared/hx-breadcrumb-item-TKRcrMYc.js.map +0 -1
- package/dist/shared/hx-button-SAbf4_jC.js.map +0 -1
- package/dist/shared/hx-checkbox-group-CIIijwmc.js.map +0 -1
- package/dist/shared/hx-container-BXZBaOGG.js.map +0 -1
- package/dist/shared/hx-drawer-CenIAGuR.js.map +0 -1
- package/dist/shared/hx-image-CzkOEeO4.js.map +0 -1
- package/dist/shared/hx-radio-reSaVmIB.js.map +0 -1
- package/dist/shared/hx-slider-CzHOl3Ur.js.map +0 -1
- package/dist/shared/hx-textarea-BLcReynr.js.map +0 -1
- package/dist/shared/hx-tree-item-CIo3ek2M.js.map +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { css as m, LitElement as u, html as d, nothing as x } from "lit";
|
|
2
2
|
import { property as l, customElement as b } from "lit/decorators.js";
|
|
3
3
|
import { tokenStyles as f } from "@helixui/tokens/lit";
|
|
4
|
-
const
|
|
4
|
+
const y = m`
|
|
5
5
|
:host {
|
|
6
6
|
display: block;
|
|
7
7
|
font-family: var(
|
|
@@ -38,10 +38,10 @@ const _ = m`
|
|
|
38
38
|
display: none;
|
|
39
39
|
}
|
|
40
40
|
`;
|
|
41
|
-
var
|
|
42
|
-
for (var r = i > 1 ? void 0 : i ?
|
|
41
|
+
var _ = Object.defineProperty, v = Object.getOwnPropertyDescriptor, p = (e, s, t, i) => {
|
|
42
|
+
for (var r = i > 1 ? void 0 : i ? v(s, t) : s, a = e.length - 1, n; a >= 0; a--)
|
|
43
43
|
(n = e[a]) && (r = (i ? n(s, t, r) : n(r)) || r);
|
|
44
|
-
return i && r &&
|
|
44
|
+
return i && r && _(s, t, r), r;
|
|
45
45
|
};
|
|
46
46
|
let o = class extends u {
|
|
47
47
|
constructor() {
|
|
@@ -188,21 +188,21 @@ let o = class extends u {
|
|
|
188
188
|
`;
|
|
189
189
|
}
|
|
190
190
|
};
|
|
191
|
-
o.styles = [f,
|
|
191
|
+
o.styles = [f, y];
|
|
192
192
|
o._instanceCounter = 0;
|
|
193
|
-
|
|
193
|
+
p([
|
|
194
194
|
l({ type: String })
|
|
195
195
|
], o.prototype, "separator", 2);
|
|
196
|
-
|
|
196
|
+
p([
|
|
197
197
|
l({ type: String })
|
|
198
198
|
], o.prototype, "label", 2);
|
|
199
|
-
|
|
199
|
+
p([
|
|
200
200
|
l({ type: Number, attribute: "max-items" })
|
|
201
201
|
], o.prototype, "maxItems", 2);
|
|
202
|
-
|
|
202
|
+
p([
|
|
203
203
|
l({ type: Boolean, attribute: "json-ld" })
|
|
204
204
|
], o.prototype, "jsonLd", 2);
|
|
205
|
-
o =
|
|
205
|
+
o = p([
|
|
206
206
|
b("hx-breadcrumb")
|
|
207
207
|
], o);
|
|
208
208
|
const g = m`
|
|
@@ -211,6 +211,13 @@ const g = m`
|
|
|
211
211
|
align-items: center;
|
|
212
212
|
}
|
|
213
213
|
|
|
214
|
+
/*
|
|
215
|
+
* display: contents removes [part='item'] from the box model entirely.
|
|
216
|
+
* This is intentional — the wrapper exists only for slot selection purposes.
|
|
217
|
+
* Consumers using ::part(item) CANNOT apply box-model properties (padding,
|
|
218
|
+
* margin, background, border) to this part. Use ::part(link) or ::part(text)
|
|
219
|
+
* for visual styling of breadcrumb item content.
|
|
220
|
+
*/
|
|
214
221
|
[part='item'] {
|
|
215
222
|
display: contents;
|
|
216
223
|
}
|
|
@@ -268,10 +275,10 @@ const g = m`
|
|
|
268
275
|
padding: 0;
|
|
269
276
|
}
|
|
270
277
|
`;
|
|
271
|
-
var
|
|
272
|
-
for (var r = i > 1 ? void 0 : i ?
|
|
278
|
+
var C = Object.defineProperty, L = Object.getOwnPropertyDescriptor, h = (e, s, t, i) => {
|
|
279
|
+
for (var r = i > 1 ? void 0 : i ? L(s, t) : s, a = e.length - 1, n; a >= 0; a--)
|
|
273
280
|
(n = e[a]) && (r = (i ? n(s, t, r) : n(r)) || r);
|
|
274
|
-
return i && r &&
|
|
281
|
+
return i && r && C(s, t, r), r;
|
|
275
282
|
};
|
|
276
283
|
let c = class extends u {
|
|
277
284
|
constructor() {
|
|
@@ -290,20 +297,20 @@ let c = class extends u {
|
|
|
290
297
|
}
|
|
291
298
|
};
|
|
292
299
|
c.styles = [f, g];
|
|
293
|
-
|
|
300
|
+
h([
|
|
294
301
|
l({ type: String, reflect: !0 })
|
|
295
302
|
], c.prototype, "href", 2);
|
|
296
|
-
|
|
303
|
+
h([
|
|
297
304
|
l({ type: Boolean, attribute: "data-bc-last", reflect: !0 })
|
|
298
305
|
], c.prototype, "dataBcLast", 2);
|
|
299
|
-
|
|
306
|
+
h([
|
|
300
307
|
l({ type: Boolean, reflect: !0 })
|
|
301
308
|
], c.prototype, "current", 2);
|
|
302
|
-
c =
|
|
309
|
+
c = h([
|
|
303
310
|
b("hx-breadcrumb-item")
|
|
304
311
|
], c);
|
|
305
312
|
export {
|
|
306
313
|
o as H,
|
|
307
314
|
c as a
|
|
308
315
|
};
|
|
309
|
-
//# sourceMappingURL=hx-breadcrumb-item-
|
|
316
|
+
//# sourceMappingURL=hx-breadcrumb-item-DtSxRZ_W.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hx-breadcrumb-item-DtSxRZ_W.js","sources":["../../src/components/hx-breadcrumb/hx-breadcrumb.styles.ts","../../src/components/hx-breadcrumb/hx-breadcrumb.ts","../../src/components/hx-breadcrumb/hx-breadcrumb-item.styles.ts","../../src/components/hx-breadcrumb/hx-breadcrumb-item.ts"],"sourcesContent":["import { css } from 'lit';\n\nexport const helixBreadcrumbStyles = css`\n :host {\n display: block;\n font-family: var(\n --hx-breadcrumb-font-family,\n var(--hx-font-family-sans, system-ui, sans-serif)\n );\n font-size: var(--hx-breadcrumb-font-size, var(--hx-font-size-sm, 0.875rem));\n }\n\n [part='nav'] {\n /* nav landmark — no additional styling needed */\n }\n\n [part='list'] {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n list-style: none;\n margin: 0;\n padding: 0;\n gap: 0;\n }\n\n /* Hide middle items when collapsed via maxItems */\n ::slotted([data-bc-hidden]) {\n display: none;\n }\n\n /* Visually hide the separator slot — used only to read text content.\n * display:none is intentional: the slot contains no interactive or focusable\n * content. If a future change adds focusable elements to this slot, switch to\n * visibility:hidden + position:absolute to preserve focus reachability. */\n .separator-slot {\n display: none;\n }\n`;\n","import { LitElement, html } from 'lit';\nimport { customElement, property } from 'lit/decorators.js';\nimport { tokenStyles } from '@helixui/tokens/lit';\nimport { helixBreadcrumbStyles } from './hx-breadcrumb.styles.js';\n\n/**\n * Hierarchical page path navigation showing current location in site structure.\n *\n * @summary Navigation breadcrumb showing the page hierarchy. Works with Drupal's breadcrumb system.\n *\n * @tag hx-breadcrumb\n *\n * @slot - Default slot for hx-breadcrumb-item children.\n * @slot separator - Optional separator element. Its text content overrides the `separator` property.\n *\n * @csspart nav - The nav landmark element.\n * @csspart list - The ordered list containing items.\n *\n * @cssprop [--hx-breadcrumb-separator-content='/'] - Separator character between items.\n * NOTE: If overriding this custom property directly in CSS (rather than via the `separator`\n * attribute), the value MUST be quoted: `--hx-breadcrumb-separator-content: \">\"`. An unquoted\n * value is invalid for the CSS `content` property and will silently render nothing.\n * @cssprop [--hx-breadcrumb-separator-color=var(--hx-color-neutral-400)] - Separator color.\n * @cssprop [--hx-breadcrumb-separator-gap=var(--hx-space-1)] - Horizontal gap around separators.\n * @cssprop [--hx-breadcrumb-font-size=var(--hx-font-size-sm)] - Font size.\n * @cssprop [--hx-breadcrumb-link-color=var(--hx-color-primary-600)] - Link color.\n * @cssprop [--hx-breadcrumb-link-hover-color=var(--hx-color-primary-700)] - Link hover color.\n * @cssprop [--hx-breadcrumb-text-color=var(--hx-color-neutral-700)] - Current page text color.\n * @cssprop [--hx-breadcrumb-item-max-width] - Max-width for item text truncation (e.g. `12rem`).\n */\n/** Typed schema.org ListItem entry for JSON-LD BreadcrumbList structured data. */\ninterface JsonLdListItem {\n '@type': string;\n position: number;\n name: string;\n item?: string;\n}\n\n@customElement('hx-breadcrumb')\nexport class HelixBreadcrumb extends LitElement {\n static override styles = [tokenStyles, helixBreadcrumbStyles];\n\n /**\n * Per-instance counter used to generate stable, deterministic IDs for the\n * injected JSON-LD script tags. Deterministic IDs (vs Math.random()) allow\n * SSR frameworks to match server-rendered script tags during hydration.\n */\n private static _instanceCounter = 0;\n\n /**\n * The separator character displayed between breadcrumb items.\n * @attr separator\n */\n @property({ type: String })\n separator = '/';\n\n /**\n * The accessible label for the nav landmark.\n * @attr label\n */\n @property({ type: String })\n label = 'Breadcrumb';\n\n /**\n * Maximum number of items to show before collapsing middle items with an ellipsis.\n * Set to 0 (default) to show all items. The ellipsis is a keyboard-accessible\n * button; activating it expands the full breadcrumb by setting maxItems to 0.\n * @attr max-items\n */\n @property({ type: Number, attribute: 'max-items' })\n maxItems = 0;\n\n /**\n * When true, injects a JSON-LD BreadcrumbList structured data script into the document head.\n *\n * NOTE: Drupal manages `<head>` content via its own render pipeline. Injecting a\n * `<script>` directly via `document.head.appendChild()` in a Drupal context:\n * 1. Bypasses Drupal's deduplication and `hook_html_head_alter()` hook.\n * 2. Is not cacheable by Drupal's page cache.\n * 3. Will be wiped on BigPipe partial page replacements.\n *\n * For Drupal integrations, leave `json-ld` false and use the structured data\n * Twig template instead (see `hx-breadcrumb.twig` in the component directory).\n *\n * @attr json-ld\n */\n @property({ type: Boolean, attribute: 'json-ld' })\n jsonLd = false;\n\n private _ellipsisItem: Element | null = null;\n private _jsonLdScript: HTMLScriptElement | null = null;\n private _boundEllipsisClick: (e: Event) => void = () => undefined;\n private _boundEllipsisKeydown: (e: KeyboardEvent) => void = () => undefined;\n\n /**\n * Tracks which items had their `current` attribute set by this component\n * (as opposed to set by a consumer/Drupal template). This lets us re-evaluate\n * positional current-page detection on each slotchange without incorrectly\n * treating a previously component-set `current` attribute as a consumer-set\n * explicit override.\n */\n private readonly _managedCurrentItems = new WeakSet<Element>();\n\n /**\n * Stable per-instance ID used to tag the injected script element so that\n * multiple hx-breadcrumb instances on the same page don't produce conflicting\n * or duplicate structured-data blocks. Each instance owns exactly one script\n * tag identified by this ID; any stale tag from a previous render cycle is\n * removed before a new one is inserted.\n *\n * Uses a static counter (not Math.random()) so IDs are deterministic across\n * server and client renders, enabling SSR hydration matching.\n */\n private readonly _jsonLdId = `hx-breadcrumb-ld-${++HelixBreadcrumb._instanceCounter}`;\n\n // ─── Item Helpers ───\n\n /** Returns only real breadcrumb items, excluding the managed ellipsis element. */\n private _getBreadcrumbItems(slot: HTMLSlotElement): Element[] {\n return slot\n .assignedElements({ flatten: true })\n .filter(\n (el) =>\n el.tagName.toLowerCase() === 'hx-breadcrumb-item' &&\n !el.classList.contains('hx-bc-ellipsis'),\n );\n }\n\n /**\n * Applies aria/state attributes to the item list.\n *\n * Current-page detection: if any item has an explicit `current` attribute\n * (e.g. set by a Drupal Twig template), that item is treated as the current\n * page. Otherwise the last item is the current page (default behaviour).\n *\n * This separation allows Drupal to control current-page marking without\n * relying on item order.\n */\n private _applyItemAttributes(items: Element[]): void {\n // Detect consumer-set 'current' attributes. An item has an explicit consumer\n // current if it has the 'current' attribute AND the component did not set it\n // (tracked via _managedCurrentItems). This prevents component-managed state\n // from being misread as a consumer override on subsequent slotchange events.\n const hasExplicitCurrent = items.some(\n (el) => el.hasAttribute('current') && !this._managedCurrentItems.has(el),\n );\n\n items.forEach((item, i) => {\n const el = item as HTMLElement;\n const isLast = i === items.length - 1;\n\n // Separator hiding: always positional — last item has no trailing separator.\n if (isLast) {\n el.setAttribute('data-bc-last', '');\n } else {\n el.removeAttribute('data-bc-last');\n }\n\n // Current-page marker: explicit consumer attribute wins over positional last.\n // The item component renders aria-current=\"page\" on its inner element\n // based on this attribute (see hx-breadcrumb-item.ts).\n if (!hasExplicitCurrent) {\n if (isLast) {\n el.setAttribute('current', '');\n this._managedCurrentItems.add(el);\n } else {\n el.removeAttribute('current');\n this._managedCurrentItems.delete(el);\n }\n }\n // When hasExplicitCurrent is true, leave 'current' attributes as-is so\n // consumer or Drupal template markup is not overridden.\n });\n }\n\n // ─── Slot Handling ───\n\n private _handleSlotChange(e: Event): void {\n const slot = e.target as HTMLSlotElement;\n const items = this._getBreadcrumbItems(slot);\n\n // Handle collapse behaviour\n if (this.maxItems > 0 && items.length > this.maxItems) {\n this._applyCollapse(items);\n } else {\n this._removeCollapse(items);\n }\n\n this._applyItemAttributes(items);\n\n if (this.jsonLd) {\n this._updateJsonLd(items);\n }\n }\n\n private _handleSeparatorSlotChange(e: Event): void {\n const slot = e.target as HTMLSlotElement;\n const assigned = slot.assignedElements({ flatten: true });\n if (assigned.length > 0) {\n const text = (assigned[0] as HTMLElement).textContent?.trim() ?? '';\n this.style.setProperty('--hx-breadcrumb-separator-content', JSON.stringify(text));\n }\n }\n\n // ─── Collapse ───\n\n private _applyCollapse(items: Element[]): void {\n // Show only first and last; hide all middle items\n items.forEach((item, i) => {\n const el = item as HTMLElement;\n if (i === 0 || i === items.length - 1) {\n el.removeAttribute('data-bc-hidden');\n } else {\n el.setAttribute('data-bc-hidden', '');\n }\n });\n\n // Create the ellipsis element once\n if (!this._ellipsisItem) {\n const ellipsis = document.createElement('hx-breadcrumb-item');\n ellipsis.classList.add('hx-bc-ellipsis');\n\n // Keyboard-accessible expand button. Events handled via host-level delegation\n // in _handleEllipsisClick / _handleEllipsisKeydown.\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.textContent = '…';\n btn.setAttribute('aria-label', 'Show all breadcrumb items');\n ellipsis.appendChild(btn);\n\n this._ellipsisItem = ellipsis;\n }\n\n // Insert ellipsis after first item only if not already correctly placed\n const firstItem = items[0];\n if (!firstItem) return;\n if (this._ellipsisItem.previousElementSibling !== firstItem) {\n firstItem.after(this._ellipsisItem);\n }\n }\n\n private _removeCollapse(items: Element[]): void {\n items.forEach((item) => {\n (item as HTMLElement).removeAttribute('data-bc-hidden');\n });\n\n if (this._ellipsisItem?.isConnected) {\n this._ellipsisItem.remove();\n }\n }\n\n private _handleEllipsisClick(e: Event): void {\n if ((e.target as Element)?.closest?.('.hx-bc-ellipsis')) {\n this._expandBreadcrumb();\n }\n }\n\n private _handleEllipsisKeydown(e: KeyboardEvent): void {\n if (e.key === 'Enter' || e.key === ' ') {\n if ((e.target as Element)?.closest?.('.hx-bc-ellipsis')) {\n e.preventDefault();\n this._expandBreadcrumb();\n }\n }\n }\n\n /**\n * Expands a collapsed breadcrumb by resetting maxItems to 0.\n * Called by the ellipsis expand button (click or Enter/Space).\n */\n private _expandBreadcrumb(): void {\n this.maxItems = 0;\n // updated() will detect the maxItems change and call _removeCollapse.\n }\n\n // ─── JSON-LD ───\n\n /**\n * JSON-LD ListItem entry with typed fields to avoid Record<string, unknown>.\n */\n private _buildListItem(item: Element, position: number): JsonLdListItem {\n const href = (item as HTMLElement).getAttribute('href');\n const name = (item as HTMLElement).textContent?.trim() ?? '';\n const entry: JsonLdListItem = {\n '@type': 'ListItem',\n position,\n name,\n };\n if (href) entry.item = href;\n return entry;\n }\n\n private _updateJsonLd(items: Element[]): void {\n const schema = {\n '@context': 'https://schema.org',\n '@type': 'BreadcrumbList',\n itemListElement: items.map((item, i) => this._buildListItem(item, i + 1)),\n };\n\n if (!this._jsonLdScript) {\n // Dedup guard: remove any stale script with this instance's ID before\n // creating a fresh one. This handles the edge case where the element was\n // reconnected to the DOM after being disconnected without the script\n // reference being re-established.\n document.getElementById(this._jsonLdId)?.remove();\n\n this._jsonLdScript = document.createElement('script');\n this._jsonLdScript.type = 'application/ld+json';\n this._jsonLdScript.id = this._jsonLdId;\n this._jsonLdScript.setAttribute('data-hx-breadcrumb', '');\n document.head.appendChild(this._jsonLdScript);\n }\n\n this._jsonLdScript.textContent = JSON.stringify(schema);\n }\n\n private _removeJsonLd(): void {\n this._jsonLdScript?.remove();\n this._jsonLdScript = null;\n }\n\n // ─── Lifecycle ───\n\n override connectedCallback(): void {\n super.connectedCallback();\n this._boundEllipsisClick = this._handleEllipsisClick.bind(this);\n this._boundEllipsisKeydown = this._handleEllipsisKeydown.bind(this);\n this.addEventListener('click', this._boundEllipsisClick);\n this.addEventListener('keydown', this._boundEllipsisKeydown as EventListener);\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n this.removeEventListener('click', this._boundEllipsisClick);\n this.removeEventListener('keydown', this._boundEllipsisKeydown as EventListener);\n this._removeJsonLd();\n }\n\n override updated(changedProperties: Map<string, unknown>): void {\n super.updated(changedProperties);\n\n if (changedProperties.has('separator')) {\n // JSON.stringify wraps the string in quotes so the value is valid\n // for use in the CSS `content` property (e.g. '/' becomes '\"/\"').\n this.style.setProperty('--hx-breadcrumb-separator-content', JSON.stringify(this.separator));\n }\n\n if (changedProperties.has('maxItems')) {\n // Re-evaluate collapse state when maxItems changes programmatically\n // (e.g. when the expand button resets maxItems to 0).\n const slot = this.shadowRoot?.querySelector<HTMLSlotElement>('slot:not([name])');\n if (slot) {\n const items = this._getBreadcrumbItems(slot);\n if (this.maxItems > 0 && items.length > this.maxItems) {\n this._applyCollapse(items);\n } else {\n this._removeCollapse(items);\n }\n this._applyItemAttributes(items);\n }\n }\n\n if (changedProperties.has('jsonLd')) {\n if (this.jsonLd) {\n // json-ld toggled on after initial render — inject script immediately.\n const slot = this.shadowRoot?.querySelector<HTMLSlotElement>('slot:not([name])');\n if (slot) {\n this._updateJsonLd(this._getBreadcrumbItems(slot));\n }\n } else {\n // json-ld toggled off — remove existing script.\n this._removeJsonLd();\n }\n }\n }\n\n // ─── Render ───\n\n override render() {\n return html`\n <nav part=\"nav\" aria-label=${this.label}>\n <ol part=\"list\">\n <slot @slotchange=${this._handleSlotChange}></slot>\n </ol>\n </nav>\n <slot\n name=\"separator\"\n class=\"separator-slot\"\n @slotchange=${this._handleSeparatorSlotChange}\n ></slot>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-breadcrumb': HelixBreadcrumb;\n }\n}\n","import { css } from 'lit';\n\nexport const helixBreadcrumbItemStyles = css`\n :host {\n display: inline-flex;\n align-items: center;\n }\n\n /*\n * display: contents removes [part='item'] from the box model entirely.\n * This is intentional — the wrapper exists only for slot selection purposes.\n * Consumers using ::part(item) CANNOT apply box-model properties (padding,\n * margin, background, border) to this part. Use ::part(link) or ::part(text)\n * for visual styling of breadcrumb item content.\n */\n [part='item'] {\n display: contents;\n }\n\n [part='link'] {\n color: var(--hx-breadcrumb-link-color, var(--hx-color-primary-600));\n text-decoration: none;\n cursor: pointer;\n font-family: inherit;\n font-size: inherit;\n max-width: var(--hx-breadcrumb-item-max-width);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n [part='link']:hover {\n color: var(--hx-breadcrumb-link-hover-color, var(--hx-color-primary-700));\n text-decoration: underline;\n }\n\n [part='link']:focus-visible {\n outline: 2px solid var(--hx-focus-ring-color, var(--hx-color-primary-500));\n outline-offset: 2px;\n border-radius: var(--hx-border-radius-sm, 0.125rem);\n }\n\n [part='text'] {\n color: var(--hx-breadcrumb-text-color, var(--hx-color-neutral-700));\n font-family: inherit;\n font-size: inherit;\n max-width: var(--hx-breadcrumb-item-max-width);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .separator {\n margin-inline: var(--hx-breadcrumb-separator-gap, var(--hx-space-1, 0.25rem));\n color: var(--hx-breadcrumb-separator-color, var(--hx-color-neutral-400));\n user-select: none;\n }\n\n .separator::before {\n content: var(--hx-breadcrumb-separator-content, '/');\n }\n\n /* Normalize buttons slotted into breadcrumb items (e.g. the expand-ellipsis button). */\n ::slotted(button) {\n background: none;\n border: none;\n cursor: pointer;\n font: inherit;\n color: inherit;\n padding: 0;\n }\n`;\n","import { LitElement, html, nothing } from 'lit';\nimport { customElement, property } from 'lit/decorators.js';\nimport { tokenStyles } from '@helixui/tokens/lit';\nimport { helixBreadcrumbItemStyles } from './hx-breadcrumb-item.styles.js';\n\n/**\n * A single breadcrumb navigation item.\n *\n * @summary A navigation item within an hx-breadcrumb component. Renders as a link when `href` is\n * provided, or as static text for the current page item. The current page item is determined by\n * the `current` attribute (set explicitly or automatically by the parent `hx-breadcrumb`).\n *\n * @tag hx-breadcrumb-item\n *\n * @slot - The link or page text content. Accepts text, HTML, or icon elements.\n *\n * @csspart item - Wrapper around the link or text content.\n * @csspart link - The anchor element when href is provided (non-current items only).\n * @csspart text - The span element for the current page or items without href.\n * @csspart separator - The separator element rendered after non-last items.\n *\n * @cssprop [--hx-breadcrumb-link-color=var(--hx-color-primary-600)] - Link text color.\n * @cssprop [--hx-breadcrumb-link-hover-color=var(--hx-color-primary-700)] - Link hover text color.\n * @cssprop [--hx-breadcrumb-text-color=var(--hx-color-neutral-700)] - Current page text color.\n * @cssprop [--hx-breadcrumb-separator-content='/'] - Separator character displayed after non-last items.\n * @cssprop [--hx-breadcrumb-separator-color=var(--hx-color-neutral-400)] - Separator color.\n * @cssprop [--hx-breadcrumb-separator-gap=var(--hx-space-1)] - Horizontal margin around separator.\n * @cssprop [--hx-breadcrumb-item-max-width] - Optional max-width for text truncation.\n */\n@customElement('hx-breadcrumb-item')\nexport class HelixBreadcrumbItem extends LitElement {\n static override styles = [tokenStyles, helixBreadcrumbItemStyles];\n\n override connectedCallback(): void {\n super.connectedCallback();\n // Only apply role=\"listitem\" when this item is a direct child of an\n // hx-breadcrumb element. Setting the role unconditionally when used\n // standalone (outside a list context) creates an invalid ARIA hierarchy\n // because listitem requires a list ancestor.\n //\n // IMPORTANT: If programmatically creating an ellipsis element, set aria-hidden\n // BEFORE inserting into the DOM. connectedCallback fires on insertion and sets\n // role=\"listitem\"; setting aria-hidden after would momentarily expose an\n // un-hidden listitem to the accessibility tree.\n if (this.closest('hx-breadcrumb') !== null) {\n this.setAttribute('role', 'listitem');\n } else {\n this.removeAttribute('role');\n }\n }\n\n /**\n * The URL for this breadcrumb link. Omit for the current page item.\n * When `current` is true, this attribute is ignored and the item always\n * renders as static text per WAI-ARIA APG breadcrumb guidance.\n * @attr href\n */\n @property({ type: String, reflect: true })\n href: string | undefined = undefined;\n\n /**\n * Whether this is the last item in the breadcrumb trail. Set by the parent\n * hx-breadcrumb component via the `data-bc-last` boolean attribute. When\n * present the trailing separator is hidden.\n *\n * @attr data-bc-last\n * @internal\n */\n @property({ type: Boolean, attribute: 'data-bc-last', reflect: true })\n dataBcLast = false;\n\n /**\n * Marks this item as the current page. When set, the item always renders as\n * static text (never a navigable link) and `aria-current=\"page\"` is placed on\n * the inner text element per WAI-ARIA APG breadcrumb guidance, yielding the\n * canonical AT announcement (\"current page, Patient Records\").\n *\n * Can be set explicitly by consumers (e.g. Drupal Twig templates) to override\n * the default positional last-item detection in `hx-breadcrumb`. When any item\n * in the breadcrumb has an explicit `current` attribute, the parent will not\n * override it.\n *\n * @attr current\n */\n @property({ type: Boolean, reflect: true })\n current = false;\n\n override render() {\n // Per WAI-ARIA APG, the current page item MUST NOT be a navigable link.\n // aria-current=\"page\" is placed on the inner element (not the listitem host)\n // for canonical AT announcement (\"current page, Patient Records\" vs\n // \"current page, list item\").\n return html`\n <span part=\"item\">\n ${this.current\n ? html`<span part=\"text\" aria-current=\"page\"><slot></slot></span>`\n : this.href\n ? html`<a part=\"link\" href=${this.href}><slot></slot></a>`\n : html`<span part=\"text\"><slot></slot></span>`}\n </span>\n ${!this.dataBcLast\n ? html`<span class=\"separator\" part=\"separator\" aria-hidden=\"true\"></span>`\n : nothing}\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-breadcrumb-item': HelixBreadcrumbItem;\n }\n}\n"],"names":["helixBreadcrumbStyles","css","HelixBreadcrumb","LitElement","slot","el","items","hasExplicitCurrent","item","isLast","assigned","text","_a","ellipsis","btn","firstItem","_b","position","href","name","entry","schema","i","changedProperties","html","tokenStyles","__decorateClass","property","customElement","helixBreadcrumbItemStyles","HelixBreadcrumbItem","nothing"],"mappings":"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"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { css as
|
|
2
|
-
import { property as e, customElement as
|
|
3
|
-
import { classMap as
|
|
4
|
-
import { ifDefined as
|
|
1
|
+
import { css as d, LitElement as x, html as l, nothing as n } from "lit";
|
|
2
|
+
import { property as e, customElement as f } from "lit/decorators.js";
|
|
3
|
+
import { classMap as p } from "lit/directives/class-map.js";
|
|
4
|
+
import { ifDefined as c } from "lit/directives/if-defined.js";
|
|
5
5
|
import { tokenStyles as v } from "@helixui/tokens/lit";
|
|
6
|
-
const m =
|
|
6
|
+
const m = d`
|
|
7
7
|
:host {
|
|
8
8
|
display: inline-block;
|
|
9
9
|
}
|
|
@@ -41,7 +41,7 @@ const m = c`
|
|
|
41
41
|
|
|
42
42
|
.button:focus-visible {
|
|
43
43
|
outline: var(--hx-focus-ring-width, 2px) solid
|
|
44
|
-
var(--hx-button-focus-ring-color, var(--hx-focus-ring-color,
|
|
44
|
+
var(--hx-button-focus-ring-color, var(--hx-focus-ring-color, var(--hx-color-primary-500)));
|
|
45
45
|
outline-offset: var(--hx-focus-ring-offset, 2px);
|
|
46
46
|
}
|
|
47
47
|
|
|
@@ -76,63 +76,65 @@ const m = c`
|
|
|
76
76
|
/* ─── Style Variants ─── */
|
|
77
77
|
|
|
78
78
|
.button--primary {
|
|
79
|
-
--hx-button-bg: var(--hx-color-primary-500
|
|
80
|
-
--hx-button-color: var(--hx-color-neutral-0
|
|
79
|
+
--hx-button-bg: var(--hx-color-primary-500);
|
|
80
|
+
--hx-button-color: var(--hx-color-neutral-0);
|
|
81
81
|
--hx-button-border-color: transparent;
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
.button--secondary {
|
|
85
85
|
--hx-button-bg: transparent;
|
|
86
|
-
--hx-button-color: var(--hx-color-primary-500
|
|
87
|
-
--hx-button-border-color: var(--hx-color-primary-500
|
|
86
|
+
--hx-button-color: var(--hx-color-primary-500);
|
|
87
|
+
--hx-button-border-color: var(--hx-color-primary-500);
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
.button--secondary:hover {
|
|
91
|
-
--hx-button-bg: var(--hx-color-primary-50
|
|
91
|
+
--hx-button-bg: var(--hx-color-primary-50);
|
|
92
92
|
}
|
|
93
93
|
|
|
94
94
|
.button--tertiary {
|
|
95
|
-
--hx-button-bg: var(--hx-color-neutral-100
|
|
96
|
-
--hx-button-color: var(--hx-color-neutral-900
|
|
95
|
+
--hx-button-bg: var(--hx-color-neutral-100);
|
|
96
|
+
--hx-button-color: var(--hx-color-neutral-900);
|
|
97
97
|
--hx-button-border-color: transparent;
|
|
98
98
|
}
|
|
99
99
|
|
|
100
100
|
.button--tertiary:hover {
|
|
101
|
-
--hx-button-bg: var(--hx-color-neutral-200
|
|
101
|
+
--hx-button-bg: var(--hx-color-neutral-200);
|
|
102
102
|
}
|
|
103
103
|
|
|
104
104
|
.button--danger {
|
|
105
|
-
--hx-button-bg: var(--hx-color-error-500
|
|
106
|
-
--hx-button-color: var(--hx-color-neutral-0
|
|
105
|
+
--hx-button-bg: var(--hx-color-error-500);
|
|
106
|
+
--hx-button-color: var(--hx-color-neutral-0);
|
|
107
107
|
--hx-button-border-color: transparent;
|
|
108
108
|
}
|
|
109
109
|
|
|
110
110
|
.button--danger:hover {
|
|
111
|
-
--hx-button-bg: var(--hx-color-error-600
|
|
111
|
+
--hx-button-bg: var(--hx-color-error-600);
|
|
112
112
|
}
|
|
113
113
|
|
|
114
114
|
.button--ghost {
|
|
115
115
|
--hx-button-bg: transparent;
|
|
116
|
-
--hx-button-color: var(--hx-color-primary-500
|
|
116
|
+
--hx-button-color: var(--hx-color-primary-500);
|
|
117
117
|
--hx-button-border-color: transparent;
|
|
118
118
|
}
|
|
119
119
|
|
|
120
120
|
.button--ghost:hover {
|
|
121
|
-
--hx-button-bg: var(--hx-color-neutral-100
|
|
121
|
+
--hx-button-bg: var(--hx-color-neutral-100);
|
|
122
122
|
}
|
|
123
123
|
|
|
124
124
|
.button--outline {
|
|
125
125
|
--hx-button-bg: transparent;
|
|
126
|
-
--hx-button-color: var(--hx-color-neutral-900
|
|
127
|
-
--hx-button-border-color: var(--hx-color-neutral-300
|
|
126
|
+
--hx-button-color: var(--hx-color-neutral-900);
|
|
127
|
+
--hx-button-border-color: var(--hx-color-neutral-300);
|
|
128
128
|
}
|
|
129
129
|
|
|
130
130
|
.button--outline:hover {
|
|
131
|
-
--hx-button-bg: var(--hx-color-neutral-50
|
|
131
|
+
--hx-button-bg: var(--hx-color-neutral-50);
|
|
132
132
|
}
|
|
133
133
|
|
|
134
134
|
/* ─── Disabled ─── */
|
|
135
135
|
|
|
136
|
+
/* Note: opacity is applied on :host([disabled]) above — do NOT add opacity here.
|
|
137
|
+
Stacking opacity on both :host and .button[disabled] would multiply to 0.25. */
|
|
136
138
|
.button[disabled] {
|
|
137
139
|
cursor: not-allowed;
|
|
138
140
|
}
|
|
@@ -182,7 +184,7 @@ var g = Object.defineProperty, y = Object.getOwnPropertyDescriptor, r = (o, i, h
|
|
|
182
184
|
(b = o[u]) && (a = (s ? b(i, h, a) : b(a)) || a);
|
|
183
185
|
return s && a && g(i, h, a), a;
|
|
184
186
|
};
|
|
185
|
-
let t = class extends
|
|
187
|
+
let t = class extends x {
|
|
186
188
|
constructor() {
|
|
187
189
|
super(), this.variant = "primary", this.size = "md", this.disabled = !1, this.loading = !1, this.type = "button", this.href = void 0, this.target = void 0, this.name = void 0, this.value = void 0, this.ariaLabel = null, this._internals = this.attachInternals();
|
|
188
190
|
}
|
|
@@ -262,9 +264,9 @@ let t = class extends d {
|
|
|
262
264
|
return this.href !== void 0 ? l`
|
|
263
265
|
<a
|
|
264
266
|
part="button"
|
|
265
|
-
class=${
|
|
266
|
-
href=${this.disabled || this.loading ? n :
|
|
267
|
-
target=${
|
|
267
|
+
class=${p(o)}
|
|
268
|
+
href=${this.disabled || this.loading ? n : c(this.href)}
|
|
269
|
+
target=${c(this.target)}
|
|
268
270
|
rel=${this.target === "_blank" ? "noopener noreferrer" : n}
|
|
269
271
|
aria-label=${this.ariaLabel ?? n}
|
|
270
272
|
aria-disabled=${this.disabled ? "true" : n}
|
|
@@ -276,7 +278,7 @@ let t = class extends d {
|
|
|
276
278
|
` : l`
|
|
277
279
|
<button
|
|
278
280
|
part="button"
|
|
279
|
-
class=${
|
|
281
|
+
class=${p(o)}
|
|
280
282
|
?disabled=${this.disabled}
|
|
281
283
|
type=${this.type}
|
|
282
284
|
aria-label=${this.ariaLabel ?? n}
|
|
@@ -321,9 +323,9 @@ r([
|
|
|
321
323
|
e({ type: String, reflect: !0, attribute: "aria-label" })
|
|
322
324
|
], t.prototype, "ariaLabel", 2);
|
|
323
325
|
t = r([
|
|
324
|
-
|
|
326
|
+
f("hx-button")
|
|
325
327
|
], t);
|
|
326
328
|
export {
|
|
327
329
|
t as H
|
|
328
330
|
};
|
|
329
|
-
//# sourceMappingURL=hx-button-
|
|
331
|
+
//# sourceMappingURL=hx-button-CtiJsmOg.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hx-button-CtiJsmOg.js","sources":["../../src/components/hx-button/hx-button.styles.ts","../../src/components/hx-button/hx-button.ts"],"sourcesContent":["import { css } from 'lit';\n\nexport const helixButtonStyles = css`\n :host {\n display: inline-block;\n }\n\n :host([disabled]) {\n pointer-events: none;\n opacity: var(--hx-opacity-disabled, 0.5);\n }\n\n /* ─── Base Button ─── */\n\n .button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--hx-space-2, 0.5rem);\n border: var(--hx-border-width-thin, 1px) solid var(--hx-button-border-color, transparent);\n border-radius: var(--hx-button-border-radius, var(--hx-border-radius-md, 0.375rem));\n background-color: var(--hx-button-bg, var(--hx-color-primary-500, #2563eb));\n color: var(--hx-button-color, var(--hx-color-neutral-0, #ffffff));\n font-family: var(--hx-button-font-family, var(--hx-font-family-sans, sans-serif));\n font-weight: var(--hx-button-font-weight, var(--hx-font-weight-semibold, 600));\n line-height: var(--hx-line-height-tight, 1.25);\n cursor: pointer;\n transition:\n background-color var(--hx-transition-fast, 150ms ease),\n color var(--hx-transition-fast, 150ms ease),\n border-color var(--hx-transition-fast, 150ms ease),\n box-shadow var(--hx-transition-fast, 150ms ease);\n text-decoration: none;\n white-space: nowrap;\n user-select: none;\n -webkit-user-select: none;\n }\n\n .button:focus-visible {\n outline: var(--hx-focus-ring-width, 2px) solid\n var(--hx-button-focus-ring-color, var(--hx-focus-ring-color, var(--hx-color-primary-500)));\n outline-offset: var(--hx-focus-ring-offset, 2px);\n }\n\n .button:hover {\n filter: brightness(var(--hx-filter-brightness-hover, 0.9));\n }\n\n .button:active {\n filter: brightness(var(--hx-filter-brightness-active, 0.8));\n }\n\n /* ─── Size Variants ─── */\n\n .button--sm {\n padding: var(--hx-space-1, 0.25rem) var(--hx-space-3, 0.75rem);\n font-size: var(--hx-font-size-sm, 0.875rem);\n min-height: var(--hx-size-8, 2rem);\n }\n\n .button--md {\n padding: var(--hx-space-2, 0.5rem) var(--hx-space-4, 1rem);\n font-size: var(--hx-font-size-md, 1rem);\n min-height: var(--hx-size-10, 2.5rem);\n }\n\n .button--lg {\n padding: var(--hx-space-3, 0.75rem) var(--hx-space-6, 1.5rem);\n font-size: var(--hx-font-size-lg, 1.125rem);\n min-height: var(--hx-size-12, 3rem);\n }\n\n /* ─── Style Variants ─── */\n\n .button--primary {\n --hx-button-bg: var(--hx-color-primary-500);\n --hx-button-color: var(--hx-color-neutral-0);\n --hx-button-border-color: transparent;\n }\n\n .button--secondary {\n --hx-button-bg: transparent;\n --hx-button-color: var(--hx-color-primary-500);\n --hx-button-border-color: var(--hx-color-primary-500);\n }\n\n .button--secondary:hover {\n --hx-button-bg: var(--hx-color-primary-50);\n }\n\n .button--tertiary {\n --hx-button-bg: var(--hx-color-neutral-100);\n --hx-button-color: var(--hx-color-neutral-900);\n --hx-button-border-color: transparent;\n }\n\n .button--tertiary:hover {\n --hx-button-bg: var(--hx-color-neutral-200);\n }\n\n .button--danger {\n --hx-button-bg: var(--hx-color-error-500);\n --hx-button-color: var(--hx-color-neutral-0);\n --hx-button-border-color: transparent;\n }\n\n .button--danger:hover {\n --hx-button-bg: var(--hx-color-error-600);\n }\n\n .button--ghost {\n --hx-button-bg: transparent;\n --hx-button-color: var(--hx-color-primary-500);\n --hx-button-border-color: transparent;\n }\n\n .button--ghost:hover {\n --hx-button-bg: var(--hx-color-neutral-100);\n }\n\n .button--outline {\n --hx-button-bg: transparent;\n --hx-button-color: var(--hx-color-neutral-900);\n --hx-button-border-color: var(--hx-color-neutral-300);\n }\n\n .button--outline:hover {\n --hx-button-bg: var(--hx-color-neutral-50);\n }\n\n /* ─── Disabled ─── */\n\n /* Note: opacity is applied on :host([disabled]) above — do NOT add opacity here.\n Stacking opacity on both :host and .button[disabled] would multiply to 0.25. */\n .button[disabled] {\n cursor: not-allowed;\n }\n\n /* ─── Loading State ─── */\n\n .button--loading {\n position: relative;\n cursor: wait;\n }\n\n .button__spinner {\n width: 1em;\n height: 1em;\n flex-shrink: 0;\n animation: hx-spin var(--hx-duration-spinner, 750ms) linear infinite;\n }\n\n @keyframes hx-spin {\n to {\n transform: rotate(360deg);\n }\n }\n\n @media (prefers-reduced-motion: reduce) {\n .button__spinner {\n animation: none;\n opacity: var(--hx-opacity-muted, 0.6);\n }\n }\n\n /* ─── Prefix / Suffix / Label ─── */\n\n .button__prefix,\n .button__suffix {\n display: inline-flex;\n align-items: center;\n flex-shrink: 0;\n }\n\n .button__label {\n flex: 1 1 auto;\n }\n`;\n","import { LitElement, html, nothing, type TemplateResult } from 'lit';\nimport { customElement, property } from 'lit/decorators.js';\nimport { classMap } from 'lit/directives/class-map.js';\nimport { ifDefined } from 'lit/directives/if-defined.js';\nimport { tokenStyles } from '@helixui/tokens/lit';\nimport { helixButtonStyles } from './hx-button.styles.js';\n\n/**\n * A production-grade button component for user interaction. Supports multiple\n * visual variants, sizes, loading state, prefix/suffix slots, anchor rendering,\n * and full ElementInternals form association.\n *\n * @summary Primary interactive element for triggering actions and form submission.\n *\n * @tag hx-button\n *\n * @slot - Default slot for button label text or content.\n * @slot prefix - Icon or content rendered before the label.\n * @slot suffix - Icon or content rendered after the label.\n *\n * @fires {CustomEvent<{originalEvent: MouseEvent}>} hx-click - Dispatched when\n * the button is clicked and is neither disabled nor loading.\n *\n * @csspart button - The native button or anchor element.\n * @csspart label - The label text wrapper span.\n * @csspart prefix - The prefix slot container span.\n * @csspart suffix - The suffix slot container span.\n * @csspart spinner - The loading spinner SVG element.\n *\n * @cssprop [--hx-button-bg=var(--hx-color-primary-500)] - Button background color.\n * @cssprop [--hx-button-color=var(--hx-color-neutral-0)] - Button text color.\n * @cssprop [--hx-button-border-color=transparent] - Button border color.\n * @cssprop [--hx-button-border-radius=var(--hx-border-radius-md)] - Button border radius.\n * @cssprop [--hx-button-font-family=var(--hx-font-family-sans)] - Button font family.\n * @cssprop [--hx-button-font-weight=var(--hx-font-weight-semibold)] - Button font weight.\n * @cssprop [--hx-button-focus-ring-color=var(--hx-focus-ring-color)] - Focus ring color.\n */\n@customElement('hx-button')\nexport class HelixButton extends LitElement {\n static override styles = [tokenStyles, helixButtonStyles];\n\n // ─── Form Association ───\n\n static formAssociated = true;\n\n private _internals: ElementInternals;\n\n constructor() {\n super();\n this._internals = this.attachInternals();\n }\n\n // ─── Public Properties ───\n\n /**\n * Visual style variant of the button.\n * @attr variant\n */\n @property({ type: String, reflect: true })\n variant: 'primary' | 'secondary' | 'tertiary' | 'danger' | 'ghost' | 'outline' = 'primary';\n\n /**\n * Size of the button.\n * @attr hx-size\n */\n @property({ type: String, reflect: true, attribute: 'hx-size' })\n size: 'sm' | 'md' | 'lg' = 'md';\n\n /**\n * Whether the button is disabled. Prevents all interaction and form actions.\n * @attr disabled\n */\n @property({ type: Boolean, reflect: true })\n disabled = false;\n\n /**\n * Whether the button is in a loading state. Shows spinner, prevents interaction,\n * and sets aria-busy. Does not set the disabled attribute.\n * @attr loading\n */\n @property({ type: Boolean, reflect: true })\n loading = false;\n\n /**\n * The type attribute for the underlying button element. Ignored when href is set.\n * @attr type\n */\n @property({ type: String })\n type: 'button' | 'submit' | 'reset' = 'button';\n\n /**\n * When set, renders an anchor element instead of a button.\n * @attr href\n */\n @property({ type: String })\n href: string | undefined = undefined;\n\n /**\n * Anchor target attribute. Only used when href is set.\n * @attr target\n */\n @property({ type: String })\n target: string | undefined = undefined;\n\n /**\n * Form field name submitted via ElementInternals.setFormValue on submit.\n * @attr name\n */\n @property({ type: String })\n name: string | undefined = undefined;\n\n /**\n * Form field value submitted via ElementInternals.setFormValue on submit.\n * @attr value\n */\n @property({ type: String })\n value: string | undefined = undefined;\n\n /**\n * Accessible label forwarded to the inner button/anchor. Required for icon-only usage.\n * @attr aria-label\n */\n @property({ type: String, reflect: true, attribute: 'aria-label' })\n override ariaLabel: string | null = null;\n\n // ─── Form API ───\n\n /** Returns the associated form element, if any. */\n get form(): HTMLFormElement | null {\n return this._internals.form;\n }\n\n // ─── Event Handling ───\n\n /** @private */\n private _handleClick(e: MouseEvent): void {\n if (this.disabled || this.loading) {\n e.preventDefault();\n e.stopPropagation();\n return;\n }\n\n /**\n * Dispatched when the button is clicked.\n * @event hx-click\n */\n this.dispatchEvent(\n new CustomEvent('hx-click', {\n bubbles: true,\n composed: true,\n detail: { originalEvent: e },\n }),\n );\n\n // Handle form submission/reset if form-associated and not in anchor mode\n if (this.href === undefined && this.type === 'submit' && this._internals.form) {\n if (this.name !== undefined && this.value !== undefined) {\n this._internals.setFormValue(this.value);\n }\n this._internals.form.requestSubmit();\n } else if (this.href === undefined && this.type === 'reset' && this._internals.form) {\n this._internals.form.reset();\n }\n }\n\n // ─── Render Helpers ───\n\n /** @private */\n private _renderSpinner(): TemplateResult {\n return html`\n <svg\n class=\"button__spinner\"\n part=\"spinner\"\n aria-hidden=\"true\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n >\n <circle\n class=\"button__spinner-track\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n stroke-width=\"3\"\n opacity=\"0.3\"\n />\n <path\n class=\"button__spinner-arc\"\n d=\"M12 2a10 10 0 0 1 10 10\"\n stroke=\"currentColor\"\n stroke-width=\"3\"\n stroke-linecap=\"round\"\n />\n </svg>\n `;\n }\n\n /** @private */\n private _renderInner(): TemplateResult {\n return html`\n ${this.loading ? this._renderSpinner() : nothing}\n <span part=\"prefix\" class=\"button__prefix\">\n <slot name=\"prefix\"></slot>\n </span>\n <span part=\"label\" class=\"button__label\">\n <slot></slot>\n </span>\n <span part=\"suffix\" class=\"button__suffix\">\n <slot name=\"suffix\"></slot>\n </span>\n `;\n }\n\n // ─── Render ───\n\n override render() {\n const classes = {\n button: true,\n [`button--${this.variant}`]: true,\n [`button--${this.size}`]: true,\n 'button--loading': this.loading,\n };\n\n if (this.href !== undefined) {\n return html`\n <a\n part=\"button\"\n class=${classMap(classes)}\n href=${this.disabled || this.loading ? nothing : ifDefined(this.href)}\n target=${ifDefined(this.target)}\n rel=${this.target === '_blank' ? 'noopener noreferrer' : nothing}\n aria-label=${this.ariaLabel ?? nothing}\n aria-disabled=${this.disabled ? 'true' : nothing}\n aria-busy=${this.loading ? 'true' : nothing}\n @click=${this._handleClick}\n >\n ${this._renderInner()}\n </a>\n `;\n }\n\n return html`\n <button\n part=\"button\"\n class=${classMap(classes)}\n ?disabled=${this.disabled}\n type=${this.type}\n aria-label=${this.ariaLabel ?? nothing}\n aria-busy=${this.loading ? 'true' : nothing}\n @click=${this._handleClick}\n >\n ${this._renderInner()}\n </button>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-button': HelixButton;\n }\n}\n"],"names":["helixButtonStyles","css","HelixButton","LitElement","e","html","nothing","classes","classMap","ifDefined","tokenStyles","__decorateClass","property","customElement"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { css as h, LitElement as u, html as c } from "lit";
|
|
2
|
-
import { property as
|
|
2
|
+
import { property as d, customElement as p } from "lit/decorators.js";
|
|
3
3
|
import { classMap as b } from "lit/directives/class-map.js";
|
|
4
4
|
import { tokenStyles as m } from "@helixui/tokens/lit";
|
|
5
5
|
const x = h`
|
|
@@ -94,19 +94,25 @@ const x = h`
|
|
|
94
94
|
position: relative;
|
|
95
95
|
}
|
|
96
96
|
`;
|
|
97
|
-
var
|
|
98
|
-
for (var
|
|
99
|
-
(
|
|
100
|
-
return
|
|
97
|
+
var g = Object.defineProperty, f = Object.getOwnPropertyDescriptor, l = (r, i, s, e) => {
|
|
98
|
+
for (var t = e > 1 ? void 0 : e ? f(i, s) : i, a = r.length - 1, n; a >= 0; a--)
|
|
99
|
+
(n = r[a]) && (t = (e ? n(i, s, t) : n(t)) || t);
|
|
100
|
+
return e && t && g(i, s, t), t;
|
|
101
101
|
};
|
|
102
102
|
let o = class extends u {
|
|
103
103
|
// ─── Constructor ───
|
|
104
104
|
constructor() {
|
|
105
|
-
super(), this.
|
|
105
|
+
super(), this._orientation = "horizontal", this.size = "md", this.label = "", this.internals = this.attachInternals(), this.internals.role = "group";
|
|
106
|
+
}
|
|
107
|
+
get orientation() {
|
|
108
|
+
return this._orientation;
|
|
109
|
+
}
|
|
110
|
+
set orientation(r) {
|
|
111
|
+
r !== "horizontal" && r !== "vertical" && (console.warn(`[hx-button-group] Invalid orientation "${r}", defaulting to "horizontal".`), r = "horizontal"), this._orientation = r;
|
|
106
112
|
}
|
|
107
113
|
// ─── Lifecycle ───
|
|
108
|
-
updated(
|
|
109
|
-
super.updated(
|
|
114
|
+
updated(r) {
|
|
115
|
+
super.updated(r), r.has("size") && this.style.setProperty("--hx-button-group-size", this.size), r.has("label") && (this.internals.ariaLabel = this.label || null);
|
|
110
116
|
}
|
|
111
117
|
connectedCallback() {
|
|
112
118
|
super.connectedCallback(), this.style.setProperty("--hx-button-group-size", this.size), this.label && (this.internals.ariaLabel = this.label);
|
|
@@ -129,13 +135,13 @@ let o = class extends u {
|
|
|
129
135
|
};
|
|
130
136
|
o.styles = [m, x];
|
|
131
137
|
l([
|
|
132
|
-
|
|
133
|
-
], o.prototype, "orientation",
|
|
138
|
+
d({ type: String, reflect: !0 })
|
|
139
|
+
], o.prototype, "orientation", 1);
|
|
134
140
|
l([
|
|
135
|
-
|
|
141
|
+
d({ type: String, reflect: !0, attribute: "hx-size" })
|
|
136
142
|
], o.prototype, "size", 2);
|
|
137
143
|
l([
|
|
138
|
-
|
|
144
|
+
d({ type: String })
|
|
139
145
|
], o.prototype, "label", 2);
|
|
140
146
|
o = l([
|
|
141
147
|
p("hx-button-group")
|
|
@@ -143,4 +149,4 @@ o = l([
|
|
|
143
149
|
export {
|
|
144
150
|
o as H
|
|
145
151
|
};
|
|
146
|
-
//# sourceMappingURL=hx-button-group-
|
|
152
|
+
//# sourceMappingURL=hx-button-group-BMV5qFs4.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hx-button-group-
|
|
1
|
+
{"version":3,"file":"hx-button-group-BMV5qFs4.js","sources":["../../src/components/hx-button-group/hx-button-group.styles.ts","../../src/components/hx-button-group/hx-button-group.ts"],"sourcesContent":["import { css } from 'lit';\n\nexport const helixButtonGroupStyles = css`\n :host {\n display: inline-flex;\n contain: layout style;\n }\n\n .group {\n display: inline-flex;\n align-items: stretch;\n }\n\n /* ─── Orientation Variants ─── */\n\n .group--horizontal {\n flex-direction: row;\n }\n\n .group--vertical {\n flex-direction: column;\n }\n\n /* ─── No Double Borders: Horizontal ─── */\n\n .group--horizontal ::slotted(*:not(:first-child)) {\n margin-left: calc(-1 * var(--hx-border-width-thin, 1px));\n }\n\n /* ─── No Double Borders: Vertical ─── */\n\n .group--vertical ::slotted(*:not(:first-child)) {\n margin-top: calc(-1 * var(--hx-border-width-thin, 1px));\n }\n\n /* ─── Border Radius: Horizontal — Single child keeps all corners ─── */\n\n .group--horizontal ::slotted(:only-child) {\n --hx-button-border-radius: var(--hx-border-radius-md, 0.375rem);\n }\n\n /* ─── Border Radius: Horizontal — First child keeps left corners ─── */\n\n .group--horizontal ::slotted(:first-child:not(:only-child)) {\n --hx-button-border-radius: var(--hx-border-radius-md, 0.375rem) 0 0\n var(--hx-border-radius-md, 0.375rem);\n }\n\n /* ─── Border Radius: Horizontal — Last child keeps right corners ─── */\n\n .group--horizontal ::slotted(:last-child:not(:only-child)) {\n --hx-button-border-radius: 0 var(--hx-border-radius-md, 0.375rem)\n var(--hx-border-radius-md, 0.375rem) 0;\n }\n\n /* ─── Border Radius: Horizontal — Middle children have no radius ─── */\n\n .group--horizontal ::slotted(:not(:first-child):not(:last-child)) {\n --hx-button-border-radius: 0;\n }\n\n /* ─── Border Radius: Vertical — Single child keeps all corners ─── */\n\n .group--vertical ::slotted(:only-child) {\n --hx-button-border-radius: var(--hx-border-radius-md, 0.375rem);\n }\n\n /* ─── Border Radius: Vertical — First child keeps top corners ─── */\n\n .group--vertical ::slotted(:first-child:not(:only-child)) {\n --hx-button-border-radius: var(--hx-border-radius-md, 0.375rem)\n var(--hx-border-radius-md, 0.375rem) 0 0;\n }\n\n /* ─── Border Radius: Vertical — Last child keeps bottom corners ─── */\n\n .group--vertical ::slotted(:last-child:not(:only-child)) {\n --hx-button-border-radius: 0 0 var(--hx-border-radius-md, 0.375rem)\n var(--hx-border-radius-md, 0.375rem);\n }\n\n /* ─── Border Radius: Vertical — Middle children have no radius ─── */\n\n .group--vertical ::slotted(:not(:first-child):not(:last-child)) {\n --hx-button-border-radius: 0;\n }\n\n /* ─── Z-index: Raise focused child above siblings to show full focus ring ─── */\n\n .group ::slotted(:focus-within) {\n z-index: 1;\n position: relative;\n }\n`;\n","import { LitElement, html } from 'lit';\nimport { customElement, property } from 'lit/decorators.js';\nimport { classMap } from 'lit/directives/class-map.js';\nimport { tokenStyles } from '@helixui/tokens/lit';\nimport { helixButtonGroupStyles } from './hx-button-group.styles.js';\n\n/**\n * A container component that groups related hx-button elements into a cohesive\n * horizontal or vertical action set. Eliminates double borders between adjacent\n * buttons and squares off inner border-radius for a unified visual appearance.\n *\n * **Accessibility:** Always provide an accessible label via `aria-label` or\n * `aria-labelledby` so screen readers can announce the group purpose.\n *\n * @summary Groups hx-button elements into a horizontal or vertical action set with shared borders.\n *\n * @tag hx-button-group\n *\n * @slot - Default slot accepting hx-button children.\n *\n * @csspart group - The container div element wrapping all slotted buttons.\n *\n * @cssprop [--hx-button-group-size=md] - Size token forwarded to child buttons. Accepts 'sm', 'md', or 'lg'.\n */\n@customElement('hx-button-group')\nexport class HelixButtonGroup extends LitElement {\n static override styles = [tokenStyles, helixButtonGroupStyles];\n\n private internals!: ElementInternals;\n\n /**\n * Layout orientation of the button group.\n * @attr orientation\n */\n @property({ type: String, reflect: true })\n get orientation(): 'horizontal' | 'vertical' {\n return this._orientation;\n }\n set orientation(value: string) {\n if (value !== 'horizontal' && value !== 'vertical') {\n console.warn(`[hx-button-group] Invalid orientation \"${value}\", defaulting to \"horizontal\".`);\n value = 'horizontal';\n }\n this._orientation = value as 'horizontal' | 'vertical';\n }\n private _orientation: 'horizontal' | 'vertical' = 'horizontal';\n\n /**\n * Size applied to the button group and cascaded to child buttons via\n * the --hx-button-group-size CSS custom property.\n * @attr hx-size\n */\n @property({ type: String, reflect: true, attribute: 'hx-size' })\n size: 'sm' | 'md' | 'lg' = 'md';\n\n /**\n * Accessible label for the button group. Sets aria-label via ElementInternals.\n * **Strongly recommended** for WCAG 2.1 AA compliance — without it, screen\n * readers announce an unnamed \"group\". For Drupal/Twig compatibility, prefer\n * applying `aria-label` directly as an HTML attribute instead.\n * @attr label\n */\n @property({ type: String })\n label: string = '';\n\n // ─── Constructor ───\n\n constructor() {\n super();\n this.internals = this.attachInternals();\n this.internals.role = 'group';\n }\n\n // ─── Lifecycle ───\n\n override updated(changedProperties: Map<PropertyKey, unknown>): void {\n super.updated(changedProperties);\n\n if (changedProperties.has('size')) {\n this.style.setProperty('--hx-button-group-size', this.size);\n }\n\n if (changedProperties.has('label')) {\n this.internals.ariaLabel = this.label || null;\n }\n }\n\n override connectedCallback(): void {\n super.connectedCallback();\n this.style.setProperty('--hx-button-group-size', this.size);\n if (this.label) {\n this.internals.ariaLabel = this.label;\n }\n }\n\n // ─── Render ───\n\n override render() {\n return html`\n <div\n part=\"group\"\n class=${classMap({\n group: true,\n 'group--horizontal': this.orientation === 'horizontal',\n 'group--vertical': this.orientation === 'vertical',\n })}\n >\n <slot></slot>\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-button-group': HelixButtonGroup;\n }\n}\n"],"names":["helixButtonGroupStyles","css","HelixButtonGroup","LitElement","value","changedProperties","html","classMap","tokenStyles","__decorateClass","property","customElement"],"mappings":";;;;AAEO,MAAMA,IAAyBC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;;;;ACuB/B,IAAMC,IAAN,cAA+BC,EAAW;AAAA;AAAA,EA0C/C,cAAc;AACZ,UAAA,GAvBF,KAAQ,eAA0C,cAQlD,KAAA,OAA2B,MAU3B,KAAA,QAAgB,IAMd,KAAK,YAAY,KAAK,gBAAA,GACtB,KAAK,UAAU,OAAO;AAAA,EACxB;AAAA,EApCA,IAAI,cAAyC;AAC3C,WAAO,KAAK;AAAA,EACd;AAAA,EACA,IAAI,YAAYC,GAAe;AAC7B,IAAIA,MAAU,gBAAgBA,MAAU,eACtC,QAAQ,KAAK,0CAA0CA,CAAK,gCAAgC,GAC5FA,IAAQ,eAEV,KAAK,eAAeA;AAAA,EACtB;AAAA;AAAA,EA+BS,QAAQC,GAAoD;AACnE,UAAM,QAAQA,CAAiB,GAE3BA,EAAkB,IAAI,MAAM,KAC9B,KAAK,MAAM,YAAY,0BAA0B,KAAK,IAAI,GAGxDA,EAAkB,IAAI,OAAO,MAC/B,KAAK,UAAU,YAAY,KAAK,SAAS;AAAA,EAE7C;AAAA,EAES,oBAA0B;AACjC,UAAM,kBAAA,GACN,KAAK,MAAM,YAAY,0BAA0B,KAAK,IAAI,GACtD,KAAK,UACP,KAAK,UAAU,YAAY,KAAK;AAAA,EAEpC;AAAA;AAAA,EAIS,SAAS;AAChB,WAAOC;AAAA;AAAA;AAAA,gBAGKC,EAAS;AAAA,MACf,OAAO;AAAA,MACP,qBAAqB,KAAK,gBAAgB;AAAA,MAC1C,mBAAmB,KAAK,gBAAgB;AAAA,IAAA,CACzC,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,EAKR;AACF;AAtFaL,EACK,SAAS,CAACM,GAAaR,CAAsB;AASzDS,EAAA;AAAA,EADHC,EAAS,EAAE,MAAM,QAAQ,SAAS,IAAM;AAAA,GAT9BR,EAUP,WAAA,eAAA,CAAA;AAkBJO,EAAA;AAAA,EADCC,EAAS,EAAE,MAAM,QAAQ,SAAS,IAAM,WAAW,WAAW;AAAA,GA3BpDR,EA4BX,WAAA,QAAA,CAAA;AAUAO,EAAA;AAAA,EADCC,EAAS,EAAE,MAAM,OAAA,CAAQ;AAAA,GArCfR,EAsCX,WAAA,SAAA,CAAA;AAtCWA,IAANO,EAAA;AAAA,EADNE,EAAc,iBAAiB;AAAA,GACnBT,CAAA;"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { css as
|
|
1
|
+
import { css as _, LitElement as u, nothing as d, html as h } from "lit";
|
|
2
2
|
import { property as l, state as p, customElement as g } from "lit/decorators.js";
|
|
3
3
|
import { classMap as x } from "lit/directives/class-map.js";
|
|
4
4
|
import { tokenStyles as f } from "@helixui/tokens/lit";
|
|
5
|
-
const
|
|
5
|
+
const b = _`
|
|
6
6
|
:host {
|
|
7
7
|
display: block;
|
|
8
8
|
}
|
|
@@ -80,14 +80,14 @@ const m = u`
|
|
|
80
80
|
line-height: var(--hx-line-height-normal);
|
|
81
81
|
}
|
|
82
82
|
`;
|
|
83
|
-
var
|
|
84
|
-
for (var
|
|
85
|
-
(c = e[n]) && (
|
|
86
|
-
return o &&
|
|
83
|
+
var m = Object.defineProperty, k = Object.getOwnPropertyDescriptor, i = (e, t, s, o) => {
|
|
84
|
+
for (var a = o > 1 ? void 0 : o ? k(t, s) : t, n = e.length - 1, c; n >= 0; n--)
|
|
85
|
+
(c = e[n]) && (a = (o ? c(t, s, a) : c(a)) || a);
|
|
86
|
+
return o && a && m(t, s, a), a;
|
|
87
87
|
};
|
|
88
|
-
let y = 0, r = class extends
|
|
88
|
+
let y = 0, r = class extends u {
|
|
89
89
|
constructor() {
|
|
90
|
-
super(), this.name = "", this.label = "", this.required = !1, this.disabled = !1, this.error = "", this.
|
|
90
|
+
super(), this.name = "", this.label = "", this.required = !1, this.disabled = !1, this.error = "", this._orientation = "vertical", this._hasErrorSlot = !1, this._hasHelpSlot = !1, this._groupId = `hx-checkbox-group-${++y}`, this._helpTextId = `${this._groupId}-help`, this._errorId = `${this._groupId}-error`, this._handleCheckboxChange = (e) => {
|
|
91
91
|
if (e.target === this) return;
|
|
92
92
|
e.stopImmediatePropagation();
|
|
93
93
|
const t = this._getCheckedValues();
|
|
@@ -100,6 +100,12 @@ let y = 0, r = class extends _ {
|
|
|
100
100
|
);
|
|
101
101
|
}, this._internals = this.attachInternals();
|
|
102
102
|
}
|
|
103
|
+
get orientation() {
|
|
104
|
+
return this._orientation;
|
|
105
|
+
}
|
|
106
|
+
set orientation(e) {
|
|
107
|
+
e !== "vertical" && e !== "horizontal" && (console.warn(`[hx-checkbox-group] Invalid orientation "${e}", defaulting to "vertical".`), e = "vertical"), this._orientation = e;
|
|
108
|
+
}
|
|
103
109
|
// ─── Slot Handlers ───
|
|
104
110
|
_handleErrorSlotChange(e) {
|
|
105
111
|
const t = e.target;
|
|
@@ -236,36 +242,36 @@ let y = 0, r = class extends _ {
|
|
|
236
242
|
`;
|
|
237
243
|
}
|
|
238
244
|
};
|
|
239
|
-
r.styles = [f,
|
|
245
|
+
r.styles = [f, b];
|
|
240
246
|
r.formAssociated = !0;
|
|
241
|
-
|
|
247
|
+
i([
|
|
242
248
|
l({ type: String })
|
|
243
249
|
], r.prototype, "name", 2);
|
|
244
|
-
|
|
250
|
+
i([
|
|
245
251
|
l({ type: String })
|
|
246
252
|
], r.prototype, "label", 2);
|
|
247
|
-
|
|
253
|
+
i([
|
|
248
254
|
l({ type: Boolean, reflect: !0 })
|
|
249
255
|
], r.prototype, "required", 2);
|
|
250
|
-
|
|
256
|
+
i([
|
|
251
257
|
l({ type: Boolean, reflect: !0 })
|
|
252
258
|
], r.prototype, "disabled", 2);
|
|
253
|
-
|
|
259
|
+
i([
|
|
254
260
|
l({ type: String })
|
|
255
261
|
], r.prototype, "error", 2);
|
|
256
|
-
|
|
262
|
+
i([
|
|
257
263
|
l({ type: String, reflect: !0 })
|
|
258
|
-
], r.prototype, "orientation",
|
|
259
|
-
|
|
264
|
+
], r.prototype, "orientation", 1);
|
|
265
|
+
i([
|
|
260
266
|
p()
|
|
261
267
|
], r.prototype, "_hasErrorSlot", 2);
|
|
262
|
-
|
|
268
|
+
i([
|
|
263
269
|
p()
|
|
264
270
|
], r.prototype, "_hasHelpSlot", 2);
|
|
265
|
-
r =
|
|
271
|
+
r = i([
|
|
266
272
|
g("hx-checkbox-group")
|
|
267
273
|
], r);
|
|
268
274
|
export {
|
|
269
275
|
r as H
|
|
270
276
|
};
|
|
271
|
-
//# sourceMappingURL=hx-checkbox-group-
|
|
277
|
+
//# sourceMappingURL=hx-checkbox-group-DTS9iT4b.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hx-checkbox-group-DTS9iT4b.js","sources":["../../src/components/hx-checkbox-group/hx-checkbox-group.styles.ts","../../src/components/hx-checkbox-group/hx-checkbox-group.ts"],"sourcesContent":["import { css } from 'lit';\n\nexport const helixCheckboxGroupStyles = css`\n :host {\n display: block;\n }\n\n :host([disabled]) {\n opacity: var(--hx-opacity-disabled);\n cursor: not-allowed;\n }\n\n * {\n box-sizing: border-box;\n }\n\n /* ─── Fieldset ─── */\n\n .fieldset {\n border: none;\n margin: 0;\n padding: 0;\n display: flex;\n flex-direction: column;\n gap: var(--hx-space-2);\n font-family: var(--hx-font-family-sans);\n }\n\n /* ─── Legend ─── */\n\n .fieldset__legend {\n display: flex;\n align-items: baseline;\n gap: var(--hx-space-1);\n font-size: var(--hx-font-size-sm);\n font-weight: var(--hx-font-weight-medium);\n color: var(--hx-checkbox-group-label-color, var(--hx-color-neutral-700));\n line-height: var(--hx-line-height-normal);\n padding: 0;\n margin-bottom: var(--hx-space-1);\n }\n\n .fieldset__required-marker {\n color: var(--hx-checkbox-group-error-color, var(--hx-color-error-500, #dc3545));\n font-weight: var(--hx-font-weight-bold);\n }\n\n /* ─── Items Container ─── */\n\n .fieldset__items {\n display: flex;\n flex-direction: column;\n gap: var(--hx-checkbox-group-gap, var(--hx-space-3));\n }\n\n :host([orientation='horizontal']) .fieldset__items {\n flex-direction: row;\n flex-wrap: wrap;\n }\n\n /* ─── Error State ─── */\n\n .fieldset--error .fieldset__legend {\n color: var(--hx-checkbox-group-error-color, var(--hx-color-error-500, #dc3545));\n }\n\n /* ─── Help Text & Error Messages ─── */\n\n .fieldset__help-text {\n font-size: var(--hx-font-size-xs);\n color: var(--hx-checkbox-group-help-text-color, var(--hx-color-neutral-500));\n line-height: var(--hx-line-height-normal);\n }\n\n .fieldset__error {\n font-size: var(--hx-font-size-xs);\n color: var(--hx-checkbox-group-error-color, var(--hx-color-error-500, #dc3545));\n line-height: var(--hx-line-height-normal);\n }\n`;\n","import { LitElement, html, nothing } from 'lit';\nimport { customElement, property, state } from 'lit/decorators.js';\nimport { classMap } from 'lit/directives/class-map.js';\nimport { tokenStyles } from '@helixui/tokens/lit';\nimport { helixCheckboxGroupStyles } from './hx-checkbox-group.styles.js';\nimport type { HelixCheckbox } from '../hx-checkbox/hx-checkbox.js';\n\n/** Monotonic counter for stable, SSR-safe IDs. */\nlet _uid = 0;\n\n/**\n * A form-associated checkbox group that manages a set of `<hx-checkbox>` children.\n *\n * @summary Form-associated checkbox group with label, validation, help text, and multi-value form submission.\n *\n * @tag hx-checkbox-group\n *\n * @slot - `<hx-checkbox>` elements.\n * @slot label - Rich HTML group label (overrides the label property when used).\n * @slot error - Custom error content (overrides the error property).\n * @slot help - Group-level help text.\n *\n * @fires {CustomEvent<{values: string[]}>} hx-change - Dispatched when any child checkbox changes.\n *\n * @csspart group - The fieldset wrapper.\n * @csspart label - The legend/label.\n * @csspart help-text - The help text container.\n * @csspart error-message - The error message container.\n *\n * @cssprop [--hx-checkbox-group-gap=var(--hx-space-3, 0.75rem)] - Gap between checkbox items.\n * @cssprop [--hx-checkbox-group-label-color=var(--hx-color-neutral-700, #343a40)] - Label text color.\n * @cssprop [--hx-checkbox-group-error-color=var(--hx-color-error-500, #dc3545)] - Error message color.\n * @cssprop [--hx-checkbox-group-help-text-color=var(--hx-color-neutral-500)] - Help text color.\n *\n * @drupal\n * Form-associated; render via Twig:\n * ```twig\n * <hx-checkbox-group name=\"{{ field_name }}\" label=\"{{ label }}\"{{ required ? ' required' : '' }}>\n * {% for option in options %}\n * <hx-checkbox value=\"{{ option.value }}\" label=\"{{ option.label }}\"></hx-checkbox>\n * {% endfor %}\n * </hx-checkbox-group>\n * ```\n * The `name` attribute propagates automatically to child checkboxes — no Drupal behavior required.\n */\n@customElement('hx-checkbox-group')\nexport class HelixCheckboxGroup extends LitElement {\n static override styles = [tokenStyles, helixCheckboxGroupStyles];\n\n // ─── Form Association ───\n\n static formAssociated = true;\n\n private _internals: ElementInternals;\n\n constructor() {\n super();\n this._internals = this.attachInternals();\n }\n\n // ─── Properties ───\n\n /**\n * The name used for form submission. Passed to child `hx-checkbox` elements.\n * @attr name\n */\n @property({ type: String })\n name = '';\n\n /**\n * The fieldset legend/label text.\n * @attr label\n */\n @property({ type: String })\n label = '';\n\n /**\n * Whether at least one checkbox must be checked for form submission.\n * @attr required\n */\n @property({ type: Boolean, reflect: true })\n required = false;\n\n /**\n * Whether the entire group is disabled.\n * @attr disabled\n */\n @property({ type: Boolean, reflect: true })\n disabled = false;\n\n /**\n * Error message to display. When set, the group enters an error state.\n * @attr error\n */\n @property({ type: String })\n error = '';\n\n /**\n * Layout orientation of the checkbox items.\n * @attr orientation\n */\n @property({ type: String, reflect: true })\n get orientation(): 'vertical' | 'horizontal' {\n return this._orientation;\n }\n set orientation(value: string) {\n if (value !== 'vertical' && value !== 'horizontal') {\n console.warn(`[hx-checkbox-group] Invalid orientation \"${value}\", defaulting to \"vertical\".`);\n value = 'vertical';\n }\n this._orientation = value as 'vertical' | 'horizontal';\n }\n private _orientation: 'vertical' | 'horizontal' = 'vertical';\n\n @state() private _hasErrorSlot = false;\n @state() private _hasHelpSlot = false;\n\n // ─── Internal IDs ───\n\n private _groupId = `hx-checkbox-group-${++_uid}`;\n private _helpTextId = `${this._groupId}-help`;\n private _errorId = `${this._groupId}-error`;\n\n // ─── Slot Handlers ───\n\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 private _handleHelpSlotChange(e: Event): void {\n const slot = e.target as HTMLSlotElement;\n this._hasHelpSlot = slot.assignedNodes({ flatten: true }).length > 0;\n }\n\n // ─── Lifecycle ───\n\n override connectedCallback(): void {\n super.connectedCallback();\n this.addEventListener('hx-change', this._handleCheckboxChange);\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n this.removeEventListener('hx-change', this._handleCheckboxChange);\n }\n\n override updated(changedProperties: Map<string, unknown>): void {\n super.updated(changedProperties);\n if (changedProperties.has('disabled')) {\n this._syncCheckboxes();\n }\n if (changedProperties.has('name')) {\n this._syncCheckboxNames();\n }\n if (changedProperties.has('required')) {\n this._updateValidity();\n }\n }\n\n override firstUpdated(changedProperties: Map<string, unknown>): void {\n super.firstUpdated(changedProperties);\n this._syncCheckboxes();\n this._syncCheckboxNames();\n const checkedValues = this._getCheckedValues();\n this._updateFormValue(checkedValues);\n this._updateValidity(checkedValues);\n }\n\n // ─── Checkbox Management ───\n\n private _getCheckboxes(): HelixCheckbox[] {\n return Array.from(this.children).filter((c): c is HelixCheckbox => c.tagName === 'HX-CHECKBOX');\n }\n\n private _getCheckedValues(): string[] {\n return this._getCheckboxes()\n .filter((cb) => cb.checked)\n .map((cb) => cb.value);\n }\n\n private _syncCheckboxes(): void {\n const checkboxes = this._getCheckboxes();\n checkboxes.forEach((cb) => {\n cb.disabled = this.disabled;\n });\n }\n\n private _syncCheckboxNames(): void {\n if (!this.name) return;\n const checkboxes = this._getCheckboxes();\n checkboxes.forEach((cb) => {\n cb.name = this.name;\n });\n }\n\n // ─── Event Handling ───\n\n private _handleCheckboxChange = (e: Event): void => {\n // Only intercept events from direct hx-checkbox children — do not re-intercept\n // the hx-change we dispatch ourselves from this element.\n if (e.target === this) return;\n\n e.stopImmediatePropagation();\n\n const values = this._getCheckedValues();\n this._updateFormValue(values);\n this._updateValidity(values);\n\n /**\n * Dispatched when any child checkbox changes.\n * @event hx-change\n */\n this.dispatchEvent(\n new CustomEvent('hx-change', {\n bubbles: true,\n composed: true,\n detail: { values },\n }),\n );\n };\n\n private _handleSlotChange(): void {\n this._syncCheckboxes();\n this._syncCheckboxNames();\n const checkedValues = this._getCheckedValues();\n this._updateFormValue(checkedValues);\n this._updateValidity(checkedValues);\n }\n\n // ─── Form Integration ───\n\n private _updateFormValue(values: string[]): void {\n if (values.length === 0) {\n this._internals.setFormValue(null);\n return;\n }\n const formData = new FormData();\n values.forEach((v) => formData.append(this.name, v));\n this._internals.setFormValue(formData);\n }\n\n private _updateValidity(values?: string[]): void {\n const checkedValues = values ?? this._getCheckedValues();\n if (this.required && checkedValues.length === 0) {\n const firstCheckbox = this._getCheckboxes()[0];\n this._internals.setValidity(\n { valueMissing: true },\n this.error || 'Please select at least one option.',\n firstCheckbox,\n );\n } else {\n this._internals.setValidity({});\n }\n }\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 group 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 /** Called by the form when it resets. */\n formResetCallback(): void {\n const checkboxes = this._getCheckboxes();\n checkboxes.forEach((cb) => {\n cb.checked = false;\n });\n this._internals.setFormValue(null);\n this._updateValidity([]);\n }\n\n /** Called when the form restores state (e.g., back/forward navigation). */\n formStateRestoreCallback(state: string | File | FormData): void {\n if (!(state instanceof FormData)) return;\n const restoredValues = state.getAll(this.name).map((v) => String(v));\n const checkboxes = this._getCheckboxes();\n checkboxes.forEach((cb) => {\n cb.checked = restoredValues.includes(cb.value);\n });\n this._updateFormValue(restoredValues);\n this._updateValidity(restoredValues);\n }\n\n // ─── Render ───\n\n override render() {\n const hasError = !!this.error || this._hasErrorSlot;\n\n const fieldsetClasses = {\n fieldset: true,\n 'fieldset--error': hasError,\n 'fieldset--disabled': this.disabled,\n 'fieldset--required': this.required,\n };\n\n const describedBy =\n [hasError ? this._errorId : null, this._hasHelpSlot ? this._helpTextId : null]\n .filter(Boolean)\n .join(' ') || undefined;\n\n return html`\n <fieldset\n part=\"group\"\n class=${classMap(fieldsetClasses)}\n aria-describedby=${describedBy ?? nothing}\n >\n <legend part=\"label\" class=\"fieldset__legend\">\n <slot name=\"label\">${this.label}</slot>\n ${this.required\n ? html`<span class=\"fieldset__required-marker\" aria-hidden=\"true\">*</span>`\n : nothing}\n </legend>\n\n <div class=\"fieldset__items\">\n <slot @slotchange=${this._handleSlotChange}></slot>\n </div>\n\n ${hasError\n ? html`<div part=\"error-message\" class=\"fieldset__error\" id=${this._errorId} role=\"alert\">\n <slot name=\"error\" @slotchange=${this._handleErrorSlotChange}> ${this.error} </slot>\n </div>`\n : html`<slot name=\"error\" @slotchange=${this._handleErrorSlotChange}></slot>`}\n\n <div part=\"help-text\" class=\"fieldset__help-text\" id=${this._helpTextId}>\n <slot name=\"help\" @slotchange=${this._handleHelpSlotChange}></slot>\n </div>\n </fieldset>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-checkbox-group': HelixCheckboxGroup;\n }\n}\n"],"names":["helixCheckboxGroupStyles","css","_uid","HelixCheckboxGroup","LitElement","values","value","slot","changedProperties","checkedValues","c","cb","formData","v","firstCheckbox","state","restoredValues","hasError","fieldsetClasses","describedBy","html","classMap","nothing","tokenStyles","__decorateClass","property","customElement"],"mappings":"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"}
|