@cdevhub/ngx-tw 0.6.1 → 0.7.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.
Files changed (47) hide show
  1. package/fesm2022/cdevhub-ngx-tw-alert.mjs +8 -1
  2. package/fesm2022/cdevhub-ngx-tw-alert.mjs.map +1 -1
  3. package/fesm2022/cdevhub-ngx-tw-badge.mjs +18 -8
  4. package/fesm2022/cdevhub-ngx-tw-badge.mjs.map +1 -1
  5. package/fesm2022/cdevhub-ngx-tw-button.mjs +14 -8
  6. package/fesm2022/cdevhub-ngx-tw-button.mjs.map +1 -1
  7. package/fesm2022/cdevhub-ngx-tw-card.mjs +7 -7
  8. package/fesm2022/cdevhub-ngx-tw-card.mjs.map +1 -1
  9. package/fesm2022/cdevhub-ngx-tw-checkbox.mjs +2 -2
  10. package/fesm2022/cdevhub-ngx-tw-checkbox.mjs.map +1 -1
  11. package/fesm2022/cdevhub-ngx-tw-collapsible.mjs +7 -7
  12. package/fesm2022/cdevhub-ngx-tw-collapsible.mjs.map +1 -1
  13. package/fesm2022/cdevhub-ngx-tw-combobox.mjs +8 -8
  14. package/fesm2022/cdevhub-ngx-tw-combobox.mjs.map +1 -1
  15. package/fesm2022/cdevhub-ngx-tw-date-picker.mjs +8 -8
  16. package/fesm2022/cdevhub-ngx-tw-date-picker.mjs.map +1 -1
  17. package/fesm2022/cdevhub-ngx-tw-date-range-picker.mjs +8 -8
  18. package/fesm2022/cdevhub-ngx-tw-date-range-picker.mjs.map +1 -1
  19. package/fesm2022/cdevhub-ngx-tw-form-field.mjs +16 -16
  20. package/fesm2022/cdevhub-ngx-tw-form-field.mjs.map +1 -1
  21. package/fesm2022/cdevhub-ngx-tw-input.mjs +1 -1
  22. package/fesm2022/cdevhub-ngx-tw-input.mjs.map +1 -1
  23. package/fesm2022/cdevhub-ngx-tw-paginator.mjs +7 -7
  24. package/fesm2022/cdevhub-ngx-tw-paginator.mjs.map +1 -1
  25. package/fesm2022/cdevhub-ngx-tw-popover.mjs +10 -4
  26. package/fesm2022/cdevhub-ngx-tw-popover.mjs.map +1 -1
  27. package/fesm2022/cdevhub-ngx-tw-radio.mjs +2 -2
  28. package/fesm2022/cdevhub-ngx-tw-radio.mjs.map +1 -1
  29. package/fesm2022/cdevhub-ngx-tw-select.mjs +7 -7
  30. package/fesm2022/cdevhub-ngx-tw-select.mjs.map +1 -1
  31. package/fesm2022/cdevhub-ngx-tw-separator.mjs +7 -7
  32. package/fesm2022/cdevhub-ngx-tw-separator.mjs.map +1 -1
  33. package/fesm2022/cdevhub-ngx-tw-slider.mjs +21 -21
  34. package/fesm2022/cdevhub-ngx-tw-slider.mjs.map +1 -1
  35. package/fesm2022/cdevhub-ngx-tw-switch.mjs +1 -1
  36. package/fesm2022/cdevhub-ngx-tw-switch.mjs.map +1 -1
  37. package/fesm2022/cdevhub-ngx-tw-tabs.mjs +29 -9
  38. package/fesm2022/cdevhub-ngx-tw-tabs.mjs.map +1 -1
  39. package/fesm2022/cdevhub-ngx-tw-tags-input.mjs +8 -8
  40. package/fesm2022/cdevhub-ngx-tw-tags-input.mjs.map +1 -1
  41. package/fesm2022/cdevhub-ngx-tw-theme.mjs.map +1 -1
  42. package/fesm2022/cdevhub-ngx-tw-time-picker.mjs +8 -8
  43. package/fesm2022/cdevhub-ngx-tw-time-picker.mjs.map +1 -1
  44. package/index.json +1 -1
  45. package/package.json +1 -1
  46. package/types/cdevhub-ngx-tw-tabs.d.ts +23 -3
  47. package/types/cdevhub-ngx-tw-theme.d.ts +18 -1
