@aceshooting/lyra-ui 0.1.1 → 0.1.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.
Files changed (117) hide show
  1. package/README.md +77 -6
  2. package/custom-elements.json +12015 -0
  3. package/dist/components/chart/bar-chart.d.ts +14 -0
  4. package/dist/components/chart/bar-chart.js +14 -0
  5. package/dist/components/chart/box-plot.d.ts +46 -0
  6. package/dist/components/chart/box-plot.js +145 -0
  7. package/dist/components/chart/box-plot.styles.d.ts +1 -0
  8. package/dist/components/chart/box-plot.styles.js +22 -0
  9. package/dist/components/chart/bubble-chart.d.ts +19 -0
  10. package/dist/components/chart/bubble-chart.js +18 -0
  11. package/dist/components/chart/chart-loader.d.ts +8 -0
  12. package/dist/components/chart/chart-loader.js +26 -0
  13. package/dist/components/chart/chart.d.ts +91 -0
  14. package/dist/components/chart/chart.js +275 -0
  15. package/dist/components/chart/chart.styles.d.ts +1 -0
  16. package/dist/components/chart/chart.styles.js +33 -0
  17. package/dist/components/chart/doughnut-chart.d.ts +15 -0
  18. package/dist/components/chart/doughnut-chart.js +14 -0
  19. package/dist/components/chart/histogram-bin.d.ts +6 -0
  20. package/dist/components/chart/histogram-bin.js +19 -0
  21. package/dist/components/chart/histogram.d.ts +20 -0
  22. package/dist/components/chart/histogram.js +70 -0
  23. package/dist/components/chart/histogram.styles.d.ts +1 -0
  24. package/dist/components/chart/histogram.styles.js +1 -0
  25. package/dist/components/chart/line-chart.d.ts +14 -0
  26. package/dist/components/chart/line-chart.js +14 -0
  27. package/dist/components/chart/pie-chart.d.ts +16 -0
  28. package/dist/components/chart/pie-chart.js +15 -0
  29. package/dist/components/chart/polar-area-chart.d.ts +15 -0
  30. package/dist/components/chart/polar-area-chart.js +14 -0
  31. package/dist/components/chart/radar-chart.d.ts +15 -0
  32. package/dist/components/chart/radar-chart.js +14 -0
  33. package/dist/components/chart/scatter-chart.d.ts +15 -0
  34. package/dist/components/chart/scatter-chart.js +15 -0
  35. package/dist/components/combobox/combobox.d.ts +16 -0
  36. package/dist/components/combobox/combobox.js +113 -6
  37. package/dist/components/combobox/combobox.styles.js +68 -7
  38. package/dist/components/combobox/option.d.ts +2 -2
  39. package/dist/components/combobox/option.js +11 -7
  40. package/dist/components/date-picker/date-input.d.ts +12 -1
  41. package/dist/components/date-picker/date-input.js +68 -6
  42. package/dist/components/date-picker/date-input.styles.js +58 -6
  43. package/dist/components/date-picker/date-picker.js +5 -2
  44. package/dist/components/date-picker/date-picker.styles.js +9 -2
  45. package/dist/components/empty/empty.d.ts +1 -0
  46. package/dist/components/empty/empty.js +14 -2
  47. package/dist/components/export-button/csv.d.ts +10 -0
  48. package/dist/components/export-button/csv.js +28 -0
  49. package/dist/components/export-button/export-button.d.ts +41 -0
  50. package/dist/components/export-button/export-button.js +151 -0
  51. package/dist/components/export-button/export-button.styles.d.ts +1 -0
  52. package/dist/components/export-button/export-button.styles.js +79 -0
  53. package/dist/components/file-input/accept.d.ts +14 -0
  54. package/dist/components/file-input/accept.js +30 -0
  55. package/dist/components/file-input/file-input.d.ts +47 -0
  56. package/dist/components/file-input/file-input.js +182 -0
  57. package/dist/components/file-input/file-input.styles.d.ts +1 -0
  58. package/dist/components/file-input/file-input.styles.js +44 -0
  59. package/dist/components/flag/flag.d.ts +4 -0
  60. package/dist/components/flag/flag.js +24 -1
  61. package/dist/components/flag/flag.styles.js +1 -1
  62. package/dist/components/gauge/gauge.d.ts +29 -0
  63. package/dist/components/gauge/gauge.js +133 -0
  64. package/dist/components/gauge/gauge.styles.d.ts +1 -0
  65. package/dist/components/gauge/gauge.styles.js +60 -0
  66. package/dist/components/graph/graph.d.ts +68 -0
  67. package/dist/components/graph/graph.js +276 -0
  68. package/dist/components/graph/graph.styles.d.ts +1 -0
  69. package/dist/components/graph/graph.styles.js +34 -0
  70. package/dist/components/heatmap/heatmap-scale.d.ts +8 -0
  71. package/dist/components/heatmap/heatmap-scale.js +17 -0
  72. package/dist/components/heatmap/heatmap.d.ts +66 -0
  73. package/dist/components/heatmap/heatmap.js +252 -0
  74. package/dist/components/heatmap/heatmap.styles.d.ts +1 -0
  75. package/dist/components/heatmap/heatmap.styles.js +39 -0
  76. package/dist/components/map/map-loader.d.ts +8 -0
  77. package/dist/components/map/map-loader.js +17 -0
  78. package/dist/components/map/map.d.ts +49 -0
  79. package/dist/components/map/map.js +189 -0
  80. package/dist/components/map/map.styles.d.ts +1 -0
  81. package/dist/components/map/map.styles.js +48 -0
  82. package/dist/components/playback/playback.d.ts +51 -0
  83. package/dist/components/playback/playback.js +146 -0
  84. package/dist/components/playback/playback.styles.d.ts +1 -0
  85. package/dist/components/playback/playback.styles.js +40 -0
  86. package/dist/components/split/split.d.ts +41 -0
  87. package/dist/components/split/split.js +171 -0
  88. package/dist/components/split/split.styles.d.ts +1 -0
  89. package/dist/components/split/split.styles.js +51 -0
  90. package/dist/components/stat/stat.d.ts +9 -0
  91. package/dist/components/stat/stat.js +52 -7
  92. package/dist/components/stat/stat.styles.js +15 -5
  93. package/dist/components/table/table.d.ts +18 -6
  94. package/dist/components/table/table.js +76 -24
  95. package/dist/components/table/table.styles.js +32 -0
  96. package/dist/components/time-range/time-range.d.ts +40 -0
  97. package/dist/components/time-range/time-range.js +219 -0
  98. package/dist/components/time-range/time-range.styles.d.ts +1 -0
  99. package/dist/components/time-range/time-range.styles.js +78 -0
  100. package/dist/components/toast/toast-item.js +10 -2
  101. package/dist/components/toast/toast-item.styles.js +13 -4
  102. package/dist/components/toast/toast.styles.js +0 -1
  103. package/dist/components/tree/tree-node.d.ts +50 -0
  104. package/dist/components/tree/tree-node.js +196 -0
  105. package/dist/components/tree/tree.d.ts +65 -0
  106. package/dist/components/tree/tree.js +227 -0
  107. package/dist/components/tree/tree.styles.d.ts +1 -0
  108. package/dist/components/tree/tree.styles.js +13 -0
  109. package/dist/internal/form-associated.js +49 -1
  110. package/dist/internal/icons.d.ts +11 -0
  111. package/dist/internal/icons.js +64 -0
  112. package/dist/internal/tokens.styles.js +41 -1
  113. package/dist/lyra.d.ts +67 -0
  114. package/dist/lyra.js +55 -0
  115. package/llms-full.txt +1425 -0
  116. package/llms.txt +47 -0
  117. package/package.json +53 -4
