@vialiq/web-components 0.1.1 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,708 @@
1
+ import { unsafeCSS, css, html } from 'lit';
2
+ import { customElement, property, state } from 'lit/decorators.js';
3
+ import { V as ViElement } from '../vi-element-C6GfDPs3.js';
4
+
5
+ /**
6
+ * FocusableMixin
7
+ *
8
+ * Applies to all interactive Vi components. Provides:
9
+ *
10
+ * 1. `delegatesFocus: true` on the shadow root — when the host is Tab-focused
11
+ * or `.focus()` is called on it, the browser routes focus to the inner
12
+ * native control. Also activates `:focus` and `:focus-within` on the host.
13
+ *
14
+ * 2. A `focus()` override that delegates to `_focusableElement` so callers
15
+ * can do `myInput.focus()` and it Just Works without knowing shadow internals.
16
+ *
17
+ * ─────────────────────────────────────────────────────────────────────────
18
+ * ARCHITECTURE: host is the tab stop
19
+ * ─────────────────────────────────────────────────────────────────────────
20
+ *
21
+ * Host: tabIndex = 0 ← consumer-visible tab stop
22
+ * Inner element: tabindex="-1" ← NOT directly in tab order; only reachable
23
+ * via host delegation
24
+ * delegatesFocus: true ← routes host focus → inner element
25
+ *
26
+ * This means:
27
+ * - Tab → lands on host → delegatesFocus → inner element gets visual focus
28
+ * - `:host(:focus)` and `:host(:focus-within)` both work correctly
29
+ * - `element.focus()` calls our override → inner element focused explicitly
30
+ * - Consumer sets tabindex="-1" on host to remove from tab order entirely
31
+ * - Consumer sets tabindex="2" for explicit positioning — just works
32
+ *
33
+ * CRITICAL: Every component using this mixin MUST set tabindex="-1" on its
34
+ * inner native element in render() to prevent double-tab. Failing to do so
35
+ * creates two tab stops for a single logical control.
36
+ *
37
+ * DISABLED: When the `disabled` prop changes, the component MUST sync the
38
+ * host's tabIndex:
39
+ *
40
+ * override updated(changed: PropertyValues) {
41
+ * super.updated(changed);
42
+ * if (changed.has('disabled')) {
43
+ * this.tabIndex = this.disabled ? -1 : (previous tabIndex value or 0);
44
+ * }
45
+ * }
46
+ *
47
+ * Usage:
48
+ * class ViInput extends FocusableMixin(ViElement) {
49
+ * protected override get _focusableElement() {
50
+ * return this.shadowRoot?.querySelector('input') ?? null;
51
+ * }
52
+ * }
53
+ */ function FocusableMixin(Base) {
54
+ class FocusableMixinClass extends Base {
55
+ /**
56
+ * Spread existing shadow root options so we don't clobber `mode: 'open'`
57
+ * or any other options already set by a base class or another mixin.
58
+ * `override` is omitted: TypeScript cannot verify the static side of the
59
+ * generic `Base` constructor has `shadowRootOptions`, so we re-declare
60
+ * without override (the property is still inherited at runtime).
61
+ */ // eslint-disable-next-line @typescript-eslint/no-explicit-any
62
+ static shadowRootOptions = {
63
+ ...Base.shadowRootOptions,
64
+ delegatesFocus: true
65
+ };
66
+ /**
67
+ * The tabIndex to restore when transitioning from disabled → enabled.
68
+ * Snapshotted in connectedCallback and updated whenever we save before
69
+ * disabling, so we can honour custom consumer tabindex values (e.g. 2)
70
+ * rather than blindly restoring to 0.
71
+ */ _savedTabIndex = 0;
72
+ connectedCallback() {
73
+ super.connectedCallback();
74
+ // The host is the user-visible tab stop. Custom elements are NOT in the
75
+ // tab order by default (tabIndex = -1), so we must explicitly opt in.
76
+ // Only set the default if the consumer hasn't already specified a value.
77
+ // `tabIndex` is a reflected IDL attribute — both attribute sets and
78
+ // programmatic sets (`element.tabIndex = 2`) always reflect to the
79
+ // `tabindex` attribute, so `hasAttribute` is a complete guard for both.
80
+ // tabindex="-1" → remove from tab order entirely (e.g. inside a focus trap)
81
+ // tabindex="0" → participate (same as our default)
82
+ // tabindex="2" → explicit ordering position
83
+ // Note: connectedCallback is used (not constructor) to avoid the
84
+ // "DOMException: The result must not have attributes" error during upgrade.
85
+ if (!this.hasAttribute('tabindex')) {
86
+ this.tabIndex = 0;
87
+ }
88
+ // Snapshot the current effective tabIndex so _setHostFocusable(true)
89
+ // can restore it rather than blindly resetting to 0.
90
+ this._savedTabIndex = this.tabIndex;
91
+ }
92
+ /**
93
+ * Centralizes the tabIndex policy for enabled/disabled state.
94
+ *
95
+ * enabled=true → restore the tabIndex that was in effect before disabling
96
+ * (respects consumer tabindex="2", tabindex="-1", etc.)
97
+ * enabled=false → tabIndex = -1 (host skipped by Tab; whole component unreachable)
98
+ *
99
+ * The pre-disable tabIndex is saved so that a consumer who set tabindex="2"
100
+ * gets back tabindex="2" after re-enabling, not a hardcoded 0.
101
+ *
102
+ * All components with a `disabled` prop MUST call this in `updated()`:
103
+ *
104
+ * if (changed.has('disabled')) this._setHostFocusable(!this.disabled);
105
+ */ _setHostFocusable(enabled) {
106
+ if (enabled) {
107
+ this.tabIndex = this._savedTabIndex;
108
+ } else {
109
+ // Only snapshot when we are actually in an enabled state; if this is
110
+ // called repeatedly while disabled (tabIndex already -1) we must not
111
+ // overwrite the real saved value with -1.
112
+ if (this.tabIndex !== -1) {
113
+ this._savedTabIndex = this.tabIndex;
114
+ }
115
+ this.tabIndex = -1;
116
+ }
117
+ }
118
+ /**
119
+ * Subclasses MUST override this getter to return the specific inner element
120
+ * that should receive programmatic focus.
121
+ * Returning `null` before first render is safe — `focus()` no-ops.
122
+ */ get _focusableElement() {
123
+ return null;
124
+ }
125
+ /**
126
+ * Public focus() override.
127
+ *
128
+ * Explicitly delegates to `_focusableElement` when available. While `delegatesFocus: true`
129
+ * handles click routing, relying solely on native programmatic focus hands control
130
+ * to the browser, which blindly targets the *first* focusable element in
131
+ * shadow DOM order — not necessarily the intended one.
132
+ *
133
+ * Example: a vi-input might render a "Clear" <button> before the <input>
134
+ * in the DOM. Native focus would land on the clear button; this explicit
135
+ * call guarantees focus lands on the <input> regardless of DOM order.
136
+ *
137
+ * If called before the first render (when `_focusableElement` is null),
138
+ * it safely falls back to `super.focus()`.
139
+ */ focus(options) {
140
+ const target = this._focusableElement;
141
+ if (target) {
142
+ target.focus(options);
143
+ } else {
144
+ // Fallback to native behavior if called before first render
145
+ super.focus(options);
146
+ }
147
+ }
148
+ }
149
+ // Cast required: TypeScript cannot reconcile LitElement's private fields
150
+ // with the anonymous class return type. `as unknown as` is the standard
151
+ // pattern recommended by both the TypeScript and Lit teams for mixins.
152
+ return FocusableMixinClass;
153
+ }
154
+
155
+ const buttonStyles = "@charset \"UTF-8\";@layer reset,components,utilities;@layer components{.button{display:inline-flex;align-items:center;justify-content:center;gap:var(--vi-spacing-xs, 8px);border:var(--vi-border-width-thin, 1px) solid transparent;border-radius:var(--vi-button-shape-border-radius, var(--vi-border-radius-md, 4px));padding:var(--vi-button-spacing-padding-block, var(--vi-spacing-sm, 16px)) var(--vi-button-spacing-padding-inline, var(--vi-spacing-md, 24px));font-size:var(--vi-button-typography-font-size, var(--vi-font-size-base, 16px));font-weight:var(--vi-button-typography-font-weight, var(--vi-font-weight-semibold, 600));line-height:var(--vi-line-height-tight, 1.2);cursor:pointer;-webkit-user-select:none;user-select:none;transition:opacity var(--vi-button-effect-transition-duration, .16s) ease}}:host{display:inline-block}:host([size=xs]){--vi-button-spacing-padding-block: 2px;--vi-button-spacing-padding-inline: 8px;--vi-button-typography-font-size: var(--vi-font-size-xs, 12px)}:host([size=sm]){--vi-button-spacing-padding-block: 4px;--vi-button-spacing-padding-inline: 12px;--vi-button-typography-font-size: var(--vi-font-size-sm, 14px)}:host([size=lg]){--vi-button-spacing-padding-block: 12px;--vi-button-spacing-padding-inline: 24px;--vi-button-typography-font-size: var(--vi-font-size-lg, 18px)}:host([full-width]){display:block}:host([full-width]) .button{width:100%}:host([icon-only]) .button{aspect-ratio:1/1;padding:var(--vi-button-spacing-padding-block, var(--vi-spacing-sm, 16px));justify-content:center}:host([icon-only]) .label{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}:host([variant=primary]) .button{background-color:var(--vi-button-surface-primary-background-color, var(--vi-color-primary, #3676d0));color:var(--vi-button-surface-primary-text-color, var(--vi-color-grey-100, #f5f5f5))}:host([variant=secondary]) .button{background-color:var(--vi-button-surface-secondary-background-color, var(--vi-color-secondary, #f0f4f8));color:var(--vi-button-surface-secondary-text-color, var(--vi-color-foreground, #111827));border-color:var(--vi-color-border, #e5e7eb)}:host([variant=danger]) .button{background-color:var(--vi-button-surface-danger-background-color, var(--vi-color-error, #ef4444));color:var(--vi-button-surface-danger-text-color, var(--vi-color-grey-100, #f5f5f5))}:host([variant=success]) .button{background-color:var(--vi-button-surface-success-background-color, var(--vi-color-success, #489167));color:var(--vi-button-surface-success-text-color, var(--vi-color-grey-100, #f5f5f5))}:host([variant=info]) .button{background-color:var(--vi-button-surface-info-background-color, var(--vi-color-info, #3676d0));color:var(--vi-button-surface-info-text-color, var(--vi-color-grey-100, #f5f5f5))}:host([variant=ghost]) .button{background-color:var(--vi-button-surface-ghost-background-color, transparent);color:var(--vi-button-surface-ghost-text-color, var(--vi-color-primary, #3676d0))}:host([disabled]) .button,.button:disabled{opacity:.6;cursor:not-allowed}.button:not(:disabled){box-shadow:var(--vi-button-effect-shadow-raised, inset 0 1px 0 rgba(255, 255, 255, .14), 0 2px 4px rgba(0, 0, 0, .18), 0 1px 2px rgba(0, 0, 0, .08))}.button:hover:not(:disabled){opacity:.92;box-shadow:var(--vi-button-effect-shadow-hover, inset 0 1px 0 rgba(255, 255, 255, .18), 0 4px 8px rgba(0, 0, 0, .22), 0 2px 4px rgba(0, 0, 0, .1));transform:translateY(-1px)}.button:active:not(:disabled){box-shadow:var(--vi-button-effect-shadow-pressed, inset 0 2px 4px rgba(0, 0, 0, .22), 0 1px 1px rgba(0, 0, 0, .06));transform:translateY(1px);opacity:1}:host([variant=ghost]) .button:hover:not(:disabled){background-color:#0000000a;text-decoration:underline;opacity:1}:host([variant=ghost]) .button:not(:disabled){box-shadow:none}:host([variant=ghost]) .button:active:not(:disabled){box-shadow:inset 0 1px 3px #00000024;transform:translateY(0)}@media(prefers-reduced-motion:reduce){.button{transform:none!important;transition-property:color,background-color,border-color,box-shadow,opacity!important}}.icon{order:-1;display:inline-flex;flex-shrink:0}.icon[hidden]{display:none}:host([icon-placement=end]) .icon{order:1}::slotted(vi-icon),::slotted(svg){--vi-icon-size: 1em;width:1em;height:1em}.label{flex:1 1 auto;min-width:0}";
156
+
157
+ function applyDecs2203RFactory() {
158
+ function createAddInitializerMethod(initializers, decoratorFinishedRef) {
159
+ return function addInitializer(initializer) {
160
+ assertNotFinished(decoratorFinishedRef, "addInitializer");
161
+ assertCallable(initializer, "An initializer");
162
+ initializers.push(initializer);
163
+ };
164
+ }
165
+ function memberDec(dec, name, desc, initializers, kind, isStatic, isPrivate, metadata, value) {
166
+ var kindStr;
167
+ switch(kind){
168
+ case 1:
169
+ kindStr = "accessor";
170
+ break;
171
+ case 2:
172
+ kindStr = "method";
173
+ break;
174
+ case 3:
175
+ kindStr = "getter";
176
+ break;
177
+ case 4:
178
+ kindStr = "setter";
179
+ break;
180
+ default:
181
+ kindStr = "field";
182
+ }
183
+ var ctx = {
184
+ kind: kindStr,
185
+ name: isPrivate ? "#" + name : name,
186
+ static: isStatic,
187
+ private: isPrivate,
188
+ metadata: metadata
189
+ };
190
+ var decoratorFinishedRef = {
191
+ v: false
192
+ };
193
+ ctx.addInitializer = createAddInitializerMethod(initializers, decoratorFinishedRef);
194
+ var get, set;
195
+ if (kind === 0) {
196
+ if (isPrivate) {
197
+ get = desc.get;
198
+ set = desc.set;
199
+ } else {
200
+ get = function() {
201
+ return this[name];
202
+ };
203
+ set = function(v) {
204
+ this[name] = v;
205
+ };
206
+ }
207
+ } else if (kind === 2) {
208
+ get = function() {
209
+ return desc.value;
210
+ };
211
+ } else {
212
+ if (kind === 1 || kind === 3) {
213
+ get = function() {
214
+ return desc.get.call(this);
215
+ };
216
+ }
217
+ if (kind === 1 || kind === 4) {
218
+ set = function(v) {
219
+ desc.set.call(this, v);
220
+ };
221
+ }
222
+ }
223
+ ctx.access = get && set ? {
224
+ get: get,
225
+ set: set
226
+ } : get ? {
227
+ get: get
228
+ } : {
229
+ set: set
230
+ };
231
+ try {
232
+ return dec(value, ctx);
233
+ } finally{
234
+ decoratorFinishedRef.v = true;
235
+ }
236
+ }
237
+ function assertNotFinished(decoratorFinishedRef, fnName) {
238
+ if (decoratorFinishedRef.v) {
239
+ throw new Error("attempted to call " + fnName + " after decoration was finished");
240
+ }
241
+ }
242
+ function assertCallable(fn, hint) {
243
+ if (typeof fn !== "function") {
244
+ throw new TypeError(hint + " must be a function");
245
+ }
246
+ }
247
+ function assertValidReturnValue(kind, value) {
248
+ var type = typeof value;
249
+ if (kind === 1) {
250
+ if (type !== "object" || value === null) {
251
+ throw new TypeError("accessor decorators must return an object with get, set, or init properties or void 0");
252
+ }
253
+ if (value.get !== undefined) {
254
+ assertCallable(value.get, "accessor.get");
255
+ }
256
+ if (value.set !== undefined) {
257
+ assertCallable(value.set, "accessor.set");
258
+ }
259
+ if (value.init !== undefined) {
260
+ assertCallable(value.init, "accessor.init");
261
+ }
262
+ } else if (type !== "function") {
263
+ var hint;
264
+ if (kind === 0) {
265
+ hint = "field";
266
+ } else if (kind === 10) {
267
+ hint = "class";
268
+ } else {
269
+ hint = "method";
270
+ }
271
+ throw new TypeError(hint + " decorators must return a function or void 0");
272
+ }
273
+ }
274
+ function applyMemberDec(ret, base, decInfo, name, kind, isStatic, isPrivate, initializers, metadata) {
275
+ var decs = decInfo[0];
276
+ var desc, init, value;
277
+ if (isPrivate) {
278
+ if (kind === 0 || kind === 1) {
279
+ desc = {
280
+ get: decInfo[3],
281
+ set: decInfo[4]
282
+ };
283
+ } else if (kind === 3) {
284
+ desc = {
285
+ get: decInfo[3]
286
+ };
287
+ } else if (kind === 4) {
288
+ desc = {
289
+ set: decInfo[3]
290
+ };
291
+ } else {
292
+ desc = {
293
+ value: decInfo[3]
294
+ };
295
+ }
296
+ } else if (kind !== 0) {
297
+ desc = Object.getOwnPropertyDescriptor(base, name);
298
+ }
299
+ if (kind === 1) {
300
+ value = {
301
+ get: desc.get,
302
+ set: desc.set
303
+ };
304
+ } else if (kind === 2) {
305
+ value = desc.value;
306
+ } else if (kind === 3) {
307
+ value = desc.get;
308
+ } else if (kind === 4) {
309
+ value = desc.set;
310
+ }
311
+ var newValue, get, set;
312
+ if (typeof decs === "function") {
313
+ newValue = memberDec(decs, name, desc, initializers, kind, isStatic, isPrivate, metadata, value);
314
+ if (newValue !== void 0) {
315
+ assertValidReturnValue(kind, newValue);
316
+ if (kind === 0) {
317
+ init = newValue;
318
+ } else if (kind === 1) {
319
+ init = newValue.init;
320
+ get = newValue.get || value.get;
321
+ set = newValue.set || value.set;
322
+ value = {
323
+ get: get,
324
+ set: set
325
+ };
326
+ } else {
327
+ value = newValue;
328
+ }
329
+ }
330
+ } else {
331
+ for(var i = decs.length - 1; i >= 0; i--){
332
+ var dec = decs[i];
333
+ newValue = memberDec(dec, name, desc, initializers, kind, isStatic, isPrivate, metadata, value);
334
+ if (newValue !== void 0) {
335
+ assertValidReturnValue(kind, newValue);
336
+ var newInit;
337
+ if (kind === 0) {
338
+ newInit = newValue;
339
+ } else if (kind === 1) {
340
+ newInit = newValue.init;
341
+ get = newValue.get || value.get;
342
+ set = newValue.set || value.set;
343
+ value = {
344
+ get: get,
345
+ set: set
346
+ };
347
+ } else {
348
+ value = newValue;
349
+ }
350
+ if (newInit !== void 0) {
351
+ if (init === void 0) {
352
+ init = newInit;
353
+ } else if (typeof init === "function") {
354
+ init = [
355
+ init,
356
+ newInit
357
+ ];
358
+ } else {
359
+ init.push(newInit);
360
+ }
361
+ }
362
+ }
363
+ }
364
+ }
365
+ if (kind === 0 || kind === 1) {
366
+ if (init === void 0) {
367
+ init = function(instance, init) {
368
+ return init;
369
+ };
370
+ } else if (typeof init !== "function") {
371
+ var ownInitializers = init;
372
+ init = function(instance, init) {
373
+ var value = init;
374
+ for(var i = 0; i < ownInitializers.length; i++){
375
+ value = ownInitializers[i].call(instance, value);
376
+ }
377
+ return value;
378
+ };
379
+ } else {
380
+ var originalInitializer = init;
381
+ init = function(instance, init) {
382
+ return originalInitializer.call(instance, init);
383
+ };
384
+ }
385
+ ret.push(init);
386
+ }
387
+ if (kind !== 0) {
388
+ if (kind === 1) {
389
+ desc.get = value.get;
390
+ desc.set = value.set;
391
+ } else if (kind === 2) {
392
+ desc.value = value;
393
+ } else if (kind === 3) {
394
+ desc.get = value;
395
+ } else if (kind === 4) {
396
+ desc.set = value;
397
+ }
398
+ if (isPrivate) {
399
+ if (kind === 1) {
400
+ ret.push(function(instance, args) {
401
+ return value.get.call(instance, args);
402
+ });
403
+ ret.push(function(instance, args) {
404
+ return value.set.call(instance, args);
405
+ });
406
+ } else if (kind === 2) {
407
+ ret.push(value);
408
+ } else {
409
+ ret.push(function(instance, args) {
410
+ return value.call(instance, args);
411
+ });
412
+ }
413
+ } else {
414
+ Object.defineProperty(base, name, desc);
415
+ }
416
+ }
417
+ }
418
+ function applyMemberDecs(Class, decInfos, metadata) {
419
+ var ret = [];
420
+ var protoInitializers;
421
+ var staticInitializers;
422
+ var existingProtoNonFields = new Map();
423
+ var existingStaticNonFields = new Map();
424
+ for(var i = 0; i < decInfos.length; i++){
425
+ var decInfo = decInfos[i];
426
+ if (!Array.isArray(decInfo)) continue;
427
+ var kind = decInfo[1];
428
+ var name = decInfo[2];
429
+ var isPrivate = decInfo.length > 3;
430
+ var isStatic = kind >= 5;
431
+ var base;
432
+ var initializers;
433
+ if (isStatic) {
434
+ base = Class;
435
+ kind = kind - 5;
436
+ staticInitializers = staticInitializers || [];
437
+ initializers = staticInitializers;
438
+ } else {
439
+ base = Class.prototype;
440
+ protoInitializers = protoInitializers || [];
441
+ initializers = protoInitializers;
442
+ }
443
+ if (kind !== 0 && !isPrivate) {
444
+ var existingNonFields = isStatic ? existingStaticNonFields : existingProtoNonFields;
445
+ var existingKind = existingNonFields.get(name) || 0;
446
+ if (existingKind === true || existingKind === 3 && kind !== 4 || existingKind === 4 && kind !== 3) {
447
+ throw new Error("Attempted to decorate a public method/accessor that has the same name as a previously decorated public method/accessor. This is not currently supported by the decorators plugin. Property name was: " + name);
448
+ } else if (!existingKind && kind > 2) {
449
+ existingNonFields.set(name, kind);
450
+ } else {
451
+ existingNonFields.set(name, true);
452
+ }
453
+ }
454
+ applyMemberDec(ret, base, decInfo, name, kind, isStatic, isPrivate, initializers, metadata);
455
+ }
456
+ pushInitializers(ret, protoInitializers);
457
+ pushInitializers(ret, staticInitializers);
458
+ return ret;
459
+ }
460
+ function pushInitializers(ret, initializers) {
461
+ if (initializers) {
462
+ ret.push(function(instance) {
463
+ for(var i = 0; i < initializers.length; i++){
464
+ initializers[i].call(instance);
465
+ }
466
+ return instance;
467
+ });
468
+ }
469
+ }
470
+ function applyClassDecs(targetClass, classDecs, metadata) {
471
+ if (classDecs.length > 0) {
472
+ var initializers = [];
473
+ var newClass = targetClass;
474
+ var name = targetClass.name;
475
+ for(var i = classDecs.length - 1; i >= 0; i--){
476
+ var decoratorFinishedRef = {
477
+ v: false
478
+ };
479
+ try {
480
+ var nextNewClass = classDecs[i](newClass, {
481
+ kind: "class",
482
+ name: name,
483
+ addInitializer: createAddInitializerMethod(initializers, decoratorFinishedRef),
484
+ metadata
485
+ });
486
+ } finally{
487
+ decoratorFinishedRef.v = true;
488
+ }
489
+ if (nextNewClass !== undefined) {
490
+ assertValidReturnValue(10, nextNewClass);
491
+ newClass = nextNewClass;
492
+ }
493
+ }
494
+ return [
495
+ defineMetadata(newClass, metadata),
496
+ function() {
497
+ for(var i = 0; i < initializers.length; i++){
498
+ initializers[i].call(newClass);
499
+ }
500
+ }
501
+ ];
502
+ }
503
+ }
504
+ function defineMetadata(Class, metadata) {
505
+ return Object.defineProperty(Class, Symbol.metadata || Symbol.for("Symbol.metadata"), {
506
+ configurable: true,
507
+ enumerable: true,
508
+ value: metadata
509
+ });
510
+ }
511
+ return function applyDecs2203R(targetClass, memberDecs, classDecs, parentClass) {
512
+ if (parentClass !== void 0) {
513
+ var parentMetadata = parentClass[Symbol.metadata || Symbol.for("Symbol.metadata")];
514
+ }
515
+ var metadata = Object.create(parentMetadata === void 0 ? null : parentMetadata);
516
+ var e = applyMemberDecs(targetClass, memberDecs, metadata);
517
+ if (!classDecs.length) defineMetadata(targetClass, metadata);
518
+ return {
519
+ e: e,
520
+ get c () {
521
+ return applyClassDecs(targetClass, classDecs, metadata);
522
+ }
523
+ };
524
+ };
525
+ }
526
+ function _apply_decs_2203_r(targetClass, memberDecs, classDecs, parentClass) {
527
+ return (_apply_decs_2203_r = applyDecs2203RFactory())(targetClass, memberDecs, classDecs, parentClass);
528
+ }
529
+ function _identity(x) {
530
+ return x;
531
+ }
532
+ var _dec, _initClass, _FocusableMixin, _dec1, _dec2, _dec3, _dec4, _dec5, _dec6, _dec7, /** Visual variant. */ _init_variant, /** Size scale — controls padding and font-size. */ _init_size, /** Icon placement: 'start' (before label) or 'end' (after label). CSS order handles it — no DOM changes on toggle. */ _init_iconPlacement, /** When true, stretches the button to fill the width of its container. */ _init_fullWidth, /** When true, styles the button for an icon-only layout (typically square with equal padding). */ _init_iconOnly, /** Disables the button. */ _init_disabled, _init__hasIcon, _initProto;
533
+ let _ViButton;
534
+ _dec = customElement('vi-button'), _dec1 = property({
535
+ type: String,
536
+ reflect: true
537
+ }), _dec2 = property({
538
+ type: String,
539
+ reflect: true
540
+ }), _dec3 = property({
541
+ type: String,
542
+ reflect: true,
543
+ attribute: 'icon-placement'
544
+ }), _dec4 = property({
545
+ type: Boolean,
546
+ reflect: true,
547
+ attribute: 'full-width'
548
+ }), _dec5 = property({
549
+ type: Boolean,
550
+ reflect: true,
551
+ attribute: 'icon-only'
552
+ }), _dec6 = property({
553
+ type: Boolean,
554
+ reflect: true
555
+ }), _dec7 = state();
556
+ new class extends _identity {
557
+ constructor(){
558
+ super(_ViButton), _initClass();
559
+ }
560
+ static{
561
+ class ViButton extends (_FocusableMixin = FocusableMixin(ViElement)) {
562
+ static{
563
+ ({ e: [_init_variant, _init_size, _init_iconPlacement, _init_fullWidth, _init_iconOnly, _init_disabled, _init__hasIcon, _initProto], c: [_ViButton, _initClass] } = _apply_decs_2203_r(this, [
564
+ [
565
+ _dec1,
566
+ 1,
567
+ "variant"
568
+ ],
569
+ [
570
+ _dec2,
571
+ 1,
572
+ "size"
573
+ ],
574
+ [
575
+ _dec3,
576
+ 1,
577
+ "iconPlacement"
578
+ ],
579
+ [
580
+ _dec4,
581
+ 1,
582
+ "fullWidth"
583
+ ],
584
+ [
585
+ _dec5,
586
+ 1,
587
+ "iconOnly"
588
+ ],
589
+ [
590
+ _dec6,
591
+ 1,
592
+ "disabled"
593
+ ],
594
+ [
595
+ _dec7,
596
+ 1,
597
+ "_hasIcon"
598
+ ]
599
+ ], [
600
+ _dec
601
+ ], _FocusableMixin));
602
+ }
603
+ static styles = css`${unsafeCSS(buttonStyles)}`;
604
+ get _focusableElement() {
605
+ return this.shadowRoot?.querySelector('button') ?? null;
606
+ }
607
+ #___private_variant_1 = (_initProto(this), _init_variant(this, 'primary'));
608
+ get variant() {
609
+ return this.#___private_variant_1;
610
+ }
611
+ set variant(_v) {
612
+ this.#___private_variant_1 = _v;
613
+ }
614
+ #___private_size_2 = _init_size(this, 'md');
615
+ get size() {
616
+ return this.#___private_size_2;
617
+ }
618
+ set size(_v) {
619
+ this.#___private_size_2 = _v;
620
+ }
621
+ #___private_iconPlacement_3 = _init_iconPlacement(this, 'start');
622
+ get iconPlacement() {
623
+ return this.#___private_iconPlacement_3;
624
+ }
625
+ set iconPlacement(_v) {
626
+ this.#___private_iconPlacement_3 = _v;
627
+ }
628
+ #___private_fullWidth_4 = _init_fullWidth(this, false);
629
+ get fullWidth() {
630
+ return this.#___private_fullWidth_4;
631
+ }
632
+ set fullWidth(_v) {
633
+ this.#___private_fullWidth_4 = _v;
634
+ }
635
+ #___private_iconOnly_5 = _init_iconOnly(this, false);
636
+ get iconOnly() {
637
+ return this.#___private_iconOnly_5;
638
+ }
639
+ set iconOnly(_v) {
640
+ this.#___private_iconOnly_5 = _v;
641
+ }
642
+ #___private_disabled_6 = _init_disabled(this, false);
643
+ get disabled() {
644
+ return this.#___private_disabled_6;
645
+ }
646
+ set disabled(_v) {
647
+ this.#___private_disabled_6 = _v;
648
+ }
649
+ #___private__hasIcon_7 = _init__hasIcon(this, false);
650
+ get _hasIcon() {
651
+ return this.#___private__hasIcon_7;
652
+ }
653
+ set _hasIcon(_v) {
654
+ this.#___private__hasIcon_7 = _v;
655
+ }
656
+ updated(changed) {
657
+ super.updated(changed);
658
+ if (changed.has('disabled')) {
659
+ if (this.disabled) {
660
+ // Becoming disabled — always remove from tab order.
661
+ this._setHostFocusable(false);
662
+ } else if (changed.get('disabled') !== undefined) {
663
+ // Transitioning from a real disabled state back to enabled.
664
+ // Skip when old value is `undefined` (first render) — connectedCallback
665
+ // already set the correct tabIndex, respecting any consumer tabindex attr.
666
+ this._setHostFocusable(true);
667
+ }
668
+ }
669
+ }
670
+ onIconSlotChange(e) {
671
+ const slot = e.target;
672
+ this._hasIcon = slot.assignedElements({
673
+ flatten: true
674
+ }).length > 0;
675
+ }
676
+ onClick(event) {
677
+ if (this.disabled) {
678
+ event.preventDefault();
679
+ event.stopImmediatePropagation();
680
+ }
681
+ }
682
+ render() {
683
+ const { _hasIcon, disabled, onClick, onIconSlotChange } = this;
684
+ return html`
685
+ <button
686
+ class="button"
687
+ part="button"
688
+ type="button"
689
+ tabindex="-1"
690
+ ?disabled=${disabled}
691
+ @click=${onClick}
692
+ >
693
+ <slot
694
+ name="icon"
695
+ class="icon"
696
+ part="icon"
697
+ ?hidden=${!_hasIcon}
698
+ @slotchange=${onIconSlotChange}
699
+ ></slot>
700
+ <span part="label" class="label"><slot></slot></span>
701
+ </button>
702
+ `;
703
+ }
704
+ }
705
+ }
706
+ }();
707
+
708
+ export { _ViButton as ViButton };
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Icon Registry
3
+ *
4
+ * A Map-based store for SvgIconDef objects sourced from @vialiq/icons.
5
+ * Icons must be explicitly registered before <vi-icon> can render them.
6
+ * Only the icons you register end up in your bundle — full tree-shaking.
7
+ *
8
+ * Usage:
9
+ * import { registerIcons } from '@vialiq/web-components';
10
+ * import { checkIcon } from '@vialiq/icons/check';
11
+ *
12
+ * registerIcons([checkIcon]);
13
+ * // <vi-icon name="check"></vi-icon>
14
+ */ const registry = new Map();
15
+ /**
16
+ * Defence-in-depth guard for SVG data passed to registerIcons().
17
+ *
18
+ * registerIcons() is a **trusted-only** API. SVG data must originate from
19
+ * @vialiq/icons or another vetted source — never from user-supplied strings.
20
+ * This validation is not a substitute for a full sanitiser; it raises early
21
+ * on the most obvious injection vectors (script elements, inline event handlers).
22
+ */ function assertSafeSvg(name, data) {
23
+ const trimmed = data.trim();
24
+ if (!trimmed.startsWith('<svg')) {
25
+ throw new Error(`[vi-icon] Icon "${name}": SVG data must begin with an <svg> element.`);
26
+ }
27
+ if (/<script[\s>]/i.test(trimmed)) {
28
+ throw new Error(`[vi-icon] Icon "${name}": SVG data must not contain <script> elements.`);
29
+ }
30
+ if (/\bon\w+\s*=/i.test(trimmed)) {
31
+ throw new Error(`[vi-icon] Icon "${name}": SVG data must not contain inline event handlers (on*=).`);
32
+ }
33
+ }
34
+ /**
35
+ * Register one or more icons. Call this before using <vi-icon>.
36
+ *
37
+ * @param icons - Icon definitions from @vialiq/icons (trusted source only).
38
+ */ function registerIcons(icons) {
39
+ const list = Array.isArray(icons) ? icons : [
40
+ icons
41
+ ];
42
+ for (const icon of list){
43
+ assertSafeSvg(icon.name, icon.data);
44
+ registry.set(icon.name, icon);
45
+ }
46
+ }
47
+ /**
48
+ * Look up a registered icon by name.
49
+ */ function getIcon(name) {
50
+ return registry.get(name);
51
+ }
52
+
53
+ export { getIcon, registerIcons };
@@ -0,0 +1,526 @@
1
+ import { css, nothing, html } from 'lit';
2
+ import { customElement, property, state } from 'lit/decorators.js';
3
+ import { unsafeHTML } from 'lit/directives/unsafe-html.js';
4
+ import { V as ViElement } from '../vi-element-C6GfDPs3.js';
5
+ import { getIcon } from './registry.js';
6
+
7
+ function applyDecs2203RFactory() {
8
+ function createAddInitializerMethod(initializers, decoratorFinishedRef) {
9
+ return function addInitializer(initializer) {
10
+ assertNotFinished(decoratorFinishedRef, "addInitializer");
11
+ assertCallable(initializer, "An initializer");
12
+ initializers.push(initializer);
13
+ };
14
+ }
15
+ function memberDec(dec, name, desc, initializers, kind, isStatic, isPrivate, metadata, value) {
16
+ var kindStr;
17
+ switch(kind){
18
+ case 1:
19
+ kindStr = "accessor";
20
+ break;
21
+ case 2:
22
+ kindStr = "method";
23
+ break;
24
+ case 3:
25
+ kindStr = "getter";
26
+ break;
27
+ case 4:
28
+ kindStr = "setter";
29
+ break;
30
+ default:
31
+ kindStr = "field";
32
+ }
33
+ var ctx = {
34
+ kind: kindStr,
35
+ name: isPrivate ? "#" + name : name,
36
+ static: isStatic,
37
+ private: isPrivate,
38
+ metadata: metadata
39
+ };
40
+ var decoratorFinishedRef = {
41
+ v: false
42
+ };
43
+ ctx.addInitializer = createAddInitializerMethod(initializers, decoratorFinishedRef);
44
+ var get, set;
45
+ if (kind === 0) {
46
+ if (isPrivate) {
47
+ get = desc.get;
48
+ set = desc.set;
49
+ } else {
50
+ get = function() {
51
+ return this[name];
52
+ };
53
+ set = function(v) {
54
+ this[name] = v;
55
+ };
56
+ }
57
+ } else if (kind === 2) {
58
+ get = function() {
59
+ return desc.value;
60
+ };
61
+ } else {
62
+ if (kind === 1 || kind === 3) {
63
+ get = function() {
64
+ return desc.get.call(this);
65
+ };
66
+ }
67
+ if (kind === 1 || kind === 4) {
68
+ set = function(v) {
69
+ desc.set.call(this, v);
70
+ };
71
+ }
72
+ }
73
+ ctx.access = get && set ? {
74
+ get: get,
75
+ set: set
76
+ } : get ? {
77
+ get: get
78
+ } : {
79
+ set: set
80
+ };
81
+ try {
82
+ return dec(value, ctx);
83
+ } finally{
84
+ decoratorFinishedRef.v = true;
85
+ }
86
+ }
87
+ function assertNotFinished(decoratorFinishedRef, fnName) {
88
+ if (decoratorFinishedRef.v) {
89
+ throw new Error("attempted to call " + fnName + " after decoration was finished");
90
+ }
91
+ }
92
+ function assertCallable(fn, hint) {
93
+ if (typeof fn !== "function") {
94
+ throw new TypeError(hint + " must be a function");
95
+ }
96
+ }
97
+ function assertValidReturnValue(kind, value) {
98
+ var type = typeof value;
99
+ if (kind === 1) {
100
+ if (type !== "object" || value === null) {
101
+ throw new TypeError("accessor decorators must return an object with get, set, or init properties or void 0");
102
+ }
103
+ if (value.get !== undefined) {
104
+ assertCallable(value.get, "accessor.get");
105
+ }
106
+ if (value.set !== undefined) {
107
+ assertCallable(value.set, "accessor.set");
108
+ }
109
+ if (value.init !== undefined) {
110
+ assertCallable(value.init, "accessor.init");
111
+ }
112
+ } else if (type !== "function") {
113
+ var hint;
114
+ if (kind === 0) {
115
+ hint = "field";
116
+ } else if (kind === 10) {
117
+ hint = "class";
118
+ } else {
119
+ hint = "method";
120
+ }
121
+ throw new TypeError(hint + " decorators must return a function or void 0");
122
+ }
123
+ }
124
+ function applyMemberDec(ret, base, decInfo, name, kind, isStatic, isPrivate, initializers, metadata) {
125
+ var decs = decInfo[0];
126
+ var desc, init, value;
127
+ if (isPrivate) {
128
+ if (kind === 0 || kind === 1) {
129
+ desc = {
130
+ get: decInfo[3],
131
+ set: decInfo[4]
132
+ };
133
+ } else if (kind === 3) {
134
+ desc = {
135
+ get: decInfo[3]
136
+ };
137
+ } else if (kind === 4) {
138
+ desc = {
139
+ set: decInfo[3]
140
+ };
141
+ } else {
142
+ desc = {
143
+ value: decInfo[3]
144
+ };
145
+ }
146
+ } else if (kind !== 0) {
147
+ desc = Object.getOwnPropertyDescriptor(base, name);
148
+ }
149
+ if (kind === 1) {
150
+ value = {
151
+ get: desc.get,
152
+ set: desc.set
153
+ };
154
+ } else if (kind === 2) {
155
+ value = desc.value;
156
+ } else if (kind === 3) {
157
+ value = desc.get;
158
+ } else if (kind === 4) {
159
+ value = desc.set;
160
+ }
161
+ var newValue, get, set;
162
+ if (typeof decs === "function") {
163
+ newValue = memberDec(decs, name, desc, initializers, kind, isStatic, isPrivate, metadata, value);
164
+ if (newValue !== void 0) {
165
+ assertValidReturnValue(kind, newValue);
166
+ if (kind === 0) {
167
+ init = newValue;
168
+ } else if (kind === 1) {
169
+ init = newValue.init;
170
+ get = newValue.get || value.get;
171
+ set = newValue.set || value.set;
172
+ value = {
173
+ get: get,
174
+ set: set
175
+ };
176
+ } else {
177
+ value = newValue;
178
+ }
179
+ }
180
+ } else {
181
+ for(var i = decs.length - 1; i >= 0; i--){
182
+ var dec = decs[i];
183
+ newValue = memberDec(dec, name, desc, initializers, kind, isStatic, isPrivate, metadata, value);
184
+ if (newValue !== void 0) {
185
+ assertValidReturnValue(kind, newValue);
186
+ var newInit;
187
+ if (kind === 0) {
188
+ newInit = newValue;
189
+ } else if (kind === 1) {
190
+ newInit = newValue.init;
191
+ get = newValue.get || value.get;
192
+ set = newValue.set || value.set;
193
+ value = {
194
+ get: get,
195
+ set: set
196
+ };
197
+ } else {
198
+ value = newValue;
199
+ }
200
+ if (newInit !== void 0) {
201
+ if (init === void 0) {
202
+ init = newInit;
203
+ } else if (typeof init === "function") {
204
+ init = [
205
+ init,
206
+ newInit
207
+ ];
208
+ } else {
209
+ init.push(newInit);
210
+ }
211
+ }
212
+ }
213
+ }
214
+ }
215
+ if (kind === 0 || kind === 1) {
216
+ if (init === void 0) {
217
+ init = function(instance, init) {
218
+ return init;
219
+ };
220
+ } else if (typeof init !== "function") {
221
+ var ownInitializers = init;
222
+ init = function(instance, init) {
223
+ var value = init;
224
+ for(var i = 0; i < ownInitializers.length; i++){
225
+ value = ownInitializers[i].call(instance, value);
226
+ }
227
+ return value;
228
+ };
229
+ } else {
230
+ var originalInitializer = init;
231
+ init = function(instance, init) {
232
+ return originalInitializer.call(instance, init);
233
+ };
234
+ }
235
+ ret.push(init);
236
+ }
237
+ if (kind !== 0) {
238
+ if (kind === 1) {
239
+ desc.get = value.get;
240
+ desc.set = value.set;
241
+ } else if (kind === 2) {
242
+ desc.value = value;
243
+ } else if (kind === 3) {
244
+ desc.get = value;
245
+ } else if (kind === 4) {
246
+ desc.set = value;
247
+ }
248
+ if (isPrivate) {
249
+ if (kind === 1) {
250
+ ret.push(function(instance, args) {
251
+ return value.get.call(instance, args);
252
+ });
253
+ ret.push(function(instance, args) {
254
+ return value.set.call(instance, args);
255
+ });
256
+ } else if (kind === 2) {
257
+ ret.push(value);
258
+ } else {
259
+ ret.push(function(instance, args) {
260
+ return value.call(instance, args);
261
+ });
262
+ }
263
+ } else {
264
+ Object.defineProperty(base, name, desc);
265
+ }
266
+ }
267
+ }
268
+ function applyMemberDecs(Class, decInfos, metadata) {
269
+ var ret = [];
270
+ var protoInitializers;
271
+ var staticInitializers;
272
+ var existingProtoNonFields = new Map();
273
+ var existingStaticNonFields = new Map();
274
+ for(var i = 0; i < decInfos.length; i++){
275
+ var decInfo = decInfos[i];
276
+ if (!Array.isArray(decInfo)) continue;
277
+ var kind = decInfo[1];
278
+ var name = decInfo[2];
279
+ var isPrivate = decInfo.length > 3;
280
+ var isStatic = kind >= 5;
281
+ var base;
282
+ var initializers;
283
+ if (isStatic) {
284
+ base = Class;
285
+ kind = kind - 5;
286
+ staticInitializers = staticInitializers || [];
287
+ initializers = staticInitializers;
288
+ } else {
289
+ base = Class.prototype;
290
+ protoInitializers = protoInitializers || [];
291
+ initializers = protoInitializers;
292
+ }
293
+ if (kind !== 0 && !isPrivate) {
294
+ var existingNonFields = isStatic ? existingStaticNonFields : existingProtoNonFields;
295
+ var existingKind = existingNonFields.get(name) || 0;
296
+ if (existingKind === true || existingKind === 3 && kind !== 4 || existingKind === 4 && kind !== 3) {
297
+ throw new Error("Attempted to decorate a public method/accessor that has the same name as a previously decorated public method/accessor. This is not currently supported by the decorators plugin. Property name was: " + name);
298
+ } else if (!existingKind && kind > 2) {
299
+ existingNonFields.set(name, kind);
300
+ } else {
301
+ existingNonFields.set(name, true);
302
+ }
303
+ }
304
+ applyMemberDec(ret, base, decInfo, name, kind, isStatic, isPrivate, initializers, metadata);
305
+ }
306
+ pushInitializers(ret, protoInitializers);
307
+ pushInitializers(ret, staticInitializers);
308
+ return ret;
309
+ }
310
+ function pushInitializers(ret, initializers) {
311
+ if (initializers) {
312
+ ret.push(function(instance) {
313
+ for(var i = 0; i < initializers.length; i++){
314
+ initializers[i].call(instance);
315
+ }
316
+ return instance;
317
+ });
318
+ }
319
+ }
320
+ function applyClassDecs(targetClass, classDecs, metadata) {
321
+ if (classDecs.length > 0) {
322
+ var initializers = [];
323
+ var newClass = targetClass;
324
+ var name = targetClass.name;
325
+ for(var i = classDecs.length - 1; i >= 0; i--){
326
+ var decoratorFinishedRef = {
327
+ v: false
328
+ };
329
+ try {
330
+ var nextNewClass = classDecs[i](newClass, {
331
+ kind: "class",
332
+ name: name,
333
+ addInitializer: createAddInitializerMethod(initializers, decoratorFinishedRef),
334
+ metadata
335
+ });
336
+ } finally{
337
+ decoratorFinishedRef.v = true;
338
+ }
339
+ if (nextNewClass !== undefined) {
340
+ assertValidReturnValue(10, nextNewClass);
341
+ newClass = nextNewClass;
342
+ }
343
+ }
344
+ return [
345
+ defineMetadata(newClass, metadata),
346
+ function() {
347
+ for(var i = 0; i < initializers.length; i++){
348
+ initializers[i].call(newClass);
349
+ }
350
+ }
351
+ ];
352
+ }
353
+ }
354
+ function defineMetadata(Class, metadata) {
355
+ return Object.defineProperty(Class, Symbol.metadata || Symbol.for("Symbol.metadata"), {
356
+ configurable: true,
357
+ enumerable: true,
358
+ value: metadata
359
+ });
360
+ }
361
+ return function applyDecs2203R(targetClass, memberDecs, classDecs, parentClass) {
362
+ if (parentClass !== void 0) {
363
+ var parentMetadata = parentClass[Symbol.metadata || Symbol.for("Symbol.metadata")];
364
+ }
365
+ var metadata = Object.create(parentMetadata === void 0 ? null : parentMetadata);
366
+ var e = applyMemberDecs(targetClass, memberDecs, metadata);
367
+ if (!classDecs.length) defineMetadata(targetClass, metadata);
368
+ return {
369
+ e: e,
370
+ get c () {
371
+ return applyClassDecs(targetClass, classDecs, metadata);
372
+ }
373
+ };
374
+ };
375
+ }
376
+ function _apply_decs_2203_r(targetClass, memberDecs, classDecs, parentClass) {
377
+ return (_apply_decs_2203_r = applyDecs2203RFactory())(targetClass, memberDecs, classDecs, parentClass);
378
+ }
379
+ function _identity(x) {
380
+ return x;
381
+ }
382
+ var _dec, _initClass, _ViElement, _dec1, _dec2, _dec3, _dec4, /**
383
+ * The registered icon name to render.
384
+ * @attr
385
+ */ _init_name, /**
386
+ * Size in pixels applied as a CSS custom property.
387
+ * @attr
388
+ */ _init_size, /**
389
+ * Accessible label. When set the SVG gets role="img" + aria-label.
390
+ * When omitted the icon is treated as decorative (aria-hidden).
391
+ * @attr
392
+ */ _init_label, _init__icon, _initProto;
393
+ let _ViIcon;
394
+ _dec = customElement('vi-icon'), _dec1 = property({
395
+ type: String,
396
+ reflect: true
397
+ }), _dec2 = property({
398
+ type: Number
399
+ }), _dec3 = property({
400
+ type: String
401
+ }), _dec4 = state();
402
+ new class extends _identity {
403
+ constructor(){
404
+ super(_ViIcon), _initClass();
405
+ }
406
+ static{
407
+ class ViIcon extends (_ViElement = ViElement) {
408
+ static{
409
+ ({ e: [_init_name, _init_size, _init_label, _init__icon, _initProto], c: [_ViIcon, _initClass] } = _apply_decs_2203_r(this, [
410
+ [
411
+ _dec1,
412
+ 1,
413
+ "name"
414
+ ],
415
+ [
416
+ _dec2,
417
+ 1,
418
+ "size"
419
+ ],
420
+ [
421
+ _dec3,
422
+ 1,
423
+ "label"
424
+ ],
425
+ [
426
+ _dec4,
427
+ 1,
428
+ "_icon"
429
+ ]
430
+ ], [
431
+ _dec
432
+ ], _ViElement));
433
+ }
434
+ static styles = css`
435
+ :host {
436
+ display: inline-flex;
437
+ align-items: center;
438
+ justify-content: center;
439
+ width: var(--vi-icon-size, 24px);
440
+ height: var(--vi-icon-size, 24px);
441
+ }
442
+
443
+ svg {
444
+ width: 100%;
445
+ height: 100%;
446
+ fill: none;
447
+ stroke: currentColor;
448
+ stroke-width: 2;
449
+ stroke-linecap: round;
450
+ stroke-linejoin: round;
451
+ }
452
+ `;
453
+ #___private_name_1 = (_initProto(this), _init_name(this, ''));
454
+ get name() {
455
+ return this.#___private_name_1;
456
+ }
457
+ set name(_v) {
458
+ this.#___private_name_1 = _v;
459
+ }
460
+ #___private_size_2 = _init_size(this, 24);
461
+ get size() {
462
+ return this.#___private_size_2;
463
+ }
464
+ set size(_v) {
465
+ this.#___private_size_2 = _v;
466
+ }
467
+ #___private_label_3 = _init_label(this, '');
468
+ get label() {
469
+ return this.#___private_label_3;
470
+ }
471
+ set label(_v) {
472
+ this.#___private_label_3 = _v;
473
+ }
474
+ #___private__icon_4 = _init__icon(this, undefined);
475
+ get _icon() {
476
+ return this.#___private__icon_4;
477
+ }
478
+ set _icon(_v) {
479
+ this.#___private__icon_4 = _v;
480
+ }
481
+ updated(changedProperties) {
482
+ super.updated(changedProperties);
483
+ if (changedProperties.has('name')) {
484
+ this._icon = getIcon(this.name);
485
+ }
486
+ // Set or clear the inline custom property based on whether the consumer
487
+ // has explicitly provided a size attribute. Clearing on removal ensures
488
+ // a stale inline style does not keep overriding consumer CSS.
489
+ if (changedProperties.has('size')) {
490
+ if (this.hasAttribute('size')) {
491
+ this.style.setProperty('--vi-icon-size', `${this.size}px`);
492
+ } else {
493
+ this.style.removeProperty('--vi-icon-size');
494
+ }
495
+ }
496
+ }
497
+ firstUpdated(changedProperties) {
498
+ super.firstUpdated(changedProperties);
499
+ this._icon = getIcon(this.name);
500
+ if (this.hasAttribute('size')) {
501
+ this.style.setProperty('--vi-icon-size', `${this.size}px`);
502
+ }
503
+ }
504
+ render() {
505
+ if (!this._icon) {
506
+ // Not registered — render nothing; avoids broken UI silently.
507
+ return html`${nothing}`;
508
+ }
509
+ if (this.label) {
510
+ return html`
511
+ <span role="img" aria-label=${this.label}>
512
+ ${unsafeHTML(this._icon.data)}
513
+ </span>
514
+ `;
515
+ }
516
+ return html`
517
+ <span aria-hidden="true">
518
+ ${unsafeHTML(this._icon.data)}
519
+ </span>
520
+ `;
521
+ }
522
+ }
523
+ }
524
+ }();
525
+
526
+ export { _ViIcon as ViIcon };
package/index.js ADDED
@@ -0,0 +1,4 @@
1
+ export { V as ViElement } from './vi-element-C6GfDPs3.js';
2
+ export { ViButton } from './button/vi-button.js';
3
+ export { ViIcon } from './icons/vi-icon.js';
4
+ export { getIcon, registerIcons } from './icons/registry.js';
package/package.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "@vialiq/web-components",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "private": false,
5
+ "publishConfig": {
6
+ "access": "public"
7
+ },
5
8
  "repository": {
6
9
  "type": "git",
7
10
  "url": "https://github.com/prasworld/Vialiq.git"
8
11
  },
