@vialiq/web-components 0.4.0 → 0.6.0

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,64 @@
1
+ import { ifDefined } from 'lit/directives/if-defined.js';
2
+
3
+ /**
4
+ * ifNonEmpty — conditional attribute directive
5
+ *
6
+ * A wrapper around Lit's `ifDefined` that additionally removes the attribute
7
+ * when the value is an empty string. Use this for every optional string
8
+ * attribute on inner native elements where `""` and "absent" have different
9
+ * meaning for browsers and screen readers.
10
+ *
11
+ * Problem with raw `ifDefined`:
12
+ * - `ifDefined(undefined)` → removes the attribute ✅
13
+ * - `ifDefined(null)` → removes the attribute ✅
14
+ * - `ifDefined('')` → sets attribute to "" ❌
15
+ *
16
+ * With `ifNonEmpty`:
17
+ * - `ifNonEmpty(undefined)` → removes the attribute ✅
18
+ * - `ifNonEmpty(null)` → removes the attribute ✅
19
+ * - `ifNonEmpty('')` → removes the attribute ✅
20
+ * - `ifNonEmpty('hello')` → sets attribute to "hello" ✅
21
+ *
22
+ * Why it matters — real screen reader / browser bugs caused by `=""`:
23
+ * - `placeholder=""` → JAWS/NVDA still announce it as an empty placeholder
24
+ * - `aria-label=""` → NVDA reads "blank" instead of deriving the name elsewhere
25
+ * - `aria-describedby=""`→ browsers may still look for id="" element
26
+ * - `title=""` → browsers show an empty tooltip on hover in some engines
27
+ *
28
+ * ---
29
+ *
30
+ * USAGE
31
+ *
32
+ * Import in any shadow template that has optional string attributes:
33
+ *
34
+ * import { ifNonEmpty } from '../base/if-non-empty.js';
35
+ *
36
+ * In the template:
37
+ *
38
+ * // ✅ Use ifNonEmpty for optional string attributes on inner native elements
39
+ * <input
40
+ * placeholder=${ifNonEmpty(this.placeholder)}
41
+ * aria-label=${ifNonEmpty(this.label)}
42
+ * aria-describedby=${ifNonEmpty(this._descriptionId)}
43
+ * />
44
+ *
45
+ * // ❌ Do NOT use for boolean attributes — Lit has ?attr=${bool} for that
46
+ * // ❌ Do NOT use for property bindings — Lit has .prop=${val} for that
47
+ * // ❌ Do NOT use for event bindings — Lit has @event=${handler} for that
48
+ *
49
+ * ---
50
+ *
51
+ * WHEN TO USE vs NOT USE
52
+ *
53
+ * Use ifNonEmpty when:
54
+ * - The attribute is optional (component has a prop that defaults to '')
55
+ * - The inner native element is a standard HTML element (input, button, a, etc.)
56
+ * - The attribute has accessibility or UI meaning when absent vs present
57
+ *
58
+ * Skip ifNonEmpty when:
59
+ * - The attribute is always required (e.g. type="button" is never absent)
60
+ * - You need the attribute to literally be "" (rare, document when intentional)
61
+ * - The binding is to a custom element property — use .prop=${val} instead
62
+ */ const ifNonEmpty = (value)=>ifDefined(value === '' ? undefined : value ?? undefined);
63
+
64
+ export { ifNonEmpty as i };
package/index.d.ts CHANGED
@@ -2,7 +2,7 @@ export { ViElement } from './base/vi-element.js';
2
2
  export type { ViSize, ViStatus } from './base/vi-element.js';
3
3
  export type { ControlStatus } from './base/validity-mixin.js';
4
4
  export { ViButton } from './button/vi-button.js';
5
- export type { ButtonVariant, ButtonSize, ButtonIconPlacement } from './button/vi-button.js';
5
+ export type { ButtonVariant, ButtonSize, ButtonIconPlacement, } from './button/vi-button.js';
6
6
  export { ViInput } from './input/vi-input.js';
7
7
  export type { InputType, InputSize } from './input/vi-input.js';
8
8
  export { ViIcon } from './icons/vi-icon.js';
@@ -14,4 +14,8 @@ export { ViRadioGroup } from './radio/vi-radio-group.js';
14
14
  export type { RadioGroupOrientation } from './radio/vi-radio-group.js';
15
15
  export { ViCheckbox } from './checkbox/vi-checkbox.js';
16
16
  export type { CheckboxSize } from './checkbox/vi-checkbox.js';
17
+ export { ViTooltip } from './tooltip/vi-tooltip.js';
18
+ export type { TooltipPlacement, TooltipTrigger } from './tooltip/vi-tooltip.js';
19
+ export { ViTextarea } from './textarea/vi-textarea.js';
20
+ export type { TextareaResize } from './textarea/vi-textarea.js';
17
21
  //# sourceMappingURL=index.d.ts.map
package/index.js CHANGED
@@ -6,3 +6,5 @@ export { getIcon, registerIcons } from './icons/registry.js';
6
6
  export { ViRadio } from './radio/vi-radio.js';