@@ -0,0 +1,65 @@
1
+ import { type PropertyValues, type TemplateResult } from 'lit';
2
+ import { LyraElement } from '../../internal/lyra-element.js';
3
+ import './tree-node.js';
4
+ export interface TreeItem {
5
+ id: string;
6
+ label: string;
7
+ children?: TreeItem[];
8
+ badge?: string | number;
9
+ }
10
+ /**
11
+ * `<lyra-tree>` — an expand/collapse hierarchy for graph/document navigation.
12
+ *
13
+ * Implements the WAI-ARIA treeitem keyboard pattern: a single roving
14
+ * `tabindex` (tracked here as `activeId`, pushed down to every
15
+ * `<lyra-tree-node>` — including nested ones, recursively) and
16
+ * ArrowUp/Down/Right/Left/Home/End/Enter/Space handled by one delegated
17
+ * `keydown` listener. Native `KeyboardEvent`s are `composed: true` and
18
+ * bubble across shadow-DOM boundaries, so a press inside a deeply-nested
19
+ * `<lyra-tree-node>`'s own shadow root still reaches this listener.
20
+ *
21
+ * @customElement lyra-tree
22
+ * @event lyra-node-toggle - `detail: { id, expanded }`, re-emitted from a child `<lyra-tree-node>`.
23
+ * @event lyra-node-select - `detail: { id }`, re-emitted from a child `<lyra-tree-node>`.
24
+ * @csspart base
25
+ * @slot - `<lyra-tree-node>` elements (top-level tree items).
26
+ */
27
+ export declare class LyraTree extends LyraElement {
28
+ static styles: import("lit").CSSResultGroup[];
29
+ data: TreeItem[];
30
+ private activeId;
31
+ private get nodeElements();
32
+ private childrenOf;
33
+ /** Every currently *visible* (ancestor-expanded) node, top-to-bottom. */
34
+ private visibleNodeElements;
35
+ private findItem;
36
+ protected willUpdate(changed: PropertyValues): void;
37
+ protected updated(changed: PropertyValues): void;
38
+ /** Unchanged from the existing implementation — by-id reconciliation of top-level items. */
39
+ private syncNodes;
40
+ private focusNode;
41
+ /**
42
+ * `updated()` only pushes the new `activeId` to *top-level* nodes; a
43
+ * nested node only receives it once its ancestor chain's own renders
44
+ * cascade it down (one more pending update per depth level). Cascade
45
+ * `updateComplete` itself to match: awaiting `<lyra-tree>`'s (or any
46
+ * `<lyra-tree-node>`'s — see the matching override there) `updateComplete`
47
+ * now transitively waits for every visible descendant node's own update,
48
+ * not just this element's. Without this, `focusNode()`'s `.focus()` call
49
+ * can run while a nested target is still mid-cascade (no `tabindex`
50
+ * attribute committed yet), and `.focus()` on an element with no
51
+ * `tabindex` attribute at all is a silent no-op.
52
+ */
53
+ protected getUpdateComplete(): Promise<boolean>;
54
+ private onTreeKeyDown;
55
+ /** Expand every node in the tree, recursively. (unchanged) */
56
+ expandAll(): void;
57
+ /** Collapse every node in the tree. (unchanged) */
58
+ collapseAll(): void;
59
+ render(): TemplateResult;
60
+ }
61
+ declare global {
62
+ interface HTMLElementTagNameMap {
63
+ 'lyra-tree': LyraTree;
64
+ }
65
+ }
@@ -0,0 +1,227 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { html } from 'lit';
8
+ import { property, state } from 'lit/decorators.js';
9
+ import { LyraElement } from '../../internal/lyra-element.js';
10
+ import { defineElement } from '../../internal/prefix.js';
11
+ import { styles } from './tree.styles.js';
12
+ import './tree-node.js';
13
+ /**
14
+ * `<lyra-tree>` — an expand/collapse hierarchy for graph/document navigation.
15
+ *
16
+ * Implements the WAI-ARIA treeitem keyboard pattern: a single roving
17
+ * `tabindex` (tracked here as `activeId`, pushed down to every
18
+ * `<lyra-tree-node>` — including nested ones, recursively) and
19
+ * ArrowUp/Down/Right/Left/Home/End/Enter/Space handled by one delegated
20
+ * `keydown` listener. Native `KeyboardEvent`s are `composed: true` and
21
+ * bubble across shadow-DOM boundaries, so a press inside a deeply-nested
22
+ * `<lyra-tree-node>`'s own shadow root still reaches this listener.
23
+ *
24
+ * @customElement lyra-tree
25
+ * @event lyra-node-toggle - `detail: { id, expanded }`, re-emitted from a child `<lyra-tree-node>`.
26
+ * @event lyra-node-select - `detail: { id }`, re-emitted from a child `<lyra-tree-node>`.
27
+ * @csspart base
28
+ * @slot - `<lyra-tree-node>` elements (top-level tree items).
29
+ */
30
+ export class LyraTree extends LyraElement {
31
+ constructor() {
32
+ super(...arguments);
33
+ this.data = [];
34
+ this.activeId = null;
35
+ this.onTreeKeyDown = (e) => {
36
+ const visible = this.visibleNodeElements();
37
+ if (visible.length === 0)
38
+ return;
39
+ const currentIndex = visible.findIndex((n) => n.item.id === this.activeId);
40
+ const current = currentIndex >= 0 ? visible[currentIndex] : visible[0];
41
+ switch (e.key) {
42
+ case 'ArrowDown':
43
+ e.preventDefault();
44
+ this.focusNode(visible[Math.min(visible.length - 1, currentIndex + 1)]);
45
+ break;
46
+ case 'ArrowUp':
47
+ e.preventDefault();
48
+ this.focusNode(visible[Math.max(0, currentIndex - 1)]);
49
+ break;
50
+ case 'Home':
51
+ e.preventDefault();
52
+ this.focusNode(visible[0]);
53
+ break;
54
+ case 'End':
55
+ e.preventDefault();
56
+ this.focusNode(visible[visible.length - 1]);
57
+ break;
58
+ case 'ArrowRight':
59
+ e.preventDefault();
60
+ if (!current.hasChildren)
61
+ break;
62
+ if (!current.expanded) {
63
+ current.expand(); // focus stays put; a 2nd ArrowRight steps into the first child
64
+ }
65
+ else {
66
+ const child = visible[currentIndex + 1];
67
+ if (child && child.depth > current.depth)
68
+ this.focusNode(child);
69
+ }
70
+ break;
71
+ case 'ArrowLeft':
72
+ e.preventDefault();
73
+ if (current.hasChildren && current.expanded) {
74
+ current.collapse();
75
+ }
76
+ else {
77
+ for (let i = currentIndex - 1; i >= 0; i--) {
78
+ if (visible[i].depth < current.depth) {
79
+ this.focusNode(visible[i]);
80
+ break;
81
+ }
82
+ }
83
+ }
84
+ break;
85
+ case 'Enter':
86
+ case ' ':
87
+ e.preventDefault();
88
+ current.select();
89
+ break;
90
+ default:
91
+ return;
92
+ }
93
+ };
94
+ }
95
+ static { this.styles = [LyraElement.styles, styles]; }
96
+ get nodeElements() {
97
+ return [...this.querySelectorAll('lyra-tree-node')];
98
+ }
99
+ childrenOf(node) {
100
+ return [...(node.shadowRoot?.querySelectorAll('lyra-tree-node') ?? [])];
101
+ }
102
+ /** Every currently *visible* (ancestor-expanded) node, top-to-bottom. */
103
+ visibleNodeElements() {
104
+ const acc = [];
105
+ const walk = (nodes) => {
106
+ for (const n of nodes) {
107
+ acc.push(n);
108
+ if (n.expanded)
109
+ walk(this.childrenOf(n));
110
+ }
111
+ };
112
+ walk(this.nodeElements);
113
+ return acc;
114
+ }
115
+ findItem(items, id) {
116
+ for (const item of items) {
117
+ if (item.id === id)
118
+ return item;
119
+ const nested = item.children && this.findItem(item.children, id);
120
+ if (nested)
121
+ return nested;
122
+ }
123
+ return undefined;
124
+ }
125
+ willUpdate(changed) {
126
+ if (changed.has('data')) {
127
+ this.syncNodes();
128
+ if (!this.activeId || !this.findItem(this.data, this.activeId)) {
129
+ this.activeId = this.data[0]?.id ?? null;
130
+ }
131
+ }
132
+ }
133
+ updated(changed) {
134
+ if (changed.has('activeId') || changed.has('data')) {
135
+ const count = this.data.length;
136
+ this.nodeElements.forEach((node, i) => {
137
+ node.activeId = this.activeId;
138
+ node.setSize = count;
139
+ node.posInSet = i + 1;
140
+ });
141
+ }
142
+ }
143
+ /** Unchanged from the existing implementation — by-id reconciliation of top-level items. */
144
+ syncNodes() {
145
+ const existingById = new Map();
146
+ for (const node of this.nodeElements) {
147
+ if (node.item)
148
+ existingById.set(node.item.id, node);
149
+ }
150
+ const seen = new Set();
151
+ let previousSibling = null;
152
+ for (const item of this.data) {
153
+ const reused = !seen.has(item.id) ? existingById.get(item.id) : undefined;
154
+ const node = reused ?? document.createElement('lyra-tree-node');
155
+ node.item = item;
156
+ node.depth = 0;
157
+ seen.add(item.id);
158
+ const targetPosition = previousSibling
159
+ ? previousSibling.nextElementSibling
160
+ : this.firstElementChild;
161
+ if (targetPosition !== node)
162
+ this.insertBefore(node, targetPosition);
163
+ previousSibling = node;
164
+ }
165
+ for (const [id, node] of existingById) {
166
+ if (!seen.has(id))
167
+ node.remove();
168
+ }
169
+ }
170
+ focusNode(node) {
171
+ if (!node)
172
+ return;
173
+ this.activeId = node.item.id;
174
+ node.focus();
175
+ }
176
+ /**
177
+ * `updated()` only pushes the new `activeId` to *top-level* nodes; a
178
+ * nested node only receives it once its ancestor chain's own renders
179
+ * cascade it down (one more pending update per depth level). Cascade
180
+ * `updateComplete` itself to match: awaiting `<lyra-tree>`'s (or any
181
+ * `<lyra-tree-node>`'s — see the matching override there) `updateComplete`
182
+ * now transitively waits for every visible descendant node's own update,
183
+ * not just this element's. Without this, `focusNode()`'s `.focus()` call
184
+ * can run while a nested target is still mid-cascade (no `tabindex`
185
+ * attribute committed yet), and `.focus()` on an element with no
186
+ * `tabindex` attribute at all is a silent no-op.
187
+ */
188
+ async getUpdateComplete() {
189
+ const result = await super.getUpdateComplete();
190
+ await Promise.all(this.nodeElements.map((n) => n.updateComplete));
191
+ return result;
192
+ }
193
+ /** Expand every node in the tree, recursively. (unchanged) */
194
+ expandAll() {
195
+ const setAll = (nodes) => {
196
+ for (const n of nodes) {
197
+ n.expanded = true;
198
+ void n.updateComplete.then(() => setAll(this.childrenOf(n)));
199
+ }
200
+ };
201
+ setAll(this.nodeElements);
202
+ }
203
+ /** Collapse every node in the tree. (unchanged) */
204
+ collapseAll() {
205
+ const setAll = (nodes) => {
206
+ for (const n of nodes) {
207
+ setAll(this.childrenOf(n));
208
+ n.expanded = false;
209
+ }
210
+ };
211
+ setAll(this.nodeElements);
212
+ }
213
+ render() {
214
+ return html `
215
+ <div part="base" role="tree" @keydown=${this.onTreeKeyDown}>
216
+ <slot></slot>
217
+ </div>
218
+ `;
219
+ }
220
+ }
221
+ __decorate([
222
+ property({ attribute: false })
223
+ ], LyraTree.prototype, "data", void 0);
224
+ __decorate([
225
+ state()
226
+ ], LyraTree.prototype, "activeId", void 0);
227
+ defineElement('tree', LyraTree);
@@ -0,0 +1 @@
1
+ export declare const styles: import("lit").CSSResult;
@@ -0,0 +1,13 @@
1
+ import { css } from 'lit';
2
+ export const styles = css `
3
+ :host {
4
+ display: block;
5
+ }
6
+ [part='base'] {
7
+ display: flex;
8
+ flex-direction: column;
9
+ /* Fallback for a deeply-indented node whose row still overflows despite
10
+ the [part=label] truncation + padding-inline-start cap in tree-node.ts. */
11
+ overflow-x: auto;
12
+ }
13
+ `;
@@ -24,6 +24,16 @@ export function FormAssociated(Base) {
24
24
  this.disabled = false;
25
25
  this.required = false;
26
26
  this._value = '';
27
+ // What native `defaultValue`/`form.reset()` restores to. Mirrors the
28
+ // `value` *content attribute* only (see `attributeChangedCallback`
29
+ // below) — exactly like native `<input>`: setting the `.value` IDL
30
+ // property (whether from a user typing, a picker commit, or a
31
+ // consumer's own script) never touches `defaultValue`, only
32
+ // `setAttribute('value', ...)`/declarative markup does. Using the
33
+ // property setter itself to capture "whichever assignment happens
34
+ // first" would wrongly let a user's first-ever edit become permanent
35
+ // (a required field could never be reset back to blank again).
36
+ this._defaultValue = '';
27
37
  this.internals = this.attachInternals();
28
38
  }