@@ -1 +1 @@
1
- {"version":3,"file":"cdevhub-ngx-tw-tags-input.mjs","sources":["../../../projects/ngx-tw/tags-input/tags-input.ts","../../../projects/ngx-tw/tags-input/cdevhub-ngx-tw-tags-input.ts"],"sourcesContent":["import {\n afterNextRender,\n ChangeDetectionStrategy,\n Component,\n computed,\n DestroyRef,\n effect,\n ElementRef,\n forwardRef,\n inject,\n input,\n isDevMode,\n type OnInit,\n output,\n signal,\n type Signal,\n untracked,\n viewChild,\n viewChildren,\n} from '@angular/core';\nimport { type ControlValueAccessor, NgControl } from '@angular/forms';\nimport { FocusMonitor, LiveAnnouncer } from '@angular/cdk/a11y';\nimport { Directionality } from '@angular/cdk/bidi';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { isObservable } from 'rxjs';\nimport { tv } from 'tailwind-variants';\nimport {\n type ErrorStateMatcher,\n type TwColor,\n type TwSize,\n wireErrorState,\n} from '@cdevhub/ngx-tw/core';\nimport {\n FormFieldControl,\n TW_FORM_FIELD,\n TW_FORM_FIELD_CONTROL,\n} from '@cdevhub/ngx-tw/form-field';\nimport { BadgeComponent } from '@cdevhub/ngx-tw/badge';\nimport type {\n TwTagAddedEvent,\n TwTagCompareFn,\n TwTagFactory,\n TwTagLabelFn,\n TwTagRemovedEvent,\n} from './types';\n\n// ── tv() config ──\n// `focus-within:outline-{color}-500` and the chip color classes are emitted by\n// combobox / badge already, so the Tailwind v4 JIT scanner picks them up.\n\nconst tagsInputVariants = tv(\n {\n slots: {\n // Host is the `role=\"group\"` chip strip. `flex-wrap` lets chips wrap; the\n // container owns the focus-within ring (standalone) or strips its chrome\n // inside a `<tw-form-field>` (the field draws the border / focus border).\n root: 'flex flex-wrap items-center gap-1.5 w-full text-fg',\n chip: 'max-w-full min-w-0',\n chipLabel: 'truncate',\n // Real DOM focus → canonical outline ring (NOT the activedescendant\n // background-shift carve-out). `text-current` inherits the chip color.\n // Per-size sets the square-interactive target size + negative margins.\n removeButton:\n 'inline-flex items-center justify-center shrink-0 ml-0.5 rounded-md text-current opacity-70 hover:opacity-100 transition-opacity duration-normal motion-reduce:transition-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary-500 disabled:pointer-events-none',\n removeIcon: 'shrink-0',\n input:\n 'flex-1 min-w-24 bg-transparent text-fg placeholder:text-fg-subtle outline-none disabled:cursor-not-allowed',\n },\n variants: {\n inFormField: {\n // Inside a form-field: keep only the chip-strip layout; the field owns\n // border, padding, background and the focused-border indicator.\n true: { root: '' },\n false: {\n root: 'rounded-md border border-border bg-surface transition-colors duration-normal motion-reduce:transition-none hover:border-border-strong focus-within:outline-2 focus-within:outline-offset-2',\n },\n },\n size: {\n // removeButton uses the square-interactive sub-scale (the button IS the\n // touch target): size-6 (24px) meets WCAG 2.5.8; negative margins absorb\n // the overflow so the chip height is unchanged. Mirrors badge's dismiss.\n // `size-3.5` half-step on the md remove glyph lines up the X with text-sm\n // at md density (codified half-step per CLAUDE.md icon sizing).\n xs: { root: 'text-xs', removeButton: 'size-6 -my-1 -mr-1', removeIcon: 'size-3' },\n sm: { root: 'text-sm', removeButton: 'size-6 -my-1 -mr-1', removeIcon: 'size-3' },\n md: { root: 'text-sm', removeButton: 'size-7 -my-1.5 -mr-1.5', removeIcon: 'size-3.5' },\n lg: { root: 'text-base', removeButton: 'size-8 -my-1.5 -mr-1.5', removeIcon: 'size-4' },\n xl: { root: 'text-base', removeButton: 'size-8 -my-1.5 -mr-1.5', removeIcon: 'size-4' },\n },\n color: {\n primary: { root: 'focus-within:outline-primary-500' },\n secondary: { root: 'focus-within:outline-secondary-500' },\n accent: { root: 'focus-within:outline-accent-500' },\n neutral: { root: 'focus-within:outline-border-strong' },\n info: { root: 'focus-within:outline-info-500' },\n success: { root: 'focus-within:outline-success-500' },\n warning: { root: 'focus-within:outline-warning-500' },\n error: { root: 'focus-within:outline-error-500' },\n },\n disabled: {\n true: { root: 'opacity-50 pointer-events-none cursor-not-allowed' },\n false: {},\n },\n errorState: {\n true: {},\n false: {},\n },\n },\n compoundVariants: [\n // Standalone density × size — inline padding scale (mirrors combobox trigger)\n // plus the control-height FLOOR. Per docs/vertical-rhythm.md §2 the chip\n // strip is a `min-h` control, not a pinned one: chips wrap, so `py-*` stays\n // exactly as it is and `min-h-*` only guarantees the box never sits below\n // the control scale. Standalone-only, alongside the padding: inside a\n // `tw-form-field` the root drops its border and padding and the field owns\n // the box, so a floor here would stack on top of the field's own padding.\n // Vertical padding is set so the `min-h-*` floor actually BINDS at rest.\n //\n // The tallest resting content is a CHIP, not the bare input line box. A\n // chip is a badge: its own padding and text size make it taller than the\n // input beside it at every size, so the box arithmetic that decides\n // whether the floor binds is\n //\n // chip + 2*py + 2px border <= floor\n //\n // Sizing the padding against the input line box instead left the floor\n // inert the moment a single tag existed. Empty, the control measured\n // correctly at all five sizes; populated, it measured 26 / 32 / 38 / 50 /\n // 54 against a 24 / 32 / 36 / 44 / 48 scale — so a filter bar was on the\n // grid until the user typed the first tag, then jumped 2px at xs and md\n // and 6px at lg and xl. Only sm was ever correct, which is why the\n // isolated slot reading looked like a one-off rather than a broken rule.\n //\n // Resting appearance does not change: once the floor binds, `items-center`\n // centres the chip and the padding is no longer what sets the height. The\n // padding still governs the multi-line case, where chips wrap and the box\n // legitimately grows past the floor.\n //\n // Chip heights are 20 / 20 / 24 / 32 / 32, so the padding ceiling is\n // 1 / 5 / 5 / 5 / 7px. `py-px` at xs is not decorative restraint: a 20px\n // chip inside a 24px control with a 1px border leaves exactly 1px a side.\n { inFormField: false, size: 'xs', class: { root: 'px-2 py-px min-h-6' } },\n { inFormField: false, size: 'sm', class: { root: 'px-3 py-1 min-h-8' } },\n { inFormField: false, size: 'md', class: { root: 'px-4 py-1 min-h-9' } },\n { inFormField: false, size: 'lg', class: { root: 'px-5 py-1 min-h-11' } },\n { inFormField: false, size: 'xl', class: { root: 'px-6 py-1.5 min-h-12' } },\n // Standalone error state — colored border + focus ring.\n {\n inFormField: false,\n errorState: true,\n class: { root: 'border-error-500 focus-within:outline-error-500' },\n },\n ],\n defaultVariants: {\n inFormField: false,\n size: 'md',\n color: 'primary',\n disabled: false,\n errorState: false,\n },\n },\n { twMerge: true },\n);\n\nconst DEFAULT_SEPARATORS: readonly string[] = ['Enter', ','];\n\nlet nextId = 0;\n\n/**\n * Free-text multi-value input. The user types a token and commits it via Enter,\n * a separator key, paste, or blur; committed tokens render as dismissible chips\n * (composing `[twBadge]`) inline with the text input. The value is exposed as a\n * real `T[]` (default `string[]`) through `ControlValueAccessor`, so it works\n * with template-driven, reactive, and signal forms and integrates with\n * `<tw-form-field>` for label / hint / error chrome.\n *\n * The control is a single tab stop with a roving-tabindex chip strip\n * (Material `MatChipGrid` interaction model): Arrow keys traverse chips and the\n * input, Delete / a two-step Backspace remove chips, and `LiveAnnouncer` voices\n * add / remove. Autocomplete suggestions are out of scope (use `tw-combobox`).\n */\n@Component({\n selector: 'tw-tags-input',\n exportAs: 'twTagsInput',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [BadgeComponent],\n providers: [\n {\n provide: TW_FORM_FIELD_CONTROL,\n useExisting: forwardRef(() => TagsInputComponent),\n },\n ],\n template: `\n @for (chip of chipViews(); track chip.index) {\n <span twBadge variant=\"soft\" [color]=\"color()\" [size]=\"size()\" [class]=\"chipClasses()\">\n <span [class]=\"chipLabelClasses()\">{{ chip.label }}</span>\n <button\n #removeBtn\n type=\"button\"\n [class]=\"removeButtonClasses()\"\n [attr.tabindex]=\"activeChipIndex() === chip.index ? 0 : -1\"\n [attr.aria-label]=\"chip.removeLabel\"\n [disabled]=\"disabled()\"\n (click)=\"onRemoveClick(chip.index)\"\n (keydown)=\"onChipKeydown($event, chip.index)\"\n >\n <svg\n viewBox=\"0 0 16 16\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n [class]=\"removeIconClasses()\"\n >\n <path\n d=\"M5.28 4.22a.75.75 0 0 0-1.06 1.06L6.94 8l-2.72 2.72a.75.75 0 1 0 1.06 1.06L8 9.06l2.72 2.72a.75.75 0 1 0 1.06-1.06L9.06 8l2.72-2.72a.75.75 0 0 0-1.06-1.06L8 6.94 5.28 4.22Z\"\n />\n </svg>\n </button>\n </span>\n }\n <input\n #textInput\n type=\"text\"\n [class]=\"inputClasses()\"\n [attr.tabindex]=\"activeChipIndex() === null ? 0 : -1\"\n [attr.placeholder]=\"placeholder() || null\"\n [attr.aria-required]=\"required() || null\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-labelledby]=\"resolvedLabelledBy() || null\"\n [attr.aria-describedby]=\"resolvedDescribedBy() || null\"\n [attr.aria-invalid]=\"errorState() || null\"\n [attr.name]=\"name() || null\"\n [disabled]=\"disabled()\"\n (input)=\"onInput($event)\"\n (keydown)=\"onInputKeydown($event)\"\n (paste)=\"onPaste($event)\"\n />\n `,\n host: {\n 'role': 'group',\n '[id]': 'id()',\n '[class]': 'rootClasses()',\n '[attr.aria-label]': 'ariaLabel() || null',\n '[attr.aria-labelledby]': 'resolvedLabelledBy() || null',\n '[attr.aria-describedby]': 'resolvedDescribedBy() || null',\n '[attr.aria-disabled]': 'disabled() || null',\n // NOTE: no `aria-invalid` here. ARIA 1.2 does not allow it on\n // `role=\"group\"` (axe: critical `aria-allowed-attr`). The inner\n // `<input type=\"text\">` already carries it — that is the control with the\n // value. Latent rather than observed: it only fires once a consumer puts\n // the control into an error state.\n '[attr.data-focused]': 'focused() || null',\n },\n})\nexport class TagsInputComponent<T = string>\n extends FormFieldControl<T[]>\n implements ControlValueAccessor, OnInit\n{\n /** Semantic color for the container focus-within ring and the chip accent. Defaults to `'primary'`. */\n readonly color = input<TwColor>('primary');\n\n /** Controls overall density: container padding, chip size, and text scale. Defaults to `'md'`. */\n readonly size = input<TwSize>('md');\n\n /** When true, blocks typing, committing, and chip removal, and applies muted styling. Reactive forms also propagate disabled via `setDisabledState`. Defaults to `false`. */\n readonly disabledInput = input(false, { alias: 'disabled' });\n\n /** Marks the control as required. Mirrored to the input's `aria-required`. Also inferred from `Validators.required` on a bound control. Defaults to `false`. */\n readonly requiredInput = input(false, { alias: 'required' });\n\n /** Placeholder shown in the text input only while there are no chips and the input is empty. Defaults to `undefined`. */\n readonly placeholder = input<string | undefined>(undefined);\n\n /** Keys that commit the in-progress text as a tag. Each entry is a `KeyboardEvent.key` value (`'Enter'`) or a single separator character (`','`). Single-character separators also split pasted text. Defaults to `['Enter', ',']`. */\n readonly separatorKeys = input<readonly string[]>(DEFAULT_SEPARATORS);\n\n /** When true, blurring the control while the input holds non-empty text commits it as a tag. Defaults to `false`. */\n readonly addOnBlur = input(false);\n\n /** Maximum number of tags. Once reached, further commits are blocked and announced. Does not truncate an oversized `writeValue`. Defaults to `undefined` (no limit). */\n readonly maxTags = input<number | undefined>(undefined);\n\n /** When false (default), a committed tag equal (per `compareWith`) to an existing tag is dropped silently. When true, duplicates are kept. Defaults to `false`. */\n readonly allowDuplicates = input(false);\n\n /** Maps committed text to a tag value. Default is identity — the trimmed string. Override to build object tags. */\n readonly createTag = input<TwTagFactory<T>>(\n ((text: string) => text) as unknown as TwTagFactory<T>,\n );\n\n /** Maps a tag value to its visible chip label and the remove-button accessible name. Defaults to `String(tag)`. */\n readonly tagLabel = input<TwTagLabelFn<T>>((tag: T) => String(tag));\n\n /** Equality comparator used for dedup when `allowDuplicates` is false. Defaults to `Object.is` (reference / value identity). String tags dedupe case-sensitively by default; pass `(a, b) => a.toLowerCase() === b.toLowerCase()` for case-insensitive dedup. */\n readonly compareWith = input<TwTagCompareFn<T>>((a: T, b: T) => Object.is(a, b));\n\n /** Applied to the text input for labeling and identification only; does not submit the tag array via native (non-Angular) form posting. Defaults to `undefined`. */\n readonly name = input<string | undefined>(undefined);\n\n /** Id on the host element. Auto-generated as `tw-tags-input-N` when not provided. Used by the form-field's `<label for>` association. */\n readonly idInput = input<string | undefined>(undefined, { alias: 'id' });\n\n /** Accessible name applied to the control when no visible label is wired. Mirrored to `aria-label`. Defaults to `undefined`. */\n readonly ariaLabel = input<string | undefined>(undefined, { alias: 'aria-label' });\n\n /** ID of an external element that labels the control. Mirrored to `aria-labelledby`. Defaults to `undefined`. */\n readonly ariaLabelledby = input<string | undefined>(undefined, { alias: 'aria-labelledby' });\n\n /** ID of an external element that describes the control. Form-field merges its hint / error ids alongside. Defaults to `undefined`. Alias: `aria-describedby`. */\n readonly ariaDescribedby = input<string | undefined>(undefined, { alias: 'aria-describedby' });\n\n /** Per-instance override of the {@link ErrorStateMatcher}. When omitted, uses the `TW_ERROR_STATE_MATCHER` token's value. */\n readonly errorStateMatcher = input<ErrorStateMatcher | undefined>(undefined);\n\n /**\n * Fires when the tag array changes through user interaction (add, remove,\n * clear). Emits a fresh array reference. Does **not** fire on `writeValue` /\n * `FormControl.setValue` / `ngModel`.\n *\n * This is a hand-written, user-gesture-only output. The control exposes no\n * `value` input and therefore no two-way binding, so — unlike\n * `tw-checkbox` / `tw-switch` / `tw-radio-group`, where `(valueChange)` /\n * `(checkedChange)` is minted by a `model()` and fires on programmatic writes\n * too — there is no any-change channel here. Observe programmatic writes\n * through the bound form control's own `valueChanges`.\n */\n readonly valueChange = output<T[]>();\n\n /** Fires when a tag is committed via Enter, a separator key, paste, or `addTag()`. Does not fire for dropped duplicates, blocked-by-max commits, empty commits, or `writeValue`. */\n readonly tagAdded = output<TwTagAddedEvent<T>>();\n\n /** Fires when a tag is removed via the remove button, Backspace / Delete, or `removeTag()`. Does not fire on `writeValue` or `clear()`. */\n readonly tagRemoved = output<TwTagRemovedEvent<T>>();\n\n private readonly focusMonitor = inject(FocusMonitor);\n private readonly liveAnnouncer = inject(LiveAnnouncer);\n private readonly elementRef = inject(ElementRef<HTMLElement>);\n private readonly destroyRef = inject(DestroyRef);\n private readonly ngControl = inject(NgControl, { optional: true, self: true });\n private readonly formField = inject(TW_FORM_FIELD, { optional: true });\n /**\n * Optional so a consumer that never imports `BidiModule` still gets a working\n * control — chip navigation falls back to LTR when the token is absent. Read\n * imperatively inside the keydown handlers; nothing here needs to re-render\n * on a direction change.\n */\n private readonly directionality = inject(Directionality, { optional: true });\n\n private readonly textInputRef = viewChild<ElementRef<HTMLInputElement>>('textInput');\n private readonly removeButtons = viewChildren<ElementRef<HTMLButtonElement>>('removeBtn');\n\n private onChange: (value: T[]) => void = () => {};\n private onTouched: () => void = () => {};\n\n private readonly tags = signal<T[]>([]);\n /** The current in-progress (uncommitted) text in the input. Empty when nothing is typed. */\n readonly inputText = signal('');\n /** @internal Roving-tabindex position. `null` = the text input is the active element; a number = that chip's remove button. */\n protected readonly activeChipIndex = signal<number | null>(null);\n private readonly cvaDisabled = signal(false);\n private readonly _focused = signal(false);\n\n /** @internal Shared `errorState` / `required` / `errors` derivation — see `wireErrorState`. */\n private readonly errorWiring = wireErrorState({\n ngControl: () => this.ngControl,\n matcher: () => this.errorStateMatcher(),\n required: () => this.requiredInput(),\n track: [() => this._focused()],\n });\n private readonly describedByIdsSignal = signal<readonly string[]>([]);\n private readonly labelledByIdsSignal = signal<readonly string[]>([]);\n /** Nonce bumped only on explicit focus intent — keeps the focus effect from stealing focus on unrelated renders. */\n private readonly focusNonce = signal(0);\n private lastMaxAnnounce = 0;\n\n private readonly uid = nextId++;\n /** @internal Fallback id used when the consumer does not set `[id]`. */\n readonly hostId = `tw-tags-input-${this.uid}`;\n\n // ── FormFieldControl signals ──\n\n /** @internal */\n readonly id: Signal<string> = computed(() => this.idInput() ?? this.hostId);\n\n /** The current tag array (empty array when there are no tags). Read from a template ref (`#t=\"twTagsInput\"`) for non-form usage. Doubles as the `FormFieldControl` contract member. */\n readonly value: Signal<T[]> = this.tags.asReadonly();\n\n /** @internal */\n readonly focused: Signal<boolean> = this._focused.asReadonly();\n\n /** @internal Empty when there are no chips AND the input text is blank — drives the form-field floating label. */\n readonly empty: Signal<boolean> = computed(\n () => this.tags().length === 0 && this.inputText().trim().length === 0,\n );\n\n /** @internal */\n readonly disabled: Signal<boolean> = computed(\n () => this.disabledInput() || this.cvaDisabled(),\n );\n\n /** @internal */\n readonly required: Signal<boolean> = this.errorWiring.required;\n\n /** @internal */\n readonly errorState: Signal<boolean> = this.errorWiring.errorState;\n\n /** @internal Active validation errors map from the bound control, for `[twError match=\"…\"]` filtering. */\n override readonly errors = this.errorWiring.errors;\n\n /** @internal */\n readonly controlType = 'tags-input';\n\n /** @internal */\n readonly userAriaDescribedBy: Signal<string | undefined> = computed(() => this.ariaDescribedby());\n\n /** @internal */\n override readonly userAriaLabelledby: Signal<string | undefined> = computed(() =>\n this.ariaLabelledby(),\n );\n\n // ── Effective ARIA ──\n //\n // When wrapped by `<tw-form-field>`, the form-field pushes the FULLY MERGED\n // id list (hint/error/label + the consumer's `aria-*by` ids) via\n // `setDescribedByIds` / `setLabelledByIds`. In that case the pushed ids alone\n // are the source of truth — re-merging the consumer's `aria-*by` input on top\n // would duplicate ids. When standalone, fall back to the consumer-supplied\n // `aria-*by` input.\n\n /** @internal Merged `aria-describedby` (form-field hint/error ids + consumer-supplied). */\n readonly resolvedDescribedBy = computed(() => {\n const pushed = this.describedByIdsSignal();\n if (pushed.length) return pushed.join(' ');\n const user = this.ariaDescribedby();\n if (user) return user.split(/\\s+/).filter(Boolean).join(' ');\n return '';\n });\n\n /** @internal Merged `aria-labelledby` (form-field label id + consumer-supplied). */\n readonly resolvedLabelledBy = computed(() => {\n const pushed = this.labelledByIdsSignal();\n if (pushed.length) return pushed.join(' ');\n const user = this.ariaLabelledby();\n if (user) return user.split(/\\s+/).filter(Boolean).join(' ');\n return '';\n });\n\n // ── tv() class bindings ──\n\n private readonly variantResult = computed(() =>\n tagsInputVariants({\n inFormField: !!this.formField,\n size: this.size(),\n color: this.color(),\n disabled: this.disabled(),\n errorState: this.errorState(),\n }),\n );\n\n /** @internal */\n readonly rootClasses = computed(() => this.variantResult().root());\n /** @internal */\n readonly chipClasses = computed(() => this.variantResult().chip());\n /** @internal */\n readonly chipLabelClasses = computed(() => this.variantResult().chipLabel());\n /** @internal */\n readonly removeButtonClasses = computed(() => this.variantResult().removeButton());\n /** @internal */\n readonly removeIconClasses = computed(() => this.variantResult().removeIcon());\n /** @internal */\n readonly inputClasses = computed(() => this.variantResult().input());\n\n /** @internal Pre-resolved chip view models so the template never calls accessor functions inline. */\n readonly chipViews = computed(() => {\n const label = this.tagLabel();\n return this.tags().map((tag, index) => {\n const text = label(tag);\n return { tag, label: text, removeLabel: `Remove ${text}`, index };\n });\n });\n\n constructor() {\n super();\n // Runtime CVA wiring — register on any host-level NgControl. The component\n // injects `NgControl { self }` for TW_ERROR_STATE_MATCHER, so a static\n // NG_VALUE_ACCESSOR provider would create circular DI on the same instance.\n if (this.ngControl) {\n this.ngControl.valueAccessor = this;\n }\n\n // Focus side-effect (leaves the signal graph; writes no signal → no cycle).\n // Triggered only by `focusNonce` bumps so it never steals focus on an\n // unrelated render (e.g. initial mount). Reads the active index and refs\n // untracked so it does not re-fire when the chip list changes on its own.\n effect(() => {\n if (this.focusNonce() === 0) return;\n untracked(() => {\n const idx = this.activeChipIndex();\n if (idx === null) {\n this.textInputRef()?.nativeElement.focus();\n } else {\n this.removeButtons()[idx]?.nativeElement.focus();\n }\n });\n });\n\n afterNextRender(() => {\n if (isDevMode() && !this.hasAccessibleNameHint()) {\n console.warn(\n '[tw-tags-input] The control has no accessible name. Provide `aria-label` / `aria-labelledby`, or wrap it in a <tw-form-field> with a <label twLabel>.',\n );\n }\n });\n }\n\n // ── Public instance API ──\n\n /** Commits `text` as a tag (trim → `createTag` → dedup unless `allowDuplicates` → `maxTags` check). Returns true if a tag was added, false if dropped (empty / duplicate / max). Emits `tagAdded` + `valueChange` on success. No-op when disabled. */\n addTag(text: string): boolean {\n if (this.disabled()) return false;\n const trimmed = text.trim();\n if (!trimmed) return false;\n return this.tryAdd(this.createTag()(trimmed)) === 'added';\n }\n\n /** Removes a tag by value (first match via `compareWith`) or by index when a number is passed. Emits `tagRemoved` + `valueChange` and restores focus. No-op when disabled or when no match. Note: when the tag type is `number`, the argument is treated as an index. */\n removeTag(tag: T | number): void {\n if (this.disabled()) return;\n if (typeof tag === 'number') {\n this.removeAt(tag);\n return;\n }\n const cmp = this.compareWith();\n const idx = this.tags().findIndex((t) => cmp(t, tag));\n if (idx >= 0) this.removeAt(idx);\n }\n\n /** Removes all tags and clears the in-progress input text. Emits `valueChange` with `[]`. Does NOT emit `tagRemoved` per tag (bulk reset). No-op when already empty or disabled. */\n clear(): void {\n if (this.disabled()) return;\n if (this.tags().length === 0 && this.inputText().length === 0) return;\n this.tags.set([]);\n this.setInputText('');\n this.activeChipIndex.set(null);\n this.onChange([]);\n this.valueChange.emit([]);\n this.liveAnnouncer.announce('All tags removed', 'polite');\n }\n\n /** Moves focus to the text input. */\n focus(): void {\n this.activeChipIndex.set(null);\n this.requestFocus();\n }\n\n // ── Internal commit / remove pipeline ──\n\n private tryAdd(tag: T): 'added' | 'duplicate' | 'max' {\n const current = this.tags();\n if (!this.allowDuplicates()) {\n const cmp = this.compareWith();\n if (current.some((e) => cmp(e, tag))) return 'duplicate';\n }\n const max = this.maxTags();\n if (max !== undefined && current.length >= max) {\n this.announceMax();\n return 'max';\n }\n const next = [...current, tag];\n this.tags.set(next);\n this.onChange(next);\n this.tagAdded.emit({ tag, value: next });\n this.valueChange.emit(next);\n this.liveAnnouncer.announce(`${this.tagLabel()(tag)} added`, 'polite');\n return 'added';\n }\n\n private commitInput(): void {\n if (this.disabled()) return;\n const trimmed = this.inputText().trim();\n if (!trimmed) {\n this.setInputText('');\n return;\n }\n const result = this.tryAdd(this.createTag()(trimmed));\n // Clear on success or duplicate (gesture consumed); retain on max so the\n // user can retry after removing a tag.\n if (result !== 'max') this.setInputText('');\n }\n\n private removeAt(index: number): void {\n if (this.disabled()) return;\n const current = this.tags();\n if (index < 0 || index >= current.length) return;\n const tag = current[index];\n const next = current.filter((_, i) => i !== index);\n this.tags.set(next);\n this.onChange(next);\n this.tagRemoved.emit({ tag, value: next, index });\n this.valueChange.emit(next);\n this.liveAnnouncer.announce(`${this.tagLabel()(tag)} removed`, 'polite');\n // Focus restoration: next chip at this index, else the previous chip, else the input.\n if (next.length === 0) {\n this.focusInput();\n } else if (index < next.length) {\n this.focusChip(index);\n } else {\n this.focusChip(next.length - 1);\n }\n }\n\n // ── DOM event handlers ──\n\n /** @internal */\n onInput(event: Event): void {\n this.inputText.set((event.target as HTMLInputElement).value);\n }\n\n /** @internal */\n onInputKeydown(event: KeyboardEvent): void {\n if (this.disabled()) return;\n const separators = this.separatorKeys();\n const key = event.key;\n\n // Single-character separator → commit (and swallow the character).\n if (key.length === 1 && separators.includes(key)) {\n event.preventDefault();\n this.commitInput();\n return;\n }\n // Enter separator → commit only when there is text (otherwise let the form submit).\n if (key === 'Enter' && separators.includes('Enter')) {\n if (this.inputText().trim().length > 0) {\n event.preventDefault();\n this.commitInput();\n }\n return;\n }\n // Stepping out of the input into the last chip is a *backwards* move: the\n // chip row is rendered before the input, so it is ArrowLeft in LTR and\n // ArrowRight in an RTL locale, where the row lays out right-to-left. The\n // caret test is direction-independent — `selectionStart === 0` is the\n // logical start of the text in both directions.\n const backKey = this.directionality?.value === 'rtl' ? 'ArrowRight' : 'ArrowLeft';\n if (key === backKey) {\n const el = event.target as HTMLInputElement;\n const atStart = (el.selectionStart ?? 0) === 0 && (el.selectionEnd ?? 0) === 0;\n if (atStart && this.tags().length > 0) {\n event.preventDefault();\n this.focusChip(this.tags().length - 1);\n }\n return;\n }\n if (key === 'Backspace' && this.inputText().length === 0) {\n if (this.tags().length > 0) {\n event.preventDefault();\n this.focusChip(this.tags().length - 1);\n }\n return;\n }\n if (key === 'Escape' && this.inputText().length > 0) {\n event.preventDefault();\n this.setInputText('');\n }\n }\n\n /** @internal */\n onChipKeydown(event: KeyboardEvent, index: number): void {\n if (this.disabled()) return;\n const last = this.tags().length - 1;\n switch (event.key) {\n case 'ArrowLeft':\n case 'ArrowRight': {\n // Horizontal arrows follow the layout direction. Chips sit on a\n // flex row that lays out right-to-left in an RTL locale, so ArrowLeft\n // is the *forward* key there. The chip host is a custom element, not a\n // native control, so the browser does no flipping for us. Home/End stay\n // logical — CDK's ListKeyManager does not flip them either.\n event.preventDefault();\n const rtl = this.directionality?.value === 'rtl';\n const forward = rtl ? event.key === 'ArrowLeft' : event.key === 'ArrowRight';\n if (forward) {\n if (index < last) this.focusChip(index + 1);\n else this.focusInput();\n } else if (index > 0) {\n this.focusChip(index - 1);\n }\n return;\n }\n case 'Home':\n event.preventDefault();\n this.focusChip(0);\n return;\n case 'End':\n event.preventDefault();\n this.focusInput();\n return;\n case 'Delete':\n case 'Backspace':\n event.preventDefault();\n this.removeAt(index);\n return;\n case 'Escape':\n event.preventDefault();\n this.focusInput();\n return;\n default:\n return;\n }\n }\n\n /** @internal */\n onRemoveClick(index: number): void {\n this.removeAt(index);\n }\n\n /** @internal */\n onPaste(event: ClipboardEvent): void {\n if (this.disabled()) return;\n const data = event.clipboardData?.getData('text') ?? '';\n const charSeparators = this.separatorKeys().filter((k) => k.length === 1);\n const hasSeparator = charSeparators.some((s) => data.includes(s));\n if (!hasSeparator) {\n // No separator: let the browser merge the text into the input natively.\n return;\n }\n event.preventDefault();\n const combined = this.inputText() + data;\n this.setInputText('');\n for (const piece of this.splitOnSeparators(combined, charSeparators)) {\n const trimmed = piece.trim();\n if (!trimmed) continue;\n if (this.tryAdd(this.createTag()(trimmed)) === 'max') break;\n }\n }\n\n // ── ControlValueAccessor ──\n\n writeValue(value: T[] | null | undefined): void {\n this.tags.set(Array.isArray(value) ? [...value] : []);\n this.setInputText('');\n }\n\n registerOnChange(fn: (value: T[]) => void): void {\n this.onChange = fn;\n }\n\n registerOnTouched(fn: () => void): void {\n this.onTouched = fn;\n }\n\n setDisabledState(isDisabled: boolean): void {\n this.cvaDisabled.set(isDisabled);\n }\n\n // ── FormFieldControl methods ──\n\n /** @internal */\n setDescribedByIds(ids: string[]): void {\n this.describedByIdsSignal.set([...ids]);\n }\n\n /** @internal */\n override setLabelledByIds(ids: string[]): void {\n this.labelledByIdsSignal.set([...ids]);\n }\n\n /** @internal Clicking the form-field surface (outside the control) focuses the text input. Clicks inside the control are left alone so chip removal keeps its own focus restoration. */\n onContainerClick(event: MouseEvent): void {\n if (this.disabled()) return;\n if (event.defaultPrevented) return;\n const host = this.elementRef.nativeElement;\n if (event.target === host || host.contains(event.target as Node)) return;\n this.focus();\n }\n\n // ── Lifecycle ──\n\n ngOnInit(): void {\n // checkChildren: true — internal focus moves (input ↔ chips) stay \"focused\";\n // origin === null fires only when focus leaves the whole control, the single\n // source for onTouched and the addOnBlur commit.\n const monitor$ = this.focusMonitor.monitor(this.elementRef, true);\n if (isObservable(monitor$)) {\n monitor$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((origin) => {\n const wasFocused = this._focused();\n this._focused.set(!!origin);\n if (wasFocused && !origin) {\n if (this.addOnBlur() && this.inputText().trim().length > 0) {\n this.commitInput();\n }\n this.onTouched();\n this.errorWiring.bump();\n // Reset roving so the next Tab into the control lands on the input.\n this.activeChipIndex.set(null);\n }\n });\n }\n this.destroyRef.onDestroy(() => this.focusMonitor.stopMonitoring(this.elementRef));\n\n this.errorWiring.connect();\n }\n\n // ── Helpers ──\n\n private focusChip(index: number): void {\n this.activeChipIndex.set(index);\n this.requestFocus();\n }\n\n private focusInput(): void {\n this.activeChipIndex.set(null);\n this.requestFocus();\n }\n\n private requestFocus(): void {\n this.focusNonce.update((n) => n + 1);\n }\n\n private setInputText(value: string): void {\n this.inputText.set(value);\n const el = this.textInputRef()?.nativeElement;\n if (el && el.value !== value) el.value = value;\n }\n\n private announceMax(): void {\n const now = Date.now();\n if (now - this.lastMaxAnnounce < 500) return;\n this.lastMaxAnnounce = now;\n this.liveAnnouncer.announce(`Maximum ${this.maxTags()} tags reached`, 'assertive');\n }\n\n private splitOnSeparators(text: string, separators: readonly string[]): string[] {\n if (separators.length === 0) return [text];\n let normalized = text;\n for (const s of separators) normalized = normalized.split(s).join('\\u0000');\n return normalized.split('\\u0000');\n }\n\n private hasAccessibleNameHint(): boolean {\n return (\n !!this.ariaLabel() ||\n !!this.ariaLabelledby() ||\n this.labelledByIdsSignal().length > 0\n );\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;;;;;;;;;AA8CA;AACA;AACA;AAEA,MAAM,iBAAiB,GAAG,EAAE,CAC1B;AACE,IAAA,KAAK,EAAE;;;;AAIL,QAAA,IAAI,EAAE,oDAAoD;AAC1D,QAAA,IAAI,EAAE,oBAAoB;AAC1B,QAAA,SAAS,EAAE,UAAU;;;;AAIrB,QAAA,YAAY,EACV,qSAAqS;AACvS,QAAA,UAAU,EAAE,UAAU;AACtB,QAAA,KAAK,EACH,4GAA4G;AAC/G,KAAA;AACD,IAAA,QAAQ,EAAE;AACR,QAAA,WAAW,EAAE;;;AAGX,YAAA,IAAI,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE;AAClB,YAAA,KAAK,EAAE;AACL,gBAAA,IAAI,EAAE,4LAA4L;AACnM,aAAA;AACF,SAAA;AACD,QAAA,IAAI,EAAE;;;;;;AAMJ,YAAA,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,YAAY,EAAE,oBAAoB,EAAE,UAAU,EAAE,QAAQ,EAAE;AACjF,YAAA,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,YAAY,EAAE,oBAAoB,EAAE,UAAU,EAAE,QAAQ,EAAE;AACjF,YAAA,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,YAAY,EAAE,wBAAwB,EAAE,UAAU,EAAE,UAAU,EAAE;AACvF,YAAA,EAAE,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,YAAY,EAAE,wBAAwB,EAAE,UAAU,EAAE,QAAQ,EAAE;AACvF,YAAA,EAAE,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,YAAY,EAAE,wBAAwB,EAAE,UAAU,EAAE,QAAQ,EAAE;AACxF,SAAA;AACD,QAAA,KAAK,EAAE;AACL,YAAA,OAAO,EAAE,EAAE,IAAI,EAAE,kCAAkC,EAAE;AACrD,YAAA,SAAS,EAAE,EAAE,IAAI,EAAE,oCAAoC,EAAE;AACzD,YAAA,MAAM,EAAE,EAAE,IAAI,EAAE,iCAAiC,EAAE;AACnD,YAAA,OAAO,EAAE,EAAE,IAAI,EAAE,oCAAoC,EAAE;AACvD,YAAA,IAAI,EAAE,EAAE,IAAI,EAAE,+BAA+B,EAAE;AAC/C,YAAA,OAAO,EAAE,EAAE,IAAI,EAAE,kCAAkC,EAAE;AACrD,YAAA,OAAO,EAAE,EAAE,IAAI,EAAE,kCAAkC,EAAE;AACrD,YAAA,KAAK,EAAE,EAAE,IAAI,EAAE,gCAAgC,EAAE;AAClD,SAAA;AACD,QAAA,QAAQ,EAAE;AACR,YAAA,IAAI,EAAE,EAAE,IAAI,EAAE,mDAAmD,EAAE;AACnE,YAAA,KAAK,EAAE,EAAE;AACV,SAAA;AACD,QAAA,UAAU,EAAE;AACV,YAAA,IAAI,EAAE,EAAE;AACR,YAAA,KAAK,EAAE,EAAE;AACV,SAAA;AACF,KAAA;AACD,IAAA,gBAAgB,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiChB,QAAA,EAAE,WAAW,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,oBAAoB,EAAE,EAAE;AACzE,QAAA,EAAE,WAAW,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,mBAAmB,EAAE,EAAE;AACxE,QAAA,EAAE,WAAW,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,mBAAmB,EAAE,EAAE;AACxE,QAAA,EAAE,WAAW,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,oBAAoB,EAAE,EAAE;AACzE,QAAA,EAAE,WAAW,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,sBAAsB,EAAE,EAAE;;AAE3E,QAAA;AACE,YAAA,WAAW,EAAE,KAAK;AAClB,YAAA,UAAU,EAAE,IAAI;AAChB,YAAA,KAAK,EAAE,EAAE,IAAI,EAAE,iDAAiD,EAAE;AACnE,SAAA;AACF,KAAA;AACD,IAAA,eAAe,EAAE;AACf,QAAA,WAAW,EAAE,KAAK;AAClB,QAAA,IAAI,EAAE,IAAI;AACV,QAAA,KAAK,EAAE,SAAS;AAChB,QAAA,QAAQ,EAAE,KAAK;AACf,QAAA,UAAU,EAAE,KAAK;AAClB,KAAA;AACF,CAAA,EACD,EAAE,OAAO,EAAE,IAAI,EAAE,CAClB;AAED,MAAM,kBAAkB,GAAsB,CAAC,OAAO,EAAE,GAAG,CAAC;AAE5D,IAAI,MAAM,GAAG,CAAC;AAEd;;;;;;;;;;;;AAYG;AAyEG,MAAO,kBACX,SAAQ,gBAAqB,CAAA;;IAIpB,KAAK,GAAG,KAAK,CAAU,SAAS;8EAAC;;IAGjC,IAAI,GAAG,KAAK,CAAS,IAAI;6EAAC;;IAG1B,aAAa,GAAG,KAAK,CAAC,KAAK,qFAAI,KAAK,EAAE,UAAU,EAAA,CAAG;;IAGnD,aAAa,GAAG,KAAK,CAAC,KAAK,qFAAI,KAAK,EAAE,UAAU,EAAA,CAAG;;IAGnD,WAAW,GAAG,KAAK,CAAqB,SAAS;oFAAC;;IAGlD,aAAa,GAAG,KAAK,CAAoB,kBAAkB;sFAAC;;IAG5D,SAAS,GAAG,KAAK,CAAC,KAAK;kFAAC;;IAGxB,OAAO,GAAG,KAAK,CAAqB,SAAS;gFAAC;;IAG9C,eAAe,GAAG,KAAK,CAAC,KAAK;wFAAC;;IAG9B,SAAS,GAAG,KAAK,EACvB,CAAC,IAAY,KAAK,IAAI;kFACxB;;IAGQ,QAAQ,GAAG,KAAK,CAAkB,CAAC,GAAM,KAAK,MAAM,CAAC,GAAG,CAAC;iFAAC;;AAG1D,IAAA,WAAW,GAAG,KAAK,CAAoB,CAAC,CAAI,EAAE,CAAI,KAAK,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;oFAAC;;IAGvE,IAAI,GAAG,KAAK,CAAqB,SAAS;6EAAC;;IAG3C,OAAO,GAAG,KAAK,CAAqB,SAAS,+EAAI,KAAK,EAAE,IAAI,EAAA,CAAG;;IAG/D,SAAS,GAAG,KAAK,CAAqB,SAAS,iFAAI,KAAK,EAAE,YAAY,EAAA,CAAG;;IAGzE,cAAc,GAAG,KAAK,CAAqB,SAAS,sFAAI,KAAK,EAAE,iBAAiB,EAAA,CAAG;;IAGnF,eAAe,GAAG,KAAK,CAAqB,SAAS,uFAAI,KAAK,EAAE,kBAAkB,EAAA,CAAG;;IAGrF,iBAAiB,GAAG,KAAK,CAAgC,SAAS;0FAAC;AAE5E;;;;;;;;;;;AAWG;IACM,WAAW,GAAG,MAAM,EAAO;;IAG3B,QAAQ,GAAG,MAAM,EAAsB;;IAGvC,UAAU,GAAG,MAAM,EAAwB;AAEnC,IAAA,YAAY,GAAG,MAAM,CAAC,YAAY,CAAC;AACnC,IAAA,aAAa,GAAG,MAAM,CAAC,aAAa,CAAC;AACrC,IAAA,UAAU,GAAG,MAAM,EAAC,UAAuB,EAAC;AAC5C,IAAA,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;AAC/B,IAAA,SAAS,GAAG,MAAM,CAAC,SAAS,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IAC7D,SAAS,GAAG,MAAM,CAAC,aAAa,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;AACtE;;;;;AAKG;IACc,cAAc,GAAG,MAAM,CAAC,cAAc,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAE3D,YAAY,GAAG,SAAS,CAA+B,WAAW;qFAAC;IACnE,aAAa,GAAG,YAAY,CAAgC,WAAW;sFAAC;AAEjF,IAAA,QAAQ,GAAyB,MAAK,EAAE,CAAC;AACzC,IAAA,SAAS,GAAe,MAAK,EAAE,CAAC;IAEvB,IAAI,GAAG,MAAM,CAAM,EAAE;6EAAC;;IAE9B,SAAS,GAAG,MAAM,CAAC,EAAE;kFAAC;;IAEZ,eAAe,GAAG,MAAM,CAAgB,IAAI;wFAAC;IAC/C,WAAW,GAAG,MAAM,CAAC,KAAK;oFAAC;IAC3B,QAAQ,GAAG,MAAM,CAAC,KAAK;iFAAC;;IAGxB,WAAW,GAAG,cAAc,CAAC;AAC5C,QAAA,SAAS,EAAE,MAAM,IAAI,CAAC,SAAS;AAC/B,QAAA,OAAO,EAAE,MAAM,IAAI,CAAC,iBAAiB,EAAE;AACvC,QAAA,QAAQ,EAAE,MAAM,IAAI,CAAC,aAAa,EAAE;QACpC,KAAK,EAAE,CAAC,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;AAC/B,KAAA,CAAC;IACe,oBAAoB,GAAG,MAAM,CAAoB,EAAE;6FAAC;IACpD,mBAAmB,GAAG,MAAM,CAAoB,EAAE;4FAAC;;IAEnD,UAAU,GAAG,MAAM,CAAC,CAAC;mFAAC;IAC/B,eAAe,GAAG,CAAC;IAEV,GAAG,GAAG,MAAM,EAAE;;AAEtB,IAAA,MAAM,GAAG,CAAA,cAAA,EAAiB,IAAI,CAAC,GAAG,EAAE;;;AAKpC,IAAA,EAAE,GAAmB,QAAQ,CAAC,MAAM,IAAI,CAAC,OAAO,EAAE,IAAI,IAAI,CAAC,MAAM;2EAAC;;AAGlE,IAAA,KAAK,GAAgB,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE;;AAG3C,IAAA,OAAO,GAAoB,IAAI,CAAC,QAAQ,CAAC,UAAU,EAAE;;IAGrD,KAAK,GAAoB,QAAQ,CACxC,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC;8EACvE;;AAGQ,IAAA,QAAQ,GAAoB,QAAQ,CAC3C,MAAM,IAAI,CAAC,aAAa,EAAE,IAAI,IAAI,CAAC,WAAW,EAAE;iFACjD;;AAGQ,IAAA,QAAQ,GAAoB,IAAI,CAAC,WAAW,CAAC,QAAQ;;AAGrD,IAAA,UAAU,GAAoB,IAAI,CAAC,WAAW,CAAC,UAAU;;AAGhD,IAAA,MAAM,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM;;IAGzC,WAAW,GAAG,YAAY;;IAG1B,mBAAmB,GAA+B,QAAQ,CAAC,MAAM,IAAI,CAAC,eAAe,EAAE;4FAAC;;IAG/E,kBAAkB,GAA+B,QAAQ,CAAC,MAC1E,IAAI,CAAC,cAAc,EAAE;2FACtB;;;;;;;;;;AAYQ,IAAA,mBAAmB,GAAG,QAAQ,CAAC,MAAK;AAC3C,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,oBAAoB,EAAE;QAC1C,IAAI,MAAM,CAAC,MAAM;AAAE,YAAA,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC;AAC1C,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,eAAe,EAAE;AACnC,QAAA,IAAI,IAAI;AAAE,YAAA,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;AAC5D,QAAA,OAAO,EAAE;IACX,CAAC;4FAAC;;AAGO,IAAA,kBAAkB,GAAG,QAAQ,CAAC,MAAK;AAC1C,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,mBAAmB,EAAE;QACzC,IAAI,MAAM,CAAC,MAAM;AAAE,YAAA,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC;AAC1C,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,cAAc,EAAE;AAClC,QAAA,IAAI,IAAI;AAAE,YAAA,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;AAC5D,QAAA,OAAO,EAAE;IACX,CAAC;2FAAC;;AAIe,IAAA,aAAa,GAAG,QAAQ,CAAC,MACxC,iBAAiB,CAAC;AAChB,QAAA,WAAW,EAAE,CAAC,CAAC,IAAI,CAAC,SAAS;AAC7B,QAAA,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE;AACjB,QAAA,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE;AACnB,QAAA,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE;AACzB,QAAA,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE;KAC9B,CAAC;sFACH;;AAGQ,IAAA,WAAW,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC,IAAI,EAAE;oFAAC;;AAEzD,IAAA,WAAW,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC,IAAI,EAAE;oFAAC;;AAEzD,IAAA,gBAAgB,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC,SAAS,EAAE;yFAAC;;AAEnE,IAAA,mBAAmB,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC,YAAY,EAAE;4FAAC;;AAEzE,IAAA,iBAAiB,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC,UAAU,EAAE;0FAAC;;AAErE,IAAA,YAAY,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC,KAAK,EAAE;qFAAC;;AAG3D,IAAA,SAAS,GAAG,QAAQ,CAAC,MAAK;AACjC,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,EAAE;AAC7B,QAAA,OAAO,IAAI,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,KAAK,KAAI;AACpC,YAAA,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC;AACvB,YAAA,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,UAAU,IAAI,CAAA,CAAE,EAAE,KAAK,EAAE;AACnE,QAAA,CAAC,CAAC;IACJ,CAAC;kFAAC;AAEF,IAAA,WAAA,GAAA;AACE,QAAA,KAAK,EAAE;;;;AAIP,QAAA,IAAI,IAAI,CAAC,SAAS,EAAE;AAClB,YAAA,IAAI,CAAC,SAAS,CAAC,aAAa,GAAG,IAAI;QACrC;;;;;QAMA,MAAM,CAAC,MAAK;AACV,YAAA,IAAI,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC;gBAAE;YAC7B,SAAS,CAAC,MAAK;AACb,gBAAA,MAAM,GAAG,GAAG,IAAI,CAAC,eAAe,EAAE;AAClC,gBAAA,IAAI,GAAG,KAAK,IAAI,EAAE;oBAChB,IAAI,CAAC,YAAY,EAAE,EAAE,aAAa,CAAC,KAAK,EAAE;gBAC5C;qBAAO;oBACL,IAAI,CAAC,aAAa,EAAE,CAAC,GAAG,CAAC,EAAE,aAAa,CAAC,KAAK,EAAE;gBAClD;AACF,YAAA,CAAC,CAAC;AACJ,QAAA,CAAC,CAAC;QAEF,eAAe,CAAC,MAAK;YACnB,IAAI,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,qBAAqB,EAAE,EAAE;AAChD,gBAAA,OAAO,CAAC,IAAI,CACV,uJAAuJ,CACxJ;YACH;AACF,QAAA,CAAC,CAAC;IACJ;;;AAKA,IAAA,MAAM,CAAC,IAAY,EAAA;QACjB,IAAI,IAAI,CAAC,QAAQ,EAAE;AAAE,YAAA,OAAO,KAAK;AACjC,QAAA,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE;AAC3B,QAAA,IAAI,CAAC,OAAO;AAAE,YAAA,OAAO,KAAK;AAC1B,QAAA,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,OAAO,CAAC,CAAC,KAAK,OAAO;IAC3D;;AAGA,IAAA,SAAS,CAAC,GAAe,EAAA;QACvB,IAAI,IAAI,CAAC,QAAQ,EAAE;YAAE;AACrB,QAAA,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE;AAC3B,YAAA,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;YAClB;QACF;AACA,QAAA,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,EAAE;QAC9B,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;QACrD,IAAI,GAAG,IAAI,CAAC;AAAE,YAAA,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;IAClC;;IAGA,KAAK,GAAA;QACH,IAAI,IAAI,CAAC,QAAQ,EAAE;YAAE;AACrB,QAAA,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC,MAAM,KAAK,CAAC;YAAE;AAC/D,QAAA,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;AACjB,QAAA,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC;AACrB,QAAA,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC;AAC9B,QAAA,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;AACjB,QAAA,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC;QACzB,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,kBAAkB,EAAE,QAAQ,CAAC;IAC3D;;IAGA,KAAK,GAAA;AACH,QAAA,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC;QAC9B,IAAI,CAAC,YAAY,EAAE;IACrB;;AAIQ,IAAA,MAAM,CAAC,GAAM,EAAA;AACnB,QAAA,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE;AAC3B,QAAA,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,EAAE;AAC3B,YAAA,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,EAAE;AAC9B,YAAA,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AAAE,gBAAA,OAAO,WAAW;QAC1D;AACA,QAAA,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,EAAE;QAC1B,IAAI,GAAG,KAAK,SAAS,IAAI,OAAO,CAAC,MAAM,IAAI,GAAG,EAAE;YAC9C,IAAI,CAAC,WAAW,EAAE;AAClB,YAAA,OAAO,KAAK;QACd;QACA,MAAM,IAAI,GAAG,CAAC,GAAG,OAAO,EAAE,GAAG,CAAC;AAC9B,QAAA,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;AACnB,QAAA,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;AACnB,QAAA,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;AACxC,QAAA,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC;AAC3B,QAAA,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAC;AACtE,QAAA,OAAO,OAAO;IAChB;IAEQ,WAAW,GAAA;QACjB,IAAI,IAAI,CAAC,QAAQ,EAAE;YAAE;QACrB,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE;QACvC,IAAI,CAAC,OAAO,EAAE;AACZ,YAAA,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC;YACrB;QACF;AACA,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,OAAO,CAAC,CAAC;;;QAGrD,IAAI,MAAM,KAAK,KAAK;AAAE,YAAA,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC;IAC7C;AAEQ,IAAA,QAAQ,CAAC,KAAa,EAAA;QAC5B,IAAI,IAAI,CAAC,QAAQ,EAAE;YAAE;AACrB,QAAA,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE;QAC3B,IAAI,KAAK,GAAG,CAAC,IAAI,KAAK,IAAI,OAAO,CAAC,MAAM;YAAE;AAC1C,QAAA,MAAM,GAAG,GAAG,OAAO,CAAC,KAAK,CAAC;AAC1B,QAAA,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,KAAK,CAAC;AAClD,QAAA,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;AACnB,QAAA,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;AACnB,QAAA,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;AACjD,QAAA,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC;AAC3B,QAAA,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,UAAU,EAAE,QAAQ,CAAC;;AAExE,QAAA,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE;YACrB,IAAI,CAAC,UAAU,EAAE;QACnB;AAAO,aAAA,IAAI,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE;AAC9B,YAAA,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC;QACvB;aAAO;YACL,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;QACjC;IACF;;;AAKA,IAAA,OAAO,CAAC,KAAY,EAAA;QAClB,IAAI,CAAC,SAAS,CAAC,GAAG,CAAE,KAAK,CAAC,MAA2B,CAAC,KAAK,CAAC;IAC9D;;AAGA,IAAA,cAAc,CAAC,KAAoB,EAAA;QACjC,IAAI,IAAI,CAAC,QAAQ,EAAE;YAAE;AACrB,QAAA,MAAM,UAAU,GAAG,IAAI,CAAC,aAAa,EAAE;AACvC,QAAA,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG;;AAGrB,QAAA,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,IAAI,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE;YAChD,KAAK,CAAC,cAAc,EAAE;YACtB,IAAI,CAAC,WAAW,EAAE;YAClB;QACF;;QAEA,IAAI,GAAG,KAAK,OAAO,IAAI,UAAU,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE;AACnD,YAAA,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE;gBACtC,KAAK,CAAC,cAAc,EAAE;gBACtB,IAAI,CAAC,WAAW,EAAE;YACpB;YACA;QACF;;;;;;AAMA,QAAA,MAAM,OAAO,GAAG,IAAI,CAAC,cAAc,EAAE,KAAK,KAAK,KAAK,GAAG,YAAY,GAAG,WAAW;AACjF,QAAA,IAAI,GAAG,KAAK,OAAO,EAAE;AACnB,YAAA,MAAM,EAAE,GAAG,KAAK,CAAC,MAA0B;YAC3C,MAAM,OAAO,GAAG,CAAC,EAAE,CAAC,cAAc,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,YAAY,IAAI,CAAC,MAAM,CAAC;YAC9E,IAAI,OAAO,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE;gBACrC,KAAK,CAAC,cAAc,EAAE;AACtB,gBAAA,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;YACxC;YACA;QACF;AACA,QAAA,IAAI,GAAG,KAAK,WAAW,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE;YACxD,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE;gBAC1B,KAAK,CAAC,cAAc,EAAE;AACtB,gBAAA,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;YACxC;YACA;QACF;AACA,QAAA,IAAI,GAAG,KAAK,QAAQ,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE;YACnD,KAAK,CAAC,cAAc,EAAE;AACtB,YAAA,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC;QACvB;IACF;;IAGA,aAAa,CAAC,KAAoB,EAAE,KAAa,EAAA;QAC/C,IAAI,IAAI,CAAC,QAAQ,EAAE;YAAE;QACrB,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC;AACnC,QAAA,QAAQ,KAAK,CAAC,GAAG;AACf,YAAA,KAAK,WAAW;YAChB,KAAK,YAAY,EAAE;;;;;;gBAMjB,KAAK,CAAC,cAAc,EAAE;gBACtB,MAAM,GAAG,GAAG,IAAI,CAAC,cAAc,EAAE,KAAK,KAAK,KAAK;AAChD,gBAAA,MAAM,OAAO,GAAG,GAAG,GAAG,KAAK,CAAC,GAAG,KAAK,WAAW,GAAG,KAAK,CAAC,GAAG,KAAK,YAAY;gBAC5E,IAAI,OAAO,EAAE;oBACX,IAAI,KAAK,GAAG,IAAI;AAAE,wBAAA,IAAI,CAAC,SAAS,CAAC,KAAK,GAAG,CAAC,CAAC;;wBACtC,IAAI,CAAC,UAAU,EAAE;gBACxB;AAAO,qBAAA,IAAI,KAAK,GAAG,CAAC,EAAE;AACpB,oBAAA,IAAI,CAAC,SAAS,CAAC,KAAK,GAAG,CAAC,CAAC;gBAC3B;gBACA;YACF;AACA,YAAA,KAAK,MAAM;gBACT,KAAK,CAAC,cAAc,EAAE;AACtB,gBAAA,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;gBACjB;AACF,YAAA,KAAK,KAAK;gBACR,KAAK,CAAC,cAAc,EAAE;gBACtB,IAAI,CAAC,UAAU,EAAE;gBACjB;AACF,YAAA,KAAK,QAAQ;AACb,YAAA,KAAK,WAAW;gBACd,KAAK,CAAC,cAAc,EAAE;AACtB,gBAAA,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;gBACpB;AACF,YAAA,KAAK,QAAQ;gBACX,KAAK,CAAC,cAAc,EAAE;gBACtB,IAAI,CAAC,UAAU,EAAE;gBACjB;AACF,YAAA;gBACE;;IAEN;;AAGA,IAAA,aAAa,CAAC,KAAa,EAAA;AACzB,QAAA,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;IACtB;;AAGA,IAAA,OAAO,CAAC,KAAqB,EAAA;QAC3B,IAAI,IAAI,CAAC,QAAQ,EAAE;YAAE;AACrB,QAAA,MAAM,IAAI,GAAG,KAAK,CAAC,aAAa,EAAE,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE;QACvD,MAAM,cAAc,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC;AACzE,QAAA,MAAM,YAAY,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;QACjE,IAAI,CAAC,YAAY,EAAE;;YAEjB;QACF;QACA,KAAK,CAAC,cAAc,EAAE;QACtB,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,EAAE,GAAG,IAAI;AACxC,QAAA,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC;AACrB,QAAA,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,iBAAiB,CAAC,QAAQ,EAAE,cAAc,CAAC,EAAE;AACpE,YAAA,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE;AAC5B,YAAA,IAAI,CAAC,OAAO;gBAAE;AACd,YAAA,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,OAAO,CAAC,CAAC,KAAK,KAAK;gBAAE;QACxD;IACF;;AAIA,IAAA,UAAU,CAAC,KAA6B,EAAA;QACtC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,GAAG,EAAE,CAAC;AACrD,QAAA,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC;IACvB;AAEA,IAAA,gBAAgB,CAAC,EAAwB,EAAA;AACvC,QAAA,IAAI,CAAC,QAAQ,GAAG,EAAE;IACpB;AAEA,IAAA,iBAAiB,CAAC,EAAc,EAAA;AAC9B,QAAA,IAAI,CAAC,SAAS,GAAG,EAAE;IACrB;AAEA,IAAA,gBAAgB,CAAC,UAAmB,EAAA;AAClC,QAAA,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,UAAU,CAAC;IAClC;;;AAKA,IAAA,iBAAiB,CAAC,GAAa,EAAA;QAC7B,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC;IACzC;;AAGS,IAAA,gBAAgB,CAAC,GAAa,EAAA;QACrC,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC;IACxC;;AAGA,IAAA,gBAAgB,CAAC,KAAiB,EAAA;QAChC,IAAI,IAAI,CAAC,QAAQ,EAAE;YAAE;QACrB,IAAI,KAAK,CAAC,gBAAgB;YAAE;AAC5B,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,aAAa;AAC1C,QAAA,IAAI,KAAK,CAAC,MAAM,KAAK,IAAI,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAc,CAAC;YAAE;QAClE,IAAI,CAAC,KAAK,EAAE;IACd;;IAIA,QAAQ,GAAA;;;;AAIN,QAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC;AACjE,QAAA,IAAI,YAAY,CAAC,QAAQ,CAAC,EAAE;AAC1B,YAAA,QAAQ,CAAC,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,MAAM,KAAI;AACtE,gBAAA,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,EAAE;gBAClC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC;AAC3B,gBAAA,IAAI,UAAU,IAAI,CAAC,MAAM,EAAE;AACzB,oBAAA,IAAI,IAAI,CAAC,SAAS,EAAE,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE;wBAC1D,IAAI,CAAC,WAAW,EAAE;oBACpB;oBACA,IAAI,CAAC,SAAS,EAAE;AAChB,oBAAA,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE;;AAEvB,oBAAA,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC;gBAChC;AACF,YAAA,CAAC,CAAC;QACJ;AACA,QAAA,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,MAAM,IAAI,CAAC,YAAY,CAAC,cAAc,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;AAElF,QAAA,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE;IAC5B;;AAIQ,IAAA,SAAS,CAAC,KAAa,EAAA;AAC7B,QAAA,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,KAAK,CAAC;QAC/B,IAAI,CAAC,YAAY,EAAE;IACrB;IAEQ,UAAU,GAAA;AAChB,QAAA,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC;QAC9B,IAAI,CAAC,YAAY,EAAE;IACrB;IAEQ,YAAY,GAAA;AAClB,QAAA,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACtC;AAEQ,IAAA,YAAY,CAAC,KAAa,EAAA;AAChC,QAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC;QACzB,MAAM,EAAE,GAAG,IAAI,CAAC,YAAY,EAAE,EAAE,aAAa;AAC7C,QAAA,IAAI,EAAE,IAAI,EAAE,CAAC,KAAK,KAAK,KAAK;AAAE,YAAA,EAAE,CAAC,KAAK,GAAG,KAAK;IAChD;IAEQ,WAAW,GAAA;AACjB,QAAA,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE;AACtB,QAAA,IAAI,GAAG,GAAG,IAAI,CAAC,eAAe,GAAG,GAAG;YAAE;AACtC,QAAA,IAAI,CAAC,eAAe,GAAG,GAAG;AAC1B,QAAA,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAA,QAAA,EAAW,IAAI,CAAC,OAAO,EAAE,CAAA,aAAA,CAAe,EAAE,WAAW,CAAC;IACpF;IAEQ,iBAAiB,CAAC,IAAY,EAAE,UAA6B,EAAA;AACnE,QAAA,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,CAAC,IAAI,CAAC;QAC1C,IAAI,UAAU,GAAG,IAAI;QACrB,KAAK,MAAM,CAAC,IAAI,UAAU;AAAE,YAAA,UAAU,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC;AAC3E,QAAA,OAAO,UAAU,CAAC,KAAK,CAAC,QAAQ,CAAC;IACnC;IAEQ,qBAAqB,GAAA;AAC3B,QAAA,QACE,CAAC,CAAC,IAAI,CAAC,SAAS,EAAE;AAClB,YAAA,CAAC,CAAC,IAAI,CAAC,cAAc,EAAE;YACvB,IAAI,CAAC,mBAAmB,EAAE,CAAC,MAAM,GAAG,CAAC;IAEzC;uGA/kBW,kBAAkB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAlB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,kBAAkB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,eAAA,EAAA,MAAA,EAAA,EAAA,KAAA,EAAA,EAAA,iBAAA,EAAA,OAAA,EAAA,UAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,IAAA,EAAA,EAAA,iBAAA,EAAA,MAAA,EAAA,UAAA,EAAA,MAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,aAAA,EAAA,EAAA,iBAAA,EAAA,eAAA,EAAA,UAAA,EAAA,UAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,aAAA,EAAA,EAAA,iBAAA,EAAA,eAAA,EAAA,UAAA,EAAA,UAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,WAAA,EAAA,EAAA,iBAAA,EAAA,aAAA,EAAA,UAAA,EAAA,aAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,aAAA,EAAA,EAAA,iBAAA,EAAA,eAAA,EAAA,UAAA,EAAA,eAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,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,OAAA,EAAA,EAAA,iBAAA,EAAA,SAAA,EAAA,UAAA,EAAA,SAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,eAAA,EAAA,EAAA,iBAAA,EAAA,iBAAA,EAAA,UAAA,EAAA,iBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,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,QAAA,EAAA,EAAA,iBAAA,EAAA,UAAA,EAAA,UAAA,EAAA,UAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,WAAA,EAAA,EAAA,iBAAA,EAAA,aAAA,EAAA,UAAA,EAAA,aAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,IAAA,EAAA,EAAA,iBAAA,EAAA,MAAA,EAAA,UAAA,EAAA,MAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,OAAA,EAAA,EAAA,iBAAA,EAAA,SAAA,EAAA,UAAA,EAAA,IAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,iBAAA,EAAA,WAAA,EAAA,UAAA,EAAA,YAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,cAAA,EAAA,EAAA,iBAAA,EAAA,gBAAA,EAAA,UAAA,EAAA,iBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,eAAA,EAAA,EAAA,iBAAA,EAAA,iBAAA,EAAA,UAAA,EAAA,kBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,iBAAA,EAAA,EAAA,iBAAA,EAAA,mBAAA,EAAA,UAAA,EAAA,mBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,OAAA,EAAA,EAAA,WAAA,EAAA,aAAA,EAAA,QAAA,EAAA,UAAA,EAAA,UAAA,EAAA,YAAA,EAAA,EAAA,IAAA,EAAA,EAAA,UAAA,EAAA,EAAA,MAAA,EAAA,OAAA,EAAA,EAAA,UAAA,EAAA,EAAA,IAAA,EAAA,MAAA,EAAA,OAAA,EAAA,eAAA,EAAA,iBAAA,EAAA,qBAAA,EAAA,sBAAA,EAAA,8BAAA,EAAA,uBAAA,EAAA,+BAAA,EAAA,oBAAA,EAAA,oBAAA,EAAA,mBAAA,EAAA,mBAAA,EAAA,EAAA,EAAA,SAAA,EAnElB;AACT,YAAA;AACE,gBAAA,OAAO,EAAE,qBAAqB;AAC9B,gBAAA,WAAW,EAAE,UAAU,CAAC,MAAM,kBAAkB,CAAC;AAClD,aAAA;SACF,EAAA,WAAA,EAAA,CAAA,EAAA,YAAA,EAAA,cAAA,EAAA,KAAA,EAAA,IAAA,EAAA,SAAA,EAAA,CAAA,WAAA,CAAA,EAAA,WAAA,EAAA,IAAA,EAAA,QAAA,EAAA,IAAA,EAAA,EAAA,EAAA,YAAA,EAAA,eAAA,EAAA,SAAA,EAAA,CAAA,WAAA,CAAA,EAAA,WAAA,EAAA,IAAA,EAAA,QAAA,EAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,CAAA,aAAA,CAAA,EAAA,eAAA,EAAA,IAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EACS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4CT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAnDS,cAAc,EAAA,QAAA,EAAA,WAAA,EAAA,MAAA,EAAA,CAAA,OAAA,EAAA,SAAA,EAAA,MAAA,EAAA,MAAA,EAAA,aAAA,EAAA,MAAA,EAAA,cAAA,CAAA,EAAA,OAAA,EAAA,CAAA,WAAA,CAAA,EAAA,QAAA,EAAA,CAAA,SAAA,CAAA,EAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;2FAoEb,kBAAkB,EAAA,UAAA,EAAA,CAAA;kBAxE9B,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,eAAe;AACzB,oBAAA,QAAQ,EAAE,aAAa;oBACvB,eAAe,EAAE,uBAAuB,CAAC,MAAM;oBAC/C,OAAO,EAAE,CAAC,cAAc,CAAC;AACzB,oBAAA,SAAS,EAAE;AACT,wBAAA;AACE,4BAAA,OAAO,EAAE,qBAAqB;AAC9B,4BAAA,WAAW,EAAE,UAAU,CAAC,wBAAwB,CAAC;AAClD,yBAAA;AACF,qBAAA;AACD,oBAAA,QAAQ,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4CT,EAAA,CAAA;AACD,oBAAA,IAAI,EAAE;AACJ,wBAAA,MAAM,EAAE,OAAO;AACf,wBAAA,MAAM,EAAE,MAAM;AACd,wBAAA,SAAS,EAAE,eAAe;AAC1B,wBAAA,mBAAmB,EAAE,qBAAqB;AAC1C,wBAAA,wBAAwB,EAAE,8BAA8B;AACxD,wBAAA,yBAAyB,EAAE,+BAA+B;AAC1D,wBAAA,sBAAsB,EAAE,oBAAoB;;;;;;AAM5C,wBAAA,qBAAqB,EAAE,mBAAmB;AAC3C,qBAAA;AACF,iBAAA;AA+FyE,SAAA,CAAA,EAAA,cAAA,EAAA,MAAA,EAAA,EAAA,cAAA,EAAA,EAAA,KAAA,EAAA,CAAA,EAAA,IAAA,EAAA,EAAA,CAAA,KAAA,EAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,KAAA,EAAA,OAAA,EAAA,QAAA,EAAA,KAAA,EAAA,CAAA,EAAA,CAAA,EAAA,IAAA,EAAA,CAAA,EAAA,IAAA,EAAA,EAAA,CAAA,KAAA,EAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,KAAA,EAAA,MAAA,EAAA,QAAA,EAAA,KAAA,EAAA,CAAA,EAAA,CAAA,EAAA,aAAA,EAAA,CAAA,EAAA,IAAA,EAAA,EAAA,CAAA,KAAA,EAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,KAAA,EAAA,UAAA,EAAA,QAAA,EAAA,KAAA,EAAA,CAAA,EAAA,CAAA,EAAA,aAAA,EAAA,CAAA,EAAA,IAAA,EAAA,EAAA,CAAA,KAAA,EAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,KAAA,EAAA,UAAA,EAAA,QAAA,EAAA,KAAA,EAAA,CAAA,EAAA,CAAA,EAAA,WAAA,EAAA,CAAA,EAAA,IAAA,EAAA,EAAA,CAAA,KAAA,EAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,KAAA,EAAA,aAAA,EAAA,QAAA,EAAA,KAAA,EAAA,CAAA,EAAA,CAAA,EAAA,aAAA,EAAA,CAAA,EAAA,IAAA,EAAA,EAAA,CAAA,KAAA,EAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,KAAA,EAAA,eAAA,EAAA,QAAA,EAAA,KAAA,EAAA,CAAA,EAAA,CAAA,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,OAAA,EAAA,CAAA,EAAA,IAAA,EAAA,EAAA,CAAA,KAAA,EAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,KAAA,EAAA,SAAA,EAAA,QAAA,EAAA,KAAA,EAAA,CAAA,EAAA,CAAA,EAAA,eAAA,EAAA,CAAA,EAAA,IAAA,EAAA,EAAA,CAAA,KAAA,EAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,QAAA,EAAA,KAAA,EAAA,CAAA,EAAA,CAAA,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,QAAA,EAAA,CAAA,EAAA,IAAA,EAAA,EAAA,CAAA,KAAA,EAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,KAAA,EAAA,UAAA,EAAA,QAAA,EAAA,KAAA,EAAA,CAAA,EAAA,CAAA,EAAA,WAAA,EAAA,CAAA,EAAA,IAAA,EAAA,EAAA,CAAA,KAAA,EAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,KAAA,EAAA,aAAA,EAAA,QAAA,EAAA,KAAA,EAAA,CAAA,EAAA,CAAA,EAAA,IAAA,EAAA,CAAA,EAAA,IAAA,EAAA,EAAA,CAAA,KAAA,EAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,KAAA,EAAA,MAAA,EAAA,QAAA,EAAA,KAAA,EAAA,CAAA,EAAA,CAAA,EAAA,OAAA,EAAA,CAAA,EAAA,IAAA,EAAA,EAAA,CAAA,KAAA,EAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,KAAA,EAAA,IAAA,EAAA,QAAA,EAAA,KAAA,EAAA,CAAA,EAAA,CAAA,EAAA,SAAA,EAAA,CAAA,EAAA,IAAA,EAAA,EAAA,CAAA,KAAA,EAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,KAAA,EAAA,YAAA,EAAA,QAAA,EAAA,KAAA,EAAA,CAAA,EAAA,CAAA,EAAA,cAAA,EAAA,CAAA,EAAA,IAAA,EAAA,EAAA,CAAA,KAAA,EAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,QAAA,EAAA,KAAA,EAAA,CAAA,EAAA,CAAA,EAAA,eAAA,EAAA,CAAA,EAAA,IAAA,EAAA,EAAA,CAAA,KAAA,EAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,KAAA,EAAA,kBAAA,EAAA,QAAA,EAAA,KAAA,EAAA,CAAA,EAAA,CAAA,EAAA,iBAAA,EAAA,CAAA,EAAA,IAAA,EAAA,EAAA,CAAA,KAAA,EAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,KAAA,EAAA,mBAAA,EAAA,QAAA,EAAA,KAAA,EAAA,CAAA,EAAA,CAAA,EAAA,WAAA,EAAA,CAAA,EAAA,IAAA,EAAA,EAAA,CAAA,MAAA,EAAA,IAAA,EAAA,CAAA,aAAA,CAAA,EAAA,CAAA,EAAA,QAAA,EAAA,CAAA,EAAA,IAAA,EAAA,EAAA,CAAA,MAAA,EAAA,IAAA,EAAA,CAAA,UAAA,CAAA,EAAA,CAAA,EAAA,UAAA,EAAA,CAAA,EAAA,IAAA,EAAA,EAAA,CAAA,MAAA,EAAA,IAAA,EAAA,CAAA,YAAA,CAAA,EAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,EAAA,CAAA,SAAA,EAAA,IAAA,EAAA,CAAA,WAAW,0EACN,WAAW,EAAA,EAAA,QAAA,EAAA,IAAA,EAAA,CAAA,EAAA,CAAA,EAAA,EAAA,CAAA;;AC5V1F;;AAEG;;;;"}
1
+ {"version":3,"file":"cdevhub-ngx-tw-tags-input.mjs","sources":["../../../projects/ngx-tw/tags-input/tags-input.ts","../../../projects/ngx-tw/tags-input/cdevhub-ngx-tw-tags-input.ts"],"sourcesContent":["import {\n afterNextRender,\n ChangeDetectionStrategy,\n Component,\n computed,\n DestroyRef,\n effect,\n ElementRef,\n forwardRef,\n inject,\n input,\n isDevMode,\n type OnInit,\n output,\n signal,\n type Signal,\n untracked,\n viewChild,\n viewChildren,\n} from '@angular/core';\nimport { type ControlValueAccessor, NgControl } from '@angular/forms';\nimport { FocusMonitor, LiveAnnouncer } from '@angular/cdk/a11y';\nimport { Directionality } from '@angular/cdk/bidi';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { isObservable } from 'rxjs';\nimport { tv } from 'tailwind-variants';\nimport {\n type ErrorStateMatcher,\n type TwColor,\n type TwSize,\n wireErrorState,\n} from '@cdevhub/ngx-tw/core';\nimport {\n FormFieldControl,\n TW_FORM_FIELD,\n TW_FORM_FIELD_CONTROL,\n} from '@cdevhub/ngx-tw/form-field';\nimport { BadgeComponent } from '@cdevhub/ngx-tw/badge';\nimport type {\n TwTagAddedEvent,\n TwTagCompareFn,\n TwTagFactory,\n TwTagLabelFn,\n TwTagRemovedEvent,\n} from './types';\n\n// ── tv() config ──\n// `focus-within:outline-{color}-500` and the chip color classes are emitted by\n// combobox / badge already, so the Tailwind v4 JIT scanner picks them up.\n\nconst tagsInputVariants = tv(\n {\n slots: {\n // Host is the `role=\"group\"` chip strip. `flex-wrap` lets chips wrap; the\n // container owns the focus-within ring (standalone) or strips its chrome\n // inside a `<tw-form-field>` (the field draws the border / focus border).\n root: 'flex flex-wrap items-center gap-1.5 w-full text-fg',\n chip: 'max-w-full min-w-0',\n chipLabel: 'truncate',\n // Real DOM focus → canonical outline ring (NOT the activedescendant\n // background-shift carve-out). `text-current` inherits the chip color.\n // Per-size sets the square-interactive target size + negative margins.\n removeButton:\n 'inline-flex items-center justify-center shrink-0 ml-0.5 rounded-md text-current opacity-70 hover:opacity-100 transition-opacity duration-normal motion-reduce:transition-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary-500 disabled:pointer-events-none',\n removeIcon: 'shrink-0',\n input:\n 'flex-1 min-w-24 bg-transparent text-fg placeholder:text-fg-subtle outline-none disabled:cursor-not-allowed',\n },\n variants: {\n inFormField: {\n // Inside a form-field: keep only the chip-strip layout; the field owns\n // border, padding, background and the focused-border indicator.\n true: { root: '' },\n false: {\n root: 'rounded-md border border-border bg-surface transition-colors duration-normal motion-reduce:transition-none hover:border-border-strong focus-within:outline-2 focus-within:outline-offset-2',\n },\n },\n size: {\n // removeButton uses the square-interactive sub-scale (the button IS the\n // touch target): size-6 (24px) meets WCAG 2.5.8; negative margins absorb\n // the overflow so the chip height is unchanged. Mirrors badge's dismiss.\n // `size-3.5` half-step on the md remove glyph lines up the X with text-sm\n // at md density (codified half-step per CLAUDE.md icon sizing).\n xs: { root: 'text-xs', removeButton: 'size-6 -my-1 -mr-1', removeIcon: 'size-3' },\n sm: { root: 'text-sm', removeButton: 'size-6 -my-1 -mr-1', removeIcon: 'size-3' },\n md: { root: 'text-sm', removeButton: 'size-7 -my-1.5 -mr-1.5', removeIcon: 'size-3.5' },\n lg: { root: 'text-base', removeButton: 'size-8 -my-1.5 -mr-1.5', removeIcon: 'size-4' },\n xl: { root: 'text-base', removeButton: 'size-8 -my-1.5 -mr-1.5', removeIcon: 'size-4' },\n },\n color: {\n primary: { root: 'focus-within:outline-primary-border' },\n secondary: { root: 'focus-within:outline-secondary-border' },\n accent: { root: 'focus-within:outline-accent-border' },\n neutral: { root: 'focus-within:outline-border-strong' },\n info: { root: 'focus-within:outline-info-border' },\n success: { root: 'focus-within:outline-success-border' },\n warning: { root: 'focus-within:outline-warning-border' },\n error: { root: 'focus-within:outline-error-border' },\n },\n disabled: {\n true: { root: 'opacity-50 pointer-events-none cursor-not-allowed' },\n false: {},\n },\n errorState: {\n true: {},\n false: {},\n },\n },\n compoundVariants: [\n // Standalone density × size — inline padding scale (mirrors combobox trigger)\n // plus the control-height FLOOR. Per docs/vertical-rhythm.md §2 the chip\n // strip is a `min-h` control, not a pinned one: chips wrap, so `py-*` stays\n // exactly as it is and `min-h-*` only guarantees the box never sits below\n // the control scale. Standalone-only, alongside the padding: inside a\n // `tw-form-field` the root drops its border and padding and the field owns\n // the box, so a floor here would stack on top of the field's own padding.\n // Vertical padding is set so the `min-h-*` floor actually BINDS at rest.\n //\n // The tallest resting content is a CHIP, not the bare input line box. A\n // chip is a badge: its own padding and text size make it taller than the\n // input beside it at every size, so the box arithmetic that decides\n // whether the floor binds is\n //\n // chip + 2*py + 2px border <= floor\n //\n // Sizing the padding against the input line box instead left the floor\n // inert the moment a single tag existed. Empty, the control measured\n // correctly at all five sizes; populated, it measured 26 / 32 / 38 / 50 /\n // 54 against a 24 / 32 / 36 / 44 / 48 scale — so a filter bar was on the\n // grid until the user typed the first tag, then jumped 2px at xs and md\n // and 6px at lg and xl. Only sm was ever correct, which is why the\n // isolated slot reading looked like a one-off rather than a broken rule.\n //\n // Resting appearance does not change: once the floor binds, `items-center`\n // centres the chip and the padding is no longer what sets the height. The\n // padding still governs the multi-line case, where chips wrap and the box\n // legitimately grows past the floor.\n //\n // Chip heights are 20 / 20 / 24 / 32 / 32, so the padding ceiling is\n // 1 / 5 / 5 / 5 / 7px. `py-px` at xs is not decorative restraint: a 20px\n // chip inside a 24px control with a 1px border leaves exactly 1px a side.\n { inFormField: false, size: 'xs', class: { root: 'px-2 py-px min-h-6' } },\n { inFormField: false, size: 'sm', class: { root: 'px-3 py-1 min-h-8' } },\n { inFormField: false, size: 'md', class: { root: 'px-4 py-1 min-h-9' } },\n { inFormField: false, size: 'lg', class: { root: 'px-5 py-1 min-h-11' } },\n { inFormField: false, size: 'xl', class: { root: 'px-6 py-1.5 min-h-12' } },\n // Standalone error state — colored border + focus ring.\n {\n inFormField: false,\n errorState: true,\n class: { root: 'border-error-border focus-within:outline-error-border' },\n },\n ],\n defaultVariants: {\n inFormField: false,\n size: 'md',\n color: 'primary',\n disabled: false,\n errorState: false,\n },\n },\n { twMerge: true },\n);\n\nconst DEFAULT_SEPARATORS: readonly string[] = ['Enter', ','];\n\nlet nextId = 0;\n\n/**\n * Free-text multi-value input. The user types a token and commits it via Enter,\n * a separator key, paste, or blur; committed tokens render as dismissible chips\n * (composing `[twBadge]`) inline with the text input. The value is exposed as a\n * real `T[]` (default `string[]`) through `ControlValueAccessor`, so it works\n * with template-driven, reactive, and signal forms and integrates with\n * `<tw-form-field>` for label / hint / error chrome.\n *\n * The control is a single tab stop with a roving-tabindex chip strip\n * (Material `MatChipGrid` interaction model): Arrow keys traverse chips and the\n * input, Delete / a two-step Backspace remove chips, and `LiveAnnouncer` voices\n * add / remove. Autocomplete suggestions are out of scope (use `tw-combobox`).\n */\n@Component({\n selector: 'tw-tags-input',\n exportAs: 'twTagsInput',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [BadgeComponent],\n providers: [\n {\n provide: TW_FORM_FIELD_CONTROL,\n useExisting: forwardRef(() => TagsInputComponent),\n },\n ],\n template: `\n @for (chip of chipViews(); track chip.index) {\n <span twBadge variant=\"soft\" [color]=\"color()\" [size]=\"size()\" [class]=\"chipClasses()\">\n <span [class]=\"chipLabelClasses()\">{{ chip.label }}</span>\n <button\n #removeBtn\n type=\"button\"\n [class]=\"removeButtonClasses()\"\n [attr.tabindex]=\"activeChipIndex() === chip.index ? 0 : -1\"\n [attr.aria-label]=\"chip.removeLabel\"\n [disabled]=\"disabled()\"\n (click)=\"onRemoveClick(chip.index)\"\n (keydown)=\"onChipKeydown($event, chip.index)\"\n >\n <svg\n viewBox=\"0 0 16 16\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n [class]=\"removeIconClasses()\"\n >\n <path\n d=\"M5.28 4.22a.75.75 0 0 0-1.06 1.06L6.94 8l-2.72 2.72a.75.75 0 1 0 1.06 1.06L8 9.06l2.72 2.72a.75.75 0 1 0 1.06-1.06L9.06 8l2.72-2.72a.75.75 0 0 0-1.06-1.06L8 6.94 5.28 4.22Z\"\n />\n </svg>\n </button>\n </span>\n }\n <input\n #textInput\n type=\"text\"\n [class]=\"inputClasses()\"\n [attr.tabindex]=\"activeChipIndex() === null ? 0 : -1\"\n [attr.placeholder]=\"placeholder() || null\"\n [attr.aria-required]=\"required() || null\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-labelledby]=\"resolvedLabelledBy() || null\"\n [attr.aria-describedby]=\"resolvedDescribedBy() || null\"\n [attr.aria-invalid]=\"errorState() || null\"\n [attr.name]=\"name() || null\"\n [disabled]=\"disabled()\"\n (input)=\"onInput($event)\"\n (keydown)=\"onInputKeydown($event)\"\n (paste)=\"onPaste($event)\"\n />\n `,\n host: {\n 'role': 'group',\n '[id]': 'id()',\n '[class]': 'rootClasses()',\n '[attr.aria-label]': 'ariaLabel() || null',\n '[attr.aria-labelledby]': 'resolvedLabelledBy() || null',\n '[attr.aria-describedby]': 'resolvedDescribedBy() || null',\n '[attr.aria-disabled]': 'disabled() || null',\n // NOTE: no `aria-invalid` here. ARIA 1.2 does not allow it on\n // `role=\"group\"` (axe: critical `aria-allowed-attr`). The inner\n // `<input type=\"text\">` already carries it — that is the control with the\n // value. Latent rather than observed: it only fires once a consumer puts\n // the control into an error state.\n '[attr.data-focused]': 'focused() || null',\n },\n})\nexport class TagsInputComponent<T = string>\n extends FormFieldControl<T[]>\n implements ControlValueAccessor, OnInit\n{\n /** Semantic color for the container focus-within ring and the chip accent. Defaults to `'primary'`. */\n readonly color = input<TwColor>('primary');\n\n /** Controls overall density: container padding, chip size, and text scale. Defaults to `'md'`. */\n readonly size = input<TwSize>('md');\n\n /** When true, blocks typing, committing, and chip removal, and applies muted styling. Reactive forms also propagate disabled via `setDisabledState`. Defaults to `false`. */\n readonly disabledInput = input(false, { alias: 'disabled' });\n\n /** Marks the control as required. Mirrored to the input's `aria-required`. Also inferred from `Validators.required` on a bound control. Defaults to `false`. */\n readonly requiredInput = input(false, { alias: 'required' });\n\n /** Placeholder shown in the text input only while there are no chips and the input is empty. Defaults to `undefined`. */\n readonly placeholder = input<string | undefined>(undefined);\n\n /** Keys that commit the in-progress text as a tag. Each entry is a `KeyboardEvent.key` value (`'Enter'`) or a single separator character (`','`). Single-character separators also split pasted text. Defaults to `['Enter', ',']`. */\n readonly separatorKeys = input<readonly string[]>(DEFAULT_SEPARATORS);\n\n /** When true, blurring the control while the input holds non-empty text commits it as a tag. Defaults to `false`. */\n readonly addOnBlur = input(false);\n\n /** Maximum number of tags. Once reached, further commits are blocked and announced. Does not truncate an oversized `writeValue`. Defaults to `undefined` (no limit). */\n readonly maxTags = input<number | undefined>(undefined);\n\n /** When false (default), a committed tag equal (per `compareWith`) to an existing tag is dropped silently. When true, duplicates are kept. Defaults to `false`. */\n readonly allowDuplicates = input(false);\n\n /** Maps committed text to a tag value. Default is identity — the trimmed string. Override to build object tags. */\n readonly createTag = input<TwTagFactory<T>>(\n ((text: string) => text) as unknown as TwTagFactory<T>,\n );\n\n /** Maps a tag value to its visible chip label and the remove-button accessible name. Defaults to `String(tag)`. */\n readonly tagLabel = input<TwTagLabelFn<T>>((tag: T) => String(tag));\n\n /** Equality comparator used for dedup when `allowDuplicates` is false. Defaults to `Object.is` (reference / value identity). String tags dedupe case-sensitively by default; pass `(a, b) => a.toLowerCase() === b.toLowerCase()` for case-insensitive dedup. */\n readonly compareWith = input<TwTagCompareFn<T>>((a: T, b: T) => Object.is(a, b));\n\n /** Applied to the text input for labeling and identification only; does not submit the tag array via native (non-Angular) form posting. Defaults to `undefined`. */\n readonly name = input<string | undefined>(undefined);\n\n /** Id on the host element. Auto-generated as `tw-tags-input-N` when not provided. Used by the form-field's `<label for>` association. */\n readonly idInput = input<string | undefined>(undefined, { alias: 'id' });\n\n /** Accessible name applied to the control when no visible label is wired. Mirrored to `aria-label`. Defaults to `undefined`. */\n readonly ariaLabel = input<string | undefined>(undefined, { alias: 'aria-label' });\n\n /** ID of an external element that labels the control. Mirrored to `aria-labelledby`. Defaults to `undefined`. */\n readonly ariaLabelledby = input<string | undefined>(undefined, { alias: 'aria-labelledby' });\n\n /** ID of an external element that describes the control. Form-field merges its hint / error ids alongside. Defaults to `undefined`. Alias: `aria-describedby`. */\n readonly ariaDescribedby = input<string | undefined>(undefined, { alias: 'aria-describedby' });\n\n /** Per-instance override of the {@link ErrorStateMatcher}. When omitted, uses the `TW_ERROR_STATE_MATCHER` token's value. */\n readonly errorStateMatcher = input<ErrorStateMatcher | undefined>(undefined);\n\n /**\n * Fires when the tag array changes through user interaction (add, remove,\n * clear). Emits a fresh array reference. Does **not** fire on `writeValue` /\n * `FormControl.setValue` / `ngModel`.\n *\n * This is a hand-written, user-gesture-only output. The control exposes no\n * `value` input and therefore no two-way binding, so — unlike\n * `tw-checkbox` / `tw-switch` / `tw-radio-group`, where `(valueChange)` /\n * `(checkedChange)` is minted by a `model()` and fires on programmatic writes\n * too — there is no any-change channel here. Observe programmatic writes\n * through the bound form control's own `valueChanges`.\n */\n readonly valueChange = output<T[]>();\n\n /** Fires when a tag is committed via Enter, a separator key, paste, or `addTag()`. Does not fire for dropped duplicates, blocked-by-max commits, empty commits, or `writeValue`. */\n readonly tagAdded = output<TwTagAddedEvent<T>>();\n\n /** Fires when a tag is removed via the remove button, Backspace / Delete, or `removeTag()`. Does not fire on `writeValue` or `clear()`. */\n readonly tagRemoved = output<TwTagRemovedEvent<T>>();\n\n private readonly focusMonitor = inject(FocusMonitor);\n private readonly liveAnnouncer = inject(LiveAnnouncer);\n private readonly elementRef = inject(ElementRef<HTMLElement>);\n private readonly destroyRef = inject(DestroyRef);\n private readonly ngControl = inject(NgControl, { optional: true, self: true });\n private readonly formField = inject(TW_FORM_FIELD, { optional: true });\n /**\n * Optional so a consumer that never imports `BidiModule` still gets a working\n * control — chip navigation falls back to LTR when the token is absent. Read\n * imperatively inside the keydown handlers; nothing here needs to re-render\n * on a direction change.\n */\n private readonly directionality = inject(Directionality, { optional: true });\n\n private readonly textInputRef = viewChild<ElementRef<HTMLInputElement>>('textInput');\n private readonly removeButtons = viewChildren<ElementRef<HTMLButtonElement>>('removeBtn');\n\n private onChange: (value: T[]) => void = () => {};\n private onTouched: () => void = () => {};\n\n private readonly tags = signal<T[]>([]);\n /** The current in-progress (uncommitted) text in the input. Empty when nothing is typed. */\n readonly inputText = signal('');\n /** @internal Roving-tabindex position. `null` = the text input is the active element; a number = that chip's remove button. */\n protected readonly activeChipIndex = signal<number | null>(null);\n private readonly cvaDisabled = signal(false);\n private readonly _focused = signal(false);\n\n /** @internal Shared `errorState` / `required` / `errors` derivation — see `wireErrorState`. */\n private readonly errorWiring = wireErrorState({\n ngControl: () => this.ngControl,\n matcher: () => this.errorStateMatcher(),\n required: () => this.requiredInput(),\n track: [() => this._focused()],\n });\n private readonly describedByIdsSignal = signal<readonly string[]>([]);\n private readonly labelledByIdsSignal = signal<readonly string[]>([]);\n /** Nonce bumped only on explicit focus intent — keeps the focus effect from stealing focus on unrelated renders. */\n private readonly focusNonce = signal(0);\n private lastMaxAnnounce = 0;\n\n private readonly uid = nextId++;\n /** @internal Fallback id used when the consumer does not set `[id]`. */\n readonly hostId = `tw-tags-input-${this.uid}`;\n\n // ── FormFieldControl signals ──\n\n /** @internal */\n readonly id: Signal<string> = computed(() => this.idInput() ?? this.hostId);\n\n /** The current tag array (empty array when there are no tags). Read from a template ref (`#t=\"twTagsInput\"`) for non-form usage. Doubles as the `FormFieldControl` contract member. */\n readonly value: Signal<T[]> = this.tags.asReadonly();\n\n /** @internal */\n readonly focused: Signal<boolean> = this._focused.asReadonly();\n\n /** @internal Empty when there are no chips AND the input text is blank — drives the form-field floating label. */\n readonly empty: Signal<boolean> = computed(\n () => this.tags().length === 0 && this.inputText().trim().length === 0,\n );\n\n /** @internal */\n readonly disabled: Signal<boolean> = computed(\n () => this.disabledInput() || this.cvaDisabled(),\n );\n\n /** @internal */\n readonly required: Signal<boolean> = this.errorWiring.required;\n\n /** @internal */\n readonly errorState: Signal<boolean> = this.errorWiring.errorState;\n\n /** @internal Active validation errors map from the bound control, for `[twError match=\"…\"]` filtering. */\n override readonly errors = this.errorWiring.errors;\n\n /** @internal */\n readonly controlType = 'tags-input';\n\n /** @internal */\n readonly userAriaDescribedBy: Signal<string | undefined> = computed(() => this.ariaDescribedby());\n\n /** @internal */\n override readonly userAriaLabelledby: Signal<string | undefined> = computed(() =>\n this.ariaLabelledby(),\n );\n\n // ── Effective ARIA ──\n //\n // When wrapped by `<tw-form-field>`, the form-field pushes the FULLY MERGED\n // id list (hint/error/label + the consumer's `aria-*by` ids) via\n // `setDescribedByIds` / `setLabelledByIds`. In that case the pushed ids alone\n // are the source of truth — re-merging the consumer's `aria-*by` input on top\n // would duplicate ids. When standalone, fall back to the consumer-supplied\n // `aria-*by` input.\n\n /** @internal Merged `aria-describedby` (form-field hint/error ids + consumer-supplied). */\n readonly resolvedDescribedBy = computed(() => {\n const pushed = this.describedByIdsSignal();\n if (pushed.length) return pushed.join(' ');\n const user = this.ariaDescribedby();\n if (user) return user.split(/\\s+/).filter(Boolean).join(' ');\n return '';\n });\n\n /** @internal Merged `aria-labelledby` (form-field label id + consumer-supplied). */\n readonly resolvedLabelledBy = computed(() => {\n const pushed = this.labelledByIdsSignal();\n if (pushed.length) return pushed.join(' ');\n const user = this.ariaLabelledby();\n if (user) return user.split(/\\s+/).filter(Boolean).join(' ');\n return '';\n });\n\n // ── tv() class bindings ──\n\n private readonly variantResult = computed(() =>\n tagsInputVariants({\n inFormField: !!this.formField,\n size: this.size(),\n color: this.color(),\n disabled: this.disabled(),\n errorState: this.errorState(),\n }),\n );\n\n /** @internal */\n readonly rootClasses = computed(() => this.variantResult().root());\n /** @internal */\n readonly chipClasses = computed(() => this.variantResult().chip());\n /** @internal */\n readonly chipLabelClasses = computed(() => this.variantResult().chipLabel());\n /** @internal */\n readonly removeButtonClasses = computed(() => this.variantResult().removeButton());\n /** @internal */\n readonly removeIconClasses = computed(() => this.variantResult().removeIcon());\n /** @internal */\n readonly inputClasses = computed(() => this.variantResult().input());\n\n /** @internal Pre-resolved chip view models so the template never calls accessor functions inline. */\n readonly chipViews = computed(() => {\n const label = this.tagLabel();\n return this.tags().map((tag, index) => {\n const text = label(tag);\n return { tag, label: text, removeLabel: `Remove ${text}`, index };\n });\n });\n\n constructor() {\n super();\n // Runtime CVA wiring — register on any host-level NgControl. The component\n // injects `NgControl { self }` for TW_ERROR_STATE_MATCHER, so a static\n // NG_VALUE_ACCESSOR provider would create circular DI on the same instance.\n if (this.ngControl) {\n this.ngControl.valueAccessor = this;\n }\n\n // Focus side-effect (leaves the signal graph; writes no signal → no cycle).\n // Triggered only by `focusNonce` bumps so it never steals focus on an\n // unrelated render (e.g. initial mount). Reads the active index and refs\n // untracked so it does not re-fire when the chip list changes on its own.\n effect(() => {\n if (this.focusNonce() === 0) return;\n untracked(() => {\n const idx = this.activeChipIndex();\n if (idx === null) {\n this.textInputRef()?.nativeElement.focus();\n } else {\n this.removeButtons()[idx]?.nativeElement.focus();\n }\n });\n });\n\n afterNextRender(() => {\n if (isDevMode() && !this.hasAccessibleNameHint()) {\n console.warn(\n '[tw-tags-input] The control has no accessible name. Provide `aria-label` / `aria-labelledby`, or wrap it in a <tw-form-field> with a <label twLabel>.',\n );\n }\n });\n }\n\n // ── Public instance API ──\n\n /** Commits `text` as a tag (trim → `createTag` → dedup unless `allowDuplicates` → `maxTags` check). Returns true if a tag was added, false if dropped (empty / duplicate / max). Emits `tagAdded` + `valueChange` on success. No-op when disabled. */\n addTag(text: string): boolean {\n if (this.disabled()) return false;\n const trimmed = text.trim();\n if (!trimmed) return false;\n return this.tryAdd(this.createTag()(trimmed)) === 'added';\n }\n\n /** Removes a tag by value (first match via `compareWith`) or by index when a number is passed. Emits `tagRemoved` + `valueChange` and restores focus. No-op when disabled or when no match. Note: when the tag type is `number`, the argument is treated as an index. */\n removeTag(tag: T | number): void {\n if (this.disabled()) return;\n if (typeof tag === 'number') {\n this.removeAt(tag);\n return;\n }\n const cmp = this.compareWith();\n const idx = this.tags().findIndex((t) => cmp(t, tag));\n if (idx >= 0) this.removeAt(idx);\n }\n\n /** Removes all tags and clears the in-progress input text. Emits `valueChange` with `[]`. Does NOT emit `tagRemoved` per tag (bulk reset). No-op when already empty or disabled. */\n clear(): void {\n if (this.disabled()) return;\n if (this.tags().length === 0 && this.inputText().length === 0) return;\n this.tags.set([]);\n this.setInputText('');\n this.activeChipIndex.set(null);\n this.onChange([]);\n this.valueChange.emit([]);\n this.liveAnnouncer.announce('All tags removed', 'polite');\n }\n\n /** Moves focus to the text input. */\n focus(): void {\n this.activeChipIndex.set(null);\n this.requestFocus();\n }\n\n // ── Internal commit / remove pipeline ──\n\n private tryAdd(tag: T): 'added' | 'duplicate' | 'max' {\n const current = this.tags();\n if (!this.allowDuplicates()) {\n const cmp = this.compareWith();\n if (current.some((e) => cmp(e, tag))) return 'duplicate';\n }\n const max = this.maxTags();\n if (max !== undefined && current.length >= max) {\n this.announceMax();\n return 'max';\n }\n const next = [...current, tag];\n this.tags.set(next);\n this.onChange(next);\n this.tagAdded.emit({ tag, value: next });\n this.valueChange.emit(next);\n this.liveAnnouncer.announce(`${this.tagLabel()(tag)} added`, 'polite');\n return 'added';\n }\n\n private commitInput(): void {\n if (this.disabled()) return;\n const trimmed = this.inputText().trim();\n if (!trimmed) {\n this.setInputText('');\n return;\n }\n const result = this.tryAdd(this.createTag()(trimmed));\n // Clear on success or duplicate (gesture consumed); retain on max so the\n // user can retry after removing a tag.\n if (result !== 'max') this.setInputText('');\n }\n\n private removeAt(index: number): void {\n if (this.disabled()) return;\n const current = this.tags();\n if (index < 0 || index >= current.length) return;\n const tag = current[index];\n const next = current.filter((_, i) => i !== index);\n this.tags.set(next);\n this.onChange(next);\n this.tagRemoved.emit({ tag, value: next, index });\n this.valueChange.emit(next);\n this.liveAnnouncer.announce(`${this.tagLabel()(tag)} removed`, 'polite');\n // Focus restoration: next chip at this index, else the previous chip, else the input.\n if (next.length === 0) {\n this.focusInput();\n } else if (index < next.length) {\n this.focusChip(index);\n } else {\n this.focusChip(next.length - 1);\n }\n }\n\n // ── DOM event handlers ──\n\n /** @internal */\n onInput(event: Event): void {\n this.inputText.set((event.target as HTMLInputElement).value);\n }\n\n /** @internal */\n onInputKeydown(event: KeyboardEvent): void {\n if (this.disabled()) return;\n const separators = this.separatorKeys();\n const key = event.key;\n\n // Single-character separator → commit (and swallow the character).\n if (key.length === 1 && separators.includes(key)) {\n event.preventDefault();\n this.commitInput();\n return;\n }\n // Enter separator → commit only when there is text (otherwise let the form submit).\n if (key === 'Enter' && separators.includes('Enter')) {\n if (this.inputText().trim().length > 0) {\n event.preventDefault();\n this.commitInput();\n }\n return;\n }\n // Stepping out of the input into the last chip is a *backwards* move: the\n // chip row is rendered before the input, so it is ArrowLeft in LTR and\n // ArrowRight in an RTL locale, where the row lays out right-to-left. The\n // caret test is direction-independent — `selectionStart === 0` is the\n // logical start of the text in both directions.\n const backKey = this.directionality?.value === 'rtl' ? 'ArrowRight' : 'ArrowLeft';\n if (key === backKey) {\n const el = event.target as HTMLInputElement;\n const atStart = (el.selectionStart ?? 0) === 0 && (el.selectionEnd ?? 0) === 0;\n if (atStart && this.tags().length > 0) {\n event.preventDefault();\n this.focusChip(this.tags().length - 1);\n }\n return;\n }\n if (key === 'Backspace' && this.inputText().length === 0) {\n if (this.tags().length > 0) {\n event.preventDefault();\n this.focusChip(this.tags().length - 1);\n }\n return;\n }\n if (key === 'Escape' && this.inputText().length > 0) {\n event.preventDefault();\n this.setInputText('');\n }\n }\n\n /** @internal */\n onChipKeydown(event: KeyboardEvent, index: number): void {\n if (this.disabled()) return;\n const last = this.tags().length - 1;\n switch (event.key) {\n case 'ArrowLeft':\n case 'ArrowRight': {\n // Horizontal arrows follow the layout direction. Chips sit on a\n // flex row that lays out right-to-left in an RTL locale, so ArrowLeft\n // is the *forward* key there. The chip host is a custom element, not a\n // native control, so the browser does no flipping for us. Home/End stay\n // logical — CDK's ListKeyManager does not flip them either.\n event.preventDefault();\n const rtl = this.directionality?.value === 'rtl';\n const forward = rtl ? event.key === 'ArrowLeft' : event.key === 'ArrowRight';\n if (forward) {\n if (index < last) this.focusChip(index + 1);\n else this.focusInput();\n } else if (index > 0) {\n this.focusChip(index - 1);\n }\n return;\n }\n case 'Home':\n event.preventDefault();\n this.focusChip(0);\n return;\n case 'End':\n event.preventDefault();\n this.focusInput();\n return;\n case 'Delete':\n case 'Backspace':\n event.preventDefault();\n this.removeAt(index);\n return;\n case 'Escape':\n event.preventDefault();\n this.focusInput();\n return;\n default:\n return;\n }\n }\n\n /** @internal */\n onRemoveClick(index: number): void {\n this.removeAt(index);\n }\n\n /** @internal */\n onPaste(event: ClipboardEvent): void {\n if (this.disabled()) return;\n const data = event.clipboardData?.getData('text') ?? '';\n const charSeparators = this.separatorKeys().filter((k) => k.length === 1);\n const hasSeparator = charSeparators.some((s) => data.includes(s));\n if (!hasSeparator) {\n // No separator: let the browser merge the text into the input natively.\n return;\n }\n event.preventDefault();\n const combined = this.inputText() + data;\n this.setInputText('');\n for (const piece of this.splitOnSeparators(combined, charSeparators)) {\n const trimmed = piece.trim();\n if (!trimmed) continue;\n if (this.tryAdd(this.createTag()(trimmed)) === 'max') break;\n }\n }\n\n // ── ControlValueAccessor ──\n\n writeValue(value: T[] | null | undefined): void {\n this.tags.set(Array.isArray(value) ? [...value] : []);\n this.setInputText('');\n }\n\n registerOnChange(fn: (value: T[]) => void): void {\n this.onChange = fn;\n }\n\n registerOnTouched(fn: () => void): void {\n this.onTouched = fn;\n }\n\n setDisabledState(isDisabled: boolean): void {\n this.cvaDisabled.set(isDisabled);\n }\n\n // ── FormFieldControl methods ──\n\n /** @internal */\n setDescribedByIds(ids: string[]): void {\n this.describedByIdsSignal.set([...ids]);\n }\n\n /** @internal */\n override setLabelledByIds(ids: string[]): void {\n this.labelledByIdsSignal.set([...ids]);\n }\n\n /** @internal Clicking the form-field surface (outside the control) focuses the text input. Clicks inside the control are left alone so chip removal keeps its own focus restoration. */\n onContainerClick(event: MouseEvent): void {\n if (this.disabled()) return;\n if (event.defaultPrevented) return;\n const host = this.elementRef.nativeElement;\n if (event.target === host || host.contains(event.target as Node)) return;\n this.focus();\n }\n\n // ── Lifecycle ──\n\n ngOnInit(): void {\n // checkChildren: true — internal focus moves (input ↔ chips) stay \"focused\";\n // origin === null fires only when focus leaves the whole control, the single\n // source for onTouched and the addOnBlur commit.\n const monitor$ = this.focusMonitor.monitor(this.elementRef, true);\n if (isObservable(monitor$)) {\n monitor$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((origin) => {\n const wasFocused = this._focused();\n this._focused.set(!!origin);\n if (wasFocused && !origin) {\n if (this.addOnBlur() && this.inputText().trim().length > 0) {\n this.commitInput();\n }\n this.onTouched();\n this.errorWiring.bump();\n // Reset roving so the next Tab into the control lands on the input.\n this.activeChipIndex.set(null);\n }\n });\n }\n this.destroyRef.onDestroy(() => this.focusMonitor.stopMonitoring(this.elementRef));\n\n this.errorWiring.connect();\n }\n\n // ── Helpers ──\n\n private focusChip(index: number): void {\n this.activeChipIndex.set(index);\n this.requestFocus();\n }\n\n private focusInput(): void {\n this.activeChipIndex.set(null);\n this.requestFocus();\n }\n\n private requestFocus(): void {\n this.focusNonce.update((n) => n + 1);\n }\n\n private setInputText(value: string): void {\n this.inputText.set(value);\n const el = this.textInputRef()?.nativeElement;\n if (el && el.value !== value) el.value = value;\n }\n\n private announceMax(): void {\n const now = Date.now();\n if (now - this.lastMaxAnnounce < 500) return;\n this.lastMaxAnnounce = now;\n this.liveAnnouncer.announce(`Maximum ${this.maxTags()} tags reached`, 'assertive');\n }\n\n private splitOnSeparators(text: string, separators: readonly string[]): string[] {\n if (separators.length === 0) return [text];\n let normalized = text;\n for (const s of separators) normalized = normalized.split(s).join('\\u0000');\n return normalized.split('\\u0000');\n }\n\n private hasAccessibleNameHint(): boolean {\n return (\n !!this.ariaLabel() ||\n !!this.ariaLabelledby() ||\n this.labelledByIdsSignal().length > 0\n );\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"cdevhub-ngx-tw-theme.mjs","sources":["../../../projects/ngx-tw/theme/theme.types.ts","../../../projects/ngx-tw/theme/theme.config.ts","../../../projects/ngx-tw/theme/theme.service.ts","../../../projects/ngx-tw/theme/theme.directive.ts","../../../projects/ngx-tw/theme/theme.bootstrap.ts","../../../projects/ngx-tw/theme/cdevhub-ngx-tw-theme.ts"],"sourcesContent":["/**\n * The user-selectable theme. `'system'` defers to the OS, resolving\n * `prefers-color-scheme` and `prefers-contrast` as two independent axes: dark\n * plus increased contrast lands on `'high-contrast-dark'`, light plus increased\n * contrast on `'high-contrast'`.\n */\nexport type TwTheme = 'light' | 'dark' | 'high-contrast' | 'high-contrast-dark' | 'system';\n\n/**\n * The theme actually applied to the DOM after resolving `'system'` against the\n * OS preference.\n *\n * The two axes are appearance (light / dark) and contrast (normal / increased),\n * so the four values are their product: `'high-contrast'` is the light-based\n * increased-contrast scheme and `'high-contrast-dark'` the dark-based one.\n */\nexport type TwResolvedTheme = 'light' | 'dark' | 'high-contrast' | 'high-contrast-dark';\n\n/** Ordered list of every {@link TwTheme} value, used by `cycleTheme()` and for UI iteration. */\nexport const TW_THEMES = [\n 'light',\n 'dark',\n 'high-contrast',\n 'high-contrast-dark',\n 'system',\n] as const satisfies readonly TwTheme[];\n\n/** Ordered list of every {@link TwResolvedTheme} value (i.e. {@link TW_THEMES} minus `'system'`). */\nexport const TW_RESOLVED_THEMES = [\n 'light',\n 'dark',\n 'high-contrast',\n 'high-contrast-dark',\n] as const satisfies readonly TwResolvedTheme[];\n\n/**\n * Runtime configuration for {@link provideTheme}; controls storage, attribute\n * name, target element, and default.\n *\n * Every member is optional. This interface only ever reaches consumers through\n * `provideTheme(config?: Partial<TwThemeConfig>)`, which fills each unset key\n * from {@link DEFAULT_TW_THEME_CONFIG} — so a consumer holding a config object\n * typed as `TwThemeConfig` must not be forced to restate keys they do not\n * override, and adding a member in a future minor must not break them. The\n * resolved value handed to {@link TW_THEME_CONFIG} is `Required<TwThemeConfig>`.\n */\nexport interface TwThemeConfig {\n /** The default theme when no preference is stored. Defaults to `'system'`. */\n defaultTheme?: TwTheme;\n /**\n * localStorage key for persisting an explicit theme choice. Defaults to\n * `'ngx-tw-theme'`. Only `setTheme()` / `cycleTheme()` write it — providing\n * the service never does.\n */\n storageKey?: string;\n /** The HTML attribute written to the target element. Defaults to `'data-theme'`. */\n attribute?: string;\n /** Which element receives the theme attribute. Defaults to `'documentElement'`. */\n target?: 'documentElement' | 'body';\n}\n\n/**\n * Composite snapshot of `ThemeService` state — selected, resolved, system, and\n * boolean flags.\n *\n * The three flags are **not** mutually exclusive: `'high-contrast-dark'` sets\n * both {@link isDark} and {@link isHighContrast}, because it is dark *and*\n * high contrast. Branch on {@link resolvedTheme} when you need one case.\n */\nexport interface TwThemeState {\n /** The user-selected theme — may be `'system'`. */\n readonly theme: TwTheme;\n /** The theme actually applied to the DOM — never `'system'`. */\n readonly resolvedTheme: TwResolvedTheme;\n /** The OS appearance preference detected via `prefers-color-scheme` and `prefers-contrast`. */\n readonly systemTheme: TwResolvedTheme;\n /** True when {@link resolvedTheme} is a dark scheme — `'dark'` or `'high-contrast-dark'`. */\n readonly isDark: boolean;\n /** True when {@link resolvedTheme} is exactly `'light'`; the light-based `'high-contrast'` does not set it. */\n readonly isLight: boolean;\n /** True when {@link resolvedTheme} is an increased-contrast scheme — `'high-contrast'` or `'high-contrast-dark'`. */\n readonly isHighContrast: boolean;\n}\n\n/**\n * Built-in defaults merged under any user-provided {@link TwThemeConfig} by\n * `provideTheme()`. Typed `Required<TwThemeConfig>` so readers keep a\n * non-optional `string` / `TwTheme` for every field even though the interface\n * itself is all-optional.\n */\nexport const DEFAULT_TW_THEME_CONFIG: Required<TwThemeConfig> = {\n defaultTheme: 'system',\n storageKey: 'ngx-tw-theme',\n attribute: 'data-theme',\n target: 'documentElement',\n};\n","import {\n InjectionToken,\n inject,\n makeEnvironmentProviders,\n provideEnvironmentInitializer,\n type EnvironmentProviders,\n} from '@angular/core';\nimport { type TwThemeConfig, DEFAULT_TW_THEME_CONFIG } from './theme.types';\nimport { ThemeService } from './theme.service';\n\n/**\n * Injection token carrying the resolved {@link TwThemeConfig} (storage key,\n * attribute, target element, default theme).\n *\n * The value is `Required<TwThemeConfig>`: `TwThemeConfig`'s members are\n * optional so consumers can pass a partial config, but `provideTheme` fills\n * every key from {@link DEFAULT_TW_THEME_CONFIG} before providing it. Injectors\n * therefore still read a non-optional field for each setting, exactly as\n * before this token's type was tightened.\n */\nexport const TW_THEME_CONFIG = new InjectionToken<Required<TwThemeConfig>>('TW_THEME_CONFIG');\n\n/**\n * @deprecated Renamed to {@link TW_THEME_CONFIG} for consistency with every\n * other ngx-tw injection token. This is the *same token instance*, not a copy —\n * providing under either name and injecting under the other resolves — so the\n * rename is safe to adopt incrementally. Removed in the next major.\n */\nexport const THEME_CONFIG = TW_THEME_CONFIG;\n\n/**\n * Registers {@link ThemeService}, a {@link TW_THEME_CONFIG} value built by merging\n * `config` over {@link DEFAULT_TW_THEME_CONFIG}, and an environment initializer\n * that constructs the service at bootstrap. Call once in the app's environment\n * providers.\n *\n * The initializer is what makes the call self-sufficient. Everything that\n * applies a theme lives in `ThemeService`'s field initialisers and constructor\n * effect, so without it the stored preference was read — and `data-theme`\n * written — only once something happened to `inject(ThemeService)`. An app\n * whose theme toggle sits in a lazily-loaded route therefore rendered every\n * other route with no `data-theme` at all, silently falling back to the\n * `prefers-color-scheme` CSS branch; the failure looked intermittent because\n * it disappeared whenever the stored choice agreed with the OS. Injecting the\n * service yourself is still supported and is idempotent.\n *\n * Keys explicitly set to `undefined` are dropped before merging. Root\n * `tsconfig.json` does not set `exactOptionalPropertyTypes`, so\n * `provideTheme({ storageKey: env.themeKey })` type-checks even when\n * `env.themeKey` is `string | undefined` — and a plain spread would then write\n * `undefined` into a field `TwThemeConfig` types as `string`, making\n * `ThemeService` persist under the literal `localStorage` key `\"undefined\"`\n * (and, for `attribute`, call `setAttribute(\"undefined\", …)`).\n *\n * Providing the service does **not** write to `localStorage`; only an explicit\n * `setTheme()` / `cycleTheme()` does. For a flash-free first paint when the\n * stored choice disagrees with the OS, pair this with\n * {@link TW_THEME_BOOTSTRAP_SCRIPT} in `index.html`.\n */\nexport function provideTheme(config?: Partial<TwThemeConfig>): EnvironmentProviders {\n const overrides = Object.fromEntries(\n Object.entries(config ?? {}).filter(([, value]) => value !== undefined),\n );\n return makeEnvironmentProviders([\n {\n provide: TW_THEME_CONFIG,\n useValue: { ...DEFAULT_TW_THEME_CONFIG, ...overrides } as Required<TwThemeConfig>,\n },\n ThemeService,\n provideEnvironmentInitializer(() => {\n inject(ThemeService);\n }),\n ]);\n}\n","import {\n Injectable,\n NgZone,\n computed,\n effect,\n inject,\n signal,\n PLATFORM_ID,\n type OnDestroy,\n} from '@angular/core';\nimport { DOCUMENT, isPlatformBrowser } from '@angular/common';\nimport { TW_THEME_CONFIG } from './theme.config';\nimport { TW_THEMES, type TwTheme, type TwResolvedTheme, type TwThemeState } from './theme.types';\n\n/** OS colour-scheme query backing `'system'` resolution. */\nconst DARK_QUERY = '(prefers-color-scheme: dark)';\n\n/** OS contrast query backing `'system'` → `'high-contrast'` / `'high-contrast-dark'` resolution. */\nconst CONTRAST_QUERY = '(prefers-contrast: more)';\n\n/**\n * Stateful runtime service that owns the active theme, reacts to OS\n * `prefers-color-scheme` / `prefers-contrast` changes, persists an explicit\n * user selection to `localStorage`, and writes the resolved theme onto the\n * configured DOM target as a `data-theme` attribute.\n *\n * The selected {@link theme} may be `'system'` (defer to the OS); the\n * {@link resolvedTheme} computed from it is always one of `'light'`,\n * `'dark'`, `'high-contrast'`, or `'high-contrast-dark'` — never `'system'`.\n * Register via\n * {@link provideTheme} in the app's environment providers; `provideTheme`\n * also constructs the service at bootstrap, so injecting it is only needed\n * to read or change the theme.\n *\n * Storage is written **only** by {@link setTheme} / {@link cycleTheme}.\n * Merely providing the service never touches `localStorage`, so the\n * configured `defaultTheme` keeps applying until the user actually picks\n * something, and apps under a storage-consent flow can provide the service\n * before consent is granted.\n */\n@Injectable()\nexport class ThemeService implements OnDestroy {\n private readonly config = inject(TW_THEME_CONFIG);\n private readonly document = inject(DOCUMENT);\n private readonly isBrowser = isPlatformBrowser(inject(PLATFORM_ID));\n private readonly ngZone = inject(NgZone);\n\n private darkQuery: MediaQueryList | null = null;\n private contrastQuery: MediaQueryList | null = null;\n\n // One listener for both queries: the resolution rule reads them together, so\n // a handler that only knew its own query would clobber the other's decision\n // on the next OS tick. The event payload is deliberately ignored — a\n // `MediaQueryList`'s `matches` is already updated when `change` fires, so\n // re-reading both is the single source of truth.\n private readonly mediaListener = () => {\n this.systemTheme.set(this.detectSystemTheme());\n };\n\n /** The user-selected theme (may be `'system'`). */\n readonly theme = signal<TwTheme>(this.loadInitialTheme());\n\n /** The OS appearance preference — `prefers-color-scheme` plus `prefers-contrast`. */\n readonly systemTheme = signal<TwResolvedTheme>(this.detectSystemTheme());\n\n /** The resolved theme actually applied to the DOM (never `'system'`). */\n readonly resolvedTheme = computed<TwResolvedTheme>(() => {\n const t = this.theme();\n return t === 'system' ? this.systemTheme() : t;\n });\n\n /**\n * True when the resolved theme is a **dark** scheme — `'dark'` or\n * `'high-contrast-dark'`.\n *\n * It answers the appearance question, not \"which scheme\": the canonical use\n * is picking a colour that has to sit on the page background (a chart grid,\n * a canvas fill), and dark high contrast needs the dark answer there just as\n * much as plain dark does. It is therefore **not** mutually exclusive with\n * {@link isHighContrast}; branch on {@link resolvedTheme} for one case.\n */\n readonly isDark = computed(() => {\n const t = this.resolvedTheme();\n return t === 'dark' || t === 'high-contrast-dark';\n });\n /**\n * True when the resolved theme is exactly `'light'`.\n *\n * Deliberately narrower than {@link isDark}'s mirror image: the light-based\n * `'high-contrast'` does **not** set it, because widening it would change\n * what a shipped scheme reports to consumers already reading this flag.\n * Use `!isDark()` for the appearance question.\n */\n readonly isLight = computed(() => this.resolvedTheme() === 'light');\n /**\n * True when the resolved theme is an **increased-contrast** scheme —\n * `'high-contrast'` or `'high-contrast-dark'`.\n *\n * It answers the contrast question, so it can be true at the same time as\n * {@link isDark}.\n */\n readonly isHighContrast = computed(() => {\n const t = this.resolvedTheme();\n return t === 'high-contrast' || t === 'high-contrast-dark';\n });\n\n /** Snapshot of the full theme state — selected, resolved, system, and boolean flags. */\n readonly state = computed<TwThemeState>(() => ({\n theme: this.theme(),\n resolvedTheme: this.resolvedTheme(),\n systemTheme: this.systemTheme(),\n isDark: this.isDark(),\n isLight: this.isLight(),\n isHighContrast: this.isHighContrast(),\n }));\n\n constructor() {\n if (this.isBrowser) {\n // Register the media-query listeners outside the Angular zone — they fire\n // on OS preference changes, not user interaction, and we don't want\n // zone.js bookkeeping for every system tick. The listener calls\n // `signal.set()`, which schedules its own change detection.\n // Both `MediaQueryList`s already exist: the `systemTheme` field\n // initialiser above ran `detectSystemTheme()`, which mints them. The\n // `??=` keeps this correct if that ever stops being true.\n this.ngZone.runOutsideAngular(() => {\n this.darkQuery ??= window.matchMedia(DARK_QUERY);\n this.contrastQuery ??= window.matchMedia(CONTRAST_QUERY);\n this.darkQuery.addEventListener('change', this.mediaListener);\n this.contrastQuery.addEventListener('change', this.mediaListener);\n });\n }\n\n effect(() => {\n this.applyToDocument(this.resolvedTheme());\n });\n }\n\n /**\n * Sets the selected theme and persists it. Pass `'system'` to follow the OS\n * preference.\n *\n * This is the only entry point that writes to `localStorage` — see the note\n * on the class.\n */\n setTheme(theme: TwTheme): void {\n this.theme.set(theme);\n this.persistTheme(theme);\n }\n\n /** Advances the selected theme to the next entry in {@link TW_THEMES}, wrapping around, and persists it. */\n cycleTheme(): void {\n const idx = TW_THEMES.indexOf(this.theme());\n this.setTheme(TW_THEMES[(idx + 1) % TW_THEMES.length]);\n }\n\n /**\n * Writes the configured theme attribute onto an arbitrary element, scoping\n * that subtree to the given theme.\n *\n * Each of the four schemes ships an element-agnostic `[data-theme=…]` block\n * (`_light.css`, `_dark.css`, `_high-contrast.css`,\n * `_high-contrast-dark.css`), so the tokens really do re-resolve on the\n * element and cascade into its descendants — including back to `'light'`\n * from inside a dark page.\n *\n * Caveat: those CSS blocks key off the literal `data-theme` attribute. If\n * `provideTheme({ attribute })` renamed it, this method writes the renamed\n * attribute and the shipped stylesheet will not react — a custom attribute\n * only works with matching custom CSS.\n */\n applyToElement(element: HTMLElement, theme: TwResolvedTheme): void {\n element.setAttribute(this.config.attribute, theme);\n }\n\n ngOnDestroy(): void {\n this.darkQuery?.removeEventListener('change', this.mediaListener);\n this.contrastQuery?.removeEventListener('change', this.mediaListener);\n }\n\n private loadInitialTheme(): TwTheme {\n if (!this.isBrowser) return this.config.defaultTheme;\n try {\n const stored = localStorage.getItem(this.config.storageKey);\n if (stored && (TW_THEMES as readonly string[]).includes(stored)) {\n return stored as TwTheme;\n }\n } catch {\n /* localStorage unavailable */\n }\n return this.config.defaultTheme;\n }\n\n /**\n * Resolves `'system'` against the OS.\n *\n * The two preferences are treated as independent axes and composed, not\n * ranked: `prefers-color-scheme` picks the appearance and\n * `prefers-contrast: more` picks the contrast, giving the full 2×2 —\n * `light` / `dark` / `high-contrast` / `high-contrast-dark`.\n *\n * This is only correct because the library ships **both** high-contrast\n * ramps. While `_high-contrast.css` was the only one, contrast had to be\n * suppressed whenever the OS also asked for dark, or a user running dark +\n * increased contrast — a common pairing — would have been moved from a dark\n * surface onto a white one. `_high-contrast-dark.css` removed that\n * constraint, so the ranking is gone; if a future change ever drops one of\n * the two ramps, this method has to go back to ranking them.\n *\n * Both queries are minted here (not in the constructor) because the\n * `systemTheme` field initialiser calls this before the constructor body\n * runs; the constructor then attaches `change` listeners to the same two\n * objects, so the resolution stays live rather than read-once.\n */\n private detectSystemTheme(): TwResolvedTheme {\n if (!this.isBrowser) return 'light';\n const prefersDark = (this.darkQuery ??= window.matchMedia(DARK_QUERY)).matches;\n const prefersMoreContrast = (this.contrastQuery ??= window.matchMedia(CONTRAST_QUERY)).matches;\n if (prefersMoreContrast) return prefersDark ? 'high-contrast-dark' : 'high-contrast';\n return prefersDark ? 'dark' : 'light';\n }\n\n private applyToDocument(theme: TwResolvedTheme): void {\n if (!this.isBrowser) return;\n const target =\n this.config.target === 'documentElement'\n ? this.document.documentElement\n : this.document.body;\n target.setAttribute(this.config.attribute, theme);\n }\n\n private persistTheme(theme: TwTheme): void {\n if (!this.isBrowser) return;\n try {\n localStorage.setItem(this.config.storageKey, theme);\n } catch {\n /* localStorage unavailable */\n }\n }\n}\n","import { Directive, input } from '@angular/core';\nimport type { TwResolvedTheme } from './theme.types';\n\n@Directive({\n selector: '[twTheme]',\n host: {\n '[attr.data-theme]': 'twTheme()',\n },\n})\nexport class ThemeDirective {\n /**\n * Scopes a subtree to a specific resolved theme by writing `data-theme` on\n * the host. Required.\n *\n * Works in every direction: each of the four schemes ships an\n * element-agnostic `[data-theme=\"…\"]` block (`_light.css`, `_dark.css`,\n * `_high-contrast.css`, `_high-contrast-dark.css`), so a `'light'` pane\n * inside a dark page re-resolves the tokens rather than inheriting the\n * ancestor's.\n *\n * The attribute name is the literal `data-theme` that the shipped CSS keys\n * off — it deliberately ignores `provideTheme({ attribute })`, since a\n * renamed attribute matches none of those blocks.\n */\n readonly twTheme = input.required<TwResolvedTheme>();\n}\n","import { DEFAULT_TW_THEME_CONFIG } from './theme.types';\n\n/**\n * Body of an inline `<head>` script that applies a previously persisted theme\n * before the app bundle runs, eliminating the flash of the wrong theme on\n * reload.\n *\n * `ThemeService` cannot cover this case: it is JavaScript in the application\n * bundle, so the browser has already painted by the time it writes\n * `data-theme` — and `provideTheme`'s environment initializer does not change\n * that. The CSS `@media (prefers-color-scheme: dark)` fallback covers users\n * who never chose a theme; the flash is what an *explicit* choice that\n * disagrees with the OS looks like — light chosen on a dark machine, or\n * either high-contrast scheme chosen on a machine not already asking for\n * increased contrast (the CSS has a `prefers-color-scheme` branch but\n * deliberately no `prefers-contrast` one, so neither contrast scheme is\n * reachable without an explicit `data-theme`).\n *\n * The string is built from {@link DEFAULT_TW_THEME_CONFIG}, so the storage key\n * and attribute cannot drift from what `ThemeService` actually uses — that\n * drift is the reason this ships as code rather than as a README snippet\n * alone. Copy the literal script into `index.html`, or interpolate this\n * constant during an SSR / index transform:\n *\n * ```html\n * <head>\n * <script>try{var t=localStorage.getItem('ngx-tw-theme');if(t&&t!=='system')document.documentElement.setAttribute('data-theme',t)}catch(e){}</script>\n * </head>\n * ```\n *\n * Notes on the behaviour it deliberately does *not* have:\n * - A stored `'system'` writes nothing, so the CSS `prefers-color-scheme`\n * fallback keeps deciding — which is exactly what `'system'` means.\n * - It assumes the default `target: 'documentElement'`. A `<head>` script runs\n * before `<body>` exists, so `target: 'body'` cannot be bootstrapped this\n * way.\n * - If you overrode `storageKey` or `attribute` via `provideTheme`, adapt the\n * literal snippet to match; this constant only encodes the defaults.\n * - It is dependency-free and wrapped in `try`/`catch`, so a browser with\n * storage blocked falls through to the CSS behaviour instead of throwing\n * before the app loads.\n */\nexport const TW_THEME_BOOTSTRAP_SCRIPT =\n `try{var t=localStorage.getItem(${JSON.stringify(DEFAULT_TW_THEME_CONFIG.storageKey)});` +\n `if(t&&t!=='system')document.documentElement.setAttribute(` +\n `${JSON.stringify(DEFAULT_TW_THEME_CONFIG.attribute)},t)}catch(e){}`;\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cdevhub-ngx-tw-theme.mjs","sources":["../../../projects/ngx-tw/theme/theme.types.ts","../../../projects/ngx-tw/theme/theme.config.ts","../../../projects/ngx-tw/theme/theme.service.ts","../../../projects/ngx-tw/theme/theme.directive.ts","../../../projects/ngx-tw/theme/theme.bootstrap.ts","../../../projects/ngx-tw/theme/cdevhub-ngx-tw-theme.ts"],"sourcesContent":["/**\n * The user-selectable theme. `'system'` defers to the OS, resolving\n * `prefers-color-scheme` and `prefers-contrast` as two independent axes: dark\n * plus increased contrast lands on `'high-contrast-dark'`, light plus increased\n * contrast on `'high-contrast'`.\n */\nexport type TwTheme = 'light' | 'dark' | 'high-contrast' | 'high-contrast-dark' | 'system';\n\n/**\n * The theme actually applied to the DOM after resolving `'system'` against the\n * OS preference.\n *\n * The two axes are appearance (light / dark) and contrast (normal / increased),\n * so the four values are their product: `'high-contrast'` is the light-based\n * increased-contrast scheme and `'high-contrast-dark'` the dark-based one.\n */\nexport type TwResolvedTheme = 'light' | 'dark' | 'high-contrast' | 'high-contrast-dark';\n\n/** Ordered list of every {@link TwTheme} value, used by `cycleTheme()` and for UI iteration. */\nexport const TW_THEMES = [\n 'light',\n 'dark',\n 'high-contrast',\n 'high-contrast-dark',\n 'system',\n] as const satisfies readonly TwTheme[];\n\n/** Ordered list of every {@link TwResolvedTheme} value (i.e. {@link TW_THEMES} minus `'system'`). */\nexport const TW_RESOLVED_THEMES = [\n 'light',\n 'dark',\n 'high-contrast',\n 'high-contrast-dark',\n] as const satisfies readonly TwResolvedTheme[];\n\n/**\n * Runtime configuration for {@link provideTheme}; controls storage, attribute\n * name, target element, and default.\n *\n * Every member is optional. This interface only ever reaches consumers through\n * `provideTheme(config?: Partial<TwThemeConfig>)`, which fills each unset key\n * from {@link DEFAULT_TW_THEME_CONFIG} — so a consumer holding a config object\n * typed as `TwThemeConfig` must not be forced to restate keys they do not\n * override, and adding a member in a future minor must not break them. The\n * resolved value handed to {@link TW_THEME_CONFIG} is `Required<TwThemeConfig>`.\n */\nexport interface TwThemeConfig {\n /** The default theme when no preference is stored. Defaults to `'system'`. */\n defaultTheme?: TwTheme;\n /**\n * localStorage key for persisting an explicit theme choice. Defaults to\n * `'ngx-tw-theme'`. Only `setTheme()` / `cycleTheme()` write it — providing\n * the service never does.\n */\n storageKey?: string;\n /**\n * The HTML attribute written to the target element. Defaults to `'data-theme'`.\n *\n * @deprecated Changing this breaks theming, and cannot be made to work. The\n * shipped stylesheets key off the **literal** `data-theme` — `_light.css`,\n * `_dark.css` and both high-contrast files each declare an element-agnostic\n * `[data-theme=\"…\"]` block, and CSS cannot parameterise an attribute name. So\n * a renamed attribute matches none of them: `ThemeService.applyToElement()`\n * writes the new name and nothing reacts, while `ThemeDirective` ignores this\n * option entirely and keeps writing `data-theme` (which is the only reason\n * `[twTheme]` still works when it is set). Two of the three consumers\n * therefore disagree with it by design.\n *\n * It is deprecated rather than removed because removing it is a breaking\n * change; it will go in the next major. To scope a theme to a subtree use the\n * `[twTheme]` directive, and to retheme, override the semantic tokens in your\n * own `@theme` block rather than renaming the attribute they hang off.\n */\n attribute?: string;\n /** Which element receives the theme attribute. Defaults to `'documentElement'`. */\n target?: 'documentElement' | 'body';\n}\n\n/**\n * Composite snapshot of `ThemeService` state — selected, resolved, system, and\n * boolean flags.\n *\n * The three flags are **not** mutually exclusive: `'high-contrast-dark'` sets\n * both {@link isDark} and {@link isHighContrast}, because it is dark *and*\n * high contrast. Branch on {@link resolvedTheme} when you need one case.\n */\nexport interface TwThemeState {\n /** The user-selected theme — may be `'system'`. */\n readonly theme: TwTheme;\n /** The theme actually applied to the DOM — never `'system'`. */\n readonly resolvedTheme: TwResolvedTheme;\n /** The OS appearance preference detected via `prefers-color-scheme` and `prefers-contrast`. */\n readonly systemTheme: TwResolvedTheme;\n /** True when {@link resolvedTheme} is a dark scheme — `'dark'` or `'high-contrast-dark'`. */\n readonly isDark: boolean;\n /** True when {@link resolvedTheme} is exactly `'light'`; the light-based `'high-contrast'` does not set it. */\n readonly isLight: boolean;\n /** True when {@link resolvedTheme} is an increased-contrast scheme — `'high-contrast'` or `'high-contrast-dark'`. */\n readonly isHighContrast: boolean;\n}\n\n/**\n * Built-in defaults merged under any user-provided {@link TwThemeConfig} by\n * `provideTheme()`. Typed `Required<TwThemeConfig>` so readers keep a\n * non-optional `string` / `TwTheme` for every field even though the interface\n * itself is all-optional.\n */\nexport const DEFAULT_TW_THEME_CONFIG: Required<TwThemeConfig> = {\n defaultTheme: 'system',\n storageKey: 'ngx-tw-theme',\n attribute: 'data-theme',\n target: 'documentElement',\n};\n","import {\n InjectionToken,\n inject,\n makeEnvironmentProviders,\n provideEnvironmentInitializer,\n type EnvironmentProviders,\n} from '@angular/core';\nimport { type TwThemeConfig, DEFAULT_TW_THEME_CONFIG } from './theme.types';\nimport { ThemeService } from './theme.service';\n\n/**\n * Injection token carrying the resolved {@link TwThemeConfig} (storage key,\n * attribute, target element, default theme).\n *\n * The value is `Required<TwThemeConfig>`: `TwThemeConfig`'s members are\n * optional so consumers can pass a partial config, but `provideTheme` fills\n * every key from {@link DEFAULT_TW_THEME_CONFIG} before providing it. Injectors\n * therefore still read a non-optional field for each setting, exactly as\n * before this token's type was tightened.\n */\nexport const TW_THEME_CONFIG = new InjectionToken<Required<TwThemeConfig>>('TW_THEME_CONFIG');\n\n/**\n * @deprecated Renamed to {@link TW_THEME_CONFIG} for consistency with every\n * other ngx-tw injection token. This is the *same token instance*, not a copy —\n * providing under either name and injecting under the other resolves — so the\n * rename is safe to adopt incrementally. Removed in the next major.\n */\nexport const THEME_CONFIG = TW_THEME_CONFIG;\n\n/**\n * Registers {@link ThemeService}, a {@link TW_THEME_CONFIG} value built by merging\n * `config` over {@link DEFAULT_TW_THEME_CONFIG}, and an environment initializer\n * that constructs the service at bootstrap. Call once in the app's environment\n * providers.\n *\n * The initializer is what makes the call self-sufficient. Everything that\n * applies a theme lives in `ThemeService`'s field initialisers and constructor\n * effect, so without it the stored preference was read — and `data-theme`\n * written — only once something happened to `inject(ThemeService)`. An app\n * whose theme toggle sits in a lazily-loaded route therefore rendered every\n * other route with no `data-theme` at all, silently falling back to the\n * `prefers-color-scheme` CSS branch; the failure looked intermittent because\n * it disappeared whenever the stored choice agreed with the OS. Injecting the\n * service yourself is still supported and is idempotent.\n *\n * Keys explicitly set to `undefined` are dropped before merging. Root\n * `tsconfig.json` does not set `exactOptionalPropertyTypes`, so\n * `provideTheme({ storageKey: env.themeKey })` type-checks even when\n * `env.themeKey` is `string | undefined` — and a plain spread would then write\n * `undefined` into a field `TwThemeConfig` types as `string`, making\n * `ThemeService` persist under the literal `localStorage` key `\"undefined\"`\n * (and, for `attribute`, call `setAttribute(\"undefined\", …)`).\n *\n * Providing the service does **not** write to `localStorage`; only an explicit\n * `setTheme()` / `cycleTheme()` does. For a flash-free first paint when the\n * stored choice disagrees with the OS, pair this with\n * {@link TW_THEME_BOOTSTRAP_SCRIPT} in `index.html`.\n */\nexport function provideTheme(config?: Partial<TwThemeConfig>): EnvironmentProviders {\n const overrides = Object.fromEntries(\n Object.entries(config ?? {}).filter(([, value]) => value !== undefined),\n );\n return makeEnvironmentProviders([\n {\n provide: TW_THEME_CONFIG,\n useValue: { ...DEFAULT_TW_THEME_CONFIG, ...overrides } as Required<TwThemeConfig>,\n },\n ThemeService,\n provideEnvironmentInitializer(() => {\n inject(ThemeService);\n }),\n ]);\n}\n","import {\n Injectable,\n NgZone,\n computed,\n effect,\n inject,\n signal,\n PLATFORM_ID,\n type OnDestroy,\n} from '@angular/core';\nimport { DOCUMENT, isPlatformBrowser } from '@angular/common';\nimport { TW_THEME_CONFIG } from './theme.config';\nimport { TW_THEMES, type TwTheme, type TwResolvedTheme, type TwThemeState } from './theme.types';\n\n/** OS colour-scheme query backing `'system'` resolution. */\nconst DARK_QUERY = '(prefers-color-scheme: dark)';\n\n/** OS contrast query backing `'system'` → `'high-contrast'` / `'high-contrast-dark'` resolution. */\nconst CONTRAST_QUERY = '(prefers-contrast: more)';\n\n/**\n * Stateful runtime service that owns the active theme, reacts to OS\n * `prefers-color-scheme` / `prefers-contrast` changes, persists an explicit\n * user selection to `localStorage`, and writes the resolved theme onto the\n * configured DOM target as a `data-theme` attribute.\n *\n * The selected {@link theme} may be `'system'` (defer to the OS); the\n * {@link resolvedTheme} computed from it is always one of `'light'`,\n * `'dark'`, `'high-contrast'`, or `'high-contrast-dark'` — never `'system'`.\n * Register via\n * {@link provideTheme} in the app's environment providers; `provideTheme`\n * also constructs the service at bootstrap, so injecting it is only needed\n * to read or change the theme.\n *\n * Storage is written **only** by {@link setTheme} / {@link cycleTheme}.\n * Merely providing the service never touches `localStorage`, so the\n * configured `defaultTheme` keeps applying until the user actually picks\n * something, and apps under a storage-consent flow can provide the service\n * before consent is granted.\n */\n@Injectable()\nexport class ThemeService implements OnDestroy {\n private readonly config = inject(TW_THEME_CONFIG);\n private readonly document = inject(DOCUMENT);\n private readonly isBrowser = isPlatformBrowser(inject(PLATFORM_ID));\n private readonly ngZone = inject(NgZone);\n\n private darkQuery: MediaQueryList | null = null;\n private contrastQuery: MediaQueryList | null = null;\n\n // One listener for both queries: the resolution rule reads them together, so\n // a handler that only knew its own query would clobber the other's decision\n // on the next OS tick. The event payload is deliberately ignored — a\n // `MediaQueryList`'s `matches` is already updated when `change` fires, so\n // re-reading both is the single source of truth.\n private readonly mediaListener = () => {\n this.systemTheme.set(this.detectSystemTheme());\n };\n\n /** The user-selected theme (may be `'system'`). */\n readonly theme = signal<TwTheme>(this.loadInitialTheme());\n\n /** The OS appearance preference — `prefers-color-scheme` plus `prefers-contrast`. */\n readonly systemTheme = signal<TwResolvedTheme>(this.detectSystemTheme());\n\n /** The resolved theme actually applied to the DOM (never `'system'`). */\n readonly resolvedTheme = computed<TwResolvedTheme>(() => {\n const t = this.theme();\n return t === 'system' ? this.systemTheme() : t;\n });\n\n /**\n * True when the resolved theme is a **dark** scheme — `'dark'` or\n * `'high-contrast-dark'`.\n *\n * It answers the appearance question, not \"which scheme\": the canonical use\n * is picking a colour that has to sit on the page background (a chart grid,\n * a canvas fill), and dark high contrast needs the dark answer there just as\n * much as plain dark does. It is therefore **not** mutually exclusive with\n * {@link isHighContrast}; branch on {@link resolvedTheme} for one case.\n */\n readonly isDark = computed(() => {\n const t = this.resolvedTheme();\n return t === 'dark' || t === 'high-contrast-dark';\n });\n /**\n * True when the resolved theme is exactly `'light'`.\n *\n * Deliberately narrower than {@link isDark}'s mirror image: the light-based\n * `'high-contrast'` does **not** set it, because widening it would change\n * what a shipped scheme reports to consumers already reading this flag.\n * Use `!isDark()` for the appearance question.\n */\n readonly isLight = computed(() => this.resolvedTheme() === 'light');\n /**\n * True when the resolved theme is an **increased-contrast** scheme —\n * `'high-contrast'` or `'high-contrast-dark'`.\n *\n * It answers the contrast question, so it can be true at the same time as\n * {@link isDark}.\n */\n readonly isHighContrast = computed(() => {\n const t = this.resolvedTheme();\n return t === 'high-contrast' || t === 'high-contrast-dark';\n });\n\n /** Snapshot of the full theme state — selected, resolved, system, and boolean flags. */\n readonly state = computed<TwThemeState>(() => ({\n theme: this.theme(),\n resolvedTheme: this.resolvedTheme(),\n systemTheme: this.systemTheme(),\n isDark: this.isDark(),\n isLight: this.isLight(),\n isHighContrast: this.isHighContrast(),\n }));\n\n constructor() {\n if (this.isBrowser) {\n // Register the media-query listeners outside the Angular zone — they fire\n // on OS preference changes, not user interaction, and we don't want\n // zone.js bookkeeping for every system tick. The listener calls\n // `signal.set()`, which schedules its own change detection.\n // Both `MediaQueryList`s already exist: the `systemTheme` field\n // initialiser above ran `detectSystemTheme()`, which mints them. The\n // `??=` keeps this correct if that ever stops being true.\n this.ngZone.runOutsideAngular(() => {\n this.darkQuery ??= window.matchMedia(DARK_QUERY);\n this.contrastQuery ??= window.matchMedia(CONTRAST_QUERY);\n this.darkQuery.addEventListener('change', this.mediaListener);\n this.contrastQuery.addEventListener('change', this.mediaListener);\n });\n }\n\n effect(() => {\n this.applyToDocument(this.resolvedTheme());\n });\n }\n\n /**\n * Sets the selected theme and persists it. Pass `'system'` to follow the OS\n * preference.\n *\n * This is the only entry point that writes to `localStorage` — see the note\n * on the class.\n */\n setTheme(theme: TwTheme): void {\n this.theme.set(theme);\n this.persistTheme(theme);\n }\n\n /** Advances the selected theme to the next entry in {@link TW_THEMES}, wrapping around, and persists it. */\n cycleTheme(): void {\n const idx = TW_THEMES.indexOf(this.theme());\n this.setTheme(TW_THEMES[(idx + 1) % TW_THEMES.length]);\n }\n\n /**\n * Writes the configured theme attribute onto an arbitrary element, scoping\n * that subtree to the given theme.\n *\n * Each of the four schemes ships an element-agnostic `[data-theme=…]` block\n * (`_light.css`, `_dark.css`, `_high-contrast.css`,\n * `_high-contrast-dark.css`), so the tokens really do re-resolve on the\n * element and cascade into its descendants — including back to `'light'`\n * from inside a dark page.\n *\n * Caveat: those CSS blocks key off the literal `data-theme` attribute. If\n * `provideTheme({ attribute })` renamed it, this method writes the renamed\n * attribute and the shipped stylesheet will not react — a custom attribute\n * only works with matching custom CSS.\n */\n applyToElement(element: HTMLElement, theme: TwResolvedTheme): void {\n element.setAttribute(this.config.attribute, theme);\n }\n\n ngOnDestroy(): void {\n this.darkQuery?.removeEventListener('change', this.mediaListener);\n this.contrastQuery?.removeEventListener('change', this.mediaListener);\n }\n\n private loadInitialTheme(): TwTheme {\n if (!this.isBrowser) return this.config.defaultTheme;\n try {\n const stored = localStorage.getItem(this.config.storageKey);\n if (stored && (TW_THEMES as readonly string[]).includes(stored)) {\n return stored as TwTheme;\n }\n } catch {\n /* localStorage unavailable */\n }\n return this.config.defaultTheme;\n }\n\n /**\n * Resolves `'system'` against the OS.\n *\n * The two preferences are treated as independent axes and composed, not\n * ranked: `prefers-color-scheme` picks the appearance and\n * `prefers-contrast: more` picks the contrast, giving the full 2×2 —\n * `light` / `dark` / `high-contrast` / `high-contrast-dark`.\n *\n * This is only correct because the library ships **both** high-contrast\n * ramps. While `_high-contrast.css` was the only one, contrast had to be\n * suppressed whenever the OS also asked for dark, or a user running dark +\n * increased contrast — a common pairing — would have been moved from a dark\n * surface onto a white one. `_high-contrast-dark.css` removed that\n * constraint, so the ranking is gone; if a future change ever drops one of\n * the two ramps, this method has to go back to ranking them.\n *\n * Both queries are minted here (not in the constructor) because the\n * `systemTheme` field initialiser calls this before the constructor body\n * runs; the constructor then attaches `change` listeners to the same two\n * objects, so the resolution stays live rather than read-once.\n */\n private detectSystemTheme(): TwResolvedTheme {\n if (!this.isBrowser) return 'light';\n const prefersDark = (this.darkQuery ??= window.matchMedia(DARK_QUERY)).matches;\n const prefersMoreContrast = (this.contrastQuery ??= window.matchMedia(CONTRAST_QUERY)).matches;\n if (prefersMoreContrast) return prefersDark ? 'high-contrast-dark' : 'high-contrast';\n return prefersDark ? 'dark' : 'light';\n }\n\n private applyToDocument(theme: TwResolvedTheme): void {\n if (!this.isBrowser) return;\n const target =\n this.config.target === 'documentElement'\n ? this.document.documentElement\n : this.document.body;\n target.setAttribute(this.config.attribute, theme);\n }\n\n private persistTheme(theme: TwTheme): void {\n if (!this.isBrowser) return;\n try {\n localStorage.setItem(this.config.storageKey, theme);\n } catch {\n /* localStorage unavailable */\n }\n }\n}\n","import { Directive, input } from '@angular/core';\nimport type { TwResolvedTheme } from './theme.types';\n\n@Directive({\n selector: '[twTheme]',\n host: {\n '[attr.data-theme]': 'twTheme()',\n },\n})\nexport class ThemeDirective {\n /**\n * Scopes a subtree to a specific resolved theme by writing `data-theme` on\n * the host. Required.\n *\n * Works in every direction: each of the four schemes ships an\n * element-agnostic `[data-theme=\"…\"]` block (`_light.css`, `_dark.css`,\n * `_high-contrast.css`, `_high-contrast-dark.css`), so a `'light'` pane\n * inside a dark page re-resolves the tokens rather than inheriting the\n * ancestor's.\n *\n * The attribute name is the literal `data-theme` that the shipped CSS keys\n * off — it deliberately ignores `provideTheme({ attribute })`, since a\n * renamed attribute matches none of those blocks.\n */\n readonly twTheme = input.required<TwResolvedTheme>();\n}\n","import { DEFAULT_TW_THEME_CONFIG } from './theme.types';\n\n/**\n * Body of an inline `<head>` script that applies a previously persisted theme\n * before the app bundle runs, eliminating the flash of the wrong theme on\n * reload.\n *\n * `ThemeService` cannot cover this case: it is JavaScript in the application\n * bundle, so the browser has already painted by the time it writes\n * `data-theme` — and `provideTheme`'s environment initializer does not change\n * that. The CSS `@media (prefers-color-scheme: dark)` fallback covers users\n * who never chose a theme; the flash is what an *explicit* choice that\n * disagrees with the OS looks like — light chosen on a dark machine, or\n * either high-contrast scheme chosen on a machine not already asking for\n * increased contrast (the CSS has a `prefers-color-scheme` branch but\n * deliberately no `prefers-contrast` one, so neither contrast scheme is\n * reachable without an explicit `data-theme`).\n *\n * The string is built from {@link DEFAULT_TW_THEME_CONFIG}, so the storage key\n * and attribute cannot drift from what `ThemeService` actually uses — that\n * drift is the reason this ships as code rather than as a README snippet\n * alone. Copy the literal script into `index.html`, or interpolate this\n * constant during an SSR / index transform:\n *\n * ```html\n * <head>\n * <script>try{var t=localStorage.getItem('ngx-tw-theme');if(t&&t!=='system')document.documentElement.setAttribute('data-theme',t)}catch(e){}</script>\n * </head>\n * ```\n *\n * Notes on the behaviour it deliberately does *not* have:\n * - A stored `'system'` writes nothing, so the CSS `prefers-color-scheme`\n * fallback keeps deciding — which is exactly what `'system'` means.\n * - It assumes the default `target: 'documentElement'`. A `<head>` script runs\n * before `<body>` exists, so `target: 'body'` cannot be bootstrapped this\n * way.\n * - If you overrode `storageKey` or `attribute` via `provideTheme`, adapt the\n * literal snippet to match; this constant only encodes the defaults.\n * - It is dependency-free and wrapped in `try`/`catch`, so a browser with\n * storage blocked falls through to the CSS behaviour instead of throwing\n * before the app loads.\n */\nexport const TW_THEME_BOOTSTRAP_SCRIPT =\n `try{var t=localStorage.getItem(${JSON.stringify(DEFAULT_TW_THEME_CONFIG.storageKey)});` +\n `if(t&&t!=='system')document.documentElement.setAttribute(` +\n `${JSON.stringify(DEFAULT_TW_THEME_CONFIG.attribute)},t)}catch(e){}`;\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
@@ -229,15 +229,15 @@ const timePickerVariants = tv({
229
229
  { variant: 'default', size: 'md', class: { root: 'h-9' } },
230
230
  { variant: 'default', size: 'lg', class: { root: 'h-11' } },
231
231
  { variant: 'default', size: 'xl', class: { root: 'h-12' } },
232
- { variant: 'default', focused: true, color: 'primary', class: { root: 'border-primary-500' } },
233
- { variant: 'default', focused: true, color: 'secondary', class: { root: 'border-secondary-500' } },
234
- { variant: 'default', focused: true, color: 'accent', class: { root: 'border-accent-500' } },
232
+ { variant: 'default', focused: true, color: 'primary', class: { root: 'border-primary-border' } },
233
+ { variant: 'default', focused: true, color: 'secondary', class: { root: 'border-secondary-border' } },
234
+ { variant: 'default', focused: true, color: 'accent', class: { root: 'border-accent-border' } },
235
235
  { variant: 'default', focused: true, color: 'neutral', class: { root: 'border-border-strong' } },
236
- { variant: 'default', focused: true, color: 'info', class: { root: 'border-info-500' } },
237
- { variant: 'default', focused: true, color: 'success', class: { root: 'border-success-500' } },
238
- { variant: 'default', focused: true, color: 'warning', class: { root: 'border-warning-500' } },
239
- { variant: 'default', focused: true, color: 'error', class: { root: 'border-error-500' } },
240
- { variant: 'default', errorState: true, class: { root: 'border-error-500' } },
236
+ { variant: 'default', focused: true, color: 'info', class: { root: 'border-info-border' } },
237
+ { variant: 'default', focused: true, color: 'success', class: { root: 'border-success-border' } },
238
+ { variant: 'default', focused: true, color: 'warning', class: { root: 'border-warning-border' } },
239
+ { variant: 'default', focused: true, color: 'error', class: { root: 'border-error-border' } },
240
+ { variant: 'default', errorState: true, class: { root: 'border-error-border' } },
241
241
  ],
242
242
  defaultVariants: {
243
243
  size: 'md',