7
7
  export { ViRadioGroup } from './radio/vi-radio-group.js';
8
8
  export { ViCheckbox } from './checkbox/vi-checkbox.js';
9
+ export { ViTooltip } from './tooltip/vi-tooltip.js';
10
+ export { ViTextarea } from './textarea/vi-textarea.js';
package/input/index.js ADDED
@@ -0,0 +1 @@
1
+ export { ViInput } from './vi-input.js';
@@ -71,6 +71,10 @@ export declare class ViInput extends ViInput_base {
71
71
  accessor size: InputSize;
72
72
  /** When true, the value cannot be edited but is still submitted. */
73
73
  accessor readonly: boolean;
74
+ /** The accessibility label. */
75
+ accessor ariaLabel: string;
76
+ /** Reference to an element id containing the label. */
77
+ accessor ariaLabelledby: string;
74
78
  protected _testValidity(): Partial<ValidityStateFlags>;
75
79
  updated(changed: PropertyValues): void;
76
80
  /** Resets value and validation state when the associated form resets. */
@@ -1 +1 @@
1
- {"version":3,"file":"vi-input.d.ts","sourceRoot":"","sources":["../../../../libs/web-components/src/input/vi-input.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,cAAc,EACnB,KAAK,cAAc,EACpB,MAAM,KAAK,CAAC;AAGb,OAAO,EAAiB,KAAK,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC9E,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAIlD;;;;;GAKG;AACH,MAAM,MAAM,SAAS,GACjB,MAAM,GACN,OAAO,GACP,UAAU,GACV,QAAQ,GACR,KAAK,GACL,KAAK,GACL,QAAQ,CAAC;AAEb,MAAM,MAAM,SAAS,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;;AAElD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,qBACa,OAAQ,SAAQ,YAAwC;IACnE,MAAM,CAAC,cAAc,UAAQ;IAC7B,OAAgB,MAAM,0BAEpB;IAEF,SAAS,CAAC,QAAQ,CAAC,UAAU,mBAA0B;IAEvD,cAAuB,iBAAiB,IAAI,gBAAgB,GAAG,IAAI,CAElE;IAI4B,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAa;IAC5B,QAAQ,CAAC,QAAQ,UAAS;IAC1D,QAAQ,CAAC,eAAe,SAAM;IAI1C,uFAAuF;IAC5C,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAU;IAE7E,qCAAqC;IACzB,QAAQ,CAAC,WAAW,SAAM;IAEtC,yDAAyD;IAC7C,QAAQ,CAAC,IAAI,SAAM;IAE/B,wEAAwE;IAC5D,QAAQ,CAAC,KAAK,SAAM;IAEhC,uEAAuE;IAC3B,QAAQ,CAAC,QAAQ,UAAS;IAEtE,mDAAmD;IACR,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAQ;IAE3E,oEAAoE;IACxB,QAAQ,CAAC,QAAQ,UAAS;IAOtE,SAAS,CAAC,aAAa,IAAI,OAAO,CAAC,kBAAkB,CAAC;IAmC7C,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI;IAU/C,yEAAyE;IACzE,iBAAiB,IAAI,IAAI;IAMzB,6EAA6E;IAC7E,oBAAoB,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI;IAM7C,OAAO,CAAC,QAAQ;IAahB,OAAO,CAAC,SAAS;IAejB,OAAO,KAAK,cAAc,GAIzB;IAED,OAAO,KAAK,kBAAkB,GAgB7B;IAEQ,MAAM,IAAI,cAAc;CAkClC;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,UAAU,EAAE,OAAO,CAAC;KACrB;CACF"}
1
+ {"version":3,"file":"vi-input.d.ts","sourceRoot":"","sources":["../../../../libs/web-components/src/input/vi-input.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,cAAc,EACnB,KAAK,cAAc,EACpB,MAAM,KAAK,CAAC;AAGb,OAAO,EAAiB,KAAK,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC9E,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAIlD;;;;;GAKG;AACH,MAAM,MAAM,SAAS,GACjB,MAAM,GACN,OAAO,GACP,UAAU,GACV,QAAQ,GACR,KAAK,GACL,KAAK,GACL,QAAQ,CAAC;AAEb,MAAM,MAAM,SAAS,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;;AAElD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,qBACa,OAAQ,SAAQ,YAAwC;IACnE,MAAM,CAAC,cAAc,UAAQ;IAC7B,OAAgB,MAAM,0BAEpB;IAEF,SAAS,CAAC,QAAQ,CAAC,UAAU,mBAA0B;IAEvD,cAAuB,iBAAiB,IAAI,gBAAgB,GAAG,IAAI,CAElE;IAI4B,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAa;IAC5B,QAAQ,CAAC,QAAQ,UAAS;IAC1D,QAAQ,CAAC,eAAe,SAAM;IAI1C,uFAAuF;IAC5C,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAU;IAE7E,qCAAqC;IACzB,QAAQ,CAAC,WAAW,SAAM;IAEtC,yDAAyD;IAC7C,QAAQ,CAAC,IAAI,SAAM;IAE/B,wEAAwE;IAC5D,QAAQ,CAAC,KAAK,SAAM;IAEhC,uEAAuE;IAC3B,QAAQ,CAAC,QAAQ,UAAS;IAEtE,mDAAmD;IACR,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAQ;IAE3E,oEAAoE;IACxB,QAAQ,CAAC,QAAQ,UAAS;IAEtE,+BAA+B;IACQ,QAAQ,CAAC,SAAS,SAAM;IAE/D,uDAAuD;IACX,QAAQ,CAAC,cAAc,SAAM;IAOzE,SAAS,CAAC,aAAa,IAAI,OAAO,CAAC,kBAAkB,CAAC;IAqC7C,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI;IAU/C,yEAAyE;IACzE,iBAAiB,IAAI,IAAI;IAMzB,6EAA6E;IAC7E,oBAAoB,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI;IAM7C,OAAO,CAAC,QAAQ;IAahB,OAAO,CAAC,SAAS;IAejB,OAAO,KAAK,cAAc,GAIzB;IAED,OAAO,KAAK,kBAAkB,GAgB7B;IAEQ,MAAM,IAAI,cAAc;CAoClC;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,UAAU,EAAE,OAAO,CAAC;KACrB;CACF"}
package/input/vi-input.js CHANGED
@@ -3,70 +3,9 @@ import { customElement, property } from 'lit/decorators.js';
3
3
  import { F as FocusableMixin } from '../focusable-mixin-CmxOyPX5.js';
4
4
  import { V as ValidityMixin } from '../validity-mixin-BjmXwgWk.js';
5
5
  import { V as ViElement } from '../vi-element-C6GfDPs3.js';
6
- import { ifDefined } from 'lit/directives/if-defined.js';
6
+ import { i as ifNonEmpty } from '../if-non-empty-DX8UGa-B.js';
7
7
 
8
- /**
9
- * ifNonEmpty — conditional attribute directive
10
- *
11
- * A wrapper around Lit's `ifDefined` that additionally removes the attribute
12
- * when the value is an empty string. Use this for every optional string
13
- * attribute on inner native elements where `""` and "absent" have different
14
- * meaning for browsers and screen readers.
15
- *
16
- * Problem with raw `ifDefined`:
17
- * - `ifDefined(undefined)` → removes the attribute ✅
18
- * - `ifDefined(null)` → removes the attribute ✅
19
- * - `ifDefined('')` → sets attribute to "" ❌
20
- *
21
- * With `ifNonEmpty`:
22
- * - `ifNonEmpty(undefined)` → removes the attribute ✅
23
- * - `ifNonEmpty(null)` → removes the attribute ✅
24
- * - `ifNonEmpty('')` → removes the attribute ✅
25
- * - `ifNonEmpty('hello')` → sets attribute to "hello" ✅
26
- *
27
- * Why it matters — real screen reader / browser bugs caused by `=""`:
28
- * - `placeholder=""` → JAWS/NVDA still announce it as an empty placeholder
29
- * - `aria-label=""` → NVDA reads "blank" instead of deriving the name elsewhere
30
- * - `aria-describedby=""`→ browsers may still look for id="" element
31
- * - `title=""` → browsers show an empty tooltip on hover in some engines
32
- *
33
- * ---
34
- *
35
- * USAGE
36
- *
37
- * Import in any shadow template that has optional string attributes:
38
- *
39
- * import { ifNonEmpty } from '../base/if-non-empty.js';
40
- *
41
- * In the template:
42
- *
43
- * // ✅ Use ifNonEmpty for optional string attributes on inner native elements
44
- * <input
45
- * placeholder=${ifNonEmpty(this.placeholder)}
46
- * aria-label=${ifNonEmpty(this.label)}
47
- * aria-describedby=${ifNonEmpty(this._descriptionId)}
48
- * />
49
- *
50
- * // ❌ Do NOT use for boolean attributes — Lit has ?attr=${bool} for that
51
- * // ❌ Do NOT use for property bindings — Lit has .prop=${val} for that
52
- * // ❌ Do NOT use for event bindings — Lit has @event=${handler} for that
53
- *
54
- * ---
55
- *
56
- * WHEN TO USE vs NOT USE
57
- *
58
- * Use ifNonEmpty when:
59
- * - The attribute is optional (component has a prop that defaults to '')
60
- * - The inner native element is a standard HTML element (input, button, a, etc.)
61
- * - The attribute has accessibility or UI meaning when absent vs present
62
- *
63
- * Skip ifNonEmpty when:
64
- * - The attribute is always required (e.g. type="button" is never absent)
65
- * - You need the attribute to literally be "" (rare, document when intentional)
66
- * - The binding is to a custom element property — use .prop=${val} instead
67
- */ const ifNonEmpty = (value)=>ifDefined(value === '' ? undefined : value ?? undefined);
68
-
69
- const inputStyles = "@charset \"UTF-8\";@layer reset,components,utilities;@layer components{.input-field{display:flex;flex-direction:column;gap:var(--vi-input-spacing-field-gap, var(--vi-spacing-xs, 8px));width:100%}.input-control{appearance:none;-webkit-appearance:none;display:block;width:100%;box-sizing:border-box;min-height:var(--vi-input-sizing-min-height, 40px);border:var(--vi-border-width-thin, 1px) solid var(--vi-input-border-color, var(--vi-color-grey-300, #e0e0e0));border-radius:var(--vi-input-shape-border-radius, var(--vi-border-radius-lg, 8px));padding:var(--vi-input-spacing-padding-block, var(--vi-spacing-xs, 8px)) var(--vi-input-spacing-padding-inline, var(--vi-spacing-sm, 16px));font-family:var(--vi-font-family-base, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif);font-size:var(--vi-input-typography-font-size, var(--vi-font-size-base, 16px));font-weight:var(--vi-font-weight-normal, 400);line-height:var(--vi-input-typography-line-height, var(--vi-line-height-normal, 1.5));color:var(--vi-input-text-color, var(--vi-color-foreground, #111827));background-color:var(--vi-input-background-color, var(--vi-color-background, #ffffff));transition:border-color .15s ease,box-shadow .15s ease}.input-control:hover:not(:focus-visible){border-color:var(--vi-input-border-color-hover, var(--vi-color-grey-500, #9e9e9e))}.input-control:focus-visible,.input-control:focus{outline:var(--vi-border-width-base, 2px) solid var(--vi-input-focus-ring-color, var(--vi-color-primary, #3676d0));outline-offset:0;box-shadow:0 0 0 3px var(--vi-input-focus-ring-glow, var(--vi-color-blue-200, #cee6ff))}.input-control::placeholder{color:var(--vi-input-placeholder-color, var(--vi-color-grey-500, #9e9e9e))}.input-helper{font-size:var(--vi-input-helper-size, var(--vi-font-size-xs, 12px));line-height:var(--vi-input-helper-leading, var(--vi-line-height-normal, 1.5));color:var(--vi-input-helper-color, var(--vi-color-grey-500, #9e9e9e))}.input-error{font-size:var(--vi-input-error-size, var(--vi-font-size-xs, 12px));line-height:var(--vi-input-error-leading, var(--vi-line-height-normal, 1.5));color:var(--vi-input-error-color, var(--vi-color-error, #ef4444))}@media(prefers-reduced-motion:reduce){.input-control{transition:none}}}:host{display:block;outline:none}:host([disabled]){opacity:.6;cursor:not-allowed;pointer-events:none}:host([status=invalid]){--vi-input-border-color: var(--vi-color-error, #ef4444);--vi-input-border-color-hover: var(--vi-color-error, #ef4444);--vi-input-focus-ring-color: var(--vi-color-error, #ef4444);--vi-input-focus-ring-glow: var(--vi-color-red-100, #ffccce);--vi-input-label-color: var(--vi-color-error, #ef4444)}:host([status=valid]){--vi-input-border-color: var(--vi-color-success, #489167);--vi-input-border-color-hover: var(--vi-color-success, #489167);--vi-input-focus-ring-color: var(--vi-color-success, #489167);--vi-input-focus-ring-glow: var(--vi-color-green-100, #e6f0eb)}.input-validation{font-family:var(--vi-font-family-base, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif);font-size:var(--vi-font-size-xs, 12px);line-height:var(--vi-line-height-normal, 1.5);letter-spacing:var(--vi-letter-spacing-wider, .05em);color:var(--vi-input-helper-color, var(--vi-color-grey-500, #9e9e9e))}.input-validation--invalid{color:var(--vi-input-error-color, var(--vi-color-error, #ef4444))}.input-validation--valid{color:var(--vi-input-success-color, var(--vi-color-success, #489167))}::slotted([slot=helper]){font-family:var(--vi-font-family-base, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif);font-size:var(--vi-font-size-xs, 12px);line-height:var(--vi-line-height-normal, 1.5);letter-spacing:var(--vi-letter-spacing-wider, .05em);color:var(--vi-input-helper-color, var(--vi-color-grey-500, #9e9e9e))}:host([size=xs]){--vi-input-spacing-padding-block: 2px;--vi-input-spacing-padding-inline: 8px;--vi-input-typography-font-size: var(--vi-font-size-xs, 12px)}:host([size=sm]){--vi-input-spacing-padding-block: 4px;--vi-input-spacing-padding-inline: 12px;--vi-input-typography-font-size: var(--vi-font-size-sm, 14px)}:host([size=lg]){--vi-input-spacing-padding-block: 12px;--vi-input-spacing-padding-inline: 20px;--vi-input-typography-font-size: var(--vi-font-size-lg, 18px)}";
8
+ const inputStyles = "@charset \"UTF-8\";@layer reset,components,utilities;@layer components{.input-field{display:flex;flex-direction:column;gap:var(--vi-input-spacing-field-gap, var(--vi-spacing-xs, 8px));width:100%}.input-control{appearance:none;-webkit-appearance:none;display:block;width:100%;box-sizing:border-box;min-height:var(--vi-input-sizing-min-height, 40px);border:var(--vi-border-width-thin, 1px) solid var(--vi-input-border-color, var(--vi-color-grey-300, #e0e0e0));border-radius:var(--vi-input-shape-border-radius, var(--vi-border-radius-lg, 8px));padding:var(--vi-input-spacing-padding-block, var(--vi-spacing-xs, 8px)) var(--vi-input-spacing-padding-inline, var(--vi-spacing-sm, 16px));font-family:var(--vi-font-family-base, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif);font-size:var(--vi-input-typography-font-size, var(--vi-font-size-base, 16px));font-weight:var(--vi-font-weight-normal, 400);line-height:var(--vi-input-typography-line-height, var(--vi-line-height-normal, 1.5));color:var(--vi-input-text-color, var(--vi-color-foreground, #111827));background-color:var(--vi-input-background-color, var(--vi-color-background, #ffffff));transition:border-color .15s ease,box-shadow .15s ease}.input-control:hover:not(:focus-visible){border-color:var(--vi-input-border-color-hover, var(--vi-color-grey-500, #9e9e9e))}.input-control:focus-visible,.input-control:focus{outline:var(--vi-border-width-base, 2px) solid var(--vi-input-focus-ring-color, var(--vi-color-primary, #3676d0));outline-offset:0;box-shadow:0 0 0 3px var(--vi-input-focus-ring-glow, var(--vi-color-blue-200, #cee6ff))}.input-control::placeholder{color:var(--vi-input-placeholder-color, var(--vi-color-grey-500, #9e9e9e))}.input-helper{font-size:var(--vi-input-helper-size, var(--vi-font-size-xs, 12px));line-height:var(--vi-input-helper-leading, var(--vi-line-height-normal, 1.5));color:var(--vi-input-helper-color, var(--vi-text-helper, #9e9e9e))}.input-error{font-size:var(--vi-input-error-size, var(--vi-font-size-xs, 12px));line-height:var(--vi-input-error-leading, var(--vi-line-height-normal, 1.5));color:var(--vi-input-error-color, var(--vi-color-error, #ef4444))}@media(prefers-reduced-motion:reduce){.input-control{transition:none}}}:host{display:block;outline:none}:host([disabled]){opacity:.6;cursor:not-allowed;pointer-events:none}:host([status=invalid]){--vi-input-border-color: var(--vi-color-error, #ef4444);--vi-input-border-color-hover: var(--vi-color-error, #ef4444);--vi-input-focus-ring-color: var(--vi-color-error, #ef4444);--vi-input-focus-ring-glow: var(--vi-color-red-100, #ffccce);--vi-input-label-color: var(--vi-color-error, #ef4444)}:host([status=valid]){--vi-input-border-color: var(--vi-color-success, #489167);--vi-input-border-color-hover: var(--vi-color-success, #489167);--vi-input-focus-ring-color: var(--vi-color-success, #489167);--vi-input-focus-ring-glow: var(--vi-color-green-100, #e6f0eb)}.input-validation{font-family:var(--vi-font-family-base, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif);font-size:var(--vi-font-size-xs, 12px);line-height:var(--vi-line-height-normal, 1.5);letter-spacing:var(--vi-letter-spacing-wider, .05em);color:var(--vi-input-helper-color, var(--vi-text-helper, #9e9e9e))}.input-validation--invalid{color:var(--vi-input-error-color, var(--vi-color-error, #ef4444))}.input-validation--valid{color:var(--vi-input-success-color, var(--vi-color-success, #489167))}::slotted([slot=helper]){font-family:var(--vi-font-family-base, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif);font-size:var(--vi-font-size-xs, 12px);line-height:var(--vi-line-height-normal, 1.5);letter-spacing:var(--vi-letter-spacing-wider, .05em);color:var(--vi-input-helper-color, var(--vi-text-helper, #9e9e9e))}:host([size=xs]){--vi-input-spacing-padding-block: 2px;--vi-input-spacing-padding-inline: 8px;--vi-input-typography-font-size: var(--vi-font-size-xs, 12px)}:host([size=sm]){--vi-input-spacing-padding-block: 4px;--vi-input-spacing-padding-inline: 12px;--vi-input-typography-font-size: var(--vi-font-size-sm, 14px)}:host([size=lg]){--vi-input-spacing-padding-block: 12px;--vi-input-spacing-padding-inline: 20px;--vi-input-typography-font-size: var(--vi-font-size-lg, 18px)}";
70
9
 
71
10
  function applyDecs2203RFactory() {
72
11
  function createAddInitializerMethod(initializers, decoratorFinishedRef) {
@@ -443,9 +382,9 @@ function _apply_decs_2203_r(targetClass, memberDecs, classDecs, parentClass) {
443
382
  function _identity(x) {
444
383
  return x;
445
384
  }
446
- var _dec, _initClass, _ValidityMixin, _dec1, _dec2, _dec3, _dec4, _dec5, _dec6, _dec7, _dec8, _dec9, _dec10, // ── ValidityMixin contract — must be declared as @property —————————————
385
+ var _dec, _initClass, _ValidityMixin, _dec1, _dec2, _dec3, _dec4, _dec5, _dec6, _dec7, _dec8, _dec9, _dec10, _dec11, _dec12, // ── ValidityMixin contract — must be declared as @property —————————————
447
386
  _init_status, _init_required, _init_validityMessage, // ── Public API ─────────────────────────────────────────────────────────────
448
- /** Input type. Controls the keyboard/picker on mobile and browser validation hints. */ _init_type, /** Native input placeholder text. */ _init_placeholder, /** Form field name. Submitted with the form when set. */ _init_name, /** Current value. Synced to ElementInternals for form participation. */ _init_value, /** When true, disables the input and removes it from the tab order. */ _init_disabled, /** Size scale — controls padding and font-size. */ _init_size, /** When true, the value cannot be edited but is still submitted. */ _init_readonly, _initProto;
387
+ /** Input type. Controls the keyboard/picker on mobile and browser validation hints. */ _init_type, /** Native input placeholder text. */ _init_placeholder, /** Form field name. Submitted with the form when set. */ _init_name, /** Current value. Synced to ElementInternals for form participation. */ _init_value, /** When true, disables the input and removes it from the tab order. */ _init_disabled, /** Size scale — controls padding and font-size. */ _init_size, /** When true, the value cannot be edited but is still submitted. */ _init_readonly, /** The accessibility label. */ _init_ariaLabel, /** Reference to an element id containing the label. */ _init_ariaLabelledby, _initProto;
449
388
  let _ViInput;
450
389
  _dec = customElement('vi-input'), _dec1 = property({
451
390
  reflect: true
@@ -464,6 +403,10 @@ _dec = customElement('vi-input'), _dec1 = property({
464
403
  }), _dec10 = property({
465
404
  type: Boolean,
466
405
  reflect: true
406
+ }), _dec11 = property({
407
+ attribute: 'aria-label'
408
+ }), _dec12 = property({
409
+ attribute: 'aria-labelledby'
467
410
  });
468
411
  new class extends _identity {
469
412
  constructor(){
@@ -472,7 +415,7 @@ new class extends _identity {
472
415
  static{
473
416
  class ViInput extends (_ValidityMixin = ValidityMixin(FocusableMixin(ViElement))) {
474
417
  static{
475
- ({ e: [_init_status, _init_required, _init_validityMessage, _init_type, _init_placeholder, _init_name, _init_value, _init_disabled, _init_size, _init_readonly, _initProto], c: [_ViInput, _initClass] } = _apply_decs_2203_r(this, [
418
+ ({ e: [_init_status, _init_required, _init_validityMessage, _init_type, _init_placeholder, _init_name, _init_value, _init_disabled, _init_size, _init_readonly, _init_ariaLabel, _init_ariaLabelledby, _initProto], c: [_ViInput, _initClass] } = _apply_decs_2203_r(this, [
476
419
  [
477
420
  _dec1,
478
421
  1,
@@ -522,6 +465,16 @@ new class extends _identity {
522
465
  _dec10,
523
466
  1,
524
467
  "readonly"
468
+ ],
469
+ [
470
+ _dec11,
471
+ 1,
472
+ "ariaLabel"
473
+ ],
474
+ [
475
+ _dec12,
476
+ 1,
477
+ "ariaLabelledby"
525
478
  ]
526
479
  ], [
527
480
  _dec
@@ -605,6 +558,20 @@ new class extends _identity {
605
558
  set readonly(_v) {
606
559
  this.#___private_readonly_10 = _v;
607
560
  }
561
+ #___private_ariaLabel_11 = _init_ariaLabel(this, '');
562
+ get ariaLabel() {
563
+ return this.#___private_ariaLabel_11;
564
+ }
565
+ set ariaLabel(_v) {
566
+ this.#___private_ariaLabel_11 = _v;
567
+ }
568
+ #___private_ariaLabelledby_12 = _init_ariaLabelledby(this, '');
569
+ get ariaLabelledby() {
570
+ return this.#___private_ariaLabelledby_12;
571
+ }
572
+ set ariaLabelledby(_v) {
573
+ this.#___private_ariaLabelledby_12 = _v;
574
+ }
608
575
  // ── ValidityMixin hook ─────────────────────────────────────────────────────
609
576
  // _testValidity is declared protected in ValidityInterface, but TypeScript's
610
577
  // mixin intersection type does not always surface protected members for
@@ -637,7 +604,9 @@ new class extends _identity {
637
604
  };
638
605
  }
639
606
  } else if (this.required && !this.value) {
640
- this.validityMessage = 'Please fill out this field.';
607
+ const temp = document.createElement('input');
608
+ temp.required = true;
609
+ this.validityMessage = temp.validationMessage;
641
610
  return {
642
611
  valueMissing: true
643
612
  };
@@ -720,6 +689,8 @@ new class extends _identity {
720
689
  ?required=${required}
721
690
  aria-required=${ifNonEmpty(required ? 'true' : '')}
722
691
  aria-invalid=${this.status === 'invalid' ? 'true' : 'false'}
692
+ aria-label=${ifNonEmpty(this.ariaLabel)}
693
+ aria-labelledby=${ifNonEmpty(this.ariaLabelledby)}
723
694
  aria-describedby=${this.validityMessage ? 'helper-text validation-message' : 'helper-text'}
724
695
  aria-errormessage=${ifNonEmpty(this.status === 'invalid' && this.validityMessage ? 'validation-message' : '')}
725
696
  placeholder=${ifNonEmpty(placeholder)}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vialiq/web-components",
3
- "version": "0.4.0",
3
+ "version": "0.6.0",
4
4
  "private": false,
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -21,6 +21,10 @@
21
21
  "default": "./index.js"
22
22
  },
23
23
  "./button": {
24
+ "types": "./button/index.d.ts",
25
+ "default": "./button/index.js"
26
+ },
27
+ "./button/vi-button": {
24
28
  "types": "./button/vi-button.d.ts",
25
29
  "default": "./button/vi-button.js"
26
30
  },
@@ -33,6 +37,10 @@
33
37
  "default": "./icons/registry.js"
34
38
  },
35
39
  "./input": {
40
+ "types": "./input/index.d.ts",
41
+ "default": "./input/index.js"
42
+ },
43
+ "./input/vi-input": {
36
44
  "types": "./input/vi-input.d.ts",
37
45
  "default": "./input/vi-input.js"
38
46
  },
@@ -47,10 +55,35 @@
47
55
  "./radio": {
48
56
  "types": "./radio/index.d.ts",
49
57
  "default": "./radio/index.js"
58
+ },
59
+ "./checkbox": {
60
+ "types": "./checkbox/index.d.ts",
61
+ "default": "./checkbox/index.js"
62
+ },
63
+ "./checkbox/vi-checkbox": {
64
+ "types": "./checkbox/vi-checkbox.d.ts",
65
+ "default": "./checkbox/vi-checkbox.js"
66
+ },
67
+ "./textarea": {
68
+ "types": "./textarea/index.d.ts",
69
+ "default": "./textarea/index.js"
70
+ },
71
+ "./textarea/vi-textarea": {
72
+ "types": "./textarea/vi-textarea.d.ts",
73
+ "default": "./textarea/vi-textarea.js"
74
+ },
75
+ "./tooltip": {
76
+ "types": "./tooltip/index.d.ts",
77
+ "default": "./tooltip/index.js"
78
+ },
79
+ "./tooltip/vi-tooltip": {
80
+ "types": "./tooltip/vi-tooltip.d.ts",
81
+ "default": "./tooltip/vi-tooltip.js"
50
82
  }
51
83
  },
52
84
  "peerDependencies": {
53
- "@vialiq/flux-ui": "^0.3.0",
85
+ "@floating-ui/dom": ">=1.0.0",
86
+ "@vialiq/flux-ui": "^0.5.0",
54
87
  "@vialiq/icons": ">=0.0.3 <0.1.0",
55
88
  "lit": "^3.0.0"
56
89
  },
@@ -69,6 +102,9 @@
69
102
  "button/",
70
103
  "icons/",
71
104
  "input/",
105
+ "radio/",
106
+ "checkbox/",
107
+ "tooltip/",
72
108
  "README.md"
73
109
  ]
74
110
  }
@@ -0,0 +1,5 @@
1
+ export { ViRadio } from './vi-radio.js';
2
+ export type { RadioSize } from './vi-radio.js';
3
+ export { ViRadioGroup } from './vi-radio-group.js';
4
+ export type { RadioGroupOrientation } from './vi-radio-group.js';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../libs/web-components/src/radio/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,YAAY,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,YAAY,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC"}
package/radio/index.js ADDED
@@ -0,0 +1,2 @@
1
+ export { ViRadio } from './vi-radio.js';
2
+ export { ViRadioGroup } from './vi-radio-group.js';
@@ -0,0 +1,72 @@
1
+ import { type PropertyValues, type TemplateResult } from 'lit';
2
+ import { type ControlStatus } from '../base/validity-mixin.js';
3
+ import { ViElement } from '../base/vi-element.js';
4
+ import { type RadioSize } from './vi-radio.js';
5
+ export type RadioGroupOrientation = 'vertical' | 'horizontal';
6
+ declare const ViRadioGroup_base: typeof ViElement & (new (...args: any[]) => import("../base/validity-mixin.js").ValidityInterface);
7
+ /**
8
+ * vi-radio-group
9
+ * Form-associated radio button group container.
10
+ * Manages WAI-ARIA compliant keyboard roving tabindex and selection state.
11
+ *
12
+ * @element vi-radio-group
13
+ *
14
+ * @attr {string} value - Value of the currently selected radio option.
15
+ * @attr {string} name - Shared name for all child radios.
16
+ * @attr {boolean} disabled - Disables the entire radio group (reflected).
17
+ * @attr {boolean} required - Marks the group as requiring a selection (reflected).
18
+ * @attr {ControlStatus} status - Visual status: default | valid | invalid (reflected).
19
+ * @attr {string} validity-message - Error message shown when validation fails.
20
+ * @attr {RadioGroupOrientation} orientation - Layout direction: vertical | horizontal (reflected).
21
+ *
22
+ * @slot - Child vi-radio elements.
23
+ * @slot label - Text displayed above the group.
24
+ * @slot helper - Helper text displayed below the group.
25
+ *
26
+ * @fires {CustomEvent<{value: string}>} vialiq-change - Dispatched when selection changes. Bubbles, composed.
27
+ * @fires {Event} invalid - Fired when validation check fails.
28
+ */
29
+ export declare class ViRadioGroup extends ViRadioGroup_base {
30
+ static formAssociated: boolean;
31
+ static styles: import("lit").CSSResult;
32
+ protected readonly _internals: ElementInternals;
33
+ accessor status: ControlStatus;
34
+ accessor required: boolean;
35
+ accessor validityMessage: string;
36
+ /** Currently selected radio's value. */
37
+ accessor value: string;
38
+ /** Shared name for all child radios. */
39
+ accessor name: string;
40
+ /** Disables the entire group. */
41
+ accessor disabled: boolean;
42
+ /** Layout direction of the radio group. */
43
+ accessor orientation: RadioGroupOrientation;
44
+ /** Size scale — controls spacing and propagates to child radios. */
45
+ accessor size: RadioSize;
46
+ /** Allows clearing the selected radio button on double click. */
47
+ accessor allowDblclickClear: boolean;
48
+ private _observer?;
49
+ private _initialValue;
50
+ connectedCallback(): void;
51
+ disconnectedCallback(): void;
52
+ updated(changed: PropertyValues): void;
53
+ /** Resets the value and validation state when the parent form resets. */
54
+ formResetCallback(): void;
55
+ /** Keeps disabled in sync when a containing fieldset/form is disabled. */
56
+ formDisabledCallback(disabled: boolean): void;
57
+ protected _testValidity(): Partial<ValidityStateFlags>;
58
+ private _getRadios;
59
+ private _updateRadios;
60
+ private _handleRadioChecked;
61
+ private _onKeydown;
62
+ private _onDblclick;
63
+ private get _validationMessage();
64
+ render(): TemplateResult;
65
+ }
66
+ declare global {
67
+ interface HTMLElementTagNameMap {
68
+ 'vi-radio-group': ViRadioGroup;
69
+ }
70
+ }
71
+ export {};
72
+ //# sourceMappingURL=vi-radio-group.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vi-radio-group.d.ts","sourceRoot":"","sources":["../../../../libs/web-components/src/radio/vi-radio-group.ts"],"names":[],"mappings":"AAAA,OAAO,EAAwB,KAAK,cAAc,EAAE,KAAK,cAAc,EAAE,MAAM,KAAK,CAAC;AAErF,OAAO,EAAiB,KAAK,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC9E,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAIlD,OAAO,EAAW,KAAK,SAAS,EAAE,MAAM,eAAe,CAAC;AAExD,MAAM,MAAM,qBAAqB,GAAG,UAAU,GAAG,YAAY,CAAC;;AAE9D;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,qBACa,YAAa,SAAQ,iBAAwB;IACxD,MAAM,CAAC,cAAc,UAAQ;IAC7B,OAAgB,MAAM,0BAEpB;IAEF,SAAS,CAAC,QAAQ,CAAC,UAAU,mBAA0B;IAI1B,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAa;IAC5B,QAAQ,CAAC,QAAQ,UAAS;IACzB,QAAQ,CAAC,eAAe,SAAM;IAI3E,wCAAwC;IACX,QAAQ,CAAC,KAAK,SAAM;IAEjD,wCAAwC;IAC5B,QAAQ,CAAC,IAAI,SAAM;IAE/B,iCAAiC;IACW,QAAQ,CAAC,QAAQ,UAAS;IAEtE,2CAA2C;IACd,QAAQ,CAAC,WAAW,EAAE,qBAAqB,CAAc;IAEtF,oEAAoE;IACzB,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAQ;IAE3E,iEAAiE;IAEjE,QAAQ,CAAC,kBAAkB,UAAS;IAEpC,OAAO,CAAC,SAAS,CAAC,CAAmB;IAErC,OAAO,CAAC,aAAa,CAAM;IAElB,iBAAiB,IAAI,IAAI;IAsBzB,oBAAoB,IAAI,IAAI;IAQ5B,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI;IAkB/C,yEAAyE;IACzE,iBAAiB,IAAI,IAAI;IAOzB,0EAA0E;IAC1E,oBAAoB,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI;cAI1B,aAAa,IAAI,OAAO,CAAC,kBAAkB,CAAC;IA4B/D,OAAO,CAAC,UAAU;IAIlB,OAAO,CAAC,aAAa;IA0CrB,OAAO,CAAC,mBAAmB;IAmB3B,OAAO,CAAC,UAAU;IA0DlB,OAAO,CAAC,WAAW,CAqBjB;IAIF,OAAO,KAAK,kBAAkB,GAmB7B;IAEQ,MAAM,IAAI,cAAc;CA+BlC;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,gBAAgB,EAAE,YAAY,CAAC;KAChC;CACF"}