29
39
  get value() {
@@ -33,12 +43,36 @@ export function FormAssociated(Base) {
33
43
  const old = this._value;
34
44
  this._value = next ?? '';
35
45
  this.internals.setFormValue(this._value);
46
+ this.updateValidity();
36
47
  this.requestUpdate('value', old);
37
48
  }
49
+ attributeChangedCallback(name, old, value) {
50
+ super.attributeChangedCallback(name, old, value);
51
+ if (name === 'value') {
52
+ // Runs after the base class has already applied the attribute to
53
+ // the `value` property (via the setter above), so `_value` here
54
+ // reflects the newly-parsed/assigned attribute value.
55
+ this._defaultValue = this._value;
56
+ }
57
+ }
38
58
  /** Programmatically set the submitted value (alias kept for clarity). */
39
59
  setFormValue(next) {
40
60
  this.value = next;
41
61
  }
62
+ /**
63
+ * Recomputes `ElementInternals`'s validity state. Without this,
64
+ * `internals` defaults to permanently "valid" and `required` never
65
+ * blocks form submission — the single highest-leverage correctness gap
66
+ * the 2026-07-10 cross-repo audit found (forms-core §internal/, High).
67
+ */
68
+ updateValidity() {
69
+ if (this.required && this._value === '') {
70
+ this.internals.setValidity({ valueMissing: true }, 'Please fill out this field.');
71
+ }
72
+ else {
73
+ this.internals.setValidity({});
74
+ }
75
+ }
42
76
  checkValidity() {
43
77
  return this.internals.checkValidity();
44
78
  }
@@ -46,11 +80,25 @@ export function FormAssociated(Base) {
46
80
  return this.internals.reportValidity();
47
81
  }
48
82
  formResetCallback() {
49
- this.value = '';
83
+ // Restore the constructed default value (native `defaultValue`
84
+ // semantics) — previously this unconditionally blanked the field.
85
+ this.value = this._defaultValue;
50
86
  }
51
87
  formDisabledCallback(disabled) {
52
88
  this.disabled = disabled;
53
89
  }
90
+ connectedCallback() {
91
+ super.connectedCallback();
92
+ // `required` may already be set from an attribute by the time this
93
+ // runs; reflect validity from the start, not only after the first
94
+ // `value` write.
95
+ this.updateValidity();
96
+ }
97
+ updated(changed) {
98
+ super.updated(changed);
99
+ if (changed.has('required'))
100
+ this.updateValidity();
101
+ }
54
102
  }
