@akcelik/strct 0.4.0 → 0.5.1

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.
@@ -88,7 +88,6 @@ const STRCT_ICONS = {
88
88
  chevronLeft: '<path d="M10 3.5L5.5 8 10 12.5"/>',
89
89
  chevronDoubleRight: '<path d="M3.5 3.5L8 8l-4.5 4.5M8.5 3.5L13 8l-4.5 4.5"/>',
90
90
  chevronDown: '<path d="M3.5 6L8 10.5 12.5 6"/>',
91
- ellipsis: '<circle cx="3.5" cy="8" r=".9" fill="currentColor" stroke="none"/><circle cx="8" cy="8" r=".9" fill="currentColor" stroke="none"/><circle cx="12.5" cy="8" r=".9" fill="currentColor" stroke="none"/>',
92
91
  compass: '<circle cx="8" cy="8" r="6"/><path d="M10.6 5.4l-1.5 3.7-3.7 1.5 1.5-3.7 3.7-1.5z"/>',
93
92
  close: '<path d="M4 4l8 8M12 4l-8 8"/>',
94
93
  check: '<path d="M3.5 8.5l3 3 6-7"/>',
@@ -97,7 +96,6 @@ const STRCT_ICONS = {
97
96
  search: '<circle cx="7" cy="7" r="4"/><path d="M10 10l3.5 3.5"/>',
98
97
  calendar: '<rect x="2.5" y="3.5" width="11" height="10" rx="1.5"/><path d="M2.5 6.5h11M5.5 2v3M10.5 2v3"/>',
99
98
  eye: '<path d="M1.5 8S4 3.5 8 3.5 14.5 8 14.5 8 12 12.5 8 12.5 1.5 8 1.5 8z"/><circle cx="8" cy="8" r="2"/>',
100
- eyeOff: '<path d="M1.5 8S4 3.5 8 3.5 14.5 8 14.5 8 12 12.5 8 12.5 1.5 8 1.5 8z"/><circle cx="8" cy="8" r="2"/><path d="M2.5 2.5l11 11"/>',
101
99
  upload: '<path d="M8 10.5V3M5 5.8L8 2.8l3 3M3 12.8h10"/>',
102
100
  download: '<path d="M8 2.5V10M5 7.2L8 10.2l3-3M3 12.8h10"/>',
103
101
  droplet: '<path d="M8 2.4S12 6.6 12 9.4a4 4 0 01-8 0c0-2.8 4-7 4-7z"/>',
@@ -108,7 +106,7 @@ const STRCT_ICONS = {
108
106
  moon: '<path d="M13 9a5 5 0 01-6-6 5.5 5.5 0 106 6z"/>',
109
107
  info: '<circle cx="8" cy="8" r="6"/><path d="M8 7.2v3.6M8 5.2v.2"/>',
110
108
  warning: '<path d="M8 2.5l6 11H2l6-11z"/><path d="M8 6.8v3M8 11.6v.2"/>',
111
- danger: '<circle cx="8" cy="8" r="6"/><path d="M8 5v3.6M8 10.8v.2"/>',
109
+ critical: '<circle cx="8" cy="8" r="6"/><path d="M8 5v3.6M8 10.8v.2"/>',
112
110
  success: '<circle cx="8" cy="8" r="6"/><path d="M5.2 8.2l2 2 3.6-4"/>',
113
111
  bell: '<path d="M8 2.6a3.4 3.4 0 00-3.4 3.4c0 2.9-1.1 3.9-1.1 3.9h9s-1.1-1-1.1-3.9A3.4 3.4 0 008 2.6z"/><path d="M6.8 12.8a1.3 1.3 0 002.4 0"/>',
114
112
  heart: '<path d="M8 13.3S2.7 10 2.7 6.3A2.6 2.6 0 018 4.9a2.6 2.6 0 015.3 1.4C13.3 10 8 13.3 8 13.3z"/>',
@@ -127,6 +125,23 @@ const STRCT_ICONS = {
127
125
  folder: '<path d="M2 4.6a1 1 0 0 1 1-1h3.1l1.3 1.6H13a1 1 0 0 1 1 1V12a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1z"/>',
128
126
  template: '<path d="M4.3 2.5h4.6l3.1 3.1V13a.5.5 0 0 1-.5.5H4.3a.5.5 0 0 1-.5-.5V3a.5.5 0 0 1 .5-.5z"/><path d="M8.7 2.6v3.1h3.1"/><path d="M5.8 9h4.2M5.8 11h2.6"/>',
129
127
  tag: '<path d="M2.6 7.7V3.2a.6.6 0 0 1 .6-.6h4.5l5.6 5.6a1 1 0 0 1 0 1.4l-3.5 3.5a1 1 0 0 1-1.4 0z"/><circle cx="5.4" cy="5.4" r=".9" fill="currentColor" stroke="none"/>',
128
+ // ── Actions ──────────────────────────────────────────────────
129
+ plus: '<path d="M8 3v10M3 8h10"/>',
130
+ minus: '<path d="M3 8h10"/>',
131
+ pencil: '<path d="M11.5 2.5l2 2-8.5 8.5-3 .5.5-3z"/>',
132
+ trash: '<path d="M2.5 4.5h11M5.5 4.5v8.5a1 1 0 001 1h3a1 1 0 001-1V4.5M6.5 3h3"/>',
133
+ refresh: '<path d="M13.5 7.5a5.5 5.5 0 11-2-5.2"/><path d="M13.5 2.5v3.5H10"/>',
134
+ filter: '<path d="M2 3.5h12l-4.5 5.5v4.5h-3V9z"/>',
135
+ settings: '<path d="M8 5.5a2.5 2.5 0 100 5 2.5 2.5 0 000-5z"/><path d="M7.2 1.5h1.6l.3 1.8c.4.1.8.3 1.2.5l1.5-1.1 1.1 1.1-1.1 1.5c.2.4.4.8.5 1.2l1.8.3v1.6l-1.8.3c-.1.4-.3.8-.5 1.2l1.1 1.5-1.1 1.1-1.5-1.1c-.4.2-.8.4-1.2.5l-.3 1.8H7.2l-.3-1.8a5.4 5.4 0 01-1.2-.5l-1.5 1.1-1.1-1.1 1.1-1.5a5.4 5.4 0 01-.5-1.2l-1.8-.3V7.2l1.8-.3c.1-.4.3-.8.5-1.2L2.7 4.2l1.1-1.1 1.5 1.1c.4-.2.8-.4 1.2-.5z"/>',
136
+ user: '<path d="M8 8a2.5 2.5 0 100-5A2.5 2.5 0 008 8z"/><path d="M3 14.5c0-2.8 2.2-5 5-5s5 2.2 5 5"/>',
137
+ logout: '<path d="M10 3.5h2a1 1 0 011 1v7a1 1 0 01-1 1h-2M6.5 5.5L3.5 8l3 3M3.5 8h6.5"/>',
138
+ undo: '<path d="M4.5 5.5L2 8l2.5 2.5M2.5 8h7a3 3 0 013 3v.5"/>',
139
+ redo: '<path d="M11.5 5.5L14 8l-2.5 2.5M13.5 8h-7a3 3 0 00-3 3v.5"/>',
140
+ arrowUp: '<path d="M8 13V3M3.5 6.5L8 2l4.5 4.5"/>',
141
+ arrowDown: '<path d="M8 3v10M3.5 9.5L8 14l4.5-4.5"/>',
142
+ arrowLeft: '<path d="M13 8H3M6.5 3.5L2 8l4.5 4.5"/>',
143
+ arrowRight: '<path d="M3 8h10M9.5 3.5L14 8l-4.5 4.5"/>',
144
+ externalLink: '<path d="M9 2.5h4.5V7M13.5 2.5L8.5 7.5M11.5 9v3.5a1 1 0 01-1 1h-7a1 1 0 01-1-1v-7a1 1 0 011-1H7"/>',
130
145
  // ── Datacenter / infrastructure ─────────────────────────────
131
146
  datacenter: '<rect x="2.5" y="2.5" width="11" height="11" rx="1"/><path d="M5 5h6M5 7.3h6M5 9.6h3.5"/><circle cx="11" cy="9.7" r=".5" fill="currentColor" stroke="none"/>',
132
147
  rack: '<rect x="3.5" y="2" width="9" height="12" rx="1"/><path d="M3.5 5.2h9M3.5 8.4h9M3.5 11.6h9"/><circle cx="5.4" cy="3.6" r=".4" fill="currentColor" stroke="none"/><circle cx="5.4" cy="6.8" r=".4" fill="currentColor" stroke="none"/><circle cx="5.4" cy="10" r=".4" fill="currentColor" stroke="none"/>',
@@ -151,6 +166,21 @@ const STRCT_ICONS = {
151
166
  resourcePool: '<circle cx="8" cy="8" r="5.6"/><path d="M8 8V2.4M8 8l4.9 2.7"/>',
152
167
  // Port group — a grouped set of switch ports under a shared rail.
153
168
  portGroup: '<path d="M1.8 4.4h12.4"/><rect x="2.2" y="6.2" width="3.4" height="4" rx=".5"/><rect x="6.3" y="6.2" width="3.4" height="4" rx=".5"/><rect x="10.4" y="6.2" width="3.4" height="4" rx=".5"/><path d="M3.9 10.2v1.6M8 10.2v1.6M12.1 10.2v1.6"/>',
169
+ // ── Modern infrastructure ────────────────────────────────────
170
+ pod: '<path d="M3 4.5c0-1.1 2.2-2 5-2s5 .9 5 2v7c0 1.1-2.2 2-5 2s-5-.9-5-2z"/><path d="M3 4.5c0 1.1 2.2 2 5 2s5-.9 5-2"/>',
171
+ deployment: '<rect x="2.5" y="2.5" width="11" height="4.5" rx="1"/><rect x="2.5" y="9" width="11" height="4.5" rx="1"/><path d="M11.5 5.5l2.5-1.5v4l-2.5-1.5"/>',
172
+ service: '<circle cx="4.5" cy="8" r="2"/><circle cx="11.5" cy="4.5" r="2"/><circle cx="11.5" cy="11.5" r="2"/><path d="M6.2 6.8l3.3-1.3M6.2 9.2l3.3 1.3"/>',
173
+ node: '<rect x="2.5" y="4" width="11" height="8" rx="1"/><path d="M5 7h6M5 10h3"/><circle cx="11" cy="10" r=".7" fill="currentColor" stroke="none"/>',
174
+ ingress: '<path d="M1.5 4.5h10M1.5 8h8M1.5 11.5h10"/><path d="M10.5 6.5l3 1.5-3 1.5"/>',
175
+ cloud: '<path d="M11.5 10.5a2.5 2.5 0 00-1.5-4.5 2.8 2.8 0 00-5.2.3A2.5 2.5 0 004 10.5z"/>',
176
+ container: '<rect x="2.5" y="2.5" width="11" height="11" rx="1.5"/><path d="M2.5 5.5h11M5.5 5.5V3M8 5.5V3M10.5 5.5V3"/>',
177
+ firewall: '<path d="M1.5 4h13v8h-13z"/><path d="M1.5 6.5h13M5 6.5V12M8 4V12M11 6.5V12"/>',
178
+ shield: '<path d="M8 2.3l5.2 1.9v3.3c0 3.1-2.3 5.1-5.2 6.4C5.1 12.6 2.8 10.6 2.8 7.5V4.2z"/>',
179
+ certificate: '<path d="M3 2.5h10v9H3z"/><path d="M3 5.5h10M6 8h4"/><circle cx="8" cy="11" r=".6" fill="currentColor" stroke="none"/><path d="M12 3.5l2 1.5-2 1.5V3.5z"/>',
180
+ key: '<circle cx="5" cy="9" r="2.8"/><path d="M6.9 7.1l5.6-5.6M11 4.5h2.5V7"/>',
181
+ metrics: '<path d="M2.5 13V3M2.5 13H13"/><path d="M4.5 10l2.5-4 2 2 3-5"/>',
182
+ logs: '<path d="M3 4.5h10M3 7h10M3 9.5h7M3 12h4"/>',
183
+ trace: '<circle cx="3.5" cy="5.5" r="1.2"/><circle cx="8" cy="11" r="1.2"/><circle cx="12.5" cy="5.5" r="1.2"/><path d="M4.5 6.3l2.5 3.4M9 9.2l2.5-3.4"/>',
154
184
  // ── Accessibility (original glyphs for generic concepts) ─────
155
185
  universalAccess: '<circle cx="8" cy="8" r="6"/><circle cx="8" cy="4.9" r=".9" fill="currentColor" stroke="none"/><path d="M4.9 6.3c2 .8 4.2 .8 6.2 0M8 6.4v3.1M6.3 11.9 8 9.4l1.7 2.5"/>',
156
186
  wheelchair: '<circle cx="6.5" cy="3.1" r="1.3"/><path d="M6.5 4.5v3.3h3.1l1.7 3.4"/><circle cx="6.7" cy="11.3" r="2.6"/><path d="M9.3 11.3h2.1l-.5 1.6"/>',
@@ -161,7 +191,6 @@ const STRCT_ICONS = {
161
191
  // ── Alert (original glyphs) ─────────────────────────────────
162
192
  siren: '<path d="M3.5 13h9M5 13V8a3 3 0 0 1 6 0v5M8 2.4V4M3.6 4.6l1 .9M12.4 4.6l-1 .9"/>',
163
193
  alarm: '<circle cx="8" cy="9" r="4.4"/><path d="M8 6.6V9l1.7 1M5 2.6 3.1 4.3M11 2.6l1.9 1.7M8 4.6V3"/>',
164
- bellOff: '<path d="M8 2.6a3.4 3.4 0 00-3.4 3.4c0 2.9-1.1 3.9-1.1 3.9h9s-1.1-1-1.1-3.9A3.4 3.4 0 008 2.6z"/><path d="M6.8 12.8a1.3 1.3 0 002.4 0"/><path d="M2.6 2.6l10.8 10.8"/>',
165
194
  megaphone: '<path d="M3 7.3v1.6l7 3V4.3zM10 5.7 12.5 4.2v7.6L10 10.3M4 9.6l.9 3.1h1.6l-.7-2.9"/>',
166
195
  flag: '<path d="M4 13.5V3M4 3.6h7.4L9.8 6.2l1.6 2.6H4"/>',
167
196
  shieldAlert: '<path d="M8 2.3l5.2 1.9v3.3c0 3.1-2.3 5.1-5.2 6.4C5.1 12.6 2.8 10.6 2.8 7.5V4.2z"/><path d="M8 5.5v3.1M8 10.6v.2"/>',
@@ -180,20 +209,71 @@ const STRCT_ICONS = {
180
209
  vendorDell: '<circle cx="8" cy="8" r="5.6"/><path d="M5.4 8h3.4M5.4 6.6h2.6M5.4 9.4h2.6"/>',
181
210
  vendorKaytus: '<path d="M5 3v10M5 8l4.5-4.5M5 8l4.5 5"/>',
182
211
  };
212
+ // Composite "off" variants — re-use base glyph + diagonal slash.
213
+ STRCT_ICONS['eyeOff'] = `${STRCT_ICONS['eye']}<path d="M2.5 2.5l11 11"/>`;
214
+ STRCT_ICONS['bellOff'] = `${STRCT_ICONS['bell']}<path d="M2.6 2.6l10.8 10.8"/>`;
183
215
  /** Icon names grouped for galleries / documentation. */
184
216
  const STRCT_ICON_GROUPS = [
185
217
  {
186
218
  label: 'General',
187
219
  names: [
188
- 'hexagon', 'search', 'menu', 'ellipsis', 'dots', 'close', 'check', 'calendar',
189
- 'eye', 'eyeOff', 'upload', 'download', 'sun', 'moon', 'bell', 'heart', 'layers',
190
- 'grid', 'form', 'chart', 'bars', 'gauge', 'palette', 'sidebar', 'compass',
191
- 'copy', 'code', 'book', 'terminal', 'folder', 'template', 'tag',
220
+ 'hexagon',
221
+ 'search',
222
+ 'menu',
223
+ 'dots',
224
+ 'close',
225
+ 'check',
226
+ 'calendar',
227
+ 'eye',
228
+ 'eyeOff',
229
+ 'upload',
230
+ 'download',
231
+ 'sun',
232
+ 'moon',
233
+ 'bell',
234
+ 'heart',
235
+ 'layers',
236
+ 'grid',
237
+ 'form',
238
+ 'chart',
239
+ 'bars',
240
+ 'gauge',
241
+ 'palette',
242
+ 'sidebar',
243
+ 'compass',
244
+ 'copy',
245
+ 'code',
246
+ 'book',
247
+ 'terminal',
248
+ 'folder',
249
+ 'template',
250
+ 'tag',
251
+ ],
252
+ },
253
+ {
254
+ label: 'Actions',
255
+ names: [
256
+ 'plus',
257
+ 'minus',
258
+ 'pencil',
259
+ 'trash',
260
+ 'refresh',
261
+ 'filter',
262
+ 'settings',
263
+ 'user',
264
+ 'logout',
265
+ 'undo',
266
+ 'redo',
267
+ 'arrowUp',
268
+ 'arrowDown',
269
+ 'arrowLeft',
270
+ 'arrowRight',
271
+ 'externalLink',
192
272
  ],
193
273
  },
194
274
  {
195
275
  label: 'Status',
196
- names: ['info', 'success', 'warning', 'danger', 'sync', 'lock', 'snapshot'],
276
+ names: ['info', 'success', 'warning', 'critical', 'sync', 'lock', 'snapshot'],
197
277
  },
198
278
  {
199
279
  label: 'Alert',
@@ -206,9 +286,43 @@ const STRCT_ICON_GROUPS = [
206
286
  {
207
287
  label: 'Datacenter',
208
288
  names: [
209
- 'datacenter', 'rack', 'cluster', 'host', 'vm', 'switch', 'storage',
210
- 'network', 'cpu', 'memory', 'disk', 'port', 'nic', 'hba', 'ethernet', 'power',
211
- 'resourcePool', 'portGroup',
289
+ 'datacenter',
290
+ 'rack',
291
+ 'cluster',
292
+ 'host',
293
+ 'vm',
294
+ 'switch',
295
+ 'storage',
296
+ 'network',
297
+ 'cpu',
298
+ 'memory',
299
+ 'disk',
300
+ 'port',
301
+ 'nic',
302
+ 'hba',
303
+ 'ethernet',
304
+ 'power',
305
+ 'resourcePool',
306
+ 'portGroup',
307
+ ],
308
+ },
309
+ {
310
+ label: 'Infrastructure',
311
+ names: [
312
+ 'pod',
313
+ 'deployment',
314
+ 'service',
315
+ 'node',
316
+ 'ingress',
317
+ 'cloud',
318
+ 'container',
319
+ 'firewall',
320
+ 'shield',
321
+ 'certificate',
322
+ 'key',
323
+ 'metrics',
324
+ 'logs',
325
+ 'trace',
212
326
  ],
213
327
  },
214
328
  {
@@ -240,24 +354,34 @@ function registerStrctIcon(name, content, options = {}) {
240
354
  }
241
355
  }
242
356
  /**
243
- * Inline stroke icon. `<strct-icon name="host" badge="ok" />` renders the host
357
+ * Inline stroke icon. `<strct-icon name="host" badge="success" />` renders the host
244
358
  * glyph with a green status dot (a "running host"). Unknown names render
245
359
  * nothing rather than throwing.
246
360
  */
247
361
  class StrctIcon {
248
362
  sanitizer = inject(DomSanitizer);
363
+ /** Icon name from the STRCT_ICONS registry. */
249
364
  name = input.required(...(ngDevMode ? [{ debugName: "name" }] : /* istanbul ignore next */ []));
365
+ /** Icon size in pixels. */
250
366
  size = input(16, ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
367
+ /** Stroke width for outline icons. */
251
368
  strokeWidth = input(1.4, ...(ngDevMode ? [{ debugName: "strokeWidth" }] : /* istanbul ignore next */ []));
252
369
  /** Optional status dot overlaid on the glyph (object state). */
253
370
  badge = input('none', ...(ngDevMode ? [{ debugName: "badge" }] : /* istanbul ignore next */ []));
371
+ /** Accessible label for the icon. When empty the icon is hidden from assistive tech. */
372
+ ariaLabel = input('', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
254
373
  /** True when the named icon is a full-SVG (raw) icon registered by the app. */
255
374
  isRaw = computed(() => Object.prototype.hasOwnProperty.call(STRCT_RAW_ICONS, this.name()), ...(ngDevMode ? [{ debugName: "isRaw" }] : /* istanbul ignore next */ []));
256
375
  svg = computed(() => this.sanitizer.bypassSecurityTrustHtml(STRCT_ICONS[this.name()] ?? ''), ...(ngDevMode ? [{ debugName: "svg" }] : /* istanbul ignore next */ []));
257
376
  rawSvg = computed(() => this.sanitizer.bypassSecurityTrustHtml(STRCT_RAW_ICONS[this.name()] ?? ''), ...(ngDevMode ? [{ debugName: "rawSvg" }] : /* istanbul ignore next */ []));
258
377
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctIcon, deps: [], target: i0.ɵɵFactoryTarget.Component });
259
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: StrctIcon, isStandalone: true, selector: "strct-icon", inputs: { name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: true, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, strokeWidth: { classPropertyName: "strokeWidth", publicName: "strokeWidth", isSignal: true, isRequired: false, transformFunction: null }, badge: { classPropertyName: "badge", publicName: "badge", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "strct-icon" }, ngImport: i0, template: `@if (isRaw()) {
260
- <span class="strct-icon__raw" [style.width.px]="size()" [style.height.px]="size()" [innerHTML]="rawSvg()"></span>
378
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: StrctIcon, isStandalone: true, selector: "strct-icon", inputs: { name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: true, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, strokeWidth: { classPropertyName: "strokeWidth", publicName: "strokeWidth", isSignal: true, isRequired: false, transformFunction: null }, badge: { classPropertyName: "badge", publicName: "badge", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "strct-icon" }, ngImport: i0, template: `@if (isRaw()) {
379
+ <span
380
+ class="strct-icon__raw"
381
+ [style.width.px]="size()"
382
+ [style.height.px]="size()"
383
+ [innerHTML]="rawSvg()"
384
+ ></span>
261
385
  } @else {
262
386
  <svg
263
387
  viewBox="0 0 16 16"
@@ -269,16 +393,24 @@ class StrctIcon {
269
393
  [style.width.px]="size()"
270
394
  [style.height.px]="size()"
271
395
  [innerHTML]="svg()"
396
+ role="img"
397
+ [attr.aria-label]="ariaLabel() || null"
398
+ [attr.aria-hidden]="ariaLabel() ? null : 'true'"
272
399
  ></svg>
273
400
  }
274
401
  @if (badge() !== 'none') {
275
402
  <span class="strct-icon__badge strct-icon__badge--{{ badge() }}"></span>
276
- }`, isInline: true, styles: [".strct-icon{position:relative;display:inline-flex;align-items:center;justify-content:center;line-height:0}.strct-icon__raw{display:inline-flex}.strct-icon__raw>svg{width:100%;height:100%;display:block}.strct-icon__badge{position:absolute;right:-1px;bottom:-1px;width:38%;height:38%;min-width:6px;min-height:6px;max-width:9px;max-height:9px;border-radius:50%;box-shadow:0 0 0 1.5px var(--bg-1)}.strct-icon__badge--ok{background:var(--ok)}.strct-icon__badge--warn{background:var(--wrn)}.strct-icon__badge--crit{background:var(--crt)}.strct-icon__badge--off{background:var(--t3)}.strct-icon__badge--info{background:var(--acc)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
403
+ }`, isInline: true, styles: [".strct-icon{position:relative;display:inline-flex;align-items:center;justify-content:center;line-height:0}.strct-icon__raw{display:inline-flex}.strct-icon__raw>svg{width:100%;height:100%;display:block}.strct-icon__badge{position:absolute;right:-1px;bottom:-1px;width:38%;height:38%;min-width:6px;min-height:6px;max-width:9px;max-height:9px;border-radius:50%;box-shadow:0 0 0 1.5px var(--bg-1)}.strct-icon__badge--success{background:var(--success)}.strct-icon__badge--warning{background:var(--warning)}.strct-icon__badge--critical{background:var(--critical)}.strct-icon__badge--off{background:var(--t3)}.strct-icon__badge--info{background:var(--acc)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
277
404
  }
278
405
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctIcon, decorators: [{
279
406
  type: Component,
280
407
  args: [{ selector: 'strct-icon', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: `@if (isRaw()) {
281
- <span class="strct-icon__raw" [style.width.px]="size()" [style.height.px]="size()" [innerHTML]="rawSvg()"></span>
408
+ <span
409
+ class="strct-icon__raw"
410
+ [style.width.px]="size()"
411
+ [style.height.px]="size()"
412
+ [innerHTML]="rawSvg()"
413
+ ></span>
282
414
  } @else {
283
415
  <svg
284
416
  viewBox="0 0 16 16"
@@ -290,12 +422,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
290
422
  [style.width.px]="size()"
291
423
  [style.height.px]="size()"
292
424
  [innerHTML]="svg()"
425
+ role="img"
426
+ [attr.aria-label]="ariaLabel() || null"
427
+ [attr.aria-hidden]="ariaLabel() ? null : 'true'"
293
428
  ></svg>
294
429
  }
295
430
  @if (badge() !== 'none') {
296
431
  <span class="strct-icon__badge strct-icon__badge--{{ badge() }}"></span>
297
- }`, host: { class: 'strct-icon' }, styles: [".strct-icon{position:relative;display:inline-flex;align-items:center;justify-content:center;line-height:0}.strct-icon__raw{display:inline-flex}.strct-icon__raw>svg{width:100%;height:100%;display:block}.strct-icon__badge{position:absolute;right:-1px;bottom:-1px;width:38%;height:38%;min-width:6px;min-height:6px;max-width:9px;max-height:9px;border-radius:50%;box-shadow:0 0 0 1.5px var(--bg-1)}.strct-icon__badge--ok{background:var(--ok)}.strct-icon__badge--warn{background:var(--wrn)}.strct-icon__badge--crit{background:var(--crt)}.strct-icon__badge--off{background:var(--t3)}.strct-icon__badge--info{background:var(--acc)}\n"] }]
298
- }], propDecorators: { name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: true }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], strokeWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "strokeWidth", required: false }] }], badge: [{ type: i0.Input, args: [{ isSignal: true, alias: "badge", required: false }] }] } });
432
+ }`, host: { class: 'strct-icon' }, styles: [".strct-icon{position:relative;display:inline-flex;align-items:center;justify-content:center;line-height:0}.strct-icon__raw{display:inline-flex}.strct-icon__raw>svg{width:100%;height:100%;display:block}.strct-icon__badge{position:absolute;right:-1px;bottom:-1px;width:38%;height:38%;min-width:6px;min-height:6px;max-width:9px;max-height:9px;border-radius:50%;box-shadow:0 0 0 1.5px var(--bg-1)}.strct-icon__badge--success{background:var(--success)}.strct-icon__badge--warning{background:var(--warning)}.strct-icon__badge--critical{background:var(--critical)}.strct-icon__badge--off{background:var(--t3)}.strct-icon__badge--info{background:var(--acc)}\n"] }]
433
+ }], propDecorators: { name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: true }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], strokeWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "strokeWidth", required: false }] }], badge: [{ type: i0.Input, args: [{ isSignal: true, alias: "badge", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }] } });
299
434
 
300
435
  /** Palette dots + light/dark pill, wired to {@link StrctThemeService}. */
301
436
  class StrctThemeSwitcher {
@@ -339,7 +474,7 @@ class StrctThemeSwitcher {
339
474
  <strct-icon name="moon" [size]="15" [strokeWidth]="1.5" />
340
475
  </button>
341
476
  </div>
342
- `, isInline: true, styles: [".strct-ts{display:inline-flex;align-items:center;gap:14px}.strct-ts__pal{display:inline-flex;gap:7px}.strct-ts__dot{display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;border-radius:50%;padding:0;cursor:pointer;background:transparent;border:1.5px solid rgba(255,255,255,.35);transition:transform .15s ease,border-color .15s ease}.strct-ts__dot:hover{transform:scale(1.12)}.strct-ts__inner{width:11px;height:11px;border-radius:50%;display:block}.strct-ts__dot--on{border-color:#fff;box-shadow:0 0 0 2px #ffffff40}.strct-ts__pill{display:inline-flex;padding:2px;gap:2px;border-radius:7px;background:#ffffff1a}.strct-ts__pbtn{display:inline-flex;align-items:center;justify-content:center;width:26px;height:22px;border:0;border-radius:5px;cursor:pointer;background:transparent;color:#fff9;transition:background .14s ease,color .14s ease}.strct-ts__pbtn--on{background:#ffffff2e;color:#fff}\n"], dependencies: [{ kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "size", "strokeWidth", "badge"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
477
+ `, isInline: true, styles: [".strct-ts{display:inline-flex;align-items:center;gap:14px}.strct-ts__pal{display:inline-flex;gap:7px}.strct-ts__dot{display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;border-radius:50%;padding:0;cursor:pointer;background:transparent;border:1.5px solid rgba(255,255,255,.35);transition:transform .15s ease,border-color .15s ease}.strct-ts__dot:hover{transform:scale(1.12)}.strct-ts__inner{width:11px;height:11px;border-radius:50%;display:block}.strct-ts__dot--on{border-color:#fff;box-shadow:0 0 0 2px #ffffff40}.strct-ts__pill{display:inline-flex;padding:2px;gap:2px;border-radius:7px;background:#ffffff1a}.strct-ts__pbtn{display:inline-flex;align-items:center;justify-content:center;width:26px;height:22px;border:0;border-radius:5px;cursor:pointer;background:transparent;color:#fff9;transition:background .14s ease,color .14s ease}.strct-ts__pbtn--on{background:#ffffff2e;color:#fff}\n"], dependencies: [{ kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "size", "strokeWidth", "badge", "ariaLabel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
343
478
  }
344
479
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctThemeSwitcher, decorators: [{
345
480
  type: Component,
@@ -400,10 +535,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
400
535
  class StrctOverlay {
401
536
  el = inject((ElementRef)).nativeElement;
402
537
  zone = inject(NgZone);
538
+ /** Anchor element for positioning. */
403
539
  anchor = input.required({ ...(ngDevMode ? { debugName: "anchor" } : /* istanbul ignore next */ {}), alias: 'strctOverlay' });
540
+ /** Preferred placement relative to the anchor. */
404
541
  placement = input('bottom-start', { ...(ngDevMode ? { debugName: "placement" } : /* istanbul ignore next */ {}), alias: 'strctOverlayPlacement' });
405
542
  /** Match the panel width to the anchor (combobox / date / cascade fields). */
406
543
  matchWidth = input(false, { ...(ngDevMode ? { debugName: "matchWidth" } : /* istanbul ignore next */ {}), alias: 'strctOverlayMatchWidth' });
544
+ /** Gap between anchor and panel in pixels. */
407
545
  gap = input(5, { ...(ngDevMode ? { debugName: "gap" } : /* istanbul ignore next */ {}), alias: 'strctOverlayGap' });
408
546
  onScrollResize = () => this.position();
409
547
  bound = false;
@@ -510,14 +648,39 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
510
648
  <ng-content select="strct-footer" />
511
649
  `, host: { class: 'strct-shell' }, styles: [".strct-shell{display:grid;grid-template-rows:auto 1fr auto;height:100vh;overflow:hidden;background:var(--bg-2)}.strct-shell__main{display:flex;min-height:0;overflow:hidden}\n"] }]
512
650
  }] });
651
+ /** Shared layout state between shell parts. */
652
+ class StrctShellService {
653
+ mobileNavOpen = signal(false, ...(ngDevMode ? [{ debugName: "mobileNavOpen" }] : /* istanbul ignore next */ []));
654
+ }
513
655
  /** Top application bar. Holds brand on the left and actions on the right. */
514
656
  class StrctHeader {
657
+ shell = inject(StrctShellService);
515
658
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctHeader, deps: [], target: i0.ɵɵFactoryTarget.Component });
516
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.16", type: StrctHeader, isStandalone: true, selector: "strct-header", host: { classAttribute: "strct-header" }, ngImport: i0, template: `<ng-content />`, isInline: true, styles: [".strct-header{display:flex;align-items:center;gap:14px;height:56px;padding:0 18px;background:var(--hdr);border-bottom:1px solid var(--b2);color:#ffffffeb}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
659
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.16", type: StrctHeader, isStandalone: true, selector: "strct-header", host: { classAttribute: "strct-header" }, ngImport: i0, template: `
660
+ <button
661
+ type="button"
662
+ class="strct-header__drawer-toggle"
663
+ aria-label="Toggle navigation"
664
+ (click)="shell.mobileNavOpen.update((v) => !v)"
665
+ >
666
+ <strct-icon name="menu" [size]="18" />
667
+ </button>
668
+ <ng-content />
669
+ `, isInline: true, styles: [".strct-header{display:flex;align-items:center;gap:14px;height:56px;padding:0 18px;background:var(--hdr);border-bottom:1px solid var(--b2);color:#ffffffeb}.strct-header__drawer-toggle{display:none;align-items:center;justify-content:center;padding:4px;border:0;border-radius:5px;background:transparent;color:#ffffffd9;cursor:pointer}.strct-header__drawer-toggle:hover{background:#ffffff1f;color:#fff}@media(max-width:768px){.strct-header__drawer-toggle{display:inline-flex}}\n"], dependencies: [{ kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "size", "strokeWidth", "badge", "ariaLabel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
517
670
  }
518
671
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctHeader, decorators: [{
519
672
  type: Component,
520
- args: [{ selector: 'strct-header', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: `<ng-content />`, host: { class: 'strct-header' }, styles: [".strct-header{display:flex;align-items:center;gap:14px;height:56px;padding:0 18px;background:var(--hdr);border-bottom:1px solid var(--b2);color:#ffffffeb}\n"] }]
673
+ args: [{ selector: 'strct-header', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [StrctIcon], template: `
674
+ <button
675
+ type="button"
676
+ class="strct-header__drawer-toggle"
677
+ aria-label="Toggle navigation"
678
+ (click)="shell.mobileNavOpen.update((v) => !v)"
679
+ >
680
+ <strct-icon name="menu" [size]="18" />
681
+ </button>
682
+ <ng-content />
683
+ `, host: { class: 'strct-header' }, styles: [".strct-header{display:flex;align-items:center;gap:14px;height:56px;padding:0 18px;background:var(--hdr);border-bottom:1px solid var(--b2);color:#ffffffeb}.strct-header__drawer-toggle{display:none;align-items:center;justify-content:center;padding:4px;border:0;border-radius:5px;background:transparent;color:#ffffffd9;cursor:pointer}.strct-header__drawer-toggle:hover{background:#ffffff1f;color:#fff}@media(max-width:768px){.strct-header__drawer-toggle{display:inline-flex}}\n"] }]
521
684
  }] });
522
685
  /** Bottom status bar. */
523
686
  class StrctFooter {
@@ -531,12 +694,42 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
531
694
 
532
695
  /** Scrollable left sidebar surface. Holds the icon nav and/or a tree. */
533
696
  class StrctVerticalNav {
697
+ shell = inject(StrctShellService);
534
698
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctVerticalNav, deps: [], target: i0.ɵɵFactoryTarget.Component });
535
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.16", type: StrctVerticalNav, isStandalone: true, selector: "strct-vertical-nav", host: { classAttribute: "strct-vnav" }, ngImport: i0, template: `<ng-content />`, isInline: true, styles: [".strct-vnav{display:flex;flex-direction:column;width:264px;flex-shrink:0;background:var(--bg-1);border-right:1px solid var(--b2);overflow:hidden}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
699
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: StrctVerticalNav, isStandalone: true, selector: "strct-vertical-nav", host: { properties: { "class.strct-vnav--open": "shell.mobileNavOpen()" }, classAttribute: "strct-vnav" }, ngImport: i0, template: `
700
+ @if (shell.mobileNavOpen()) {
701
+ <div
702
+ class="strct-vnav__backdrop"
703
+ tabindex="0"
704
+ role="button"
705
+ aria-label="Close navigation"
706
+ (click)="shell.mobileNavOpen.set(false)"
707
+ (keydown.enter)="shell.mobileNavOpen.set(false)"
708
+ (keydown.space)="shell.mobileNavOpen.set(false)"
709
+ ></div>
710
+ }
711
+ <ng-content />
712
+ `, isInline: true, styles: [".strct-vnav{display:flex;flex-direction:column;width:264px;flex-shrink:0;background:var(--bg-1);border-right:1px solid var(--b2);overflow:hidden}@media(max-width:768px){.strct-vnav{position:fixed;top:0;left:0;bottom:0;z-index:300;transform:translate(-100%);transition:transform .2s ease}.strct-vnav--open{transform:translate(0)}.strct-vnav__backdrop{position:fixed;inset:0;z-index:299;background:#00000080;animation:strct-vnav-backdrop-in .2s ease}}@media(min-width:769px){.strct-vnav__backdrop{display:none}}@keyframes strct-vnav-backdrop-in{0%{opacity:0}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
536
713
  }
537
714
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctVerticalNav, decorators: [{
538
715
  type: Component,
539
- args: [{ selector: 'strct-vertical-nav', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: `<ng-content />`, host: { class: 'strct-vnav' }, styles: [".strct-vnav{display:flex;flex-direction:column;width:264px;flex-shrink:0;background:var(--bg-1);border-right:1px solid var(--b2);overflow:hidden}\n"] }]
716
+ args: [{ selector: 'strct-vertical-nav', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: `
717
+ @if (shell.mobileNavOpen()) {
718
+ <div
719
+ class="strct-vnav__backdrop"
720
+ tabindex="0"
721
+ role="button"
722
+ aria-label="Close navigation"
723
+ (click)="shell.mobileNavOpen.set(false)"
724
+ (keydown.enter)="shell.mobileNavOpen.set(false)"
725
+ (keydown.space)="shell.mobileNavOpen.set(false)"
726
+ ></div>
727
+ }
728
+ <ng-content />
729
+ `, host: {
730
+ class: 'strct-vnav',
731
+ '[class.strct-vnav--open]': 'shell.mobileNavOpen()',
732
+ }, styles: [".strct-vnav{display:flex;flex-direction:column;width:264px;flex-shrink:0;background:var(--bg-1);border-right:1px solid var(--b2);overflow:hidden}@media(max-width:768px){.strct-vnav{position:fixed;top:0;left:0;bottom:0;z-index:300;transform:translate(-100%);transition:transform .2s ease}.strct-vnav--open{transform:translate(0)}.strct-vnav__backdrop{position:fixed;inset:0;z-index:299;background:#00000080;animation:strct-vnav-backdrop-in .2s ease}}@media(min-width:769px){.strct-vnav__backdrop{display:none}}@keyframes strct-vnav-backdrop-in{0%{opacity:0}}\n"] }]
540
733
  }] });
541
734
  /** Horizontal strip of icon tabs (e.g. section switcher at the top of a sidebar). */
542
735
  class StrctNav {
@@ -549,7 +742,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
549
742
  }] });
550
743
  /** A single icon tab inside `<strct-nav>`. */
551
744
  class StrctNavItem {
745
+ /** Whether the item is active / selected. */
552
746
  active = input(false, ...(ngDevMode ? [{ debugName: "active" }] : /* istanbul ignore next */ []));
747
+ /** Label text. */
553
748
  label = input('', ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
554
749
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctNavItem, deps: [], target: i0.ɵɵFactoryTarget.Component });
555
750
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.16", type: StrctNavItem, isStandalone: true, selector: "strct-nav-item", inputs: { active: { classPropertyName: "active", publicName: "active", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "button", "tabindex": "0" }, properties: { "class.strct-nav-item--active": "active()", "attr.title": "label() || null", "attr.aria-label": "label() || null", "attr.aria-pressed": "active()" }, classAttribute: "strct-nav-item" }, ngImport: i0, template: `<ng-content />`, isInline: true, styles: [".strct-nav-item{display:inline-flex;align-items:center;justify-content:center;width:34px;height:34px;border-radius:7px;cursor:pointer;color:var(--t2);transition:background .14s ease,color .14s ease}.strct-nav-item:hover{background:var(--bg-3);color:var(--t1)}.strct-nav-item--active{background:var(--acc-m);color:var(--acc)}.strct-nav-item:focus-visible{outline:2px solid var(--acc50);outline-offset:1px}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
@@ -579,7 +774,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
579
774
  * </strct-login>
580
775
  */
581
776
  class StrctLogin {
777
+ /** Maximum width in pixels. */
582
778
  maxWidth = input(880, ...(ngDevMode ? [{ debugName: "maxWidth" }] : /* istanbul ignore next */ []));
779
+ /** Enable two-panel split layout. */
583
780
  split = input(false, { ...(ngDevMode ? { debugName: "split" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
584
781
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctLogin, deps: [], target: i0.ɵɵFactoryTarget.Component });
585
782
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: StrctLogin, isStandalone: true, selector: "strct-login", inputs: { maxWidth: { classPropertyName: "maxWidth", publicName: "maxWidth", isSignal: true, isRequired: false, transformFunction: null }, split: { classPropertyName: "split", publicName: "split", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "strct-login" }, ngImport: i0, template: `
@@ -626,22 +823,25 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
626
823
  * <a strct-button variant="flat" size="sm" href="...">Cancel</a>
627
824
  */
628
825
  class StrctButton {
826
+ /** Visual variant. */
629
827
  variant = input('neutral', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
828
+ /** Size variant. */
630
829
  size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
631
830
  /** Opt in to a filled surface (use sparingly, for the primary action). */
632
831
  solid = input(false, { ...(ngDevMode ? { debugName: "solid" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
832
+ /** Expand to full width. */
633
833
  block = input(false, { ...(ngDevMode ? { debugName: "block" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
634
834
  /** Square padding for a single-icon button. */
635
835
  iconOnly = input(false, { ...(ngDevMode ? { debugName: "iconOnly" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
636
836
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctButton, deps: [], target: i0.ɵɵFactoryTarget.Component });
637
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.16", type: StrctButton, isStandalone: true, selector: "button[strct-button], a[strct-button]", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, solid: { classPropertyName: "solid", publicName: "solid", isSignal: true, isRequired: false, transformFunction: null }, block: { classPropertyName: "block", publicName: "block", isSignal: true, isRequired: false, transformFunction: null }, iconOnly: { classPropertyName: "iconOnly", publicName: "iconOnly", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.strct-btn--primary": "variant() === 'primary'", "class.strct-btn--danger": "variant() === 'danger'", "class.strct-btn--outline": "variant() === 'outline'", "class.strct-btn--flat": "variant() === 'flat'", "class.strct-btn--solid": "solid()", "class.strct-btn--sm": "size() === 'sm'", "class.strct-btn--mini": "size() === 'mini'", "class.strct-btn--block": "block()", "class.strct-btn--icon": "iconOnly()" }, classAttribute: "strct-btn" }, ngImport: i0, template: `<ng-content />`, isInline: true, styles: [".strct-btn{display:inline-flex;align-items:center;justify-content:center;gap:6px;font-family:var(--font);font-size:13px;font-weight:500;line-height:1;padding:7px 14px;border-radius:6px;cursor:pointer;-webkit-user-select:none;user-select:none;color:var(--t1);background:transparent;border:1px solid var(--b3);transition:background .14s ease,border-color .14s ease,color .14s ease,opacity .14s ease;text-decoration:none;white-space:nowrap}.strct-btn:hover{background:var(--bg-3);text-decoration:none}.strct-btn:active{background:var(--bg-a)}.strct-btn:disabled,.strct-btn[aria-disabled=true]{opacity:.45;cursor:not-allowed}.strct-btn--primary{border-color:var(--acc50);color:var(--acc)}.strct-btn--primary:hover{background:var(--acc-m);border-color:var(--acc)}.strct-btn--danger{border-color:var(--crt);color:var(--crt)}.strct-btn--danger:hover{background:var(--crt-bg)}.strct-btn--outline{border-color:var(--b3);color:var(--t1)}.strct-btn--outline:hover{background:var(--bg-3)}.strct-btn--flat{border-color:transparent;color:var(--t2)}.strct-btn--flat:hover{background:var(--bg-3);color:var(--t1)}.strct-btn--solid{background:var(--bg-3);border-color:transparent;color:var(--t1)}.strct-btn--solid:hover{background:var(--bg-h)}.strct-btn--solid.strct-btn--primary{background:var(--acc);color:#fff}.strct-btn--solid.strct-btn--primary:hover{background:var(--acc);filter:brightness(1.08)}.strct-btn--solid.strct-btn--danger{background:var(--crt);color:#fff}.strct-btn--solid.strct-btn--danger:hover{background:var(--crt);filter:brightness(1.08)}.strct-btn--sm{padding:4px 10px;font-size:12px;border-radius:5px}.strct-btn--mini{padding:2px 8px;font-size:11px;border-radius:4px}.strct-btn--block{display:flex;width:100%}.strct-btn--icon{padding:7px}.strct-btn--icon.strct-btn--sm{padding:5px}.strct-btn--icon.strct-btn--mini{padding:3px}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
837
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.16", type: StrctButton, isStandalone: true, selector: "button[strct-button], a[strct-button]", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, solid: { classPropertyName: "solid", publicName: "solid", isSignal: true, isRequired: false, transformFunction: null }, block: { classPropertyName: "block", publicName: "block", isSignal: true, isRequired: false, transformFunction: null }, iconOnly: { classPropertyName: "iconOnly", publicName: "iconOnly", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.strct-btn--primary": "variant() === 'primary'", "class.strct-btn--critical": "variant() === 'critical'", "class.strct-btn--outline": "variant() === 'outline'", "class.strct-btn--flat": "variant() === 'flat'", "class.strct-btn--solid": "solid()", "class.strct-btn--sm": "size() === 'sm'", "class.strct-btn--mini": "size() === 'mini'", "class.strct-btn--block": "block()", "class.strct-btn--icon": "iconOnly()" }, classAttribute: "strct-btn" }, ngImport: i0, template: `<ng-content />`, isInline: true, styles: [".strct-btn{display:inline-flex;align-items:center;justify-content:center;gap:var(--space-1);font-family:var(--font);font-size:13px;font-weight:500;line-height:1;padding:var(--space-2) var(--space-4);border-radius:var(--radius-md);cursor:pointer;-webkit-user-select:none;user-select:none;color:var(--t1);background:transparent;border:1px solid var(--b3);transition:background .14s ease,border-color .14s ease,color .14s ease,opacity .14s ease;text-decoration:none;white-space:nowrap}.strct-btn:hover{background:var(--bg-3);text-decoration:none}.strct-btn:active{background:var(--bg-a)}.strct-btn:disabled,.strct-btn[aria-disabled=true]{opacity:.45;cursor:not-allowed}.strct-btn--primary{border-color:var(--acc50);color:var(--acc)}.strct-btn--primary:hover{background:var(--acc-m);border-color:var(--acc)}.strct-btn--critical{border-color:var(--critical);color:var(--critical)}.strct-btn--critical:hover{background:var(--critical-bg)}.strct-btn--outline{border-color:var(--b3);color:var(--t1)}.strct-btn--outline:hover{background:var(--bg-3)}.strct-btn--flat{border-color:transparent;color:var(--t2)}.strct-btn--flat:hover{background:var(--bg-3);color:var(--t1)}.strct-btn--solid{background:var(--bg-3);border-color:transparent;color:var(--t1)}.strct-btn--solid:hover{background:var(--bg-h)}.strct-btn--solid.strct-btn--primary{background:var(--acc);color:#fff}.strct-btn--solid.strct-btn--primary:hover{background:var(--acc);filter:brightness(1.08)}.strct-btn--solid.strct-btn--critical{background:var(--critical);color:#fff}.strct-btn--solid.strct-btn--critical:hover{background:var(--critical);filter:brightness(1.08)}.strct-btn--sm{padding:var(--space-1) var(--space-3);font-size:12px;border-radius:var(--radius-sm)}.strct-btn--mini{padding:2px var(--space-2);font-size:11px;border-radius:var(--radius-sm)}.strct-btn--block{display:flex;width:100%}.strct-btn--icon{padding:var(--space-2)}.strct-btn--icon.strct-btn--sm{padding:var(--space-1)}.strct-btn--icon.strct-btn--mini{padding:3px}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
638
838
  }
639
839
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctButton, decorators: [{
640
840
  type: Component,
641
841
  args: [{ selector: 'button[strct-button], a[strct-button]', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: `<ng-content />`, host: {
642
842
  class: 'strct-btn',
643
843
  '[class.strct-btn--primary]': "variant() === 'primary'",
644
- '[class.strct-btn--danger]': "variant() === 'danger'",
844
+ '[class.strct-btn--critical]': "variant() === 'critical'",
645
845
  '[class.strct-btn--outline]': "variant() === 'outline'",
646
846
  '[class.strct-btn--flat]': "variant() === 'flat'",
647
847
  '[class.strct-btn--solid]': 'solid()',
@@ -649,25 +849,26 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
649
849
  '[class.strct-btn--mini]': "size() === 'mini'",
650
850
  '[class.strct-btn--block]': 'block()',
651
851
  '[class.strct-btn--icon]': 'iconOnly()',
652
- }, styles: [".strct-btn{display:inline-flex;align-items:center;justify-content:center;gap:6px;font-family:var(--font);font-size:13px;font-weight:500;line-height:1;padding:7px 14px;border-radius:6px;cursor:pointer;-webkit-user-select:none;user-select:none;color:var(--t1);background:transparent;border:1px solid var(--b3);transition:background .14s ease,border-color .14s ease,color .14s ease,opacity .14s ease;text-decoration:none;white-space:nowrap}.strct-btn:hover{background:var(--bg-3);text-decoration:none}.strct-btn:active{background:var(--bg-a)}.strct-btn:disabled,.strct-btn[aria-disabled=true]{opacity:.45;cursor:not-allowed}.strct-btn--primary{border-color:var(--acc50);color:var(--acc)}.strct-btn--primary:hover{background:var(--acc-m);border-color:var(--acc)}.strct-btn--danger{border-color:var(--crt);color:var(--crt)}.strct-btn--danger:hover{background:var(--crt-bg)}.strct-btn--outline{border-color:var(--b3);color:var(--t1)}.strct-btn--outline:hover{background:var(--bg-3)}.strct-btn--flat{border-color:transparent;color:var(--t2)}.strct-btn--flat:hover{background:var(--bg-3);color:var(--t1)}.strct-btn--solid{background:var(--bg-3);border-color:transparent;color:var(--t1)}.strct-btn--solid:hover{background:var(--bg-h)}.strct-btn--solid.strct-btn--primary{background:var(--acc);color:#fff}.strct-btn--solid.strct-btn--primary:hover{background:var(--acc);filter:brightness(1.08)}.strct-btn--solid.strct-btn--danger{background:var(--crt);color:#fff}.strct-btn--solid.strct-btn--danger:hover{background:var(--crt);filter:brightness(1.08)}.strct-btn--sm{padding:4px 10px;font-size:12px;border-radius:5px}.strct-btn--mini{padding:2px 8px;font-size:11px;border-radius:4px}.strct-btn--block{display:flex;width:100%}.strct-btn--icon{padding:7px}.strct-btn--icon.strct-btn--sm{padding:5px}.strct-btn--icon.strct-btn--mini{padding:3px}\n"] }]
852
+ }, styles: [".strct-btn{display:inline-flex;align-items:center;justify-content:center;gap:var(--space-1);font-family:var(--font);font-size:13px;font-weight:500;line-height:1;padding:var(--space-2) var(--space-4);border-radius:var(--radius-md);cursor:pointer;-webkit-user-select:none;user-select:none;color:var(--t1);background:transparent;border:1px solid var(--b3);transition:background .14s ease,border-color .14s ease,color .14s ease,opacity .14s ease;text-decoration:none;white-space:nowrap}.strct-btn:hover{background:var(--bg-3);text-decoration:none}.strct-btn:active{background:var(--bg-a)}.strct-btn:disabled,.strct-btn[aria-disabled=true]{opacity:.45;cursor:not-allowed}.strct-btn--primary{border-color:var(--acc50);color:var(--acc)}.strct-btn--primary:hover{background:var(--acc-m);border-color:var(--acc)}.strct-btn--critical{border-color:var(--critical);color:var(--critical)}.strct-btn--critical:hover{background:var(--critical-bg)}.strct-btn--outline{border-color:var(--b3);color:var(--t1)}.strct-btn--outline:hover{background:var(--bg-3)}.strct-btn--flat{border-color:transparent;color:var(--t2)}.strct-btn--flat:hover{background:var(--bg-3);color:var(--t1)}.strct-btn--solid{background:var(--bg-3);border-color:transparent;color:var(--t1)}.strct-btn--solid:hover{background:var(--bg-h)}.strct-btn--solid.strct-btn--primary{background:var(--acc);color:#fff}.strct-btn--solid.strct-btn--primary:hover{background:var(--acc);filter:brightness(1.08)}.strct-btn--solid.strct-btn--critical{background:var(--critical);color:#fff}.strct-btn--solid.strct-btn--critical:hover{background:var(--critical);filter:brightness(1.08)}.strct-btn--sm{padding:var(--space-1) var(--space-3);font-size:12px;border-radius:var(--radius-sm)}.strct-btn--mini{padding:2px var(--space-2);font-size:11px;border-radius:var(--radius-sm)}.strct-btn--block{display:flex;width:100%}.strct-btn--icon{padding:var(--space-2)}.strct-btn--icon.strct-btn--sm{padding:var(--space-1)}.strct-btn--icon.strct-btn--mini{padding:3px}\n"] }]
653
853
  }], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], solid: [{ type: i0.Input, args: [{ isSignal: true, alias: "solid", required: false }] }], block: [{ type: i0.Input, args: [{ isSignal: true, alias: "block", required: false }] }], iconOnly: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconOnly", required: false }] }] } });
654
854
  /** Segments adjacent buttons into a single joined control. */
655
855
  class StrctButtonGroup {
656
856
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctButtonGroup, deps: [], target: i0.ɵɵFactoryTarget.Component });
657
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.16", type: StrctButtonGroup, isStandalone: true, selector: "strct-button-group", host: { attributes: { "role": "group" }, classAttribute: "strct-btn-group" }, ngImport: i0, template: `<ng-content />`, isInline: true, styles: [".strct-btn-group{display:inline-flex}.strct-btn-group>.strct-btn{border-radius:0}.strct-btn-group>.strct-btn:not(:first-child){margin-left:-1px}.strct-btn-group>.strct-btn:first-child{border-top-left-radius:6px;border-bottom-left-radius:6px}.strct-btn-group>.strct-btn:last-child{border-top-right-radius:6px;border-bottom-right-radius:6px}.strct-btn-group>.strct-btn:hover,.strct-btn-group>.strct-btn:focus-visible{position:relative;z-index:1}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
857
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.16", type: StrctButtonGroup, isStandalone: true, selector: "strct-button-group", host: { attributes: { "role": "group" }, classAttribute: "strct-btn-group" }, ngImport: i0, template: `<ng-content />`, isInline: true, styles: [".strct-btn-group{display:inline-flex}.strct-btn-group>.strct-btn{border-radius:0}.strct-btn-group>.strct-btn:not(:first-child){margin-left:-1px}.strct-btn-group>.strct-btn:first-child{border-top-left-radius:var(--radius-md);border-bottom-left-radius:var(--radius-md)}.strct-btn-group>.strct-btn:last-child{border-top-right-radius:var(--radius-md);border-bottom-right-radius:var(--radius-md)}.strct-btn-group>.strct-btn:hover,.strct-btn-group>.strct-btn:focus-visible{position:relative;z-index:1}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
658
858
  }
659
859
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctButtonGroup, decorators: [{
660
860
  type: Component,
661
- args: [{ selector: 'strct-button-group', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: `<ng-content />`, host: { class: 'strct-btn-group', role: 'group' }, styles: [".strct-btn-group{display:inline-flex}.strct-btn-group>.strct-btn{border-radius:0}.strct-btn-group>.strct-btn:not(:first-child){margin-left:-1px}.strct-btn-group>.strct-btn:first-child{border-top-left-radius:6px;border-bottom-left-radius:6px}.strct-btn-group>.strct-btn:last-child{border-top-right-radius:6px;border-bottom-right-radius:6px}.strct-btn-group>.strct-btn:hover,.strct-btn-group>.strct-btn:focus-visible{position:relative;z-index:1}\n"] }]
861
+ args: [{ selector: 'strct-button-group', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: `<ng-content />`, host: { class: 'strct-btn-group', role: 'group' }, styles: [".strct-btn-group{display:inline-flex}.strct-btn-group>.strct-btn{border-radius:0}.strct-btn-group>.strct-btn:not(:first-child){margin-left:-1px}.strct-btn-group>.strct-btn:first-child{border-top-left-radius:var(--radius-md);border-bottom-left-radius:var(--radius-md)}.strct-btn-group>.strct-btn:last-child{border-top-right-radius:var(--radius-md);border-bottom-right-radius:var(--radius-md)}.strct-btn-group>.strct-btn:hover,.strct-btn-group>.strct-btn:focus-visible{position:relative;z-index:1}\n"] }]
662
862
  }] });
663
863
 
664
864
  /** Small inline status pill: `<strct-badge status="success">Active</strct-badge>`. */
665
865
  class StrctBadge {
866
+ /** Visual status color. */
666
867
  status = input('neutral', ...(ngDevMode ? [{ debugName: "status" }] : /* istanbul ignore next */ []));
667
868
  /** Opt-in filled style instead of the default outlined style. */
668
869
  solid = input(false, { ...(ngDevMode ? { debugName: "solid" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
669
870
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctBadge, deps: [], target: i0.ɵɵFactoryTarget.Component });
670
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.16", type: StrctBadge, isStandalone: true, selector: "strct-badge", inputs: { status: { classPropertyName: "status", publicName: "status", isSignal: true, isRequired: false, transformFunction: null }, solid: { classPropertyName: "solid", publicName: "solid", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.strct-badge--accent": "status() === 'accent'", "class.strct-badge--success": "status() === 'success'", "class.strct-badge--warning": "status() === 'warning'", "class.strct-badge--danger": "status() === 'danger'", "class.strct-badge--solid": "solid()" }, classAttribute: "strct-badge" }, ngImport: i0, template: `<ng-content />`, isInline: true, styles: [".strct-badge{display:inline-flex;align-items:center;gap:4px;font-size:11px;font-weight:600;line-height:1;letter-spacing:.2px;padding:3px 7px 3px 9px;border-radius:4px;white-space:nowrap;color:var(--t2);background:transparent;border:1px solid var(--b3);border-left-width:3px}.strct-badge--accent{color:var(--acc);border-color:var(--acc30)}.strct-badge--success{color:var(--ok);border-color:var(--ok)}.strct-badge--warning{color:var(--wrn);border-color:var(--wrn)}.strct-badge--danger{color:var(--crt);border-color:var(--crt)}.strct-badge--solid{color:var(--t1);background:var(--bg-a);border-color:transparent;border-left-width:1px;padding-left:7px}.strct-badge--solid.strct-badge--accent{background:var(--acc);color:#fff}.strct-badge--solid.strct-badge--success{background:var(--ok);color:#fff}.strct-badge--solid.strct-badge--warning{background:var(--wrn);color:#fff}.strct-badge--solid.strct-badge--danger{background:var(--crt);color:#fff}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
871
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.16", type: StrctBadge, isStandalone: true, selector: "strct-badge", inputs: { status: { classPropertyName: "status", publicName: "status", isSignal: true, isRequired: false, transformFunction: null }, solid: { classPropertyName: "solid", publicName: "solid", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.strct-badge--accent": "status() === 'accent'", "class.strct-badge--success": "status() === 'success'", "class.strct-badge--warninging": "status() === 'warning'", "class.strct-badge--critical": "status() === 'critical'", "class.strct-badge--solid": "solid()" }, classAttribute: "strct-badge" }, ngImport: i0, template: `<ng-content />`, isInline: true, styles: [".strct-badge{display:inline-flex;align-items:center;gap:4px;font-size:11px;font-weight:600;line-height:1;letter-spacing:.2px;padding:3px 7px 3px 9px;border-radius:var(--radius-sm);white-space:nowrap;color:var(--t2);background:transparent;border:1px solid var(--b3);border-left-width:3px}.strct-badge--accent{color:var(--acc);border-color:var(--acc30)}.strct-badge--success{color:var(--success);border-color:var(--success)}.strct-badge--warninging{color:var(--warning);border-color:var(--warning)}.strct-badge--critical{color:var(--critical);border-color:var(--critical)}.strct-badge--solid{color:var(--t1);background:var(--bg-a);border-color:transparent;border-left-width:1px;padding-left:7px}.strct-badge--solid.strct-badge--accent{background:var(--acc);color:#fff}.strct-badge--solid.strct-badge--success{background:var(--success);color:#fff}.strct-badge--solid.strct-badge--warninging{background:var(--warning);color:#fff}.strct-badge--solid.strct-badge--critical{background:var(--critical);color:#fff}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
671
872
  }
672
873
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctBadge, decorators: [{
673
874
  type: Component,
@@ -675,10 +876,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
675
876
  class: 'strct-badge',
676
877
  '[class.strct-badge--accent]': "status() === 'accent'",
677
878
  '[class.strct-badge--success]': "status() === 'success'",
678
- '[class.strct-badge--warning]': "status() === 'warning'",
679
- '[class.strct-badge--danger]': "status() === 'danger'",
879
+ '[class.strct-badge--warninging]': "status() === 'warning'",
880
+ '[class.strct-badge--critical]': "status() === 'critical'",
680
881
  '[class.strct-badge--solid]': 'solid()',
681
- }, styles: [".strct-badge{display:inline-flex;align-items:center;gap:4px;font-size:11px;font-weight:600;line-height:1;letter-spacing:.2px;padding:3px 7px 3px 9px;border-radius:4px;white-space:nowrap;color:var(--t2);background:transparent;border:1px solid var(--b3);border-left-width:3px}.strct-badge--accent{color:var(--acc);border-color:var(--acc30)}.strct-badge--success{color:var(--ok);border-color:var(--ok)}.strct-badge--warning{color:var(--wrn);border-color:var(--wrn)}.strct-badge--danger{color:var(--crt);border-color:var(--crt)}.strct-badge--solid{color:var(--t1);background:var(--bg-a);border-color:transparent;border-left-width:1px;padding-left:7px}.strct-badge--solid.strct-badge--accent{background:var(--acc);color:#fff}.strct-badge--solid.strct-badge--success{background:var(--ok);color:#fff}.strct-badge--solid.strct-badge--warning{background:var(--wrn);color:#fff}.strct-badge--solid.strct-badge--danger{background:var(--crt);color:#fff}\n"] }]
882
+ }, styles: [".strct-badge{display:inline-flex;align-items:center;gap:4px;font-size:11px;font-weight:600;line-height:1;letter-spacing:.2px;padding:3px 7px 3px 9px;border-radius:var(--radius-sm);white-space:nowrap;color:var(--t2);background:transparent;border:1px solid var(--b3);border-left-width:3px}.strct-badge--accent{color:var(--acc);border-color:var(--acc30)}.strct-badge--success{color:var(--success);border-color:var(--success)}.strct-badge--warninging{color:var(--warning);border-color:var(--warning)}.strct-badge--critical{color:var(--critical);border-color:var(--critical)}.strct-badge--solid{color:var(--t1);background:var(--bg-a);border-color:transparent;border-left-width:1px;padding-left:7px}.strct-badge--solid.strct-badge--accent{background:var(--acc);color:#fff}.strct-badge--solid.strct-badge--success{background:var(--success);color:#fff}.strct-badge--solid.strct-badge--warninging{background:var(--warning);color:#fff}.strct-badge--solid.strct-badge--critical{background:var(--critical);color:#fff}\n"] }]
682
883
  }], propDecorators: { status: [{ type: i0.Input, args: [{ isSignal: true, alias: "status", required: false }] }], solid: [{ type: i0.Input, args: [{ isSignal: true, alias: "solid", required: false }] }] } });
683
884
 
684
885
  /**
@@ -686,18 +887,21 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
686
887
  * <strct-tag status="accent" removable (removed)="drop()">Frontend</strct-tag>
687
888
  */
688
889
  class StrctTag {
890
+ /** Visual status color. */
689
891
  status = input('neutral', ...(ngDevMode ? [{ debugName: "status" }] : /* istanbul ignore next */ []));
892
+ /** Show a remove button. */
690
893
  removable = input(false, { ...(ngDevMode ? { debugName: "removable" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
894
+ /** Emitted when the user clicks the remove button. */
691
895
  removed = output();
692
896
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctTag, deps: [], target: i0.ɵɵFactoryTarget.Component });
693
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: StrctTag, isStandalone: true, selector: "strct-tag", inputs: { status: { classPropertyName: "status", publicName: "status", isSignal: true, isRequired: false, transformFunction: null }, removable: { classPropertyName: "removable", publicName: "removable", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { removed: "removed" }, host: { properties: { "class.strct-tag--accent": "status() === 'accent'", "class.strct-tag--success": "status() === 'success'", "class.strct-tag--warning": "status() === 'warning'", "class.strct-tag--danger": "status() === 'danger'" }, classAttribute: "strct-tag" }, ngImport: i0, template: `
897
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: StrctTag, isStandalone: true, selector: "strct-tag", inputs: { status: { classPropertyName: "status", publicName: "status", isSignal: true, isRequired: false, transformFunction: null }, removable: { classPropertyName: "removable", publicName: "removable", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { removed: "removed" }, host: { properties: { "class.strct-tag--accent": "status() === 'accent'", "class.strct-tag--success": "status() === 'success'", "class.strct-tag--warning": "status() === 'warning'", "class.strct-tag--critical": "status() === 'critical'" }, classAttribute: "strct-tag" }, ngImport: i0, template: `
694
898
  <span class="strct-tag__text"><ng-content /></span>
695
899
  @if (removable()) {
696
900
  <button type="button" class="strct-tag__remove" aria-label="Remove" (click)="removed.emit()">
697
901
  <strct-icon name="close" [size]="11" [strokeWidth]="1.6" />
698
902
  </button>
699
903
  }
700
- `, isInline: true, styles: [".strct-tag{display:inline-flex;align-items:center;gap:5px;padding:3px 4px 3px 9px;border-radius:4px;font-size:12px;font-weight:500;color:var(--t1);background:var(--bg-3);border:1px solid var(--b2)}.strct-tag:not(:has(.strct-tag__remove)){padding-right:9px}.strct-tag--accent{color:var(--acc);border-color:var(--acc30);background:var(--acc-s)}.strct-tag--success{color:var(--ok);border-color:var(--ok);background:transparent}.strct-tag--warning{color:var(--wrn);border-color:var(--wrn);background:transparent}.strct-tag--danger{color:var(--crt);border-color:var(--crt);background:transparent}.strct-tag__remove{display:inline-flex;padding:2px;border:0;border-radius:3px;background:transparent;color:currentColor;opacity:.65;cursor:pointer}.strct-tag__remove:hover{opacity:1;background:var(--dn)}\n"], dependencies: [{ kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "size", "strokeWidth", "badge"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
904
+ `, isInline: true, styles: [".strct-tag{display:inline-flex;align-items:center;gap:5px;padding:3px 4px 3px 9px;border-radius:4px;font-size:12px;font-weight:500;color:var(--t1);background:var(--bg-3);border:1px solid var(--b2)}.strct-tag:not(:has(.strct-tag__remove)){padding-right:9px}.strct-tag--accent{color:var(--acc);border-color:var(--acc30);background:var(--acc-s)}.strct-tag--success{color:var(--success);border-color:var(--success);background:transparent}.strct-tag--warning{color:var(--warning);border-color:var(--warning);background:transparent}.strct-tag--critical{color:var(--critical);border-color:var(--critical);background:transparent}.strct-tag__remove{display:inline-flex;padding:2px;border:0;border-radius:3px;background:transparent;color:currentColor;opacity:.65;cursor:pointer}.strct-tag__remove:hover{opacity:1;background:var(--dn)}\n"], dependencies: [{ kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "size", "strokeWidth", "badge", "ariaLabel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
701
905
  }
702
906
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctTag, decorators: [{
703
907
  type: Component,
@@ -713,8 +917,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
713
917
  '[class.strct-tag--accent]': "status() === 'accent'",
714
918
  '[class.strct-tag--success]': "status() === 'success'",
715
919
  '[class.strct-tag--warning]': "status() === 'warning'",
716
- '[class.strct-tag--danger]': "status() === 'danger'",
717
- }, styles: [".strct-tag{display:inline-flex;align-items:center;gap:5px;padding:3px 4px 3px 9px;border-radius:4px;font-size:12px;font-weight:500;color:var(--t1);background:var(--bg-3);border:1px solid var(--b2)}.strct-tag:not(:has(.strct-tag__remove)){padding-right:9px}.strct-tag--accent{color:var(--acc);border-color:var(--acc30);background:var(--acc-s)}.strct-tag--success{color:var(--ok);border-color:var(--ok);background:transparent}.strct-tag--warning{color:var(--wrn);border-color:var(--wrn);background:transparent}.strct-tag--danger{color:var(--crt);border-color:var(--crt);background:transparent}.strct-tag__remove{display:inline-flex;padding:2px;border:0;border-radius:3px;background:transparent;color:currentColor;opacity:.65;cursor:pointer}.strct-tag__remove:hover{opacity:1;background:var(--dn)}\n"] }]
920
+ '[class.strct-tag--critical]': "status() === 'critical'",
921
+ }, styles: [".strct-tag{display:inline-flex;align-items:center;gap:5px;padding:3px 4px 3px 9px;border-radius:4px;font-size:12px;font-weight:500;color:var(--t1);background:var(--bg-3);border:1px solid var(--b2)}.strct-tag:not(:has(.strct-tag__remove)){padding-right:9px}.strct-tag--accent{color:var(--acc);border-color:var(--acc30);background:var(--acc-s)}.strct-tag--success{color:var(--success);border-color:var(--success);background:transparent}.strct-tag--warning{color:var(--warning);border-color:var(--warning);background:transparent}.strct-tag--critical{color:var(--critical);border-color:var(--critical);background:transparent}.strct-tag__remove{display:inline-flex;padding:2px;border:0;border-radius:3px;background:transparent;color:currentColor;opacity:.65;cursor:pointer}.strct-tag__remove:hover{opacity:1;background:var(--dn)}\n"] }]
718
922
  }], propDecorators: { status: [{ type: i0.Input, args: [{ isSignal: true, alias: "status", required: false }] }], removable: [{ type: i0.Input, args: [{ isSignal: true, alias: "removable", required: false }] }], removed: [{ type: i0.Output, args: ["removed"] }] } });
719
923
 
720
924
  /**
@@ -722,9 +926,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
722
926
  * <strct-avatar name="Ada Lovelace" status="online" />
723
927
  */
724
928
  class StrctAvatar {
929
+ /** Image URL. */
725
930
  src = input('', ...(ngDevMode ? [{ debugName: "src" }] : /* istanbul ignore next */ []));
931
+ /** Display name (used for initials when src is absent). */
726
932
  name = input('', ...(ngDevMode ? [{ debugName: "name" }] : /* istanbul ignore next */ []));
933
+ /** Size variant. */
727
934
  size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
935
+ /** Visual status color. */
728
936
  status = input('none', ...(ngDevMode ? [{ debugName: "status" }] : /* istanbul ignore next */ []));
729
937
  initials = computed(() => {
730
938
  const parts = this.name().trim().split(/\s+/).filter(Boolean);
@@ -744,7 +952,7 @@ class StrctAvatar {
744
952
  @if (status() !== 'none') {
745
953
  <span class="strct-av__status"></span>
746
954
  }
747
- `, isInline: true, styles: [".strct-av{position:relative;display:inline-flex;align-items:center;justify-content:center;width:36px;height:36px;border-radius:50%;flex-shrink:0;background:var(--bg-3);color:var(--t1);overflow:visible;font-size:13px;font-weight:600;-webkit-user-select:none;user-select:none;border:1px solid var(--b2)}.strct-av--sm{width:26px;height:26px;font-size:11px}.strct-av--lg{width:48px;height:48px;font-size:17px}.strct-av__img{width:100%;height:100%;border-radius:50%;object-fit:cover}.strct-av__initials{line-height:1}.strct-av__status{position:absolute;right:-1px;bottom:-1px;width:30%;height:30%;min-width:8px;min-height:8px;border-radius:50%;border:2px solid var(--bg-1);background:var(--t3)}.strct-av--online .strct-av__status{background:var(--ok)}.strct-av--busy .strct-av__status{background:var(--crt)}.strct-av--offline .strct-av__status{background:var(--t3)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
955
+ `, isInline: true, styles: [".strct-av{position:relative;display:inline-flex;align-items:center;justify-content:center;width:36px;height:36px;border-radius:50%;flex-shrink:0;background:var(--bg-3);color:var(--t1);overflow:visible;font-size:13px;font-weight:600;-webkit-user-select:none;user-select:none;border:1px solid var(--b2)}.strct-av--sm{width:26px;height:26px;font-size:11px}.strct-av--lg{width:48px;height:48px;font-size:17px}.strct-av__img{width:100%;height:100%;border-radius:50%;object-fit:cover}.strct-av__initials{line-height:1}.strct-av__status{position:absolute;right:-1px;bottom:-1px;width:30%;height:30%;min-width:8px;min-height:8px;border-radius:50%;border:2px solid var(--bg-1);background:var(--t3)}.strct-av--online .strct-av__status{background:var(--success)}.strct-av--busy .strct-av__status{background:var(--critical)}.strct-av--offline .strct-av__status{background:var(--t3)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
748
956
  }
749
957
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctAvatar, decorators: [{
750
958
  type: Component,
@@ -765,16 +973,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
765
973
  '[class.strct-av--busy]': "status() === 'busy'",
766
974
  '[class.strct-av--offline]': "status() === 'offline'",
767
975
  '[attr.title]': 'name() || null',
768
- }, styles: [".strct-av{position:relative;display:inline-flex;align-items:center;justify-content:center;width:36px;height:36px;border-radius:50%;flex-shrink:0;background:var(--bg-3);color:var(--t1);overflow:visible;font-size:13px;font-weight:600;-webkit-user-select:none;user-select:none;border:1px solid var(--b2)}.strct-av--sm{width:26px;height:26px;font-size:11px}.strct-av--lg{width:48px;height:48px;font-size:17px}.strct-av__img{width:100%;height:100%;border-radius:50%;object-fit:cover}.strct-av__initials{line-height:1}.strct-av__status{position:absolute;right:-1px;bottom:-1px;width:30%;height:30%;min-width:8px;min-height:8px;border-radius:50%;border:2px solid var(--bg-1);background:var(--t3)}.strct-av--online .strct-av__status{background:var(--ok)}.strct-av--busy .strct-av__status{background:var(--crt)}.strct-av--offline .strct-av__status{background:var(--t3)}\n"] }]
976
+ }, styles: [".strct-av{position:relative;display:inline-flex;align-items:center;justify-content:center;width:36px;height:36px;border-radius:50%;flex-shrink:0;background:var(--bg-3);color:var(--t1);overflow:visible;font-size:13px;font-weight:600;-webkit-user-select:none;user-select:none;border:1px solid var(--b2)}.strct-av--sm{width:26px;height:26px;font-size:11px}.strct-av--lg{width:48px;height:48px;font-size:17px}.strct-av__img{width:100%;height:100%;border-radius:50%;object-fit:cover}.strct-av__initials{line-height:1}.strct-av__status{position:absolute;right:-1px;bottom:-1px;width:30%;height:30%;min-width:8px;min-height:8px;border-radius:50%;border:2px solid var(--bg-1);background:var(--t3)}.strct-av--online .strct-av__status{background:var(--success)}.strct-av--busy .strct-av__status{background:var(--critical)}.strct-av--offline .strct-av__status{background:var(--t3)}\n"] }]
769
977
  }], propDecorators: { src: [{ type: i0.Input, args: [{ isSignal: true, alias: "src", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], status: [{ type: i0.Input, args: [{ isSignal: true, alias: "status", required: false }] }] } });
770
978
 
771
979
  /** Horizontal value/usage bar. `<strct-progress [value]="72" status="warning" />`. */
772
980
  class StrctProgress {
981
+ /** Current value. */
773
982
  value = input(0, ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
983
+ /** Visual status color. */
774
984
  status = input('accent', ...(ngDevMode ? [{ debugName: "status" }] : /* istanbul ignore next */ []));
775
985
  clamped = computed(() => Math.max(0, Math.min(100, this.value())), ...(ngDevMode ? [{ debugName: "clamped" }] : /* istanbul ignore next */ []));
776
986
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctProgress, deps: [], target: i0.ɵɵFactoryTarget.Component });
777
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.16", type: StrctProgress, isStandalone: true, selector: "strct-progress", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, status: { classPropertyName: "status", publicName: "status", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.strct-progress--success": "status() === 'success'", "class.strct-progress--warning": "status() === 'warning'", "class.strct-progress--danger": "status() === 'danger'" }, classAttribute: "strct-progress" }, ngImport: i0, template: `
987
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.16", type: StrctProgress, isStandalone: true, selector: "strct-progress", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, status: { classPropertyName: "status", publicName: "status", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.strct-progress--success": "status() === 'success'", "class.strct-progress--warning": "status() === 'warning'", "class.strct-progress--critical": "status() === 'critical'" }, classAttribute: "strct-progress" }, ngImport: i0, template: `
778
988
  <div
779
989
  class="strct-progress__track"
780
990
  role="progressbar"
@@ -784,7 +994,7 @@ class StrctProgress {
784
994
  >
785
995
  <div class="strct-progress__fill" [style.width.%]="clamped()"></div>
786
996
  </div>
787
- `, isInline: true, styles: [".strct-progress{display:block}.strct-progress__track{height:6px;border-radius:4px;background:var(--bg-3);overflow:hidden}.strct-progress__fill{height:100%;border-radius:4px;background:var(--acc);transition:width .3s ease}.strct-progress--success .strct-progress__fill{background:var(--ok)}.strct-progress--warning .strct-progress__fill{background:var(--wrn)}.strct-progress--danger .strct-progress__fill{background:var(--crt)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
997
+ `, isInline: true, styles: [".strct-progress{display:block}.strct-progress__track{height:6px;border-radius:4px;background:var(--bg-3);overflow:hidden}.strct-progress__fill{height:100%;border-radius:4px;background:var(--acc);transition:width .3s ease}.strct-progress--success .strct-progress__fill{background:var(--success)}.strct-progress--warning .strct-progress__fill{background:var(--warning)}.strct-progress--critical .strct-progress__fill{background:var(--critical)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
788
998
  }
789
999
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctProgress, decorators: [{
790
1000
  type: Component,
@@ -802,12 +1012,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
802
1012
  class: 'strct-progress',
803
1013
  '[class.strct-progress--success]': "status() === 'success'",
804
1014
  '[class.strct-progress--warning]': "status() === 'warning'",
805
- '[class.strct-progress--danger]': "status() === 'danger'",
806
- }, styles: [".strct-progress{display:block}.strct-progress__track{height:6px;border-radius:4px;background:var(--bg-3);overflow:hidden}.strct-progress__fill{height:100%;border-radius:4px;background:var(--acc);transition:width .3s ease}.strct-progress--success .strct-progress__fill{background:var(--ok)}.strct-progress--warning .strct-progress__fill{background:var(--wrn)}.strct-progress--danger .strct-progress__fill{background:var(--crt)}\n"] }]
1015
+ '[class.strct-progress--critical]': "status() === 'critical'",
1016
+ }, styles: [".strct-progress{display:block}.strct-progress__track{height:6px;border-radius:4px;background:var(--bg-3);overflow:hidden}.strct-progress__fill{height:100%;border-radius:4px;background:var(--acc);transition:width .3s ease}.strct-progress--success .strct-progress__fill{background:var(--success)}.strct-progress--warning .strct-progress__fill{background:var(--warning)}.strct-progress--critical .strct-progress__fill{background:var(--critical)}\n"] }]
807
1017
  }], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], status: [{ type: i0.Input, args: [{ isSignal: true, alias: "status", required: false }] }] } });
808
1018
 
809
1019
  /** Indeterminate loading ring. `<strct-spinner size="sm" />`. */
810
1020
  class StrctSpinner {
1021
+ /** Size variant. */
811
1022
  size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
812
1023
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctSpinner, deps: [], target: i0.ɵɵFactoryTarget.Component });
813
1024
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.16", type: StrctSpinner, isStandalone: true, selector: "strct-spinner", inputs: { size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "progressbar", "aria-label": "Loading" }, properties: { "class.strct-spinner--sm": "size() === 'sm'", "class.strct-spinner--lg": "size() === 'lg'" }, classAttribute: "strct-spinner" }, ngImport: i0, template: '', isInline: true, styles: [".strct-spinner{display:inline-block;width:22px;height:22px;border:2.5px solid var(--b3);border-top-color:var(--acc);border-radius:50%;animation:strct-spin .7s linear infinite}.strct-spinner--sm{width:14px;height:14px;border-width:2px}.strct-spinner--lg{width:34px;height:34px;border-width:3px}@keyframes strct-spin{to{transform:rotate(360deg)}}@media(prefers-reduced-motion:reduce){.strct-spinner{animation-duration:1.6s}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
@@ -829,8 +1040,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
829
1040
  * <strct-skeleton circle width="40px" height="40px" />
830
1041
  */
831
1042
  class StrctSkeleton {
1043
+ /** Width (CSS length). */
832
1044
  width = input('100%', ...(ngDevMode ? [{ debugName: "width" }] : /* istanbul ignore next */ []));
1045
+ /** Height in pixels. */
833
1046
  height = input('14px', ...(ngDevMode ? [{ debugName: "height" }] : /* istanbul ignore next */ []));
1047
+ /** Circle. */
834
1048
  circle = input(false, { ...(ngDevMode ? { debugName: "circle" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
835
1049
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctSkeleton, deps: [], target: i0.ɵɵFactoryTarget.Component });
836
1050
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.16", type: StrctSkeleton, isStandalone: true, selector: "strct-skeleton", inputs: { width: { classPropertyName: "width", publicName: "width", isSignal: true, isRequired: false, transformFunction: null }, height: { classPropertyName: "height", publicName: "height", isSignal: true, isRequired: false, transformFunction: null }, circle: { classPropertyName: "circle", publicName: "circle", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "presentation", "aria-hidden": "true" }, properties: { "class.strct-skel--circle": "circle()", "style.width": "width()", "style.height": "height()" }, classAttribute: "strct-skel" }, ngImport: i0, template: '', isInline: true, styles: [".strct-skel{display:block;border-radius:5px;background:linear-gradient(90deg,var(--bg-3) 25%,var(--bg-h) 37%,var(--bg-3) 63%);background-size:400% 100%;animation:strct-skel-shimmer 1.4s ease infinite}.strct-skel--circle{border-radius:50%}@keyframes strct-skel-shimmer{0%{background-position:100% 50%}to{background-position:0 50%}}@media(prefers-reduced-motion:reduce){.strct-skel{animation:none}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
@@ -857,7 +1071,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
857
1071
  */
858
1072
  class StrctSpeedDial {
859
1073
  host = inject((ElementRef));
1074
+ /** Icon name. */
860
1075
  icon = input('ellipsis', ...(ngDevMode ? [{ debugName: "icon" }] : /* istanbul ignore next */ []));
1076
+ /** Direction the actions fan out. */
861
1077
  direction = input('up', ...(ngDevMode ? [{ debugName: "direction" }] : /* istanbul ignore next */ []));
862
1078
  open = signal(false, ...(ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []));
863
1079
  toggle() {
@@ -888,7 +1104,7 @@ class StrctSpeedDial {
888
1104
  <strct-icon [name]="icon()" [size]="18" [strokeWidth]="1.5" />
889
1105
  </button>
890
1106
  </div>
891
- `, isInline: true, styles: [".strct-sd-host{display:inline-block}.strct-sd{position:relative;display:inline-flex}.strct-sd__fab{display:inline-flex;align-items:center;justify-content:center;width:44px;height:44px;border-radius:50%;cursor:pointer;color:#fff;background:var(--acc);border:0;box-shadow:var(--shh);transition:filter .14s ease,transform .16s ease}.strct-sd__fab:hover{filter:brightness(1.08)}.strct-sd__fab--open{transform:rotate(45deg)}.strct-sd__actions{position:absolute;display:flex;gap:10px;z-index:10;animation:strct-sd-in .14s ease}.strct-sd__actions .strct-btn{border-radius:50%;box-shadow:var(--sh);background:var(--bg-1)}.strct-sd--up .strct-sd__actions{flex-direction:column;bottom:calc(100% + 12px);left:50%;transform:translate(-50%)}.strct-sd--down .strct-sd__actions{flex-direction:column;top:calc(100% + 12px);left:50%;transform:translate(-50%)}.strct-sd--left .strct-sd__actions{flex-direction:row;right:calc(100% + 12px);top:50%;transform:translateY(-50%)}.strct-sd--right .strct-sd__actions{flex-direction:row;left:calc(100% + 12px);top:50%;transform:translateY(-50%)}@keyframes strct-sd-in{0%{opacity:0}}\n"], dependencies: [{ kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "size", "strokeWidth", "badge"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1107
+ `, isInline: true, styles: [".strct-sd-host{display:inline-block}.strct-sd{position:relative;display:inline-flex}.strct-sd__fab{display:inline-flex;align-items:center;justify-content:center;width:44px;height:44px;border-radius:50%;cursor:pointer;color:#fff;background:var(--acc);border:0;box-shadow:var(--shh);transition:filter .14s ease,transform .16s ease}.strct-sd__fab:hover{filter:brightness(1.08)}.strct-sd__fab--open{transform:rotate(45deg)}.strct-sd__actions{position:absolute;display:flex;gap:10px;z-index:10;animation:strct-sd-in .14s ease}.strct-sd__actions .strct-btn{border-radius:50%;box-shadow:var(--sh);background:var(--bg-1)}.strct-sd--up .strct-sd__actions{flex-direction:column;bottom:calc(100% + 12px);left:50%;transform:translate(-50%)}.strct-sd--down .strct-sd__actions{flex-direction:column;top:calc(100% + 12px);left:50%;transform:translate(-50%)}.strct-sd--left .strct-sd__actions{flex-direction:row;right:calc(100% + 12px);top:50%;transform:translateY(-50%)}.strct-sd--right .strct-sd__actions{flex-direction:row;left:calc(100% + 12px);top:50%;transform:translateY(-50%)}@keyframes strct-sd-in{0%{opacity:0}}\n"], dependencies: [{ kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "size", "strokeWidth", "badge", "ariaLabel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
892
1108
  }
893
1109
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctSpeedDial, decorators: [{
894
1110
  type: Component,
@@ -927,35 +1143,38 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
927
1143
  */
928
1144
  class StrctCard {
929
1145
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctCard, deps: [], target: i0.ɵɵFactoryTarget.Component });
930
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.16", type: StrctCard, isStandalone: true, selector: "strct-card", ngImport: i0, template: `<ng-content />`, isInline: true, styles: [":host{display:block;background:var(--bg-1);border:1px solid var(--b2);border-radius:8px;box-shadow:var(--sh);overflow:hidden}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1146
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.16", type: StrctCard, isStandalone: true, selector: "strct-card", ngImport: i0, template: `<ng-content />`, isInline: true, styles: [":host{display:block;background:var(--bg-1);border:1px solid var(--b2);border-radius:var(--radius-lg);box-shadow:var(--sh);overflow:hidden}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
931
1147
  }
932
1148
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctCard, decorators: [{
933
1149
  type: Component,
934
- args: [{ selector: 'strct-card', changeDetection: ChangeDetectionStrategy.OnPush, template: `<ng-content />`, styles: [":host{display:block;background:var(--bg-1);border:1px solid var(--b2);border-radius:8px;box-shadow:var(--sh);overflow:hidden}\n"] }]
1150
+ args: [{ selector: 'strct-card', changeDetection: ChangeDetectionStrategy.OnPush, template: `<ng-content />`, styles: [":host{display:block;background:var(--bg-1);border:1px solid var(--b2);border-radius:var(--radius-lg);box-shadow:var(--sh);overflow:hidden}\n"] }]
935
1151
  }] });
1152
+ /** Header section of a {@link StrctCard}. */
936
1153
  class StrctCardHeader {
937
1154
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctCardHeader, deps: [], target: i0.ɵɵFactoryTarget.Component });
938
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.16", type: StrctCardHeader, isStandalone: true, selector: "strct-card-header", ngImport: i0, template: `<ng-content />`, isInline: true, styles: [":host{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:13px 16px;border-bottom:1px solid var(--b1);font-size:13px;font-weight:600;color:var(--t1)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1155
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.16", type: StrctCardHeader, isStandalone: true, selector: "strct-card-header", ngImport: i0, template: `<ng-content />`, isInline: true, styles: [":host{display:flex;align-items:center;justify-content:space-between;gap:var(--space-2);padding:var(--space-3) var(--space-4);border-bottom:1px solid var(--b1);font-size:13px;font-weight:600;color:var(--t1)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
939
1156
  }
940
1157
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctCardHeader, decorators: [{
941
1158
  type: Component,
942
- args: [{ selector: 'strct-card-header', changeDetection: ChangeDetectionStrategy.OnPush, template: `<ng-content />`, styles: [":host{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:13px 16px;border-bottom:1px solid var(--b1);font-size:13px;font-weight:600;color:var(--t1)}\n"] }]
1159
+ args: [{ selector: 'strct-card-header', changeDetection: ChangeDetectionStrategy.OnPush, template: `<ng-content />`, styles: [":host{display:flex;align-items:center;justify-content:space-between;gap:var(--space-2);padding:var(--space-3) var(--space-4);border-bottom:1px solid var(--b1);font-size:13px;font-weight:600;color:var(--t1)}\n"] }]
943
1160
  }] });
1161
+ /** Body section of a {@link StrctCard}. */
944
1162
  class StrctCardBlock {
945
1163
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctCardBlock, deps: [], target: i0.ɵɵFactoryTarget.Component });
946
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.16", type: StrctCardBlock, isStandalone: true, selector: "strct-card-block", ngImport: i0, template: `<ng-content />`, isInline: true, styles: [":host{display:block;padding:16px;color:var(--t2);font-size:13px}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1164
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.16", type: StrctCardBlock, isStandalone: true, selector: "strct-card-block", ngImport: i0, template: `<ng-content />`, isInline: true, styles: [":host{display:block;padding:var(--space-4);color:var(--t2);font-size:13px}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
947
1165
  }
948
1166
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctCardBlock, decorators: [{
949
1167
  type: Component,
950
- args: [{ selector: 'strct-card-block', changeDetection: ChangeDetectionStrategy.OnPush, template: `<ng-content />`, styles: [":host{display:block;padding:16px;color:var(--t2);font-size:13px}\n"] }]
1168
+ args: [{ selector: 'strct-card-block', changeDetection: ChangeDetectionStrategy.OnPush, template: `<ng-content />`, styles: [":host{display:block;padding:var(--space-4);color:var(--t2);font-size:13px}\n"] }]
951
1169
  }] });
1170
+ /** Footer section of a {@link StrctCard}. */
952
1171
  class StrctCardFooter {
953
1172
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctCardFooter, deps: [], target: i0.ɵɵFactoryTarget.Component });
954
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.16", type: StrctCardFooter, isStandalone: true, selector: "strct-card-footer", ngImport: i0, template: `<ng-content />`, isInline: true, styles: [":host{display:flex;align-items:center;justify-content:flex-end;gap:8px;padding:12px 16px;border-top:1px solid var(--b1);background:var(--bg-2)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1173
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.16", type: StrctCardFooter, isStandalone: true, selector: "strct-card-footer", ngImport: i0, template: `<ng-content />`, isInline: true, styles: [":host{display:flex;align-items:center;justify-content:flex-end;gap:var(--space-2);padding:var(--space-3) var(--space-4);border-top:1px solid var(--b1);background:var(--bg-2)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
955
1174
  }
956
1175
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctCardFooter, decorators: [{
957
1176
  type: Component,
958
- args: [{ selector: 'strct-card-footer', changeDetection: ChangeDetectionStrategy.OnPush, template: `<ng-content />`, styles: [":host{display:flex;align-items:center;justify-content:flex-end;gap:8px;padding:12px 16px;border-top:1px solid var(--b1);background:var(--bg-2)}\n"] }]
1177
+ args: [{ selector: 'strct-card-footer', changeDetection: ChangeDetectionStrategy.OnPush, template: `<ng-content />`, styles: [":host{display:flex;align-items:center;justify-content:flex-end;gap:var(--space-2);padding:var(--space-3) var(--space-4);border-top:1px solid var(--b1);background:var(--bg-2)}\n"] }]
959
1178
  }] });
960
1179
 
961
1180
  /** Vertical container for `<strct-accordion-panel>` items. */
@@ -969,7 +1188,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
969
1188
  }] });
970
1189
  /** Collapsible panel with a header. `expanded` is two-way bindable. */
971
1190
  class StrctAccordionPanel {
1191
+ /** Panel heading. */
972
1192
  heading = input.required(...(ngDevMode ? [{ debugName: "heading" }] : /* istanbul ignore next */ []));
1193
+ /** Whether the panel is open (two-way). */
973
1194
  expanded = model(false, ...(ngDevMode ? [{ debugName: "expanded" }] : /* istanbul ignore next */ []));
974
1195
  toggle() {
975
1196
  this.expanded.update((v) => !v);
@@ -990,7 +1211,7 @@ class StrctAccordionPanel {
990
1211
  @if (expanded()) {
991
1212
  <div class="strct-acc__body"><ng-content /></div>
992
1213
  }
993
- `, isInline: true, styles: [".strct-acc{display:block;background:var(--bg-1);border:1px solid var(--b2);border-radius:7px;overflow:hidden}.strct-acc__head{display:flex;align-items:center;gap:9px;width:100%;padding:11px 14px;border:0;background:transparent;cursor:pointer;font-family:var(--font);font-size:13px;font-weight:500;color:var(--t1);text-align:left}.strct-acc__head:hover{background:var(--bg-3)}.strct-acc__chevron{display:inline-flex;color:var(--t3);transition:transform .16s ease}.strct-acc__chevron--open{transform:rotate(90deg);color:var(--acc)}.strct-acc__title{flex:1}.strct-acc__body{padding:4px 14px 14px 32px;color:var(--t2);font-size:13px;border-top:1px solid var(--b1)}\n"], dependencies: [{ kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "size", "strokeWidth", "badge"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1214
+ `, isInline: true, styles: [".strct-acc{display:block;background:var(--bg-1);border:1px solid var(--b2);border-radius:7px;overflow:hidden}.strct-acc__head{display:flex;align-items:center;gap:9px;width:100%;padding:11px 14px;border:0;background:transparent;cursor:pointer;font-family:var(--font);font-size:13px;font-weight:500;color:var(--t1);text-align:left}.strct-acc__head:hover{background:var(--bg-3)}.strct-acc__chevron{display:inline-flex;color:var(--t3);transition:transform .16s ease}.strct-acc__chevron--open{transform:rotate(90deg);color:var(--acc)}.strct-acc__title{flex:1}.strct-acc__body{padding:4px 14px 14px 32px;color:var(--t2);font-size:13px;border-top:1px solid var(--b1)}\n"], dependencies: [{ kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "size", "strokeWidth", "badge", "ariaLabel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
994
1215
  }
995
1216
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctAccordionPanel, decorators: [{
996
1217
  type: Component,
@@ -1014,7 +1235,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
1014
1235
 
1015
1236
  /** A single tab. Place inside `<strct-tabs>`; `label` names its button. */
1016
1237
  class StrctTab {
1238
+ /** Label text. */
1017
1239
  label = input.required(...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
1240
+ /** Static disable flag. */
1018
1241
  disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
1019
1242
  _active = signal(false, ...(ngDevMode ? [{ debugName: "_active" }] : /* istanbul ignore next */ []));
1020
1243
  active = this._active.asReadonly();
@@ -1088,7 +1311,13 @@ class StrctTabs {
1088
1311
  }
1089
1312
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctTabs, deps: [], target: i0.ɵɵFactoryTarget.Component });
1090
1313
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: StrctTabs, isStandalone: true, selector: "strct-tabs", host: { classAttribute: "strct-tabs" }, queries: [{ propertyName: "tabs", predicate: StrctTab, isSignal: true }], ngImport: i0, template: `
1091
- <div class="strct-tabs__bar" role="tablist" #bar (keydown)="onKeydown($event, bar)">
1314
+ <div
1315
+ class="strct-tabs__bar"
1316
+ role="tablist"
1317
+ tabindex="0"
1318
+ #bar
1319
+ (keydown)="onKeydown($event, bar)"
1320
+ >
1092
1321
  @for (tab of tabs(); track tab; let i = $index) {
1093
1322
  <button
1094
1323
  type="button"
@@ -1105,12 +1334,18 @@ class StrctTabs {
1105
1334
  }
1106
1335
  </div>
1107
1336
  <div class="strct-tabs__panels"><ng-content /></div>
1108
- `, isInline: true, styles: [".strct-tabs{display:block}.strct-tabs__bar{display:flex;gap:2px;border-bottom:1px solid var(--b2)}.strct-tabs__btn{appearance:none;border:0;background:transparent;cursor:pointer;font-family:var(--font);font-size:13px;font-weight:500;color:var(--t2);padding:9px 14px;border-bottom:2px solid transparent;margin-bottom:-1px;transition:color .14s ease,border-color .14s ease}.strct-tabs__btn:hover{color:var(--t1)}.strct-tabs__btn--active{color:var(--acc);border-bottom-color:var(--acc)}.strct-tabs__btn:disabled{color:var(--t4);cursor:not-allowed}.strct-tabs__panels{padding-top:16px}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1337
+ `, isInline: true, styles: [".strct-tabs{display:block}.strct-tabs__bar{display:flex;gap:2px;border-bottom:1px solid var(--b2);overflow-x:auto;white-space:nowrap;scrollbar-width:none}.strct-tabs__btn{appearance:none;border:0;background:transparent;cursor:pointer;font-family:var(--font);font-size:13px;font-weight:500;color:var(--t2);padding:9px 14px;border-bottom:2px solid transparent;margin-bottom:-1px;transition:color .14s ease,border-color .14s ease}.strct-tabs__btn:hover{color:var(--t1)}.strct-tabs__btn--active{color:var(--acc);border-bottom-color:var(--acc)}.strct-tabs__btn:disabled{color:var(--t4);cursor:not-allowed}.strct-tabs__panels{padding-top:16px}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1109
1338
  }
1110
1339
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctTabs, decorators: [{
1111
1340
  type: Component,
1112
1341
  args: [{ selector: 'strct-tabs', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: `
1113
- <div class="strct-tabs__bar" role="tablist" #bar (keydown)="onKeydown($event, bar)">
1342
+ <div
1343
+ class="strct-tabs__bar"
1344
+ role="tablist"
1345
+ tabindex="0"
1346
+ #bar
1347
+ (keydown)="onKeydown($event, bar)"
1348
+ >
1114
1349
  @for (tab of tabs(); track tab; let i = $index) {
1115
1350
  <button
1116
1351
  type="button"
@@ -1127,7 +1362,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
1127
1362
  }
1128
1363
  </div>
1129
1364
  <div class="strct-tabs__panels"><ng-content /></div>
1130
- `, host: { class: 'strct-tabs' }, styles: [".strct-tabs{display:block}.strct-tabs__bar{display:flex;gap:2px;border-bottom:1px solid var(--b2)}.strct-tabs__btn{appearance:none;border:0;background:transparent;cursor:pointer;font-family:var(--font);font-size:13px;font-weight:500;color:var(--t2);padding:9px 14px;border-bottom:2px solid transparent;margin-bottom:-1px;transition:color .14s ease,border-color .14s ease}.strct-tabs__btn:hover{color:var(--t1)}.strct-tabs__btn--active{color:var(--acc);border-bottom-color:var(--acc)}.strct-tabs__btn:disabled{color:var(--t4);cursor:not-allowed}.strct-tabs__panels{padding-top:16px}\n"] }]
1365
+ `, host: { class: 'strct-tabs' }, styles: [".strct-tabs{display:block}.strct-tabs__bar{display:flex;gap:2px;border-bottom:1px solid var(--b2);overflow-x:auto;white-space:nowrap;scrollbar-width:none}.strct-tabs__btn{appearance:none;border:0;background:transparent;cursor:pointer;font-family:var(--font);font-size:13px;font-weight:500;color:var(--t2);padding:9px 14px;border-bottom:2px solid transparent;margin-bottom:-1px;transition:color .14s ease,border-color .14s ease}.strct-tabs__btn:hover{color:var(--t1)}.strct-tabs__btn--active{color:var(--acc);border-bottom-color:var(--acc)}.strct-tabs__btn:disabled{color:var(--t4);cursor:not-allowed}.strct-tabs__panels{padding-top:16px}\n"] }]
1131
1366
  }], ctorParameters: () => [], propDecorators: { tabs: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => StrctTab), { isSignal: true }] }] } });
1132
1367
 
1133
1368
  /**
@@ -1138,12 +1373,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
1138
1373
  */
1139
1374
  class StrctMenuPanel {
1140
1375
  host = inject(ElementRef);
1376
+ /** Menu items to display. */
1141
1377
  items = input.required(...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
1378
+ /** Arbitrary payload passed to item actions. */
1142
1379
  data = input(undefined, ...(ngDevMode ? [{ debugName: "data" }] : /* istanbul ignore next */ []));
1380
+ /** Horizontal position in pixels. */
1143
1381
  x = input(0, ...(ngDevMode ? [{ debugName: "x" }] : /* istanbul ignore next */ []));
1382
+ /** Vertical position in pixels. */
1144
1383
  y = input(0, ...(ngDevMode ? [{ debugName: "y" }] : /* istanbul ignore next */ []));
1384
+ /** Render as a nested submenu panel. */
1145
1385
  submenu = input(false, { ...(ngDevMode ? { debugName: "submenu" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
1386
+ /** Emitted when an item is selected. */
1146
1387
  select = output();
1388
+ /** Emitted when the menu requests closing. */
1147
1389
  close = output();
1148
1390
  /** ArrowLeft inside a submenu — asks the parent to close it. */
1149
1391
  back = output();
@@ -1291,7 +1533,7 @@ class StrctMenuPanel {
1291
1533
  type="button"
1292
1534
  class="strct-menu__item"
1293
1535
  [attr.data-idx]="i"
1294
- [class.strct-menu__item--danger]="item.danger"
1536
+ [class.strct-menu__item--critical]="item.critical"
1295
1537
  [class.strct-menu__item--active]="i === activeIndex()"
1296
1538
  [disabled]="item.disabled"
1297
1539
  role="menuitem"
@@ -1301,13 +1543,23 @@ class StrctMenuPanel {
1301
1543
  (click)="onItemClick(item, i, $event)"
1302
1544
  >
1303
1545
  @if (item.icon) {
1304
- <strct-icon class="strct-menu__icon" [name]="item.icon" [size]="14" [strokeWidth]="1.3" />
1546
+ <strct-icon
1547
+ class="strct-menu__icon"
1548
+ [name]="item.icon"
1549
+ [size]="14"
1550
+ [strokeWidth]="1.3"
1551
+ />
1305
1552
  } @else {
1306
1553
  <span class="strct-menu__icon-spacer" aria-hidden="true"></span>
1307
1554
  }
1308
1555
  <span class="strct-menu__label">{{ item.label }}</span>
1309
1556
  @if (item.children?.length) {
1310
- <strct-icon class="strct-menu__arrow" name="chevronRight" [size]="12" [strokeWidth]="1.6" />
1557
+ <strct-icon
1558
+ class="strct-menu__arrow"
1559
+ name="chevronRight"
1560
+ [size]="12"
1561
+ [strokeWidth]="1.6"
1562
+ />
1311
1563
  }
1312
1564
  </button>
1313
1565
  @if (openSubIndex() === i && item.children?.length) {
@@ -1326,7 +1578,7 @@ class StrctMenuPanel {
1326
1578
  }
1327
1579
  }
1328
1580
  </div>
1329
- `, isInline: true, styles: [".strct-menu-host{display:block}.strct-menu{min-width:180px;padding:4px;background:var(--bg-1);border:1px solid var(--b2);border-radius:7px;box-shadow:var(--shh);animation:strct-menu-in .1s ease}.strct-menu:focus{outline:none}.strct-menu__wrap{position:relative}.strct-menu__item{display:flex;align-items:center;gap:8px;width:100%;padding:7px 8px 7px 10px;border:0;border-radius:5px;cursor:pointer;background:transparent;color:var(--t1);font-size:13px;font-family:var(--font);text-align:left}.strct-menu__item:hover:not(:disabled),.strct-menu__item--active:not(:disabled){background:var(--bg-3)}.strct-menu__item:focus-visible{outline:none;background:var(--bg-3)}.strct-menu__item--danger{color:var(--crt)}.strct-menu__item--danger:hover:not(:disabled),.strct-menu__item--danger.strct-menu__item--active:not(:disabled){background:var(--crt-bg)}.strct-menu__item:disabled{opacity:.45;cursor:not-allowed}.strct-menu__icon{color:var(--t2);flex-shrink:0}.strct-menu__item--danger .strct-menu__icon{color:var(--crt)}.strct-menu__icon-spacer{width:14px;flex-shrink:0}.strct-menu__label{flex:1;white-space:nowrap}.strct-menu__arrow{color:var(--t3);flex-shrink:0}.strct-menu__sep{height:1px;margin:4px 6px;background:var(--b1)}.strct-menu__subpanel{position:absolute;top:-5px;left:100%;margin-left:2px;z-index:1}.strct-menu__subpanel--flip{left:auto;right:100%;margin-left:0;margin-right:2px}@keyframes strct-menu-in{0%{opacity:0;transform:scale(.97)}}\n"], dependencies: [{ kind: "component", type: StrctMenuPanel, selector: "strct-menu-panel", inputs: ["items", "data", "x", "y", "submenu"], outputs: ["select", "close", "back"] }, { kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "size", "strokeWidth", "badge"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1581
+ `, isInline: true, styles: [".strct-menu-host{display:block}.strct-menu{min-width:180px;padding:4px;background:var(--bg-1);border:1px solid var(--b2);border-radius:7px;box-shadow:var(--shh);animation:strct-menu-in .1s ease}.strct-menu:focus{outline:none}.strct-menu__wrap{position:relative}.strct-menu__item{display:flex;align-items:center;gap:8px;width:100%;padding:7px 8px 7px 10px;border:0;border-radius:5px;cursor:pointer;background:transparent;color:var(--t1);font-size:13px;font-family:var(--font);text-align:left}.strct-menu__item:hover:not(:disabled),.strct-menu__item--active:not(:disabled){background:var(--bg-3)}.strct-menu__item:focus-visible{outline:none;background:var(--bg-3)}.strct-menu__item--critical{color:var(--critical)}.strct-menu__item--critical:hover:not(:disabled),.strct-menu__item--critical.strct-menu__item--active:not(:disabled){background:var(--critical-bg)}.strct-menu__item:disabled{opacity:.45;cursor:not-allowed}.strct-menu__icon{color:var(--t2);flex-shrink:0}.strct-menu__item--critical .strct-menu__icon{color:var(--critical)}.strct-menu__icon-spacer{width:14px;flex-shrink:0}.strct-menu__label{flex:1;white-space:nowrap}.strct-menu__arrow{color:var(--t3);flex-shrink:0}.strct-menu__sep{height:1px;margin:4px 6px;background:var(--b1)}.strct-menu__subpanel{position:absolute;top:-5px;left:100%;margin-left:2px;z-index:1}.strct-menu__subpanel--flip{left:auto;right:100%;margin-left:0;margin-right:2px}@keyframes strct-menu-in{0%{opacity:0;transform:scale(.97)}}\n"], dependencies: [{ kind: "component", type: StrctMenuPanel, selector: "strct-menu-panel", inputs: ["items", "data", "x", "y", "submenu"], outputs: ["select", "close", "back"] }, { kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "size", "strokeWidth", "badge", "ariaLabel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1330
1582
  }
1331
1583
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctMenuPanel, decorators: [{
1332
1584
  type: Component,
@@ -1341,7 +1593,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
1341
1593
  type="button"
1342
1594
  class="strct-menu__item"
1343
1595
  [attr.data-idx]="i"
1344
- [class.strct-menu__item--danger]="item.danger"
1596
+ [class.strct-menu__item--critical]="item.critical"
1345
1597
  [class.strct-menu__item--active]="i === activeIndex()"
1346
1598
  [disabled]="item.disabled"
1347
1599
  role="menuitem"
@@ -1351,13 +1603,23 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
1351
1603
  (click)="onItemClick(item, i, $event)"
1352
1604
  >
1353
1605
  @if (item.icon) {
1354
- <strct-icon class="strct-menu__icon" [name]="item.icon" [size]="14" [strokeWidth]="1.3" />
1606
+ <strct-icon
1607
+ class="strct-menu__icon"
1608
+ [name]="item.icon"
1609
+ [size]="14"
1610
+ [strokeWidth]="1.3"
1611
+ />
1355
1612
  } @else {
1356
1613
  <span class="strct-menu__icon-spacer" aria-hidden="true"></span>
1357
1614
  }
1358
1615
  <span class="strct-menu__label">{{ item.label }}</span>
1359
1616
  @if (item.children?.length) {
1360
- <strct-icon class="strct-menu__arrow" name="chevronRight" [size]="12" [strokeWidth]="1.6" />
1617
+ <strct-icon
1618
+ class="strct-menu__arrow"
1619
+ name="chevronRight"
1620
+ [size]="12"
1621
+ [strokeWidth]="1.6"
1622
+ />
1361
1623
  }
1362
1624
  </button>
1363
1625
  @if (openSubIndex() === i && item.children?.length) {
@@ -1382,7 +1644,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
1382
1644
  '[style.left.px]': 'submenu() ? null : posX()',
1383
1645
  '[style.top.px]': 'submenu() ? null : posY()',
1384
1646
  '[style.zIndex]': 'submenu() ? null : 1100',
1385
- }, styles: [".strct-menu-host{display:block}.strct-menu{min-width:180px;padding:4px;background:var(--bg-1);border:1px solid var(--b2);border-radius:7px;box-shadow:var(--shh);animation:strct-menu-in .1s ease}.strct-menu:focus{outline:none}.strct-menu__wrap{position:relative}.strct-menu__item{display:flex;align-items:center;gap:8px;width:100%;padding:7px 8px 7px 10px;border:0;border-radius:5px;cursor:pointer;background:transparent;color:var(--t1);font-size:13px;font-family:var(--font);text-align:left}.strct-menu__item:hover:not(:disabled),.strct-menu__item--active:not(:disabled){background:var(--bg-3)}.strct-menu__item:focus-visible{outline:none;background:var(--bg-3)}.strct-menu__item--danger{color:var(--crt)}.strct-menu__item--danger:hover:not(:disabled),.strct-menu__item--danger.strct-menu__item--active:not(:disabled){background:var(--crt-bg)}.strct-menu__item:disabled{opacity:.45;cursor:not-allowed}.strct-menu__icon{color:var(--t2);flex-shrink:0}.strct-menu__item--danger .strct-menu__icon{color:var(--crt)}.strct-menu__icon-spacer{width:14px;flex-shrink:0}.strct-menu__label{flex:1;white-space:nowrap}.strct-menu__arrow{color:var(--t3);flex-shrink:0}.strct-menu__sep{height:1px;margin:4px 6px;background:var(--b1)}.strct-menu__subpanel{position:absolute;top:-5px;left:100%;margin-left:2px;z-index:1}.strct-menu__subpanel--flip{left:auto;right:100%;margin-left:0;margin-right:2px}@keyframes strct-menu-in{0%{opacity:0;transform:scale(.97)}}\n"] }]
1647
+ }, styles: [".strct-menu-host{display:block}.strct-menu{min-width:180px;padding:4px;background:var(--bg-1);border:1px solid var(--b2);border-radius:7px;box-shadow:var(--shh);animation:strct-menu-in .1s ease}.strct-menu:focus{outline:none}.strct-menu__wrap{position:relative}.strct-menu__item{display:flex;align-items:center;gap:8px;width:100%;padding:7px 8px 7px 10px;border:0;border-radius:5px;cursor:pointer;background:transparent;color:var(--t1);font-size:13px;font-family:var(--font);text-align:left}.strct-menu__item:hover:not(:disabled),.strct-menu__item--active:not(:disabled){background:var(--bg-3)}.strct-menu__item:focus-visible{outline:none;background:var(--bg-3)}.strct-menu__item--critical{color:var(--critical)}.strct-menu__item--critical:hover:not(:disabled),.strct-menu__item--critical.strct-menu__item--active:not(:disabled){background:var(--critical-bg)}.strct-menu__item:disabled{opacity:.45;cursor:not-allowed}.strct-menu__icon{color:var(--t2);flex-shrink:0}.strct-menu__item--critical .strct-menu__icon{color:var(--critical)}.strct-menu__icon-spacer{width:14px;flex-shrink:0}.strct-menu__label{flex:1;white-space:nowrap}.strct-menu__arrow{color:var(--t3);flex-shrink:0}.strct-menu__sep{height:1px;margin:4px 6px;background:var(--b1)}.strct-menu__subpanel{position:absolute;top:-5px;left:100%;margin-left:2px;z-index:1}.strct-menu__subpanel--flip{left:auto;right:100%;margin-left:0;margin-right:2px}@keyframes strct-menu-in{0%{opacity:0;transform:scale(.97)}}\n"] }]
1386
1648
  }], ctorParameters: () => [], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: true }] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], x: [{ type: i0.Input, args: [{ isSignal: true, alias: "x", required: false }] }], y: [{ type: i0.Input, args: [{ isSignal: true, alias: "y", required: false }] }], submenu: [{ type: i0.Input, args: [{ isSignal: true, alias: "submenu", required: false }] }], select: [{ type: i0.Output, args: ["select"] }], close: [{ type: i0.Output, args: ["close"] }], back: [{ type: i0.Output, args: ["back"] }] } });
1387
1649
  /**
1388
1650
  * Right-click (context) menu driven by a data array. Attach to any trigger; the
@@ -1395,8 +1657,11 @@ class StrctContextMenuTrigger {
1395
1657
  envInjector = inject(EnvironmentInjector);
1396
1658
  zone = inject(NgZone);
1397
1659
  doc = inject(DOCUMENT$1);
1660
+ /** Menu items to display. */
1398
1661
  items = input.required({ ...(ngDevMode ? { debugName: "items" } : /* istanbul ignore next */ {}), alias: 'strctContextMenu' });
1662
+ /** Arbitrary payload passed to item actions. */
1399
1663
  data = input(undefined, { ...(ngDevMode ? { debugName: "data" } : /* istanbul ignore next */ {}), alias: 'strctContextMenuData' });
1664
+ /** Emitted when a menu item is selected. */
1400
1665
  menuSelect = output();
1401
1666
  ref = null;
1402
1667
  onClose = () => this.zone.run(() => this.closeMenu());
@@ -1466,17 +1731,22 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
1466
1731
  * - **Data:** pass a `[node]` object that recurses over its `children` —
1467
1732
  * used internally by `<strct-tree [nodes]>`.
1468
1733
  *
1469
- * <strct-tree-node label="Group" icon="layers" badge="ok" [(expanded)]="open">
1734
+ * <strct-tree-node label="Group" icon="layers" badge="success" [(expanded)]="open">
1470
1735
  * <strct-tree-node label="Leaf" icon="vm" [active]="true" />
1471
1736
  * </strct-tree-node>
1472
1737
  */
1473
1738
  class StrctTreeNode {
1474
1739
  /** Data-driven node; when set, label/icon/children come from it. */
1475
1740
  node = input(null, ...(ngDevMode ? [{ debugName: "node" }] : /* istanbul ignore next */ []));
1741
+ /** Label text. */
1476
1742
  label = input('', ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
1743
+ /** Icon name. */
1477
1744
  icon = input(undefined, ...(ngDevMode ? [{ debugName: "icon" }] : /* istanbul ignore next */ []));
1745
+ /** Status dot variant. */
1478
1746
  badge = input('none', ...(ngDevMode ? [{ debugName: "badge" }] : /* istanbul ignore next */ []));
1747
+ /** Whether the item is active / selected. */
1479
1748
  active = input(false, ...(ngDevMode ? [{ debugName: "active" }] : /* istanbul ignore next */ []));
1749
+ /** Whether the panel is open (two-way). */
1480
1750
  expanded = model(false, ...(ngDevMode ? [{ debugName: "expanded" }] : /* istanbul ignore next */ []));
1481
1751
  /** Per-node menu resolver (data mode); bubbles down the recursion. */
1482
1752
  nodeMenu = input(null, ...(ngDevMode ? [{ debugName: "nodeMenu" }] : /* istanbul ignore next */ []));
@@ -1534,17 +1804,25 @@ class StrctTreeNode {
1534
1804
  class="strct-tnode__row"
1535
1805
  [class.strct-tnode__row--active]="displayActive()"
1536
1806
  role="treeitem"
1807
+ tabindex="0"
1808
+ [attr.aria-selected]="displayActive()"
1537
1809
  [attr.aria-expanded]="hasChildren() ? isOpen() : null"
1538
1810
  [strctContextMenu]="menuItems()"
1539
1811
  [strctContextMenuData]="node()"
1540
1812
  (menuSelect)="onMenuSelect($event)"
1541
1813
  (click)="onActivate()"
1814
+ (keydown.enter)="onActivate()"
1815
+ (keydown.space)="onActivate()"
1542
1816
  >
1543
1817
  @if (hasChildren()) {
1544
1818
  <span
1545
1819
  class="strct-tnode__chevron"
1546
1820
  [class.strct-tnode__chevron--open]="isOpen()"
1821
+ role="button"
1822
+ tabindex="0"
1547
1823
  (click)="$event.stopPropagation(); toggle()"
1824
+ (keydown.enter)="$event.stopPropagation(); toggle()"
1825
+ (keydown.space)="$event.stopPropagation(); toggle()"
1548
1826
  >
1549
1827
  <strct-icon name="chevronRight" [size]="12" [strokeWidth]="1.7" />
1550
1828
  </span>
@@ -1579,7 +1857,7 @@ class StrctTreeNode {
1579
1857
  }
1580
1858
  </div>
1581
1859
  }
1582
- `, isInline: true, styles: [".strct-tnode{display:block}.strct-tnode__row{display:flex;align-items:center;gap:7px;padding:7px 10px;border-radius:5px;cursor:pointer;font-size:13px;color:var(--t1);-webkit-user-select:none;user-select:none}.strct-tnode__row:hover{background:var(--bg-3)}.strct-tnode__row--active{background:var(--acc-m);color:var(--acc);font-weight:500}.strct-tnode__row--active .strct-tnode__icon,.strct-tnode__row--active .strct-tnode__chevron{color:var(--acc)}.strct-tnode__chevron{display:inline-flex;color:var(--t3);transition:transform .15s ease;width:14px;justify-content:center}.strct-tnode__chevron--open{transform:rotate(90deg)}.strct-tnode__spacer{width:14px;flex-shrink:0}.strct-tnode__icon{color:var(--t2);flex-shrink:0}.strct-tnode__label{flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.strct-tnode__children{margin-left:16px}\n"], dependencies: [{ kind: "component", type: StrctTreeNode, selector: "strct-tree-node", inputs: ["node", "label", "icon", "badge", "active", "expanded", "nodeMenu"], outputs: ["expandedChange", "activated", "nodeActivated", "nodeMenuSelect"] }, { kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "size", "strokeWidth", "badge"] }, { kind: "directive", type: StrctContextMenuTrigger, selector: "[strctContextMenu]", inputs: ["strctContextMenu", "strctContextMenuData"], outputs: ["menuSelect"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1860
+ `, isInline: true, styles: [".strct-tnode{display:block}.strct-tnode__row{display:flex;align-items:center;gap:7px;padding:7px 10px;border-radius:5px;cursor:pointer;font-size:13px;color:var(--t1);-webkit-user-select:none;user-select:none}.strct-tnode__row:hover{background:var(--bg-3)}.strct-tnode__row--active{background:var(--acc-m);color:var(--acc);font-weight:500}.strct-tnode__row--active .strct-tnode__icon,.strct-tnode__row--active .strct-tnode__chevron{color:var(--acc)}.strct-tnode__chevron{display:inline-flex;color:var(--t3);transition:transform .15s ease;width:14px;justify-content:center}.strct-tnode__chevron--open{transform:rotate(90deg)}.strct-tnode__spacer{width:14px;flex-shrink:0}.strct-tnode__icon{color:var(--t2);flex-shrink:0}.strct-tnode__label{flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.strct-tnode__children{margin-left:16px}\n"], dependencies: [{ kind: "component", type: StrctTreeNode, selector: "strct-tree-node", inputs: ["node", "label", "icon", "badge", "active", "expanded", "nodeMenu"], outputs: ["expandedChange", "activated", "nodeActivated", "nodeMenuSelect"] }, { kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "size", "strokeWidth", "badge", "ariaLabel"] }, { kind: "directive", type: StrctContextMenuTrigger, selector: "[strctContextMenu]", inputs: ["strctContextMenu", "strctContextMenuData"], outputs: ["menuSelect"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1583
1861
  }
1584
1862
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctTreeNode, decorators: [{
1585
1863
  type: Component,
@@ -1588,17 +1866,25 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
1588
1866
  class="strct-tnode__row"
1589
1867
  [class.strct-tnode__row--active]="displayActive()"
1590
1868
  role="treeitem"
1869
+ tabindex="0"
1870
+ [attr.aria-selected]="displayActive()"
1591
1871
  [attr.aria-expanded]="hasChildren() ? isOpen() : null"
1592
1872
  [strctContextMenu]="menuItems()"
1593
1873
  [strctContextMenuData]="node()"
1594
1874
  (menuSelect)="onMenuSelect($event)"
1595
1875
  (click)="onActivate()"
1876
+ (keydown.enter)="onActivate()"
1877
+ (keydown.space)="onActivate()"
1596
1878
  >
1597
1879
  @if (hasChildren()) {
1598
1880
  <span
1599
1881
  class="strct-tnode__chevron"
1600
1882
  [class.strct-tnode__chevron--open]="isOpen()"
1883
+ role="button"
1884
+ tabindex="0"
1601
1885
  (click)="$event.stopPropagation(); toggle()"
1886
+ (keydown.enter)="$event.stopPropagation(); toggle()"
1887
+ (keydown.space)="$event.stopPropagation(); toggle()"
1602
1888
  >
1603
1889
  <strct-icon name="chevronRight" [size]="12" [strokeWidth]="1.7" />
1604
1890
  </span>
@@ -1711,12 +1997,17 @@ function unlockBodyScroll(doc) {
1711
1997
  class StrctModal {
1712
1998
  elementRef = inject((ElementRef));
1713
1999
  doc = inject(DOCUMENT);
2000
+ /** Whether the panel is open (two-way). */
1714
2001
  open = model(false, ...(ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []));
2002
+ /** Dialog title. */
1715
2003
  title = input('', ...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
2004
+ /** Size variant. */
1716
2005
  size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
2006
+ /** Hide the footer slot. */
1717
2007
  hideFooter = input(false, { ...(ngDevMode ? { debugName: "hideFooter" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
1718
2008
  /** Allow closing via backdrop click / Escape. */
1719
- dismissable = input(true, { ...(ngDevMode ? { debugName: "dismissable" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
2009
+ dismissible = input(true, { ...(ngDevMode ? { debugName: "dismissible" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
2010
+ /** Emitted when the alert is dismissed. */
1720
2011
  closed = output();
1721
2012
  titleId = `strct-modal-${++modalCounter}`;
1722
2013
  /** Element that had focus before the dialog opened, restored on close. */
@@ -1755,11 +2046,11 @@ class StrctModal {
1755
2046
  this.closed.emit();
1756
2047
  }
1757
2048
  onBackdrop() {
1758
- if (this.dismissable())
2049
+ if (this.dismissible())
1759
2050
  this.close();
1760
2051
  }
1761
2052
  onEscape() {
1762
- if (this.open() && this.dismissable())
2053
+ if (this.open() && this.dismissible())
1763
2054
  this.close();
1764
2055
  }
1765
2056
  /** Wrap Tab focus within the dialog. */
@@ -1796,9 +2087,16 @@ class StrctModal {
1796
2087
  (items[0] ?? this.dialog())?.focus();
1797
2088
  }
1798
2089
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctModal, deps: [], target: i0.ɵɵFactoryTarget.Component });
1799
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: StrctModal, isStandalone: true, selector: "strct-modal", inputs: { open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, hideFooter: { classPropertyName: "hideFooter", publicName: "hideFooter", isSignal: true, isRequired: false, transformFunction: null }, dismissable: { classPropertyName: "dismissable", publicName: "dismissable", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { open: "openChange", closed: "closed" }, host: { listeners: { "document:keydown.escape": "onEscape()" } }, ngImport: i0, template: `
2090
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: StrctModal, isStandalone: true, selector: "strct-modal", inputs: { open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, hideFooter: { classPropertyName: "hideFooter", publicName: "hideFooter", isSignal: true, isRequired: false, transformFunction: null }, dismissible: { classPropertyName: "dismissible", publicName: "dismissible", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { open: "openChange", closed: "closed" }, host: { listeners: { "document:keydown.escape": "onEscape()" } }, ngImport: i0, template: `
1800
2091
  @if (open()) {
1801
- <div class="strct-modal__overlay" (click)="onBackdrop()">
2092
+ <div
2093
+ class="strct-modal__overlay"
2094
+ role="button"
2095
+ tabindex="0"
2096
+ (click)="onBackdrop()"
2097
+ (keydown.enter)="onBackdrop()"
2098
+ (keydown.space)="onBackdrop()"
2099
+ >
1802
2100
  <div
1803
2101
  #dialog
1804
2102
  class="strct-modal__dialog"
@@ -1825,13 +2123,20 @@ class StrctModal {
1825
2123
  </div>
1826
2124
  </div>
1827
2125
  }
1828
- `, isInline: true, styles: [".strct-modal__overlay{position:fixed;inset:0;z-index:1000;display:flex;align-items:center;justify-content:center;padding:24px;background:#00000080;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);animation:strct-modal-fade .12s ease}.strct-modal__dialog{width:100%;max-width:460px;max-height:calc(100vh - 48px);display:flex;flex-direction:column;background:var(--bg-1);border:1px solid var(--b2);border-radius:10px;box-shadow:var(--shh);overflow:hidden;animation:strct-modal-rise .14s ease}.strct-modal__dialog--sm{max-width:360px}.strct-modal__dialog--lg{max-width:720px}.strct-modal__head{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:14px 18px;border-bottom:1px solid var(--b1)}.strct-modal__title{font-size:14px;font-weight:600;color:var(--t1)}.strct-modal__close{display:inline-flex;padding:4px;border:0;border-radius:5px;background:transparent;color:var(--t3);cursor:pointer}.strct-modal__close:hover{color:var(--t1);background:var(--bg-3)}.strct-modal__body{padding:18px;overflow-y:auto;color:var(--t2);font-size:13px}.strct-modal__foot{display:flex;align-items:center;justify-content:flex-end;gap:8px;padding:13px 18px;border-top:1px solid var(--b1);background:var(--bg-2)}@keyframes strct-modal-fade{0%{opacity:0}}@keyframes strct-modal-rise{0%{opacity:0;transform:translateY(8px) scale(.98)}}\n"], dependencies: [{ kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "size", "strokeWidth", "badge"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2126
+ `, isInline: true, styles: [".strct-modal__overlay{position:fixed;inset:0;z-index:1000;display:flex;align-items:center;justify-content:center;padding:var(--space-5);background:#00000080;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);animation:strct-modal-fade .12s ease}@media(max-width:768px){.strct-modal__overlay{padding:var(--space-3)}}.strct-modal__dialog{width:100%;max-width:min(460px,calc(100vw - 32px));max-height:calc(100vh - 48px);display:flex;flex-direction:column;background:var(--bg-1);border:1px solid var(--b2);border-radius:var(--radius-xl);box-shadow:var(--shadow-elevated);overflow:hidden;animation:strct-modal-rise .14s ease}.strct-modal__dialog--sm{max-width:min(360px,calc(100vw - 32px))}.strct-modal__dialog--lg{max-width:min(720px,calc(100vw - 32px))}.strct-modal__head{display:flex;align-items:center;justify-content:space-between;gap:var(--space-3);padding:var(--space-3) var(--space-4);border-bottom:1px solid var(--b1)}.strct-modal__title{font-size:14px;font-weight:600;color:var(--t1)}.strct-modal__close{display:inline-flex;padding:4px;border:0;border-radius:5px;background:transparent;color:var(--t3);cursor:pointer}.strct-modal__close:hover{color:var(--t1);background:var(--bg-3)}.strct-modal__body{padding:var(--space-4);overflow-y:auto;color:var(--t2);font-size:13px}.strct-modal__foot{display:flex;align-items:center;justify-content:flex-end;gap:var(--space-2);padding:var(--space-3) var(--space-4);border-top:1px solid var(--b1);background:var(--bg-2)}@keyframes strct-modal-fade{0%{opacity:0}}@keyframes strct-modal-rise{0%{opacity:0;transform:translateY(8px) scale(.98)}}\n"], dependencies: [{ kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "size", "strokeWidth", "badge", "ariaLabel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1829
2127
  }
1830
2128
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctModal, decorators: [{
1831
2129
  type: Component,
1832
2130
  args: [{ selector: 'strct-modal', changeDetection: ChangeDetectionStrategy.OnPush, imports: [StrctIcon], template: `
1833
2131
  @if (open()) {
1834
- <div class="strct-modal__overlay" (click)="onBackdrop()">
2132
+ <div
2133
+ class="strct-modal__overlay"
2134
+ role="button"
2135
+ tabindex="0"
2136
+ (click)="onBackdrop()"
2137
+ (keydown.enter)="onBackdrop()"
2138
+ (keydown.space)="onBackdrop()"
2139
+ >
1835
2140
  <div
1836
2141
  #dialog
1837
2142
  class="strct-modal__dialog"
@@ -1860,19 +2165,20 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
1860
2165
  }
1861
2166
  `, host: {
1862
2167
  '(document:keydown.escape)': 'onEscape()',
1863
- }, styles: [".strct-modal__overlay{position:fixed;inset:0;z-index:1000;display:flex;align-items:center;justify-content:center;padding:24px;background:#00000080;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);animation:strct-modal-fade .12s ease}.strct-modal__dialog{width:100%;max-width:460px;max-height:calc(100vh - 48px);display:flex;flex-direction:column;background:var(--bg-1);border:1px solid var(--b2);border-radius:10px;box-shadow:var(--shh);overflow:hidden;animation:strct-modal-rise .14s ease}.strct-modal__dialog--sm{max-width:360px}.strct-modal__dialog--lg{max-width:720px}.strct-modal__head{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:14px 18px;border-bottom:1px solid var(--b1)}.strct-modal__title{font-size:14px;font-weight:600;color:var(--t1)}.strct-modal__close{display:inline-flex;padding:4px;border:0;border-radius:5px;background:transparent;color:var(--t3);cursor:pointer}.strct-modal__close:hover{color:var(--t1);background:var(--bg-3)}.strct-modal__body{padding:18px;overflow-y:auto;color:var(--t2);font-size:13px}.strct-modal__foot{display:flex;align-items:center;justify-content:flex-end;gap:8px;padding:13px 18px;border-top:1px solid var(--b1);background:var(--bg-2)}@keyframes strct-modal-fade{0%{opacity:0}}@keyframes strct-modal-rise{0%{opacity:0;transform:translateY(8px) scale(.98)}}\n"] }]
1864
- }], ctorParameters: () => [], propDecorators: { open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }, { type: i0.Output, args: ["openChange"] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], hideFooter: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideFooter", required: false }] }], dismissable: [{ type: i0.Input, args: [{ isSignal: true, alias: "dismissable", required: false }] }], closed: [{ type: i0.Output, args: ["closed"] }] } });
2168
+ }, styles: [".strct-modal__overlay{position:fixed;inset:0;z-index:1000;display:flex;align-items:center;justify-content:center;padding:var(--space-5);background:#00000080;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);animation:strct-modal-fade .12s ease}@media(max-width:768px){.strct-modal__overlay{padding:var(--space-3)}}.strct-modal__dialog{width:100%;max-width:min(460px,calc(100vw - 32px));max-height:calc(100vh - 48px);display:flex;flex-direction:column;background:var(--bg-1);border:1px solid var(--b2);border-radius:var(--radius-xl);box-shadow:var(--shadow-elevated);overflow:hidden;animation:strct-modal-rise .14s ease}.strct-modal__dialog--sm{max-width:min(360px,calc(100vw - 32px))}.strct-modal__dialog--lg{max-width:min(720px,calc(100vw - 32px))}.strct-modal__head{display:flex;align-items:center;justify-content:space-between;gap:var(--space-3);padding:var(--space-3) var(--space-4);border-bottom:1px solid var(--b1)}.strct-modal__title{font-size:14px;font-weight:600;color:var(--t1)}.strct-modal__close{display:inline-flex;padding:4px;border:0;border-radius:5px;background:transparent;color:var(--t3);cursor:pointer}.strct-modal__close:hover{color:var(--t1);background:var(--bg-3)}.strct-modal__body{padding:var(--space-4);overflow-y:auto;color:var(--t2);font-size:13px}.strct-modal__foot{display:flex;align-items:center;justify-content:flex-end;gap:var(--space-2);padding:var(--space-3) var(--space-4);border-top:1px solid var(--b1);background:var(--bg-2)}@keyframes strct-modal-fade{0%{opacity:0}}@keyframes strct-modal-rise{0%{opacity:0;transform:translateY(8px) scale(.98)}}\n"] }]
2169
+ }], ctorParameters: () => [], propDecorators: { open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }, { type: i0.Output, args: ["openChange"] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], hideFooter: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideFooter", required: false }] }], dismissible: [{ type: i0.Input, args: [{ isSignal: true, alias: "dismissible", required: false }] }], closed: [{ type: i0.Output, args: ["closed"] }] } });
1865
2170
 
1866
2171
  /**
1867
2172
  * Click-to-open menu:
1868
2173
  * <strct-dropdown align="end">
1869
2174
  * <button strct-button strctDropdownTrigger>Actions</button>
1870
2175
  * <strct-dropdown-item>Rename</strct-dropdown-item>
1871
- * <strct-dropdown-item danger>Delete</strct-dropdown-item>
2176
+ * <strct-dropdown-item critical>Delete</strct-dropdown-item>
1872
2177
  * </strct-dropdown>
1873
2178
  */
1874
2179
  class StrctDropdown {
1875
2180
  host = inject((ElementRef));
2181
+ /** Horizontal alignment of the menu. */
1876
2182
  align = input('start', ...(ngDevMode ? [{ debugName: "align" }] : /* istanbul ignore next */ []));
1877
2183
  open = signal(false, ...(ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []));
1878
2184
  toggle() {
@@ -1891,7 +2197,15 @@ class StrctDropdown {
1891
2197
  }
1892
2198
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctDropdown, deps: [], target: i0.ɵɵFactoryTarget.Component });
1893
2199
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: StrctDropdown, isStandalone: true, selector: "strct-dropdown", inputs: { align: { classPropertyName: "align", publicName: "align", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "document:click": "onDocClick($event)", "document:keydown.escape": "onEscape()" }, classAttribute: "strct-dd" }, ngImport: i0, template: `
1894
- <div #trigger class="strct-dd__trigger" (click)="toggle()">
2200
+ <div
2201
+ #trigger
2202
+ class="strct-dd__trigger"
2203
+ role="button"
2204
+ tabindex="0"
2205
+ (click)="toggle()"
2206
+ (keydown.enter)="toggle()"
2207
+ (keydown.space)="toggle()"
2208
+ >
1895
2209
  <ng-content select="[strctDropdownTrigger]" />
1896
2210
  </div>
1897
2211
  @if (open()) {
@@ -1900,17 +2214,28 @@ class StrctDropdown {
1900
2214
  [strctOverlay]="trigger"
1901
2215
  [strctOverlayPlacement]="align() === 'end' ? 'bottom-end' : 'bottom-start'"
1902
2216
  role="menu"
2217
+ tabindex="0"
1903
2218
  (click)="close()"
2219
+ (keydown.enter)="close()"
2220
+ (keydown.space)="close()"
1904
2221
  >
1905
2222
  <ng-content />
1906
2223
  </div>
1907
2224
  }
1908
- `, isInline: true, styles: [".strct-dd{position:relative;display:inline-block}.strct-dd__trigger{display:inline-flex}.strct-dd__menu{position:absolute;top:calc(100% + 4px);left:0;z-index:200;min-width:170px;padding:4px;background:var(--bg-1);border:1px solid var(--b2);border-radius:7px;box-shadow:var(--shh);animation:strct-dd-in .1s ease}.strct-dd__menu--end{left:auto;right:0}@keyframes strct-dd-in{0%{opacity:0;transform:translateY(-4px)}}\n"], dependencies: [{ kind: "directive", type: StrctOverlay, selector: "[strctOverlay]", inputs: ["strctOverlay", "strctOverlayPlacement", "strctOverlayMatchWidth", "strctOverlayGap"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
2225
+ `, isInline: true, styles: [".strct-dd{position:relative;display:inline-block}.strct-dd__trigger{display:inline-flex}.strct-dd__menu{position:absolute;top:calc(100% + 4px);left:0;z-index:200;min-width:170px;max-width:calc(100vw - 24px);padding:4px;background:var(--bg-1);border:1px solid var(--b2);border-radius:7px;box-shadow:var(--shh);animation:strct-dd-in .1s ease}.strct-dd__menu--end{left:auto;right:0}@keyframes strct-dd-in{0%{opacity:0;transform:translateY(-4px)}}\n"], dependencies: [{ kind: "directive", type: StrctOverlay, selector: "[strctOverlay]", inputs: ["strctOverlay", "strctOverlayPlacement", "strctOverlayMatchWidth", "strctOverlayGap"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1909
2226
  }
1910
2227
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctDropdown, decorators: [{
1911
2228
  type: Component,
1912
2229
  args: [{ selector: 'strct-dropdown', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [StrctOverlay], template: `
1913
- <div #trigger class="strct-dd__trigger" (click)="toggle()">
2230
+ <div
2231
+ #trigger
2232
+ class="strct-dd__trigger"
2233
+ role="button"
2234
+ tabindex="0"
2235
+ (click)="toggle()"
2236
+ (keydown.enter)="toggle()"
2237
+ (keydown.space)="toggle()"
2238
+ >
1914
2239
  <ng-content select="[strctDropdownTrigger]" />
1915
2240
  </div>
1916
2241
  @if (open()) {
@@ -1919,12 +2244,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
1919
2244
  [strctOverlay]="trigger"
1920
2245
  [strctOverlayPlacement]="align() === 'end' ? 'bottom-end' : 'bottom-start'"
1921
2246
  role="menu"
2247
+ tabindex="0"
1922
2248
  (click)="close()"
2249
+ (keydown.enter)="close()"
2250
+ (keydown.space)="close()"
1923
2251
  >
1924
2252
  <ng-content />
1925
2253
  </div>
1926
2254
  }
1927
- `, host: { class: 'strct-dd' }, styles: [".strct-dd{position:relative;display:inline-block}.strct-dd__trigger{display:inline-flex}.strct-dd__menu{position:absolute;top:calc(100% + 4px);left:0;z-index:200;min-width:170px;padding:4px;background:var(--bg-1);border:1px solid var(--b2);border-radius:7px;box-shadow:var(--shh);animation:strct-dd-in .1s ease}.strct-dd__menu--end{left:auto;right:0}@keyframes strct-dd-in{0%{opacity:0;transform:translateY(-4px)}}\n"] }]
2255
+ `, host: { class: 'strct-dd' }, styles: [".strct-dd{position:relative;display:inline-block}.strct-dd__trigger{display:inline-flex}.strct-dd__menu{position:absolute;top:calc(100% + 4px);left:0;z-index:200;min-width:170px;max-width:calc(100vw - 24px);padding:4px;background:var(--bg-1);border:1px solid var(--b2);border-radius:7px;box-shadow:var(--shh);animation:strct-dd-in .1s ease}.strct-dd__menu--end{left:auto;right:0}@keyframes strct-dd-in{0%{opacity:0;transform:translateY(-4px)}}\n"] }]
1928
2256
  }], propDecorators: { align: [{ type: i0.Input, args: [{ isSignal: true, alias: "align", required: false }] }], onDocClick: [{
1929
2257
  type: HostListener,
1930
2258
  args: ['document:click', ['$event']]
@@ -1934,20 +2262,22 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
1934
2262
  }] } });
1935
2263
  /** A selectable row inside a `<strct-dropdown>`. */
1936
2264
  class StrctDropdownItem {
1937
- danger = input(false, { ...(ngDevMode ? { debugName: "danger" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
2265
+ /** Danger. */
2266
+ critical = input(false, { ...(ngDevMode ? { debugName: "critical" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
2267
+ /** Static disable flag. */
1938
2268
  disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
1939
2269
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctDropdownItem, deps: [], target: i0.ɵɵFactoryTarget.Component });
1940
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.16", type: StrctDropdownItem, isStandalone: true, selector: "strct-dropdown-item", inputs: { danger: { classPropertyName: "danger", publicName: "danger", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "menuitem" }, properties: { "class.strct-dd__item--danger": "danger()", "attr.aria-disabled": "disabled() || null" }, classAttribute: "strct-dd__item" }, ngImport: i0, template: `<ng-content />`, isInline: true, styles: [".strct-dd__item{display:flex;align-items:center;gap:8px;padding:7px 10px;border-radius:5px;cursor:pointer;font-size:13px;color:var(--t1)}.strct-dd__item:hover{background:var(--bg-3)}.strct-dd__item--danger{color:var(--crt)}.strct-dd__item--danger:hover{background:var(--crt-bg)}.strct-dd__item[aria-disabled=true]{color:var(--t4);pointer-events:none}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
2270
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.16", type: StrctDropdownItem, isStandalone: true, selector: "strct-dropdown-item", inputs: { critical: { classPropertyName: "critical", publicName: "critical", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "menuitem" }, properties: { "class.strct-dd__item--critical": "critical()", "attr.aria-disabled": "disabled() || null" }, classAttribute: "strct-dd__item" }, ngImport: i0, template: `<ng-content />`, isInline: true, styles: [".strct-dd__item{display:flex;align-items:center;gap:8px;padding:7px 10px;border-radius:5px;cursor:pointer;font-size:13px;color:var(--t1)}.strct-dd__item:hover{background:var(--bg-3)}.strct-dd__item--critical{color:var(--critical)}.strct-dd__item--critical:hover{background:var(--critical-bg)}.strct-dd__item[aria-disabled=true]{color:var(--t4);pointer-events:none}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1941
2271
  }
1942
2272
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctDropdownItem, decorators: [{
1943
2273
  type: Component,
1944
2274
  args: [{ selector: 'strct-dropdown-item', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: `<ng-content />`, host: {
1945
2275
  class: 'strct-dd__item',
1946
2276
  role: 'menuitem',
1947
- '[class.strct-dd__item--danger]': 'danger()',
2277
+ '[class.strct-dd__item--critical]': 'critical()',
1948
2278
  '[attr.aria-disabled]': 'disabled() || null',
1949
- }, styles: [".strct-dd__item{display:flex;align-items:center;gap:8px;padding:7px 10px;border-radius:5px;cursor:pointer;font-size:13px;color:var(--t1)}.strct-dd__item:hover{background:var(--bg-3)}.strct-dd__item--danger{color:var(--crt)}.strct-dd__item--danger:hover{background:var(--crt-bg)}.strct-dd__item[aria-disabled=true]{color:var(--t4);pointer-events:none}\n"] }]
1950
- }], propDecorators: { danger: [{ type: i0.Input, args: [{ isSignal: true, alias: "danger", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }] } });
2279
+ }, styles: [".strct-dd__item{display:flex;align-items:center;gap:8px;padding:7px 10px;border-radius:5px;cursor:pointer;font-size:13px;color:var(--t1)}.strct-dd__item:hover{background:var(--bg-3)}.strct-dd__item--critical{color:var(--critical)}.strct-dd__item--critical:hover{background:var(--critical-bg)}.strct-dd__item[aria-disabled=true]{color:var(--t4);pointer-events:none}\n"] }]
2280
+ }], propDecorators: { critical: [{ type: i0.Input, args: [{ isSignal: true, alias: "critical", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }] } });
1951
2281
  /** Thin separator between groups of menu items. */
1952
2282
  class StrctDropdownDivider {
1953
2283
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctDropdownDivider, deps: [], target: i0.ɵɵFactoryTarget.Component });
@@ -1965,7 +2295,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
1965
2295
  * <div>Right-click here</div>
1966
2296
  * <ng-container strctContextMenuItems>
1967
2297
  * <strct-dropdown-item>Open</strct-dropdown-item>
1968
- * <strct-dropdown-item danger>Delete</strct-dropdown-item>
2298
+ * <strct-dropdown-item critical>Delete</strct-dropdown-item>
1969
2299
  * </ng-container>
1970
2300
  * </strct-context-menu>
1971
2301
  */
@@ -2006,10 +2336,13 @@ class StrctContextMenu {
2006
2336
  <div
2007
2337
  class="strct-ctx__menu"
2008
2338
  role="menu"
2339
+ tabindex="0"
2009
2340
  [style.left.px]="x()"
2010
2341
  [style.top.px]="y()"
2011
2342
  (click)="close()"
2012
2343
  (contextmenu)="$event.preventDefault(); close()"
2344
+ (keydown.enter)="close()"
2345
+ (keydown.space)="close()"
2013
2346
  >
2014
2347
  <ng-content select="[strctContextMenuItems]" />
2015
2348
  </div>
@@ -2026,10 +2359,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
2026
2359
  <div
2027
2360
  class="strct-ctx__menu"
2028
2361
  role="menu"
2362
+ tabindex="0"
2029
2363
  [style.left.px]="x()"
2030
2364
  [style.top.px]="y()"
2031
2365
  (click)="close()"
2032
2366
  (contextmenu)="$event.preventDefault(); close()"
2367
+ (keydown.enter)="close()"
2368
+ (keydown.space)="close()"
2033
2369
  >
2034
2370
  <ng-content select="[strctContextMenuItems]" />
2035
2371
  </div>
@@ -2057,6 +2393,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
2057
2393
  */
2058
2394
  class StrctSubmenu {
2059
2395
  host = inject(ElementRef);
2396
+ /** Label text. */
2060
2397
  label = input('', ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
2061
2398
  /** Optional leading icon; when omitted the icon column is still reserved so
2062
2399
  * the label stays aligned with sibling items that do have icons. */
@@ -2092,8 +2429,15 @@ class StrctSubmenu {
2092
2429
  } @else {
2093
2430
  <span class="strct-submenu__icon-spacer" aria-hidden="true"></span>
2094
2431
  }
2095
- <span class="strct-submenu__label">{{ label() }}<ng-content select="[strctSubmenuLabel]" /></span>
2096
- <strct-icon class="strct-submenu__arrow" name="chevronRight" [size]="12" [strokeWidth]="1.6" />
2432
+ <span class="strct-submenu__label"
2433
+ >{{ label() }}<ng-content select="[strctSubmenuLabel]"
2434
+ /></span>
2435
+ <strct-icon
2436
+ class="strct-submenu__arrow"
2437
+ name="chevronRight"
2438
+ [size]="12"
2439
+ [strokeWidth]="1.6"
2440
+ />
2097
2441
  </div>
2098
2442
  @if (open()) {
2099
2443
  <div class="strct-submenu__panel" [class.strct-submenu__panel--flip]="flip()" role="menu">
@@ -2101,7 +2445,7 @@ class StrctSubmenu {
2101
2445
  </div>
2102
2446
  }
2103
2447
  </div>
2104
- `, isInline: true, styles: [".strct-submenu{position:relative}.strct-submenu__trigger{display:flex;align-items:center;gap:8px;padding:7px 8px 7px 10px;border-radius:5px;cursor:default;font-size:13px;color:var(--t1)}.strct-submenu__trigger:hover{background:var(--bg-3)}.strct-submenu__trigger:focus-visible{outline:none;background:var(--bg-3)}.strct-submenu__icon{color:var(--t2);flex-shrink:0}.strct-submenu__icon-spacer{width:14px;flex-shrink:0}.strct-submenu__label{flex:1;display:inline-flex;align-items:center;gap:8px}.strct-submenu__arrow{color:var(--t3)}.strct-submenu__panel{position:absolute;top:-5px;left:100%;z-index:1;min-width:170px;margin-left:2px;padding:4px;background:var(--bg-1);border:1px solid var(--b2);border-radius:7px;box-shadow:var(--shh);animation:strct-submenu-in .1s ease}.strct-submenu__panel--flip{left:auto;right:100%;margin-left:0;margin-right:2px}@keyframes strct-submenu-in{0%{opacity:0;transform:translate(-4px)}}\n"], dependencies: [{ kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "size", "strokeWidth", "badge"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
2448
+ `, isInline: true, styles: [".strct-submenu{position:relative}.strct-submenu__trigger{display:flex;align-items:center;gap:8px;padding:7px 8px 7px 10px;border-radius:5px;cursor:default;font-size:13px;color:var(--t1)}.strct-submenu__trigger:hover{background:var(--bg-3)}.strct-submenu__trigger:focus-visible{outline:none;background:var(--bg-3)}.strct-submenu__icon{color:var(--t2);flex-shrink:0}.strct-submenu__icon-spacer{width:14px;flex-shrink:0}.strct-submenu__label{flex:1;display:inline-flex;align-items:center;gap:8px}.strct-submenu__arrow{color:var(--t3)}.strct-submenu__panel{position:absolute;top:-5px;left:100%;z-index:1;min-width:170px;margin-left:2px;padding:4px;background:var(--bg-1);border:1px solid var(--b2);border-radius:7px;box-shadow:var(--shh);animation:strct-submenu-in .1s ease}.strct-submenu__panel--flip{left:auto;right:100%;margin-left:0;margin-right:2px}@keyframes strct-submenu-in{0%{opacity:0;transform:translate(-4px)}}\n"], dependencies: [{ kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "size", "strokeWidth", "badge", "ariaLabel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
2105
2449
  }
2106
2450
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctSubmenu, decorators: [{
2107
2451
  type: Component,
@@ -2125,8 +2469,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
2125
2469
  } @else {
2126
2470
  <span class="strct-submenu__icon-spacer" aria-hidden="true"></span>
2127
2471
  }
2128
- <span class="strct-submenu__label">{{ label() }}<ng-content select="[strctSubmenuLabel]" /></span>
2129
- <strct-icon class="strct-submenu__arrow" name="chevronRight" [size]="12" [strokeWidth]="1.6" />
2472
+ <span class="strct-submenu__label"
2473
+ >{{ label() }}<ng-content select="[strctSubmenuLabel]"
2474
+ /></span>
2475
+ <strct-icon
2476
+ class="strct-submenu__arrow"
2477
+ name="chevronRight"
2478
+ [size]="12"
2479
+ [strokeWidth]="1.6"
2480
+ />
2130
2481
  </div>
2131
2482
  @if (open()) {
2132
2483
  <div class="strct-submenu__panel" [class.strct-submenu__panel--flip]="flip()" role="menu">
@@ -2139,6 +2490,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
2139
2490
 
2140
2491
  /** A single wizard step. `label` names it in the step header. */
2141
2492
  class StrctStep {
2493
+ /** Label text. */
2142
2494
  label = input.required(...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
2143
2495
  /** When false, the wizard's Next / Finish is disabled on this step. */
2144
2496
  canAdvance = input(true, { ...(ngDevMode ? { debugName: "canAdvance" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
@@ -2174,7 +2526,9 @@ class StrctWizard {
2174
2526
  submitting = input(false, { ...(ngDevMode ? { debugName: "submitting" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
2175
2527
  /** Show a Cancel button on the left. */
2176
2528
  cancelable = input(false, { ...(ngDevMode ? { debugName: "cancelable" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
2529
+ /** Emitted when the user clicks Finish. */
2177
2530
  finished = output();
2531
+ /** Emitted when the user clicks Cancel. */
2178
2532
  cancelled = output();
2179
2533
  /** Emits the new step index after a Back / Next move. */
2180
2534
  stepChange = output();
@@ -2229,7 +2583,9 @@ class StrctWizard {
2229
2583
  Cancel
2230
2584
  </button>
2231
2585
  }
2232
- <button strct-button variant="flat" [disabled]="current() === 0" (click)="back()">Back</button>
2586
+ <button strct-button variant="flat" [disabled]="current() === 0" (click)="back()">
2587
+ Back
2588
+ </button>
2233
2589
  @if (isLast()) {
2234
2590
  <button
2235
2591
  strct-button
@@ -2240,7 +2596,9 @@ class StrctWizard {
2240
2596
  {{ submitting() ? 'Submitting…' : finishLabel() }}
2241
2597
  </button>
2242
2598
  } @else {
2243
- <button strct-button variant="primary" [disabled]="!canAdvance()" (click)="next()">Next</button>
2599
+ <button strct-button variant="primary" [disabled]="!canAdvance()" (click)="next()">
2600
+ Next
2601
+ </button>
2244
2602
  }
2245
2603
  </div>
2246
2604
  `, isInline: true, styles: [".strct-wiz{display:block}.strct-wiz__steps{display:flex;align-items:center;gap:6px}.strct-wiz__step{display:flex;align-items:center;gap:8px}.strct-wiz__dot{display:inline-flex;align-items:center;justify-content:center;width:22px;height:22px;border-radius:50%;font-size:11px;font-weight:600;color:var(--t2);background:var(--bg-3);border:1px solid var(--b2)}.strct-wiz__label{font-size:12px;color:var(--t2)}.strct-wiz__step--active .strct-wiz__dot{background:var(--acc-m);color:var(--acc);border-color:var(--acc)}.strct-wiz__step--active .strct-wiz__label{color:var(--t1);font-weight:600}.strct-wiz__step--done .strct-wiz__dot{background:var(--acc-m);color:var(--acc);border-color:var(--acc30)}.strct-wiz__sep{flex:1;height:1px;background:var(--b2);min-width:18px}.strct-wiz__content{margin:18px 0;padding:16px;min-height:80px;background:var(--bg-1);border:1px solid var(--b2);border-radius:8px;color:var(--t2);font-size:13px}.strct-wiz__foot{display:flex;justify-content:flex-end;gap:8px}.strct-wiz__cancel{margin-right:auto}\n"], dependencies: [{ kind: "component", type: StrctButton, selector: "button[strct-button], a[strct-button]", inputs: ["variant", "size", "solid", "block", "iconOnly"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
@@ -2272,7 +2630,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
2272
2630
  Cancel
2273
2631
  </button>
2274
2632
  }
2275
- <button strct-button variant="flat" [disabled]="current() === 0" (click)="back()">Back</button>
2633
+ <button strct-button variant="flat" [disabled]="current() === 0" (click)="back()">
2634
+ Back
2635
+ </button>
2276
2636
  @if (isLast()) {
2277
2637
  <button
2278
2638
  strct-button
@@ -2283,7 +2643,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
2283
2643
  {{ submitting() ? 'Submitting…' : finishLabel() }}
2284
2644
  </button>
2285
2645
  } @else {
2286
- <button strct-button variant="primary" [disabled]="!canAdvance()" (click)="next()">Next</button>
2646
+ <button strct-button variant="primary" [disabled]="!canAdvance()" (click)="next()">
2647
+ Next
2648
+ </button>
2287
2649
  }
2288
2650
  </div>
2289
2651
  `, host: { class: 'strct-wiz' }, styles: [".strct-wiz{display:block}.strct-wiz__steps{display:flex;align-items:center;gap:6px}.strct-wiz__step{display:flex;align-items:center;gap:8px}.strct-wiz__dot{display:inline-flex;align-items:center;justify-content:center;width:22px;height:22px;border-radius:50%;font-size:11px;font-weight:600;color:var(--t2);background:var(--bg-3);border:1px solid var(--b2)}.strct-wiz__label{font-size:12px;color:var(--t2)}.strct-wiz__step--active .strct-wiz__dot{background:var(--acc-m);color:var(--acc);border-color:var(--acc)}.strct-wiz__step--active .strct-wiz__label{color:var(--t1);font-weight:600}.strct-wiz__step--done .strct-wiz__dot{background:var(--acc-m);color:var(--acc);border-color:var(--acc30)}.strct-wiz__sep{flex:1;height:1px;background:var(--b2);min-width:18px}.strct-wiz__content{margin:18px 0;padding:16px;min-height:80px;background:var(--bg-1);border:1px solid var(--b2);border-radius:8px;color:var(--t2);font-size:13px}.strct-wiz__foot{display:flex;justify-content:flex-end;gap:8px}.strct-wiz__cancel{margin-right:auto}\n"] }]
@@ -2296,6 +2658,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
2296
2658
  * <strct-divider vertical />
2297
2659
  */
2298
2660
  class StrctDivider {
2661
+ /** Render as a vertical rule. */
2299
2662
  vertical = input(false, { ...(ngDevMode ? { debugName: "vertical" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
2300
2663
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctDivider, deps: [], target: i0.ɵɵFactoryTarget.Component });
2301
2664
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.16", type: StrctDivider, isStandalone: true, selector: "strct-divider", inputs: { vertical: { classPropertyName: "vertical", publicName: "vertical", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "separator" }, properties: { "class.strct-divider--vertical": "vertical()", "attr.aria-orientation": "vertical() ? 'vertical' : 'horizontal'" }, classAttribute: "strct-divider" }, ngImport: i0, template: `<span class="strct-divider__label"><ng-content /></span>`, isInline: true, styles: [".strct-divider{display:flex;align-items:center;gap:12px;width:100%;color:var(--t3);font-size:11px;text-transform:uppercase;letter-spacing:.5px}.strct-divider:before,.strct-divider:after{content:\"\";flex:1;height:1px;background:var(--b2)}.strct-divider__label:empty{display:none}.strct-divider:has(.strct-divider__label:empty){gap:0}.strct-divider--vertical{display:inline-block;width:1px;min-height:1em;height:auto;align-self:stretch;background:var(--b2);margin:0 2px}.strct-divider--vertical:before,.strct-divider--vertical:after{content:none}.strct-divider--vertical .strct-divider__label{display:none}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
@@ -2321,6 +2684,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
2321
2684
  }] });
2322
2685
  /** One crumb. Mark the final one `current`. */
2323
2686
  class StrctBreadcrumbItem {
2687
+ /** Mark as the current page. */
2324
2688
  current = input(false, { ...(ngDevMode ? { debugName: "current" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
2325
2689
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctBreadcrumbItem, deps: [], target: i0.ɵɵFactoryTarget.Component });
2326
2690
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.16", type: StrctBreadcrumbItem, isStandalone: true, selector: "strct-breadcrumb-item", inputs: { current: { classPropertyName: "current", publicName: "current", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.strct-bc__item--current": "current()", "attr.aria-current": "current() ? 'page' : null" }, classAttribute: "strct-bc__item" }, ngImport: i0, template: `<ng-content />`, isInline: true, styles: [".strct-bc__item{display:inline-flex;align-items:center;color:var(--t2)}.strct-bc__item a{color:var(--t2);text-decoration:none}.strct-bc__item a:hover{color:var(--acc);text-decoration:none}.strct-bc__item--current{color:var(--t1);font-weight:600}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
@@ -2339,8 +2703,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
2339
2703
  * <strct-pagination [total]="240" [pageSize]="20" [(page)]="page" />
2340
2704
  */
2341
2705
  class StrctPagination {
2706
+ /** Total number of items. */
2342
2707
  total = input.required(...(ngDevMode ? [{ debugName: "total" }] : /* istanbul ignore next */ []));
2708
+ /** Rows per page (0 disables paging). */
2343
2709
  pageSize = input(10, ...(ngDevMode ? [{ debugName: "pageSize" }] : /* istanbul ignore next */ []));
2710
+ /** Current page (two-way). */
2344
2711
  page = model(1, ...(ngDevMode ? [{ debugName: "page" }] : /* istanbul ignore next */ []));
2345
2712
  pageCount = computed(() => Math.max(1, Math.ceil(this.total() / Math.max(1, this.pageSize()))), ...(ngDevMode ? [{ debugName: "pageCount" }] : /* istanbul ignore next */ []));
2346
2713
  pages = computed(() => {
@@ -2403,7 +2770,7 @@ class StrctPagination {
2403
2770
  >
2404
2771
  <strct-icon name="chevronRight" [size]="13" [strokeWidth]="1.7" />
2405
2772
  </button>
2406
- `, isInline: true, styles: [".strct-pg{display:inline-flex;align-items:center;gap:4px}.strct-pg__btn{display:inline-flex;align-items:center;justify-content:center;min-width:30px;height:30px;padding:0 7px;border-radius:6px;font-family:var(--font);font-size:13px;cursor:pointer;color:var(--t1);background:transparent;border:1px solid transparent;transition:background .14s ease,border-color .14s ease,color .14s ease}.strct-pg__btn:hover{background:var(--bg-3)}.strct-pg__btn--active{color:var(--acc);border-color:var(--acc30);background:var(--acc-m)}.strct-pg__btn:disabled{color:var(--t4);cursor:not-allowed;background:transparent}.strct-pg__nav{color:var(--t2)}.strct-pg__dots{display:inline-flex;align-items:center;justify-content:center;min-width:24px;height:30px;color:var(--t3)}\n"], dependencies: [{ kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "size", "strokeWidth", "badge"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
2773
+ `, isInline: true, styles: [".strct-pg{display:inline-flex;align-items:center;gap:4px}.strct-pg__btn{display:inline-flex;align-items:center;justify-content:center;min-width:30px;height:30px;padding:0 7px;border-radius:6px;font-family:var(--font);font-size:13px;cursor:pointer;color:var(--t1);background:transparent;border:1px solid transparent;transition:background .14s ease,border-color .14s ease,color .14s ease}.strct-pg__btn:hover{background:var(--bg-3)}.strct-pg__btn--active{color:var(--acc);border-color:var(--acc30);background:var(--acc-m)}.strct-pg__btn:disabled{color:var(--t4);cursor:not-allowed;background:transparent}.strct-pg__nav{color:var(--t2)}.strct-pg__dots{display:inline-flex;align-items:center;justify-content:center;min-width:24px;height:30px;color:var(--t3)}\n"], dependencies: [{ kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "size", "strokeWidth", "badge", "ariaLabel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
2407
2774
  }
2408
2775
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctPagination, decorators: [{
2409
2776
  type: Component,
@@ -2457,8 +2824,11 @@ let fieldCounter = 0;
2457
2824
  * </strct-field>
2458
2825
  */
2459
2826
  class StrctField {
2827
+ /** Label text. */
2460
2828
  label = input('', ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
2829
+ /** Show a required marker on the label. */
2461
2830
  required = input(false, { ...(ngDevMode ? { debugName: "required" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
2831
+ /** Helper text shown below the field. */
2462
2832
  hint = input('', ...(ngDevMode ? [{ debugName: "hint" }] : /* istanbul ignore next */ []));
2463
2833
  /** Error message (string or first-of array); falsy clears the error state. */
2464
2834
  error = input(null, ...(ngDevMode ? [{ debugName: "error" }] : /* istanbul ignore next */ []));
@@ -2510,7 +2880,10 @@ class StrctField {
2510
2880
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: StrctField, isStandalone: true, selector: "strct-field", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, error: { classPropertyName: "error", publicName: "error", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.strct-field--invalid": "!!errorText()" }, classAttribute: "strct-field" }, ngImport: i0, template: `
2511
2881
  @if (label()) {
2512
2882
  <label class="strct-field__label" [attr.for]="controlId() || null">
2513
- {{ label() }}@if (required()) {<span class="strct-field__req" aria-hidden="true">*</span>}
2883
+ {{ label() }}
2884
+ @if (required()) {
2885
+ <span class="strct-field__req" aria-hidden="true">*</span>
2886
+ }
2514
2887
  </label>
2515
2888
  }
2516
2889
  <div class="strct-field__control"><ng-content /></div>
@@ -2521,14 +2894,17 @@ class StrctField {
2521
2894
  } @else if (hint()) {
2522
2895
  <div class="strct-field__msg strct-field__msg--hint" [id]="hintId">{{ hint() }}</div>
2523
2896
  }
2524
- `, isInline: true, styles: [".strct-field{display:flex;flex-direction:column;gap:6px}.strct-field__label{font-size:12px;font-weight:600;color:var(--t2)}.strct-field__req{color:var(--crt);margin-left:2px}.strct-field__control{display:flex;flex-direction:column}.strct-field__msg{font-size:12px;line-height:1.4}.strct-field__msg--hint{color:var(--t3)}.strct-field__msg--error{color:var(--crt)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
2897
+ `, isInline: true, styles: [".strct-field{display:flex;flex-direction:column;gap:6px}.strct-field__label{font-size:12px;font-weight:600;color:var(--t2)}.strct-field__req{color:var(--critical);margin-left:2px}.strct-field__control{display:flex;flex-direction:column}.strct-field__msg{font-size:12px;line-height:1.4}.strct-field__msg--hint{color:var(--t3)}.strct-field__msg--error{color:var(--critical)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
2525
2898
  }
2526
2899
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctField, decorators: [{
2527
2900
  type: Component,
2528
2901
  args: [{ selector: 'strct-field', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: `
2529
2902
  @if (label()) {
2530
2903
  <label class="strct-field__label" [attr.for]="controlId() || null">
2531
- {{ label() }}@if (required()) {<span class="strct-field__req" aria-hidden="true">*</span>}
2904
+ {{ label() }}
2905
+ @if (required()) {
2906
+ <span class="strct-field__req" aria-hidden="true">*</span>
2907
+ }
2532
2908
  </label>
2533
2909
  }
2534
2910
  <div class="strct-field__control"><ng-content /></div>
@@ -2542,7 +2918,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
2542
2918
  `, host: {
2543
2919
  class: 'strct-field',
2544
2920
  '[class.strct-field--invalid]': '!!errorText()',
2545
- }, styles: [".strct-field{display:flex;flex-direction:column;gap:6px}.strct-field__label{font-size:12px;font-weight:600;color:var(--t2)}.strct-field__req{color:var(--crt);margin-left:2px}.strct-field__control{display:flex;flex-direction:column}.strct-field__msg{font-size:12px;line-height:1.4}.strct-field__msg--hint{color:var(--t3)}.strct-field__msg--error{color:var(--crt)}\n"] }]
2921
+ }, styles: [".strct-field{display:flex;flex-direction:column;gap:6px}.strct-field__label{font-size:12px;font-weight:600;color:var(--t2)}.strct-field__req{color:var(--critical);margin-left:2px}.strct-field__control{display:flex;flex-direction:column}.strct-field__msg{font-size:12px;line-height:1.4}.strct-field__msg--hint{color:var(--t3)}.strct-field__msg--error{color:var(--critical)}\n"] }]
2546
2922
  }], ctorParameters: () => [], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }] } });
2547
2923
 
2548
2924
  /**
@@ -2610,7 +2986,7 @@ class StrctCheckbox {
2610
2986
  </span>
2611
2987
  <span class="strct-cb__label"><ng-content /></span>
2612
2988
  </label>
2613
- `, isInline: true, styles: [".strct-cb{display:inline-flex;align-items:center;gap:8px;cursor:pointer;font-size:13px;color:var(--t1);-webkit-user-select:none;user-select:none}.strct-cb--disabled{opacity:.5;cursor:not-allowed}.strct-cb__native{position:absolute;opacity:0;width:0;height:0}.strct-cb__box{display:inline-flex;align-items:center;justify-content:center;width:17px;height:17px;border-radius:4px;flex-shrink:0;background:var(--bg-2);border:1px solid var(--b3);color:transparent;transition:background .14s ease,border-color .14s ease}.strct-cb__native:checked+.strct-cb__box{background:var(--acc);border-color:transparent;color:#fff}.strct-cb__native:focus-visible+.strct-cb__box{box-shadow:0 0 0 3px var(--acc18)}\n"], dependencies: [{ kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "size", "strokeWidth", "badge"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2989
+ `, isInline: true, styles: [".strct-cb{display:inline-flex;align-items:center;gap:8px;cursor:pointer;font-size:13px;color:var(--t1);-webkit-user-select:none;user-select:none}.strct-cb--disabled{opacity:.5;cursor:not-allowed}.strct-cb__native{position:absolute;opacity:0;width:0;height:0}.strct-cb__box{display:inline-flex;align-items:center;justify-content:center;width:17px;height:17px;border-radius:4px;flex-shrink:0;background:var(--bg-2);border:1px solid var(--b3);color:transparent;transition:background .14s ease,border-color .14s ease}.strct-cb__native:checked+.strct-cb__box{background:var(--acc);border-color:transparent;color:#fff}.strct-cb__native:focus-visible+.strct-cb__box{box-shadow:0 0 0 3px var(--acc18)}\n"], dependencies: [{ kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "size", "strokeWidth", "badge", "ariaLabel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2614
2990
  }
2615
2991
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctCheckbox, decorators: [{
2616
2992
  type: Component,
@@ -2746,7 +3122,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
2746
3122
  }] });
2747
3123
  /** One option inside a `<strct-radio-group>`. */
2748
3124
  class StrctRadio {
3125
+ /** Current value. */
2749
3126
  value = input.required(...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
3127
+ /** Static disable flag. */
2750
3128
  disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
2751
3129
  group = inject(StrctRadioGroup);
2752
3130
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctRadio, deps: [], target: i0.ɵɵFactoryTarget.Component });
@@ -2788,10 +3166,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
2788
3166
  * <strct-range [min]="0" [max]="100" [(ngModel)]="volume" showValue />
2789
3167
  */
2790
3168
  class StrctRange {
3169
+ /** Minimum allowed value. */
2791
3170
  min = input(0, ...(ngDevMode ? [{ debugName: "min" }] : /* istanbul ignore next */ []));
3171
+ /** Maximum allowed value or top of the value axis. */
2792
3172
  max = input(100, ...(ngDevMode ? [{ debugName: "max" }] : /* istanbul ignore next */ []));
3173
+ /** Step increment. */
2793
3174
  step = input(1, ...(ngDevMode ? [{ debugName: "step" }] : /* istanbul ignore next */ []));
3175
+ /** Display the current numeric value. */
2794
3176
  showValue = input(false, { ...(ngDevMode ? { debugName: "showValue" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
3177
+ /** Static disable flag. */
2795
3178
  disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
2796
3179
  value = signal(0, ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
2797
3180
  isDisabled = signal(false, ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
@@ -2866,19 +3249,22 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
2866
3249
  }], ctorParameters: () => [], propDecorators: { min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], step: [{ type: i0.Input, args: [{ isSignal: true, alias: "step", required: false }] }], showValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "showValue", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }] } });
2867
3250
 
2868
3251
  const LEVELS = [
2869
- { label: 'Weak', color: 'var(--crt)' },
2870
- { label: 'Weak', color: 'var(--crt)' },
2871
- { label: 'Fair', color: 'var(--wrn)' },
3252
+ { label: 'Weak', color: 'var(--critical)' },
3253
+ { label: 'Weak', color: 'var(--critical)' },
3254
+ { label: 'Fair', color: 'var(--warning)' },
2872
3255
  { label: 'Good', color: 'var(--acc)' },
2873
- { label: 'Strong', color: 'var(--ok)' },
3256
+ { label: 'Strong', color: 'var(--success)' },
2874
3257
  ];
2875
3258
  /**
2876
3259
  * Password input with a reveal toggle and an optional strength meter. CVA-compatible.
2877
3260
  * <strct-password [(ngModel)]="pw" meter />
2878
3261
  */
2879
3262
  class StrctPassword {
3263
+ /** Placeholder text when empty. */
2880
3264
  placeholder = input('', ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
3265
+ /** Show a strength meter. */
2881
3266
  meter = input(false, { ...(ngDevMode ? { debugName: "meter" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
3267
+ /** Static disable flag. */
2882
3268
  disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
2883
3269
  value = signal('', ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
2884
3270
  revealed = signal(false, ...(ngDevMode ? [{ debugName: "revealed" }] : /* istanbul ignore next */ []));
@@ -2956,7 +3342,7 @@ class StrctPassword {
2956
3342
  <span class="strct-pw__label" [style.color]="level().color">{{ level().label }}</span>
2957
3343
  </div>
2958
3344
  }
2959
- `, isInline: true, styles: [".strct-pw{display:block;width:100%;max-width:280px}.strct-pw__field{position:relative}.strct-pw__input{padding-right:38px}.strct-pw__toggle{position:absolute;right:4px;top:50%;transform:translateY(-50%);display:inline-flex;padding:5px;border:0;border-radius:5px;background:transparent;color:var(--t2);cursor:pointer}.strct-pw__toggle:hover{color:var(--acc);background:var(--bg-3)}.strct-pw__meter{display:flex;align-items:center;gap:9px;margin-top:7px}.strct-pw__bars{display:flex;gap:3px;flex:1}.strct-pw__bar{flex:1;height:3px;border-radius:2px;transition:background .2s ease}.strct-pw__label{font-size:11px;font-weight:600;min-width:42px;text-align:right}\n"], dependencies: [{ kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "size", "strokeWidth", "badge"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
3345
+ `, isInline: true, styles: [".strct-pw{display:block;width:100%;max-width:280px}.strct-pw__field{position:relative}.strct-pw__input{padding-right:38px}.strct-pw__toggle{position:absolute;right:4px;top:50%;transform:translateY(-50%);display:inline-flex;padding:5px;border:0;border-radius:5px;background:transparent;color:var(--t2);cursor:pointer}.strct-pw__toggle:hover{color:var(--acc);background:var(--bg-3)}.strct-pw__meter{display:flex;align-items:center;gap:9px;margin-top:7px}.strct-pw__bars{display:flex;gap:3px;flex:1}.strct-pw__bar{flex:1;height:3px;border-radius:2px;transition:background .2s ease}.strct-pw__label{font-size:11px;font-weight:600;min-width:42px;text-align:right}\n"], dependencies: [{ kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "size", "strokeWidth", "badge", "ariaLabel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
2960
3346
  }
2961
3347
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctPassword, decorators: [{
2962
3348
  type: Component,
@@ -3005,8 +3391,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
3005
3391
  * <strct-file [(ngModel)]="files" multiple accept="image/*" />
3006
3392
  */
3007
3393
  class StrctFile {
3394
+ /** Multiple. */
3008
3395
  multiple = input(false, { ...(ngDevMode ? { debugName: "multiple" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
3396
+ /** Accept. */
3009
3397
  accept = input('', ...(ngDevMode ? [{ debugName: "accept" }] : /* istanbul ignore next */ []));
3398
+ /** Static disable flag. */
3010
3399
  disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
3011
3400
  files = signal([], ...(ngDevMode ? [{ debugName: "files" }] : /* istanbul ignore next */ []));
3012
3401
  dragging = signal(false, ...(ngDevMode ? [{ debugName: "dragging" }] : /* istanbul ignore next */ []));
@@ -3099,14 +3488,19 @@ class StrctFile {
3099
3488
  <li class="strct-file__file">
3100
3489
  <span class="strct-file__name">{{ file.name }}</span>
3101
3490
  <span class="strct-file__size">{{ humanSize(file.size) }}</span>
3102
- <button type="button" class="strct-file__remove" aria-label="Remove" (click)="remove(file)">
3491
+ <button
3492
+ type="button"
3493
+ class="strct-file__remove"
3494
+ aria-label="Remove"
3495
+ (click)="remove(file)"
3496
+ >
3103
3497
  <strct-icon name="close" [size]="12" />
3104
3498
  </button>
3105
3499
  </li>
3106
3500
  }
3107
3501
  </ul>
3108
3502
  }
3109
- `, isInline: true, styles: [".strct-file{display:block;width:100%;max-width:360px}.strct-file__zone{display:flex;flex-direction:column;align-items:center;gap:8px;padding:22px 16px;text-align:center;cursor:pointer;color:var(--t2);background:var(--bg-2);border:1px dashed var(--b3);border-radius:8px;transition:border-color .14s ease,background .14s ease,color .14s ease}.strct-file__zone:hover{border-color:var(--acc30);color:var(--t1)}.strct-file__zone strct-icon{color:var(--t3)}.strct-file__zone--drag{border-color:var(--acc);background:var(--acc-m);color:var(--t1)}.strct-file__zone--drag strct-icon{color:var(--acc)}.strct-file__zone--disabled{opacity:.5;cursor:not-allowed}.strct-file__prompt{font-size:13px}.strct-file__browse{color:var(--acc)}.strct-file__native{display:none}.strct-file__list{list-style:none;margin:10px 0 0;padding:0;display:flex;flex-direction:column;gap:6px}.strct-file__file{display:flex;align-items:center;gap:10px;padding:7px 10px;font-size:13px;background:var(--bg-1);border:1px solid var(--b2);border-radius:6px}.strct-file__name{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--t1)}.strct-file__size{font-size:11px;color:var(--t3);font-family:var(--mono)}.strct-file__remove{display:inline-flex;padding:3px;border:0;border-radius:4px;background:transparent;color:var(--t3);cursor:pointer}.strct-file__remove:hover{color:var(--crt);background:var(--crt-bg)}\n"], dependencies: [{ kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "size", "strokeWidth", "badge"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
3503
+ `, isInline: true, styles: [".strct-file{display:block;width:100%;max-width:360px}.strct-file__zone{display:flex;flex-direction:column;align-items:center;gap:8px;padding:22px 16px;text-align:center;cursor:pointer;color:var(--t2);background:var(--bg-2);border:1px dashed var(--b3);border-radius:8px;transition:border-color .14s ease,background .14s ease,color .14s ease}.strct-file__zone:hover{border-color:var(--acc30);color:var(--t1)}.strct-file__zone strct-icon{color:var(--t3)}.strct-file__zone--drag{border-color:var(--acc);background:var(--acc-m);color:var(--t1)}.strct-file__zone--drag strct-icon{color:var(--acc)}.strct-file__zone--disabled{opacity:.5;cursor:not-allowed}.strct-file__prompt{font-size:13px}.strct-file__browse{color:var(--acc)}.strct-file__native{display:none}.strct-file__list{list-style:none;margin:10px 0 0;padding:0;display:flex;flex-direction:column;gap:6px}.strct-file__file{display:flex;align-items:center;gap:10px;padding:7px 10px;font-size:13px;background:var(--bg-1);border:1px solid var(--b2);border-radius:6px}.strct-file__name{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--t1)}.strct-file__size{font-size:11px;color:var(--t3);font-family:var(--mono)}.strct-file__remove{display:inline-flex;padding:3px;border:0;border-radius:4px;background:transparent;color:var(--t3);cursor:pointer}.strct-file__remove:hover{color:var(--critical);background:var(--critical-bg)}\n"], dependencies: [{ kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "size", "strokeWidth", "badge", "ariaLabel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
3110
3504
  }
3111
3505
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctFile, decorators: [{
3112
3506
  type: Component,
@@ -3147,20 +3541,28 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
3147
3541
  <li class="strct-file__file">
3148
3542
  <span class="strct-file__name">{{ file.name }}</span>
3149
3543
  <span class="strct-file__size">{{ humanSize(file.size) }}</span>
3150
- <button type="button" class="strct-file__remove" aria-label="Remove" (click)="remove(file)">
3544
+ <button
3545
+ type="button"
3546
+ class="strct-file__remove"
3547
+ aria-label="Remove"
3548
+ (click)="remove(file)"
3549
+ >
3151
3550
  <strct-icon name="close" [size]="12" />
3152
3551
  </button>
3153
3552
  </li>
3154
3553
  }
3155
3554
  </ul>
3156
3555
  }
3157
- `, host: { class: 'strct-file' }, styles: [".strct-file{display:block;width:100%;max-width:360px}.strct-file__zone{display:flex;flex-direction:column;align-items:center;gap:8px;padding:22px 16px;text-align:center;cursor:pointer;color:var(--t2);background:var(--bg-2);border:1px dashed var(--b3);border-radius:8px;transition:border-color .14s ease,background .14s ease,color .14s ease}.strct-file__zone:hover{border-color:var(--acc30);color:var(--t1)}.strct-file__zone strct-icon{color:var(--t3)}.strct-file__zone--drag{border-color:var(--acc);background:var(--acc-m);color:var(--t1)}.strct-file__zone--drag strct-icon{color:var(--acc)}.strct-file__zone--disabled{opacity:.5;cursor:not-allowed}.strct-file__prompt{font-size:13px}.strct-file__browse{color:var(--acc)}.strct-file__native{display:none}.strct-file__list{list-style:none;margin:10px 0 0;padding:0;display:flex;flex-direction:column;gap:6px}.strct-file__file{display:flex;align-items:center;gap:10px;padding:7px 10px;font-size:13px;background:var(--bg-1);border:1px solid var(--b2);border-radius:6px}.strct-file__name{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--t1)}.strct-file__size{font-size:11px;color:var(--t3);font-family:var(--mono)}.strct-file__remove{display:inline-flex;padding:3px;border:0;border-radius:4px;background:transparent;color:var(--t3);cursor:pointer}.strct-file__remove:hover{color:var(--crt);background:var(--crt-bg)}\n"] }]
3556
+ `, host: { class: 'strct-file' }, styles: [".strct-file{display:block;width:100%;max-width:360px}.strct-file__zone{display:flex;flex-direction:column;align-items:center;gap:8px;padding:22px 16px;text-align:center;cursor:pointer;color:var(--t2);background:var(--bg-2);border:1px dashed var(--b3);border-radius:8px;transition:border-color .14s ease,background .14s ease,color .14s ease}.strct-file__zone:hover{border-color:var(--acc30);color:var(--t1)}.strct-file__zone strct-icon{color:var(--t3)}.strct-file__zone--drag{border-color:var(--acc);background:var(--acc-m);color:var(--t1)}.strct-file__zone--drag strct-icon{color:var(--acc)}.strct-file__zone--disabled{opacity:.5;cursor:not-allowed}.strct-file__prompt{font-size:13px}.strct-file__browse{color:var(--acc)}.strct-file__native{display:none}.strct-file__list{list-style:none;margin:10px 0 0;padding:0;display:flex;flex-direction:column;gap:6px}.strct-file__file{display:flex;align-items:center;gap:10px;padding:7px 10px;font-size:13px;background:var(--bg-1);border:1px solid var(--b2);border-radius:6px}.strct-file__name{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--t1)}.strct-file__size{font-size:11px;color:var(--t3);font-family:var(--mono)}.strct-file__remove{display:inline-flex;padding:3px;border:0;border-radius:4px;background:transparent;color:var(--t3);cursor:pointer}.strct-file__remove:hover{color:var(--critical);background:var(--critical-bg)}\n"] }]
3158
3557
  }], propDecorators: { multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], accept: [{ type: i0.Input, args: [{ isSignal: true, alias: "accept", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }] } });
3159
3558
 
3160
3559
  /** Star rating input. CVA value is the selected count (0–max). */
3161
3560
  class StrctRating {
3561
+ /** Maximum allowed value or top of the value axis. */
3162
3562
  max = input(5, ...(ngDevMode ? [{ debugName: "max" }] : /* istanbul ignore next */ []));
3563
+ /** Size variant. */
3163
3564
  size = input(18, ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
3565
+ /** Prevent user interaction. */
3164
3566
  readonly = input(false, { ...(ngDevMode ? { debugName: "readonly" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
3165
3567
  value = signal(0, ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
3166
3568
  hover = signal(0, ...(ngDevMode ? [{ debugName: "hover" }] : /* istanbul ignore next */ []));
@@ -3194,7 +3596,13 @@ class StrctRating {
3194
3596
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: StrctRating, isStandalone: true, selector: "strct-rating", inputs: { max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null } }, providers: [
3195
3597
  { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => StrctRating), multi: true },
3196
3598
  ], ngImport: i0, template: `
3197
- <div class="strct-rating" role="slider" [attr.aria-valuemin]="0" [attr.aria-valuemax]="max()" [attr.aria-valuenow]="value()">
3599
+ <div
3600
+ class="strct-rating"
3601
+ role="slider"
3602
+ [attr.aria-valuemin]="0"
3603
+ [attr.aria-valuemax]="max()"
3604
+ [attr.aria-valuenow]="value()"
3605
+ >
3198
3606
  @for (star of stars(); track star) {
3199
3607
  <button
3200
3608
  type="button"
@@ -3218,14 +3626,20 @@ class StrctRating {
3218
3626
  </button>
3219
3627
  }
3220
3628
  </div>
3221
- `, isInline: true, styles: [".strct-rating{display:inline-flex;gap:3px}.strct-rating__star{display:inline-flex;padding:1px;border:0;background:transparent;cursor:pointer;color:var(--t4);transition:color .12s ease,transform .1s ease}.strct-rating__star:hover:not(:disabled){transform:scale(1.12)}.strct-rating__star--on{color:var(--wrn)}.strct-rating__star:disabled{cursor:default}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
3629
+ `, isInline: true, styles: [".strct-rating{display:inline-flex;gap:3px}.strct-rating__star{display:inline-flex;padding:1px;border:0;background:transparent;cursor:pointer;color:var(--t4);transition:color .12s ease,transform .1s ease}.strct-rating__star:hover:not(:disabled){transform:scale(1.12)}.strct-rating__star--on{color:var(--warning)}.strct-rating__star:disabled{cursor:default}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
3222
3630
  }
3223
3631
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctRating, decorators: [{
3224
3632
  type: Component,
3225
3633
  args: [{ selector: 'strct-rating', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, providers: [
3226
3634
  { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => StrctRating), multi: true },
3227
3635
  ], template: `
3228
- <div class="strct-rating" role="slider" [attr.aria-valuemin]="0" [attr.aria-valuemax]="max()" [attr.aria-valuenow]="value()">
3636
+ <div
3637
+ class="strct-rating"
3638
+ role="slider"
3639
+ [attr.aria-valuemin]="0"
3640
+ [attr.aria-valuemax]="max()"
3641
+ [attr.aria-valuenow]="value()"
3642
+ >
3229
3643
  @for (star of stars(); track star) {
3230
3644
  <button
3231
3645
  type="button"
@@ -3249,7 +3663,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
3249
3663
  </button>
3250
3664
  }
3251
3665
  </div>
3252
- `, styles: [".strct-rating{display:inline-flex;gap:3px}.strct-rating__star{display:inline-flex;padding:1px;border:0;background:transparent;cursor:pointer;color:var(--t4);transition:color .12s ease,transform .1s ease}.strct-rating__star:hover:not(:disabled){transform:scale(1.12)}.strct-rating__star--on{color:var(--wrn)}.strct-rating__star:disabled{cursor:default}\n"] }]
3666
+ `, styles: [".strct-rating{display:inline-flex;gap:3px}.strct-rating__star{display:inline-flex;padding:1px;border:0;background:transparent;cursor:pointer;color:var(--t4);transition:color .12s ease,transform .1s ease}.strct-rating__star:hover:not(:disabled){transform:scale(1.12)}.strct-rating__star--on{color:var(--warning)}.strct-rating__star:disabled{cursor:default}\n"] }]
3253
3667
  }], propDecorators: { max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }] } });
3254
3668
 
3255
3669
  /**
@@ -3258,7 +3672,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
3258
3672
  * <strct-chips [(ngModel)]="labels" placeholder="Add a tag…" />
3259
3673
  */
3260
3674
  class StrctChips {
3675
+ /** Placeholder text when empty. */
3261
3676
  placeholder = input('', ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
3677
+ /** Allow duplicate tags. */
3262
3678
  allowDuplicates = input(false, ...(ngDevMode ? [{ debugName: "allowDuplicates" }] : /* istanbul ignore next */ []));
3263
3679
  value = signal([], ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
3264
3680
  draft = signal('', ...(ngDevMode ? [{ debugName: "draft" }] : /* istanbul ignore next */ []));
@@ -3308,7 +3724,14 @@ class StrctChips {
3308
3724
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: StrctChips, isStandalone: true, selector: "strct-chips", inputs: { placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, allowDuplicates: { classPropertyName: "allowDuplicates", publicName: "allowDuplicates", isSignal: true, isRequired: false, transformFunction: null } }, providers: [
3309
3725
  { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => StrctChips), multi: true },
3310
3726
  ], ngImport: i0, template: `
3311
- <div class="strct-chips" (click)="input.focus()">
3727
+ <div
3728
+ class="strct-chips"
3729
+ role="button"
3730
+ tabindex="0"
3731
+ (click)="input.focus()"
3732
+ (keydown.enter)="input.focus()"
3733
+ (keydown.space)="input.focus()"
3734
+ >
3312
3735
  @for (chip of value(); track chip) {
3313
3736
  <strct-tag status="accent" removable (removed)="remove(chip)">{{ chip }}</strct-tag>
3314
3737
  }
@@ -3331,7 +3754,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
3331
3754
  args: [{ selector: 'strct-chips', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [StrctTag], providers: [
3332
3755
  { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => StrctChips), multi: true },
3333
3756
  ], template: `
3334
- <div class="strct-chips" (click)="input.focus()">
3757
+ <div
3758
+ class="strct-chips"
3759
+ role="button"
3760
+ tabindex="0"
3761
+ (click)="input.focus()"
3762
+ (keydown.enter)="input.focus()"
3763
+ (keydown.space)="input.focus()"
3764
+ >
3335
3765
  @for (chip of value(); track chip) {
3336
3766
  <strct-tag status="accent" removable (removed)="remove(chip)">{{ chip }}</strct-tag>
3337
3767
  }
@@ -3357,7 +3787,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
3357
3787
  */
3358
3788
  class StrctInputOtp {
3359
3789
  host = inject((ElementRef));
3790
+ /** Number of OTP boxes. */
3360
3791
  length = input(6, ...(ngDevMode ? [{ debugName: "length" }] : /* istanbul ignore next */ []));
3792
+ /** Mask each box as a password dot. */
3361
3793
  masked = input(false, ...(ngDevMode ? [{ debugName: "masked" }] : /* istanbul ignore next */ []));
3362
3794
  slots = signal([], ...(ngDevMode ? [{ debugName: "slots" }] : /* istanbul ignore next */ []));
3363
3795
  isDisabled = signal(false, ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
@@ -3479,9 +3911,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
3479
3911
 
3480
3912
  const COLOR$2 = {
3481
3913
  accent: 'var(--acc)',
3482
- success: 'var(--ok)',
3483
- warning: 'var(--wrn)',
3484
- danger: 'var(--crt)',
3914
+ success: 'var(--success)',
3915
+ warning: 'var(--warning)',
3916
+ critical: 'var(--critical)',
3485
3917
  };
3486
3918
  /**
3487
3919
  * Rotary dial input. Drag (up/down), arrow keys, Home/End or the wheel change
@@ -3490,12 +3922,19 @@ const COLOR$2 = {
3490
3922
  */
3491
3923
  class StrctKnob {
3492
3924
  elementRef = inject((ElementRef));
3925
+ /** Minimum allowed value. */
3493
3926
  min = input(0, ...(ngDevMode ? [{ debugName: "min" }] : /* istanbul ignore next */ []));
3927
+ /** Maximum allowed value or top of the value axis. */
3494
3928
  max = input(100, ...(ngDevMode ? [{ debugName: "max" }] : /* istanbul ignore next */ []));
3929
+ /** Step increment. */
3495
3930
  step = input(1, ...(ngDevMode ? [{ debugName: "step" }] : /* istanbul ignore next */ []));
3931
+ /** Size variant. */
3496
3932
  size = input(96, ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
3933
+ /** Stroke thickness in pixels. */
3497
3934
  thickness = input(9, ...(ngDevMode ? [{ debugName: "thickness" }] : /* istanbul ignore next */ []));
3935
+ /** Visual status color. */
3498
3936
  status = input('accent', ...(ngDevMode ? [{ debugName: "status" }] : /* istanbul ignore next */ []));
3937
+ /** Label text. */
3499
3938
  label = input('', ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
3500
3939
  value = signal(0, ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
3501
3940
  isDisabled = signal(false, ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
@@ -3561,7 +4000,8 @@ class StrctKnob {
3561
4000
  case 'End':
3562
4001
  this.setValue(this.max());
3563
4002
  break;
3564
- default: handled = false;
4003
+ default:
4004
+ handled = false;
3565
4005
  }
3566
4006
  if (handled) {
3567
4007
  event.preventDefault();
@@ -3616,23 +4056,36 @@ class StrctKnob {
3616
4056
  <g [attr.transform]="'rotate(135 ' + half() + ' ' + half() + ')'">
3617
4057
  <circle
3618
4058
  class="strct-knob__track"
3619
- [attr.cx]="half()" [attr.cy]="half()" [attr.r]="radius()"
3620
- fill="none" [attr.stroke-width]="thickness()" stroke-linecap="round"
4059
+ [attr.cx]="half()"
4060
+ [attr.cy]="half()"
4061
+ [attr.r]="radius()"
4062
+ fill="none"
4063
+ [attr.stroke-width]="thickness()"
4064
+ stroke-linecap="round"
3621
4065
  [attr.stroke-dasharray]="trackDash()"
3622
4066
  />
3623
4067
  <circle
3624
4068
  class="strct-knob__value"
3625
- [attr.cx]="half()" [attr.cy]="half()" [attr.r]="radius()"
3626
- fill="none" [attr.stroke]="color()" [attr.stroke-width]="thickness()" stroke-linecap="round"
4069
+ [attr.cx]="half()"
4070
+ [attr.cy]="half()"
4071
+ [attr.r]="radius()"
4072
+ fill="none"
4073
+ [attr.stroke]="color()"
4074
+ [attr.stroke-width]="thickness()"
4075
+ stroke-linecap="round"
3627
4076
  [attr.stroke-dasharray]="valueDash()"
3628
4077
  />
3629
4078
  </g>
3630
4079
  <g [attr.transform]="'rotate(' + pointerAngle() + ' ' + half() + ' ' + half() + ')'">
3631
4080
  <line
3632
4081
  class="strct-knob__pointer"
3633
- [attr.x1]="half()" [attr.y1]="half()"
3634
- [attr.x2]="half()" [attr.y2]="thickness() + 3"
3635
- [attr.stroke]="color()" stroke-width="2.5" stroke-linecap="round"
4082
+ [attr.x1]="half()"
4083
+ [attr.y1]="half()"
4084
+ [attr.x2]="half()"
4085
+ [attr.y2]="thickness() + 3"
4086
+ [attr.stroke]="color()"
4087
+ stroke-width="2.5"
4088
+ stroke-linecap="round"
3636
4089
  />
3637
4090
  </g>
3638
4091
  </svg>
@@ -3666,23 +4119,36 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
3666
4119
  <g [attr.transform]="'rotate(135 ' + half() + ' ' + half() + ')'">
3667
4120
  <circle
3668
4121
  class="strct-knob__track"
3669
- [attr.cx]="half()" [attr.cy]="half()" [attr.r]="radius()"
3670
- fill="none" [attr.stroke-width]="thickness()" stroke-linecap="round"
4122
+ [attr.cx]="half()"
4123
+ [attr.cy]="half()"
4124
+ [attr.r]="radius()"
4125
+ fill="none"
4126
+ [attr.stroke-width]="thickness()"
4127
+ stroke-linecap="round"
3671
4128
  [attr.stroke-dasharray]="trackDash()"
3672
4129
  />
3673
4130
  <circle
3674
4131
  class="strct-knob__value"
3675
- [attr.cx]="half()" [attr.cy]="half()" [attr.r]="radius()"
3676
- fill="none" [attr.stroke]="color()" [attr.stroke-width]="thickness()" stroke-linecap="round"
4132
+ [attr.cx]="half()"
4133
+ [attr.cy]="half()"
4134
+ [attr.r]="radius()"
4135
+ fill="none"
4136
+ [attr.stroke]="color()"
4137
+ [attr.stroke-width]="thickness()"
4138
+ stroke-linecap="round"
3677
4139
  [attr.stroke-dasharray]="valueDash()"
3678
4140
  />
3679
4141
  </g>
3680
4142
  <g [attr.transform]="'rotate(' + pointerAngle() + ' ' + half() + ' ' + half() + ')'">
3681
4143
  <line
3682
4144
  class="strct-knob__pointer"
3683
- [attr.x1]="half()" [attr.y1]="half()"
3684
- [attr.x2]="half()" [attr.y2]="thickness() + 3"
3685
- [attr.stroke]="color()" stroke-width="2.5" stroke-linecap="round"
4145
+ [attr.x1]="half()"
4146
+ [attr.y1]="half()"
4147
+ [attr.x2]="half()"
4148
+ [attr.y2]="thickness() + 3"
4149
+ [attr.stroke]="color()"
4150
+ stroke-width="2.5"
4151
+ stroke-linecap="round"
3686
4152
  />
3687
4153
  </g>
3688
4154
  </svg>
@@ -3720,7 +4186,9 @@ const STRCT_MASKS = {
3720
4186
  * <strct-input-mask mask="HH:HH:HH:HH:HH:HH" uppercase [(ngModel)]="mac" />
3721
4187
  */
3722
4188
  class StrctInputMask {
4189
+ /** Mask pattern (9=digit, A=letter, H=hex, *=alnum). */
3723
4190
  mask = input.required(...(ngDevMode ? [{ debugName: "mask" }] : /* istanbul ignore next */ []));
4191
+ /** Placeholder text when empty. */
3724
4192
  placeholder = input('', ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
3725
4193
  /** Upper-case entered letters (handy for hex MAC / WWPN). */
3726
4194
  uppercase = input(false, { ...(ngDevMode ? { debugName: "uppercase" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
@@ -3832,8 +4300,12 @@ let comboboxCounter = 0;
3832
4300
  class StrctCombobox {
3833
4301
  host = inject((ElementRef));
3834
4302
  listId = `strct-cbx-${++comboboxCounter}`;
4303
+ /** Available options. */
3835
4304
  options = input([], ...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
4305
+ /** Placeholder text when empty. */
3836
4306
  placeholder = input('', ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
4307
+ /** Show a skeleton placeholder while options are loading. */
4308
+ loading = input(false, { ...(ngDevMode ? { debugName: "loading" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
3837
4309
  query = signal('', ...(ngDevMode ? [{ debugName: "query" }] : /* istanbul ignore next */ []));
3838
4310
  value = signal(null, ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
3839
4311
  open = signal(false, ...(ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []));
@@ -3940,7 +4412,7 @@ class StrctCombobox {
3940
4412
  this.isDisabled.set(isDisabled);
3941
4413
  }
3942
4414
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctCombobox, deps: [], target: i0.ɵɵFactoryTarget.Component });
3943
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: StrctCombobox, isStandalone: true, selector: "strct-combobox", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "document:click": "onDocClick($event)" }, classAttribute: "strct-cbx" }, providers: [
4415
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: StrctCombobox, isStandalone: true, selector: "strct-combobox", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "document:click": "onDocClick($event)" }, classAttribute: "strct-cbx" }, providers: [
3944
4416
  { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => StrctCombobox), multi: true },
3945
4417
  ], ngImport: i0, template: `
3946
4418
  <div #field class="strct-cbx__field">
@@ -3952,7 +4424,9 @@ class StrctCombobox {
3952
4424
  autocomplete="off"
3953
4425
  [attr.aria-expanded]="open()"
3954
4426
  [attr.aria-controls]="listId"
3955
- [attr.aria-activedescendant]="open() && filtered().length ? listId + '-' + activeIndex() : null"
4427
+ [attr.aria-activedescendant]="
4428
+ open() && filtered().length ? listId + '-' + activeIndex() : null
4429
+ "
3956
4430
  [placeholder]="placeholder()"
3957
4431
  [value]="query()"
3958
4432
  [disabled]="isDisabled()"
@@ -3972,25 +4446,31 @@ class StrctCombobox {
3972
4446
  strctOverlayPlacement="bottom-start"
3973
4447
  [strctOverlayMatchWidth]="true"
3974
4448
  >
3975
- @for (opt of filtered(); track opt.value; let i = $index) {
3976
- <div
3977
- class="strct-cbx__opt"
3978
- [id]="listId + '-' + i"
3979
- [class.strct-cbx__opt--active]="opt.value === value()"
3980
- [class.strct-cbx__opt--highlight]="i === activeIndex()"
3981
- role="option"
3982
- [attr.aria-selected]="opt.value === value()"
3983
- (mousedown)="select(opt, $event)"
3984
- (mousemove)="activeIndex.set(i)"
3985
- >
3986
- {{ opt.label }}
4449
+ @if (loading()) {
4450
+ <div class="strct-cbx__skeleton">
4451
+ <div class="strct-cbx__skeleton-block"></div>
3987
4452
  </div>
3988
- } @empty {
3989
- <div class="strct-cbx__empty">No matches</div>
4453
+ } @else {
4454
+ @for (opt of filtered(); track opt.value; let i = $index) {
4455
+ <div
4456
+ class="strct-cbx__opt"
4457
+ [id]="listId + '-' + i"
4458
+ [class.strct-cbx__opt--active]="opt.value === value()"
4459
+ [class.strct-cbx__opt--highlight]="i === activeIndex()"
4460
+ role="option"
4461
+ [attr.aria-selected]="opt.value === value()"
4462
+ (mousedown)="select(opt, $event)"
4463
+ (mousemove)="activeIndex.set(i)"
4464
+ >
4465
+ {{ opt.label }}
4466
+ </div>
4467
+ } @empty {
4468
+ <div class="strct-cbx__empty">No matches</div>
4469
+ }
3990
4470
  }
3991
4471
  </div>
3992
4472
  }
3993
- `, isInline: true, styles: [".strct-cbx{position:relative;display:block;width:100%}.strct-cbx__field{position:relative}.strct-cbx__input{padding-right:30px}.strct-cbx__caret{position:absolute;right:9px;top:50%;transform:translateY(-50%);color:var(--t3);pointer-events:none}.strct-cbx__menu{z-index:200;max-height:220px;overflow-y:auto;padding:4px;background:var(--bg-1);border:1px solid var(--b2);border-radius:7px;box-shadow:var(--shh)}.strct-cbx__opt{padding:7px 10px;border-radius:5px;cursor:pointer;font-size:13px;color:var(--t1)}.strct-cbx__opt--highlight{background:var(--bg-3)}.strct-cbx__opt--active{color:var(--acc)}.strct-cbx__opt--active.strct-cbx__opt--highlight{background:var(--acc-m)}.strct-cbx__empty{padding:9px 10px;font-size:13px;color:var(--t3)}\n"], dependencies: [{ kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "size", "strokeWidth", "badge"] }, { kind: "directive", type: StrctOverlay, selector: "[strctOverlay]", inputs: ["strctOverlay", "strctOverlayPlacement", "strctOverlayMatchWidth", "strctOverlayGap"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
4473
+ `, isInline: true, styles: [".strct-cbx{position:relative;display:block;width:100%}.strct-cbx__field{position:relative}.strct-cbx__input{padding-right:30px}.strct-cbx__caret{position:absolute;right:9px;top:50%;transform:translateY(-50%);color:var(--t3);pointer-events:none}.strct-cbx__menu{z-index:200;max-height:220px;overflow-y:auto;padding:4px;background:var(--bg-1);border:1px solid var(--b2);border-radius:7px;box-shadow:var(--shh)}.strct-cbx__opt{padding:7px 10px;border-radius:5px;cursor:pointer;font-size:13px;color:var(--t1)}.strct-cbx__opt--highlight{background:var(--bg-3)}.strct-cbx__opt--active{color:var(--acc)}.strct-cbx__opt--active.strct-cbx__opt--highlight{background:var(--acc-m)}@keyframes strct-skeleton-pulse{0%,to{opacity:.4}50%{opacity:.7}}.strct-cbx__skeleton{padding:9px 10px}.strct-cbx__skeleton-block{height:12px;background:var(--bg-3);border-radius:var(--radius-sm);animation:strct-skeleton-pulse 1.4s ease infinite}.strct-cbx__empty{padding:9px 10px;font-size:13px;color:var(--t3)}\n"], dependencies: [{ kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "size", "strokeWidth", "badge", "ariaLabel"] }, { kind: "directive", type: StrctOverlay, selector: "[strctOverlay]", inputs: ["strctOverlay", "strctOverlayPlacement", "strctOverlayMatchWidth", "strctOverlayGap"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
3994
4474
  }
3995
4475
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctCombobox, decorators: [{
3996
4476
  type: Component,
@@ -4006,7 +4486,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
4006
4486
  autocomplete="off"
4007
4487
  [attr.aria-expanded]="open()"
4008
4488
  [attr.aria-controls]="listId"
4009
- [attr.aria-activedescendant]="open() && filtered().length ? listId + '-' + activeIndex() : null"
4489
+ [attr.aria-activedescendant]="
4490
+ open() && filtered().length ? listId + '-' + activeIndex() : null
4491
+ "
4010
4492
  [placeholder]="placeholder()"
4011
4493
  [value]="query()"
4012
4494
  [disabled]="isDisabled()"
@@ -4026,33 +4508,49 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
4026
4508
  strctOverlayPlacement="bottom-start"
4027
4509
  [strctOverlayMatchWidth]="true"
4028
4510
  >
4029
- @for (opt of filtered(); track opt.value; let i = $index) {
4030
- <div
4031
- class="strct-cbx__opt"
4032
- [id]="listId + '-' + i"
4033
- [class.strct-cbx__opt--active]="opt.value === value()"
4034
- [class.strct-cbx__opt--highlight]="i === activeIndex()"
4035
- role="option"
4036
- [attr.aria-selected]="opt.value === value()"
4037
- (mousedown)="select(opt, $event)"
4038
- (mousemove)="activeIndex.set(i)"
4039
- >
4040
- {{ opt.label }}
4511
+ @if (loading()) {
4512
+ <div class="strct-cbx__skeleton">
4513
+ <div class="strct-cbx__skeleton-block"></div>
4041
4514
  </div>
4042
- } @empty {
4043
- <div class="strct-cbx__empty">No matches</div>
4515
+ } @else {
4516
+ @for (opt of filtered(); track opt.value; let i = $index) {
4517
+ <div
4518
+ class="strct-cbx__opt"
4519
+ [id]="listId + '-' + i"
4520
+ [class.strct-cbx__opt--active]="opt.value === value()"
4521
+ [class.strct-cbx__opt--highlight]="i === activeIndex()"
4522
+ role="option"
4523
+ [attr.aria-selected]="opt.value === value()"
4524
+ (mousedown)="select(opt, $event)"
4525
+ (mousemove)="activeIndex.set(i)"
4526
+ >
4527
+ {{ opt.label }}
4528
+ </div>
4529
+ } @empty {
4530
+ <div class="strct-cbx__empty">No matches</div>
4531
+ }
4044
4532
  }
4045
4533
  </div>
4046
4534
  }
4047
- `, host: { class: 'strct-cbx' }, styles: [".strct-cbx{position:relative;display:block;width:100%}.strct-cbx__field{position:relative}.strct-cbx__input{padding-right:30px}.strct-cbx__caret{position:absolute;right:9px;top:50%;transform:translateY(-50%);color:var(--t3);pointer-events:none}.strct-cbx__menu{z-index:200;max-height:220px;overflow-y:auto;padding:4px;background:var(--bg-1);border:1px solid var(--b2);border-radius:7px;box-shadow:var(--shh)}.strct-cbx__opt{padding:7px 10px;border-radius:5px;cursor:pointer;font-size:13px;color:var(--t1)}.strct-cbx__opt--highlight{background:var(--bg-3)}.strct-cbx__opt--active{color:var(--acc)}.strct-cbx__opt--active.strct-cbx__opt--highlight{background:var(--acc-m)}.strct-cbx__empty{padding:9px 10px;font-size:13px;color:var(--t3)}\n"] }]
4048
- }], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], onDocClick: [{
4535
+ `, host: { class: 'strct-cbx' }, styles: [".strct-cbx{position:relative;display:block;width:100%}.strct-cbx__field{position:relative}.strct-cbx__input{padding-right:30px}.strct-cbx__caret{position:absolute;right:9px;top:50%;transform:translateY(-50%);color:var(--t3);pointer-events:none}.strct-cbx__menu{z-index:200;max-height:220px;overflow-y:auto;padding:4px;background:var(--bg-1);border:1px solid var(--b2);border-radius:7px;box-shadow:var(--shh)}.strct-cbx__opt{padding:7px 10px;border-radius:5px;cursor:pointer;font-size:13px;color:var(--t1)}.strct-cbx__opt--highlight{background:var(--bg-3)}.strct-cbx__opt--active{color:var(--acc)}.strct-cbx__opt--active.strct-cbx__opt--highlight{background:var(--acc-m)}@keyframes strct-skeleton-pulse{0%,to{opacity:.4}50%{opacity:.7}}.strct-cbx__skeleton{padding:9px 10px}.strct-cbx__skeleton-block{height:12px;background:var(--bg-3);border-radius:var(--radius-sm);animation:strct-skeleton-pulse 1.4s ease infinite}.strct-cbx__empty{padding:9px 10px;font-size:13px;color:var(--t3)}\n"] }]
4536
+ }], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], onDocClick: [{
4049
4537
  type: HostListener,
4050
4538
  args: ['document:click', ['$event']]
4051
4539
  }] } });
4052
4540
 
4053
4541
  const MONTHS = [
4054
- 'January', 'February', 'March', 'April', 'May', 'June',
4055
- 'July', 'August', 'September', 'October', 'November', 'December',
4542
+ 'January',
4543
+ 'February',
4544
+ 'March',
4545
+ 'April',
4546
+ 'May',
4547
+ 'June',
4548
+ 'July',
4549
+ 'August',
4550
+ 'September',
4551
+ 'October',
4552
+ 'November',
4553
+ 'December',
4056
4554
  ];
4057
4555
  const DOW = ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'];
4058
4556
  const pad = (n) => String(n).padStart(2, '0');
@@ -4063,6 +4561,7 @@ const toIso = (y, m, d) => `${y}-${pad(m + 1)}-${pad(d)}`;
4063
4561
  */
4064
4562
  class StrctDatepicker {
4065
4563
  host = inject((ElementRef));
4564
+ /** Placeholder text when empty. */
4066
4565
  placeholder = input('Select a date', ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
4067
4566
  dow = DOW;
4068
4567
  value = signal('', ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
@@ -4236,13 +4735,28 @@ class StrctDatepicker {
4236
4735
  </div>
4237
4736
 
4238
4737
  @if (open()) {
4239
- <div class="strct-dp__panel" role="dialog" [strctOverlay]="field" strctOverlayPlacement="bottom-start">
4738
+ <div
4739
+ class="strct-dp__panel"
4740
+ role="dialog"
4741
+ [strctOverlay]="field"
4742
+ strctOverlayPlacement="bottom-start"
4743
+ >
4240
4744
  <div class="strct-dp__head">
4241
- <button type="button" class="strct-dp__nav" aria-label="Previous month" (click)="shiftMonth(-1)">
4745
+ <button
4746
+ type="button"
4747
+ class="strct-dp__nav"
4748
+ aria-label="Previous month"
4749
+ (click)="shiftMonth(-1)"
4750
+ >
4242
4751
  <strct-icon name="chevronLeft" [size]="14" [strokeWidth]="1.7" />
4243
4752
  </button>
4244
4753
  <span class="strct-dp__title">{{ monthLabel() }}</span>
4245
- <button type="button" class="strct-dp__nav" aria-label="Next month" (click)="shiftMonth(1)">
4754
+ <button
4755
+ type="button"
4756
+ class="strct-dp__nav"
4757
+ aria-label="Next month"
4758
+ (click)="shiftMonth(1)"
4759
+ >
4246
4760
  <strct-icon name="chevronRight" [size]="14" [strokeWidth]="1.7" />
4247
4761
  </button>
4248
4762
  </div>
@@ -4268,7 +4782,7 @@ class StrctDatepicker {
4268
4782
  </div>
4269
4783
  </div>
4270
4784
  }
4271
- `, isInline: true, styles: [".strct-dp{position:relative;display:inline-block;width:100%;max-width:240px}.strct-dp__field{position:relative}.strct-dp__input{padding-right:36px;cursor:pointer}.strct-dp__icon{position:absolute;right:4px;top:50%;transform:translateY(-50%);display:inline-flex;padding:5px;border:0;border-radius:5px;background:transparent;color:var(--t2);cursor:pointer}.strct-dp__icon:hover{color:var(--acc);background:var(--bg-3)}.strct-dp__panel{position:absolute;top:calc(100% + 5px);left:0;z-index:250;width:250px;padding:10px;background:var(--bg-1);border:1px solid var(--b2);border-radius:9px;box-shadow:var(--shh)}.strct-dp__head{display:flex;align-items:center;justify-content:space-between;margin-bottom:8px}.strct-dp__title{font-size:13px;font-weight:600;color:var(--t1)}.strct-dp__nav{display:inline-flex;padding:5px;border:0;border-radius:5px;background:transparent;color:var(--t2);cursor:pointer}.strct-dp__nav:hover{color:var(--t1);background:var(--bg-3)}.strct-dp__dow{display:grid;grid-template-columns:repeat(7,1fr);margin-bottom:4px}.strct-dp__dow span{text-align:center;font-size:10px;font-weight:600;color:var(--t3);padding:4px 0}.strct-dp__grid{display:grid;grid-template-columns:repeat(7,1fr);gap:2px}.strct-dp__day{aspect-ratio:1;display:inline-flex;align-items:center;justify-content:center;border:0;border-radius:6px;background:transparent;cursor:pointer;font-family:var(--font);font-size:12px;color:var(--t1)}.strct-dp__day:hover{background:var(--bg-3)}.strct-dp__day--muted{color:var(--t3)}.strct-dp__day--today{box-shadow:inset 0 0 0 1px var(--acc30)}.strct-dp__day--focused{box-shadow:inset 0 0 0 2px var(--acc)}.strct-dp__day--selected{background:var(--acc);color:#fff}.strct-dp__day--selected:hover{background:var(--acc)}\n"], dependencies: [{ kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "size", "strokeWidth", "badge"] }, { kind: "directive", type: StrctOverlay, selector: "[strctOverlay]", inputs: ["strctOverlay", "strctOverlayPlacement", "strctOverlayMatchWidth", "strctOverlayGap"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
4785
+ `, isInline: true, styles: [".strct-dp{position:relative;display:inline-block;width:100%;max-width:240px}.strct-dp__field{position:relative}.strct-dp__input{padding-right:36px;cursor:pointer}.strct-dp__icon{position:absolute;right:4px;top:50%;transform:translateY(-50%);display:inline-flex;padding:5px;border:0;border-radius:5px;background:transparent;color:var(--t2);cursor:pointer}.strct-dp__icon:hover{color:var(--acc);background:var(--bg-3)}.strct-dp__panel{position:absolute;top:calc(100% + 5px);left:0;z-index:250;width:250px;padding:10px;background:var(--bg-1);border:1px solid var(--b2);border-radius:9px;box-shadow:var(--shh)}.strct-dp__head{display:flex;align-items:center;justify-content:space-between;margin-bottom:8px}.strct-dp__title{font-size:13px;font-weight:600;color:var(--t1)}.strct-dp__nav{display:inline-flex;padding:5px;border:0;border-radius:5px;background:transparent;color:var(--t2);cursor:pointer}.strct-dp__nav:hover{color:var(--t1);background:var(--bg-3)}.strct-dp__dow{display:grid;grid-template-columns:repeat(7,1fr);margin-bottom:4px}.strct-dp__dow span{text-align:center;font-size:10px;font-weight:600;color:var(--t3);padding:4px 0}.strct-dp__grid{display:grid;grid-template-columns:repeat(7,1fr);gap:2px}.strct-dp__day{aspect-ratio:1;display:inline-flex;align-items:center;justify-content:center;border:0;border-radius:6px;background:transparent;cursor:pointer;font-family:var(--font);font-size:12px;color:var(--t1)}.strct-dp__day:hover{background:var(--bg-3)}.strct-dp__day--muted{color:var(--t3)}.strct-dp__day--today{box-shadow:inset 0 0 0 1px var(--acc30)}.strct-dp__day--focused{box-shadow:inset 0 0 0 2px var(--acc)}.strct-dp__day--selected{background:var(--acc);color:#fff}.strct-dp__day--selected:hover{background:var(--acc)}\n"], dependencies: [{ kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "size", "strokeWidth", "badge", "ariaLabel"] }, { kind: "directive", type: StrctOverlay, selector: "[strctOverlay]", inputs: ["strctOverlay", "strctOverlayPlacement", "strctOverlayMatchWidth", "strctOverlayGap"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
4272
4786
  }
4273
4787
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctDatepicker, decorators: [{
4274
4788
  type: Component,
@@ -4298,13 +4812,28 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
4298
4812
  </div>
4299
4813
 
4300
4814
  @if (open()) {
4301
- <div class="strct-dp__panel" role="dialog" [strctOverlay]="field" strctOverlayPlacement="bottom-start">
4815
+ <div
4816
+ class="strct-dp__panel"
4817
+ role="dialog"
4818
+ [strctOverlay]="field"
4819
+ strctOverlayPlacement="bottom-start"
4820
+ >
4302
4821
  <div class="strct-dp__head">
4303
- <button type="button" class="strct-dp__nav" aria-label="Previous month" (click)="shiftMonth(-1)">
4822
+ <button
4823
+ type="button"
4824
+ class="strct-dp__nav"
4825
+ aria-label="Previous month"
4826
+ (click)="shiftMonth(-1)"
4827
+ >
4304
4828
  <strct-icon name="chevronLeft" [size]="14" [strokeWidth]="1.7" />
4305
4829
  </button>
4306
4830
  <span class="strct-dp__title">{{ monthLabel() }}</span>
4307
- <button type="button" class="strct-dp__nav" aria-label="Next month" (click)="shiftMonth(1)">
4831
+ <button
4832
+ type="button"
4833
+ class="strct-dp__nav"
4834
+ aria-label="Next month"
4835
+ (click)="shiftMonth(1)"
4836
+ >
4308
4837
  <strct-icon name="chevronRight" [size]="14" [strokeWidth]="1.7" />
4309
4838
  </button>
4310
4839
  </div>
@@ -4340,8 +4869,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
4340
4869
  }] } });
4341
4870
 
4342
4871
  const DEFAULT_SWATCHES = [
4343
- '#7b9ec8', '#5a7ea3', '#7da87e', '#5e8a60', '#bfae6a', '#9a8a3e',
4344
- '#b87872', '#a0635c', '#96724e', '#c49a6c', '#8d7bc8', '#5a5a64',
4872
+ '#7b9ec8',
4873
+ '#5a7ea3',
4874
+ '#7da87e',
4875
+ '#5e8a60',
4876
+ '#bfae6a',
4877
+ '#9a8a3e',
4878
+ '#b87872',
4879
+ '#a0635c',
4880
+ '#96724e',
4881
+ '#c49a6c',
4882
+ '#8d7bc8',
4883
+ '#5a5a64',
4345
4884
  ];
4346
4885
  const HEX = /^#([0-9a-f]{6})$/i;
4347
4886
  /**
@@ -4350,6 +4889,7 @@ const HEX = /^#([0-9a-f]{6})$/i;
4350
4889
  */
4351
4890
  class StrctColorPicker {
4352
4891
  host = inject((ElementRef));
4892
+ /** Custom palette swatches. */
4353
4893
  swatches = input(DEFAULT_SWATCHES, ...(ngDevMode ? [{ debugName: "swatches" }] : /* istanbul ignore next */ []));
4354
4894
  value = signal('', ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
4355
4895
  draft = signal('', ...(ngDevMode ? [{ debugName: "draft" }] : /* istanbul ignore next */ []));
@@ -4420,7 +4960,12 @@ class StrctColorPicker {
4420
4960
  </button>
4421
4961
 
4422
4962
  @if (open()) {
4423
- <div class="strct-cp__panel" role="dialog" [strctOverlay]="trigger" strctOverlayPlacement="bottom-start">
4963
+ <div
4964
+ class="strct-cp__panel"
4965
+ role="dialog"
4966
+ [strctOverlay]="trigger"
4967
+ strctOverlayPlacement="bottom-start"
4968
+ >
4424
4969
  <div class="strct-cp__grid">
4425
4970
  @for (color of swatches(); track color) {
4426
4971
  <button
@@ -4462,7 +5007,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
4462
5007
  </button>
4463
5008
 
4464
5009
  @if (open()) {
4465
- <div class="strct-cp__panel" role="dialog" [strctOverlay]="trigger" strctOverlayPlacement="bottom-start">
5010
+ <div
5011
+ class="strct-cp__panel"
5012
+ role="dialog"
5013
+ [strctOverlay]="trigger"
5014
+ strctOverlayPlacement="bottom-start"
5015
+ >
4466
5016
  <div class="strct-cp__grid">
4467
5017
  @for (color of swatches(); track color) {
4468
5018
  <button
@@ -4502,6 +5052,7 @@ class StrctCascadeHost {
4502
5052
  */
4503
5053
  class StrctCascadeNode {
4504
5054
  host = inject(StrctCascadeHost);
5055
+ /** Option. */
4505
5056
  option = input.required(...(ngDevMode ? [{ debugName: "option" }] : /* istanbul ignore next */ []));
4506
5057
  open = signal(false, ...(ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []));
4507
5058
  hasChildren = computed(() => !!this.option().children?.length, ...(ngDevMode ? [{ debugName: "hasChildren" }] : /* istanbul ignore next */ []));
@@ -4520,9 +5071,12 @@ class StrctCascadeNode {
4520
5071
  class="strct-csn"
4521
5072
  [class.strct-csn--selected]="isLeafSelected()"
4522
5073
  role="menuitem"
5074
+ tabindex="0"
4523
5075
  (mouseenter)="hasChildren() && open.set(true)"
4524
5076
  (mouseleave)="open.set(false)"
4525
5077
  (click)="onClick($event)"
5078
+ (keydown.enter)="onClick($event)"
5079
+ (keydown.space)="onClick($event)"
4526
5080
  >
4527
5081
  <span class="strct-csn__label">{{ option().label }}</span>
4528
5082
  @if (hasChildren()) {
@@ -4536,7 +5090,7 @@ class StrctCascadeNode {
4536
5090
  </div>
4537
5091
  }
4538
5092
  </div>
4539
- `, isInline: true, styles: [".strct-csn{position:relative;display:flex;align-items:center;gap:8px;padding:7px 8px 7px 10px;border-radius:5px;cursor:pointer;font-size:13px;color:var(--t1)}.strct-csn:hover{background:var(--bg-3)}.strct-csn--selected{color:var(--acc);background:var(--acc-m)}.strct-csn__label{flex:1;white-space:nowrap}.strct-csn__arrow{color:var(--t3)}.strct-csn__flyout{position:absolute;top:-5px;left:100%;z-index:1;min-width:160px;margin-left:2px;padding:4px;background:var(--bg-1);border:1px solid var(--b2);border-radius:7px;box-shadow:var(--shh)}\n"], dependencies: [{ kind: "component", type: i0.forwardRef(() => StrctCascadeNode), selector: "strct-cascade-node", inputs: ["option"] }, { kind: "component", type: i0.forwardRef(() => StrctIcon), selector: "strct-icon", inputs: ["name", "size", "strokeWidth", "badge"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
5093
+ `, isInline: true, styles: [".strct-csn{position:relative;display:flex;align-items:center;gap:8px;padding:7px 8px 7px 10px;border-radius:5px;cursor:pointer;font-size:13px;color:var(--t1)}.strct-csn:hover{background:var(--bg-3)}.strct-csn--selected{color:var(--acc);background:var(--acc-m)}.strct-csn__label{flex:1;white-space:nowrap}.strct-csn__arrow{color:var(--t3)}.strct-csn__flyout{position:absolute;top:-5px;left:100%;z-index:1;min-width:160px;margin-left:2px;padding:4px;background:var(--bg-1);border:1px solid var(--b2);border-radius:7px;box-shadow:var(--shh)}\n"], dependencies: [{ kind: "component", type: i0.forwardRef(() => StrctCascadeNode), selector: "strct-cascade-node", inputs: ["option"] }, { kind: "component", type: i0.forwardRef(() => StrctIcon), selector: "strct-icon", inputs: ["name", "size", "strokeWidth", "badge", "ariaLabel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
4540
5094
  }
4541
5095
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctCascadeNode, decorators: [{
4542
5096
  type: Component,
@@ -4545,9 +5099,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
4545
5099
  class="strct-csn"
4546
5100
  [class.strct-csn--selected]="isLeafSelected()"
4547
5101
  role="menuitem"
5102
+ tabindex="0"
4548
5103
  (mouseenter)="hasChildren() && open.set(true)"
4549
5104
  (mouseleave)="open.set(false)"
4550
5105
  (click)="onClick($event)"
5106
+ (keydown.enter)="onClick($event)"
5107
+ (keydown.space)="onClick($event)"
4551
5108
  >
4552
5109
  <span class="strct-csn__label">{{ option().label }}</span>
4553
5110
  @if (hasChildren()) {
@@ -4570,7 +5127,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
4570
5127
  */
4571
5128
  class StrctCascadeSelect extends StrctCascadeHost {
4572
5129
  elementRef = inject((ElementRef));
5130
+ /** Available options. */
4573
5131
  options = input([], ...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
5132
+ /** Placeholder text when empty. */
4574
5133
  placeholder = input('Select…', ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
4575
5134
  value = signal(null, ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
4576
5135
  open = signal(false, ...(ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []));
@@ -4642,13 +5201,18 @@ class StrctCascadeSelect extends StrctCascadeHost {
4642
5201
  <strct-icon class="strct-cs__caret" name="chevronDown" [size]="14" />
4643
5202
  </button>
4644
5203
  @if (open()) {
4645
- <div class="strct-cs__panel" role="menu" [strctOverlay]="trigger" strctOverlayPlacement="bottom-start">
5204
+ <div
5205
+ class="strct-cs__panel"
5206
+ role="menu"
5207
+ [strctOverlay]="trigger"
5208
+ strctOverlayPlacement="bottom-start"
5209
+ >
4646
5210
  @for (opt of options(); track opt) {
4647
5211
  <strct-cascade-node [option]="opt" />
4648
5212
  }
4649
5213
  </div>
4650
5214
  }
4651
- `, isInline: true, styles: [".strct-cs{position:relative;display:inline-block;width:100%;max-width:280px}.strct-cs__trigger{display:flex;align-items:center;gap:8px;width:100%;padding:7px 10px;border-radius:6px;cursor:pointer;font-family:var(--font);font-size:13px;color:var(--t1);background:var(--bg-2);border:1px solid var(--b2);text-align:left}.strct-cs__trigger:hover{border-color:var(--b3)}.strct-cs__value{flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.strct-cs__value--empty,.strct-cs__caret{color:var(--t3)}.strct-cs__panel{position:absolute;top:calc(100% + 4px);left:0;z-index:200;min-width:180px;padding:4px;background:var(--bg-1);border:1px solid var(--b2);border-radius:7px;box-shadow:var(--shh)}\n"], dependencies: [{ kind: "component", type: StrctCascadeNode, selector: "strct-cascade-node", inputs: ["option"] }, { kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "size", "strokeWidth", "badge"] }, { kind: "directive", type: StrctOverlay, selector: "[strctOverlay]", inputs: ["strctOverlay", "strctOverlayPlacement", "strctOverlayMatchWidth", "strctOverlayGap"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
5215
+ `, isInline: true, styles: [".strct-cs{position:relative;display:inline-block;width:100%;max-width:280px}.strct-cs__trigger{display:flex;align-items:center;gap:8px;width:100%;padding:7px 10px;border-radius:6px;cursor:pointer;font-family:var(--font);font-size:13px;color:var(--t1);background:var(--bg-2);border:1px solid var(--b2);text-align:left}.strct-cs__trigger:hover{border-color:var(--b3)}.strct-cs__value{flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.strct-cs__value--empty,.strct-cs__caret{color:var(--t3)}.strct-cs__panel{position:absolute;top:calc(100% + 4px);left:0;z-index:200;min-width:180px;padding:4px;background:var(--bg-1);border:1px solid var(--b2);border-radius:7px;box-shadow:var(--shh)}\n"], dependencies: [{ kind: "component", type: StrctCascadeNode, selector: "strct-cascade-node", inputs: ["option"] }, { kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "size", "strokeWidth", "badge", "ariaLabel"] }, { kind: "directive", type: StrctOverlay, selector: "[strctOverlay]", inputs: ["strctOverlay", "strctOverlayPlacement", "strctOverlayMatchWidth", "strctOverlayGap"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
4652
5216
  }
4653
5217
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctCascadeSelect, decorators: [{
4654
5218
  type: Component,
@@ -4670,7 +5234,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
4670
5234
  <strct-icon class="strct-cs__caret" name="chevronDown" [size]="14" />
4671
5235
  </button>
4672
5236
  @if (open()) {
4673
- <div class="strct-cs__panel" role="menu" [strctOverlay]="trigger" strctOverlayPlacement="bottom-start">
5237
+ <div
5238
+ class="strct-cs__panel"
5239
+ role="menu"
5240
+ [strctOverlay]="trigger"
5241
+ strctOverlayPlacement="bottom-start"
5242
+ >
4674
5243
  @for (opt of options(); track opt) {
4675
5244
  <strct-cascade-node [option]="opt" />
4676
5245
  }
@@ -4690,10 +5259,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
4690
5259
  * is the directive value; the row, value and column are the template context:
4691
5260
  *
4692
5261
  * <ng-template strctCell="status" let-row let-value="value">
4693
- * <strct-badge [status]="row['ok'] ? 'success' : 'danger'">{{ value }}</strct-badge>
5262
+ * <strct-badge [status]="row['success'] ? 'success' : 'critical'">{{ value }}</strct-badge>
4694
5263
  * </ng-template>
4695
5264
  */
4696
5265
  class StrctCellDef {
5266
+ /** Key. */
4697
5267
  key = input.required({ ...(ngDevMode ? { debugName: "key" } : /* istanbul ignore next */ {}), alias: 'strctCell' });
4698
5268
  template = inject(TemplateRef);
4699
5269
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctCellDef, deps: [], target: i0.ɵɵFactoryTarget.Directive });
@@ -4709,11 +5279,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
4709
5279
  * <strct-table [columns]="cols" [rows]="data" hover />
4710
5280
  */
4711
5281
  class StrctTable {
5282
+ /** Column definitions. */
4712
5283
  columns = input.required(...(ngDevMode ? [{ debugName: "columns" }] : /* istanbul ignore next */ []));
5284
+ /** Data rows. */
4713
5285
  rows = input.required(...(ngDevMode ? [{ debugName: "rows" }] : /* istanbul ignore next */ []));
5286
+ /** Enable zebra-striping. */
4714
5287
  striped = input(false, { ...(ngDevMode ? { debugName: "striped" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
5288
+ /** Highlight rows on hover. */
4715
5289
  hover = input(false, { ...(ngDevMode ? { debugName: "hover" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
5290
+ /** Message shown when there are no rows. */
4716
5291
  emptyText = input('No data', ...(ngDevMode ? [{ debugName: "emptyText" }] : /* istanbul ignore next */ []));
5292
+ /** Show skeleton rows while data is loading. */
5293
+ loading = input(false, { ...(ngDevMode ? { debugName: "loading" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
4717
5294
  cellDefs = contentChildren(StrctCellDef, ...(ngDevMode ? [{ debugName: "cellDefs" }] : /* istanbul ignore next */ []));
4718
5295
  cellMap = computed(() => {
4719
5296
  const m = new Map();
@@ -4725,39 +5302,59 @@ class StrctTable {
4725
5302
  return this.cellMap().get(key) ?? null;
4726
5303
  }
4727
5304
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctTable, deps: [], target: i0.ɵɵFactoryTarget.Component });
4728
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: StrctTable, isStandalone: true, selector: "strct-table", inputs: { columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: true, transformFunction: null }, rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: true, transformFunction: null }, striped: { classPropertyName: "striped", publicName: "striped", isSignal: true, isRequired: false, transformFunction: null }, hover: { classPropertyName: "hover", publicName: "hover", isSignal: true, isRequired: false, transformFunction: null }, emptyText: { classPropertyName: "emptyText", publicName: "emptyText", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.strct-table-host--striped": "striped()", "class.strct-table-host--hover": "hover()" }, classAttribute: "strct-table-host" }, queries: [{ propertyName: "cellDefs", predicate: StrctCellDef, isSignal: true }], ngImport: i0, template: `
5305
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: StrctTable, isStandalone: true, selector: "strct-table", inputs: { columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: true, transformFunction: null }, rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: true, transformFunction: null }, striped: { classPropertyName: "striped", publicName: "striped", isSignal: true, isRequired: false, transformFunction: null }, hover: { classPropertyName: "hover", publicName: "hover", isSignal: true, isRequired: false, transformFunction: null }, emptyText: { classPropertyName: "emptyText", publicName: "emptyText", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.strct-table-host--striped": "striped()", "class.strct-table-host--hover": "hover()" }, classAttribute: "strct-table-host" }, queries: [{ propertyName: "cellDefs", predicate: StrctCellDef, isSignal: true }], ngImport: i0, template: `
4729
5306
  <table class="strct-table">
4730
5307
  <thead>
4731
5308
  <tr>
4732
5309
  @for (col of columns(); track col.key) {
4733
- <th [style.text-align]="col.align ?? 'start'" [style.width]="col.width">{{ col.label }}</th>
5310
+ <th [style.text-align]="col.align ?? 'start'" [style.width]="col.width">
5311
+ {{ col.label }}
5312
+ </th>
4734
5313
  }
4735
5314
  </tr>
4736
5315
  </thead>
4737
5316
  <tbody>
4738
- @for (row of rows(); track $index) {
4739
- <tr>
4740
- @for (col of columns(); track col.key) {
4741
- <td [style.text-align]="col.align ?? 'start'">
4742
- @if (cellTemplate(col.key); as tpl) {
4743
- <ng-container
4744
- [ngTemplateOutlet]="tpl"
4745
- [ngTemplateOutletContext]="{ $implicit: row, value: row[col.key], column: col }"
4746
- />
4747
- } @else {
4748
- {{ row[col.key] }}
4749
- }
5317
+ @if (loading()) {
5318
+ @for (_ of [1, 2, 3]; track $index) {
5319
+ <tr class="strct-table__skeleton-row">
5320
+ @for (col of columns(); track col.key) {
5321
+ <td [style.text-align]="col.align ?? 'start'">
5322
+ <div class="strct-table__skeleton-block"></div>
5323
+ </td>
5324
+ }
5325
+ </tr>
5326
+ }
5327
+ } @else {
5328
+ @for (row of rows(); track $index) {
5329
+ <tr>
5330
+ @for (col of columns(); track col.key) {
5331
+ <td [style.text-align]="col.align ?? 'start'">
5332
+ @if (cellTemplate(col.key); as tpl) {
5333
+ <ng-container
5334
+ [ngTemplateOutlet]="tpl"
5335
+ [ngTemplateOutletContext]="{
5336
+ $implicit: row,
5337
+ value: row[col.key],
5338
+ column: col,
5339
+ }"
5340
+ />
5341
+ } @else {
5342
+ {{ row[col.key] }}
5343
+ }
5344
+ </td>
5345
+ }
5346
+ </tr>
5347
+ } @empty {
5348
+ <tr>
5349
+ <td class="strct-table__empty" [attr.colspan]="columns().length">
5350
+ {{ emptyText() }}
4750
5351
  </td>
4751
- }
4752
- </tr>
4753
- } @empty {
4754
- <tr>
4755
- <td class="strct-table__empty" [attr.colspan]="columns().length">{{ emptyText() }}</td>
4756
- </tr>
5352
+ </tr>
5353
+ }
4757
5354
  }
4758
5355
  </tbody>
4759
5356
  </table>
4760
- `, isInline: true, styles: [".strct-table-host{display:block;overflow-x:auto}.strct-table{width:100%;border-collapse:collapse;font-size:13px;border:1px solid var(--b2);border-radius:8px;overflow:hidden}.strct-table th,.strct-table td{padding:9px 13px;text-align:left;border-bottom:1px solid var(--b1)}.strct-table th{font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.4px;color:var(--t2);background:var(--bg-2)}.strct-table td{color:var(--t1)}.strct-table tbody tr:last-child td{border-bottom:0}.strct-table-host--striped tbody tr:nth-child(2n) td{background:var(--bg-2)}.strct-table-host--hover tbody tr:hover td{background:var(--acc-s)}.strct-table__empty{text-align:center;color:var(--t3);padding:22px}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5357
+ `, isInline: true, styles: [".strct-table-host{display:block;overflow-x:auto}.strct-table{width:100%;border-collapse:collapse;font-size:13px;border:1px solid var(--b2);border-radius:8px;overflow:hidden}.strct-table th,.strct-table td{padding:9px 13px;text-align:left;border-bottom:1px solid var(--b1)}.strct-table th{font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.4px;color:var(--t2);background:var(--bg-2)}.strct-table td{color:var(--t1)}.strct-table tbody tr:last-child td{border-bottom:0}.strct-table-host--striped tbody tr:nth-child(2n) td{background:var(--bg-2)}.strct-table-host--hover tbody tr:hover td{background:var(--acc-s)}@keyframes strct-skeleton-pulse{0%,to{opacity:.4}50%{opacity:.7}}.strct-table__skeleton-block{height:12px;background:var(--bg-3);border-radius:var(--radius-sm);animation:strct-skeleton-pulse 1.4s ease infinite}.strct-table__skeleton-row td{border-bottom:1px solid var(--b1)}.strct-table__empty{text-align:center;color:var(--t3);padding:22px}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4761
5358
  }
4762
5359
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctTable, decorators: [{
4763
5360
  type: Component,
@@ -4766,30 +5363,50 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
4766
5363
  <thead>
4767
5364
  <tr>
4768
5365
  @for (col of columns(); track col.key) {
4769
- <th [style.text-align]="col.align ?? 'start'" [style.width]="col.width">{{ col.label }}</th>
5366
+ <th [style.text-align]="col.align ?? 'start'" [style.width]="col.width">
5367
+ {{ col.label }}
5368
+ </th>
4770
5369
  }
4771
5370
  </tr>
4772
5371
  </thead>
4773
5372
  <tbody>
4774
- @for (row of rows(); track $index) {
4775
- <tr>
4776
- @for (col of columns(); track col.key) {
4777
- <td [style.text-align]="col.align ?? 'start'">
4778
- @if (cellTemplate(col.key); as tpl) {
4779
- <ng-container
4780
- [ngTemplateOutlet]="tpl"
4781
- [ngTemplateOutletContext]="{ $implicit: row, value: row[col.key], column: col }"
4782
- />
4783
- } @else {
4784
- {{ row[col.key] }}
4785
- }
5373
+ @if (loading()) {
5374
+ @for (_ of [1, 2, 3]; track $index) {
5375
+ <tr class="strct-table__skeleton-row">
5376
+ @for (col of columns(); track col.key) {
5377
+ <td [style.text-align]="col.align ?? 'start'">
5378
+ <div class="strct-table__skeleton-block"></div>
5379
+ </td>
5380
+ }
5381
+ </tr>
5382
+ }
5383
+ } @else {
5384
+ @for (row of rows(); track $index) {
5385
+ <tr>
5386
+ @for (col of columns(); track col.key) {
5387
+ <td [style.text-align]="col.align ?? 'start'">
5388
+ @if (cellTemplate(col.key); as tpl) {
5389
+ <ng-container
5390
+ [ngTemplateOutlet]="tpl"
5391
+ [ngTemplateOutletContext]="{
5392
+ $implicit: row,
5393
+ value: row[col.key],
5394
+ column: col,
5395
+ }"
5396
+ />
5397
+ } @else {
5398
+ {{ row[col.key] }}
5399
+ }
5400
+ </td>
5401
+ }
5402
+ </tr>
5403
+ } @empty {
5404
+ <tr>
5405
+ <td class="strct-table__empty" [attr.colspan]="columns().length">
5406
+ {{ emptyText() }}
4786
5407
  </td>
4787
- }
4788
- </tr>
4789
- } @empty {
4790
- <tr>
4791
- <td class="strct-table__empty" [attr.colspan]="columns().length">{{ emptyText() }}</td>
4792
- </tr>
5408
+ </tr>
5409
+ }
4793
5410
  }
4794
5411
  </tbody>
4795
5412
  </table>
@@ -4797,8 +5414,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
4797
5414
  class: 'strct-table-host',
4798
5415
  '[class.strct-table-host--striped]': 'striped()',
4799
5416
  '[class.strct-table-host--hover]': 'hover()',
4800
- }, styles: [".strct-table-host{display:block;overflow-x:auto}.strct-table{width:100%;border-collapse:collapse;font-size:13px;border:1px solid var(--b2);border-radius:8px;overflow:hidden}.strct-table th,.strct-table td{padding:9px 13px;text-align:left;border-bottom:1px solid var(--b1)}.strct-table th{font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.4px;color:var(--t2);background:var(--bg-2)}.strct-table td{color:var(--t1)}.strct-table tbody tr:last-child td{border-bottom:0}.strct-table-host--striped tbody tr:nth-child(2n) td{background:var(--bg-2)}.strct-table-host--hover tbody tr:hover td{background:var(--acc-s)}.strct-table__empty{text-align:center;color:var(--t3);padding:22px}\n"] }]
4801
- }], propDecorators: { columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: true }] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: true }] }], striped: [{ type: i0.Input, args: [{ isSignal: true, alias: "striped", required: false }] }], hover: [{ type: i0.Input, args: [{ isSignal: true, alias: "hover", required: false }] }], emptyText: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyText", required: false }] }], cellDefs: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => StrctCellDef), { isSignal: true }] }] } });
5417
+ }, styles: [".strct-table-host{display:block;overflow-x:auto}.strct-table{width:100%;border-collapse:collapse;font-size:13px;border:1px solid var(--b2);border-radius:8px;overflow:hidden}.strct-table th,.strct-table td{padding:9px 13px;text-align:left;border-bottom:1px solid var(--b1)}.strct-table th{font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.4px;color:var(--t2);background:var(--bg-2)}.strct-table td{color:var(--t1)}.strct-table tbody tr:last-child td{border-bottom:0}.strct-table-host--striped tbody tr:nth-child(2n) td{background:var(--bg-2)}.strct-table-host--hover tbody tr:hover td{background:var(--acc-s)}@keyframes strct-skeleton-pulse{0%,to{opacity:.4}50%{opacity:.7}}.strct-table__skeleton-block{height:12px;background:var(--bg-3);border-radius:var(--radius-sm);animation:strct-skeleton-pulse 1.4s ease infinite}.strct-table__skeleton-row td{border-bottom:1px solid var(--b1)}.strct-table__empty{text-align:center;color:var(--t3);padding:22px}\n"] }]
5418
+ }], propDecorators: { columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: true }] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: true }] }], striped: [{ type: i0.Input, args: [{ isSignal: true, alias: "striped", required: false }] }], hover: [{ type: i0.Input, args: [{ isSignal: true, alias: "hover", required: false }] }], emptyText: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyText", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], cellDefs: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => StrctCellDef), { isSignal: true }] }] } });
4802
5419
 
4803
5420
  /**
4804
5421
  * Marks the expandable-row detail template. The row is the template's implicit
@@ -4831,23 +5448,32 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
4831
5448
  * </strct-datagrid>
4832
5449
  */
4833
5450
  class StrctDatagrid {
5451
+ /** Column definitions. */
4834
5452
  columns = input.required(...(ngDevMode ? [{ debugName: "columns" }] : /* istanbul ignore next */ []));
5453
+ /** Data rows. */
4835
5454
  rows = input.required(...(ngDevMode ? [{ debugName: "rows" }] : /* istanbul ignore next */ []));
5455
+ /** Rows per page (0 disables paging). */
4836
5456
  pageSize = input(0, ...(ngDevMode ? [{ debugName: "pageSize" }] : /* istanbul ignore next */ []));
5457
+ /** Enable row selection. */
4837
5458
  selectable = input(false, { ...(ngDevMode ? { debugName: "selectable" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
4838
5459
  /** Expand a row in place to reveal its detail template below it. */
4839
5460
  expandable = input(false, { ...(ngDevMode ? { debugName: "expandable" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
4840
5461
  /** Collapse the grid to a single column and open a side detail pane for the
4841
5462
  * clicked row (distinct from {@link expandable}). */
4842
5463
  detailPane = input(false, { ...(ngDevMode ? { debugName: "detailPane" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
5464
+ /** Compact density mode. */
4843
5465
  compact = input(false, { ...(ngDevMode ? { debugName: "compact" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
5466
+ /** Message shown when there are no rows. */
4844
5467
  emptyText = input('No data', ...(ngDevMode ? [{ debugName: "emptyText" }] : /* istanbul ignore next */ []));
5468
+ /** Show skeleton rows while data is loading. */
5469
+ loading = input(false, { ...(ngDevMode ? { debugName: "loading" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
4845
5470
  /**
4846
5471
  * Stable row identity (property key or function). Set this for live-refreshing
4847
5472
  * data so selection, expansion and the active detail row survive re-fetches
4848
5473
  * that replace the row objects. Defaults to object identity.
4849
5474
  */
4850
5475
  rowId = input(null, ...(ngDevMode ? [{ debugName: "rowId" }] : /* istanbul ignore next */ []));
5476
+ /** Emitted when the selection changes. */
4851
5477
  selectionChange = output();
4852
5478
  detailDef = contentChild(StrctRowDetailDef, ...(ngDevMode ? [{ debugName: "detailDef" }] : /* istanbul ignore next */ []));
4853
5479
  actionBarDef = contentChild(StrctDatagridActionBar, ...(ngDevMode ? [{ debugName: "actionBarDef" }] : /* istanbul ignore next */ []));
@@ -4972,13 +5598,23 @@ class StrctDatagrid {
4972
5598
  toggleExpand(row) {
4973
5599
  const id = this.idOf(row);
4974
5600
  const next = new Set(this.expandedRows());
4975
- next.has(id) ? next.delete(id) : next.add(id);
5601
+ if (next.has(id)) {
5602
+ next.delete(id);
5603
+ }
5604
+ else {
5605
+ next.add(id);
5606
+ }
4976
5607
  this.expandedRows.set(next);
4977
5608
  }
4978
5609
  toggleRow(row) {
4979
5610
  const id = this.idOf(row);
4980
5611
  const next = new Set(this.selected());
4981
- next.has(id) ? next.delete(id) : next.add(id);
5612
+ if (next.has(id)) {
5613
+ next.delete(id);
5614
+ }
5615
+ else {
5616
+ next.add(id);
5617
+ }
4982
5618
  this.commitSelection(next);
4983
5619
  }
4984
5620
  toggleAll() {
@@ -5007,143 +5643,184 @@ class StrctDatagrid {
5007
5643
  return String(a ?? '').localeCompare(String(b ?? ''), undefined, { numeric: true });
5008
5644
  }
5009
5645
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctDatagrid, deps: [], target: i0.ɵɵFactoryTarget.Component });
5010
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: StrctDatagrid, isStandalone: true, selector: "strct-datagrid", inputs: { columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: true, transformFunction: null }, rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: true, transformFunction: null }, pageSize: { classPropertyName: "pageSize", publicName: "pageSize", isSignal: true, isRequired: false, transformFunction: null }, selectable: { classPropertyName: "selectable", publicName: "selectable", isSignal: true, isRequired: false, transformFunction: null }, expandable: { classPropertyName: "expandable", publicName: "expandable", isSignal: true, isRequired: false, transformFunction: null }, detailPane: { classPropertyName: "detailPane", publicName: "detailPane", isSignal: true, isRequired: false, transformFunction: null }, compact: { classPropertyName: "compact", publicName: "compact", isSignal: true, isRequired: false, transformFunction: null }, emptyText: { classPropertyName: "emptyText", publicName: "emptyText", isSignal: true, isRequired: false, transformFunction: null }, rowId: { classPropertyName: "rowId", publicName: "rowId", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectionChange: "selectionChange" }, host: { properties: { "class.strct-dg-host--compact": "compact()" }, classAttribute: "strct-dg-host" }, queries: [{ propertyName: "detailDef", first: true, predicate: StrctRowDetailDef, descendants: true, isSignal: true }, { propertyName: "actionBarDef", first: true, predicate: StrctDatagridActionBar, descendants: true, isSignal: true }, { propertyName: "cellDefs", predicate: StrctCellDef, isSignal: true }], ngImport: i0, template: `
5646
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: StrctDatagrid, isStandalone: true, selector: "strct-datagrid", inputs: { columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: true, transformFunction: null }, rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: true, transformFunction: null }, pageSize: { classPropertyName: "pageSize", publicName: "pageSize", isSignal: true, isRequired: false, transformFunction: null }, selectable: { classPropertyName: "selectable", publicName: "selectable", isSignal: true, isRequired: false, transformFunction: null }, expandable: { classPropertyName: "expandable", publicName: "expandable", isSignal: true, isRequired: false, transformFunction: null }, detailPane: { classPropertyName: "detailPane", publicName: "detailPane", isSignal: true, isRequired: false, transformFunction: null }, compact: { classPropertyName: "compact", publicName: "compact", isSignal: true, isRequired: false, transformFunction: null }, emptyText: { classPropertyName: "emptyText", publicName: "emptyText", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, rowId: { classPropertyName: "rowId", publicName: "rowId", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectionChange: "selectionChange" }, host: { properties: { "class.strct-dg-host--compact": "compact()" }, classAttribute: "strct-dg-host" }, queries: [{ propertyName: "detailDef", first: true, predicate: StrctRowDetailDef, descendants: true, isSignal: true }, { propertyName: "actionBarDef", first: true, predicate: StrctDatagridActionBar, descendants: true, isSignal: true }, { propertyName: "cellDefs", predicate: StrctCellDef, isSignal: true }], ngImport: i0, template: `
5011
5647
  @if (actionBarDef()) {
5012
5648
  <div class="strct-dg__toolbar"><ng-content select="[strctDatagridActionBar]" /></div>
5013
5649
  }
5014
5650
 
5015
- @if (selectable() && selectedCount() > 0) {
5016
- <div class="strct-dg__actionbar">
5017
- <span class="strct-dg__actionbar-count">{{ selectedCount() }} selected</span>
5018
- <button type="button" class="strct-dg__actionbar-clear" (click)="clearSelection()">Clear</button>
5019
- <span class="strct-dg__actionbar-actions"><ng-content select="[strctDatagridActions]" /></span>
5020
- </div>
5021
- }
5022
-
5023
5651
  <div class="strct-dg__layout" [class.strct-dg__layout--paned]="paneOpen()">
5024
- <table class="strct-dg">
5025
- <thead>
5026
- <tr>
5027
- @if (canDetail()) {
5028
- <th class="strct-dg__expandcol"></th>
5029
- }
5030
- @if (canExpand()) {
5031
- <th class="strct-dg__expandcol"></th>
5032
- }
5033
- @if (selectable()) {
5034
- <th class="strct-dg__sel">
5035
- <input
5036
- type="checkbox"
5037
- aria-label="Select all rows on this page"
5038
- [checked]="allPageSelected()"
5039
- [indeterminate]="somePageSelected()"
5040
- (change)="toggleAll()"
5041
- />
5042
- </th>
5043
- }
5044
- @for (col of visibleColumns(); track col.key) {
5045
- <th
5046
- [style.text-align]="col.align ?? 'start'"
5047
- [style.width]="col.width"
5048
- [class.strct-dg__th--sortable]="col.sortable"
5049
- [attr.tabindex]="col.sortable ? 0 : null"
5050
- [attr.aria-sort]="col.sortable ? ariaSort(col.key) : null"
5051
- (click)="col.sortable && sortBy(col.key)"
5052
- (keydown.enter)="col.sortable && sortBy(col.key)"
5053
- (keydown.space)="col.sortable && onHeaderSpace($event, col.key)"
5054
- >
5055
- <span class="strct-dg__hd">
5056
- {{ col.label }}
5057
- @if (col.sortable) {
5058
- <strct-icon class="strct-dg__sorticon" [name]="sortIcon(col.key)" [size]="13" />
5059
- }
5060
- </span>
5061
- </th>
5062
- }
5063
- </tr>
5064
- </thead>
5065
- <tbody>
5066
- @for (row of paged(); track rowKey(row)) {
5067
- <tr
5068
- [class.strct-dg__row--selected]="isSelected(row)"
5069
- [class.strct-dg__row--active]="paneOpen() && row === activeRow()"
5070
- >
5071
- @if (canDetail()) {
5072
- <td class="strct-dg__expandcell">
5073
- <button
5074
- type="button"
5075
- class="strct-dg__detailbtn"
5076
- [class.strct-dg__detailbtn--active]="row === activeRow()"
5077
- [attr.aria-expanded]="row === activeRow()"
5078
- aria-label="Open detail"
5079
- (click)="openDetail(row)"
5080
- >
5081
- <strct-icon name="chevronDoubleRight" [size]="13" [strokeWidth]="1.6" />
5082
- </button>
5083
- </td>
5084
- }
5085
- @if (canExpand()) {
5086
- <td class="strct-dg__expandcell">
5087
- <button
5088
- type="button"
5089
- class="strct-dg__expandbtn"
5090
- [class.strct-dg__expandbtn--open]="isExpanded(row)"
5091
- [attr.aria-expanded]="isExpanded(row)"
5092
- aria-label="Toggle detail"
5093
- (click)="toggleExpand(row)"
5094
- >
5095
- <strct-icon name="chevronRight" [size]="12" [strokeWidth]="1.7" />
5096
- </button>
5097
- </td>
5098
- }
5099
- @if (selectable()) {
5100
- <td class="strct-dg__sel">
5101
- <input
5102
- type="checkbox"
5103
- aria-label="Select row"
5104
- [checked]="isSelected(row)"
5105
- (change)="toggleRow(row)"
5106
- />
5107
- </td>
5652
+ <div class="strct-dg__scroll">
5653
+ <table class="strct-dg">
5654
+ <thead>
5655
+ @if (selectable() && selectedCount() > 0) {
5656
+ <tr class="strct-dg__selbar">
5657
+ <th [attr.colspan]="colspan()" class="strct-dg__selbar-cell">
5658
+ <span class="strct-dg__selbar-count">{{ selectedCount() }} selected</span>
5659
+ <button type="button" class="strct-dg__selbar-clear" (click)="clearSelection()">
5660
+ Clear
5661
+ </button>
5662
+ <span class="strct-dg__selbar-actions">
5663
+ <ng-content select="[strctDatagridActions]" />
5664
+ </span>
5665
+ </th>
5666
+ </tr>
5108
5667
  }
5109
- @for (col of visibleColumns(); track col.key) {
5110
- <td [style.text-align]="col.align ?? 'start'">
5111
- @if (cellTemplate(col.key); as tpl) {
5112
- <ng-container
5113
- [ngTemplateOutlet]="tpl"
5114
- [ngTemplateOutletContext]="{ $implicit: row, value: row[col.key], column: col }"
5668
+ <tr>
5669
+ @if (canDetail()) {
5670
+ <th class="strct-dg__expandcol"></th>
5671
+ }
5672
+ @if (canExpand()) {
5673
+ <th class="strct-dg__expandcol"></th>
5674
+ }
5675
+ @if (selectable()) {
5676
+ <th class="strct-dg__sel">
5677
+ <input
5678
+ type="checkbox"
5679
+ aria-label="Select all rows on this page"
5680
+ [checked]="allPageSelected()"
5681
+ [indeterminate]="somePageSelected()"
5682
+ (change)="toggleAll()"
5115
5683
  />
5116
- } @else {
5117
- {{ row[col.key] }}
5684
+ </th>
5685
+ }
5686
+ @for (col of visibleColumns(); track col.key) {
5687
+ <th
5688
+ [style.text-align]="col.align ?? 'start'"
5689
+ [style.width]="col.width"
5690
+ [class.strct-dg__th--sortable]="col.sortable"
5691
+ [attr.tabindex]="col.sortable ? 0 : null"
5692
+ [attr.aria-sort]="col.sortable ? ariaSort(col.key) : null"
5693
+ (click)="col.sortable && sortBy(col.key)"
5694
+ (keydown.enter)="col.sortable && sortBy(col.key)"
5695
+ (keydown.space)="col.sortable && onHeaderSpace($event, col.key)"
5696
+ >
5697
+ <span class="strct-dg__hd">
5698
+ {{ col.label }}
5699
+ @if (col.sortable) {
5700
+ <strct-icon
5701
+ class="strct-dg__sorticon"
5702
+ [name]="sortIcon(col.key)"
5703
+ [size]="13"
5704
+ />
5705
+ }
5706
+ </span>
5707
+ </th>
5708
+ }
5709
+ </tr>
5710
+ </thead>
5711
+ <tbody>
5712
+ @if (loading()) {
5713
+ @for (_ of [1, 2, 3, 4, 5]; track $index) {
5714
+ <tr class="strct-dg__skeleton-row">
5715
+ @if (canDetail()) {
5716
+ <td class="strct-dg__expandcell"></td>
5717
+ }
5718
+ @if (canExpand()) {
5719
+ <td class="strct-dg__expandcell"></td>
5720
+ }
5721
+ @if (selectable()) {
5722
+ <td class="strct-dg__sel"></td>
5723
+ }
5724
+ @for (col of visibleColumns(); track col.key) {
5725
+ <td [style.text-align]="col.align ?? 'start'">
5726
+ <div class="strct-dg__skeleton-block"></div>
5727
+ </td>
5728
+ }
5729
+ </tr>
5730
+ }
5731
+ } @else {
5732
+ @for (row of paged(); track rowKey(row)) {
5733
+ <tr
5734
+ [class.strct-dg__row--selected]="isSelected(row)"
5735
+ [class.strct-dg__row--active]="paneOpen() && row === activeRow()"
5736
+ >
5737
+ @if (canDetail()) {
5738
+ <td class="strct-dg__expandcell">
5739
+ <button
5740
+ type="button"
5741
+ class="strct-dg__detailbtn"
5742
+ [class.strct-dg__detailbtn--active]="row === activeRow()"
5743
+ [attr.aria-expanded]="row === activeRow()"
5744
+ aria-label="Open detail"
5745
+ (click)="openDetail(row)"
5746
+ >
5747
+ <strct-icon name="chevronDoubleRight" [size]="13" [strokeWidth]="1.6" />
5748
+ </button>
5749
+ </td>
5750
+ }
5751
+ @if (canExpand()) {
5752
+ <td class="strct-dg__expandcell">
5753
+ <button
5754
+ type="button"
5755
+ class="strct-dg__expandbtn"
5756
+ [class.strct-dg__expandbtn--open]="isExpanded(row)"
5757
+ [attr.aria-expanded]="isExpanded(row)"
5758
+ aria-label="Toggle detail"
5759
+ (click)="toggleExpand(row)"
5760
+ >
5761
+ <strct-icon name="chevronRight" [size]="12" [strokeWidth]="1.7" />
5762
+ </button>
5763
+ </td>
5764
+ }
5765
+ @if (selectable()) {
5766
+ <td class="strct-dg__sel">
5767
+ <input
5768
+ type="checkbox"
5769
+ aria-label="Select row"
5770
+ [checked]="isSelected(row)"
5771
+ (change)="toggleRow(row)"
5772
+ />
5773
+ </td>
5774
+ }
5775
+ @for (col of visibleColumns(); track col.key) {
5776
+ <td [style.text-align]="col.align ?? 'start'">
5777
+ @if (cellTemplate(col.key); as tpl) {
5778
+ <ng-container
5779
+ [ngTemplateOutlet]="tpl"
5780
+ [ngTemplateOutletContext]="{
5781
+ $implicit: row,
5782
+ value: row[col.key],
5783
+ column: col,
5784
+ }"
5785
+ />
5786
+ } @else {
5787
+ {{ row[col.key] }}
5788
+ }
5789
+ </td>
5790
+ }
5791
+ </tr>
5792
+ @if (canExpand() && isExpanded(row)) {
5793
+ <tr class="strct-dg__detailrow">
5794
+ <td [attr.colspan]="colspan()">
5795
+ <div class="strct-dg__detail">
5796
+ <ng-container
5797
+ [ngTemplateOutlet]="detailDef()!.template"
5798
+ [ngTemplateOutletContext]="{ $implicit: row }"
5799
+ />
5800
+ </div>
5801
+ </td>
5802
+ </tr>
5118
5803
  }
5119
- </td>
5804
+ } @empty {
5805
+ <tr>
5806
+ <td class="strct-dg__empty" [attr.colspan]="colspan()">{{ emptyText() }}</td>
5807
+ </tr>
5808
+ }
5120
5809
  }
5121
- </tr>
5122
- @if (canExpand() && isExpanded(row)) {
5123
- <tr class="strct-dg__detailrow">
5124
- <td [attr.colspan]="colspan()">
5125
- <div class="strct-dg__detail">
5126
- <ng-container
5127
- [ngTemplateOutlet]="detailDef()!.template"
5128
- [ngTemplateOutletContext]="{ $implicit: row }"
5129
- />
5130
- </div>
5131
- </td>
5132
- </tr>
5133
- }
5134
- } @empty {
5135
- <tr>
5136
- <td class="strct-dg__empty" [attr.colspan]="colspan()">{{ emptyText() }}</td>
5137
- </tr>
5138
- }
5139
- </tbody>
5140
- </table>
5810
+ </tbody>
5811
+ </table>
5812
+ </div>
5141
5813
 
5142
5814
  @if (paneOpen()) {
5143
5815
  <aside class="strct-dg__pane">
5144
5816
  <div class="strct-dg__pane-head">
5145
5817
  <span class="strct-dg__pane-title">{{ activeRow()![columns()[0].key] }}</span>
5146
- <button type="button" class="strct-dg__pane-close" aria-label="Close detail" (click)="closePane()">
5818
+ <button
5819
+ type="button"
5820
+ class="strct-dg__pane-close"
5821
+ aria-label="Close detail"
5822
+ (click)="closePane()"
5823
+ >
5147
5824
  <strct-icon name="close" [size]="13" />
5148
5825
  </button>
5149
5826
  </div>
@@ -5157,7 +5834,7 @@ class StrctDatagrid {
5157
5834
  }
5158
5835
  </div>
5159
5836
 
5160
- @if (pageSize() > 0) {
5837
+ @if (pageSize() > 0 && !loading()) {
5161
5838
  <div class="strct-dg__foot">
5162
5839
  <span class="strct-dg__count">
5163
5840
  {{ sorted().length }} {{ sorted().length === 1 ? 'row' : 'rows' }}
@@ -5168,7 +5845,7 @@ class StrctDatagrid {
5168
5845
  <strct-pagination [total]="sorted().length" [pageSize]="pageSize()" [(page)]="page" />
5169
5846
  </div>
5170
5847
  }
5171
- `, isInline: true, styles: [".strct-dg-host{display:block}.strct-dg{width:100%;border-collapse:collapse;font-size:13px;border:1px solid var(--b2);border-radius:8px;overflow:hidden}.strct-dg th,.strct-dg td{padding:9px 13px;text-align:left;border-bottom:1px solid var(--b1)}.strct-dg-host--compact .strct-dg th,.strct-dg-host--compact .strct-dg td{padding:5px 11px}.strct-dg th{font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.4px;color:var(--t2);background:var(--bg-2);white-space:nowrap;-webkit-user-select:none;user-select:none}.strct-dg__th--sortable{cursor:pointer}.strct-dg__th--sortable:hover{color:var(--t1)}.strct-dg__th--sortable:focus-visible{outline:2px solid var(--acc50);outline-offset:-2px}.strct-dg__hd{display:inline-flex;align-items:center;gap:5px}.strct-dg__sorticon{color:var(--t3)}.strct-dg__th--sortable:hover .strct-dg__sorticon{color:var(--acc)}.strct-dg td{color:var(--t1)}.strct-dg tbody tr:last-child td{border-bottom:0}.strct-dg tbody tr:not(.strct-dg__detailrow):hover td{background:var(--acc-s)}.strct-dg__row--selected td{background:var(--acc-m)}.strct-dg__sel{width:1%;white-space:nowrap}.strct-dg__sel input{accent-color:var(--acc);width:15px;height:15px;cursor:pointer}.strct-dg__expandcol,.strct-dg__expandcell{width:1%;white-space:nowrap}.strct-dg__expandbtn{display:inline-flex;padding:3px;border:0;border-radius:4px;background:transparent;color:var(--t3);cursor:pointer;transition:transform .15s ease,color .15s ease}.strct-dg__expandbtn:hover{color:var(--t1);background:var(--bg-3)}.strct-dg__expandbtn--open{transform:rotate(90deg);color:var(--acc)}.strct-dg__detailbtn{display:inline-flex;padding:3px;border:0;border-radius:4px;background:transparent;color:var(--t3);cursor:pointer;transition:color .14s ease,background .14s ease}.strct-dg__detailbtn:hover{color:var(--acc);background:var(--bg-3)}.strct-dg__detailbtn--active{color:var(--acc);background:var(--acc-m)}.strct-dg__detailrow td{background:var(--bg-2);padding:0}.strct-dg__detail{padding:14px 16px;font-size:13px;color:var(--t2)}.strct-dg__layout{display:flex;gap:14px;align-items:flex-start}.strct-dg__layout--paned .strct-dg{width:auto;min-width:180px;max-width:260px;flex-shrink:0}.strct-dg__row--clickable{cursor:pointer}.strct-dg__row--active td{background:var(--acc-m)}.strct-dg__layout--paned .strct-dg__row--active td:last-child{position:relative;padding-right:26px}.strct-dg__layout--paned .strct-dg__row--active td:last-child:after{content:\"\";position:absolute;right:11px;top:50%;width:6px;height:6px;border-top:1.6px solid var(--acc);border-right:1.6px solid var(--acc);transform:translateY(-50%) rotate(45deg)}.strct-dg__pane{flex:1;min-width:0;align-self:stretch;background:var(--bg-1);border:1px solid var(--b2);border-left:2px solid var(--acc);border-radius:8px;overflow:hidden;animation:strct-dg-pane-in .14s ease}.strct-dg__pane-head{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:11px 14px;border-bottom:1px solid var(--b1);font-size:13px;font-weight:600;color:var(--t1)}.strct-dg__pane-close{display:inline-flex;padding:3px;border:0;border-radius:4px;background:transparent;color:var(--t3);cursor:pointer}.strct-dg__pane-close:hover{color:var(--t1);background:var(--bg-3)}.strct-dg__pane-body{padding:14px 16px;font-size:13px;color:var(--t2)}@keyframes strct-dg-pane-in{0%{opacity:0;transform:translate(8px)}}.strct-dg__empty{text-align:center;color:var(--t3);padding:22px}.strct-dg__toolbar{display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding:8px 10px;margin-bottom:10px;background:var(--bg-2);border:1px solid var(--b2);border-radius:8px}.strct-dg__actionbar{display:flex;align-items:center;gap:14px;padding:8px 12px;margin-bottom:10px;background:var(--acc-m);border:1px solid var(--acc30);border-radius:7px;font-size:13px;animation:strct-dg-bar-in .12s ease}.strct-dg__actionbar-count{color:var(--acc);font-weight:600}.strct-dg__actionbar-clear{border:0;background:transparent;color:var(--t2);cursor:pointer;font-size:12px;padding:2px 4px}.strct-dg__actionbar-clear:hover{color:var(--t1)}.strct-dg__actionbar-actions{display:flex;gap:8px;margin-left:auto}@keyframes strct-dg-bar-in{0%{opacity:0;transform:translateY(-4px)}}.strct-dg__foot{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-top:12px;flex-wrap:wrap}.strct-dg__count{font-size:12px;color:var(--t2)}\n"], dependencies: [{ kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "size", "strokeWidth", "badge"] }, { kind: "component", type: StrctPagination, selector: "strct-pagination", inputs: ["total", "pageSize", "page"], outputs: ["pageChange"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
5848
+ `, isInline: true, styles: [".strct-dg-host{display:block}.strct-dg__scroll{overflow-x:auto;-webkit-overflow-scrolling:touch}.strct-dg{width:100%;border-collapse:collapse;font-size:13px;border:1px solid var(--b2);border-radius:8px;overflow:hidden}.strct-dg th,.strct-dg td{padding:9px 13px;text-align:left;border-bottom:1px solid var(--b1)}.strct-dg-host--compact .strct-dg th,.strct-dg-host--compact .strct-dg td{padding:5px 11px}.strct-dg th{font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.4px;color:var(--t2);background:var(--bg-2);white-space:nowrap;-webkit-user-select:none;user-select:none}.strct-dg__th--sortable{cursor:pointer}.strct-dg__th--sortable:hover{color:var(--t1)}.strct-dg__th--sortable:focus-visible{outline:2px solid var(--acc50);outline-offset:-2px}.strct-dg__hd{display:inline-flex;align-items:center;gap:5px}.strct-dg__sorticon{color:var(--t3)}.strct-dg__th--sortable:hover .strct-dg__sorticon{color:var(--acc)}.strct-dg td{color:var(--t1)}.strct-dg tbody tr:last-child td{border-bottom:0}.strct-dg tbody tr:not(.strct-dg__detailrow):hover td{background:var(--acc-s)}.strct-dg__row--selected td{background:var(--acc-m)}.strct-dg__sel{width:1%;white-space:nowrap}.strct-dg__sel input{accent-color:var(--acc);width:15px;height:15px;cursor:pointer}.strct-dg__expandcol,.strct-dg__expandcell{width:1%;white-space:nowrap}.strct-dg__expandbtn{display:inline-flex;padding:3px;border:0;border-radius:4px;background:transparent;color:var(--t3);cursor:pointer;transition:transform .15s ease,color .15s ease}.strct-dg__expandbtn:hover{color:var(--t1);background:var(--bg-3)}.strct-dg__expandbtn--open{transform:rotate(90deg);color:var(--acc)}.strct-dg__detailbtn{display:inline-flex;padding:3px;border:0;border-radius:4px;background:transparent;color:var(--t3);cursor:pointer;transition:color .14s ease,background .14s ease}.strct-dg__detailbtn:hover{color:var(--acc);background:var(--bg-3)}.strct-dg__detailbtn--active{color:var(--acc);background:var(--acc-m)}.strct-dg__detailrow td{background:var(--bg-2);padding:0}.strct-dg__detail{padding:14px 16px;font-size:13px;color:var(--t2)}.strct-dg__layout{display:flex;gap:14px;align-items:flex-start}.strct-dg__layout--paned .strct-dg{width:auto;min-width:180px;max-width:260px;flex-shrink:0}.strct-dg__row--clickable{cursor:pointer}.strct-dg__row--active td{background:var(--acc-m)}.strct-dg__layout--paned .strct-dg__row--active td:last-child{position:relative;padding-right:26px}.strct-dg__layout--paned .strct-dg__row--active td:last-child:after{content:\"\";position:absolute;right:11px;top:50%;width:6px;height:6px;border-top:1.6px solid var(--acc);border-right:1.6px solid var(--acc);transform:translateY(-50%) rotate(45deg)}.strct-dg__pane{flex:1;min-width:0;align-self:stretch;background:var(--bg-1);border:1px solid var(--b2);border-left:2px solid var(--acc);border-radius:8px;overflow:hidden;animation:strct-dg-pane-in .14s ease}.strct-dg__pane-head{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:11px 14px;border-bottom:1px solid var(--b1);font-size:13px;font-weight:600;color:var(--t1)}.strct-dg__pane-close{display:inline-flex;padding:3px;border:0;border-radius:4px;background:transparent;color:var(--t3);cursor:pointer}.strct-dg__pane-close:hover{color:var(--t1);background:var(--bg-3)}.strct-dg__pane-body{padding:14px 16px;font-size:13px;color:var(--t2)}@keyframes strct-dg-pane-in{0%{opacity:0;transform:translate(8px)}}@keyframes strct-skeleton-pulse{0%,to{opacity:.4}50%{opacity:.7}}.strct-dg__skeleton-block{height:12px;background:var(--bg-3);border-radius:var(--radius-sm);animation:strct-skeleton-pulse 1.4s ease infinite}.strct-dg__skeleton-row td{border-bottom:1px solid var(--b1)}.strct-dg__empty{text-align:center;color:var(--t3);padding:22px}.strct-dg__toolbar{display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding:8px 0;margin-bottom:8px;border-bottom:1px solid var(--b1)}.strct-dg__selbar{animation:strct-dg-bar-in .12s ease}.strct-dg__selbar-cell{padding:7px 13px;font-size:12px;font-weight:500;color:var(--acc);border-bottom:1px solid var(--b1);background:var(--acc-m);text-align:left}.strct-dg__selbar-count{font-weight:600}.strct-dg__selbar-clear{border:0;background:transparent;color:var(--t2);cursor:pointer;font-size:12px;padding:2px 6px;margin-left:10px;border-radius:var(--radius-sm)}.strct-dg__selbar-clear:hover{color:var(--t1);background:var(--bg-3)}.strct-dg__selbar-actions{display:inline-flex;gap:8px;margin-left:auto}@keyframes strct-dg-bar-in{0%{opacity:0}}.strct-dg__foot{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-top:12px;flex-wrap:wrap}.strct-dg__count{font-size:12px;color:var(--t2)}\n"], dependencies: [{ kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "size", "strokeWidth", "badge", "ariaLabel"] }, { kind: "component", type: StrctPagination, selector: "strct-pagination", inputs: ["total", "pageSize", "page"], outputs: ["pageChange"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
5172
5849
  }
5173
5850
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctDatagrid, decorators: [{
5174
5851
  type: Component,
@@ -5177,138 +5854,179 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
5177
5854
  <div class="strct-dg__toolbar"><ng-content select="[strctDatagridActionBar]" /></div>
5178
5855
  }
5179
5856
 
5180
- @if (selectable() && selectedCount() > 0) {
5181
- <div class="strct-dg__actionbar">
5182
- <span class="strct-dg__actionbar-count">{{ selectedCount() }} selected</span>
5183
- <button type="button" class="strct-dg__actionbar-clear" (click)="clearSelection()">Clear</button>
5184
- <span class="strct-dg__actionbar-actions"><ng-content select="[strctDatagridActions]" /></span>
5185
- </div>
5186
- }
5187
-
5188
5857
  <div class="strct-dg__layout" [class.strct-dg__layout--paned]="paneOpen()">
5189
- <table class="strct-dg">
5190
- <thead>
5191
- <tr>
5192
- @if (canDetail()) {
5193
- <th class="strct-dg__expandcol"></th>
5194
- }
5195
- @if (canExpand()) {
5196
- <th class="strct-dg__expandcol"></th>
5197
- }
5198
- @if (selectable()) {
5199
- <th class="strct-dg__sel">
5200
- <input
5201
- type="checkbox"
5202
- aria-label="Select all rows on this page"
5203
- [checked]="allPageSelected()"
5204
- [indeterminate]="somePageSelected()"
5205
- (change)="toggleAll()"
5206
- />
5207
- </th>
5208
- }
5209
- @for (col of visibleColumns(); track col.key) {
5210
- <th
5211
- [style.text-align]="col.align ?? 'start'"
5212
- [style.width]="col.width"
5213
- [class.strct-dg__th--sortable]="col.sortable"
5214
- [attr.tabindex]="col.sortable ? 0 : null"
5215
- [attr.aria-sort]="col.sortable ? ariaSort(col.key) : null"
5216
- (click)="col.sortable && sortBy(col.key)"
5217
- (keydown.enter)="col.sortable && sortBy(col.key)"
5218
- (keydown.space)="col.sortable && onHeaderSpace($event, col.key)"
5219
- >
5220
- <span class="strct-dg__hd">
5221
- {{ col.label }}
5222
- @if (col.sortable) {
5223
- <strct-icon class="strct-dg__sorticon" [name]="sortIcon(col.key)" [size]="13" />
5224
- }
5225
- </span>
5226
- </th>
5227
- }
5228
- </tr>
5229
- </thead>
5230
- <tbody>
5231
- @for (row of paged(); track rowKey(row)) {
5232
- <tr
5233
- [class.strct-dg__row--selected]="isSelected(row)"
5234
- [class.strct-dg__row--active]="paneOpen() && row === activeRow()"
5235
- >
5236
- @if (canDetail()) {
5237
- <td class="strct-dg__expandcell">
5238
- <button
5239
- type="button"
5240
- class="strct-dg__detailbtn"
5241
- [class.strct-dg__detailbtn--active]="row === activeRow()"
5242
- [attr.aria-expanded]="row === activeRow()"
5243
- aria-label="Open detail"
5244
- (click)="openDetail(row)"
5245
- >
5246
- <strct-icon name="chevronDoubleRight" [size]="13" [strokeWidth]="1.6" />
5247
- </button>
5248
- </td>
5249
- }
5250
- @if (canExpand()) {
5251
- <td class="strct-dg__expandcell">
5252
- <button
5253
- type="button"
5254
- class="strct-dg__expandbtn"
5255
- [class.strct-dg__expandbtn--open]="isExpanded(row)"
5256
- [attr.aria-expanded]="isExpanded(row)"
5257
- aria-label="Toggle detail"
5258
- (click)="toggleExpand(row)"
5259
- >
5260
- <strct-icon name="chevronRight" [size]="12" [strokeWidth]="1.7" />
5261
- </button>
5262
- </td>
5858
+ <div class="strct-dg__scroll">
5859
+ <table class="strct-dg">
5860
+ <thead>
5861
+ @if (selectable() && selectedCount() > 0) {
5862
+ <tr class="strct-dg__selbar">
5863
+ <th [attr.colspan]="colspan()" class="strct-dg__selbar-cell">
5864
+ <span class="strct-dg__selbar-count">{{ selectedCount() }} selected</span>
5865
+ <button type="button" class="strct-dg__selbar-clear" (click)="clearSelection()">
5866
+ Clear
5867
+ </button>
5868
+ <span class="strct-dg__selbar-actions">
5869
+ <ng-content select="[strctDatagridActions]" />
5870
+ </span>
5871
+ </th>
5872
+ </tr>
5263
5873
  }
5264
- @if (selectable()) {
5265
- <td class="strct-dg__sel">
5266
- <input
5267
- type="checkbox"
5268
- aria-label="Select row"
5269
- [checked]="isSelected(row)"
5270
- (change)="toggleRow(row)"
5271
- />
5272
- </td>
5273
- }
5274
- @for (col of visibleColumns(); track col.key) {
5275
- <td [style.text-align]="col.align ?? 'start'">
5276
- @if (cellTemplate(col.key); as tpl) {
5277
- <ng-container
5278
- [ngTemplateOutlet]="tpl"
5279
- [ngTemplateOutletContext]="{ $implicit: row, value: row[col.key], column: col }"
5874
+ <tr>
5875
+ @if (canDetail()) {
5876
+ <th class="strct-dg__expandcol"></th>
5877
+ }
5878
+ @if (canExpand()) {
5879
+ <th class="strct-dg__expandcol"></th>
5880
+ }
5881
+ @if (selectable()) {
5882
+ <th class="strct-dg__sel">
5883
+ <input
5884
+ type="checkbox"
5885
+ aria-label="Select all rows on this page"
5886
+ [checked]="allPageSelected()"
5887
+ [indeterminate]="somePageSelected()"
5888
+ (change)="toggleAll()"
5280
5889
  />
5281
- } @else {
5282
- {{ row[col.key] }}
5890
+ </th>
5891
+ }
5892
+ @for (col of visibleColumns(); track col.key) {
5893
+ <th
5894
+ [style.text-align]="col.align ?? 'start'"
5895
+ [style.width]="col.width"
5896
+ [class.strct-dg__th--sortable]="col.sortable"
5897
+ [attr.tabindex]="col.sortable ? 0 : null"
5898
+ [attr.aria-sort]="col.sortable ? ariaSort(col.key) : null"
5899
+ (click)="col.sortable && sortBy(col.key)"
5900
+ (keydown.enter)="col.sortable && sortBy(col.key)"
5901
+ (keydown.space)="col.sortable && onHeaderSpace($event, col.key)"
5902
+ >
5903
+ <span class="strct-dg__hd">
5904
+ {{ col.label }}
5905
+ @if (col.sortable) {
5906
+ <strct-icon
5907
+ class="strct-dg__sorticon"
5908
+ [name]="sortIcon(col.key)"
5909
+ [size]="13"
5910
+ />
5911
+ }
5912
+ </span>
5913
+ </th>
5914
+ }
5915
+ </tr>
5916
+ </thead>
5917
+ <tbody>
5918
+ @if (loading()) {
5919
+ @for (_ of [1, 2, 3, 4, 5]; track $index) {
5920
+ <tr class="strct-dg__skeleton-row">
5921
+ @if (canDetail()) {
5922
+ <td class="strct-dg__expandcell"></td>
5923
+ }
5924
+ @if (canExpand()) {
5925
+ <td class="strct-dg__expandcell"></td>
5926
+ }
5927
+ @if (selectable()) {
5928
+ <td class="strct-dg__sel"></td>
5929
+ }
5930
+ @for (col of visibleColumns(); track col.key) {
5931
+ <td [style.text-align]="col.align ?? 'start'">
5932
+ <div class="strct-dg__skeleton-block"></div>
5933
+ </td>
5934
+ }
5935
+ </tr>
5936
+ }
5937
+ } @else {
5938
+ @for (row of paged(); track rowKey(row)) {
5939
+ <tr
5940
+ [class.strct-dg__row--selected]="isSelected(row)"
5941
+ [class.strct-dg__row--active]="paneOpen() && row === activeRow()"
5942
+ >
5943
+ @if (canDetail()) {
5944
+ <td class="strct-dg__expandcell">
5945
+ <button
5946
+ type="button"
5947
+ class="strct-dg__detailbtn"
5948
+ [class.strct-dg__detailbtn--active]="row === activeRow()"
5949
+ [attr.aria-expanded]="row === activeRow()"
5950
+ aria-label="Open detail"
5951
+ (click)="openDetail(row)"
5952
+ >
5953
+ <strct-icon name="chevronDoubleRight" [size]="13" [strokeWidth]="1.6" />
5954
+ </button>
5955
+ </td>
5956
+ }
5957
+ @if (canExpand()) {
5958
+ <td class="strct-dg__expandcell">
5959
+ <button
5960
+ type="button"
5961
+ class="strct-dg__expandbtn"
5962
+ [class.strct-dg__expandbtn--open]="isExpanded(row)"
5963
+ [attr.aria-expanded]="isExpanded(row)"
5964
+ aria-label="Toggle detail"
5965
+ (click)="toggleExpand(row)"
5966
+ >
5967
+ <strct-icon name="chevronRight" [size]="12" [strokeWidth]="1.7" />
5968
+ </button>
5969
+ </td>
5970
+ }
5971
+ @if (selectable()) {
5972
+ <td class="strct-dg__sel">
5973
+ <input
5974
+ type="checkbox"
5975
+ aria-label="Select row"
5976
+ [checked]="isSelected(row)"
5977
+ (change)="toggleRow(row)"
5978
+ />
5979
+ </td>
5980
+ }
5981
+ @for (col of visibleColumns(); track col.key) {
5982
+ <td [style.text-align]="col.align ?? 'start'">
5983
+ @if (cellTemplate(col.key); as tpl) {
5984
+ <ng-container
5985
+ [ngTemplateOutlet]="tpl"
5986
+ [ngTemplateOutletContext]="{
5987
+ $implicit: row,
5988
+ value: row[col.key],
5989
+ column: col,
5990
+ }"
5991
+ />
5992
+ } @else {
5993
+ {{ row[col.key] }}
5994
+ }
5995
+ </td>
5996
+ }
5997
+ </tr>
5998
+ @if (canExpand() && isExpanded(row)) {
5999
+ <tr class="strct-dg__detailrow">
6000
+ <td [attr.colspan]="colspan()">
6001
+ <div class="strct-dg__detail">
6002
+ <ng-container
6003
+ [ngTemplateOutlet]="detailDef()!.template"
6004
+ [ngTemplateOutletContext]="{ $implicit: row }"
6005
+ />
6006
+ </div>
6007
+ </td>
6008
+ </tr>
5283
6009
  }
5284
- </td>
6010
+ } @empty {
6011
+ <tr>
6012
+ <td class="strct-dg__empty" [attr.colspan]="colspan()">{{ emptyText() }}</td>
6013
+ </tr>
6014
+ }
5285
6015
  }
5286
- </tr>
5287
- @if (canExpand() && isExpanded(row)) {
5288
- <tr class="strct-dg__detailrow">
5289
- <td [attr.colspan]="colspan()">
5290
- <div class="strct-dg__detail">
5291
- <ng-container
5292
- [ngTemplateOutlet]="detailDef()!.template"
5293
- [ngTemplateOutletContext]="{ $implicit: row }"
5294
- />
5295
- </div>
5296
- </td>
5297
- </tr>
5298
- }
5299
- } @empty {
5300
- <tr>
5301
- <td class="strct-dg__empty" [attr.colspan]="colspan()">{{ emptyText() }}</td>
5302
- </tr>
5303
- }
5304
- </tbody>
5305
- </table>
6016
+ </tbody>
6017
+ </table>
6018
+ </div>
5306
6019
 
5307
6020
  @if (paneOpen()) {
5308
6021
  <aside class="strct-dg__pane">
5309
6022
  <div class="strct-dg__pane-head">
5310
6023
  <span class="strct-dg__pane-title">{{ activeRow()![columns()[0].key] }}</span>
5311
- <button type="button" class="strct-dg__pane-close" aria-label="Close detail" (click)="closePane()">
6024
+ <button
6025
+ type="button"
6026
+ class="strct-dg__pane-close"
6027
+ aria-label="Close detail"
6028
+ (click)="closePane()"
6029
+ >
5312
6030
  <strct-icon name="close" [size]="13" />
5313
6031
  </button>
5314
6032
  </div>
@@ -5322,7 +6040,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
5322
6040
  }
5323
6041
  </div>
5324
6042
 
5325
- @if (pageSize() > 0) {
6043
+ @if (pageSize() > 0 && !loading()) {
5326
6044
  <div class="strct-dg__foot">
5327
6045
  <span class="strct-dg__count">
5328
6046
  {{ sorted().length }} {{ sorted().length === 1 ? 'row' : 'rows' }}
@@ -5336,8 +6054,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
5336
6054
  `, host: {
5337
6055
  class: 'strct-dg-host',
5338
6056
  '[class.strct-dg-host--compact]': 'compact()',
5339
- }, styles: [".strct-dg-host{display:block}.strct-dg{width:100%;border-collapse:collapse;font-size:13px;border:1px solid var(--b2);border-radius:8px;overflow:hidden}.strct-dg th,.strct-dg td{padding:9px 13px;text-align:left;border-bottom:1px solid var(--b1)}.strct-dg-host--compact .strct-dg th,.strct-dg-host--compact .strct-dg td{padding:5px 11px}.strct-dg th{font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.4px;color:var(--t2);background:var(--bg-2);white-space:nowrap;-webkit-user-select:none;user-select:none}.strct-dg__th--sortable{cursor:pointer}.strct-dg__th--sortable:hover{color:var(--t1)}.strct-dg__th--sortable:focus-visible{outline:2px solid var(--acc50);outline-offset:-2px}.strct-dg__hd{display:inline-flex;align-items:center;gap:5px}.strct-dg__sorticon{color:var(--t3)}.strct-dg__th--sortable:hover .strct-dg__sorticon{color:var(--acc)}.strct-dg td{color:var(--t1)}.strct-dg tbody tr:last-child td{border-bottom:0}.strct-dg tbody tr:not(.strct-dg__detailrow):hover td{background:var(--acc-s)}.strct-dg__row--selected td{background:var(--acc-m)}.strct-dg__sel{width:1%;white-space:nowrap}.strct-dg__sel input{accent-color:var(--acc);width:15px;height:15px;cursor:pointer}.strct-dg__expandcol,.strct-dg__expandcell{width:1%;white-space:nowrap}.strct-dg__expandbtn{display:inline-flex;padding:3px;border:0;border-radius:4px;background:transparent;color:var(--t3);cursor:pointer;transition:transform .15s ease,color .15s ease}.strct-dg__expandbtn:hover{color:var(--t1);background:var(--bg-3)}.strct-dg__expandbtn--open{transform:rotate(90deg);color:var(--acc)}.strct-dg__detailbtn{display:inline-flex;padding:3px;border:0;border-radius:4px;background:transparent;color:var(--t3);cursor:pointer;transition:color .14s ease,background .14s ease}.strct-dg__detailbtn:hover{color:var(--acc);background:var(--bg-3)}.strct-dg__detailbtn--active{color:var(--acc);background:var(--acc-m)}.strct-dg__detailrow td{background:var(--bg-2);padding:0}.strct-dg__detail{padding:14px 16px;font-size:13px;color:var(--t2)}.strct-dg__layout{display:flex;gap:14px;align-items:flex-start}.strct-dg__layout--paned .strct-dg{width:auto;min-width:180px;max-width:260px;flex-shrink:0}.strct-dg__row--clickable{cursor:pointer}.strct-dg__row--active td{background:var(--acc-m)}.strct-dg__layout--paned .strct-dg__row--active td:last-child{position:relative;padding-right:26px}.strct-dg__layout--paned .strct-dg__row--active td:last-child:after{content:\"\";position:absolute;right:11px;top:50%;width:6px;height:6px;border-top:1.6px solid var(--acc);border-right:1.6px solid var(--acc);transform:translateY(-50%) rotate(45deg)}.strct-dg__pane{flex:1;min-width:0;align-self:stretch;background:var(--bg-1);border:1px solid var(--b2);border-left:2px solid var(--acc);border-radius:8px;overflow:hidden;animation:strct-dg-pane-in .14s ease}.strct-dg__pane-head{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:11px 14px;border-bottom:1px solid var(--b1);font-size:13px;font-weight:600;color:var(--t1)}.strct-dg__pane-close{display:inline-flex;padding:3px;border:0;border-radius:4px;background:transparent;color:var(--t3);cursor:pointer}.strct-dg__pane-close:hover{color:var(--t1);background:var(--bg-3)}.strct-dg__pane-body{padding:14px 16px;font-size:13px;color:var(--t2)}@keyframes strct-dg-pane-in{0%{opacity:0;transform:translate(8px)}}.strct-dg__empty{text-align:center;color:var(--t3);padding:22px}.strct-dg__toolbar{display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding:8px 10px;margin-bottom:10px;background:var(--bg-2);border:1px solid var(--b2);border-radius:8px}.strct-dg__actionbar{display:flex;align-items:center;gap:14px;padding:8px 12px;margin-bottom:10px;background:var(--acc-m);border:1px solid var(--acc30);border-radius:7px;font-size:13px;animation:strct-dg-bar-in .12s ease}.strct-dg__actionbar-count{color:var(--acc);font-weight:600}.strct-dg__actionbar-clear{border:0;background:transparent;color:var(--t2);cursor:pointer;font-size:12px;padding:2px 4px}.strct-dg__actionbar-clear:hover{color:var(--t1)}.strct-dg__actionbar-actions{display:flex;gap:8px;margin-left:auto}@keyframes strct-dg-bar-in{0%{opacity:0;transform:translateY(-4px)}}.strct-dg__foot{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-top:12px;flex-wrap:wrap}.strct-dg__count{font-size:12px;color:var(--t2)}\n"] }]
5340
- }], ctorParameters: () => [], propDecorators: { columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: true }] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: true }] }], pageSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSize", required: false }] }], selectable: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectable", required: false }] }], expandable: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandable", required: false }] }], detailPane: [{ type: i0.Input, args: [{ isSignal: true, alias: "detailPane", required: false }] }], compact: [{ type: i0.Input, args: [{ isSignal: true, alias: "compact", required: false }] }], emptyText: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyText", required: false }] }], rowId: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowId", required: false }] }], selectionChange: [{ type: i0.Output, args: ["selectionChange"] }], detailDef: [{ type: i0.ContentChild, args: [i0.forwardRef(() => StrctRowDetailDef), { isSignal: true }] }], actionBarDef: [{ type: i0.ContentChild, args: [i0.forwardRef(() => StrctDatagridActionBar), { isSignal: true }] }], cellDefs: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => StrctCellDef), { isSignal: true }] }] } });
6057
+ }, styles: [".strct-dg-host{display:block}.strct-dg__scroll{overflow-x:auto;-webkit-overflow-scrolling:touch}.strct-dg{width:100%;border-collapse:collapse;font-size:13px;border:1px solid var(--b2);border-radius:8px;overflow:hidden}.strct-dg th,.strct-dg td{padding:9px 13px;text-align:left;border-bottom:1px solid var(--b1)}.strct-dg-host--compact .strct-dg th,.strct-dg-host--compact .strct-dg td{padding:5px 11px}.strct-dg th{font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.4px;color:var(--t2);background:var(--bg-2);white-space:nowrap;-webkit-user-select:none;user-select:none}.strct-dg__th--sortable{cursor:pointer}.strct-dg__th--sortable:hover{color:var(--t1)}.strct-dg__th--sortable:focus-visible{outline:2px solid var(--acc50);outline-offset:-2px}.strct-dg__hd{display:inline-flex;align-items:center;gap:5px}.strct-dg__sorticon{color:var(--t3)}.strct-dg__th--sortable:hover .strct-dg__sorticon{color:var(--acc)}.strct-dg td{color:var(--t1)}.strct-dg tbody tr:last-child td{border-bottom:0}.strct-dg tbody tr:not(.strct-dg__detailrow):hover td{background:var(--acc-s)}.strct-dg__row--selected td{background:var(--acc-m)}.strct-dg__sel{width:1%;white-space:nowrap}.strct-dg__sel input{accent-color:var(--acc);width:15px;height:15px;cursor:pointer}.strct-dg__expandcol,.strct-dg__expandcell{width:1%;white-space:nowrap}.strct-dg__expandbtn{display:inline-flex;padding:3px;border:0;border-radius:4px;background:transparent;color:var(--t3);cursor:pointer;transition:transform .15s ease,color .15s ease}.strct-dg__expandbtn:hover{color:var(--t1);background:var(--bg-3)}.strct-dg__expandbtn--open{transform:rotate(90deg);color:var(--acc)}.strct-dg__detailbtn{display:inline-flex;padding:3px;border:0;border-radius:4px;background:transparent;color:var(--t3);cursor:pointer;transition:color .14s ease,background .14s ease}.strct-dg__detailbtn:hover{color:var(--acc);background:var(--bg-3)}.strct-dg__detailbtn--active{color:var(--acc);background:var(--acc-m)}.strct-dg__detailrow td{background:var(--bg-2);padding:0}.strct-dg__detail{padding:14px 16px;font-size:13px;color:var(--t2)}.strct-dg__layout{display:flex;gap:14px;align-items:flex-start}.strct-dg__layout--paned .strct-dg{width:auto;min-width:180px;max-width:260px;flex-shrink:0}.strct-dg__row--clickable{cursor:pointer}.strct-dg__row--active td{background:var(--acc-m)}.strct-dg__layout--paned .strct-dg__row--active td:last-child{position:relative;padding-right:26px}.strct-dg__layout--paned .strct-dg__row--active td:last-child:after{content:\"\";position:absolute;right:11px;top:50%;width:6px;height:6px;border-top:1.6px solid var(--acc);border-right:1.6px solid var(--acc);transform:translateY(-50%) rotate(45deg)}.strct-dg__pane{flex:1;min-width:0;align-self:stretch;background:var(--bg-1);border:1px solid var(--b2);border-left:2px solid var(--acc);border-radius:8px;overflow:hidden;animation:strct-dg-pane-in .14s ease}.strct-dg__pane-head{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:11px 14px;border-bottom:1px solid var(--b1);font-size:13px;font-weight:600;color:var(--t1)}.strct-dg__pane-close{display:inline-flex;padding:3px;border:0;border-radius:4px;background:transparent;color:var(--t3);cursor:pointer}.strct-dg__pane-close:hover{color:var(--t1);background:var(--bg-3)}.strct-dg__pane-body{padding:14px 16px;font-size:13px;color:var(--t2)}@keyframes strct-dg-pane-in{0%{opacity:0;transform:translate(8px)}}@keyframes strct-skeleton-pulse{0%,to{opacity:.4}50%{opacity:.7}}.strct-dg__skeleton-block{height:12px;background:var(--bg-3);border-radius:var(--radius-sm);animation:strct-skeleton-pulse 1.4s ease infinite}.strct-dg__skeleton-row td{border-bottom:1px solid var(--b1)}.strct-dg__empty{text-align:center;color:var(--t3);padding:22px}.strct-dg__toolbar{display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding:8px 0;margin-bottom:8px;border-bottom:1px solid var(--b1)}.strct-dg__selbar{animation:strct-dg-bar-in .12s ease}.strct-dg__selbar-cell{padding:7px 13px;font-size:12px;font-weight:500;color:var(--acc);border-bottom:1px solid var(--b1);background:var(--acc-m);text-align:left}.strct-dg__selbar-count{font-weight:600}.strct-dg__selbar-clear{border:0;background:transparent;color:var(--t2);cursor:pointer;font-size:12px;padding:2px 6px;margin-left:10px;border-radius:var(--radius-sm)}.strct-dg__selbar-clear:hover{color:var(--t1);background:var(--bg-3)}.strct-dg__selbar-actions{display:inline-flex;gap:8px;margin-left:auto}@keyframes strct-dg-bar-in{0%{opacity:0}}.strct-dg__foot{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-top:12px;flex-wrap:wrap}.strct-dg__count{font-size:12px;color:var(--t2)}\n"] }]
6058
+ }], ctorParameters: () => [], propDecorators: { columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: true }] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: true }] }], pageSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSize", required: false }] }], selectable: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectable", required: false }] }], expandable: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandable", required: false }] }], detailPane: [{ type: i0.Input, args: [{ isSignal: true, alias: "detailPane", required: false }] }], compact: [{ type: i0.Input, args: [{ isSignal: true, alias: "compact", required: false }] }], emptyText: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyText", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], rowId: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowId", required: false }] }], selectionChange: [{ type: i0.Output, args: ["selectionChange"] }], detailDef: [{ type: i0.ContentChild, args: [i0.forwardRef(() => StrctRowDetailDef), { isSignal: true }] }], actionBarDef: [{ type: i0.ContentChild, args: [i0.forwardRef(() => StrctDatagridActionBar), { isSignal: true }] }], cellDefs: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => StrctCellDef), { isSignal: true }] }] } });
5341
6059
 
5342
6060
  /** Vertical timeline container. Wraps `<strct-timeline-item>` children. */
5343
6061
  class StrctTimeline {
@@ -5350,10 +6068,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
5350
6068
  }] });
5351
6069
  /** A timeline entry: a node on the rail plus a title and projected body. */
5352
6070
  class StrctTimelineItem {
6071
+ /** Dialog title. */
5353
6072
  title = input.required(...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
6073
+ /** State. */
5354
6074
  state = input('default', ...(ngDevMode ? [{ debugName: "state" }] : /* istanbul ignore next */ []));
5355
6075
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctTimelineItem, deps: [], target: i0.ɵɵFactoryTarget.Component });
5356
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.16", type: StrctTimelineItem, isStandalone: true, selector: "strct-timeline-item", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: true, transformFunction: null }, state: { classPropertyName: "state", publicName: "state", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.strct-tli--current": "state() === 'current'", "class.strct-tli--success": "state() === 'success'", "class.strct-tli--warning": "state() === 'warning'", "class.strct-tli--danger": "state() === 'danger'" }, classAttribute: "strct-tli" }, ngImport: i0, template: `
6076
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.16", type: StrctTimelineItem, isStandalone: true, selector: "strct-timeline-item", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: true, transformFunction: null }, state: { classPropertyName: "state", publicName: "state", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.strct-tli--current": "state() === 'current'", "class.strct-tli--success": "state() === 'success'", "class.strct-tli--warning": "state() === 'warning'", "class.strct-tli--critical": "state() === 'critical'" }, classAttribute: "strct-tli" }, ngImport: i0, template: `
5357
6077
  <div class="strct-tli__rail">
5358
6078
  <span class="strct-tli__node"></span>
5359
6079
  <span class="strct-tli__line"></span>
@@ -5362,7 +6082,7 @@ class StrctTimelineItem {
5362
6082
  <div class="strct-tli__title">{{ title() }}</div>
5363
6083
  <div class="strct-tli__body"><ng-content /></div>
5364
6084
  </div>
5365
- `, isInline: true, styles: [".strct-tli{display:flex;gap:12px}.strct-tli__rail{display:flex;flex-direction:column;align-items:center}.strct-tli__node{width:11px;height:11px;border-radius:50%;margin-top:3px;flex-shrink:0;background:var(--bg-1);border:2px solid var(--b3)}.strct-tli__line{flex:1;width:2px;background:var(--b2);margin:4px 0}.strct-tli:last-child .strct-tli__line{display:none}.strct-tli__content{padding-bottom:18px}.strct-tli__title{font-size:13px;font-weight:600;color:var(--t1)}.strct-tli__body{margin-top:3px;font-size:13px;color:var(--t2)}.strct-tli--current .strct-tli__node{border-color:var(--acc);background:var(--acc-m);box-shadow:0 0 0 3px var(--acc18)}.strct-tli--success .strct-tli__node{border-color:var(--ok);background:var(--ok)}.strct-tli--warning .strct-tli__node{border-color:var(--wrn);background:var(--wrn)}.strct-tli--danger .strct-tli__node{border-color:var(--crt);background:var(--crt)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
6085
+ `, isInline: true, styles: [".strct-tli{display:flex;gap:12px}.strct-tli__rail{display:flex;flex-direction:column;align-items:center}.strct-tli__node{width:11px;height:11px;border-radius:50%;margin-top:3px;flex-shrink:0;background:var(--bg-1);border:2px solid var(--b3)}.strct-tli__line{flex:1;width:2px;background:var(--b2);margin:4px 0}.strct-tli:last-child .strct-tli__line{display:none}.strct-tli__content{padding-bottom:18px}.strct-tli__title{font-size:13px;font-weight:600;color:var(--t1)}.strct-tli__body{margin-top:3px;font-size:13px;color:var(--t2)}.strct-tli--current .strct-tli__node{border-color:var(--acc);background:var(--acc-m);box-shadow:0 0 0 3px var(--acc18)}.strct-tli--success .strct-tli__node{border-color:var(--success);background:var(--success)}.strct-tli--warning .strct-tli__node{border-color:var(--warning);background:var(--warning)}.strct-tli--critical .strct-tli__node{border-color:var(--critical);background:var(--critical)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
5366
6086
  }
5367
6087
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctTimelineItem, decorators: [{
5368
6088
  type: Component,
@@ -5380,8 +6100,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
5380
6100
  '[class.strct-tli--current]': "state() === 'current'",
5381
6101
  '[class.strct-tli--success]': "state() === 'success'",
5382
6102
  '[class.strct-tli--warning]': "state() === 'warning'",
5383
- '[class.strct-tli--danger]': "state() === 'danger'",
5384
- }, styles: [".strct-tli{display:flex;gap:12px}.strct-tli__rail{display:flex;flex-direction:column;align-items:center}.strct-tli__node{width:11px;height:11px;border-radius:50%;margin-top:3px;flex-shrink:0;background:var(--bg-1);border:2px solid var(--b3)}.strct-tli__line{flex:1;width:2px;background:var(--b2);margin:4px 0}.strct-tli:last-child .strct-tli__line{display:none}.strct-tli__content{padding-bottom:18px}.strct-tli__title{font-size:13px;font-weight:600;color:var(--t1)}.strct-tli__body{margin-top:3px;font-size:13px;color:var(--t2)}.strct-tli--current .strct-tli__node{border-color:var(--acc);background:var(--acc-m);box-shadow:0 0 0 3px var(--acc18)}.strct-tli--success .strct-tli__node{border-color:var(--ok);background:var(--ok)}.strct-tli--warning .strct-tli__node{border-color:var(--wrn);background:var(--wrn)}.strct-tli--danger .strct-tli__node{border-color:var(--crt);background:var(--crt)}\n"] }]
6103
+ '[class.strct-tli--critical]': "state() === 'critical'",
6104
+ }, styles: [".strct-tli{display:flex;gap:12px}.strct-tli__rail{display:flex;flex-direction:column;align-items:center}.strct-tli__node{width:11px;height:11px;border-radius:50%;margin-top:3px;flex-shrink:0;background:var(--bg-1);border:2px solid var(--b3)}.strct-tli__line{flex:1;width:2px;background:var(--b2);margin:4px 0}.strct-tli:last-child .strct-tli__line{display:none}.strct-tli__content{padding-bottom:18px}.strct-tli__title{font-size:13px;font-weight:600;color:var(--t1)}.strct-tli__body{margin-top:3px;font-size:13px;color:var(--t2)}.strct-tli--current .strct-tli__node{border-color:var(--acc);background:var(--acc-m);box-shadow:0 0 0 3px var(--acc18)}.strct-tli--success .strct-tli__node{border-color:var(--success);background:var(--success)}.strct-tli--warning .strct-tli__node{border-color:var(--warning);background:var(--warning)}.strct-tli--critical .strct-tli__node{border-color:var(--critical);background:var(--critical)}\n"] }]
5385
6105
  }], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: true }] }], state: [{ type: i0.Input, args: [{ isSignal: true, alias: "state", required: false }] }] } });
5386
6106
 
5387
6107
  /** Key/value definition list. Wraps `<strct-stack-item>` rows. */
@@ -5395,6 +6115,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
5395
6115
  }] });
5396
6116
  /** A label + value row. The value is projected content. */
5397
6117
  class StrctStackItem {
6118
+ /** Label text. */
5398
6119
  label = input.required(...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
5399
6120
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctStackItem, deps: [], target: i0.ɵɵFactoryTarget.Component });
5400
6121
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.16", type: StrctStackItem, isStandalone: true, selector: "strct-stack-item", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null } }, host: { classAttribute: "strct-stack__item" }, ngImport: i0, template: `
@@ -5412,18 +6133,23 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
5412
6133
 
5413
6134
  const STROKE = {
5414
6135
  accent: 'var(--acc)',
5415
- success: 'var(--ok)',
5416
- warning: 'var(--wrn)',
5417
- danger: 'var(--crt)',
6136
+ success: 'var(--success)',
6137
+ warning: 'var(--warning)',
6138
+ critical: 'var(--critical)',
5418
6139
  };
5419
6140
  /**
5420
6141
  * Tiny inline trend line. `<strct-sparkline [data]="[3,5,4,8,6,9]" area />`.
5421
6142
  */
5422
6143
  class StrctSparkline {
6144
+ /** Data array. */
5423
6145
  data = input.required(...(ngDevMode ? [{ debugName: "data" }] : /* istanbul ignore next */ []));
6146
+ /** Visual status color. */
5424
6147
  status = input('accent', ...(ngDevMode ? [{ debugName: "status" }] : /* istanbul ignore next */ []));
6148
+ /** Fill the area under the line. */
5425
6149
  area = input(false, { ...(ngDevMode ? { debugName: "area" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
6150
+ /** Width (CSS length). */
5426
6151
  width = input(100, ...(ngDevMode ? [{ debugName: "width" }] : /* istanbul ignore next */ []));
6152
+ /** Height in pixels. */
5427
6153
  height = input(30, ...(ngDevMode ? [{ debugName: "height" }] : /* istanbul ignore next */ []));
5428
6154
  color = computed(() => STROKE[this.status()], ...(ngDevMode ? [{ debugName: "color" }] : /* istanbul ignore next */ []));
5429
6155
  points = computed(() => {
@@ -5436,7 +6162,9 @@ class StrctSparkline {
5436
6162
  const stepX = d.length > 1 ? 100 / (d.length - 1) : 0;
5437
6163
  return d.map((v, i) => ({ x: i * stepX, y: 29 - ((v - min) / span) * 28 }));
5438
6164
  }, ...(ngDevMode ? [{ debugName: "points" }] : /* istanbul ignore next */ []));
5439
- linePoints = computed(() => this.points().map((p) => `${p.x},${p.y}`).join(' '), ...(ngDevMode ? [{ debugName: "linePoints" }] : /* istanbul ignore next */ []));
6165
+ linePoints = computed(() => this.points()
6166
+ .map((p) => `${p.x},${p.y}`)
6167
+ .join(' '), ...(ngDevMode ? [{ debugName: "linePoints" }] : /* istanbul ignore next */ []));
5440
6168
  areaPoints = computed(() => {
5441
6169
  const pts = this.points();
5442
6170
  if (!pts.length)
@@ -5489,9 +6217,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
5489
6217
 
5490
6218
  const COLOR$1 = {
5491
6219
  accent: 'var(--acc)',
5492
- success: 'var(--ok)',
5493
- warning: 'var(--wrn)',
5494
- danger: 'var(--crt)',
6220
+ success: 'var(--success)',
6221
+ warning: 'var(--warning)',
6222
+ critical: 'var(--critical)',
5495
6223
  };
5496
6224
  const VB_W = 320;
5497
6225
  const PAD = { l: 6, r: 6, t: 10, b: 10 };
@@ -5500,10 +6228,15 @@ const PAD = { l: 6, r: 6, t: 10, b: 10 };
5500
6228
  * <strct-chart [data]="cpu" type="area" [labels]="hours" status="warning" />
5501
6229
  */
5502
6230
  class StrctChart {
6231
+ /** Data array. */
5503
6232
  data = input.required(...(ngDevMode ? [{ debugName: "data" }] : /* istanbul ignore next */ []));
6233
+ /** Visual type / variant. */
5504
6234
  type = input('line', ...(ngDevMode ? [{ debugName: "type" }] : /* istanbul ignore next */ []));
6235
+ /** X-axis labels. */
5505
6236
  labels = input([], ...(ngDevMode ? [{ debugName: "labels" }] : /* istanbul ignore next */ []));
6237
+ /** Visual status color. */
5506
6238
  status = input('accent', ...(ngDevMode ? [{ debugName: "status" }] : /* istanbul ignore next */ []));
6239
+ /** Height in pixels. */
5507
6240
  height = input(160, ...(ngDevMode ? [{ debugName: "height" }] : /* istanbul ignore next */ []));
5508
6241
  /** Override the top of the value axis (defaults to the data max + headroom). */
5509
6242
  max = input(null, ...(ngDevMode ? [{ debugName: "max" }] : /* istanbul ignore next */ []));
@@ -5530,7 +6263,9 @@ class StrctChart {
5530
6263
  y: PAD.t + (1 - Math.max(0, v) / max) * this.chartH(),
5531
6264
  }));
5532
6265
  }, ...(ngDevMode ? [{ debugName: "points" }] : /* istanbul ignore next */ []));
5533
- linePoints = computed(() => this.points().map((p) => `${p.x},${p.y}`).join(' '), ...(ngDevMode ? [{ debugName: "linePoints" }] : /* istanbul ignore next */ []));
6266
+ linePoints = computed(() => this.points()
6267
+ .map((p) => `${p.x},${p.y}`)
6268
+ .join(' '), ...(ngDevMode ? [{ debugName: "linePoints" }] : /* istanbul ignore next */ []));
5534
6269
  areaPoints = computed(() => {
5535
6270
  const pts = this.points();
5536
6271
  if (!pts.length)
@@ -5564,20 +6299,44 @@ class StrctChart {
5564
6299
  [style.height.px]="height()"
5565
6300
  >
5566
6301
  @for (g of gridY(); track g) {
5567
- <line class="strct-chart__grid" [attr.x1]="pad.l" [attr.x2]="vbW - pad.r" [attr.y1]="g" [attr.y2]="g" />
6302
+ <line
6303
+ class="strct-chart__grid"
6304
+ [attr.x1]="pad.l"
6305
+ [attr.x2]="vbW - pad.r"
6306
+ [attr.y1]="g"
6307
+ [attr.y2]="g"
6308
+ />
5568
6309
  }
5569
6310
 
5570
6311
  @if (type() === 'bar') {
5571
6312
  @for (b of bars(); track $index) {
5572
- <rect class="strct-chart__bar" [attr.x]="b.x" [attr.y]="b.y" [attr.width]="b.w" [attr.height]="b.h" [attr.fill]="color()" />
6313
+ <rect
6314
+ class="strct-chart__bar"
6315
+ [attr.x]="b.x"
6316
+ [attr.y]="b.y"
6317
+ [attr.width]="b.w"
6318
+ [attr.height]="b.h"
6319
+ [attr.fill]="color()"
6320
+ />
5573
6321
  }
5574
6322
  } @else {
5575
6323
  @if (type() === 'area') {
5576
6324
  <polygon class="strct-chart__area" [attr.points]="areaPoints()" [attr.fill]="color()" />
5577
6325
  }
5578
- <polyline class="strct-chart__line" fill="none" [attr.points]="linePoints()" [attr.stroke]="color()" />
6326
+ <polyline
6327
+ class="strct-chart__line"
6328
+ fill="none"
6329
+ [attr.points]="linePoints()"
6330
+ [attr.stroke]="color()"
6331
+ />
5579
6332
  @for (p of points(); track $index) {
5580
- <circle class="strct-chart__dot" [attr.cx]="p.x" [attr.cy]="p.y" r="2" [attr.fill]="color()" />
6333
+ <circle
6334
+ class="strct-chart__dot"
6335
+ [attr.cx]="p.x"
6336
+ [attr.cy]="p.y"
6337
+ r="2"
6338
+ [attr.fill]="color()"
6339
+ />
5581
6340
  }
5582
6341
  }
5583
6342
  </svg>
@@ -5601,20 +6360,44 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
5601
6360
  [style.height.px]="height()"
5602
6361
  >
5603
6362
  @for (g of gridY(); track g) {
5604
- <line class="strct-chart__grid" [attr.x1]="pad.l" [attr.x2]="vbW - pad.r" [attr.y1]="g" [attr.y2]="g" />
6363
+ <line
6364
+ class="strct-chart__grid"
6365
+ [attr.x1]="pad.l"
6366
+ [attr.x2]="vbW - pad.r"
6367
+ [attr.y1]="g"
6368
+ [attr.y2]="g"
6369
+ />
5605
6370
  }
5606
6371
 
5607
6372
  @if (type() === 'bar') {
5608
6373
  @for (b of bars(); track $index) {
5609
- <rect class="strct-chart__bar" [attr.x]="b.x" [attr.y]="b.y" [attr.width]="b.w" [attr.height]="b.h" [attr.fill]="color()" />
6374
+ <rect
6375
+ class="strct-chart__bar"
6376
+ [attr.x]="b.x"
6377
+ [attr.y]="b.y"
6378
+ [attr.width]="b.w"
6379
+ [attr.height]="b.h"
6380
+ [attr.fill]="color()"
6381
+ />
5610
6382
  }
5611
6383
  } @else {
5612
6384
  @if (type() === 'area') {
5613
6385
  <polygon class="strct-chart__area" [attr.points]="areaPoints()" [attr.fill]="color()" />
5614
6386
  }
5615
- <polyline class="strct-chart__line" fill="none" [attr.points]="linePoints()" [attr.stroke]="color()" />
6387
+ <polyline
6388
+ class="strct-chart__line"
6389
+ fill="none"
6390
+ [attr.points]="linePoints()"
6391
+ [attr.stroke]="color()"
6392
+ />
5616
6393
  @for (p of points(); track $index) {
5617
- <circle class="strct-chart__dot" [attr.cx]="p.x" [attr.cy]="p.y" r="2" [attr.fill]="color()" />
6394
+ <circle
6395
+ class="strct-chart__dot"
6396
+ [attr.cx]="p.x"
6397
+ [attr.cy]="p.y"
6398
+ r="2"
6399
+ [attr.fill]="color()"
6400
+ />
5618
6401
  }
5619
6402
  }
5620
6403
  </svg>
@@ -5629,17 +6412,29 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
5629
6412
  `, host: { class: 'strct-chart' }, styles: [".strct-chart{display:block}.strct-chart__svg{width:100%;display:block}.strct-chart__grid{stroke:var(--b1);stroke-width:1;vector-effect:non-scaling-stroke}.strct-chart__line{stroke-width:2;vector-effect:non-scaling-stroke;stroke-linejoin:round;stroke-linecap:round}.strct-chart__area{opacity:.13}.strct-chart__dot{stroke:var(--bg-1);stroke-width:1.5}.strct-chart__bar{rx:1.5}.strct-chart__labels{display:flex;justify-content:space-between;margin-top:6px;font-size:10px;color:var(--t3)}\n"] }]
5630
6413
  }], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: true }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], labels: [{ type: i0.Input, args: [{ isSignal: true, alias: "labels", required: false }] }], status: [{ type: i0.Input, args: [{ isSignal: true, alias: "status", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }] } });
5631
6414
 
5632
- const PALETTE = ['var(--acc)', 'var(--ok)', 'var(--wrn)', 'var(--crt)', 'var(--acc50)', 'var(--t3)'];
6415
+ const PALETTE = [
6416
+ 'var(--acc)',
6417
+ 'var(--success)',
6418
+ 'var(--warning)',
6419
+ 'var(--critical)',
6420
+ 'var(--acc50)',
6421
+ 'var(--t3)',
6422
+ ];
5633
6423
  /**
5634
6424
  * Donut / ring chart from weighted segments.
5635
6425
  * <strct-donut [segments]="[{value:6,label:'Running'},{value:2,label:'Off'}]"
5636
6426
  * centerValue="8" centerLabel="VMs" />
5637
6427
  */
5638
6428
  class StrctDonut {
6429
+ /** Weighted segments. */
5639
6430
  segments = input.required(...(ngDevMode ? [{ debugName: "segments" }] : /* istanbul ignore next */ []));
6431
+ /** Size variant. */
5640
6432
  size = input(120, ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
6433
+ /** Stroke thickness in pixels. */
5641
6434
  thickness = input(14, ...(ngDevMode ? [{ debugName: "thickness" }] : /* istanbul ignore next */ []));
6435
+ /** Value shown in the donut center. */
5642
6436
  centerValue = input('', ...(ngDevMode ? [{ debugName: "centerValue" }] : /* istanbul ignore next */ []));
6437
+ /** Label shown in the donut center. */
5643
6438
  centerLabel = input('', ...(ngDevMode ? [{ debugName: "centerLabel" }] : /* istanbul ignore next */ []));
5644
6439
  half = computed(() => this.size() / 2, ...(ngDevMode ? [{ debugName: "half" }] : /* istanbul ignore next */ []));
5645
6440
  radius = computed(() => (this.size() - this.thickness()) / 2, ...(ngDevMode ? [{ debugName: "radius" }] : /* istanbul ignore next */ []));
@@ -5659,17 +6454,28 @@ class StrctDonut {
5659
6454
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctDonut, deps: [], target: i0.ɵɵFactoryTarget.Component });
5660
6455
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: StrctDonut, isStandalone: true, selector: "strct-donut", inputs: { segments: { classPropertyName: "segments", publicName: "segments", isSignal: true, isRequired: true, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, thickness: { classPropertyName: "thickness", publicName: "thickness", isSignal: true, isRequired: false, transformFunction: null }, centerValue: { classPropertyName: "centerValue", publicName: "centerValue", isSignal: true, isRequired: false, transformFunction: null }, centerLabel: { classPropertyName: "centerLabel", publicName: "centerLabel", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "strct-donut" }, ngImport: i0, template: `
5661
6456
  <div class="strct-donut__wrap" [style.width.px]="size()" [style.height.px]="size()">
5662
- <svg [attr.viewBox]="'0 0 ' + size() + ' ' + size()" [style.width.px]="size()" [style.height.px]="size()">
6457
+ <svg
6458
+ [attr.viewBox]="'0 0 ' + size() + ' ' + size()"
6459
+ [style.width.px]="size()"
6460
+ [style.height.px]="size()"
6461
+ >
5663
6462
  <g [attr.transform]="'rotate(-90 ' + half() + ' ' + half() + ')'">
5664
6463
  <circle
5665
6464
  class="strct-donut__track"
5666
- [attr.cx]="half()" [attr.cy]="half()" [attr.r]="radius()"
5667
- fill="none" [attr.stroke-width]="thickness()"
6465
+ [attr.cx]="half()"
6466
+ [attr.cy]="half()"
6467
+ [attr.r]="radius()"
6468
+ fill="none"
6469
+ [attr.stroke-width]="thickness()"
5668
6470
  />
5669
6471
  @for (arc of arcs(); track $index) {
5670
6472
  <circle
5671
- [attr.cx]="half()" [attr.cy]="half()" [attr.r]="radius()"
5672
- fill="none" [attr.stroke]="arc.color" [attr.stroke-width]="thickness()"
6473
+ [attr.cx]="half()"
6474
+ [attr.cy]="half()"
6475
+ [attr.r]="radius()"
6476
+ fill="none"
6477
+ [attr.stroke]="arc.color"
6478
+ [attr.stroke-width]="thickness()"
5673
6479
  [attr.stroke-dasharray]="arc.len + ' ' + (circumference() - arc.len)"
5674
6480
  [attr.stroke-dashoffset]="-arc.offset"
5675
6481
  />
@@ -5689,17 +6495,28 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
5689
6495
  type: Component,
5690
6496
  args: [{ selector: 'strct-donut', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: `
5691
6497
  <div class="strct-donut__wrap" [style.width.px]="size()" [style.height.px]="size()">
5692
- <svg [attr.viewBox]="'0 0 ' + size() + ' ' + size()" [style.width.px]="size()" [style.height.px]="size()">
6498
+ <svg
6499
+ [attr.viewBox]="'0 0 ' + size() + ' ' + size()"
6500
+ [style.width.px]="size()"
6501
+ [style.height.px]="size()"
6502
+ >
5693
6503
  <g [attr.transform]="'rotate(-90 ' + half() + ' ' + half() + ')'">
5694
6504
  <circle
5695
6505
  class="strct-donut__track"
5696
- [attr.cx]="half()" [attr.cy]="half()" [attr.r]="radius()"
5697
- fill="none" [attr.stroke-width]="thickness()"
6506
+ [attr.cx]="half()"
6507
+ [attr.cy]="half()"
6508
+ [attr.r]="radius()"
6509
+ fill="none"
6510
+ [attr.stroke-width]="thickness()"
5698
6511
  />
5699
6512
  @for (arc of arcs(); track $index) {
5700
6513
  <circle
5701
- [attr.cx]="half()" [attr.cy]="half()" [attr.r]="radius()"
5702
- fill="none" [attr.stroke]="arc.color" [attr.stroke-width]="thickness()"
6514
+ [attr.cx]="half()"
6515
+ [attr.cy]="half()"
6516
+ [attr.r]="radius()"
6517
+ fill="none"
6518
+ [attr.stroke]="arc.color"
6519
+ [attr.stroke-width]="thickness()"
5703
6520
  [attr.stroke-dasharray]="arc.len + ' ' + (circumference() - arc.len)"
5704
6521
  [attr.stroke-dashoffset]="-arc.offset"
5705
6522
  />
@@ -5718,19 +6535,24 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
5718
6535
 
5719
6536
  const COLOR = {
5720
6537
  accent: 'var(--acc)',
5721
- success: 'var(--ok)',
5722
- warning: 'var(--wrn)',
5723
- danger: 'var(--crt)',
6538
+ success: 'var(--success)',
6539
+ warning: 'var(--warning)',
6540
+ critical: 'var(--critical)',
5724
6541
  };
5725
6542
  /**
5726
6543
  * 270° radial gauge for a 0–100 value (CPU, memory, capacity …).
5727
6544
  * <strct-gauge [value]="72" status="warning" label="CPU" />
5728
6545
  */
5729
6546
  class StrctGauge {
6547
+ /** Current value. */
5730
6548
  value = input(0, ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
6549
+ /** Visual status color. */
5731
6550
  status = input('accent', ...(ngDevMode ? [{ debugName: "status" }] : /* istanbul ignore next */ []));
6551
+ /** Label text. */
5732
6552
  label = input('', ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
6553
+ /** Size variant. */
5733
6554
  size = input(120, ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
6555
+ /** Stroke thickness in pixels. */
5734
6556
  thickness = input(12, ...(ngDevMode ? [{ debugName: "thickness" }] : /* istanbul ignore next */ []));
5735
6557
  clamped = computed(() => Math.round(Math.max(0, Math.min(100, this.value()))), ...(ngDevMode ? [{ debugName: "clamped" }] : /* istanbul ignore next */ []));
5736
6558
  half = computed(() => this.size() / 2, ...(ngDevMode ? [{ debugName: "half" }] : /* istanbul ignore next */ []));
@@ -5748,18 +6570,31 @@ class StrctGauge {
5748
6570
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctGauge, deps: [], target: i0.ɵɵFactoryTarget.Component });
5749
6571
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: StrctGauge, isStandalone: true, selector: "strct-gauge", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, status: { classPropertyName: "status", publicName: "status", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, thickness: { classPropertyName: "thickness", publicName: "thickness", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "strct-gauge" }, ngImport: i0, template: `
5750
6572
  <div class="strct-gauge__wrap" [style.width.px]="size()" [style.height.px]="size()">
5751
- <svg [attr.viewBox]="'0 0 ' + size() + ' ' + size()" [style.width.px]="size()" [style.height.px]="size()">
6573
+ <svg
6574
+ [attr.viewBox]="'0 0 ' + size() + ' ' + size()"
6575
+ [style.width.px]="size()"
6576
+ [style.height.px]="size()"
6577
+ >
5752
6578
  <g [attr.transform]="'rotate(135 ' + half() + ' ' + half() + ')'">
5753
6579
  <circle
5754
6580
  class="strct-gauge__track"
5755
- [attr.cx]="half()" [attr.cy]="half()" [attr.r]="radius()"
5756
- fill="none" [attr.stroke-width]="thickness()" stroke-linecap="round"
6581
+ [attr.cx]="half()"
6582
+ [attr.cy]="half()"
6583
+ [attr.r]="radius()"
6584
+ fill="none"
6585
+ [attr.stroke-width]="thickness()"
6586
+ stroke-linecap="round"
5757
6587
  [attr.stroke-dasharray]="trackDash()"
5758
6588
  />
5759
6589
  <circle
5760
6590
  class="strct-gauge__value"
5761
- [attr.cx]="half()" [attr.cy]="half()" [attr.r]="radius()"
5762
- fill="none" [attr.stroke]="color()" [attr.stroke-width]="thickness()" stroke-linecap="round"
6591
+ [attr.cx]="half()"
6592
+ [attr.cy]="half()"
6593
+ [attr.r]="radius()"
6594
+ fill="none"
6595
+ [attr.stroke]="color()"
6596
+ [attr.stroke-width]="thickness()"
6597
+ stroke-linecap="round"
5763
6598
  [attr.stroke-dasharray]="valueDash()"
5764
6599
  />
5765
6600
  </g>
@@ -5777,18 +6612,31 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
5777
6612
  type: Component,
5778
6613
  args: [{ selector: 'strct-gauge', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: `
5779
6614
  <div class="strct-gauge__wrap" [style.width.px]="size()" [style.height.px]="size()">
5780
- <svg [attr.viewBox]="'0 0 ' + size() + ' ' + size()" [style.width.px]="size()" [style.height.px]="size()">
6615
+ <svg
6616
+ [attr.viewBox]="'0 0 ' + size() + ' ' + size()"
6617
+ [style.width.px]="size()"
6618
+ [style.height.px]="size()"
6619
+ >
5781
6620
  <g [attr.transform]="'rotate(135 ' + half() + ' ' + half() + ')'">
5782
6621
  <circle
5783
6622
  class="strct-gauge__track"
5784
- [attr.cx]="half()" [attr.cy]="half()" [attr.r]="radius()"
5785
- fill="none" [attr.stroke-width]="thickness()" stroke-linecap="round"
6623
+ [attr.cx]="half()"
6624
+ [attr.cy]="half()"
6625
+ [attr.r]="radius()"
6626
+ fill="none"
6627
+ [attr.stroke-width]="thickness()"
6628
+ stroke-linecap="round"
5786
6629
  [attr.stroke-dasharray]="trackDash()"
5787
6630
  />
5788
6631
  <circle
5789
6632
  class="strct-gauge__value"
5790
- [attr.cx]="half()" [attr.cy]="half()" [attr.r]="radius()"
5791
- fill="none" [attr.stroke]="color()" [attr.stroke-width]="thickness()" stroke-linecap="round"
6633
+ [attr.cx]="half()"
6634
+ [attr.cy]="half()"
6635
+ [attr.r]="radius()"
6636
+ fill="none"
6637
+ [attr.stroke]="color()"
6638
+ [attr.stroke-width]="thickness()"
6639
+ stroke-linecap="round"
5792
6640
  [attr.stroke-dasharray]="valueDash()"
5793
6641
  />
5794
6642
  </g>
@@ -5805,8 +6653,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
5805
6653
 
5806
6654
  /** Inline contextual banner. `<strct-alert type="warning">…</strct-alert>`. */
5807
6655
  class StrctAlert {
6656
+ /** Visual type / variant. */
5808
6657
  type = input('info', ...(ngDevMode ? [{ debugName: "type" }] : /* istanbul ignore next */ []));
6658
+ /** Show a dismiss button. */
5809
6659
  closable = input(false, { ...(ngDevMode ? { debugName: "closable" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
6660
+ /** Emitted when the alert is dismissed. */
5810
6661
  closed = output();
5811
6662
  icon = computed(() => {
5812
6663
  switch (this.type()) {
@@ -5814,14 +6665,14 @@ class StrctAlert {
5814
6665
  return 'success';
5815
6666
  case 'warning':
5816
6667
  return 'warning';
5817
- case 'danger':
5818
- return 'danger';
6668
+ case 'critical':
6669
+ return 'critical';
5819
6670
  default:
5820
6671
  return 'info';
5821
6672
  }
5822
6673
  }, ...(ngDevMode ? [{ debugName: "icon" }] : /* istanbul ignore next */ []));
5823
6674
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctAlert, deps: [], target: i0.ɵɵFactoryTarget.Component });
5824
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: StrctAlert, isStandalone: true, selector: "strct-alert", inputs: { type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, closable: { classPropertyName: "closable", publicName: "closable", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { closed: "closed" }, host: { attributes: { "role": "status" }, properties: { "class.strct-alert--success": "type() === 'success'", "class.strct-alert--warning": "type() === 'warning'", "class.strct-alert--danger": "type() === 'danger'" }, classAttribute: "strct-alert" }, ngImport: i0, template: `
6675
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: StrctAlert, isStandalone: true, selector: "strct-alert", inputs: { type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, closable: { classPropertyName: "closable", publicName: "closable", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { closed: "closed" }, host: { attributes: { "role": "status" }, properties: { "class.strct-alert--success": "type() === 'success'", "class.strct-alert--warning": "type() === 'warning'", "class.strct-alert--critical": "type() === 'critical'" }, classAttribute: "strct-alert" }, ngImport: i0, template: `
5825
6676
  <strct-icon [name]="icon()" [size]="15" />
5826
6677
  <div class="strct-alert__body"><ng-content /></div>
5827
6678
  @if (closable()) {
@@ -5829,7 +6680,7 @@ class StrctAlert {
5829
6680
  <strct-icon name="close" [size]="13" />
5830
6681
  </button>
5831
6682
  }
5832
- `, isInline: true, styles: [".strct-alert{display:flex;align-items:flex-start;gap:10px;padding:10px 12px;border-radius:7px;font-size:13px;color:var(--t1);background:var(--bg-1);border:1px solid var(--b2);border-left:3px solid var(--acc)}.strct-alert strct-icon{color:var(--acc);margin-top:1px;flex-shrink:0}.strct-alert__body{flex:1;color:var(--t1)}.strct-alert__close{flex-shrink:0;display:inline-flex;padding:2px;margin:-2px -2px 0 0;border:0;background:transparent;color:var(--t3);cursor:pointer;border-radius:4px}.strct-alert__close:hover{color:var(--t1);background:var(--bg-3)}.strct-alert--success{border-left-color:var(--ok)}.strct-alert--success strct-icon{color:var(--ok)}.strct-alert--warning{border-left-color:var(--wrn)}.strct-alert--warning strct-icon{color:var(--wrn)}.strct-alert--danger{border-left-color:var(--crt)}.strct-alert--danger strct-icon{color:var(--crt)}\n"], dependencies: [{ kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "size", "strokeWidth", "badge"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
6683
+ `, isInline: true, styles: [".strct-alert{display:flex;align-items:flex-start;gap:var(--space-2);padding:var(--space-2) var(--space-3);border-radius:var(--radius-lg);font-size:13px;color:var(--t1);background:var(--bg-1);border:1px solid var(--b2);border-left:3px solid var(--acc)}.strct-alert strct-icon{color:var(--acc);margin-top:1px;flex-shrink:0}.strct-alert__body{flex:1;color:var(--t1)}.strct-alert__close{flex-shrink:0;display:inline-flex;padding:2px;margin:-2px -2px 0 0;border:0;background:transparent;color:var(--t3);cursor:pointer;border-radius:4px}.strct-alert__close:hover{color:var(--t1);background:var(--bg-3)}.strct-alert--success{border-left-color:var(--success)}.strct-alert--success strct-icon{color:var(--success)}.strct-alert--warning{border-left-color:var(--warning)}.strct-alert--warning strct-icon{color:var(--warning)}.strct-alert--critical{border-left-color:var(--critical)}.strct-alert--critical strct-icon{color:var(--critical)}\n"], dependencies: [{ kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "size", "strokeWidth", "badge", "ariaLabel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
5833
6684
  }
5834
6685
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctAlert, decorators: [{
5835
6686
  type: Component,
@@ -5846,8 +6697,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
5846
6697
  role: 'status',
5847
6698
  '[class.strct-alert--success]': "type() === 'success'",
5848
6699
  '[class.strct-alert--warning]': "type() === 'warning'",
5849
- '[class.strct-alert--danger]': "type() === 'danger'",
5850
- }, styles: [".strct-alert{display:flex;align-items:flex-start;gap:10px;padding:10px 12px;border-radius:7px;font-size:13px;color:var(--t1);background:var(--bg-1);border:1px solid var(--b2);border-left:3px solid var(--acc)}.strct-alert strct-icon{color:var(--acc);margin-top:1px;flex-shrink:0}.strct-alert__body{flex:1;color:var(--t1)}.strct-alert__close{flex-shrink:0;display:inline-flex;padding:2px;margin:-2px -2px 0 0;border:0;background:transparent;color:var(--t3);cursor:pointer;border-radius:4px}.strct-alert__close:hover{color:var(--t1);background:var(--bg-3)}.strct-alert--success{border-left-color:var(--ok)}.strct-alert--success strct-icon{color:var(--ok)}.strct-alert--warning{border-left-color:var(--wrn)}.strct-alert--warning strct-icon{color:var(--wrn)}.strct-alert--danger{border-left-color:var(--crt)}.strct-alert--danger strct-icon{color:var(--crt)}\n"] }]
6700
+ '[class.strct-alert--critical]': "type() === 'critical'",
6701
+ }, styles: [".strct-alert{display:flex;align-items:flex-start;gap:var(--space-2);padding:var(--space-2) var(--space-3);border-radius:var(--radius-lg);font-size:13px;color:var(--t1);background:var(--bg-1);border:1px solid var(--b2);border-left:3px solid var(--acc)}.strct-alert strct-icon{color:var(--acc);margin-top:1px;flex-shrink:0}.strct-alert__body{flex:1;color:var(--t1)}.strct-alert__close{flex-shrink:0;display:inline-flex;padding:2px;margin:-2px -2px 0 0;border:0;background:transparent;color:var(--t3);cursor:pointer;border-radius:4px}.strct-alert__close:hover{color:var(--t1);background:var(--bg-3)}.strct-alert--success{border-left-color:var(--success)}.strct-alert--success strct-icon{color:var(--success)}.strct-alert--warning{border-left-color:var(--warning)}.strct-alert--warning strct-icon{color:var(--warning)}.strct-alert--critical{border-left-color:var(--critical)}.strct-alert--critical strct-icon{color:var(--critical)}\n"] }]
5851
6702
  }], propDecorators: { type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], closable: [{ type: i0.Input, args: [{ isSignal: true, alias: "closable", required: false }] }], closed: [{ type: i0.Output, args: ["closed"] }] } });
5852
6703
 
5853
6704
  /**
@@ -5860,7 +6711,9 @@ class StrctTooltip {
5860
6711
  renderer = inject(Renderer2);
5861
6712
  doc = inject(DOCUMENT);
5862
6713
  bubble = null;
6714
+ /** Tooltip text. */
5863
6715
  strctTooltip = input.required(...(ngDevMode ? [{ debugName: "strctTooltip" }] : /* istanbul ignore next */ []));
6716
+ /** Tooltip placement relative to the host. */
5864
6717
  tooltipPosition = input('top', ...(ngDevMode ? [{ debugName: "tooltipPosition" }] : /* istanbul ignore next */ []));
5865
6718
  show() {
5866
6719
  const text = this.strctTooltip();
@@ -5958,6 +6811,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
5958
6811
  */
5959
6812
  class StrctSignpost {
5960
6813
  host = inject((ElementRef));
6814
+ /** Popover placement relative to the trigger. */
5961
6815
  position = input('bottom', ...(ngDevMode ? [{ debugName: "position" }] : /* istanbul ignore next */ []));
5962
6816
  open = signal(false, ...(ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []));
5963
6817
  toggle() {
@@ -5988,7 +6842,15 @@ class StrctSignpost {
5988
6842
  }
5989
6843
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctSignpost, deps: [], target: i0.ɵɵFactoryTarget.Component });
5990
6844
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: StrctSignpost, isStandalone: true, selector: "strct-signpost", inputs: { position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "document:click": "onDocClick($event)", "document:keydown.escape": "onEscape()" }, classAttribute: "strct-sp" }, ngImport: i0, template: `
5991
- <div #trigger class="strct-sp__trigger" (click)="toggle()">
6845
+ <div
6846
+ #trigger
6847
+ class="strct-sp__trigger"
6848
+ role="button"
6849
+ tabindex="0"
6850
+ (click)="toggle()"
6851
+ (keydown.enter)="toggle()"
6852
+ (keydown.space)="toggle()"
6853
+ >
5992
6854
  <ng-content select="[strctSignpostTrigger]" />
5993
6855
  </div>
5994
6856
  @if (open()) {
@@ -6007,7 +6869,15 @@ class StrctSignpost {
6007
6869
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctSignpost, decorators: [{
6008
6870
  type: Component,
6009
6871
  args: [{ selector: 'strct-signpost', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [StrctOverlay], template: `
6010
- <div #trigger class="strct-sp__trigger" (click)="toggle()">
6872
+ <div
6873
+ #trigger
6874
+ class="strct-sp__trigger"
6875
+ role="button"
6876
+ tabindex="0"
6877
+ (click)="toggle()"
6878
+ (keydown.enter)="toggle()"
6879
+ (keydown.space)="toggle()"
6880
+ >
6011
6881
  <ng-content select="[strctSignpostTrigger]" />
6012
6882
  </div>
6013
6883
  @if (open()) {
@@ -6042,7 +6912,10 @@ class StrctToastService {
6042
6912
  show(message, options = {}) {
6043
6913
  const id = ++this.counter;
6044
6914
  const duration = options.duration ?? 4000;
6045
- this._toasts.update((list) => [...list, { id, type: options.type ?? 'info', message, duration }]);
6915
+ this._toasts.update((list) => [
6916
+ ...list,
6917
+ { id, type: options.type ?? 'info', message, duration },
6918
+ ]);
6046
6919
  if (duration > 0) {
6047
6920
  setTimeout(() => this.dismiss(id), duration);
6048
6921
  }
@@ -6057,8 +6930,8 @@ class StrctToastService {
6057
6930
  warning(message, duration) {
6058
6931
  return this.show(message, { type: 'warning', duration });
6059
6932
  }
6060
- danger(message, duration) {
6061
- return this.show(message, { type: 'danger', duration });
6933
+ critical(message, duration) {
6934
+ return this.show(message, { type: 'critical', duration });
6062
6935
  }
6063
6936
  dismiss(id) {
6064
6937
  this._toasts.update((list) => list.filter((t) => t.id !== id));
@@ -6077,7 +6950,7 @@ const TOAST_ICON = {
6077
6950
  info: 'info',
6078
6951
  success: 'success',
6079
6952
  warning: 'warning',
6080
- danger: 'danger',
6953
+ critical: 'critical',
6081
6954
  };
6082
6955
  /** Renders the toast stack. Place once, typically just inside the app shell. */
6083
6956
  class StrctToastOutlet {
@@ -6093,7 +6966,7 @@ class StrctToastOutlet {
6093
6966
  class="strct-toast"
6094
6967
  [class.strct-toast--success]="toast.type === 'success'"
6095
6968
  [class.strct-toast--warning]="toast.type === 'warning'"
6096
- [class.strct-toast--danger]="toast.type === 'danger'"
6969
+ [class.strct-toast--critical]="toast.type === 'critical'"
6097
6970
  >
6098
6971
  <strct-icon [name]="icon(toast.type)" [size]="15" />
6099
6972
  <span class="strct-toast__msg">{{ toast.message }}</span>
@@ -6108,7 +6981,7 @@ class StrctToastOutlet {
6108
6981
  </div>
6109
6982
  }
6110
6983
  </div>
6111
- `, isInline: true, styles: [".strct-toasts{position:fixed;top:16px;right:16px;z-index:1200;display:flex;flex-direction:column;gap:10px;max-width:360px;pointer-events:none}.strct-toast{pointer-events:auto;display:flex;align-items:flex-start;gap:10px;padding:11px 12px;font-size:13px;color:var(--t1);background:var(--bg-1);border:1px solid var(--b2);border-left:3px solid var(--acc);border-radius:7px;box-shadow:var(--shh);animation:strct-toast-in .16s ease}.strct-toast strct-icon{color:var(--acc);margin-top:1px;flex-shrink:0}.strct-toast__msg{flex:1}.strct-toast__close{flex-shrink:0;display:inline-flex;padding:2px;margin:-2px -2px 0 0;border:0;background:transparent;color:var(--t3);cursor:pointer;border-radius:4px}.strct-toast__close:hover{color:var(--t1);background:var(--bg-3)}.strct-toast--success{border-left-color:var(--ok)}.strct-toast--success strct-icon{color:var(--ok)}.strct-toast--warning{border-left-color:var(--wrn)}.strct-toast--warning strct-icon{color:var(--wrn)}.strct-toast--danger{border-left-color:var(--crt)}.strct-toast--danger strct-icon{color:var(--crt)}@keyframes strct-toast-in{0%{opacity:0;transform:translate(16px)}}\n"], dependencies: [{ kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "size", "strokeWidth", "badge"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
6984
+ `, isInline: true, styles: [".strct-toasts{position:fixed;top:var(--space-4);right:var(--space-4);z-index:1200;display:flex;flex-direction:column;gap:var(--space-2);max-width:360px;pointer-events:none}.strct-toast{pointer-events:auto;display:flex;align-items:flex-start;gap:var(--space-2);padding:var(--space-3);font-size:13px;color:var(--t1);background:var(--bg-1);border:1px solid var(--b2);border-left:3px solid var(--acc);border-radius:var(--radius-lg);box-shadow:var(--shadow-floating);animation:strct-toast-in .16s ease}.strct-toast strct-icon{color:var(--acc);margin-top:1px;flex-shrink:0}.strct-toast__msg{flex:1}.strct-toast__close{flex-shrink:0;display:inline-flex;padding:2px;margin:-2px -2px 0 0;border:0;background:transparent;color:var(--t3);cursor:pointer;border-radius:4px}.strct-toast__close:hover{color:var(--t1);background:var(--bg-3)}.strct-toast--success{border-left-color:var(--success)}.strct-toast--success strct-icon{color:var(--success)}.strct-toast--warning{border-left-color:var(--warning)}.strct-toast--warning strct-icon{color:var(--warning)}.strct-toast--critical{border-left-color:var(--critical)}.strct-toast--critical strct-icon{color:var(--critical)}@keyframes strct-toast-in{0%{opacity:0;transform:translate(16px)}}\n"], dependencies: [{ kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "size", "strokeWidth", "badge", "ariaLabel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
6112
6985
  }
6113
6986
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctToastOutlet, decorators: [{
6114
6987
  type: Component,
@@ -6119,7 +6992,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
6119
6992
  class="strct-toast"
6120
6993
  [class.strct-toast--success]="toast.type === 'success'"
6121
6994
  [class.strct-toast--warning]="toast.type === 'warning'"
6122
- [class.strct-toast--danger]="toast.type === 'danger'"
6995
+ [class.strct-toast--critical]="toast.type === 'critical'"
6123
6996
  >
6124
6997
  <strct-icon [name]="icon(toast.type)" [size]="15" />
6125
6998
  <span class="strct-toast__msg">{{ toast.message }}</span>
@@ -6134,10 +7007,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
6134
7007
  </div>
6135
7008
  }
6136
7009
  </div>
6137
- `, styles: [".strct-toasts{position:fixed;top:16px;right:16px;z-index:1200;display:flex;flex-direction:column;gap:10px;max-width:360px;pointer-events:none}.strct-toast{pointer-events:auto;display:flex;align-items:flex-start;gap:10px;padding:11px 12px;font-size:13px;color:var(--t1);background:var(--bg-1);border:1px solid var(--b2);border-left:3px solid var(--acc);border-radius:7px;box-shadow:var(--shh);animation:strct-toast-in .16s ease}.strct-toast strct-icon{color:var(--acc);margin-top:1px;flex-shrink:0}.strct-toast__msg{flex:1}.strct-toast__close{flex-shrink:0;display:inline-flex;padding:2px;margin:-2px -2px 0 0;border:0;background:transparent;color:var(--t3);cursor:pointer;border-radius:4px}.strct-toast__close:hover{color:var(--t1);background:var(--bg-3)}.strct-toast--success{border-left-color:var(--ok)}.strct-toast--success strct-icon{color:var(--ok)}.strct-toast--warning{border-left-color:var(--wrn)}.strct-toast--warning strct-icon{color:var(--wrn)}.strct-toast--danger{border-left-color:var(--crt)}.strct-toast--danger strct-icon{color:var(--crt)}@keyframes strct-toast-in{0%{opacity:0;transform:translate(16px)}}\n"] }]
7010
+ `, styles: [".strct-toasts{position:fixed;top:var(--space-4);right:var(--space-4);z-index:1200;display:flex;flex-direction:column;gap:var(--space-2);max-width:360px;pointer-events:none}.strct-toast{pointer-events:auto;display:flex;align-items:flex-start;gap:var(--space-2);padding:var(--space-3);font-size:13px;color:var(--t1);background:var(--bg-1);border:1px solid var(--b2);border-left:3px solid var(--acc);border-radius:var(--radius-lg);box-shadow:var(--shadow-floating);animation:strct-toast-in .16s ease}.strct-toast strct-icon{color:var(--acc);margin-top:1px;flex-shrink:0}.strct-toast__msg{flex:1}.strct-toast__close{flex-shrink:0;display:inline-flex;padding:2px;margin:-2px -2px 0 0;border:0;background:transparent;color:var(--t3);cursor:pointer;border-radius:4px}.strct-toast__close:hover{color:var(--t1);background:var(--bg-3)}.strct-toast--success{border-left-color:var(--success)}.strct-toast--success strct-icon{color:var(--success)}.strct-toast--warning{border-left-color:var(--warning)}.strct-toast--warning strct-icon{color:var(--warning)}.strct-toast--critical{border-left-color:var(--critical)}.strct-toast--critical strct-icon{color:var(--critical)}@keyframes strct-toast-in{0%{opacity:0;transform:translate(16px)}}\n"] }]
6138
7011
  }] });
6139
7012
 
6140
- /*
7013
+ /**
6141
7014
  * Public API surface of the strct UI library.
6142
7015
  */
6143
7016
  // Theme
@@ -6146,5 +7019,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
6146
7019
  * Generated bundle index. Do not edit.
6147
7020
  */
6148
7021
 
6149
- export { STRCT_ICONS, STRCT_ICON_GROUPS, STRCT_MASKS, STRCT_PALETTES, STRCT_RAW_ICONS, StrctAccordion, StrctAccordionPanel, StrctAlert, StrctAvatar, StrctBadge, StrctBreadcrumb, StrctBreadcrumbItem, StrctButton, StrctButtonGroup, StrctCard, StrctCardBlock, StrctCardFooter, StrctCardHeader, StrctCascadeHost, StrctCascadeNode, StrctCascadeSelect, StrctCellDef, StrctChart, StrctCheckbox, StrctChips, StrctColorPicker, StrctCombobox, StrctContextMenu, StrctContextMenuTrigger, StrctDatagrid, StrctDatagridActionBar, StrctDatepicker, StrctDivider, StrctDonut, StrctDropdown, StrctDropdownDivider, StrctDropdownItem, StrctField, StrctFile, StrctFooter, StrctGauge, StrctHeader, StrctIcon, StrctInput, StrctInputMask, StrctInputOtp, StrctKnob, StrctLogin, StrctMenuPanel, StrctModal, StrctNav, StrctNavItem, StrctOverlay, StrctPagination, StrctPassword, StrctProgress, StrctRadio, StrctRadioGroup, StrctRange, StrctRating, StrctRowDetailDef, StrctShell, StrctSignpost, StrctSkeleton, StrctSparkline, StrctSpeedDial, StrctSpinner, StrctStack, StrctStackItem, StrctStep, StrctSubmenu, StrctTab, StrctTable, StrctTabs, StrctTag, StrctThemeService, StrctThemeSwitcher, StrctTimeline, StrctTimelineItem, StrctToastOutlet, StrctToastService, StrctToggle, StrctTooltip, StrctTree, StrctTreeNode, StrctVerticalNav, StrctWizard, registerStrctIcon };
7022
+ export { STRCT_ICONS, STRCT_ICON_GROUPS, STRCT_MASKS, STRCT_PALETTES, STRCT_RAW_ICONS, StrctAccordion, StrctAccordionPanel, StrctAlert, StrctAvatar, StrctBadge, StrctBreadcrumb, StrctBreadcrumbItem, StrctButton, StrctButtonGroup, StrctCard, StrctCardBlock, StrctCardFooter, StrctCardHeader, StrctCascadeHost, StrctCascadeNode, StrctCascadeSelect, StrctCellDef, StrctChart, StrctCheckbox, StrctChips, StrctColorPicker, StrctCombobox, StrctContextMenu, StrctContextMenuTrigger, StrctDatagrid, StrctDatagridActionBar, StrctDatepicker, StrctDivider, StrctDonut, StrctDropdown, StrctDropdownDivider, StrctDropdownItem, StrctField, StrctFile, StrctFooter, StrctGauge, StrctHeader, StrctIcon, StrctInput, StrctInputMask, StrctInputOtp, StrctKnob, StrctLogin, StrctMenuPanel, StrctModal, StrctNav, StrctNavItem, StrctOverlay, StrctPagination, StrctPassword, StrctProgress, StrctRadio, StrctRadioGroup, StrctRange, StrctRating, StrctRowDetailDef, StrctShell, StrctShellService, StrctSignpost, StrctSkeleton, StrctSparkline, StrctSpeedDial, StrctSpinner, StrctStack, StrctStackItem, StrctStep, StrctSubmenu, StrctTab, StrctTable, StrctTabs, StrctTag, StrctThemeService, StrctThemeSwitcher, StrctTimeline, StrctTimelineItem, StrctToastOutlet, StrctToastService, StrctToggle, StrctTooltip, StrctTree, StrctTreeNode, StrctVerticalNav, StrctWizard, registerStrctIcon };
6150
7023
  //# sourceMappingURL=akcelik-strct.mjs.map