@skra/ui 0.5.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.
- package/consumer-guide/README.md +88 -85
- package/consumer-guide/custom-components.md +154 -0
- package/consumer-guide/wrapping-patterns.md +98 -90
- package/fesm2022/skra-ui-button.mjs +2 -2
- package/fesm2022/skra-ui-button.mjs.map +1 -1
- package/fesm2022/skra-ui-checkbox.mjs +2 -2
- package/fesm2022/skra-ui-checkbox.mjs.map +1 -1
- package/fesm2022/skra-ui-core.mjs +28 -3
- package/fesm2022/skra-ui-core.mjs.map +1 -1
- package/fesm2022/skra-ui-input.mjs +2 -2
- package/fesm2022/skra-ui-input.mjs.map +1 -1
- package/fesm2022/skra-ui-menu.mjs +38 -14
- package/fesm2022/skra-ui-menu.mjs.map +1 -1
- package/fesm2022/skra-ui-popover.mjs +25 -9
- package/fesm2022/skra-ui-popover.mjs.map +1 -1
- package/fesm2022/skra-ui-radio.mjs +2 -2
- package/fesm2022/skra-ui-radio.mjs.map +1 -1
- package/fesm2022/skra-ui-rating-display.mjs +2 -2
- package/fesm2022/skra-ui-rating-display.mjs.map +1 -1
- package/fesm2022/skra-ui-star-rating.mjs +2 -2
- package/fesm2022/skra-ui-star-rating.mjs.map +1 -1
- package/fesm2022/skra-ui-switch.mjs +2 -2
- package/fesm2022/skra-ui-switch.mjs.map +1 -1
- package/fesm2022/skra-ui-tooltip.mjs +7 -2
- package/fesm2022/skra-ui-tooltip.mjs.map +1 -1
- package/package.json +2 -2
- package/types/skra-ui-core.d.ts.map +1 -1
- package/types/skra-ui-menu.d.ts +18 -6
- package/types/skra-ui-menu.d.ts.map +1 -1
- package/types/skra-ui-popover.d.ts +13 -4
- package/types/skra-ui-popover.d.ts.map +1 -1
- package/types/skra-ui-tooltip.d.ts.map +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skra-ui-core.mjs","sources":["../../../../libs/ui/core/src/lib/select/select-types.ts","../../../../libs/ui/core/src/lib/select/option.directives.ts","../../../../libs/ui/core/src/lib/select/option.ts","../../../../libs/ui/core/src/lib/select/select-trigger.ts","../../../../libs/ui/core/src/lib/positioning/positioner.ts","../../../../libs/ui/core/src/lib/select/listbox-keyboard.ts","../../../../libs/ui/core/src/lib/select/listbox-widget-base.ts","../../../../libs/ui/core/src/lib/select/select-base.ts","../../../../libs/ui/core/src/index.ts","../../../../libs/ui/core/src/skra-ui-core.ts"],"sourcesContent":["import { InjectionToken } from '@angular/core';\n\n/**\n * What a `skra-option` needs from its listbox parent — a narrow contract that breaks the\n * parent↔option import cycle (the `SKRA_MENU` precedent). A token (not a concrete class) so the option\n * file never imports a widget file — no runtime import cycle. Implemented by `_SkraListboxWidgetBase`,\n * so it is shared by `skra-select`, `skra-multi-select` AND `skra-combobox` (ADR 0046 amendment).\n */\nexport interface SkraListboxPanel {\n /** Live selection test for an option's value (signal-driven: default `Object.is` or consumer `compareWith`). */\n isSelected(value: unknown): boolean;\n /**\n * A user picked this value (pointer/keyboard). Single-select emits `valueChange` + closes; multi-select\n * TOGGLES membership and keeps the panel open (ADR 0046); combobox replaces + closes (ADR 0049).\n * Consumer owns `value` (ADR 037).\n */\n selectValue(value: unknown): void;\n /**\n * Cardinality hint (ADR 0046) — `false` on single widgets (`skra-select`/`skra-combobox`), `true` on\n * `skra-multi-select`. The ONLY thing `skra-option` reads to swap its component-rendered indicator\n * (checkmark ↔ checkbox). NOT an Angular input; cardinality is a component identity, never a runtime flag.\n */\n readonly multiple: boolean;\n}\n\n/**\n * The item shape the listbox keyboard controller drives. Structurally a CDK `Highlightable`\n * (`setActiveStyles`/`setInactiveStyles`) + `ListKeyManagerOption` (`getLabel`/`disabled`), plus the\n * option's `id` (→ `aria-activedescendant`) and `getValue()` (Enter-to-select). Declared HERE — cdk-free —\n * so the only `@angular/cdk` importer stays `listbox-keyboard.ts` (the `menu-types.ts` precedent).\n */\nexport interface SkraListboxKeyboardItem {\n readonly optionId: string;\n setActiveStyles(): void;\n setInactiveStyles(): void;\n getLabel(): string;\n getValue(): unknown;\n readonly disabled: boolean;\n}\n\n/**\n * DI token a listbox widget provides (`useExisting`) and a `skra-option` injects. A token (not a concrete\n * class) so the option file never imports a widget file — no runtime import cycle. Provided by\n * `skra-select`, `skra-multi-select`, and `skra-combobox`.\n */\nexport const SKRA_LISTBOX_PANEL = new InjectionToken<SkraListboxPanel>(\n 'SKRA_LISTBOX_PANEL',\n);\n","import { Directive } from '@angular/core';\n\n/**\n * Slot marker: the leading icon/flag of a `skra-option` — part of the option IDENTITY (ADR 0045\n * Rule 4), so it flows into `getLabel()` (emoji/glyph leading appears in the default trigger for free).\n */\n@Directive({\n selector: '[skra-option-leading]',\n standalone: true,\n})\nexport class SkraOptionLeading {}\n\n/**\n * Slot marker: secondary DETAIL text of a `skra-option` (e.g. a dial code, a description) — list-only\n * (ADR 0045 Rule 4), EXCLUDED from `getLabel()` and the trigger summary.\n */\n@Directive({\n selector: '[skra-option-detail]',\n standalone: true,\n})\nexport class SkraOptionDetail {}\n","import {\n ChangeDetectionStrategy,\n Component,\n ElementRef,\n ViewEncapsulation,\n computed,\n contentChild,\n inject,\n input,\n signal,\n} from '@angular/core';\n\nimport {\n SKRA_LISTBOX_PANEL,\n type SkraListboxKeyboardItem,\n} from './select-types';\nimport { SkraOptionDetail, SkraOptionLeading } from './option.directives';\n\ndeclare const ngDevMode: boolean | undefined;\n\nlet nextOptionId = 0;\n\n/**\n * SkraOption — one selectable row in a `skra-select` listbox, a Component on the custom-element host\n * `skra-option` (ADR 040 content-bearing host; there is no native option element that holds rich content\n * outside `<select>`). Carries `value` + rich projected content: a leading icon (`[skra-option-leading]`)\n * and a primary label = the IDENTITY (→ `getLabel()` / the default trigger, ADR 0045), plus an optional\n * secondary `[skra-option-detail]` that is list-only (excluded from the trigger). The selection\n * indicator (trailing checkmark) is component-rendered, driven by `aria-selected` — NOT a slot; iteration 2\n * swaps it for a per-row checkbox with no API change.\n *\n * Implements `SkraListboxKeyboardItem` so `_SkraListboxKeyboard` (CDK `ActiveDescendantKeyManager`) can\n * highlight it (`setActiveStyles`/`setInactiveStyles` → `data-skra-active`) and type-ahead to it\n * (`getLabel`). Disabled is native-attr-first (Menu precedent): the consumer sets `aria-disabled=\"true\"`\n * and Forge OBSERVES it — disabled options stay navigable (discoverable) but cannot be selected.\n *\n * Full contract: adr/specs/component-select-spec.md.\n */\n@Component({\n selector: 'skra-option',\n standalone: true,\n exportAs: 'skraOption',\n template: `\n @if (hasLeading()) {\n <span class=\"skra-select-option-leading\"\n ><ng-content select=\"[skra-option-leading]\"></ng-content\n ></span>\n }\n <span class=\"skra-select-option-label\"><ng-content></ng-content></span>\n @if (hasDetail()) {\n <span class=\"skra-select-option-detail\"\n ><ng-content select=\"[skra-option-detail]\"></ng-content\n ></span>\n }\n <span\n class=\"skra-select-option-indicator\"\n [class.skra-select-option-indicator--checkbox]=\"multiple()\"\n aria-hidden=\"true\"\n ></span>\n `,\n styleUrl: './option.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.Emulated,\n host: {\n role: 'option',\n '[id]': 'optionId',\n '[attr.aria-selected]': 'selected() ? \"true\" : \"false\"',\n '[attr.data-skra-active]': 'active() ? \"\" : null',\n '(click)': 'onActivate()',\n // Disabled = the consumer's native `aria-disabled=\"true\"` (observed live) — no Forge binding.\n },\n})\nexport class SkraOption<T = unknown> implements SkraListboxKeyboardItem {\n /** The option's value (ADR 037 — consumer-owned; compared against the select's `value()`). */\n readonly value = input.required<T>();\n\n /** Stable id, the target of the trigger's `aria-activedescendant`. Internal — never consumer-facing. */\n readonly optionId = `skra-option-${nextOptionId++}`;\n\n private readonly el = inject<ElementRef<HTMLElement>>(ElementRef);\n private readonly select = inject(SKRA_LISTBOX_PANEL, { optional: true });\n\n private readonly leadingSlot = contentChild(SkraOptionLeading);\n private readonly detailSlot = contentChild(SkraOptionDetail);\n protected readonly hasLeading = computed(() => !!this.leadingSlot());\n protected readonly hasDetail = computed(() => !!this.detailSlot());\n\n /** Keyboard active-descendant highlight (ADR 0044 §7 — Highlightable, NOT roving focus). */\n protected readonly active = signal(false);\n\n /**\n * Cardinality hint from the parent panel (ADR 0046): `false` under `skra-select` → checkmark\n * indicator; `true` under `skra-multi-select` → checkbox indicator. The only thing the shared\n * `skra-option` reads to swap the component-rendered indicator. No public-API change.\n */\n protected readonly multiple = computed(() => this.select?.multiple ?? false);\n\n /** Selection is signal-derived (ADR 0045 / ADR 037): re-derives on parent `value()`/`compareWith()` or own `value()`. */\n protected readonly selected = computed(\n () => this.select?.isSelected(this.value()) ?? false,\n );\n\n constructor() {\n if (typeof ngDevMode === 'undefined' || ngDevMode) {\n if (!this.select) {\n console.warn(\n '[skra-option] has no <skra-select> ancestor — it is not registered with the keyboard ' +\n 'controller / selection model and cannot be picked. Project it inside a <skra-select>.',\n );\n }\n }\n }\n\n // ── SkraListboxKeyboardItem (driven by _SkraListboxKeyboard / CDK ActiveDescendantKeyManager) ──\n setActiveStyles(): void {\n this.active.set(true);\n }\n setInactiveStyles(): void {\n this.active.set(false);\n }\n\n /**\n * ADR 0045 Rule 1: the option's IDENTITY text (leading + label), EXCLUDING `[skra-option-detail]` and\n * the component-rendered indicator. Own-host `textContent` walk (the `skraMenuItem.getLabel()`\n * precedent) — drives the default trigger text AND type-ahead. Reading own content, NOT\n * `document.querySelector` (ADR 001-clean).\n */\n getLabel(): string {\n let text = '';\n const skip = (el: HTMLElement): boolean =>\n el.classList.contains('skra-select-option-detail') ||\n el.classList.contains('skra-select-option-indicator') ||\n el.hasAttribute('skra-option-detail');\n const walk = (node: Node): void => {\n if (node.nodeType === Node.TEXT_NODE) {\n text += node.textContent ?? '';\n return;\n }\n if (node.nodeType === Node.ELEMENT_NODE) {\n const el = node as HTMLElement;\n if (skip(el)) return;\n el.childNodes.forEach(walk);\n }\n };\n this.el.nativeElement.childNodes.forEach(walk);\n return text.replace(/\\s+/g, ' ').trim();\n }\n\n getValue(): unknown {\n return this.value();\n }\n\n /** Soft-disabled = the consumer's `aria-disabled=\"true\"` (native-attr-first, Menu precedent); read live. */\n get disabled(): boolean {\n return this.el.nativeElement.getAttribute('aria-disabled') === 'true';\n }\n\n protected onActivate(): void {\n if (this.disabled) return; // soft-disabled: not selectable (APG)\n this.select?.selectValue(this.value());\n }\n}\n","import { Directive } from '@angular/core';\n\n/**\n * SkraSelectTrigger — the opt-in rich-trigger marker (ADR 0045 Rule 2). Place on an `<ng-template>`\n * inside `<skra-select>`; the select reads it as a `TemplateRef` and stamps it in the trigger via\n * `ngTemplateOutlet` with `{ $implicit: value, option: selectedOption }` context — the ONLY supported\n * path for non-text (SVG/`<img>`) trigger presentation. With no trigger template the default trigger is\n * the selected option's `getLabel()` text (emoji/glyph leading content appears for free).\n *\n * <skra-select [value]=\"country()\" (valueChange)=\"country.set($event)\">\n * <ng-template skraSelectTrigger let-value>\n * <skra-icon [innerSVG]=\"flagOf(value)\"></skra-icon> {{ nameOf(value) }}\n * </ng-template>\n * <skra-option value=\"de\"><skra-icon [innerSVG]=\"flagOf('de')\"></skra-icon> Germany</skra-option>\n * </skra-select>\n */\n@Directive({\n selector: '[skraSelectTrigger]',\n standalone: true,\n})\nexport class SkraSelectTrigger {}\n","import {\n autoUpdate,\n computePosition,\n flip,\n offset as offsetMiddleware,\n shift,\n type Placement,\n} from '@floating-ui/dom';\n\n/**\n * Forge's single overlay positioning abstraction (ADR 0044 §3 rules 4–5).\n *\n * Wraps `@floating-ui/dom` so the library is an IMPLEMENTATION DETAIL: nothing outside this folder\n * imports it, and swapping the engine (e.g. to native CSS Anchor Positioning once it is baseline\n * cross-browser) is a one-file change with zero public-API impact.\n *\n * It writes **geometry only** (`left`/`top` + the resolved-side `data-skra-placement`) inline on the\n * floating element — the scoped geometry-only exception to ADR 021 / Visual Purism granted by\n * ADR 0044 §3 rule 4. It MUST NOT write any theme/state/token value inline (those stay `var(--skra-*)`\n * + `data-skra-*`). No portal, no z-index, no CDK, no library stylesheet.\n *\n * Decided at the first anchored component (Tooltip, 2026-06-06): a single JS path on all engines\n * (not native-CSS-primary + JS-fallback) — see ADR 0044 §7 + the rule-4 refinement note.\n */\n\n/** Forge placement intent — the base four sides; flip/shift adjust at runtime. */\nexport type SkraPlacement = 'top' | 'bottom' | 'left' | 'right';\n\nexport interface _PositionerOptions {\n /** Preferred side; `flip` re-sides on viewport collision. */\n placement: SkraPlacement;\n /** Gap between trigger and floating element, in px (resolved from a comp token by the caller). */\n offset?: number;\n /** Minimum distance from the viewport edge for `shift`, in px. */\n viewportPadding?: number;\n}\n\nexport interface _PositionerHandle {\n /** Stop repositioning and release the `autoUpdate` listeners. Idempotent. */\n destroy(): void;\n}\n\n/**\n * Anchor `floating` to `reference` and keep it positioned while visible. Returns a handle whose\n * `destroy()` MUST be called when the overlay hides or the owner is destroyed (no listener leak).\n *\n * `options` is a getter so live token values (offset) are re-read on every reposition.\n */\nexport function _attachPositioner(\n reference: HTMLElement,\n floating: HTMLElement,\n options: () => _PositionerOptions,\n): _PositionerHandle {\n const update = (): void => {\n const { placement, offset = 0, viewportPadding = 8 } = options();\n void computePosition(reference, floating, {\n strategy: 'fixed', // floating element renders in the top layer → viewport-relative\n placement: placement as Placement,\n middleware: [\n offsetMiddleware(offset),\n flip(),\n shift({ padding: viewportPadding }),\n ],\n }).then(({ x, y, placement: resolved }) => {\n // Geometry only (ADR 0044 §3 rule 4). Never theme/state.\n floating.style.left = `${x}px`;\n floating.style.top = `${y}px`;\n // Resolved side (post-flip) for orientation CSS / future arrow — a data-attr, not a style.\n floating.setAttribute('data-skra-placement', resolved.split('-')[0]);\n });\n };\n\n // autoUpdate repositions on scroll, resize and element resize; returns its own cleanup.\n const cleanup = autoUpdate(reference, floating, update);\n let destroyed = false;\n return {\n destroy(): void {\n if (destroyed) return;\n destroyed = true;\n cleanup();\n },\n };\n}\n","import { ActiveDescendantKeyManager } from '@angular/cdk/a11y';\n\nimport type { SkraListboxKeyboardItem } from './select-types';\n\n/**\n * _SkraListboxKeyboard — the WAI-ARIA APG **Select-Only Combobox** listbox keyboard model, confined to\n * ONE file. Sibling to `menu-keyboard.ts`: per ADR 0044 §7 (2026-06-07), `@angular/cdk/a11y` is confined\n * to one swappable `*-keyboard.ts` controller PER APG pattern. Menu uses `FocusKeyManager` (roving REAL\n * focus); the listbox uses **`ActiveDescendantKeyManager`** — focus STAYS on the combobox trigger and the\n * active option is virtual (`aria-activedescendant`), the APG-canonical select-only model. Swapping the\n * engine is a one-file change, exactly as `SkraPositioner` wraps `@floating-ui/dom`.\n *\n * Owns: Down/Up active-descendant movement, Home/End, and type-ahead. Enter/Space (select), Escape and\n * light-dismiss (`popover=\"auto\"`) stay with the select / platform — this controller never touches them.\n */\nexport class _SkraListboxKeyboard {\n private manager?: ActiveDescendantKeyManager<SkraListboxKeyboardItem>;\n private items: SkraListboxKeyboardItem[] = [];\n private changeHandler?: (item: SkraListboxKeyboardItem | null) => void;\n\n /** Notified whenever the active descendant changes — the select mirrors it to `aria-activedescendant`. */\n onActiveChange(\n handler: (item: SkraListboxKeyboardItem | null) => void,\n ): void {\n this.changeHandler = handler;\n }\n\n /**\n * (Re)build the manager from the current projected option set. Called from an `effect` on the select's\n * signal `contentChildren` — a passed array is a static snapshot (it does not auto-track like a live\n * `QueryList`), so the manager is rebuilt whenever the option set changes (the documented signal↔CDK seam).\n */\n setItems(items: readonly SkraListboxKeyboardItem[]): void {\n this.items = [...items];\n this.manager?.destroy();\n this.manager = new ActiveDescendantKeyManager<SkraListboxKeyboardItem>(\n this.items,\n )\n .withTypeAhead()\n .withHomeAndEnd()\n // Disabled options stay navigable (APG-discoverable); selection is guarded by the select.\n // `() => false` also stops the manager from reading `item.disabled` to skip-during-navigation.\n .skipPredicate(() => false);\n this.manager.change.subscribe((index) =>\n this.changeHandler?.(this.items[index] ?? null),\n );\n }\n\n /** Delegate Down/Up/Home/End/type-ahead. Enter/Space/Escape are intentionally left to the select/platform. */\n onKeydown(event: KeyboardEvent): void {\n this.manager?.onKeydown(event);\n }\n\n get activeItem(): SkraListboxKeyboardItem | null {\n return this.manager?.activeItem ?? null;\n }\n\n /** Seed the active descendant on open: the selected option, else the first. */\n setActive(item: SkraListboxKeyboardItem | null): void {\n if (!this.manager) return;\n if (item) this.manager.setActiveItem(item);\n else this.manager.setFirstItemActive();\n }\n\n /** Deactivate (close): `setActiveItem(-1)` clears `_activeItem` and the highlight. */\n clearActive(): void {\n this.manager?.setActiveItem(-1);\n }\n\n destroy(): void {\n this.manager?.destroy();\n this.manager = undefined;\n }\n}\n","import {\n DestroyRef,\n Directive,\n ElementRef,\n booleanAttribute,\n computed,\n contentChildren,\n effect,\n inject,\n input,\n signal,\n viewChild,\n} from '@angular/core';\nimport { SkraFieldContext } from '@skra/ui/field';\n\nimport {\n _attachPositioner,\n type SkraPlacement,\n type _PositionerHandle,\n} from '../positioning/positioner';\nimport { _SkraListboxKeyboard } from './listbox-keyboard';\nimport { SkraOption } from './option';\nimport type { SkraListboxKeyboardItem, SkraListboxPanel } from './select-types';\n\nlet nextListboxId = 0;\n\n/**\n * _SkraListboxWidgetBase — the **trigger-shape-agnostic** core shared by every Forge listbox widget,\n * per the **ADR 0046 amendment (2026-06-13)**. It owns ONLY the substrate that does not depend on what\n * the trigger looks like: the `SkraFieldContext` cascade (ADR 013), the panel `(toggle)` →\n * `SkraPositioner` lifecycle + active-descendant seeding, the `_SkraListboxKeyboard` wiring\n * (CDK `ActiveDescendantKeyManager`, ADR 0044 §7), imperative `open()`/`close()`, teardown, and the\n * abstract `SkraListboxPanel` selection seam.\n *\n * Trigger BEHAVIOUR lives one level down, in a per-shape base:\n * - `_SkraSelectBase` adds the button + native `popovertarget` + type-ahead trigger (Select-Only\n * Combobox) and the ADR 0045 `[skraSelectTrigger]` rich-trigger template.\n * - `SkraCombobox` (no extra base) adds the editable `<input>` + filter-output trigger (ADR 0049).\n *\n * The keydown skeleton is NOT here — each trigger shape routes keys differently (the select selects on\n * Space and type-aheads; the combobox types into the input and never type-aheads). Forcing one keydown\n * through both shapes is the wrong abstraction.\n *\n * `panelTokenPrefix` makes the panel comp-token namespace overridable so each widget reads its OWN\n * `--skra-comp-<prefix>-panel-*` tokens (`select` for the select family, `combobox` for the combobox).\n *\n * Full contracts: adr/specs/component-{select,multi-select,combobox}-spec.md.\n */\n@Directive({\n host: {\n // Shell state reflection for the skin (the trigger control carries the ARIA + native disabled).\n '[attr.data-skra-disabled]': 'isDisabled() ? \"\" : null',\n '[attr.data-skra-readonly]': 'isReadonly() ? \"\" : null',\n '[attr.data-skra-validation]': 'hasError() ? \"invalid\" : null',\n },\n})\nexport abstract class _SkraListboxWidgetBase<T = unknown>\n implements SkraListboxPanel\n{\n /** Equality strategy seam (ADR 037 selection model): default `Object.is`; object values pass a custom comparator. */\n readonly compareWith = input<(a: T, b: T) => boolean>(Object.is);\n /** Value-empty hint shown in the trigger (NOT the accessible name — ADR 033). */\n readonly placeholder = input<string>('');\n /** Placement intent; flip/shift adjust at runtime. */\n readonly placement = input<SkraPlacement>('bottom');\n /** Standalone availability source (Q-1) — `SkraFieldContext` wins when present. */\n readonly disabled = input(false, { transform: booleanAttribute });\n readonly readonly = input(false, { transform: booleanAttribute });\n\n protected readonly options = contentChildren(SkraOption);\n\n protected readonly triggerRef = viewChild<ElementRef<HTMLElement>>('trigger');\n protected readonly panelRef = viewChild<ElementRef<HTMLElement>>('panel');\n\n protected readonly context = inject(SkraFieldContext, { optional: true });\n protected readonly keyboard = new _SkraListboxKeyboard();\n\n readonly panelId = `skra-listbox-${nextListboxId++}`;\n protected readonly isOpen = signal(false);\n protected readonly activeOptionId = signal<string | null>(null);\n\n private positioner?: _PositionerHandle;\n\n /** Panel comp-token namespace — `--skra-comp-<panelTokenPrefix>-panel-*`. Overridden per widget. */\n protected abstract readonly panelTokenPrefix: string;\n\n // ── Availability / validation (SkraFieldContext, ADR 013, with standalone fallbacks — Q-1) ──\n protected readonly isDisabled = computed(\n () => this.context?.isDisabled() ?? this.disabled(),\n );\n protected readonly isReadonly = computed(\n () => this.context?.isReadonly() ?? this.readonly(),\n );\n protected readonly hasError = computed(\n () => this.context?.hasError() ?? false,\n );\n protected readonly isRequired = computed(\n () => this.context?.isRequired() ?? false,\n );\n protected readonly triggerId = computed(\n () => this.context?.fieldId() || null,\n );\n protected readonly describedBy = computed(\n () => this.context?.describedByIds() ?? null,\n );\n\n constructor() {\n // Feed the keyboard controller whenever the projected option set changes (signal → array rebuild).\n effect(() => this.keyboard.setItems(this.options()));\n // Mirror the active descendant to the trigger's aria-activedescendant.\n this.keyboard.onActiveChange((item) =>\n this.activeOptionId.set(item?.optionId ?? null),\n );\n inject(DestroyRef).onDestroy(() => this.teardown());\n }\n\n // ── SkraListboxPanel seam — the per-widget divergence (implemented by each concrete) ──\n /** Live selection test: single = equality, multi = membership (both via `compareWith`). */\n abstract isSelected(value: unknown): boolean;\n /** User picked a value: single = replace + close; multi = toggle membership + keep open. */\n abstract selectValue(value: unknown): void;\n /** Cardinality hint read by `skra-option` for the indicator swap — `false` single / `true` multi. */\n abstract readonly multiple: boolean;\n /** Seed the active descendant on open: single = the selected option; multi = the first selected. */\n protected abstract activeSeedItem(): SkraListboxKeyboardItem | null;\n\n // ── Panel open / close (native toggle from the Popover API) ──\n protected onPanelToggle(event: Event): void {\n const open = (event as ToggleEvent).newState === 'open';\n this.isOpen.set(open);\n if (open) this.onOpen();\n else this.onClose();\n }\n\n /**\n * The element the panel is positioned against AND matched in width to (Q-5). Defaults to the trigger\n * — correct for the select family, whose trigger button fills the host. The combobox overrides it to\n * the host box, because its trigger is the INNER input (narrower than the bordered box + chevron), so\n * the panel must align to and match the box, not the input — visual parity with select.\n */\n protected positioningAnchor(): HTMLElement | undefined {\n return this.triggerRef()?.nativeElement;\n }\n\n private onOpen(): void {\n const anchor = this.positioningAnchor();\n const panel = this.panelRef()?.nativeElement;\n if (anchor && panel) {\n // Geometry-only (ADR 0044 §3 rule 4): the panel is at least as wide as the anchor (Q-5).\n panel.style.minInlineSize = `${anchor.offsetWidth}px`;\n this.positioner?.destroy();\n this.positioner = _attachPositioner(anchor, panel, () => ({\n placement: this.placement(),\n offset: this.cssLenPx(\n `--skra-comp-${this.panelTokenPrefix}-panel-offset`,\n ),\n viewportPadding: this.cssLenPx(\n `--skra-comp-${this.panelTokenPrefix}-panel-viewport-padding`,\n ),\n }));\n }\n // Seed the active descendant (single → selected; multi → first selected, else first).\n this.keyboard.setActive(this.activeSeedItem());\n }\n\n private onClose(): void {\n this.positioner?.destroy();\n this.positioner = undefined;\n this.keyboard.clearActive();\n this.activeOptionId.set(null);\n }\n\n /** Select the keyboard's active option (Enter), unless it is soft-disabled. Shared by every trigger shape. */\n protected selectActive(): void {\n const active = this.keyboard.activeItem;\n if (active && !active.disabled) this.selectValue(active.getValue());\n }\n\n protected open(): void {\n this.panelRef()?.nativeElement.showPopover?.();\n }\n protected close(): void {\n this.panelRef()?.nativeElement.hidePopover?.();\n }\n\n /** Read a length comp token (px/rem) off the panel computed style for the positioner. */\n private cssLenPx(prop: string): number {\n const el = this.panelRef()?.nativeElement;\n if (!el) return 0;\n const raw = getComputedStyle(el).getPropertyValue(prop).trim();\n if (raw.endsWith('px')) return parseFloat(raw);\n if (raw.endsWith('rem')) {\n const rootFontSize =\n parseFloat(getComputedStyle(document.documentElement).fontSize) || 16;\n return parseFloat(raw) * rootFontSize;\n }\n return parseFloat(raw) || 0;\n }\n\n private teardown(): void {\n this.keyboard.destroy();\n this.positioner?.destroy();\n }\n}\n","import { Directive, TemplateRef, contentChild } from '@angular/core';\n\nimport { _SkraListboxWidgetBase } from './listbox-widget-base';\nimport { SkraSelectTrigger } from './select-trigger';\n\n/**\n * _SkraSelectBase — the SELECT-family trigger model over {@link _SkraListboxWidgetBase}: the WAI-ARIA APG\n * **Select-Only Combobox** trigger. It adds the `<button>` + native `popovertarget` interaction, the\n * type-ahead keydown skeleton, and the ADR 0045 `[skraSelectTrigger]` rich-trigger template. Shared by\n * `skra-select` (single) and `skra-multi-select` (multi) — the cardinality split (ADR 0046) lives in\n * those concretes (the `SkraListboxPanel` seam: single replaces + closes, multi toggles + stays open).\n *\n * The trigger-shape-agnostic substrate (field cascade, panel toggle/positioner, keyboard wiring,\n * open/close, the selection seam) lives in the parent base, shared verbatim with `skra-combobox`\n * (which has a different — editable input — trigger; ADR 0046 amendment 2026-06-13).\n *\n * Full contract: adr/specs/component-select-spec.md + adr/specs/component-multi-select-spec.md.\n */\n@Directive()\nexport abstract class _SkraSelectBase<\n T = unknown,\n> extends _SkraListboxWidgetBase<T> {\n /** Select-family panel token namespace — `--skra-comp-select-panel-*` (shared single + multi). */\n protected readonly panelTokenPrefix = 'select';\n\n /** Opt-in rich trigger template (ADR 0045 Rule 2). Select-family only — a combobox input shows text. */\n protected readonly triggerTemplate = contentChild(SkraSelectTrigger, {\n read: TemplateRef,\n });\n\n // ── Trigger interaction (button + native popovertarget) ──\n protected onTriggerClick(event: MouseEvent): void {\n // Block the native popovertarget open when readonly (disabled is unfocusable/inert natively).\n if (this.isReadonly()) event.preventDefault();\n }\n\n protected onTriggerKeydown(event: KeyboardEvent): void {\n if (this.isDisabled() || this.isReadonly()) return; // never opens / never mutates\n const key = event.key;\n const isSpace = key === ' ' || key === 'Spacebar';\n const isNav =\n key === 'ArrowDown' ||\n key === 'ArrowUp' ||\n key === 'Home' ||\n key === 'End';\n const isPrintable =\n key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey;\n\n if (!this.isOpen()) {\n // Single open path: suppress the popovertarget's own toggle (Enter/Space) too and open here.\n if (isNav || isSpace || key === 'Enter' || isPrintable) {\n event.preventDefault();\n this.open();\n }\n return;\n }\n\n // Open:\n if (key === 'Enter' || isSpace) {\n // Suppress the popovertarget toggle; the concrete `selectValue` decides close (single) vs stay-open (multi).\n event.preventDefault();\n this.selectActive();\n return;\n }\n if (key === 'Tab') {\n this.close(); // APG: Tab closes (keep value); focus proceeds (no preventDefault)\n return;\n }\n if (key === 'Escape') return; // platform (popover=\"auto\") closes; onPanelToggle handles cleanup\n if (isNav || isPrintable) {\n event.preventDefault();\n this.keyboard.onKeydown(event); // move / type-ahead the active descendant\n }\n }\n}\n","// @skra/ui/core — shared internal satellites (ADR 0054). Consumed cross-entry by\n// select / multi-select / combobox / datepicker / menu / popover / tooltip.\n\n// --- Public shared surface ---\nexport * from './lib/select/option';\nexport * from './lib/select/option.directives';\nexport * from './lib/select/select-trigger';\nexport {\n SKRA_LISTBOX_PANEL,\n type SkraListboxPanel,\n type SkraListboxKeyboardItem,\n} from './lib/select/select-types';\n\n// --- Internal shared bases (`_`-prefixed = outside SemVer, ADR 0054 R-54.4/R-54.5) ---\nexport * from './lib/select/select-base';\nexport * from './lib/select/listbox-widget-base';\n// Positioner: `_attachPositioner`/`_PositionerOptions`/`_PositionerHandle` are internal\n// (`_`-prefixed = outside SemVer — O-33 (6a) done). `SkraPlacement` is PUBLIC by ruling\n// (consumer-facing placement inputs, re-exported by tooltip/popover/menu/datepicker).\n// See ADR 0054 §7 (2026-07-03 note); enforced by export-surface-validator.\nexport * from './lib/positioning/positioner';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":["offset","offsetMiddleware"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"skra-ui-core.mjs","sources":["../../../../libs/ui/core/src/lib/select/select-types.ts","../../../../libs/ui/core/src/lib/select/option.directives.ts","../../../../libs/ui/core/src/lib/select/option.ts","../../../../libs/ui/core/src/lib/select/select-trigger.ts","../../../../libs/ui/core/src/lib/positioning/positioner.ts","../../../../libs/ui/core/src/lib/select/listbox-keyboard.ts","../../../../libs/ui/core/src/lib/select/listbox-widget-base.ts","../../../../libs/ui/core/src/lib/select/select-base.ts","../../../../libs/ui/core/src/index.ts","../../../../libs/ui/core/src/skra-ui-core.ts"],"sourcesContent":["import { InjectionToken } from '@angular/core';\n\n/**\n * What a `skra-option` needs from its listbox parent — a narrow contract that breaks the\n * parent↔option import cycle (the `SKRA_MENU` precedent). A token (not a concrete class) so the option\n * file never imports a widget file — no runtime import cycle. Implemented by `_SkraListboxWidgetBase`,\n * so it is shared by `skra-select`, `skra-multi-select` AND `skra-combobox` (ADR 0046 amendment).\n */\nexport interface SkraListboxPanel {\n /** Live selection test for an option's value (signal-driven: default `Object.is` or consumer `compareWith`). */\n isSelected(value: unknown): boolean;\n /**\n * A user picked this value (pointer/keyboard). Single-select emits `valueChange` + closes; multi-select\n * TOGGLES membership and keeps the panel open (ADR 0046); combobox replaces + closes (ADR 0049).\n * Consumer owns `value` (ADR 037).\n */\n selectValue(value: unknown): void;\n /**\n * Cardinality hint (ADR 0046) — `false` on single widgets (`skra-select`/`skra-combobox`), `true` on\n * `skra-multi-select`. The ONLY thing `skra-option` reads to swap its component-rendered indicator\n * (checkmark ↔ checkbox). NOT an Angular input; cardinality is a component identity, never a runtime flag.\n */\n readonly multiple: boolean;\n}\n\n/**\n * The item shape the listbox keyboard controller drives. Structurally a CDK `Highlightable`\n * (`setActiveStyles`/`setInactiveStyles`) + `ListKeyManagerOption` (`getLabel`/`disabled`), plus the\n * option's `id` (→ `aria-activedescendant`) and `getValue()` (Enter-to-select). Declared HERE — cdk-free —\n * so the only `@angular/cdk` importer stays `listbox-keyboard.ts` (the `menu-types.ts` precedent).\n */\nexport interface SkraListboxKeyboardItem {\n readonly optionId: string;\n setActiveStyles(): void;\n setInactiveStyles(): void;\n getLabel(): string;\n getValue(): unknown;\n readonly disabled: boolean;\n}\n\n/**\n * DI token a listbox widget provides (`useExisting`) and a `skra-option` injects. A token (not a concrete\n * class) so the option file never imports a widget file — no runtime import cycle. Provided by\n * `skra-select`, `skra-multi-select`, and `skra-combobox`.\n */\nexport const SKRA_LISTBOX_PANEL = new InjectionToken<SkraListboxPanel>(\n 'SKRA_LISTBOX_PANEL',\n);\n","import { Directive } from '@angular/core';\n\n/**\n * Slot marker: the leading icon/flag of a `skra-option` — part of the option IDENTITY (ADR 0045\n * Rule 4), so it flows into `getLabel()` (emoji/glyph leading appears in the default trigger for free).\n */\n@Directive({\n selector: '[skra-option-leading]',\n standalone: true,\n})\nexport class SkraOptionLeading {}\n\n/**\n * Slot marker: secondary DETAIL text of a `skra-option` (e.g. a dial code, a description) — list-only\n * (ADR 0045 Rule 4), EXCLUDED from `getLabel()` and the trigger summary.\n */\n@Directive({\n selector: '[skra-option-detail]',\n standalone: true,\n})\nexport class SkraOptionDetail {}\n","import {\n ChangeDetectionStrategy,\n Component,\n ElementRef,\n ViewEncapsulation,\n computed,\n contentChild,\n inject,\n input,\n signal,\n} from '@angular/core';\n\nimport {\n SKRA_LISTBOX_PANEL,\n type SkraListboxKeyboardItem,\n} from './select-types';\nimport { SkraOptionDetail, SkraOptionLeading } from './option.directives';\n\ndeclare const ngDevMode: boolean | undefined;\n\nlet nextOptionId = 0;\n\n/**\n * SkraOption — one selectable row in a `skra-select` listbox, a Component on the custom-element host\n * `skra-option` (ADR 040 content-bearing host; there is no native option element that holds rich content\n * outside `<select>`). Carries `value` + rich projected content: a leading icon (`[skra-option-leading]`)\n * and a primary label = the IDENTITY (→ `getLabel()` / the default trigger, ADR 0045), plus an optional\n * secondary `[skra-option-detail]` that is list-only (excluded from the trigger). The selection\n * indicator (trailing checkmark) is component-rendered, driven by `aria-selected` — NOT a slot; iteration 2\n * swaps it for a per-row checkbox with no API change.\n *\n * Implements `SkraListboxKeyboardItem` so `_SkraListboxKeyboard` (CDK `ActiveDescendantKeyManager`) can\n * highlight it (`setActiveStyles`/`setInactiveStyles` → `data-skra-active`) and type-ahead to it\n * (`getLabel`). Disabled is native-attr-first (Menu precedent): the consumer sets `aria-disabled=\"true\"`\n * and Forge OBSERVES it — disabled options stay navigable (discoverable) but cannot be selected.\n *\n * Full contract: adr/specs/component-select-spec.md.\n */\n@Component({\n selector: 'skra-option',\n standalone: true,\n exportAs: 'skraOption',\n template: `\n @if (hasLeading()) {\n <span class=\"skra-select-option-leading\"\n ><ng-content select=\"[skra-option-leading]\"></ng-content\n ></span>\n }\n <span class=\"skra-select-option-label\"><ng-content></ng-content></span>\n @if (hasDetail()) {\n <span class=\"skra-select-option-detail\"\n ><ng-content select=\"[skra-option-detail]\"></ng-content\n ></span>\n }\n <span\n class=\"skra-select-option-indicator\"\n [class.skra-select-option-indicator--checkbox]=\"multiple()\"\n aria-hidden=\"true\"\n ></span>\n `,\n styleUrl: './option.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.Emulated,\n host: {\n role: 'option',\n '[id]': 'optionId',\n '[attr.aria-selected]': 'selected() ? \"true\" : \"false\"',\n '[attr.data-skra-active]': 'active() ? \"\" : null',\n '(click)': 'onActivate()',\n // Disabled = the consumer's native `aria-disabled=\"true\"` (observed live) — no Forge binding.\n },\n})\nexport class SkraOption<T = unknown> implements SkraListboxKeyboardItem {\n /** The option's value (ADR 037 — consumer-owned; compared against the select's `value()`). */\n readonly value = input.required<T>();\n\n /** Stable id, the target of the trigger's `aria-activedescendant`. Internal — never consumer-facing. */\n readonly optionId = `skra-option-${nextOptionId++}`;\n\n private readonly el = inject<ElementRef<HTMLElement>>(ElementRef);\n private readonly select = inject(SKRA_LISTBOX_PANEL, { optional: true });\n\n private readonly leadingSlot = contentChild(SkraOptionLeading);\n private readonly detailSlot = contentChild(SkraOptionDetail);\n protected readonly hasLeading = computed(() => !!this.leadingSlot());\n protected readonly hasDetail = computed(() => !!this.detailSlot());\n\n /** Keyboard active-descendant highlight (ADR 0044 §7 — Highlightable, NOT roving focus). */\n protected readonly active = signal(false);\n\n /**\n * Cardinality hint from the parent panel (ADR 0046): `false` under `skra-select` → checkmark\n * indicator; `true` under `skra-multi-select` → checkbox indicator. The only thing the shared\n * `skra-option` reads to swap the component-rendered indicator. No public-API change.\n */\n protected readonly multiple = computed(() => this.select?.multiple ?? false);\n\n /** Selection is signal-derived (ADR 0045 / ADR 037): re-derives on parent `value()`/`compareWith()` or own `value()`. */\n protected readonly selected = computed(\n () => this.select?.isSelected(this.value()) ?? false,\n );\n\n constructor() {\n if (typeof ngDevMode === 'undefined' || ngDevMode) {\n if (!this.select) {\n console.warn(\n '[skra-option] has no <skra-select> ancestor — it is not registered with the keyboard ' +\n 'controller / selection model and cannot be picked. Project it inside a <skra-select>.',\n );\n }\n }\n }\n\n // ── SkraListboxKeyboardItem (driven by _SkraListboxKeyboard / CDK ActiveDescendantKeyManager) ──\n setActiveStyles(): void {\n this.active.set(true);\n }\n setInactiveStyles(): void {\n this.active.set(false);\n }\n\n /**\n * ADR 0045 Rule 1: the option's IDENTITY text (leading + label), EXCLUDING `[skra-option-detail]` and\n * the component-rendered indicator. Own-host `textContent` walk (the `skraMenuItem.getLabel()`\n * precedent) — drives the default trigger text AND type-ahead. Reading own content, NOT\n * `document.querySelector` (ADR 001-clean).\n */\n getLabel(): string {\n let text = '';\n const skip = (el: HTMLElement): boolean =>\n el.classList.contains('skra-select-option-detail') ||\n el.classList.contains('skra-select-option-indicator') ||\n el.hasAttribute('skra-option-detail');\n const walk = (node: Node): void => {\n if (node.nodeType === Node.TEXT_NODE) {\n text += node.textContent ?? '';\n return;\n }\n if (node.nodeType === Node.ELEMENT_NODE) {\n const el = node as HTMLElement;\n if (skip(el)) return;\n el.childNodes.forEach(walk);\n }\n };\n this.el.nativeElement.childNodes.forEach(walk);\n return text.replace(/\\s+/g, ' ').trim();\n }\n\n getValue(): unknown {\n return this.value();\n }\n\n /** Soft-disabled = the consumer's `aria-disabled=\"true\"` (native-attr-first, Menu precedent); read live. */\n get disabled(): boolean {\n return this.el.nativeElement.getAttribute('aria-disabled') === 'true';\n }\n\n protected onActivate(): void {\n if (this.disabled) return; // soft-disabled: not selectable (APG)\n this.select?.selectValue(this.value());\n }\n}\n","import { Directive } from '@angular/core';\n\n/**\n * SkraSelectTrigger — the opt-in rich-trigger marker (ADR 0045 Rule 2). Place on an `<ng-template>`\n * inside `<skra-select>`; the select reads it as a `TemplateRef` and stamps it in the trigger via\n * `ngTemplateOutlet` with `{ $implicit: value, option: selectedOption }` context — the ONLY supported\n * path for non-text (SVG/`<img>`) trigger presentation. With no trigger template the default trigger is\n * the selected option's `getLabel()` text (emoji/glyph leading content appears for free).\n *\n * <skra-select [value]=\"country()\" (valueChange)=\"country.set($event)\">\n * <ng-template skraSelectTrigger let-value>\n * <skra-icon [innerSVG]=\"flagOf(value)\"></skra-icon> {{ nameOf(value) }}\n * </ng-template>\n * <skra-option value=\"de\"><skra-icon [innerSVG]=\"flagOf('de')\"></skra-icon> Germany</skra-option>\n * </skra-select>\n */\n@Directive({\n selector: '[skraSelectTrigger]',\n standalone: true,\n})\nexport class SkraSelectTrigger {}\n","import {\r\n autoUpdate,\r\n computePosition,\r\n flip,\r\n offset as offsetMiddleware,\r\n shift,\r\n type Placement,\r\n} from '@floating-ui/dom';\r\n\r\n/**\r\n * Forge's single overlay positioning abstraction (ADR 0044 §3 rules 4–5).\r\n *\r\n * Wraps `@floating-ui/dom` so the library is an IMPLEMENTATION DETAIL: nothing outside this folder\r\n * imports it, and swapping the engine (e.g. to native CSS Anchor Positioning once it is baseline\r\n * cross-browser) is a one-file change with zero public-API impact.\r\n *\r\n * It writes **geometry only** (`left`/`top` + the resolved-side `data-skra-placement`) inline on the\r\n * floating element — the scoped geometry-only exception to ADR 021 / Visual Purism granted by\r\n * ADR 0044 §3 rule 4. It MUST NOT write any theme/state/token value inline (those stay `var(--skra-*)`\r\n * + `data-skra-*`). No portal, no z-index, no CDK, no library stylesheet.\r\n *\r\n * Decided at the first anchored component (Tooltip, 2026-06-06): a single JS path on all engines\r\n * (not native-CSS-primary + JS-fallback) — see ADR 0044 §7 + the rule-4 refinement note.\r\n */\r\n\r\n/** Forge placement intent — the base four sides; flip/shift adjust at runtime. */\r\nexport type SkraPlacement = 'top' | 'bottom' | 'left' | 'right';\r\n\r\nexport interface _PositionerOptions {\r\n /** Preferred side; `flip` re-sides on viewport collision. */\r\n placement: SkraPlacement;\r\n /** Gap between trigger and floating element, in px (resolved from a comp token by the caller). */\r\n offset?: number;\r\n /** Minimum distance from the viewport edge for `shift`, in px. */\r\n viewportPadding?: number;\r\n}\r\n\r\nexport interface _PositionerHandle {\r\n /** Stop repositioning and release the `autoUpdate` listeners. Idempotent. */\r\n destroy(): void;\r\n}\r\n\r\n/**\r\n * Anchor `floating` to `reference` and keep it positioned while visible. Returns a handle whose\r\n * `destroy()` MUST be called when the overlay hides or the owner is destroyed (no listener leak).\r\n *\r\n * `options` is a getter so live token values (offset) are re-read on every reposition.\r\n */\r\nexport function _attachPositioner(\r\n reference: HTMLElement,\r\n floating: HTMLElement,\r\n options: () => _PositionerOptions,\r\n): _PositionerHandle {\r\n let destroyed = false;\r\n let seq = 0;\r\n\r\n const update = (): void => {\r\n const { placement, offset = 0, viewportPadding = 8 } = options();\r\n // `computePosition` is async, so two things can go wrong between call and settle: the handle can\r\n // be destroyed (writing geometry onto a detached / hidden node), and a newer update can settle\r\n // first (landing stale coordinates). Guard on both — this file positions every overlay in the\r\n // library, so a two-line guard is cheap insurance.\r\n const token = ++seq;\r\n computePosition(reference, floating, {\r\n strategy: 'fixed', // floating element renders in the top layer → viewport-relative\r\n placement: placement as Placement,\r\n middleware: [\r\n offsetMiddleware(offset),\r\n // NOTE: `flip()` deliberately left unpadded pending a decision — see the review residual.\r\n // Giving it `viewportPadding` would change resolved placement for all 7 overlay consumers\r\n // with no visual test to catch a regression; that is a measured change, not a cleanup.\r\n flip(),\r\n shift({ padding: viewportPadding }),\r\n ],\r\n })\r\n .then(({ x, y, placement: resolved }) => {\r\n if (destroyed || token !== seq) return;\r\n // Geometry only (ADR 0044 §3 rule 4). Never theme/state.\r\n floating.style.left = `${x}px`;\r\n floating.style.top = `${y}px`;\r\n // Resolved side (post-flip) for orientation CSS / future arrow — a data-attr, not a style.\r\n floating.setAttribute('data-skra-placement', resolved.split('-')[0]);\r\n })\r\n .catch(() => {\r\n // Positioning is best-effort: a rejection must never surface as an unhandled rejection\r\n // (fatal under Node, e.g. any future SSR/prerender path).\r\n });\r\n };\r\n\r\n // autoUpdate repositions on scroll, resize and element resize; returns its own cleanup.\r\n const cleanup = autoUpdate(reference, floating, update);\r\n return {\r\n destroy(): void {\r\n if (destroyed) return;\r\n destroyed = true;\r\n cleanup();\r\n },\r\n };\r\n}\r\n","import { ActiveDescendantKeyManager } from '@angular/cdk/a11y';\n\nimport type { SkraListboxKeyboardItem } from './select-types';\n\n/**\n * _SkraListboxKeyboard — the WAI-ARIA APG **Select-Only Combobox** listbox keyboard model, confined to\n * ONE file. Sibling to `menu-keyboard.ts`: per ADR 0044 §7 (2026-06-07), `@angular/cdk/a11y` is confined\n * to one swappable `*-keyboard.ts` controller PER APG pattern. Menu uses `FocusKeyManager` (roving REAL\n * focus); the listbox uses **`ActiveDescendantKeyManager`** — focus STAYS on the combobox trigger and the\n * active option is virtual (`aria-activedescendant`), the APG-canonical select-only model. Swapping the\n * engine is a one-file change, exactly as `SkraPositioner` wraps `@floating-ui/dom`.\n *\n * Owns: Down/Up active-descendant movement, Home/End, and type-ahead. Enter/Space (select), Escape and\n * light-dismiss (`popover=\"auto\"`) stay with the select / platform — this controller never touches them.\n */\nexport class _SkraListboxKeyboard {\n private manager?: ActiveDescendantKeyManager<SkraListboxKeyboardItem>;\n private items: SkraListboxKeyboardItem[] = [];\n private changeHandler?: (item: SkraListboxKeyboardItem | null) => void;\n\n /** Notified whenever the active descendant changes — the select mirrors it to `aria-activedescendant`. */\n onActiveChange(\n handler: (item: SkraListboxKeyboardItem | null) => void,\n ): void {\n this.changeHandler = handler;\n }\n\n /**\n * (Re)build the manager from the current projected option set. Called from an `effect` on the select's\n * signal `contentChildren` — a passed array is a static snapshot (it does not auto-track like a live\n * `QueryList`), so the manager is rebuilt whenever the option set changes (the documented signal↔CDK seam).\n */\n setItems(items: readonly SkraListboxKeyboardItem[]): void {\n this.items = [...items];\n this.manager?.destroy();\n this.manager = new ActiveDescendantKeyManager<SkraListboxKeyboardItem>(\n this.items,\n )\n .withTypeAhead()\n .withHomeAndEnd()\n // Disabled options stay navigable (APG-discoverable); selection is guarded by the select.\n // `() => false` also stops the manager from reading `item.disabled` to skip-during-navigation.\n .skipPredicate(() => false);\n this.manager.change.subscribe((index) =>\n this.changeHandler?.(this.items[index] ?? null),\n );\n }\n\n /** Delegate Down/Up/Home/End/type-ahead. Enter/Space/Escape are intentionally left to the select/platform. */\n onKeydown(event: KeyboardEvent): void {\n this.manager?.onKeydown(event);\n }\n\n get activeItem(): SkraListboxKeyboardItem | null {\n return this.manager?.activeItem ?? null;\n }\n\n /** Seed the active descendant on open: the selected option, else the first. */\n setActive(item: SkraListboxKeyboardItem | null): void {\n if (!this.manager) return;\n if (item) this.manager.setActiveItem(item);\n else this.manager.setFirstItemActive();\n }\n\n /** Deactivate (close): `setActiveItem(-1)` clears `_activeItem` and the highlight. */\n clearActive(): void {\n this.manager?.setActiveItem(-1);\n }\n\n destroy(): void {\n this.manager?.destroy();\n this.manager = undefined;\n }\n}\n","import {\n DestroyRef,\n Directive,\n ElementRef,\n booleanAttribute,\n computed,\n contentChildren,\n effect,\n inject,\n input,\n signal,\n viewChild,\n} from '@angular/core';\nimport { SkraFieldContext } from '@skra/ui/field';\n\nimport {\n _attachPositioner,\n type SkraPlacement,\n type _PositionerHandle,\n} from '../positioning/positioner';\nimport { _SkraListboxKeyboard } from './listbox-keyboard';\nimport { SkraOption } from './option';\nimport type { SkraListboxKeyboardItem, SkraListboxPanel } from './select-types';\n\nlet nextListboxId = 0;\n\n/**\n * _SkraListboxWidgetBase — the **trigger-shape-agnostic** core shared by every Forge listbox widget,\n * per the **ADR 0046 amendment (2026-06-13)**. It owns ONLY the substrate that does not depend on what\n * the trigger looks like: the `SkraFieldContext` cascade (ADR 013), the panel `(toggle)` →\n * `SkraPositioner` lifecycle + active-descendant seeding, the `_SkraListboxKeyboard` wiring\n * (CDK `ActiveDescendantKeyManager`, ADR 0044 §7), imperative `open()`/`close()`, teardown, and the\n * abstract `SkraListboxPanel` selection seam.\n *\n * Trigger BEHAVIOUR lives one level down, in a per-shape base:\n * - `_SkraSelectBase` adds the button + native `popovertarget` + type-ahead trigger (Select-Only\n * Combobox) and the ADR 0045 `[skraSelectTrigger]` rich-trigger template.\n * - `SkraCombobox` (no extra base) adds the editable `<input>` + filter-output trigger (ADR 0049).\n *\n * The keydown skeleton is NOT here — each trigger shape routes keys differently (the select selects on\n * Space and type-aheads; the combobox types into the input and never type-aheads). Forcing one keydown\n * through both shapes is the wrong abstraction.\n *\n * `panelTokenPrefix` makes the panel comp-token namespace overridable so each widget reads its OWN\n * `--skra-comp-<prefix>-panel-*` tokens (`select` for the select family, `combobox` for the combobox).\n *\n * Full contracts: adr/specs/component-{select,multi-select,combobox}-spec.md.\n */\n@Directive({\n host: {\n // Shell state reflection for the skin (the trigger control carries the ARIA + native disabled).\n '[attr.data-skra-disabled]': 'isDisabled() ? \"\" : null',\n '[attr.data-skra-readonly]': 'isReadonly() ? \"\" : null',\n '[attr.data-skra-validation]': 'hasError() ? \"invalid\" : null',\n },\n})\nexport abstract class _SkraListboxWidgetBase<T = unknown>\n implements SkraListboxPanel\n{\n /** Equality strategy seam (ADR 037 selection model): default `Object.is`; object values pass a custom comparator. */\n readonly compareWith = input<(a: T, b: T) => boolean>(Object.is);\n /** Value-empty hint shown in the trigger (NOT the accessible name — ADR 033). */\n readonly placeholder = input<string>('');\n /** Placement intent; flip/shift adjust at runtime. */\n readonly placement = input<SkraPlacement>('bottom');\n /** Standalone availability source (Q-1) — `SkraFieldContext` wins when present. */\n readonly disabled = input(false, { transform: booleanAttribute });\n readonly readonly = input(false, { transform: booleanAttribute });\n\n protected readonly options = contentChildren(SkraOption);\n\n protected readonly triggerRef = viewChild<ElementRef<HTMLElement>>('trigger');\n protected readonly panelRef = viewChild<ElementRef<HTMLElement>>('panel');\n\n protected readonly context = inject(SkraFieldContext, { optional: true });\n protected readonly keyboard = new _SkraListboxKeyboard();\n\n readonly panelId = `skra-listbox-${nextListboxId++}`;\n protected readonly isOpen = signal(false);\n protected readonly activeOptionId = signal<string | null>(null);\n\n private positioner?: _PositionerHandle;\n\n /** Panel comp-token namespace — `--skra-comp-<panelTokenPrefix>-panel-*`. Overridden per widget. */\n protected abstract readonly panelTokenPrefix: string;\n\n // ── Availability / validation (SkraFieldContext, ADR 013, with standalone fallbacks — Q-1) ──\n protected readonly isDisabled = computed(\n () => this.context?.isDisabled() ?? this.disabled(),\n );\n protected readonly isReadonly = computed(\n () => this.context?.isReadonly() ?? this.readonly(),\n );\n protected readonly hasError = computed(\n () => this.context?.hasError() ?? false,\n );\n protected readonly isRequired = computed(\n () => this.context?.isRequired() ?? false,\n );\n protected readonly triggerId = computed(\n () => this.context?.fieldId() || null,\n );\n protected readonly describedBy = computed(\n () => this.context?.describedByIds() ?? null,\n );\n\n constructor() {\n // Feed the keyboard controller whenever the projected option set changes (signal → array rebuild).\n effect(() => this.keyboard.setItems(this.options()));\n // Mirror the active descendant to the trigger's aria-activedescendant.\n this.keyboard.onActiveChange((item) =>\n this.activeOptionId.set(item?.optionId ?? null),\n );\n inject(DestroyRef).onDestroy(() => this.teardown());\n }\n\n // ── SkraListboxPanel seam — the per-widget divergence (implemented by each concrete) ──\n /** Live selection test: single = equality, multi = membership (both via `compareWith`). */\n abstract isSelected(value: unknown): boolean;\n /** User picked a value: single = replace + close; multi = toggle membership + keep open. */\n abstract selectValue(value: unknown): void;\n /** Cardinality hint read by `skra-option` for the indicator swap — `false` single / `true` multi. */\n abstract readonly multiple: boolean;\n /** Seed the active descendant on open: single = the selected option; multi = the first selected. */\n protected abstract activeSeedItem(): SkraListboxKeyboardItem | null;\n\n // ── Panel open / close (native toggle from the Popover API) ──\n protected onPanelToggle(event: Event): void {\n const open = (event as ToggleEvent).newState === 'open';\n this.isOpen.set(open);\n if (open) this.onOpen();\n else this.onClose();\n }\n\n /**\n * The element the panel is positioned against AND matched in width to (Q-5). Defaults to the trigger\n * — correct for the select family, whose trigger button fills the host. The combobox overrides it to\n * the host box, because its trigger is the INNER input (narrower than the bordered box + chevron), so\n * the panel must align to and match the box, not the input — visual parity with select.\n */\n protected positioningAnchor(): HTMLElement | undefined {\n return this.triggerRef()?.nativeElement;\n }\n\n private onOpen(): void {\n const anchor = this.positioningAnchor();\n const panel = this.panelRef()?.nativeElement;\n if (anchor && panel) {\n // Geometry-only (ADR 0044 §3 rule 4): the panel is at least as wide as the anchor (Q-5).\n panel.style.minInlineSize = `${anchor.offsetWidth}px`;\n this.positioner?.destroy();\n this.positioner = _attachPositioner(anchor, panel, () => ({\n placement: this.placement(),\n offset: this.cssLenPx(\n `--skra-comp-${this.panelTokenPrefix}-panel-offset`,\n ),\n viewportPadding: this.cssLenPx(\n `--skra-comp-${this.panelTokenPrefix}-panel-viewport-padding`,\n ),\n }));\n }\n // Seed the active descendant (single → selected; multi → first selected, else first).\n this.keyboard.setActive(this.activeSeedItem());\n }\n\n private onClose(): void {\n this.positioner?.destroy();\n this.positioner = undefined;\n this.keyboard.clearActive();\n this.activeOptionId.set(null);\n }\n\n /** Select the keyboard's active option (Enter), unless it is soft-disabled. Shared by every trigger shape. */\n protected selectActive(): void {\n const active = this.keyboard.activeItem;\n if (active && !active.disabled) this.selectValue(active.getValue());\n }\n\n protected open(): void {\n this.panelRef()?.nativeElement.showPopover?.();\n }\n protected close(): void {\n this.panelRef()?.nativeElement.hidePopover?.();\n }\n\n /** Read a length comp token (px/rem) off the panel computed style for the positioner. */\n private cssLenPx(prop: string): number {\n const el = this.panelRef()?.nativeElement;\n if (!el) return 0;\n const raw = getComputedStyle(el).getPropertyValue(prop).trim();\n if (raw.endsWith('px')) return parseFloat(raw);\n if (raw.endsWith('rem')) {\n const rootFontSize =\n parseFloat(getComputedStyle(document.documentElement).fontSize) || 16;\n return parseFloat(raw) * rootFontSize;\n }\n return parseFloat(raw) || 0;\n }\n\n private teardown(): void {\n this.keyboard.destroy();\n this.positioner?.destroy();\n }\n}\n","import { Directive, TemplateRef, contentChild } from '@angular/core';\r\n\r\nimport { _SkraListboxWidgetBase } from './listbox-widget-base';\r\nimport { SkraSelectTrigger } from './select-trigger';\r\n\r\n/**\r\n * _SkraSelectBase — the SELECT-family trigger model over {@link _SkraListboxWidgetBase}: the WAI-ARIA APG\r\n * **Select-Only Combobox** trigger. It adds the `<button>` + native `popovertarget` interaction, the\r\n * type-ahead keydown skeleton, and the ADR 0045 `[skraSelectTrigger]` rich-trigger template. Shared by\r\n * `skra-select` (single) and `skra-multi-select` (multi) — the cardinality split (ADR 0046) lives in\r\n * those concretes (the `SkraListboxPanel` seam: single replaces + closes, multi toggles + stays open).\r\n *\r\n * The trigger-shape-agnostic substrate (field cascade, panel toggle/positioner, keyboard wiring,\r\n * open/close, the selection seam) lives in the parent base, shared verbatim with `skra-combobox`\r\n * (which has a different — editable input — trigger; ADR 0046 amendment 2026-06-13).\r\n *\r\n * Full contract: adr/specs/component-select-spec.md + adr/specs/component-multi-select-spec.md.\r\n */\r\n@Directive()\r\nexport abstract class _SkraSelectBase<\r\n T = unknown,\r\n> extends _SkraListboxWidgetBase<T> {\r\n /** Select-family panel token namespace — `--skra-comp-select-panel-*` (shared single + multi). */\r\n protected readonly panelTokenPrefix = 'select';\r\n\r\n /** Opt-in rich trigger template (ADR 0045 Rule 2). Select-family only — a combobox input shows text. */\r\n protected readonly triggerTemplate = contentChild(SkraSelectTrigger, {\r\n read: TemplateRef,\r\n });\r\n\r\n // ── Trigger interaction (button + native popovertarget) ──\r\n protected onTriggerClick(event: MouseEvent): void {\r\n // Block the native popovertarget open when readonly (disabled is unfocusable/inert natively).\r\n if (this.isReadonly()) event.preventDefault();\r\n }\r\n\r\n protected onTriggerKeydown(event: KeyboardEvent): void {\r\n if (this.isDisabled() || this.isReadonly()) return; // never opens / never mutates\r\n const key = event.key;\r\n const isSpace = key === ' ' || key === 'Spacebar';\r\n const isNav =\r\n key === 'ArrowDown' ||\r\n key === 'ArrowUp' ||\r\n key === 'Home' ||\r\n key === 'End';\r\n const isPrintable =\r\n key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey;\r\n\r\n if (!this.isOpen()) {\r\n // Single open path: suppress the popovertarget's own toggle (Enter/Space) too and open here.\r\n if (isNav || isSpace || key === 'Enter' || isPrintable) {\r\n event.preventDefault();\r\n this.open();\r\n }\r\n return;\r\n }\r\n\r\n // Open:\r\n if (key === 'Enter' || isSpace) {\r\n // Suppress the popovertarget toggle; the concrete `selectValue` decides close (single) vs stay-open (multi).\r\n event.preventDefault();\r\n this.selectActive();\r\n return;\r\n }\r\n if (key === 'Tab') {\r\n this.close(); // APG: Tab closes (keep value); focus proceeds (no preventDefault)\r\n return;\r\n }\r\n if (key === 'Escape') return; // platform (popover=\"auto\") closes; onPanelToggle handles cleanup\r\n if (key === 'ArrowUp' && event.altKey) {\r\n // APG select-only combobox: Alt+Up closes and keeps the current value, focus stays on the\r\n // trigger. Must be handled BEFORE the nav branch — `ArrowUp` is `isNav`, so it would otherwise\r\n // be preventDefault'ed and handed to the key manager, which ignores modified arrows: the\r\n // keystroke did nothing at all.\r\n event.preventDefault();\r\n this.close();\r\n return;\r\n }\r\n if (isNav || isPrintable) {\r\n event.preventDefault();\r\n this.keyboard.onKeydown(event); // move / type-ahead the active descendant\r\n }\r\n }\r\n}\r\n","// @skra/ui/core — shared internal satellites (ADR 0054). Consumed cross-entry by\n// select / multi-select / combobox / datepicker / menu / popover / tooltip.\n\n// --- Public shared surface ---\nexport * from './lib/select/option';\nexport * from './lib/select/option.directives';\nexport * from './lib/select/select-trigger';\nexport {\n SKRA_LISTBOX_PANEL,\n type SkraListboxPanel,\n type SkraListboxKeyboardItem,\n} from './lib/select/select-types';\n\n// --- Internal shared bases (`_`-prefixed = outside SemVer, ADR 0054 R-54.4/R-54.5) ---\nexport * from './lib/select/select-base';\nexport * from './lib/select/listbox-widget-base';\n// Positioner: `_attachPositioner`/`_PositionerOptions`/`_PositionerHandle` are internal\n// (`_`-prefixed = outside SemVer — O-33 (6a) done). `SkraPlacement` is PUBLIC by ruling\n// (consumer-facing placement inputs, re-exported by tooltip/popover/menu/datepicker).\n// See ADR 0054 §7 (2026-07-03 note); enforced by export-surface-validator.\nexport * from './lib/positioning/positioner';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":["offset","offsetMiddleware"],"mappings":"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"}
|
|
@@ -57,7 +57,7 @@ class SkraInput {
|
|
|
57
57
|
}
|
|
58
58
|
}
|
|
59
59
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.1", ngImport: i0, type: SkraInput, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
60
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.1.1", type: SkraInput, isStandalone: true, selector: "input[skraInput]", host: { properties: { "attr.aria-describedby": "context?.describedByIds() ?? null", "attr.aria-invalid": "context?.hasError() ? \"true\" : null", "attr.aria-required": "context?.isRequired() ? \"true\" : null" } }, ngImport: i0, template: '', isInline: true, styles: [":host{background:var(--skra-comp-field-background);color:var(--skra-comp-field-foreground);border-color:var(--skra-comp-field-border-color);border-width:var(--skra-comp-field-border-width);border-style:var(--skra-comp-field-border-style);border-radius:var(--skra-comp-field-radius);padding-block:var(--skra-comp-field-padding-block);padding-inline:var(--skra-comp-field-padding-inline);box-shadow:var(--skra-comp-field-shadow);font:inherit;outline:none;transition:background-color var(--skra-comp-field-motion-duration) var(--skra-comp-field-motion-easing),border-color var(--skra-comp-field-motion-duration) var(--skra-comp-field-motion-easing),color var(--skra-comp-field-motion-duration) var(--skra-comp-field-motion-easing),box-shadow var(--skra-comp-field-motion-duration) var(--skra-comp-field-motion-easing)}@media(hover:hover)and (pointer:fine){:host(:hover:not(:disabled):not([readonly])){background:var(--skra-comp-field-background-hover);border-color:var(--skra-comp-field-border-color-hover)}}:host(:focus-visible){border-color:var(--skra-comp-field-focus-ring-color);box-shadow:0 0 0 var(--skra-comp-field-focus-ring-width) var(--skra-comp-field-focus-ring-color)}:host(:disabled){cursor:not-allowed;opacity:var(--skra-sys-opacity-disabled)}:host([readonly]){cursor:default}:host([aria-invalid=true]){border-color:var(--skra-comp-field-error-color)}:host([aria-invalid=true]:focus-visible){box-shadow:0 0 0 var(--skra-comp-field-focus-ring-width) var(--skra-comp-field-error-color)}:host([type=date]),:host([type=month]),:host([type=week]),:host([type=time]),:host([type=datetime-local]){min-block-size:var(--skra-comp-field-temporal-min-block-size);padding-inline-end:var(--skra-comp-field-temporal-indicator-padding-inline-end)}:host([type=date])::-webkit-calendar-picker-indicator,:host([type=month])::-webkit-calendar-picker-indicator,:host([type=week])::-webkit-calendar-picker-indicator,:host([type=datetime-local])::-webkit-calendar-picker-indicator{background-image:var(--skra-comp-field-calendar-indicator-glyph)}:host([type=time])::-webkit-calendar-picker-indicator{background-image:var(--skra-comp-field-clock-indicator-glyph)}:host([type=date])::-webkit-calendar-picker-indicator,:host([type=month])::-webkit-calendar-picker-indicator,:host([type=week])::-webkit-calendar-picker-indicator,:host([type=time])::-webkit-calendar-picker-indicator,:host([type=datetime-local])::-webkit-calendar-picker-indicator{inline-size:var(--skra-comp-field-temporal-indicator-icon-size);block-size:var(--skra-comp-field-temporal-indicator-icon-size);background-repeat:no-repeat;background-position:center;background-size:contain;opacity:1;cursor:pointer}:host(:disabled)::-webkit-calendar-picker-indicator{cursor:not-allowed}:host::-webkit-datetime-edit{color:var(--skra-comp-field-foreground)}@media(prefers-reduced-motion:reduce){:host{transition:none}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
60
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.1.1", type: SkraInput, isStandalone: true, selector: "input[skraInput]", host: { properties: { "attr.aria-describedby": "context?.describedByIds() ?? null", "attr.aria-invalid": "context?.hasError() ? \"true\" : null", "attr.aria-required": "context?.isRequired() ? \"true\" : null" } }, ngImport: i0, template: '', isInline: true, styles: [":host{background:var(--skra-comp-field-background);color:var(--skra-comp-field-foreground);border-color:var(--skra-comp-field-border-color);border-width:var(--skra-comp-field-border-width);border-style:var(--skra-comp-field-border-style);border-radius:var(--skra-comp-field-radius);padding-block:var(--skra-comp-field-padding-block);padding-inline:var(--skra-comp-field-padding-inline);box-shadow:var(--skra-comp-field-shadow);font:inherit;outline:none;transition:background-color var(--skra-comp-field-motion-duration) var(--skra-comp-field-motion-easing),border-color var(--skra-comp-field-motion-duration) var(--skra-comp-field-motion-easing),color var(--skra-comp-field-motion-duration) var(--skra-comp-field-motion-easing),box-shadow var(--skra-comp-field-motion-duration) var(--skra-comp-field-motion-easing)}@media(hover:hover)and (pointer:fine){:host(:hover:not(:disabled):not([readonly])){background:var(--skra-comp-field-background-hover);border-color:var(--skra-comp-field-border-color-hover)}}:host(:focus-visible){border-color:var(--skra-comp-field-focus-ring-color);box-shadow:0 0 0 var(--skra-comp-field-focus-ring-width) var(--skra-comp-field-focus-ring-color)}:host(:disabled){cursor:not-allowed;opacity:var(--skra-sys-opacity-disabled)}:host([readonly]){cursor:default}:host([aria-invalid=true]){border-color:var(--skra-comp-field-error-color)}:host([aria-invalid=true]:focus-visible){box-shadow:0 0 0 var(--skra-comp-field-focus-ring-width) var(--skra-comp-field-error-color)}:host([type=date]),:host([type=month]),:host([type=week]),:host([type=time]),:host([type=datetime-local]){box-sizing:border-box;min-block-size:var(--skra-comp-field-temporal-min-block-size);padding-inline-end:var(--skra-comp-field-temporal-indicator-padding-inline-end)}:host([type=date])::-webkit-calendar-picker-indicator,:host([type=month])::-webkit-calendar-picker-indicator,:host([type=week])::-webkit-calendar-picker-indicator,:host([type=datetime-local])::-webkit-calendar-picker-indicator{background-image:var(--skra-comp-field-calendar-indicator-glyph)}:host([type=time])::-webkit-calendar-picker-indicator{background-image:var(--skra-comp-field-clock-indicator-glyph)}:host([type=date])::-webkit-calendar-picker-indicator,:host([type=month])::-webkit-calendar-picker-indicator,:host([type=week])::-webkit-calendar-picker-indicator,:host([type=time])::-webkit-calendar-picker-indicator,:host([type=datetime-local])::-webkit-calendar-picker-indicator{inline-size:var(--skra-comp-field-temporal-indicator-icon-size);block-size:var(--skra-comp-field-temporal-indicator-icon-size);background-repeat:no-repeat;background-position:center;background-size:contain;opacity:1;cursor:pointer}:host(:disabled)::-webkit-calendar-picker-indicator{cursor:not-allowed}:host::-webkit-datetime-edit{color:var(--skra-comp-field-foreground)}:host::-webkit-datetime-edit-fields-wrapper{padding-block:0}@media(prefers-reduced-motion:reduce){:host{transition:none}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
61
61
|
}
|
|
62
62
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.1", ngImport: i0, type: SkraInput, decorators: [{
|
|
63
63
|
type: Component,
|
|
@@ -72,7 +72,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.1", ngImpor
|
|
|
72
72
|
// state is forbidden). Readonly styling keys off `:read-only`/`[readonly]`.
|
|
73
73
|
// The native props are driven imperatively below, NOT as host bindings —
|
|
74
74
|
// see the constructor note on standalone attribute ownership.
|
|
75
|
-
}, styles: [":host{background:var(--skra-comp-field-background);color:var(--skra-comp-field-foreground);border-color:var(--skra-comp-field-border-color);border-width:var(--skra-comp-field-border-width);border-style:var(--skra-comp-field-border-style);border-radius:var(--skra-comp-field-radius);padding-block:var(--skra-comp-field-padding-block);padding-inline:var(--skra-comp-field-padding-inline);box-shadow:var(--skra-comp-field-shadow);font:inherit;outline:none;transition:background-color var(--skra-comp-field-motion-duration) var(--skra-comp-field-motion-easing),border-color var(--skra-comp-field-motion-duration) var(--skra-comp-field-motion-easing),color var(--skra-comp-field-motion-duration) var(--skra-comp-field-motion-easing),box-shadow var(--skra-comp-field-motion-duration) var(--skra-comp-field-motion-easing)}@media(hover:hover)and (pointer:fine){:host(:hover:not(:disabled):not([readonly])){background:var(--skra-comp-field-background-hover);border-color:var(--skra-comp-field-border-color-hover)}}:host(:focus-visible){border-color:var(--skra-comp-field-focus-ring-color);box-shadow:0 0 0 var(--skra-comp-field-focus-ring-width) var(--skra-comp-field-focus-ring-color)}:host(:disabled){cursor:not-allowed;opacity:var(--skra-sys-opacity-disabled)}:host([readonly]){cursor:default}:host([aria-invalid=true]){border-color:var(--skra-comp-field-error-color)}:host([aria-invalid=true]:focus-visible){box-shadow:0 0 0 var(--skra-comp-field-focus-ring-width) var(--skra-comp-field-error-color)}:host([type=date]),:host([type=month]),:host([type=week]),:host([type=time]),:host([type=datetime-local]){min-block-size:var(--skra-comp-field-temporal-min-block-size);padding-inline-end:var(--skra-comp-field-temporal-indicator-padding-inline-end)}:host([type=date])::-webkit-calendar-picker-indicator,:host([type=month])::-webkit-calendar-picker-indicator,:host([type=week])::-webkit-calendar-picker-indicator,:host([type=datetime-local])::-webkit-calendar-picker-indicator{background-image:var(--skra-comp-field-calendar-indicator-glyph)}:host([type=time])::-webkit-calendar-picker-indicator{background-image:var(--skra-comp-field-clock-indicator-glyph)}:host([type=date])::-webkit-calendar-picker-indicator,:host([type=month])::-webkit-calendar-picker-indicator,:host([type=week])::-webkit-calendar-picker-indicator,:host([type=time])::-webkit-calendar-picker-indicator,:host([type=datetime-local])::-webkit-calendar-picker-indicator{inline-size:var(--skra-comp-field-temporal-indicator-icon-size);block-size:var(--skra-comp-field-temporal-indicator-icon-size);background-repeat:no-repeat;background-position:center;background-size:contain;opacity:1;cursor:pointer}:host(:disabled)::-webkit-calendar-picker-indicator{cursor:not-allowed}:host::-webkit-datetime-edit{color:var(--skra-comp-field-foreground)}@media(prefers-reduced-motion:reduce){:host{transition:none}}\n"] }]
|
|
75
|
+
}, styles: [":host{background:var(--skra-comp-field-background);color:var(--skra-comp-field-foreground);border-color:var(--skra-comp-field-border-color);border-width:var(--skra-comp-field-border-width);border-style:var(--skra-comp-field-border-style);border-radius:var(--skra-comp-field-radius);padding-block:var(--skra-comp-field-padding-block);padding-inline:var(--skra-comp-field-padding-inline);box-shadow:var(--skra-comp-field-shadow);font:inherit;outline:none;transition:background-color var(--skra-comp-field-motion-duration) var(--skra-comp-field-motion-easing),border-color var(--skra-comp-field-motion-duration) var(--skra-comp-field-motion-easing),color var(--skra-comp-field-motion-duration) var(--skra-comp-field-motion-easing),box-shadow var(--skra-comp-field-motion-duration) var(--skra-comp-field-motion-easing)}@media(hover:hover)and (pointer:fine){:host(:hover:not(:disabled):not([readonly])){background:var(--skra-comp-field-background-hover);border-color:var(--skra-comp-field-border-color-hover)}}:host(:focus-visible){border-color:var(--skra-comp-field-focus-ring-color);box-shadow:0 0 0 var(--skra-comp-field-focus-ring-width) var(--skra-comp-field-focus-ring-color)}:host(:disabled){cursor:not-allowed;opacity:var(--skra-sys-opacity-disabled)}:host([readonly]){cursor:default}:host([aria-invalid=true]){border-color:var(--skra-comp-field-error-color)}:host([aria-invalid=true]:focus-visible){box-shadow:0 0 0 var(--skra-comp-field-focus-ring-width) var(--skra-comp-field-error-color)}:host([type=date]),:host([type=month]),:host([type=week]),:host([type=time]),:host([type=datetime-local]){box-sizing:border-box;min-block-size:var(--skra-comp-field-temporal-min-block-size);padding-inline-end:var(--skra-comp-field-temporal-indicator-padding-inline-end)}:host([type=date])::-webkit-calendar-picker-indicator,:host([type=month])::-webkit-calendar-picker-indicator,:host([type=week])::-webkit-calendar-picker-indicator,:host([type=datetime-local])::-webkit-calendar-picker-indicator{background-image:var(--skra-comp-field-calendar-indicator-glyph)}:host([type=time])::-webkit-calendar-picker-indicator{background-image:var(--skra-comp-field-clock-indicator-glyph)}:host([type=date])::-webkit-calendar-picker-indicator,:host([type=month])::-webkit-calendar-picker-indicator,:host([type=week])::-webkit-calendar-picker-indicator,:host([type=time])::-webkit-calendar-picker-indicator,:host([type=datetime-local])::-webkit-calendar-picker-indicator{inline-size:var(--skra-comp-field-temporal-indicator-icon-size);block-size:var(--skra-comp-field-temporal-indicator-icon-size);background-repeat:no-repeat;background-position:center;background-size:contain;opacity:1;cursor:pointer}:host(:disabled)::-webkit-calendar-picker-indicator{cursor:not-allowed}:host::-webkit-datetime-edit{color:var(--skra-comp-field-foreground)}:host::-webkit-datetime-edit-fields-wrapper{padding-block:0}@media(prefers-reduced-motion:reduce){:host{transition:none}}\n"] }]
|
|
76
76
|
}], ctorParameters: () => [] });
|
|
77
77
|
|
|
78
78
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skra-ui-input.mjs","sources":["../../../../libs/ui/input/src/lib/input/input.ts","../../../../libs/ui/input/src/skra-ui-input.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n ElementRef,\n ViewEncapsulation,\n effect,\n inject,\n} from '@angular/core';\nimport { SkraFieldContext } from '@skra/ui/field';\n\n/**\n * `input[skraInput]` — text-input atom. Per ADR 040 this is a\n * Component-on-a-native-host (not a directive): `<input>` is a void element, so\n * `template: ''` is correct — there is no consumer content to project. Angular\n * Emulated encapsulation scopes `input.scss` to the host, the same way\n * <skra-button> carries its own CSS. Replaces the ADR 038 global slice branch.\n *\n * DI wiring (ADR 013), host a11y bindings (ADR 021/027), and the agnostic\n * value posture (ADR 037 — no value channel, no @angular/forms) are unchanged\n * from the prior directive form.\n *\n * `SkraFieldContext` is injected `{ optional: true }` (ADR 013 §3.7) — the same\n * posture as `skraCheckbox` / `skraRadio` / `skraSwitch`. Inside `<skra-field>`\n * the atom takes the field's id + describedby + availability cascade; standalone\n * it renders the skin only and the consumer owns every attribute, including the\n * accessible name:\n *\n * <!-- inside Field — label association via the DI-generated id/for pair -->\n * <skra-field>\n * <label skraLabelFor>Email</label>\n * <input skraInput type=\"email\" />\n * </skra-field>\n *\n * <!-- standalone: native implicit label (wrapping) — no id/for needed -->\n * <label>Search <input skraInput type=\"search\" /></label>\n *\n * Standalone use does NOT relax the ADR 033 accessible-name contract; it moves\n * the name onto the consumer's own native markup. An input with no name is an\n * a11y defect wherever it appears — including inside a `<skra-field>` that\n * carries no `label[skraLabelFor]` — so the check belongs to the a11y gate, not\n * to this injection site (ADR 013 §3.7).\n */\n@Component({\n selector: 'input[skraInput]',\n standalone: true,\n // Void host — no <ng-content>. See ADR 040 §2.\n template: '',\n styleUrl: './input.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.Emulated,\n host: {\n // ARIA relationships — Skra-owned, present only while a field cascades them.\n '[attr.aria-describedby]': 'context?.describedByIds() ?? null',\n '[attr.aria-invalid]': 'context?.hasError() ? \"true\" : null',\n '[attr.aria-required]': 'context?.isRequired() ? \"true\" : null',\n // Availability — native attrs only (native-attr-first, boundary #9). <input>\n // supports native `readonly`/`disabled`, which AT already exposes; NO\n // `aria-readonly`/`aria-disabled` here (setting both native + ARIA for one\n // state is forbidden). Readonly styling keys off `:read-only`/`[readonly]`.\n // The native props are driven imperatively below, NOT as host bindings —\n // see the constructor note on standalone attribute ownership.\n },\n})\nexport class SkraInput {\n private readonly el = inject<ElementRef<HTMLInputElement>>(ElementRef);\n readonly context = inject(SkraFieldContext, { optional: true });\n\n constructor() {\n const el = this.el.nativeElement;\n\n // Field-cascaded native properties — only bind when context is present so\n // standalone consumers retain full control of their static attributes\n // (a host `[attr.disabled]=\"null\"` binding would strip a consumer-authored\n // `disabled` / `readonly` / `id`). Mirrors SkraCheckbox.\n if (this.context) {\n const ctx = this.context;\n effect(() => {\n el.id = ctx.fieldId();\n });\n effect(() => {\n el.disabled = ctx.isDisabled();\n });\n effect(() => {\n el.readOnly = ctx.isReadonly();\n });\n }\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;AAUA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+BG;MAsBU,SAAS,CAAA;AACH,IAAA,EAAE,GAAG,MAAM,CAA+B,UAAU,CAAC;IAC7D,OAAO,GAAG,MAAM,CAAC,gBAAgB,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;AAE/D,IAAA,WAAA,GAAA;AACE,QAAA,MAAM,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC,aAAa;;;;;AAMhC,QAAA,IAAI,IAAI,CAAC,OAAO,EAAE;AAChB,YAAA,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO;YACxB,MAAM,CAAC,MAAK;AACV,gBAAA,EAAE,CAAC,EAAE,GAAG,GAAG,CAAC,OAAO,EAAE;AACvB,YAAA,CAAC,CAAC;YACF,MAAM,CAAC,MAAK;AACV,gBAAA,EAAE,CAAC,QAAQ,GAAG,GAAG,CAAC,UAAU,EAAE;AAChC,YAAA,CAAC,CAAC;YACF,MAAM,CAAC,MAAK;AACV,gBAAA,EAAE,CAAC,QAAQ,GAAG,GAAG,CAAC,UAAU,EAAE;AAChC,YAAA,CAAC,CAAC;QACJ;IACF;uGAvBW,SAAS,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAT,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,SAAS,mSAjBV,EAAE,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,
|
|
1
|
+
{"version":3,"file":"skra-ui-input.mjs","sources":["../../../../libs/ui/input/src/lib/input/input.ts","../../../../libs/ui/input/src/skra-ui-input.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n ElementRef,\n ViewEncapsulation,\n effect,\n inject,\n} from '@angular/core';\nimport { SkraFieldContext } from '@skra/ui/field';\n\n/**\n * `input[skraInput]` — text-input atom. Per ADR 040 this is a\n * Component-on-a-native-host (not a directive): `<input>` is a void element, so\n * `template: ''` is correct — there is no consumer content to project. Angular\n * Emulated encapsulation scopes `input.scss` to the host, the same way\n * <skra-button> carries its own CSS. Replaces the ADR 038 global slice branch.\n *\n * DI wiring (ADR 013), host a11y bindings (ADR 021/027), and the agnostic\n * value posture (ADR 037 — no value channel, no @angular/forms) are unchanged\n * from the prior directive form.\n *\n * `SkraFieldContext` is injected `{ optional: true }` (ADR 013 §3.7) — the same\n * posture as `skraCheckbox` / `skraRadio` / `skraSwitch`. Inside `<skra-field>`\n * the atom takes the field's id + describedby + availability cascade; standalone\n * it renders the skin only and the consumer owns every attribute, including the\n * accessible name:\n *\n * <!-- inside Field — label association via the DI-generated id/for pair -->\n * <skra-field>\n * <label skraLabelFor>Email</label>\n * <input skraInput type=\"email\" />\n * </skra-field>\n *\n * <!-- standalone: native implicit label (wrapping) — no id/for needed -->\n * <label>Search <input skraInput type=\"search\" /></label>\n *\n * Standalone use does NOT relax the ADR 033 accessible-name contract; it moves\n * the name onto the consumer's own native markup. An input with no name is an\n * a11y defect wherever it appears — including inside a `<skra-field>` that\n * carries no `label[skraLabelFor]` — so the check belongs to the a11y gate, not\n * to this injection site (ADR 013 §3.7).\n */\n@Component({\n selector: 'input[skraInput]',\n standalone: true,\n // Void host — no <ng-content>. See ADR 040 §2.\n template: '',\n styleUrl: './input.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.Emulated,\n host: {\n // ARIA relationships — Skra-owned, present only while a field cascades them.\n '[attr.aria-describedby]': 'context?.describedByIds() ?? null',\n '[attr.aria-invalid]': 'context?.hasError() ? \"true\" : null',\n '[attr.aria-required]': 'context?.isRequired() ? \"true\" : null',\n // Availability — native attrs only (native-attr-first, boundary #9). <input>\n // supports native `readonly`/`disabled`, which AT already exposes; NO\n // `aria-readonly`/`aria-disabled` here (setting both native + ARIA for one\n // state is forbidden). Readonly styling keys off `:read-only`/`[readonly]`.\n // The native props are driven imperatively below, NOT as host bindings —\n // see the constructor note on standalone attribute ownership.\n },\n})\nexport class SkraInput {\n private readonly el = inject<ElementRef<HTMLInputElement>>(ElementRef);\n readonly context = inject(SkraFieldContext, { optional: true });\n\n constructor() {\n const el = this.el.nativeElement;\n\n // Field-cascaded native properties — only bind when context is present so\n // standalone consumers retain full control of their static attributes\n // (a host `[attr.disabled]=\"null\"` binding would strip a consumer-authored\n // `disabled` / `readonly` / `id`). Mirrors SkraCheckbox.\n if (this.context) {\n const ctx = this.context;\n effect(() => {\n el.id = ctx.fieldId();\n });\n effect(() => {\n el.disabled = ctx.isDisabled();\n });\n effect(() => {\n el.readOnly = ctx.isReadonly();\n });\n }\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;AAUA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+BG;MAsBU,SAAS,CAAA;AACH,IAAA,EAAE,GAAG,MAAM,CAA+B,UAAU,CAAC;IAC7D,OAAO,GAAG,MAAM,CAAC,gBAAgB,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;AAE/D,IAAA,WAAA,GAAA;AACE,QAAA,MAAM,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC,aAAa;;;;;AAMhC,QAAA,IAAI,IAAI,CAAC,OAAO,EAAE;AAChB,YAAA,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO;YACxB,MAAM,CAAC,MAAK;AACV,gBAAA,EAAE,CAAC,EAAE,GAAG,GAAG,CAAC,OAAO,EAAE;AACvB,YAAA,CAAC,CAAC;YACF,MAAM,CAAC,MAAK;AACV,gBAAA,EAAE,CAAC,QAAQ,GAAG,GAAG,CAAC,UAAU,EAAE;AAChC,YAAA,CAAC,CAAC;YACF,MAAM,CAAC,MAAK;AACV,gBAAA,EAAE,CAAC,QAAQ,GAAG,GAAG,CAAC,UAAU,EAAE;AAChC,YAAA,CAAC,CAAC;QACJ;IACF;uGAvBW,SAAS,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAT,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,SAAS,mSAjBV,EAAE,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,s4FAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;2FAiBD,SAAS,EAAA,UAAA,EAAA,CAAA;kBArBrB,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,kBAAkB,EAAA,UAAA,EAChB,IAAI,EAAA,QAAA,EAEN,EAAE,EAAA,eAAA,EAEK,uBAAuB,CAAC,MAAM,EAAA,aAAA,EAChC,iBAAiB,CAAC,QAAQ,EAAA,IAAA,EACnC;;AAEJ,wBAAA,yBAAyB,EAAE,mCAAmC;AAC9D,wBAAA,qBAAqB,EAAE,qCAAqC;AAC5D,wBAAA,sBAAsB,EAAE,uCAAuC;;;;;;;AAOhE,qBAAA,EAAA,MAAA,EAAA,CAAA,s4FAAA,CAAA,EAAA;;;AC7DH;;AAEG;;;;"}
|
|
@@ -6,7 +6,10 @@ import { FocusKeyManager } from '@angular/cdk/a11y';
|
|
|
6
6
|
/**
|
|
7
7
|
* SkraMenuKeyboard — the WAI-ARIA APG Menu keyboard model, confined to ONE file.
|
|
8
8
|
*
|
|
9
|
-
* This is the
|
|
9
|
+
* This is the only module in `@skra/ui/menu` that imports `@angular/cdk`. ADR 0044 §7 was later
|
|
10
|
+
* generalized library-wide to "one swappable `*-keyboard.ts` per APG pattern", so there are now
|
|
11
|
+
* three such files — this one, `core/select/listbox-keyboard.ts` (`ActiveDescendantKeyManager`) and
|
|
12
|
+
* `tabs/tabs-keyboard.ts` — enforced by `tools/cdk-confinement-validator.mjs`. It wraps CDK `FocusKeyManager`
|
|
10
13
|
* (roving REAL focus — the APG-canonical menu model, NOT `aria-activedescendant`) so the engine is an
|
|
11
14
|
* implementation detail: swapping it (e.g. to a hand-rolled controller) is a one-file change with zero
|
|
12
15
|
* impact on `SkraMenu` / `SkraMenuItem` — exactly as `SkraPositioner` wraps `@floating-ui/dom`
|
|
@@ -107,8 +110,11 @@ class SkraMenuItem {
|
|
|
107
110
|
}
|
|
108
111
|
onActivate(event) {
|
|
109
112
|
if (this.isDisabled()) {
|
|
110
|
-
// Soft-disabled: block the native default
|
|
111
|
-
//
|
|
113
|
+
// Soft-disabled: block the native default. This is a SECOND line of defence only — it cannot
|
|
114
|
+
// stop the consumer's own (click) on this same host, because a component host listener
|
|
115
|
+
// registers AFTER the parent template's binding, so this bubble-phase handler runs too late.
|
|
116
|
+
// The capture-phase guard on the panel (`SkraMenu`) is what actually blocks activation, for
|
|
117
|
+
// both pointer and keyboard (Enter/Space produce a UA-synthesized click). Do not delete it.
|
|
112
118
|
event.preventDefault();
|
|
113
119
|
event.stopImmediatePropagation();
|
|
114
120
|
return;
|
|
@@ -142,11 +148,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.1", ngImpor
|
|
|
142
148
|
* <button skraButton popovertarget="actions" aria-haspopup="menu">Actions</button>
|
|
143
149
|
* <skra-menu id="actions">
|
|
144
150
|
* <button skraMenuItem (click)="edit()">Edit</button>
|
|
145
|
-
* <button skraMenuItem disabled (click)="archive()">Archive</button>
|
|
151
|
+
* <button skraMenuItem aria-disabled="true" (click)="archive()">Archive</button>
|
|
146
152
|
* <button skraMenuItem (click)="remove()">Delete</button>
|
|
147
153
|
* </skra-menu>
|
|
148
154
|
*
|
|
149
|
-
*
|
|
155
|
+
* A disabled item is `aria-disabled="true"` set by the CONSUMER — never native `disabled` (boundary
|
|
156
|
+
* #9, native-attr-first): the item stays focusable and in the roving order per APG, and a
|
|
157
|
+
* capture-phase guard on the panel blocks activation. Native `disabled` would keep it in the roving
|
|
158
|
+
* order but make `focus()` a no-op, so arrow navigation would silently dead-end on that row.
|
|
159
|
+
*
|
|
160
|
+
* Skra adds, on top of the Popover substrate: the `role="menu"` keyboard model via `SkraMenuKeyboard`
|
|
150
161
|
* (CDK `FocusKeyManager` — Down/Up roving + wrap, Home/End, type-ahead, Tab-dismiss), **focus moving
|
|
151
162
|
* INTO the menu on open** (a composite widget — unlike non-modal Popover; the per-component ADR 0044
|
|
152
163
|
* §3 rule-8 decision), and the trigger's disclosure ARIA (`aria-haspopup="menu"` / `aria-controls` /
|
|
@@ -164,9 +175,10 @@ class SkraMenu {
|
|
|
164
175
|
host = inject(ElementRef);
|
|
165
176
|
renderer = inject(Renderer2);
|
|
166
177
|
keyboard = new SkraMenuKeyboard();
|
|
167
|
-
/** The consumer's `[popovertarget]` button
|
|
178
|
+
/** The consumer's `[popovertarget]` button; resolution is retried until it succeeds. */
|
|
168
179
|
trigger = null;
|
|
169
|
-
|
|
180
|
+
/** Latches the dev warning, NOT the resolution — see `ensureTrigger()`. */
|
|
181
|
+
warned = false;
|
|
170
182
|
positioner;
|
|
171
183
|
constructor() {
|
|
172
184
|
// Feed the controller whenever the projected item set changes (signal → array snapshot rebuild).
|
|
@@ -239,16 +251,22 @@ class SkraMenu {
|
|
|
239
251
|
}
|
|
240
252
|
/**
|
|
241
253
|
* Resolve the `[popovertarget]` trigger and establish the menu disclosure ARIA on it (sanctioned a11y
|
|
242
|
-
* wiring, ADR 013-style — not style mutation).
|
|
243
|
-
*
|
|
254
|
+
* wiring, ADR 013-style — not style mutation). Returns the trigger (or null for an orphan menu,
|
|
255
|
+
* dev-warned once).
|
|
256
|
+
*
|
|
257
|
+
* Idempotent on SUCCESS only — see the same note on `SkraPopover.ensureTrigger()`. Latching on
|
|
258
|
+
* failure would permanently strand a trigger rendered behind an `@if` / lazy route / `@defer`:
|
|
259
|
+
* no disclosure ARIA, and `onOpen()` bails on the null anchor so the panel opens unpositioned at
|
|
260
|
+
* viewport 0,0 — the exact signature of impl-finding #1 in the spec. The dev warning latches
|
|
261
|
+
* separately via `warned`.
|
|
244
262
|
*/
|
|
245
263
|
ensureTrigger() {
|
|
246
|
-
if (this.
|
|
264
|
+
if (this.trigger)
|
|
247
265
|
return this.trigger;
|
|
248
|
-
this.resolved = true;
|
|
249
266
|
const id = this.host.nativeElement.id;
|
|
250
267
|
if (!id) {
|
|
251
|
-
if (typeof ngDevMode === 'undefined' || ngDevMode) {
|
|
268
|
+
if (!this.warned && (typeof ngDevMode === 'undefined' || ngDevMode)) {
|
|
269
|
+
this.warned = true;
|
|
252
270
|
console.warn('[skra-menu] has no `id` — it cannot be targeted by a `popovertarget` trigger and the ' +
|
|
253
271
|
'disclosure ARIA (aria-haspopup/aria-controls/aria-expanded) cannot be wired. Give the ' +
|
|
254
272
|
'menu an id and point a button at it: ' +
|
|
@@ -256,11 +274,17 @@ class SkraMenu {
|
|
|
256
274
|
}
|
|
257
275
|
return null;
|
|
258
276
|
}
|
|
277
|
+
// Scope to this node's own root, not `document`: under the ADR 012 §5 delivery contract both
|
|
278
|
+
// trigger and panel live inside a shadow root, where a document-rooted query finds nothing.
|
|
279
|
+
// `getRootNode()` returns `document` in the light-DOM case, so this is strictly a widening.
|
|
280
|
+
//
|
|
259
281
|
// Match by attribute value (no escaping; robust to special chars; `CSS.escape` is not universal).
|
|
282
|
+
const root = this.host.nativeElement.getRootNode();
|
|
260
283
|
this.trigger =
|
|
261
|
-
Array.from(
|
|
284
|
+
Array.from(root.querySelectorAll('[popovertarget]')).find((el) => el.getAttribute('popovertarget') === id) ?? null;
|
|
262
285
|
if (!this.trigger) {
|
|
263
|
-
if (typeof ngDevMode === 'undefined' || ngDevMode) {
|
|
286
|
+
if (!this.warned && (typeof ngDevMode === 'undefined' || ngDevMode)) {
|
|
287
|
+
this.warned = true;
|
|
264
288
|
console.warn(`[skra-menu] no trigger found with [popovertarget="${id}"] — the menu is unreachable and ` +
|
|
265
289
|
'has no element to carry aria-haspopup/aria-controls/aria-expanded. Add a focusable trigger ' +
|
|
266
290
|
'button with the matching popovertarget.');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skra-ui-menu.mjs","sources":["../../../../libs/ui/menu/src/lib/menu/menu-keyboard.ts","../../../../libs/ui/menu/src/lib/menu/menu-types.ts","../../../../libs/ui/menu/src/lib/menu/menu-item.ts","../../../../libs/ui/menu/src/lib/menu/menu.ts","../../../../libs/ui/menu/src/skra-ui-menu.ts"],"sourcesContent":["import { FocusKeyManager } from '@angular/cdk/a11y';\n\nimport type { SkraMenuKeyboardItem } from './menu-types';\n\n/**\n * SkraMenuKeyboard — the WAI-ARIA APG Menu keyboard model, confined to ONE file.\n *\n * This is the **only** module in Forge that imports `@angular/cdk`. It wraps CDK `FocusKeyManager`\n * (roving REAL focus — the APG-canonical menu model, NOT `aria-activedescendant`) so the engine is an\n * implementation detail: swapping it (e.g. to a hand-rolled controller) is a one-file change with zero\n * impact on `SkraMenu` / `SkraMenuItem` — exactly as `SkraPositioner` wraps `@floating-ui/dom`\n * (ADR 0044 §3 rule 5; recorded in §7, 2026-06-07).\n *\n * Owns: Down/Up roving (wrap), Home/End, type-ahead, and Tab→dismiss. Enter/Space (native button\n * activation) and Escape + light-dismiss (`popover=\"auto\"`) stay platform-owned — the controller never\n * touches them.\n */\nexport class SkraMenuKeyboard {\n private manager?: FocusKeyManager<SkraMenuKeyboardItem>;\n private items: SkraMenuKeyboardItem[] = [];\n private tabOutHandler?: () => void;\n\n /** Register the APG \"Tab dismisses the menu\" callback (fired by `FocusKeyManager.tabOut`). */\n onTabOut(handler: () => void): void {\n this.tabOutHandler = handler;\n }\n\n /**\n * (Re)build the manager from the current projected item set. Called from an `effect` on the menu's\n * signal `contentChildren` — a passed array is a static snapshot (it does not auto-track like a live\n * `QueryList`), so the manager is rebuilt whenever the item set changes (the documented signal↔CDK seam).\n */\n setItems(items: readonly SkraMenuKeyboardItem[]): void {\n this.items = [...items];\n this.manager?.destroy();\n this.manager = new FocusKeyManager<SkraMenuKeyboardItem>(this.items)\n .withWrap()\n .withTypeAhead()\n .withHomeAndEnd()\n // Disabled items stay in the roving order (APG focusable-but-inert — discoverable); activation is\n // blocked on the item itself. `() => false` also stops `FocusKeyManager` from reading `item.disabled`\n // (which on our signal-input component would be a truthy function).\n .skipPredicate(() => false);\n this.manager.tabOut.subscribe(() => this.tabOutHandler?.());\n }\n\n /** Delegate Up/Down/Home/End/type-ahead. Enter/Space/Escape are intentionally left to the platform. */\n onKeydown(event: KeyboardEvent): void {\n this.manager?.onKeydown(event);\n }\n\n /** Move roving focus to the first ENABLED item (APG: focus enters the menu on open). */\n focusFirst(): void {\n if (!this.manager || this.items.length === 0) return;\n const firstEnabled = this.items.findIndex((item) => !item.isDisabled());\n this.manager.setActiveItem(firstEnabled >= 0 ? firstEnabled : 0);\n }\n\n destroy(): void {\n this.manager?.destroy();\n this.manager = undefined;\n }\n}\n","import { InjectionToken } from '@angular/core';\n\n/**\n * The item shape the menu keyboard controller drives. Structurally a CDK `FocusableOption`\n * (`focus()`), plus the menu's own `getLabel()` (type-ahead) and `isDisabled()` (focusable-but-inert\n * roving). Declared HERE — cdk-free — so the only `@angular/cdk` importer stays `menu-keyboard.ts`.\n */\nexport interface SkraMenuKeyboardItem {\n focus(): void;\n getLabel(): string;\n isDisabled(): boolean;\n}\n\n/** What a `skraMenuItem` needs from its `skra-menu` — narrow contract that breaks the menu↔item cycle. */\nexport interface SkraMenuPanel {\n /** Dismiss the menu after an item activates (native `hidePopover()` → focus returns to the trigger). */\n requestClose(): void;\n}\n\n/**\n * DI token a `skra-menu` provides (`useExisting`) and a `button[skraMenuItem]` injects. A token\n * (not the `SkraMenu` class) so the item file never imports the menu file — no runtime import cycle.\n */\nexport const SKRA_MENU = new InjectionToken<SkraMenuPanel>('SKRA_MENU');\n","import {\n ChangeDetectionStrategy,\n Component,\n ElementRef,\n ViewEncapsulation,\n inject,\n} from '@angular/core';\n\nimport { SKRA_MENU, type SkraMenuKeyboardItem } from './menu-types';\n\ndeclare const ngDevMode: boolean | undefined;\n\n/**\n * SkraMenuItem — a single command in a `skra-menu`, a Component on the native command host\n * `button[skraMenuItem]` (ADR 012/040: a `<button>` is the right semantic — Enter/Space→click +\n * focusability for free; its implicit role is overridden to `role=\"menuitem\"` per WAI-ARIA APG).\n *\n * Roving focus: `tabindex=\"-1\"` (the keyboard controller moves real focus). Implements\n * `SkraMenuKeyboardItem` (`focus`/`getLabel`/`isDisabled`) so `SkraMenuKeyboard` (CDK `FocusKeyManager`)\n * can drive it. On activation it asks the menu to close (native `hidePopover()` → focus returns to the\n * trigger).\n *\n * **Disabled is native-attr-first (boundary #9, ADR 039 precedent): the consumer sets\n * `aria-disabled=\"true\"` directly — Forge OBSERVES it, exposing NO `disabled` input.** This (a) keeps a\n * disabled item **focusable/discoverable** in the roving order (APG) — native `disabled` would remove it\n * from focus, and (b) avoids a Forge input shadowing the native `disabled` attribute. Styling keys off\n * `:host([aria-disabled=\"true\"])`; activation is blocked here.\n *\n * Full contract: adr/specs/component-menu-spec.md.\n */\n@Component({\n selector: 'button[skraMenuItem]',\n standalone: true,\n exportAs: 'skraMenuItem',\n template: '<ng-content></ng-content>',\n styleUrl: './menu-item.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.Emulated,\n host: {\n role: 'menuitem',\n type: 'button', // never an implicit submit if the menu sits inside a <form>\n tabindex: '-1', // roving — focus is moved programmatically by SkraMenuKeyboard\n '(click)': 'onActivate($event)',\n },\n})\nexport class SkraMenuItem implements SkraMenuKeyboardItem {\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef);\n private readonly menu = inject(SKRA_MENU, { optional: true });\n\n constructor() {\n if (typeof ngDevMode === 'undefined' || ngDevMode) {\n if (!this.menu) {\n console.warn(\n '[skraMenuItem] has no <skra-menu> ancestor — it is not registered with any keyboard ' +\n 'controller and cannot close a menu on activation. Project it inside a <skra-menu>.',\n );\n }\n }\n }\n\n // ── SkraMenuKeyboardItem (driven by SkraMenuKeyboard / CDK FocusKeyManager) ──\n focus(): void {\n this.host.nativeElement.focus();\n }\n getLabel(): string {\n return (this.host.nativeElement.textContent ?? '').trim();\n }\n /** Soft-disabled = the consumer's `aria-disabled=\"true\"` (native-attr-first); read live (no input). */\n isDisabled(): boolean {\n return this.host.nativeElement.getAttribute('aria-disabled') === 'true';\n }\n\n protected onActivate(event: MouseEvent): void {\n if (this.isDisabled()) {\n // Soft-disabled: block the native default AND the consumer's own (click) on this same host\n // (the host listener runs first — Material's MatMenuItem precedent).\n event.preventDefault();\n event.stopImmediatePropagation();\n return;\n }\n // Activating a command closes the menu (APG). The consumer's (click) handler runs independently.\n this.menu?.requestClose();\n }\n}\n","import {\n ChangeDetectionStrategy,\n Component,\n DestroyRef,\n ElementRef,\n Renderer2,\n ViewEncapsulation,\n afterNextRender,\n contentChildren,\n effect,\n inject,\n input,\n} from '@angular/core';\n\nimport {\n _attachPositioner,\n type SkraPlacement,\n type _PositionerHandle,\n} from '@skra/ui/core';\nimport { SkraMenuKeyboard } from './menu-keyboard';\nimport { SkraMenuItem } from './menu-item';\nimport { SKRA_MENU, type SkraMenuPanel } from './menu-types';\n\ndeclare const ngDevMode: boolean | undefined;\n\n/**\n * SkraMenu — a WAI-ARIA APG **Menu Button** menu: a homogeneous set of commands anchored to a\n * trigger, navigated as one composite widget with arrow keys, where activating a command closes it.\n * Rendered in the browser TOP LAYER via the native Popover API (`popover=\"auto\"`), per ADR 0044.\n *\n * SHAPE (scope 2026-06-07): a Component on the PANEL with projected `button[skraMenuItem]` children\n * (the Popover model, ADR 040) — NOT a directive on the trigger, NOT a data-driven `[items]` array.\n * The trigger is the consumer's own button linked by the native `popovertarget` attribute; toggle,\n * light-dismiss and Escape are platform-owned. The consumer MUST give `<skra-menu>` an `id`.\n *\n * <button skraButton popovertarget=\"actions\" aria-haspopup=\"menu\">Actions</button>\n * <skra-menu id=\"actions\">\n * <button skraMenuItem (click)=\"edit()\">Edit</button>\n * <button skraMenuItem disabled (click)=\"archive()\">Archive</button>\n * <button skraMenuItem (click)=\"remove()\">Delete</button>\n * </skra-menu>\n *\n * Forge adds, on top of the Popover substrate: the `role=\"menu\"` keyboard model via `SkraMenuKeyboard`\n * (CDK `FocusKeyManager` — Down/Up roving + wrap, Home/End, type-ahead, Tab-dismiss), **focus moving\n * INTO the menu on open** (a composite widget — unlike non-modal Popover; the per-component ADR 0044\n * §3 rule-8 decision), and the trigger's disclosure ARIA (`aria-haspopup=\"menu\"` / `aria-controls` /\n * `aria-expanded`). Side effects on open/close: bind the native `(toggle)` — there is no Forge output\n * (native-first; contrast Dialog, whose `<dialog>` has no open event). Context menus (right-click) are\n * a recipe with a visible button, never a trigger mode (SRP + WCAG 2.1.1).\n *\n * Full contract: adr/specs/component-menu-spec.md.\n */\n@Component({\n selector: 'skra-menu',\n standalone: true,\n exportAs: 'skraMenu',\n template: '<ng-content></ng-content>',\n styleUrl: './menu.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.Emulated,\n providers: [{ provide: SKRA_MENU, useExisting: SkraMenu }],\n host: {\n role: 'menu',\n // Native top layer + platform-owned toggle / light-dismiss / Escape / stacking (ADR 0044).\n popover: 'auto',\n // NOTE: `toggle` and `keydown` are wired IMPERATIVELY in the constructor, NOT as host listeners.\n // A consumer template binding `(toggle)` on <skra-menu> (the documented side-effect path) SHADOWS a\n // host-metadata `(toggle)` listener for the same event — which would silently break positioning +\n // aria-expanded. A raw `addEventListener` is independent of Angular's host/template listener slot, so\n // it always fires alongside the consumer's binding.\n },\n})\nexport class SkraMenu implements SkraMenuPanel {\n /** Placement intent; `flip`/`shift` adjust at runtime. */\n readonly placement = input<SkraPlacement>('bottom');\n\n private readonly menuItems = contentChildren(SkraMenuItem, {\n descendants: true,\n });\n\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef);\n private readonly renderer = inject(Renderer2);\n private readonly keyboard = new SkraMenuKeyboard();\n\n /** The consumer's `[popovertarget]` button, resolved once (lazily-idempotent via `resolved`). */\n private trigger: HTMLElement | null = null;\n private resolved = false;\n private positioner?: _PositionerHandle;\n\n constructor() {\n // Feed the controller whenever the projected item set changes (signal → array snapshot rebuild).\n effect(() => this.keyboard.setItems(this.menuItems()));\n // APG: Tab/Shift+Tab dismisses the menu; native Tab then proceeds from the trigger.\n this.keyboard.onTabOut(() => this.host.nativeElement.hidePopover?.());\n\n // All imperative DOM wiring lives in afterNextRender — a browser-only hook, so the native listeners\n // and the trigger resolution never run on the server (SSR-safe by construction; O-18). The listeners\n // attach right after first paint, long before any user interaction can fire them.\n afterNextRender(() => {\n const el = this.host.nativeElement;\n // Gate disabled items at the CAPTURE phase: a component host listener registers AFTER the parent\n // template's `(click)` on the same button, so a bubble-phase guard cannot stop the consumer's own\n // handler. A capture listener on the menu host fires before the target's listeners — preventing both\n // the consumer's `(click)` and the item's `onActivate` for an `aria-disabled` item.\n el.addEventListener('click', this.onCaptureClick, true);\n // Imperative (NOT host-metadata) so a consumer `(toggle)` binding does not shadow them — see host {}.\n el.addEventListener('toggle', this.onToggleNative);\n el.addEventListener('keydown', this.onKeydownNative);\n\n // Resolve + wire the trigger after the view exists (it may be a later sibling), so the disclosure\n // relationship (aria-haspopup + aria-controls + aria-expanded=\"false\") is present before first open.\n this.ensureTrigger();\n if (typeof ngDevMode === 'undefined' || ngDevMode) this.warnIfEmpty();\n });\n inject(DestroyRef).onDestroy(() => this.teardown());\n }\n\n /** SKRA_MENU contract — close on item activation (native focus-return to the trigger). */\n requestClose(): void {\n this.host.nativeElement.hidePopover?.();\n }\n\n /** Capture-phase guard: block clicks on an `aria-disabled` item before they reach its listeners. */\n private readonly onCaptureClick = (event: Event): void => {\n const item = (event.target as HTMLElement | null)?.closest?.(\n '[skraMenuItem]',\n );\n if (item?.getAttribute('aria-disabled') === 'true') {\n event.preventDefault();\n event.stopPropagation();\n }\n };\n\n // ── Toggle / keydown (imperative native listeners — see host {} note) ─────────\n private readonly onToggleNative = (event: Event): void => {\n if ((event as ToggleEvent).newState === 'open') this.onOpen();\n else this.onClose();\n };\n\n private readonly onKeydownNative = (event: Event): void => {\n this.keyboard.onKeydown(event as KeyboardEvent);\n };\n\n private onOpen(): void {\n const anchor = this.ensureTrigger(); // safety net if afterNextRender has not yet run\n if (anchor) {\n this.renderer.setAttribute(anchor, 'aria-expanded', 'true');\n this.positioner?.destroy();\n this.positioner = _attachPositioner(\n anchor,\n this.host.nativeElement,\n () => ({\n placement: this.placement(),\n offset: this.cssLenPx('--skra-comp-menu-offset'),\n viewportPadding: this.cssLenPx('--skra-comp-menu-viewport-padding'),\n }),\n );\n }\n // Focus enters the menu (APG Menu Button) regardless of how it opened — unlike non-modal Popover.\n this.keyboard.focusFirst();\n }\n\n private onClose(): void {\n if (this.trigger) {\n this.renderer.setAttribute(this.trigger, 'aria-expanded', 'false');\n }\n this.positioner?.destroy();\n this.positioner = undefined;\n }\n\n /**\n * Resolve the `[popovertarget]` trigger and establish the menu disclosure ARIA on it (sanctioned a11y\n * wiring, ADR 013-style — not style mutation). Idempotent. Returns the trigger (or null for an orphan\n * menu, dev-warned once).\n */\n private ensureTrigger(): HTMLElement | null {\n if (this.resolved) return this.trigger;\n this.resolved = true;\n\n const id = this.host.nativeElement.id;\n if (!id) {\n if (typeof ngDevMode === 'undefined' || ngDevMode) {\n console.warn(\n '[skra-menu] has no `id` — it cannot be targeted by a `popovertarget` trigger and the ' +\n 'disclosure ARIA (aria-haspopup/aria-controls/aria-expanded) cannot be wired. Give the ' +\n 'menu an id and point a button at it: ' +\n '<button popovertarget=\"my-id\" aria-haspopup=\"menu\">…</button> <skra-menu id=\"my-id\">…',\n );\n }\n return null;\n }\n\n // Match by attribute value (no escaping; robust to special chars; `CSS.escape` is not universal).\n this.trigger =\n Array.from(\n document.querySelectorAll<HTMLElement>('[popovertarget]'),\n ).find((el) => el.getAttribute('popovertarget') === id) ?? null;\n if (!this.trigger) {\n if (typeof ngDevMode === 'undefined' || ngDevMode) {\n console.warn(\n `[skra-menu] no trigger found with [popovertarget=\"${id}\"] — the menu is unreachable and ` +\n 'has no element to carry aria-haspopup/aria-controls/aria-expanded. Add a focusable trigger ' +\n 'button with the matching popovertarget.',\n );\n }\n return null;\n }\n\n // Establish the Menu Button relationship before the first open (APG; aria-haspopup distinguishes a\n // menu from Popover's generic disclosure).\n this.renderer.setAttribute(this.trigger, 'aria-haspopup', 'menu');\n this.renderer.setAttribute(this.trigger, 'aria-controls', id);\n this.renderer.setAttribute(this.trigger, 'aria-expanded', 'false');\n return this.trigger;\n }\n\n /** Read a length comp token (px/rem) off the host computed style for the positioner. */\n private cssLenPx(prop: string): number {\n const raw = getComputedStyle(this.host.nativeElement)\n .getPropertyValue(prop)\n .trim();\n if (raw.endsWith('px')) return parseFloat(raw);\n if (raw.endsWith('rem')) {\n const rootFontSize =\n parseFloat(getComputedStyle(document.documentElement).fontSize) || 16;\n return parseFloat(raw) * rootFontSize;\n }\n return parseFloat(raw) || 0;\n }\n\n /** Dev-only nudge: a role=\"menu\" with no menuitems is invalid — a link-list/content panel is a Popover. */\n private warnIfEmpty(): void {\n if (this.menuItems().length === 0) {\n console.warn(\n '[skra-menu] has no `button[skraMenuItem]` children — a `role=\"menu\"` with no menu items is ' +\n 'invalid. If this is a panel of arbitrary content or a list of navigation links, use ' +\n '<skra-popover> (disclosure) instead — see the Menu-vs-Popover boundary in the spec.',\n );\n }\n }\n\n private teardown(): void {\n const el = this.host.nativeElement;\n el.removeEventListener('click', this.onCaptureClick, true);\n el.removeEventListener('toggle', this.onToggleNative);\n el.removeEventListener('keydown', this.onKeydownNative);\n this.keyboard.destroy();\n this.positioner?.destroy();\n if (this.trigger) {\n this.renderer.removeAttribute(this.trigger, 'aria-haspopup');\n this.renderer.removeAttribute(this.trigger, 'aria-expanded');\n this.renderer.removeAttribute(this.trigger, 'aria-controls');\n }\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;;AAIA;;;;;;;;;;;;AAYG;MACU,gBAAgB,CAAA;AACnB,IAAA,OAAO;IACP,KAAK,GAA2B,EAAE;AAClC,IAAA,aAAa;;AAGrB,IAAA,QAAQ,CAAC,OAAmB,EAAA;AAC1B,QAAA,IAAI,CAAC,aAAa,GAAG,OAAO;IAC9B;AAEA;;;;AAIG;AACH,IAAA,QAAQ,CAAC,KAAsC,EAAA;AAC7C,QAAA,IAAI,CAAC,KAAK,GAAG,CAAC,GAAG,KAAK,CAAC;AACvB,QAAA,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE;QACvB,IAAI,CAAC,OAAO,GAAG,IAAI,eAAe,CAAuB,IAAI,CAAC,KAAK;AAChE,aAAA,QAAQ;AACR,aAAA,aAAa;AACb,aAAA,cAAc;;;;AAId,aAAA,aAAa,CAAC,MAAM,KAAK,CAAC;AAC7B,QAAA,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,IAAI,CAAC,aAAa,IAAI,CAAC;IAC7D;;AAGA,IAAA,SAAS,CAAC,KAAoB,EAAA;AAC5B,QAAA,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,KAAK,CAAC;IAChC;;IAGA,UAAU,GAAA;QACR,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE;AAC9C,QAAA,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;AACvE,QAAA,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,YAAY,IAAI,CAAC,GAAG,YAAY,GAAG,CAAC,CAAC;IAClE;IAEA,OAAO,GAAA;AACL,QAAA,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE;AACvB,QAAA,IAAI,CAAC,OAAO,GAAG,SAAS;IAC1B;AACD;;AC3CD;;;AAGG;AACI,MAAM,SAAS,GAAG,IAAI,cAAc,CAAgB,WAAW,CAAC;;ACXvE;;;;;;;;;;;;;;;;;AAiBG;MAgBU,YAAY,CAAA;AACN,IAAA,IAAI,GAAG,MAAM,CAA0B,UAAU,CAAC;IAClD,IAAI,GAAG,MAAM,CAAC,SAAS,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;AAE7D,IAAA,WAAA,GAAA;AACE,QAAA,IAAI,OAAO,SAAS,KAAK,WAAW,IAAI,SAAS,EAAE;AACjD,YAAA,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE;gBACd,OAAO,CAAC,IAAI,CACV,sFAAsF;AACpF,oBAAA,oFAAoF,CACvF;YACH;QACF;IACF;;IAGA,KAAK,GAAA;AACH,QAAA,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE;IACjC;IACA,QAAQ,GAAA;AACN,QAAA,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,WAAW,IAAI,EAAE,EAAE,IAAI,EAAE;IAC3D;;IAEA,UAAU,GAAA;AACR,QAAA,OAAO,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,YAAY,CAAC,eAAe,CAAC,KAAK,MAAM;IACzE;AAEU,IAAA,UAAU,CAAC,KAAiB,EAAA;AACpC,QAAA,IAAI,IAAI,CAAC,UAAU,EAAE,EAAE;;;YAGrB,KAAK,CAAC,cAAc,EAAE;YACtB,KAAK,CAAC,wBAAwB,EAAE;YAChC;QACF;;AAEA,QAAA,IAAI,CAAC,IAAI,EAAE,YAAY,EAAE;IAC3B;uGArCW,YAAY,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAZ,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,YAAY,4OAXb,2BAA2B,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,k8CAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;2FAW1B,YAAY,EAAA,UAAA,EAAA,CAAA;kBAfxB,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,sBAAsB,EAAA,UAAA,EACpB,IAAI,EAAA,QAAA,EACN,cAAc,YACd,2BAA2B,EAAA,eAAA,EAEpB,uBAAuB,CAAC,MAAM,EAAA,aAAA,EAChC,iBAAiB,CAAC,QAAQ,EAAA,IAAA,EACnC;AACJ,wBAAA,IAAI,EAAE,UAAU;wBAChB,IAAI,EAAE,QAAQ;wBACd,QAAQ,EAAE,IAAI;AACd,wBAAA,SAAS,EAAE,oBAAoB;AAChC,qBAAA,EAAA,MAAA,EAAA,CAAA,k8CAAA,CAAA,EAAA;;;AClBH;;;;;;;;;;;;;;;;;;;;;;;;;;AA0BG;MAqBU,QAAQ,CAAA;;IAEV,SAAS,GAAG,KAAK,CAAgB,QAAQ;kFAAC;IAElC,SAAS,GAAG,eAAe,CAAC,YAAY,iFACvD,WAAW,EAAE,IAAI,EAAA,CACjB;AAEe,IAAA,IAAI,GAAG,MAAM,CAA0B,UAAU,CAAC;AAClD,IAAA,QAAQ,GAAG,MAAM,CAAC,SAAS,CAAC;AAC5B,IAAA,QAAQ,GAAG,IAAI,gBAAgB,EAAE;;IAG1C,OAAO,GAAuB,IAAI;IAClC,QAAQ,GAAG,KAAK;AAChB,IAAA,UAAU;AAElB,IAAA,WAAA,GAAA;;AAEE,QAAA,MAAM,CAAC,MAAM,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;;AAEtD,QAAA,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,WAAW,IAAI,CAAC;;;;QAKrE,eAAe,CAAC,MAAK;AACnB,YAAA,MAAM,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa;;;;;YAKlC,EAAE,CAAC,gBAAgB,CAAC,OAAO,EAAE,IAAI,CAAC,cAAc,EAAE,IAAI,CAAC;;YAEvD,EAAE,CAAC,gBAAgB,CAAC,QAAQ,EAAE,IAAI,CAAC,cAAc,CAAC;YAClD,EAAE,CAAC,gBAAgB,CAAC,SAAS,EAAE,IAAI,CAAC,eAAe,CAAC;;;YAIpD,IAAI,CAAC,aAAa,EAAE;AACpB,YAAA,IAAI,OAAO,SAAS,KAAK,WAAW,IAAI,SAAS;gBAAE,IAAI,CAAC,WAAW,EAAE;AACvE,QAAA,CAAC,CAAC;AACF,QAAA,MAAM,CAAC,UAAU,CAAC,CAAC,SAAS,CAAC,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;IACrD;;IAGA,YAAY,GAAA;QACV,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,WAAW,IAAI;IACzC;;AAGiB,IAAA,cAAc,GAAG,CAAC,KAAY,KAAU;QACvD,MAAM,IAAI,GAAI,KAAK,CAAC,MAA6B,EAAE,OAAO,GACxD,gBAAgB,CACjB;QACD,IAAI,IAAI,EAAE,YAAY,CAAC,eAAe,CAAC,KAAK,MAAM,EAAE;YAClD,KAAK,CAAC,cAAc,EAAE;YACtB,KAAK,CAAC,eAAe,EAAE;QACzB;AACF,IAAA,CAAC;;AAGgB,IAAA,cAAc,GAAG,CAAC,KAAY,KAAU;AACvD,QAAA,IAAK,KAAqB,CAAC,QAAQ,KAAK,MAAM;YAAE,IAAI,CAAC,MAAM,EAAE;;YACxD,IAAI,CAAC,OAAO,EAAE;AACrB,IAAA,CAAC;AAEgB,IAAA,eAAe,GAAG,CAAC,KAAY,KAAU;AACxD,QAAA,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,KAAsB,CAAC;AACjD,IAAA,CAAC;IAEO,MAAM,GAAA;QACZ,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;QACpC,IAAI,MAAM,EAAE;YACV,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,MAAM,EAAE,eAAe,EAAE,MAAM,CAAC;AAC3D,YAAA,IAAI,CAAC,UAAU,EAAE,OAAO,EAAE;AAC1B,YAAA,IAAI,CAAC,UAAU,GAAG,iBAAiB,CACjC,MAAM,EACN,IAAI,CAAC,IAAI,CAAC,aAAa,EACvB,OAAO;AACL,gBAAA,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE;AAC3B,gBAAA,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,yBAAyB,CAAC;AAChD,gBAAA,eAAe,EAAE,IAAI,CAAC,QAAQ,CAAC,mCAAmC,CAAC;AACpE,aAAA,CAAC,CACH;QACH;;AAEA,QAAA,IAAI,CAAC,QAAQ,CAAC,UAAU,EAAE;IAC5B;IAEQ,OAAO,GAAA;AACb,QAAA,IAAI,IAAI,CAAC,OAAO,EAAE;AAChB,YAAA,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,EAAE,eAAe,EAAE,OAAO,CAAC;QACpE;AACA,QAAA,IAAI,CAAC,UAAU,EAAE,OAAO,EAAE;AAC1B,QAAA,IAAI,CAAC,UAAU,GAAG,SAAS;IAC7B;AAEA;;;;AAIG;IACK,aAAa,GAAA;QACnB,IAAI,IAAI,CAAC,QAAQ;YAAE,OAAO,IAAI,CAAC,OAAO;AACtC,QAAA,IAAI,CAAC,QAAQ,GAAG,IAAI;QAEpB,MAAM,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,EAAE;QACrC,IAAI,CAAC,EAAE,EAAE;AACP,YAAA,IAAI,OAAO,SAAS,KAAK,WAAW,IAAI,SAAS,EAAE;gBACjD,OAAO,CAAC,IAAI,CACV,uFAAuF;oBACrF,wFAAwF;oBACxF,uCAAuC;AACvC,oBAAA,uFAAuF,CAC1F;YACH;AACA,YAAA,OAAO,IAAI;QACb;;AAGA,QAAA,IAAI,CAAC,OAAO;AACV,YAAA,KAAK,CAAC,IAAI,CACR,QAAQ,CAAC,gBAAgB,CAAc,iBAAiB,CAAC,CAC1D,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,YAAY,CAAC,eAAe,CAAC,KAAK,EAAE,CAAC,IAAI,IAAI;AACjE,QAAA,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE;AACjB,YAAA,IAAI,OAAO,SAAS,KAAK,WAAW,IAAI,SAAS,EAAE;AACjD,gBAAA,OAAO,CAAC,IAAI,CACV,CAAA,kDAAA,EAAqD,EAAE,CAAA,iCAAA,CAAmC;oBACxF,6FAA6F;AAC7F,oBAAA,yCAAyC,CAC5C;YACH;AACA,YAAA,OAAO,IAAI;QACb;;;AAIA,QAAA,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,EAAE,eAAe,EAAE,MAAM,CAAC;AACjE,QAAA,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,EAAE,eAAe,EAAE,EAAE,CAAC;AAC7D,QAAA,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,EAAE,eAAe,EAAE,OAAO,CAAC;QAClE,OAAO,IAAI,CAAC,OAAO;IACrB;;AAGQ,IAAA,QAAQ,CAAC,IAAY,EAAA;QAC3B,MAAM,GAAG,GAAG,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa;aACjD,gBAAgB,CAAC,IAAI;AACrB,aAAA,IAAI,EAAE;AACT,QAAA,IAAI,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC;AAAE,YAAA,OAAO,UAAU,CAAC,GAAG,CAAC;AAC9C,QAAA,IAAI,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE;AACvB,YAAA,MAAM,YAAY,GAChB,UAAU,CAAC,gBAAgB,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC,QAAQ,CAAC,IAAI,EAAE;AACvE,YAAA,OAAO,UAAU,CAAC,GAAG,CAAC,GAAG,YAAY;QACvC;AACA,QAAA,OAAO,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC;IAC7B;;IAGQ,WAAW,GAAA;QACjB,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE;YACjC,OAAO,CAAC,IAAI,CACV,6FAA6F;gBAC3F,sFAAsF;AACtF,gBAAA,qFAAqF,CACxF;QACH;IACF;IAEQ,QAAQ,GAAA;AACd,QAAA,MAAM,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa;QAClC,EAAE,CAAC,mBAAmB,CAAC,OAAO,EAAE,IAAI,CAAC,cAAc,EAAE,IAAI,CAAC;QAC1D,EAAE,CAAC,mBAAmB,CAAC,QAAQ,EAAE,IAAI,CAAC,cAAc,CAAC;QACrD,EAAE,CAAC,mBAAmB,CAAC,SAAS,EAAE,IAAI,CAAC,eAAe,CAAC;AACvD,QAAA,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE;AACvB,QAAA,IAAI,CAAC,UAAU,EAAE,OAAO,EAAE;AAC1B,QAAA,IAAI,IAAI,CAAC,OAAO,EAAE;YAChB,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,CAAC,OAAO,EAAE,eAAe,CAAC;YAC5D,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,CAAC,OAAO,EAAE,eAAe,CAAC;YAC5D,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,CAAC,OAAO,EAAE,eAAe,CAAC;QAC9D;IACF;uGArLW,QAAQ,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAR,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,QAAQ,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,WAAA,EAAA,MAAA,EAAA,EAAA,SAAA,EAAA,EAAA,iBAAA,EAAA,WAAA,EAAA,UAAA,EAAA,WAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,IAAA,EAAA,EAAA,UAAA,EAAA,EAAA,MAAA,EAAA,MAAA,EAAA,SAAA,EAAA,MAAA,EAAA,EAAA,EAAA,SAAA,EAZR,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,QAAQ,EAAE,CAAC,EAAA,OAAA,EAAA,CAAA,EAAA,YAAA,EAAA,WAAA,EAAA,SAAA,EAgBb,YAAY,wFApB/C,2BAA2B,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,w9BAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;2FAgB1B,QAAQ,EAAA,UAAA,EAAA,CAAA;kBApBpB,SAAS;+BACE,WAAW,EAAA,UAAA,EACT,IAAI,EAAA,QAAA,EACN,UAAU,EAAA,QAAA,EACV,2BAA2B,EAAA,eAAA,EAEpB,uBAAuB,CAAC,MAAM,EAAA,aAAA,EAChC,iBAAiB,CAAC,QAAQ,EAAA,SAAA,EAC9B,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,WAAW,EAAA,QAAU,EAAE,CAAC,EAAA,IAAA,EACpD;AACJ,wBAAA,IAAI,EAAE,MAAM;;AAEZ,wBAAA,OAAO,EAAE,MAAM;;;;;;AAMhB,qBAAA,EAAA,MAAA,EAAA,CAAA,w9BAAA,CAAA,EAAA;AAM4C,SAAA,CAAA,EAAA,cAAA,EAAA,MAAA,EAAA,EAAA,cAAA,EAAA,EAAA,SAAA,EAAA,CAAA,EAAA,IAAA,EAAA,EAAA,CAAA,KAAA,EAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,KAAA,EAAA,WAAA,EAAA,QAAA,EAAA,KAAA,EAAA,CAAA,EAAA,CAAA,EAAA,SAAA,EAAA,CAAA,EAAA,IAAA,EAAA,EAAA,CAAA,eAAA,EAAA,IAAA,EAAA,CAAA,EAAA,CAAA,UAAA,CAAA,MAAA,YAAY,CAAA,EAAA,EAAA,GAAE;AACzD,4BAAA,WAAW,EAAE,IAAI;AAClB,yBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,CAAA,EAAA,CAAA,EAAA,EAAA,CAAA;;AC9EH;;AAEG;;;;"}
|
|
1
|
+
{"version":3,"file":"skra-ui-menu.mjs","sources":["../../../../libs/ui/menu/src/lib/menu/menu-keyboard.ts","../../../../libs/ui/menu/src/lib/menu/menu-types.ts","../../../../libs/ui/menu/src/lib/menu/menu-item.ts","../../../../libs/ui/menu/src/lib/menu/menu.ts","../../../../libs/ui/menu/src/skra-ui-menu.ts"],"sourcesContent":["import { FocusKeyManager } from '@angular/cdk/a11y';\r\n\r\nimport type { SkraMenuKeyboardItem } from './menu-types';\r\n\r\n/**\r\n * SkraMenuKeyboard — the WAI-ARIA APG Menu keyboard model, confined to ONE file.\r\n *\r\n * This is the only module in `@skra/ui/menu` that imports `@angular/cdk`. ADR 0044 §7 was later\r\n * generalized library-wide to \"one swappable `*-keyboard.ts` per APG pattern\", so there are now\r\n * three such files — this one, `core/select/listbox-keyboard.ts` (`ActiveDescendantKeyManager`) and\r\n * `tabs/tabs-keyboard.ts` — enforced by `tools/cdk-confinement-validator.mjs`. It wraps CDK `FocusKeyManager`\r\n * (roving REAL focus — the APG-canonical menu model, NOT `aria-activedescendant`) so the engine is an\r\n * implementation detail: swapping it (e.g. to a hand-rolled controller) is a one-file change with zero\r\n * impact on `SkraMenu` / `SkraMenuItem` — exactly as `SkraPositioner` wraps `@floating-ui/dom`\r\n * (ADR 0044 §3 rule 5; recorded in §7, 2026-06-07).\r\n *\r\n * Owns: Down/Up roving (wrap), Home/End, type-ahead, and Tab→dismiss. Enter/Space (native button\r\n * activation) and Escape + light-dismiss (`popover=\"auto\"`) stay platform-owned — the controller never\r\n * touches them.\r\n */\r\nexport class SkraMenuKeyboard {\r\n private manager?: FocusKeyManager<SkraMenuKeyboardItem>;\r\n private items: SkraMenuKeyboardItem[] = [];\r\n private tabOutHandler?: () => void;\r\n\r\n /** Register the APG \"Tab dismisses the menu\" callback (fired by `FocusKeyManager.tabOut`). */\r\n onTabOut(handler: () => void): void {\r\n this.tabOutHandler = handler;\r\n }\r\n\r\n /**\r\n * (Re)build the manager from the current projected item set. Called from an `effect` on the menu's\r\n * signal `contentChildren` — a passed array is a static snapshot (it does not auto-track like a live\r\n * `QueryList`), so the manager is rebuilt whenever the item set changes (the documented signal↔CDK seam).\r\n */\r\n setItems(items: readonly SkraMenuKeyboardItem[]): void {\r\n this.items = [...items];\r\n this.manager?.destroy();\r\n this.manager = new FocusKeyManager<SkraMenuKeyboardItem>(this.items)\r\n .withWrap()\r\n .withTypeAhead()\r\n .withHomeAndEnd()\r\n // Disabled items stay in the roving order (APG focusable-but-inert — discoverable); activation is\r\n // blocked on the item itself. `() => false` also stops `FocusKeyManager` from reading `item.disabled`\r\n // (which on our signal-input component would be a truthy function).\r\n .skipPredicate(() => false);\r\n this.manager.tabOut.subscribe(() => this.tabOutHandler?.());\r\n }\r\n\r\n /** Delegate Up/Down/Home/End/type-ahead. Enter/Space/Escape are intentionally left to the platform. */\r\n onKeydown(event: KeyboardEvent): void {\r\n this.manager?.onKeydown(event);\r\n }\r\n\r\n /** Move roving focus to the first ENABLED item (APG: focus enters the menu on open). */\r\n focusFirst(): void {\r\n if (!this.manager || this.items.length === 0) return;\r\n const firstEnabled = this.items.findIndex((item) => !item.isDisabled());\r\n this.manager.setActiveItem(firstEnabled >= 0 ? firstEnabled : 0);\r\n }\r\n\r\n destroy(): void {\r\n this.manager?.destroy();\r\n this.manager = undefined;\r\n }\r\n}\r\n","import { InjectionToken } from '@angular/core';\n\n/**\n * The item shape the menu keyboard controller drives. Structurally a CDK `FocusableOption`\n * (`focus()`), plus the menu's own `getLabel()` (type-ahead) and `isDisabled()` (focusable-but-inert\n * roving). Declared HERE — cdk-free — so the only `@angular/cdk` importer stays `menu-keyboard.ts`.\n */\nexport interface SkraMenuKeyboardItem {\n focus(): void;\n getLabel(): string;\n isDisabled(): boolean;\n}\n\n/** What a `skraMenuItem` needs from its `skra-menu` — narrow contract that breaks the menu↔item cycle. */\nexport interface SkraMenuPanel {\n /** Dismiss the menu after an item activates (native `hidePopover()` → focus returns to the trigger). */\n requestClose(): void;\n}\n\n/**\n * DI token a `skra-menu` provides (`useExisting`) and a `button[skraMenuItem]` injects. A token\n * (not the `SkraMenu` class) so the item file never imports the menu file — no runtime import cycle.\n */\nexport const SKRA_MENU = new InjectionToken<SkraMenuPanel>('SKRA_MENU');\n","import {\r\n ChangeDetectionStrategy,\r\n Component,\r\n ElementRef,\r\n ViewEncapsulation,\r\n inject,\r\n} from '@angular/core';\r\n\r\nimport { SKRA_MENU, type SkraMenuKeyboardItem } from './menu-types';\r\n\r\ndeclare const ngDevMode: boolean | undefined;\r\n\r\n/**\r\n * SkraMenuItem — a single command in a `skra-menu`, a Component on the native command host\r\n * `button[skraMenuItem]` (ADR 012/040: a `<button>` is the right semantic — Enter/Space→click +\r\n * focusability for free; its implicit role is overridden to `role=\"menuitem\"` per WAI-ARIA APG).\r\n *\r\n * Roving focus: `tabindex=\"-1\"` (the keyboard controller moves real focus). Implements\r\n * `SkraMenuKeyboardItem` (`focus`/`getLabel`/`isDisabled`) so `SkraMenuKeyboard` (CDK `FocusKeyManager`)\r\n * can drive it. On activation it asks the menu to close (native `hidePopover()` → focus returns to the\r\n * trigger).\r\n *\r\n * **Disabled is native-attr-first (boundary #9, ADR 039 precedent): the consumer sets\r\n * `aria-disabled=\"true\"` directly — Forge OBSERVES it, exposing NO `disabled` input.** This (a) keeps a\r\n * disabled item **focusable/discoverable** in the roving order (APG) — native `disabled` would remove it\r\n * from focus, and (b) avoids a Forge input shadowing the native `disabled` attribute. Styling keys off\r\n * `:host([aria-disabled=\"true\"])`; activation is blocked here.\r\n *\r\n * Full contract: adr/specs/component-menu-spec.md.\r\n */\r\n@Component({\r\n selector: 'button[skraMenuItem]',\r\n standalone: true,\r\n exportAs: 'skraMenuItem',\r\n template: '<ng-content></ng-content>',\r\n styleUrl: './menu-item.scss',\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n encapsulation: ViewEncapsulation.Emulated,\r\n host: {\r\n role: 'menuitem',\r\n type: 'button', // never an implicit submit if the menu sits inside a <form>\r\n tabindex: '-1', // roving — focus is moved programmatically by SkraMenuKeyboard\r\n '(click)': 'onActivate($event)',\r\n },\r\n})\r\nexport class SkraMenuItem implements SkraMenuKeyboardItem {\r\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef);\r\n private readonly menu = inject(SKRA_MENU, { optional: true });\r\n\r\n constructor() {\r\n if (typeof ngDevMode === 'undefined' || ngDevMode) {\r\n if (!this.menu) {\r\n console.warn(\r\n '[skraMenuItem] has no <skra-menu> ancestor — it is not registered with any keyboard ' +\r\n 'controller and cannot close a menu on activation. Project it inside a <skra-menu>.',\r\n );\r\n }\r\n }\r\n }\r\n\r\n // ── SkraMenuKeyboardItem (driven by SkraMenuKeyboard / CDK FocusKeyManager) ──\r\n focus(): void {\r\n this.host.nativeElement.focus();\r\n }\r\n getLabel(): string {\r\n return (this.host.nativeElement.textContent ?? '').trim();\r\n }\r\n /** Soft-disabled = the consumer's `aria-disabled=\"true\"` (native-attr-first); read live (no input). */\r\n isDisabled(): boolean {\r\n return this.host.nativeElement.getAttribute('aria-disabled') === 'true';\r\n }\r\n\r\n protected onActivate(event: MouseEvent): void {\r\n if (this.isDisabled()) {\r\n // Soft-disabled: block the native default. This is a SECOND line of defence only — it cannot\r\n // stop the consumer's own (click) on this same host, because a component host listener\r\n // registers AFTER the parent template's binding, so this bubble-phase handler runs too late.\r\n // The capture-phase guard on the panel (`SkraMenu`) is what actually blocks activation, for\r\n // both pointer and keyboard (Enter/Space produce a UA-synthesized click). Do not delete it.\r\n event.preventDefault();\r\n event.stopImmediatePropagation();\r\n return;\r\n }\r\n // Activating a command closes the menu (APG). The consumer's (click) handler runs independently.\r\n this.menu?.requestClose();\r\n }\r\n}\r\n","import {\r\n ChangeDetectionStrategy,\r\n Component,\r\n DestroyRef,\r\n ElementRef,\r\n Renderer2,\r\n ViewEncapsulation,\r\n afterNextRender,\r\n contentChildren,\r\n effect,\r\n inject,\r\n input,\r\n} from '@angular/core';\r\n\r\nimport {\r\n _attachPositioner,\r\n type SkraPlacement,\r\n type _PositionerHandle,\r\n} from '@skra/ui/core';\r\nimport { SkraMenuKeyboard } from './menu-keyboard';\r\nimport { SkraMenuItem } from './menu-item';\r\nimport { SKRA_MENU, type SkraMenuPanel } from './menu-types';\r\n\r\ndeclare const ngDevMode: boolean | undefined;\r\n\r\n/**\r\n * SkraMenu — a WAI-ARIA APG **Menu Button** menu: a homogeneous set of commands anchored to a\r\n * trigger, navigated as one composite widget with arrow keys, where activating a command closes it.\r\n * Rendered in the browser TOP LAYER via the native Popover API (`popover=\"auto\"`), per ADR 0044.\r\n *\r\n * SHAPE (scope 2026-06-07): a Component on the PANEL with projected `button[skraMenuItem]` children\r\n * (the Popover model, ADR 040) — NOT a directive on the trigger, NOT a data-driven `[items]` array.\r\n * The trigger is the consumer's own button linked by the native `popovertarget` attribute; toggle,\r\n * light-dismiss and Escape are platform-owned. The consumer MUST give `<skra-menu>` an `id`.\r\n *\r\n * <button skraButton popovertarget=\"actions\" aria-haspopup=\"menu\">Actions</button>\r\n * <skra-menu id=\"actions\">\r\n * <button skraMenuItem (click)=\"edit()\">Edit</button>\r\n * <button skraMenuItem aria-disabled=\"true\" (click)=\"archive()\">Archive</button>\r\n * <button skraMenuItem (click)=\"remove()\">Delete</button>\r\n * </skra-menu>\r\n *\r\n * A disabled item is `aria-disabled=\"true\"` set by the CONSUMER — never native `disabled` (boundary\r\n * #9, native-attr-first): the item stays focusable and in the roving order per APG, and a\r\n * capture-phase guard on the panel blocks activation. Native `disabled` would keep it in the roving\r\n * order but make `focus()` a no-op, so arrow navigation would silently dead-end on that row.\r\n *\r\n * Skra adds, on top of the Popover substrate: the `role=\"menu\"` keyboard model via `SkraMenuKeyboard`\r\n * (CDK `FocusKeyManager` — Down/Up roving + wrap, Home/End, type-ahead, Tab-dismiss), **focus moving\r\n * INTO the menu on open** (a composite widget — unlike non-modal Popover; the per-component ADR 0044\r\n * §3 rule-8 decision), and the trigger's disclosure ARIA (`aria-haspopup=\"menu\"` / `aria-controls` /\r\n * `aria-expanded`). Side effects on open/close: bind the native `(toggle)` — there is no Forge output\r\n * (native-first; contrast Dialog, whose `<dialog>` has no open event). Context menus (right-click) are\r\n * a recipe with a visible button, never a trigger mode (SRP + WCAG 2.1.1).\r\n *\r\n * Full contract: adr/specs/component-menu-spec.md.\r\n */\r\n@Component({\r\n selector: 'skra-menu',\r\n standalone: true,\r\n exportAs: 'skraMenu',\r\n template: '<ng-content></ng-content>',\r\n styleUrl: './menu.scss',\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n encapsulation: ViewEncapsulation.Emulated,\r\n providers: [{ provide: SKRA_MENU, useExisting: SkraMenu }],\r\n host: {\r\n role: 'menu',\r\n // Native top layer + platform-owned toggle / light-dismiss / Escape / stacking (ADR 0044).\r\n popover: 'auto',\r\n // NOTE: `toggle` and `keydown` are wired IMPERATIVELY in the constructor, NOT as host listeners.\r\n // A consumer template binding `(toggle)` on <skra-menu> (the documented side-effect path) SHADOWS a\r\n // host-metadata `(toggle)` listener for the same event — which would silently break positioning +\r\n // aria-expanded. A raw `addEventListener` is independent of Angular's host/template listener slot, so\r\n // it always fires alongside the consumer's binding.\r\n },\r\n})\r\nexport class SkraMenu implements SkraMenuPanel {\r\n /** Placement intent; `flip`/`shift` adjust at runtime. */\r\n readonly placement = input<SkraPlacement>('bottom');\r\n\r\n private readonly menuItems = contentChildren(SkraMenuItem, {\r\n descendants: true,\r\n });\r\n\r\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef);\r\n private readonly renderer = inject(Renderer2);\r\n private readonly keyboard = new SkraMenuKeyboard();\r\n\r\n /** The consumer's `[popovertarget]` button; resolution is retried until it succeeds. */\r\n private trigger: HTMLElement | null = null;\r\n /** Latches the dev warning, NOT the resolution — see `ensureTrigger()`. */\r\n private warned = false;\r\n private positioner?: _PositionerHandle;\r\n\r\n constructor() {\r\n // Feed the controller whenever the projected item set changes (signal → array snapshot rebuild).\r\n effect(() => this.keyboard.setItems(this.menuItems()));\r\n // APG: Tab/Shift+Tab dismisses the menu; native Tab then proceeds from the trigger.\r\n this.keyboard.onTabOut(() => this.host.nativeElement.hidePopover?.());\r\n\r\n // All imperative DOM wiring lives in afterNextRender — a browser-only hook, so the native listeners\r\n // and the trigger resolution never run on the server (SSR-safe by construction; O-18). The listeners\r\n // attach right after first paint, long before any user interaction can fire them.\r\n afterNextRender(() => {\r\n const el = this.host.nativeElement;\r\n // Gate disabled items at the CAPTURE phase: a component host listener registers AFTER the parent\r\n // template's `(click)` on the same button, so a bubble-phase guard cannot stop the consumer's own\r\n // handler. A capture listener on the menu host fires before the target's listeners — preventing both\r\n // the consumer's `(click)` and the item's `onActivate` for an `aria-disabled` item.\r\n el.addEventListener('click', this.onCaptureClick, true);\r\n // Imperative (NOT host-metadata) so a consumer `(toggle)` binding does not shadow them — see host {}.\r\n el.addEventListener('toggle', this.onToggleNative);\r\n el.addEventListener('keydown', this.onKeydownNative);\r\n\r\n // Resolve + wire the trigger after the view exists (it may be a later sibling), so the disclosure\r\n // relationship (aria-haspopup + aria-controls + aria-expanded=\"false\") is present before first open.\r\n this.ensureTrigger();\r\n if (typeof ngDevMode === 'undefined' || ngDevMode) this.warnIfEmpty();\r\n });\r\n inject(DestroyRef).onDestroy(() => this.teardown());\r\n }\r\n\r\n /** SKRA_MENU contract — close on item activation (native focus-return to the trigger). */\r\n requestClose(): void {\r\n this.host.nativeElement.hidePopover?.();\r\n }\r\n\r\n /** Capture-phase guard: block clicks on an `aria-disabled` item before they reach its listeners. */\r\n private readonly onCaptureClick = (event: Event): void => {\r\n const item = (event.target as HTMLElement | null)?.closest?.(\r\n '[skraMenuItem]',\r\n );\r\n if (item?.getAttribute('aria-disabled') === 'true') {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n }\r\n };\r\n\r\n // ── Toggle / keydown (imperative native listeners — see host {} note) ─────────\r\n private readonly onToggleNative = (event: Event): void => {\r\n if ((event as ToggleEvent).newState === 'open') this.onOpen();\r\n else this.onClose();\r\n };\r\n\r\n private readonly onKeydownNative = (event: Event): void => {\r\n this.keyboard.onKeydown(event as KeyboardEvent);\r\n };\r\n\r\n private onOpen(): void {\r\n const anchor = this.ensureTrigger(); // safety net if afterNextRender has not yet run\r\n if (anchor) {\r\n this.renderer.setAttribute(anchor, 'aria-expanded', 'true');\r\n this.positioner?.destroy();\r\n this.positioner = _attachPositioner(\r\n anchor,\r\n this.host.nativeElement,\r\n () => ({\r\n placement: this.placement(),\r\n offset: this.cssLenPx('--skra-comp-menu-offset'),\r\n viewportPadding: this.cssLenPx('--skra-comp-menu-viewport-padding'),\r\n }),\r\n );\r\n }\r\n // Focus enters the menu (APG Menu Button) regardless of how it opened — unlike non-modal Popover.\r\n this.keyboard.focusFirst();\r\n }\r\n\r\n private onClose(): void {\r\n if (this.trigger) {\r\n this.renderer.setAttribute(this.trigger, 'aria-expanded', 'false');\r\n }\r\n this.positioner?.destroy();\r\n this.positioner = undefined;\r\n }\r\n\r\n /**\r\n * Resolve the `[popovertarget]` trigger and establish the menu disclosure ARIA on it (sanctioned a11y\r\n * wiring, ADR 013-style — not style mutation). Returns the trigger (or null for an orphan menu,\r\n * dev-warned once).\r\n *\r\n * Idempotent on SUCCESS only — see the same note on `SkraPopover.ensureTrigger()`. Latching on\r\n * failure would permanently strand a trigger rendered behind an `@if` / lazy route / `@defer`:\r\n * no disclosure ARIA, and `onOpen()` bails on the null anchor so the panel opens unpositioned at\r\n * viewport 0,0 — the exact signature of impl-finding #1 in the spec. The dev warning latches\r\n * separately via `warned`.\r\n */\r\n private ensureTrigger(): HTMLElement | null {\r\n if (this.trigger) return this.trigger;\r\n\r\n const id = this.host.nativeElement.id;\r\n if (!id) {\r\n if (!this.warned && (typeof ngDevMode === 'undefined' || ngDevMode)) {\r\n this.warned = true;\r\n console.warn(\r\n '[skra-menu] has no `id` — it cannot be targeted by a `popovertarget` trigger and the ' +\r\n 'disclosure ARIA (aria-haspopup/aria-controls/aria-expanded) cannot be wired. Give the ' +\r\n 'menu an id and point a button at it: ' +\r\n '<button popovertarget=\"my-id\" aria-haspopup=\"menu\">…</button> <skra-menu id=\"my-id\">…',\r\n );\r\n }\r\n return null;\r\n }\r\n\r\n // Scope to this node's own root, not `document`: under the ADR 012 §5 delivery contract both\r\n // trigger and panel live inside a shadow root, where a document-rooted query finds nothing.\r\n // `getRootNode()` returns `document` in the light-DOM case, so this is strictly a widening.\r\n //\r\n // Match by attribute value (no escaping; robust to special chars; `CSS.escape` is not universal).\r\n const root = this.host.nativeElement.getRootNode() as Document | ShadowRoot;\r\n this.trigger =\r\n Array.from(root.querySelectorAll<HTMLElement>('[popovertarget]')).find(\r\n (el) => el.getAttribute('popovertarget') === id,\r\n ) ?? null;\r\n if (!this.trigger) {\r\n if (!this.warned && (typeof ngDevMode === 'undefined' || ngDevMode)) {\r\n this.warned = true;\r\n console.warn(\r\n `[skra-menu] no trigger found with [popovertarget=\"${id}\"] — the menu is unreachable and ` +\r\n 'has no element to carry aria-haspopup/aria-controls/aria-expanded. Add a focusable trigger ' +\r\n 'button with the matching popovertarget.',\r\n );\r\n }\r\n return null;\r\n }\r\n\r\n // Establish the Menu Button relationship before the first open (APG; aria-haspopup distinguishes a\r\n // menu from Popover's generic disclosure).\r\n this.renderer.setAttribute(this.trigger, 'aria-haspopup', 'menu');\r\n this.renderer.setAttribute(this.trigger, 'aria-controls', id);\r\n this.renderer.setAttribute(this.trigger, 'aria-expanded', 'false');\r\n return this.trigger;\r\n }\r\n\r\n /** Read a length comp token (px/rem) off the host computed style for the positioner. */\r\n private cssLenPx(prop: string): number {\r\n const raw = getComputedStyle(this.host.nativeElement)\r\n .getPropertyValue(prop)\r\n .trim();\r\n if (raw.endsWith('px')) return parseFloat(raw);\r\n if (raw.endsWith('rem')) {\r\n const rootFontSize =\r\n parseFloat(getComputedStyle(document.documentElement).fontSize) || 16;\r\n return parseFloat(raw) * rootFontSize;\r\n }\r\n return parseFloat(raw) || 0;\r\n }\r\n\r\n /** Dev-only nudge: a role=\"menu\" with no menuitems is invalid — a link-list/content panel is a Popover. */\r\n private warnIfEmpty(): void {\r\n if (this.menuItems().length === 0) {\r\n console.warn(\r\n '[skra-menu] has no `button[skraMenuItem]` children — a `role=\"menu\"` with no menu items is ' +\r\n 'invalid. If this is a panel of arbitrary content or a list of navigation links, use ' +\r\n '<skra-popover> (disclosure) instead — see the Menu-vs-Popover boundary in the spec.',\r\n );\r\n }\r\n }\r\n\r\n private teardown(): void {\r\n const el = this.host.nativeElement;\r\n el.removeEventListener('click', this.onCaptureClick, true);\r\n el.removeEventListener('toggle', this.onToggleNative);\r\n el.removeEventListener('keydown', this.onKeydownNative);\r\n this.keyboard.destroy();\r\n this.positioner?.destroy();\r\n if (this.trigger) {\r\n this.renderer.removeAttribute(this.trigger, 'aria-haspopup');\r\n this.renderer.removeAttribute(this.trigger, 'aria-expanded');\r\n this.renderer.removeAttribute(this.trigger, 'aria-controls');\r\n }\r\n }\r\n}\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|