55
103
  return FormAssociatedElement;
56
104
  }
@@ -0,0 +1,11 @@
1
+ import { type SVGTemplateResult } from 'lit';
2
+ /** A single right-pointing chevron. Rotate the wrapping element for other directions. */
3
+ export declare function chevronIcon(): SVGTemplateResult;
4
+ /** An "x" close/clear glyph. */
5
+ export declare function closeIcon(): SVGTemplateResult;
6
+ /** A right-pointing play triangle. */
7
+ export declare function playIcon(): SVGTemplateResult;
8
+ /** Two vertical pause bars. */
9
+ export declare function pauseIcon(): SVGTemplateResult;
10
+ /** A calendar/date glyph, for date-input's open-calendar toggle. */
11
+ export declare function calendarIcon(): SVGTemplateResult;
@@ -0,0 +1,64 @@
1
+ import { svg } from 'lit';
2
+ /**
3
+ * Shared inline-SVG icon set. Every component in this library previously
4
+ * rendered functional icons (chevrons, close buttons, play/pause, the
5
+ * date-input calendar toggle) as literal Unicode/HTML-entity/emoji text
6
+ * glyphs — font-dependent, non-recolorable beyond plain text color, and
7
+ * inconsistent in weight/size across the OS/browser font stack a host page
8
+ * happens to ship (2026-07-10 design review). These replace all of them.
9
+ *
10
+ * Every icon shares one 24x24 viewBox and one stroke-width so the whole set
11
+ * reads as one visual language; each renders at `1em` so it inherits the
12
+ * caller's own font-size instead of imposing a fixed pixel size. None bakes
13
+ * in a direction/rotation — callers needing "up"/"left"/"open" etc. rotate
14
+ * the *wrapping part element* via CSS `transform: rotate(...)`, not the svg.
15
+ */
16
+ const STROKE_WIDTH = '1.75';
17
+ const VIEW_BOX = '0 0 24 24';
18
+ function icon(paths) {
19
+ return svg `
20
+ <svg
21
+ width="1em"
22
+ height="1em"
23
+ viewBox=${VIEW_BOX}
24
+ fill="none"
25
+ stroke="currentColor"
26
+ stroke-width=${STROKE_WIDTH}
27
+ stroke-linecap="round"
28
+ stroke-linejoin="round"
29
+ aria-hidden="true"
30
+ focusable="false"
31
+ >${paths}</svg>
32
+ `;
33
+ }
34
+ /** A single right-pointing chevron. Rotate the wrapping element for other directions. */
35
+ export function chevronIcon() {
36
+ return icon(svg `<polyline points="9 6 15 12 9 18"></polyline>`);
37
+ }
38
+ /** An "x" close/clear glyph. */
39
+ export function closeIcon() {
40
+ return icon(svg `
41
+ <line x1="18" y1="6" x2="6" y2="18"></line>
42
+ <line x1="6" y1="6" x2="18" y2="18"></line>
43
+ `);
44
+ }
45
+ /** A right-pointing play triangle. */
46
+ export function playIcon() {
47
+ return icon(svg `<polygon points="6 4 20 12 6 20 6 4"></polygon>`);
48
+ }
49
+ /** Two vertical pause bars. */
50
+ export function pauseIcon() {
51
+ return icon(svg `
52
+ <rect x="6" y="4" width="4" height="16" rx="1"></rect>
53
+ <rect x="14" y="4" width="4" height="16" rx="1"></rect>
54
+ `);
55
+ }
56
+ /** A calendar/date glyph, for date-input's open-calendar toggle. */
57
+ export function calendarIcon() {
58
+ return icon(svg `
59
+ <rect x="3" y="5" width="18" height="16" rx="2"></rect>
60
+ <line x1="16" y1="3" x2="16" y2="7"></line>
61
+ <line x1="8" y1="3" x2="8" y2="7"></line>
62
+ <line x1="3" y1="10" x2="21" y2="10"></line>
63
+ `);
64
+ }
@@ -6,7 +6,7 @@ export const tokens = css `
6
6
  --lyra-color-surface: var(--wa-color-surface-default, #fff);
7
7
  --lyra-color-text: var(--wa-color-text-normal, #1a1a1a);
8
8
  --lyra-color-text-quiet: var(--wa-color-text-quiet, #6b7280);
9
- --lyra-color-border: var(--wa-color-neutral-fill-normal, #d4d4d8);
9
+ --lyra-color-border: var(--wa-color-neutral-fill-normal, #8a8a90);
10
10
  --lyra-color-brand: var(--wa-color-brand-fill-loud, #0969da);
11
11
  --lyra-color-brand-quiet: var(--wa-color-brand-fill-quiet, #ddf4ff);
12
12
  --lyra-color-success: var(--wa-color-success-fill-loud, #1a7f37);
@@ -20,10 +20,50 @@ export const tokens = css `
20
20
  --lyra-shadow: var(--wa-shadow-m, 0 2px 8px rgb(0 0 0 / 0.15));
