@atelier-ui/angular 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -0
- package/fesm2022/atelier-ui-angular.mjs +3182 -0
- package/fesm2022/atelier-ui-angular.mjs.map +1 -0
- package/package.json +41 -0
- package/types/atelier-ui-angular.d.ts +1278 -0
|
@@ -0,0 +1,3182 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { input, computed, ChangeDetectionStrategy, Component, model, viewChild, effect, InjectionToken, inject, ElementRef, signal, output, Directive, ViewEncapsulation, Injector, Injectable, DestroyRef, untracked, contentChildren } from '@angular/core';
|
|
3
|
+
import * as i1 from '@angular/cdk/text-field';
|
|
4
|
+
import { TextFieldModule } from '@angular/cdk/text-field';
|
|
5
|
+
import * as i1$1 from '@angular/cdk/a11y';
|
|
6
|
+
import { ActiveDescendantKeyManager, A11yModule } from '@angular/cdk/a11y';
|
|
7
|
+
import * as i1$2 from '@angular/cdk/accordion';
|
|
8
|
+
import { CdkAccordion, CdkAccordionItem } from '@angular/cdk/accordion';
|
|
9
|
+
import * as i1$3 from '@angular/cdk/menu';
|
|
10
|
+
import { CdkMenuTrigger, CdkMenu, CdkMenuItem } from '@angular/cdk/menu';
|
|
11
|
+
import { createFlexibleConnectedPositionStrategy, createRepositionScrollStrategy, createOverlayRef } from '@angular/cdk/overlay';
|
|
12
|
+
import { ComponentPortal } from '@angular/cdk/portal';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Accessible button component with visual variants and sizes.
|
|
16
|
+
*
|
|
17
|
+
* Usage:
|
|
18
|
+
* ```html
|
|
19
|
+
* <llm-button variant="primary" size="md" (click)="save()">Save</llm-button>
|
|
20
|
+
* <llm-button variant="outline" [disabled]="true">Cancel</llm-button>
|
|
21
|
+
* <llm-button [loading]="isSaving">Saving…</llm-button>
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
class LlmButton {
|
|
25
|
+
/** Visual style of the button. */
|
|
26
|
+
variant = input('primary', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
|
|
27
|
+
/** Size of the button. */
|
|
28
|
+
size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
29
|
+
/** Disables the button, preventing interaction. */
|
|
30
|
+
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
|
|
31
|
+
/** Shows a loading spinner and disables interaction. */
|
|
32
|
+
loading = input(false, ...(ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []));
|
|
33
|
+
isDisabled = computed(() => this.disabled() || this.loading(), ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
|
|
34
|
+
hostClasses = computed(() => `variant-${this.variant()} size-${this.size()}${this.isDisabled() ? ' is-disabled' : ''}${this.loading() ? ' is-loading' : ''}`, ...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
|
|
35
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmButton, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
36
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.4", type: LlmButton, isStandalone: true, selector: "llm-button", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "button" }, properties: { "class": "hostClasses()", "attr.aria-disabled": "isDisabled()", "attr.disabled": "isDisabled() ? true : null" } }, ngImport: i0, template: `
|
|
37
|
+
@if (loading()) {
|
|
38
|
+
<span class="spinner" aria-hidden="true"></span>
|
|
39
|
+
}
|
|
40
|
+
<ng-content />
|
|
41
|
+
`, isInline: true, styles: [":host{display:inline-flex;align-items:center;justify-content:center;gap:var(--ui-spacing-2);border:1px solid transparent;border-radius:var(--ui-radius-md);font-family:var(--ui-font-family);font-size:var(--ui-font-size-md);font-weight:var(--ui-font-weight-medium);line-height:var(--ui-line-height-tight);cursor:pointer;transition:background-color var(--ui-transition-fast),border-color var(--ui-transition-fast),color var(--ui-transition-fast),box-shadow var(--ui-transition-fast),transform var(--ui-transition-fast);white-space:nowrap;text-decoration:none;-webkit-user-select:none;user-select:none}:host(:focus-visible){outline:none;box-shadow:var(--ui-focus-ring)}:host(.variant-primary){background-color:var(--ui-color-primary);color:var(--ui-color-text-on-primary);border-color:var(--ui-color-primary);box-shadow:var(--ui-shadow-xs)}:host(.variant-primary:hover:not(.is-disabled)){background-color:var(--ui-color-primary-hover);border-color:var(--ui-color-primary-hover);box-shadow:var(--ui-shadow-md);transform:translateY(-1px)}:host(.variant-primary:active:not(.is-disabled)){background-color:var(--ui-color-primary-active);border-color:var(--ui-color-primary-active);box-shadow:var(--ui-shadow-xs);transform:scale(.97)}:host(.variant-secondary){background-color:var(--ui-color-secondary);color:var(--ui-color-text-on-secondary);border-color:var(--ui-color-secondary);box-shadow:var(--ui-shadow-xs)}:host(.variant-secondary:hover:not(.is-disabled)){background-color:var(--ui-color-secondary-hover);border-color:var(--ui-color-secondary-hover);box-shadow:var(--ui-shadow-md);transform:translateY(-1px)}:host(.variant-secondary:active:not(.is-disabled)){background-color:var(--ui-color-secondary-active);border-color:var(--ui-color-secondary-active);box-shadow:var(--ui-shadow-xs);transform:scale(.97)}:host(.variant-outline){background-color:transparent;color:var(--ui-color-primary);border-color:var(--ui-color-border)}:host(.variant-outline:hover:not(.is-disabled)){background-color:var(--ui-color-primary-light);border-color:var(--ui-color-primary);transform:translateY(-1px)}:host(.variant-outline:active:not(.is-disabled)){background-color:color-mix(in srgb,var(--ui-color-primary) 12%,transparent);transform:scale(.97)}:host(.size-sm){padding:var(--ui-spacing-1) var(--ui-spacing-3);font-size:var(--ui-font-size-sm)}:host(.size-md){padding:var(--ui-spacing-2) var(--ui-spacing-4);font-size:var(--ui-font-size-md)}:host(.size-lg){padding:var(--ui-spacing-3) var(--ui-spacing-6);font-size:var(--ui-font-size-lg)}:host(.is-disabled){opacity:var(--ui-opacity-disabled);cursor:not-allowed;pointer-events:none}.spinner{display:inline-block;width:1em;height:1em;border:1.5px solid currentColor;border-top-color:transparent;border-radius:var(--ui-radius-full);animation:llm-spin .7s linear infinite;flex-shrink:0}@keyframes llm-spin{to{transform:rotate(360deg)}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
42
|
+
}
|
|
43
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmButton, decorators: [{
|
|
44
|
+
type: Component,
|
|
45
|
+
args: [{ selector: 'llm-button', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: `
|
|
46
|
+
@if (loading()) {
|
|
47
|
+
<span class="spinner" aria-hidden="true"></span>
|
|
48
|
+
}
|
|
49
|
+
<ng-content />
|
|
50
|
+
`, host: {
|
|
51
|
+
role: 'button',
|
|
52
|
+
'[class]': 'hostClasses()',
|
|
53
|
+
'[attr.aria-disabled]': 'isDisabled()',
|
|
54
|
+
'[attr.disabled]': 'isDisabled() ? true : null',
|
|
55
|
+
}, styles: [":host{display:inline-flex;align-items:center;justify-content:center;gap:var(--ui-spacing-2);border:1px solid transparent;border-radius:var(--ui-radius-md);font-family:var(--ui-font-family);font-size:var(--ui-font-size-md);font-weight:var(--ui-font-weight-medium);line-height:var(--ui-line-height-tight);cursor:pointer;transition:background-color var(--ui-transition-fast),border-color var(--ui-transition-fast),color var(--ui-transition-fast),box-shadow var(--ui-transition-fast),transform var(--ui-transition-fast);white-space:nowrap;text-decoration:none;-webkit-user-select:none;user-select:none}:host(:focus-visible){outline:none;box-shadow:var(--ui-focus-ring)}:host(.variant-primary){background-color:var(--ui-color-primary);color:var(--ui-color-text-on-primary);border-color:var(--ui-color-primary);box-shadow:var(--ui-shadow-xs)}:host(.variant-primary:hover:not(.is-disabled)){background-color:var(--ui-color-primary-hover);border-color:var(--ui-color-primary-hover);box-shadow:var(--ui-shadow-md);transform:translateY(-1px)}:host(.variant-primary:active:not(.is-disabled)){background-color:var(--ui-color-primary-active);border-color:var(--ui-color-primary-active);box-shadow:var(--ui-shadow-xs);transform:scale(.97)}:host(.variant-secondary){background-color:var(--ui-color-secondary);color:var(--ui-color-text-on-secondary);border-color:var(--ui-color-secondary);box-shadow:var(--ui-shadow-xs)}:host(.variant-secondary:hover:not(.is-disabled)){background-color:var(--ui-color-secondary-hover);border-color:var(--ui-color-secondary-hover);box-shadow:var(--ui-shadow-md);transform:translateY(-1px)}:host(.variant-secondary:active:not(.is-disabled)){background-color:var(--ui-color-secondary-active);border-color:var(--ui-color-secondary-active);box-shadow:var(--ui-shadow-xs);transform:scale(.97)}:host(.variant-outline){background-color:transparent;color:var(--ui-color-primary);border-color:var(--ui-color-border)}:host(.variant-outline:hover:not(.is-disabled)){background-color:var(--ui-color-primary-light);border-color:var(--ui-color-primary);transform:translateY(-1px)}:host(.variant-outline:active:not(.is-disabled)){background-color:color-mix(in srgb,var(--ui-color-primary) 12%,transparent);transform:scale(.97)}:host(.size-sm){padding:var(--ui-spacing-1) var(--ui-spacing-3);font-size:var(--ui-font-size-sm)}:host(.size-md){padding:var(--ui-spacing-2) var(--ui-spacing-4);font-size:var(--ui-font-size-md)}:host(.size-lg){padding:var(--ui-spacing-3) var(--ui-spacing-6);font-size:var(--ui-font-size-lg)}:host(.is-disabled){opacity:var(--ui-opacity-disabled);cursor:not-allowed;pointer-events:none}.spinner{display:inline-block;width:1em;height:1em;border:1.5px solid currentColor;border-top-color:transparent;border-radius:var(--ui-radius-full);animation:llm-spin .7s linear infinite;flex-shrink:0}@keyframes llm-spin{to{transform:rotate(360deg)}}\n"] }]
|
|
56
|
+
}], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }] } });
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Card container component supporting elevated, outlined, and flat visual variants.
|
|
60
|
+
* Compose with `llm-card-header`, `llm-card-content`, and `llm-card-footer` sub-components.
|
|
61
|
+
*
|
|
62
|
+
* Usage:
|
|
63
|
+
* ```html
|
|
64
|
+
* <llm-card variant="elevated" padding="md">
|
|
65
|
+
* <llm-card-header>Card Title</llm-card-header>
|
|
66
|
+
* <llm-card-content>Main content goes here.</llm-card-content>
|
|
67
|
+
* <llm-card-footer>
|
|
68
|
+
* <llm-button variant="primary">Save</llm-button>
|
|
69
|
+
* </llm-card-footer>
|
|
70
|
+
* </llm-card>
|
|
71
|
+
* ```
|
|
72
|
+
*/
|
|
73
|
+
class LlmCard {
|
|
74
|
+
/** Visual style of the card. */
|
|
75
|
+
variant = input('elevated', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
|
|
76
|
+
/** Internal padding of the card. */
|
|
77
|
+
padding = input('md', ...(ngDevMode ? [{ debugName: "padding" }] : /* istanbul ignore next */ []));
|
|
78
|
+
hostClasses = computed(() => `variant-${this.variant()} padding-${this.padding()}`, ...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
|
|
79
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmCard, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
80
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.4", type: LlmCard, isStandalone: true, selector: "llm-card", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, padding: { classPropertyName: "padding", publicName: "padding", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "hostClasses()" } }, ngImport: i0, template: `<ng-content />`, isInline: true, styles: ["llm-card{display:block;border-radius:var(--ui-radius-xl);background-color:var(--ui-color-surface);overflow:hidden}llm-card.variant-elevated{box-shadow:var(--ui-shadow-md);border:1px solid var(--ui-color-border)}llm-card.variant-outlined{border:1px solid var(--ui-color-border);background-color:var(--ui-color-surface)}llm-card.variant-flat{background-color:var(--ui-color-surface-sunken)}llm-card.padding-none llm-card-header,llm-card.padding-none llm-card-content,llm-card.padding-none llm-card-footer{padding:0}llm-card.padding-sm llm-card-header,llm-card.padding-sm llm-card-content,llm-card.padding-sm llm-card-footer{padding:var(--ui-spacing-3)}llm-card.padding-md llm-card-header,llm-card.padding-md llm-card-content,llm-card.padding-md llm-card-footer{padding:var(--ui-spacing-4)}llm-card.padding-lg llm-card-header,llm-card.padding-lg llm-card-content,llm-card.padding-lg llm-card-footer{padding:var(--ui-spacing-6)}llm-card-header{display:block;font-size:var(--ui-font-size-lg);font-weight:var(--ui-font-weight-semibold);color:var(--ui-color-text);border-bottom:1px solid var(--ui-color-border);letter-spacing:var(--ui-letter-spacing-tight)}llm-card-content{display:block;color:var(--ui-color-text);line-height:var(--ui-line-height-normal)}llm-card-footer{display:flex;align-items:center;gap:var(--ui-spacing-2);border-top:1px solid var(--ui-color-border)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
81
|
+
}
|
|
82
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmCard, decorators: [{
|
|
83
|
+
type: Component,
|
|
84
|
+
args: [{ selector: 'llm-card', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: `<ng-content />`, host: {
|
|
85
|
+
'[class]': 'hostClasses()',
|
|
86
|
+
}, styles: ["llm-card{display:block;border-radius:var(--ui-radius-xl);background-color:var(--ui-color-surface);overflow:hidden}llm-card.variant-elevated{box-shadow:var(--ui-shadow-md);border:1px solid var(--ui-color-border)}llm-card.variant-outlined{border:1px solid var(--ui-color-border);background-color:var(--ui-color-surface)}llm-card.variant-flat{background-color:var(--ui-color-surface-sunken)}llm-card.padding-none llm-card-header,llm-card.padding-none llm-card-content,llm-card.padding-none llm-card-footer{padding:0}llm-card.padding-sm llm-card-header,llm-card.padding-sm llm-card-content,llm-card.padding-sm llm-card-footer{padding:var(--ui-spacing-3)}llm-card.padding-md llm-card-header,llm-card.padding-md llm-card-content,llm-card.padding-md llm-card-footer{padding:var(--ui-spacing-4)}llm-card.padding-lg llm-card-header,llm-card.padding-lg llm-card-content,llm-card.padding-lg llm-card-footer{padding:var(--ui-spacing-6)}llm-card-header{display:block;font-size:var(--ui-font-size-lg);font-weight:var(--ui-font-weight-semibold);color:var(--ui-color-text);border-bottom:1px solid var(--ui-color-border);letter-spacing:var(--ui-letter-spacing-tight)}llm-card-content{display:block;color:var(--ui-color-text);line-height:var(--ui-line-height-normal)}llm-card-footer{display:flex;align-items:center;gap:var(--ui-spacing-2);border-top:1px solid var(--ui-color-border)}\n"] }]
|
|
87
|
+
}], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], padding: [{ type: i0.Input, args: [{ isSignal: true, alias: "padding", required: false }] }] } });
|
|
88
|
+
/**
|
|
89
|
+
* Header slot for `llm-card`. Renders above the main content with a bottom separator.
|
|
90
|
+
*
|
|
91
|
+
* Usage:
|
|
92
|
+
* ```html
|
|
93
|
+
* <llm-card-header>Card Title</llm-card-header>
|
|
94
|
+
* ```
|
|
95
|
+
*/
|
|
96
|
+
class LlmCardHeader {
|
|
97
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmCardHeader, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
98
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.4", type: LlmCardHeader, isStandalone: true, selector: "llm-card-header", ngImport: i0, template: `<ng-content />`, isInline: true, styles: ["llm-card{display:block;border-radius:var(--ui-radius-xl);background-color:var(--ui-color-surface);overflow:hidden}llm-card.variant-elevated{box-shadow:var(--ui-shadow-md);border:1px solid var(--ui-color-border)}llm-card.variant-outlined{border:1px solid var(--ui-color-border);background-color:var(--ui-color-surface)}llm-card.variant-flat{background-color:var(--ui-color-surface-sunken)}llm-card.padding-none llm-card-header,llm-card.padding-none llm-card-content,llm-card.padding-none llm-card-footer{padding:0}llm-card.padding-sm llm-card-header,llm-card.padding-sm llm-card-content,llm-card.padding-sm llm-card-footer{padding:var(--ui-spacing-3)}llm-card.padding-md llm-card-header,llm-card.padding-md llm-card-content,llm-card.padding-md llm-card-footer{padding:var(--ui-spacing-4)}llm-card.padding-lg llm-card-header,llm-card.padding-lg llm-card-content,llm-card.padding-lg llm-card-footer{padding:var(--ui-spacing-6)}llm-card-header{display:block;font-size:var(--ui-font-size-lg);font-weight:var(--ui-font-weight-semibold);color:var(--ui-color-text);border-bottom:1px solid var(--ui-color-border);letter-spacing:var(--ui-letter-spacing-tight)}llm-card-content{display:block;color:var(--ui-color-text);line-height:var(--ui-line-height-normal)}llm-card-footer{display:flex;align-items:center;gap:var(--ui-spacing-2);border-top:1px solid var(--ui-color-border)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
99
|
+
}
|
|
100
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmCardHeader, decorators: [{
|
|
101
|
+
type: Component,
|
|
102
|
+
args: [{ selector: 'llm-card-header', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: `<ng-content />`, styles: ["llm-card{display:block;border-radius:var(--ui-radius-xl);background-color:var(--ui-color-surface);overflow:hidden}llm-card.variant-elevated{box-shadow:var(--ui-shadow-md);border:1px solid var(--ui-color-border)}llm-card.variant-outlined{border:1px solid var(--ui-color-border);background-color:var(--ui-color-surface)}llm-card.variant-flat{background-color:var(--ui-color-surface-sunken)}llm-card.padding-none llm-card-header,llm-card.padding-none llm-card-content,llm-card.padding-none llm-card-footer{padding:0}llm-card.padding-sm llm-card-header,llm-card.padding-sm llm-card-content,llm-card.padding-sm llm-card-footer{padding:var(--ui-spacing-3)}llm-card.padding-md llm-card-header,llm-card.padding-md llm-card-content,llm-card.padding-md llm-card-footer{padding:var(--ui-spacing-4)}llm-card.padding-lg llm-card-header,llm-card.padding-lg llm-card-content,llm-card.padding-lg llm-card-footer{padding:var(--ui-spacing-6)}llm-card-header{display:block;font-size:var(--ui-font-size-lg);font-weight:var(--ui-font-weight-semibold);color:var(--ui-color-text);border-bottom:1px solid var(--ui-color-border);letter-spacing:var(--ui-letter-spacing-tight)}llm-card-content{display:block;color:var(--ui-color-text);line-height:var(--ui-line-height-normal)}llm-card-footer{display:flex;align-items:center;gap:var(--ui-spacing-2);border-top:1px solid var(--ui-color-border)}\n"] }]
|
|
103
|
+
}] });
|
|
104
|
+
/**
|
|
105
|
+
* Content slot for `llm-card`. Primary content area of the card.
|
|
106
|
+
*
|
|
107
|
+
* Usage:
|
|
108
|
+
* ```html
|
|
109
|
+
* <llm-card-content>Body text here.</llm-card-content>
|
|
110
|
+
* ```
|
|
111
|
+
*/
|
|
112
|
+
class LlmCardContent {
|
|
113
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmCardContent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
114
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.4", type: LlmCardContent, isStandalone: true, selector: "llm-card-content", ngImport: i0, template: `<ng-content />`, isInline: true, styles: ["llm-card{display:block;border-radius:var(--ui-radius-xl);background-color:var(--ui-color-surface);overflow:hidden}llm-card.variant-elevated{box-shadow:var(--ui-shadow-md);border:1px solid var(--ui-color-border)}llm-card.variant-outlined{border:1px solid var(--ui-color-border);background-color:var(--ui-color-surface)}llm-card.variant-flat{background-color:var(--ui-color-surface-sunken)}llm-card.padding-none llm-card-header,llm-card.padding-none llm-card-content,llm-card.padding-none llm-card-footer{padding:0}llm-card.padding-sm llm-card-header,llm-card.padding-sm llm-card-content,llm-card.padding-sm llm-card-footer{padding:var(--ui-spacing-3)}llm-card.padding-md llm-card-header,llm-card.padding-md llm-card-content,llm-card.padding-md llm-card-footer{padding:var(--ui-spacing-4)}llm-card.padding-lg llm-card-header,llm-card.padding-lg llm-card-content,llm-card.padding-lg llm-card-footer{padding:var(--ui-spacing-6)}llm-card-header{display:block;font-size:var(--ui-font-size-lg);font-weight:var(--ui-font-weight-semibold);color:var(--ui-color-text);border-bottom:1px solid var(--ui-color-border);letter-spacing:var(--ui-letter-spacing-tight)}llm-card-content{display:block;color:var(--ui-color-text);line-height:var(--ui-line-height-normal)}llm-card-footer{display:flex;align-items:center;gap:var(--ui-spacing-2);border-top:1px solid var(--ui-color-border)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
115
|
+
}
|
|
116
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmCardContent, decorators: [{
|
|
117
|
+
type: Component,
|
|
118
|
+
args: [{ selector: 'llm-card-content', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: `<ng-content />`, styles: ["llm-card{display:block;border-radius:var(--ui-radius-xl);background-color:var(--ui-color-surface);overflow:hidden}llm-card.variant-elevated{box-shadow:var(--ui-shadow-md);border:1px solid var(--ui-color-border)}llm-card.variant-outlined{border:1px solid var(--ui-color-border);background-color:var(--ui-color-surface)}llm-card.variant-flat{background-color:var(--ui-color-surface-sunken)}llm-card.padding-none llm-card-header,llm-card.padding-none llm-card-content,llm-card.padding-none llm-card-footer{padding:0}llm-card.padding-sm llm-card-header,llm-card.padding-sm llm-card-content,llm-card.padding-sm llm-card-footer{padding:var(--ui-spacing-3)}llm-card.padding-md llm-card-header,llm-card.padding-md llm-card-content,llm-card.padding-md llm-card-footer{padding:var(--ui-spacing-4)}llm-card.padding-lg llm-card-header,llm-card.padding-lg llm-card-content,llm-card.padding-lg llm-card-footer{padding:var(--ui-spacing-6)}llm-card-header{display:block;font-size:var(--ui-font-size-lg);font-weight:var(--ui-font-weight-semibold);color:var(--ui-color-text);border-bottom:1px solid var(--ui-color-border);letter-spacing:var(--ui-letter-spacing-tight)}llm-card-content{display:block;color:var(--ui-color-text);line-height:var(--ui-line-height-normal)}llm-card-footer{display:flex;align-items:center;gap:var(--ui-spacing-2);border-top:1px solid var(--ui-color-border)}\n"] }]
|
|
119
|
+
}] });
|
|
120
|
+
/**
|
|
121
|
+
* Footer slot for `llm-card`. Renders below the main content, typically holds actions.
|
|
122
|
+
*
|
|
123
|
+
* Usage:
|
|
124
|
+
* ```html
|
|
125
|
+
* <llm-card-footer>
|
|
126
|
+
* <llm-button variant="primary">Save</llm-button>
|
|
127
|
+
* </llm-card-footer>
|
|
128
|
+
* ```
|
|
129
|
+
*/
|
|
130
|
+
class LlmCardFooter {
|
|
131
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmCardFooter, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
132
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.4", type: LlmCardFooter, isStandalone: true, selector: "llm-card-footer", ngImport: i0, template: `<ng-content />`, isInline: true, styles: ["llm-card{display:block;border-radius:var(--ui-radius-xl);background-color:var(--ui-color-surface);overflow:hidden}llm-card.variant-elevated{box-shadow:var(--ui-shadow-md);border:1px solid var(--ui-color-border)}llm-card.variant-outlined{border:1px solid var(--ui-color-border);background-color:var(--ui-color-surface)}llm-card.variant-flat{background-color:var(--ui-color-surface-sunken)}llm-card.padding-none llm-card-header,llm-card.padding-none llm-card-content,llm-card.padding-none llm-card-footer{padding:0}llm-card.padding-sm llm-card-header,llm-card.padding-sm llm-card-content,llm-card.padding-sm llm-card-footer{padding:var(--ui-spacing-3)}llm-card.padding-md llm-card-header,llm-card.padding-md llm-card-content,llm-card.padding-md llm-card-footer{padding:var(--ui-spacing-4)}llm-card.padding-lg llm-card-header,llm-card.padding-lg llm-card-content,llm-card.padding-lg llm-card-footer{padding:var(--ui-spacing-6)}llm-card-header{display:block;font-size:var(--ui-font-size-lg);font-weight:var(--ui-font-weight-semibold);color:var(--ui-color-text);border-bottom:1px solid var(--ui-color-border);letter-spacing:var(--ui-letter-spacing-tight)}llm-card-content{display:block;color:var(--ui-color-text);line-height:var(--ui-line-height-normal)}llm-card-footer{display:flex;align-items:center;gap:var(--ui-spacing-2);border-top:1px solid var(--ui-color-border)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
133
|
+
}
|
|
134
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmCardFooter, decorators: [{
|
|
135
|
+
type: Component,
|
|
136
|
+
args: [{ selector: 'llm-card-footer', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: `<ng-content />`, styles: ["llm-card{display:block;border-radius:var(--ui-radius-xl);background-color:var(--ui-color-surface);overflow:hidden}llm-card.variant-elevated{box-shadow:var(--ui-shadow-md);border:1px solid var(--ui-color-border)}llm-card.variant-outlined{border:1px solid var(--ui-color-border);background-color:var(--ui-color-surface)}llm-card.variant-flat{background-color:var(--ui-color-surface-sunken)}llm-card.padding-none llm-card-header,llm-card.padding-none llm-card-content,llm-card.padding-none llm-card-footer{padding:0}llm-card.padding-sm llm-card-header,llm-card.padding-sm llm-card-content,llm-card.padding-sm llm-card-footer{padding:var(--ui-spacing-3)}llm-card.padding-md llm-card-header,llm-card.padding-md llm-card-content,llm-card.padding-md llm-card-footer{padding:var(--ui-spacing-4)}llm-card.padding-lg llm-card-header,llm-card.padding-lg llm-card-content,llm-card.padding-lg llm-card-footer{padding:var(--ui-spacing-6)}llm-card-header{display:block;font-size:var(--ui-font-size-lg);font-weight:var(--ui-font-weight-semibold);color:var(--ui-color-text);border-bottom:1px solid var(--ui-color-border);letter-spacing:var(--ui-letter-spacing-tight)}llm-card-content{display:block;color:var(--ui-color-text);line-height:var(--ui-line-height-normal)}llm-card-footer{display:flex;align-items:center;gap:var(--ui-spacing-2);border-top:1px solid var(--ui-color-border)}\n"] }]
|
|
137
|
+
}] });
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Inline status badge for labeling items with semantic color variants.
|
|
141
|
+
*
|
|
142
|
+
* Usage:
|
|
143
|
+
* ```html
|
|
144
|
+
* <llm-badge variant="success">Active</llm-badge>
|
|
145
|
+
* <llm-badge variant="danger" size="sm">Error</llm-badge>
|
|
146
|
+
* <llm-badge variant="warning">Pending</llm-badge>
|
|
147
|
+
* ```
|
|
148
|
+
*/
|
|
149
|
+
class LlmBadge {
|
|
150
|
+
/** Semantic color variant of the badge. */
|
|
151
|
+
variant = input('default', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
|
|
152
|
+
/** Size of the badge. */
|
|
153
|
+
size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
154
|
+
hostClasses = computed(() => `variant-${this.variant()} size-${this.size()}`, ...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
|
|
155
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmBadge, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
156
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.4", type: LlmBadge, isStandalone: true, selector: "llm-badge", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "status" }, properties: { "class": "hostClasses()" } }, ngImport: i0, template: `<ng-content />`, isInline: true, styles: [":host{display:inline-flex;align-items:center;justify-content:center;border-radius:var(--ui-radius-full);font-family:var(--ui-font-family);font-weight:var(--ui-font-weight-semibold);line-height:var(--ui-line-height-tight);white-space:nowrap;letter-spacing:.01em}:host(.size-sm){padding:.1875rem var(--ui-spacing-2);font-size:var(--ui-font-size-xs)}:host(.size-md){padding:.3125rem var(--ui-spacing-3);font-size:var(--ui-font-size-sm)}:host(.variant-default){background-color:var(--ui-color-surface-sunken);color:var(--ui-color-text-muted);border:1px solid var(--ui-color-border)}:host(.variant-success){background-color:color-mix(in srgb,var(--ui-color-success) 12%,transparent);color:var(--ui-color-success);border:1px solid color-mix(in srgb,var(--ui-color-success) 25%,transparent)}:host(.variant-warning){background-color:color-mix(in srgb,var(--ui-color-warning) 12%,transparent);color:var(--ui-color-warning);border:1px solid color-mix(in srgb,var(--ui-color-warning) 25%,transparent)}:host(.variant-danger){background-color:color-mix(in srgb,var(--ui-color-danger) 12%,transparent);color:var(--ui-color-danger);border:1px solid color-mix(in srgb,var(--ui-color-danger) 25%,transparent)}:host(.variant-info){background-color:color-mix(in srgb,var(--ui-color-info) 12%,transparent);color:var(--ui-color-info);border:1px solid color-mix(in srgb,var(--ui-color-info) 25%,transparent)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
157
|
+
}
|
|
158
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmBadge, decorators: [{
|
|
159
|
+
type: Component,
|
|
160
|
+
args: [{ selector: 'llm-badge', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: `<ng-content />`, host: {
|
|
161
|
+
'[class]': 'hostClasses()',
|
|
162
|
+
role: 'status',
|
|
163
|
+
}, styles: [":host{display:inline-flex;align-items:center;justify-content:center;border-radius:var(--ui-radius-full);font-family:var(--ui-font-family);font-weight:var(--ui-font-weight-semibold);line-height:var(--ui-line-height-tight);white-space:nowrap;letter-spacing:.01em}:host(.size-sm){padding:.1875rem var(--ui-spacing-2);font-size:var(--ui-font-size-xs)}:host(.size-md){padding:.3125rem var(--ui-spacing-3);font-size:var(--ui-font-size-sm)}:host(.variant-default){background-color:var(--ui-color-surface-sunken);color:var(--ui-color-text-muted);border:1px solid var(--ui-color-border)}:host(.variant-success){background-color:color-mix(in srgb,var(--ui-color-success) 12%,transparent);color:var(--ui-color-success);border:1px solid color-mix(in srgb,var(--ui-color-success) 25%,transparent)}:host(.variant-warning){background-color:color-mix(in srgb,var(--ui-color-warning) 12%,transparent);color:var(--ui-color-warning);border:1px solid color-mix(in srgb,var(--ui-color-warning) 25%,transparent)}:host(.variant-danger){background-color:color-mix(in srgb,var(--ui-color-danger) 12%,transparent);color:var(--ui-color-danger);border:1px solid color-mix(in srgb,var(--ui-color-danger) 25%,transparent)}:host(.variant-info){background-color:color-mix(in srgb,var(--ui-color-info) 12%,transparent);color:var(--ui-color-info);border:1px solid color-mix(in srgb,var(--ui-color-info) 25%,transparent)}\n"] }]
|
|
164
|
+
}], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }] } });
|
|
165
|
+
|
|
166
|
+
let nextId$a = 0;
|
|
167
|
+
/**
|
|
168
|
+
* Accessible text input component for use with Angular Signal Forms.
|
|
169
|
+
*
|
|
170
|
+
* Usage:
|
|
171
|
+
* ```html
|
|
172
|
+
* <llm-input type="email" placeholder="you@example.com" [(value)]="email" />
|
|
173
|
+
* <llm-input [formField]="loginForm.email" placeholder="Email" />
|
|
174
|
+
* ```
|
|
175
|
+
*/
|
|
176
|
+
class LlmInput {
|
|
177
|
+
/** The current input value. Bound by [formField] directive. Supports [(value)] two-way binding. */
|
|
178
|
+
value = model('', ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
179
|
+
/** The type of input field. */
|
|
180
|
+
type = input('text', ...(ngDevMode ? [{ debugName: "type" }] : /* istanbul ignore next */ []));
|
|
181
|
+
/** Placeholder text shown when the input is empty. */
|
|
182
|
+
placeholder = input('', ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
|
|
183
|
+
/** Whether the input is disabled. Bound by [formField] directive. */
|
|
184
|
+
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
|
|
185
|
+
/** Whether the input is read-only. Bound by [formField] directive. */
|
|
186
|
+
readonly = input(false, ...(ngDevMode ? [{ debugName: "readonly" }] : /* istanbul ignore next */ []));
|
|
187
|
+
/** Whether the input has validation errors. Bound by [formField] directive. */
|
|
188
|
+
invalid = input(false, ...(ngDevMode ? [{ debugName: "invalid" }] : /* istanbul ignore next */ []));
|
|
189
|
+
/** Validation errors from the form system. Bound by [formField] directive. */
|
|
190
|
+
errors = input([], ...(ngDevMode ? [{ debugName: "errors" }] : /* istanbul ignore next */ []));
|
|
191
|
+
/** Whether the user has interacted with the input. Bound by [formField] directive. */
|
|
192
|
+
touched = model(false, ...(ngDevMode ? [{ debugName: "touched" }] : /* istanbul ignore next */ []));
|
|
193
|
+
/** Whether the input is required. Bound by [formField] directive. */
|
|
194
|
+
required = input(false, ...(ngDevMode ? [{ debugName: "required" }] : /* istanbul ignore next */ []));
|
|
195
|
+
/** The input's name attribute. Bound by [formField] directive. */
|
|
196
|
+
name = input('', ...(ngDevMode ? [{ debugName: "name" }] : /* istanbul ignore next */ []));
|
|
197
|
+
/** @internal */
|
|
198
|
+
errorId = `llm-input-errors-${nextId$a++}`;
|
|
199
|
+
/** @internal */
|
|
200
|
+
showErrors = computed(() => this.touched() && this.invalid() && this.errors().length > 0, ...(ngDevMode ? [{ debugName: "showErrors" }] : /* istanbul ignore next */ []));
|
|
201
|
+
/** @internal */
|
|
202
|
+
hostClasses = computed(() => {
|
|
203
|
+
const classes = [];
|
|
204
|
+
if (this.disabled())
|
|
205
|
+
classes.push('is-disabled');
|
|
206
|
+
if (this.invalid())
|
|
207
|
+
classes.push('is-invalid');
|
|
208
|
+
if (this.readonly())
|
|
209
|
+
classes.push('is-readonly');
|
|
210
|
+
if (this.touched())
|
|
211
|
+
classes.push('is-touched');
|
|
212
|
+
return classes.join(' ');
|
|
213
|
+
}, ...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
|
|
214
|
+
/** @internal */
|
|
215
|
+
onInput(event) {
|
|
216
|
+
const target = event.target;
|
|
217
|
+
this.value.set(target.value);
|
|
218
|
+
}
|
|
219
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmInput, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
220
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.4", type: LlmInput, isStandalone: true, selector: "llm-input", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, errors: { classPropertyName: "errors", publicName: "errors", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", touched: "touchedChange" }, host: { properties: { "class": "hostClasses()" } }, ngImport: i0, template: `
|
|
221
|
+
<input
|
|
222
|
+
[type]="type()"
|
|
223
|
+
[value]="value()"
|
|
224
|
+
(input)="onInput($event)"
|
|
225
|
+
(blur)="touched.set(true)"
|
|
226
|
+
[disabled]="disabled()"
|
|
227
|
+
[readOnly]="readonly()"
|
|
228
|
+
[placeholder]="placeholder()"
|
|
229
|
+
[attr.name]="name() || null"
|
|
230
|
+
[attr.aria-invalid]="invalid() || null"
|
|
231
|
+
[attr.aria-required]="required() || null"
|
|
232
|
+
[attr.aria-describedby]="showErrors() ? errorId : null"
|
|
233
|
+
/>
|
|
234
|
+
@if (showErrors()) {
|
|
235
|
+
<div class="errors" [id]="errorId" aria-live="polite">
|
|
236
|
+
@for (error of errors(); track error.kind) {
|
|
237
|
+
<p class="error-message">{{ error.message }}</p>
|
|
238
|
+
}
|
|
239
|
+
</div>
|
|
240
|
+
}
|
|
241
|
+
`, isInline: true, styles: [":host{display:block;font-family:var(--ui-font-family);font-size:var(--ui-font-size-md)}input{display:block;width:100%;padding:.625rem var(--ui-spacing-3);font-size:inherit;font-family:inherit;line-height:var(--ui-line-height-normal);color:var(--ui-color-text);background-color:var(--ui-color-input-bg);border:1px solid var(--ui-color-input-border);border-radius:var(--ui-radius-md);box-shadow:inset 0 1px 2px #0000000a;transition:border-color var(--ui-transition-fast),box-shadow var(--ui-transition-fast),background-color var(--ui-transition-fast);outline:none;box-sizing:border-box}input::placeholder{color:var(--ui-color-placeholder)}input:hover:not(:disabled):not(:read-only){border-color:var(--ui-color-input-border-hover)}input:focus{border-color:var(--ui-color-input-border-focus);background-color:var(--ui-color-input-bg-focus);box-shadow:var(--ui-focus-ring)}:host(.is-invalid) input{border-color:var(--ui-color-input-border-invalid)}:host(.is-invalid) input:focus{border-color:var(--ui-color-input-border-invalid);box-shadow:0 0 0 2px var(--ui-color-surface),0 0 0 4px var(--ui-color-danger)}:host(.is-disabled){opacity:var(--ui-opacity-disabled);cursor:not-allowed}:host(.is-disabled) input{cursor:not-allowed}:host(.is-readonly) input{background-color:var(--ui-color-surface-sunken);cursor:default;box-shadow:none}.errors{margin-top:var(--ui-spacing-1)}.error-message{margin:0;font-size:var(--ui-font-size-sm);color:var(--ui-color-error-text);line-height:var(--ui-line-height-normal)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
242
|
+
}
|
|
243
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmInput, decorators: [{
|
|
244
|
+
type: Component,
|
|
245
|
+
args: [{ selector: 'llm-input', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: `
|
|
246
|
+
<input
|
|
247
|
+
[type]="type()"
|
|
248
|
+
[value]="value()"
|
|
249
|
+
(input)="onInput($event)"
|
|
250
|
+
(blur)="touched.set(true)"
|
|
251
|
+
[disabled]="disabled()"
|
|
252
|
+
[readOnly]="readonly()"
|
|
253
|
+
[placeholder]="placeholder()"
|
|
254
|
+
[attr.name]="name() || null"
|
|
255
|
+
[attr.aria-invalid]="invalid() || null"
|
|
256
|
+
[attr.aria-required]="required() || null"
|
|
257
|
+
[attr.aria-describedby]="showErrors() ? errorId : null"
|
|
258
|
+
/>
|
|
259
|
+
@if (showErrors()) {
|
|
260
|
+
<div class="errors" [id]="errorId" aria-live="polite">
|
|
261
|
+
@for (error of errors(); track error.kind) {
|
|
262
|
+
<p class="error-message">{{ error.message }}</p>
|
|
263
|
+
}
|
|
264
|
+
</div>
|
|
265
|
+
}
|
|
266
|
+
`, host: {
|
|
267
|
+
'[class]': 'hostClasses()',
|
|
268
|
+
}, styles: [":host{display:block;font-family:var(--ui-font-family);font-size:var(--ui-font-size-md)}input{display:block;width:100%;padding:.625rem var(--ui-spacing-3);font-size:inherit;font-family:inherit;line-height:var(--ui-line-height-normal);color:var(--ui-color-text);background-color:var(--ui-color-input-bg);border:1px solid var(--ui-color-input-border);border-radius:var(--ui-radius-md);box-shadow:inset 0 1px 2px #0000000a;transition:border-color var(--ui-transition-fast),box-shadow var(--ui-transition-fast),background-color var(--ui-transition-fast);outline:none;box-sizing:border-box}input::placeholder{color:var(--ui-color-placeholder)}input:hover:not(:disabled):not(:read-only){border-color:var(--ui-color-input-border-hover)}input:focus{border-color:var(--ui-color-input-border-focus);background-color:var(--ui-color-input-bg-focus);box-shadow:var(--ui-focus-ring)}:host(.is-invalid) input{border-color:var(--ui-color-input-border-invalid)}:host(.is-invalid) input:focus{border-color:var(--ui-color-input-border-invalid);box-shadow:0 0 0 2px var(--ui-color-surface),0 0 0 4px var(--ui-color-danger)}:host(.is-disabled){opacity:var(--ui-opacity-disabled);cursor:not-allowed}:host(.is-disabled) input{cursor:not-allowed}:host(.is-readonly) input{background-color:var(--ui-color-surface-sunken);cursor:default;box-shadow:none}.errors{margin-top:var(--ui-spacing-1)}.error-message{margin:0;font-size:var(--ui-font-size-sm);color:var(--ui-color-error-text);line-height:var(--ui-line-height-normal)}\n"] }]
|
|
269
|
+
}], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], errors: [{ type: i0.Input, args: [{ isSignal: true, alias: "errors", required: false }] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }, { type: i0.Output, args: ["touchedChange"] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }] } });
|
|
270
|
+
|
|
271
|
+
let nextId$9 = 0;
|
|
272
|
+
/**
|
|
273
|
+
* Accessible multiline text input component for use with Angular Signal Forms.
|
|
274
|
+
*
|
|
275
|
+
* Usage:
|
|
276
|
+
* ```html
|
|
277
|
+
* <llm-textarea placeholder="Enter a description" [(value)]="description" />
|
|
278
|
+
* <llm-textarea [formField]="form.bio" [rows]="4" />
|
|
279
|
+
* ```
|
|
280
|
+
*/
|
|
281
|
+
class LlmTextarea {
|
|
282
|
+
/** The current textarea value. Supports [(value)] two-way binding. */
|
|
283
|
+
value = model('', ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
284
|
+
/** Number of visible text rows. */
|
|
285
|
+
rows = input(3, ...(ngDevMode ? [{ debugName: "rows" }] : /* istanbul ignore next */ []));
|
|
286
|
+
/** Placeholder text shown when the textarea is empty. */
|
|
287
|
+
placeholder = input('', ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
|
|
288
|
+
/** Whether the textarea is disabled. Bound by [formField] directive. */
|
|
289
|
+
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
|
|
290
|
+
/** Whether the textarea is read-only. Bound by [formField] directive. */
|
|
291
|
+
readonly = input(false, ...(ngDevMode ? [{ debugName: "readonly" }] : /* istanbul ignore next */ []));
|
|
292
|
+
/** Whether the textarea has validation errors. Bound by [formField] directive. */
|
|
293
|
+
invalid = input(false, ...(ngDevMode ? [{ debugName: "invalid" }] : /* istanbul ignore next */ []));
|
|
294
|
+
/** Validation errors from the form system. Bound by [formField] directive. */
|
|
295
|
+
errors = input([], ...(ngDevMode ? [{ debugName: "errors" }] : /* istanbul ignore next */ []));
|
|
296
|
+
/** Whether the user has interacted with the textarea. Bound by [formField] directive. */
|
|
297
|
+
touched = model(false, ...(ngDevMode ? [{ debugName: "touched" }] : /* istanbul ignore next */ []));
|
|
298
|
+
/** Whether the textarea is required. Bound by [formField] directive. */
|
|
299
|
+
required = input(false, ...(ngDevMode ? [{ debugName: "required" }] : /* istanbul ignore next */ []));
|
|
300
|
+
/** The textarea's name attribute. Bound by [formField] directive. */
|
|
301
|
+
name = input('', ...(ngDevMode ? [{ debugName: "name" }] : /* istanbul ignore next */ []));
|
|
302
|
+
/** Whether to auto-resize the textarea height to fit its content. */
|
|
303
|
+
autoResize = input(false, ...(ngDevMode ? [{ debugName: "autoResize" }] : /* istanbul ignore next */ []));
|
|
304
|
+
/** @internal */
|
|
305
|
+
errorId = `llm-textarea-errors-${nextId$9++}`;
|
|
306
|
+
/** @internal */
|
|
307
|
+
showErrors = computed(() => this.touched() && this.invalid() && this.errors().length > 0, ...(ngDevMode ? [{ debugName: "showErrors" }] : /* istanbul ignore next */ []));
|
|
308
|
+
/** @internal */
|
|
309
|
+
hostClasses = computed(() => {
|
|
310
|
+
const classes = [];
|
|
311
|
+
if (this.disabled())
|
|
312
|
+
classes.push('is-disabled');
|
|
313
|
+
if (this.invalid())
|
|
314
|
+
classes.push('is-invalid');
|
|
315
|
+
if (this.readonly())
|
|
316
|
+
classes.push('is-readonly');
|
|
317
|
+
if (this.touched())
|
|
318
|
+
classes.push('is-touched');
|
|
319
|
+
if (this.autoResize())
|
|
320
|
+
classes.push('is-auto-resize');
|
|
321
|
+
return classes.join(' ');
|
|
322
|
+
}, ...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
|
|
323
|
+
/** @internal */
|
|
324
|
+
onInput(event) {
|
|
325
|
+
const target = event.target;
|
|
326
|
+
this.value.set(target.value);
|
|
327
|
+
}
|
|
328
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmTextarea, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
329
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.4", type: LlmTextarea, isStandalone: true, selector: "llm-textarea", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, errors: { classPropertyName: "errors", publicName: "errors", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, autoResize: { classPropertyName: "autoResize", publicName: "autoResize", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", touched: "touchedChange" }, host: { properties: { "class": "hostClasses()" } }, ngImport: i0, template: `
|
|
330
|
+
<textarea
|
|
331
|
+
[value]="value()"
|
|
332
|
+
(input)="onInput($event)"
|
|
333
|
+
(blur)="touched.set(true)"
|
|
334
|
+
[disabled]="disabled()"
|
|
335
|
+
[readOnly]="readonly()"
|
|
336
|
+
[placeholder]="placeholder()"
|
|
337
|
+
[rows]="rows()"
|
|
338
|
+
[attr.name]="name() || null"
|
|
339
|
+
[attr.aria-invalid]="invalid() || null"
|
|
340
|
+
[attr.aria-required]="required() || null"
|
|
341
|
+
[attr.aria-describedby]="showErrors() ? errorId : null"
|
|
342
|
+
[cdkTextareaAutosize]="autoResize()"
|
|
343
|
+
[cdkAutosizeMinRows]="rows()"
|
|
344
|
+
></textarea>
|
|
345
|
+
@if (showErrors()) {
|
|
346
|
+
<div class="errors" [id]="errorId" aria-live="polite">
|
|
347
|
+
@for (error of errors(); track error.kind) {
|
|
348
|
+
<p class="error-message">{{ error.message }}</p>
|
|
349
|
+
}
|
|
350
|
+
</div>
|
|
351
|
+
}
|
|
352
|
+
`, isInline: true, styles: [":host{display:block;font-family:var(--ui-font-family);font-size:var(--ui-font-size-md)}textarea{display:block;width:100%;padding:.625rem var(--ui-spacing-3);font-size:inherit;font-family:inherit;line-height:var(--ui-line-height-normal);color:var(--ui-color-text);background-color:var(--ui-color-input-bg);border:1px solid var(--ui-color-input-border);border-radius:var(--ui-radius-md);box-shadow:inset 0 1px 2px #0000000a;transition:border-color var(--ui-transition-fast),box-shadow var(--ui-transition-fast),background-color var(--ui-transition-fast);outline:none;box-sizing:border-box;resize:vertical;min-height:80px}textarea::placeholder{color:var(--ui-color-placeholder)}textarea:hover:not(:disabled):not(:read-only){border-color:var(--ui-color-input-border-hover)}textarea:focus{border-color:var(--ui-color-input-border-focus);background-color:var(--ui-color-input-bg-focus);box-shadow:var(--ui-focus-ring)}:host(.is-invalid) textarea{border-color:var(--ui-color-input-border-invalid)}:host(.is-invalid) textarea:focus{border-color:var(--ui-color-input-border-invalid);box-shadow:0 0 0 2px var(--ui-color-surface),0 0 0 4px var(--ui-color-danger)}:host(.is-disabled){opacity:var(--ui-opacity-disabled);cursor:not-allowed}:host(.is-disabled) textarea{cursor:not-allowed}:host(.is-readonly) textarea{background-color:var(--ui-color-surface-sunken);cursor:default;box-shadow:none}:host(.is-auto-resize) textarea{resize:none;overflow:hidden}.errors{margin-top:var(--ui-spacing-1)}.error-message{margin:0;font-size:var(--ui-font-size-sm);color:var(--ui-color-error-text);line-height:var(--ui-line-height-normal)}\n"], dependencies: [{ kind: "ngmodule", type: TextFieldModule }, { kind: "directive", type: i1.CdkTextareaAutosize, selector: "textarea[cdkTextareaAutosize]", inputs: ["cdkAutosizeMinRows", "cdkAutosizeMaxRows", "cdkTextareaAutosize", "placeholder"], exportAs: ["cdkTextareaAutosize"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
353
|
+
}
|
|
354
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmTextarea, decorators: [{
|
|
355
|
+
type: Component,
|
|
356
|
+
args: [{ selector: 'llm-textarea', standalone: true, imports: [TextFieldModule], changeDetection: ChangeDetectionStrategy.OnPush, template: `
|
|
357
|
+
<textarea
|
|
358
|
+
[value]="value()"
|
|
359
|
+
(input)="onInput($event)"
|
|
360
|
+
(blur)="touched.set(true)"
|
|
361
|
+
[disabled]="disabled()"
|
|
362
|
+
[readOnly]="readonly()"
|
|
363
|
+
[placeholder]="placeholder()"
|
|
364
|
+
[rows]="rows()"
|
|
365
|
+
[attr.name]="name() || null"
|
|
366
|
+
[attr.aria-invalid]="invalid() || null"
|
|
367
|
+
[attr.aria-required]="required() || null"
|
|
368
|
+
[attr.aria-describedby]="showErrors() ? errorId : null"
|
|
369
|
+
[cdkTextareaAutosize]="autoResize()"
|
|
370
|
+
[cdkAutosizeMinRows]="rows()"
|
|
371
|
+
></textarea>
|
|
372
|
+
@if (showErrors()) {
|
|
373
|
+
<div class="errors" [id]="errorId" aria-live="polite">
|
|
374
|
+
@for (error of errors(); track error.kind) {
|
|
375
|
+
<p class="error-message">{{ error.message }}</p>
|
|
376
|
+
}
|
|
377
|
+
</div>
|
|
378
|
+
}
|
|
379
|
+
`, host: {
|
|
380
|
+
'[class]': 'hostClasses()',
|
|
381
|
+
}, styles: [":host{display:block;font-family:var(--ui-font-family);font-size:var(--ui-font-size-md)}textarea{display:block;width:100%;padding:.625rem var(--ui-spacing-3);font-size:inherit;font-family:inherit;line-height:var(--ui-line-height-normal);color:var(--ui-color-text);background-color:var(--ui-color-input-bg);border:1px solid var(--ui-color-input-border);border-radius:var(--ui-radius-md);box-shadow:inset 0 1px 2px #0000000a;transition:border-color var(--ui-transition-fast),box-shadow var(--ui-transition-fast),background-color var(--ui-transition-fast);outline:none;box-sizing:border-box;resize:vertical;min-height:80px}textarea::placeholder{color:var(--ui-color-placeholder)}textarea:hover:not(:disabled):not(:read-only){border-color:var(--ui-color-input-border-hover)}textarea:focus{border-color:var(--ui-color-input-border-focus);background-color:var(--ui-color-input-bg-focus);box-shadow:var(--ui-focus-ring)}:host(.is-invalid) textarea{border-color:var(--ui-color-input-border-invalid)}:host(.is-invalid) textarea:focus{border-color:var(--ui-color-input-border-invalid);box-shadow:0 0 0 2px var(--ui-color-surface),0 0 0 4px var(--ui-color-danger)}:host(.is-disabled){opacity:var(--ui-opacity-disabled);cursor:not-allowed}:host(.is-disabled) textarea{cursor:not-allowed}:host(.is-readonly) textarea{background-color:var(--ui-color-surface-sunken);cursor:default;box-shadow:none}:host(.is-auto-resize) textarea{resize:none;overflow:hidden}.errors{margin-top:var(--ui-spacing-1)}.error-message{margin:0;font-size:var(--ui-font-size-sm);color:var(--ui-color-error-text);line-height:var(--ui-line-height-normal)}\n"] }]
|
|
382
|
+
}], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], errors: [{ type: i0.Input, args: [{ isSignal: true, alias: "errors", required: false }] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }, { type: i0.Output, args: ["touchedChange"] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], autoResize: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoResize", required: false }] }] } });
|
|
383
|
+
|
|
384
|
+
let nextId$8 = 0;
|
|
385
|
+
/**
|
|
386
|
+
* Accessible checkbox component for use with Angular Signal Forms.
|
|
387
|
+
*
|
|
388
|
+
* Usage:
|
|
389
|
+
* ```html
|
|
390
|
+
* <llm-checkbox [(checked)]="accepted">I agree to the terms</llm-checkbox>
|
|
391
|
+
* <llm-checkbox [formField]="form.accepted">Accept</llm-checkbox>
|
|
392
|
+
* ```
|
|
393
|
+
*/
|
|
394
|
+
class LlmCheckbox {
|
|
395
|
+
/** The checked state. Bound by [formField] directive. Supports [(checked)] two-way binding. */
|
|
396
|
+
checked = model(false, ...(ngDevMode ? [{ debugName: "checked" }] : /* istanbul ignore next */ []));
|
|
397
|
+
/** Whether the user has interacted with the input. Bound by [formField] directive. */
|
|
398
|
+
touched = model(false, ...(ngDevMode ? [{ debugName: "touched" }] : /* istanbul ignore next */ []));
|
|
399
|
+
/** Tri-state indeterminate mode (e.g. "select all"). Set via DOM property. */
|
|
400
|
+
indeterminate = input(false, ...(ngDevMode ? [{ debugName: "indeterminate" }] : /* istanbul ignore next */ []));
|
|
401
|
+
/** Whether the checkbox is disabled. Bound by [formField] directive. */
|
|
402
|
+
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
|
|
403
|
+
/** Whether the checkbox has validation errors. Bound by [formField] directive. */
|
|
404
|
+
invalid = input(false, ...(ngDevMode ? [{ debugName: "invalid" }] : /* istanbul ignore next */ []));
|
|
405
|
+
/** Whether the checkbox is required. Bound by [formField] directive. */
|
|
406
|
+
required = input(false, ...(ngDevMode ? [{ debugName: "required" }] : /* istanbul ignore next */ []));
|
|
407
|
+
/** The input's name attribute. Bound by [formField] directive. */
|
|
408
|
+
name = input('', ...(ngDevMode ? [{ debugName: "name" }] : /* istanbul ignore next */ []));
|
|
409
|
+
/** Validation errors from the form system. Bound by [formField] directive. */
|
|
410
|
+
errors = input([], ...(ngDevMode ? [{ debugName: "errors" }] : /* istanbul ignore next */ []));
|
|
411
|
+
/** @internal */
|
|
412
|
+
inputId = `llm-checkbox-${nextId$8++}`;
|
|
413
|
+
/** @internal */
|
|
414
|
+
errorId = `llm-checkbox-errors-${nextId$8++}`;
|
|
415
|
+
/** @internal */
|
|
416
|
+
nativeInput = viewChild('nativeInput', ...(ngDevMode ? [{ debugName: "nativeInput" }] : /* istanbul ignore next */ []));
|
|
417
|
+
/** @internal */
|
|
418
|
+
showErrors = computed(() => this.touched() && this.invalid() && this.errors().length > 0, ...(ngDevMode ? [{ debugName: "showErrors" }] : /* istanbul ignore next */ []));
|
|
419
|
+
/** @internal */
|
|
420
|
+
hostClasses = computed(() => {
|
|
421
|
+
const classes = [];
|
|
422
|
+
if (this.checked())
|
|
423
|
+
classes.push('is-checked');
|
|
424
|
+
if (this.disabled())
|
|
425
|
+
classes.push('is-disabled');
|
|
426
|
+
if (this.invalid())
|
|
427
|
+
classes.push('is-invalid');
|
|
428
|
+
if (this.touched())
|
|
429
|
+
classes.push('is-touched');
|
|
430
|
+
return classes.join(' ');
|
|
431
|
+
}, ...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
|
|
432
|
+
constructor() {
|
|
433
|
+
effect(() => {
|
|
434
|
+
const el = this.nativeInput()?.nativeElement;
|
|
435
|
+
if (el) {
|
|
436
|
+
el.indeterminate = this.indeterminate();
|
|
437
|
+
}
|
|
438
|
+
});
|
|
439
|
+
}
|
|
440
|
+
/** @internal */
|
|
441
|
+
onChange(event) {
|
|
442
|
+
const target = event.target;
|
|
443
|
+
this.checked.set(target.checked);
|
|
444
|
+
}
|
|
445
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmCheckbox, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
446
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.4", type: LlmCheckbox, isStandalone: true, selector: "llm-checkbox", inputs: { checked: { classPropertyName: "checked", publicName: "checked", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null }, indeterminate: { classPropertyName: "indeterminate", publicName: "indeterminate", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, errors: { classPropertyName: "errors", publicName: "errors", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { checked: "checkedChange", touched: "touchedChange" }, host: { properties: { "class": "hostClasses()" } }, viewQueries: [{ propertyName: "nativeInput", first: true, predicate: ["nativeInput"], descendants: true, isSignal: true }], ngImport: i0, template: `
|
|
447
|
+
<label [attr.for]="inputId">
|
|
448
|
+
<input
|
|
449
|
+
#nativeInput
|
|
450
|
+
type="checkbox"
|
|
451
|
+
[id]="inputId"
|
|
452
|
+
[checked]="checked()"
|
|
453
|
+
(change)="onChange($event)"
|
|
454
|
+
(blur)="touched.set(true)"
|
|
455
|
+
[disabled]="disabled()"
|
|
456
|
+
[attr.name]="name() || null"
|
|
457
|
+
[attr.aria-invalid]="invalid() || null"
|
|
458
|
+
[attr.aria-required]="required() || null"
|
|
459
|
+
[attr.aria-describedby]="showErrors() ? errorId : null"
|
|
460
|
+
/>
|
|
461
|
+
<ng-content />
|
|
462
|
+
</label>
|
|
463
|
+
@if (showErrors()) {
|
|
464
|
+
<div class="errors" [id]="errorId" aria-live="polite">
|
|
465
|
+
@for (error of errors(); track error.kind) {
|
|
466
|
+
<p class="error-message">{{ error.message }}</p>
|
|
467
|
+
}
|
|
468
|
+
</div>
|
|
469
|
+
}
|
|
470
|
+
`, isInline: true, styles: [":host{display:block;font-family:var(--ui-font-family);font-size:var(--ui-font-size-md)}label{display:inline-flex;align-items:center;gap:var(--ui-spacing-2);cursor:pointer;-webkit-user-select:none;user-select:none;color:var(--ui-color-text);line-height:var(--ui-line-height-normal)}input[type=checkbox]{appearance:none;-webkit-appearance:none;flex-shrink:0;width:1.25rem;height:1.25rem;border:1.5px solid var(--ui-color-input-border);border-radius:var(--ui-radius-sm);background-color:var(--ui-color-input-bg);cursor:pointer;position:relative;transition:border-color var(--ui-transition-fast),background-color var(--ui-transition-fast),box-shadow var(--ui-transition-fast);outline:none}input[type=checkbox]:hover:not(:disabled){border-color:var(--ui-color-input-border-hover);background-color:var(--ui-color-primary-light)}input[type=checkbox]:focus-visible{box-shadow:var(--ui-focus-ring);border-color:var(--ui-color-input-border-focus)}input[type=checkbox]:checked{background-color:var(--ui-color-primary);border-color:var(--ui-color-primary)}input[type=checkbox]:checked:after{content:\"\";position:absolute;inset:0;margin:auto;width:.35rem;height:.6rem;border:2px solid var(--ui-color-on-primary);border-top:none;border-left:none;transform:rotate(45deg) translate(-1px,-1px);animation:llm-check-pop var(--ui-duration-normal) var(--ui-ease-spring)}input[type=checkbox]:indeterminate{background-color:var(--ui-color-primary);border-color:var(--ui-color-primary)}input[type=checkbox]:indeterminate:after{content:\"\";position:absolute;inset:0;margin:auto;width:.5rem;height:2px;background-color:var(--ui-color-on-primary);animation:llm-check-pop var(--ui-duration-normal) var(--ui-ease-spring)}:host(.is-invalid) input[type=checkbox]{border-color:var(--ui-color-input-border-invalid)}:host(.is-invalid) input[type=checkbox]:focus-visible{border-color:var(--ui-color-input-border-invalid);box-shadow:0 0 0 2px var(--ui-color-surface),0 0 0 4px var(--ui-color-danger)}:host(.is-disabled){opacity:var(--ui-opacity-disabled);cursor:not-allowed}:host(.is-disabled) label{cursor:not-allowed}:host(.is-disabled) input[type=checkbox]{cursor:not-allowed}.errors{margin-top:var(--ui-spacing-1)}.error-message{margin:0;font-size:var(--ui-font-size-sm);color:var(--ui-color-error-text);line-height:var(--ui-line-height-normal)}@keyframes llm-check-pop{0%{transform:rotate(45deg) translate(-1px,-1px) scale(0)}60%{transform:rotate(45deg) translate(-1px,-1px) scale(1.15)}to{transform:rotate(45deg) translate(-1px,-1px) scale(1)}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
471
|
+
}
|
|
472
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmCheckbox, decorators: [{
|
|
473
|
+
type: Component,
|
|
474
|
+
args: [{ selector: 'llm-checkbox', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: `
|
|
475
|
+
<label [attr.for]="inputId">
|
|
476
|
+
<input
|
|
477
|
+
#nativeInput
|
|
478
|
+
type="checkbox"
|
|
479
|
+
[id]="inputId"
|
|
480
|
+
[checked]="checked()"
|
|
481
|
+
(change)="onChange($event)"
|
|
482
|
+
(blur)="touched.set(true)"
|
|
483
|
+
[disabled]="disabled()"
|
|
484
|
+
[attr.name]="name() || null"
|
|
485
|
+
[attr.aria-invalid]="invalid() || null"
|
|
486
|
+
[attr.aria-required]="required() || null"
|
|
487
|
+
[attr.aria-describedby]="showErrors() ? errorId : null"
|
|
488
|
+
/>
|
|
489
|
+
<ng-content />
|
|
490
|
+
</label>
|
|
491
|
+
@if (showErrors()) {
|
|
492
|
+
<div class="errors" [id]="errorId" aria-live="polite">
|
|
493
|
+
@for (error of errors(); track error.kind) {
|
|
494
|
+
<p class="error-message">{{ error.message }}</p>
|
|
495
|
+
}
|
|
496
|
+
</div>
|
|
497
|
+
}
|
|
498
|
+
`, host: {
|
|
499
|
+
'[class]': 'hostClasses()',
|
|
500
|
+
}, styles: [":host{display:block;font-family:var(--ui-font-family);font-size:var(--ui-font-size-md)}label{display:inline-flex;align-items:center;gap:var(--ui-spacing-2);cursor:pointer;-webkit-user-select:none;user-select:none;color:var(--ui-color-text);line-height:var(--ui-line-height-normal)}input[type=checkbox]{appearance:none;-webkit-appearance:none;flex-shrink:0;width:1.25rem;height:1.25rem;border:1.5px solid var(--ui-color-input-border);border-radius:var(--ui-radius-sm);background-color:var(--ui-color-input-bg);cursor:pointer;position:relative;transition:border-color var(--ui-transition-fast),background-color var(--ui-transition-fast),box-shadow var(--ui-transition-fast);outline:none}input[type=checkbox]:hover:not(:disabled){border-color:var(--ui-color-input-border-hover);background-color:var(--ui-color-primary-light)}input[type=checkbox]:focus-visible{box-shadow:var(--ui-focus-ring);border-color:var(--ui-color-input-border-focus)}input[type=checkbox]:checked{background-color:var(--ui-color-primary);border-color:var(--ui-color-primary)}input[type=checkbox]:checked:after{content:\"\";position:absolute;inset:0;margin:auto;width:.35rem;height:.6rem;border:2px solid var(--ui-color-on-primary);border-top:none;border-left:none;transform:rotate(45deg) translate(-1px,-1px);animation:llm-check-pop var(--ui-duration-normal) var(--ui-ease-spring)}input[type=checkbox]:indeterminate{background-color:var(--ui-color-primary);border-color:var(--ui-color-primary)}input[type=checkbox]:indeterminate:after{content:\"\";position:absolute;inset:0;margin:auto;width:.5rem;height:2px;background-color:var(--ui-color-on-primary);animation:llm-check-pop var(--ui-duration-normal) var(--ui-ease-spring)}:host(.is-invalid) input[type=checkbox]{border-color:var(--ui-color-input-border-invalid)}:host(.is-invalid) input[type=checkbox]:focus-visible{border-color:var(--ui-color-input-border-invalid);box-shadow:0 0 0 2px var(--ui-color-surface),0 0 0 4px var(--ui-color-danger)}:host(.is-disabled){opacity:var(--ui-opacity-disabled);cursor:not-allowed}:host(.is-disabled) label{cursor:not-allowed}:host(.is-disabled) input[type=checkbox]{cursor:not-allowed}.errors{margin-top:var(--ui-spacing-1)}.error-message{margin:0;font-size:var(--ui-font-size-sm);color:var(--ui-color-error-text);line-height:var(--ui-line-height-normal)}@keyframes llm-check-pop{0%{transform:rotate(45deg) translate(-1px,-1px) scale(0)}60%{transform:rotate(45deg) translate(-1px,-1px) scale(1.15)}to{transform:rotate(45deg) translate(-1px,-1px) scale(1)}}\n"] }]
|
|
501
|
+
}], ctorParameters: () => [], propDecorators: { checked: [{ type: i0.Input, args: [{ isSignal: true, alias: "checked", required: false }] }, { type: i0.Output, args: ["checkedChange"] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }, { type: i0.Output, args: ["touchedChange"] }], indeterminate: [{ type: i0.Input, args: [{ isSignal: true, alias: "indeterminate", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], errors: [{ type: i0.Input, args: [{ isSignal: true, alias: "errors", required: false }] }], nativeInput: [{ type: i0.ViewChild, args: ['nativeInput', { isSignal: true }] }] } });
|
|
502
|
+
|
|
503
|
+
const LLM_RADIO_GROUP = new InjectionToken('LLM_RADIO_GROUP');
|
|
504
|
+
|
|
505
|
+
let nextId$7 = 0;
|
|
506
|
+
/**
|
|
507
|
+
* Individual radio button. Must be placed inside an `llm-radio-group`.
|
|
508
|
+
*
|
|
509
|
+
* Usage:
|
|
510
|
+
* ```html
|
|
511
|
+
* <llm-radio-group [(value)]="selected" name="plan">
|
|
512
|
+
* <llm-radio radioValue="free">Free</llm-radio>
|
|
513
|
+
* <llm-radio radioValue="pro">Pro</llm-radio>
|
|
514
|
+
* </llm-radio-group>
|
|
515
|
+
* ```
|
|
516
|
+
*/
|
|
517
|
+
class LlmRadio {
|
|
518
|
+
/** The value this radio option represents within the group. */
|
|
519
|
+
radioValue = input.required(...(ngDevMode ? [{ debugName: "radioValue" }] : /* istanbul ignore next */ []));
|
|
520
|
+
/** Whether this specific radio is individually disabled (stacked with group disabled). */
|
|
521
|
+
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
|
|
522
|
+
/** @internal */
|
|
523
|
+
group = inject(LLM_RADIO_GROUP, { optional: true });
|
|
524
|
+
/** @internal */
|
|
525
|
+
el = inject(ElementRef);
|
|
526
|
+
/** @internal */
|
|
527
|
+
inputId = `llm-radio-${nextId$7++}`;
|
|
528
|
+
/** @internal */
|
|
529
|
+
isChecked = computed(() => this.group?.value() === this.radioValue(), ...(ngDevMode ? [{ debugName: "isChecked" }] : /* istanbul ignore next */ []));
|
|
530
|
+
/** @internal */
|
|
531
|
+
isDisabled = computed(() => this.disabled() || (this.group?.disabled() ?? false), ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
|
|
532
|
+
/** @internal */
|
|
533
|
+
effectiveName = computed(() => this.group?.name() ?? '', ...(ngDevMode ? [{ debugName: "effectiveName" }] : /* istanbul ignore next */ []));
|
|
534
|
+
/** @internal */
|
|
535
|
+
hostClasses = computed(() => {
|
|
536
|
+
const classes = [];
|
|
537
|
+
if (this.isChecked())
|
|
538
|
+
classes.push('is-checked');
|
|
539
|
+
if (this.isDisabled())
|
|
540
|
+
classes.push('is-disabled');
|
|
541
|
+
return classes.join(' ');
|
|
542
|
+
}, ...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
|
|
543
|
+
/** @internal — for FocusKeyManager */
|
|
544
|
+
focusInput() {
|
|
545
|
+
this.el.nativeElement.querySelector('input')?.focus();
|
|
546
|
+
}
|
|
547
|
+
ngOnInit() {
|
|
548
|
+
this.group?.registerItem(this);
|
|
549
|
+
}
|
|
550
|
+
ngOnDestroy() {
|
|
551
|
+
this.group?.unregisterItem(this);
|
|
552
|
+
}
|
|
553
|
+
/** @internal */
|
|
554
|
+
onChange() {
|
|
555
|
+
this.group?.select(this.radioValue());
|
|
556
|
+
}
|
|
557
|
+
/** @internal */
|
|
558
|
+
onBlur() {
|
|
559
|
+
this.group?.markTouched();
|
|
560
|
+
}
|
|
561
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmRadio, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
562
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.4", type: LlmRadio, isStandalone: true, selector: "llm-radio", inputs: { radioValue: { classPropertyName: "radioValue", publicName: "radioValue", isSignal: true, isRequired: true, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "hostClasses()" } }, ngImport: i0, template: `
|
|
563
|
+
<label [attr.for]="inputId">
|
|
564
|
+
<input
|
|
565
|
+
type="radio"
|
|
566
|
+
[id]="inputId"
|
|
567
|
+
[value]="radioValue()"
|
|
568
|
+
[checked]="isChecked()"
|
|
569
|
+
[disabled]="isDisabled()"
|
|
570
|
+
[attr.name]="effectiveName() || null"
|
|
571
|
+
(change)="onChange()"
|
|
572
|
+
(blur)="onBlur()"
|
|
573
|
+
/>
|
|
574
|
+
<ng-content />
|
|
575
|
+
</label>
|
|
576
|
+
`, isInline: true, styles: [":host{display:block;font-family:var(--ui-font-family);font-size:var(--ui-font-size-md)}label{display:inline-flex;align-items:center;gap:var(--ui-spacing-2);cursor:pointer;-webkit-user-select:none;user-select:none;color:var(--ui-color-text);line-height:var(--ui-line-height-normal)}input[type=radio]{appearance:none;-webkit-appearance:none;flex-shrink:0;width:1.25rem;height:1.25rem;border:1.5px solid var(--ui-color-input-border);border-radius:50%;background-color:var(--ui-color-input-bg);cursor:pointer;position:relative;transition:border-color var(--ui-transition-fast),background-color var(--ui-transition-fast),box-shadow var(--ui-transition-fast);outline:none}input[type=radio]:hover:not(:disabled){border-color:var(--ui-color-input-border-hover);background-color:var(--ui-color-primary-light)}input[type=radio]:focus-visible{box-shadow:var(--ui-focus-ring);border-color:var(--ui-color-input-border-focus)}input[type=radio]:checked{background-color:var(--ui-color-primary);border-color:var(--ui-color-primary)}input[type=radio]:checked:after{content:\"\";position:absolute;inset:0;margin:auto;width:.45rem;height:.45rem;border-radius:50%;background-color:var(--ui-color-on-primary);animation:llm-radio-pop var(--ui-duration-normal) var(--ui-ease-spring)}:host-context(llm-radio-group.is-invalid) input[type=radio],:host(.is-invalid) input[type=radio]{border-color:var(--ui-color-input-border-invalid)}:host-context(llm-radio-group.is-invalid) input[type=radio]:focus-visible,:host(.is-invalid) input[type=radio]:focus-visible{border-color:var(--ui-color-input-border-invalid);box-shadow:0 0 0 2px var(--ui-color-surface),0 0 0 4px var(--ui-color-danger)}:host(.is-disabled){opacity:var(--ui-opacity-disabled);cursor:not-allowed}:host(.is-disabled) label{cursor:not-allowed}:host(.is-disabled) input[type=radio]{cursor:not-allowed}@keyframes llm-radio-pop{0%{transform:scale(0)}60%{transform:scale(1.2)}to{transform:scale(1)}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
577
|
+
}
|
|
578
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmRadio, decorators: [{
|
|
579
|
+
type: Component,
|
|
580
|
+
args: [{ selector: 'llm-radio', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: `
|
|
581
|
+
<label [attr.for]="inputId">
|
|
582
|
+
<input
|
|
583
|
+
type="radio"
|
|
584
|
+
[id]="inputId"
|
|
585
|
+
[value]="radioValue()"
|
|
586
|
+
[checked]="isChecked()"
|
|
587
|
+
[disabled]="isDisabled()"
|
|
588
|
+
[attr.name]="effectiveName() || null"
|
|
589
|
+
(change)="onChange()"
|
|
590
|
+
(blur)="onBlur()"
|
|
591
|
+
/>
|
|
592
|
+
<ng-content />
|
|
593
|
+
</label>
|
|
594
|
+
`, host: {
|
|
595
|
+
'[class]': 'hostClasses()',
|
|
596
|
+
}, styles: [":host{display:block;font-family:var(--ui-font-family);font-size:var(--ui-font-size-md)}label{display:inline-flex;align-items:center;gap:var(--ui-spacing-2);cursor:pointer;-webkit-user-select:none;user-select:none;color:var(--ui-color-text);line-height:var(--ui-line-height-normal)}input[type=radio]{appearance:none;-webkit-appearance:none;flex-shrink:0;width:1.25rem;height:1.25rem;border:1.5px solid var(--ui-color-input-border);border-radius:50%;background-color:var(--ui-color-input-bg);cursor:pointer;position:relative;transition:border-color var(--ui-transition-fast),background-color var(--ui-transition-fast),box-shadow var(--ui-transition-fast);outline:none}input[type=radio]:hover:not(:disabled){border-color:var(--ui-color-input-border-hover);background-color:var(--ui-color-primary-light)}input[type=radio]:focus-visible{box-shadow:var(--ui-focus-ring);border-color:var(--ui-color-input-border-focus)}input[type=radio]:checked{background-color:var(--ui-color-primary);border-color:var(--ui-color-primary)}input[type=radio]:checked:after{content:\"\";position:absolute;inset:0;margin:auto;width:.45rem;height:.45rem;border-radius:50%;background-color:var(--ui-color-on-primary);animation:llm-radio-pop var(--ui-duration-normal) var(--ui-ease-spring)}:host-context(llm-radio-group.is-invalid) input[type=radio],:host(.is-invalid) input[type=radio]{border-color:var(--ui-color-input-border-invalid)}:host-context(llm-radio-group.is-invalid) input[type=radio]:focus-visible,:host(.is-invalid) input[type=radio]:focus-visible{border-color:var(--ui-color-input-border-invalid);box-shadow:0 0 0 2px var(--ui-color-surface),0 0 0 4px var(--ui-color-danger)}:host(.is-disabled){opacity:var(--ui-opacity-disabled);cursor:not-allowed}:host(.is-disabled) label{cursor:not-allowed}:host(.is-disabled) input[type=radio]{cursor:not-allowed}@keyframes llm-radio-pop{0%{transform:scale(0)}60%{transform:scale(1.2)}to{transform:scale(1)}}\n"] }]
|
|
597
|
+
}], propDecorators: { radioValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "radioValue", required: true }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }] } });
|
|
598
|
+
|
|
599
|
+
let nextId$6 = 0;
|
|
600
|
+
/**
|
|
601
|
+
* Container for a group of radio buttons. Manages keyboard navigation, shared name,
|
|
602
|
+
* and Signal Forms integration.
|
|
603
|
+
*
|
|
604
|
+
* Usage:
|
|
605
|
+
* ```html
|
|
606
|
+
* <llm-radio-group [(value)]="size" name="size">
|
|
607
|
+
* <llm-radio radioValue="sm">Small</llm-radio>
|
|
608
|
+
* <llm-radio radioValue="md">Medium</llm-radio>
|
|
609
|
+
* <llm-radio radioValue="lg">Large</llm-radio>
|
|
610
|
+
* </llm-radio-group>
|
|
611
|
+
*
|
|
612
|
+
* <!-- With Signal Forms -->
|
|
613
|
+
* <llm-radio-group [formField]="form.size">
|
|
614
|
+
* <llm-radio radioValue="sm">Small</llm-radio>
|
|
615
|
+
* </llm-radio-group>
|
|
616
|
+
* ```
|
|
617
|
+
*/
|
|
618
|
+
class LlmRadioGroup {
|
|
619
|
+
/** The selected value. Bound by [formField] directive. Supports [(value)] two-way binding. */
|
|
620
|
+
value = model('', ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
621
|
+
/** Whether the user has interacted. Bound by [formField] directive. */
|
|
622
|
+
touched = model(false, ...(ngDevMode ? [{ debugName: "touched" }] : /* istanbul ignore next */ []));
|
|
623
|
+
/** Whether the group is disabled. Bound by [formField] directive. */
|
|
624
|
+
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
|
|
625
|
+
/** Whether the group has validation errors. Bound by [formField] directive. */
|
|
626
|
+
invalid = input(false, ...(ngDevMode ? [{ debugName: "invalid" }] : /* istanbul ignore next */ []));
|
|
627
|
+
/** Whether the group is required. Bound by [formField] directive. */
|
|
628
|
+
required = input(false, ...(ngDevMode ? [{ debugName: "required" }] : /* istanbul ignore next */ []));
|
|
629
|
+
/** Shared name attribute propagated to all child radio inputs. Bound by [formField] directive. */
|
|
630
|
+
name = input('', ...(ngDevMode ? [{ debugName: "name" }] : /* istanbul ignore next */ []));
|
|
631
|
+
/** Validation errors from the form system. Bound by [formField] directive. */
|
|
632
|
+
errors = input([], ...(ngDevMode ? [{ debugName: "errors" }] : /* istanbul ignore next */ []));
|
|
633
|
+
/** @internal */
|
|
634
|
+
errorId = `llm-radio-group-errors-${nextId$6++}`;
|
|
635
|
+
/** @internal */
|
|
636
|
+
items = signal([], ...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
|
|
637
|
+
/** @internal */
|
|
638
|
+
showErrors = computed(() => this.touched() && this.invalid() && this.errors().length > 0, ...(ngDevMode ? [{ debugName: "showErrors" }] : /* istanbul ignore next */ []));
|
|
639
|
+
/** @internal */
|
|
640
|
+
hostClasses = computed(() => {
|
|
641
|
+
const classes = [];
|
|
642
|
+
if (this.disabled())
|
|
643
|
+
classes.push('is-disabled');
|
|
644
|
+
if (this.invalid())
|
|
645
|
+
classes.push('is-invalid');
|
|
646
|
+
if (this.touched())
|
|
647
|
+
classes.push('is-touched');
|
|
648
|
+
return classes.join(' ');
|
|
649
|
+
}, ...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
|
|
650
|
+
/** @internal — called by LlmRadio on change */
|
|
651
|
+
select(v) {
|
|
652
|
+
if (!this.disabled()) {
|
|
653
|
+
this.value.set(v);
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
/** @internal — called by LlmRadio on blur */
|
|
657
|
+
markTouched() {
|
|
658
|
+
this.touched.set(true);
|
|
659
|
+
}
|
|
660
|
+
/** @internal — called by LlmRadio on init */
|
|
661
|
+
registerItem(item) {
|
|
662
|
+
this.items.update((list) => [...list, item]);
|
|
663
|
+
}
|
|
664
|
+
/** @internal — called by LlmRadio on destroy */
|
|
665
|
+
unregisterItem(item) {
|
|
666
|
+
this.items.update((list) => list.filter((i) => i !== item));
|
|
667
|
+
}
|
|
668
|
+
/** @internal */
|
|
669
|
+
onKeydown(event) {
|
|
670
|
+
const key = event.key;
|
|
671
|
+
if (key !== 'ArrowDown' && key !== 'ArrowRight' && key !== 'ArrowUp' && key !== 'ArrowLeft')
|
|
672
|
+
return;
|
|
673
|
+
event.preventDefault();
|
|
674
|
+
const radioItems = this.items();
|
|
675
|
+
const enabled = radioItems.filter((item) => !item.isDisabled());
|
|
676
|
+
if (enabled.length === 0)
|
|
677
|
+
return;
|
|
678
|
+
const currentPos = enabled.findIndex((i) => i.radioValue() === this.value());
|
|
679
|
+
const isNext = key === 'ArrowDown' || key === 'ArrowRight';
|
|
680
|
+
const n = enabled.length;
|
|
681
|
+
const nextPos = isNext
|
|
682
|
+
? (currentPos + 1) % n
|
|
683
|
+
: (currentPos - 1 + n) % n;
|
|
684
|
+
const target = enabled[nextPos];
|
|
685
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition, @typescript-eslint/strict-boolean-expressions
|
|
686
|
+
if (target) {
|
|
687
|
+
target.focusInput();
|
|
688
|
+
this.value.set(target.radioValue());
|
|
689
|
+
this.touched.set(true);
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmRadioGroup, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
693
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.4", type: LlmRadioGroup, isStandalone: true, selector: "llm-radio-group", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, errors: { classPropertyName: "errors", publicName: "errors", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", touched: "touchedChange" }, host: { attributes: { "role": "radiogroup" }, listeners: { "keydown": "onKeydown($event)" }, properties: { "class": "hostClasses()", "attr.aria-invalid": "invalid() || null", "attr.aria-required": "required() || null", "attr.aria-describedby": "showErrors() ? errorId : null" } }, providers: [{ provide: LLM_RADIO_GROUP, useExisting: LlmRadioGroup }], ngImport: i0, template: `
|
|
694
|
+
<ng-content />
|
|
695
|
+
@if (showErrors()) {
|
|
696
|
+
<div class="errors" [id]="errorId" aria-live="polite">
|
|
697
|
+
@for (error of errors(); track error.kind) {
|
|
698
|
+
<p class="error-message">{{ error.message }}</p>
|
|
699
|
+
}
|
|
700
|
+
</div>
|
|
701
|
+
}
|
|
702
|
+
`, isInline: true, styles: [":host{display:block;font-family:var(--ui-font-family)}:host(.is-disabled){opacity:var(--ui-opacity-disabled);cursor:not-allowed}.errors{margin-top:var(--ui-spacing-1)}.error-message{margin:0;font-size:var(--ui-font-size-sm);color:var(--ui-color-error-text);line-height:var(--ui-line-height-normal)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
703
|
+
}
|
|
704
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmRadioGroup, decorators: [{
|
|
705
|
+
type: Component,
|
|
706
|
+
args: [{ selector: 'llm-radio-group', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: `
|
|
707
|
+
<ng-content />
|
|
708
|
+
@if (showErrors()) {
|
|
709
|
+
<div class="errors" [id]="errorId" aria-live="polite">
|
|
710
|
+
@for (error of errors(); track error.kind) {
|
|
711
|
+
<p class="error-message">{{ error.message }}</p>
|
|
712
|
+
}
|
|
713
|
+
</div>
|
|
714
|
+
}
|
|
715
|
+
`, host: {
|
|
716
|
+
role: 'radiogroup',
|
|
717
|
+
'[class]': 'hostClasses()',
|
|
718
|
+
'[attr.aria-invalid]': 'invalid() || null',
|
|
719
|
+
'[attr.aria-required]': 'required() || null',
|
|
720
|
+
'[attr.aria-describedby]': 'showErrors() ? errorId : null',
|
|
721
|
+
'(keydown)': 'onKeydown($event)',
|
|
722
|
+
}, providers: [{ provide: LLM_RADIO_GROUP, useExisting: LlmRadioGroup }], styles: [":host{display:block;font-family:var(--ui-font-family)}:host(.is-disabled){opacity:var(--ui-opacity-disabled);cursor:not-allowed}.errors{margin-top:var(--ui-spacing-1)}.error-message{margin:0;font-size:var(--ui-font-size-sm);color:var(--ui-color-error-text);line-height:var(--ui-line-height-normal)}\n"] }]
|
|
723
|
+
}], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }, { type: i0.Output, args: ["touchedChange"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], errors: [{ type: i0.Input, args: [{ isSignal: true, alias: "errors", required: false }] }] } });
|
|
724
|
+
|
|
725
|
+
let nextId$5 = 0;
|
|
726
|
+
/**
|
|
727
|
+
* Accessible toggle (switch) component for use with Angular Signal Forms.
|
|
728
|
+
* Presents as a pill-shaped on/off slider instead of a checkbox box,
|
|
729
|
+
* but has identical boolean semantics and implements FormCheckboxControl.
|
|
730
|
+
*
|
|
731
|
+
* Usage:
|
|
732
|
+
* ```html
|
|
733
|
+
* <llm-toggle [(checked)]="enabled">Enable notifications</llm-toggle>
|
|
734
|
+
* <llm-toggle [formField]="form.enabled">Enable</llm-toggle>
|
|
735
|
+
* ```
|
|
736
|
+
*/
|
|
737
|
+
class LlmToggle {
|
|
738
|
+
/** The checked state. Bound by [formField] directive. Supports [(checked)] two-way binding. */
|
|
739
|
+
checked = model(false, ...(ngDevMode ? [{ debugName: "checked" }] : /* istanbul ignore next */ []));
|
|
740
|
+
/** Whether the user has interacted with the input. Bound by [formField] directive. */
|
|
741
|
+
touched = model(false, ...(ngDevMode ? [{ debugName: "touched" }] : /* istanbul ignore next */ []));
|
|
742
|
+
/** Whether the toggle is disabled. Bound by [formField] directive. */
|
|
743
|
+
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
|
|
744
|
+
/** Whether the toggle has validation errors. Bound by [formField] directive. */
|
|
745
|
+
invalid = input(false, ...(ngDevMode ? [{ debugName: "invalid" }] : /* istanbul ignore next */ []));
|
|
746
|
+
/** Whether the toggle is required. Bound by [formField] directive. */
|
|
747
|
+
required = input(false, ...(ngDevMode ? [{ debugName: "required" }] : /* istanbul ignore next */ []));
|
|
748
|
+
/** The input's name attribute. Bound by [formField] directive. */
|
|
749
|
+
name = input('', ...(ngDevMode ? [{ debugName: "name" }] : /* istanbul ignore next */ []));
|
|
750
|
+
/** Validation errors from the form system. Bound by [formField] directive. */
|
|
751
|
+
errors = input([], ...(ngDevMode ? [{ debugName: "errors" }] : /* istanbul ignore next */ []));
|
|
752
|
+
/** @internal */
|
|
753
|
+
inputId = `llm-toggle-${nextId$5++}`;
|
|
754
|
+
/** @internal */
|
|
755
|
+
errorId = `llm-toggle-errors-${nextId$5++}`;
|
|
756
|
+
/** @internal */
|
|
757
|
+
showErrors = computed(() => this.touched() && this.invalid() && this.errors().length > 0, ...(ngDevMode ? [{ debugName: "showErrors" }] : /* istanbul ignore next */ []));
|
|
758
|
+
/** @internal */
|
|
759
|
+
hostClasses = computed(() => {
|
|
760
|
+
const classes = [];
|
|
761
|
+
if (this.checked())
|
|
762
|
+
classes.push('is-checked');
|
|
763
|
+
if (this.disabled())
|
|
764
|
+
classes.push('is-disabled');
|
|
765
|
+
if (this.invalid())
|
|
766
|
+
classes.push('is-invalid');
|
|
767
|
+
if (this.touched())
|
|
768
|
+
classes.push('is-touched');
|
|
769
|
+
return classes.join(' ');
|
|
770
|
+
}, ...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
|
|
771
|
+
/** @internal */
|
|
772
|
+
onChange(event) {
|
|
773
|
+
const target = event.target;
|
|
774
|
+
this.checked.set(target.checked);
|
|
775
|
+
}
|
|
776
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmToggle, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
777
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.4", type: LlmToggle, isStandalone: true, selector: "llm-toggle", inputs: { checked: { classPropertyName: "checked", publicName: "checked", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, errors: { classPropertyName: "errors", publicName: "errors", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { checked: "checkedChange", touched: "touchedChange" }, host: { properties: { "class": "hostClasses()" } }, ngImport: i0, template: `
|
|
778
|
+
<label [attr.for]="inputId">
|
|
779
|
+
<input
|
|
780
|
+
type="checkbox"
|
|
781
|
+
role="switch"
|
|
782
|
+
[id]="inputId"
|
|
783
|
+
[checked]="checked()"
|
|
784
|
+
(change)="onChange($event)"
|
|
785
|
+
(blur)="touched.set(true)"
|
|
786
|
+
[disabled]="disabled()"
|
|
787
|
+
[attr.name]="name() || null"
|
|
788
|
+
[attr.aria-checked]="checked()"
|
|
789
|
+
[attr.aria-invalid]="invalid() || null"
|
|
790
|
+
[attr.aria-required]="required() || null"
|
|
791
|
+
[attr.aria-describedby]="showErrors() ? errorId : null"
|
|
792
|
+
/>
|
|
793
|
+
<span class="track" aria-hidden="true">
|
|
794
|
+
<span class="thumb"></span>
|
|
795
|
+
</span>
|
|
796
|
+
<ng-content />
|
|
797
|
+
</label>
|
|
798
|
+
@if (showErrors()) {
|
|
799
|
+
<div class="errors" [id]="errorId" aria-live="polite">
|
|
800
|
+
@for (error of errors(); track error.kind) {
|
|
801
|
+
<p class="error-message">{{ error.message }}</p>
|
|
802
|
+
}
|
|
803
|
+
</div>
|
|
804
|
+
}
|
|
805
|
+
`, isInline: true, styles: [":host{display:block;font-family:var(--ui-font-family);font-size:var(--ui-font-size-md)}label{display:inline-flex;align-items:center;gap:var(--ui-spacing-2);cursor:pointer;-webkit-user-select:none;user-select:none;color:var(--ui-color-text);line-height:var(--ui-line-height-normal)}input[type=checkbox]{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.track{position:relative;display:inline-flex;align-items:center;flex-shrink:0;width:2.75rem;height:1.5rem;border-radius:var(--ui-radius-full);border:1.5px solid var(--ui-color-input-border);background-color:var(--ui-color-input-bg);transition:background-color var(--ui-transition-fast),border-color var(--ui-transition-fast),box-shadow var(--ui-transition-fast);cursor:pointer}.thumb{position:absolute;left:.125rem;width:1.125rem;height:1.125rem;border-radius:var(--ui-radius-full);background-color:var(--ui-color-input-border);box-shadow:var(--ui-shadow-xs);transition:transform var(--ui-transition-fast),background-color var(--ui-transition-fast)}label:hover:not(:has(input:disabled)) .track{border-color:var(--ui-color-input-border-hover)}input[type=checkbox]:focus-visible+.track{box-shadow:var(--ui-focus-ring);border-color:var(--ui-color-input-border-focus)}:host(.is-checked) .track{background-color:var(--ui-color-primary);border-color:var(--ui-color-primary)}:host(.is-checked) .thumb{transform:translate(1.25rem);background-color:var(--ui-color-surface)}:host(.is-invalid) .track{border-color:var(--ui-color-input-border-invalid)}:host(.is-invalid) input[type=checkbox]:focus-visible+.track{border-color:var(--ui-color-input-border-invalid);box-shadow:0 0 0 2px var(--ui-color-surface),0 0 0 4px var(--ui-color-danger)}:host(.is-disabled){opacity:var(--ui-opacity-disabled);cursor:not-allowed}:host(.is-disabled) label{cursor:not-allowed}:host(.is-disabled) .track{cursor:not-allowed}.errors{margin-top:var(--ui-spacing-1)}.error-message{margin:0;font-size:var(--ui-font-size-sm);color:var(--ui-color-error-text);line-height:var(--ui-line-height-normal)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
806
|
+
}
|
|
807
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmToggle, decorators: [{
|
|
808
|
+
type: Component,
|
|
809
|
+
args: [{ selector: 'llm-toggle', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: `
|
|
810
|
+
<label [attr.for]="inputId">
|
|
811
|
+
<input
|
|
812
|
+
type="checkbox"
|
|
813
|
+
role="switch"
|
|
814
|
+
[id]="inputId"
|
|
815
|
+
[checked]="checked()"
|
|
816
|
+
(change)="onChange($event)"
|
|
817
|
+
(blur)="touched.set(true)"
|
|
818
|
+
[disabled]="disabled()"
|
|
819
|
+
[attr.name]="name() || null"
|
|
820
|
+
[attr.aria-checked]="checked()"
|
|
821
|
+
[attr.aria-invalid]="invalid() || null"
|
|
822
|
+
[attr.aria-required]="required() || null"
|
|
823
|
+
[attr.aria-describedby]="showErrors() ? errorId : null"
|
|
824
|
+
/>
|
|
825
|
+
<span class="track" aria-hidden="true">
|
|
826
|
+
<span class="thumb"></span>
|
|
827
|
+
</span>
|
|
828
|
+
<ng-content />
|
|
829
|
+
</label>
|
|
830
|
+
@if (showErrors()) {
|
|
831
|
+
<div class="errors" [id]="errorId" aria-live="polite">
|
|
832
|
+
@for (error of errors(); track error.kind) {
|
|
833
|
+
<p class="error-message">{{ error.message }}</p>
|
|
834
|
+
}
|
|
835
|
+
</div>
|
|
836
|
+
}
|
|
837
|
+
`, host: {
|
|
838
|
+
'[class]': 'hostClasses()',
|
|
839
|
+
}, styles: [":host{display:block;font-family:var(--ui-font-family);font-size:var(--ui-font-size-md)}label{display:inline-flex;align-items:center;gap:var(--ui-spacing-2);cursor:pointer;-webkit-user-select:none;user-select:none;color:var(--ui-color-text);line-height:var(--ui-line-height-normal)}input[type=checkbox]{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.track{position:relative;display:inline-flex;align-items:center;flex-shrink:0;width:2.75rem;height:1.5rem;border-radius:var(--ui-radius-full);border:1.5px solid var(--ui-color-input-border);background-color:var(--ui-color-input-bg);transition:background-color var(--ui-transition-fast),border-color var(--ui-transition-fast),box-shadow var(--ui-transition-fast);cursor:pointer}.thumb{position:absolute;left:.125rem;width:1.125rem;height:1.125rem;border-radius:var(--ui-radius-full);background-color:var(--ui-color-input-border);box-shadow:var(--ui-shadow-xs);transition:transform var(--ui-transition-fast),background-color var(--ui-transition-fast)}label:hover:not(:has(input:disabled)) .track{border-color:var(--ui-color-input-border-hover)}input[type=checkbox]:focus-visible+.track{box-shadow:var(--ui-focus-ring);border-color:var(--ui-color-input-border-focus)}:host(.is-checked) .track{background-color:var(--ui-color-primary);border-color:var(--ui-color-primary)}:host(.is-checked) .thumb{transform:translate(1.25rem);background-color:var(--ui-color-surface)}:host(.is-invalid) .track{border-color:var(--ui-color-input-border-invalid)}:host(.is-invalid) input[type=checkbox]:focus-visible+.track{border-color:var(--ui-color-input-border-invalid);box-shadow:0 0 0 2px var(--ui-color-surface),0 0 0 4px var(--ui-color-danger)}:host(.is-disabled){opacity:var(--ui-opacity-disabled);cursor:not-allowed}:host(.is-disabled) label{cursor:not-allowed}:host(.is-disabled) .track{cursor:not-allowed}.errors{margin-top:var(--ui-spacing-1)}.error-message{margin:0;font-size:var(--ui-font-size-sm);color:var(--ui-color-error-text);line-height:var(--ui-line-height-normal)}\n"] }]
|
|
840
|
+
}], propDecorators: { checked: [{ type: i0.Input, args: [{ isSignal: true, alias: "checked", required: false }] }, { type: i0.Output, args: ["checkedChange"] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }, { type: i0.Output, args: ["touchedChange"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], errors: [{ type: i0.Input, args: [{ isSignal: true, alias: "errors", required: false }] }] } });
|
|
841
|
+
|
|
842
|
+
/**
|
|
843
|
+
* Inline notification banner with semantic color variants and optional dismiss button.
|
|
844
|
+
*
|
|
845
|
+
* Usage:
|
|
846
|
+
* ```html
|
|
847
|
+
* <llm-alert variant="success">Your changes were saved.</llm-alert>
|
|
848
|
+
* <llm-alert variant="warning" [dismissible]="true" (dismissed)="onDismiss()">
|
|
849
|
+
* Your session expires soon.
|
|
850
|
+
* </llm-alert>
|
|
851
|
+
* ```
|
|
852
|
+
*/
|
|
853
|
+
class LlmAlert {
|
|
854
|
+
/** Semantic color variant of the alert. */
|
|
855
|
+
variant = input('info', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
|
|
856
|
+
/** Whether to show a dismiss button. */
|
|
857
|
+
dismissible = input(false, ...(ngDevMode ? [{ debugName: "dismissible" }] : /* istanbul ignore next */ []));
|
|
858
|
+
/** Emitted when the dismiss button is clicked. */
|
|
859
|
+
dismissed = output();
|
|
860
|
+
hostClasses = computed(() => `variant-${this.variant()}`, ...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
|
|
861
|
+
/** @internal */
|
|
862
|
+
get isDismissible() {
|
|
863
|
+
return this.dismissible();
|
|
864
|
+
}
|
|
865
|
+
/** @internal */
|
|
866
|
+
get hostClassesValue() {
|
|
867
|
+
return this.hostClasses();
|
|
868
|
+
}
|
|
869
|
+
/** @internal */
|
|
870
|
+
get ariaLive() {
|
|
871
|
+
return this.variant() === 'danger' ? 'assertive' : 'polite';
|
|
872
|
+
}
|
|
873
|
+
dismiss() {
|
|
874
|
+
this.dismissed.emit();
|
|
875
|
+
}
|
|
876
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmAlert, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
877
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.4", type: LlmAlert, isStandalone: true, selector: "llm-alert", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, dismissible: { classPropertyName: "dismissible", publicName: "dismissible", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { dismissed: "dismissed" }, host: { attributes: { "role": "alert" }, properties: { "class": "hostClassesValue", "attr.aria-live": "ariaLive" } }, ngImport: i0, template: `
|
|
878
|
+
<span class="content"><ng-content /></span>
|
|
879
|
+
@if (isDismissible) {
|
|
880
|
+
<button class="dismiss" type="button" aria-label="Dismiss" (click)="dismiss()">
|
|
881
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
|
882
|
+
<line x1="18" y1="6" x2="6" y2="18" />
|
|
883
|
+
<line x1="6" y1="6" x2="18" y2="18" />
|
|
884
|
+
</svg>
|
|
885
|
+
</button>
|
|
886
|
+
}
|
|
887
|
+
`, isInline: true, styles: [":host{display:flex;align-items:flex-start;gap:var(--ui-spacing-3);padding:var(--ui-spacing-3) var(--ui-spacing-4);border-radius:var(--ui-radius-md);border:1px solid transparent;font-family:var(--ui-font-family);font-size:var(--ui-font-size-sm);line-height:var(--ui-line-height-normal);box-sizing:border-box;width:100%}.content{flex:1}:host(.variant-info){background-color:color-mix(in srgb,var(--ui-color-info) 10%,transparent);color:var(--ui-color-info);border-color:color-mix(in srgb,var(--ui-color-info) 25%,transparent)}:host(.variant-success){background-color:color-mix(in srgb,var(--ui-color-success) 10%,transparent);color:var(--ui-color-success);border-color:color-mix(in srgb,var(--ui-color-success) 25%,transparent)}:host(.variant-warning){background-color:color-mix(in srgb,var(--ui-color-warning) 10%,transparent);color:var(--ui-color-warning);border-color:color-mix(in srgb,var(--ui-color-warning) 25%,transparent)}:host(.variant-danger){background-color:color-mix(in srgb,var(--ui-color-danger) 10%,transparent);color:var(--ui-color-danger);border-color:color-mix(in srgb,var(--ui-color-danger) 25%,transparent)}.dismiss{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;padding:.125rem;background:transparent;border:none;border-radius:var(--ui-radius-sm);cursor:pointer;color:inherit;opacity:.7;transition:opacity var(--ui-transition-fast),background-color var(--ui-transition-fast);line-height:1}.dismiss:hover{opacity:1;background-color:color-mix(in srgb,currentColor 10%,transparent)}.dismiss:focus-visible{outline:none;box-shadow:var(--ui-focus-ring);opacity:1}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
888
|
+
}
|
|
889
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmAlert, decorators: [{
|
|
890
|
+
type: Component,
|
|
891
|
+
args: [{ selector: 'llm-alert', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: `
|
|
892
|
+
<span class="content"><ng-content /></span>
|
|
893
|
+
@if (isDismissible) {
|
|
894
|
+
<button class="dismiss" type="button" aria-label="Dismiss" (click)="dismiss()">
|
|
895
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
|
896
|
+
<line x1="18" y1="6" x2="6" y2="18" />
|
|
897
|
+
<line x1="6" y1="6" x2="18" y2="18" />
|
|
898
|
+
</svg>
|
|
899
|
+
</button>
|
|
900
|
+
}
|
|
901
|
+
`, host: {
|
|
902
|
+
'[class]': 'hostClassesValue',
|
|
903
|
+
role: 'alert',
|
|
904
|
+
'[attr.aria-live]': 'ariaLive',
|
|
905
|
+
}, styles: [":host{display:flex;align-items:flex-start;gap:var(--ui-spacing-3);padding:var(--ui-spacing-3) var(--ui-spacing-4);border-radius:var(--ui-radius-md);border:1px solid transparent;font-family:var(--ui-font-family);font-size:var(--ui-font-size-sm);line-height:var(--ui-line-height-normal);box-sizing:border-box;width:100%}.content{flex:1}:host(.variant-info){background-color:color-mix(in srgb,var(--ui-color-info) 10%,transparent);color:var(--ui-color-info);border-color:color-mix(in srgb,var(--ui-color-info) 25%,transparent)}:host(.variant-success){background-color:color-mix(in srgb,var(--ui-color-success) 10%,transparent);color:var(--ui-color-success);border-color:color-mix(in srgb,var(--ui-color-success) 25%,transparent)}:host(.variant-warning){background-color:color-mix(in srgb,var(--ui-color-warning) 10%,transparent);color:var(--ui-color-warning);border-color:color-mix(in srgb,var(--ui-color-warning) 25%,transparent)}:host(.variant-danger){background-color:color-mix(in srgb,var(--ui-color-danger) 10%,transparent);color:var(--ui-color-danger);border-color:color-mix(in srgb,var(--ui-color-danger) 25%,transparent)}.dismiss{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;padding:.125rem;background:transparent;border:none;border-radius:var(--ui-radius-sm);cursor:pointer;color:inherit;opacity:.7;transition:opacity var(--ui-transition-fast),background-color var(--ui-transition-fast);line-height:1}.dismiss:hover{opacity:1;background-color:color-mix(in srgb,currentColor 10%,transparent)}.dismiss:focus-visible{outline:none;box-shadow:var(--ui-focus-ring);opacity:1}\n"] }]
|
|
906
|
+
}], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], dismissible: [{ type: i0.Input, args: [{ isSignal: true, alias: "dismissible", required: false }] }], dismissed: [{ type: i0.Output, args: ["dismissed"] }] } });
|
|
907
|
+
|
|
908
|
+
const LLM_SELECT = new InjectionToken('LLM_SELECT');
|
|
909
|
+
|
|
910
|
+
/** @internal — Wrapper item for ActiveDescendantKeyManager integration. */
|
|
911
|
+
class SelectOptionItem {
|
|
912
|
+
id;
|
|
913
|
+
value;
|
|
914
|
+
labelText;
|
|
915
|
+
activeOptionId;
|
|
916
|
+
disabled;
|
|
917
|
+
constructor(id, value, labelText, disabled, activeOptionId) {
|
|
918
|
+
this.id = id;
|
|
919
|
+
this.value = value;
|
|
920
|
+
this.labelText = labelText;
|
|
921
|
+
this.activeOptionId = activeOptionId;
|
|
922
|
+
this.disabled = disabled;
|
|
923
|
+
}
|
|
924
|
+
getLabel() {
|
|
925
|
+
return this.labelText;
|
|
926
|
+
}
|
|
927
|
+
setActiveStyles() {
|
|
928
|
+
this.activeOptionId.set(this.id);
|
|
929
|
+
}
|
|
930
|
+
setInactiveStyles() {
|
|
931
|
+
// Handled by key manager — no-op here
|
|
932
|
+
}
|
|
933
|
+
}
|
|
934
|
+
let nextId$4 = 0;
|
|
935
|
+
/**
|
|
936
|
+
* Accessible dropdown select component for use with Angular Signal Forms.
|
|
937
|
+
* Uses the native Popover API for the panel overlay.
|
|
938
|
+
*
|
|
939
|
+
* Usage:
|
|
940
|
+
* ```html
|
|
941
|
+
* <llm-select [(value)]="country" placeholder="Select a country">
|
|
942
|
+
* <llm-option optionValue="us">United States</llm-option>
|
|
943
|
+
* <llm-option optionValue="ca">Canada</llm-option>
|
|
944
|
+
* </llm-select>
|
|
945
|
+
*
|
|
946
|
+
* <!-- With Signal Forms -->
|
|
947
|
+
* <llm-select [formField]="form.country" placeholder="Select a country">
|
|
948
|
+
* <llm-option optionValue="us">United States</llm-option>
|
|
949
|
+
* </llm-select>
|
|
950
|
+
* ```
|
|
951
|
+
*/
|
|
952
|
+
class LlmSelect {
|
|
953
|
+
/** The selected value. Bound by [formField] directive. Supports [(value)] two-way binding. */
|
|
954
|
+
value = model('', ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
955
|
+
/** Whether the user has interacted. Bound by [formField] directive. */
|
|
956
|
+
touched = model(false, ...(ngDevMode ? [{ debugName: "touched" }] : /* istanbul ignore next */ []));
|
|
957
|
+
/** Placeholder text shown when no option is selected. */
|
|
958
|
+
placeholder = input('', ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
|
|
959
|
+
/** Whether the select is disabled. Bound by [formField] directive. */
|
|
960
|
+
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
|
|
961
|
+
/** Whether the select has validation errors. Bound by [formField] directive. */
|
|
962
|
+
invalid = input(false, ...(ngDevMode ? [{ debugName: "invalid" }] : /* istanbul ignore next */ []));
|
|
963
|
+
/** Whether the select is required. Bound by [formField] directive. */
|
|
964
|
+
required = input(false, ...(ngDevMode ? [{ debugName: "required" }] : /* istanbul ignore next */ []));
|
|
965
|
+
/** The input's name attribute. Bound by [formField] directive. */
|
|
966
|
+
name = input('', ...(ngDevMode ? [{ debugName: "name" }] : /* istanbul ignore next */ []));
|
|
967
|
+
/** Validation errors from the form system. Bound by [formField] directive. */
|
|
968
|
+
errors = input([], ...(ngDevMode ? [{ debugName: "errors" }] : /* istanbul ignore next */ []));
|
|
969
|
+
/** @internal */
|
|
970
|
+
activeOptionId = signal(null, ...(ngDevMode ? [{ debugName: "activeOptionId" }] : /* istanbul ignore next */ []));
|
|
971
|
+
/** @internal */
|
|
972
|
+
isOpen = signal(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : /* istanbul ignore next */ []));
|
|
973
|
+
/** @internal */
|
|
974
|
+
optionsList = signal([], ...(ngDevMode ? [{ debugName: "optionsList" }] : /* istanbul ignore next */ []));
|
|
975
|
+
/** @internal */
|
|
976
|
+
panelRef = viewChild('panel', ...(ngDevMode ? [{ debugName: "panelRef" }] : /* istanbul ignore next */ []));
|
|
977
|
+
/** @internal */
|
|
978
|
+
triggerId = `llm-select-trigger-${nextId$4}`;
|
|
979
|
+
/** @internal */
|
|
980
|
+
panelId = `llm-select-panel-${nextId$4}`;
|
|
981
|
+
/** @internal */
|
|
982
|
+
errorId = `llm-select-errors-${nextId$4++}`;
|
|
983
|
+
/** @internal */
|
|
984
|
+
selectedLabel = computed(() => this.optionsList().find((o) => o.value === this.value())?.labelText ?? '', ...(ngDevMode ? [{ debugName: "selectedLabel" }] : /* istanbul ignore next */ []));
|
|
985
|
+
/** @internal */
|
|
986
|
+
showErrors = computed(() => this.touched() && this.invalid() && this.errors().length > 0, ...(ngDevMode ? [{ debugName: "showErrors" }] : /* istanbul ignore next */ []));
|
|
987
|
+
/** @internal */
|
|
988
|
+
hostClasses = computed(() => {
|
|
989
|
+
const classes = [];
|
|
990
|
+
if (this.isOpen())
|
|
991
|
+
classes.push('is-open');
|
|
992
|
+
if (this.disabled())
|
|
993
|
+
classes.push('is-disabled');
|
|
994
|
+
if (this.invalid())
|
|
995
|
+
classes.push('is-invalid');
|
|
996
|
+
if (this.touched())
|
|
997
|
+
classes.push('is-touched');
|
|
998
|
+
return classes.join(' ');
|
|
999
|
+
}, ...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
|
|
1000
|
+
/** @internal */
|
|
1001
|
+
keyManager = null;
|
|
1002
|
+
outsideClickHandler = null;
|
|
1003
|
+
elementRef = inject(ElementRef);
|
|
1004
|
+
/** @internal — called by LlmOption on init */
|
|
1005
|
+
registerOption(id, value, labelText, disabled) {
|
|
1006
|
+
this.optionsList.update((list) => [...list, { id, value, labelText, disabled }]);
|
|
1007
|
+
}
|
|
1008
|
+
/** @internal — called by LlmOption on destroy */
|
|
1009
|
+
unregisterOption(id) {
|
|
1010
|
+
this.optionsList.update((list) => list.filter((o) => o.id !== id));
|
|
1011
|
+
}
|
|
1012
|
+
/** @internal — called by LlmOption on select */
|
|
1013
|
+
select(v) {
|
|
1014
|
+
if (!this.disabled()) {
|
|
1015
|
+
this.value.set(v);
|
|
1016
|
+
this.close();
|
|
1017
|
+
}
|
|
1018
|
+
}
|
|
1019
|
+
/** @internal — called by LlmOption on interaction */
|
|
1020
|
+
markTouched() {
|
|
1021
|
+
this.touched.set(true);
|
|
1022
|
+
}
|
|
1023
|
+
/** @internal */
|
|
1024
|
+
onTriggerClick() {
|
|
1025
|
+
if (this.disabled())
|
|
1026
|
+
return;
|
|
1027
|
+
if (this.isOpen()) {
|
|
1028
|
+
this.close();
|
|
1029
|
+
}
|
|
1030
|
+
else {
|
|
1031
|
+
this.open();
|
|
1032
|
+
}
|
|
1033
|
+
}
|
|
1034
|
+
/** @internal */
|
|
1035
|
+
onTriggerBlur() {
|
|
1036
|
+
if (!this.isOpen()) {
|
|
1037
|
+
this.touched.set(true);
|
|
1038
|
+
}
|
|
1039
|
+
}
|
|
1040
|
+
/** @internal */
|
|
1041
|
+
onPanelToggle(event) {
|
|
1042
|
+
const toggleEvent = event;
|
|
1043
|
+
if (toggleEvent.newState === 'closed') {
|
|
1044
|
+
this.isOpen.set(false);
|
|
1045
|
+
this.activeOptionId.set(null);
|
|
1046
|
+
}
|
|
1047
|
+
}
|
|
1048
|
+
/** @internal */
|
|
1049
|
+
onKeydown(event) {
|
|
1050
|
+
if (this.disabled())
|
|
1051
|
+
return;
|
|
1052
|
+
switch (event.key) {
|
|
1053
|
+
case 'Enter':
|
|
1054
|
+
case ' ': {
|
|
1055
|
+
event.preventDefault();
|
|
1056
|
+
if (!this.isOpen()) {
|
|
1057
|
+
this.open();
|
|
1058
|
+
}
|
|
1059
|
+
else {
|
|
1060
|
+
const activeItem = this.keyManager?.activeItem;
|
|
1061
|
+
if (activeItem) {
|
|
1062
|
+
this.select(activeItem.value);
|
|
1063
|
+
}
|
|
1064
|
+
}
|
|
1065
|
+
break;
|
|
1066
|
+
}
|
|
1067
|
+
case 'Escape': {
|
|
1068
|
+
event.preventDefault();
|
|
1069
|
+
this.close();
|
|
1070
|
+
break;
|
|
1071
|
+
}
|
|
1072
|
+
default: {
|
|
1073
|
+
const isNav = ['ArrowDown', 'ArrowUp', 'ArrowLeft', 'ArrowRight', 'Home', 'End'].includes(event.key);
|
|
1074
|
+
const isTypeahead = event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey;
|
|
1075
|
+
if ((isNav || isTypeahead) && !this.isOpen()) {
|
|
1076
|
+
this.open();
|
|
1077
|
+
if (isNav)
|
|
1078
|
+
return; // open() already sets active item
|
|
1079
|
+
}
|
|
1080
|
+
this.keyManager?.onKeydown(event);
|
|
1081
|
+
}
|
|
1082
|
+
}
|
|
1083
|
+
}
|
|
1084
|
+
open() {
|
|
1085
|
+
const panel = this.panelRef();
|
|
1086
|
+
if (!panel)
|
|
1087
|
+
return;
|
|
1088
|
+
panel.nativeElement.showPopover();
|
|
1089
|
+
this.isOpen.set(true);
|
|
1090
|
+
// (Re)create key manager with current options
|
|
1091
|
+
const items = this.optionsList().map((o) => new SelectOptionItem(o.id, o.value, o.labelText, o.disabled, this.activeOptionId));
|
|
1092
|
+
this.keyManager = new ActiveDescendantKeyManager(items)
|
|
1093
|
+
.withWrap()
|
|
1094
|
+
.withTypeAhead(500)
|
|
1095
|
+
.withHomeAndEnd()
|
|
1096
|
+
.withVerticalOrientation();
|
|
1097
|
+
// Set active option to currently selected or first enabled
|
|
1098
|
+
const selectedIdx = items.findIndex((i) => i.value === this.value() && !i.disabled);
|
|
1099
|
+
const firstEnabledIdx = items.findIndex((i) => !i.disabled);
|
|
1100
|
+
const activeIdx = selectedIdx >= 0 ? selectedIdx : firstEnabledIdx;
|
|
1101
|
+
if (activeIdx >= 0) {
|
|
1102
|
+
this.keyManager.setActiveItem(activeIdx);
|
|
1103
|
+
}
|
|
1104
|
+
// Outside click listener
|
|
1105
|
+
this.outsideClickHandler = (e) => {
|
|
1106
|
+
if (!this.elementRef.nativeElement.contains(e.target)) {
|
|
1107
|
+
this.close();
|
|
1108
|
+
}
|
|
1109
|
+
};
|
|
1110
|
+
document.addEventListener('click', this.outsideClickHandler);
|
|
1111
|
+
}
|
|
1112
|
+
close() {
|
|
1113
|
+
const panel = this.panelRef();
|
|
1114
|
+
if (!panel)
|
|
1115
|
+
return;
|
|
1116
|
+
try {
|
|
1117
|
+
panel.nativeElement.hidePopover();
|
|
1118
|
+
}
|
|
1119
|
+
catch {
|
|
1120
|
+
// Panel may already be hidden
|
|
1121
|
+
}
|
|
1122
|
+
this.isOpen.set(false);
|
|
1123
|
+
this.activeOptionId.set(null);
|
|
1124
|
+
this.keyManager = null;
|
|
1125
|
+
if (this.outsideClickHandler) {
|
|
1126
|
+
document.removeEventListener('click', this.outsideClickHandler);
|
|
1127
|
+
this.outsideClickHandler = null;
|
|
1128
|
+
}
|
|
1129
|
+
}
|
|
1130
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmSelect, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1131
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.4", type: LlmSelect, isStandalone: true, selector: "llm-select", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, errors: { classPropertyName: "errors", publicName: "errors", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", touched: "touchedChange" }, host: { attributes: { "role": "combobox" }, listeners: { "keydown": "onKeydown($event)" }, properties: { "class": "hostClasses()" } }, providers: [{ provide: LLM_SELECT, useExisting: LlmSelect }], viewQueries: [{ propertyName: "panelRef", first: true, predicate: ["panel"], descendants: true, isSignal: true }], ngImport: i0, template: `
|
|
1132
|
+
<button
|
|
1133
|
+
type="button"
|
|
1134
|
+
class="trigger"
|
|
1135
|
+
[id]="triggerId"
|
|
1136
|
+
[attr.aria-expanded]="isOpen()"
|
|
1137
|
+
aria-haspopup="listbox"
|
|
1138
|
+
[attr.aria-controls]="panelId"
|
|
1139
|
+
[attr.aria-activedescendant]="activeOptionId()"
|
|
1140
|
+
[attr.aria-invalid]="invalid() || null"
|
|
1141
|
+
[attr.disabled]="disabled() || null"
|
|
1142
|
+
(click)="onTriggerClick()"
|
|
1143
|
+
(blur)="onTriggerBlur()"
|
|
1144
|
+
>
|
|
1145
|
+
<span class="trigger-text">{{ selectedLabel() || placeholder() }}</span>
|
|
1146
|
+
<span class="trigger-icon" aria-hidden="true">▾</span>
|
|
1147
|
+
</button>
|
|
1148
|
+
|
|
1149
|
+
<div
|
|
1150
|
+
#panel
|
|
1151
|
+
[id]="panelId"
|
|
1152
|
+
popover="manual"
|
|
1153
|
+
role="listbox"
|
|
1154
|
+
class="panel"
|
|
1155
|
+
[attr.aria-labelledby]="triggerId"
|
|
1156
|
+
(toggle)="onPanelToggle($event)"
|
|
1157
|
+
>
|
|
1158
|
+
<ng-content />
|
|
1159
|
+
</div>
|
|
1160
|
+
|
|
1161
|
+
@if (showErrors()) {
|
|
1162
|
+
<div class="errors" [id]="errorId" aria-live="polite">
|
|
1163
|
+
@for (error of errors(); track error.kind) {
|
|
1164
|
+
<p class="error-message">{{ error.message }}</p>
|
|
1165
|
+
}
|
|
1166
|
+
</div>
|
|
1167
|
+
}
|
|
1168
|
+
`, isInline: true, styles: [":host{display:inline-block;position:relative;font-family:var(--ui-font-family);font-size:var(--ui-font-size-md)}.trigger{display:flex;align-items:center;justify-content:space-between;gap:var(--ui-spacing-2);width:100%;padding:var(--ui-spacing-2) var(--ui-spacing-3);background:var(--ui-color-input-bg);border:1px solid var(--ui-color-input-border);border-radius:var(--ui-radius-md);color:var(--ui-color-text);font-family:inherit;font-size:inherit;cursor:pointer;transition:border-color var(--ui-transition-fast),box-shadow var(--ui-transition-fast);anchor-name:--select-trigger}.trigger:hover:not(:disabled){border-color:var(--ui-color-input-border-hover)}.trigger:focus-visible{outline:none;box-shadow:var(--ui-focus-ring);border-color:var(--ui-color-input-border-focus)}.trigger:disabled{opacity:var(--ui-opacity-disabled);cursor:not-allowed}:host(.is-invalid) .trigger{border-color:var(--ui-color-input-border-invalid)}:host(.is-open) .trigger{border-color:var(--ui-color-input-border-focus);box-shadow:var(--ui-focus-ring)}.trigger-text{flex:1;text-align:start;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--ui-color-text)}.trigger-text:empty,.trigger[data-placeholder] .trigger-text{color:var(--ui-color-placeholder)}.trigger-icon{flex-shrink:0;font-size:var(--ui-font-size-xs);color:var(--ui-color-text-muted);transition:transform var(--ui-transition-fast)}:host(.is-open) .trigger-icon{transform:rotate(180deg)}.panel[popover]{position:absolute;position-anchor:--select-trigger;inset-block-start:anchor(bottom);inset-inline-start:anchor(left);min-width:anchor-size(width);margin-block-start:var(--ui-spacing-1);padding:var(--ui-spacing-1) 0;background:var(--ui-color-surface-raised);border:1px solid var(--ui-color-border);border-radius:var(--ui-radius-md);box-shadow:var(--ui-shadow-lg);z-index:var(--ui-z-dropdown);max-height:16rem;overflow-y:auto;opacity:0;transform:translateY(-4px);transition:opacity var(--ui-transition-normal),transform var(--ui-transition-normal)}.panel[popover]:popover-open{opacity:1;transform:translateY(0)}llm-option [role=option]{padding:var(--ui-spacing-2) var(--ui-spacing-3);cursor:pointer;color:var(--ui-color-text);transition:background var(--ui-transition-fast)}llm-option [role=option]:hover,llm-option [role=option].is-active{background:var(--ui-color-surface-sunken)}llm-option [role=option].is-selected{background:var(--ui-color-primary-light);color:var(--ui-color-primary);font-weight:var(--ui-font-weight-medium)}llm-option [role=option].is-disabled{opacity:var(--ui-opacity-disabled);cursor:not-allowed}.errors{margin-top:var(--ui-spacing-1)}.error-message{margin:0;font-size:var(--ui-font-size-xs);color:var(--ui-color-error-text)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1169
|
+
}
|
|
1170
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmSelect, decorators: [{
|
|
1171
|
+
type: Component,
|
|
1172
|
+
args: [{ selector: 'llm-select', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: `
|
|
1173
|
+
<button
|
|
1174
|
+
type="button"
|
|
1175
|
+
class="trigger"
|
|
1176
|
+
[id]="triggerId"
|
|
1177
|
+
[attr.aria-expanded]="isOpen()"
|
|
1178
|
+
aria-haspopup="listbox"
|
|
1179
|
+
[attr.aria-controls]="panelId"
|
|
1180
|
+
[attr.aria-activedescendant]="activeOptionId()"
|
|
1181
|
+
[attr.aria-invalid]="invalid() || null"
|
|
1182
|
+
[attr.disabled]="disabled() || null"
|
|
1183
|
+
(click)="onTriggerClick()"
|
|
1184
|
+
(blur)="onTriggerBlur()"
|
|
1185
|
+
>
|
|
1186
|
+
<span class="trigger-text">{{ selectedLabel() || placeholder() }}</span>
|
|
1187
|
+
<span class="trigger-icon" aria-hidden="true">▾</span>
|
|
1188
|
+
</button>
|
|
1189
|
+
|
|
1190
|
+
<div
|
|
1191
|
+
#panel
|
|
1192
|
+
[id]="panelId"
|
|
1193
|
+
popover="manual"
|
|
1194
|
+
role="listbox"
|
|
1195
|
+
class="panel"
|
|
1196
|
+
[attr.aria-labelledby]="triggerId"
|
|
1197
|
+
(toggle)="onPanelToggle($event)"
|
|
1198
|
+
>
|
|
1199
|
+
<ng-content />
|
|
1200
|
+
</div>
|
|
1201
|
+
|
|
1202
|
+
@if (showErrors()) {
|
|
1203
|
+
<div class="errors" [id]="errorId" aria-live="polite">
|
|
1204
|
+
@for (error of errors(); track error.kind) {
|
|
1205
|
+
<p class="error-message">{{ error.message }}</p>
|
|
1206
|
+
}
|
|
1207
|
+
</div>
|
|
1208
|
+
}
|
|
1209
|
+
`, host: {
|
|
1210
|
+
role: 'combobox',
|
|
1211
|
+
'[class]': 'hostClasses()',
|
|
1212
|
+
'(keydown)': 'onKeydown($event)',
|
|
1213
|
+
}, providers: [{ provide: LLM_SELECT, useExisting: LlmSelect }], styles: [":host{display:inline-block;position:relative;font-family:var(--ui-font-family);font-size:var(--ui-font-size-md)}.trigger{display:flex;align-items:center;justify-content:space-between;gap:var(--ui-spacing-2);width:100%;padding:var(--ui-spacing-2) var(--ui-spacing-3);background:var(--ui-color-input-bg);border:1px solid var(--ui-color-input-border);border-radius:var(--ui-radius-md);color:var(--ui-color-text);font-family:inherit;font-size:inherit;cursor:pointer;transition:border-color var(--ui-transition-fast),box-shadow var(--ui-transition-fast);anchor-name:--select-trigger}.trigger:hover:not(:disabled){border-color:var(--ui-color-input-border-hover)}.trigger:focus-visible{outline:none;box-shadow:var(--ui-focus-ring);border-color:var(--ui-color-input-border-focus)}.trigger:disabled{opacity:var(--ui-opacity-disabled);cursor:not-allowed}:host(.is-invalid) .trigger{border-color:var(--ui-color-input-border-invalid)}:host(.is-open) .trigger{border-color:var(--ui-color-input-border-focus);box-shadow:var(--ui-focus-ring)}.trigger-text{flex:1;text-align:start;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--ui-color-text)}.trigger-text:empty,.trigger[data-placeholder] .trigger-text{color:var(--ui-color-placeholder)}.trigger-icon{flex-shrink:0;font-size:var(--ui-font-size-xs);color:var(--ui-color-text-muted);transition:transform var(--ui-transition-fast)}:host(.is-open) .trigger-icon{transform:rotate(180deg)}.panel[popover]{position:absolute;position-anchor:--select-trigger;inset-block-start:anchor(bottom);inset-inline-start:anchor(left);min-width:anchor-size(width);margin-block-start:var(--ui-spacing-1);padding:var(--ui-spacing-1) 0;background:var(--ui-color-surface-raised);border:1px solid var(--ui-color-border);border-radius:var(--ui-radius-md);box-shadow:var(--ui-shadow-lg);z-index:var(--ui-z-dropdown);max-height:16rem;overflow-y:auto;opacity:0;transform:translateY(-4px);transition:opacity var(--ui-transition-normal),transform var(--ui-transition-normal)}.panel[popover]:popover-open{opacity:1;transform:translateY(0)}llm-option [role=option]{padding:var(--ui-spacing-2) var(--ui-spacing-3);cursor:pointer;color:var(--ui-color-text);transition:background var(--ui-transition-fast)}llm-option [role=option]:hover,llm-option [role=option].is-active{background:var(--ui-color-surface-sunken)}llm-option [role=option].is-selected{background:var(--ui-color-primary-light);color:var(--ui-color-primary);font-weight:var(--ui-font-weight-medium)}llm-option [role=option].is-disabled{opacity:var(--ui-opacity-disabled);cursor:not-allowed}.errors{margin-top:var(--ui-spacing-1)}.error-message{margin:0;font-size:var(--ui-font-size-xs);color:var(--ui-color-error-text)}\n"] }]
|
|
1214
|
+
}], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }, { type: i0.Output, args: ["touchedChange"] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], errors: [{ type: i0.Input, args: [{ isSignal: true, alias: "errors", required: false }] }], panelRef: [{ type: i0.ViewChild, args: ['panel', { isSignal: true }] }] } });
|
|
1215
|
+
|
|
1216
|
+
let nextOptionId = 0;
|
|
1217
|
+
/**
|
|
1218
|
+
* Option item for use inside `<llm-select>`.
|
|
1219
|
+
*
|
|
1220
|
+
* Usage:
|
|
1221
|
+
* ```html
|
|
1222
|
+
* <llm-option optionValue="us">United States</llm-option>
|
|
1223
|
+
* ```
|
|
1224
|
+
*/
|
|
1225
|
+
class LlmOption {
|
|
1226
|
+
/** The value this option represents. Required. */
|
|
1227
|
+
optionValue = input.required(...(ngDevMode ? [{ debugName: "optionValue" }] : /* istanbul ignore next */ []));
|
|
1228
|
+
/** Whether this option is disabled. */
|
|
1229
|
+
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
|
|
1230
|
+
/** @internal */
|
|
1231
|
+
optionId = `llm-option-${nextOptionId++}`;
|
|
1232
|
+
/** @internal */
|
|
1233
|
+
context = inject(LLM_SELECT);
|
|
1234
|
+
/** @internal */
|
|
1235
|
+
elementRef = inject(ElementRef);
|
|
1236
|
+
/** @internal */
|
|
1237
|
+
isSelected = computed(() => this.context.value() === this.optionValue(), ...(ngDevMode ? [{ debugName: "isSelected" }] : /* istanbul ignore next */ []));
|
|
1238
|
+
/** @internal */
|
|
1239
|
+
isActive = computed(() => this.context.activeOptionId() === this.optionId, ...(ngDevMode ? [{ debugName: "isActive" }] : /* istanbul ignore next */ []));
|
|
1240
|
+
ngOnInit() {
|
|
1241
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
1242
|
+
const labelText = (this.elementRef.nativeElement.textContent ?? '').trim();
|
|
1243
|
+
this.context.registerOption(this.optionId, this.optionValue(), labelText, this.disabled());
|
|
1244
|
+
}
|
|
1245
|
+
ngOnDestroy() {
|
|
1246
|
+
this.context.unregisterOption(this.optionId);
|
|
1247
|
+
}
|
|
1248
|
+
/** @internal */
|
|
1249
|
+
onClick() {
|
|
1250
|
+
if (this.disabled())
|
|
1251
|
+
return;
|
|
1252
|
+
this.context.select(this.optionValue());
|
|
1253
|
+
this.context.markTouched();
|
|
1254
|
+
}
|
|
1255
|
+
/** @internal */
|
|
1256
|
+
onMouseEnter() {
|
|
1257
|
+
if (!this.disabled()) {
|
|
1258
|
+
this.context.activeOptionId.set(this.optionId);
|
|
1259
|
+
}
|
|
1260
|
+
}
|
|
1261
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmOption, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1262
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.4", type: LlmOption, isStandalone: true, selector: "llm-option", inputs: { optionValue: { classPropertyName: "optionValue", publicName: "optionValue", isSignal: true, isRequired: true, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
|
|
1263
|
+
<!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->
|
|
1264
|
+
<div
|
|
1265
|
+
role="option"
|
|
1266
|
+
[attr.id]="optionId"
|
|
1267
|
+
[attr.aria-selected]="isSelected()"
|
|
1268
|
+
[attr.aria-disabled]="disabled() || null"
|
|
1269
|
+
[class.is-selected]="isSelected()"
|
|
1270
|
+
[class.is-active]="isActive()"
|
|
1271
|
+
[class.is-disabled]="disabled()"
|
|
1272
|
+
(click)="onClick()"
|
|
1273
|
+
(mouseenter)="onMouseEnter()"
|
|
1274
|
+
>
|
|
1275
|
+
<ng-content />
|
|
1276
|
+
</div>
|
|
1277
|
+
`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1278
|
+
}
|
|
1279
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmOption, decorators: [{
|
|
1280
|
+
type: Component,
|
|
1281
|
+
args: [{
|
|
1282
|
+
selector: 'llm-option',
|
|
1283
|
+
standalone: true,
|
|
1284
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
1285
|
+
template: `
|
|
1286
|
+
<!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->
|
|
1287
|
+
<div
|
|
1288
|
+
role="option"
|
|
1289
|
+
[attr.id]="optionId"
|
|
1290
|
+
[attr.aria-selected]="isSelected()"
|
|
1291
|
+
[attr.aria-disabled]="disabled() || null"
|
|
1292
|
+
[class.is-selected]="isSelected()"
|
|
1293
|
+
[class.is-active]="isActive()"
|
|
1294
|
+
[class.is-disabled]="disabled()"
|
|
1295
|
+
(click)="onClick()"
|
|
1296
|
+
(mouseenter)="onMouseEnter()"
|
|
1297
|
+
>
|
|
1298
|
+
<ng-content />
|
|
1299
|
+
</div>
|
|
1300
|
+
`,
|
|
1301
|
+
}]
|
|
1302
|
+
}], propDecorators: { optionValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionValue", required: true }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }] } });
|
|
1303
|
+
|
|
1304
|
+
const LLM_DIALOG = new InjectionToken('LLM_DIALOG');
|
|
1305
|
+
|
|
1306
|
+
let nextId$3 = 0;
|
|
1307
|
+
/**
|
|
1308
|
+
* Accessible modal dialog using the native `<dialog>` element.
|
|
1309
|
+
* Includes focus trap, Escape to close, backdrop click to close, and animation.
|
|
1310
|
+
* Compose with `llm-dialog-header`, `llm-dialog-content`, and `llm-dialog-footer`.
|
|
1311
|
+
*
|
|
1312
|
+
* Usage:
|
|
1313
|
+
* ```html
|
|
1314
|
+
* <llm-dialog [(open)]="isOpen">
|
|
1315
|
+
* <llm-dialog-header>Dialog Title</llm-dialog-header>
|
|
1316
|
+
* <llm-dialog-content>Dialog body content.</llm-dialog-content>
|
|
1317
|
+
* <llm-dialog-footer>
|
|
1318
|
+
* <llm-button variant="primary" (click)="isOpen = false">Confirm</llm-button>
|
|
1319
|
+
* </llm-dialog-footer>
|
|
1320
|
+
* </llm-dialog>
|
|
1321
|
+
* ```
|
|
1322
|
+
*/
|
|
1323
|
+
class LlmDialog {
|
|
1324
|
+
/** Whether the dialog is open. Supports two-way binding: [(open)]="isOpen". */
|
|
1325
|
+
open = model(false, ...(ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []));
|
|
1326
|
+
/** Whether clicking the backdrop closes the dialog. */
|
|
1327
|
+
closeOnBackdrop = input(true, ...(ngDevMode ? [{ debugName: "closeOnBackdrop" }] : /* istanbul ignore next */ []));
|
|
1328
|
+
/** Size of the dialog panel. */
|
|
1329
|
+
size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
1330
|
+
/** Accessible label for the dialog (use instead of aria-labelledby when no header is present). */
|
|
1331
|
+
ariaLabel = input('', { ...(ngDevMode ? { debugName: "ariaLabel" } : /* istanbul ignore next */ {}), alias: 'aria-label' });
|
|
1332
|
+
/** ID of the element that labels the dialog (defaults to the llm-dialog-header id). */
|
|
1333
|
+
ariaLabelledby = input('', { ...(ngDevMode ? { debugName: "ariaLabelledby" } : /* istanbul ignore next */ {}), alias: 'aria-labelledby' });
|
|
1334
|
+
/** @internal — referenced by LlmDialogHeader via LLM_DIALOG token */
|
|
1335
|
+
headerId = `llm-dialog-header-${nextId$3}`;
|
|
1336
|
+
dialogId = `llm-dialog-${nextId$3++}`;
|
|
1337
|
+
dialogRef = viewChild('dialogEl', ...(ngDevMode ? [{ debugName: "dialogRef" }] : /* istanbul ignore next */ []));
|
|
1338
|
+
triggerEl = signal(null, ...(ngDevMode ? [{ debugName: "triggerEl" }] : /* istanbul ignore next */ []));
|
|
1339
|
+
panelClass = computed(() => `panel size-${this.size()}`, ...(ngDevMode ? [{ debugName: "panelClass" }] : /* istanbul ignore next */ []));
|
|
1340
|
+
hostClasses = computed(() => (this.open() ? 'is-open' : ''), ...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
|
|
1341
|
+
constructor() {
|
|
1342
|
+
effect(() => {
|
|
1343
|
+
const dialog = this.dialogRef()?.nativeElement;
|
|
1344
|
+
if (!dialog)
|
|
1345
|
+
return;
|
|
1346
|
+
if (this.open()) {
|
|
1347
|
+
this.triggerEl.set(document.activeElement);
|
|
1348
|
+
dialog.showModal();
|
|
1349
|
+
}
|
|
1350
|
+
else {
|
|
1351
|
+
if (dialog.open)
|
|
1352
|
+
dialog.close();
|
|
1353
|
+
this.triggerEl()?.focus();
|
|
1354
|
+
this.triggerEl.set(null);
|
|
1355
|
+
}
|
|
1356
|
+
});
|
|
1357
|
+
}
|
|
1358
|
+
onCancel(event) {
|
|
1359
|
+
event.preventDefault();
|
|
1360
|
+
this.open.set(false);
|
|
1361
|
+
}
|
|
1362
|
+
onBackdropClick(event) {
|
|
1363
|
+
if (this.closeOnBackdrop() && event.target === this.dialogRef()?.nativeElement) {
|
|
1364
|
+
this.open.set(false);
|
|
1365
|
+
}
|
|
1366
|
+
}
|
|
1367
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmDialog, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1368
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.2.4", type: LlmDialog, isStandalone: true, selector: "llm-dialog", inputs: { open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null }, closeOnBackdrop: { classPropertyName: "closeOnBackdrop", publicName: "closeOnBackdrop", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "aria-label", isSignal: true, isRequired: false, transformFunction: null }, ariaLabelledby: { classPropertyName: "ariaLabelledby", publicName: "aria-labelledby", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { open: "openChange" }, host: { properties: { "class": "hostClasses()" } }, providers: [
|
|
1369
|
+
{
|
|
1370
|
+
provide: LLM_DIALOG,
|
|
1371
|
+
useFactory: (dialog) => ({
|
|
1372
|
+
headerId: dialog.headerId,
|
|
1373
|
+
close: () => dialog.open.set(false),
|
|
1374
|
+
}),
|
|
1375
|
+
deps: [LlmDialog],
|
|
1376
|
+
},
|
|
1377
|
+
], viewQueries: [{ propertyName: "dialogRef", first: true, predicate: ["dialogEl"], descendants: true, isSignal: true }], ngImport: i0, template: `
|
|
1378
|
+
<!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->
|
|
1379
|
+
<dialog
|
|
1380
|
+
#dialogEl
|
|
1381
|
+
[attr.aria-label]="ariaLabel() || null"
|
|
1382
|
+
[attr.aria-labelledby]="ariaLabel() ? null : (ariaLabelledby() || headerId)"
|
|
1383
|
+
aria-modal="true"
|
|
1384
|
+
[cdkTrapFocus]="open()"
|
|
1385
|
+
(cancel)="onCancel($event)"
|
|
1386
|
+
(click)="onBackdropClick($event)"
|
|
1387
|
+
>
|
|
1388
|
+
<div [class]="panelClass()">
|
|
1389
|
+
<ng-content />
|
|
1390
|
+
</div>
|
|
1391
|
+
</dialog>
|
|
1392
|
+
`, isInline: true, styles: ["llm-dialog{display:contents}dialog{all:unset;position:fixed;inset:0;margin:auto;display:none;flex-direction:column;max-height:calc(100dvh - var(--ui-spacing-8));border-radius:var(--ui-radius-lg);background:var(--ui-color-surface);box-shadow:var(--ui-shadow-xl, 0 20px 60px rgba(0, 0, 0, .3));color:var(--ui-color-text);overflow:hidden;opacity:0;transform:scale(.95);transition:opacity var(--ui-duration-slow) var(--ui-ease-out, ease-out),transform var(--ui-duration-slow) var(--ui-ease-out, ease-out),display var(--ui-duration-slow) allow-discrete,overlay var(--ui-duration-slow) allow-discrete}dialog[open]{display:flex;opacity:1;transform:scale(1)}@starting-style{dialog[open]{opacity:0;transform:scale(.95)}}dialog::backdrop{background:#00000080;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);transition:opacity var(--ui-duration-slow) var(--ui-ease-out, ease-out),display var(--ui-duration-slow) allow-discrete,overlay var(--ui-duration-slow) allow-discrete}@starting-style{dialog[open]::backdrop{opacity:0}}@media(prefers-color-scheme:dark){dialog::backdrop{background:#000000b3}}[data-theme=dark] dialog::backdrop{background:#000000b3}.panel{display:flex;flex-direction:column;width:100%;max-height:inherit;overflow:hidden}.size-sm{width:min(24rem,90vw)}.size-md{width:min(36rem,90vw)}.size-lg{width:min(48rem,90vw)}.size-xl{width:min(64rem,90vw)}.size-full{width:100vw;height:100dvh;max-height:100dvh;border-radius:0;margin:0}llm-dialog-header{display:flex;align-items:center;justify-content:space-between;padding:var(--ui-spacing-4) var(--ui-spacing-5);border-bottom:1px solid var(--ui-color-border);font-size:var(--ui-font-size-xl);font-weight:600;letter-spacing:var(--ui-letter-spacing-tight);color:var(--ui-color-text);flex-shrink:0}llm-dialog-content{display:block;padding:var(--ui-spacing-5);overflow-y:auto;flex:1;color:var(--ui-color-text)}llm-dialog-footer{display:flex;align-items:center;justify-content:flex-end;gap:var(--ui-spacing-2);padding:var(--ui-spacing-4) var(--ui-spacing-5);border-top:1px solid var(--ui-color-border);flex-shrink:0}.close-btn{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;width:1.75rem;height:1.75rem;padding:0;margin-left:var(--ui-spacing-3);background:transparent;border:none;border-radius:var(--ui-radius-sm);cursor:pointer;color:var(--ui-color-text-muted);transition:background-color var(--ui-transition-fast),color var(--ui-transition-fast);line-height:1}.close-btn:hover{background-color:var(--ui-color-surface-sunken);color:var(--ui-color-text)}.close-btn:focus-visible{outline:none;box-shadow:var(--ui-focus-ring)}\n"], dependencies: [{ kind: "ngmodule", type: A11yModule }, { kind: "directive", type: i1$1.CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1393
|
+
}
|
|
1394
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmDialog, decorators: [{
|
|
1395
|
+
type: Component,
|
|
1396
|
+
args: [{ selector: 'llm-dialog', standalone: true, imports: [A11yModule], changeDetection: ChangeDetectionStrategy.OnPush, providers: [
|
|
1397
|
+
{
|
|
1398
|
+
provide: LLM_DIALOG,
|
|
1399
|
+
useFactory: (dialog) => ({
|
|
1400
|
+
headerId: dialog.headerId,
|
|
1401
|
+
close: () => dialog.open.set(false),
|
|
1402
|
+
}),
|
|
1403
|
+
deps: [LlmDialog],
|
|
1404
|
+
},
|
|
1405
|
+
], template: `
|
|
1406
|
+
<!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->
|
|
1407
|
+
<dialog
|
|
1408
|
+
#dialogEl
|
|
1409
|
+
[attr.aria-label]="ariaLabel() || null"
|
|
1410
|
+
[attr.aria-labelledby]="ariaLabel() ? null : (ariaLabelledby() || headerId)"
|
|
1411
|
+
aria-modal="true"
|
|
1412
|
+
[cdkTrapFocus]="open()"
|
|
1413
|
+
(cancel)="onCancel($event)"
|
|
1414
|
+
(click)="onBackdropClick($event)"
|
|
1415
|
+
>
|
|
1416
|
+
<div [class]="panelClass()">
|
|
1417
|
+
<ng-content />
|
|
1418
|
+
</div>
|
|
1419
|
+
</dialog>
|
|
1420
|
+
`, host: {
|
|
1421
|
+
'[class]': 'hostClasses()',
|
|
1422
|
+
}, styles: ["llm-dialog{display:contents}dialog{all:unset;position:fixed;inset:0;margin:auto;display:none;flex-direction:column;max-height:calc(100dvh - var(--ui-spacing-8));border-radius:var(--ui-radius-lg);background:var(--ui-color-surface);box-shadow:var(--ui-shadow-xl, 0 20px 60px rgba(0, 0, 0, .3));color:var(--ui-color-text);overflow:hidden;opacity:0;transform:scale(.95);transition:opacity var(--ui-duration-slow) var(--ui-ease-out, ease-out),transform var(--ui-duration-slow) var(--ui-ease-out, ease-out),display var(--ui-duration-slow) allow-discrete,overlay var(--ui-duration-slow) allow-discrete}dialog[open]{display:flex;opacity:1;transform:scale(1)}@starting-style{dialog[open]{opacity:0;transform:scale(.95)}}dialog::backdrop{background:#00000080;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);transition:opacity var(--ui-duration-slow) var(--ui-ease-out, ease-out),display var(--ui-duration-slow) allow-discrete,overlay var(--ui-duration-slow) allow-discrete}@starting-style{dialog[open]::backdrop{opacity:0}}@media(prefers-color-scheme:dark){dialog::backdrop{background:#000000b3}}[data-theme=dark] dialog::backdrop{background:#000000b3}.panel{display:flex;flex-direction:column;width:100%;max-height:inherit;overflow:hidden}.size-sm{width:min(24rem,90vw)}.size-md{width:min(36rem,90vw)}.size-lg{width:min(48rem,90vw)}.size-xl{width:min(64rem,90vw)}.size-full{width:100vw;height:100dvh;max-height:100dvh;border-radius:0;margin:0}llm-dialog-header{display:flex;align-items:center;justify-content:space-between;padding:var(--ui-spacing-4) var(--ui-spacing-5);border-bottom:1px solid var(--ui-color-border);font-size:var(--ui-font-size-xl);font-weight:600;letter-spacing:var(--ui-letter-spacing-tight);color:var(--ui-color-text);flex-shrink:0}llm-dialog-content{display:block;padding:var(--ui-spacing-5);overflow-y:auto;flex:1;color:var(--ui-color-text)}llm-dialog-footer{display:flex;align-items:center;justify-content:flex-end;gap:var(--ui-spacing-2);padding:var(--ui-spacing-4) var(--ui-spacing-5);border-top:1px solid var(--ui-color-border);flex-shrink:0}.close-btn{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;width:1.75rem;height:1.75rem;padding:0;margin-left:var(--ui-spacing-3);background:transparent;border:none;border-radius:var(--ui-radius-sm);cursor:pointer;color:var(--ui-color-text-muted);transition:background-color var(--ui-transition-fast),color var(--ui-transition-fast);line-height:1}.close-btn:hover{background-color:var(--ui-color-surface-sunken);color:var(--ui-color-text)}.close-btn:focus-visible{outline:none;box-shadow:var(--ui-focus-ring)}\n"] }]
|
|
1423
|
+
}], ctorParameters: () => [], propDecorators: { open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }, { type: i0.Output, args: ["openChange"] }], closeOnBackdrop: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnBackdrop", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "aria-label", required: false }] }], ariaLabelledby: [{ type: i0.Input, args: [{ isSignal: true, alias: "aria-labelledby", required: false }] }], dialogRef: [{ type: i0.ViewChild, args: ['dialogEl', { isSignal: true }] }] } });
|
|
1424
|
+
/**
|
|
1425
|
+
* Header slot for `llm-dialog`. Renders above content with a bottom separator.
|
|
1426
|
+
* Automatically receives the correct `id` for `aria-labelledby` association.
|
|
1427
|
+
*/
|
|
1428
|
+
class LlmDialogHeader {
|
|
1429
|
+
context = inject(LLM_DIALOG);
|
|
1430
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmDialogHeader, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1431
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.4", type: LlmDialogHeader, isStandalone: true, selector: "llm-dialog-header", host: { properties: { "attr.id": "context.headerId" } }, ngImport: i0, template: `
|
|
1432
|
+
<ng-content />
|
|
1433
|
+
<button
|
|
1434
|
+
class="close-btn"
|
|
1435
|
+
type="button"
|
|
1436
|
+
aria-label="Close dialog"
|
|
1437
|
+
(click)="context.close()"
|
|
1438
|
+
>
|
|
1439
|
+
<svg
|
|
1440
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
1441
|
+
width="14"
|
|
1442
|
+
height="14"
|
|
1443
|
+
viewBox="0 0 24 24"
|
|
1444
|
+
fill="none"
|
|
1445
|
+
stroke="currentColor"
|
|
1446
|
+
stroke-width="2.5"
|
|
1447
|
+
stroke-linecap="round"
|
|
1448
|
+
stroke-linejoin="round"
|
|
1449
|
+
aria-hidden="true"
|
|
1450
|
+
focusable="false"
|
|
1451
|
+
>
|
|
1452
|
+
<line x1="18" y1="6" x2="6" y2="18" />
|
|
1453
|
+
<line x1="6" y1="6" x2="18" y2="18" />
|
|
1454
|
+
</svg>
|
|
1455
|
+
</button>
|
|
1456
|
+
`, isInline: true, styles: ["llm-dialog{display:contents}dialog{all:unset;position:fixed;inset:0;margin:auto;display:none;flex-direction:column;max-height:calc(100dvh - var(--ui-spacing-8));border-radius:var(--ui-radius-lg);background:var(--ui-color-surface);box-shadow:var(--ui-shadow-xl, 0 20px 60px rgba(0, 0, 0, .3));color:var(--ui-color-text);overflow:hidden;opacity:0;transform:scale(.95);transition:opacity var(--ui-duration-slow) var(--ui-ease-out, ease-out),transform var(--ui-duration-slow) var(--ui-ease-out, ease-out),display var(--ui-duration-slow) allow-discrete,overlay var(--ui-duration-slow) allow-discrete}dialog[open]{display:flex;opacity:1;transform:scale(1)}@starting-style{dialog[open]{opacity:0;transform:scale(.95)}}dialog::backdrop{background:#00000080;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);transition:opacity var(--ui-duration-slow) var(--ui-ease-out, ease-out),display var(--ui-duration-slow) allow-discrete,overlay var(--ui-duration-slow) allow-discrete}@starting-style{dialog[open]::backdrop{opacity:0}}@media(prefers-color-scheme:dark){dialog::backdrop{background:#000000b3}}[data-theme=dark] dialog::backdrop{background:#000000b3}.panel{display:flex;flex-direction:column;width:100%;max-height:inherit;overflow:hidden}.size-sm{width:min(24rem,90vw)}.size-md{width:min(36rem,90vw)}.size-lg{width:min(48rem,90vw)}.size-xl{width:min(64rem,90vw)}.size-full{width:100vw;height:100dvh;max-height:100dvh;border-radius:0;margin:0}llm-dialog-header{display:flex;align-items:center;justify-content:space-between;padding:var(--ui-spacing-4) var(--ui-spacing-5);border-bottom:1px solid var(--ui-color-border);font-size:var(--ui-font-size-xl);font-weight:600;letter-spacing:var(--ui-letter-spacing-tight);color:var(--ui-color-text);flex-shrink:0}llm-dialog-content{display:block;padding:var(--ui-spacing-5);overflow-y:auto;flex:1;color:var(--ui-color-text)}llm-dialog-footer{display:flex;align-items:center;justify-content:flex-end;gap:var(--ui-spacing-2);padding:var(--ui-spacing-4) var(--ui-spacing-5);border-top:1px solid var(--ui-color-border);flex-shrink:0}.close-btn{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;width:1.75rem;height:1.75rem;padding:0;margin-left:var(--ui-spacing-3);background:transparent;border:none;border-radius:var(--ui-radius-sm);cursor:pointer;color:var(--ui-color-text-muted);transition:background-color var(--ui-transition-fast),color var(--ui-transition-fast);line-height:1}.close-btn:hover{background-color:var(--ui-color-surface-sunken);color:var(--ui-color-text)}.close-btn:focus-visible{outline:none;box-shadow:var(--ui-focus-ring)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1457
|
+
}
|
|
1458
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmDialogHeader, decorators: [{
|
|
1459
|
+
type: Component,
|
|
1460
|
+
args: [{ selector: 'llm-dialog-header', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: `
|
|
1461
|
+
<ng-content />
|
|
1462
|
+
<button
|
|
1463
|
+
class="close-btn"
|
|
1464
|
+
type="button"
|
|
1465
|
+
aria-label="Close dialog"
|
|
1466
|
+
(click)="context.close()"
|
|
1467
|
+
>
|
|
1468
|
+
<svg
|
|
1469
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
1470
|
+
width="14"
|
|
1471
|
+
height="14"
|
|
1472
|
+
viewBox="0 0 24 24"
|
|
1473
|
+
fill="none"
|
|
1474
|
+
stroke="currentColor"
|
|
1475
|
+
stroke-width="2.5"
|
|
1476
|
+
stroke-linecap="round"
|
|
1477
|
+
stroke-linejoin="round"
|
|
1478
|
+
aria-hidden="true"
|
|
1479
|
+
focusable="false"
|
|
1480
|
+
>
|
|
1481
|
+
<line x1="18" y1="6" x2="6" y2="18" />
|
|
1482
|
+
<line x1="6" y1="6" x2="18" y2="18" />
|
|
1483
|
+
</svg>
|
|
1484
|
+
</button>
|
|
1485
|
+
`, host: {
|
|
1486
|
+
'[attr.id]': 'context.headerId',
|
|
1487
|
+
}, styles: ["llm-dialog{display:contents}dialog{all:unset;position:fixed;inset:0;margin:auto;display:none;flex-direction:column;max-height:calc(100dvh - var(--ui-spacing-8));border-radius:var(--ui-radius-lg);background:var(--ui-color-surface);box-shadow:var(--ui-shadow-xl, 0 20px 60px rgba(0, 0, 0, .3));color:var(--ui-color-text);overflow:hidden;opacity:0;transform:scale(.95);transition:opacity var(--ui-duration-slow) var(--ui-ease-out, ease-out),transform var(--ui-duration-slow) var(--ui-ease-out, ease-out),display var(--ui-duration-slow) allow-discrete,overlay var(--ui-duration-slow) allow-discrete}dialog[open]{display:flex;opacity:1;transform:scale(1)}@starting-style{dialog[open]{opacity:0;transform:scale(.95)}}dialog::backdrop{background:#00000080;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);transition:opacity var(--ui-duration-slow) var(--ui-ease-out, ease-out),display var(--ui-duration-slow) allow-discrete,overlay var(--ui-duration-slow) allow-discrete}@starting-style{dialog[open]::backdrop{opacity:0}}@media(prefers-color-scheme:dark){dialog::backdrop{background:#000000b3}}[data-theme=dark] dialog::backdrop{background:#000000b3}.panel{display:flex;flex-direction:column;width:100%;max-height:inherit;overflow:hidden}.size-sm{width:min(24rem,90vw)}.size-md{width:min(36rem,90vw)}.size-lg{width:min(48rem,90vw)}.size-xl{width:min(64rem,90vw)}.size-full{width:100vw;height:100dvh;max-height:100dvh;border-radius:0;margin:0}llm-dialog-header{display:flex;align-items:center;justify-content:space-between;padding:var(--ui-spacing-4) var(--ui-spacing-5);border-bottom:1px solid var(--ui-color-border);font-size:var(--ui-font-size-xl);font-weight:600;letter-spacing:var(--ui-letter-spacing-tight);color:var(--ui-color-text);flex-shrink:0}llm-dialog-content{display:block;padding:var(--ui-spacing-5);overflow-y:auto;flex:1;color:var(--ui-color-text)}llm-dialog-footer{display:flex;align-items:center;justify-content:flex-end;gap:var(--ui-spacing-2);padding:var(--ui-spacing-4) var(--ui-spacing-5);border-top:1px solid var(--ui-color-border);flex-shrink:0}.close-btn{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;width:1.75rem;height:1.75rem;padding:0;margin-left:var(--ui-spacing-3);background:transparent;border:none;border-radius:var(--ui-radius-sm);cursor:pointer;color:var(--ui-color-text-muted);transition:background-color var(--ui-transition-fast),color var(--ui-transition-fast);line-height:1}.close-btn:hover{background-color:var(--ui-color-surface-sunken);color:var(--ui-color-text)}.close-btn:focus-visible{outline:none;box-shadow:var(--ui-focus-ring)}\n"] }]
|
|
1488
|
+
}] });
|
|
1489
|
+
/**
|
|
1490
|
+
* Content slot for `llm-dialog`. Scrollable primary content area.
|
|
1491
|
+
*/
|
|
1492
|
+
class LlmDialogContent {
|
|
1493
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmDialogContent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1494
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.4", type: LlmDialogContent, isStandalone: true, selector: "llm-dialog-content", ngImport: i0, template: `<ng-content />`, isInline: true, styles: ["llm-dialog{display:contents}dialog{all:unset;position:fixed;inset:0;margin:auto;display:none;flex-direction:column;max-height:calc(100dvh - var(--ui-spacing-8));border-radius:var(--ui-radius-lg);background:var(--ui-color-surface);box-shadow:var(--ui-shadow-xl, 0 20px 60px rgba(0, 0, 0, .3));color:var(--ui-color-text);overflow:hidden;opacity:0;transform:scale(.95);transition:opacity var(--ui-duration-slow) var(--ui-ease-out, ease-out),transform var(--ui-duration-slow) var(--ui-ease-out, ease-out),display var(--ui-duration-slow) allow-discrete,overlay var(--ui-duration-slow) allow-discrete}dialog[open]{display:flex;opacity:1;transform:scale(1)}@starting-style{dialog[open]{opacity:0;transform:scale(.95)}}dialog::backdrop{background:#00000080;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);transition:opacity var(--ui-duration-slow) var(--ui-ease-out, ease-out),display var(--ui-duration-slow) allow-discrete,overlay var(--ui-duration-slow) allow-discrete}@starting-style{dialog[open]::backdrop{opacity:0}}@media(prefers-color-scheme:dark){dialog::backdrop{background:#000000b3}}[data-theme=dark] dialog::backdrop{background:#000000b3}.panel{display:flex;flex-direction:column;width:100%;max-height:inherit;overflow:hidden}.size-sm{width:min(24rem,90vw)}.size-md{width:min(36rem,90vw)}.size-lg{width:min(48rem,90vw)}.size-xl{width:min(64rem,90vw)}.size-full{width:100vw;height:100dvh;max-height:100dvh;border-radius:0;margin:0}llm-dialog-header{display:flex;align-items:center;justify-content:space-between;padding:var(--ui-spacing-4) var(--ui-spacing-5);border-bottom:1px solid var(--ui-color-border);font-size:var(--ui-font-size-xl);font-weight:600;letter-spacing:var(--ui-letter-spacing-tight);color:var(--ui-color-text);flex-shrink:0}llm-dialog-content{display:block;padding:var(--ui-spacing-5);overflow-y:auto;flex:1;color:var(--ui-color-text)}llm-dialog-footer{display:flex;align-items:center;justify-content:flex-end;gap:var(--ui-spacing-2);padding:var(--ui-spacing-4) var(--ui-spacing-5);border-top:1px solid var(--ui-color-border);flex-shrink:0}.close-btn{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;width:1.75rem;height:1.75rem;padding:0;margin-left:var(--ui-spacing-3);background:transparent;border:none;border-radius:var(--ui-radius-sm);cursor:pointer;color:var(--ui-color-text-muted);transition:background-color var(--ui-transition-fast),color var(--ui-transition-fast);line-height:1}.close-btn:hover{background-color:var(--ui-color-surface-sunken);color:var(--ui-color-text)}.close-btn:focus-visible{outline:none;box-shadow:var(--ui-focus-ring)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1495
|
+
}
|
|
1496
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmDialogContent, decorators: [{
|
|
1497
|
+
type: Component,
|
|
1498
|
+
args: [{ selector: 'llm-dialog-content', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: `<ng-content />`, styles: ["llm-dialog{display:contents}dialog{all:unset;position:fixed;inset:0;margin:auto;display:none;flex-direction:column;max-height:calc(100dvh - var(--ui-spacing-8));border-radius:var(--ui-radius-lg);background:var(--ui-color-surface);box-shadow:var(--ui-shadow-xl, 0 20px 60px rgba(0, 0, 0, .3));color:var(--ui-color-text);overflow:hidden;opacity:0;transform:scale(.95);transition:opacity var(--ui-duration-slow) var(--ui-ease-out, ease-out),transform var(--ui-duration-slow) var(--ui-ease-out, ease-out),display var(--ui-duration-slow) allow-discrete,overlay var(--ui-duration-slow) allow-discrete}dialog[open]{display:flex;opacity:1;transform:scale(1)}@starting-style{dialog[open]{opacity:0;transform:scale(.95)}}dialog::backdrop{background:#00000080;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);transition:opacity var(--ui-duration-slow) var(--ui-ease-out, ease-out),display var(--ui-duration-slow) allow-discrete,overlay var(--ui-duration-slow) allow-discrete}@starting-style{dialog[open]::backdrop{opacity:0}}@media(prefers-color-scheme:dark){dialog::backdrop{background:#000000b3}}[data-theme=dark] dialog::backdrop{background:#000000b3}.panel{display:flex;flex-direction:column;width:100%;max-height:inherit;overflow:hidden}.size-sm{width:min(24rem,90vw)}.size-md{width:min(36rem,90vw)}.size-lg{width:min(48rem,90vw)}.size-xl{width:min(64rem,90vw)}.size-full{width:100vw;height:100dvh;max-height:100dvh;border-radius:0;margin:0}llm-dialog-header{display:flex;align-items:center;justify-content:space-between;padding:var(--ui-spacing-4) var(--ui-spacing-5);border-bottom:1px solid var(--ui-color-border);font-size:var(--ui-font-size-xl);font-weight:600;letter-spacing:var(--ui-letter-spacing-tight);color:var(--ui-color-text);flex-shrink:0}llm-dialog-content{display:block;padding:var(--ui-spacing-5);overflow-y:auto;flex:1;color:var(--ui-color-text)}llm-dialog-footer{display:flex;align-items:center;justify-content:flex-end;gap:var(--ui-spacing-2);padding:var(--ui-spacing-4) var(--ui-spacing-5);border-top:1px solid var(--ui-color-border);flex-shrink:0}.close-btn{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;width:1.75rem;height:1.75rem;padding:0;margin-left:var(--ui-spacing-3);background:transparent;border:none;border-radius:var(--ui-radius-sm);cursor:pointer;color:var(--ui-color-text-muted);transition:background-color var(--ui-transition-fast),color var(--ui-transition-fast);line-height:1}.close-btn:hover{background-color:var(--ui-color-surface-sunken);color:var(--ui-color-text)}.close-btn:focus-visible{outline:none;box-shadow:var(--ui-focus-ring)}\n"] }]
|
|
1499
|
+
}] });
|
|
1500
|
+
/**
|
|
1501
|
+
* Footer slot for `llm-dialog`. Renders below content, typically holds action buttons.
|
|
1502
|
+
*/
|
|
1503
|
+
class LlmDialogFooter {
|
|
1504
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmDialogFooter, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1505
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.4", type: LlmDialogFooter, isStandalone: true, selector: "llm-dialog-footer", ngImport: i0, template: `<ng-content />`, isInline: true, styles: ["llm-dialog{display:contents}dialog{all:unset;position:fixed;inset:0;margin:auto;display:none;flex-direction:column;max-height:calc(100dvh - var(--ui-spacing-8));border-radius:var(--ui-radius-lg);background:var(--ui-color-surface);box-shadow:var(--ui-shadow-xl, 0 20px 60px rgba(0, 0, 0, .3));color:var(--ui-color-text);overflow:hidden;opacity:0;transform:scale(.95);transition:opacity var(--ui-duration-slow) var(--ui-ease-out, ease-out),transform var(--ui-duration-slow) var(--ui-ease-out, ease-out),display var(--ui-duration-slow) allow-discrete,overlay var(--ui-duration-slow) allow-discrete}dialog[open]{display:flex;opacity:1;transform:scale(1)}@starting-style{dialog[open]{opacity:0;transform:scale(.95)}}dialog::backdrop{background:#00000080;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);transition:opacity var(--ui-duration-slow) var(--ui-ease-out, ease-out),display var(--ui-duration-slow) allow-discrete,overlay var(--ui-duration-slow) allow-discrete}@starting-style{dialog[open]::backdrop{opacity:0}}@media(prefers-color-scheme:dark){dialog::backdrop{background:#000000b3}}[data-theme=dark] dialog::backdrop{background:#000000b3}.panel{display:flex;flex-direction:column;width:100%;max-height:inherit;overflow:hidden}.size-sm{width:min(24rem,90vw)}.size-md{width:min(36rem,90vw)}.size-lg{width:min(48rem,90vw)}.size-xl{width:min(64rem,90vw)}.size-full{width:100vw;height:100dvh;max-height:100dvh;border-radius:0;margin:0}llm-dialog-header{display:flex;align-items:center;justify-content:space-between;padding:var(--ui-spacing-4) var(--ui-spacing-5);border-bottom:1px solid var(--ui-color-border);font-size:var(--ui-font-size-xl);font-weight:600;letter-spacing:var(--ui-letter-spacing-tight);color:var(--ui-color-text);flex-shrink:0}llm-dialog-content{display:block;padding:var(--ui-spacing-5);overflow-y:auto;flex:1;color:var(--ui-color-text)}llm-dialog-footer{display:flex;align-items:center;justify-content:flex-end;gap:var(--ui-spacing-2);padding:var(--ui-spacing-4) var(--ui-spacing-5);border-top:1px solid var(--ui-color-border);flex-shrink:0}.close-btn{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;width:1.75rem;height:1.75rem;padding:0;margin-left:var(--ui-spacing-3);background:transparent;border:none;border-radius:var(--ui-radius-sm);cursor:pointer;color:var(--ui-color-text-muted);transition:background-color var(--ui-transition-fast),color var(--ui-transition-fast);line-height:1}.close-btn:hover{background-color:var(--ui-color-surface-sunken);color:var(--ui-color-text)}.close-btn:focus-visible{outline:none;box-shadow:var(--ui-focus-ring)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1506
|
+
}
|
|
1507
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmDialogFooter, decorators: [{
|
|
1508
|
+
type: Component,
|
|
1509
|
+
args: [{ selector: 'llm-dialog-footer', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: `<ng-content />`, styles: ["llm-dialog{display:contents}dialog{all:unset;position:fixed;inset:0;margin:auto;display:none;flex-direction:column;max-height:calc(100dvh - var(--ui-spacing-8));border-radius:var(--ui-radius-lg);background:var(--ui-color-surface);box-shadow:var(--ui-shadow-xl, 0 20px 60px rgba(0, 0, 0, .3));color:var(--ui-color-text);overflow:hidden;opacity:0;transform:scale(.95);transition:opacity var(--ui-duration-slow) var(--ui-ease-out, ease-out),transform var(--ui-duration-slow) var(--ui-ease-out, ease-out),display var(--ui-duration-slow) allow-discrete,overlay var(--ui-duration-slow) allow-discrete}dialog[open]{display:flex;opacity:1;transform:scale(1)}@starting-style{dialog[open]{opacity:0;transform:scale(.95)}}dialog::backdrop{background:#00000080;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);transition:opacity var(--ui-duration-slow) var(--ui-ease-out, ease-out),display var(--ui-duration-slow) allow-discrete,overlay var(--ui-duration-slow) allow-discrete}@starting-style{dialog[open]::backdrop{opacity:0}}@media(prefers-color-scheme:dark){dialog::backdrop{background:#000000b3}}[data-theme=dark] dialog::backdrop{background:#000000b3}.panel{display:flex;flex-direction:column;width:100%;max-height:inherit;overflow:hidden}.size-sm{width:min(24rem,90vw)}.size-md{width:min(36rem,90vw)}.size-lg{width:min(48rem,90vw)}.size-xl{width:min(64rem,90vw)}.size-full{width:100vw;height:100dvh;max-height:100dvh;border-radius:0;margin:0}llm-dialog-header{display:flex;align-items:center;justify-content:space-between;padding:var(--ui-spacing-4) var(--ui-spacing-5);border-bottom:1px solid var(--ui-color-border);font-size:var(--ui-font-size-xl);font-weight:600;letter-spacing:var(--ui-letter-spacing-tight);color:var(--ui-color-text);flex-shrink:0}llm-dialog-content{display:block;padding:var(--ui-spacing-5);overflow-y:auto;flex:1;color:var(--ui-color-text)}llm-dialog-footer{display:flex;align-items:center;justify-content:flex-end;gap:var(--ui-spacing-2);padding:var(--ui-spacing-4) var(--ui-spacing-5);border-top:1px solid var(--ui-color-border);flex-shrink:0}.close-btn{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;width:1.75rem;height:1.75rem;padding:0;margin-left:var(--ui-spacing-3);background:transparent;border:none;border-radius:var(--ui-radius-sm);cursor:pointer;color:var(--ui-color-text-muted);transition:background-color var(--ui-transition-fast),color var(--ui-transition-fast);line-height:1}.close-btn:hover{background-color:var(--ui-color-surface-sunken);color:var(--ui-color-text)}.close-btn:focus-visible{outline:none;box-shadow:var(--ui-focus-ring)}\n"] }]
|
|
1510
|
+
}] });
|
|
1511
|
+
|
|
1512
|
+
const LLM_TAB_GROUP = new InjectionToken('LLM_TAB_GROUP');
|
|
1513
|
+
|
|
1514
|
+
let nextId$2 = 0;
|
|
1515
|
+
/**
|
|
1516
|
+
* Accessible tabbed interface container. Renders a tab list and manages
|
|
1517
|
+
* keyboard navigation with roving tabindex.
|
|
1518
|
+
*
|
|
1519
|
+
* Usage:
|
|
1520
|
+
* ```html
|
|
1521
|
+
* <llm-tab-group [(selectedIndex)]="activeTab">
|
|
1522
|
+
* <llm-tab label="Account">Account settings here.</llm-tab>
|
|
1523
|
+
* <llm-tab label="Notifications">Notification prefs here.</llm-tab>
|
|
1524
|
+
* <llm-tab label="Billing" [disabled]="true">Billing info here.</llm-tab>
|
|
1525
|
+
* </llm-tab-group>
|
|
1526
|
+
* ```
|
|
1527
|
+
*/
|
|
1528
|
+
class LlmTabGroup {
|
|
1529
|
+
/** Index of the currently active tab. Supports two-way binding. */
|
|
1530
|
+
selectedIndex = model(0, ...(ngDevMode ? [{ debugName: "selectedIndex" }] : /* istanbul ignore next */ []));
|
|
1531
|
+
/** Visual variant. */
|
|
1532
|
+
variant = input('default', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
|
|
1533
|
+
/** @internal */
|
|
1534
|
+
tabs = signal([], ...(ngDevMode ? [{ debugName: "tabs" }] : /* istanbul ignore next */ []));
|
|
1535
|
+
/** @internal */
|
|
1536
|
+
elementRef = inject(ElementRef);
|
|
1537
|
+
/** @internal */
|
|
1538
|
+
hostClasses = computed(() => `variant-${this.variant()}`, ...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
|
|
1539
|
+
/** @internal — called by LlmTab on init */
|
|
1540
|
+
registerTab(info) {
|
|
1541
|
+
this.tabs.update((list) => [...list, info]);
|
|
1542
|
+
}
|
|
1543
|
+
/** @internal — called by LlmTab on destroy */
|
|
1544
|
+
unregisterTab(id) {
|
|
1545
|
+
this.tabs.update((list) => list.filter((t) => t.id !== id));
|
|
1546
|
+
}
|
|
1547
|
+
/** @internal */
|
|
1548
|
+
selectTab(index) {
|
|
1549
|
+
const tab = this.tabs()[index];
|
|
1550
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition, @typescript-eslint/strict-boolean-expressions
|
|
1551
|
+
if (tab && !tab.disabled) {
|
|
1552
|
+
this.selectedIndex.set(index);
|
|
1553
|
+
}
|
|
1554
|
+
}
|
|
1555
|
+
/** @internal */
|
|
1556
|
+
onTabKeydown(event) {
|
|
1557
|
+
const tabs = this.tabs();
|
|
1558
|
+
const enabled = tabs.map((tab, i) => ({ tab, i })).filter(({ tab }) => !tab.disabled);
|
|
1559
|
+
if (enabled.length === 0)
|
|
1560
|
+
return;
|
|
1561
|
+
const currentPos = enabled.findIndex(({ i }) => i === this.selectedIndex());
|
|
1562
|
+
const n = enabled.length;
|
|
1563
|
+
let targetEntry = null;
|
|
1564
|
+
switch (event.key) {
|
|
1565
|
+
case 'ArrowRight':
|
|
1566
|
+
event.preventDefault();
|
|
1567
|
+
targetEntry = enabled[(currentPos + 1) % n];
|
|
1568
|
+
break;
|
|
1569
|
+
case 'ArrowLeft':
|
|
1570
|
+
event.preventDefault();
|
|
1571
|
+
targetEntry = enabled[(currentPos - 1 + n) % n];
|
|
1572
|
+
break;
|
|
1573
|
+
case 'Home':
|
|
1574
|
+
event.preventDefault();
|
|
1575
|
+
targetEntry = enabled[0];
|
|
1576
|
+
break;
|
|
1577
|
+
case 'End':
|
|
1578
|
+
event.preventDefault();
|
|
1579
|
+
targetEntry = enabled[n - 1];
|
|
1580
|
+
break;
|
|
1581
|
+
}
|
|
1582
|
+
if (targetEntry) {
|
|
1583
|
+
this.selectedIndex.set(targetEntry.i);
|
|
1584
|
+
const buttons = this.elementRef.nativeElement.querySelectorAll('[role="tab"]');
|
|
1585
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
1586
|
+
buttons[targetEntry.i]?.focus();
|
|
1587
|
+
}
|
|
1588
|
+
}
|
|
1589
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmTabGroup, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1590
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.4", type: LlmTabGroup, isStandalone: true, selector: "llm-tab-group", inputs: { selectedIndex: { classPropertyName: "selectedIndex", publicName: "selectedIndex", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectedIndex: "selectedIndexChange" }, host: { properties: { "class": "hostClasses()" } }, providers: [{ provide: LLM_TAB_GROUP, useExisting: LlmTabGroup }], ngImport: i0, template: `
|
|
1591
|
+
<div class="tablist" role="tablist">
|
|
1592
|
+
@for (tab of tabs(); track tab.id; let i = $index) {
|
|
1593
|
+
<button
|
|
1594
|
+
type="button"
|
|
1595
|
+
role="tab"
|
|
1596
|
+
[id]="tab.tabId"
|
|
1597
|
+
[attr.aria-selected]="selectedIndex() === i"
|
|
1598
|
+
[attr.aria-controls]="tab.panelId"
|
|
1599
|
+
[attr.aria-disabled]="tab.disabled || null"
|
|
1600
|
+
[attr.tabindex]="selectedIndex() === i ? 0 : -1"
|
|
1601
|
+
[class.is-active]="selectedIndex() === i"
|
|
1602
|
+
[class.is-disabled]="tab.disabled"
|
|
1603
|
+
(click)="selectTab(i)"
|
|
1604
|
+
(keydown)="onTabKeydown($event)"
|
|
1605
|
+
>
|
|
1606
|
+
{{ tab.label }}
|
|
1607
|
+
</button>
|
|
1608
|
+
}
|
|
1609
|
+
</div>
|
|
1610
|
+
<ng-content />
|
|
1611
|
+
`, isInline: true, styles: [":host{display:block;font-family:var(--ui-font-family)}.tablist{display:flex;gap:var(--ui-spacing-1);border-bottom:1px solid var(--ui-color-border);overflow-x:auto;scrollbar-width:none}.tablist::-webkit-scrollbar{display:none}.tablist button{all:unset;box-sizing:border-box;position:relative;display:inline-flex;align-items:center;padding:var(--ui-spacing-2) var(--ui-spacing-4);font-size:var(--ui-font-size-sm);font-weight:var(--ui-font-weight-medium);color:var(--ui-color-text-muted);cursor:pointer;transition:var(--ui-transition-fast);transition-property:color,background-color;border-radius:var(--ui-radius-md) var(--ui-radius-md) 0 0;white-space:nowrap;-webkit-user-select:none;user-select:none}.tablist button:after{content:\"\";position:absolute;bottom:-1px;left:0;right:0;height:2px;background:transparent;border-radius:var(--ui-radius-full);transition:background var(--ui-transition-fast)}.tablist button.is-active{color:var(--ui-color-primary)}.tablist button.is-active:after{background:var(--ui-color-primary)}.tablist button:hover:not(.is-disabled):not(.is-active){color:var(--ui-color-text);background:var(--ui-color-surface-sunken)}.tablist button:focus-visible{outline:none;box-shadow:var(--ui-focus-ring);border-radius:var(--ui-radius-md)}.tablist button.is-disabled{opacity:.4;cursor:not-allowed}llm-tab [role=tabpanel]{padding:var(--ui-spacing-4) 0}llm-tab [role=tabpanel]:focus-visible{outline:none;box-shadow:var(--ui-focus-ring);border-radius:var(--ui-radius-md)}:host(.variant-pills) .tablist{border-bottom:none;gap:var(--ui-spacing-2);padding:var(--ui-spacing-1);background:var(--ui-color-surface-sunken);border-radius:var(--ui-radius-lg)}:host(.variant-pills) .tablist button{border-radius:var(--ui-radius-md);padding:var(--ui-spacing-1) var(--ui-spacing-4);font-size:var(--ui-font-size-sm)}:host(.variant-pills) .tablist button:after{display:none}:host(.variant-pills) .tablist button.is-active{background:var(--ui-color-surface);color:var(--ui-color-text);box-shadow:var(--ui-shadow-sm)}:host(.variant-pills) .tablist button:hover:not(.is-disabled):not(.is-active){background:transparent;color:var(--ui-color-text)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1612
|
+
}
|
|
1613
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmTabGroup, decorators: [{
|
|
1614
|
+
type: Component,
|
|
1615
|
+
args: [{ selector: 'llm-tab-group', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: `
|
|
1616
|
+
<div class="tablist" role="tablist">
|
|
1617
|
+
@for (tab of tabs(); track tab.id; let i = $index) {
|
|
1618
|
+
<button
|
|
1619
|
+
type="button"
|
|
1620
|
+
role="tab"
|
|
1621
|
+
[id]="tab.tabId"
|
|
1622
|
+
[attr.aria-selected]="selectedIndex() === i"
|
|
1623
|
+
[attr.aria-controls]="tab.panelId"
|
|
1624
|
+
[attr.aria-disabled]="tab.disabled || null"
|
|
1625
|
+
[attr.tabindex]="selectedIndex() === i ? 0 : -1"
|
|
1626
|
+
[class.is-active]="selectedIndex() === i"
|
|
1627
|
+
[class.is-disabled]="tab.disabled"
|
|
1628
|
+
(click)="selectTab(i)"
|
|
1629
|
+
(keydown)="onTabKeydown($event)"
|
|
1630
|
+
>
|
|
1631
|
+
{{ tab.label }}
|
|
1632
|
+
</button>
|
|
1633
|
+
}
|
|
1634
|
+
</div>
|
|
1635
|
+
<ng-content />
|
|
1636
|
+
`, host: {
|
|
1637
|
+
'[class]': 'hostClasses()',
|
|
1638
|
+
}, providers: [{ provide: LLM_TAB_GROUP, useExisting: LlmTabGroup }], styles: [":host{display:block;font-family:var(--ui-font-family)}.tablist{display:flex;gap:var(--ui-spacing-1);border-bottom:1px solid var(--ui-color-border);overflow-x:auto;scrollbar-width:none}.tablist::-webkit-scrollbar{display:none}.tablist button{all:unset;box-sizing:border-box;position:relative;display:inline-flex;align-items:center;padding:var(--ui-spacing-2) var(--ui-spacing-4);font-size:var(--ui-font-size-sm);font-weight:var(--ui-font-weight-medium);color:var(--ui-color-text-muted);cursor:pointer;transition:var(--ui-transition-fast);transition-property:color,background-color;border-radius:var(--ui-radius-md) var(--ui-radius-md) 0 0;white-space:nowrap;-webkit-user-select:none;user-select:none}.tablist button:after{content:\"\";position:absolute;bottom:-1px;left:0;right:0;height:2px;background:transparent;border-radius:var(--ui-radius-full);transition:background var(--ui-transition-fast)}.tablist button.is-active{color:var(--ui-color-primary)}.tablist button.is-active:after{background:var(--ui-color-primary)}.tablist button:hover:not(.is-disabled):not(.is-active){color:var(--ui-color-text);background:var(--ui-color-surface-sunken)}.tablist button:focus-visible{outline:none;box-shadow:var(--ui-focus-ring);border-radius:var(--ui-radius-md)}.tablist button.is-disabled{opacity:.4;cursor:not-allowed}llm-tab [role=tabpanel]{padding:var(--ui-spacing-4) 0}llm-tab [role=tabpanel]:focus-visible{outline:none;box-shadow:var(--ui-focus-ring);border-radius:var(--ui-radius-md)}:host(.variant-pills) .tablist{border-bottom:none;gap:var(--ui-spacing-2);padding:var(--ui-spacing-1);background:var(--ui-color-surface-sunken);border-radius:var(--ui-radius-lg)}:host(.variant-pills) .tablist button{border-radius:var(--ui-radius-md);padding:var(--ui-spacing-1) var(--ui-spacing-4);font-size:var(--ui-font-size-sm)}:host(.variant-pills) .tablist button:after{display:none}:host(.variant-pills) .tablist button.is-active{background:var(--ui-color-surface);color:var(--ui-color-text);box-shadow:var(--ui-shadow-sm)}:host(.variant-pills) .tablist button:hover:not(.is-disabled):not(.is-active){background:transparent;color:var(--ui-color-text)}\n"] }]
|
|
1639
|
+
}], propDecorators: { selectedIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedIndex", required: false }] }, { type: i0.Output, args: ["selectedIndexChange"] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }] } });
|
|
1640
|
+
/**
|
|
1641
|
+
* Individual tab definition. Place inside `<llm-tab-group>`.
|
|
1642
|
+
*
|
|
1643
|
+
* Usage:
|
|
1644
|
+
* ```html
|
|
1645
|
+
* <llm-tab label="Settings">Settings content here.</llm-tab>
|
|
1646
|
+
* ```
|
|
1647
|
+
*/
|
|
1648
|
+
class LlmTab {
|
|
1649
|
+
/** Text displayed on the tab button. Required. */
|
|
1650
|
+
label = input.required(...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
|
|
1651
|
+
/** Whether this tab is disabled. */
|
|
1652
|
+
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
|
|
1653
|
+
/** @internal */
|
|
1654
|
+
tabId = `llm-tab-${nextId$2}`;
|
|
1655
|
+
/** @internal */
|
|
1656
|
+
panelId = `llm-tab-panel-${nextId$2}`;
|
|
1657
|
+
/** @internal */
|
|
1658
|
+
id = `llm-tab-instance-${nextId$2++}`;
|
|
1659
|
+
/** @internal */
|
|
1660
|
+
context = inject(LLM_TAB_GROUP);
|
|
1661
|
+
/** @internal */
|
|
1662
|
+
isActive = computed(() => {
|
|
1663
|
+
const index = this.context.tabs().findIndex((t) => t.id === this.id);
|
|
1664
|
+
return this.context.selectedIndex() === index;
|
|
1665
|
+
}, ...(ngDevMode ? [{ debugName: "isActive" }] : /* istanbul ignore next */ []));
|
|
1666
|
+
ngOnInit() {
|
|
1667
|
+
this.context.registerTab({
|
|
1668
|
+
id: this.id,
|
|
1669
|
+
label: this.label(),
|
|
1670
|
+
disabled: this.disabled(),
|
|
1671
|
+
panelId: this.panelId,
|
|
1672
|
+
tabId: this.tabId,
|
|
1673
|
+
});
|
|
1674
|
+
}
|
|
1675
|
+
ngOnDestroy() {
|
|
1676
|
+
this.context.unregisterTab(this.id);
|
|
1677
|
+
}
|
|
1678
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmTab, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1679
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.4", type: LlmTab, isStandalone: true, selector: "llm-tab", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
|
|
1680
|
+
@if (isActive()) {
|
|
1681
|
+
<div
|
|
1682
|
+
role="tabpanel"
|
|
1683
|
+
[id]="panelId"
|
|
1684
|
+
[attr.aria-labelledby]="tabId"
|
|
1685
|
+
[tabindex]="0"
|
|
1686
|
+
>
|
|
1687
|
+
<ng-content />
|
|
1688
|
+
</div>
|
|
1689
|
+
}
|
|
1690
|
+
`, isInline: true, styles: [":host{display:contents}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1691
|
+
}
|
|
1692
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmTab, decorators: [{
|
|
1693
|
+
type: Component,
|
|
1694
|
+
args: [{ selector: 'llm-tab', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: `
|
|
1695
|
+
@if (isActive()) {
|
|
1696
|
+
<div
|
|
1697
|
+
role="tabpanel"
|
|
1698
|
+
[id]="panelId"
|
|
1699
|
+
[attr.aria-labelledby]="tabId"
|
|
1700
|
+
[tabindex]="0"
|
|
1701
|
+
>
|
|
1702
|
+
<ng-content />
|
|
1703
|
+
</div>
|
|
1704
|
+
}
|
|
1705
|
+
`, styles: [":host{display:contents}\n"] }]
|
|
1706
|
+
}], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }] } });
|
|
1707
|
+
|
|
1708
|
+
const LLM_ACCORDION_GROUP = new InjectionToken('LLM_ACCORDION_GROUP');
|
|
1709
|
+
|
|
1710
|
+
let nextId$1 = 0;
|
|
1711
|
+
/**
|
|
1712
|
+
* Container that manages accordion items. Controls single vs multi expansion
|
|
1713
|
+
* and provides keyboard navigation across items.
|
|
1714
|
+
*
|
|
1715
|
+
* Usage:
|
|
1716
|
+
* ```html
|
|
1717
|
+
* <llm-accordion-group [multi]="true" variant="separated">
|
|
1718
|
+
* <llm-accordion-item [(expanded)]="open">
|
|
1719
|
+
* <span llmAccordionHeader>Title</span>
|
|
1720
|
+
* Body content here.
|
|
1721
|
+
* </llm-accordion-item>
|
|
1722
|
+
* </llm-accordion-group>
|
|
1723
|
+
* ```
|
|
1724
|
+
*/
|
|
1725
|
+
class LlmAccordionGroup {
|
|
1726
|
+
/** Allow multiple items to be expanded simultaneously. */
|
|
1727
|
+
multi = input(false, ...(ngDevMode ? [{ debugName: "multi" }] : /* istanbul ignore next */ []));
|
|
1728
|
+
/** Visual variant. */
|
|
1729
|
+
variant = input('default', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
|
|
1730
|
+
/** @internal */
|
|
1731
|
+
hostClasses = computed(() => `variant-${this.variant()}`, ...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
|
|
1732
|
+
/** @internal */
|
|
1733
|
+
get hostClassesValue() {
|
|
1734
|
+
return this.hostClasses();
|
|
1735
|
+
}
|
|
1736
|
+
/** @internal */
|
|
1737
|
+
items = signal([], ...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
|
|
1738
|
+
register(item) {
|
|
1739
|
+
this.items.update((list) => [...list, item]);
|
|
1740
|
+
}
|
|
1741
|
+
unregister(item) {
|
|
1742
|
+
this.items.update((list) => list.filter((i) => i !== item));
|
|
1743
|
+
}
|
|
1744
|
+
handleKeydown(event, item) {
|
|
1745
|
+
const allItems = this.items();
|
|
1746
|
+
const enabled = allItems.filter((i) => !i.isItemDisabled());
|
|
1747
|
+
if (enabled.length === 0)
|
|
1748
|
+
return;
|
|
1749
|
+
const pos = enabled.indexOf(item);
|
|
1750
|
+
const n = enabled.length;
|
|
1751
|
+
let target = null;
|
|
1752
|
+
switch (event.key) {
|
|
1753
|
+
case 'ArrowDown':
|
|
1754
|
+
event.preventDefault();
|
|
1755
|
+
target = enabled[(pos + 1) % n];
|
|
1756
|
+
break;
|
|
1757
|
+
case 'ArrowUp':
|
|
1758
|
+
event.preventDefault();
|
|
1759
|
+
target = enabled[(pos - 1 + n) % n];
|
|
1760
|
+
break;
|
|
1761
|
+
case 'Home':
|
|
1762
|
+
event.preventDefault();
|
|
1763
|
+
target = enabled[0];
|
|
1764
|
+
break;
|
|
1765
|
+
case 'End':
|
|
1766
|
+
event.preventDefault();
|
|
1767
|
+
target = enabled[n - 1];
|
|
1768
|
+
break;
|
|
1769
|
+
}
|
|
1770
|
+
target?.focusTrigger();
|
|
1771
|
+
}
|
|
1772
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmAccordionGroup, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1773
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.4", type: LlmAccordionGroup, isStandalone: true, selector: "llm-accordion-group", inputs: { multi: { classPropertyName: "multi", publicName: "multi", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "presentation" }, properties: { "class": "hostClassesValue" } }, providers: [{ provide: LLM_ACCORDION_GROUP, useExisting: LlmAccordionGroup }], hostDirectives: [{ directive: i1$2.CdkAccordion, inputs: ["multi", "multi"] }], ngImport: i0, template: `<ng-content />`, isInline: true, styles: [":host{display:block;font-family:var(--ui-font-family)}:host(.variant-default){border-top:1px solid var(--ui-color-border)}:host(.variant-default) llm-accordion-item{border-bottom:1px solid var(--ui-color-border)}:host(.variant-bordered){border:1px solid var(--ui-color-border);border-radius:var(--ui-radius-lg);overflow:hidden}:host(.variant-bordered) llm-accordion-item:not(:last-child){border-bottom:1px solid var(--ui-color-border)}:host(.variant-separated){display:flex;flex-direction:column;gap:var(--ui-spacing-2)}:host(.variant-separated) llm-accordion-item{border:1px solid var(--ui-color-border);border-radius:var(--ui-radius-lg);overflow:hidden}llm-accordion-item{display:block}.accordion-heading{all:unset;display:block}.accordion-trigger{all:unset;box-sizing:border-box;display:flex;align-items:center;justify-content:space-between;width:100%;padding:var(--ui-spacing-4);font-size:var(--ui-font-size-md);font-weight:var(--ui-font-weight-medium);color:var(--ui-color-text);cursor:pointer;transition:background-color var(--ui-transition-fast);-webkit-user-select:none;user-select:none}.accordion-trigger:hover:not(.is-disabled){background:var(--ui-color-surface-sunken)}.accordion-trigger:focus-visible{outline:none;box-shadow:var(--ui-focus-ring);position:relative;z-index:1}.accordion-trigger.is-disabled{opacity:var(--ui-opacity-disabled);cursor:not-allowed}.chevron{flex-shrink:0;color:var(--ui-color-text-muted);transition:transform var(--ui-duration-normal) var(--ui-ease-out)}.chevron.is-expanded{transform:rotate(180deg)}.accordion-panel-wrapper{display:grid;grid-template-rows:0fr;transition:grid-template-rows var(--ui-duration-normal) var(--ui-ease-out)}.accordion-panel-wrapper.is-expanded{grid-template-rows:1fr}.accordion-panel{overflow:hidden}.accordion-panel-wrapper.is-expanded .accordion-panel{padding:0 var(--ui-spacing-4) var(--ui-spacing-4)}.accordion-panel-wrapper:not(.is-expanded) .accordion-panel{padding:0 var(--ui-spacing-4)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1774
|
+
}
|
|
1775
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmAccordionGroup, decorators: [{
|
|
1776
|
+
type: Component,
|
|
1777
|
+
args: [{ selector: 'llm-accordion-group', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: `<ng-content />`, hostDirectives: [{ directive: CdkAccordion, inputs: ['multi'] }], host: {
|
|
1778
|
+
'[class]': 'hostClassesValue',
|
|
1779
|
+
role: 'presentation',
|
|
1780
|
+
}, providers: [{ provide: LLM_ACCORDION_GROUP, useExisting: LlmAccordionGroup }], styles: [":host{display:block;font-family:var(--ui-font-family)}:host(.variant-default){border-top:1px solid var(--ui-color-border)}:host(.variant-default) llm-accordion-item{border-bottom:1px solid var(--ui-color-border)}:host(.variant-bordered){border:1px solid var(--ui-color-border);border-radius:var(--ui-radius-lg);overflow:hidden}:host(.variant-bordered) llm-accordion-item:not(:last-child){border-bottom:1px solid var(--ui-color-border)}:host(.variant-separated){display:flex;flex-direction:column;gap:var(--ui-spacing-2)}:host(.variant-separated) llm-accordion-item{border:1px solid var(--ui-color-border);border-radius:var(--ui-radius-lg);overflow:hidden}llm-accordion-item{display:block}.accordion-heading{all:unset;display:block}.accordion-trigger{all:unset;box-sizing:border-box;display:flex;align-items:center;justify-content:space-between;width:100%;padding:var(--ui-spacing-4);font-size:var(--ui-font-size-md);font-weight:var(--ui-font-weight-medium);color:var(--ui-color-text);cursor:pointer;transition:background-color var(--ui-transition-fast);-webkit-user-select:none;user-select:none}.accordion-trigger:hover:not(.is-disabled){background:var(--ui-color-surface-sunken)}.accordion-trigger:focus-visible{outline:none;box-shadow:var(--ui-focus-ring);position:relative;z-index:1}.accordion-trigger.is-disabled{opacity:var(--ui-opacity-disabled);cursor:not-allowed}.chevron{flex-shrink:0;color:var(--ui-color-text-muted);transition:transform var(--ui-duration-normal) var(--ui-ease-out)}.chevron.is-expanded{transform:rotate(180deg)}.accordion-panel-wrapper{display:grid;grid-template-rows:0fr;transition:grid-template-rows var(--ui-duration-normal) var(--ui-ease-out)}.accordion-panel-wrapper.is-expanded{grid-template-rows:1fr}.accordion-panel{overflow:hidden}.accordion-panel-wrapper.is-expanded .accordion-panel{padding:0 var(--ui-spacing-4) var(--ui-spacing-4)}.accordion-panel-wrapper:not(.is-expanded) .accordion-panel{padding:0 var(--ui-spacing-4)}\n"] }]
|
|
1781
|
+
}], propDecorators: { multi: [{ type: i0.Input, args: [{ isSignal: true, alias: "multi", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }] } });
|
|
1782
|
+
/**
|
|
1783
|
+
* Directive to mark the accordion header content.
|
|
1784
|
+
*/
|
|
1785
|
+
class LlmAccordionHeader {
|
|
1786
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmAccordionHeader, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
1787
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.4", type: LlmAccordionHeader, isStandalone: true, selector: "[llmAccordionHeader]", ngImport: i0 });
|
|
1788
|
+
}
|
|
1789
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmAccordionHeader, decorators: [{
|
|
1790
|
+
type: Directive,
|
|
1791
|
+
args: [{
|
|
1792
|
+
selector: '[llmAccordionHeader]',
|
|
1793
|
+
standalone: true,
|
|
1794
|
+
}]
|
|
1795
|
+
}] });
|
|
1796
|
+
/**
|
|
1797
|
+
* Individual collapsible accordion item. Place inside `<llm-accordion-group>`.
|
|
1798
|
+
*
|
|
1799
|
+
* Usage:
|
|
1800
|
+
* ```html
|
|
1801
|
+
* <llm-accordion-item [(expanded)]="isOpen">
|
|
1802
|
+
* <span llmAccordionHeader>Section Title</span>
|
|
1803
|
+
* Section content goes here.
|
|
1804
|
+
* </llm-accordion-item>
|
|
1805
|
+
* ```
|
|
1806
|
+
*/
|
|
1807
|
+
class LlmAccordionItem {
|
|
1808
|
+
/** Whether this item is expanded. Supports two-way binding. */
|
|
1809
|
+
expanded = model(false, ...(ngDevMode ? [{ debugName: "expanded" }] : /* istanbul ignore next */ []));
|
|
1810
|
+
/** Whether this item is disabled. */
|
|
1811
|
+
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
|
|
1812
|
+
/** @internal */
|
|
1813
|
+
id = `llm-accordion-item-${nextId$1++}`;
|
|
1814
|
+
/** @internal */
|
|
1815
|
+
triggerId = `${this.id}-trigger`;
|
|
1816
|
+
/** @internal */
|
|
1817
|
+
panelId = `${this.id}-panel`;
|
|
1818
|
+
/** @internal */
|
|
1819
|
+
group = inject(LlmAccordionGroup);
|
|
1820
|
+
/** @internal */
|
|
1821
|
+
cdkItem = inject(CdkAccordionItem);
|
|
1822
|
+
/** @internal */
|
|
1823
|
+
el = inject(ElementRef);
|
|
1824
|
+
/** @internal */
|
|
1825
|
+
isExpanded = signal(false, ...(ngDevMode ? [{ debugName: "isExpanded" }] : /* istanbul ignore next */ []));
|
|
1826
|
+
/** @internal */
|
|
1827
|
+
get isExpandedValue() {
|
|
1828
|
+
return this.isExpanded();
|
|
1829
|
+
}
|
|
1830
|
+
/** @internal */
|
|
1831
|
+
get isDisabled() {
|
|
1832
|
+
return this.disabled();
|
|
1833
|
+
}
|
|
1834
|
+
/** @internal */
|
|
1835
|
+
get ariaDisabled() {
|
|
1836
|
+
return this.disabled() || null;
|
|
1837
|
+
}
|
|
1838
|
+
constructor() {
|
|
1839
|
+
this.cdkItem.expandedChange.subscribe((expanded) => {
|
|
1840
|
+
this.isExpanded.set(expanded);
|
|
1841
|
+
this.expanded.set(expanded);
|
|
1842
|
+
});
|
|
1843
|
+
}
|
|
1844
|
+
ngOnInit() {
|
|
1845
|
+
this.group.register(this);
|
|
1846
|
+
// Sync initial expanded model
|
|
1847
|
+
if (this.expanded()) {
|
|
1848
|
+
this.cdkItem.open();
|
|
1849
|
+
}
|
|
1850
|
+
}
|
|
1851
|
+
ngOnDestroy() {
|
|
1852
|
+
this.group.unregister(this);
|
|
1853
|
+
}
|
|
1854
|
+
/** @internal — for FocusKeyManager */
|
|
1855
|
+
focusTrigger() {
|
|
1856
|
+
this.el.nativeElement.querySelector('.accordion-trigger')?.focus();
|
|
1857
|
+
}
|
|
1858
|
+
/** @internal — for FocusKeyManager */
|
|
1859
|
+
isItemDisabled() {
|
|
1860
|
+
return this.disabled();
|
|
1861
|
+
}
|
|
1862
|
+
/** @internal */
|
|
1863
|
+
onToggle() {
|
|
1864
|
+
if (this.disabled())
|
|
1865
|
+
return;
|
|
1866
|
+
this.cdkItem.toggle();
|
|
1867
|
+
}
|
|
1868
|
+
/** @internal */
|
|
1869
|
+
onKeydown(event) {
|
|
1870
|
+
this.group.handleKeydown(event, this);
|
|
1871
|
+
}
|
|
1872
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmAccordionItem, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1873
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.4", type: LlmAccordionItem, isStandalone: true, selector: "llm-accordion-item", inputs: { expanded: { classPropertyName: "expanded", publicName: "expanded", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { expanded: "expandedChange" }, host: { properties: { "attr.data-accordion-id": "id" } }, hostDirectives: [{ directive: i1$2.CdkAccordionItem }], ngImport: i0, template: `
|
|
1874
|
+
<h3 class="accordion-heading">
|
|
1875
|
+
<button
|
|
1876
|
+
type="button"
|
|
1877
|
+
class="accordion-trigger"
|
|
1878
|
+
[id]="triggerId"
|
|
1879
|
+
[attr.aria-expanded]="isExpandedValue"
|
|
1880
|
+
[attr.aria-controls]="panelId"
|
|
1881
|
+
[attr.aria-disabled]="ariaDisabled"
|
|
1882
|
+
[class.is-disabled]="isDisabled"
|
|
1883
|
+
(click)="onToggle()"
|
|
1884
|
+
(keydown)="onKeydown($event)"
|
|
1885
|
+
>
|
|
1886
|
+
<ng-content select="[llmAccordionHeader]" />
|
|
1887
|
+
<svg
|
|
1888
|
+
class="chevron"
|
|
1889
|
+
[class.is-expanded]="isExpandedValue"
|
|
1890
|
+
width="16"
|
|
1891
|
+
height="16"
|
|
1892
|
+
viewBox="0 0 16 16"
|
|
1893
|
+
fill="none"
|
|
1894
|
+
aria-hidden="true"
|
|
1895
|
+
>
|
|
1896
|
+
<path
|
|
1897
|
+
d="M4 6L8 10L12 6"
|
|
1898
|
+
stroke="currentColor"
|
|
1899
|
+
stroke-width="1.5"
|
|
1900
|
+
stroke-linecap="round"
|
|
1901
|
+
stroke-linejoin="round"
|
|
1902
|
+
/>
|
|
1903
|
+
</svg>
|
|
1904
|
+
</button>
|
|
1905
|
+
</h3>
|
|
1906
|
+
<div
|
|
1907
|
+
class="accordion-panel-wrapper"
|
|
1908
|
+
[class.is-expanded]="isExpandedValue"
|
|
1909
|
+
>
|
|
1910
|
+
<div
|
|
1911
|
+
role="region"
|
|
1912
|
+
[id]="panelId"
|
|
1913
|
+
[attr.aria-labelledby]="triggerId"
|
|
1914
|
+
class="accordion-panel"
|
|
1915
|
+
>
|
|
1916
|
+
<ng-content />
|
|
1917
|
+
</div>
|
|
1918
|
+
</div>
|
|
1919
|
+
`, isInline: true, styles: [":host{display:block;font-family:var(--ui-font-family)}:host(.variant-default){border-top:1px solid var(--ui-color-border)}:host(.variant-default) llm-accordion-item{border-bottom:1px solid var(--ui-color-border)}:host(.variant-bordered){border:1px solid var(--ui-color-border);border-radius:var(--ui-radius-lg);overflow:hidden}:host(.variant-bordered) llm-accordion-item:not(:last-child){border-bottom:1px solid var(--ui-color-border)}:host(.variant-separated){display:flex;flex-direction:column;gap:var(--ui-spacing-2)}:host(.variant-separated) llm-accordion-item{border:1px solid var(--ui-color-border);border-radius:var(--ui-radius-lg);overflow:hidden}llm-accordion-item{display:block}.accordion-heading{all:unset;display:block}.accordion-trigger{all:unset;box-sizing:border-box;display:flex;align-items:center;justify-content:space-between;width:100%;padding:var(--ui-spacing-4);font-size:var(--ui-font-size-md);font-weight:var(--ui-font-weight-medium);color:var(--ui-color-text);cursor:pointer;transition:background-color var(--ui-transition-fast);-webkit-user-select:none;user-select:none}.accordion-trigger:hover:not(.is-disabled){background:var(--ui-color-surface-sunken)}.accordion-trigger:focus-visible{outline:none;box-shadow:var(--ui-focus-ring);position:relative;z-index:1}.accordion-trigger.is-disabled{opacity:var(--ui-opacity-disabled);cursor:not-allowed}.chevron{flex-shrink:0;color:var(--ui-color-text-muted);transition:transform var(--ui-duration-normal) var(--ui-ease-out)}.chevron.is-expanded{transform:rotate(180deg)}.accordion-panel-wrapper{display:grid;grid-template-rows:0fr;transition:grid-template-rows var(--ui-duration-normal) var(--ui-ease-out)}.accordion-panel-wrapper.is-expanded{grid-template-rows:1fr}.accordion-panel{overflow:hidden}.accordion-panel-wrapper.is-expanded .accordion-panel{padding:0 var(--ui-spacing-4) var(--ui-spacing-4)}.accordion-panel-wrapper:not(.is-expanded) .accordion-panel{padding:0 var(--ui-spacing-4)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1920
|
+
}
|
|
1921
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmAccordionItem, decorators: [{
|
|
1922
|
+
type: Component,
|
|
1923
|
+
args: [{ selector: 'llm-accordion-item', standalone: true, imports: [], changeDetection: ChangeDetectionStrategy.OnPush, hostDirectives: [CdkAccordionItem], template: `
|
|
1924
|
+
<h3 class="accordion-heading">
|
|
1925
|
+
<button
|
|
1926
|
+
type="button"
|
|
1927
|
+
class="accordion-trigger"
|
|
1928
|
+
[id]="triggerId"
|
|
1929
|
+
[attr.aria-expanded]="isExpandedValue"
|
|
1930
|
+
[attr.aria-controls]="panelId"
|
|
1931
|
+
[attr.aria-disabled]="ariaDisabled"
|
|
1932
|
+
[class.is-disabled]="isDisabled"
|
|
1933
|
+
(click)="onToggle()"
|
|
1934
|
+
(keydown)="onKeydown($event)"
|
|
1935
|
+
>
|
|
1936
|
+
<ng-content select="[llmAccordionHeader]" />
|
|
1937
|
+
<svg
|
|
1938
|
+
class="chevron"
|
|
1939
|
+
[class.is-expanded]="isExpandedValue"
|
|
1940
|
+
width="16"
|
|
1941
|
+
height="16"
|
|
1942
|
+
viewBox="0 0 16 16"
|
|
1943
|
+
fill="none"
|
|
1944
|
+
aria-hidden="true"
|
|
1945
|
+
>
|
|
1946
|
+
<path
|
|
1947
|
+
d="M4 6L8 10L12 6"
|
|
1948
|
+
stroke="currentColor"
|
|
1949
|
+
stroke-width="1.5"
|
|
1950
|
+
stroke-linecap="round"
|
|
1951
|
+
stroke-linejoin="round"
|
|
1952
|
+
/>
|
|
1953
|
+
</svg>
|
|
1954
|
+
</button>
|
|
1955
|
+
</h3>
|
|
1956
|
+
<div
|
|
1957
|
+
class="accordion-panel-wrapper"
|
|
1958
|
+
[class.is-expanded]="isExpandedValue"
|
|
1959
|
+
>
|
|
1960
|
+
<div
|
|
1961
|
+
role="region"
|
|
1962
|
+
[id]="panelId"
|
|
1963
|
+
[attr.aria-labelledby]="triggerId"
|
|
1964
|
+
class="accordion-panel"
|
|
1965
|
+
>
|
|
1966
|
+
<ng-content />
|
|
1967
|
+
</div>
|
|
1968
|
+
</div>
|
|
1969
|
+
`, host: {
|
|
1970
|
+
'[attr.data-accordion-id]': 'id',
|
|
1971
|
+
}, styles: [":host{display:block;font-family:var(--ui-font-family)}:host(.variant-default){border-top:1px solid var(--ui-color-border)}:host(.variant-default) llm-accordion-item{border-bottom:1px solid var(--ui-color-border)}:host(.variant-bordered){border:1px solid var(--ui-color-border);border-radius:var(--ui-radius-lg);overflow:hidden}:host(.variant-bordered) llm-accordion-item:not(:last-child){border-bottom:1px solid var(--ui-color-border)}:host(.variant-separated){display:flex;flex-direction:column;gap:var(--ui-spacing-2)}:host(.variant-separated) llm-accordion-item{border:1px solid var(--ui-color-border);border-radius:var(--ui-radius-lg);overflow:hidden}llm-accordion-item{display:block}.accordion-heading{all:unset;display:block}.accordion-trigger{all:unset;box-sizing:border-box;display:flex;align-items:center;justify-content:space-between;width:100%;padding:var(--ui-spacing-4);font-size:var(--ui-font-size-md);font-weight:var(--ui-font-weight-medium);color:var(--ui-color-text);cursor:pointer;transition:background-color var(--ui-transition-fast);-webkit-user-select:none;user-select:none}.accordion-trigger:hover:not(.is-disabled){background:var(--ui-color-surface-sunken)}.accordion-trigger:focus-visible{outline:none;box-shadow:var(--ui-focus-ring);position:relative;z-index:1}.accordion-trigger.is-disabled{opacity:var(--ui-opacity-disabled);cursor:not-allowed}.chevron{flex-shrink:0;color:var(--ui-color-text-muted);transition:transform var(--ui-duration-normal) var(--ui-ease-out)}.chevron.is-expanded{transform:rotate(180deg)}.accordion-panel-wrapper{display:grid;grid-template-rows:0fr;transition:grid-template-rows var(--ui-duration-normal) var(--ui-ease-out)}.accordion-panel-wrapper.is-expanded{grid-template-rows:1fr}.accordion-panel{overflow:hidden}.accordion-panel-wrapper.is-expanded .accordion-panel{padding:0 var(--ui-spacing-4) var(--ui-spacing-4)}.accordion-panel-wrapper:not(.is-expanded) .accordion-panel{padding:0 var(--ui-spacing-4)}\n"] }]
|
|
1972
|
+
}], ctorParameters: () => [], propDecorators: { expanded: [{ type: i0.Input, args: [{ isSignal: true, alias: "expanded", required: false }] }, { type: i0.Output, args: ["expandedChange"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }] } });
|
|
1973
|
+
|
|
1974
|
+
/**
|
|
1975
|
+
* Trigger directive that opens an `<llm-menu>` dropdown.
|
|
1976
|
+
* Apply to any element (typically `<llm-button>`) to wire up click + keyboard open/close.
|
|
1977
|
+
*
|
|
1978
|
+
* Usage:
|
|
1979
|
+
* ```html
|
|
1980
|
+
* <llm-button [llmMenuTriggerFor]="myMenu">Open</llm-button>
|
|
1981
|
+
* <ng-template #myMenu>
|
|
1982
|
+
* <llm-menu>
|
|
1983
|
+
* <llm-menu-item (triggered)="action()">Action</llm-menu-item>
|
|
1984
|
+
* </llm-menu>
|
|
1985
|
+
* </ng-template>
|
|
1986
|
+
* ```
|
|
1987
|
+
*/
|
|
1988
|
+
class LlmMenuTrigger {
|
|
1989
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmMenuTrigger, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
1990
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.4", type: LlmMenuTrigger, isStandalone: true, selector: "[llmMenuTriggerFor]", hostDirectives: [{ directive: i1$3.CdkMenuTrigger, inputs: ["cdkMenuTriggerFor", "llmMenuTriggerFor"] }], ngImport: i0 });
|
|
1991
|
+
}
|
|
1992
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmMenuTrigger, decorators: [{
|
|
1993
|
+
type: Directive,
|
|
1994
|
+
args: [{
|
|
1995
|
+
selector: '[llmMenuTriggerFor]',
|
|
1996
|
+
standalone: true,
|
|
1997
|
+
hostDirectives: [
|
|
1998
|
+
{
|
|
1999
|
+
directive: CdkMenuTrigger,
|
|
2000
|
+
inputs: ['cdkMenuTriggerFor: llmMenuTriggerFor'],
|
|
2001
|
+
},
|
|
2002
|
+
],
|
|
2003
|
+
}]
|
|
2004
|
+
}] });
|
|
2005
|
+
/**
|
|
2006
|
+
* Accessible dropdown menu panel.
|
|
2007
|
+
* Uses `@angular/cdk/menu` for keyboard navigation, focus management, and ARIA.
|
|
2008
|
+
*
|
|
2009
|
+
* Usage:
|
|
2010
|
+
* ```html
|
|
2011
|
+
* <llm-button [llmMenuTriggerFor]="actions">Actions</llm-button>
|
|
2012
|
+
* <ng-template #actions>
|
|
2013
|
+
* <llm-menu>
|
|
2014
|
+
* <llm-menu-item (triggered)="onCopy()">Copy</llm-menu-item>
|
|
2015
|
+
* <llm-menu-separator />
|
|
2016
|
+
* <llm-menu-item [disabled]="true">Paste</llm-menu-item>
|
|
2017
|
+
* </llm-menu>
|
|
2018
|
+
* </ng-template>
|
|
2019
|
+
* ```
|
|
2020
|
+
*/
|
|
2021
|
+
class LlmMenu {
|
|
2022
|
+
/** Visual variant. `compact` reduces font size and padding. */
|
|
2023
|
+
variant = input('default', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
|
|
2024
|
+
/** @internal */
|
|
2025
|
+
hostClasses = computed(() => `llm-menu variant-${this.variant()}`, ...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
|
|
2026
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmMenu, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2027
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.4", type: LlmMenu, isStandalone: true, selector: "llm-menu", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "hostClasses()" } }, hostDirectives: [{ directive: i1$3.CdkMenu }], ngImport: i0, template: `<ng-content />`, isInline: true, styles: ["llm-menu{display:block;min-width:10rem;padding:var(--ui-spacing-1) 0;background:var(--ui-color-surface-raised);border:1px solid var(--ui-color-border);border-radius:var(--ui-radius-md);box-shadow:var(--ui-shadow-lg);font-family:var(--ui-font-family);font-size:var(--ui-font-size-md);color:var(--ui-color-text);outline:none;overflow:hidden;opacity:0;transform:translateY(-4px);animation:llm-menu-enter var(--ui-duration-normal) var(--ui-ease-out) forwards}llm-menu.variant-compact{font-size:var(--ui-font-size-sm)}llm-menu.variant-compact .llm-menu-item{padding:var(--ui-spacing-1) var(--ui-spacing-3)}@keyframes llm-menu-enter{to{opacity:1;transform:translateY(0)}}.llm-menu-item{display:flex;align-items:center;gap:var(--ui-spacing-2);padding:var(--ui-spacing-2) var(--ui-spacing-3);cursor:pointer;color:var(--ui-color-text);transition:background var(--ui-transition-fast);outline:none;border:none;background:none;font:inherit;width:100%;text-align:start}.llm-menu-item:hover,.llm-menu-item:focus-visible,.llm-menu-item.cdk-menu-item-highlighted{background:var(--ui-color-surface-sunken)}.llm-menu-item.is-disabled{opacity:var(--ui-opacity-disabled);cursor:not-allowed}.llm-menu-item-chevron{margin-inline-start:auto;font-size:var(--ui-font-size-lg);color:var(--ui-color-text-muted);line-height:1}.llm-menu-separator{display:block;height:1px;margin:var(--ui-spacing-1) 0;background:var(--ui-color-border)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
2028
|
+
}
|
|
2029
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmMenu, decorators: [{
|
|
2030
|
+
type: Component,
|
|
2031
|
+
args: [{ selector: 'llm-menu', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, hostDirectives: [CdkMenu], template: `<ng-content />`, host: {
|
|
2032
|
+
'[class]': 'hostClasses()',
|
|
2033
|
+
}, styles: ["llm-menu{display:block;min-width:10rem;padding:var(--ui-spacing-1) 0;background:var(--ui-color-surface-raised);border:1px solid var(--ui-color-border);border-radius:var(--ui-radius-md);box-shadow:var(--ui-shadow-lg);font-family:var(--ui-font-family);font-size:var(--ui-font-size-md);color:var(--ui-color-text);outline:none;overflow:hidden;opacity:0;transform:translateY(-4px);animation:llm-menu-enter var(--ui-duration-normal) var(--ui-ease-out) forwards}llm-menu.variant-compact{font-size:var(--ui-font-size-sm)}llm-menu.variant-compact .llm-menu-item{padding:var(--ui-spacing-1) var(--ui-spacing-3)}@keyframes llm-menu-enter{to{opacity:1;transform:translateY(0)}}.llm-menu-item{display:flex;align-items:center;gap:var(--ui-spacing-2);padding:var(--ui-spacing-2) var(--ui-spacing-3);cursor:pointer;color:var(--ui-color-text);transition:background var(--ui-transition-fast);outline:none;border:none;background:none;font:inherit;width:100%;text-align:start}.llm-menu-item:hover,.llm-menu-item:focus-visible,.llm-menu-item.cdk-menu-item-highlighted{background:var(--ui-color-surface-sunken)}.llm-menu-item.is-disabled{opacity:var(--ui-opacity-disabled);cursor:not-allowed}.llm-menu-item-chevron{margin-inline-start:auto;font-size:var(--ui-font-size-lg);color:var(--ui-color-text-muted);line-height:1}.llm-menu-separator{display:block;height:1px;margin:var(--ui-spacing-1) 0;background:var(--ui-color-border)}\n"] }]
|
|
2034
|
+
}], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }] } });
|
|
2035
|
+
/**
|
|
2036
|
+
* A single item inside an `<llm-menu>`.
|
|
2037
|
+
* Supports keyboard navigation, disabled state, and nested submenus via `[llmMenuTriggerFor]`.
|
|
2038
|
+
*
|
|
2039
|
+
* Usage:
|
|
2040
|
+
* ```html
|
|
2041
|
+
* <llm-menu-item (triggered)="doSomething()">Label</llm-menu-item>
|
|
2042
|
+
* <llm-menu-item [disabled]="true">Disabled</llm-menu-item>
|
|
2043
|
+
* ```
|
|
2044
|
+
*/
|
|
2045
|
+
class LlmMenuItem {
|
|
2046
|
+
/** Whether this menu item is disabled. */
|
|
2047
|
+
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
|
|
2048
|
+
/** @internal — detect if this item also triggers a submenu */
|
|
2049
|
+
menuTrigger = inject(CdkMenuTrigger, { optional: true, self: true });
|
|
2050
|
+
/** @internal */
|
|
2051
|
+
hasSubmenu = computed(() => !!this.menuTrigger, ...(ngDevMode ? [{ debugName: "hasSubmenu" }] : /* istanbul ignore next */ []));
|
|
2052
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmMenuItem, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2053
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.4", type: LlmMenuItem, isStandalone: true, selector: "llm-menu-item", inputs: { disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.is-disabled": "disabled()" }, classAttribute: "llm-menu-item" }, hostDirectives: [{ directive: i1$3.CdkMenuItem, inputs: ["cdkMenuItemDisabled", "disabled"], outputs: ["cdkMenuItemTriggered", "triggered"] }], ngImport: i0, template: `
|
|
2054
|
+
<ng-content />
|
|
2055
|
+
@if (hasSubmenu()) {
|
|
2056
|
+
<span class="llm-menu-item-chevron" aria-hidden="true">›</span>
|
|
2057
|
+
}
|
|
2058
|
+
`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2059
|
+
}
|
|
2060
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmMenuItem, decorators: [{
|
|
2061
|
+
type: Component,
|
|
2062
|
+
args: [{
|
|
2063
|
+
selector: 'llm-menu-item',
|
|
2064
|
+
standalone: true,
|
|
2065
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
2066
|
+
hostDirectives: [
|
|
2067
|
+
{
|
|
2068
|
+
directive: CdkMenuItem,
|
|
2069
|
+
inputs: ['cdkMenuItemDisabled: disabled'],
|
|
2070
|
+
outputs: ['cdkMenuItemTriggered: triggered'],
|
|
2071
|
+
},
|
|
2072
|
+
],
|
|
2073
|
+
template: `
|
|
2074
|
+
<ng-content />
|
|
2075
|
+
@if (hasSubmenu()) {
|
|
2076
|
+
<span class="llm-menu-item-chevron" aria-hidden="true">›</span>
|
|
2077
|
+
}
|
|
2078
|
+
`,
|
|
2079
|
+
host: {
|
|
2080
|
+
class: 'llm-menu-item',
|
|
2081
|
+
'[class.is-disabled]': 'disabled()',
|
|
2082
|
+
},
|
|
2083
|
+
}]
|
|
2084
|
+
}], propDecorators: { disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }] } });
|
|
2085
|
+
/**
|
|
2086
|
+
* Visual separator between groups of menu items.
|
|
2087
|
+
*
|
|
2088
|
+
* Usage:
|
|
2089
|
+
* ```html
|
|
2090
|
+
* <llm-menu-item>Copy</llm-menu-item>
|
|
2091
|
+
* <llm-menu-separator />
|
|
2092
|
+
* <llm-menu-item>Delete</llm-menu-item>
|
|
2093
|
+
* ```
|
|
2094
|
+
*/
|
|
2095
|
+
class LlmMenuSeparator {
|
|
2096
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmMenuSeparator, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2097
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.4", type: LlmMenuSeparator, isStandalone: true, selector: "llm-menu-separator", host: { attributes: { "role": "separator" }, classAttribute: "llm-menu-separator" }, ngImport: i0, template: ``, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2098
|
+
}
|
|
2099
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmMenuSeparator, decorators: [{
|
|
2100
|
+
type: Component,
|
|
2101
|
+
args: [{
|
|
2102
|
+
selector: 'llm-menu-separator',
|
|
2103
|
+
standalone: true,
|
|
2104
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
2105
|
+
template: ``,
|
|
2106
|
+
host: {
|
|
2107
|
+
class: 'llm-menu-separator',
|
|
2108
|
+
role: 'separator',
|
|
2109
|
+
},
|
|
2110
|
+
}]
|
|
2111
|
+
}] });
|
|
2112
|
+
|
|
2113
|
+
let nextTooltipId = 0;
|
|
2114
|
+
/** @internal — Rendered inside the CDK overlay when the tooltip is visible. */
|
|
2115
|
+
class LlmTooltipContent {
|
|
2116
|
+
/** @internal */
|
|
2117
|
+
text = input('', ...(ngDevMode ? [{ debugName: "text" }] : /* istanbul ignore next */ []));
|
|
2118
|
+
/** @internal */
|
|
2119
|
+
tooltipId = input('', ...(ngDevMode ? [{ debugName: "tooltipId" }] : /* istanbul ignore next */ []));
|
|
2120
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmTooltipContent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2121
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.4", type: LlmTooltipContent, isStandalone: true, selector: "llm-tooltip-content", inputs: { text: { classPropertyName: "text", publicName: "text", isSignal: true, isRequired: false, transformFunction: null }, tooltipId: { classPropertyName: "tooltipId", publicName: "tooltipId", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "tooltip" }, properties: { "id": "tooltipId()" }, classAttribute: "llm-tooltip" }, ngImport: i0, template: `{{ text() }}`, isInline: true, styles: [".llm-tooltip{display:block;padding:var(--ui-spacing-1) var(--ui-spacing-2);background:var(--ui-color-text);color:var(--ui-color-surface);font-family:var(--ui-font-family);font-size:var(--ui-font-size-xs);line-height:var(--ui-line-height-normal);border-radius:var(--ui-radius-sm);box-shadow:var(--ui-shadow-md);max-width:20rem;word-wrap:break-word;pointer-events:none;animation:llm-tooltip-enter var(--ui-duration-fast) var(--ui-ease-out) forwards}@keyframes llm-tooltip-enter{0%{opacity:0;transform:scale(.95)}to{opacity:1;transform:scale(1)}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
2122
|
+
}
|
|
2123
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmTooltipContent, decorators: [{
|
|
2124
|
+
type: Component,
|
|
2125
|
+
args: [{ selector: 'llm-tooltip-content', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: `{{ text() }}`, host: {
|
|
2126
|
+
class: 'llm-tooltip',
|
|
2127
|
+
role: 'tooltip',
|
|
2128
|
+
'[id]': 'tooltipId()',
|
|
2129
|
+
}, styles: [".llm-tooltip{display:block;padding:var(--ui-spacing-1) var(--ui-spacing-2);background:var(--ui-color-text);color:var(--ui-color-surface);font-family:var(--ui-font-family);font-size:var(--ui-font-size-xs);line-height:var(--ui-line-height-normal);border-radius:var(--ui-radius-sm);box-shadow:var(--ui-shadow-md);max-width:20rem;word-wrap:break-word;pointer-events:none;animation:llm-tooltip-enter var(--ui-duration-fast) var(--ui-ease-out) forwards}@keyframes llm-tooltip-enter{0%{opacity:0;transform:scale(.95)}to{opacity:1;transform:scale(1)}}\n"] }]
|
|
2130
|
+
}], propDecorators: { text: [{ type: i0.Input, args: [{ isSignal: true, alias: "text", required: false }] }], tooltipId: [{ type: i0.Input, args: [{ isSignal: true, alias: "tooltipId", required: false }] }] } });
|
|
2131
|
+
const POSITIONS = {
|
|
2132
|
+
above: [
|
|
2133
|
+
{ originX: 'center', originY: 'top', overlayX: 'center', overlayY: 'bottom', offsetY: -8 },
|
|
2134
|
+
{ originX: 'center', originY: 'bottom', overlayX: 'center', overlayY: 'top', offsetY: 8 },
|
|
2135
|
+
],
|
|
2136
|
+
below: [
|
|
2137
|
+
{ originX: 'center', originY: 'bottom', overlayX: 'center', overlayY: 'top', offsetY: 8 },
|
|
2138
|
+
{ originX: 'center', originY: 'top', overlayX: 'center', overlayY: 'bottom', offsetY: -8 },
|
|
2139
|
+
],
|
|
2140
|
+
left: [
|
|
2141
|
+
{ originX: 'start', originY: 'center', overlayX: 'end', overlayY: 'center', offsetX: -8 },
|
|
2142
|
+
{ originX: 'end', originY: 'center', overlayX: 'start', overlayY: 'center', offsetX: 8 },
|
|
2143
|
+
],
|
|
2144
|
+
right: [
|
|
2145
|
+
{ originX: 'end', originY: 'center', overlayX: 'start', overlayY: 'center', offsetX: 8 },
|
|
2146
|
+
{ originX: 'start', originY: 'center', overlayX: 'end', overlayY: 'center', offsetX: -8 },
|
|
2147
|
+
],
|
|
2148
|
+
};
|
|
2149
|
+
/**
|
|
2150
|
+
* Attribute directive that displays a text tooltip on hover or focus.
|
|
2151
|
+
* Uses `@angular/cdk/overlay` for viewport-aware positioning.
|
|
2152
|
+
*
|
|
2153
|
+
* Usage:
|
|
2154
|
+
* ```html
|
|
2155
|
+
* <llm-button llmTooltip="Save your changes">Save</llm-button>
|
|
2156
|
+
* <llm-button llmTooltip="Copy to clipboard" llmTooltipPosition="right">Copy</llm-button>
|
|
2157
|
+
* ```
|
|
2158
|
+
*/
|
|
2159
|
+
class LlmTooltip {
|
|
2160
|
+
/** The tooltip text. */
|
|
2161
|
+
llmTooltip = input.required(...(ngDevMode ? [{ debugName: "llmTooltip" }] : /* istanbul ignore next */ []));
|
|
2162
|
+
/** Preferred tooltip placement. Falls back to the opposite side if clipped. */
|
|
2163
|
+
llmTooltipPosition = input('above', ...(ngDevMode ? [{ debugName: "llmTooltipPosition" }] : /* istanbul ignore next */ []));
|
|
2164
|
+
/** Disable the tooltip without removing the directive. */
|
|
2165
|
+
llmTooltipDisabled = input(false, ...(ngDevMode ? [{ debugName: "llmTooltipDisabled" }] : /* istanbul ignore next */ []));
|
|
2166
|
+
/** Delay in ms before the tooltip appears. */
|
|
2167
|
+
llmTooltipShowDelay = input(300, ...(ngDevMode ? [{ debugName: "llmTooltipShowDelay" }] : /* istanbul ignore next */ []));
|
|
2168
|
+
/** Delay in ms before the tooltip hides. */
|
|
2169
|
+
llmTooltipHideDelay = input(0, ...(ngDevMode ? [{ debugName: "llmTooltipHideDelay" }] : /* istanbul ignore next */ []));
|
|
2170
|
+
injector = inject(Injector);
|
|
2171
|
+
elementRef = inject(ElementRef);
|
|
2172
|
+
overlayRef = null;
|
|
2173
|
+
showTimer = null;
|
|
2174
|
+
hideTimer = null;
|
|
2175
|
+
/** @internal — links host aria-describedby to the tooltip element */
|
|
2176
|
+
activeTooltipId = signal(null, ...(ngDevMode ? [{ debugName: "activeTooltipId" }] : /* istanbul ignore next */ []));
|
|
2177
|
+
/** @internal */
|
|
2178
|
+
show() {
|
|
2179
|
+
if (this.llmTooltipDisabled() || !this.llmTooltip())
|
|
2180
|
+
return;
|
|
2181
|
+
this.clearHideTimer();
|
|
2182
|
+
if (this.overlayRef?.hasAttached())
|
|
2183
|
+
return;
|
|
2184
|
+
this.showTimer = setTimeout(() => {
|
|
2185
|
+
this.showTimer = null;
|
|
2186
|
+
this.attach();
|
|
2187
|
+
}, this.llmTooltipShowDelay());
|
|
2188
|
+
}
|
|
2189
|
+
/** @internal */
|
|
2190
|
+
hide() {
|
|
2191
|
+
this.clearShowTimer();
|
|
2192
|
+
if (!this.overlayRef?.hasAttached())
|
|
2193
|
+
return;
|
|
2194
|
+
this.hideTimer = setTimeout(() => {
|
|
2195
|
+
this.hideTimer = null;
|
|
2196
|
+
this.overlayRef?.detach();
|
|
2197
|
+
this.activeTooltipId.set(null);
|
|
2198
|
+
}, this.llmTooltipHideDelay());
|
|
2199
|
+
}
|
|
2200
|
+
ngOnDestroy() {
|
|
2201
|
+
this.clearShowTimer();
|
|
2202
|
+
this.clearHideTimer();
|
|
2203
|
+
this.overlayRef?.dispose();
|
|
2204
|
+
this.overlayRef = null;
|
|
2205
|
+
}
|
|
2206
|
+
attach() {
|
|
2207
|
+
if (!this.overlayRef) {
|
|
2208
|
+
this.overlayRef = this.createOverlay();
|
|
2209
|
+
}
|
|
2210
|
+
if (this.overlayRef.hasAttached())
|
|
2211
|
+
return;
|
|
2212
|
+
const id = `llm-tooltip-${nextTooltipId++}`;
|
|
2213
|
+
const portal = new ComponentPortal(LlmTooltipContent);
|
|
2214
|
+
const ref = this.overlayRef.attach(portal);
|
|
2215
|
+
ref.setInput('text', this.llmTooltip());
|
|
2216
|
+
ref.setInput('tooltipId', id);
|
|
2217
|
+
this.activeTooltipId.set(id);
|
|
2218
|
+
}
|
|
2219
|
+
createOverlay() {
|
|
2220
|
+
const positions = POSITIONS[this.llmTooltipPosition()] ?? POSITIONS['above'];
|
|
2221
|
+
const positionStrategy = createFlexibleConnectedPositionStrategy(this.injector, this.elementRef)
|
|
2222
|
+
.withPositions(positions)
|
|
2223
|
+
.withFlexibleDimensions(false)
|
|
2224
|
+
.withPush(true);
|
|
2225
|
+
const scrollStrategy = createRepositionScrollStrategy(this.injector);
|
|
2226
|
+
return createOverlayRef(this.injector, {
|
|
2227
|
+
positionStrategy,
|
|
2228
|
+
scrollStrategy,
|
|
2229
|
+
panelClass: 'llm-tooltip-panel',
|
|
2230
|
+
});
|
|
2231
|
+
}
|
|
2232
|
+
clearShowTimer() {
|
|
2233
|
+
if (this.showTimer !== null) {
|
|
2234
|
+
clearTimeout(this.showTimer);
|
|
2235
|
+
this.showTimer = null;
|
|
2236
|
+
}
|
|
2237
|
+
}
|
|
2238
|
+
clearHideTimer() {
|
|
2239
|
+
if (this.hideTimer !== null) {
|
|
2240
|
+
clearTimeout(this.hideTimer);
|
|
2241
|
+
this.hideTimer = null;
|
|
2242
|
+
}
|
|
2243
|
+
}
|
|
2244
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmTooltip, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
2245
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.4", type: LlmTooltip, isStandalone: true, selector: "[llmTooltip]", inputs: { llmTooltip: { classPropertyName: "llmTooltip", publicName: "llmTooltip", isSignal: true, isRequired: true, transformFunction: null }, llmTooltipPosition: { classPropertyName: "llmTooltipPosition", publicName: "llmTooltipPosition", isSignal: true, isRequired: false, transformFunction: null }, llmTooltipDisabled: { classPropertyName: "llmTooltipDisabled", publicName: "llmTooltipDisabled", isSignal: true, isRequired: false, transformFunction: null }, llmTooltipShowDelay: { classPropertyName: "llmTooltipShowDelay", publicName: "llmTooltipShowDelay", isSignal: true, isRequired: false, transformFunction: null }, llmTooltipHideDelay: { classPropertyName: "llmTooltipHideDelay", publicName: "llmTooltipHideDelay", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "mouseenter": "show()", "mouseleave": "hide()", "focusin": "show()", "focusout": "hide()", "keydown.escape": "hide()" }, properties: { "attr.aria-describedby": "activeTooltipId()" } }, ngImport: i0 });
|
|
2246
|
+
}
|
|
2247
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmTooltip, decorators: [{
|
|
2248
|
+
type: Directive,
|
|
2249
|
+
args: [{
|
|
2250
|
+
selector: '[llmTooltip]',
|
|
2251
|
+
standalone: true,
|
|
2252
|
+
host: {
|
|
2253
|
+
'(mouseenter)': 'show()',
|
|
2254
|
+
'(mouseleave)': 'hide()',
|
|
2255
|
+
'(focusin)': 'show()',
|
|
2256
|
+
'(focusout)': 'hide()',
|
|
2257
|
+
'(keydown.escape)': 'hide()',
|
|
2258
|
+
'[attr.aria-describedby]': 'activeTooltipId()',
|
|
2259
|
+
},
|
|
2260
|
+
}]
|
|
2261
|
+
}], propDecorators: { llmTooltip: [{ type: i0.Input, args: [{ isSignal: true, alias: "llmTooltip", required: true }] }], llmTooltipPosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "llmTooltipPosition", required: false }] }], llmTooltipDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "llmTooltipDisabled", required: false }] }], llmTooltipShowDelay: [{ type: i0.Input, args: [{ isSignal: true, alias: "llmTooltipShowDelay", required: false }] }], llmTooltipHideDelay: [{ type: i0.Input, args: [{ isSignal: true, alias: "llmTooltipHideDelay", required: false }] }] } });
|
|
2262
|
+
|
|
2263
|
+
/**
|
|
2264
|
+
* Loading placeholder that mimics the shape of content while it loads.
|
|
2265
|
+
*
|
|
2266
|
+
* Usage:
|
|
2267
|
+
* ```html
|
|
2268
|
+
* <llm-skeleton />
|
|
2269
|
+
* <llm-skeleton variant="circular" width="40px" />
|
|
2270
|
+
* <llm-skeleton variant="rectangular" height="200px" />
|
|
2271
|
+
* ```
|
|
2272
|
+
*/
|
|
2273
|
+
class LlmSkeleton {
|
|
2274
|
+
/** Shape variant of the skeleton placeholder. */
|
|
2275
|
+
variant = input('text', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
|
|
2276
|
+
/** CSS width of the skeleton. */
|
|
2277
|
+
width = input('100%', ...(ngDevMode ? [{ debugName: "width" }] : /* istanbul ignore next */ []));
|
|
2278
|
+
/** CSS height — when empty, a sensible default is chosen per variant. */
|
|
2279
|
+
height = input('', ...(ngDevMode ? [{ debugName: "height" }] : /* istanbul ignore next */ []));
|
|
2280
|
+
/** Whether the shimmer animation is active. */
|
|
2281
|
+
animated = input(true, ...(ngDevMode ? [{ debugName: "animated" }] : /* istanbul ignore next */ []));
|
|
2282
|
+
computedHeight = computed(() => {
|
|
2283
|
+
if (this.height())
|
|
2284
|
+
return this.height();
|
|
2285
|
+
switch (this.variant()) {
|
|
2286
|
+
case 'text':
|
|
2287
|
+
return '1em';
|
|
2288
|
+
case 'circular':
|
|
2289
|
+
return this.width();
|
|
2290
|
+
case 'rectangular':
|
|
2291
|
+
return '100px';
|
|
2292
|
+
}
|
|
2293
|
+
}, ...(ngDevMode ? [{ debugName: "computedHeight" }] : /* istanbul ignore next */ []));
|
|
2294
|
+
hostClasses = computed(() => {
|
|
2295
|
+
const classes = [`variant-${this.variant()}`];
|
|
2296
|
+
if (this.animated())
|
|
2297
|
+
classes.push('is-animated');
|
|
2298
|
+
return classes.join(' ');
|
|
2299
|
+
}, ...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
|
|
2300
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmSkeleton, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2301
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.4", type: LlmSkeleton, isStandalone: true, selector: "llm-skeleton", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, width: { classPropertyName: "width", publicName: "width", isSignal: true, isRequired: false, transformFunction: null }, height: { classPropertyName: "height", publicName: "height", isSignal: true, isRequired: false, transformFunction: null }, animated: { classPropertyName: "animated", publicName: "animated", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "aria-hidden": "true" }, properties: { "class": "hostClasses()", "style.width": "width()", "style.height": "computedHeight()" } }, ngImport: i0, template: ``, isInline: true, styles: [":host{display:block;background:var(--ui-color-border);overflow:hidden;position:relative}:host(.variant-text){border-radius:var(--ui-radius-sm)}:host(.variant-circular){border-radius:var(--ui-radius-full, 9999px)}:host(.variant-rectangular){border-radius:var(--ui-radius-md)}:host(.is-animated):after{content:\"\";position:absolute;inset:0;background:linear-gradient(90deg,transparent 0%,rgba(255,255,255,.3) 50%,transparent 100%);animation:shimmer 1.5s infinite}@keyframes shimmer{0%{transform:translate(-100%)}to{transform:translate(100%)}}@media(prefers-reduced-motion:reduce){:host(.is-animated):after{animation:none}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2302
|
+
}
|
|
2303
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmSkeleton, decorators: [{
|
|
2304
|
+
type: Component,
|
|
2305
|
+
args: [{ selector: 'llm-skeleton', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: ``, host: {
|
|
2306
|
+
'[class]': 'hostClasses()',
|
|
2307
|
+
'[style.width]': 'width()',
|
|
2308
|
+
'[style.height]': 'computedHeight()',
|
|
2309
|
+
'aria-hidden': 'true',
|
|
2310
|
+
}, styles: [":host{display:block;background:var(--ui-color-border);overflow:hidden;position:relative}:host(.variant-text){border-radius:var(--ui-radius-sm)}:host(.variant-circular){border-radius:var(--ui-radius-full, 9999px)}:host(.variant-rectangular){border-radius:var(--ui-radius-md)}:host(.is-animated):after{content:\"\";position:absolute;inset:0;background:linear-gradient(90deg,transparent 0%,rgba(255,255,255,.3) 50%,transparent 100%);animation:shimmer 1.5s infinite}@keyframes shimmer{0%{transform:translate(-100%)}to{transform:translate(100%)}}@media(prefers-reduced-motion:reduce){:host(.is-animated):after{animation:none}}\n"] }]
|
|
2311
|
+
}], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }], animated: [{ type: i0.Input, args: [{ isSignal: true, alias: "animated", required: false }] }] } });
|
|
2312
|
+
|
|
2313
|
+
let toastId = 0;
|
|
2314
|
+
/**
|
|
2315
|
+
* Service for showing transient toast notifications.
|
|
2316
|
+
*
|
|
2317
|
+
* Usage:
|
|
2318
|
+
* ```typescript
|
|
2319
|
+
* const toast = inject(LlmToastService);
|
|
2320
|
+
* toast.show('Saved successfully', { variant: 'success' });
|
|
2321
|
+
* ```
|
|
2322
|
+
*/
|
|
2323
|
+
class LlmToastService {
|
|
2324
|
+
toasts = signal([], ...(ngDevMode ? [{ debugName: "toasts" }] : /* istanbul ignore next */ []));
|
|
2325
|
+
timers = new Map();
|
|
2326
|
+
/**
|
|
2327
|
+
* Show a toast notification.
|
|
2328
|
+
* @returns The unique id of the toast, which can be used with `dismiss()`.
|
|
2329
|
+
*/
|
|
2330
|
+
show(message, options) {
|
|
2331
|
+
const id = `llm-toast-${toastId++}`;
|
|
2332
|
+
const toast = {
|
|
2333
|
+
id,
|
|
2334
|
+
message,
|
|
2335
|
+
variant: options?.variant ?? 'default',
|
|
2336
|
+
duration: options?.duration ?? 5000,
|
|
2337
|
+
dismissible: options?.dismissible ?? true,
|
|
2338
|
+
};
|
|
2339
|
+
this.toasts.update((list) => [...list, toast]);
|
|
2340
|
+
if (toast.duration > 0) {
|
|
2341
|
+
const timer = setTimeout(() => this.dismiss(id), toast.duration);
|
|
2342
|
+
this.timers.set(id, timer);
|
|
2343
|
+
}
|
|
2344
|
+
return id;
|
|
2345
|
+
}
|
|
2346
|
+
/** Dismiss a single toast by id. */
|
|
2347
|
+
dismiss(id) {
|
|
2348
|
+
const timer = this.timers.get(id);
|
|
2349
|
+
if (timer !== undefined) {
|
|
2350
|
+
clearTimeout(timer);
|
|
2351
|
+
this.timers.delete(id);
|
|
2352
|
+
}
|
|
2353
|
+
this.toasts.update((list) => list.filter((t) => t.id !== id));
|
|
2354
|
+
}
|
|
2355
|
+
/** Clear all active toasts. */
|
|
2356
|
+
clear() {
|
|
2357
|
+
for (const timer of this.timers.values()) {
|
|
2358
|
+
clearTimeout(timer);
|
|
2359
|
+
}
|
|
2360
|
+
this.timers.clear();
|
|
2361
|
+
this.toasts.set([]);
|
|
2362
|
+
}
|
|
2363
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmToastService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
2364
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmToastService, providedIn: 'root' });
|
|
2365
|
+
}
|
|
2366
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmToastService, decorators: [{
|
|
2367
|
+
type: Injectable,
|
|
2368
|
+
args: [{ providedIn: 'root' }]
|
|
2369
|
+
}] });
|
|
2370
|
+
/**
|
|
2371
|
+
* Individual toast notification.
|
|
2372
|
+
*
|
|
2373
|
+
* Typically rendered by `llm-toast-container`, but can also be used standalone.
|
|
2374
|
+
*/
|
|
2375
|
+
class LlmToast {
|
|
2376
|
+
/** Semantic color variant. */
|
|
2377
|
+
variant = input('default', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
|
|
2378
|
+
/** Whether to show a dismiss button. */
|
|
2379
|
+
dismissible = input(true, ...(ngDevMode ? [{ debugName: "dismissible" }] : /* istanbul ignore next */ []));
|
|
2380
|
+
/** The message to display. */
|
|
2381
|
+
message = input('', ...(ngDevMode ? [{ debugName: "message" }] : /* istanbul ignore next */ []));
|
|
2382
|
+
/** Unique identifier for this toast. */
|
|
2383
|
+
toastId = input('', ...(ngDevMode ? [{ debugName: "toastId" }] : /* istanbul ignore next */ []));
|
|
2384
|
+
/** Emitted when the toast is dismissed by the user. */
|
|
2385
|
+
dismissed = output();
|
|
2386
|
+
hostClasses = computed(() => `variant-${this.variant()}`, ...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
|
|
2387
|
+
onDismiss() {
|
|
2388
|
+
this.dismissed.emit(this.toastId());
|
|
2389
|
+
}
|
|
2390
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmToast, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2391
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.4", type: LlmToast, isStandalone: true, selector: "llm-toast", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, dismissible: { classPropertyName: "dismissible", publicName: "dismissible", isSignal: true, isRequired: false, transformFunction: null }, message: { classPropertyName: "message", publicName: "message", isSignal: true, isRequired: false, transformFunction: null }, toastId: { classPropertyName: "toastId", publicName: "toastId", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { dismissed: "dismissed" }, host: { attributes: { "role": "status" }, properties: { "class": "hostClasses()" } }, ngImport: i0, template: `
|
|
2392
|
+
<span class="message">{{ message() }}</span>
|
|
2393
|
+
@if (dismissible()) {
|
|
2394
|
+
<button class="dismiss" type="button" aria-label="Dismiss" (click)="onDismiss()">
|
|
2395
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">
|
|
2396
|
+
<line x1="18" y1="6" x2="6" y2="18" />
|
|
2397
|
+
<line x1="6" y1="6" x2="18" y2="18" />
|
|
2398
|
+
</svg>
|
|
2399
|
+
</button>
|
|
2400
|
+
}
|
|
2401
|
+
`, isInline: true, styles: [":host{display:flex;align-items:center;gap:var(--ui-spacing-3);padding:var(--ui-spacing-3) var(--ui-spacing-4);border-radius:var(--ui-radius-md);border-left:3px solid transparent;font-family:var(--ui-font-family);font-size:var(--ui-font-size-sm);line-height:var(--ui-line-height-normal);box-shadow:var(--ui-shadow-md);background-color:var(--ui-color-surface-raised, var(--ui-color-surface));color:var(--ui-color-text);pointer-events:auto;min-width:16rem;max-width:100%;box-sizing:border-box;animation:toast-enter .3s ease-out}:host(.variant-default){border-left-color:var(--ui-color-border)}:host(.variant-success){border-left-color:var(--ui-color-success);background-color:color-mix(in srgb,var(--ui-color-success) 8%,var(--ui-color-surface-raised, var(--ui-color-surface)))}:host(.variant-warning){border-left-color:var(--ui-color-warning);background-color:color-mix(in srgb,var(--ui-color-warning) 8%,var(--ui-color-surface-raised, var(--ui-color-surface)))}:host(.variant-danger){border-left-color:var(--ui-color-danger);background-color:color-mix(in srgb,var(--ui-color-danger) 8%,var(--ui-color-surface-raised, var(--ui-color-surface)))}:host(.variant-info){border-left-color:var(--ui-color-info);background-color:color-mix(in srgb,var(--ui-color-info) 8%,var(--ui-color-surface-raised, var(--ui-color-surface)))}.message{flex:1}.dismiss{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;padding:.125rem;background:transparent;border:none;border-radius:var(--ui-radius-sm);cursor:pointer;color:var(--ui-color-text-muted, currentColor);opacity:.7;transition:opacity var(--ui-transition-fast, .15s),background-color var(--ui-transition-fast, .15s);line-height:1}.dismiss:hover{opacity:1;background-color:color-mix(in srgb,currentColor 10%,transparent)}.dismiss:focus-visible{outline:none;box-shadow:var(--ui-focus-ring);opacity:1}@keyframes toast-enter{0%{opacity:0;transform:translateY(.5rem)}to{opacity:1;transform:translateY(0)}}@media(prefers-reduced-motion:reduce){:host{animation:none}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2402
|
+
}
|
|
2403
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmToast, decorators: [{
|
|
2404
|
+
type: Component,
|
|
2405
|
+
args: [{ selector: 'llm-toast', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: `
|
|
2406
|
+
<span class="message">{{ message() }}</span>
|
|
2407
|
+
@if (dismissible()) {
|
|
2408
|
+
<button class="dismiss" type="button" aria-label="Dismiss" (click)="onDismiss()">
|
|
2409
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">
|
|
2410
|
+
<line x1="18" y1="6" x2="6" y2="18" />
|
|
2411
|
+
<line x1="6" y1="6" x2="18" y2="18" />
|
|
2412
|
+
</svg>
|
|
2413
|
+
</button>
|
|
2414
|
+
}
|
|
2415
|
+
`, host: {
|
|
2416
|
+
'[class]': 'hostClasses()',
|
|
2417
|
+
role: 'status',
|
|
2418
|
+
}, styles: [":host{display:flex;align-items:center;gap:var(--ui-spacing-3);padding:var(--ui-spacing-3) var(--ui-spacing-4);border-radius:var(--ui-radius-md);border-left:3px solid transparent;font-family:var(--ui-font-family);font-size:var(--ui-font-size-sm);line-height:var(--ui-line-height-normal);box-shadow:var(--ui-shadow-md);background-color:var(--ui-color-surface-raised, var(--ui-color-surface));color:var(--ui-color-text);pointer-events:auto;min-width:16rem;max-width:100%;box-sizing:border-box;animation:toast-enter .3s ease-out}:host(.variant-default){border-left-color:var(--ui-color-border)}:host(.variant-success){border-left-color:var(--ui-color-success);background-color:color-mix(in srgb,var(--ui-color-success) 8%,var(--ui-color-surface-raised, var(--ui-color-surface)))}:host(.variant-warning){border-left-color:var(--ui-color-warning);background-color:color-mix(in srgb,var(--ui-color-warning) 8%,var(--ui-color-surface-raised, var(--ui-color-surface)))}:host(.variant-danger){border-left-color:var(--ui-color-danger);background-color:color-mix(in srgb,var(--ui-color-danger) 8%,var(--ui-color-surface-raised, var(--ui-color-surface)))}:host(.variant-info){border-left-color:var(--ui-color-info);background-color:color-mix(in srgb,var(--ui-color-info) 8%,var(--ui-color-surface-raised, var(--ui-color-surface)))}.message{flex:1}.dismiss{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;padding:.125rem;background:transparent;border:none;border-radius:var(--ui-radius-sm);cursor:pointer;color:var(--ui-color-text-muted, currentColor);opacity:.7;transition:opacity var(--ui-transition-fast, .15s),background-color var(--ui-transition-fast, .15s);line-height:1}.dismiss:hover{opacity:1;background-color:color-mix(in srgb,currentColor 10%,transparent)}.dismiss:focus-visible{outline:none;box-shadow:var(--ui-focus-ring);opacity:1}@keyframes toast-enter{0%{opacity:0;transform:translateY(.5rem)}to{opacity:1;transform:translateY(0)}}@media(prefers-reduced-motion:reduce){:host{animation:none}}\n"] }]
|
|
2419
|
+
}], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], dismissible: [{ type: i0.Input, args: [{ isSignal: true, alias: "dismissible", required: false }] }], message: [{ type: i0.Input, args: [{ isSignal: true, alias: "message", required: false }] }], toastId: [{ type: i0.Input, args: [{ isSignal: true, alias: "toastId", required: false }] }], dismissed: [{ type: i0.Output, args: ["dismissed"] }] } });
|
|
2420
|
+
/**
|
|
2421
|
+
* Container that renders the toast stack at a fixed viewport position.
|
|
2422
|
+
* Place once in your app root or layout component.
|
|
2423
|
+
*
|
|
2424
|
+
* Usage:
|
|
2425
|
+
* ```html
|
|
2426
|
+
* <llm-toast-container position="bottom-right" />
|
|
2427
|
+
* ```
|
|
2428
|
+
*/
|
|
2429
|
+
class LlmToastContainer {
|
|
2430
|
+
toastService = inject(LlmToastService);
|
|
2431
|
+
destroyRef = inject(DestroyRef);
|
|
2432
|
+
/** Position of the toast stack on the viewport. */
|
|
2433
|
+
position = input('bottom-right', ...(ngDevMode ? [{ debugName: "position" }] : /* istanbul ignore next */ []));
|
|
2434
|
+
hostClasses = computed(() => `position-${this.position()}`, ...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
|
|
2435
|
+
constructor() {
|
|
2436
|
+
this.destroyRef.onDestroy(() => this.toastService.clear());
|
|
2437
|
+
}
|
|
2438
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmToastContainer, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2439
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.4", type: LlmToastContainer, isStandalone: true, selector: "llm-toast-container", inputs: { position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "aria-live": "polite", "role": "status" }, properties: { "class": "hostClasses()" } }, ngImport: i0, template: `
|
|
2440
|
+
@for (toast of toastService.toasts(); track toast.id) {
|
|
2441
|
+
<llm-toast
|
|
2442
|
+
[variant]="toast.variant"
|
|
2443
|
+
[dismissible]="toast.dismissible"
|
|
2444
|
+
[message]="toast.message"
|
|
2445
|
+
[toastId]="toast.id"
|
|
2446
|
+
(dismissed)="toastService.dismiss($event)"
|
|
2447
|
+
/>
|
|
2448
|
+
}
|
|
2449
|
+
`, isInline: true, styles: [":host{position:fixed;z-index:var(--ui-z-toast, 400);display:flex;flex-direction:column;gap:var(--ui-spacing-2);pointer-events:none;max-width:min(24rem,calc(100vw - 2rem));box-sizing:border-box}:host(.position-bottom-right){bottom:var(--ui-spacing-4);right:var(--ui-spacing-4);align-items:flex-end}:host(.position-bottom-center){bottom:var(--ui-spacing-4);left:50%;transform:translate(-50%);align-items:center}:host(.position-top-right){top:var(--ui-spacing-4);right:var(--ui-spacing-4);align-items:flex-end}:host(.position-top-center){top:var(--ui-spacing-4);left:50%;transform:translate(-50%);align-items:center}\n"], dependencies: [{ kind: "component", type: LlmToast, selector: "llm-toast", inputs: ["variant", "dismissible", "message", "toastId"], outputs: ["dismissed"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2450
|
+
}
|
|
2451
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmToastContainer, decorators: [{
|
|
2452
|
+
type: Component,
|
|
2453
|
+
args: [{ selector: 'llm-toast-container', standalone: true, imports: [LlmToast], changeDetection: ChangeDetectionStrategy.OnPush, template: `
|
|
2454
|
+
@for (toast of toastService.toasts(); track toast.id) {
|
|
2455
|
+
<llm-toast
|
|
2456
|
+
[variant]="toast.variant"
|
|
2457
|
+
[dismissible]="toast.dismissible"
|
|
2458
|
+
[message]="toast.message"
|
|
2459
|
+
[toastId]="toast.id"
|
|
2460
|
+
(dismissed)="toastService.dismiss($event)"
|
|
2461
|
+
/>
|
|
2462
|
+
}
|
|
2463
|
+
`, host: {
|
|
2464
|
+
'[class]': 'hostClasses()',
|
|
2465
|
+
'aria-live': 'polite',
|
|
2466
|
+
role: 'status',
|
|
2467
|
+
}, styles: [":host{position:fixed;z-index:var(--ui-z-toast, 400);display:flex;flex-direction:column;gap:var(--ui-spacing-2);pointer-events:none;max-width:min(24rem,calc(100vw - 2rem));box-sizing:border-box}:host(.position-bottom-right){bottom:var(--ui-spacing-4);right:var(--ui-spacing-4);align-items:flex-end}:host(.position-bottom-center){bottom:var(--ui-spacing-4);left:50%;transform:translate(-50%);align-items:center}:host(.position-top-right){top:var(--ui-spacing-4);right:var(--ui-spacing-4);align-items:flex-end}:host(.position-top-center){top:var(--ui-spacing-4);left:50%;transform:translate(-50%);align-items:center}\n"] }]
|
|
2468
|
+
}], ctorParameters: () => [], propDecorators: { position: [{ type: i0.Input, args: [{ isSignal: true, alias: "position", required: false }] }] } });
|
|
2469
|
+
|
|
2470
|
+
/**
|
|
2471
|
+
* Displays a user avatar with image, initials, or icon fallback.
|
|
2472
|
+
*
|
|
2473
|
+
* Fallback order: image → initials (from `name`) → generic icon.
|
|
2474
|
+
*
|
|
2475
|
+
* Usage:
|
|
2476
|
+
* ```html
|
|
2477
|
+
* <llm-avatar src="https://example.com/photo.jpg" name="Jane Doe" />
|
|
2478
|
+
* <llm-avatar name="John Smith" size="lg" status="online" />
|
|
2479
|
+
* <llm-avatar size="sm" shape="square" />
|
|
2480
|
+
* ```
|
|
2481
|
+
*/
|
|
2482
|
+
class LlmAvatar {
|
|
2483
|
+
/** Image URL. Falls back to initials or icon if empty or fails to load. */
|
|
2484
|
+
src = input('', ...(ngDevMode ? [{ debugName: "src" }] : /* istanbul ignore next */ []));
|
|
2485
|
+
/** Alt text for the image (also used as aria-label). */
|
|
2486
|
+
alt = input('', ...(ngDevMode ? [{ debugName: "alt" }] : /* istanbul ignore next */ []));
|
|
2487
|
+
/** Full name used to generate initials fallback and default aria-label. */
|
|
2488
|
+
name = input('', ...(ngDevMode ? [{ debugName: "name" }] : /* istanbul ignore next */ []));
|
|
2489
|
+
/** Size of the avatar. */
|
|
2490
|
+
size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
2491
|
+
/** Shape of the avatar. */
|
|
2492
|
+
shape = input('circle', ...(ngDevMode ? [{ debugName: "shape" }] : /* istanbul ignore next */ []));
|
|
2493
|
+
/** Presence status indicator dot. Empty string hides the dot. */
|
|
2494
|
+
status = input('', ...(ngDevMode ? [{ debugName: "status" }] : /* istanbul ignore next */ []));
|
|
2495
|
+
/** @internal — reset to true whenever src changes */
|
|
2496
|
+
showImage = signal(true, ...(ngDevMode ? [{ debugName: "showImage" }] : /* istanbul ignore next */ []));
|
|
2497
|
+
/** @internal */
|
|
2498
|
+
initials = computed(() => {
|
|
2499
|
+
const name = this.name();
|
|
2500
|
+
if (!name)
|
|
2501
|
+
return '';
|
|
2502
|
+
return name
|
|
2503
|
+
.split(' ')
|
|
2504
|
+
.filter(Boolean)
|
|
2505
|
+
.slice(0, 2)
|
|
2506
|
+
.map((w) => w[0].toUpperCase())
|
|
2507
|
+
.join('');
|
|
2508
|
+
}, ...(ngDevMode ? [{ debugName: "initials" }] : /* istanbul ignore next */ []));
|
|
2509
|
+
/** @internal */
|
|
2510
|
+
ariaLabel = computed(() => this.alt() || this.name() || 'Avatar', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
|
|
2511
|
+
/** @internal */
|
|
2512
|
+
hostClasses = computed(() => `size-${this.size()} shape-${this.shape()}`, ...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
|
|
2513
|
+
constructor() {
|
|
2514
|
+
effect(() => {
|
|
2515
|
+
this.src(); // track src changes
|
|
2516
|
+
untracked(() => this.showImage.set(true));
|
|
2517
|
+
});
|
|
2518
|
+
}
|
|
2519
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmAvatar, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2520
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.4", type: LlmAvatar, isStandalone: true, selector: "llm-avatar", inputs: { src: { classPropertyName: "src", publicName: "src", isSignal: true, isRequired: false, transformFunction: null }, alt: { classPropertyName: "alt", publicName: "alt", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, shape: { classPropertyName: "shape", publicName: "shape", isSignal: true, isRequired: false, transformFunction: null }, status: { classPropertyName: "status", publicName: "status", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "img" }, properties: { "class": "hostClasses()", "attr.aria-label": "ariaLabel()" } }, ngImport: i0, template: `
|
|
2521
|
+
<!-- eslint-disable -->
|
|
2522
|
+
@if (src() && showImage()) {
|
|
2523
|
+
<img [src]="src()" [alt]="alt()" (error)="showImage.set(false)" />
|
|
2524
|
+
} @else if (initials()) {
|
|
2525
|
+
<span class="initials" aria-hidden="true">{{ initials() }}</span>
|
|
2526
|
+
} @else {
|
|
2527
|
+
<svg class="icon" aria-hidden="true" viewBox="0 0 24 24" fill="currentColor">
|
|
2528
|
+
<path d="M12 12c2.761 0 5-2.239 5-5s-2.239-5-5-5-5 2.239-5 5 2.239 5 5 5zm0 2c-3.314 0-10 1.343-10 4v2h20v-2c0-2.657-6.686-4-10-4z" />
|
|
2529
|
+
</svg>
|
|
2530
|
+
}
|
|
2531
|
+
@if (status()) {
|
|
2532
|
+
<span [class]="'status-dot status-' + status()" aria-hidden="true"></span>
|
|
2533
|
+
}
|
|
2534
|
+
`, isInline: true, styles: [":host{display:inline-flex;align-items:center;justify-content:center;position:relative;overflow:hidden;flex-shrink:0;font-family:var(--ui-font-family);font-weight:var(--ui-font-weight-semibold);background-color:color-mix(in srgb,var(--ui-color-primary) 12%,var(--ui-color-surface-sunken));color:var(--ui-color-primary);-webkit-user-select:none;user-select:none}:host(.size-xs){width:24px;height:24px;font-size:.625rem}:host(.size-sm){width:32px;height:32px;font-size:var(--ui-font-size-xs)}:host(.size-md){width:40px;height:40px;font-size:var(--ui-font-size-sm)}:host(.size-lg){width:48px;height:48px;font-size:var(--ui-font-size-md)}:host(.size-xl){width:64px;height:64px;font-size:var(--ui-font-size-lg)}:host(.shape-circle){border-radius:var(--ui-radius-full)}:host(.shape-square){border-radius:var(--ui-radius-md)}img{width:100%;height:100%;object-fit:cover;display:block}.initials{line-height:1;letter-spacing:.02em}.icon{width:55%;height:55%;opacity:.6}.status-dot{position:absolute;bottom:0;right:0;width:25%;height:25%;min-width:6px;min-height:6px;max-width:14px;max-height:14px;border-radius:var(--ui-radius-full);border:2px solid var(--ui-color-surface);box-sizing:content-box}.status-dot.status-online{background-color:var(--ui-color-success)}.status-dot.status-offline{background-color:var(--ui-color-text-muted)}.status-dot.status-away{background-color:var(--ui-color-warning)}.status-dot.status-busy{background-color:var(--ui-color-danger)}:host(.group){display:inline-flex;align-items:center;background:none;overflow:visible;padding-inline-start:4px}:host-context(llm-avatar-group){box-shadow:0 0 0 2px var(--ui-color-surface);margin-inline-start:-8px}.overflow-badge{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;background-color:var(--ui-color-surface-sunken);color:var(--ui-color-text-muted);border:1px solid var(--ui-color-border);border-radius:var(--ui-radius-full);font-family:var(--ui-font-family);font-weight:var(--ui-font-weight-semibold);box-shadow:0 0 0 2px var(--ui-color-surface);margin-inline-start:-8px}.overflow-badge.size-xs{width:24px;height:24px;font-size:.5625rem}.overflow-badge.size-sm{width:32px;height:32px;font-size:var(--ui-font-size-xs)}.overflow-badge.size-md{width:40px;height:40px;font-size:var(--ui-font-size-sm)}.overflow-badge.size-lg{width:48px;height:48px;font-size:var(--ui-font-size-sm)}.overflow-badge.size-xl{width:64px;height:64px;font-size:var(--ui-font-size-md)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2535
|
+
}
|
|
2536
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmAvatar, decorators: [{
|
|
2537
|
+
type: Component,
|
|
2538
|
+
args: [{ selector: 'llm-avatar', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: `
|
|
2539
|
+
<!-- eslint-disable -->
|
|
2540
|
+
@if (src() && showImage()) {
|
|
2541
|
+
<img [src]="src()" [alt]="alt()" (error)="showImage.set(false)" />
|
|
2542
|
+
} @else if (initials()) {
|
|
2543
|
+
<span class="initials" aria-hidden="true">{{ initials() }}</span>
|
|
2544
|
+
} @else {
|
|
2545
|
+
<svg class="icon" aria-hidden="true" viewBox="0 0 24 24" fill="currentColor">
|
|
2546
|
+
<path d="M12 12c2.761 0 5-2.239 5-5s-2.239-5-5-5-5 2.239-5 5 2.239 5 5 5zm0 2c-3.314 0-10 1.343-10 4v2h20v-2c0-2.657-6.686-4-10-4z" />
|
|
2547
|
+
</svg>
|
|
2548
|
+
}
|
|
2549
|
+
@if (status()) {
|
|
2550
|
+
<span [class]="'status-dot status-' + status()" aria-hidden="true"></span>
|
|
2551
|
+
}
|
|
2552
|
+
`, host: {
|
|
2553
|
+
'[class]': 'hostClasses()',
|
|
2554
|
+
role: 'img',
|
|
2555
|
+
'[attr.aria-label]': 'ariaLabel()',
|
|
2556
|
+
}, styles: [":host{display:inline-flex;align-items:center;justify-content:center;position:relative;overflow:hidden;flex-shrink:0;font-family:var(--ui-font-family);font-weight:var(--ui-font-weight-semibold);background-color:color-mix(in srgb,var(--ui-color-primary) 12%,var(--ui-color-surface-sunken));color:var(--ui-color-primary);-webkit-user-select:none;user-select:none}:host(.size-xs){width:24px;height:24px;font-size:.625rem}:host(.size-sm){width:32px;height:32px;font-size:var(--ui-font-size-xs)}:host(.size-md){width:40px;height:40px;font-size:var(--ui-font-size-sm)}:host(.size-lg){width:48px;height:48px;font-size:var(--ui-font-size-md)}:host(.size-xl){width:64px;height:64px;font-size:var(--ui-font-size-lg)}:host(.shape-circle){border-radius:var(--ui-radius-full)}:host(.shape-square){border-radius:var(--ui-radius-md)}img{width:100%;height:100%;object-fit:cover;display:block}.initials{line-height:1;letter-spacing:.02em}.icon{width:55%;height:55%;opacity:.6}.status-dot{position:absolute;bottom:0;right:0;width:25%;height:25%;min-width:6px;min-height:6px;max-width:14px;max-height:14px;border-radius:var(--ui-radius-full);border:2px solid var(--ui-color-surface);box-sizing:content-box}.status-dot.status-online{background-color:var(--ui-color-success)}.status-dot.status-offline{background-color:var(--ui-color-text-muted)}.status-dot.status-away{background-color:var(--ui-color-warning)}.status-dot.status-busy{background-color:var(--ui-color-danger)}:host(.group){display:inline-flex;align-items:center;background:none;overflow:visible;padding-inline-start:4px}:host-context(llm-avatar-group){box-shadow:0 0 0 2px var(--ui-color-surface);margin-inline-start:-8px}.overflow-badge{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;background-color:var(--ui-color-surface-sunken);color:var(--ui-color-text-muted);border:1px solid var(--ui-color-border);border-radius:var(--ui-radius-full);font-family:var(--ui-font-family);font-weight:var(--ui-font-weight-semibold);box-shadow:0 0 0 2px var(--ui-color-surface);margin-inline-start:-8px}.overflow-badge.size-xs{width:24px;height:24px;font-size:.5625rem}.overflow-badge.size-sm{width:32px;height:32px;font-size:var(--ui-font-size-xs)}.overflow-badge.size-md{width:40px;height:40px;font-size:var(--ui-font-size-sm)}.overflow-badge.size-lg{width:48px;height:48px;font-size:var(--ui-font-size-sm)}.overflow-badge.size-xl{width:64px;height:64px;font-size:var(--ui-font-size-md)}\n"] }]
|
|
2557
|
+
}], ctorParameters: () => [], propDecorators: { src: [{ type: i0.Input, args: [{ isSignal: true, alias: "src", required: false }] }], alt: [{ type: i0.Input, args: [{ isSignal: true, alias: "alt", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], shape: [{ type: i0.Input, args: [{ isSignal: true, alias: "shape", required: false }] }], status: [{ type: i0.Input, args: [{ isSignal: true, alias: "status", required: false }] }] } });
|
|
2558
|
+
/**
|
|
2559
|
+
* Groups multiple avatars with overlap and an overflow count badge.
|
|
2560
|
+
*
|
|
2561
|
+
* Usage:
|
|
2562
|
+
* ```html
|
|
2563
|
+
* <llm-avatar-group [max]="3" size="md">
|
|
2564
|
+
* <llm-avatar name="Alice" />
|
|
2565
|
+
* <llm-avatar name="Bob" />
|
|
2566
|
+
* <llm-avatar name="Charlie" />
|
|
2567
|
+
* <llm-avatar name="Dave" />
|
|
2568
|
+
* </llm-avatar-group>
|
|
2569
|
+
* ```
|
|
2570
|
+
*/
|
|
2571
|
+
class LlmAvatarGroup {
|
|
2572
|
+
/** Maximum visible avatars before showing an overflow count. */
|
|
2573
|
+
max = input(5, ...(ngDevMode ? [{ debugName: "max" }] : /* istanbul ignore next */ []));
|
|
2574
|
+
/** Size applied to the overflow badge (match the size used on child avatars). */
|
|
2575
|
+
size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
2576
|
+
avatarEls = contentChildren(LlmAvatar, { ...(ngDevMode ? { debugName: "avatarEls" } : /* istanbul ignore next */ {}), read: ElementRef });
|
|
2577
|
+
overflowCount = computed(() => Math.max(0, this.avatarEls().length - this.max()), ...(ngDevMode ? [{ debugName: "overflowCount" }] : /* istanbul ignore next */ []));
|
|
2578
|
+
constructor() {
|
|
2579
|
+
effect(() => {
|
|
2580
|
+
const max = this.max();
|
|
2581
|
+
this.avatarEls().forEach((el, i) => {
|
|
2582
|
+
el.nativeElement.style.display = i >= max ? 'none' : '';
|
|
2583
|
+
});
|
|
2584
|
+
});
|
|
2585
|
+
}
|
|
2586
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmAvatarGroup, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2587
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.4", type: LlmAvatarGroup, isStandalone: true, selector: "llm-avatar-group", inputs: { max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "\"group size-\" + size()" }, classAttribute: "group" }, queries: [{ propertyName: "avatarEls", predicate: LlmAvatar, read: ElementRef, isSignal: true }], ngImport: i0, template: `
|
|
2588
|
+
<ng-content />
|
|
2589
|
+
@if (overflowCount() > 0) {
|
|
2590
|
+
<span [class]="'overflow-badge size-' + size()">+{{ overflowCount() }}</span>
|
|
2591
|
+
}
|
|
2592
|
+
`, isInline: true, styles: [":host{display:inline-flex;align-items:center;justify-content:center;position:relative;overflow:hidden;flex-shrink:0;font-family:var(--ui-font-family);font-weight:var(--ui-font-weight-semibold);background-color:color-mix(in srgb,var(--ui-color-primary) 12%,var(--ui-color-surface-sunken));color:var(--ui-color-primary);-webkit-user-select:none;user-select:none}:host(.size-xs){width:24px;height:24px;font-size:.625rem}:host(.size-sm){width:32px;height:32px;font-size:var(--ui-font-size-xs)}:host(.size-md){width:40px;height:40px;font-size:var(--ui-font-size-sm)}:host(.size-lg){width:48px;height:48px;font-size:var(--ui-font-size-md)}:host(.size-xl){width:64px;height:64px;font-size:var(--ui-font-size-lg)}:host(.shape-circle){border-radius:var(--ui-radius-full)}:host(.shape-square){border-radius:var(--ui-radius-md)}img{width:100%;height:100%;object-fit:cover;display:block}.initials{line-height:1;letter-spacing:.02em}.icon{width:55%;height:55%;opacity:.6}.status-dot{position:absolute;bottom:0;right:0;width:25%;height:25%;min-width:6px;min-height:6px;max-width:14px;max-height:14px;border-radius:var(--ui-radius-full);border:2px solid var(--ui-color-surface);box-sizing:content-box}.status-dot.status-online{background-color:var(--ui-color-success)}.status-dot.status-offline{background-color:var(--ui-color-text-muted)}.status-dot.status-away{background-color:var(--ui-color-warning)}.status-dot.status-busy{background-color:var(--ui-color-danger)}:host(.group){display:inline-flex;align-items:center;background:none;overflow:visible;padding-inline-start:4px}:host-context(llm-avatar-group){box-shadow:0 0 0 2px var(--ui-color-surface);margin-inline-start:-8px}.overflow-badge{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;background-color:var(--ui-color-surface-sunken);color:var(--ui-color-text-muted);border:1px solid var(--ui-color-border);border-radius:var(--ui-radius-full);font-family:var(--ui-font-family);font-weight:var(--ui-font-weight-semibold);box-shadow:0 0 0 2px var(--ui-color-surface);margin-inline-start:-8px}.overflow-badge.size-xs{width:24px;height:24px;font-size:.5625rem}.overflow-badge.size-sm{width:32px;height:32px;font-size:var(--ui-font-size-xs)}.overflow-badge.size-md{width:40px;height:40px;font-size:var(--ui-font-size-sm)}.overflow-badge.size-lg{width:48px;height:48px;font-size:var(--ui-font-size-sm)}.overflow-badge.size-xl{width:64px;height:64px;font-size:var(--ui-font-size-md)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2593
|
+
}
|
|
2594
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmAvatarGroup, decorators: [{
|
|
2595
|
+
type: Component,
|
|
2596
|
+
args: [{ selector: 'llm-avatar-group', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: `
|
|
2597
|
+
<ng-content />
|
|
2598
|
+
@if (overflowCount() > 0) {
|
|
2599
|
+
<span [class]="'overflow-badge size-' + size()">+{{ overflowCount() }}</span>
|
|
2600
|
+
}
|
|
2601
|
+
`, host: {
|
|
2602
|
+
class: 'group',
|
|
2603
|
+
'[class]': '"group size-" + size()',
|
|
2604
|
+
}, styles: [":host{display:inline-flex;align-items:center;justify-content:center;position:relative;overflow:hidden;flex-shrink:0;font-family:var(--ui-font-family);font-weight:var(--ui-font-weight-semibold);background-color:color-mix(in srgb,var(--ui-color-primary) 12%,var(--ui-color-surface-sunken));color:var(--ui-color-primary);-webkit-user-select:none;user-select:none}:host(.size-xs){width:24px;height:24px;font-size:.625rem}:host(.size-sm){width:32px;height:32px;font-size:var(--ui-font-size-xs)}:host(.size-md){width:40px;height:40px;font-size:var(--ui-font-size-sm)}:host(.size-lg){width:48px;height:48px;font-size:var(--ui-font-size-md)}:host(.size-xl){width:64px;height:64px;font-size:var(--ui-font-size-lg)}:host(.shape-circle){border-radius:var(--ui-radius-full)}:host(.shape-square){border-radius:var(--ui-radius-md)}img{width:100%;height:100%;object-fit:cover;display:block}.initials{line-height:1;letter-spacing:.02em}.icon{width:55%;height:55%;opacity:.6}.status-dot{position:absolute;bottom:0;right:0;width:25%;height:25%;min-width:6px;min-height:6px;max-width:14px;max-height:14px;border-radius:var(--ui-radius-full);border:2px solid var(--ui-color-surface);box-sizing:content-box}.status-dot.status-online{background-color:var(--ui-color-success)}.status-dot.status-offline{background-color:var(--ui-color-text-muted)}.status-dot.status-away{background-color:var(--ui-color-warning)}.status-dot.status-busy{background-color:var(--ui-color-danger)}:host(.group){display:inline-flex;align-items:center;background:none;overflow:visible;padding-inline-start:4px}:host-context(llm-avatar-group){box-shadow:0 0 0 2px var(--ui-color-surface);margin-inline-start:-8px}.overflow-badge{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;background-color:var(--ui-color-surface-sunken);color:var(--ui-color-text-muted);border:1px solid var(--ui-color-border);border-radius:var(--ui-radius-full);font-family:var(--ui-font-family);font-weight:var(--ui-font-weight-semibold);box-shadow:0 0 0 2px var(--ui-color-surface);margin-inline-start:-8px}.overflow-badge.size-xs{width:24px;height:24px;font-size:.5625rem}.overflow-badge.size-sm{width:32px;height:32px;font-size:var(--ui-font-size-xs)}.overflow-badge.size-md{width:40px;height:40px;font-size:var(--ui-font-size-sm)}.overflow-badge.size-lg{width:48px;height:48px;font-size:var(--ui-font-size-sm)}.overflow-badge.size-xl{width:64px;height:64px;font-size:var(--ui-font-size-md)}\n"] }]
|
|
2605
|
+
}], ctorParameters: () => [], propDecorators: { max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], avatarEls: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => LlmAvatar), { ...{ read: ElementRef }, isSignal: true }] }] } });
|
|
2606
|
+
|
|
2607
|
+
/**
|
|
2608
|
+
* Progress bar with determinate and indeterminate states.
|
|
2609
|
+
*
|
|
2610
|
+
* Usage:
|
|
2611
|
+
* ```html
|
|
2612
|
+
* <llm-progress [value]="75" />
|
|
2613
|
+
* <llm-progress variant="success" [value]="100" />
|
|
2614
|
+
* <llm-progress [indeterminate]="true" />
|
|
2615
|
+
* ```
|
|
2616
|
+
*/
|
|
2617
|
+
class LlmProgress {
|
|
2618
|
+
/** Current value of the progress bar. */
|
|
2619
|
+
value = input(0, ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
2620
|
+
/** Maximum value. */
|
|
2621
|
+
max = input(100, ...(ngDevMode ? [{ debugName: "max" }] : /* istanbul ignore next */ []));
|
|
2622
|
+
/** Semantic color variant. */
|
|
2623
|
+
variant = input('default', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
|
|
2624
|
+
/** Height size of the track. */
|
|
2625
|
+
size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
2626
|
+
/** Shows an animated indeterminate state (loading). */
|
|
2627
|
+
indeterminate = input(false, ...(ngDevMode ? [{ debugName: "indeterminate" }] : /* istanbul ignore next */ []));
|
|
2628
|
+
clampedValue = computed(() => Math.min(Math.max(this.value(), 0), this.max()), ...(ngDevMode ? [{ debugName: "clampedValue" }] : /* istanbul ignore next */ []));
|
|
2629
|
+
fillWidth = computed(() => this.indeterminate()
|
|
2630
|
+
? '100%'
|
|
2631
|
+
: `${(this.clampedValue() / this.max()) * 100}%`, ...(ngDevMode ? [{ debugName: "fillWidth" }] : /* istanbul ignore next */ []));
|
|
2632
|
+
hostClasses = computed(() => `variant-${this.variant()} size-${this.size()}${this.indeterminate() ? ' is-indeterminate' : ''}`, ...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
|
|
2633
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmProgress, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2634
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.4", type: LlmProgress, isStandalone: true, selector: "llm-progress", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, indeterminate: { classPropertyName: "indeterminate", publicName: "indeterminate", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "progressbar", "aria-valuemin": "0" }, properties: { "attr.aria-valuenow": "indeterminate() ? null : clampedValue()", "attr.aria-valuemax": "indeterminate() ? null : max()", "class": "hostClasses()" } }, ngImport: i0, template: `
|
|
2635
|
+
<div class="track">
|
|
2636
|
+
<div class="fill" [style.width]="fillWidth()"></div>
|
|
2637
|
+
</div>
|
|
2638
|
+
`, isInline: true, styles: [":host{display:block;width:100%;font-family:var(--ui-font-family)}.track{position:relative;width:100%;border-radius:var(--ui-radius-full);background-color:var(--ui-color-surface-sunken);overflow:hidden}:host(.size-sm) .track{height:4px}:host(.size-md) .track{height:8px}:host(.size-lg) .track{height:12px}.fill{height:100%;border-radius:var(--ui-radius-full);background-color:var(--ui-color-primary);transition:width var(--ui-transition-normal)}:host(.variant-success) .fill{background-color:var(--ui-color-success)}:host(.variant-warning) .fill{background-color:var(--ui-color-warning)}:host(.variant-danger) .fill{background-color:var(--ui-color-danger)}@keyframes progress-indeterminate{0%{transform:translate(-150%)}to{transform:translate(350%)}}:host(.is-indeterminate) .fill{width:40%!important;animation:progress-indeterminate 1.4s var(--ui-ease-in-out) infinite}@media(prefers-reduced-motion:reduce){:host(.is-indeterminate) .fill{animation:none;opacity:.5}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2639
|
+
}
|
|
2640
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmProgress, decorators: [{
|
|
2641
|
+
type: Component,
|
|
2642
|
+
args: [{ selector: 'llm-progress', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: `
|
|
2643
|
+
<div class="track">
|
|
2644
|
+
<div class="fill" [style.width]="fillWidth()"></div>
|
|
2645
|
+
</div>
|
|
2646
|
+
`, host: {
|
|
2647
|
+
role: 'progressbar',
|
|
2648
|
+
'aria-valuemin': '0',
|
|
2649
|
+
'[attr.aria-valuenow]': 'indeterminate() ? null : clampedValue()',
|
|
2650
|
+
'[attr.aria-valuemax]': 'indeterminate() ? null : max()',
|
|
2651
|
+
'[class]': 'hostClasses()',
|
|
2652
|
+
}, styles: [":host{display:block;width:100%;font-family:var(--ui-font-family)}.track{position:relative;width:100%;border-radius:var(--ui-radius-full);background-color:var(--ui-color-surface-sunken);overflow:hidden}:host(.size-sm) .track{height:4px}:host(.size-md) .track{height:8px}:host(.size-lg) .track{height:12px}.fill{height:100%;border-radius:var(--ui-radius-full);background-color:var(--ui-color-primary);transition:width var(--ui-transition-normal)}:host(.variant-success) .fill{background-color:var(--ui-color-success)}:host(.variant-warning) .fill{background-color:var(--ui-color-warning)}:host(.variant-danger) .fill{background-color:var(--ui-color-danger)}@keyframes progress-indeterminate{0%{transform:translate(-150%)}to{transform:translate(350%)}}:host(.is-indeterminate) .fill{width:40%!important;animation:progress-indeterminate 1.4s var(--ui-ease-in-out) infinite}@media(prefers-reduced-motion:reduce){:host(.is-indeterminate) .fill{animation:none;opacity:.5}}\n"] }]
|
|
2653
|
+
}], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], indeterminate: [{ type: i0.Input, args: [{ isSignal: true, alias: "indeterminate", required: false }] }] } });
|
|
2654
|
+
|
|
2655
|
+
const LLM_BREADCRUMBS = new InjectionToken('LLM_BREADCRUMBS');
|
|
2656
|
+
|
|
2657
|
+
/**
|
|
2658
|
+
* Accessible breadcrumb navigation. Wrap `llm-breadcrumb-item` elements inside.
|
|
2659
|
+
* The last item is automatically marked as the current page.
|
|
2660
|
+
*
|
|
2661
|
+
* Usage:
|
|
2662
|
+
* ```html
|
|
2663
|
+
* <llm-breadcrumbs>
|
|
2664
|
+
* <llm-breadcrumb-item href="/home">Home</llm-breadcrumb-item>
|
|
2665
|
+
* <llm-breadcrumb-item href="/products">Products</llm-breadcrumb-item>
|
|
2666
|
+
* <llm-breadcrumb-item>Widget X</llm-breadcrumb-item>
|
|
2667
|
+
* </llm-breadcrumbs>
|
|
2668
|
+
* ```
|
|
2669
|
+
*/
|
|
2670
|
+
class LlmBreadcrumbs {
|
|
2671
|
+
_itemIds = signal([], ...(ngDevMode ? [{ debugName: "_itemIds" }] : /* istanbul ignore next */ []));
|
|
2672
|
+
_nextId = 0;
|
|
2673
|
+
/** @internal — used by LlmBreadcrumbItem via LLM_BREADCRUMBS token */
|
|
2674
|
+
lastItemId = computed(() => {
|
|
2675
|
+
const ids = this._itemIds();
|
|
2676
|
+
return ids.length > 0 ? ids[ids.length - 1] : -1;
|
|
2677
|
+
}, ...(ngDevMode ? [{ debugName: "lastItemId" }] : /* istanbul ignore next */ []));
|
|
2678
|
+
/** @internal */
|
|
2679
|
+
registerItem() {
|
|
2680
|
+
const id = this._nextId++;
|
|
2681
|
+
this._itemIds.update((ids) => [...ids, id]);
|
|
2682
|
+
return id;
|
|
2683
|
+
}
|
|
2684
|
+
/** @internal */
|
|
2685
|
+
unregisterItem(id) {
|
|
2686
|
+
this._itemIds.update((ids) => ids.filter((i) => i !== id));
|
|
2687
|
+
}
|
|
2688
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmBreadcrumbs, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2689
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.4", type: LlmBreadcrumbs, isStandalone: true, selector: "llm-breadcrumbs", providers: [
|
|
2690
|
+
{
|
|
2691
|
+
provide: LLM_BREADCRUMBS,
|
|
2692
|
+
useFactory: (bc) => ({
|
|
2693
|
+
registerItem: () => bc.registerItem(),
|
|
2694
|
+
unregisterItem: (id) => bc.unregisterItem(id),
|
|
2695
|
+
lastItemId: bc.lastItemId,
|
|
2696
|
+
}),
|
|
2697
|
+
deps: [LlmBreadcrumbs],
|
|
2698
|
+
},
|
|
2699
|
+
], ngImport: i0, template: `
|
|
2700
|
+
<nav aria-label="Breadcrumb">
|
|
2701
|
+
<ol role="list" class="list">
|
|
2702
|
+
<ng-content />
|
|
2703
|
+
</ol>
|
|
2704
|
+
</nav>
|
|
2705
|
+
`, isInline: true, styles: ["llm-breadcrumbs{display:block;font-family:var(--ui-font-family)}nav{display:block}.list{display:flex;flex-wrap:wrap;align-items:center;gap:0;list-style:none;margin:0;padding:0;font-size:var(--ui-font-size-sm);color:var(--ui-color-text-muted)}llm-breadcrumb-item{display:contents}.item{display:flex;align-items:center}.item:after{content:\"\\203a\";margin:0 var(--ui-spacing-2);color:var(--ui-color-border-hover);font-size:var(--ui-font-size-md);line-height:1}:host(.is-current) .item:after{display:none}.item a[href]{color:var(--ui-color-text-muted);text-decoration:none;border-radius:var(--ui-radius-sm);padding:.125rem .25rem;margin:-.125rem -.25rem;transition:color var(--ui-transition-fast)}.item a[href]:hover{color:var(--ui-color-text);text-decoration:underline}.item a[href]:focus-visible{outline:none;box-shadow:var(--ui-focus-ring)}.item a:not([href]){color:var(--ui-color-text);font-weight:var(--ui-font-weight-semibold)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2706
|
+
}
|
|
2707
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmBreadcrumbs, decorators: [{
|
|
2708
|
+
type: Component,
|
|
2709
|
+
args: [{ selector: 'llm-breadcrumbs', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, providers: [
|
|
2710
|
+
{
|
|
2711
|
+
provide: LLM_BREADCRUMBS,
|
|
2712
|
+
useFactory: (bc) => ({
|
|
2713
|
+
registerItem: () => bc.registerItem(),
|
|
2714
|
+
unregisterItem: (id) => bc.unregisterItem(id),
|
|
2715
|
+
lastItemId: bc.lastItemId,
|
|
2716
|
+
}),
|
|
2717
|
+
deps: [LlmBreadcrumbs],
|
|
2718
|
+
},
|
|
2719
|
+
], template: `
|
|
2720
|
+
<nav aria-label="Breadcrumb">
|
|
2721
|
+
<ol role="list" class="list">
|
|
2722
|
+
<ng-content />
|
|
2723
|
+
</ol>
|
|
2724
|
+
</nav>
|
|
2725
|
+
`, styles: ["llm-breadcrumbs{display:block;font-family:var(--ui-font-family)}nav{display:block}.list{display:flex;flex-wrap:wrap;align-items:center;gap:0;list-style:none;margin:0;padding:0;font-size:var(--ui-font-size-sm);color:var(--ui-color-text-muted)}llm-breadcrumb-item{display:contents}.item{display:flex;align-items:center}.item:after{content:\"\\203a\";margin:0 var(--ui-spacing-2);color:var(--ui-color-border-hover);font-size:var(--ui-font-size-md);line-height:1}:host(.is-current) .item:after{display:none}.item a[href]{color:var(--ui-color-text-muted);text-decoration:none;border-radius:var(--ui-radius-sm);padding:.125rem .25rem;margin:-.125rem -.25rem;transition:color var(--ui-transition-fast)}.item a[href]:hover{color:var(--ui-color-text);text-decoration:underline}.item a[href]:focus-visible{outline:none;box-shadow:var(--ui-focus-ring)}.item a:not([href]){color:var(--ui-color-text);font-weight:var(--ui-font-weight-semibold)}\n"] }]
|
|
2726
|
+
}] });
|
|
2727
|
+
/**
|
|
2728
|
+
* A single breadcrumb step. The last item is automatically treated as
|
|
2729
|
+
* `aria-current="page"` and rendered as plain text (no link).
|
|
2730
|
+
*/
|
|
2731
|
+
class LlmBreadcrumbItem {
|
|
2732
|
+
/** Optional href for navigation. Ignored on the last (current) item. */
|
|
2733
|
+
href = input('', ...(ngDevMode ? [{ debugName: "href" }] : /* istanbul ignore next */ []));
|
|
2734
|
+
context = inject(LLM_BREADCRUMBS);
|
|
2735
|
+
myIndex = signal(-1, ...(ngDevMode ? [{ debugName: "myIndex" }] : /* istanbul ignore next */ []));
|
|
2736
|
+
isCurrent = computed(() => this.myIndex() >= 0 && this.myIndex() === this.context.lastItemId(), ...(ngDevMode ? [{ debugName: "isCurrent" }] : /* istanbul ignore next */ []));
|
|
2737
|
+
ngOnInit() {
|
|
2738
|
+
this.myIndex.set(this.context.registerItem());
|
|
2739
|
+
}
|
|
2740
|
+
ngOnDestroy() {
|
|
2741
|
+
if (this.myIndex() >= 0) {
|
|
2742
|
+
this.context.unregisterItem(this.myIndex());
|
|
2743
|
+
}
|
|
2744
|
+
}
|
|
2745
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmBreadcrumbItem, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2746
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.4", type: LlmBreadcrumbItem, isStandalone: true, selector: "llm-breadcrumb-item", inputs: { href: { classPropertyName: "href", publicName: "href", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.is-current": "isCurrent()" } }, ngImport: i0, template: `
|
|
2747
|
+
<li class="item">
|
|
2748
|
+
<a
|
|
2749
|
+
[attr.href]="href() && !isCurrent() ? href() : null"
|
|
2750
|
+
[attr.aria-current]="isCurrent() ? 'page' : null"
|
|
2751
|
+
><ng-content /></a>
|
|
2752
|
+
</li>
|
|
2753
|
+
`, isInline: true, styles: ["llm-breadcrumbs{display:block;font-family:var(--ui-font-family)}nav{display:block}.list{display:flex;flex-wrap:wrap;align-items:center;gap:0;list-style:none;margin:0;padding:0;font-size:var(--ui-font-size-sm);color:var(--ui-color-text-muted)}llm-breadcrumb-item{display:contents}.item{display:flex;align-items:center}.item:after{content:\"\\203a\";margin:0 var(--ui-spacing-2);color:var(--ui-color-border-hover);font-size:var(--ui-font-size-md);line-height:1}:host(.is-current) .item:after{display:none}.item a[href]{color:var(--ui-color-text-muted);text-decoration:none;border-radius:var(--ui-radius-sm);padding:.125rem .25rem;margin:-.125rem -.25rem;transition:color var(--ui-transition-fast)}.item a[href]:hover{color:var(--ui-color-text);text-decoration:underline}.item a[href]:focus-visible{outline:none;box-shadow:var(--ui-focus-ring)}.item a:not([href]){color:var(--ui-color-text);font-weight:var(--ui-font-weight-semibold)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2754
|
+
}
|
|
2755
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmBreadcrumbItem, decorators: [{
|
|
2756
|
+
type: Component,
|
|
2757
|
+
args: [{ selector: 'llm-breadcrumb-item', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: `
|
|
2758
|
+
<li class="item">
|
|
2759
|
+
<a
|
|
2760
|
+
[attr.href]="href() && !isCurrent() ? href() : null"
|
|
2761
|
+
[attr.aria-current]="isCurrent() ? 'page' : null"
|
|
2762
|
+
><ng-content /></a>
|
|
2763
|
+
</li>
|
|
2764
|
+
`, host: {
|
|
2765
|
+
'[class.is-current]': 'isCurrent()',
|
|
2766
|
+
}, styles: ["llm-breadcrumbs{display:block;font-family:var(--ui-font-family)}nav{display:block}.list{display:flex;flex-wrap:wrap;align-items:center;gap:0;list-style:none;margin:0;padding:0;font-size:var(--ui-font-size-sm);color:var(--ui-color-text-muted)}llm-breadcrumb-item{display:contents}.item{display:flex;align-items:center}.item:after{content:\"\\203a\";margin:0 var(--ui-spacing-2);color:var(--ui-color-border-hover);font-size:var(--ui-font-size-md);line-height:1}:host(.is-current) .item:after{display:none}.item a[href]{color:var(--ui-color-text-muted);text-decoration:none;border-radius:var(--ui-radius-sm);padding:.125rem .25rem;margin:-.125rem -.25rem;transition:color var(--ui-transition-fast)}.item a[href]:hover{color:var(--ui-color-text);text-decoration:underline}.item a[href]:focus-visible{outline:none;box-shadow:var(--ui-focus-ring)}.item a:not([href]){color:var(--ui-color-text);font-weight:var(--ui-font-weight-semibold)}\n"] }]
|
|
2767
|
+
}], propDecorators: { href: [{ type: i0.Input, args: [{ isSignal: true, alias: "href", required: false }] }] } });
|
|
2768
|
+
|
|
2769
|
+
/**
|
|
2770
|
+
* Pagination control for navigating multi-page content.
|
|
2771
|
+
*
|
|
2772
|
+
* Usage:
|
|
2773
|
+
* ```html
|
|
2774
|
+
* <llm-pagination [(page)]="currentPage" [pageCount]="totalPages" />
|
|
2775
|
+
* ```
|
|
2776
|
+
*/
|
|
2777
|
+
class LlmPagination {
|
|
2778
|
+
/** Current page (1-based). Supports two-way binding: [(page)]="currentPage". */
|
|
2779
|
+
page = model(1, ...(ngDevMode ? [{ debugName: "page" }] : /* istanbul ignore next */ []));
|
|
2780
|
+
/** Total number of pages. */
|
|
2781
|
+
pageCount = input(1, ...(ngDevMode ? [{ debugName: "pageCount" }] : /* istanbul ignore next */ []));
|
|
2782
|
+
/** Number of page buttons to show on each side of the current page. */
|
|
2783
|
+
siblingCount = input(1, ...(ngDevMode ? [{ debugName: "siblingCount" }] : /* istanbul ignore next */ []));
|
|
2784
|
+
/** Whether to show first/last page jump buttons. */
|
|
2785
|
+
showFirstLast = input(true, ...(ngDevMode ? [{ debugName: "showFirstLast" }] : /* istanbul ignore next */ []));
|
|
2786
|
+
pageItems = computed(() => {
|
|
2787
|
+
const total = this.pageCount();
|
|
2788
|
+
const current = this.page();
|
|
2789
|
+
const siblings = this.siblingCount();
|
|
2790
|
+
if (total <= 1)
|
|
2791
|
+
return [{ type: 'page', page: 1 }];
|
|
2792
|
+
const items = [];
|
|
2793
|
+
// Always include first page
|
|
2794
|
+
items.push({ type: 'page', page: 1 });
|
|
2795
|
+
const left = Math.max(2, current - siblings);
|
|
2796
|
+
const right = Math.min(total - 1, current + siblings);
|
|
2797
|
+
// Left ellipsis
|
|
2798
|
+
if (left > 2) {
|
|
2799
|
+
items.push({ type: 'ellipsis', key: 'ellipsis-start' });
|
|
2800
|
+
}
|
|
2801
|
+
// Middle pages
|
|
2802
|
+
for (let p = left; p <= right; p++) {
|
|
2803
|
+
items.push({ type: 'page', page: p });
|
|
2804
|
+
}
|
|
2805
|
+
// Right ellipsis
|
|
2806
|
+
if (right < total - 1) {
|
|
2807
|
+
items.push({ type: 'ellipsis', key: 'ellipsis-end' });
|
|
2808
|
+
}
|
|
2809
|
+
// Always include last page
|
|
2810
|
+
items.push({ type: 'page', page: total });
|
|
2811
|
+
return items;
|
|
2812
|
+
}, ...(ngDevMode ? [{ debugName: "pageItems" }] : /* istanbul ignore next */ []));
|
|
2813
|
+
goTo(p) {
|
|
2814
|
+
const clamped = Math.min(Math.max(p, 1), this.pageCount());
|
|
2815
|
+
this.page.set(clamped);
|
|
2816
|
+
}
|
|
2817
|
+
goPrev() {
|
|
2818
|
+
this.goTo(this.page() - 1);
|
|
2819
|
+
}
|
|
2820
|
+
goNext() {
|
|
2821
|
+
this.goTo(this.page() + 1);
|
|
2822
|
+
}
|
|
2823
|
+
goFirst() {
|
|
2824
|
+
this.goTo(1);
|
|
2825
|
+
}
|
|
2826
|
+
goLast() {
|
|
2827
|
+
this.goTo(this.pageCount());
|
|
2828
|
+
}
|
|
2829
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmPagination, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2830
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.4", type: LlmPagination, isStandalone: true, selector: "llm-pagination", inputs: { page: { classPropertyName: "page", publicName: "page", isSignal: true, isRequired: false, transformFunction: null }, pageCount: { classPropertyName: "pageCount", publicName: "pageCount", isSignal: true, isRequired: false, transformFunction: null }, siblingCount: { classPropertyName: "siblingCount", publicName: "siblingCount", isSignal: true, isRequired: false, transformFunction: null }, showFirstLast: { classPropertyName: "showFirstLast", publicName: "showFirstLast", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { page: "pageChange" }, ngImport: i0, template: `
|
|
2831
|
+
<nav aria-label="Pagination">
|
|
2832
|
+
<ul role="list" class="page-list">
|
|
2833
|
+
@if (showFirstLast()) {
|
|
2834
|
+
<li>
|
|
2835
|
+
<button
|
|
2836
|
+
class="page-btn"
|
|
2837
|
+
[class.is-disabled]="page() <= 1"
|
|
2838
|
+
[disabled]="page() <= 1"
|
|
2839
|
+
aria-label="First page"
|
|
2840
|
+
(click)="goFirst()"
|
|
2841
|
+
>«</button>
|
|
2842
|
+
</li>
|
|
2843
|
+
}
|
|
2844
|
+
<li>
|
|
2845
|
+
<button
|
|
2846
|
+
class="page-btn"
|
|
2847
|
+
[class.is-disabled]="page() <= 1"
|
|
2848
|
+
[disabled]="page() <= 1"
|
|
2849
|
+
aria-label="Previous page"
|
|
2850
|
+
(click)="goPrev()"
|
|
2851
|
+
>‹</button>
|
|
2852
|
+
</li>
|
|
2853
|
+
|
|
2854
|
+
@for (item of pageItems(); track $index) {
|
|
2855
|
+
@if (item.type === 'page') {
|
|
2856
|
+
<li>
|
|
2857
|
+
<button
|
|
2858
|
+
class="page-btn"
|
|
2859
|
+
[class.is-active]="item.page === page()"
|
|
2860
|
+
[attr.aria-current]="item.page === page() ? 'page' : null"
|
|
2861
|
+
[attr.aria-label]="'Page ' + item.page"
|
|
2862
|
+
(click)="goTo(item.page)"
|
|
2863
|
+
>{{ item.page }}</button>
|
|
2864
|
+
</li>
|
|
2865
|
+
} @else {
|
|
2866
|
+
<li>
|
|
2867
|
+
<span class="ellipsis" aria-hidden="true">…</span>
|
|
2868
|
+
</li>
|
|
2869
|
+
}
|
|
2870
|
+
}
|
|
2871
|
+
|
|
2872
|
+
<li>
|
|
2873
|
+
<button
|
|
2874
|
+
class="page-btn"
|
|
2875
|
+
[class.is-disabled]="page() >= pageCount()"
|
|
2876
|
+
[disabled]="page() >= pageCount()"
|
|
2877
|
+
aria-label="Next page"
|
|
2878
|
+
(click)="goNext()"
|
|
2879
|
+
>›</button>
|
|
2880
|
+
</li>
|
|
2881
|
+
@if (showFirstLast()) {
|
|
2882
|
+
<li>
|
|
2883
|
+
<button
|
|
2884
|
+
class="page-btn"
|
|
2885
|
+
[class.is-disabled]="page() >= pageCount()"
|
|
2886
|
+
[disabled]="page() >= pageCount()"
|
|
2887
|
+
aria-label="Last page"
|
|
2888
|
+
(click)="goLast()"
|
|
2889
|
+
>»</button>
|
|
2890
|
+
</li>
|
|
2891
|
+
}
|
|
2892
|
+
</ul>
|
|
2893
|
+
</nav>
|
|
2894
|
+
`, isInline: true, styles: [":host{display:block;font-family:var(--ui-font-family)}nav{display:block}.page-list{display:flex;flex-wrap:wrap;align-items:center;gap:var(--ui-spacing-1);list-style:none;margin:0;padding:0}.page-btn{all:unset;display:inline-flex;align-items:center;justify-content:center;width:2rem;height:2rem;border-radius:var(--ui-radius-md);border:1px solid var(--ui-color-border);background:var(--ui-color-surface);color:var(--ui-color-text);font-size:var(--ui-font-size-sm);font-weight:var(--ui-font-weight-medium);cursor:pointer;-webkit-user-select:none;user-select:none;transition:background-color var(--ui-transition-fast),border-color var(--ui-transition-fast),color var(--ui-transition-fast)}.page-btn:hover:not(:disabled){background-color:var(--ui-color-surface-sunken);border-color:var(--ui-color-border-hover)}.page-btn:focus-visible{outline:none;box-shadow:var(--ui-focus-ring)}.page-btn.is-active{background-color:var(--ui-color-primary);border-color:var(--ui-color-primary);color:var(--ui-color-text-on-primary)}.page-btn.is-active:hover{background-color:var(--ui-color-primary-hover);border-color:var(--ui-color-primary-hover)}.page-btn.is-disabled,.page-btn:disabled{opacity:.4;pointer-events:none;cursor:default}.ellipsis{display:inline-flex;align-items:center;justify-content:center;width:2rem;height:2rem;color:var(--ui-color-text-muted);font-size:var(--ui-font-size-sm);-webkit-user-select:none;user-select:none}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2895
|
+
}
|
|
2896
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmPagination, decorators: [{
|
|
2897
|
+
type: Component,
|
|
2898
|
+
args: [{ selector: 'llm-pagination', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: `
|
|
2899
|
+
<nav aria-label="Pagination">
|
|
2900
|
+
<ul role="list" class="page-list">
|
|
2901
|
+
@if (showFirstLast()) {
|
|
2902
|
+
<li>
|
|
2903
|
+
<button
|
|
2904
|
+
class="page-btn"
|
|
2905
|
+
[class.is-disabled]="page() <= 1"
|
|
2906
|
+
[disabled]="page() <= 1"
|
|
2907
|
+
aria-label="First page"
|
|
2908
|
+
(click)="goFirst()"
|
|
2909
|
+
>«</button>
|
|
2910
|
+
</li>
|
|
2911
|
+
}
|
|
2912
|
+
<li>
|
|
2913
|
+
<button
|
|
2914
|
+
class="page-btn"
|
|
2915
|
+
[class.is-disabled]="page() <= 1"
|
|
2916
|
+
[disabled]="page() <= 1"
|
|
2917
|
+
aria-label="Previous page"
|
|
2918
|
+
(click)="goPrev()"
|
|
2919
|
+
>‹</button>
|
|
2920
|
+
</li>
|
|
2921
|
+
|
|
2922
|
+
@for (item of pageItems(); track $index) {
|
|
2923
|
+
@if (item.type === 'page') {
|
|
2924
|
+
<li>
|
|
2925
|
+
<button
|
|
2926
|
+
class="page-btn"
|
|
2927
|
+
[class.is-active]="item.page === page()"
|
|
2928
|
+
[attr.aria-current]="item.page === page() ? 'page' : null"
|
|
2929
|
+
[attr.aria-label]="'Page ' + item.page"
|
|
2930
|
+
(click)="goTo(item.page)"
|
|
2931
|
+
>{{ item.page }}</button>
|
|
2932
|
+
</li>
|
|
2933
|
+
} @else {
|
|
2934
|
+
<li>
|
|
2935
|
+
<span class="ellipsis" aria-hidden="true">…</span>
|
|
2936
|
+
</li>
|
|
2937
|
+
}
|
|
2938
|
+
}
|
|
2939
|
+
|
|
2940
|
+
<li>
|
|
2941
|
+
<button
|
|
2942
|
+
class="page-btn"
|
|
2943
|
+
[class.is-disabled]="page() >= pageCount()"
|
|
2944
|
+
[disabled]="page() >= pageCount()"
|
|
2945
|
+
aria-label="Next page"
|
|
2946
|
+
(click)="goNext()"
|
|
2947
|
+
>›</button>
|
|
2948
|
+
</li>
|
|
2949
|
+
@if (showFirstLast()) {
|
|
2950
|
+
<li>
|
|
2951
|
+
<button
|
|
2952
|
+
class="page-btn"
|
|
2953
|
+
[class.is-disabled]="page() >= pageCount()"
|
|
2954
|
+
[disabled]="page() >= pageCount()"
|
|
2955
|
+
aria-label="Last page"
|
|
2956
|
+
(click)="goLast()"
|
|
2957
|
+
>»</button>
|
|
2958
|
+
</li>
|
|
2959
|
+
}
|
|
2960
|
+
</ul>
|
|
2961
|
+
</nav>
|
|
2962
|
+
`, styles: [":host{display:block;font-family:var(--ui-font-family)}nav{display:block}.page-list{display:flex;flex-wrap:wrap;align-items:center;gap:var(--ui-spacing-1);list-style:none;margin:0;padding:0}.page-btn{all:unset;display:inline-flex;align-items:center;justify-content:center;width:2rem;height:2rem;border-radius:var(--ui-radius-md);border:1px solid var(--ui-color-border);background:var(--ui-color-surface);color:var(--ui-color-text);font-size:var(--ui-font-size-sm);font-weight:var(--ui-font-weight-medium);cursor:pointer;-webkit-user-select:none;user-select:none;transition:background-color var(--ui-transition-fast),border-color var(--ui-transition-fast),color var(--ui-transition-fast)}.page-btn:hover:not(:disabled){background-color:var(--ui-color-surface-sunken);border-color:var(--ui-color-border-hover)}.page-btn:focus-visible{outline:none;box-shadow:var(--ui-focus-ring)}.page-btn.is-active{background-color:var(--ui-color-primary);border-color:var(--ui-color-primary);color:var(--ui-color-text-on-primary)}.page-btn.is-active:hover{background-color:var(--ui-color-primary-hover);border-color:var(--ui-color-primary-hover)}.page-btn.is-disabled,.page-btn:disabled{opacity:.4;pointer-events:none;cursor:default}.ellipsis{display:inline-flex;align-items:center;justify-content:center;width:2rem;height:2rem;color:var(--ui-color-text-muted);font-size:var(--ui-font-size-sm);-webkit-user-select:none;user-select:none}\n"] }]
|
|
2963
|
+
}], propDecorators: { page: [{ type: i0.Input, args: [{ isSignal: true, alias: "page", required: false }] }, { type: i0.Output, args: ["pageChange"] }], pageCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageCount", required: false }] }], siblingCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "siblingCount", required: false }] }], showFirstLast: [{ type: i0.Input, args: [{ isSignal: true, alias: "showFirstLast", required: false }] }] } });
|
|
2964
|
+
|
|
2965
|
+
const LLM_DRAWER = new InjectionToken('LLM_DRAWER');
|
|
2966
|
+
|
|
2967
|
+
let nextId = 0;
|
|
2968
|
+
/**
|
|
2969
|
+
* Slide-in drawer panel using the native `<dialog>` element.
|
|
2970
|
+
* Supports left, right, top, and bottom positions with focus trap,
|
|
2971
|
+
* Escape to close, and backdrop click to close.
|
|
2972
|
+
* Compose with `llm-drawer-header`, `llm-drawer-content`, and `llm-drawer-footer`.
|
|
2973
|
+
*
|
|
2974
|
+
* Usage:
|
|
2975
|
+
* ```html
|
|
2976
|
+
* <llm-button (click)="isOpen = true">Open</llm-button>
|
|
2977
|
+
* <llm-drawer [(open)]="isOpen" position="right">
|
|
2978
|
+
* <llm-drawer-header>Settings</llm-drawer-header>
|
|
2979
|
+
* <llm-drawer-content>Content here.</llm-drawer-content>
|
|
2980
|
+
* <llm-drawer-footer>
|
|
2981
|
+
* <llm-button variant="primary" (click)="isOpen = false">Save</llm-button>
|
|
2982
|
+
* </llm-drawer-footer>
|
|
2983
|
+
* </llm-drawer>
|
|
2984
|
+
* ```
|
|
2985
|
+
*/
|
|
2986
|
+
class LlmDrawer {
|
|
2987
|
+
/** Whether the drawer is open. Supports two-way binding: [(open)]="isOpen". */
|
|
2988
|
+
open = model(false, ...(ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []));
|
|
2989
|
+
/** Which edge the drawer slides in from. */
|
|
2990
|
+
position = input('right', ...(ngDevMode ? [{ debugName: "position" }] : /* istanbul ignore next */ []));
|
|
2991
|
+
/** Width (for left/right) or height (for top/bottom) of the panel. */
|
|
2992
|
+
size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
2993
|
+
/** Whether clicking the backdrop closes the drawer. */
|
|
2994
|
+
closeOnBackdrop = input(true, ...(ngDevMode ? [{ debugName: "closeOnBackdrop" }] : /* istanbul ignore next */ []));
|
|
2995
|
+
/** @internal — referenced by LlmDrawerHeader via LLM_DRAWER token */
|
|
2996
|
+
headerId = `llm-drawer-header-${nextId}`;
|
|
2997
|
+
drawerId = `llm-drawer-${nextId++}`;
|
|
2998
|
+
dialogRef = viewChild('dialogEl', ...(ngDevMode ? [{ debugName: "dialogRef" }] : /* istanbul ignore next */ []));
|
|
2999
|
+
triggerEl = signal(null, ...(ngDevMode ? [{ debugName: "triggerEl" }] : /* istanbul ignore next */ []));
|
|
3000
|
+
hostClasses = computed(() => `position-${this.position()} size-${this.size()}${this.open() ? ' is-open' : ''}`, ...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
|
|
3001
|
+
constructor() {
|
|
3002
|
+
effect(() => {
|
|
3003
|
+
const dialog = this.dialogRef()?.nativeElement;
|
|
3004
|
+
if (!dialog)
|
|
3005
|
+
return;
|
|
3006
|
+
if (this.open()) {
|
|
3007
|
+
this.triggerEl.set(document.activeElement);
|
|
3008
|
+
dialog.showModal();
|
|
3009
|
+
}
|
|
3010
|
+
else {
|
|
3011
|
+
if (dialog.open)
|
|
3012
|
+
dialog.close();
|
|
3013
|
+
this.triggerEl()?.focus();
|
|
3014
|
+
this.triggerEl.set(null);
|
|
3015
|
+
}
|
|
3016
|
+
});
|
|
3017
|
+
}
|
|
3018
|
+
onCancel(event) {
|
|
3019
|
+
event.preventDefault();
|
|
3020
|
+
this.open.set(false);
|
|
3021
|
+
}
|
|
3022
|
+
onBackdropClick(event) {
|
|
3023
|
+
if (this.closeOnBackdrop() && event.target === this.dialogRef()?.nativeElement) {
|
|
3024
|
+
this.open.set(false);
|
|
3025
|
+
}
|
|
3026
|
+
}
|
|
3027
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmDrawer, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3028
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.2.4", type: LlmDrawer, isStandalone: true, selector: "llm-drawer", inputs: { open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null }, position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, closeOnBackdrop: { classPropertyName: "closeOnBackdrop", publicName: "closeOnBackdrop", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { open: "openChange" }, host: { properties: { "class": "hostClasses()" } }, providers: [
|
|
3029
|
+
{
|
|
3030
|
+
provide: LLM_DRAWER,
|
|
3031
|
+
useFactory: (drawer) => ({
|
|
3032
|
+
headerId: drawer.headerId,
|
|
3033
|
+
close: () => drawer.open.set(false),
|
|
3034
|
+
}),
|
|
3035
|
+
deps: [LlmDrawer],
|
|
3036
|
+
},
|
|
3037
|
+
], viewQueries: [{ propertyName: "dialogRef", first: true, predicate: ["dialogEl"], descendants: true, isSignal: true }], ngImport: i0, template: `
|
|
3038
|
+
<!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->
|
|
3039
|
+
<dialog
|
|
3040
|
+
#dialogEl
|
|
3041
|
+
[attr.aria-labelledby]="headerId"
|
|
3042
|
+
aria-modal="true"
|
|
3043
|
+
[cdkTrapFocus]="open()"
|
|
3044
|
+
(cancel)="onCancel($event)"
|
|
3045
|
+
(close)="open.set(false)"
|
|
3046
|
+
(click)="onBackdropClick($event)"
|
|
3047
|
+
>
|
|
3048
|
+
<!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->
|
|
3049
|
+
<div class="panel" (click)="$event.stopPropagation()">
|
|
3050
|
+
<ng-content />
|
|
3051
|
+
</div>
|
|
3052
|
+
</dialog>
|
|
3053
|
+
`, isInline: true, styles: ["llm-drawer{display:contents}dialog{all:unset;position:fixed;display:none;flex-direction:column;background:var(--ui-color-surface);box-shadow:var(--ui-shadow-xl, 0 20px 60px rgba(0, 0, 0, .3));color:var(--ui-color-text);overflow:hidden;transition:transform var(--ui-duration-slow) var(--ui-ease-out, ease-out),display var(--ui-duration-slow) allow-discrete,overlay var(--ui-duration-slow) allow-discrete}dialog[open]{display:flex;transform:translate(0)!important}dialog::backdrop{background:#00000080;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);transition:opacity var(--ui-duration-slow) var(--ui-ease-out, ease-out),display var(--ui-duration-slow) allow-discrete,overlay var(--ui-duration-slow) allow-discrete}@starting-style{dialog[open]::backdrop{opacity:0}}@media(prefers-color-scheme:dark){dialog::backdrop{background:#000000b3}}[data-theme=dark] dialog::backdrop{background:#000000b3}.panel{display:flex;flex-direction:column;width:100%;height:100%;overflow:hidden}:host(.position-right) dialog{inset:0 0 0 auto;height:100dvh;transform:translate(100%)}@starting-style{:host(.position-right) dialog[open]{transform:translate(100%)}}:host(.position-left) dialog{inset:0 auto 0 0;height:100dvh;transform:translate(-100%)}@starting-style{:host(.position-left) dialog[open]{transform:translate(-100%)}}:host(.position-top) dialog{inset:0 0 auto;width:100vw;transform:translateY(-100%)}@starting-style{:host(.position-top) dialog[open]{transform:translateY(-100%)}}:host(.position-bottom) dialog{inset:auto 0 0;width:100vw;transform:translateY(100%)}@starting-style{:host(.position-bottom) dialog[open]{transform:translateY(100%)}}:host(.position-right.size-sm) dialog,:host(.position-left.size-sm) dialog{width:20rem}:host(.position-right.size-md) dialog,:host(.position-left.size-md) dialog{width:28rem}:host(.position-right.size-lg) dialog,:host(.position-left.size-lg) dialog{width:40rem}:host(.position-right.size-full) dialog,:host(.position-left.size-full) dialog{width:100vw}:host(.position-top.size-sm) dialog,:host(.position-bottom.size-sm) dialog{height:12rem}:host(.position-top.size-md) dialog,:host(.position-bottom.size-md) dialog{height:20rem}:host(.position-top.size-lg) dialog,:host(.position-bottom.size-lg) dialog{height:32rem}:host(.position-top.size-full) dialog,:host(.position-bottom.size-full) dialog{height:100dvh}llm-drawer-header{display:flex;align-items:center;justify-content:space-between;padding:var(--ui-spacing-4) var(--ui-spacing-5);border-bottom:1px solid var(--ui-color-border);font-size:var(--ui-font-size-xl);font-weight:600;letter-spacing:var(--ui-letter-spacing-tight);color:var(--ui-color-text);flex-shrink:0}llm-drawer-content{display:block;padding:var(--ui-spacing-5);overflow-y:auto;flex:1;color:var(--ui-color-text)}llm-drawer-footer{display:flex;align-items:center;justify-content:flex-end;gap:var(--ui-spacing-2);padding:var(--ui-spacing-4) var(--ui-spacing-5);border-top:1px solid var(--ui-color-border);flex-shrink:0}.close-btn{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;width:1.75rem;height:1.75rem;padding:0;margin-left:var(--ui-spacing-3);background:transparent;border:none;border-radius:var(--ui-radius-sm);cursor:pointer;color:var(--ui-color-text-muted);transition:background-color var(--ui-transition-fast),color var(--ui-transition-fast);line-height:1}.close-btn:hover{background-color:var(--ui-color-surface-sunken);color:var(--ui-color-text)}.close-btn:focus-visible{outline:none;box-shadow:var(--ui-focus-ring)}\n"], dependencies: [{ kind: "ngmodule", type: A11yModule }, { kind: "directive", type: i1$1.CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3054
|
+
}
|
|
3055
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmDrawer, decorators: [{
|
|
3056
|
+
type: Component,
|
|
3057
|
+
args: [{ selector: 'llm-drawer', standalone: true, imports: [A11yModule], changeDetection: ChangeDetectionStrategy.OnPush, providers: [
|
|
3058
|
+
{
|
|
3059
|
+
provide: LLM_DRAWER,
|
|
3060
|
+
useFactory: (drawer) => ({
|
|
3061
|
+
headerId: drawer.headerId,
|
|
3062
|
+
close: () => drawer.open.set(false),
|
|
3063
|
+
}),
|
|
3064
|
+
deps: [LlmDrawer],
|
|
3065
|
+
},
|
|
3066
|
+
], template: `
|
|
3067
|
+
<!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->
|
|
3068
|
+
<dialog
|
|
3069
|
+
#dialogEl
|
|
3070
|
+
[attr.aria-labelledby]="headerId"
|
|
3071
|
+
aria-modal="true"
|
|
3072
|
+
[cdkTrapFocus]="open()"
|
|
3073
|
+
(cancel)="onCancel($event)"
|
|
3074
|
+
(close)="open.set(false)"
|
|
3075
|
+
(click)="onBackdropClick($event)"
|
|
3076
|
+
>
|
|
3077
|
+
<!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->
|
|
3078
|
+
<div class="panel" (click)="$event.stopPropagation()">
|
|
3079
|
+
<ng-content />
|
|
3080
|
+
</div>
|
|
3081
|
+
</dialog>
|
|
3082
|
+
`, host: {
|
|
3083
|
+
'[class]': 'hostClasses()',
|
|
3084
|
+
}, styles: ["llm-drawer{display:contents}dialog{all:unset;position:fixed;display:none;flex-direction:column;background:var(--ui-color-surface);box-shadow:var(--ui-shadow-xl, 0 20px 60px rgba(0, 0, 0, .3));color:var(--ui-color-text);overflow:hidden;transition:transform var(--ui-duration-slow) var(--ui-ease-out, ease-out),display var(--ui-duration-slow) allow-discrete,overlay var(--ui-duration-slow) allow-discrete}dialog[open]{display:flex;transform:translate(0)!important}dialog::backdrop{background:#00000080;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);transition:opacity var(--ui-duration-slow) var(--ui-ease-out, ease-out),display var(--ui-duration-slow) allow-discrete,overlay var(--ui-duration-slow) allow-discrete}@starting-style{dialog[open]::backdrop{opacity:0}}@media(prefers-color-scheme:dark){dialog::backdrop{background:#000000b3}}[data-theme=dark] dialog::backdrop{background:#000000b3}.panel{display:flex;flex-direction:column;width:100%;height:100%;overflow:hidden}:host(.position-right) dialog{inset:0 0 0 auto;height:100dvh;transform:translate(100%)}@starting-style{:host(.position-right) dialog[open]{transform:translate(100%)}}:host(.position-left) dialog{inset:0 auto 0 0;height:100dvh;transform:translate(-100%)}@starting-style{:host(.position-left) dialog[open]{transform:translate(-100%)}}:host(.position-top) dialog{inset:0 0 auto;width:100vw;transform:translateY(-100%)}@starting-style{:host(.position-top) dialog[open]{transform:translateY(-100%)}}:host(.position-bottom) dialog{inset:auto 0 0;width:100vw;transform:translateY(100%)}@starting-style{:host(.position-bottom) dialog[open]{transform:translateY(100%)}}:host(.position-right.size-sm) dialog,:host(.position-left.size-sm) dialog{width:20rem}:host(.position-right.size-md) dialog,:host(.position-left.size-md) dialog{width:28rem}:host(.position-right.size-lg) dialog,:host(.position-left.size-lg) dialog{width:40rem}:host(.position-right.size-full) dialog,:host(.position-left.size-full) dialog{width:100vw}:host(.position-top.size-sm) dialog,:host(.position-bottom.size-sm) dialog{height:12rem}:host(.position-top.size-md) dialog,:host(.position-bottom.size-md) dialog{height:20rem}:host(.position-top.size-lg) dialog,:host(.position-bottom.size-lg) dialog{height:32rem}:host(.position-top.size-full) dialog,:host(.position-bottom.size-full) dialog{height:100dvh}llm-drawer-header{display:flex;align-items:center;justify-content:space-between;padding:var(--ui-spacing-4) var(--ui-spacing-5);border-bottom:1px solid var(--ui-color-border);font-size:var(--ui-font-size-xl);font-weight:600;letter-spacing:var(--ui-letter-spacing-tight);color:var(--ui-color-text);flex-shrink:0}llm-drawer-content{display:block;padding:var(--ui-spacing-5);overflow-y:auto;flex:1;color:var(--ui-color-text)}llm-drawer-footer{display:flex;align-items:center;justify-content:flex-end;gap:var(--ui-spacing-2);padding:var(--ui-spacing-4) var(--ui-spacing-5);border-top:1px solid var(--ui-color-border);flex-shrink:0}.close-btn{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;width:1.75rem;height:1.75rem;padding:0;margin-left:var(--ui-spacing-3);background:transparent;border:none;border-radius:var(--ui-radius-sm);cursor:pointer;color:var(--ui-color-text-muted);transition:background-color var(--ui-transition-fast),color var(--ui-transition-fast);line-height:1}.close-btn:hover{background-color:var(--ui-color-surface-sunken);color:var(--ui-color-text)}.close-btn:focus-visible{outline:none;box-shadow:var(--ui-focus-ring)}\n"] }]
|
|
3085
|
+
}], ctorParameters: () => [], propDecorators: { open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }, { type: i0.Output, args: ["openChange"] }], position: [{ type: i0.Input, args: [{ isSignal: true, alias: "position", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], closeOnBackdrop: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnBackdrop", required: false }] }], dialogRef: [{ type: i0.ViewChild, args: ['dialogEl', { isSignal: true }] }] } });
|
|
3086
|
+
/**
|
|
3087
|
+
* Header slot for `llm-drawer`. Contains the title and a close button.
|
|
3088
|
+
* Automatically receives the correct `id` for `aria-labelledby` association.
|
|
3089
|
+
*/
|
|
3090
|
+
class LlmDrawerHeader {
|
|
3091
|
+
context = inject(LLM_DRAWER);
|
|
3092
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmDrawerHeader, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3093
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.4", type: LlmDrawerHeader, isStandalone: true, selector: "llm-drawer-header", host: { properties: { "attr.id": "context.headerId" } }, ngImport: i0, template: `
|
|
3094
|
+
<ng-content />
|
|
3095
|
+
<button
|
|
3096
|
+
class="close-btn"
|
|
3097
|
+
type="button"
|
|
3098
|
+
aria-label="Close drawer"
|
|
3099
|
+
(click)="context.close()"
|
|
3100
|
+
>
|
|
3101
|
+
<svg
|
|
3102
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
3103
|
+
width="14"
|
|
3104
|
+
height="14"
|
|
3105
|
+
viewBox="0 0 24 24"
|
|
3106
|
+
fill="none"
|
|
3107
|
+
stroke="currentColor"
|
|
3108
|
+
stroke-width="2.5"
|
|
3109
|
+
stroke-linecap="round"
|
|
3110
|
+
stroke-linejoin="round"
|
|
3111
|
+
aria-hidden="true"
|
|
3112
|
+
focusable="false"
|
|
3113
|
+
>
|
|
3114
|
+
<line x1="18" y1="6" x2="6" y2="18" />
|
|
3115
|
+
<line x1="6" y1="6" x2="18" y2="18" />
|
|
3116
|
+
</svg>
|
|
3117
|
+
</button>
|
|
3118
|
+
`, isInline: true, styles: ["llm-drawer{display:contents}dialog{all:unset;position:fixed;display:none;flex-direction:column;background:var(--ui-color-surface);box-shadow:var(--ui-shadow-xl, 0 20px 60px rgba(0, 0, 0, .3));color:var(--ui-color-text);overflow:hidden;transition:transform var(--ui-duration-slow) var(--ui-ease-out, ease-out),display var(--ui-duration-slow) allow-discrete,overlay var(--ui-duration-slow) allow-discrete}dialog[open]{display:flex;transform:translate(0)!important}dialog::backdrop{background:#00000080;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);transition:opacity var(--ui-duration-slow) var(--ui-ease-out, ease-out),display var(--ui-duration-slow) allow-discrete,overlay var(--ui-duration-slow) allow-discrete}@starting-style{dialog[open]::backdrop{opacity:0}}@media(prefers-color-scheme:dark){dialog::backdrop{background:#000000b3}}[data-theme=dark] dialog::backdrop{background:#000000b3}.panel{display:flex;flex-direction:column;width:100%;height:100%;overflow:hidden}:host(.position-right) dialog{inset:0 0 0 auto;height:100dvh;transform:translate(100%)}@starting-style{:host(.position-right) dialog[open]{transform:translate(100%)}}:host(.position-left) dialog{inset:0 auto 0 0;height:100dvh;transform:translate(-100%)}@starting-style{:host(.position-left) dialog[open]{transform:translate(-100%)}}:host(.position-top) dialog{inset:0 0 auto;width:100vw;transform:translateY(-100%)}@starting-style{:host(.position-top) dialog[open]{transform:translateY(-100%)}}:host(.position-bottom) dialog{inset:auto 0 0;width:100vw;transform:translateY(100%)}@starting-style{:host(.position-bottom) dialog[open]{transform:translateY(100%)}}:host(.position-right.size-sm) dialog,:host(.position-left.size-sm) dialog{width:20rem}:host(.position-right.size-md) dialog,:host(.position-left.size-md) dialog{width:28rem}:host(.position-right.size-lg) dialog,:host(.position-left.size-lg) dialog{width:40rem}:host(.position-right.size-full) dialog,:host(.position-left.size-full) dialog{width:100vw}:host(.position-top.size-sm) dialog,:host(.position-bottom.size-sm) dialog{height:12rem}:host(.position-top.size-md) dialog,:host(.position-bottom.size-md) dialog{height:20rem}:host(.position-top.size-lg) dialog,:host(.position-bottom.size-lg) dialog{height:32rem}:host(.position-top.size-full) dialog,:host(.position-bottom.size-full) dialog{height:100dvh}llm-drawer-header{display:flex;align-items:center;justify-content:space-between;padding:var(--ui-spacing-4) var(--ui-spacing-5);border-bottom:1px solid var(--ui-color-border);font-size:var(--ui-font-size-xl);font-weight:600;letter-spacing:var(--ui-letter-spacing-tight);color:var(--ui-color-text);flex-shrink:0}llm-drawer-content{display:block;padding:var(--ui-spacing-5);overflow-y:auto;flex:1;color:var(--ui-color-text)}llm-drawer-footer{display:flex;align-items:center;justify-content:flex-end;gap:var(--ui-spacing-2);padding:var(--ui-spacing-4) var(--ui-spacing-5);border-top:1px solid var(--ui-color-border);flex-shrink:0}.close-btn{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;width:1.75rem;height:1.75rem;padding:0;margin-left:var(--ui-spacing-3);background:transparent;border:none;border-radius:var(--ui-radius-sm);cursor:pointer;color:var(--ui-color-text-muted);transition:background-color var(--ui-transition-fast),color var(--ui-transition-fast);line-height:1}.close-btn:hover{background-color:var(--ui-color-surface-sunken);color:var(--ui-color-text)}.close-btn:focus-visible{outline:none;box-shadow:var(--ui-focus-ring)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3119
|
+
}
|
|
3120
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmDrawerHeader, decorators: [{
|
|
3121
|
+
type: Component,
|
|
3122
|
+
args: [{ selector: 'llm-drawer-header', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: `
|
|
3123
|
+
<ng-content />
|
|
3124
|
+
<button
|
|
3125
|
+
class="close-btn"
|
|
3126
|
+
type="button"
|
|
3127
|
+
aria-label="Close drawer"
|
|
3128
|
+
(click)="context.close()"
|
|
3129
|
+
>
|
|
3130
|
+
<svg
|
|
3131
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
3132
|
+
width="14"
|
|
3133
|
+
height="14"
|
|
3134
|
+
viewBox="0 0 24 24"
|
|
3135
|
+
fill="none"
|
|
3136
|
+
stroke="currentColor"
|
|
3137
|
+
stroke-width="2.5"
|
|
3138
|
+
stroke-linecap="round"
|
|
3139
|
+
stroke-linejoin="round"
|
|
3140
|
+
aria-hidden="true"
|
|
3141
|
+
focusable="false"
|
|
3142
|
+
>
|
|
3143
|
+
<line x1="18" y1="6" x2="6" y2="18" />
|
|
3144
|
+
<line x1="6" y1="6" x2="18" y2="18" />
|
|
3145
|
+
</svg>
|
|
3146
|
+
</button>
|
|
3147
|
+
`, host: {
|
|
3148
|
+
'[attr.id]': 'context.headerId',
|
|
3149
|
+
}, styles: ["llm-drawer{display:contents}dialog{all:unset;position:fixed;display:none;flex-direction:column;background:var(--ui-color-surface);box-shadow:var(--ui-shadow-xl, 0 20px 60px rgba(0, 0, 0, .3));color:var(--ui-color-text);overflow:hidden;transition:transform var(--ui-duration-slow) var(--ui-ease-out, ease-out),display var(--ui-duration-slow) allow-discrete,overlay var(--ui-duration-slow) allow-discrete}dialog[open]{display:flex;transform:translate(0)!important}dialog::backdrop{background:#00000080;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);transition:opacity var(--ui-duration-slow) var(--ui-ease-out, ease-out),display var(--ui-duration-slow) allow-discrete,overlay var(--ui-duration-slow) allow-discrete}@starting-style{dialog[open]::backdrop{opacity:0}}@media(prefers-color-scheme:dark){dialog::backdrop{background:#000000b3}}[data-theme=dark] dialog::backdrop{background:#000000b3}.panel{display:flex;flex-direction:column;width:100%;height:100%;overflow:hidden}:host(.position-right) dialog{inset:0 0 0 auto;height:100dvh;transform:translate(100%)}@starting-style{:host(.position-right) dialog[open]{transform:translate(100%)}}:host(.position-left) dialog{inset:0 auto 0 0;height:100dvh;transform:translate(-100%)}@starting-style{:host(.position-left) dialog[open]{transform:translate(-100%)}}:host(.position-top) dialog{inset:0 0 auto;width:100vw;transform:translateY(-100%)}@starting-style{:host(.position-top) dialog[open]{transform:translateY(-100%)}}:host(.position-bottom) dialog{inset:auto 0 0;width:100vw;transform:translateY(100%)}@starting-style{:host(.position-bottom) dialog[open]{transform:translateY(100%)}}:host(.position-right.size-sm) dialog,:host(.position-left.size-sm) dialog{width:20rem}:host(.position-right.size-md) dialog,:host(.position-left.size-md) dialog{width:28rem}:host(.position-right.size-lg) dialog,:host(.position-left.size-lg) dialog{width:40rem}:host(.position-right.size-full) dialog,:host(.position-left.size-full) dialog{width:100vw}:host(.position-top.size-sm) dialog,:host(.position-bottom.size-sm) dialog{height:12rem}:host(.position-top.size-md) dialog,:host(.position-bottom.size-md) dialog{height:20rem}:host(.position-top.size-lg) dialog,:host(.position-bottom.size-lg) dialog{height:32rem}:host(.position-top.size-full) dialog,:host(.position-bottom.size-full) dialog{height:100dvh}llm-drawer-header{display:flex;align-items:center;justify-content:space-between;padding:var(--ui-spacing-4) var(--ui-spacing-5);border-bottom:1px solid var(--ui-color-border);font-size:var(--ui-font-size-xl);font-weight:600;letter-spacing:var(--ui-letter-spacing-tight);color:var(--ui-color-text);flex-shrink:0}llm-drawer-content{display:block;padding:var(--ui-spacing-5);overflow-y:auto;flex:1;color:var(--ui-color-text)}llm-drawer-footer{display:flex;align-items:center;justify-content:flex-end;gap:var(--ui-spacing-2);padding:var(--ui-spacing-4) var(--ui-spacing-5);border-top:1px solid var(--ui-color-border);flex-shrink:0}.close-btn{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;width:1.75rem;height:1.75rem;padding:0;margin-left:var(--ui-spacing-3);background:transparent;border:none;border-radius:var(--ui-radius-sm);cursor:pointer;color:var(--ui-color-text-muted);transition:background-color var(--ui-transition-fast),color var(--ui-transition-fast);line-height:1}.close-btn:hover{background-color:var(--ui-color-surface-sunken);color:var(--ui-color-text)}.close-btn:focus-visible{outline:none;box-shadow:var(--ui-focus-ring)}\n"] }]
|
|
3150
|
+
}] });
|
|
3151
|
+
/**
|
|
3152
|
+
* Content slot for `llm-drawer`. Scrollable primary content area.
|
|
3153
|
+
*/
|
|
3154
|
+
class LlmDrawerContent {
|
|
3155
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmDrawerContent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3156
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.4", type: LlmDrawerContent, isStandalone: true, selector: "llm-drawer-content", ngImport: i0, template: `<ng-content />`, isInline: true, styles: ["llm-drawer{display:contents}dialog{all:unset;position:fixed;display:none;flex-direction:column;background:var(--ui-color-surface);box-shadow:var(--ui-shadow-xl, 0 20px 60px rgba(0, 0, 0, .3));color:var(--ui-color-text);overflow:hidden;transition:transform var(--ui-duration-slow) var(--ui-ease-out, ease-out),display var(--ui-duration-slow) allow-discrete,overlay var(--ui-duration-slow) allow-discrete}dialog[open]{display:flex;transform:translate(0)!important}dialog::backdrop{background:#00000080;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);transition:opacity var(--ui-duration-slow) var(--ui-ease-out, ease-out),display var(--ui-duration-slow) allow-discrete,overlay var(--ui-duration-slow) allow-discrete}@starting-style{dialog[open]::backdrop{opacity:0}}@media(prefers-color-scheme:dark){dialog::backdrop{background:#000000b3}}[data-theme=dark] dialog::backdrop{background:#000000b3}.panel{display:flex;flex-direction:column;width:100%;height:100%;overflow:hidden}:host(.position-right) dialog{inset:0 0 0 auto;height:100dvh;transform:translate(100%)}@starting-style{:host(.position-right) dialog[open]{transform:translate(100%)}}:host(.position-left) dialog{inset:0 auto 0 0;height:100dvh;transform:translate(-100%)}@starting-style{:host(.position-left) dialog[open]{transform:translate(-100%)}}:host(.position-top) dialog{inset:0 0 auto;width:100vw;transform:translateY(-100%)}@starting-style{:host(.position-top) dialog[open]{transform:translateY(-100%)}}:host(.position-bottom) dialog{inset:auto 0 0;width:100vw;transform:translateY(100%)}@starting-style{:host(.position-bottom) dialog[open]{transform:translateY(100%)}}:host(.position-right.size-sm) dialog,:host(.position-left.size-sm) dialog{width:20rem}:host(.position-right.size-md) dialog,:host(.position-left.size-md) dialog{width:28rem}:host(.position-right.size-lg) dialog,:host(.position-left.size-lg) dialog{width:40rem}:host(.position-right.size-full) dialog,:host(.position-left.size-full) dialog{width:100vw}:host(.position-top.size-sm) dialog,:host(.position-bottom.size-sm) dialog{height:12rem}:host(.position-top.size-md) dialog,:host(.position-bottom.size-md) dialog{height:20rem}:host(.position-top.size-lg) dialog,:host(.position-bottom.size-lg) dialog{height:32rem}:host(.position-top.size-full) dialog,:host(.position-bottom.size-full) dialog{height:100dvh}llm-drawer-header{display:flex;align-items:center;justify-content:space-between;padding:var(--ui-spacing-4) var(--ui-spacing-5);border-bottom:1px solid var(--ui-color-border);font-size:var(--ui-font-size-xl);font-weight:600;letter-spacing:var(--ui-letter-spacing-tight);color:var(--ui-color-text);flex-shrink:0}llm-drawer-content{display:block;padding:var(--ui-spacing-5);overflow-y:auto;flex:1;color:var(--ui-color-text)}llm-drawer-footer{display:flex;align-items:center;justify-content:flex-end;gap:var(--ui-spacing-2);padding:var(--ui-spacing-4) var(--ui-spacing-5);border-top:1px solid var(--ui-color-border);flex-shrink:0}.close-btn{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;width:1.75rem;height:1.75rem;padding:0;margin-left:var(--ui-spacing-3);background:transparent;border:none;border-radius:var(--ui-radius-sm);cursor:pointer;color:var(--ui-color-text-muted);transition:background-color var(--ui-transition-fast),color var(--ui-transition-fast);line-height:1}.close-btn:hover{background-color:var(--ui-color-surface-sunken);color:var(--ui-color-text)}.close-btn:focus-visible{outline:none;box-shadow:var(--ui-focus-ring)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3157
|
+
}
|
|
3158
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmDrawerContent, decorators: [{
|
|
3159
|
+
type: Component,
|
|
3160
|
+
args: [{ selector: 'llm-drawer-content', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: `<ng-content />`, styles: ["llm-drawer{display:contents}dialog{all:unset;position:fixed;display:none;flex-direction:column;background:var(--ui-color-surface);box-shadow:var(--ui-shadow-xl, 0 20px 60px rgba(0, 0, 0, .3));color:var(--ui-color-text);overflow:hidden;transition:transform var(--ui-duration-slow) var(--ui-ease-out, ease-out),display var(--ui-duration-slow) allow-discrete,overlay var(--ui-duration-slow) allow-discrete}dialog[open]{display:flex;transform:translate(0)!important}dialog::backdrop{background:#00000080;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);transition:opacity var(--ui-duration-slow) var(--ui-ease-out, ease-out),display var(--ui-duration-slow) allow-discrete,overlay var(--ui-duration-slow) allow-discrete}@starting-style{dialog[open]::backdrop{opacity:0}}@media(prefers-color-scheme:dark){dialog::backdrop{background:#000000b3}}[data-theme=dark] dialog::backdrop{background:#000000b3}.panel{display:flex;flex-direction:column;width:100%;height:100%;overflow:hidden}:host(.position-right) dialog{inset:0 0 0 auto;height:100dvh;transform:translate(100%)}@starting-style{:host(.position-right) dialog[open]{transform:translate(100%)}}:host(.position-left) dialog{inset:0 auto 0 0;height:100dvh;transform:translate(-100%)}@starting-style{:host(.position-left) dialog[open]{transform:translate(-100%)}}:host(.position-top) dialog{inset:0 0 auto;width:100vw;transform:translateY(-100%)}@starting-style{:host(.position-top) dialog[open]{transform:translateY(-100%)}}:host(.position-bottom) dialog{inset:auto 0 0;width:100vw;transform:translateY(100%)}@starting-style{:host(.position-bottom) dialog[open]{transform:translateY(100%)}}:host(.position-right.size-sm) dialog,:host(.position-left.size-sm) dialog{width:20rem}:host(.position-right.size-md) dialog,:host(.position-left.size-md) dialog{width:28rem}:host(.position-right.size-lg) dialog,:host(.position-left.size-lg) dialog{width:40rem}:host(.position-right.size-full) dialog,:host(.position-left.size-full) dialog{width:100vw}:host(.position-top.size-sm) dialog,:host(.position-bottom.size-sm) dialog{height:12rem}:host(.position-top.size-md) dialog,:host(.position-bottom.size-md) dialog{height:20rem}:host(.position-top.size-lg) dialog,:host(.position-bottom.size-lg) dialog{height:32rem}:host(.position-top.size-full) dialog,:host(.position-bottom.size-full) dialog{height:100dvh}llm-drawer-header{display:flex;align-items:center;justify-content:space-between;padding:var(--ui-spacing-4) var(--ui-spacing-5);border-bottom:1px solid var(--ui-color-border);font-size:var(--ui-font-size-xl);font-weight:600;letter-spacing:var(--ui-letter-spacing-tight);color:var(--ui-color-text);flex-shrink:0}llm-drawer-content{display:block;padding:var(--ui-spacing-5);overflow-y:auto;flex:1;color:var(--ui-color-text)}llm-drawer-footer{display:flex;align-items:center;justify-content:flex-end;gap:var(--ui-spacing-2);padding:var(--ui-spacing-4) var(--ui-spacing-5);border-top:1px solid var(--ui-color-border);flex-shrink:0}.close-btn{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;width:1.75rem;height:1.75rem;padding:0;margin-left:var(--ui-spacing-3);background:transparent;border:none;border-radius:var(--ui-radius-sm);cursor:pointer;color:var(--ui-color-text-muted);transition:background-color var(--ui-transition-fast),color var(--ui-transition-fast);line-height:1}.close-btn:hover{background-color:var(--ui-color-surface-sunken);color:var(--ui-color-text)}.close-btn:focus-visible{outline:none;box-shadow:var(--ui-focus-ring)}\n"] }]
|
|
3161
|
+
}] });
|
|
3162
|
+
/**
|
|
3163
|
+
* Footer slot for `llm-drawer`. Renders at the bottom with action buttons.
|
|
3164
|
+
*/
|
|
3165
|
+
class LlmDrawerFooter {
|
|
3166
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmDrawerFooter, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3167
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.4", type: LlmDrawerFooter, isStandalone: true, selector: "llm-drawer-footer", ngImport: i0, template: `<ng-content />`, isInline: true, styles: ["llm-drawer{display:contents}dialog{all:unset;position:fixed;display:none;flex-direction:column;background:var(--ui-color-surface);box-shadow:var(--ui-shadow-xl, 0 20px 60px rgba(0, 0, 0, .3));color:var(--ui-color-text);overflow:hidden;transition:transform var(--ui-duration-slow) var(--ui-ease-out, ease-out),display var(--ui-duration-slow) allow-discrete,overlay var(--ui-duration-slow) allow-discrete}dialog[open]{display:flex;transform:translate(0)!important}dialog::backdrop{background:#00000080;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);transition:opacity var(--ui-duration-slow) var(--ui-ease-out, ease-out),display var(--ui-duration-slow) allow-discrete,overlay var(--ui-duration-slow) allow-discrete}@starting-style{dialog[open]::backdrop{opacity:0}}@media(prefers-color-scheme:dark){dialog::backdrop{background:#000000b3}}[data-theme=dark] dialog::backdrop{background:#000000b3}.panel{display:flex;flex-direction:column;width:100%;height:100%;overflow:hidden}:host(.position-right) dialog{inset:0 0 0 auto;height:100dvh;transform:translate(100%)}@starting-style{:host(.position-right) dialog[open]{transform:translate(100%)}}:host(.position-left) dialog{inset:0 auto 0 0;height:100dvh;transform:translate(-100%)}@starting-style{:host(.position-left) dialog[open]{transform:translate(-100%)}}:host(.position-top) dialog{inset:0 0 auto;width:100vw;transform:translateY(-100%)}@starting-style{:host(.position-top) dialog[open]{transform:translateY(-100%)}}:host(.position-bottom) dialog{inset:auto 0 0;width:100vw;transform:translateY(100%)}@starting-style{:host(.position-bottom) dialog[open]{transform:translateY(100%)}}:host(.position-right.size-sm) dialog,:host(.position-left.size-sm) dialog{width:20rem}:host(.position-right.size-md) dialog,:host(.position-left.size-md) dialog{width:28rem}:host(.position-right.size-lg) dialog,:host(.position-left.size-lg) dialog{width:40rem}:host(.position-right.size-full) dialog,:host(.position-left.size-full) dialog{width:100vw}:host(.position-top.size-sm) dialog,:host(.position-bottom.size-sm) dialog{height:12rem}:host(.position-top.size-md) dialog,:host(.position-bottom.size-md) dialog{height:20rem}:host(.position-top.size-lg) dialog,:host(.position-bottom.size-lg) dialog{height:32rem}:host(.position-top.size-full) dialog,:host(.position-bottom.size-full) dialog{height:100dvh}llm-drawer-header{display:flex;align-items:center;justify-content:space-between;padding:var(--ui-spacing-4) var(--ui-spacing-5);border-bottom:1px solid var(--ui-color-border);font-size:var(--ui-font-size-xl);font-weight:600;letter-spacing:var(--ui-letter-spacing-tight);color:var(--ui-color-text);flex-shrink:0}llm-drawer-content{display:block;padding:var(--ui-spacing-5);overflow-y:auto;flex:1;color:var(--ui-color-text)}llm-drawer-footer{display:flex;align-items:center;justify-content:flex-end;gap:var(--ui-spacing-2);padding:var(--ui-spacing-4) var(--ui-spacing-5);border-top:1px solid var(--ui-color-border);flex-shrink:0}.close-btn{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;width:1.75rem;height:1.75rem;padding:0;margin-left:var(--ui-spacing-3);background:transparent;border:none;border-radius:var(--ui-radius-sm);cursor:pointer;color:var(--ui-color-text-muted);transition:background-color var(--ui-transition-fast),color var(--ui-transition-fast);line-height:1}.close-btn:hover{background-color:var(--ui-color-surface-sunken);color:var(--ui-color-text)}.close-btn:focus-visible{outline:none;box-shadow:var(--ui-focus-ring)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3168
|
+
}
|
|
3169
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: LlmDrawerFooter, decorators: [{
|
|
3170
|
+
type: Component,
|
|
3171
|
+
args: [{ selector: 'llm-drawer-footer', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: `<ng-content />`, styles: ["llm-drawer{display:contents}dialog{all:unset;position:fixed;display:none;flex-direction:column;background:var(--ui-color-surface);box-shadow:var(--ui-shadow-xl, 0 20px 60px rgba(0, 0, 0, .3));color:var(--ui-color-text);overflow:hidden;transition:transform var(--ui-duration-slow) var(--ui-ease-out, ease-out),display var(--ui-duration-slow) allow-discrete,overlay var(--ui-duration-slow) allow-discrete}dialog[open]{display:flex;transform:translate(0)!important}dialog::backdrop{background:#00000080;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);transition:opacity var(--ui-duration-slow) var(--ui-ease-out, ease-out),display var(--ui-duration-slow) allow-discrete,overlay var(--ui-duration-slow) allow-discrete}@starting-style{dialog[open]::backdrop{opacity:0}}@media(prefers-color-scheme:dark){dialog::backdrop{background:#000000b3}}[data-theme=dark] dialog::backdrop{background:#000000b3}.panel{display:flex;flex-direction:column;width:100%;height:100%;overflow:hidden}:host(.position-right) dialog{inset:0 0 0 auto;height:100dvh;transform:translate(100%)}@starting-style{:host(.position-right) dialog[open]{transform:translate(100%)}}:host(.position-left) dialog{inset:0 auto 0 0;height:100dvh;transform:translate(-100%)}@starting-style{:host(.position-left) dialog[open]{transform:translate(-100%)}}:host(.position-top) dialog{inset:0 0 auto;width:100vw;transform:translateY(-100%)}@starting-style{:host(.position-top) dialog[open]{transform:translateY(-100%)}}:host(.position-bottom) dialog{inset:auto 0 0;width:100vw;transform:translateY(100%)}@starting-style{:host(.position-bottom) dialog[open]{transform:translateY(100%)}}:host(.position-right.size-sm) dialog,:host(.position-left.size-sm) dialog{width:20rem}:host(.position-right.size-md) dialog,:host(.position-left.size-md) dialog{width:28rem}:host(.position-right.size-lg) dialog,:host(.position-left.size-lg) dialog{width:40rem}:host(.position-right.size-full) dialog,:host(.position-left.size-full) dialog{width:100vw}:host(.position-top.size-sm) dialog,:host(.position-bottom.size-sm) dialog{height:12rem}:host(.position-top.size-md) dialog,:host(.position-bottom.size-md) dialog{height:20rem}:host(.position-top.size-lg) dialog,:host(.position-bottom.size-lg) dialog{height:32rem}:host(.position-top.size-full) dialog,:host(.position-bottom.size-full) dialog{height:100dvh}llm-drawer-header{display:flex;align-items:center;justify-content:space-between;padding:var(--ui-spacing-4) var(--ui-spacing-5);border-bottom:1px solid var(--ui-color-border);font-size:var(--ui-font-size-xl);font-weight:600;letter-spacing:var(--ui-letter-spacing-tight);color:var(--ui-color-text);flex-shrink:0}llm-drawer-content{display:block;padding:var(--ui-spacing-5);overflow-y:auto;flex:1;color:var(--ui-color-text)}llm-drawer-footer{display:flex;align-items:center;justify-content:flex-end;gap:var(--ui-spacing-2);padding:var(--ui-spacing-4) var(--ui-spacing-5);border-top:1px solid var(--ui-color-border);flex-shrink:0}.close-btn{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;width:1.75rem;height:1.75rem;padding:0;margin-left:var(--ui-spacing-3);background:transparent;border:none;border-radius:var(--ui-radius-sm);cursor:pointer;color:var(--ui-color-text-muted);transition:background-color var(--ui-transition-fast),color var(--ui-transition-fast);line-height:1}.close-btn:hover{background-color:var(--ui-color-surface-sunken);color:var(--ui-color-text)}.close-btn:focus-visible{outline:none;box-shadow:var(--ui-focus-ring)}\n"] }]
|
|
3172
|
+
}] });
|
|
3173
|
+
|
|
3174
|
+
// Design tokens stylesheet — consumers should import:
|
|
3175
|
+
// @import '@atelier-ui/angular/styles/tokens.css';
|
|
3176
|
+
|
|
3177
|
+
/**
|
|
3178
|
+
* Generated bundle index. Do not edit.
|
|
3179
|
+
*/
|
|
3180
|
+
|
|
3181
|
+
export { LLM_ACCORDION_GROUP, LLM_BREADCRUMBS, LLM_DIALOG, LLM_DRAWER, LLM_RADIO_GROUP, LLM_SELECT, LLM_TAB_GROUP, LlmAccordionGroup, LlmAccordionHeader, LlmAccordionItem, LlmAlert, LlmAvatar, LlmAvatarGroup, LlmBadge, LlmBreadcrumbItem, LlmBreadcrumbs, LlmButton, LlmCard, LlmCardContent, LlmCardFooter, LlmCardHeader, LlmCheckbox, LlmDialog, LlmDialogContent, LlmDialogFooter, LlmDialogHeader, LlmDrawer, LlmDrawerContent, LlmDrawerFooter, LlmDrawerHeader, LlmInput, LlmMenu, LlmMenuItem, LlmMenuSeparator, LlmMenuTrigger, LlmOption, LlmPagination, LlmProgress, LlmRadio, LlmRadioGroup, LlmSelect, LlmSkeleton, LlmTab, LlmTabGroup, LlmTextarea, LlmToast, LlmToastContainer, LlmToastService, LlmToggle, LlmTooltip };
|
|
3182
|
+
//# sourceMappingURL=atelier-ui-angular.mjs.map
|