@nvidia-elements/core 0.0.10 → 0.0.12
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/CHANGELOG.md +33 -0
- package/dist/accordion/accordion.examples.json +11 -11
- package/dist/accordion/accordion2.js +4 -4
- package/dist/alert/alert-group2.js +1 -1
- package/dist/alert/alert.examples.json +12 -12
- package/dist/alert/alert2.js +1 -1
- package/dist/avatar/avatar-group2.js +1 -1
- package/dist/avatar/avatar.examples.json +6 -6
- package/dist/avatar/avatar2.js +1 -1
- package/dist/badge/badge.examples.json +12 -12
- package/dist/badge/badge2.js +1 -1
- package/dist/breadcrumb/breadcrumb.examples.json +3 -3
- package/dist/breadcrumb/breadcrumb2.js +1 -1
- package/dist/bundles/index.js +4 -4
- package/dist/button/button.examples.json +24 -24
- package/dist/button/button2.js +1 -1
- package/dist/button-group/button-group.d.ts +1 -1
- package/dist/button-group/button-group.examples.json +11 -11
- package/dist/button-group/button-group2.js +1 -1
- package/dist/button-group/button-group2.js.map +1 -1
- package/dist/card/card.examples.json +10 -10
- package/dist/card/card2.js +4 -4
- package/dist/chat-message/chat-message.examples.json +7 -7
- package/dist/chat-message/chat-message2.js +1 -1
- package/dist/checkbox/checkbox-group2.js +1 -1
- package/dist/checkbox/checkbox.examples.json +7 -7
- package/dist/checkbox/checkbox2.js +1 -1
- package/dist/color/color.examples.json +4 -4
- package/dist/color/color2.js +1 -1
- package/dist/combobox/combobox.examples.json +24 -24
- package/dist/combobox/combobox2.js +1 -1
- package/dist/copy-button/copy-button.examples.json +9 -9
- package/dist/copy-button/copy-button2.js +1 -1
- package/dist/custom-elements-jsx.d.ts +1 -1
- package/dist/custom-elements-vue.d.ts +1 -1
- package/dist/custom-elements.json +15 -73
- package/dist/data.html.json +2 -2
- package/dist/date/date.examples.json +7 -7
- package/dist/date/date2.js +1 -1
- package/dist/datetime/datetime.examples.json +4 -4
- package/dist/datetime/datetime2.js +1 -1
- package/dist/dialog/dialog-footer2.js +1 -1
- package/dist/dialog/dialog-header2.js +1 -1
- package/dist/dialog/dialog.examples.json +21 -21
- package/dist/dialog/dialog2.js +1 -1
- package/dist/divider/divider.examples.json +5 -5
- package/dist/divider/divider2.js +1 -1
- package/dist/dot/dot.examples.json +5 -5
- package/dist/dot/dot2.js +1 -1
- package/dist/drawer/drawer-content2.js +1 -1
- package/dist/drawer/drawer-footer2.js +1 -1
- package/dist/drawer/drawer-header2.js +1 -1
- package/dist/drawer/drawer.examples.json +13 -13
- package/dist/drawer/drawer2.js +1 -1
- package/dist/dropdown/dropdown-footer2.js +1 -1
- package/dist/dropdown/dropdown-header2.js +1 -1
- package/dist/dropdown/dropdown.examples.json +14 -14
- package/dist/dropdown/dropdown2.js +1 -1
- package/dist/dropdown-group/dropdown-group.examples.json +4 -4
- package/dist/dropdown-group/dropdown-group.js +1 -1
- package/dist/dropzone/dropzone.examples.json +3 -3
- package/dist/dropzone/dropzone2.js +1 -1
- package/dist/file/file.examples.json +3 -3
- package/dist/file/file2.js +1 -1
- package/dist/format-datetime/format-datetime.examples.json +9 -9
- package/dist/format-datetime/format-datetime2.js +1 -1
- package/dist/format-relative-time/format-relative-time.examples.json +7 -7
- package/dist/format-relative-time/format-relative-time2.js +73 -53
- package/dist/format-relative-time/format-relative-time2.js.map +1 -1
- package/dist/forms/actions.examples.json +3 -3
- package/dist/forms/control/control.examples.json +11 -11
- package/dist/forms/control/control2.js +1 -1
- package/dist/forms/control-group/control-group2.js +1 -1
- package/dist/forms/control-message/control-message2.js +1 -1
- package/dist/forms/forms.examples.json +8 -8
- package/dist/forms/validation.examples.js.map +1 -1
- package/dist/forms/validation.examples.json +5 -5
- package/dist/grid/cell/cell2.js +1 -1
- package/dist/grid/column/column2.js +1 -1
- package/dist/grid/footer/footer2.js +1 -1
- package/dist/grid/grid.examples.json +43 -43
- package/dist/grid/grid2.js +1 -1
- package/dist/grid/header/header2.js +2 -2
- package/dist/grid/header/header2.js.map +1 -1
- package/dist/grid/placeholder/placeholder2.js +1 -1
- package/dist/grid/row/row2.js +1 -1
- package/dist/icon/icon.examples.json +8 -8
- package/dist/icon/icon2.js +2 -2
- package/dist/icon-button/icon-button.examples.json +13 -13
- package/dist/icon-button/icon-button2.js +1 -1
- package/dist/index.js +1 -1
- package/dist/input/input-group.examples.json +2 -2
- package/dist/input/input-group2.js +1 -1
- package/dist/input/input.examples.json +8 -8
- package/dist/input/input2.js +1 -1
- package/dist/internal/controllers/i18n.controller.examples.json +1 -1
- package/dist/internal/controllers/keynav-grid.controller.examples.json +2 -2
- package/dist/internal/controllers/keynav-grid.controller.js +15 -7
- package/dist/internal/controllers/keynav-grid.controller.js.map +1 -1
- package/dist/internal/controllers/keynav-list.controller.examples.json +4 -4
- package/dist/internal/controllers/keynav-list.controller.js +11 -5
- package/dist/internal/controllers/keynav-list.controller.js.map +1 -1
- package/dist/internal/controllers/popover.examples.json +8 -8
- package/dist/internal/controllers/type-button.controller.examples.json +1 -1
- package/dist/internal/controllers/type-popover.controller.examples.json +2 -2
- package/dist/internal/controllers/type-touch.controller.examples.json +1 -1
- package/dist/internal/services/global.service.js +1 -1
- package/dist/internal/utils/objects.js +17 -9
- package/dist/internal/utils/objects.js.map +1 -1
- package/dist/logo/logo.examples.json +6 -6
- package/dist/logo/logo2.js +1 -1
- package/dist/menu/menu-item2.js +1 -1
- package/dist/menu/menu.examples.json +15 -15
- package/dist/menu/menu2.js +1 -1
- package/dist/month/month.examples.json +4 -4
- package/dist/month/month2.js +1 -1
- package/dist/notification/notification-group2.js +1 -1
- package/dist/notification/notification.examples.json +15 -15
- package/dist/notification/notification2.js +1 -1
- package/dist/page/page-panel/page-panel-content2.js +1 -1
- package/dist/page/page-panel/page-panel-footer2.js +1 -1
- package/dist/page/page-panel/page-panel-header2.js +1 -1
- package/dist/page/page-panel/page-panel2.js +1 -1
- package/dist/page/page.examples.js.map +1 -1
- package/dist/page/page.examples.json +37 -35
- package/dist/page/page2.js +1 -1
- package/dist/page-header/page-header.examples.json +9 -9
- package/dist/page-header/page-header2.js +1 -1
- package/dist/page-loader/page-loader.examples.json +2 -2
- package/dist/page-loader/page-loader2.js +1 -1
- package/dist/pagination/pagination.examples.json +16 -16
- package/dist/pagination/pagination2.js +1 -1
- package/dist/panel/panel.examples.json +7 -7
- package/dist/panel/panel2.js +4 -4
- package/dist/password/password.examples.json +3 -3
- package/dist/password/password2.js +1 -1
- package/dist/preferences-input/preferences-input.examples.json +3 -3
- package/dist/preferences-input/preferences-input2.js +1 -1
- package/dist/progress-bar/progress-bar.examples.json +8 -8
- package/dist/progress-bar/progress-bar2.js +1 -1
- package/dist/progress-ring/progress-ring.examples.json +8 -8
- package/dist/progress-ring/progress-ring2.js +1 -1
- package/dist/progressive-filter-chip/progressive-filter-chip.examples.json +7 -7
- package/dist/progressive-filter-chip/progressive-filter-chip2.js +1 -1
- package/dist/pulse/pulse.examples.json +4 -4
- package/dist/pulse/pulse2.js +1 -1
- package/dist/radio/radio-group2.js +1 -1
- package/dist/radio/radio.examples.json +5 -5
- package/dist/radio/radio2.js +1 -1
- package/dist/range/range.examples.json +9 -9
- package/dist/range/range2.js +1 -1
- package/dist/resize-handle/resize-handle.examples.json +7 -7
- package/dist/resize-handle/resize-handle2.js +1 -1
- package/dist/search/search.examples.json +5 -5
- package/dist/search/search2.js +1 -1
- package/dist/select/select.examples.json +18 -18
- package/dist/select/select2.js +1 -1
- package/dist/skeleton/skeleton.examples.json +4 -4
- package/dist/skeleton/skeleton2.js +1 -1
- package/dist/sort-button/sort-button.examples.json +3 -3
- package/dist/sort-button/sort-button2.js +1 -1
- package/dist/sparkline/sparkline.examples.json +13 -13
- package/dist/sparkline/sparkline.utils.d.ts +26 -5
- package/dist/sparkline/sparkline.utils.js +30 -30
- package/dist/sparkline/sparkline.utils.js.map +1 -1
- package/dist/sparkline/sparkline2.js +21 -6
- package/dist/sparkline/sparkline2.js.map +1 -1
- package/dist/star-rating/star-rating.examples.json +4 -4
- package/dist/star-rating/star-rating2.js +1 -1
- package/dist/steps/steps.examples.json +5 -5
- package/dist/steps/steps2.js +2 -2
- package/dist/switch/switch-group2.js +1 -1
- package/dist/switch/switch.examples.json +7 -7
- package/dist/switch/switch2.js +1 -1
- package/dist/tabs/tabs-group2.js +9 -6
- package/dist/tabs/tabs-group2.js.map +1 -1
- package/dist/tabs/tabs.examples.json +14 -14
- package/dist/tabs/tabs2.js +2 -2
- package/dist/tag/tag.examples.json +8 -8
- package/dist/tag/tag2.js +1 -1
- package/dist/textarea/textarea.examples.json +5 -5
- package/dist/textarea/textarea2.js +1 -1
- package/dist/time/time.examples.json +4 -4
- package/dist/time/time2.js +1 -1
- package/dist/toast/toast.examples.json +11 -11
- package/dist/toast/toast2.js +1 -1
- package/dist/toggletip/toggletip-footer2.js +1 -1
- package/dist/toggletip/toggletip-header2.js +1 -1
- package/dist/toggletip/toggletip.examples.json +12 -12
- package/dist/toggletip/toggletip2.js +1 -1
- package/dist/toolbar/toolbar.examples.json +8 -8
- package/dist/toolbar/toolbar2.js +1 -1
- package/dist/tooltip/tooltip.examples.json +22 -22
- package/dist/tooltip/tooltip2.js +1 -1
- package/dist/tree/tree-node2.js +1 -1
- package/dist/tree/tree.examples.json +13 -13
- package/dist/tree/tree2.js +1 -1
- package/dist/week/week.examples.json +5 -5
- package/dist/week/week2.js +1 -1
- package/package.json +5 -5
|
@@ -21,7 +21,7 @@ var C = class extends _ {
|
|
|
21
21
|
static {
|
|
22
22
|
this.metadata = {
|
|
23
23
|
tag: "nve-sparkline",
|
|
24
|
-
version: "0.0.
|
|
24
|
+
version: "0.0.12"
|
|
25
25
|
};
|
|
26
26
|
}
|
|
27
27
|
render() {
|
|
@@ -50,9 +50,17 @@ var C = class extends _ {
|
|
|
50
50
|
this.style.setProperty("--_aspect-ratio", i.toFixed(4));
|
|
51
51
|
}
|
|
52
52
|
#t(e, t) {
|
|
53
|
-
let n = a(this.validData,
|
|
53
|
+
let n = a(this.validData, {
|
|
54
|
+
explicitMin: this.min,
|
|
55
|
+
explicitMax: this.max
|
|
56
|
+
});
|
|
54
57
|
if (!n) return y;
|
|
55
|
-
let r = h(0, n
|
|
58
|
+
let r = h(0, n), i = n.min < 0 && n.max > 0, s = f(this.validData, n, { width: e }), l = o(this.validData, {
|
|
59
|
+
first: this.denoteFirst,
|
|
60
|
+
last: this.denoteLast,
|
|
61
|
+
min: this.denoteMin,
|
|
62
|
+
max: this.denoteMax
|
|
63
|
+
}), p = u(this.interpolation), m = d(s, p, e), g = this.mark === "area" || this.mark === "gradient" ? c(s, p, 100) : "";
|
|
56
64
|
return b`<svg viewBox="0 0 ${e} ${t}" preserveAspectRatio="xMidYMid meet" aria-hidden="true">${this.mark === "gradient" ? this.#n(t) : y} ${g.length ? this.mark === "gradient" ? b`<path class="area" d="${g}" style="fill:url(#gradient)"></path>` : b`<path class="area" d="${g}"></path>` : y} ${i ? this.#r(r, e) : y} ${m ? b`<path class="line" d="${m}" vector-effect="non-scaling-stroke"></path>` : y}</svg> ${this.#i(s, l)}`;
|
|
57
65
|
}
|
|
58
66
|
#n(e) {
|
|
@@ -68,14 +76,21 @@ var C = class extends _ {
|
|
|
68
76
|
})}`;
|
|
69
77
|
}
|
|
70
78
|
#a(e, t) {
|
|
71
|
-
let n = a(this.validData,
|
|
79
|
+
let n = a(this.validData, {
|
|
80
|
+
explicitMin: this.min,
|
|
81
|
+
explicitMax: this.max,
|
|
82
|
+
includeZero: !0
|
|
83
|
+
});
|
|
72
84
|
if (!n) return y;
|
|
73
|
-
let r = h(0, n
|
|
85
|
+
let r = h(0, n), i = n.min < 0 && n.max > 0, o = l(f(this.validData, n, { width: e }), r, e);
|
|
74
86
|
return b`<svg viewBox="0 0 ${e} ${t}" preserveAspectRatio="xMidYMid meet" aria-hidden="true">${i ? this.#r(r, e) : y} ${o.map((e) => b`<rect class="column" x="${e.x.toFixed(2)}" y="${e.y.toFixed(2)}" width="${e.width.toFixed(2)}" height="${e.height.toFixed(2)}"></rect>`)}</svg>`;
|
|
75
87
|
}
|
|
76
88
|
#o(e, t, n) {
|
|
77
89
|
if (this.validData.length === 0) return y;
|
|
78
|
-
let r = m(this.validData, e,
|
|
90
|
+
let r = m(this.validData, e, {
|
|
91
|
+
width: t,
|
|
92
|
+
height: n
|
|
93
|
+
});
|
|
79
94
|
return b`<svg viewBox="0 0 ${t} ${n}" preserveAspectRatio="xMidYMid meet" aria-hidden="true">${this.#r(e, t)} ${r.map((e) => b`<rect class="${e.className}" x="${e.x.toFixed(2)}" y="${e.y.toFixed(2)}" width="${e.width.toFixed(2)}" height="${e.height.toFixed(2)}"></rect>`)}</svg>`;
|
|
80
95
|
}
|
|
81
96
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sparkline2.js","names":["#renderChart","#renderLineVariant","#renderColumn","#renderWinLoss","#renderGradientDef","#renderZeroLine","#renderAccents"],"sources":["../../src/sparkline/sparkline.ts"],"sourcesContent":["// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nimport type { PropertyValues, SVGTemplateResult } from 'lit';\nimport { html, LitElement, nothing, svg } from 'lit';\nimport { property } from 'lit/decorators/property.js';\nimport { state } from 'lit/decorators/state.js';\nimport type {\n DataElement,\n Interpolation,\n Point,\n SizeExpanded,\n SparklineMark,\n SupportStatus,\n TaskStatus\n} from '@nvidia-elements/core/internal';\nimport { attachInternals, statusStateStyles, supportStateStyles, useStyles } from '@nvidia-elements/core/internal';\nimport {\n calculateDomain,\n calculateSymbolIndices,\n calculateViewBox,\n PRECISION,\n toAreaPath,\n toColumnRects,\n toInterpolation,\n toLinePath,\n toPlotPoints,\n toValidData,\n toWinLossRects,\n valueToY,\n VIEW_HEIGHT\n} from './sparkline.utils.js';\nimport styles from './sparkline.css?inline';\n\n/**\n * @element nve-sparkline\n * @description A sparkline is a compact, word-sized chart with typographic scale, for data-dense layouts (text, tables, cards, dashboards).\n * @since 0.0.0\n * @entrypoint \\@nvidia-elements/core/sparkline\n * @cssprop --height - Height (defaults to 1em and scales with parent font-size).\n * @cssprop --line-color\n * @cssprop --line-width\n * @cssprop --fill-color - Color used by area and column marks.\n * @cssprop --gradient-max-color\n * @cssprop --gradient-min-color\n * @cssprop --zero-line-color\n * @cssprop --zero-line-width\n * @cssprop --win-color Color used to represent positive values (wins).\n * @cssprop --loss-color Color used to represent negative values (losses).\n * @cssprop --draw-color Color used to represent zero values (draws / neutral outcomes).\n * @cssprop --symbol-color\n * @cssprop --symbol-border-color\n * @cssprop --symbol-border-width\n * @cssprop --symbol-radius - symbol circle radius in SVG units.\n * @aria https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img\n */\nexport class Sparkline extends LitElement implements DataElement<number[]> {\n static styles = useStyles([styles, statusStateStyles, supportStateStyles]);\n\n static readonly metadata = {\n tag: 'nve-sparkline',\n version: '0.0.0'\n };\n\n /** Numeric values representing a data series. */\n @property({ type: Array }) data: number[] = [];\n\n /** Controls the visual representation of data points. */\n @property({ type: String }) mark: SparklineMark = 'line';\n\n /** Controls how the chart connects intermediate values between points in a data series. Defaults to `linear`. */\n @property({ type: String }) interpolation: Interpolation = 'linear';\n\n /** Applies semantic status colors used across Elements status patterns. */\n @property({ type: String, reflect: true }) status?: TaskStatus | SupportStatus;\n\n /** Controls the sparkline size with explicit font-size tokens. Omit to auto-scale with parent font-size (1em). */\n @property({ type: String, reflect: true }) size?: SizeExpanded;\n\n /** Denotes the first data point by rendering a symbol at its position. */\n @property({ type: Boolean, attribute: 'denote-first', reflect: true })\n denoteFirst = false;\n\n /** Denotes the last data point by rendering a symbol at its position. */\n @property({ type: Boolean, attribute: 'denote-last', reflect: true })\n denoteLast = false;\n\n /** Denotes all minimum-value data points by rendering symbols at their positions. */\n @property({ type: Boolean, attribute: 'denote-min', reflect: true })\n denoteMin = false;\n\n /** Denotes all maximum-value data points by rendering symbols at their positions. */\n @property({ type: Boolean, attribute: 'denote-max', reflect: true })\n denoteMax = false;\n\n /** Controls spacing between points in a line, in em (1 = chart height). Defaults to `0.6`. */\n @property({ type: Number, attribute: 'interval-length' }) intervalLength = 0.6;\n\n /** Lower bound for the y-axis domain. When undefined, derives the bound from data. */\n @property({ type: Number }) min?: number;\n\n /** Upper bound for the y-axis domain. When undefined, derives the bound from data. */\n @property({ type: Number }) max?: number;\n\n /** Cached valid numeric values derived from data property. */\n @state() private validData: number[] = [];\n\n /** @private */\n declare _internals: ElementInternals;\n\n render() {\n return html`<div internal-host>${this.#renderChart()}</div>`;\n }\n\n connectedCallback() {\n super.connectedCallback();\n attachInternals(this);\n this._internals.role = 'img';\n }\n\n willUpdate(changedProperties: PropertyValues<this>) {\n super.willUpdate(changedProperties);\n\n if (changedProperties.has('data')) {\n this.validData = toValidData(this.data);\n }\n }\n\n #renderChart(): SVGTemplateResult | typeof nothing {\n const { width, height } = calculateViewBox(this.mark, this.validData.length, this.intervalLength);\n\n switch (this.mark) {\n case 'line':\n case 'area':\n case 'gradient':\n return this.#renderLineVariant(width, height);\n case 'column':\n return this.#renderColumn(width, height);\n case 'winloss':\n return this.#renderWinLoss(VIEW_HEIGHT / 2, width, height);\n default:\n const _exhaustiveCheck: never = this.mark;\n return nothing;\n }\n }\n\n updated(props: PropertyValues<this>) {\n super.updated(props);\n\n const { width, height } = calculateViewBox(this.mark, this.validData.length, this.intervalLength);\n const aspectRatio = width / height;\n const validAspectRatio = Number.isFinite(aspectRatio) && aspectRatio > 0 ? aspectRatio : 1;\n this.style.setProperty('--_aspect-ratio', validAspectRatio.toFixed(4));\n }\n\n #renderLineVariant(width: number, height: number) {\n const domain = calculateDomain(this.validData, this.min, this.max);\n if (!domain) return nothing;\n\n const baselineY = valueToY(0, domain.min, domain.max);\n const drawZeroLine = domain.min < 0 && domain.max > 0;\n\n const plotPoints = toPlotPoints(this.validData, domain.min, domain.max, width);\n const symbolIndices = calculateSymbolIndices(\n this.validData,\n this.denoteFirst,\n this.denoteLast,\n this.denoteMin,\n this.denoteMax\n );\n const interpolation = toInterpolation(this.interpolation);\n\n const linePath = toLinePath(plotPoints, interpolation, width);\n const drawArea = this.mark === 'area' || this.mark === 'gradient';\n const areaPath = drawArea ? toAreaPath(plotPoints, interpolation, VIEW_HEIGHT) : '';\n\n return svg`\n <svg viewBox=\"0 0 ${width} ${height}\" preserveAspectRatio=\"xMidYMid meet\" aria-hidden=\"true\">\n ${this.mark === 'gradient' ? this.#renderGradientDef(height) : nothing}\n\n ${\n areaPath.length\n ? this.mark === 'gradient'\n ? svg`<path class=\"area\" d=${areaPath} style=\"fill: url(#gradient)\"></path>`\n : svg`<path class=\"area\" d=${areaPath}></path>`\n : nothing\n }\n\n ${drawZeroLine ? this.#renderZeroLine(baselineY, width) : nothing}\n\n ${linePath ? svg`<path class=\"line\" d=${linePath} vector-effect=\"non-scaling-stroke\"></path>` : nothing}\n </svg>\n ${this.#renderAccents(plotPoints, symbolIndices)}\n `;\n }\n\n #renderGradientDef(height: number) {\n return svg`\n <defs>\n <linearGradient id=\"gradient\" x1=\"0\" y1=\"0\" x2=\"0\" y2=\"${height}\" gradientUnits=\"userSpaceOnUse\">\n <stop offset=\"0%\" style=\"stop-color: var(--gradient-max-color)\"></stop>\n <stop offset=\"100%\" style=\"stop-color: var(--gradient-min-color)\"></stop>\n </linearGradient>\n </defs>\n `;\n }\n\n #renderZeroLine(position: number, width: number) {\n return svg`\n <line\n class=\"zero-line\"\n vector-effect=\"non-scaling-stroke\"\n x1=\"0\"\n y1=\"${position.toFixed(PRECISION)}\"\n x2=\"${width}\"\n y2=\"${position.toFixed(PRECISION)}\">\n </line>\n `;\n }\n\n #renderAccents(points: Point[], accentIndices: Set<number>) {\n if (points.length === 0 || accentIndices.size === 0) return nothing;\n\n return html`\n ${Array.from(accentIndices).map(index => {\n const point = points[index];\n if (!point) return nothing;\n\n const style = `--x: ${point.x.toFixed(PRECISION)}; --y: ${point.y.toFixed(PRECISION)}`;\n return html`\n <span style=${style} class=\"accent\"></span>\n `;\n })}\n `;\n }\n\n #renderColumn(width: number, height: number) {\n const domain = calculateDomain(this.validData, this.min, this.max, true);\n if (!domain) return nothing;\n\n const baselineY = valueToY(0, domain.min, domain.max);\n const showZeroLine = domain.min < 0 && domain.max > 0;\n const plotPoints = toPlotPoints(this.validData, domain.min, domain.max, width);\n const rects = toColumnRects(plotPoints, baselineY, width);\n\n return svg`\n <svg viewBox=\"0 0 ${width} ${height}\" preserveAspectRatio=\"xMidYMid meet\" aria-hidden=\"true\">\n ${showZeroLine ? this.#renderZeroLine(baselineY, width) : nothing}\n\n ${rects.map(rect => {\n return svg`<rect class=\"column\" x=\"${rect.x.toFixed(PRECISION)}\" y=\"${rect.y.toFixed(PRECISION)}\" width=\"${rect.width.toFixed(PRECISION)}\" height=\"${rect.height.toFixed(PRECISION)}\"></rect>`;\n })}\n </svg>\n `;\n }\n\n #renderWinLoss(baselineY: number, width: number, height: number) {\n if (this.validData.length === 0) return nothing;\n\n const rects = toWinLossRects(this.validData, baselineY, width, height);\n\n return svg`\n <svg viewBox=\"0 0 ${width} ${height}\" preserveAspectRatio=\"xMidYMid meet\" aria-hidden=\"true\">\n ${this.#renderZeroLine(baselineY, width)}\n\n ${rects.map(rect => {\n return svg`<rect class=\"${rect.className}\" x=\"${rect.x.toFixed(PRECISION)}\" y=\"${rect.y.toFixed(PRECISION)}\" width=\"${rect.width.toFixed(PRECISION)}\" height=\"${rect.height.toFixed(PRECISION)}\"></rect>`;\n })}\n </svg>\n `;\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"sparkline2.js","names":["#renderChart","#renderLineVariant","#renderColumn","#renderWinLoss","#renderGradientDef","#renderZeroLine","#renderAccents"],"sources":["../../src/sparkline/sparkline.ts"],"sourcesContent":["// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nimport type { PropertyValues, SVGTemplateResult } from 'lit';\nimport { html, LitElement, nothing, svg } from 'lit';\nimport { property } from 'lit/decorators/property.js';\nimport { state } from 'lit/decorators/state.js';\nimport type {\n DataElement,\n Interpolation,\n Point,\n SizeExpanded,\n SparklineMark,\n SupportStatus,\n TaskStatus\n} from '@nvidia-elements/core/internal';\nimport { attachInternals, statusStateStyles, supportStateStyles, useStyles } from '@nvidia-elements/core/internal';\nimport {\n calculateDomain,\n calculateSymbolIndices,\n calculateViewBox,\n PRECISION,\n toAreaPath,\n toColumnRects,\n toInterpolation,\n toLinePath,\n toPlotPoints,\n toValidData,\n toWinLossRects,\n valueToY,\n VIEW_HEIGHT\n} from './sparkline.utils.js';\nimport styles from './sparkline.css?inline';\n\n/**\n * @element nve-sparkline\n * @description A sparkline is a compact, word-sized chart with typographic scale, for data-dense layouts (text, tables, cards, dashboards).\n * @since 0.0.0\n * @entrypoint \\@nvidia-elements/core/sparkline\n * @cssprop --height - Height (defaults to 1em and scales with parent font-size).\n * @cssprop --line-color\n * @cssprop --line-width\n * @cssprop --fill-color - Color used by area and column marks.\n * @cssprop --gradient-max-color\n * @cssprop --gradient-min-color\n * @cssprop --zero-line-color\n * @cssprop --zero-line-width\n * @cssprop --win-color Color used to represent positive values (wins).\n * @cssprop --loss-color Color used to represent negative values (losses).\n * @cssprop --draw-color Color used to represent zero values (draws / neutral outcomes).\n * @cssprop --symbol-color\n * @cssprop --symbol-border-color\n * @cssprop --symbol-border-width\n * @cssprop --symbol-radius - symbol circle radius in SVG units.\n * @aria https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img\n */\nexport class Sparkline extends LitElement implements DataElement<number[]> {\n static styles = useStyles([styles, statusStateStyles, supportStateStyles]);\n\n static readonly metadata = {\n tag: 'nve-sparkline',\n version: '0.0.0'\n };\n\n /** Numeric values representing a data series. */\n @property({ type: Array }) data: number[] = [];\n\n /** Controls the visual representation of data points. */\n @property({ type: String }) mark: SparklineMark = 'line';\n\n /** Controls how the chart connects intermediate values between points in a data series. Defaults to `linear`. */\n @property({ type: String }) interpolation: Interpolation = 'linear';\n\n /** Applies semantic status colors used across Elements status patterns. */\n @property({ type: String, reflect: true }) status?: TaskStatus | SupportStatus;\n\n /** Controls the sparkline size with explicit font-size tokens. Omit to auto-scale with parent font-size (1em). */\n @property({ type: String, reflect: true }) size?: SizeExpanded;\n\n /** Denotes the first data point by rendering a symbol at its position. */\n @property({ type: Boolean, attribute: 'denote-first', reflect: true })\n denoteFirst = false;\n\n /** Denotes the last data point by rendering a symbol at its position. */\n @property({ type: Boolean, attribute: 'denote-last', reflect: true })\n denoteLast = false;\n\n /** Denotes all minimum-value data points by rendering symbols at their positions. */\n @property({ type: Boolean, attribute: 'denote-min', reflect: true })\n denoteMin = false;\n\n /** Denotes all maximum-value data points by rendering symbols at their positions. */\n @property({ type: Boolean, attribute: 'denote-max', reflect: true })\n denoteMax = false;\n\n /** Controls spacing between points in a line, in em (1 = chart height). Defaults to `0.6`. */\n @property({ type: Number, attribute: 'interval-length' }) intervalLength = 0.6;\n\n /** Lower bound for the y-axis domain. When undefined, derives the bound from data. */\n @property({ type: Number }) min?: number;\n\n /** Upper bound for the y-axis domain. When undefined, derives the bound from data. */\n @property({ type: Number }) max?: number;\n\n /** Cached valid numeric values derived from data property. */\n @state() private validData: number[] = [];\n\n /** @private */\n declare _internals: ElementInternals;\n\n render() {\n return html`<div internal-host>${this.#renderChart()}</div>`;\n }\n\n connectedCallback() {\n super.connectedCallback();\n attachInternals(this);\n this._internals.role = 'img';\n }\n\n willUpdate(changedProperties: PropertyValues<this>) {\n super.willUpdate(changedProperties);\n\n if (changedProperties.has('data')) {\n this.validData = toValidData(this.data);\n }\n }\n\n #renderChart(): SVGTemplateResult | typeof nothing {\n const { width, height } = calculateViewBox(this.mark, this.validData.length, this.intervalLength);\n\n switch (this.mark) {\n case 'line':\n case 'area':\n case 'gradient':\n return this.#renderLineVariant(width, height);\n case 'column':\n return this.#renderColumn(width, height);\n case 'winloss':\n return this.#renderWinLoss(VIEW_HEIGHT / 2, width, height);\n default:\n const _exhaustiveCheck: never = this.mark;\n return nothing;\n }\n }\n\n updated(props: PropertyValues<this>) {\n super.updated(props);\n\n const { width, height } = calculateViewBox(this.mark, this.validData.length, this.intervalLength);\n const aspectRatio = width / height;\n const validAspectRatio = Number.isFinite(aspectRatio) && aspectRatio > 0 ? aspectRatio : 1;\n this.style.setProperty('--_aspect-ratio', validAspectRatio.toFixed(4));\n }\n\n #renderLineVariant(width: number, height: number) {\n const domain = calculateDomain(this.validData, { explicitMin: this.min, explicitMax: this.max });\n if (!domain) return nothing;\n\n const baselineY = valueToY(0, domain);\n const drawZeroLine = domain.min < 0 && domain.max > 0;\n\n const plotPoints = toPlotPoints(this.validData, domain, { width });\n const symbolIndices = calculateSymbolIndices(this.validData, {\n first: this.denoteFirst,\n last: this.denoteLast,\n min: this.denoteMin,\n max: this.denoteMax\n });\n const interpolation = toInterpolation(this.interpolation);\n\n const linePath = toLinePath(plotPoints, interpolation, width);\n const drawArea = this.mark === 'area' || this.mark === 'gradient';\n const areaPath = drawArea ? toAreaPath(plotPoints, interpolation, VIEW_HEIGHT) : '';\n\n return svg`\n <svg viewBox=\"0 0 ${width} ${height}\" preserveAspectRatio=\"xMidYMid meet\" aria-hidden=\"true\">\n ${this.mark === 'gradient' ? this.#renderGradientDef(height) : nothing}\n\n ${\n areaPath.length\n ? this.mark === 'gradient'\n ? svg`<path class=\"area\" d=${areaPath} style=\"fill: url(#gradient)\"></path>`\n : svg`<path class=\"area\" d=${areaPath}></path>`\n : nothing\n }\n\n ${drawZeroLine ? this.#renderZeroLine(baselineY, width) : nothing}\n\n ${linePath ? svg`<path class=\"line\" d=${linePath} vector-effect=\"non-scaling-stroke\"></path>` : nothing}\n </svg>\n ${this.#renderAccents(plotPoints, symbolIndices)}\n `;\n }\n\n #renderGradientDef(height: number) {\n return svg`\n <defs>\n <linearGradient id=\"gradient\" x1=\"0\" y1=\"0\" x2=\"0\" y2=\"${height}\" gradientUnits=\"userSpaceOnUse\">\n <stop offset=\"0%\" style=\"stop-color: var(--gradient-max-color)\"></stop>\n <stop offset=\"100%\" style=\"stop-color: var(--gradient-min-color)\"></stop>\n </linearGradient>\n </defs>\n `;\n }\n\n #renderZeroLine(position: number, width: number) {\n return svg`\n <line\n class=\"zero-line\"\n vector-effect=\"non-scaling-stroke\"\n x1=\"0\"\n y1=\"${position.toFixed(PRECISION)}\"\n x2=\"${width}\"\n y2=\"${position.toFixed(PRECISION)}\">\n </line>\n `;\n }\n\n #renderAccents(points: Point[], accentIndices: Set<number>) {\n if (points.length === 0 || accentIndices.size === 0) return nothing;\n\n return html`\n ${Array.from(accentIndices).map(index => {\n const point = points[index];\n if (!point) return nothing;\n\n const style = `--x: ${point.x.toFixed(PRECISION)}; --y: ${point.y.toFixed(PRECISION)}`;\n return html`\n <span style=${style} class=\"accent\"></span>\n `;\n })}\n `;\n }\n\n #renderColumn(width: number, height: number) {\n const domain = calculateDomain(this.validData, {\n explicitMin: this.min,\n explicitMax: this.max,\n includeZero: true\n });\n if (!domain) return nothing;\n\n const baselineY = valueToY(0, domain);\n const showZeroLine = domain.min < 0 && domain.max > 0;\n const plotPoints = toPlotPoints(this.validData, domain, { width });\n const rects = toColumnRects(plotPoints, baselineY, width);\n\n return svg`\n <svg viewBox=\"0 0 ${width} ${height}\" preserveAspectRatio=\"xMidYMid meet\" aria-hidden=\"true\">\n ${showZeroLine ? this.#renderZeroLine(baselineY, width) : nothing}\n\n ${rects.map(rect => {\n return svg`<rect class=\"column\" x=\"${rect.x.toFixed(PRECISION)}\" y=\"${rect.y.toFixed(PRECISION)}\" width=\"${rect.width.toFixed(PRECISION)}\" height=\"${rect.height.toFixed(PRECISION)}\"></rect>`;\n })}\n </svg>\n `;\n }\n\n #renderWinLoss(baselineY: number, width: number, height: number) {\n if (this.validData.length === 0) return nothing;\n\n const rects = toWinLossRects(this.validData, baselineY, { width, height });\n\n return svg`\n <svg viewBox=\"0 0 ${width} ${height}\" preserveAspectRatio=\"xMidYMid meet\" aria-hidden=\"true\">\n ${this.#renderZeroLine(baselineY, width)}\n\n ${rects.map(rect => {\n return svg`<rect class=\"${rect.className}\" x=\"${rect.x.toFixed(PRECISION)}\" y=\"${rect.y.toFixed(PRECISION)}\" width=\"${rect.width.toFixed(PRECISION)}\" height=\"${rect.height.toFixed(PRECISION)}\"></rect>`;\n })}\n </svg>\n `;\n }\n}\n"],"mappings":"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"}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"entrypoint": "@nvidia-elements/core/star-rating/star-rating.examples.json",
|
|
4
4
|
"items": [
|
|
5
5
|
{
|
|
6
|
-
"id": "
|
|
6
|
+
"id": "star-rating",
|
|
7
7
|
"name": "Default",
|
|
8
8
|
"template": "<nve-star-rating>\n <label>rate this input</label>\n <input id=\"range\" type=\"range\" max=\"5\" value=\"3\" min=\"0\" />\n <nve-control-message>message</nve-control-message>\n</nve-star-rating>\n",
|
|
9
9
|
"summary": "Basic star rating using a range input. Use for collecting user feedback, product reviews, or satisfaction scores in forms.",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"tags": []
|
|
13
13
|
},
|
|
14
14
|
{
|
|
15
|
-
"id": "
|
|
15
|
+
"id": "star-rating-disabled",
|
|
16
16
|
"name": "Disabled",
|
|
17
17
|
"template": "<nve-star-rating>\n <label>disabled</label>\n <input type=\"range\" max=\"5\" value=\"3\" min=\"0\" disabled />\n <nve-control-message>message</nve-control-message>\n</nve-star-rating>\n",
|
|
18
18
|
"summary": "Disabled star rating for display-only contexts. Use when showing existing ratings that users cannot change.",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
]
|
|
24
24
|
},
|
|
25
25
|
{
|
|
26
|
-
"id": "
|
|
26
|
+
"id": "star-rating-half-star",
|
|
27
27
|
"name": "HalfStar",
|
|
28
28
|
"template": "<nve-star-rating>\n <label>Half-star rating</label>\n <input id=\"half-star-input\" type=\"range\" max=\"5\" value=\"3.5\" min=\"0\" step=\"0.5\" />\n <nve-control-message>message</nve-control-message>\n</nve-star-rating>\n",
|
|
29
29
|
"summary": "Half-star increments using step=\"0.5\" for more granular ratings. Ideal when detailed feedback requires finer rating precision.",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"tags": []
|
|
33
33
|
},
|
|
34
34
|
{
|
|
35
|
-
"id": "
|
|
35
|
+
"id": "star-rating-toggle",
|
|
36
36
|
"name": "Toggle",
|
|
37
37
|
"template": "<nve-star-rating>\n <label>toggle/favorite</label>\n <input type=\"range\" max=\"1\" value=\"0\" min=\"0\" />\n</nve-star-rating>\n<script type=\"module\">\n const input = document.querySelector(\"#range\");\n input.addEventListener(\"input\", () => console.log(\"input\", input.valueAsNumber));\n input.addEventListener(\"change\", () => console.log(\"change\", input.valueAsNumber));\n</script>\n",
|
|
38
38
|
"summary": "Single star toggle for favorite/bookmark functionality. Use with max=\"1\" for binary on/off states like wishlists or bookmarks.",
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"entrypoint": "@nvidia-elements/core/steps/steps.examples.json",
|
|
4
4
|
"items": [
|
|
5
5
|
{
|
|
6
|
-
"id": "
|
|
6
|
+
"id": "steps",
|
|
7
7
|
"name": "Default",
|
|
8
8
|
"template": "<nve-steps behavior-select>\n <nve-steps-item status=\"success\">Step 1</nve-steps-item>\n <nve-steps-item status=\"danger\">Step 2</nve-steps-item>\n <nve-steps-item selected>Step 3</nve-steps-item>\n <nve-steps-item status=\"pending\">Step 4</nve-steps-item>\n <nve-steps-item disabled>Disabled</nve-steps-item>\n</nve-steps>\n",
|
|
9
9
|
"summary": "Interactive step indicator with status colors for multi-step workflows. Use for wizards, onboarding flows, or process tracking where users can navigate between steps.",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"tags": []
|
|
13
13
|
},
|
|
14
14
|
{
|
|
15
|
-
"id": "
|
|
15
|
+
"id": "steps-condensed",
|
|
16
16
|
"name": "Condensed",
|
|
17
17
|
"template": "<nve-steps behavior-select container=\"condensed\">\n <nve-steps-item status=\"success\">Step 1</nve-steps-item>\n <nve-steps-item status=\"danger\">Step 2</nve-steps-item>\n <nve-steps-item selected>Step 3</nve-steps-item>\n <nve-steps-item status=\"pending\">Step 4</nve-steps-item>\n <nve-steps-item disabled>Disabled</nve-steps-item>\n</nve-steps>\n",
|
|
18
18
|
"summary": "Condensed step indicator with reduced visual weight. Ideal for space-constrained layouts or secondary navigation where steps need less prominence.",
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"tags": []
|
|
22
22
|
},
|
|
23
23
|
{
|
|
24
|
-
"id": "
|
|
24
|
+
"id": "steps-vertical-steps",
|
|
25
25
|
"name": "VerticalSteps",
|
|
26
26
|
"template": "<nve-steps vertical behavior-select style=\"width: 150px\">\n <nve-steps-item selected>Step 1</nve-steps-item>\n <nve-steps-item>Step 2</nve-steps-item>\n <nve-steps-item>Step 3</nve-steps-item>\n <nve-steps-item disabled>Disabled</nve-steps-item>\n <nve-steps-item>Step 5</nve-steps-item>\n</nve-steps>\n",
|
|
27
27
|
"summary": "Vertical step layout for sidebar navigation or tall containers. Use when horizontal space constrains layout or steps require longer labels.",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"tags": []
|
|
31
31
|
},
|
|
32
32
|
{
|
|
33
|
-
"id": "
|
|
33
|
+
"id": "steps-vertical-condensed-steps",
|
|
34
34
|
"name": "VerticalCondensedSteps",
|
|
35
35
|
"template": "<nve-steps vertical container=\"condensed\" behavior-select>\n <nve-steps-item selected>Step 1</nve-steps-item>\n <nve-steps-item>Step 2</nve-steps-item>\n <nve-steps-item>Step 3</nve-steps-item>\n <nve-steps-item disabled>Disabled</nve-steps-item>\n <nve-steps-item>Step 5</nve-steps-item>\n</nve-steps>\n",
|
|
36
36
|
"summary": "Vertical condensed steps combining both layout options. Ideal for dense sidebar navigation with minimal visual footprint.",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"tags": []
|
|
40
40
|
},
|
|
41
41
|
{
|
|
42
|
-
"id": "
|
|
42
|
+
"id": "steps-stateless-steps",
|
|
43
43
|
"name": "StatelessSteps",
|
|
44
44
|
"template": "<nve-steps>\n <nve-steps-item selected>Step 1</nve-steps-item>\n <nve-steps-item>Step 2</nve-steps-item>\n <nve-steps-item>Step 3</nve-steps-item>\n <nve-steps-item>Step 4</nve-steps-item>\n <nve-steps-item disabled>Disabled</nve-steps-item>\n</nve-steps>\n",
|
|
45
45
|
"summary": "Display-only steps without interactive selection behavior. Use for showing progress indicators where external logic controls step navigation.",
|
package/dist/steps/steps2.js
CHANGED
|
@@ -23,7 +23,7 @@ var v = class extends r {
|
|
|
23
23
|
static {
|
|
24
24
|
this.metadata = {
|
|
25
25
|
tag: "nve-steps-item",
|
|
26
|
-
version: "0.0.
|
|
26
|
+
version: "0.0.12",
|
|
27
27
|
parents: ["nve-steps"]
|
|
28
28
|
};
|
|
29
29
|
}
|
|
@@ -67,7 +67,7 @@ var y = class extends f {
|
|
|
67
67
|
static {
|
|
68
68
|
this.metadata = {
|
|
69
69
|
tag: "nve-steps",
|
|
70
|
-
version: "0.0.
|
|
70
|
+
version: "0.0.12",
|
|
71
71
|
children: ["nve-steps-item"]
|
|
72
72
|
};
|
|
73
73
|
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"entrypoint": "@nvidia-elements/core/switch/switch.examples.json",
|
|
4
4
|
"items": [
|
|
5
5
|
{
|
|
6
|
-
"id": "
|
|
6
|
+
"id": "switch",
|
|
7
7
|
"name": "Default",
|
|
8
8
|
"template": "<nve-switch>\n <label>label</label>\n <input type=\"checkbox\" />\n</nve-switch>\n",
|
|
9
9
|
"summary": "Basic toggle switch for binary on/off controls and feature activation.",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"tags": []
|
|
13
13
|
},
|
|
14
14
|
{
|
|
15
|
-
"id": "
|
|
15
|
+
"id": "switch-size",
|
|
16
16
|
"name": "Size",
|
|
17
17
|
"template": "<nve-switch\n style=\"\n --width: var(--nve-ref-size-800);\n --height: var(--nve-ref-size-400);\n --anchor-width: calc(var(--nve-ref-size-200) + var(--nve-ref-size-50));\n --anchor-height: calc(var(--nve-ref-size-200) + var(--nve-ref-size-50));\n \"\n>\n <label>label</label>\n <input type=\"checkbox\" />\n</nve-switch>\n",
|
|
18
18
|
"summary": "Size variants of toggle switches use custom CSS properties.",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
]
|
|
24
24
|
},
|
|
25
25
|
{
|
|
26
|
-
"id": "
|
|
26
|
+
"id": "switch-states",
|
|
27
27
|
"name": "States",
|
|
28
28
|
"template": "<div nve-layout=\"column gap:lg align:stretch\">\n <nve-switch>\n <label>label</label>\n <input type=\"checkbox\" />\n <nve-control-message>message</nve-control-message>\n </nve-switch>\n <nve-switch>\n <label>disabled</label>\n <input type=\"checkbox\" disabled />\n <nve-control-message>message</nve-control-message>\n </nve-switch>\n <nve-switch>\n <label>success</label>\n <input type=\"checkbox\" />\n <nve-control-message status=\"success\">message</nve-control-message>\n </nve-switch>\n <nve-switch>\n <label>error</label>\n <input type=\"checkbox\" />\n <nve-control-message status=\"error\">message</nve-control-message>\n </nve-switch>\n</div>\n",
|
|
29
29
|
"summary": "Toggle switches with different states including default, disabled, success, and error with control messages.",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"tags": []
|
|
33
33
|
},
|
|
34
34
|
{
|
|
35
|
-
"id": "
|
|
35
|
+
"id": "switch-vertical-group",
|
|
36
36
|
"name": "VerticalGroup",
|
|
37
37
|
"template": "<div nve-layout=\"column gap:lg align:stretch\">\n <nve-switch-group>\n <label>label</label>\n <nve-switch>\n <label>switch 1</label>\n <input type=\"checkbox\" checked />\n </nve-switch>\n <nve-switch>\n <label>switch 2</label>\n <input type=\"checkbox\" />\n </nve-switch>\n <nve-switch>\n <label>switch 3</label>\n <input type=\"checkbox\" />\n </nve-switch>\n <nve-control-message>message</nve-control-message>\n </nve-switch-group>\n <nve-switch-group>\n <label>disabled</label>\n <nve-switch>\n <label>switch 1</label>\n <input type=\"checkbox\" checked disabled />\n </nve-switch>\n <nve-switch>\n <label>switch 2</label>\n <input type=\"checkbox\" disabled />\n </nve-switch>\n <nve-switch>\n <label>switch 3</label>\n <input type=\"checkbox\" disabled />\n </nve-switch>\n <nve-control-message>disabled message</nve-control-message>\n </nve-switch-group>\n <nve-switch-group>\n <label>success</label>\n <nve-switch>\n <label>switch 1</label>\n <input type=\"checkbox\" checked />\n </nve-switch>\n <nve-switch>\n <label>switch 2</label>\n <input type=\"checkbox\" />\n </nve-switch>\n <nve-switch>\n <label>switch 3</label>\n <input type=\"checkbox\" />\n </nve-switch>\n <nve-control-message status=\"success\">success message</nve-control-message>\n </nve-switch-group>\n <nve-switch-group>\n <label>error</label>\n <nve-switch>\n <label>switch 1</label>\n <input type=\"checkbox\" checked />\n </nve-switch>\n <nve-switch>\n <label>switch 2</label>\n <input type=\"checkbox\" />\n </nve-switch>\n <nve-switch>\n <label>switch 3</label>\n <input type=\"checkbox\" />\n </nve-switch>\n <nve-control-message status=\"error\">error message</nve-control-message>\n </nve-switch-group>\n</div>\n",
|
|
38
38
|
"summary": "Switch groups with vertical layout for many related toggles stacked in a column with validation states.",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"tags": []
|
|
42
42
|
},
|
|
43
43
|
{
|
|
44
|
-
"id": "
|
|
44
|
+
"id": "switch-vertical-inline-group",
|
|
45
45
|
"name": "VerticalInlineGroup",
|
|
46
46
|
"template": "<div nve-layout=\"column gap:lg align:stretch\">\n <nve-switch-group layout=\"vertical-inline\">\n <label>label</label>\n <nve-switch>\n <label>switch 1</label>\n <input type=\"checkbox\" checked />\n </nve-switch>\n <nve-switch>\n <label>switch 2</label>\n <input type=\"checkbox\" />\n </nve-switch>\n <nve-switch>\n <label>switch 3</label>\n <input type=\"checkbox\" />\n </nve-switch>\n <nve-control-message>message</nve-control-message>\n </nve-switch-group>\n <nve-switch-group layout=\"vertical-inline\">\n <label>disabled</label>\n <nve-switch>\n <label>switch 1</label>\n <input type=\"checkbox\" checked disabled />\n </nve-switch>\n <nve-switch>\n <label>switch 2</label>\n <input type=\"checkbox\" disabled />\n </nve-switch>\n <nve-switch>\n <label>switch 3</label>\n <input type=\"checkbox\" disabled />\n </nve-switch>\n <nve-control-message>disabled message</nve-control-message>\n </nve-switch-group>\n <nve-switch-group layout=\"vertical-inline\">\n <label>success</label>\n <nve-switch>\n <label>switch 1</label>\n <input type=\"checkbox\" checked />\n </nve-switch>\n <nve-switch>\n <label>switch 2</label>\n <input type=\"checkbox\" />\n </nve-switch>\n <nve-switch>\n <label>switch 3</label>\n <input type=\"checkbox\" />\n </nve-switch>\n <nve-control-message status=\"success\">success message</nve-control-message>\n </nve-switch-group>\n <nve-switch-group layout=\"vertical-inline\">\n <label>error</label>\n <nve-switch>\n <label>switch 1</label>\n <input type=\"checkbox\" checked />\n </nve-switch>\n <nve-switch>\n <label>switch 2</label>\n <input type=\"checkbox\" />\n </nve-switch>\n <nve-switch>\n <label>switch 3</label>\n <input type=\"checkbox\" />\n </nve-switch>\n <nve-control-message status=\"error\">error message</nve-control-message>\n </nve-switch-group>\n</div>\n",
|
|
47
47
|
"summary": "Switch groups with vertical inline layout for compact vertical stacking with inline label positioning.",
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
]
|
|
53
53
|
},
|
|
54
54
|
{
|
|
55
|
-
"id": "
|
|
55
|
+
"id": "switch-horizontal-group",
|
|
56
56
|
"name": "HorizontalGroup",
|
|
57
57
|
"template": "<div nve-layout=\"column gap:lg align:stretch\">\n <nve-switch-group layout=\"horizontal\">\n <label>label</label>\n <nve-switch>\n <label>switch 1</label>\n <input type=\"checkbox\" checked />\n </nve-switch>\n <nve-switch>\n <label>switch 2</label>\n <input type=\"checkbox\" />\n </nve-switch>\n <nve-switch>\n <label>switch 3</label>\n <input type=\"checkbox\" />\n </nve-switch>\n <nve-control-message>message</nve-control-message>\n </nve-switch-group>\n <nve-switch-group layout=\"horizontal\">\n <label>disabled</label>\n <nve-switch>\n <label>switch 1</label>\n <input type=\"checkbox\" checked disabled />\n </nve-switch>\n <nve-switch>\n <label>switch 2</label>\n <input type=\"checkbox\" disabled />\n </nve-switch>\n <nve-switch>\n <label>switch 3</label>\n <input type=\"checkbox\" disabled />\n </nve-switch>\n <nve-control-message>disabled message</nve-control-message>\n </nve-switch-group>\n <nve-switch-group layout=\"horizontal\">\n <label>success</label>\n <nve-switch>\n <label>switch 1</label>\n <input type=\"checkbox\" checked />\n </nve-switch>\n <nve-switch>\n <label>switch 2</label>\n <input type=\"checkbox\" />\n </nve-switch>\n <nve-switch>\n <label>switch 3</label>\n <input type=\"checkbox\" />\n </nve-switch>\n <nve-control-message status=\"success\">success message</nve-control-message>\n </nve-switch-group>\n <nve-switch-group layout=\"horizontal\">\n <label>error</label>\n <nve-switch>\n <label>switch 1</label>\n <input type=\"checkbox\" checked />\n </nve-switch>\n <nve-switch>\n <label>switch 2</label>\n <input type=\"checkbox\" />\n </nve-switch>\n <nve-switch>\n <label>switch 3</label>\n <input type=\"checkbox\" />\n </nve-switch>\n <nve-control-message status=\"error\">error message</nve-control-message>\n </nve-switch-group>\n</div>\n",
|
|
58
58
|
"summary": "Switch groups with horizontal layout for many toggles arranged in a row, ideal for limited options.",
|
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
]
|
|
64
64
|
},
|
|
65
65
|
{
|
|
66
|
-
"id": "
|
|
66
|
+
"id": "switch-horizontal-inline-group",
|
|
67
67
|
"name": "HorizontalInlineGroup",
|
|
68
68
|
"template": "<div nve-layout=\"column gap:lg align:stretch\">\n <nve-switch-group layout=\"horizontal-inline\">\n <label>label</label>\n <nve-switch>\n <label>switch 1</label>\n <input type=\"checkbox\" checked />\n </nve-switch>\n <nve-switch>\n <label>switch 2</label>\n <input type=\"checkbox\" />\n </nve-switch>\n <nve-switch>\n <label>switch 3</label>\n <input type=\"checkbox\" />\n </nve-switch>\n <nve-control-message>message</nve-control-message>\n </nve-switch-group>\n <nve-switch-group layout=\"horizontal-inline\">\n <label>disabled</label>\n <nve-switch>\n <label>switch 1</label>\n <input type=\"checkbox\" checked disabled />\n </nve-switch>\n <nve-switch>\n <label>switch 2</label>\n <input type=\"checkbox\" disabled />\n </nve-switch>\n <nve-switch>\n <label>switch 3</label>\n <input type=\"checkbox\" disabled />\n </nve-switch>\n <nve-control-message>disabled message</nve-control-message>\n </nve-switch-group>\n <nve-switch-group layout=\"horizontal-inline\">\n <label>success</label>\n <nve-switch>\n <label>switch 1</label>\n <input type=\"checkbox\" checked />\n </nve-switch>\n <nve-switch>\n <label>switch 2</label>\n <input type=\"checkbox\" />\n </nve-switch>\n <nve-switch>\n <label>switch 3</label>\n <input type=\"checkbox\" />\n </nve-switch>\n <nve-control-message status=\"success\">success message</nve-control-message>\n </nve-switch-group>\n <nve-switch-group layout=\"horizontal-inline\">\n <label>error</label>\n <nve-switch>\n <label>switch 1</label>\n <input type=\"checkbox\" checked />\n </nve-switch>\n <nve-switch>\n <label>switch 2</label>\n <input type=\"checkbox\" />\n </nve-switch>\n <nve-switch>\n <label>switch 3</label>\n <input type=\"checkbox\" />\n </nve-switch>\n <nve-control-message status=\"error\">error message</nve-control-message>\n </nve-switch-group>\n</div>\n",
|
|
69
69
|
"summary": "Switch groups with horizontal inline layout for space-efficient horizontal arrangement with inline labels.",
|
package/dist/switch/switch2.js
CHANGED
package/dist/tabs/tabs-group2.js
CHANGED
|
@@ -23,7 +23,7 @@ var m, h = class extends l {
|
|
|
23
23
|
static {
|
|
24
24
|
this.metadata = {
|
|
25
25
|
tag: "nve-tabs-group",
|
|
26
|
-
version: "0.0.
|
|
26
|
+
version: "0.0.12",
|
|
27
27
|
children: ["nve-tabs"]
|
|
28
28
|
};
|
|
29
29
|
}
|
|
@@ -71,7 +71,7 @@ var m, h = class extends l {
|
|
|
71
71
|
let t = e.source?.value;
|
|
72
72
|
if (typeof t != "string" || !t.length) return;
|
|
73
73
|
let n = this.#d(), r = n.find((e) => this.#p(e) && e.value === t);
|
|
74
|
-
r && this.#o(n, r, !0);
|
|
74
|
+
r && this.#o(n, r, { emitEvent: !0 });
|
|
75
75
|
};
|
|
76
76
|
#i() {
|
|
77
77
|
this.#e?.disconnect();
|
|
@@ -84,13 +84,16 @@ var m, h = class extends l {
|
|
|
84
84
|
e.forEach((e) => e.selected = !1), this.#s(t, "");
|
|
85
85
|
return;
|
|
86
86
|
}
|
|
87
|
-
this.#o(e, r,
|
|
87
|
+
this.#o(e, r, {
|
|
88
|
+
emitEvent: !1,
|
|
89
|
+
nextPanelValues: t
|
|
90
|
+
});
|
|
88
91
|
}
|
|
89
|
-
#o(e, t, r
|
|
90
|
-
let a = this.selectedValue !== t.value || !t.selected || e.some((e) => e !== t && e.selected);
|
|
92
|
+
#o(e, t, r) {
|
|
93
|
+
let { emitEvent: i } = r, a = r.nextPanelValues ?? n(e.map((e) => e.value)), o = this.selectedValue !== t.value || !t.selected || e.some((e) => e !== t && e.selected);
|
|
91
94
|
e.forEach((e) => {
|
|
92
95
|
e.selected = e === t;
|
|
93
|
-
}), this.#s(
|
|
96
|
+
}), this.#s(a, t.value), i && o && this.dispatchEvent(new CustomEvent("select", {
|
|
94
97
|
bubbles: !0,
|
|
95
98
|
composed: !0,
|
|
96
99
|
detail: { value: t.value }
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tabs-group2.js","names":["#handleDefaultSlotChange","#handlePanelSlotChange","#handleCommand","#syncFromTabs","#tabsObserver","#observeTabs","#syncPanels","#getTabItems","#isSelectableTab","#setActiveTab","#getTabsElement","#resolveSelectedTab","#commitState","#getPanelSlots","#syncPanelSlot"],"sources":["../../src/tabs/tabs-group.ts"],"sourcesContent":["// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nimport type { PropertyValues } from 'lit';\nimport { html, LitElement } from 'lit';\nimport { property } from 'lit/decorators/property.js';\nimport { queryAssignedElements } from 'lit/decorators/query-assigned-elements.js';\nimport { state } from 'lit/decorators/state.js';\nimport {\n attachInternals,\n audit,\n generateId,\n sameOrderedStringArray,\n uniqueNonEmptyStrings,\n useStyles\n} from '@nvidia-elements/core/internal';\nimport { Tabs, type TabsItem } from './tabs.js';\nimport styles from './tabs-group.css?inline';\n\n/** Invoker command source for `--toggle` (e.g. `nve-tabs-item` with `value`). */\ntype TabsGroupCommandSource = HTMLElement & {\n disabled?: boolean;\n value?: string | null;\n};\n\n/** `command` event from Invoker Commands; `source` is the control that fired. */\ntype TabsGroupCommandEvent = Event & {\n command?: string;\n source?: TabsGroupCommandSource | null;\n};\n\n/** Payload for the composed `select` event when the active tab value changes via command. */\ntype TabsGroupSelectDetail = { value: string };\n\n/** Arranges the tab strip and slot-matched panels: stacked column (`top`), or sidebar row with tabs at inline-start (`start`) or inline-end (`end`). */\nexport type TabsGroupAlignment = 'top' | 'start' | 'end';\n\n/**\n * @element nve-tabs-group\n * @description Coordinates tabs with matching panel content using Invoker Commands and slot-matched panels.\n * @since 1.67.0\n * @entrypoint \\@nvidia-elements/core/tabs\n * @command --toggle - Select the matching tab and reveal the panel whose slot matches the invoker value.\n * @event select - Dispatched when the selected tab value changes after an invoker `--toggle` updates selection\n * @slot - Default slot for a single nve-tabs element. Do not use behavior-select on nve-tabs when using this group.\n * @slot {value} - Named panel content where the slot name matches a nve-tabs-item value.\n * @cssprop --padding\n * @aria https://www.w3.org/WAI/ARIA/apg/patterns/tabs/\n * @responsive false\n */\n@audit()\nexport class TabsGroup extends LitElement {\n static styles = useStyles([styles]);\n\n static readonly metadata = {\n tag: 'nve-tabs-group',\n version: '0.0.0',\n children: ['nve-tabs']\n };\n\n /** Options for observing the slotted `nve-tabs` subtree (tab list / item attribute changes). */\n protected static readonly subtreeObserverInit = {\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: ['disabled', 'id', 'selected', 'value']\n } as const satisfies MutationObserverInit;\n\n @queryAssignedElements({ flatten: true }) private defaultSlotElements!: HTMLElement[];\n\n /**\n * Arranges the tab strip relative to slot-matched panels: stacked column (`top`), or sidebar row with tabs at\n * inline-start (`start`) or inline-end (`end`) beside the panel region.\n */\n @property({ type: String, reflect: true }) alignment: TabsGroupAlignment = 'top';\n\n @state() private panelValues: string[] = [];\n\n @state() private selectedValue = '';\n\n /** @private */\n declare _internals: ElementInternals;\n\n #tabsObserver?: MutationObserver;\n\n /**\n * Renders the default slot (single `nve-tabs`) plus one named `<slot name={value}>` per distinct selectable\n * `nve-tabs-item` value. `#syncPanelSlot` applies panel visibility and ARIA from `selectedValue`.\n */\n render() {\n return html`\n <div internal-host>\n <slot @slotchange=${this.#handleDefaultSlotChange}></slot>\n ${this.panelValues.map(value => html`<slot name=${value} @slotchange=${this.#handlePanelSlotChange}></slot>`)}\n </div>\n `;\n }\n\n // --- Lifecycle & command ---\n\n connectedCallback() {\n super.connectedCallback();\n attachInternals(this);\n this._internals.role = 'group';\n this.addEventListener('command', this.#handleCommand as EventListener);\n }\n\n firstUpdated() {\n void this.updateComplete.then(() => {\n if (!this.isConnected) {\n return;\n }\n\n this.#syncFromTabs();\n });\n }\n\n disconnectedCallback() {\n super.disconnectedCallback();\n this.removeEventListener('command', this.#handleCommand as EventListener);\n this.#tabsObserver?.disconnect();\n }\n\n updated(changedProperties: PropertyValues<this>) {\n super.updated(changedProperties);\n\n if (!this.#tabsObserver) {\n this.#observeTabs();\n }\n\n // `@state()` fields are not in `PropertyValues<this>` keys; cast for membership checks.\n const props = changedProperties as ReadonlyMap<PropertyKey, unknown>;\n if (props.has('panelValues') || props.has('selectedValue')) {\n this.#syncPanels();\n }\n }\n\n #handleDefaultSlotChange = (): void => {\n this.#observeTabs();\n this.#syncFromTabs();\n };\n\n #handlePanelSlotChange = (): void => {\n this.#syncPanels();\n };\n\n /**\n * Handles Invoker `--toggle` on a tab item: selects the matching `nve-tabs-item` and syncs panels.\n * Ignores non-toggle commands and invokers without a non-empty string `value`.\n */\n #handleCommand = (event: TabsGroupCommandEvent): void => {\n if (event.command !== '--toggle') {\n return;\n }\n\n const value = event.source?.value;\n if (typeof value !== 'string' || !value.length) {\n return;\n }\n\n const tabItems = this.#getTabItems();\n const tabItem = tabItems.find(item => this.#isSelectableTab(item) && item.value === value);\n if (!tabItem) {\n return;\n }\n\n this.#setActiveTab(tabItems, tabItem, true);\n };\n\n // --- Tab strip sync (tabs → state) ---\n\n /** Attaches a single `MutationObserver` on the slotted `nve-tabs` element to mirror tab list changes into state. */\n #observeTabs(): void {\n this.#tabsObserver?.disconnect();\n\n const tabs = this.#getTabsElement();\n if (!tabs) {\n return;\n }\n\n this.#tabsObserver = new MutationObserver(() => this.#syncFromTabs());\n this.#tabsObserver.observe(tabs, TabsGroup.subtreeObserverInit);\n }\n\n /**\n * Reads the current tab items: derives ordered `panelValues` for render, resolves which tab should be active,\n * and commits selection. Called on slot change, subtree mutations, and after mount.\n */\n #syncFromTabs(): void {\n const tabItems = this.#getTabItems();\n const nextPanelValues = uniqueNonEmptyStrings(tabItems.map(item => item.value));\n\n const selectedTab = this.#resolveSelectedTab(tabItems);\n\n if (!selectedTab) {\n tabItems.forEach(item => (item.selected = false));\n this.#commitState(nextPanelValues, '');\n return;\n }\n\n this.#setActiveTab(tabItems, selectedTab, false, nextPanelValues);\n }\n\n /**\n * Sets exactly one selected tab, updates `panelValues` / `selectedValue`, and optionally dispatches `select`.\n *\n * @param emitEvent - When true (command path), dispatches `select` if selection actually changed.\n */\n #setActiveTab(\n tabItems: TabsItem[],\n nextTab: TabsItem,\n emitEvent: boolean,\n nextPanelValues: string[] = uniqueNonEmptyStrings(tabItems.map(item => item.value))\n ): void {\n // True when the effective selection differs from the prior committed state (value, flags, or multi-select).\n // `select` is only dispatched when both `emitEvent` (invoker/command path) and `changed` are true.\n const changed =\n this.selectedValue !== nextTab.value ||\n !nextTab.selected ||\n tabItems.some(item => item !== nextTab && item.selected);\n\n tabItems.forEach(item => {\n item.selected = item === nextTab;\n });\n\n this.#commitState(nextPanelValues, nextTab.value);\n\n if (emitEvent && changed) {\n this.dispatchEvent(\n new CustomEvent<TabsGroupSelectDetail>('select', {\n bubbles: true,\n composed: true,\n detail: { value: nextTab.value }\n })\n );\n }\n }\n\n /** Updates reactive state for panel slot names and the active tab value without touching the tab items. */\n #commitState(nextPanelValues: string[], nextSelectedValue: string): void {\n if (!sameOrderedStringArray(this.panelValues, nextPanelValues)) {\n this.panelValues = nextPanelValues;\n }\n\n if (this.selectedValue !== nextSelectedValue) {\n this.selectedValue = nextSelectedValue;\n }\n }\n\n // --- Panel sync (state → panels & ARIA) ---\n\n /** For each named panel slot, wires `hidden` and tab↔panel ARIA ids to match `selectedValue`. */\n #syncPanels(): void {\n const tabItems = this.#getTabItems();\n const tabMap = new Map(\n tabItems.filter(item => this.#isSelectableTab(item)).map(item => [item.value, item] satisfies [string, TabsItem])\n );\n\n this.#getPanelSlots().forEach(slot => {\n this.#syncPanelSlot(slot, tabMap);\n });\n }\n\n /**\n * If no selectable tab exists for `slot.name`, hides all assigned nodes. Otherwise shows only the panel(s)\n * for the active value and assigns `role=\"tabpanel\"` / `aria-labelledby` when missing.\n */\n #syncPanelSlot(slot: HTMLSlotElement, tabMap: ReadonlyMap<string, TabsItem>): void {\n const tabItem = tabMap.get(slot.name);\n const panels = slot.assignedElements({ flatten: true }) as HTMLElement[];\n\n if (!tabItem) {\n panels.forEach(panel => {\n panel.hidden = true;\n });\n return;\n }\n\n tabItem.id ||= generateId();\n\n panels.forEach((panel, index) => {\n panel.id ||= generateId();\n\n if (!tabItem.hasAttribute('aria-controls') && index === 0) {\n tabItem.setAttribute('aria-controls', panel.id);\n }\n\n if (!panel.hasAttribute('aria-labelledby')) {\n panel.setAttribute('aria-labelledby', tabItem.id);\n }\n\n if (!panel.hasAttribute('role')) {\n panel.setAttribute('role', 'tabpanel');\n }\n\n const isActive = slot.name === this.selectedValue;\n panel.hidden = !isActive;\n });\n }\n\n // --- DOM queries ---\n\n /** Resolves the single slotted `nve-tabs` (default slot), with a light-DOM fallback for edge timing. */\n #getTabsElement(): Tabs | undefined {\n const el =\n this.defaultSlotElements.find(element => element.localName === Tabs.metadata.tag) ??\n this.querySelector(Tabs.metadata.tag);\n return el instanceof Tabs ? el : undefined;\n }\n\n #getTabItems(): TabsItem[] {\n return Array.from(this.#getTabsElement()?.querySelectorAll<TabsItem>('nve-tabs-item') ?? []);\n }\n\n #getPanelSlots(): HTMLSlotElement[] {\n return Array.from(this.renderRoot.querySelectorAll<HTMLSlotElement>('slot[name]'));\n }\n\n /** Selectable tabs have a non-empty `value` and are not `disabled`. */\n #isSelectableTab(tabItem: TabsItem): tabItem is TabsItem & { value: string } {\n return typeof tabItem.value === 'string' && tabItem.value.length > 0 && !tabItem.disabled;\n }\n\n /** Prefer the selectable tab that is already selected; otherwise the first selectable tab. */\n #resolveSelectedTab(tabItems: readonly TabsItem[]): TabsItem | undefined {\n return (\n tabItems.find(item => this.#isSelectableTab(item) && item.selected) ??\n tabItems.find(item => this.#isSelectableTab(item))\n );\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"tabs-group2.js","names":["#handleDefaultSlotChange","#handlePanelSlotChange","#handleCommand","#syncFromTabs","#tabsObserver","#observeTabs","#syncPanels","#getTabItems","#isSelectableTab","#setActiveTab","#getTabsElement","#resolveSelectedTab","#commitState","#getPanelSlots","#syncPanelSlot"],"sources":["../../src/tabs/tabs-group.ts"],"sourcesContent":["// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nimport type { PropertyValues } from 'lit';\nimport { html, LitElement } from 'lit';\nimport { property } from 'lit/decorators/property.js';\nimport { queryAssignedElements } from 'lit/decorators/query-assigned-elements.js';\nimport { state } from 'lit/decorators/state.js';\nimport {\n attachInternals,\n audit,\n generateId,\n sameOrderedStringArray,\n uniqueNonEmptyStrings,\n useStyles\n} from '@nvidia-elements/core/internal';\nimport { Tabs, type TabsItem } from './tabs.js';\nimport styles from './tabs-group.css?inline';\n\n/** Invoker command source for `--toggle` (e.g. `nve-tabs-item` with `value`). */\ntype TabsGroupCommandSource = HTMLElement & {\n disabled?: boolean;\n value?: string | null;\n};\n\n/** `command` event from Invoker Commands; `source` is the control that fired. */\ntype TabsGroupCommandEvent = Event & {\n command?: string;\n source?: TabsGroupCommandSource | null;\n};\n\n/** Payload for the composed `select` event when the active tab value changes via command. */\ntype TabsGroupSelectDetail = { value: string };\n\n/** Arranges the tab strip and slot-matched panels: stacked column (`top`), or sidebar row with tabs at inline-start (`start`) or inline-end (`end`). */\nexport type TabsGroupAlignment = 'top' | 'start' | 'end';\n\n/**\n * @element nve-tabs-group\n * @description Coordinates tabs with matching panel content using Invoker Commands and slot-matched panels.\n * @since 1.67.0\n * @entrypoint \\@nvidia-elements/core/tabs\n * @command --toggle - Select the matching tab and reveal the panel whose slot matches the invoker value.\n * @event select - Dispatched when the selected tab value changes after an invoker `--toggle` updates selection\n * @slot - Default slot for a single nve-tabs element. Do not use behavior-select on nve-tabs when using this group.\n * @slot {value} - Named panel content where the slot name matches a nve-tabs-item value.\n * @cssprop --padding\n * @aria https://www.w3.org/WAI/ARIA/apg/patterns/tabs/\n * @responsive false\n */\n@audit()\nexport class TabsGroup extends LitElement {\n static styles = useStyles([styles]);\n\n static readonly metadata = {\n tag: 'nve-tabs-group',\n version: '0.0.0',\n children: ['nve-tabs']\n };\n\n /** Options for observing the slotted `nve-tabs` subtree (tab list / item attribute changes). */\n protected static readonly subtreeObserverInit = {\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: ['disabled', 'id', 'selected', 'value']\n } as const satisfies MutationObserverInit;\n\n @queryAssignedElements({ flatten: true }) private defaultSlotElements!: HTMLElement[];\n\n /**\n * Arranges the tab strip relative to slot-matched panels: stacked column (`top`), or sidebar row with tabs at\n * inline-start (`start`) or inline-end (`end`) beside the panel region.\n */\n @property({ type: String, reflect: true }) alignment: TabsGroupAlignment = 'top';\n\n @state() private panelValues: string[] = [];\n\n @state() private selectedValue = '';\n\n /** @private */\n declare _internals: ElementInternals;\n\n #tabsObserver?: MutationObserver;\n\n /**\n * Renders the default slot (single `nve-tabs`) plus one named `<slot name={value}>` per distinct selectable\n * `nve-tabs-item` value. `#syncPanelSlot` applies panel visibility and ARIA from `selectedValue`.\n */\n render() {\n return html`\n <div internal-host>\n <slot @slotchange=${this.#handleDefaultSlotChange}></slot>\n ${this.panelValues.map(value => html`<slot name=${value} @slotchange=${this.#handlePanelSlotChange}></slot>`)}\n </div>\n `;\n }\n\n // --- Lifecycle & command ---\n\n connectedCallback() {\n super.connectedCallback();\n attachInternals(this);\n this._internals.role = 'group';\n this.addEventListener('command', this.#handleCommand as EventListener);\n }\n\n firstUpdated() {\n void this.updateComplete.then(() => {\n if (!this.isConnected) {\n return;\n }\n\n this.#syncFromTabs();\n });\n }\n\n disconnectedCallback() {\n super.disconnectedCallback();\n this.removeEventListener('command', this.#handleCommand as EventListener);\n this.#tabsObserver?.disconnect();\n }\n\n updated(changedProperties: PropertyValues<this>) {\n super.updated(changedProperties);\n\n if (!this.#tabsObserver) {\n this.#observeTabs();\n }\n\n // `@state()` fields are not in `PropertyValues<this>` keys; cast for membership checks.\n const props = changedProperties as ReadonlyMap<PropertyKey, unknown>;\n if (props.has('panelValues') || props.has('selectedValue')) {\n this.#syncPanels();\n }\n }\n\n #handleDefaultSlotChange = (): void => {\n this.#observeTabs();\n this.#syncFromTabs();\n };\n\n #handlePanelSlotChange = (): void => {\n this.#syncPanels();\n };\n\n /**\n * Handles Invoker `--toggle` on a tab item: selects the matching `nve-tabs-item` and syncs panels.\n * Ignores non-toggle commands and invokers without a non-empty string `value`.\n */\n #handleCommand = (event: TabsGroupCommandEvent): void => {\n if (event.command !== '--toggle') {\n return;\n }\n\n const value = event.source?.value;\n if (typeof value !== 'string' || !value.length) {\n return;\n }\n\n const tabItems = this.#getTabItems();\n const tabItem = tabItems.find(item => this.#isSelectableTab(item) && item.value === value);\n if (!tabItem) {\n return;\n }\n\n this.#setActiveTab(tabItems, tabItem, { emitEvent: true });\n };\n\n // --- Tab strip sync (tabs → state) ---\n\n /** Attaches a single `MutationObserver` on the slotted `nve-tabs` element to mirror tab list changes into state. */\n #observeTabs(): void {\n this.#tabsObserver?.disconnect();\n\n const tabs = this.#getTabsElement();\n if (!tabs) {\n return;\n }\n\n this.#tabsObserver = new MutationObserver(() => this.#syncFromTabs());\n this.#tabsObserver.observe(tabs, TabsGroup.subtreeObserverInit);\n }\n\n /**\n * Reads the current tab items: derives ordered `panelValues` for render, resolves which tab should be active,\n * and commits selection. Called on slot change, subtree mutations, and after mount.\n */\n #syncFromTabs(): void {\n const tabItems = this.#getTabItems();\n const nextPanelValues = uniqueNonEmptyStrings(tabItems.map(item => item.value));\n\n const selectedTab = this.#resolveSelectedTab(tabItems);\n\n if (!selectedTab) {\n tabItems.forEach(item => (item.selected = false));\n this.#commitState(nextPanelValues, '');\n return;\n }\n\n this.#setActiveTab(tabItems, selectedTab, { emitEvent: false, nextPanelValues });\n }\n\n /**\n * Sets exactly one selected tab, updates `panelValues` / `selectedValue`, and optionally dispatches `select`.\n *\n * @param emitEvent - When true (command path), dispatches `select` if selection actually changed.\n */\n #setActiveTab(\n tabItems: TabsItem[],\n nextTab: TabsItem,\n options: { emitEvent: boolean; nextPanelValues?: string[] }\n ): void {\n const { emitEvent } = options;\n const nextPanelValues = options.nextPanelValues ?? uniqueNonEmptyStrings(tabItems.map(item => item.value));\n // True when the effective selection differs from the prior committed state (value, flags, or multi-select).\n // `select` is only dispatched when both `emitEvent` (invoker/command path) and `changed` are true.\n const changed =\n this.selectedValue !== nextTab.value ||\n !nextTab.selected ||\n tabItems.some(item => item !== nextTab && item.selected);\n\n tabItems.forEach(item => {\n item.selected = item === nextTab;\n });\n\n this.#commitState(nextPanelValues, nextTab.value);\n\n if (emitEvent && changed) {\n this.dispatchEvent(\n new CustomEvent<TabsGroupSelectDetail>('select', {\n bubbles: true,\n composed: true,\n detail: { value: nextTab.value }\n })\n );\n }\n }\n\n /** Updates reactive state for panel slot names and the active tab value without touching the tab items. */\n #commitState(nextPanelValues: string[], nextSelectedValue: string): void {\n if (!sameOrderedStringArray(this.panelValues, nextPanelValues)) {\n this.panelValues = nextPanelValues;\n }\n\n if (this.selectedValue !== nextSelectedValue) {\n this.selectedValue = nextSelectedValue;\n }\n }\n\n // --- Panel sync (state → panels & ARIA) ---\n\n /** For each named panel slot, wires `hidden` and tab↔panel ARIA ids to match `selectedValue`. */\n #syncPanels(): void {\n const tabItems = this.#getTabItems();\n const tabMap = new Map(\n tabItems.filter(item => this.#isSelectableTab(item)).map(item => [item.value, item] satisfies [string, TabsItem])\n );\n\n this.#getPanelSlots().forEach(slot => {\n this.#syncPanelSlot(slot, tabMap);\n });\n }\n\n /**\n * If no selectable tab exists for `slot.name`, hides all assigned nodes. Otherwise shows only the panel(s)\n * for the active value and assigns `role=\"tabpanel\"` / `aria-labelledby` when missing.\n */\n #syncPanelSlot(slot: HTMLSlotElement, tabMap: ReadonlyMap<string, TabsItem>): void {\n const tabItem = tabMap.get(slot.name);\n const panels = slot.assignedElements({ flatten: true }) as HTMLElement[];\n\n if (!tabItem) {\n panels.forEach(panel => {\n panel.hidden = true;\n });\n return;\n }\n\n tabItem.id ||= generateId();\n\n panels.forEach((panel, index) => {\n panel.id ||= generateId();\n\n if (!tabItem.hasAttribute('aria-controls') && index === 0) {\n tabItem.setAttribute('aria-controls', panel.id);\n }\n\n if (!panel.hasAttribute('aria-labelledby')) {\n panel.setAttribute('aria-labelledby', tabItem.id);\n }\n\n if (!panel.hasAttribute('role')) {\n panel.setAttribute('role', 'tabpanel');\n }\n\n const isActive = slot.name === this.selectedValue;\n panel.hidden = !isActive;\n });\n }\n\n // --- DOM queries ---\n\n /** Resolves the single slotted `nve-tabs` (default slot), with a light-DOM fallback for edge timing. */\n #getTabsElement(): Tabs | undefined {\n const el =\n this.defaultSlotElements.find(element => element.localName === Tabs.metadata.tag) ??\n this.querySelector(Tabs.metadata.tag);\n return el instanceof Tabs ? el : undefined;\n }\n\n #getTabItems(): TabsItem[] {\n return Array.from(this.#getTabsElement()?.querySelectorAll<TabsItem>('nve-tabs-item') ?? []);\n }\n\n #getPanelSlots(): HTMLSlotElement[] {\n return Array.from(this.renderRoot.querySelectorAll<HTMLSlotElement>('slot[name]'));\n }\n\n /** Selectable tabs have a non-empty `value` and are not `disabled`. */\n #isSelectableTab(tabItem: TabsItem): tabItem is TabsItem & { value: string } {\n return typeof tabItem.value === 'string' && tabItem.value.length > 0 && !tabItem.disabled;\n }\n\n /** Prefer the selectable tab that is already selected; otherwise the first selectable tab. */\n #resolveSelectedTab(tabItems: readonly TabsItem[]): TabsItem | undefined {\n return (\n tabItems.find(item => this.#isSelectableTab(item) && item.selected) ??\n tabItems.find(item => this.#isSelectableTab(item))\n );\n }\n}\n"],"mappings":"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"}
|