21
21
  --lyra-font: var(--wa-font-family-body, system-ui, sans-serif);
22
22
 
23
+ /* Motion — every component that animates (popovers, gauge fill, toast)
24
+ reads from these two instead of hand-rolling its own duration/easing,
25
+ so the library has one consistent rhythm (2026-07-10 design review). */
26
+ --lyra-transition-fast: var(--wa-transition-fast, 120ms ease-out);
27
+ --lyra-transition-base: var(--wa-transition-normal, 180ms ease-out);
28
+
29
+ /* Disabled state — one opacity value for every disabled control,
30
+ replacing three previously-independent hardcoded values (0.5/0.4/0.35). */
31
+ --lyra-opacity-disabled: var(--wa-opacity-disabled, 0.5);
32
+
33
+ /* Focus ring — every :focus-visible rule in the library should reference
34
+ these three instead of hardcoding its own width/color/offset. */
35
+ --lyra-focus-ring-width: 2px;
36
+ --lyra-focus-ring-color: var(--lyra-color-brand);
37
+ --lyra-focus-ring-offset: 2px;
38
+
39
+ /* Minimum tappable box for an icon-only button (close/dismiss/nav
40
+ controls). Visual icon size is unaffected; components pad out to this
41
+ via min-inline-size/min-block-size, not by growing the glyph itself. */
42
+ --lyra-icon-button-size: 2.5rem;
43
+
23
44
  font-family: var(--lyra-font);
