@lmvz-ds/components 0.38.0 → 0.40.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.
- package/CHANGELOG.md +17 -0
- package/README.md +12 -20
- package/cjs/{directional-focus-controller-8Xd_7MHT.js → directional-focus-controller-DDnhfX5w.js} +15 -5
- package/cjs/index.cjs.js +3 -195
- package/cjs/lmvz-action-list.cjs.entry.js +2 -2
- package/cjs/lmvz-button-group.cjs.entry.js +4 -0
- package/cjs/lmvz-button_2.cjs.entry.js +1 -1
- package/cjs/lmvz-card.cjs.entry.js +1 -1
- package/cjs/lmvz-components.cjs.js +1 -1
- package/cjs/lmvz-header_2.cjs.entry.js +3 -3
- package/cjs/lmvz-message.cjs.entry.js +2 -0
- package/cjs/lmvz-popover.cjs.entry.js +1 -1
- package/cjs/lmvz-select.cjs.entry.js +2 -3
- package/cjs/lmvz-tab.cjs.entry.js +3 -3
- package/cjs/lmvz-tabs.cjs.entry.js +43 -44
- package/cjs/loader.cjs.js +1 -1
- package/cjs/public-DTgpEs1_.js +206 -0
- package/collection/components/lmvz-action-list/lmvz-action-list.css +119 -116
- package/collection/components/lmvz-button/lmvz-button.css +109 -106
- package/collection/components/lmvz-card/lmvz-card.css +106 -103
- package/collection/components/lmvz-header/lmvz-header.js +2 -2
- package/collection/components/lmvz-select/lmvz-select.css +58 -43
- package/collection/components/lmvz-select/lmvz-select.js +1 -25
- package/collection/components/lmvz-snackbar/public.js +3 -0
- package/collection/components/lmvz-tab/lmvz-tab.css +0 -13
- package/collection/components/lmvz-tab/lmvz-tab.js +10 -14
- package/collection/components/lmvz-tabs/lmvz-tabs.css +0 -5
- package/collection/components/lmvz-tabs/lmvz-tabs.js +50 -65
- package/collection/utils/aria/directional-focus-controller.js +16 -7
- package/collection/utils/icons/public.js +3 -0
- package/components/index.js +1 -1
- package/components/lmvz-action-list.js +1 -1
- package/components/lmvz-button-group.js +1 -1
- package/components/lmvz-button.js +1 -1
- package/components/lmvz-card.js +1 -1
- package/components/lmvz-datepicker.js +1 -1
- package/components/lmvz-header.js +1 -1
- package/components/lmvz-icon.js +1 -1
- package/components/lmvz-input.js +1 -1
- package/components/lmvz-link.js +1 -1
- package/components/lmvz-menuitem.js +1 -1
- package/components/lmvz-message.js +1 -1
- package/components/lmvz-modal.js +1 -1
- package/components/lmvz-popover.js +1 -1
- package/components/lmvz-select.js +1 -1
- package/components/lmvz-snackbar.js +1 -1
- package/components/lmvz-tab.js +1 -1
- package/components/lmvz-tabs.js +1 -1
- package/components/{p-CcP_sfo8.js → p--mU29mrX.js} +1 -1
- package/components/p-BPa0FHVO.js +1 -0
- package/components/{p-SnHLBAbf.js → p-Bc5MM0zh.js} +1 -1
- package/components/p-CyDgnpOB.js +1 -0
- package/components/{p-C-pRMuMh.js → p-DIyiticz.js} +1 -1
- package/components/{p-BhALzK62.js → p-DJLdOjL4.js} +1 -1
- package/components/{p-B6bUOPCG.js → p-DSDBThqb.js} +1 -1
- package/components/p-DXhP6UeF.js +1 -0
- package/components/p-DsTgD0_a.js +1 -0
- package/components/p-DyQ1GbaN.js +1 -0
- package/components/p-niXjuPxe.js +1 -0
- package/esm/{directional-focus-controller-QukTTWBE.js → directional-focus-controller-CJ0yNC00.js} +15 -5
- package/esm/index.js +1 -197
- package/esm/lmvz-action-list.entry.js +2 -2
- package/esm/lmvz-button-group.entry.js +4 -0
- package/esm/lmvz-button_2.entry.js +1 -1
- package/esm/lmvz-card.entry.js +1 -1
- package/esm/lmvz-components.js +1 -1
- package/esm/lmvz-header_2.entry.js +3 -3
- package/esm/lmvz-message.entry.js +2 -0
- package/esm/lmvz-popover.entry.js +1 -1
- package/esm/lmvz-select.entry.js +2 -3
- package/esm/lmvz-tab.entry.js +3 -3
- package/esm/lmvz-tabs.entry.js +43 -44
- package/esm/loader.js +1 -1
- package/esm/public-m6pRVUeP.js +204 -0
- package/hydrate/index.js +280 -66
- package/hydrate/index.mjs +280 -66
- package/lmvz-components/index.esm.js +1 -1
- package/lmvz-components/lmvz-components.esm.js +1 -1
- package/lmvz-components/p-143e9621.entry.js +1 -0
- package/lmvz-components/p-220e455e.entry.js +1 -0
- package/lmvz-components/p-304c7554.entry.js +1 -0
- package/lmvz-components/p-316dd61a.entry.js +1 -0
- package/lmvz-components/{p-1e1dea53.entry.js → p-41286514.entry.js} +1 -1
- package/lmvz-components/p-93b781ca.entry.js +1 -0
- package/lmvz-components/p-BPa0FHVO.js +1 -0
- package/lmvz-components/p-BlkpdeQI.js +1 -0
- package/lmvz-components/p-c884c76e.entry.js +1 -0
- package/lmvz-components/p-ebad823c.entry.js +1 -0
- package/lmvz-components/p-edec4d09.entry.js +1 -0
- package/lmvz-components/p-f911691c.entry.js +1 -0
- package/manifest.json +38 -98
- package/package.json +2 -1
- package/types/components/lmvz-select/lmvz-select.d.ts +0 -1
- package/types/components/lmvz-snackbar/public.d.ts +6 -0
- package/types/components/lmvz-tab/lmvz-tab.d.ts +1 -1
- package/types/components/lmvz-tabs/lmvz-tabs.d.ts +8 -8
- package/types/components.d.ts +17 -39
- package/types/index.d.ts +5 -0
- package/types/utils/aria/directional-focus-controller.d.ts +9 -7
- package/types/utils/icons/public.d.ts +6 -0
- package/components/p-CgGqXTxQ.js +0 -1
- package/components/p-D3wobLRi.js +0 -1
- package/components/p-DfFdoFeH.js +0 -1
- package/components/p-GJaYKpHS.js +0 -1
- package/lmvz-components/p-3b7203a3.entry.js +0 -1
- package/lmvz-components/p-3fc6c3f6.entry.js +0 -1
- package/lmvz-components/p-9813a7d2.entry.js +0 -1
- package/lmvz-components/p-CHxiS3ja.js +0 -1
- package/lmvz-components/p-b5a5eb9a.entry.js +0 -1
- package/lmvz-components/p-cadd88e5.entry.js +0 -1
- package/lmvz-components/p-cebaddb0.entry.js +0 -1
- package/lmvz-components/p-d53e69de.entry.js +0 -1
- package/lmvz-components/p-db75e362.entry.js +0 -1
- package/lmvz-components/p-eb741e1f.entry.js +0 -1
package/manifest.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"timestamp": "2026-08-
|
|
2
|
+
"timestamp": "2026-08-17T12:33:14",
|
|
3
3
|
"compiler": {
|
|
4
4
|
"name": "@stencil/core",
|
|
5
5
|
"version": "4.43.5",
|
|
@@ -8253,7 +8253,7 @@
|
|
|
8253
8253
|
"filePath": "src/components/lmvz-select/lmvz-select.tsx",
|
|
8254
8254
|
"encapsulation": "scoped",
|
|
8255
8255
|
"tag": "lmvz-select",
|
|
8256
|
-
"readme": "# lmvz-select\n\nSelect component with floating label and pill-shaped trigger that implements the WAI-ARIA \"combobox with listbox popup\" pattern.\n\n## What changed: Breaking rewrite from native `<select>` to custom WAI-ARIA combobox\n\nIn previous versions, `lmvz-select` wrapped a native `<select>` element and inherited its form behavior and platform-specific UI (including native mobile pickers on iOS/Android). As of this version, it is a fully custom WAI-ARIA combobox implemented using:\n\n- A `role=\"combobox\"` trigger button (your interaction target)\n- A `role=\"listbox\"` popup menu hosted in `lmvz-popover`\n- Focus management via `aria-activedescendant` (trigger keeps focus; the selected item is tracked via an aria attribute rather than DOM focus)\n- Form submission via `ElementInternals` (like `lmvz-input`, `lmvz-checkbox`, etc. in this design system)\n\n**What consumers must know:**\n\n- **No native mobile picker:** On iOS, Android, and other platforms, users see the custom popup instead of the OS-native picker. This is by design, to ensure consistent styling and behavior across platforms.\n- **Slot contract:** You pass native `<option>` and `<optgroup>` elements as children. The component translates them internally to `role=\"listbox\"` and `role=\"option\"` elements.\n- **`<option selected>` is meaningful:** If you do not set the `value` prop, the first `<option selected=\"selected\">` becomes the initial value (or, in multiselect mode, all enabled `<option selected>` elements are collected into the initial `values`).\n- **Validation is minimal:** The component uses native HTML form constraint validation (`ElementInternals.setValidity()`). When `required` is true and no value is set, the browser's default validation UI appears on form submit; the component does not provide custom validation message styling beyond `errorMessage` (which you control via props).\n- **Form submission:** Use the `name` attribute (set directly on the `<lmvz-select>` host) and the current `value` to participate in HTML form submission. Form reset correctly restores the initial value.\n\n### Multiselect mode\n\nSet the `multiple` prop to enable multiselect mode. When `multiple` is `true`:\n\n- **Selection is tracked in `values`** (a `string[]` array), not in the single-select `value` prop. The `value` prop is ignored; do not set it alongside `multiple`.\n- **Options toggle membership** on selection instead of replacing a single value. Selecting an already-selected option deselects it.\n- **The listbox stays open** after selecting or deselecting an option. Close it via Escape, outside click, or re-clicking the trigger.\n- **The closed trigger renders one chip per selected value** for display only, using the `lmvz-chip` component. Removing a value is done by reselecting it in the open listbox.\n- **Keyboard selection works the same:** Space or Enter while an option is active (highlighted) toggles its selection without closing the popover.\n- **Preselection:** Pass `<option selected>` elements — *all* enabled ones are collected into the initial `values` array, not just the first (mirroring how `<select multiple>` works).\n- **Known limitation:** A \"select all\" control is not implemented in this iteration; it is planned as a future follow-up.\n\n## Slot contract\n\nThe default slot accepts only native `<option>` and `<optgroup>` elements. The component reads this markup once on mount and translates it into an internal listbox model, re-parsing whenever the slotted content changes structurally (options/optgroups added or removed) or an already-slotted option/optgroup is mutated in place (e.g. `.disabled`, `.selected`, `.value`, `.label`, or its text content), mirroring native `<select>` reactivity. The slotted markup is never rendered; it serves as a template.\n\n```html\n<lmvz-select label=\"Fruit\" name=\"fruit\">\n <option value=\"apple\">Apple</option>\n <optgroup label=\"Citrus\">\n <option value=\"orange\">Orange</option>\n <option value=\"lemon\">Lemon</option>\n </optgroup>\n <option value=\"banana\" selected>Banana</option>\n</lmvz-select>\n```\n\n## Form integration\n\n`lmvz-select` is a form-associated custom element (`formAssociated: true`). Set the `name` attribute on the host element, and the component participates in:\n\n- **Form submission:** The current `value` is submitted under the `name` key (single-select mode), or multiple form entries are submitted (multiselect mode).\n- **Form reset:** Restores `value` or `values` to their initial state (the prop values at mount time).\n- **Validation:** Set `required` to enforce that a value is present. Use `checkValidity()`, `reportValidity()`, and `getValidationMessage()` methods for programmatic validation.\n\n### Multiselect form submission\n\nIn multiselect mode (`multiple` true), form submission uses `FormData` to submit one entry per selected value:\n\n```javascript\nconst form = document.querySelector('form');\nconst formData = new FormData(form);\n// If the select has name=\"country\" and values=[\"ch\", \"de\"], then:\n// formData.getAll('country') returns ['ch', 'de']\n```\n\nForm reset restores `values` to its initial state (all enabled `<option selected>` elements, or an empty array if none). Programmatically, you can also detect multiselect form state restoration via the `formStateRestoreCallback()` lifecycle (called during form reset or history navigation).\n\n## Props explained\n\n### `size`\n\n- Type: `'small' | 'default' | 'large'`\n- Default: `'default'`\n\nControls the visual height variant of the select trigger. Use `small` for compact layouts, `default` for standard use, and `large` for emphasis.\n\n### `
|
|
8256
|
+
"readme": "# lmvz-select\n\nSelect component with floating label and pill-shaped trigger that implements the WAI-ARIA \"combobox with listbox popup\" pattern.\n\n## What changed: Breaking rewrite from native `<select>` to custom WAI-ARIA combobox\n\nIn previous versions, `lmvz-select` wrapped a native `<select>` element and inherited its form behavior and platform-specific UI (including native mobile pickers on iOS/Android). As of this version, it is a fully custom WAI-ARIA combobox implemented using:\n\n- A `role=\"combobox\"` trigger button (your interaction target)\n- A `role=\"listbox\"` popup menu hosted in `lmvz-popover`\n- Focus management via `aria-activedescendant` (trigger keeps focus; the selected item is tracked via an aria attribute rather than DOM focus)\n- Form submission via `ElementInternals` (like `lmvz-input`, `lmvz-checkbox`, etc. in this design system)\n\n**What consumers must know:**\n\n- **No native mobile picker:** On iOS, Android, and other platforms, users see the custom popup instead of the OS-native picker. This is by design, to ensure consistent styling and behavior across platforms.\n- **Slot contract:** You pass native `<option>` and `<optgroup>` elements as children. The component translates them internally to `role=\"listbox\"` and `role=\"option\"` elements.\n- **`<option selected>` is meaningful:** If you do not set the `value` prop, the first `<option selected=\"selected\">` becomes the initial value (or, in multiselect mode, all enabled `<option selected>` elements are collected into the initial `values`).\n- **Validation is minimal:** The component uses native HTML form constraint validation (`ElementInternals.setValidity()`). When `required` is true and no value is set, the browser's default validation UI appears on form submit; the component does not provide custom validation message styling beyond `errorMessage` (which you control via props).\n- **Form submission:** Use the `name` attribute (set directly on the `<lmvz-select>` host) and the current `value` to participate in HTML form submission. Form reset correctly restores the initial value.\n\n### Multiselect mode\n\nSet the `multiple` prop to enable multiselect mode. When `multiple` is `true`:\n\n- **Selection is tracked in `values`** (a `string[]` array), not in the single-select `value` prop. The `value` prop is ignored; do not set it alongside `multiple`.\n- **Options toggle membership** on selection instead of replacing a single value. Selecting an already-selected option deselects it.\n- **The listbox stays open** after selecting or deselecting an option. Close it via Escape, outside click, or re-clicking the trigger.\n- **The closed trigger renders one chip per selected value** for display only, using the `lmvz-chip` component. Removing a value is done by reselecting it in the open listbox.\n- **Keyboard selection works the same:** Space or Enter while an option is active (highlighted) toggles its selection without closing the popover.\n- **Preselection:** Pass `<option selected>` elements — *all* enabled ones are collected into the initial `values` array, not just the first (mirroring how `<select multiple>` works).\n- **Known limitation:** A \"select all\" control is not implemented in this iteration; it is planned as a future follow-up.\n\n## Slot contract\n\nThe default slot accepts only native `<option>` and `<optgroup>` elements. The component reads this markup once on mount and translates it into an internal listbox model, re-parsing whenever the slotted content changes structurally (options/optgroups added or removed) or an already-slotted option/optgroup is mutated in place (e.g. `.disabled`, `.selected`, `.value`, `.label`, or its text content), mirroring native `<select>` reactivity. The slotted markup is never rendered; it serves as a template.\n\n```html\n<lmvz-select label=\"Fruit\" name=\"fruit\">\n <option value=\"apple\">Apple</option>\n <optgroup label=\"Citrus\">\n <option value=\"orange\">Orange</option>\n <option value=\"lemon\">Lemon</option>\n </optgroup>\n <option value=\"banana\" selected>Banana</option>\n</lmvz-select>\n```\n\n## Form integration\n\n`lmvz-select` is a form-associated custom element (`formAssociated: true`). Set the `name` attribute on the host element, and the component participates in:\n\n- **Form submission:** The current `value` is submitted under the `name` key (single-select mode), or multiple form entries are submitted (multiselect mode).\n- **Form reset:** Restores `value` or `values` to their initial state (the prop values at mount time).\n- **Validation:** Set `required` to enforce that a value is present. Use `checkValidity()`, `reportValidity()`, and `getValidationMessage()` methods for programmatic validation.\n\n### Multiselect form submission\n\nIn multiselect mode (`multiple` true), form submission uses `FormData` to submit one entry per selected value:\n\n```javascript\nconst form = document.querySelector('form');\nconst formData = new FormData(form);\n// If the select has name=\"country\" and values=[\"ch\", \"de\"], then:\n// formData.getAll('country') returns ['ch', 'de']\n```\n\nForm reset restores `values` to its initial state (all enabled `<option selected>` elements, or an empty array if none). Programmatically, you can also detect multiselect form state restoration via the `formStateRestoreCallback()` lifecycle (called during form reset or history navigation).\n\n## Props explained\n\n### `size`\n\n- Type: `'small' | 'default' | 'large'`\n- Default: `'default'`\n\nControls the visual height variant of the select trigger. Use `small` for compact layouts, `default` for standard use, and `large` for emphasis.\n\n### `error`\n\n- Type: `boolean`\n- Default: `false`\n- Reflected as host attribute: yes\n\nWhen `true`:\n- Applies danger-themed border color to the combobox trigger.\n- Sets `aria-invalid=\"true\"` on the trigger element.\n\n`aria-invalid` is also automatically set to `true` when the select's real constraint validity becomes invalid following a validation attempt (e.g., after a failed `submit`, `checkValidity()`, or `reportValidity()` call), and is cleared once the constraint is resolved. This allows automatic reflect of native HTML5 validation state independent of the `error` prop.\n\nTypically set alongside `errorMessage` to provide inline error text.\n\n### `errorMessage`\n\n- Type: `string | undefined`\n- Default: `undefined`\n\nError message text rendered below the select field when `error={true}`. Rendered as an assertive live region (`role=\"alert\"`), linked to the trigger via `aria-describedby` and `aria-errormessage`.\n\nCoexists with `helperText` — both can be displayed simultaneously, with `helperText` rendered first.\n",
|
|
8257
8257
|
"docs": "Select component with floating label and pill-shaped trigger.\nImplements the WAI-ARIA APG \"combobox with listbox popup\" pattern: a `role=\"combobox\"`\ntrigger drives an `lmvz-popover`-hosted `role=\"listbox\"`/`role=\"option\"` list via the\nactivedescendant model (the trigger keeps real DOM focus; `aria-activedescendant` tracks\nthe highlighted option).\n\nSupports an opt-in multiselect mode (`multiple`): selection is tracked in `values` (an array)\ninstead of the single-select `value`, selecting an option toggles its membership without\nclosing the popup, and the closed trigger renders one `lmvz-chip` per selected value for\ndisplay only — removing a value is done by reselecting it in the open listbox, not from a\nchip control.\n\nParticipates in native HTML forms via `ElementInternals` (form-associated custom element):\nthe `name` attribute (set directly on the host element) and the current `value` (or, in\nmultiselect mode, one form entry per selected `values` entry) are submitted, and selection\nresets to its initial state on form reset.",
|
|
8258
8258
|
"docsTags": [
|
|
8259
8259
|
{
|
|
@@ -8380,35 +8380,6 @@
|
|
|
8380
8380
|
"getter": false,
|
|
8381
8381
|
"setter": false
|
|
8382
8382
|
},
|
|
8383
|
-
{
|
|
8384
|
-
"name": "highlighted",
|
|
8385
|
-
"type": "boolean",
|
|
8386
|
-
"complexType": {
|
|
8387
|
-
"original": "boolean",
|
|
8388
|
-
"resolved": "boolean",
|
|
8389
|
-
"references": {}
|
|
8390
|
-
},
|
|
8391
|
-
"mutable": false,
|
|
8392
|
-
"attr": "highlighted",
|
|
8393
|
-
"reflectToAttr": true,
|
|
8394
|
-
"docs": "Whether the select has an active filter or selection that should be visually\ndistinguished (e.g. a filter chip is applied).\n\nWhen `true`:\n- The host attribute `highlighted` is present (CSS: `:host([highlighted])`).\n- The host attribute `data-highlighted=\"true\"` is set for assistive-technology\n consumers that observe data attributes. When `false`, `data-highlighted` is\n set to `\"false\"`.\n\nNote: `aria-pressed` is intentionally not used here; it is reserved for toggle-button\nroles. `aria-selected` is reserved for this component's own `role=\"option\"` elements.\nThe `data-highlighted` attribute provides the accessible contract for this state.",
|
|
8395
|
-
"docsTags": [
|
|
8396
|
-
{
|
|
8397
|
-
"name": "default",
|
|
8398
|
-
"text": "false"
|
|
8399
|
-
}
|
|
8400
|
-
],
|
|
8401
|
-
"default": "false",
|
|
8402
|
-
"values": [
|
|
8403
|
-
{
|
|
8404
|
-
"type": "boolean"
|
|
8405
|
-
}
|
|
8406
|
-
],
|
|
8407
|
-
"optional": false,
|
|
8408
|
-
"required": false,
|
|
8409
|
-
"getter": false,
|
|
8410
|
-
"setter": false
|
|
8411
|
-
},
|
|
8412
8383
|
{
|
|
8413
8384
|
"name": "label",
|
|
8414
8385
|
"type": "string",
|
|
@@ -9129,7 +9100,7 @@
|
|
|
9129
9100
|
"filePath": "src/components/lmvz-tab/lmvz-tab.tsx",
|
|
9130
9101
|
"encapsulation": "shadow",
|
|
9131
9102
|
"tag": "lmvz-tab",
|
|
9132
|
-
"readme": "# lmvz-tab\n\nThe `lmvz-tab` is the individual tab trigger primitive. It must be used as a direct child of `lmvz-tabs`, which owns selection state, ARIA semantics (`tablist`/`tab`/`tabpanel`), keyboard management, and roving `tabindex`.\n\n## Usage\n\n```html\n<lmvz-tabs value=\"home\">\n <lmvz-tab value=\"home\">Home</lmvz-tab>\n <lmvz-tab value=\"profile\">Profile</lmvz-tab>\n <lmvz-tab value=\"settings\" disabled>Settings</lmvz-tab>\n</lmvz-tabs>\n```\n\n### With media slot (icon above label)\n\n```html\n<lmvz-tab value=\"home\">\n <lmvz-icon slot=\"media\" name=\"home\" aria-hidden=\"true\"></lmvz-icon>\n Home\n</lmvz-tab>\n```\n\n> **Icon-only tabs**: When no visible label is provided, supply an `aria-label` on the `lmvz-tab` element itself to maintain accessibility.\n\n## Visual states\n\n| State | Description |\n| -------- | --------------------------------------------------------------------------- |\n| Default | Neutral interactive surface; hidden selection indicator. |\n| Selected | Active-tinted container; active-colored text; full-width 4 px gradient bar at bottom (horizontal) or inline-start (vertical). |\n| Disabled | Reduced opacity; non-interactive. Set by consumer via `disabled` attribute. |\n| Focus | DS-style outline ring, distinct from the selection indicator. |\n\n## Orientation\n\nThe `vertical` attribute is set automatically by `lmvz-tabs` when `orientation=\"vertical\"`. When vertical, the selection indicator bar moves from the bottom edge to the inline-start edge of the button.\n",
|
|
9103
|
+
"readme": "# lmvz-tab\n\nThe `lmvz-tab` is the individual tab trigger primitive. It must be used as a direct child of `lmvz-tabs`, which owns selection state, ARIA semantics (`tablist`/`tab`/`tabpanel`), keyboard management, and roving `tabindex`.\n\n## Usage\n\n```html\n<lmvz-tabs value=\"home\">\n <lmvz-tab value=\"home\">Home</lmvz-tab>\n <lmvz-tab value=\"profile\">Profile</lmvz-tab>\n <lmvz-tab value=\"settings\" disabled>Settings</lmvz-tab>\n</lmvz-tabs>\n```\n\n### Linking to a panel by ID\n\nUse the `panel` attribute to explicitly link a tab to a panel by `id`. This is useful when DOM order does not match logical tab/panel pairing.\n\n```html\n<lmvz-tabs value=\"home\">\n <!-- Tabs in DOM order: home, profile, settings -->\n <lmvz-tab value=\"home\" panel=\"home-content\">Home</lmvz-tab>\n <lmvz-tab value=\"profile\" panel=\"profile-content\">Profile</lmvz-tab>\n <lmvz-tab value=\"settings\" panel=\"settings-content\" disabled>Settings</lmvz-tab>\n\n <!-- Panels in arbitrary order: profile, home, settings -->\n <div slot=\"panels\" id=\"profile-content\" role=\"tabpanel\">Profile content</div>\n <div slot=\"panels\" id=\"home-content\" role=\"tabpanel\">Home content</div>\n <div slot=\"panels\" id=\"settings-content\" role=\"tabpanel\">Settings content</div>\n</lmvz-tabs>\n```\n\nWhen `panel` is omitted, `lmvz-tabs` falls back to positional pairing: the first tab pairs with the first panel, the second tab with the second panel, and so on.\n\n### With media slot (icon above label)\n\n```html\n<lmvz-tab value=\"home\">\n <lmvz-icon slot=\"media\" name=\"home\" aria-hidden=\"true\"></lmvz-icon>\n Home\n</lmvz-tab>\n```\n\n> **Icon-only tabs**: When no visible label is provided, supply an `aria-label` on the `lmvz-tab` element itself to maintain accessibility.\n\n## Visual states\n\n| State | Description |\n| -------- | --------------------------------------------------------------------------- |\n| Default | Neutral interactive surface; hidden selection indicator. |\n| Selected | Active-tinted container; active-colored text; full-width 4 px gradient bar at bottom (horizontal) or inline-start (vertical). |\n| Disabled | Reduced opacity; non-interactive. Set by consumer via `disabled` attribute. |\n| Focus | DS-style outline ring, distinct from the selection indicator. |\n\n## Orientation\n\nThe `vertical` attribute is set automatically by `lmvz-tabs` when `orientation=\"vertical\"`. When vertical, the selection indicator bar moves from the bottom edge to the inline-start edge of the button.\n",
|
|
9133
9104
|
"docs": "The tab trigger primitive. Must be used as a direct child of `lmvz-tabs`.\n\nSelection state, ARIA semantics (tablist/tab/tabpanel), keyboard management,\nand roving tabindex are all owned by the parent `lmvz-tabs` component.",
|
|
9134
9105
|
"docsTags": [
|
|
9135
9106
|
{
|
|
@@ -9180,6 +9151,32 @@
|
|
|
9180
9151
|
"getter": false,
|
|
9181
9152
|
"setter": false
|
|
9182
9153
|
},
|
|
9154
|
+
{
|
|
9155
|
+
"name": "panel",
|
|
9156
|
+
"type": "string | undefined",
|
|
9157
|
+
"complexType": {
|
|
9158
|
+
"original": "string",
|
|
9159
|
+
"resolved": "string | undefined",
|
|
9160
|
+
"references": {}
|
|
9161
|
+
},
|
|
9162
|
+
"mutable": false,
|
|
9163
|
+
"attr": "panel",
|
|
9164
|
+
"reflectToAttr": true,
|
|
9165
|
+
"docs": "The `id` of the target `lmvz-tab-panel` this tab controls.\nWhen omitted, pairing falls back to DOM position.",
|
|
9166
|
+
"docsTags": [],
|
|
9167
|
+
"values": [
|
|
9168
|
+
{
|
|
9169
|
+
"type": "string"
|
|
9170
|
+
},
|
|
9171
|
+
{
|
|
9172
|
+
"type": "undefined"
|
|
9173
|
+
}
|
|
9174
|
+
],
|
|
9175
|
+
"optional": true,
|
|
9176
|
+
"required": false,
|
|
9177
|
+
"getter": false,
|
|
9178
|
+
"setter": false
|
|
9179
|
+
},
|
|
9183
9180
|
{
|
|
9184
9181
|
"name": "selected",
|
|
9185
9182
|
"type": "boolean",
|
|
@@ -9231,35 +9228,6 @@
|
|
|
9231
9228
|
"required": true,
|
|
9232
9229
|
"getter": false,
|
|
9233
9230
|
"setter": false
|
|
9234
|
-
},
|
|
9235
|
-
{
|
|
9236
|
-
"name": "vertical",
|
|
9237
|
-
"type": "boolean",
|
|
9238
|
-
"complexType": {
|
|
9239
|
-
"original": "boolean",
|
|
9240
|
-
"resolved": "boolean",
|
|
9241
|
-
"references": {}
|
|
9242
|
-
},
|
|
9243
|
-
"mutable": false,
|
|
9244
|
-
"attr": "vertical",
|
|
9245
|
-
"reflectToAttr": true,
|
|
9246
|
-
"docs": "Vertical orientation context.\nSet by the parent `lmvz-tabs` when `orientation=\"vertical\"` — do not set manually.\nWhen true the selection indicator moves to the inline-start edge.",
|
|
9247
|
-
"docsTags": [
|
|
9248
|
-
{
|
|
9249
|
-
"name": "default",
|
|
9250
|
-
"text": "false"
|
|
9251
|
-
}
|
|
9252
|
-
],
|
|
9253
|
-
"default": "false",
|
|
9254
|
-
"values": [
|
|
9255
|
-
{
|
|
9256
|
-
"type": "boolean"
|
|
9257
|
-
}
|
|
9258
|
-
],
|
|
9259
|
-
"optional": false,
|
|
9260
|
-
"required": false,
|
|
9261
|
-
"getter": false,
|
|
9262
|
-
"setter": false
|
|
9263
9231
|
}
|
|
9264
9232
|
],
|
|
9265
9233
|
"methods": [],
|
|
@@ -9295,8 +9263,8 @@
|
|
|
9295
9263
|
"filePath": "src/components/lmvz-tabs/lmvz-tabs.tsx",
|
|
9296
9264
|
"encapsulation": "shadow",
|
|
9297
9265
|
"tag": "lmvz-tabs",
|
|
9298
|
-
"readme": "# lmvz-tabs\n\n`lmvz-tabs` is the WAI-ARIA Tabs pattern owner. It renders a `tablist` containing `lmvz-tab` trigger children and links them to consumer-authored panel elements via `aria-controls` / `aria-labelledby`. Selection state, keyboard management (roving `tabindex`, directional focus, manual activation), disabled-tab skipping, and overflow behaviour are all owned here.\n\n## Usage\n\n```html\n<lmvz-tabs value=\"home\" id=\"my-tabs\">\n <lmvz-tab value=\"home\">Home</lmvz-tab>\n <lmvz-tab value=\"profile\">Profile</lmvz-tab>\n <lmvz-tab value=\"settings\" disabled>Settings</lmvz-tab>\n\n <div slot=\"panels\" role=\"tabpanel\" id=\"panel-home\">Home content</div>\n <div slot=\"panels\" role=\"tabpanel\" id=\"panel-profile\" hidden>Profile content</div>\n <div slot=\"panels\" role=\"tabpanel\" id=\"panel-settings\" hidden>Settings content</div>\n</lmvz-tabs>\n```\n\n### Panels — slotted content model\n\nPanels are **consumer-authored** light-DOM elements placed in the `panels` slot. The component does **not** own or render a `lmvz-tab-panel` primitive — consumers supply any element they like (a `<div>`, a custom element, a route outlet, …).\n\n`lmvz-tabs`
|
|
9299
|
-
"docs": "The semantics and state owner for the WAI-ARIA tabs pattern.\n\n`lmvz-tabs` owns:\n- `tablist` / `tab` / `tabpanel` ARIA semantics\n- Selected-value state and manual activation (`Enter`, `Space`, click)\n- Roving `tabindex` via `DirectionalFocusController`\n- Horizontal scroll overflow (horizontal mode only)\n- Disabled-tab skipping and nearest-enabled fallback\n- Child registration and panel linkage via `aria-controls` / `aria-labelledby`\n\nPanels are consumer-authored light-DOM elements.
|
|
9266
|
+
"readme": "# lmvz-tabs\n\n`lmvz-tabs` is the WAI-ARIA Tabs pattern owner. It renders a `tablist` containing `lmvz-tab` trigger children and links them to consumer-authored panel elements via `aria-controls` / `aria-labelledby`. Selection state, keyboard management (roving `tabindex`, directional focus, manual activation), disabled-tab skipping, and overflow behaviour are all owned here.\n\n## Usage\n\n```html\n<lmvz-tabs value=\"home\" id=\"my-tabs\">\n <lmvz-tab value=\"home\">Home</lmvz-tab>\n <lmvz-tab value=\"profile\">Profile</lmvz-tab>\n <lmvz-tab value=\"settings\" disabled>Settings</lmvz-tab>\n\n <div slot=\"panels\" role=\"tabpanel\" id=\"panel-home\">Home content</div>\n <div slot=\"panels\" role=\"tabpanel\" id=\"panel-profile\" hidden>Profile content</div>\n <div slot=\"panels\" role=\"tabpanel\" id=\"panel-settings\" hidden>Settings content</div>\n</lmvz-tabs>\n```\n\n### Panels — slotted content model\n\nPanels are **consumer-authored** light-DOM elements placed in the `panels` slot. The component does **not** own or render a `lmvz-tab-panel` primitive — consumers supply any element they like (a `<div>`, a custom element, a route outlet, …).\n\n`lmvz-tabs` pairs each tab to its panel using one of two strategies:\n\n1. **ID-based linking (preferred):** Set a `panel` attribute on an `lmvz-tab` equal to the target panel's `id`. `lmvz-tabs` matches the tab to the panel by that `id`, regardless of DOM order.\n2. **Positional fallback:** If a tab omits the `panel` attribute, `lmvz-tabs` falls back to positional pairing: tab N is paired with panel N (by DOM order).\n\nFor each paired tab/panel, `lmvz-tabs`:\n- Sets `aria-controls=\"<panelId>\"` on the tab button.\n- Sets `aria-labelledby=\"<tabId>\"` and `role=\"tabpanel\"` on the panel element.\n- Automatically manages panel visibility by toggling the `hidden` attribute based on the active tab.\n\n**Unresolved `panel` reference:** If a tab's `panel` attribute references a non-existent `id`, that tab falls back to positional pairing for that single tab.\n\n#### Example: ID-based linking (order-independent)\n\n```html\n<lmvz-tabs value=\"home\">\n <!-- Tabs explicitly link to panels via panel=\"id\" -->\n <lmvz-tab value=\"home\" panel=\"home-panel\">Home</lmvz-tab>\n <lmvz-tab value=\"profile\" panel=\"profile-panel\">Profile</lmvz-tab>\n <lmvz-tab value=\"settings\" panel=\"settings-panel\">Settings</lmvz-tab>\n\n <!-- Panels can be in any order -->\n <div slot=\"panels\" id=\"profile-panel\" role=\"tabpanel\">Profile content</div>\n <div slot=\"panels\" id=\"home-panel\" role=\"tabpanel\">Home content</div>\n <div slot=\"panels\" id=\"settings-panel\" role=\"tabpanel\" hidden>Settings content</div>\n</lmvz-tabs>\n```\n\nFor an interactive demonstration of order-independent tab/panel linking, see the **LinkedByPanelId** story in Storybook.\n\n### Reacting to tab changes\n\nPanel visibility is automatically managed by `lmvz-tabs` — the active panel is shown and all others are hidden via the `hidden` attribute. If you need to perform custom logic when a tab changes, listen to the `lmvzChange` event:\n\n```ts\nconst tabs = document.querySelector('lmvz-tabs');\n\ntabs.addEventListener('lmvzChange', (event) => {\n const { value } = event.detail; // the newly-activated tab value\n // perform custom logic (e.g. analytics, scroll, focus management)\n});\n```\n\n## Keyboard interaction\n\n| Key | Behaviour |\n| --------------------- | -------------------------------------------------------- |\n| `←` / `→` | Move focus to previous / next enabled tab. |\n| `Home` | Move focus to the first enabled tab. |\n| `End` | Move focus to the last enabled tab. |\n| `Enter` / `Space` | Activate the currently focused tab (manual activation). |\n| `Tab` | Leave the tab list; focus moves to the active panel. |\n\nDisabled tabs are skipped during arrow-key navigation and cannot be activated.\n\n## Disabled-tab fallback\n\nWhen the selected tab becomes disabled at runtime, `lmvz-tabs` automatically activates the nearest enabled tab (preferring the next sibling, then the previous). If no enabled tab exists the selection value is left unchanged.\n",
|
|
9267
|
+
"docs": "The semantics and state owner for the WAI-ARIA tabs pattern.\n\n`lmvz-tabs` owns:\n- `tablist` / `tab` / `tabpanel` ARIA semantics\n- Selected-value state and manual activation (`Enter`, `Space`, click)\n- Roving `tabindex` via `DirectionalFocusController`\n- Horizontal scroll overflow (horizontal mode only)\n- Disabled-tab skipping and nearest-enabled fallback\n- Child registration and panel linkage via `aria-controls` / `aria-labelledby`\n\nPanels are consumer-authored light-DOM elements. Each `lmvz-tab` can declare\na `panel` attribute whose value matches the target `lmvz-tab-panel`'s `id`,\nresolving the pairing explicitly. Tabs without a `panel` attribute fall back\nto positional pairing (tab N pairs with panel N).",
|
|
9300
9268
|
"docsTags": [
|
|
9301
9269
|
{
|
|
9302
9270
|
"name": "slot",
|
|
@@ -9321,40 +9289,6 @@
|
|
|
9321
9289
|
],
|
|
9322
9290
|
"usage": {},
|
|
9323
9291
|
"props": [
|
|
9324
|
-
{
|
|
9325
|
-
"name": "orientation",
|
|
9326
|
-
"type": "\"horizontal\" | \"vertical\"",
|
|
9327
|
-
"complexType": {
|
|
9328
|
-
"original": "'horizontal' | 'vertical'",
|
|
9329
|
-
"resolved": "\"horizontal\" | \"vertical\"",
|
|
9330
|
-
"references": {}
|
|
9331
|
-
},
|
|
9332
|
-
"mutable": true,
|
|
9333
|
-
"attr": "orientation",
|
|
9334
|
-
"reflectToAttr": true,
|
|
9335
|
-
"docs": "Layout and keyboard-navigation orientation.",
|
|
9336
|
-
"docsTags": [
|
|
9337
|
-
{
|
|
9338
|
-
"name": "default",
|
|
9339
|
-
"text": "'horizontal'"
|
|
9340
|
-
}
|
|
9341
|
-
],
|
|
9342
|
-
"default": "'horizontal'",
|
|
9343
|
-
"values": [
|
|
9344
|
-
{
|
|
9345
|
-
"value": "horizontal",
|
|
9346
|
-
"type": "string"
|
|
9347
|
-
},
|
|
9348
|
-
{
|
|
9349
|
-
"value": "vertical",
|
|
9350
|
-
"type": "string"
|
|
9351
|
-
}
|
|
9352
|
-
],
|
|
9353
|
-
"optional": false,
|
|
9354
|
-
"required": false,
|
|
9355
|
-
"getter": false,
|
|
9356
|
-
"setter": false
|
|
9357
|
-
},
|
|
9358
9292
|
{
|
|
9359
9293
|
"name": "value",
|
|
9360
9294
|
"type": "string",
|
|
@@ -9517,7 +9451,13 @@
|
|
|
9517
9451
|
"docsTags": []
|
|
9518
9452
|
}
|
|
9519
9453
|
],
|
|
9520
|
-
"listeners": [
|
|
9454
|
+
"listeners": [
|
|
9455
|
+
{
|
|
9456
|
+
"event": "slotchange",
|
|
9457
|
+
"capture": false,
|
|
9458
|
+
"passive": false
|
|
9459
|
+
}
|
|
9460
|
+
],
|
|
9521
9461
|
"styles": [],
|
|
9522
9462
|
"slots": [
|
|
9523
9463
|
{
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lmvz-ds/components",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.40.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "The components of the design system",
|
|
7
7
|
"author": "Patrick Nemenz <patrick.nemenz@adesso.at>",
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
"linkDirectory": false
|
|
11
11
|
},
|
|
12
12
|
"exports": {
|
|
13
|
+
"./index.js": "./index.js",
|
|
13
14
|
".": {
|
|
14
15
|
"types": "./components/index.d.ts",
|
|
15
16
|
"import": "./components/index.js"
|
|
@@ -1,2 +1,8 @@
|
|
|
1
|
+
import { SnackbarController } from './snackbar-controller';
|
|
1
2
|
export { SnackbarController } from './snackbar-controller';
|
|
2
3
|
export type { SnackbarDismissReason, SnackbarHandle, SnackbarOptions, SnackbarPriority, SnackbarStatus } from './snackbar-controller';
|
|
4
|
+
declare global {
|
|
5
|
+
interface LmvzApi {
|
|
6
|
+
SnackbarController?: typeof SnackbarController;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
@@ -6,9 +6,9 @@ export declare class LmvzTabs extends ReactiveControllerHost implements Directio
|
|
|
6
6
|
private readonly instanceId;
|
|
7
7
|
private tabSlotEl?;
|
|
8
8
|
private panelSlotEl?;
|
|
9
|
-
private
|
|
9
|
+
private tablistEl?;
|
|
10
|
+
private readonly focusController;
|
|
10
11
|
value: string;
|
|
11
|
-
orientation: 'horizontal' | 'vertical';
|
|
12
12
|
lmvzChange: EventEmitter<{
|
|
13
13
|
value: string;
|
|
14
14
|
}>;
|
|
@@ -17,21 +17,21 @@ export declare class LmvzTabs extends ReactiveControllerHost implements Directio
|
|
|
17
17
|
componentWillLoad(): void;
|
|
18
18
|
componentDidLoad(): void;
|
|
19
19
|
disconnectedCallback(): void;
|
|
20
|
+
handleSlotChangeEvent(): void;
|
|
20
21
|
handleValueChange(newValue: string): void;
|
|
21
|
-
handleOrientationChange(): void;
|
|
22
22
|
initFocus(): Promise<void>;
|
|
23
23
|
activateTab(value: string): Promise<void>;
|
|
24
24
|
getTabElements(): Promise<HTMLElement[]>;
|
|
25
25
|
setTabPanelIds(pairs: Array<[string, string]>): Promise<void>;
|
|
26
26
|
private get slottedTabs();
|
|
27
27
|
private get slottedPanels();
|
|
28
|
-
private
|
|
29
|
-
private
|
|
30
|
-
private
|
|
28
|
+
private handleTabSlotChange;
|
|
29
|
+
private handlePanelSlotChange;
|
|
30
|
+
private handleTabReady;
|
|
31
31
|
private updateIconTabsAttr;
|
|
32
32
|
private syncFocusTargets;
|
|
33
|
-
private
|
|
34
|
-
private
|
|
33
|
+
private resolvePanelForTab;
|
|
34
|
+
private warnIfMixedPanelLinking;
|
|
35
35
|
private wireAriaIds;
|
|
36
36
|
private applySelection;
|
|
37
37
|
private isTabDisabled;
|
package/types/components.d.ts
CHANGED
|
@@ -785,11 +785,6 @@ export declare namespace Components {
|
|
|
785
785
|
* Helper text displayed below the select field.
|
|
786
786
|
*/
|
|
787
787
|
"helperText"?: string;
|
|
788
|
-
/**
|
|
789
|
-
* Whether the select has an active filter or selection that should be visually distinguished (e.g. a filter chip is applied). When `true`: - The host attribute `highlighted` is present (CSS: `:host([highlighted])`). - The host attribute `data-highlighted="true"` is set for assistive-technology consumers that observe data attributes. When `false`, `data-highlighted` is set to `"false"`. Note: `aria-pressed` is intentionally not used here; it is reserved for toggle-button roles. `aria-selected` is reserved for this component's own `role="option"` elements. The `data-highlighted` attribute provides the accessible contract for this state.
|
|
790
|
-
* @default false
|
|
791
|
-
*/
|
|
792
|
-
"highlighted": boolean;
|
|
793
788
|
/**
|
|
794
789
|
* Label text displayed as a placeholder when no value is selected, and floated above the trigger when a value is present.
|
|
795
790
|
*/
|
|
@@ -871,6 +866,10 @@ export declare namespace Components {
|
|
|
871
866
|
* @default false
|
|
872
867
|
*/
|
|
873
868
|
"disabled": boolean;
|
|
869
|
+
/**
|
|
870
|
+
* The `id` of the target `lmvz-tab-panel` this tab controls. When omitted, pairing falls back to DOM position.
|
|
871
|
+
*/
|
|
872
|
+
"panel"?: string;
|
|
874
873
|
/**
|
|
875
874
|
* Whether this tab is currently selected. Set by the parent `lmvz-tabs` component — do not set manually.
|
|
876
875
|
* @default false
|
|
@@ -880,11 +879,6 @@ export declare namespace Components {
|
|
|
880
879
|
* Unique value that identifies this tab within its `lmvz-tabs` parent. The parent uses this to track the selected tab.
|
|
881
880
|
*/
|
|
882
881
|
"value": string;
|
|
883
|
-
/**
|
|
884
|
-
* Vertical orientation context. Set by the parent `lmvz-tabs` when `orientation="vertical"` — do not set manually. When true the selection indicator moves to the inline-start edge.
|
|
885
|
-
* @default false
|
|
886
|
-
*/
|
|
887
|
-
"vertical": boolean;
|
|
888
882
|
}
|
|
889
883
|
/**
|
|
890
884
|
* The semantics and state owner for the WAI-ARIA tabs pattern.
|
|
@@ -895,9 +889,10 @@ export declare namespace Components {
|
|
|
895
889
|
* - Horizontal scroll overflow (horizontal mode only)
|
|
896
890
|
* - Disabled-tab skipping and nearest-enabled fallback
|
|
897
891
|
* - Child registration and panel linkage via `aria-controls` / `aria-labelledby`
|
|
898
|
-
* Panels are consumer-authored light-DOM elements.
|
|
899
|
-
*
|
|
900
|
-
*
|
|
892
|
+
* Panels are consumer-authored light-DOM elements. Each `lmvz-tab` can declare
|
|
893
|
+
* a `panel` attribute whose value matches the target `lmvz-tab-panel`'s `id`,
|
|
894
|
+
* resolving the pairing explicitly. Tabs without a `panel` attribute fall back
|
|
895
|
+
* to positional pairing (tab N pairs with panel N).
|
|
901
896
|
* @event lmvzChange - Fired when a tab is activated. Detail: `{ value: string }`.
|
|
902
897
|
* @example ```html
|
|
903
898
|
* <lmvz-tabs value="home">
|
|
@@ -921,11 +916,6 @@ export declare namespace Components {
|
|
|
921
916
|
* Programmatically set focus to the first managed element.
|
|
922
917
|
*/
|
|
923
918
|
"initFocus": () => Promise<void>;
|
|
924
|
-
/**
|
|
925
|
-
* Layout and keyboard-navigation orientation.
|
|
926
|
-
* @default 'horizontal'
|
|
927
|
-
*/
|
|
928
|
-
"orientation": 'horizontal' | 'vertical';
|
|
929
919
|
/**
|
|
930
920
|
* Wires `aria-controls` on each tab and `aria-labelledby` on each panel using the provided ordered array of `[tabId, panelId]` pairs. Callers only need this for explicit control; `lmvz-tabs` wires positional pairs automatically on `slotchange`.
|
|
931
921
|
*/
|
|
@@ -1791,11 +1781,6 @@ export declare namespace JSX {
|
|
|
1791
1781
|
* Helper text displayed below the select field.
|
|
1792
1782
|
*/
|
|
1793
1783
|
"helperText"?: string;
|
|
1794
|
-
/**
|
|
1795
|
-
* Whether the select has an active filter or selection that should be visually distinguished (e.g. a filter chip is applied). When `true`: - The host attribute `highlighted` is present (CSS: `:host([highlighted])`). - The host attribute `data-highlighted="true"` is set for assistive-technology consumers that observe data attributes. When `false`, `data-highlighted` is set to `"false"`. Note: `aria-pressed` is intentionally not used here; it is reserved for toggle-button roles. `aria-selected` is reserved for this component's own `role="option"` elements. The `data-highlighted` attribute provides the accessible contract for this state.
|
|
1796
|
-
* @default false
|
|
1797
|
-
*/
|
|
1798
|
-
"highlighted"?: boolean;
|
|
1799
1784
|
/**
|
|
1800
1785
|
* Label text displayed as a placeholder when no value is selected, and floated above the trigger when a value is present.
|
|
1801
1786
|
*/
|
|
@@ -1876,6 +1861,10 @@ export declare namespace JSX {
|
|
|
1876
1861
|
* @default false
|
|
1877
1862
|
*/
|
|
1878
1863
|
"disabled"?: boolean;
|
|
1864
|
+
/**
|
|
1865
|
+
* The `id` of the target `lmvz-tab-panel` this tab controls. When omitted, pairing falls back to DOM position.
|
|
1866
|
+
*/
|
|
1867
|
+
"panel"?: string;
|
|
1879
1868
|
/**
|
|
1880
1869
|
* Whether this tab is currently selected. Set by the parent `lmvz-tabs` component — do not set manually.
|
|
1881
1870
|
* @default false
|
|
@@ -1885,11 +1874,6 @@ export declare namespace JSX {
|
|
|
1885
1874
|
* Unique value that identifies this tab within its `lmvz-tabs` parent. The parent uses this to track the selected tab.
|
|
1886
1875
|
*/
|
|
1887
1876
|
"value": string;
|
|
1888
|
-
/**
|
|
1889
|
-
* Vertical orientation context. Set by the parent `lmvz-tabs` when `orientation="vertical"` — do not set manually. When true the selection indicator moves to the inline-start edge.
|
|
1890
|
-
* @default false
|
|
1891
|
-
*/
|
|
1892
|
-
"vertical"?: boolean;
|
|
1893
1877
|
}
|
|
1894
1878
|
/**
|
|
1895
1879
|
* The semantics and state owner for the WAI-ARIA tabs pattern.
|
|
@@ -1900,9 +1884,10 @@ export declare namespace JSX {
|
|
|
1900
1884
|
* - Horizontal scroll overflow (horizontal mode only)
|
|
1901
1885
|
* - Disabled-tab skipping and nearest-enabled fallback
|
|
1902
1886
|
* - Child registration and panel linkage via `aria-controls` / `aria-labelledby`
|
|
1903
|
-
* Panels are consumer-authored light-DOM elements.
|
|
1904
|
-
*
|
|
1905
|
-
*
|
|
1887
|
+
* Panels are consumer-authored light-DOM elements. Each `lmvz-tab` can declare
|
|
1888
|
+
* a `panel` attribute whose value matches the target `lmvz-tab-panel`'s `id`,
|
|
1889
|
+
* resolving the pairing explicitly. Tabs without a `panel` attribute fall back
|
|
1890
|
+
* to positional pairing (tab N pairs with panel N).
|
|
1906
1891
|
* @event lmvzChange - Fired when a tab is activated. Detail: `{ value: string }`.
|
|
1907
1892
|
* @example ```html
|
|
1908
1893
|
* <lmvz-tabs value="home">
|
|
@@ -1918,11 +1903,6 @@ export declare namespace JSX {
|
|
|
1918
1903
|
* Emitted when a tab is activated. Detail: `{ value: string }`.
|
|
1919
1904
|
*/
|
|
1920
1905
|
"onLmvzChange"?: (event: LmvzTabsCustomEvent<{ value: string }>) => void;
|
|
1921
|
-
/**
|
|
1922
|
-
* Layout and keyboard-navigation orientation.
|
|
1923
|
-
* @default 'horizontal'
|
|
1924
|
-
*/
|
|
1925
|
-
"orientation"?: 'horizontal' | 'vertical';
|
|
1926
1906
|
/**
|
|
1927
1907
|
* The `value` of the currently selected tab.
|
|
1928
1908
|
*/
|
|
@@ -2126,7 +2106,6 @@ export declare namespace JSX {
|
|
|
2126
2106
|
"required": boolean;
|
|
2127
2107
|
"name": string;
|
|
2128
2108
|
"size": Select.Size;
|
|
2129
|
-
"highlighted": boolean;
|
|
2130
2109
|
}
|
|
2131
2110
|
export interface LmvzSnackbarAttributes {
|
|
2132
2111
|
"status": Snackbar.Status;
|
|
@@ -2143,11 +2122,10 @@ export declare namespace JSX {
|
|
|
2143
2122
|
"value": string;
|
|
2144
2123
|
"disabled": boolean;
|
|
2145
2124
|
"selected": boolean;
|
|
2146
|
-
"
|
|
2125
|
+
"panel": string;
|
|
2147
2126
|
}
|
|
2148
2127
|
export interface LmvzTabsAttributes {
|
|
2149
2128
|
"value": string;
|
|
2150
|
-
"orientation": 'horizontal' | 'vertical';
|
|
2151
2129
|
}
|
|
2152
2130
|
export interface LmvzToggleAttributes {
|
|
2153
2131
|
"label": string;
|
package/types/index.d.ts
CHANGED
|
@@ -10,17 +10,17 @@ export type DirectionalFocusHost = FocusHostExtensions & {
|
|
|
10
10
|
type FocusHostExtensions = {
|
|
11
11
|
initFocus: DirectionalFocusController['initFocus'];
|
|
12
12
|
};
|
|
13
|
-
export declare function isFocusControllerHost(el: HTMLElement): el is HTMLElement & FocusHostExtensions;
|
|
14
13
|
export type DirectionalFocusReceiver = {
|
|
15
14
|
resolveFocusableElement(): HTMLElement | undefined;
|
|
16
15
|
};
|
|
17
16
|
export type DirectionalFocusOrientation = 'horizontal' | 'vertical' | 'both';
|
|
18
17
|
export type DirectionalFocusControllerConfig = {
|
|
19
|
-
orientation
|
|
20
|
-
enableHomeAndEnd
|
|
21
|
-
manageTabIndex
|
|
18
|
+
orientation: DirectionalFocusOrientation;
|
|
19
|
+
enableHomeAndEnd: boolean;
|
|
20
|
+
manageTabIndex: boolean;
|
|
22
21
|
onFocusTargetChange?: (element: HTMLElement) => void;
|
|
23
22
|
isFocusableElement?: (element: HTMLElement) => boolean;
|
|
23
|
+
listenerTarget?: HTMLElement;
|
|
24
24
|
};
|
|
25
25
|
export declare class DirectionalFocusController implements ReactiveController {
|
|
26
26
|
private readonly host;
|
|
@@ -30,6 +30,8 @@ export declare class DirectionalFocusController implements ReactiveController {
|
|
|
30
30
|
constructor(host: DirectionalFocusHost, config?: DirectionalFocusControllerConfig);
|
|
31
31
|
hostConnected(): void;
|
|
32
32
|
hostDisconnected(): void;
|
|
33
|
+
updateListenerTarget(listenerTarget: HTMLElement): void;
|
|
34
|
+
private getListenerTarget;
|
|
33
35
|
updateElements(elements: Element[]): void;
|
|
34
36
|
setCurrentElement(element: Element | undefined | null): void;
|
|
35
37
|
initFocus(): Promise<void>;
|
|
@@ -44,6 +46,6 @@ export declare class DirectionalFocusController implements ReactiveController {
|
|
|
44
46
|
private applyFocusTarget;
|
|
45
47
|
private canMoveFocusTo;
|
|
46
48
|
}
|
|
47
|
-
export
|
|
48
|
-
export
|
|
49
|
-
export {
|
|
49
|
+
export declare function isFocusControllerHost(el: HTMLElement): el is HTMLElement & FocusHostExtensions;
|
|
50
|
+
export declare function isDirectionalFocusReceiver(el: HTMLElement): el is HTMLElement & DirectionalFocusReceiver;
|
|
51
|
+
export {};
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
import { typedIconFromSet } from './icons.js';
|
|
1
2
|
export type { IconSetNameMap } from '@lmvz-ds/lib-icon-api';
|
|
2
3
|
export { getRegisteredIconProvider, registerIconProvider } from './icons-registry.js';
|
|
3
4
|
export { typedIconFromSet } from './icons.js';
|
|
5
|
+
declare global {
|
|
6
|
+
interface LmvzApi {
|
|
7
|
+
typedIconFromSet?: typeof typedIconFromSet;
|
|
8
|
+
}
|
|
9
|
+
}
|
package/components/p-CgGqXTxQ.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{p as i,h as e,d as o,t as n}from"./p-DbBJxuBm.js";import{t,e as s,p as c}from"./p-DjvtQE7c.js";import{A as r}from"./p-sACbyedu.js";import{R as a}from"./p-DXFoXTse.js";const l=Symbol.for("LMVZ__iconProviderRegistry"),m={};function v(){return"undefined"==typeof window?m:window[l]??(window[l]={})}function d(i,e){const o=v(),n=i;Object.prototype.hasOwnProperty.call(o,n)&&console.warn(`Icon provider with name "${n}" is already registered. Overwriting existing provider.`),o[n]=e}function h(i){const e=v();if(i)return e[i];const o=Object.keys(e);if(0===o.length)return;o.length>1&&console.warn(`Multiple icon providers registered (${o.join(", ")}). Using the first one: "${o[0]}".`);const n=o[0];return n?e[n]:void 0}function p(i,e){return{iconset:i,icon:e}}const z=i(class extends a{intersectionObserver;ariaValidationController=new r(this);get el(){return this}validationEl;icon;weight="medium";size="md";iconset;iconData;visible=!1;ariaLabel;get ariaHidden(){return!this.ariaLabel}constructor(i){super(!1),!1!==i&&this.__registerHost(),this.addController(this.ariaValidationController)}connectedCallback(){this.waitUntilVisible((()=>{this.visible=!0,this.loadIconPathData()})),super.connectedCallback()}disconnectedCallback(){this.intersectionObserver&&"function"==typeof this.intersectionObserver.disconnect&&this.intersectionObserver.disconnect(),this.intersectionObserver=void 0,super.disconnectedCallback()}async loadIconPathData(){const{icon:i,iconset:e,visible:o}=this;if(!i||!o)return;const n=c(i);this.iconData=n||await async function(i){const{icon:e,iconset:o}=i;return await(async()=>{const i=h(o);if(i)try{const n=await Promise.resolve(i.resolve(e));if(!n?.svg)return void console.warn(`Icon "${e}"${o?` from set "${o}"`:""} not found in provider. Using default icon.`);const s=t(n.svg);if(s)return s}catch(i){return void console.error(`Error resolving icon "${e}" with provider:`,i)}else console.warn(`No icon provider registered. Unable to resolve icon "${e}"${o?` from set "${o}"`:""}. Using default icon.`)})()||(console.error(`Icon "${e}" not found${o?` in set "${o}"`:""}. Using default icon.`),s())}({icon:i,iconset:e})}componentDidRender(){this.validationEl=this.el.querySelector("svg"),this.ariaValidationController.revalidateAria(),super.componentDidRender()}render(){return e(o,{key:"be6032d11399289c3baddd63ebc7d9e1fb98b773",role:"img","aria-hidden":`${this.ariaHidden}`,innerHTML:this.iconData})}waitUntilVisible(i,e=50){"undefined"!=typeof window&&window.IntersectionObserver?(this.intersectionObserver=new IntersectionObserver((e=>{e.some((e=>!!e.isIntersecting&&(this.intersectionObserver&&"function"==typeof this.intersectionObserver.disconnect&&this.intersectionObserver.disconnect(),this.intersectionObserver=void 0,i(),!0)))}),{rootMargin:`${e}px`}),this.intersectionObserver.observe(this.el)):i()}static get watchers(){return{icon:[{loadIconPathData:0}],iconset:[{loadIconPathData:0}]}}static get style(){return".sc-lmvz-icon-h{--lmvz-icon-color:var(--lmvz-component-color, var(--lmvz-semantic-color-on-surface-input-primary, #000000));--lmvz-icon-size:var(--lmvz-component-size, var(--lmvz-component-icon-size-md, clamp(1rem, 0.94rem + 0.26vw, 1.25rem)));display:inline-block;line-height:0;svg{display:block;height:var(--lmvz-icon-size);width:auto}svg path{stroke:var(--lmvz-icon-color);fill:none}}[size='xs'].sc-lmvz-icon-h{svg{--lmvz-icon-size:var(--lmvz-component-icon-size-xs, clamp(0.75rem, 0.72rem + 0.13vw, 0.88rem))}}[size='sm'].sc-lmvz-icon-h{svg{--lmvz-icon-size:var(--lmvz-component-icon-size-sm, clamp(0.88rem, 0.84rem + 0.13vw, 1rem))}}[size='md'].sc-lmvz-icon-h{svg{--lmvz-icon-size:var(--lmvz-component-icon-size-md, clamp(1rem, 0.94rem + 0.26vw, 1.25rem))}}[size='lg'].sc-lmvz-icon-h{svg{--lmvz-icon-size:var(--lmvz-component-icon-size-lg, clamp(1.25rem, 1.19rem + 0.26vw, 1.5rem))}}[size='inherit'].sc-lmvz-icon-h{svg{height:var(--lmvz-component-size, inherit)}}[weight='light'].sc-lmvz-icon-h{svg path{stroke-width:1}}[weight='medium'].sc-lmvz-icon-h{svg path{stroke-width:1.5}}[weight='bold'].sc-lmvz-icon-h{svg path{stroke-width:2}}[weight='filled'].sc-lmvz-icon-h{svg path{stroke-width:2;fill:var(--lmvz-icon-color)}}"}},[514,"lmvz-icon",{icon:[513],weight:[513],size:[513],iconset:[513],ariaLabel:[513,"aria-label"],iconData:[32],visible:[32]},void 0,{icon:[{loadIconPathData:0}],iconset:[{loadIconPathData:0}]}]);function u(){"undefined"!=typeof customElements&&["lmvz-icon"].forEach((i=>{"lmvz-icon"===i&&(customElements.get(n(i))||customElements.define(n(i),z))}))}export{z as L,u as d,h as g,d as r,p as t}
|
package/components/p-D3wobLRi.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{p as t,c as o,h as r,d as e,t as n}from"./p-DbBJxuBm.js";import{c as a}from"./p-BfTCfPZ1.js";import{A as l}from"./p-sACbyedu.js";import{E as i}from"./p-CcP_sfo8.js";import{a as m,l as v}from"./p-BhALzK62.js";import{R as d}from"./p-DXFoXTse.js";const u=t(class extends d{get el(){return this}validationEl;inheritedAttributes={};formEl=null;formButtonEl=null;lmvzActivation;ti=0;resolveFocusableElement(){return this.validationEl}scale="default";variant;disabled=!1;type="button";form;formMethod;name;value;buttonRole;constructor(t){super(!1),!1!==t&&this.__registerHost(),this.__attachShadow(),this.lmvzActivation=o(this,"lmvzActivation",7),this.addController(new l(this)),this.addController(new i(this,{localHandler:this.handleClick.bind(this)}))}connectedCallback(){this.inheritedAttributes=m(this.el,["role"]),super.connectedCallback()}disconnectedCallback(){this.formButtonEl?.remove(),this.formButtonEl=null,this.formEl=null,super.disconnectedCallback()}renderHiddenButton(){if("submit"!==this.type)return this.formButtonEl?.remove(),this.formButtonEl=null,void(this.formEl=null);const t=v(this.form,this.el);if(!t)return this.formButtonEl?.remove(),this.formButtonEl=null,void(this.formEl=null);this.formEl=t;const o=this.formButtonEl??document.createElement("button");o.type="submit",o.style.display="none",o.disabled=this.disabled,o.name=this.name??"",o.value=this.value??"",this.formMethod?o.setAttribute("formmethod",this.formMethod):o.removeAttribute("formmethod"),this.formButtonEl!==o&&(this.formButtonEl=o),o.parentElement!==t&&(o.remove(),t.appendChild(o))}submitForm(t){this.formEl&&this.formButtonEl&&(t.preventDefault(),this.formButtonEl.click())}handleClick=t=>{"submit"===this.type&&this.submitForm(t)};render(){return this.renderHiddenButton(),r(e,{key:"eb0ee982f50f1e41b2aa72a0598d739b972cbcdf",role:"presentation"},r("button",{key:"aed6f44f51222e31d5f1deec952c0d81b8f1200a",ref:t=>this.validationEl=t,part:"button",role:this.buttonRole,disabled:this.disabled,type:this.type,class:a(this.variant??"secondary",{[this.scale??""]:!!this.scale,disabled:this.disabled}),...this.inheritedAttributes},r("slot",{key:"2aaedfde3c0d6ebf426f20a8489b22c2a356767e"})))}static get delegatesFocus(){return!0}static get style(){return" @layer lmvz-ds.reset, lmvz-ds.theme, lmvz-ds.components, lmvz-ds.overrides; @layer lmvz-ds.theme { @font-face { font-family: Router; src: local('RouterBook-Regular'), local('Router-Book'), url('/assets/fonts/Router-Book.woff') format('woff'); font-weight: 400; } @font-face { font-family: Router; src: local('RouterMedium-Regular'), local('Router-Medium'), url('/assets/fonts/Router-Medium.woff') format('woff'); font-weight: 500; } @font-face { font-family: Router; src: local('RouterBold-Regular'), local('Router-Bold'), url('/assets/fonts/Router-Bold.woff') format('woff'); font-weight: 700; } } @layer lmvz-ds.reset { body { margin: 0; } h1, h2, h3, h4, h5, h6 { margin: 0; } *[hidden] { display: none !important; } hr { height: 0; border: none; margin: var(--lmvz-dimension-8-4, clamp(0.25rem, 0.19rem + 0.26vw, 0.5rem)) 0; border-top: var(--lmvz-semantic-border-width-default, 1px) solid var(--lmvz-semantic-color-border-subtle, #f0f0f0); } fieldset { border: none; margin: 0; padding: 0; } legend { padding: 0; display: block; } } :host { button { --lmvz-button-background: var(--lmvz-button-background-override, var(--lmvz-semantic-color-int-secondary, #f0f0f0)); --lmvz-button-color: var(--lmvz-button-color-override, var(--lmvz-semantic-color-int-on-secondary, #000000)); --lmvz-button-radius: var(--lmvz-button-radius-override, var(--lmvz-component-input-radius-default, 999px)); --lmvz-button-padding-inline: var(--lmvz-button-padding-inline-override, var(--lmvz-button-padding, var(--lmvz-component-input-padding-md, clamp(0.88rem, 0.84rem + 0.13vw, 1rem)))); --lmvz-button-padding-block: var(--lmvz-button-padding-block-override, var(--lmvz-button-padding, var(--lmvz-component-input-padding-md, clamp(0.88rem, 0.84rem + 0.13vw, 1rem)))); --lmvz-button-gap: var(--lmvz-button-gap-override, var(--lmvz-component-input-gap-md, clamp(0.5rem, 0.44rem + 0.26vw, 0.75rem))); --lmvz-button-min-height: var(--lmvz-button-min-height-override, var(--lmvz-component-input-size-md, clamp(2.5rem, 2.44rem + 0.26vw, 2.75rem))); --lmvz-button-font: var(--lmvz-button-font-override, var(--lmvz-typography-label-md-strong, normal 700 clamp(0.88rem, 0.84rem + 0.13vw, 1rem) / 1.5 Router)); --lmvz-button-border-width: var(--lmvz-button-border-width-override, 0); --lmvz-button-border-color: var(--lmvz-button-border-color-override, transparent); display: inline-flex; align-items: center; justify-content: var(--lmvz-button-content-justification-override, center); gap: var(--lmvz-button-gap); padding-block: var(--lmvz-button-padding-block); padding-inline: var(--lmvz-button-padding-inline); min-height: var(--lmvz-button-min-height); min-width: var(--lmvz-button-min-height); border-radius: var(--lmvz-button-radius); border: var(--lmvz-button-border-width) solid var(--lmvz-button-border-color); background-color: var(--lmvz-button-background); color: var(--lmvz-button-color); cursor: pointer; font: var(--lmvz-button-font); text-decoration: none; white-space: nowrap; transition: background-color 0.15s ease, color 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease; } button > * { font: inherit; color: inherit; } button:focus-visible { outline: var(--lmvz-ds-outline, 1px solid #0e7ab4); outline-offset: var(--lmvz-ds-outline-offset, clamp(0.25rem, 0.19rem + 0.26vw, 0.5rem)); position: relative; z-index: 1; } button:is([disabled], .disabled) { cursor: not-allowed; pointer-events: none; opacity: var(--lmvz-component-input-disabled-opacity, 40%); } button:not([disabled]):hover { --lmvz-button-background: var(--lmvz-button-background-override, var(--lmvz-semantic-color-int-secondary-hover, #e0e0e0)); } button:not([disabled]):active { --lmvz-button-background: var(--lmvz-button-background-override, var(--lmvz-semantic-color-int-secondary-active, #d4d4d4)); } button.primary { --lmvz-button-background: var(--lmvz-button-background-override, var(--lmvz-semantic-color-int-primary, #000000)); --lmvz-button-color: var(--lmvz-button-color-override, var(--lmvz-semantic-color-int-on-primary, #ffffff)); --lmvz-button-border-width: var(--lmvz-button-border-width-override, 0); --lmvz-button-border-color: var(--lmvz-button-border-color-override, transparent); } button.primary:not([disabled], .disabled):hover { --lmvz-button-background: var(--lmvz-button-background-override, var(--lmvz-semantic-color-int-primary-hover, #2e2e2e)); } button.primary:not([disabled], .disabled):active { --lmvz-button-background: var(--lmvz-button-background-override, var(--lmvz-semantic-color-int-primary-active, #545454)); } button.danger { --lmvz-button-background: var(--lmvz-button-background-override, var(--lmvz-semantic-color-int-tertiary, #ffffff)); --lmvz-button-border-color: var(--lmvz-button-border-color-override, transparent); --lmvz-button-color: var(--lmvz-button-color-override, var(--lmvz-semantic-color-status-on-danger, #a31419)); } button.danger:not([disabled], .disabled):hover { --lmvz-button-background: var(--lmvz-button-background-override, var(--lmvz-semantic-color-status-danger, #fbdfe0)); --lmvz-button-color: var(--lmvz-button-color-override, var(--lmvz-semantic-color-status-on-danger, #a31419)); } button.danger:not([disabled], .disabled):active { --lmvz-button-background: var(--lmvz-button-background-override, var(--lmvz-semantic-color-status-on-danger-subtle, #e8454b)); --lmvz-button-color: var(--lmvz-button-color-override, var(--lmvz-semantic-color-status-on-danger, #a31419)); } button.tertiary { --lmvz-button-background: var(--lmvz-button-background-override, var(--lmvz-semantic-color-int-tertiary, #ffffff)); --lmvz-button-color: var(--lmvz-button-color-override, var(--lmvz-semantic-color-int-on-tertiary, #000000)); } button.tertiary:not([disabled], .disabled):hover { --lmvz-button-background: var(--lmvz-button-background-override, var(--lmvz-semantic-color-int-tertiary-hover, #f0f0f0)); --lmvz-button-color: var(--lmvz-button-color-override, var(--lmvz-semantic-color-int-on-tertiary-hover, #000000)); } button.tertiary:not([disabled], .disabled):active { --lmvz-button-background: var(--lmvz-button-background-override, var(--lmvz-semantic-color-int-tertiary-active, #e0e0e0)); --lmvz-button-color: var(--lmvz-button-color-override, var(--lmvz-semantic-color-int-on-tertiary-active, #000000)); } button.small { --lmvz-button-padding-inline: var(--lmvz-button-padding-inline-override, var(--lmvz-component-input-padding-sm, clamp(0.75rem, 0.72rem + 0.13vw, 0.88rem))); --lmvz-button-padding-block: var(--lmvz-button-padding-block-override, var(--lmvz-component-input-padding-sm, clamp(0.75rem, 0.72rem + 0.13vw, 0.88rem))); --lmvz-button-gap: var(--lmvz-button-gap-override, var(--lmvz-component-input-gap-sm, clamp(0.38rem, 0.31rem + 0.26vw, 0.63rem))); --lmvz-button-min-height: var(--lmvz-button-min-height-override, var(--lmvz-component-input-size-sm, clamp(2rem, 1.94rem + 0.26vw, 2.25rem))); --lmvz-button-font: var(--lmvz-button-font-override, var(--lmvz-typography-label-sm-strong, normal 700 clamp(0.75rem, 0.72rem + 0.13vw, 0.88rem) / 1.5 Router)); } button.large { --lmvz-button-padding-inline: var(--lmvz-button-padding-inline-override, var(--lmvz-component-input-padding-lg, clamp(1rem, 0.94rem + 0.26vw, 1.25rem))); --lmvz-button-padding-block: var(--lmvz-button-padding-block-override, var(--lmvz-component-input-padding-lg, clamp(1rem, 0.94rem + 0.26vw, 1.25rem))); --lmvz-button-gap: var(--lmvz-button-gap-override, var(--lmvz-component-input-gap-lg, clamp(0.75rem, 0.69rem + 0.26vw, 1rem))); --lmvz-button-min-height: var(--lmvz-button-min-height-override, var(--lmvz-component-input-size-lg, clamp(2.75rem, 2.69rem + 0.26vw, 3rem))); --lmvz-button-font: var(--lmvz-button-font-override, var(--lmvz-typography-label-lg-strong, normal 700 clamp(1rem, 0.97rem + 0.13vw, 1.13rem) / 1.5 Router)); } display: inline-block; button { width: 100%; } } ::slotted(*) { --lmvz-component-color: var(--lmvz-button-color); } "}},[785,"lmvz-button",{ti:[514,"tabindex"],scale:[513],variant:[513],disabled:[516],type:[1],form:[1],formMethod:[1,"form-method"],name:[1],value:[1],buttonRole:[1,"button-role"]}]);function s(){"undefined"!=typeof customElements&&["lmvz-button"].forEach((t=>{"lmvz-button"===t&&(customElements.get(n(t))||customElements.define(n(t),u))}))}export{u as L,s as d}
|
package/components/p-DfFdoFeH.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{p as t,H as e,h as s,d as i,t as n}from"./p-DbBJxuBm.js";import{a,i as o}from"./p-BDonpCG8.js";import{v as r}from"./p-0ctLESas.js";import{b as c,c as d,d as h,e as l,f as u,i as m,h as f}from"./p-BhALzK62.js";const p=t(class extends e{constructor(t){super(),!1!==t&&this.__registerHost(),this.__attachShadow()}get el(){return this}actionsSlot;validationMessageCache=[];actionsStateObserver;stacked=!1;get primaryEnabledAction(){return this.enabledButtons.find(c)??this.enabledButtons[0]}get hasActions(){return this.assignedButtons.some((t=>d(t)&&h(t)&&!l(t)))}componentDidLoad(){this.handleActionsSlotChange()}disconnectedCallback(){this.actionsStateObserver?.disconnect()}get assignedElements(){return this.actionsSlot?.assignedElements({flatten:!0})??[]}get assignedButtons(){return this.assignedElements.filter(h)}get visibleButtons(){return this.assignedButtons.filter(d)}get enabledButtons(){return this.visibleButtons.filter((t=l,(...e)=>{const s=t(...e);return a(s)?s.then((t=>!t)):!s}));var t}getActionValidationResult(){if(!this.visibleButtons.length)return[];const t=this.visibleButtons.filter(c),e=this.visibleButtons.filter(u),s=[],i=this.visibleButtons;if(1!==t.length&&s.push("LmvzButtonGroup actions slot should contain exactly one primary action."),e.length>1&&s.push(`LmvzButtonGroup actions slot should contain at most one secondary action (received ${e.length})`),t.length){const n=e[0];0!==i.indexOf(t[0])&&s.push("Primary action should be the first focusable element in the actions slot (i.e. first child of the actions slot)."),n&&1!==i.indexOf(n)&&s.push("Secondary action should be the second focusable element in the actions slot (i.e. immediately after the primary button).")}else e.length&&0!==i.indexOf(e[0])&&s.push("Secondary action should be the first focusable element in the actions slot when no primary action is present (i.e. first child of the actions slot).");return s}handleActionsSlotChange=()=>{this.observeActionState(),this.syncActionsState()};observeActionState(){"undefined"!=typeof MutationObserver&&(this.actionsStateObserver?.disconnect(),this.assignedButtons.length&&(this.actionsStateObserver=new MutationObserver((()=>{this.syncActionsState()})),this.assignedButtons.forEach((t=>{this.actionsStateObserver?.observe(t,{attributes:!0,attributeFilter:["disabled","hidden","variant"]})}))))}syncActionsState(){this.assignedElements.forEach((t=>{["LMVZ-BUTTON","BUTTON"].includes(t.tagName.toUpperCase())||(t.hasAttribute("hidden")||t.setAttribute("hidden",""),"true"!==t.getAttribute("aria-hidden")&&t.setAttribute("aria-hidden","true"))})),this.checkActions();const t=this.visibleButtons,e=t.length>0&&t.some((t=>c(t)||u(t)));t.length>0&&!e?this.el.setAttribute("data-only-tertiary",""):this.el.removeAttribute("data-only-tertiary"),this.visibleButtons.forEach(((t,e)=>{const s=r[e]??"tertiary";t&&(m(t)?t.getAttribute("variant")||t.variant||t.setAttribute("variant",s):t.classList.add(s))}));const s=this.visibleButtons.find((t=>"tertiary"===t.getAttribute("variant")));this.visibleButtons.forEach((t=>{t===s?t.setAttribute("data-first-tertiary",""):t.removeAttribute("data-first-tertiary")})),this.focusPrimaryAction()}focusPrimaryAction(){const t=this.primaryEnabledAction;t&&"undefined"!=typeof window&&window.requestAnimationFrame((()=>{f(t)&&t.focus()}))}checkActions(){if(!o())return;const t=this.getActionValidationResult();t.length&&t.forEach((t=>{this.validationMessageCache.includes(t)||(console.warn(t),this.validationMessageCache.push(t))}))}render(){return s(i,{key:"3e8ce38f7e83e201e47d31579f22161ff36247b1"},s("slot",{key:"bc953d19b333f51c5f5c5ba86be3a85d155a29d1",ref:t=>this.actionsSlot=t,onSlotchange:this.handleActionsSlotChange}))}static get style(){return":host{display:flex;flex-flow:row-reverse wrap;gap:var(--lmvz-component-input-gap-md, clamp(0.5rem, 0.44rem + 0.26vw, 0.75rem));font:var(--lmvz-typography-body-md, 400 clamp(0.88rem, 0.84rem + 0.13vw, 1rem) / 1.5 Router);}:host([stacked]){flex-flow:column nowrap;align-items:stretch;padding:0}:host([stacked]) ::slotted(*){display:block;width:100%}::slotted([hidden]){display:none !important}:host(:not([data-only-tertiary],[stacked])) ::slotted([data-first-tertiary]){margin-inline-end:auto}:host([data-only-tertiary]:not([stacked])){justify-content:flex-end}"}},[769,"lmvz-button-group",{stacked:[516],primaryEnabledAction:[2064],hasActions:[2052,"has-actions"]}]);function y(){"undefined"!=typeof customElements&&["lmvz-button-group"].forEach((t=>{"lmvz-button-group"===t&&(customElements.get(n(t))||customElements.define(n(t),p))}))}export{p as L,y as d}
|
package/components/p-GJaYKpHS.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{m as t,g as s}from"./p-BhALzK62.js";import{r as i,g as e}from"./p-DXFoXTse.js";function n(t){return Boolean(e(t,"isFocusControllerHost"))}const o={orientation:"both",enableHomeAndEnd:!1,manageTabIndex:!1};class r{host;elements=[];currentElement;config;constructor(t,s={}){this.host=t,this.config={...o,...s}}hostConnected(){i(this.host.el,"isFocusControllerHost",!0),this.host.el.addEventListener("keydown",this.handleKeydown),this.syncManagedFocusTarget()}hostDisconnected(){this.host.el.removeEventListener("keydown",this.handleKeydown)}updateElements(t){const s=this.currentElement??this.getManagedActiveElement()??void 0;this.elements=t.filter((t=>"focus"in t&&1===t.nodeType)),this.syncManagedFocusTarget(s)}setCurrentElement(t){const s=this.currentElement;this.currentElement=null!=t&&"focus"in t&&1===t.nodeType?t:void 0,this.syncManagedFocusTarget(s)}async initFocus(){const t=this.selectManagedElement();t&&this.applyFocusTarget(t,!0)}handleKeydown=s=>{if(t(s.target))return;const i=this.getFocusIntent(s.key);if(!i)return;const e=this.getManagedActiveElement(),n=this.getTargetElement(e,i);n&&(s.preventDefault(),this.applyFocusTarget(n,!0))};getFocusIntent(t){return this.config.enableHomeAndEnd&&"Home"===t?"first":this.config.enableHomeAndEnd&&"End"===t?"last":"horizontal"===this.config.orientation?"ArrowRight"===t?"next":"ArrowLeft"===t?"previous":void 0:"vertical"===this.config.orientation?"ArrowDown"===t?"next":"ArrowUp"===t?"previous":void 0:"ArrowDown"===t||"ArrowRight"===t?"next":"ArrowUp"===t||"ArrowLeft"===t?"previous":void 0}getManagedActiveElement(){const t=s(this.host.el.ownerDocument??document);if(t instanceof HTMLElement){const s=this.elements.find((s=>function(t){return function(t){return"function"==typeof t.resolveFocusableElement}(t)?t.resolveFocusableElement()??t:t}(s)===t));if(s&&this.canMoveFocusTo(s))return s}if(this.currentElement&&this.elements.includes(this.currentElement)&&this.canMoveFocusTo(this.currentElement))return this.currentElement}getTargetElement(t,s){if(!this.elements.length)return;if("first"===s)return this.findFocusableFromIndex(-1,"next");if("last"===s)return this.findFocusableFromIndex(this.elements.length,"previous");const i=t?this.elements.indexOf(t):-1;return-1===i?"next"===s?this.findFocusableFromIndex(-1,"next"):this.findFocusableFromIndex(this.elements.length,"previous"):this.findFocusableFromIndex(i,s)}findFocusableFromIndex(t,s){if(!this.elements.length)return;const i="next"===s?1:-1;for(let s=1;s<=this.elements.length;s++){const e=this.elements[(t+i*s+this.elements.length)%this.elements.length];if(this.canMoveFocusTo(e))return e}}syncManagedFocusTarget(t){const s=this.selectManagedElement(t),i=s!==this.currentElement;this.currentElement=s,this.config.manageTabIndex&&this.updateTabIndexes(s),i&&s&&this.config.onFocusTargetChange?.(s)}selectManagedElement(t){const s=this.getManagedActiveElement();if(s)return s;if(this.currentElement&&this.elements.includes(this.currentElement)&&this.canMoveFocusTo(this.currentElement))return this.currentElement;if(t&&this.elements.includes(t))return this.findFocusableFromIndex(this.elements.indexOf(t),"next")??this.findFocusableFromIndex(-1,"next");return this.elements.find((t=>0===t.tabIndex&&this.canMoveFocusTo(t)))||this.findFocusableFromIndex(-1,"next")}updateTabIndexes(t){this.elements.forEach((s=>{s.tabIndex=t&&s===t?0:-1}))}applyFocusTarget(t,s){const i=t!==this.currentElement;this.currentElement=t,this.config.manageTabIndex&&this.updateTabIndexes(t),s&&t.focus(),i&&this.config.onFocusTargetChange?.(t)}canMoveFocusTo(t){return!!t&&(!t.hasAttribute("disabled")&&((!("disabled"in t)||!Boolean(t.disabled))&&("true"!==t.getAttribute("aria-disabled")&&(this.config.isFocusableElement?this.config.isFocusableElement(t):(this.config.manageTabIndex||t.tabIndex>=0)&&"true"!==t.getAttribute("aria-hidden")&&(t.checkVisibility?.()??!0)&&null!==t.offsetParent))))}}export{r as D,n as i}
|