9
- "publishConfig": {
10
- "access": "public"
11
- },
12
12
  "type": "module",
13
13
  "sideEffects": true,
14
14
  "description": "Lit web component library built on @vialiq/flux-ui design tokens",
@@ -17,26 +17,26 @@
17
17
  "types": "./index.d.ts",
18
18
  "exports": {
19
19
  ".": {
20
- "default": "./index.js",
21
- "types": "./index.d.ts"
20
+ "types": "./index.d.ts",
21
+ "default": "./index.js"
22
22
  },
23
23
  "./button": {
24
- "default": "./button/vi-button.js",
25
- "types": "./button/vi-button.d.ts"
24
+ "types": "./button/vi-button.d.ts",
25
+ "default": "./button/vi-button.js"
26
26
  },
27
27
  "./icons/vi-icon": {
28
- "default": "./icons/vi-icon.js",
29
- "types": "./icons/vi-icon.d.ts"
28
+ "types": "./icons/vi-icon.d.ts",
29
+ "default": "./icons/vi-icon.js"
30
30
  },
31
31
  "./icons/registry": {
32
- "default": "./icons/registry.js",
33
- "types": "./icons/registry.d.ts"
32
+ "types": "./icons/registry.d.ts",
33
+ "default": "./icons/registry.js"
34
34
  }
35
35
  },
36
36
  "peerDependencies": {
37
- "lit": "^3.0.0",
38
- "@vialiq/flux-ui": "^0.0.4",
39
- "@vialiq/icons": "^0.0.3"
37
+ "@vialiq/flux-ui": "^0.1.2",
38
+ "@vialiq/icons": ">=0.0.7 <0.1.0",
39
+ "lit": "^3.0.0"
40
40
  },
41
41
  "keywords": [
42
42
  "web-components",
@@ -0,0 +1,9 @@
1
+ import { LitElement } from 'lit';
2
+
3
+ /**
4
+ * Shared base class for Vi web components.
5
+ * Keep this thin — behaviour is added via mixins (FocusableMixin, FocusTrapMixin).
6
+ */ class ViElement extends LitElement {
7
+ }
8
+
9
+ export { ViElement as V };