24
45
  color: var(--lyra-color-text);
25
46
  box-sizing: border-box;
26
47
  }
48
+
49
+ /* Standalone (no Web Awesome theme) dark-mode fallback. A real --wa-* value
50
+ from a consumer's theme always wins — this only changes what a bare
51
+ lyra-ui component renders when dropped, unstyled, onto a dark host page
52
+ (2026-07-10 design review: previously zero dark-mode adaptation existed
53
+ in the pure-fallback case). */
54
+ @media (prefers-color-scheme: dark) {
55
+ :host {
56
+ --lyra-color-surface: var(--wa-color-surface-default, #1a1a1a);
57
+ --lyra-color-text: var(--wa-color-text-normal, #f2f2f2);
58
+ --lyra-color-text-quiet: var(--wa-color-text-quiet, #9aa1ac);
59
+ --lyra-color-border: var(--wa-color-neutral-fill-normal, #4a4a52);
60
+ --lyra-color-brand: var(--wa-color-brand-fill-loud, #4d9fef);
61
+ --lyra-color-brand-quiet: var(--wa-color-brand-fill-quiet, #163650);
62
+ --lyra-color-success: var(--wa-color-success-fill-loud, #3fb950);
63
+ --lyra-color-warning: var(--wa-color-warning-fill-loud, #d29922);
64
+ --lyra-color-danger: var(--wa-color-danger-fill-loud, #f85149);
65
+ }
66
+ }
27
67
  :host([hidden]) {
28
68
  display: none !important;
29
69
  }
package/dist/lyra.d.ts CHANGED
@@ -6,6 +6,32 @@ import './components/combobox/option.js';
6
6
  import './components/date-picker/date-picker.js';
7
7
  import './components/date-picker/date-input.js';
8
8
  import './components/flag/flag.js';
9
+ import './components/empty/empty.js';
10
+ import './components/skeleton/skeleton.js';
11
+ import './components/stat/stat.js';
12
+ import './components/table/table.js';
13
+ import './components/gauge/gauge.js';
14
+ import './components/export-button/export-button.js';
15
+ import './components/split/split.js';
16
+ import './components/time-range/time-range.js';
17
+ import './components/playback/playback.js';
18
+ import './components/heatmap/heatmap.js';
19
+ import './components/graph/graph.js';
20
+ import './components/tree/tree.js';
21
+ import './components/tree/tree-node.js';
22
+ import './components/chart/chart.js';
23
+ import './components/chart/bar-chart.js';
24
+ import './components/chart/line-chart.js';
25
+ import './components/chart/pie-chart.js';
26
+ import './components/chart/doughnut-chart.js';
27
+ import './components/chart/scatter-chart.js';
28
+ import './components/chart/bubble-chart.js';
29
+ import './components/chart/radar-chart.js';
30
+ import './components/chart/polar-area-chart.js';
31
+ import './components/chart/box-plot.js';
32
+ import './components/chart/histogram.js';
33
+ import './components/map/map.js';
34
+ import './components/file-input/file-input.js';
9
35
  export { LyraSparkline } from './components/sparkline/sparkline.js';
10
36
  export { LyraToast } from './components/toast/toast.js';
11
37
  export type { ToastPlacement, ToastCreateOptions } from './components/toast/toast.js';
@@ -21,6 +47,47 @@ export type { DateRange } from './components/date-picker/date-picker.js';
21
47
  export { LyraDateInput } from './components/date-picker/date-input.js';
22
48
  export { LyraFlag } from './components/flag/flag.js';
23
49
  export { LANGUAGE_TO_COUNTRY, languageToCountry } from './components/flag/language-map.js';
50
+ export { LyraEmpty } from './components/empty/empty.js';
51
+ export { LyraSkeleton } from './components/skeleton/skeleton.js';
52
+ export type { SkeletonVariant, SkeletonEffect } from './components/skeleton/skeleton.js';
53
+ export { LyraStat } from './components/stat/stat.js';
54
+ export type { StatVariant } from './components/stat/stat.js';
55
+ export { LyraTable } from './components/table/table.js';
56
+ export type { TableColumn } from './components/table/table.js';
57
+ export { LyraGauge } from './components/gauge/gauge.js';
58
+ export type { GaugeType } from './components/gauge/gauge.js';
59
+ export { LyraExportButton } from './components/export-button/export-button.js';
60
+ export type { ExportFormat } from './components/export-button/export-button.js';
61
+ export { escapeCsvField, buildCsv, downloadBlob } from './components/export-button/csv.js';
62
+ export type { CsvColumn } from './components/export-button/csv.js';
63
+ export { LyraSplit } from './components/split/split.js';
64
+ export { LyraTimeRange } from './components/time-range/time-range.js';
65
+ export { LyraPlayback } from './components/playback/playback.js';
66
+ export { LyraHeatmap } from './components/heatmap/heatmap.js';
67
+ export { linearAlpha, sqrtStep } from './components/heatmap/heatmap-scale.js';
68
+ export { LyraGraph } from './components/graph/graph.js';
69
+ export type { GraphNode, GraphLink } from './components/graph/graph.js';
70
+ export { LyraTree } from './components/tree/tree.js';
71
+ export type { TreeItem } from './components/tree/tree.js';
72
+ export { LyraTreeNode } from './components/tree/tree-node.js';
73
+ export { LyraChart } from './components/chart/chart.js';
74
+ export type { Series, LyraChartType } from './components/chart/chart.js';
75
+ export { LyraBarChart } from './components/chart/bar-chart.js';
76
+ export { LyraLineChart } from './components/chart/line-chart.js';
77
+ export { LyraPieChart } from './components/chart/pie-chart.js';
78
+ export { LyraDoughnutChart } from './components/chart/doughnut-chart.js';
79
+ export { LyraScatterChart } from './components/chart/scatter-chart.js';
80
+ export { LyraBubbleChart } from './components/chart/bubble-chart.js';
81
+ export { LyraRadarChart } from './components/chart/radar-chart.js';
82
+ export { LyraPolarAreaChart } from './components/chart/polar-area-chart.js';
83
+ export { LyraBoxPlot } from './components/chart/box-plot.js';
84
+ export type { BoxPlotSeries, BoxPlotPoint } from './components/chart/box-plot.js';
85
+ export { LyraHistogram } from './components/chart/histogram.js';
86
+ export { binValues } from './components/chart/histogram-bin.js';
87
+ export type { HistogramBucket } from './components/chart/histogram-bin.js';
88
+ export { LyraMap } from './components/map/map.js';
89
+ export type { LegendEntry, ChoroplethLayer } from './components/map/map.js';
90
+ export { LyraFileInput } from './components/file-input/file-input.js';
24
91
  export { LyraElement } from './internal/lyra-element.js';
25
92
  export { FormAssociated } from './internal/form-associated.js';
26
93
  export { LYRA_PREFIX, tag, defineElement } from './internal/prefix.js';