@xui/cascader 2.0.0-alpha.20 → 2.0.0-alpha.21
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.
|
@@ -22,14 +22,19 @@ class XuiCascader {
|
|
|
22
22
|
panel = viewChild.required('panel', /* @ts-ignore */
|
|
23
23
|
...(ngDevMode ? [{ debugName: "panel" }] : /* istanbul ignore next */ []));
|
|
24
24
|
ref = null;
|
|
25
|
+
/** Extra classes, merged into the component's own rather than replacing them. */
|
|
25
26
|
class = input('', /* @ts-ignore */
|
|
26
27
|
...(ngDevMode ? [{ debugName: "class" }] : /* istanbul ignore next */ []));
|
|
28
|
+
/** The root options. Each may carry `children`, which become the next column when it is selected. */
|
|
27
29
|
options = input([], /* @ts-ignore */
|
|
28
30
|
...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
|
|
31
|
+
/** The selected path, as option values from the root down. Two-way bindable with `[(value)]`. */
|
|
29
32
|
value = model([], /* @ts-ignore */
|
|
30
33
|
...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
34
|
+
/** Trigger text shown while nothing is selected. */
|
|
31
35
|
placeholder = input('Select', /* @ts-ignore */
|
|
32
36
|
...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
|
|
37
|
+
/** Block interaction and dim the trigger. The panel cannot be opened. */
|
|
33
38
|
disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
34
39
|
open = signal(false, /* @ts-ignore */
|
|
35
40
|
...(ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"xui-cascader.mjs","sources":["../../../../../../libs/ui/cascader/xui/src/lib/cascader.ts","../../../../../../libs/ui/cascader/xui/src/index.ts","../../../../../../libs/ui/cascader/xui/src/xui-cascader.ts"],"sourcesContent":["import { BooleanInput } from '@angular/cdk/coercion';\nimport {\n booleanAttribute,\n ChangeDetectionStrategy,\n Component,\n computed,\n effect,\n ElementRef,\n input,\n model,\n signal,\n TemplateRef,\n untracked,\n viewChild,\n ViewEncapsulation\n} from '@angular/core';\nimport { xui } from '@xui/core';\nimport { injectXOverlay, type XOverlayRef } from '@xui/core/overlay';\nimport type { ClassValue } from 'clsx';\n\nexport interface XuiCascaderOption {\n value: string;\n label: string;\n children?: XuiCascaderOption[];\n disabled?: boolean;\n}\n\n/**\n * A cascading, column-based select. Each level opens the next column of children;\n * choosing a leaf commits the full path. `value` is a two-way bindable array of\n * values from root to leaf.\n *\n * The column panel floats on `@xui/core/overlay`, connected to the trigger, so\n * stacking, Escape and outside-click dismissal behave like every other overlay.\n *\n * ```html\n * <xui-cascader [options]=\"regions\" [(value)]=\"path\" placeholder=\"Select region\" />\n * ```\n */\n@Component({\n selector: 'xui-cascader',\n template: `\n <button\n #trigger\n type=\"button\"\n [class]=\"triggerClass()\"\n [disabled]=\"disabled()\"\n (click)=\"toggle()\"\n [attr.aria-expanded]=\"open()\"\n >\n <span [class]=\"selectedLabels().length ? 'text-foreground truncate' : 'text-foreground-muted'\">\n {{ selectedLabels().length ? selectedLabels().join(' / ') : placeholder() }}\n </span>\n <svg viewBox=\"0 0 24 24\" class=\"text-foreground-muted ms-auto h-4 w-4 shrink-0\" fill=\"none\">\n <path d=\"M6 9l6 6 6-6\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n </button>\n\n <ng-template #panel>\n <div [class]=\"panelClass()\">\n @for (column of columns(); track $index; let col = $index) {\n <ul class=\"border-border max-h-64 min-w-40 overflow-auto border-e last:border-e-0\">\n @for (option of column; track option.value) {\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\n <li\n role=\"option\"\n [class]=\"optionClass(option, activePath()[col] === option.value)\"\n [attr.aria-selected]=\"activePath()[col] === option.value\"\n (click)=\"select(col, option)\"\n >\n <span class=\"truncate\">{{ option.label }}</span>\n @if (option.children?.length) {\n <svg viewBox=\"0 0 24 24\" class=\"ms-auto h-3.5 w-3.5 shrink-0\" fill=\"none\">\n <path\n d=\"M9 6l6 6-6 6\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n }\n </li>\n }\n </ul>\n }\n </div>\n </ng-template>\n `,\n host: {\n '[class]': 'computedClass()'\n },\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None\n})\nexport class XuiCascader {\n private readonly overlay = injectXOverlay();\n private readonly trigger = viewChild.required<ElementRef<HTMLElement>>('trigger');\n private readonly panel = viewChild.required<TemplateRef<unknown>>('panel');\n private ref: XOverlayRef | null = null;\n\n readonly class = input<ClassValue>('');\n readonly options = input<XuiCascaderOption[]>([]);\n readonly value = model<string[]>([]);\n readonly placeholder = input<string>('Select');\n readonly disabled = input<boolean, BooleanInput>(false, { transform: booleanAttribute });\n\n protected readonly open = signal(false);\n /** The path currently being navigated (may be deeper than the committed value). */\n protected readonly activePath = signal<string[]>([]);\n\n /** The columns to render: root options, then children of each active selection. */\n protected readonly columns = computed(() => {\n const result: XuiCascaderOption[][] = [];\n let level: XuiCascaderOption[] = this.options();\n result.push(level);\n for (const value of this.activePath()) {\n const option = level.find(o => o.value === value);\n if (option?.children?.length) {\n level = option.children;\n result.push(level);\n } else {\n break;\n }\n }\n return result;\n });\n\n protected readonly selectedLabels = computed(() => {\n const labels: string[] = [];\n let level: XuiCascaderOption[] = this.options();\n for (const value of this.value()) {\n const option = level.find(o => o.value === value);\n if (!option) {\n break;\n }\n labels.push(option.label);\n level = option.children ?? [];\n }\n return labels;\n });\n\n constructor() {\n // The `open` signal is the single source of truth; the overlay follows it.\n effect(() => {\n const open = this.open();\n\n untracked(() => (open ? this.attach() : this.detach()));\n });\n }\n\n protected toggle(): void {\n if (this.disabled()) {\n return;\n }\n if (!this.open()) {\n // Reopen at the committed path.\n this.activePath.set([...this.value()]);\n }\n this.open.update(open => !open);\n }\n\n protected select(columnIndex: number, option: XuiCascaderOption): void {\n if (option.disabled) {\n return;\n }\n const path = [...this.activePath().slice(0, columnIndex), option.value];\n this.activePath.set(path);\n if (!option.children?.length) {\n this.value.set(path);\n this.open.set(false);\n }\n }\n\n private attach(): void {\n if (this.ref) {\n return;\n }\n\n // Outside clicks dismiss through the overlay's own click-phase check, so a\n // press that starts a drag outside still does not close the panel. Focus is\n // never moved into the panel, so nothing is trapped or restored.\n const ref = this.overlay.open(this.panel(), {\n origin: this.trigger().nativeElement,\n placement: 'bottom-start',\n offset: 4,\n restoreFocus: false\n });\n\n this.ref = ref;\n\n // The overlay can close itself (Escape, outside click). Fold that back into\n // `open` so the model never lies about what is on screen; a stale ref's late\n // close must not clobber a panel that was reopened in the meantime.\n void ref.closed.then(() => {\n if (this.ref === ref) {\n this.ref = null;\n untracked(() => this.open.set(false));\n }\n });\n }\n\n private detach(): void {\n // Null synchronously so a reopen in the same tick does not see a stale ref.\n const ref = this.ref;\n this.ref = null;\n ref?.close();\n }\n\n protected readonly computedClass = computed(() => xui('inline-block', this.class()));\n protected readonly triggerClass = computed(() =>\n xui(\n 'border-border bg-surface text-foreground flex h-(--control-height-md) w-full min-w-48 items-center gap-1 rounded-md border px-(--control-padding-md) text-sm outline-none focus-visible:border-primary disabled:opacity-50'\n )\n );\n protected readonly panelClass = computed(() =>\n xui('border-border bg-surface-overlay flex rounded-lg border p-1 shadow-overlay')\n );\n\n protected optionClass(option: XuiCascaderOption, active: boolean): string {\n return xui(\n 'flex cursor-pointer items-center gap-2 rounded px-2 py-1.5 text-sm select-none',\n option.disabled ? 'text-foreground-subtle cursor-not-allowed' : 'hover:bg-surface-inset',\n active && 'bg-primary/10 text-primary font-medium'\n );\n }\n}\n","import { XuiCascader } from './lib/cascader';\n\nexport * from './lib/cascader';\n\nexport const XuiCascaderImports = [XuiCascader] as const;\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"xui-cascader.mjs","sources":["../../../../../../libs/ui/cascader/xui/src/lib/cascader.ts","../../../../../../libs/ui/cascader/xui/src/index.ts","../../../../../../libs/ui/cascader/xui/src/xui-cascader.ts"],"sourcesContent":["import { BooleanInput } from '@angular/cdk/coercion';\nimport {\n booleanAttribute,\n ChangeDetectionStrategy,\n Component,\n computed,\n effect,\n ElementRef,\n input,\n model,\n signal,\n TemplateRef,\n untracked,\n viewChild,\n ViewEncapsulation\n} from '@angular/core';\nimport { xui } from '@xui/core';\nimport { injectXOverlay, type XOverlayRef } from '@xui/core/overlay';\nimport type { ClassValue } from 'clsx';\n\nexport interface XuiCascaderOption {\n value: string;\n label: string;\n children?: XuiCascaderOption[];\n disabled?: boolean;\n}\n\n/**\n * A cascading, column-based select. Each level opens the next column of children;\n * choosing a leaf commits the full path. `value` is a two-way bindable array of\n * values from root to leaf.\n *\n * The column panel floats on `@xui/core/overlay`, connected to the trigger, so\n * stacking, Escape and outside-click dismissal behave like every other overlay.\n *\n * ```html\n * <xui-cascader [options]=\"regions\" [(value)]=\"path\" placeholder=\"Select region\" />\n * ```\n */\n@Component({\n selector: 'xui-cascader',\n template: `\n <button\n #trigger\n type=\"button\"\n [class]=\"triggerClass()\"\n [disabled]=\"disabled()\"\n (click)=\"toggle()\"\n [attr.aria-expanded]=\"open()\"\n >\n <span [class]=\"selectedLabels().length ? 'text-foreground truncate' : 'text-foreground-muted'\">\n {{ selectedLabels().length ? selectedLabels().join(' / ') : placeholder() }}\n </span>\n <svg viewBox=\"0 0 24 24\" class=\"text-foreground-muted ms-auto h-4 w-4 shrink-0\" fill=\"none\">\n <path d=\"M6 9l6 6 6-6\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n </button>\n\n <ng-template #panel>\n <div [class]=\"panelClass()\">\n @for (column of columns(); track $index; let col = $index) {\n <ul class=\"border-border max-h-64 min-w-40 overflow-auto border-e last:border-e-0\">\n @for (option of column; track option.value) {\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\n <li\n role=\"option\"\n [class]=\"optionClass(option, activePath()[col] === option.value)\"\n [attr.aria-selected]=\"activePath()[col] === option.value\"\n (click)=\"select(col, option)\"\n >\n <span class=\"truncate\">{{ option.label }}</span>\n @if (option.children?.length) {\n <svg viewBox=\"0 0 24 24\" class=\"ms-auto h-3.5 w-3.5 shrink-0\" fill=\"none\">\n <path\n d=\"M9 6l6 6-6 6\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n }\n </li>\n }\n </ul>\n }\n </div>\n </ng-template>\n `,\n host: {\n '[class]': 'computedClass()'\n },\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None\n})\nexport class XuiCascader {\n private readonly overlay = injectXOverlay();\n private readonly trigger = viewChild.required<ElementRef<HTMLElement>>('trigger');\n private readonly panel = viewChild.required<TemplateRef<unknown>>('panel');\n private ref: XOverlayRef | null = null;\n\n /** Extra classes, merged into the component's own rather than replacing them. */\n readonly class = input<ClassValue>('');\n /** The root options. Each may carry `children`, which become the next column when it is selected. */\n readonly options = input<XuiCascaderOption[]>([]);\n /** The selected path, as option values from the root down. Two-way bindable with `[(value)]`. */\n readonly value = model<string[]>([]);\n /** Trigger text shown while nothing is selected. */\n readonly placeholder = input<string>('Select');\n /** Block interaction and dim the trigger. The panel cannot be opened. */\n readonly disabled = input<boolean, BooleanInput>(false, { transform: booleanAttribute });\n\n protected readonly open = signal(false);\n /** The path currently being navigated (may be deeper than the committed value). */\n protected readonly activePath = signal<string[]>([]);\n\n /** The columns to render: root options, then children of each active selection. */\n protected readonly columns = computed(() => {\n const result: XuiCascaderOption[][] = [];\n let level: XuiCascaderOption[] = this.options();\n result.push(level);\n for (const value of this.activePath()) {\n const option = level.find(o => o.value === value);\n if (option?.children?.length) {\n level = option.children;\n result.push(level);\n } else {\n break;\n }\n }\n return result;\n });\n\n protected readonly selectedLabels = computed(() => {\n const labels: string[] = [];\n let level: XuiCascaderOption[] = this.options();\n for (const value of this.value()) {\n const option = level.find(o => o.value === value);\n if (!option) {\n break;\n }\n labels.push(option.label);\n level = option.children ?? [];\n }\n return labels;\n });\n\n constructor() {\n // The `open` signal is the single source of truth; the overlay follows it.\n effect(() => {\n const open = this.open();\n\n untracked(() => (open ? this.attach() : this.detach()));\n });\n }\n\n protected toggle(): void {\n if (this.disabled()) {\n return;\n }\n if (!this.open()) {\n // Reopen at the committed path.\n this.activePath.set([...this.value()]);\n }\n this.open.update(open => !open);\n }\n\n protected select(columnIndex: number, option: XuiCascaderOption): void {\n if (option.disabled) {\n return;\n }\n const path = [...this.activePath().slice(0, columnIndex), option.value];\n this.activePath.set(path);\n if (!option.children?.length) {\n this.value.set(path);\n this.open.set(false);\n }\n }\n\n private attach(): void {\n if (this.ref) {\n return;\n }\n\n // Outside clicks dismiss through the overlay's own click-phase check, so a\n // press that starts a drag outside still does not close the panel. Focus is\n // never moved into the panel, so nothing is trapped or restored.\n const ref = this.overlay.open(this.panel(), {\n origin: this.trigger().nativeElement,\n placement: 'bottom-start',\n offset: 4,\n restoreFocus: false\n });\n\n this.ref = ref;\n\n // The overlay can close itself (Escape, outside click). Fold that back into\n // `open` so the model never lies about what is on screen; a stale ref's late\n // close must not clobber a panel that was reopened in the meantime.\n void ref.closed.then(() => {\n if (this.ref === ref) {\n this.ref = null;\n untracked(() => this.open.set(false));\n }\n });\n }\n\n private detach(): void {\n // Null synchronously so a reopen in the same tick does not see a stale ref.\n const ref = this.ref;\n this.ref = null;\n ref?.close();\n }\n\n protected readonly computedClass = computed(() => xui('inline-block', this.class()));\n protected readonly triggerClass = computed(() =>\n xui(\n 'border-border bg-surface text-foreground flex h-(--control-height-md) w-full min-w-48 items-center gap-1 rounded-md border px-(--control-padding-md) text-sm outline-none focus-visible:border-primary disabled:opacity-50'\n )\n );\n protected readonly panelClass = computed(() =>\n xui('border-border bg-surface-overlay flex rounded-lg border p-1 shadow-overlay')\n );\n\n protected optionClass(option: XuiCascaderOption, active: boolean): string {\n return xui(\n 'flex cursor-pointer items-center gap-2 rounded px-2 py-1.5 text-sm select-none',\n option.disabled ? 'text-foreground-subtle cursor-not-allowed' : 'hover:bg-surface-inset',\n active && 'bg-primary/10 text-primary font-medium'\n );\n }\n}\n","import { XuiCascader } from './lib/cascader';\n\nexport * from './lib/cascader';\n\nexport const XuiCascaderImports = [XuiCascader] as const;\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;;AA2BA;;;;;;;;;;;AAWG;MAyDU,WAAW,CAAA;IACL,OAAO,GAAG,cAAc,EAAE;AAC1B,IAAA,OAAO,GAAG,SAAS,CAAC,QAAQ,CAA0B,SAAS;gFAAC;AAChE,IAAA,KAAK,GAAG,SAAS,CAAC,QAAQ,CAAuB,OAAO;8EAAC;IAClE,GAAG,GAAuB,IAAI;;IAG7B,KAAK,GAAG,KAAK,CAAa,EAAE;8EAAC;;IAE7B,OAAO,GAAG,KAAK,CAAsB,EAAE;gFAAC;;IAExC,KAAK,GAAG,KAAK,CAAW,EAAE;8EAAC;;IAE3B,WAAW,GAAG,KAAK,CAAS,QAAQ;oFAAC;;IAErC,QAAQ,GAAG,KAAK,CAAwB,KAAK,gFAAI,SAAS,EAAE,gBAAgB,EAAA,CAAG;IAErE,IAAI,GAAG,MAAM,CAAC,KAAK;6EAAC;;IAEpB,UAAU,GAAG,MAAM,CAAW,EAAE;mFAAC;;AAGjC,IAAA,OAAO,GAAG,QAAQ,CAAC,MAAK;QACzC,MAAM,MAAM,GAA0B,EAAE;AACxC,QAAA,IAAI,KAAK,GAAwB,IAAI,CAAC,OAAO,EAAE;AAC/C,QAAA,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC;QAClB,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,UAAU,EAAE,EAAE;AACrC,YAAA,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,KAAK,KAAK,CAAC;AACjD,YAAA,IAAI,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE;AAC5B,gBAAA,KAAK,GAAG,MAAM,CAAC,QAAQ;AACvB,gBAAA,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC;YACpB;iBAAO;gBACL;YACF;QACF;AACA,QAAA,OAAO,MAAM;IACf,CAAC;gFAAC;AAEiB,IAAA,cAAc,GAAG,QAAQ,CAAC,MAAK;QAChD,MAAM,MAAM,GAAa,EAAE;AAC3B,QAAA,IAAI,KAAK,GAAwB,IAAI,CAAC,OAAO,EAAE;QAC/C,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,KAAK,EAAE,EAAE;AAChC,YAAA,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,KAAK,KAAK,CAAC;YACjD,IAAI,CAAC,MAAM,EAAE;gBACX;YACF;AACA,YAAA,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC;AACzB,YAAA,KAAK,GAAG,MAAM,CAAC,QAAQ,IAAI,EAAE;QAC/B;AACA,QAAA,OAAO,MAAM;IACf,CAAC;uFAAC;AAEF,IAAA,WAAA,GAAA;;QAEE,MAAM,CAAC,MAAK;AACV,YAAA,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE;YAExB,SAAS,CAAC,OAAO,IAAI,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;AACzD,QAAA,CAAC,CAAC;IACJ;IAEU,MAAM,GAAA;AACd,QAAA,IAAI,IAAI,CAAC,QAAQ,EAAE,EAAE;YACnB;QACF;AACA,QAAA,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE;;AAEhB,YAAA,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;QACxC;AACA,QAAA,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC;IACjC;IAEU,MAAM,CAAC,WAAmB,EAAE,MAAyB,EAAA;AAC7D,QAAA,IAAI,MAAM,CAAC,QAAQ,EAAE;YACnB;QACF;QACA,MAAM,IAAI,GAAG,CAAC,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,WAAW,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC;AACvE,QAAA,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC;AACzB,QAAA,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE;AAC5B,YAAA,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC;AACpB,YAAA,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC;QACtB;IACF;IAEQ,MAAM,GAAA;AACZ,QAAA,IAAI,IAAI,CAAC,GAAG,EAAE;YACZ;QACF;;;;AAKA,QAAA,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE;AAC1C,YAAA,MAAM,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,aAAa;AACpC,YAAA,SAAS,EAAE,cAAc;AACzB,YAAA,MAAM,EAAE,CAAC;AACT,YAAA,YAAY,EAAE;AACf,SAAA,CAAC;AAEF,QAAA,IAAI,CAAC,GAAG,GAAG,GAAG;;;;AAKd,QAAA,KAAK,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,MAAK;AACxB,YAAA,IAAI,IAAI,CAAC,GAAG,KAAK,GAAG,EAAE;AACpB,gBAAA,IAAI,CAAC,GAAG,GAAG,IAAI;AACf,gBAAA,SAAS,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YACvC;AACF,QAAA,CAAC,CAAC;IACJ;IAEQ,MAAM,GAAA;;AAEZ,QAAA,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG;AACpB,QAAA,IAAI,CAAC,GAAG,GAAG,IAAI;QACf,GAAG,EAAE,KAAK,EAAE;IACd;AAEmB,IAAA,aAAa,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,cAAc,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC;sFAAC;IACjE,YAAY,GAAG,QAAQ,CAAC,MACzC,GAAG,CACD,4NAA4N,CAC7N;qFACF;IACkB,UAAU,GAAG,QAAQ,CAAC,MACvC,GAAG,CAAC,4EAA4E,CAAC;mFAClF;IAES,WAAW,CAAC,MAAyB,EAAE,MAAe,EAAA;QAC9D,OAAO,GAAG,CACR,gFAAgF,EAChF,MAAM,CAAC,QAAQ,GAAG,2CAA2C,GAAG,wBAAwB,EACxF,MAAM,IAAI,wCAAwC,CACnD;IACH;0HAvIW,WAAW,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAX,uBAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,WAAW,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,cAAA,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,OAAA,EAAA,EAAA,iBAAA,EAAA,SAAA,EAAA,UAAA,EAAA,SAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,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,WAAA,EAAA,EAAA,iBAAA,EAAA,aAAA,EAAA,UAAA,EAAA,aAAA,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,EAAA,OAAA,EAAA,EAAA,KAAA,EAAA,aAAA,EAAA,EAAA,IAAA,EAAA,EAAA,UAAA,EAAA,EAAA,OAAA,EAAA,iBAAA,EAAA,EAAA,EAAA,WAAA,EAAA,CAAA,EAAA,YAAA,EAAA,SAAA,EAAA,KAAA,EAAA,IAAA,EAAA,SAAA,EAAA,CAAA,SAAA,CAAA,EAAA,WAAA,EAAA,IAAA,EAAA,QAAA,EAAA,IAAA,EAAA,EAAA,EAAA,YAAA,EAAA,OAAA,EAAA,KAAA,EAAA,IAAA,EAAA,SAAA,EAAA,CAAA,OAAA,CAAA,EAAA,WAAA,EAAA,IAAA,EAAA,QAAA,EAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAtDZ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+CT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,aAAA,EAAA,EAAA,CAAA,iBAAA,CAAA,IAAA,EAAA,CAAA;;2FAOU,WAAW,EAAA,UAAA,EAAA,CAAA;kBAxDvB,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,cAAc;AACxB,oBAAA,QAAQ,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+CT,EAAA,CAAA;AACD,oBAAA,IAAI,EAAE;AACJ,wBAAA,SAAS,EAAE;AACZ,qBAAA;oBACD,eAAe,EAAE,uBAAuB,CAAC,MAAM;oBAC/C,aAAa,EAAE,iBAAiB,CAAC;AAClC,iBAAA;AAGwE,SAAA,CAAA,EAAA,cAAA,EAAA,MAAA,EAAA,EAAA,cAAA,EAAA,EAAA,OAAA,EAAA,CAAA,EAAA,IAAA,EAAA,EAAA,CAAA,SAAA,EAAA,IAAA,EAAA,CAAA,SAAS,+DACd,OAAO,EAAA,EAAA,QAAA,EAAA,IAAA,EAAA,CAAA,EAAA,CAAA,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,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,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,EAAA,EAAA,IAAA,EAAA,EAAA,CAAA,MAAA,EAAA,IAAA,EAAA,CAAA,aAAA,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,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,EAAA,CAAA;;AC9FpE,MAAM,kBAAkB,GAAG,CAAC,WAAW;;ACJ9C;;AAEG;;;;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xui/cascader",
|
|
3
|
-
"version": "2.0.0-alpha.
|
|
3
|
+
"version": "2.0.0-alpha.21",
|
|
4
4
|
"description": "Modern Angular 22 UI Library based on TailwindCSS",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"angular",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"peerDependencies": {
|
|
39
39
|
"@angular/cdk": "22",
|
|
40
40
|
"@angular/core": "22",
|
|
41
|
-
"@xui/core": "2.0.0-alpha.
|
|
41
|
+
"@xui/core": "2.0.0-alpha.21",
|
|
42
42
|
"clsx": "^2.1.1"
|
|
43
43
|
},
|
|
44
44
|
"publishConfig": {
|
package/types/xui-cascader.d.ts
CHANGED
|
@@ -25,10 +25,15 @@ declare class XuiCascader {
|
|
|
25
25
|
private readonly trigger;
|
|
26
26
|
private readonly panel;
|
|
27
27
|
private ref;
|
|
28
|
+
/** Extra classes, merged into the component's own rather than replacing them. */
|
|
28
29
|
readonly class: _angular_core.InputSignal<ClassValue>;
|
|
30
|
+
/** The root options. Each may carry `children`, which become the next column when it is selected. */
|
|
29
31
|
readonly options: _angular_core.InputSignal<XuiCascaderOption[]>;
|
|
32
|
+
/** The selected path, as option values from the root down. Two-way bindable with `[(value)]`. */
|
|
30
33
|
readonly value: _angular_core.ModelSignal<string[]>;
|
|
34
|
+
/** Trigger text shown while nothing is selected. */
|
|
31
35
|
readonly placeholder: _angular_core.InputSignal<string>;
|
|
36
|
+
/** Block interaction and dim the trigger. The panel cannot be opened. */
|
|
32
37
|
readonly disabled: _angular_core.InputSignalWithTransform<boolean, BooleanInput>;
|
|
33
38
|
protected readonly open: _angular_core.WritableSignal<boolean>;
|
|
34
39
|
/** The path currently being navigated (may be deeper than the committed value). */
|