@a2ui/angular 0.8.3 → 0.9.0-alpha.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.
Files changed (48) hide show
  1. package/LICENSE +203 -0
  2. package/README.md +111 -3
  3. package/fesm2022/a2ui-angular-src-v0_8.mjs +1797 -0
  4. package/fesm2022/a2ui-angular-src-v0_8.mjs.map +1 -0
  5. package/fesm2022/a2ui-angular-src-v0_9.mjs +2525 -0
  6. package/fesm2022/a2ui-angular-src-v0_9.mjs.map +1 -0
  7. package/fesm2022/a2ui-angular-v0_8.mjs +1797 -0
  8. package/fesm2022/a2ui-angular-v0_8.mjs.map +1 -0
  9. package/fesm2022/a2ui-angular-v0_9.mjs +2525 -0
  10. package/fesm2022/a2ui-angular-v0_9.mjs.map +1 -0
  11. package/fesm2022/a2ui-angular.mjs +1558 -616
  12. package/fesm2022/a2ui-angular.mjs.map +1 -1
  13. package/package.json +51 -7
  14. package/types/a2ui-angular-src-v0_8.d.ts +400 -0
  15. package/types/a2ui-angular-src-v0_9.d.ts +964 -0
  16. package/types/a2ui-angular-v0_8.d.ts +400 -0
  17. package/types/a2ui-angular-v0_9.d.ts +964 -0
  18. package/types/a2ui-angular.d.ts +362 -35
  19. package/fesm2022/a2ui-angular-audio-DoZb9mn_.mjs +0 -48
  20. package/fesm2022/a2ui-angular-audio-DoZb9mn_.mjs.map +0 -1
  21. package/fesm2022/a2ui-angular-button-CvH0kAtN.mjs +0 -61
  22. package/fesm2022/a2ui-angular-button-CvH0kAtN.mjs.map +0 -1
  23. package/fesm2022/a2ui-angular-card-Ix6OIdUv.mjs +0 -48
  24. package/fesm2022/a2ui-angular-card-Ix6OIdUv.mjs.map +0 -1
  25. package/fesm2022/a2ui-angular-checkbox-BN4EF2Ci.mjs +0 -78
  26. package/fesm2022/a2ui-angular-checkbox-BN4EF2Ci.mjs.map +0 -1
  27. package/fesm2022/a2ui-angular-datetime-input-dmZAjvrF.mjs +0 -120
  28. package/fesm2022/a2ui-angular-datetime-input-dmZAjvrF.mjs.map +0 -1
  29. package/fesm2022/a2ui-angular-divider-BizPl3qL.mjs +0 -30
  30. package/fesm2022/a2ui-angular-divider-BizPl3qL.mjs.map +0 -1
  31. package/fesm2022/a2ui-angular-icon-BE9Hj9V6.mjs +0 -48
  32. package/fesm2022/a2ui-angular-icon-BE9Hj9V6.mjs.map +0 -1
  33. package/fesm2022/a2ui-angular-image-BWzAw0rh.mjs +0 -54
  34. package/fesm2022/a2ui-angular-image-BWzAw0rh.mjs.map +0 -1
  35. package/fesm2022/a2ui-angular-list-nEeT59V3.mjs +0 -45
  36. package/fesm2022/a2ui-angular-list-nEeT59V3.mjs.map +0 -1
  37. package/fesm2022/a2ui-angular-modal-mr9LmczA.mjs +0 -108
  38. package/fesm2022/a2ui-angular-modal-mr9LmczA.mjs.map +0 -1
  39. package/fesm2022/a2ui-angular-multiple-choice-Bry7X74i.mjs +0 -78
  40. package/fesm2022/a2ui-angular-multiple-choice-Bry7X74i.mjs.map +0 -1
  41. package/fesm2022/a2ui-angular-slider-BgseUbN2.mjs +0 -79
  42. package/fesm2022/a2ui-angular-slider-BgseUbN2.mjs.map +0 -1
  43. package/fesm2022/a2ui-angular-tabs-q5Mn9vgq.mjs +0 -87
  44. package/fesm2022/a2ui-angular-tabs-q5Mn9vgq.mjs.map +0 -1
  45. package/fesm2022/a2ui-angular-text-field-Deokh07j.mjs +0 -85
  46. package/fesm2022/a2ui-angular-text-field-Deokh07j.mjs.map +0 -1
  47. package/fesm2022/a2ui-angular-video-DuFTfN0B.mjs +0 -48
  48. package/fesm2022/a2ui-angular-video-DuFTfN0B.mjs.map +0 -1
@@ -0,0 +1,2525 @@
1
+ import * as i0 from '@angular/core';
2
+ import { InjectionToken, Inject, Injectable, signal, inject, DestroyRef, NgZone, input, ChangeDetectionStrategy, Component, computed as computed$1, effect as effect$1 } from '@angular/core';
3
+ import { MessageProcessor, effect, computed, ComponentContext, Catalog, DataContext } from '@a2ui/web_core/v0_9';
4
+ export { signal as preactSignal } from '@a2ui/web_core/v0_9';
5
+ import { NgComponentOutlet } from '@angular/common';
6
+ import { injectBasicCatalogStyles, DateTimeInputApi, SliderApi, ChoicePickerApi, CheckBoxApi, DividerApi, ModalApi, TabsApi, CardApi, ListApi, AudioPlayerApi, VideoApi, IconApi, ImageApi, TextFieldApi, ButtonApi, ColumnApi, RowApi, TextApi, BASIC_FUNCTIONS } from '@a2ui/web_core/v0_9/basic_catalog';
7
+ export { BASIC_FUNCTIONS } from '@a2ui/web_core/v0_9/basic_catalog';
8
+
9
+ /**
10
+ * Copyright 2026 Google LLC
11
+ *
12
+ * Licensed under the Apache License, Version 2.0 (the "License");
13
+ * you may not use this file except in compliance with the License.
14
+ * You may obtain a copy of the License at
15
+ *
16
+ * http://www.apache.org/licenses/LICENSE-2.0
17
+ *
18
+ * Unless required by applicable law or agreed to in writing, software
19
+ * distributed under the License is distributed on an "AS IS" BASIS,
20
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21
+ * See the License for the specific language governing permissions and
22
+ * limitations under the License.
23
+ */
24
+ /**
25
+ * Injection token for the A2UI renderer configuration.
26
+ */
27
+ const A2UI_RENDERER_CONFIG = new InjectionToken('A2UI_RENDERER_CONFIG');
28
+ /**
29
+ * Manages A2UI v0.9 rendering sessions by bridging the MessageProcessor to Angular.
30
+ *
31
+ * This service is the central entry point for the A2UI renderer. It maintains a
32
+ * {@link MessageProcessor} that turns A2UI protocol messages into a reactive
33
+ * {@link SurfaceGroupModel}.
34
+ */
35
+ class A2uiRendererService {
36
+ config;
37
+ _messageProcessor;
38
+ _catalogs = [];
39
+ constructor(config) {
40
+ this.config = config;
41
+ this._catalogs = this.config.catalogs;
42
+ this._messageProcessor = new MessageProcessor(this._catalogs, this.config.actionHandler);
43
+ }
44
+ /**
45
+ * Processes a list of A2UI messages and updates the internal surface models.
46
+ *
47
+ * This should be called whenever new messages arrive from an agent or orchestrator.
48
+ *
49
+ * @param messages The list of {@link A2uiMessage}s to process.
50
+ */
51
+ processMessages(messages) {
52
+ this._messageProcessor.processMessages(messages);
53
+ }
54
+ /**
55
+ * The current surface group model containing all active surfaces.
56
+ *
57
+ * Surfaces can be retrieved from this group using their `surfaceId`.
58
+ */
59
+ get surfaceGroup() {
60
+ return this._messageProcessor.model;
61
+ }
62
+ ngOnDestroy() {
63
+ this._messageProcessor.model.dispose();
64
+ }
65
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: A2uiRendererService, deps: [{ token: A2UI_RENDERER_CONFIG }], target: i0.ɵɵFactoryTarget.Injectable });
66
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: A2uiRendererService });
67
+ }
68
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: A2uiRendererService, decorators: [{
69
+ type: Injectable
70
+ }], ctorParameters: () => [{ type: undefined, decorators: [{
71
+ type: Inject,
72
+ args: [A2UI_RENDERER_CONFIG]
73
+ }] }] });
74
+
75
+ /**
76
+ * Copyright 2026 Google LLC
77
+ *
78
+ * Licensed under the Apache License, Version 2.0 (the "License");
79
+ * you may not use this file except in compliance with the License.
80
+ * You may obtain a copy of the License at
81
+ *
82
+ * http://www.apache.org/licenses/LICENSE-2.0
83
+ *
84
+ * Unless required by applicable law or agreed to in writing, software
85
+ * distributed under the License is distributed on an "AS IS" BASIS,
86
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
87
+ * See the License for the specific language governing permissions and
88
+ * limitations under the License.
89
+ */
90
+ function toAngularSignal(preactSignal, destroyRef, ngZone) {
91
+ const s = signal(preactSignal.peek());
92
+ const dispose = effect(() => {
93
+ if (ngZone) {
94
+ ngZone.run(() => s.set(preactSignal.value));
95
+ }
96
+ else {
97
+ s.set(preactSignal.value);
98
+ }
99
+ });
100
+ destroyRef.onDestroy(() => {
101
+ dispose();
102
+ // Some signals returned by DataContext.resolveSignal have a custom unsubscribe for AbortControllers
103
+ if (preactSignal.unsubscribe) {
104
+ preactSignal.unsubscribe();
105
+ }
106
+ });
107
+ return s.asReadonly();
108
+ }
109
+ /**
110
+ * Normalizes a data model path by combining a relative path with a base context.
111
+ *
112
+ * This is used to create unique absolute paths for components within a repeating
113
+ * collection or nested structure.
114
+ *
115
+ * @param path The relative or absolute path from the component properties.
116
+ * @param dataContextPath The current base data context path.
117
+ * @param index The index of the child component.
118
+ * @returns A fully normalized absolute path for the indexed child.
119
+ */
120
+ function getNormalizedPath(path, dataContextPath, index) {
121
+ let normalized = path || '';
122
+ if (!normalized.startsWith('/')) {
123
+ const base = dataContextPath === '/' ? '' : dataContextPath;
124
+ normalized = `${base}/${normalized}`;
125
+ }
126
+ if (normalized.endsWith('/')) {
127
+ normalized = normalized.slice(0, -1);
128
+ }
129
+ return `${normalized}/${index}`;
130
+ }
131
+
132
+ /**
133
+ * Copyright 2026 Google LLC
134
+ *
135
+ * Licensed under the Apache License, Version 2.0 (the "License");
136
+ * you may not use this file except in compliance with the License.
137
+ * You may obtain a copy of the License at
138
+ *
139
+ * http://www.apache.org/licenses/LICENSE-2.0
140
+ *
141
+ * Unless required by applicable law or agreed to in writing, software
142
+ * distributed under the License is distributed on an "AS IS" BASIS,
143
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
144
+ * See the License for the specific language governing permissions and
145
+ * limitations under the License.
146
+ */
147
+ /**
148
+ * Binds A2UI ComponentModel properties to reactive Angular Signals.
149
+ *
150
+ * This service is used by {@link ComponentHostComponent} to resolve data bindings
151
+ * from the A2UI DataContext and expose them as Angular Signals. It ensures that
152
+ * property updates from the A2UI protocol are correctly reflected in Angular
153
+ * components and provides callbacks for updating the data model.
154
+ */
155
+ class ComponentBinder {
156
+ destroyRef = inject(DestroyRef);
157
+ ngZone = inject(NgZone);
158
+ /**
159
+ * Binds all properties of a component to an object of Angular Signals.
160
+ *
161
+ * @param context The ComponentContext containing the model and data context.
162
+ * @returns An object where each key corresponds to a component prop and its value is an Angular Signal.
163
+ */
164
+ bind(context) {
165
+ const props = context.componentModel.properties;
166
+ const bound = {};
167
+ for (const key of Object.keys(props)) {
168
+ const value = props[key];
169
+ let preactSig;
170
+ const isChildListTemplate = value && typeof value === 'object' && 'componentId' in value && 'path' in value;
171
+ const isBoundPath = value && typeof value === 'object' && 'path' in value && !('componentId' in value);
172
+ if (isChildListTemplate) {
173
+ const listSig = context.dataContext.resolveSignal({ path: value.path });
174
+ const listContext = context.dataContext.nested(value.path);
175
+ preactSig = computed(() => {
176
+ const arr = listSig.value;
177
+ const currentArr = Array.isArray(arr) ? arr : [];
178
+ return currentArr.map((_, i) => ({
179
+ id: value.componentId,
180
+ basePath: listContext.nested(String(i)).path,
181
+ }));
182
+ });
183
+ }
184
+ else {
185
+ preactSig = context.dataContext.resolveSignal(value);
186
+ }
187
+ if (['child', 'trigger', 'content'].includes(key)) {
188
+ const originalSig = preactSig;
189
+ preactSig = computed(() => {
190
+ const val = originalSig.value;
191
+ if (!val)
192
+ return null;
193
+ if (typeof val === 'object' && val !== null && 'id' in val) {
194
+ return val;
195
+ }
196
+ return { id: val, basePath: context.dataContext.path };
197
+ });
198
+ }
199
+ else if (key === 'children') {
200
+ const originalSig = preactSig;
201
+ preactSig = computed(() => {
202
+ const val = originalSig.value;
203
+ const arr = Array.isArray(val) ? val : [];
204
+ return arr.map(item => {
205
+ if (typeof item === 'object' && item !== null && 'id' in item) {
206
+ return item;
207
+ }
208
+ return { id: item, basePath: context.dataContext.path };
209
+ });
210
+ });
211
+ }
212
+ const angSig = toAngularSignal(preactSig, this.destroyRef, this.ngZone);
213
+ bound[key] = {
214
+ value: angSig,
215
+ raw: value,
216
+ onUpdate: isBoundPath
217
+ ? (newValue) => context.dataContext.set(value.path, newValue)
218
+ : () => { }, // No-op for non-bound values
219
+ };
220
+ if (key === 'checks') {
221
+ const checksArray = Array.isArray(value) ? value : [];
222
+ const ruleResults = checksArray.map((rule) => {
223
+ const condition = rule.condition || rule;
224
+ const message = rule.message || 'Validation failed';
225
+ const conditionSig = context.dataContext.resolveSignal(condition);
226
+ return { conditionSig, message };
227
+ });
228
+ const isValidPreactSig = computed(() => {
229
+ return ruleResults.every((r) => !!r.conditionSig.value);
230
+ });
231
+ const validationErrorsPreactSig = computed(() => {
232
+ return ruleResults
233
+ .filter((r) => !r.conditionSig.value)
234
+ .map((r) => r.message);
235
+ });
236
+ bound['isValid'] = {
237
+ value: toAngularSignal(isValidPreactSig, this.destroyRef, this.ngZone),
238
+ raw: null,
239
+ onUpdate: () => { },
240
+ };
241
+ bound['validationErrors'] = {
242
+ value: toAngularSignal(validationErrorsPreactSig, this.destroyRef, this.ngZone),
243
+ raw: null,
244
+ onUpdate: () => { },
245
+ };
246
+ }
247
+ }
248
+ return bound;
249
+ }
250
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ComponentBinder, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
251
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ComponentBinder, providedIn: 'root' });
252
+ }
253
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ComponentBinder, decorators: [{
254
+ type: Injectable,
255
+ args: [{
256
+ providedIn: 'root',
257
+ }]
258
+ }] });
259
+
260
+ /**
261
+ * Copyright 2026 Google LLC
262
+ *
263
+ * Licensed under the Apache License, Version 2.0 (the "License");
264
+ * you may not use this file except in compliance with the License.
265
+ * You may obtain a copy of the License at
266
+ *
267
+ * http://www.apache.org/licenses/LICENSE-2.0
268
+ *
269
+ * Unless required by applicable law or agreed to in writing, software
270
+ * distributed under the License is distributed on an "AS IS" BASIS,
271
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
272
+ * See the License for the specific language governing permissions and
273
+ * limitations under the License.
274
+ */
275
+ /**
276
+ * Dynamically renders an A2UI component as defined in the current surface model.
277
+ *
278
+ * This component acts as a bridge between the A2UI surface model and Angular components.
279
+ * It resolves the appropriate component from the catalog based on the component's type,
280
+ * and uses {@link ComponentBinder} to create reactive property bindings.
281
+ *
282
+ * Usually, you'll use the higher-level {@link SurfaceComponent} which automatically
283
+ * sets up a host for the 'root' component.
284
+ */
285
+ class ComponentHostComponent {
286
+ /** The key of the component to render, either an ID string or an object with ID and basePath. Defaults to 'root'. */
287
+ componentKey = input('root', ...(ngDevMode ? [{ debugName: "componentKey" }] : /* istanbul ignore next */ []));
288
+ /** The unique identifier of the surface this component belongs to. */
289
+ surfaceId = input.required(...(ngDevMode ? [{ debugName: "surfaceId" }] : /* istanbul ignore next */ []));
290
+ rendererService = inject(A2uiRendererService);
291
+ binder = inject(ComponentBinder);
292
+ destroyRef = inject(DestroyRef);
293
+ componentType = null;
294
+ props = {};
295
+ context;
296
+ resolvedComponentId = '';
297
+ resolvedDataContextPath = '/';
298
+ ngOnInit() {
299
+ const surface = this.rendererService.surfaceGroup?.getSurface(this.surfaceId());
300
+ if (!surface) {
301
+ console.warn(`Surface ${this.surfaceId()} not found`);
302
+ return;
303
+ }
304
+ const key = this.componentKey();
305
+ let id;
306
+ let basePath;
307
+ if (typeof key === 'object' && key !== null && 'id' in key) {
308
+ id = key.id;
309
+ basePath = key.basePath || '/';
310
+ }
311
+ else {
312
+ id = key;
313
+ basePath = '/';
314
+ }
315
+ this.resolvedComponentId = id;
316
+ const componentModel = surface.componentsModel.get(id);
317
+ if (!componentModel) {
318
+ console.warn(`Component ${id} not found in surface ${this.surfaceId()}`);
319
+ return;
320
+ }
321
+ // Resolve component from the surface's catalog
322
+ const catalog = surface.catalog;
323
+ const api = catalog.components.get(componentModel.type);
324
+ if (!api) {
325
+ console.error(`Component type "${componentModel.type}" not found in catalog "${catalog.id}"`);
326
+ return;
327
+ }
328
+ this.componentType = api.component;
329
+ // Create context
330
+ this.context = new ComponentContext(surface, id, basePath);
331
+ this.props = this.binder.bind(this.context);
332
+ this.resolvedDataContextPath = this.context.dataContext.path;
333
+ this.destroyRef.onDestroy(() => {
334
+ // ComponentContext itself doesn't have a dispose, but its inner components might.
335
+ // However, SurfaceModel takes care of component disposal.
336
+ });
337
+ }
338
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ComponentHostComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
339
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: ComponentHostComponent, isStandalone: true, selector: "a2ui-v09-component-host", inputs: { componentKey: { classPropertyName: "componentKey", publicName: "componentKey", isSignal: true, isRequired: false, transformFunction: null }, surfaceId: { classPropertyName: "surfaceId", publicName: "surfaceId", isSignal: true, isRequired: true, transformFunction: null } }, host: { styleAttribute: "display: contents;" }, ngImport: i0, template: `
340
+ @if (componentType) {
341
+ <ng-container
342
+ *ngComponentOutlet="
343
+ componentType;
344
+ inputs: {
345
+ props: props,
346
+ surfaceId: surfaceId(),
347
+ componentId: resolvedComponentId,
348
+ dataContextPath: resolvedDataContextPath,
349
+ }
350
+ "
351
+ ></ng-container>
352
+ }
353
+ `, isInline: true, dependencies: [{ kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
354
+ }
355
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ComponentHostComponent, decorators: [{
356
+ type: Component,
357
+ args: [{
358
+ selector: 'a2ui-v09-component-host',
359
+ imports: [NgComponentOutlet],
360
+ host: {
361
+ 'style': 'display: contents;'
362
+ },
363
+ template: `
364
+ @if (componentType) {
365
+ <ng-container
366
+ *ngComponentOutlet="
367
+ componentType;
368
+ inputs: {
369
+ props: props,
370
+ surfaceId: surfaceId(),
371
+ componentId: resolvedComponentId,
372
+ dataContextPath: resolvedDataContextPath,
373
+ }
374
+ "
375
+ ></ng-container>
376
+ }
377
+ `,
378
+ changeDetection: ChangeDetectionStrategy.OnPush,
379
+ }]
380
+ }], propDecorators: { componentKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "componentKey", required: false }] }], surfaceId: [{ type: i0.Input, args: [{ isSignal: true, alias: "surfaceId", required: true }] }] } });
381
+
382
+ /**
383
+ * Copyright 2026 Google LLC
384
+ *
385
+ * Licensed under the Apache License, Version 2.0 (the "License");
386
+ * you may not use this file except in compliance with the License.
387
+ * You may obtain a copy of the License at
388
+ *
389
+ * http://www.apache.org/licenses/LICENSE-2.0
390
+ *
391
+ * Unless required by applicable law or agreed to in writing, software
392
+ * distributed under the License is distributed on an "AS IS" BASIS,
393
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
394
+ * See the License for the specific language governing permissions and
395
+ * limitations under the License.
396
+ */
397
+ /**
398
+ * High-level component for rendering an entire A2UI surface.
399
+ *
400
+ * This component handles the boilerplate of setting up a {@link ComponentHostComponent}
401
+ * for the 'root' component of a surface. It is the recommended way to embed an
402
+ * A2UI surface in an Angular application.
403
+ */
404
+ class SurfaceComponent {
405
+ /** The unique identifier of the surface to render. */
406
+ surfaceId = input.required(...(ngDevMode ? [{ debugName: "surfaceId" }] : /* istanbul ignore next */ []));
407
+ /**
408
+ * The path within the surface's data model that represents the current state.
409
+ * Defaults to the root ('/').
410
+ */
411
+ dataContextPath = input('/', ...(ngDevMode ? [{ debugName: "dataContextPath" }] : /* istanbul ignore next */ []));
412
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SurfaceComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
413
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.5", type: SurfaceComponent, isStandalone: true, selector: "a2ui-v09-surface", inputs: { surfaceId: { classPropertyName: "surfaceId", publicName: "surfaceId", isSignal: true, isRequired: true, transformFunction: null }, dataContextPath: { classPropertyName: "dataContextPath", publicName: "dataContextPath", isSignal: true, isRequired: false, transformFunction: null } }, host: { styleAttribute: "display: contents;" }, ngImport: i0, template: `
414
+ <a2ui-v09-component-host
415
+ [componentKey]="{ id: 'root', basePath: dataContextPath() }"
416
+ [surfaceId]="surfaceId()"
417
+ >
418
+ </a2ui-v09-component-host>
419
+ `, isInline: true, dependencies: [{ kind: "component", type: ComponentHostComponent, selector: "a2ui-v09-component-host", inputs: ["componentKey", "surfaceId"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
420
+ }
421
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SurfaceComponent, decorators: [{
422
+ type: Component,
423
+ args: [{
424
+ selector: 'a2ui-v09-surface',
425
+ standalone: true,
426
+ imports: [ComponentHostComponent],
427
+ host: {
428
+ 'style': 'display: contents;'
429
+ },
430
+ template: `
431
+ <a2ui-v09-component-host
432
+ [componentKey]="{ id: 'root', basePath: dataContextPath() }"
433
+ [surfaceId]="surfaceId()"
434
+ >
435
+ </a2ui-v09-component-host>
436
+ `,
437
+ changeDetection: ChangeDetectionStrategy.OnPush,
438
+ }]
439
+ }], propDecorators: { surfaceId: [{ type: i0.Input, args: [{ isSignal: true, alias: "surfaceId", required: true }] }], dataContextPath: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataContextPath", required: false }] }] } });
440
+
441
+ /**
442
+ * Copyright 2026 Google LLC
443
+ *
444
+ * Licensed under the Apache License, Version 2.0 (the "License");
445
+ * you may not use this file except in compliance with the License.
446
+ * You may obtain a copy of the License at
447
+ *
448
+ * http://www.apache.org/licenses/LICENSE-2.0
449
+ *
450
+ * Unless required by applicable law or agreed to in writing, software
451
+ * distributed under the License is distributed on an "AS IS" BASIS,
452
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
453
+ * See the License for the specific language governing permissions and
454
+ * limitations under the License.
455
+ */
456
+
457
+ /**
458
+ * Copyright 2026 Google LLC
459
+ *
460
+ * Licensed under the Apache License, Version 2.0 (the "License");
461
+ * you may not use this file except in compliance with the License.
462
+ * You may obtain a copy of the License at
463
+ *
464
+ * http://www.apache.org/licenses/LICENSE-2.0
465
+ *
466
+ * Unless required by applicable law or agreed to in writing, software
467
+ * distributed under the License is distributed on an "AS IS" BASIS,
468
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
469
+ * See the License for the specific language governing permissions and
470
+ * limitations under the License.
471
+ */
472
+ /**
473
+ * A collection of Angular component and function implementations mapped to
474
+ * A2UI protocol types.
475
+ *
476
+ * Catalogs are used by the {@link MessageProcessor} to resolve component
477
+ * definitions and by {@link ComponentHostComponent} to instantiate the
478
+ * correct Angular components.
479
+ */
480
+ class AngularCatalog extends Catalog {
481
+ }
482
+
483
+ /**
484
+ * Copyright 2026 Google LLC
485
+ *
486
+ * Licensed under the Apache License, Version 2.0 (the "License");
487
+ * you may not use this file except in compliance with the License.
488
+ * You may obtain a copy of the License at
489
+ *
490
+ * http://www.apache.org/licenses/LICENSE-2.0
491
+ *
492
+ * Unless required by applicable law or agreed to in writing, software
493
+ * distributed under the License is distributed on an "AS IS" BASIS,
494
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
495
+ * See the License for the specific language governing permissions and
496
+ * limitations under the License.
497
+ */
498
+ class MarkdownRenderer {
499
+ }
500
+ class DefaultMarkdownRenderer extends MarkdownRenderer {
501
+ static warningLogged = false;
502
+ async render(markdown, options) {
503
+ try {
504
+ // @ts-ignore - optional peer dependency
505
+ const { renderMarkdown } = await import('@a2ui/markdown-it');
506
+ return await renderMarkdown(markdown, options);
507
+ }
508
+ catch (e) {
509
+ if (!DefaultMarkdownRenderer.warningLogged) {
510
+ console.warn("[DefaultMarkdownRenderer] Failed to load optional `@a2ui/markdown-it` renderer. Using fallback.");
511
+ DefaultMarkdownRenderer.warningLogged = true;
512
+ }
513
+ return markdown;
514
+ }
515
+ }
516
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: DefaultMarkdownRenderer, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
517
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: DefaultMarkdownRenderer, providedIn: 'root' });
518
+ }
519
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: DefaultMarkdownRenderer, decorators: [{
520
+ type: Injectable,
521
+ args: [{
522
+ providedIn: 'root',
523
+ }]
524
+ }] });
525
+ function provideMarkdownRenderer(renderFn) {
526
+ if (renderFn) {
527
+ return {
528
+ provide: MarkdownRenderer,
529
+ useValue: {
530
+ render: renderFn,
531
+ },
532
+ };
533
+ }
534
+ return { provide: MarkdownRenderer, useClass: DefaultMarkdownRenderer };
535
+ }
536
+
537
+ /**
538
+ * Copyright 2026 Google LLC
539
+ *
540
+ * Licensed under the Apache License, Version 2.0 (the "License");
541
+ * you may not use this file except in compliance with the License.
542
+ * You may obtain a copy of the License at
543
+ *
544
+ * http://www.apache.org/licenses/LICENSE-2.0
545
+ *
546
+ * Unless required by applicable law or agreed to in writing, software
547
+ * distributed under the License is distributed on an "AS IS" BASIS,
548
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
549
+ * See the License for the specific language governing permissions and
550
+ * limitations under the License.
551
+ */
552
+ /**
553
+ * Base class for A2UI basic catalog components in Angular.
554
+ *
555
+ * Automatically injects the basic catalog styles when the component is instantiated.
556
+ */
557
+ class BasicCatalogComponent {
558
+ constructor() {
559
+ injectBasicCatalogStyles();
560
+ }
561
+ }
562
+
563
+ /**
564
+ * Copyright 2026 Google LLC
565
+ *
566
+ * Licensed under the Apache License, Version 2.0 (the "License");
567
+ * you may not use this file except in compliance with the License.
568
+ * You may obtain a copy of the License at
569
+ *
570
+ * http://www.apache.org/licenses/LICENSE-2.0
571
+ *
572
+ * Unless required by applicable law or agreed to in writing, software
573
+ * distributed under the License is distributed on an "AS IS" BASIS,
574
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
575
+ * See the License for the specific language governing permissions and
576
+ * limitations under the License.
577
+ */
578
+ /**
579
+ * Angular implementation of the A2UI Text component (v0.9).
580
+ *
581
+ * Renders text with support for simple Markdown.
582
+ *
583
+ * Supported CSS variables:
584
+ * - `--a2ui-text-color-text`: Controls the text color.
585
+ * - `--a2ui-text-margin`: Controls the margin of text elements.
586
+ * - `--a2ui-font-family-title`: Controls the font family for titles.
587
+ * - `--a2ui-line-height-headings`: Controls the line height for headings.
588
+ * - `--a2ui-line-height-body`: Controls the line height for body text.
589
+ * - `--a2ui-text-caption-color`: Controls the color for caption text.
590
+ * - `--a2ui-text-a-color`: Controls the color for links.
591
+ * - `--a2ui-text-a-font-weight`: Controls the font weight for links.
592
+ * - Font sizes: `--a2ui-font-size-2xl`, `--a2ui-font-size-xl`, `--a2ui-font-size-l`, `--a2ui-font-size-m`, `--a2ui-font-size-s`, `--a2ui-font-size-xs`.
593
+ */
594
+ class TextComponent extends BasicCatalogComponent {
595
+ /**
596
+ * Reactive properties resolved from the A2UI {@link ComponentModel}.
597
+ *
598
+ * Expected properties:
599
+ * - `text`: The string content to display.
600
+ * - `variant`: A hint for the base text style ('h1', 'h2', 'h3', 'h4', 'h5', 'caption', 'body').
601
+ */
602
+ props = input({}, ...(ngDevMode ? [{ debugName: "props" }] : /* istanbul ignore next */ []));
603
+ surfaceId = input.required(...(ngDevMode ? [{ debugName: "surfaceId" }] : /* istanbul ignore next */ []));
604
+ componentId = input(...(ngDevMode ? [undefined, { debugName: "componentId" }] : /* istanbul ignore next */ []));
605
+ dataContextPath = input('/', ...(ngDevMode ? [{ debugName: "dataContextPath" }] : /* istanbul ignore next */ []));
606
+ markdownRenderer = inject(MarkdownRenderer);
607
+ variant = computed$1(() => this.props()['variant']?.value() || 'body', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
608
+ text = computed$1(() => this.props()['text']?.value() || '', ...(ngDevMode ? [{ debugName: "text" }] : /* istanbul ignore next */ []));
609
+ resolvedText = signal('', ...(ngDevMode ? [{ debugName: "resolvedText" }] : /* istanbul ignore next */ []));
610
+ renderRequestId = 0;
611
+ constructor() {
612
+ super();
613
+ effect$1(() => {
614
+ const text = this.text();
615
+ const variant = this.variant();
616
+ let value = text;
617
+ switch (variant) {
618
+ case 'h1':
619
+ value = `# ${text}`;
620
+ break;
621
+ case 'h2':
622
+ value = `## ${text}`;
623
+ break;
624
+ case 'h3':
625
+ value = `### ${text}`;
626
+ break;
627
+ case 'h4':
628
+ value = `#### ${text}`;
629
+ break;
630
+ case 'h5':
631
+ value = `##### ${text}`;
632
+ break;
633
+ case 'caption':
634
+ value = `*${text}*`;
635
+ break;
636
+ }
637
+ const requestId = ++this.renderRequestId;
638
+ this.markdownRenderer.render(value).then(rendered => {
639
+ if (requestId === this.renderRequestId) {
640
+ this.resolvedText.set(rendered);
641
+ }
642
+ });
643
+ });
644
+ }
645
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: TextComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
646
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.5", type: TextComponent, isStandalone: true, selector: "a2ui-v09-text", inputs: { props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null }, surfaceId: { classPropertyName: "surfaceId", publicName: "surfaceId", isSignal: true, isRequired: true, transformFunction: null }, componentId: { classPropertyName: "componentId", publicName: "componentId", isSignal: true, isRequired: false, transformFunction: null }, dataContextPath: { classPropertyName: "dataContextPath", publicName: "dataContextPath", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: `
647
+ <span [class]="'a2ui-text ' + variant()" [innerHTML]="resolvedText()">
648
+ </span>
649
+ `, isInline: true, styles: [":host ::ng-deep .a2ui-text p,:host ::ng-deep .a2ui-text h1,:host ::ng-deep .a2ui-text h2,:host ::ng-deep .a2ui-text h3,:host ::ng-deep .a2ui-text h4,:host ::ng-deep .a2ui-text h5,:host ::ng-deep .a2ui-text h6,:host ::ng-deep .a2ui-text ol,:host ::ng-deep .a2ui-text ul,:host ::ng-deep .a2ui-text li,:host ::ng-deep .a2ui-text blockquote,:host ::ng-deep .a2ui-text pre{margin:var(--_a2ui-text-margin, 0)}:host ::ng-deep .a2ui-text{color:var(--_a2ui-text-color, var(--a2ui-text-color-text, var(--a2ui-color-on-background)))}:host ::ng-deep .a2ui-text h1,:host ::ng-deep .a2ui-text h2,:host ::ng-deep .a2ui-text h3,:host ::ng-deep .a2ui-text h4,:host ::ng-deep .a2ui-text h5,:host ::ng-deep .a2ui-text h6{font-family:var(--a2ui-font-family-title, inherit);line-height:var(--a2ui-line-height-headings, 1.2)}:host ::ng-deep .a2ui-text h1{font-size:var(--a2ui-font-size-2xl)}:host ::ng-deep .a2ui-text h2{font-size:var(--a2ui-font-size-xl)}:host ::ng-deep .a2ui-text h3{font-size:var(--a2ui-font-size-l)}:host ::ng-deep .a2ui-text p,:host ::ng-deep .a2ui-text h4{font-size:var(--a2ui-font-size-m)}:host ::ng-deep .a2ui-text h5{font-size:var(--a2ui-font-size-s)}:host ::ng-deep .a2ui-text p{line-height:var(--a2ui-line-height-body, 1.5)}:host ::ng-deep .a2ui-text.caption{font-size:var(--a2ui-font-size-xs);color:var(--a2ui-text-caption-color, light-dark(#666, #aaa))}:host ::ng-deep .a2ui-text a{color:var(--a2ui-text-a-color, inherit);font-weight:var(--a2ui-text-a-font-weight, inherit)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
650
+ }
651
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: TextComponent, decorators: [{
652
+ type: Component,
653
+ args: [{ selector: 'a2ui-v09-text', standalone: true, template: `
654
+ <span [class]="'a2ui-text ' + variant()" [innerHTML]="resolvedText()">
655
+ </span>
656
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host ::ng-deep .a2ui-text p,:host ::ng-deep .a2ui-text h1,:host ::ng-deep .a2ui-text h2,:host ::ng-deep .a2ui-text h3,:host ::ng-deep .a2ui-text h4,:host ::ng-deep .a2ui-text h5,:host ::ng-deep .a2ui-text h6,:host ::ng-deep .a2ui-text ol,:host ::ng-deep .a2ui-text ul,:host ::ng-deep .a2ui-text li,:host ::ng-deep .a2ui-text blockquote,:host ::ng-deep .a2ui-text pre{margin:var(--_a2ui-text-margin, 0)}:host ::ng-deep .a2ui-text{color:var(--_a2ui-text-color, var(--a2ui-text-color-text, var(--a2ui-color-on-background)))}:host ::ng-deep .a2ui-text h1,:host ::ng-deep .a2ui-text h2,:host ::ng-deep .a2ui-text h3,:host ::ng-deep .a2ui-text h4,:host ::ng-deep .a2ui-text h5,:host ::ng-deep .a2ui-text h6{font-family:var(--a2ui-font-family-title, inherit);line-height:var(--a2ui-line-height-headings, 1.2)}:host ::ng-deep .a2ui-text h1{font-size:var(--a2ui-font-size-2xl)}:host ::ng-deep .a2ui-text h2{font-size:var(--a2ui-font-size-xl)}:host ::ng-deep .a2ui-text h3{font-size:var(--a2ui-font-size-l)}:host ::ng-deep .a2ui-text p,:host ::ng-deep .a2ui-text h4{font-size:var(--a2ui-font-size-m)}:host ::ng-deep .a2ui-text h5{font-size:var(--a2ui-font-size-s)}:host ::ng-deep .a2ui-text p{line-height:var(--a2ui-line-height-body, 1.5)}:host ::ng-deep .a2ui-text.caption{font-size:var(--a2ui-font-size-xs);color:var(--a2ui-text-caption-color, light-dark(#666, #aaa))}:host ::ng-deep .a2ui-text a{color:var(--a2ui-text-a-color, inherit);font-weight:var(--a2ui-text-a-font-weight, inherit)}\n"] }]
657
+ }], ctorParameters: () => [], propDecorators: { props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], surfaceId: [{ type: i0.Input, args: [{ isSignal: true, alias: "surfaceId", required: true }] }], componentId: [{ type: i0.Input, args: [{ isSignal: true, alias: "componentId", required: false }] }], dataContextPath: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataContextPath", required: false }] }] } });
658
+
659
+ /**
660
+ * Copyright 2026 Google LLC
661
+ *
662
+ * Licensed under the Apache License, Version 2.0 (the "License");
663
+ * you may not use this file except in compliance with the License.
664
+ * You may obtain a copy of the License at
665
+ *
666
+ * http://www.apache.org/licenses/LICENSE-2.0
667
+ *
668
+ * Unless required by applicable law or agreed to in writing, software
669
+ * distributed under the License is distributed on an "AS IS" BASIS,
670
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
671
+ * See the License for the specific language governing permissions and
672
+ * limitations under the License.
673
+ */
674
+ /**
675
+ * Maps A2UI justification values to CSS justify-content values.
676
+ */
677
+ const JUSTIFY_MAP = {
678
+ start: 'flex-start',
679
+ center: 'center',
680
+ end: 'flex-end',
681
+ spaceBetween: 'space-between',
682
+ spaceAround: 'space-around',
683
+ spaceEvenly: 'space-evenly',
684
+ stretch: 'stretch',
685
+ };
686
+ /**
687
+ * Maps A2UI alignment values to CSS align-items values.
688
+ */
689
+ const ALIGN_MAP = {
690
+ start: 'flex-start',
691
+ center: 'center',
692
+ end: 'flex-end',
693
+ stretch: 'stretch',
694
+ baseline: 'baseline',
695
+ };
696
+
697
+ /**
698
+ * Copyright 2026 Google LLC
699
+ *
700
+ * Licensed under the Apache License, Version 2.0 (the "License");
701
+ * you may not use this file except in compliance with the License.
702
+ * You may obtain a copy of the License at
703
+ *
704
+ * http://www.apache.org/licenses/LICENSE-2.0
705
+ *
706
+ * Unless required by applicable law or agreed to in writing, software
707
+ * distributed under the License is distributed on an "AS IS" BASIS,
708
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
709
+ * See the License for the specific language governing permissions and
710
+ * limitations under the License.
711
+ */
712
+ /**
713
+ * Angular implementation of the A2UI Row component (v0.9).
714
+ *
715
+ * Arranges child components in a horizontal flex layout. Supports both static
716
+ * lists of children and repeating templates bound to a data collection.
717
+ *
718
+ * Supported CSS variables:
719
+ * - `--a2ui-row-gap`: Controls the gap between items in the row. Defaults to `--a2ui-spacing-m` (16px).
720
+ */
721
+ class RowComponent extends BasicCatalogComponent {
722
+ /**
723
+ * Reactive properties resolved from the A2UI {@link ComponentModel}.
724
+ *
725
+ * Expected properties:
726
+ * - `children`: A list of component IDs OR a repeating collection definition.
727
+ * - `justify`: Flexbox justify-content value (e.g., 'flex-start', 'center').
728
+ * - `align`: Flexbox align-items value (e.g., 'flex-start', 'center').
729
+ */
730
+ props = input({}, ...(ngDevMode ? [{ debugName: "props" }] : /* istanbul ignore next */ []));
731
+ surfaceId = input.required(...(ngDevMode ? [{ debugName: "surfaceId" }] : /* istanbul ignore next */ []));
732
+ componentId = input(...(ngDevMode ? [undefined, { debugName: "componentId" }] : /* istanbul ignore next */ []));
733
+ dataContextPath = input('/', ...(ngDevMode ? [{ debugName: "dataContextPath" }] : /* istanbul ignore next */ []));
734
+ justify = computed$1(() => {
735
+ const val = this.props()['justify']?.value();
736
+ return val ? (JUSTIFY_MAP[val] || val) : undefined;
737
+ }, ...(ngDevMode ? [{ debugName: "justify" }] : /* istanbul ignore next */ []));
738
+ align = computed$1(() => {
739
+ const val = this.props()['align']?.value();
740
+ return val ? (ALIGN_MAP[val] || val) : undefined;
741
+ }, ...(ngDevMode ? [{ debugName: "align" }] : /* istanbul ignore next */ []));
742
+ children = computed$1(() => {
743
+ const raw = this.props()['children']?.value() || [];
744
+ return Array.isArray(raw) ? raw : [];
745
+ }, ...(ngDevMode ? [{ debugName: "children" }] : /* istanbul ignore next */ []));
746
+ isRepeating = computed$1(() => {
747
+ return !!this.props()['children']?.raw?.componentId;
748
+ }, ...(ngDevMode ? [{ debugName: "isRepeating" }] : /* istanbul ignore next */ []));
749
+ templateId = computed$1(() => {
750
+ return this.props()['children']?.raw?.componentId;
751
+ }, ...(ngDevMode ? [{ debugName: "templateId" }] : /* istanbul ignore next */ []));
752
+ normalizedChildren = computed$1(() => {
753
+ if (this.isRepeating())
754
+ return [];
755
+ return this.children().map(child => {
756
+ if (typeof child === 'object' && child !== null && 'id' in child) {
757
+ return child;
758
+ }
759
+ return { id: child, basePath: this.dataContextPath() };
760
+ });
761
+ }, ...(ngDevMode ? [{ debugName: "normalizedChildren" }] : /* istanbul ignore next */ []));
762
+ getNormalizedPath(index) {
763
+ return getNormalizedPath(this.props()['children']?.raw?.path, this.dataContextPath(), index);
764
+ }
765
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: RowComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
766
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: RowComponent, isStandalone: true, selector: "a2ui-v09-row", inputs: { props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null }, surfaceId: { classPropertyName: "surfaceId", publicName: "surfaceId", isSignal: true, isRequired: true, transformFunction: null }, componentId: { classPropertyName: "componentId", publicName: "componentId", isSignal: true, isRequired: false, transformFunction: null }, dataContextPath: { classPropertyName: "dataContextPath", publicName: "dataContextPath", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "style.display": "\"flex\"", "style.flex-direction": "\"row\"", "style.gap": "\"var(--a2ui-row-gap, var(--a2ui-spacing-m, 16px))\"", "style.justify-content": "justify()", "style.align-items": "align()" } }, usesInheritance: true, ngImport: i0, template: `
767
+ @if (!isRepeating()) {
768
+ @for (child of normalizedChildren(); track child.id) {
769
+ <a2ui-v09-component-host
770
+ [componentKey]="child"
771
+ [surfaceId]="surfaceId()"
772
+ >
773
+ </a2ui-v09-component-host>
774
+ }
775
+ }
776
+
777
+ @if (isRepeating()) {
778
+ @for (item of children(); track item; let i = $index) {
779
+ <a2ui-v09-component-host
780
+ [componentKey]="{ id: templateId()!, basePath: getNormalizedPath(i) }"
781
+ [surfaceId]="surfaceId()"
782
+ >
783
+ </a2ui-v09-component-host>
784
+ }
785
+ }
786
+ `, isInline: true, dependencies: [{ kind: "component", type: ComponentHostComponent, selector: "a2ui-v09-component-host", inputs: ["componentKey", "surfaceId"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
787
+ }
788
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: RowComponent, decorators: [{
789
+ type: Component,
790
+ args: [{
791
+ selector: 'a2ui-v09-row',
792
+ standalone: true,
793
+ imports: [ComponentHostComponent],
794
+ host: {
795
+ '[style.display]': '"flex"',
796
+ '[style.flex-direction]': '"row"',
797
+ '[style.gap]': '"var(--a2ui-row-gap, var(--a2ui-spacing-m, 16px))"',
798
+ '[style.justify-content]': 'justify()',
799
+ '[style.align-items]': 'align()'
800
+ },
801
+ template: `
802
+ @if (!isRepeating()) {
803
+ @for (child of normalizedChildren(); track child.id) {
804
+ <a2ui-v09-component-host
805
+ [componentKey]="child"
806
+ [surfaceId]="surfaceId()"
807
+ >
808
+ </a2ui-v09-component-host>
809
+ }
810
+ }
811
+
812
+ @if (isRepeating()) {
813
+ @for (item of children(); track item; let i = $index) {
814
+ <a2ui-v09-component-host
815
+ [componentKey]="{ id: templateId()!, basePath: getNormalizedPath(i) }"
816
+ [surfaceId]="surfaceId()"
817
+ >
818
+ </a2ui-v09-component-host>
819
+ }
820
+ }
821
+ `,
822
+ changeDetection: ChangeDetectionStrategy.OnPush,
823
+ }]
824
+ }], propDecorators: { props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], surfaceId: [{ type: i0.Input, args: [{ isSignal: true, alias: "surfaceId", required: true }] }], componentId: [{ type: i0.Input, args: [{ isSignal: true, alias: "componentId", required: false }] }], dataContextPath: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataContextPath", required: false }] }] } });
825
+
826
+ /**
827
+ * Copyright 2026 Google LLC
828
+ *
829
+ * Licensed under the Apache License, Version 2.0 (the "License");
830
+ * you may not use this file except in compliance with the License.
831
+ * You may obtain a copy of the License at
832
+ *
833
+ * http://www.apache.org/licenses/LICENSE-2.0
834
+ *
835
+ * Unless required by applicable law or agreed to in writing, software
836
+ * distributed under the License is distributed on an "AS IS" BASIS,
837
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
838
+ * See the License for the specific language governing permissions and
839
+ * limitations under the License.
840
+ */
841
+ /**
842
+ * Angular implementation of the A2UI Column component (v0.9).
843
+ *
844
+ * Arranges child components in a vertical flex layout. Supports both static
845
+ * lists of children and repeating templates bound to a data collection.
846
+ *
847
+ * Supported CSS variables:
848
+ * - `--a2ui-column-gap`: Controls the gap between items in the column. Defaults to `--a2ui-spacing-m` (16px).
849
+ */
850
+ class ColumnComponent extends BasicCatalogComponent {
851
+ /**
852
+ * Reactive properties resolved from the A2UI {@link ComponentModel}.
853
+ *
854
+ * Expected properties:
855
+ * - `children`: A list of component IDs OR a repeating collection definition.
856
+ * - `justify`: Flexbox justify-content value (e.g., 'flex-start', 'center').
857
+ * - `align`: Flexbox align-items value (e.g., 'flex-start', 'center').
858
+ */
859
+ props = input({}, ...(ngDevMode ? [{ debugName: "props" }] : /* istanbul ignore next */ []));
860
+ surfaceId = input.required(...(ngDevMode ? [{ debugName: "surfaceId" }] : /* istanbul ignore next */ []));
861
+ componentId = input(...(ngDevMode ? [undefined, { debugName: "componentId" }] : /* istanbul ignore next */ []));
862
+ dataContextPath = input('/', ...(ngDevMode ? [{ debugName: "dataContextPath" }] : /* istanbul ignore next */ []));
863
+ justify = computed$1(() => {
864
+ const val = this.props()['justify']?.value();
865
+ return val ? (JUSTIFY_MAP[val] || val) : undefined;
866
+ }, ...(ngDevMode ? [{ debugName: "justify" }] : /* istanbul ignore next */ []));
867
+ align = computed$1(() => {
868
+ const val = this.props()['align']?.value();
869
+ return val ? (ALIGN_MAP[val] || val) : undefined;
870
+ }, ...(ngDevMode ? [{ debugName: "align" }] : /* istanbul ignore next */ []));
871
+ children = computed$1(() => {
872
+ const raw = this.props()['children']?.value() || [];
873
+ return Array.isArray(raw) ? raw : [];
874
+ }, ...(ngDevMode ? [{ debugName: "children" }] : /* istanbul ignore next */ []));
875
+ isRepeating = computed$1(() => {
876
+ return !!this.props()['children']?.raw?.componentId;
877
+ }, ...(ngDevMode ? [{ debugName: "isRepeating" }] : /* istanbul ignore next */ []));
878
+ templateId = computed$1(() => {
879
+ return this.props()['children']?.raw?.componentId;
880
+ }, ...(ngDevMode ? [{ debugName: "templateId" }] : /* istanbul ignore next */ []));
881
+ normalizedChildren = computed$1(() => {
882
+ if (this.isRepeating())
883
+ return [];
884
+ return this.children().map(child => {
885
+ if (typeof child === 'object' && child !== null && 'id' in child) {
886
+ return child;
887
+ }
888
+ return { id: child, basePath: this.dataContextPath() };
889
+ });
890
+ }, ...(ngDevMode ? [{ debugName: "normalizedChildren" }] : /* istanbul ignore next */ []));
891
+ getNormalizedPath(index) {
892
+ return getNormalizedPath(this.props()['children']?.raw?.path, this.dataContextPath(), index);
893
+ }
894
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ColumnComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
895
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: ColumnComponent, isStandalone: true, selector: "a2ui-v09-column", inputs: { props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null }, surfaceId: { classPropertyName: "surfaceId", publicName: "surfaceId", isSignal: true, isRequired: true, transformFunction: null }, componentId: { classPropertyName: "componentId", publicName: "componentId", isSignal: true, isRequired: false, transformFunction: null }, dataContextPath: { classPropertyName: "dataContextPath", publicName: "dataContextPath", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "style.display": "\"flex\"", "style.flex-direction": "\"column\"", "style.width": "\"100%\"", "style.gap": "\"var(--a2ui-column-gap, var(--a2ui-spacing-m, 16px))\"", "style.justify-content": "justify()", "style.align-items": "align()" } }, usesInheritance: true, ngImport: i0, template: `
896
+ @if (!isRepeating()) {
897
+ @for (child of normalizedChildren(); track child.id) {
898
+ <a2ui-v09-component-host
899
+ [componentKey]="child"
900
+ [surfaceId]="surfaceId()"
901
+ >
902
+ </a2ui-v09-component-host>
903
+ }
904
+ }
905
+
906
+ @if (isRepeating()) {
907
+ @for (item of children(); track item; let i = $index) {
908
+ <a2ui-v09-component-host
909
+ [componentKey]="{ id: templateId()!, basePath: getNormalizedPath(i) }"
910
+ [surfaceId]="surfaceId()"
911
+ >
912
+ </a2ui-v09-component-host>
913
+ }
914
+ }
915
+ `, isInline: true, dependencies: [{ kind: "component", type: ComponentHostComponent, selector: "a2ui-v09-component-host", inputs: ["componentKey", "surfaceId"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
916
+ }
917
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ColumnComponent, decorators: [{
918
+ type: Component,
919
+ args: [{
920
+ selector: 'a2ui-v09-column',
921
+ standalone: true,
922
+ imports: [ComponentHostComponent],
923
+ host: {
924
+ '[style.display]': '"flex"',
925
+ '[style.flex-direction]': '"column"',
926
+ '[style.width]': '"100%"',
927
+ '[style.gap]': '"var(--a2ui-column-gap, var(--a2ui-spacing-m, 16px))"',
928
+ '[style.justify-content]': 'justify()',
929
+ '[style.align-items]': 'align()'
930
+ },
931
+ template: `
932
+ @if (!isRepeating()) {
933
+ @for (child of normalizedChildren(); track child.id) {
934
+ <a2ui-v09-component-host
935
+ [componentKey]="child"
936
+ [surfaceId]="surfaceId()"
937
+ >
938
+ </a2ui-v09-component-host>
939
+ }
940
+ }
941
+
942
+ @if (isRepeating()) {
943
+ @for (item of children(); track item; let i = $index) {
944
+ <a2ui-v09-component-host
945
+ [componentKey]="{ id: templateId()!, basePath: getNormalizedPath(i) }"
946
+ [surfaceId]="surfaceId()"
947
+ >
948
+ </a2ui-v09-component-host>
949
+ }
950
+ }
951
+ `,
952
+ changeDetection: ChangeDetectionStrategy.OnPush,
953
+ }]
954
+ }], propDecorators: { props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], surfaceId: [{ type: i0.Input, args: [{ isSignal: true, alias: "surfaceId", required: true }] }], componentId: [{ type: i0.Input, args: [{ isSignal: true, alias: "componentId", required: false }] }], dataContextPath: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataContextPath", required: false }] }] } });
955
+
956
+ /**
957
+ * Copyright 2026 Google LLC
958
+ *
959
+ * Licensed under the Apache License, Version 2.0 (the "License");
960
+ * you may not use this file except in compliance with the License.
961
+ * You may obtain a copy of the License at
962
+ *
963
+ * http://www.apache.org/licenses/LICENSE-2.0
964
+ *
965
+ * Unless required by applicable law or agreed to in writing, software
966
+ * distributed under the License is distributed on an "AS IS" BASIS,
967
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
968
+ * See the License for the specific language governing permissions and
969
+ * limitations under the License.
970
+ */
971
+ /**
972
+ * Angular implementation of the A2UI Button component (v0.9).
973
+ *
974
+ * Renders a clickable button with a single child component (usually Text).
975
+ * Dispatches an action when clicked if an `action` property is provided.
976
+ *
977
+ * Supported CSS variables:
978
+ * - `--a2ui-button-padding`: Controls the padding.
979
+ * - `--a2ui-button-border-radius`: Controls the border radius.
980
+ * - `--a2ui-button-border`: Controls the border.
981
+ * - `--a2ui-button-margin`: Controls the margin.
982
+ * - `--a2ui-button-background`: Controls the background color.
983
+ * - `--a2ui-button-box-shadow`: Controls the box shadow.
984
+ * - `--a2ui-button-font-weight`: Controls the font weight.
985
+ */
986
+ class ButtonComponent extends BasicCatalogComponent {
987
+ /**
988
+ * Reactive properties resolved from the A2UI {@link ComponentModel}.
989
+ *
990
+ * Expected properties:
991
+ * - `child`: The ID of the component to render inside the button.
992
+ * - `variant`: Button style variant ('default', 'primary', 'borderless').
993
+ * - `action`: The A2UI action to dispatch on click.
994
+ * - `checks`: Optional validation rules.
995
+ */
996
+ props = input({}, ...(ngDevMode ? [{ debugName: "props" }] : /* istanbul ignore next */ []));
997
+ surfaceId = input.required(...(ngDevMode ? [{ debugName: "surfaceId" }] : /* istanbul ignore next */ []));
998
+ componentId = input.required(...(ngDevMode ? [{ debugName: "componentId" }] : /* istanbul ignore next */ []));
999
+ dataContextPath = input('/', ...(ngDevMode ? [{ debugName: "dataContextPath" }] : /* istanbul ignore next */ []));
1000
+ rendererService = inject(A2uiRendererService);
1001
+ variant = computed$1(() => this.props()['variant']?.value() ?? 'default', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
1002
+ child = computed$1(() => this.props()['child']?.value(), ...(ngDevMode ? [{ debugName: "child" }] : /* istanbul ignore next */ []));
1003
+ action = computed$1(() => this.props()['action']?.value(), ...(ngDevMode ? [{ debugName: "action" }] : /* istanbul ignore next */ []));
1004
+ handleClick() {
1005
+ const action = this.action();
1006
+ if (action) {
1007
+ const surface = this.rendererService.surfaceGroup?.getSurface(this.surfaceId());
1008
+ if (surface) {
1009
+ const dataContext = new DataContext(surface, this.dataContextPath());
1010
+ const resolvedAction = dataContext.resolveAction(action);
1011
+ surface.dispatchAction(resolvedAction, this.componentId());
1012
+ }
1013
+ }
1014
+ }
1015
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ButtonComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
1016
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: ButtonComponent, isStandalone: true, selector: "a2ui-v09-button", inputs: { props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null }, surfaceId: { classPropertyName: "surfaceId", publicName: "surfaceId", isSignal: true, isRequired: true, transformFunction: null }, componentId: { classPropertyName: "componentId", publicName: "componentId", isSignal: true, isRequired: true, transformFunction: null }, dataContextPath: { classPropertyName: "dataContextPath", publicName: "dataContextPath", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: `
1017
+ <button
1018
+ [type]="variant() === 'primary' ? 'submit' : 'button'"
1019
+ [class]="'a2ui-button ' + variant()"
1020
+ (click)="handleClick()"
1021
+ [disabled]="props()['isValid']?.value() === false"
1022
+ >
1023
+ @if (child()) {
1024
+ <a2ui-v09-component-host
1025
+ [componentKey]="child()!"
1026
+ [surfaceId]="surfaceId()"
1027
+ >
1028
+ </a2ui-v09-component-host>
1029
+ }
1030
+ </button>
1031
+ `, isInline: true, styles: [".a2ui-button{padding:var(--a2ui-button-padding, var(--a2ui-spacing-m, .5rem) var(--a2ui-spacing-l, 1rem));border-radius:var(--a2ui-button-border-radius, var(--a2ui-spacing-s, .25rem));border:var(--a2ui-button-border, var(--a2ui-border-width, 1px) solid var(--a2ui-color-border, #ccc));cursor:pointer;margin:var(--a2ui-button-margin, var(--a2ui-spacing-m, .5rem));background:var(--a2ui-button-background, var(--a2ui-color-surface, #fff));box-shadow:var(--a2ui-button-box-shadow, none);font-weight:var(--a2ui-button-font-weight, normal);--_a2ui-text-margin: 0;--_a2ui-text-color: var(--a2ui-color-on-secondary, #333);color:var(--_a2ui-text-color)}.a2ui-button.primary{background-color:var(--a2ui-color-primary, #17e);--_a2ui-text-color: var(--a2ui-color-on-primary, #fff);color:var(--_a2ui-text-color);border-color:var(--a2ui-color-primary-hover, #0069d9)}.a2ui-button.borderless{background:none;border:none;padding:0;color:var(--a2ui-color-primary, #17e)}.a2ui-button:disabled{background-color:#e9ecef;color:#6c757d;border-color:#ced4da;cursor:not-allowed}\n"], dependencies: [{ kind: "component", type: ComponentHostComponent, selector: "a2ui-v09-component-host", inputs: ["componentKey", "surfaceId"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1032
+ }
1033
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ButtonComponent, decorators: [{
1034
+ type: Component,
1035
+ args: [{ selector: 'a2ui-v09-button', standalone: true, imports: [ComponentHostComponent], template: `
1036
+ <button
1037
+ [type]="variant() === 'primary' ? 'submit' : 'button'"
1038
+ [class]="'a2ui-button ' + variant()"
1039
+ (click)="handleClick()"
1040
+ [disabled]="props()['isValid']?.value() === false"
1041
+ >
1042
+ @if (child()) {
1043
+ <a2ui-v09-component-host
1044
+ [componentKey]="child()!"
1045
+ [surfaceId]="surfaceId()"
1046
+ >
1047
+ </a2ui-v09-component-host>
1048
+ }
1049
+ </button>
1050
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".a2ui-button{padding:var(--a2ui-button-padding, var(--a2ui-spacing-m, .5rem) var(--a2ui-spacing-l, 1rem));border-radius:var(--a2ui-button-border-radius, var(--a2ui-spacing-s, .25rem));border:var(--a2ui-button-border, var(--a2ui-border-width, 1px) solid var(--a2ui-color-border, #ccc));cursor:pointer;margin:var(--a2ui-button-margin, var(--a2ui-spacing-m, .5rem));background:var(--a2ui-button-background, var(--a2ui-color-surface, #fff));box-shadow:var(--a2ui-button-box-shadow, none);font-weight:var(--a2ui-button-font-weight, normal);--_a2ui-text-margin: 0;--_a2ui-text-color: var(--a2ui-color-on-secondary, #333);color:var(--_a2ui-text-color)}.a2ui-button.primary{background-color:var(--a2ui-color-primary, #17e);--_a2ui-text-color: var(--a2ui-color-on-primary, #fff);color:var(--_a2ui-text-color);border-color:var(--a2ui-color-primary-hover, #0069d9)}.a2ui-button.borderless{background:none;border:none;padding:0;color:var(--a2ui-color-primary, #17e)}.a2ui-button:disabled{background-color:#e9ecef;color:#6c757d;border-color:#ced4da;cursor:not-allowed}\n"] }]
1051
+ }], propDecorators: { props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], surfaceId: [{ type: i0.Input, args: [{ isSignal: true, alias: "surfaceId", required: true }] }], componentId: [{ type: i0.Input, args: [{ isSignal: true, alias: "componentId", required: true }] }], dataContextPath: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataContextPath", required: false }] }] } });
1052
+
1053
+ /**
1054
+ * Copyright 2026 Google LLC
1055
+ *
1056
+ * Licensed under the Apache License, Version 2.0 (the "License");
1057
+ * you may not use this file except in compliance with the License.
1058
+ * You may obtain a copy of the License at
1059
+ *
1060
+ * http://www.apache.org/licenses/LICENSE-2.0
1061
+ *
1062
+ * Unless required by applicable law or agreed to in writing, software
1063
+ * distributed under the License is distributed on an "AS IS" BASIS,
1064
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1065
+ * See the License for the specific language governing permissions and
1066
+ * limitations under the License.
1067
+ */
1068
+ /**
1069
+ * Angular implementation of the A2UI TextField component (v0.9).
1070
+ *
1071
+ * Renders a text input field with an optional label and placeholder.
1072
+ * Updates the bound data model property on every input change.
1073
+ *
1074
+ * Supported CSS variables:
1075
+ * - `--a2ui-color-input`: Controls the background color of the input.
1076
+ * - `--a2ui-color-on-input`: Controls the text color of the input.
1077
+ * - `--a2ui-textfield-border`: Controls the border of the input.
1078
+ * - `--a2ui-textfield-border-radius`: Controls the border radius of the input.
1079
+ * - `--a2ui-textfield-padding`: Controls the padding of the input.
1080
+ * - `--a2ui-textfield-color-border-focus`: Controls the border color on focus.
1081
+ * - `--a2ui-textfield-color-error`: Controls the border and text color for error states.
1082
+ * - `--a2ui-textfield-label-font-size`: Controls the font size of the label.
1083
+ * - `--a2ui-textfield-label-font-weight`: Controls the font weight of the label.
1084
+ */
1085
+ class TextFieldComponent extends BasicCatalogComponent {
1086
+ /**
1087
+ * Reactive properties resolved from the A2UI {@link ComponentModel}.
1088
+ *
1089
+ * Expected properties:
1090
+ * - `value`: The current string value of the input.
1091
+ * - `label`: Optional label text to display above the input.
1092
+ * - `placeholder`: Hint text shown when the input is empty.
1093
+ * - `variant`: Input type variant ('default', 'obscured' (password), 'number').
1094
+ * - `checks`: Optional validation rules.
1095
+ */
1096
+ props = input({}, ...(ngDevMode ? [{ debugName: "props" }] : /* istanbul ignore next */ []));
1097
+ surfaceId = input.required(...(ngDevMode ? [{ debugName: "surfaceId" }] : /* istanbul ignore next */ []));
1098
+ componentId = input(...(ngDevMode ? [undefined, { debugName: "componentId" }] : /* istanbul ignore next */ []));
1099
+ dataContextPath = input('/', ...(ngDevMode ? [{ debugName: "dataContextPath" }] : /* istanbul ignore next */ []));
1100
+ label = computed$1(() => this.props()['label']?.value(), ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
1101
+ value = computed$1(() => this.props()['value']?.value() || '', ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
1102
+ placeholder = computed$1(() => this.props()['placeholder']?.value() || '', ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
1103
+ variant = computed$1(() => this.props()['variant']?.value(), ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
1104
+ inputType = computed$1(() => {
1105
+ switch (this.variant()) {
1106
+ case 'obscured':
1107
+ return 'password';
1108
+ case 'number':
1109
+ return 'number';
1110
+ default:
1111
+ return 'text';
1112
+ }
1113
+ }, ...(ngDevMode ? [{ debugName: "inputType" }] : /* istanbul ignore next */ []));
1114
+ handleInput(event) {
1115
+ const value = event.target.value;
1116
+ // Update the data path. If anything is listening to this path, it will be
1117
+ // notified.
1118
+ this.props()['value']?.onUpdate(value);
1119
+ }
1120
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: TextFieldComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
1121
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: TextFieldComponent, isStandalone: true, selector: "a2ui-v09-text-field", inputs: { props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null }, surfaceId: { classPropertyName: "surfaceId", publicName: "surfaceId", isSignal: true, isRequired: true, transformFunction: null }, componentId: { classPropertyName: "componentId", publicName: "componentId", isSignal: true, isRequired: false, transformFunction: null }, dataContextPath: { classPropertyName: "dataContextPath", publicName: "dataContextPath", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: `
1122
+ <div class="a2ui-text-field-container">
1123
+ @if (label()) {
1124
+ <label>{{ label() }}</label>
1125
+ }
1126
+ <input
1127
+ [type]="inputType()"
1128
+ [value]="value()"
1129
+ (input)="handleInput($event)"
1130
+ [placeholder]="placeholder()"
1131
+ [class.invalid]="props()['isValid']?.value() === false"
1132
+ />
1133
+ @for (message of props()['validationErrors']?.value(); track message) {
1134
+ <div class="a2ui-error-message">{{ message }}</div>
1135
+ }
1136
+ </div>
1137
+ `, isInline: true, styles: [".a2ui-text-field-container{display:flex;flex-direction:column;gap:var(--a2ui-spacing-xs, 4px);margin:var(--a2ui-spacing-xs, 4px)}label{font-size:var(--a2ui-textfield-label-font-size, var(--a2ui-label-font-size, var(--a2ui-font-size-s, 14px)));font-weight:var(--a2ui-textfield-label-font-weight, bold);color:var(--a2ui-text-color-text, var(--a2ui-color-on-background, #333))}input{padding:var(--a2ui-textfield-padding, 8px);border:var(--a2ui-textfield-border, 1px solid var(--a2ui-color-border, #ccc));border-radius:var(--a2ui-textfield-border-radius, 4px);background-color:var(--a2ui-color-input, #fff);color:var(--a2ui-color-on-input, #333)}input:focus{border-color:var(--a2ui-textfield-color-border-focus, var(--a2ui-color-primary, #17e));outline:none}input.invalid{border-color:var(--a2ui-textfield-color-error, var(--a2ui-color-error, red))}.a2ui-error-message{color:var(--a2ui-textfield-color-error, var(--a2ui-color-error, red));font-size:var(--a2ui-font-size-xs, 12px)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1138
+ }
1139
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: TextFieldComponent, decorators: [{
1140
+ type: Component,
1141
+ args: [{ selector: 'a2ui-v09-text-field', standalone: true, imports: [], template: `
1142
+ <div class="a2ui-text-field-container">
1143
+ @if (label()) {
1144
+ <label>{{ label() }}</label>
1145
+ }
1146
+ <input
1147
+ [type]="inputType()"
1148
+ [value]="value()"
1149
+ (input)="handleInput($event)"
1150
+ [placeholder]="placeholder()"
1151
+ [class.invalid]="props()['isValid']?.value() === false"
1152
+ />
1153
+ @for (message of props()['validationErrors']?.value(); track message) {
1154
+ <div class="a2ui-error-message">{{ message }}</div>
1155
+ }
1156
+ </div>
1157
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".a2ui-text-field-container{display:flex;flex-direction:column;gap:var(--a2ui-spacing-xs, 4px);margin:var(--a2ui-spacing-xs, 4px)}label{font-size:var(--a2ui-textfield-label-font-size, var(--a2ui-label-font-size, var(--a2ui-font-size-s, 14px)));font-weight:var(--a2ui-textfield-label-font-weight, bold);color:var(--a2ui-text-color-text, var(--a2ui-color-on-background, #333))}input{padding:var(--a2ui-textfield-padding, 8px);border:var(--a2ui-textfield-border, 1px solid var(--a2ui-color-border, #ccc));border-radius:var(--a2ui-textfield-border-radius, 4px);background-color:var(--a2ui-color-input, #fff);color:var(--a2ui-color-on-input, #333)}input:focus{border-color:var(--a2ui-textfield-color-border-focus, var(--a2ui-color-primary, #17e));outline:none}input.invalid{border-color:var(--a2ui-textfield-color-error, var(--a2ui-color-error, red))}.a2ui-error-message{color:var(--a2ui-textfield-color-error, var(--a2ui-color-error, red));font-size:var(--a2ui-font-size-xs, 12px)}\n"] }]
1158
+ }], propDecorators: { props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], surfaceId: [{ type: i0.Input, args: [{ isSignal: true, alias: "surfaceId", required: true }] }], componentId: [{ type: i0.Input, args: [{ isSignal: true, alias: "componentId", required: false }] }], dataContextPath: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataContextPath", required: false }] }] } });
1159
+
1160
+ /**
1161
+ * Copyright 2026 Google LLC
1162
+ *
1163
+ * Licensed under the Apache License, Version 2.0 (the "License");
1164
+ * you may not use this file except in compliance with the License.
1165
+ * You may obtain a copy of the License at
1166
+ *
1167
+ * http://www.apache.org/licenses/LICENSE-2.0
1168
+ *
1169
+ * Unless required by applicable law or agreed to in writing, software
1170
+ * distributed under the License is distributed on an "AS IS" BASIS,
1171
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1172
+ * See the License for the specific language governing permissions and
1173
+ * limitations under the License.
1174
+ */
1175
+ /**
1176
+ * Angular implementation of the A2UI Image component (v0.9).
1177
+ *
1178
+ * Renders an image with configurable fit and shape variants.
1179
+ *
1180
+ * Supported CSS variables:
1181
+ * - `--a2ui-image-border-radius`: Controls the rounded corners.
1182
+ * - `--a2ui-image-icon-size`: Size of the icon variant.
1183
+ * - `--a2ui-image-avatar-size`: Size of the avatar variant.
1184
+ * - `--a2ui-image-small-feature-size`: Max-width of smallFeature variant.
1185
+ * - `--a2ui-image-large-feature-size`: Max-height of largeFeature variant.
1186
+ * - `--a2ui-image-header-size`: Height of header variant.
1187
+ */
1188
+ class ImageComponent extends BasicCatalogComponent {
1189
+ /**
1190
+ * Reactive properties resolved from the A2UI {@link ComponentModel}.
1191
+ *
1192
+ * Expected properties:
1193
+ * - `url`: The absolute URL of the image.
1194
+ * - `description`: Accessibility text for the image.
1195
+ * - `fit`: Object-fit mode ('cover', 'contain', 'fill', 'none', 'scale-down').
1196
+ * - `variant`: Style variant ('default', 'circle', 'rounded', 'icon', 'avatar', 'smallFeature', 'mediumFeature', 'largeFeature', 'header').
1197
+ */
1198
+ props = input({}, ...(ngDevMode ? [{ debugName: "props" }] : /* istanbul ignore next */ []));
1199
+ surfaceId = input.required(...(ngDevMode ? [{ debugName: "surfaceId" }] : /* istanbul ignore next */ []));
1200
+ componentId = input(...(ngDevMode ? [undefined, { debugName: "componentId" }] : /* istanbul ignore next */ []));
1201
+ dataContextPath = input('/', ...(ngDevMode ? [{ debugName: "dataContextPath" }] : /* istanbul ignore next */ []));
1202
+ url = computed$1(() => this.props()['url']?.value(), ...(ngDevMode ? [{ debugName: "url" }] : /* istanbul ignore next */ []));
1203
+ description = computed$1(() => this.props()['description']?.value() || '', ...(ngDevMode ? [{ debugName: "description" }] : /* istanbul ignore next */ []));
1204
+ fit = computed$1(() => this.props()['fit']?.value() || 'cover', ...(ngDevMode ? [{ debugName: "fit" }] : /* istanbul ignore next */ []));
1205
+ variant = computed$1(() => this.props()['variant']?.value() || 'default', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
1206
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ImageComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
1207
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.5", type: ImageComponent, isStandalone: true, selector: "a2ui-v09-image", inputs: { props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null }, surfaceId: { classPropertyName: "surfaceId", publicName: "surfaceId", isSignal: true, isRequired: true, transformFunction: null }, componentId: { classPropertyName: "componentId", publicName: "componentId", isSignal: true, isRequired: false, transformFunction: null }, dataContextPath: { classPropertyName: "dataContextPath", publicName: "dataContextPath", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: `
1208
+ <img
1209
+ [src]="url()"
1210
+ [alt]="description()"
1211
+ [style.object-fit]="fit()"
1212
+ [class]="'a2ui-image ' + variant()"
1213
+ />
1214
+ `, isInline: true, styles: [".a2ui-image{display:block;max-width:100%;height:auto}.a2ui-image.circle{border-radius:50%;aspect-ratio:1 / 1}.a2ui-image.rounded{border-radius:var(--a2ui-image-border-radius, var(--a2ui-border-radius, 8px))}.a2ui-image.icon{width:var(--a2ui-image-icon-size, 24px);height:var(--a2ui-image-icon-size, 24px)}.a2ui-image.avatar{width:var(--a2ui-image-avatar-size, 40px);height:var(--a2ui-image-avatar-size, 40px);border-radius:50%}.a2ui-image.smallFeature{max-width:var(--a2ui-image-small-feature-size, 100px)}.a2ui-image.mediumFeature{max-width:300px;height:auto}.a2ui-image.largeFeature{width:100%;max-height:var(--a2ui-image-large-feature-size, 400px)}.a2ui-image.header{width:100%;height:var(--a2ui-image-header-size, 200px)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1215
+ }
1216
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ImageComponent, decorators: [{
1217
+ type: Component,
1218
+ args: [{ selector: 'a2ui-v09-image', standalone: true, imports: [], template: `
1219
+ <img
1220
+ [src]="url()"
1221
+ [alt]="description()"
1222
+ [style.object-fit]="fit()"
1223
+ [class]="'a2ui-image ' + variant()"
1224
+ />
1225
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".a2ui-image{display:block;max-width:100%;height:auto}.a2ui-image.circle{border-radius:50%;aspect-ratio:1 / 1}.a2ui-image.rounded{border-radius:var(--a2ui-image-border-radius, var(--a2ui-border-radius, 8px))}.a2ui-image.icon{width:var(--a2ui-image-icon-size, 24px);height:var(--a2ui-image-icon-size, 24px)}.a2ui-image.avatar{width:var(--a2ui-image-avatar-size, 40px);height:var(--a2ui-image-avatar-size, 40px);border-radius:50%}.a2ui-image.smallFeature{max-width:var(--a2ui-image-small-feature-size, 100px)}.a2ui-image.mediumFeature{max-width:300px;height:auto}.a2ui-image.largeFeature{width:100%;max-height:var(--a2ui-image-large-feature-size, 400px)}.a2ui-image.header{width:100%;height:var(--a2ui-image-header-size, 200px)}\n"] }]
1226
+ }], propDecorators: { props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], surfaceId: [{ type: i0.Input, args: [{ isSignal: true, alias: "surfaceId", required: true }] }], componentId: [{ type: i0.Input, args: [{ isSignal: true, alias: "componentId", required: false }] }], dataContextPath: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataContextPath", required: false }] }] } });
1227
+
1228
+ /**
1229
+ * Copyright 2026 Google LLC
1230
+ *
1231
+ * Licensed under the Apache License, Version 2.0 (the "License");
1232
+ * you may not use this file except in compliance with the License.
1233
+ * You may obtain a copy of the License at
1234
+ *
1235
+ * http://www.apache.org/licenses/LICENSE-2.0
1236
+ *
1237
+ * Unless required by applicable law or agreed to in writing, software
1238
+ * distributed under the License is distributed on an "AS IS" BASIS,
1239
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1240
+ * See the License for the specific language governing permissions and
1241
+ * limitations under the License.
1242
+ */
1243
+ /**
1244
+ * Angular implementation of the A2UI Icon component (v0.9).
1245
+ *
1246
+ * Supports both Material Icons (by name) and custom SVG icons (by path).
1247
+ *
1248
+ * Supported CSS variables:
1249
+ * - `--a2ui-icon-size`: Controls the width, height, and font size of the icon.
1250
+ * - `--a2ui-icon-font-family`: Controls the font family for icon fonts.
1251
+ * - `--a2ui-icon-color`: Controls the color of the icon.
1252
+ * - `--a2ui-icon-font-variation-settings`: Controls font variation settings (e.g. FILL).
1253
+ */
1254
+ class IconComponent extends BasicCatalogComponent {
1255
+ /**
1256
+ * Reactive properties resolved from the A2UI {@link ComponentModel}.
1257
+ *
1258
+ * Expected properties:
1259
+ * - `name`: The name of the icon (e.g., 'home', 'settings') OR an object
1260
+ * with a `path` property for SVG icons.
1261
+ * - `color`: The CSS color to apply to the icon.
1262
+ */
1263
+ props = input({}, ...(ngDevMode ? [{ debugName: "props" }] : /* istanbul ignore next */ []));
1264
+ surfaceId = input.required(...(ngDevMode ? [{ debugName: "surfaceId" }] : /* istanbul ignore next */ []));
1265
+ componentId = input(...(ngDevMode ? [undefined, { debugName: "componentId" }] : /* istanbul ignore next */ []));
1266
+ dataContextPath = input('/', ...(ngDevMode ? [{ debugName: "dataContextPath" }] : /* istanbul ignore next */ []));
1267
+ color = computed$1(() => this.props()['color']?.value(), ...(ngDevMode ? [{ debugName: "color" }] : /* istanbul ignore next */ []));
1268
+ iconNameRaw = computed$1(() => this.props()['name']?.value(), ...(ngDevMode ? [{ debugName: "iconNameRaw" }] : /* istanbul ignore next */ []));
1269
+ isPath = computed$1(() => {
1270
+ const name = this.iconNameRaw();
1271
+ return typeof name === 'object' && name !== null && 'path' in name;
1272
+ }, ...(ngDevMode ? [{ debugName: "isPath" }] : /* istanbul ignore next */ []));
1273
+ path = computed$1(() => {
1274
+ const name = this.iconNameRaw();
1275
+ return name?.path || '';
1276
+ }, ...(ngDevMode ? [{ debugName: "path" }] : /* istanbul ignore next */ []));
1277
+ iconName = computed$1(() => {
1278
+ const name = this.iconNameRaw();
1279
+ if (typeof name !== 'string')
1280
+ return '';
1281
+ // Convert camelCase to snake_case for Material Icons
1282
+ return name.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);
1283
+ }, ...(ngDevMode ? [{ debugName: "iconName" }] : /* istanbul ignore next */ []));
1284
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: IconComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
1285
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: IconComponent, isStandalone: true, selector: "a2ui-v09-icon", inputs: { props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null }, surfaceId: { classPropertyName: "surfaceId", publicName: "surfaceId", isSignal: true, isRequired: true, transformFunction: null }, componentId: { classPropertyName: "componentId", publicName: "componentId", isSignal: true, isRequired: false, transformFunction: null }, dataContextPath: { classPropertyName: "dataContextPath", publicName: "dataContextPath", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: `
1286
+ @if (isPath()) {
1287
+ <svg class="a2ui-icon svg" viewBox="0 0 24 24" [style.fill]="color() || 'currentColor'">
1288
+ <path [attr.d]="path()"></path>
1289
+ </svg>
1290
+ } @else {
1291
+ <i class="material-icons a2ui-icon" [style.color]="color()">
1292
+ {{ iconName() }}
1293
+ </i>
1294
+ }
1295
+ `, isInline: true, styles: [".a2ui-icon{display:inline-block;width:var(--a2ui-icon-size, 24px);height:var(--a2ui-icon-size, 24px);font-size:var(--a2ui-icon-size, 24px);font-family:var(--a2ui-icon-font-family, \"Material Icons\");color:var(--a2ui-icon-color, var(--a2ui-text-color-text, var(--a2ui-color-on-background, #333)));font-variation-settings:var(--a2ui-icon-font-variation-settings, \"FILL\" 1);line-height:1;text-transform:none;letter-spacing:normal;word-wrap:normal;white-space:nowrap;direction:ltr;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;-moz-osx-font-smoothing:grayscale;font-feature-settings:\"liga\";vertical-align:middle}.a2ui-icon.svg{fill:currentColor}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1296
+ }
1297
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: IconComponent, decorators: [{
1298
+ type: Component,
1299
+ args: [{ selector: 'a2ui-v09-icon', standalone: true, imports: [], template: `
1300
+ @if (isPath()) {
1301
+ <svg class="a2ui-icon svg" viewBox="0 0 24 24" [style.fill]="color() || 'currentColor'">
1302
+ <path [attr.d]="path()"></path>
1303
+ </svg>
1304
+ } @else {
1305
+ <i class="material-icons a2ui-icon" [style.color]="color()">
1306
+ {{ iconName() }}
1307
+ </i>
1308
+ }
1309
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".a2ui-icon{display:inline-block;width:var(--a2ui-icon-size, 24px);height:var(--a2ui-icon-size, 24px);font-size:var(--a2ui-icon-size, 24px);font-family:var(--a2ui-icon-font-family, \"Material Icons\");color:var(--a2ui-icon-color, var(--a2ui-text-color-text, var(--a2ui-color-on-background, #333)));font-variation-settings:var(--a2ui-icon-font-variation-settings, \"FILL\" 1);line-height:1;text-transform:none;letter-spacing:normal;word-wrap:normal;white-space:nowrap;direction:ltr;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;-moz-osx-font-smoothing:grayscale;font-feature-settings:\"liga\";vertical-align:middle}.a2ui-icon.svg{fill:currentColor}\n"] }]
1310
+ }], propDecorators: { props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], surfaceId: [{ type: i0.Input, args: [{ isSignal: true, alias: "surfaceId", required: true }] }], componentId: [{ type: i0.Input, args: [{ isSignal: true, alias: "componentId", required: false }] }], dataContextPath: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataContextPath", required: false }] }] } });
1311
+
1312
+ /**
1313
+ * Copyright 2026 Google LLC
1314
+ *
1315
+ * Licensed under the Apache License, Version 2.0 (the "License");
1316
+ * you may not use this file except in compliance with the License.
1317
+ * You may obtain a copy of the License at
1318
+ *
1319
+ * http://www.apache.org/licenses/LICENSE-2.0
1320
+ *
1321
+ * Unless required by applicable law or agreed to in writing, software
1322
+ * distributed under the License is distributed on an "AS IS" BASIS,
1323
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1324
+ * See the License for the specific language governing permissions and
1325
+ * limitations under the License.
1326
+ */
1327
+ /**
1328
+ * Angular implementation of the A2UI Video component (v0.9).
1329
+ *
1330
+ * Renders a video player with standard controls and an optional poster image.
1331
+ *
1332
+ * Supported CSS variables:
1333
+ * - `--a2ui-video-border-radius`: Controls the border radius of the video element.
1334
+ */
1335
+ class VideoComponent extends BasicCatalogComponent {
1336
+ /**
1337
+ * Reactive properties resolved from the A2UI {@link ComponentModel}.
1338
+ *
1339
+ * Expected properties:
1340
+ * - `url`: The absolute URL of the video file.
1341
+ * - `posterUrl`: The URL of an image to show before the video starts.
1342
+ */
1343
+ props = input({}, ...(ngDevMode ? [{ debugName: "props" }] : /* istanbul ignore next */ []));
1344
+ surfaceId = input.required(...(ngDevMode ? [{ debugName: "surfaceId" }] : /* istanbul ignore next */ []));
1345
+ componentId = input(...(ngDevMode ? [undefined, { debugName: "componentId" }] : /* istanbul ignore next */ []));
1346
+ dataContextPath = input('/', ...(ngDevMode ? [{ debugName: "dataContextPath" }] : /* istanbul ignore next */ []));
1347
+ url = computed$1(() => this.props()['url']?.value(), ...(ngDevMode ? [{ debugName: "url" }] : /* istanbul ignore next */ []));
1348
+ posterUrl = computed$1(() => this.props()['posterUrl']?.value(), ...(ngDevMode ? [{ debugName: "posterUrl" }] : /* istanbul ignore next */ []));
1349
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: VideoComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
1350
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.5", type: VideoComponent, isStandalone: true, selector: "a2ui-v09-video", inputs: { props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null }, surfaceId: { classPropertyName: "surfaceId", publicName: "surfaceId", isSignal: true, isRequired: true, transformFunction: null }, componentId: { classPropertyName: "componentId", publicName: "componentId", isSignal: true, isRequired: false, transformFunction: null }, dataContextPath: { classPropertyName: "dataContextPath", publicName: "dataContextPath", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: `
1351
+ <div class="a2ui-video-container">
1352
+ <video
1353
+ [attr.src]="url() || null"
1354
+ controls
1355
+ [attr.poster]="posterUrl() || null"
1356
+ class="a2ui-video"
1357
+ >
1358
+ Your browser does not support the video tag.
1359
+ </video>
1360
+ </div>
1361
+ `, isInline: true, styles: [".a2ui-video-container{width:100%;max-width:100%}.a2ui-video{width:100%;height:auto;display:block;border-radius:var(--a2ui-video-border-radius, 0)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1362
+ }
1363
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: VideoComponent, decorators: [{
1364
+ type: Component,
1365
+ args: [{ selector: 'a2ui-v09-video', standalone: true, imports: [], template: `
1366
+ <div class="a2ui-video-container">
1367
+ <video
1368
+ [attr.src]="url() || null"
1369
+ controls
1370
+ [attr.poster]="posterUrl() || null"
1371
+ class="a2ui-video"
1372
+ >
1373
+ Your browser does not support the video tag.
1374
+ </video>
1375
+ </div>
1376
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".a2ui-video-container{width:100%;max-width:100%}.a2ui-video{width:100%;height:auto;display:block;border-radius:var(--a2ui-video-border-radius, 0)}\n"] }]
1377
+ }], propDecorators: { props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], surfaceId: [{ type: i0.Input, args: [{ isSignal: true, alias: "surfaceId", required: true }] }], componentId: [{ type: i0.Input, args: [{ isSignal: true, alias: "componentId", required: false }] }], dataContextPath: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataContextPath", required: false }] }] } });
1378
+
1379
+ /**
1380
+ * Copyright 2026 Google LLC
1381
+ *
1382
+ * Licensed under the Apache License, Version 2.0 (the "License");
1383
+ * you may not use this file except in compliance with the License.
1384
+ * You may obtain a copy of the License at
1385
+ *
1386
+ * http://www.apache.org/licenses/LICENSE-2.0
1387
+ *
1388
+ * Unless required by applicable law or agreed to in writing, software
1389
+ * distributed under the License is distributed on an "AS IS" BASIS,
1390
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1391
+ * See the License for the specific language governing permissions and
1392
+ * limitations under the License.
1393
+ */
1394
+ /**
1395
+ * Angular implementation of the A2UI AudioPlayer component (v0.9).
1396
+ *
1397
+ * Renders an audio player with standard controls and an optional description.
1398
+ *
1399
+ * Supported CSS variables:
1400
+ * - `--a2ui-audioplayer-background`: Controls the background of the player. Defaults to `transparent`.
1401
+ * - `--a2ui-audioplayer-border-radius`: Controls the border radius. Defaults to `0`.
1402
+ * - `--a2ui-audioplayer-padding`: Controls the padding. Defaults to `0`.
1403
+ */
1404
+ class AudioPlayerComponent extends BasicCatalogComponent {
1405
+ /**
1406
+ * Reactive properties resolved from the A2UI {@link ComponentModel}.
1407
+ *
1408
+ * Expected properties:
1409
+ * - `url`: The absolute URL of the audio file.
1410
+ * - `description`: Optional text to display above the player.
1411
+ */
1412
+ props = input({}, ...(ngDevMode ? [{ debugName: "props" }] : /* istanbul ignore next */ []));
1413
+ surfaceId = input(...(ngDevMode ? [undefined, { debugName: "surfaceId" }] : /* istanbul ignore next */ []));
1414
+ componentId = input(...(ngDevMode ? [undefined, { debugName: "componentId" }] : /* istanbul ignore next */ []));
1415
+ dataContextPath = input(...(ngDevMode ? [undefined, { debugName: "dataContextPath" }] : /* istanbul ignore next */ []));
1416
+ description = computed$1(() => this.props()['description']?.value(), ...(ngDevMode ? [{ debugName: "description" }] : /* istanbul ignore next */ []));
1417
+ url = computed$1(() => this.props()['url']?.value(), ...(ngDevMode ? [{ debugName: "url" }] : /* istanbul ignore next */ []));
1418
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: AudioPlayerComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
1419
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: AudioPlayerComponent, isStandalone: true, selector: "a2ui-v09-audio-player", inputs: { props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null }, surfaceId: { classPropertyName: "surfaceId", publicName: "surfaceId", isSignal: true, isRequired: false, transformFunction: null }, componentId: { classPropertyName: "componentId", publicName: "componentId", isSignal: true, isRequired: false, transformFunction: null }, dataContextPath: { classPropertyName: "dataContextPath", publicName: "dataContextPath", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: `
1420
+ <div class="a2ui-audio-player">
1421
+ @if (description()) {
1422
+ <div class="a2ui-audio-description">
1423
+ {{ description() }}
1424
+ </div>
1425
+ }
1426
+ <audio [attr.src]="url() || null" controls class="a2ui-audio">
1427
+ Your browser does not support the audio tag.
1428
+ </audio>
1429
+ </div>
1430
+ `, isInline: true, styles: [".a2ui-audio-player{display:flex;flex-direction:column;gap:var(--a2ui-spacing-xs, .25rem);background:var(--a2ui-audioplayer-background, transparent);border-radius:var(--a2ui-audioplayer-border-radius, 0);padding:var(--a2ui-audioplayer-padding, 0);width:100%}.a2ui-audio-description{font-size:var(--a2ui-font-size-s, .875rem);color:var(--a2ui-text-caption-color, light-dark(#666, #aaa))}.a2ui-audio{width:100%}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1431
+ }
1432
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: AudioPlayerComponent, decorators: [{
1433
+ type: Component,
1434
+ args: [{ selector: 'a2ui-v09-audio-player', standalone: true, imports: [], template: `
1435
+ <div class="a2ui-audio-player">
1436
+ @if (description()) {
1437
+ <div class="a2ui-audio-description">
1438
+ {{ description() }}
1439
+ </div>
1440
+ }
1441
+ <audio [attr.src]="url() || null" controls class="a2ui-audio">
1442
+ Your browser does not support the audio tag.
1443
+ </audio>
1444
+ </div>
1445
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".a2ui-audio-player{display:flex;flex-direction:column;gap:var(--a2ui-spacing-xs, .25rem);background:var(--a2ui-audioplayer-background, transparent);border-radius:var(--a2ui-audioplayer-border-radius, 0);padding:var(--a2ui-audioplayer-padding, 0);width:100%}.a2ui-audio-description{font-size:var(--a2ui-font-size-s, .875rem);color:var(--a2ui-text-caption-color, light-dark(#666, #aaa))}.a2ui-audio{width:100%}\n"] }]
1446
+ }], propDecorators: { props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], surfaceId: [{ type: i0.Input, args: [{ isSignal: true, alias: "surfaceId", required: false }] }], componentId: [{ type: i0.Input, args: [{ isSignal: true, alias: "componentId", required: false }] }], dataContextPath: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataContextPath", required: false }] }] } });
1447
+
1448
+ /**
1449
+ * Copyright 2026 Google LLC
1450
+ *
1451
+ * Licensed under the Apache License, Version 2.0 (the "License");
1452
+ * you may not use this file except in compliance with the License.
1453
+ * You may obtain a copy of the License at
1454
+ *
1455
+ * http://www.apache.org/licenses/LICENSE-2.0
1456
+ *
1457
+ * Unless required by applicable law or agreed to in writing, software
1458
+ * distributed under the License is distributed on an "AS IS" BASIS,
1459
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1460
+ * See the License for the specific language governing permissions and
1461
+ * limitations under the License.
1462
+ */
1463
+ /**
1464
+ * Angular implementation of the A2UI List component (v0.9).
1465
+ *
1466
+ * Renders a list of child components with support for ordered, unordered,
1467
+ * and unstyled layouts in both vertical and horizontal orientations.
1468
+ *
1469
+ * Supported CSS variables:
1470
+ * - `--a2ui-list-gap`: Controls the gap between items.
1471
+ * - `--a2ui-list-padding`: Controls the padding (applied to padding-inline-start).
1472
+ */
1473
+ class ListComponent extends BasicCatalogComponent {
1474
+ /**
1475
+ * Reactive properties resolved from the A2UI {@link ComponentModel}.
1476
+ *
1477
+ * Expected properties:
1478
+ * - `children`: A list of component IDs to render as list items.
1479
+ * - `listStyle`: The type of list ('ordered', 'unordered', 'none').
1480
+ * - `orientation`: The layout direction ('vertical', 'horizontal').
1481
+ */
1482
+ props = input({}, ...(ngDevMode ? [{ debugName: "props" }] : /* istanbul ignore next */ []));
1483
+ surfaceId = input.required(...(ngDevMode ? [{ debugName: "surfaceId" }] : /* istanbul ignore next */ []));
1484
+ componentId = input(...(ngDevMode ? [undefined, { debugName: "componentId" }] : /* istanbul ignore next */ []));
1485
+ dataContextPath = input('/', ...(ngDevMode ? [{ debugName: "dataContextPath" }] : /* istanbul ignore next */ []));
1486
+ listStyle = computed$1(() => this.props()['listStyle']?.value(), ...(ngDevMode ? [{ debugName: "listStyle" }] : /* istanbul ignore next */ []));
1487
+ orientation = computed$1(() => this.props()['orientation']?.value() || 'vertical', ...(ngDevMode ? [{ debugName: "orientation" }] : /* istanbul ignore next */ []));
1488
+ children = computed$1(() => {
1489
+ const raw = this.props()['children']?.value();
1490
+ return Array.isArray(raw) ? raw : [];
1491
+ }, ...(ngDevMode ? [{ debugName: "children" }] : /* istanbul ignore next */ []));
1492
+ listTag = computed$1(() => {
1493
+ const style = this.listStyle();
1494
+ if (style === 'ordered')
1495
+ return 'ol';
1496
+ if (style === 'unordered')
1497
+ return 'ul';
1498
+ return 'div';
1499
+ }, ...(ngDevMode ? [{ debugName: "listTag" }] : /* istanbul ignore next */ []));
1500
+ styleType = computed$1(() => {
1501
+ const style = this.listStyle();
1502
+ if (style === 'none')
1503
+ return 'none';
1504
+ return '';
1505
+ }, ...(ngDevMode ? [{ debugName: "styleType" }] : /* istanbul ignore next */ []));
1506
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ListComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
1507
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: ListComponent, isStandalone: true, selector: "a2ui-v09-list", inputs: { props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null }, surfaceId: { classPropertyName: "surfaceId", publicName: "surfaceId", isSignal: true, isRequired: true, transformFunction: null }, componentId: { classPropertyName: "componentId", publicName: "componentId", isSignal: true, isRequired: false, transformFunction: null }, dataContextPath: { classPropertyName: "dataContextPath", publicName: "dataContextPath", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: `
1508
+ @switch (listTag()) {
1509
+ @case ('ol') {
1510
+ <ol [class]="'a2ui-list ' + orientation()" [style.list-style-type]="styleType()">
1511
+ @for (child of children(); track child.id) {
1512
+ <li>
1513
+ <a2ui-v09-component-host
1514
+ [componentKey]="child"
1515
+ [surfaceId]="surfaceId()"
1516
+ >
1517
+ </a2ui-v09-component-host>
1518
+ </li>
1519
+ }
1520
+ </ol>
1521
+ }
1522
+ @case ('ul') {
1523
+ <ul [class]="'a2ui-list ' + orientation()" [style.list-style-type]="styleType()">
1524
+ @for (child of children(); track child.id) {
1525
+ <li>
1526
+ <a2ui-v09-component-host
1527
+ [componentKey]="child"
1528
+ [surfaceId]="surfaceId()"
1529
+ >
1530
+ </a2ui-v09-component-host>
1531
+ </li>
1532
+ }
1533
+ </ul>
1534
+ }
1535
+ @default {
1536
+ <div [class]="'a2ui-list ' + orientation()" style="list-style-type: none;">
1537
+ @for (child of children(); track child.id) {
1538
+ <div class="a2ui-list-item-none">
1539
+ <a2ui-v09-component-host
1540
+ [componentKey]="child"
1541
+ [surfaceId]="surfaceId()"
1542
+ >
1543
+ </a2ui-v09-component-host>
1544
+ </div>
1545
+ }
1546
+ </div>
1547
+ }
1548
+ }
1549
+ `, isInline: true, styles: [".a2ui-list{display:flex;padding-inline-start:var(--a2ui-list-padding, var(--a2ui-spacing-l, 24px));margin:0}.a2ui-list.vertical{flex-direction:column;gap:var(--a2ui-list-gap, var(--a2ui-spacing-s, 8px))}.a2ui-list.horizontal{flex-direction:row;gap:var(--a2ui-list-gap, var(--a2ui-spacing-m, 16px));list-style-position:inside}.a2ui-list-item-none{display:block}.horizontal .a2ui-list-item-none{display:inline-block}\n"], dependencies: [{ kind: "component", type: ComponentHostComponent, selector: "a2ui-v09-component-host", inputs: ["componentKey", "surfaceId"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1550
+ }
1551
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ListComponent, decorators: [{
1552
+ type: Component,
1553
+ args: [{ selector: 'a2ui-v09-list', standalone: true, imports: [ComponentHostComponent], template: `
1554
+ @switch (listTag()) {
1555
+ @case ('ol') {
1556
+ <ol [class]="'a2ui-list ' + orientation()" [style.list-style-type]="styleType()">
1557
+ @for (child of children(); track child.id) {
1558
+ <li>
1559
+ <a2ui-v09-component-host
1560
+ [componentKey]="child"
1561
+ [surfaceId]="surfaceId()"
1562
+ >
1563
+ </a2ui-v09-component-host>
1564
+ </li>
1565
+ }
1566
+ </ol>
1567
+ }
1568
+ @case ('ul') {
1569
+ <ul [class]="'a2ui-list ' + orientation()" [style.list-style-type]="styleType()">
1570
+ @for (child of children(); track child.id) {
1571
+ <li>
1572
+ <a2ui-v09-component-host
1573
+ [componentKey]="child"
1574
+ [surfaceId]="surfaceId()"
1575
+ >
1576
+ </a2ui-v09-component-host>
1577
+ </li>
1578
+ }
1579
+ </ul>
1580
+ }
1581
+ @default {
1582
+ <div [class]="'a2ui-list ' + orientation()" style="list-style-type: none;">
1583
+ @for (child of children(); track child.id) {
1584
+ <div class="a2ui-list-item-none">
1585
+ <a2ui-v09-component-host
1586
+ [componentKey]="child"
1587
+ [surfaceId]="surfaceId()"
1588
+ >
1589
+ </a2ui-v09-component-host>
1590
+ </div>
1591
+ }
1592
+ </div>
1593
+ }
1594
+ }
1595
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".a2ui-list{display:flex;padding-inline-start:var(--a2ui-list-padding, var(--a2ui-spacing-l, 24px));margin:0}.a2ui-list.vertical{flex-direction:column;gap:var(--a2ui-list-gap, var(--a2ui-spacing-s, 8px))}.a2ui-list.horizontal{flex-direction:row;gap:var(--a2ui-list-gap, var(--a2ui-spacing-m, 16px));list-style-position:inside}.a2ui-list-item-none{display:block}.horizontal .a2ui-list-item-none{display:inline-block}\n"] }]
1596
+ }], propDecorators: { props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], surfaceId: [{ type: i0.Input, args: [{ isSignal: true, alias: "surfaceId", required: true }] }], componentId: [{ type: i0.Input, args: [{ isSignal: true, alias: "componentId", required: false }] }], dataContextPath: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataContextPath", required: false }] }] } });
1597
+
1598
+ /**
1599
+ * Copyright 2026 Google LLC
1600
+ *
1601
+ * Licensed under the Apache License, Version 2.0 (the "License");
1602
+ * you may not use this file except in compliance with the License.
1603
+ * You may obtain a copy of the License at
1604
+ *
1605
+ * http://www.apache.org/licenses/LICENSE-2.0
1606
+ *
1607
+ * Unless required by applicable law or agreed to in writing, software
1608
+ * distributed under the License is distributed on an "AS IS" BASIS,
1609
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1610
+ * See the License for the specific language governing permissions and
1611
+ * limitations under the License.
1612
+ */
1613
+ /**
1614
+ * Angular implementation of the A2UI Card component (v0.9).
1615
+ *
1616
+ * Renders a container with a shadow and rounded corners for grouping related content.
1617
+ *
1618
+ * Supported CSS variables:
1619
+ * - `--a2ui-card-padding`: Controls the padding.
1620
+ * - `--a2ui-card-border-radius`: Controls the border radius.
1621
+ * - `--a2ui-card-box-shadow`: Controls the box shadow.
1622
+ * - `--a2ui-card-background`: Controls the background color.
1623
+ * - `--a2ui-card-border`: Controls the border.
1624
+ * - `--a2ui-card-margin`: Controls the margin.
1625
+ */
1626
+ class CardComponent extends BasicCatalogComponent {
1627
+ /**
1628
+ * Reactive properties resolved from the A2UI {@link ComponentModel}.
1629
+ *
1630
+ * Expected properties:
1631
+ * - `child`: The component ID to render inside the card.
1632
+ */
1633
+ props = input({}, ...(ngDevMode ? [{ debugName: "props" }] : /* istanbul ignore next */ []));
1634
+ surfaceId = input.required(...(ngDevMode ? [{ debugName: "surfaceId" }] : /* istanbul ignore next */ []));
1635
+ componentId = input(...(ngDevMode ? [undefined, { debugName: "componentId" }] : /* istanbul ignore next */ []));
1636
+ dataContextPath = input('/', ...(ngDevMode ? [{ debugName: "dataContextPath" }] : /* istanbul ignore next */ []));
1637
+ child = computed$1(() => this.props()['child']?.value(), ...(ngDevMode ? [{ debugName: "child" }] : /* istanbul ignore next */ []));
1638
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: CardComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
1639
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: CardComponent, isStandalone: true, selector: "a2ui-v09-card", inputs: { props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null }, surfaceId: { classPropertyName: "surfaceId", publicName: "surfaceId", isSignal: true, isRequired: true, transformFunction: null }, componentId: { classPropertyName: "componentId", publicName: "componentId", isSignal: true, isRequired: false, transformFunction: null }, dataContextPath: { classPropertyName: "dataContextPath", publicName: "dataContextPath", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: `
1640
+ <div class="a2ui-card">
1641
+ @if (child()) {
1642
+ <a2ui-v09-component-host
1643
+ [componentKey]="child()!"
1644
+ [surfaceId]="surfaceId()"
1645
+ >
1646
+ </a2ui-v09-component-host>
1647
+ }
1648
+ </div>
1649
+ `, isInline: true, styles: [".a2ui-card{padding:var(--a2ui-card-padding, var(--a2ui-spacing-m, 16px));border-radius:var(--a2ui-card-border-radius, var(--a2ui-border-radius, 8px));box-shadow:var(--a2ui-card-box-shadow, 0 2px 4px rgba(0,0,0,.1));background-color:var(--a2ui-card-background, var(--a2ui-color-surface, #fff));border:var(--a2ui-card-border, var(--a2ui-border-width, 1px) solid var(--a2ui-color-border, #ccc));margin:var(--a2ui-card-margin, var(--a2ui-spacing-m, 16px))}\n"], dependencies: [{ kind: "component", type: ComponentHostComponent, selector: "a2ui-v09-component-host", inputs: ["componentKey", "surfaceId"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1650
+ }
1651
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: CardComponent, decorators: [{
1652
+ type: Component,
1653
+ args: [{ selector: 'a2ui-v09-card', standalone: true, imports: [ComponentHostComponent], template: `
1654
+ <div class="a2ui-card">
1655
+ @if (child()) {
1656
+ <a2ui-v09-component-host
1657
+ [componentKey]="child()!"
1658
+ [surfaceId]="surfaceId()"
1659
+ >
1660
+ </a2ui-v09-component-host>
1661
+ }
1662
+ </div>
1663
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".a2ui-card{padding:var(--a2ui-card-padding, var(--a2ui-spacing-m, 16px));border-radius:var(--a2ui-card-border-radius, var(--a2ui-border-radius, 8px));box-shadow:var(--a2ui-card-box-shadow, 0 2px 4px rgba(0,0,0,.1));background-color:var(--a2ui-card-background, var(--a2ui-color-surface, #fff));border:var(--a2ui-card-border, var(--a2ui-border-width, 1px) solid var(--a2ui-color-border, #ccc));margin:var(--a2ui-card-margin, var(--a2ui-spacing-m, 16px))}\n"] }]
1664
+ }], propDecorators: { props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], surfaceId: [{ type: i0.Input, args: [{ isSignal: true, alias: "surfaceId", required: true }] }], componentId: [{ type: i0.Input, args: [{ isSignal: true, alias: "componentId", required: false }] }], dataContextPath: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataContextPath", required: false }] }] } });
1665
+
1666
+ /**
1667
+ * Copyright 2026 Google LLC
1668
+ *
1669
+ * Licensed under the Apache License, Version 2.0 (the "License");
1670
+ * you may not use this file except in compliance with the License.
1671
+ * You may obtain a copy of the License at
1672
+ *
1673
+ * http://www.apache.org/licenses/LICENSE-2.0
1674
+ *
1675
+ * Unless required by applicable law or agreed to in writing, software
1676
+ * distributed under the License is distributed on an "AS IS" BASIS,
1677
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1678
+ * See the License for the specific language governing permissions and
1679
+ * limitations under the License.
1680
+ */
1681
+ /**
1682
+ * Angular implementation of the A2UI Tabs component (v0.9).
1683
+ *
1684
+ * Renders a set of tabs where each tab has a label and associated content.
1685
+ * Manages the active tab state internally.
1686
+ *
1687
+ * Supported CSS variables:
1688
+ * - `--a2ui-tabs-border`: Controls the border of the tab bar.
1689
+ * - `--a2ui-tabs-header-background`: Controls the background of tab buttons.
1690
+ * - `--a2ui-tabs-header-color`: Controls the text color of tab buttons.
1691
+ * - `--a2ui-tabs-header-background-active`: Controls the background of the active tab button.
1692
+ * - `--a2ui-tabs-header-color-active`: Controls the text color of the active tab button.
1693
+ * - `--a2ui-tabs-content-padding`: Controls the padding of the tab content.
1694
+ */
1695
+ class TabsComponent extends BasicCatalogComponent {
1696
+ /**
1697
+ * Reactive properties resolved from the A2UI {@link ComponentModel}.
1698
+ *
1699
+ * Expected properties:
1700
+ * - `tabs`: A list of tab objects, each containing a `label` and `content` ID.
1701
+ */
1702
+ props = input({}, ...(ngDevMode ? [{ debugName: "props" }] : /* istanbul ignore next */ []));
1703
+ surfaceId = input.required(...(ngDevMode ? [{ debugName: "surfaceId" }] : /* istanbul ignore next */ []));
1704
+ componentId = input(...(ngDevMode ? [undefined, { debugName: "componentId" }] : /* istanbul ignore next */ []));
1705
+ dataContextPath = input('/', ...(ngDevMode ? [{ debugName: "dataContextPath" }] : /* istanbul ignore next */ []));
1706
+ activeTabIndex = signal(0, ...(ngDevMode ? [{ debugName: "activeTabIndex" }] : /* istanbul ignore next */ []));
1707
+ tabs = computed$1(() => this.props()['tabs']?.value() || [], ...(ngDevMode ? [{ debugName: "tabs" }] : /* istanbul ignore next */ []));
1708
+ activeTab = computed$1(() => this.tabs()[this.activeTabIndex()], ...(ngDevMode ? [{ debugName: "activeTab" }] : /* istanbul ignore next */ []));
1709
+ normalizedActiveTabContent = computed$1(() => {
1710
+ const content = this.activeTab()?.content;
1711
+ if (!content)
1712
+ return null;
1713
+ if (typeof content === 'object' && content !== null && 'id' in content) {
1714
+ return content;
1715
+ }
1716
+ return { id: content, basePath: this.dataContextPath() };
1717
+ }, ...(ngDevMode ? [{ debugName: "normalizedActiveTabContent" }] : /* istanbul ignore next */ []));
1718
+ setActiveTab(index) {
1719
+ this.activeTabIndex.set(index);
1720
+ }
1721
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: TabsComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
1722
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: TabsComponent, isStandalone: true, selector: "a2ui-v09-tabs", inputs: { props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null }, surfaceId: { classPropertyName: "surfaceId", publicName: "surfaceId", isSignal: true, isRequired: true, transformFunction: null }, componentId: { classPropertyName: "componentId", publicName: "componentId", isSignal: true, isRequired: false, transformFunction: null }, dataContextPath: { classPropertyName: "dataContextPath", publicName: "dataContextPath", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: `
1723
+ <div class="a2ui-tabs">
1724
+ <div class="a2ui-tab-bar">
1725
+ @for (tab of tabs(); track tab; let i = $index) {
1726
+ <button
1727
+ class="a2ui-tab-button"
1728
+ [class.active]="activeTabIndex() === i"
1729
+ (click)="setActiveTab(i)"
1730
+ >
1731
+ {{ tab.label }}
1732
+ </button>
1733
+ }
1734
+ </div>
1735
+ @if (normalizedActiveTabContent()) {
1736
+ <div class="a2ui-tab-content">
1737
+ <a2ui-v09-component-host
1738
+ [componentKey]="normalizedActiveTabContent()!"
1739
+ [surfaceId]="surfaceId()"
1740
+ >
1741
+ </a2ui-v09-component-host>
1742
+ </div>
1743
+ }
1744
+ </div>
1745
+ `, isInline: true, styles: [".a2ui-tabs{display:flex;flex-direction:column;width:100%}.a2ui-tab-bar{display:flex;border-bottom:var(--a2ui-tabs-border, 2px solid var(--a2ui-color-border, #eee));gap:var(--a2ui-spacing-m, 16px)}.a2ui-tab-button{padding:var(--a2ui-spacing-s, 8px) var(--a2ui-spacing-m, 16px);border:none;background:var(--a2ui-tabs-header-background, transparent);cursor:pointer;font-weight:500;color:var(--a2ui-tabs-header-color, var(--a2ui-text-caption-color, #666));border-bottom:2px solid transparent;margin-bottom:-2px}.a2ui-tab-button.active{background:var(--a2ui-tabs-header-background-active, transparent);color:var(--a2ui-tabs-header-color-active, var(--a2ui-color-primary, #007bff));border-bottom:2px solid var(--a2ui-color-primary, #007bff)}.a2ui-tab-content{padding:var(--a2ui-tabs-content-padding, var(--a2ui-spacing-m, 16px) 0)}\n"], dependencies: [{ kind: "component", type: ComponentHostComponent, selector: "a2ui-v09-component-host", inputs: ["componentKey", "surfaceId"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1746
+ }
1747
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: TabsComponent, decorators: [{
1748
+ type: Component,
1749
+ args: [{ selector: 'a2ui-v09-tabs', standalone: true, imports: [ComponentHostComponent], template: `
1750
+ <div class="a2ui-tabs">
1751
+ <div class="a2ui-tab-bar">
1752
+ @for (tab of tabs(); track tab; let i = $index) {
1753
+ <button
1754
+ class="a2ui-tab-button"
1755
+ [class.active]="activeTabIndex() === i"
1756
+ (click)="setActiveTab(i)"
1757
+ >
1758
+ {{ tab.label }}
1759
+ </button>
1760
+ }
1761
+ </div>
1762
+ @if (normalizedActiveTabContent()) {
1763
+ <div class="a2ui-tab-content">
1764
+ <a2ui-v09-component-host
1765
+ [componentKey]="normalizedActiveTabContent()!"
1766
+ [surfaceId]="surfaceId()"
1767
+ >
1768
+ </a2ui-v09-component-host>
1769
+ </div>
1770
+ }
1771
+ </div>
1772
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".a2ui-tabs{display:flex;flex-direction:column;width:100%}.a2ui-tab-bar{display:flex;border-bottom:var(--a2ui-tabs-border, 2px solid var(--a2ui-color-border, #eee));gap:var(--a2ui-spacing-m, 16px)}.a2ui-tab-button{padding:var(--a2ui-spacing-s, 8px) var(--a2ui-spacing-m, 16px);border:none;background:var(--a2ui-tabs-header-background, transparent);cursor:pointer;font-weight:500;color:var(--a2ui-tabs-header-color, var(--a2ui-text-caption-color, #666));border-bottom:2px solid transparent;margin-bottom:-2px}.a2ui-tab-button.active{background:var(--a2ui-tabs-header-background-active, transparent);color:var(--a2ui-tabs-header-color-active, var(--a2ui-color-primary, #007bff));border-bottom:2px solid var(--a2ui-color-primary, #007bff)}.a2ui-tab-content{padding:var(--a2ui-tabs-content-padding, var(--a2ui-spacing-m, 16px) 0)}\n"] }]
1773
+ }], propDecorators: { props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], surfaceId: [{ type: i0.Input, args: [{ isSignal: true, alias: "surfaceId", required: true }] }], componentId: [{ type: i0.Input, args: [{ isSignal: true, alias: "componentId", required: false }] }], dataContextPath: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataContextPath", required: false }] }] } });
1774
+
1775
+ /**
1776
+ * Copyright 2026 Google LLC
1777
+ *
1778
+ * Licensed under the Apache License, Version 2.0 (the "License");
1779
+ * you may not use this file except in compliance with the License.
1780
+ * You may obtain a copy of the License at
1781
+ *
1782
+ * http://www.apache.org/licenses/LICENSE-2.0
1783
+ *
1784
+ * Unless required by applicable law or agreed to in writing, software
1785
+ * distributed under the License is distributed on an "AS IS" BASIS,
1786
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1787
+ * See the License for the specific language governing permissions and
1788
+ * limitations under the License.
1789
+ */
1790
+ /**
1791
+ * Angular implementation of the A2UI Modal component (v0.9).
1792
+ *
1793
+ * Renders a trigger component that opening an overlay containing a content component.
1794
+ *
1795
+ * Supported CSS variables:
1796
+ * - `--a2ui-modal-background`: Controls the background of the modal content.
1797
+ * - `--a2ui-modal-padding`: Controls the padding of the modal content.
1798
+ * - `--a2ui-modal-border-radius`: Controls the border radius of the modal content.
1799
+ * - `--a2ui-modal-box-shadow`: Controls the box shadow of the modal content.
1800
+ * - `--a2ui-modal-backdrop-bg`: Controls the background of the backdrop.
1801
+ */
1802
+ class ModalComponent extends BasicCatalogComponent {
1803
+ /**
1804
+ * Reactive properties resolved from the A2UI {@link ComponentModel}.
1805
+ *
1806
+ * Expected properties:
1807
+ * - `trigger`: The ID of the component that opens the modal.
1808
+ * - `content`: The ID of the component to display inside the modal.
1809
+ */
1810
+ props = input({}, ...(ngDevMode ? [{ debugName: "props" }] : /* istanbul ignore next */ []));
1811
+ surfaceId = input.required(...(ngDevMode ? [{ debugName: "surfaceId" }] : /* istanbul ignore next */ []));
1812
+ componentId = input(...(ngDevMode ? [undefined, { debugName: "componentId" }] : /* istanbul ignore next */ []));
1813
+ dataContextPath = input('/', ...(ngDevMode ? [{ debugName: "dataContextPath" }] : /* istanbul ignore next */ []));
1814
+ isOpen = signal(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : /* istanbul ignore next */ []));
1815
+ trigger = computed$1(() => this.props()['trigger']?.value(), ...(ngDevMode ? [{ debugName: "trigger" }] : /* istanbul ignore next */ []));
1816
+ content = computed$1(() => this.props()['content']?.value(), ...(ngDevMode ? [{ debugName: "content" }] : /* istanbul ignore next */ []));
1817
+ openModal() {
1818
+ this.isOpen.set(true);
1819
+ }
1820
+ closeModal() {
1821
+ this.isOpen.set(false);
1822
+ }
1823
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ModalComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
1824
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: ModalComponent, isStandalone: true, selector: "a2ui-v09-modal", inputs: { props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null }, surfaceId: { classPropertyName: "surfaceId", publicName: "surfaceId", isSignal: true, isRequired: true, transformFunction: null }, componentId: { classPropertyName: "componentId", publicName: "componentId", isSignal: true, isRequired: false, transformFunction: null }, dataContextPath: { classPropertyName: "dataContextPath", publicName: "dataContextPath", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: `
1825
+ <div class="a2ui-modal-wrapper">
1826
+ <div (click)="openModal()" class="a2ui-modal-trigger">
1827
+ @if (trigger()) {
1828
+ <a2ui-v09-component-host
1829
+ [componentKey]="trigger()!"
1830
+ [surfaceId]="surfaceId()"
1831
+ >
1832
+ </a2ui-v09-component-host>
1833
+ }
1834
+ </div>
1835
+
1836
+ @if (isOpen()) {
1837
+ <div class="a2ui-modal-overlay" (click)="closeModal()">
1838
+ <div class="a2ui-modal-content" (click)="$event.stopPropagation()">
1839
+ <button class="a2ui-modal-close" (click)="closeModal()">&times;</button>
1840
+ @if (content()) {
1841
+ <a2ui-v09-component-host
1842
+ [componentKey]="content()!"
1843
+ [surfaceId]="surfaceId()"
1844
+ >
1845
+ </a2ui-v09-component-host>
1846
+ }
1847
+ </div>
1848
+ </div>
1849
+ }
1850
+ </div>
1851
+ `, isInline: true, styles: [".a2ui-modal-wrapper{display:inline-block}.a2ui-modal-trigger{cursor:pointer}.a2ui-modal-overlay{position:fixed;top:0;left:0;width:100vw;height:100vh;background:var(--a2ui-modal-backdrop-bg, rgba(0, 0, 0, .5));display:flex;justify-content:center;align-items:center;z-index:1000}.a2ui-modal-content{background:var(--a2ui-modal-background, var(--a2ui-color-surface, white));padding:var(--a2ui-modal-padding, var(--a2ui-spacing-xl, 32px));border-radius:var(--a2ui-modal-border-radius, var(--a2ui-border-radius, 8px));position:relative;min-width:300px;max-width:80%;max-height:80%;overflow-y:auto;box-shadow:var(--a2ui-modal-box-shadow, 0 10px 25px rgba(0, 0, 0, .2))}.a2ui-modal-close{position:absolute;top:10px;right:15px;border:none;background:none;font-size:24px;cursor:pointer;color:var(--a2ui-text-caption-color, #999)}.a2ui-modal-close:hover{color:var(--a2ui-text-color, #333)}\n"], dependencies: [{ kind: "component", type: ComponentHostComponent, selector: "a2ui-v09-component-host", inputs: ["componentKey", "surfaceId"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1852
+ }
1853
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ModalComponent, decorators: [{
1854
+ type: Component,
1855
+ args: [{ selector: 'a2ui-v09-modal', standalone: true, imports: [ComponentHostComponent], template: `
1856
+ <div class="a2ui-modal-wrapper">
1857
+ <div (click)="openModal()" class="a2ui-modal-trigger">
1858
+ @if (trigger()) {
1859
+ <a2ui-v09-component-host
1860
+ [componentKey]="trigger()!"
1861
+ [surfaceId]="surfaceId()"
1862
+ >
1863
+ </a2ui-v09-component-host>
1864
+ }
1865
+ </div>
1866
+
1867
+ @if (isOpen()) {
1868
+ <div class="a2ui-modal-overlay" (click)="closeModal()">
1869
+ <div class="a2ui-modal-content" (click)="$event.stopPropagation()">
1870
+ <button class="a2ui-modal-close" (click)="closeModal()">&times;</button>
1871
+ @if (content()) {
1872
+ <a2ui-v09-component-host
1873
+ [componentKey]="content()!"
1874
+ [surfaceId]="surfaceId()"
1875
+ >
1876
+ </a2ui-v09-component-host>
1877
+ }
1878
+ </div>
1879
+ </div>
1880
+ }
1881
+ </div>
1882
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".a2ui-modal-wrapper{display:inline-block}.a2ui-modal-trigger{cursor:pointer}.a2ui-modal-overlay{position:fixed;top:0;left:0;width:100vw;height:100vh;background:var(--a2ui-modal-backdrop-bg, rgba(0, 0, 0, .5));display:flex;justify-content:center;align-items:center;z-index:1000}.a2ui-modal-content{background:var(--a2ui-modal-background, var(--a2ui-color-surface, white));padding:var(--a2ui-modal-padding, var(--a2ui-spacing-xl, 32px));border-radius:var(--a2ui-modal-border-radius, var(--a2ui-border-radius, 8px));position:relative;min-width:300px;max-width:80%;max-height:80%;overflow-y:auto;box-shadow:var(--a2ui-modal-box-shadow, 0 10px 25px rgba(0, 0, 0, .2))}.a2ui-modal-close{position:absolute;top:10px;right:15px;border:none;background:none;font-size:24px;cursor:pointer;color:var(--a2ui-text-caption-color, #999)}.a2ui-modal-close:hover{color:var(--a2ui-text-color, #333)}\n"] }]
1883
+ }], propDecorators: { props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], surfaceId: [{ type: i0.Input, args: [{ isSignal: true, alias: "surfaceId", required: true }] }], componentId: [{ type: i0.Input, args: [{ isSignal: true, alias: "componentId", required: false }] }], dataContextPath: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataContextPath", required: false }] }] } });
1884
+
1885
+ /**
1886
+ * Copyright 2026 Google LLC
1887
+ *
1888
+ * Licensed under the Apache License, Version 2.0 (the "License");
1889
+ * you may not use this file except in compliance with the License.
1890
+ * You may obtain a copy of the License at
1891
+ *
1892
+ * http://www.apache.org/licenses/LICENSE-2.0
1893
+ *
1894
+ * Unless required by applicable law or agreed to in writing, software
1895
+ * distributed under the License is distributed on an "AS IS" BASIS,
1896
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1897
+ * See the License for the specific language governing permissions and
1898
+ * limitations under the License.
1899
+ */
1900
+ /**
1901
+ * Angular implementation of the A2UI Divider component (v0.9).
1902
+ *
1903
+ * Renders a horizontal or vertical line to separate content.
1904
+ *
1905
+ * Supported CSS variables:
1906
+ * - `--a2ui-divider-border`: Controls the border of the divider (horizontal and vertical).
1907
+ * - `--a2ui-divider-spacing`: Controls the margin around the divider.
1908
+ */
1909
+ class DividerComponent extends BasicCatalogComponent {
1910
+ /**
1911
+ * Reactive properties resolved from the A2UI {@link ComponentModel}.
1912
+ *
1913
+ * Expected properties:
1914
+ * - `axis`: The orientation of the divider ('horizontal' (default) or 'vertical').
1915
+ */
1916
+ props = input({}, ...(ngDevMode ? [{ debugName: "props" }] : /* istanbul ignore next */ []));
1917
+ surfaceId = input.required(...(ngDevMode ? [{ debugName: "surfaceId" }] : /* istanbul ignore next */ []));
1918
+ componentId = input(...(ngDevMode ? [undefined, { debugName: "componentId" }] : /* istanbul ignore next */ []));
1919
+ dataContextPath = input('/', ...(ngDevMode ? [{ debugName: "dataContextPath" }] : /* istanbul ignore next */ []));
1920
+ axis = computed$1(() => this.props()['axis']?.value() ?? 'horizontal', ...(ngDevMode ? [{ debugName: "axis" }] : /* istanbul ignore next */ []));
1921
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: DividerComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
1922
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.5", type: DividerComponent, isStandalone: true, selector: "a2ui-v09-divider", inputs: { props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null }, surfaceId: { classPropertyName: "surfaceId", publicName: "surfaceId", isSignal: true, isRequired: true, transformFunction: null }, componentId: { classPropertyName: "componentId", publicName: "componentId", isSignal: true, isRequired: false, transformFunction: null }, dataContextPath: { classPropertyName: "dataContextPath", publicName: "dataContextPath", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "style.display": "\"block\"", "style.width": "axis() === \"horizontal\" ? \"100%\" : \"auto\"" } }, usesInheritance: true, ngImport: i0, template: `
1923
+ <hr
1924
+ class="a2ui-divider"
1925
+ [class.horizontal]="axis() === 'horizontal'"
1926
+ [class.vertical]="axis() === 'vertical'"
1927
+ />
1928
+ `, isInline: true, styles: [".a2ui-divider{border:0;border-top:var(--a2ui-divider-border, var(--a2ui-border-width, 1px) solid var(--a2ui-color-border, #ccc));margin:var(--a2ui-divider-spacing, var(--a2ui-spacing-m, 16px)) 0;width:100%}.a2ui-divider.vertical{width:var(--a2ui-border-width, 1px);height:100%;margin:0 var(--a2ui-divider-spacing, var(--a2ui-spacing-m, 16px));border-top:0;border-left:var(--a2ui-divider-border, var(--a2ui-border-width, 1px) solid var(--a2ui-color-border, #ccc))}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1929
+ }
1930
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: DividerComponent, decorators: [{
1931
+ type: Component,
1932
+ args: [{ selector: 'a2ui-v09-divider', standalone: true, imports: [], host: {
1933
+ '[style.display]': '"block"',
1934
+ '[style.width]': 'axis() === "horizontal" ? "100%" : "auto"',
1935
+ }, template: `
1936
+ <hr
1937
+ class="a2ui-divider"
1938
+ [class.horizontal]="axis() === 'horizontal'"
1939
+ [class.vertical]="axis() === 'vertical'"
1940
+ />
1941
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".a2ui-divider{border:0;border-top:var(--a2ui-divider-border, var(--a2ui-border-width, 1px) solid var(--a2ui-color-border, #ccc));margin:var(--a2ui-divider-spacing, var(--a2ui-spacing-m, 16px)) 0;width:100%}.a2ui-divider.vertical{width:var(--a2ui-border-width, 1px);height:100%;margin:0 var(--a2ui-divider-spacing, var(--a2ui-spacing-m, 16px));border-top:0;border-left:var(--a2ui-divider-border, var(--a2ui-border-width, 1px) solid var(--a2ui-color-border, #ccc))}\n"] }]
1942
+ }], propDecorators: { props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], surfaceId: [{ type: i0.Input, args: [{ isSignal: true, alias: "surfaceId", required: true }] }], componentId: [{ type: i0.Input, args: [{ isSignal: true, alias: "componentId", required: false }] }], dataContextPath: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataContextPath", required: false }] }] } });
1943
+
1944
+ /**
1945
+ * Copyright 2026 Google LLC
1946
+ *
1947
+ * Licensed under the Apache License, Version 2.0 (the "License");
1948
+ * you may not use this file except in compliance with the License.
1949
+ * You may obtain a copy of the License at
1950
+ *
1951
+ * http://www.apache.org/licenses/LICENSE-2.0
1952
+ *
1953
+ * Unless required by applicable law or agreed to in writing, software
1954
+ * distributed under the License is distributed on an "AS IS" BASIS,
1955
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1956
+ * See the License for the specific language governing permissions and
1957
+ * limitations under the License.
1958
+ */
1959
+ /**
1960
+ * Angular implementation of the A2UI CheckBox component (v0.9).
1961
+ *
1962
+ * Renders a checkbox with a label. Updates the bound data model property
1963
+ * when the checked state changes.
1964
+ *
1965
+ * Supported CSS variables:
1966
+ * - `--a2ui-checkbox-margin`: Controls the margin.
1967
+ * - `--a2ui-checkbox-gap`: Controls the gap between checkbox and label.
1968
+ * - `--a2ui-checkbox-label-font-size`: Controls the font size of the label.
1969
+ * - `--a2ui-checkbox-label-font-weight`: Controls the font weight of the label.
1970
+ * - `--a2ui-checkbox-size`: Controls the width and height of the checkbox.
1971
+ * - `--a2ui-checkbox-background`: Controls the background of the checkbox.
1972
+ * - `--a2ui-checkbox-border`: Controls the border of the checkbox.
1973
+ * - `--a2ui-checkbox-border-radius`: Controls the border radius of the checkbox.
1974
+ * - `--a2ui-checkbox-color-error`: Controls the color for error states.
1975
+ */
1976
+ class CheckBoxComponent extends BasicCatalogComponent {
1977
+ /**
1978
+ * Reactive properties resolved from the A2UI {@link ComponentModel}.
1979
+ *
1980
+ * Expected properties:
1981
+ * - `label`: The text to display next to the checkbox.
1982
+ * - `value`: Boolean indicating whether the checkbox is checked.
1983
+ */
1984
+ props = input({}, ...(ngDevMode ? [{ debugName: "props" }] : /* istanbul ignore next */ []));
1985
+ surfaceId = input.required(...(ngDevMode ? [{ debugName: "surfaceId" }] : /* istanbul ignore next */ []));
1986
+ componentId = input(...(ngDevMode ? [undefined, { debugName: "componentId" }] : /* istanbul ignore next */ []));
1987
+ dataContextPath = input('/', ...(ngDevMode ? [{ debugName: "dataContextPath" }] : /* istanbul ignore next */ []));
1988
+ value = computed$1(() => this.props()['value']?.value() === true, ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
1989
+ label = computed$1(() => this.props()['label']?.value(), ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
1990
+ handleChange(event) {
1991
+ const checked = event.target.checked;
1992
+ this.props()['value']?.onUpdate(checked);
1993
+ }
1994
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: CheckBoxComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
1995
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.5", type: CheckBoxComponent, isStandalone: true, selector: "a2ui-v09-check-box", inputs: { props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null }, surfaceId: { classPropertyName: "surfaceId", publicName: "surfaceId", isSignal: true, isRequired: true, transformFunction: null }, componentId: { classPropertyName: "componentId", publicName: "componentId", isSignal: true, isRequired: false, transformFunction: null }, dataContextPath: { classPropertyName: "dataContextPath", publicName: "dataContextPath", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: `
1996
+ <label class="a2ui-check-box-label">
1997
+ <input
1998
+ type="checkbox"
1999
+ [checked]="value()"
2000
+ (change)="handleChange($event)"
2001
+ class="a2ui-check-box-input"
2002
+ />
2003
+ <span class="a2ui-check-box-text">{{ label() }}</span>
2004
+ </label>
2005
+ `, isInline: true, styles: [".a2ui-check-box-label{display:flex;align-items:center;gap:var(--a2ui-checkbox-gap, var(--a2ui-spacing-s, .5rem));cursor:pointer;padding:4px 0;margin:var(--a2ui-checkbox-margin, var(--a2ui-spacing-m, 16px));color:var(--a2ui-text-color-text, var(--a2ui-color-on-background, #333))}.a2ui-check-box-input{width:var(--a2ui-checkbox-size, 1rem);height:var(--a2ui-checkbox-size, 1rem);cursor:pointer;background:var(--a2ui-checkbox-background, inherit);border:var(--a2ui-checkbox-border, var(--a2ui-border-width, 1px) solid #ccc);border-radius:var(--a2ui-checkbox-border-radius, 4px)}.a2ui-check-box-text{font-size:var(--a2ui-checkbox-label-font-size, var(--a2ui-label-font-size, var(--a2ui-font-size-s, 16px)));font-weight:var(--a2ui-checkbox-label-font-weight, bold)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2006
+ }
2007
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: CheckBoxComponent, decorators: [{
2008
+ type: Component,
2009
+ args: [{ selector: 'a2ui-v09-check-box', standalone: true, imports: [], template: `
2010
+ <label class="a2ui-check-box-label">
2011
+ <input
2012
+ type="checkbox"
2013
+ [checked]="value()"
2014
+ (change)="handleChange($event)"
2015
+ class="a2ui-check-box-input"
2016
+ />
2017
+ <span class="a2ui-check-box-text">{{ label() }}</span>
2018
+ </label>
2019
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".a2ui-check-box-label{display:flex;align-items:center;gap:var(--a2ui-checkbox-gap, var(--a2ui-spacing-s, .5rem));cursor:pointer;padding:4px 0;margin:var(--a2ui-checkbox-margin, var(--a2ui-spacing-m, 16px));color:var(--a2ui-text-color-text, var(--a2ui-color-on-background, #333))}.a2ui-check-box-input{width:var(--a2ui-checkbox-size, 1rem);height:var(--a2ui-checkbox-size, 1rem);cursor:pointer;background:var(--a2ui-checkbox-background, inherit);border:var(--a2ui-checkbox-border, var(--a2ui-border-width, 1px) solid #ccc);border-radius:var(--a2ui-checkbox-border-radius, 4px)}.a2ui-check-box-text{font-size:var(--a2ui-checkbox-label-font-size, var(--a2ui-label-font-size, var(--a2ui-font-size-s, 16px)));font-weight:var(--a2ui-checkbox-label-font-weight, bold)}\n"] }]
2020
+ }], propDecorators: { props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], surfaceId: [{ type: i0.Input, args: [{ isSignal: true, alias: "surfaceId", required: true }] }], componentId: [{ type: i0.Input, args: [{ isSignal: true, alias: "componentId", required: false }] }], dataContextPath: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataContextPath", required: false }] }] } });
2021
+
2022
+ /**
2023
+ * Copyright 2026 Google LLC
2024
+ *
2025
+ * Licensed under the Apache License, Version 2.0 (the "License");
2026
+ * you may not use this file except in compliance with the License.
2027
+ * You may obtain a copy of the License at
2028
+ *
2029
+ * http://www.apache.org/licenses/LICENSE-2.0
2030
+ *
2031
+ * Unless required by applicable law or agreed to in writing, software
2032
+ * distributed under the License is distributed on an "AS IS" BASIS,
2033
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2034
+ * See the License for the specific language governing permissions and
2035
+ * limitations under the License.
2036
+ */
2037
+ /**
2038
+ * Angular implementation of the A2UI ChoicePicker component (v0.9).
2039
+ *
2040
+ * Renders a set of options as either radio buttons/checkboxes or chips.
2041
+ * Supports both single and multiple selection.
2042
+ *
2043
+ * Supported CSS variables:
2044
+ * - `--a2ui-choicepicker-gap`: Controls spacing between options/chips.
2045
+ * - `--a2ui-choicepicker-padding`: Controls padding of the container.
2046
+ * - `--a2ui-choicepicker-checkbox-size`: Controls size of checkboxes/radios.
2047
+ * - `--a2ui-choicepicker-chip-padding`: Controls padding of chips.
2048
+ * - `--a2ui-choicepicker-chip-border-radius`: Controls border radius of chips.
2049
+ * - `--a2ui-choicepicker-chip-border`: Controls border of chips.
2050
+ * - `--a2ui-choicepicker-chip-background`: Controls background of chips.
2051
+ * - `--a2ui-choicepicker-chip-background-selected`: Controls background of selected chips.
2052
+ */
2053
+ class ChoicePickerComponent extends BasicCatalogComponent {
2054
+ /**
2055
+ * Reactive properties resolved from the A2UI {@link ComponentModel}.
2056
+ *
2057
+ * Expected properties:
2058
+ * - `value`: The currently selected value(s).
2059
+ * - `choices` or `options`: List of choice objects (label and value).
2060
+ * - `displayStyle`: How to render the choices ('default' or 'chips').
2061
+ * - `variant`: Selection mode ('singleSelection' or 'multipleSelection').
2062
+ */
2063
+ props = input({}, ...(ngDevMode ? [{ debugName: "props" }] : /* istanbul ignore next */ []));
2064
+ surfaceId = input.required(...(ngDevMode ? [{ debugName: "surfaceId" }] : /* istanbul ignore next */ []));
2065
+ componentId = input(...(ngDevMode ? [undefined, { debugName: "componentId" }] : /* istanbul ignore next */ []));
2066
+ dataContextPath = input('/', ...(ngDevMode ? [{ debugName: "dataContextPath" }] : /* istanbul ignore next */ []));
2067
+ displayStyle = computed$1(() => this.props()['displayStyle']?.value(), ...(ngDevMode ? [{ debugName: "displayStyle" }] : /* istanbul ignore next */ []));
2068
+ choices = computed$1(() => this.props()['choices']?.value() || this.props()['options']?.value() || [], ...(ngDevMode ? [{ debugName: "choices" }] : /* istanbul ignore next */ []));
2069
+ variant = computed$1(() => this.props()['variant']?.value(), ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
2070
+ selectedValue = computed$1(() => this.props()['value']?.value(), ...(ngDevMode ? [{ debugName: "selectedValue" }] : /* istanbul ignore next */ []));
2071
+ isMultiple() {
2072
+ return this.variant() === 'multipleSelection';
2073
+ }
2074
+ isSelected(value) {
2075
+ const selected = this.selectedValue();
2076
+ if (Array.isArray(selected)) {
2077
+ return selected.includes(value);
2078
+ }
2079
+ return selected === value;
2080
+ }
2081
+ onCheckChange(value, event) {
2082
+ const checked = event.target.checked;
2083
+ this.updateValue(value, checked);
2084
+ }
2085
+ toggleActive(value) {
2086
+ const current = this.isSelected(value);
2087
+ this.updateValue(value, !current);
2088
+ }
2089
+ updateValue(value, active) {
2090
+ const current = this.selectedValue();
2091
+ if (this.isMultiple()) {
2092
+ let next = Array.isArray(current) ? [...current] : [];
2093
+ if (active) {
2094
+ if (!next.includes(value))
2095
+ next.push(value);
2096
+ }
2097
+ else {
2098
+ next = next.filter((v) => v !== value);
2099
+ }
2100
+ this.props()['value']?.onUpdate(next);
2101
+ }
2102
+ else {
2103
+ if (active) {
2104
+ this.props()['value']?.onUpdate(value);
2105
+ }
2106
+ }
2107
+ }
2108
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ChoicePickerComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
2109
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: ChoicePickerComponent, isStandalone: true, selector: "a2ui-v09-choice-picker", inputs: { props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null }, surfaceId: { classPropertyName: "surfaceId", publicName: "surfaceId", isSignal: true, isRequired: true, transformFunction: null }, componentId: { classPropertyName: "componentId", publicName: "componentId", isSignal: true, isRequired: false, transformFunction: null }, dataContextPath: { classPropertyName: "dataContextPath", publicName: "dataContextPath", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: `
2110
+ <div class="a2ui-choice-picker">
2111
+ <!-- Chips Variant -->
2112
+ @if (displayStyle() === 'chips') {
2113
+ <div class="a2ui-chips-group">
2114
+ @for (choice of choices(); track choice.value) {
2115
+ <button
2116
+ class="a2ui-chip"
2117
+ [class.active]="isSelected(choice.value)"
2118
+ (click)="toggleActive(choice.value)"
2119
+ >
2120
+ {{ choice.label }}
2121
+ </button>
2122
+ }
2123
+ </div>
2124
+ } @else {
2125
+ <!-- Checkbox/Radio Variant -->
2126
+ <div class="a2ui-options-group">
2127
+ @for (choice of choices(); track choice.value) {
2128
+ <label class="a2ui-option-label">
2129
+ <input
2130
+ [type]="isMultiple() ? 'checkbox' : 'radio'"
2131
+ [name]="componentId()"
2132
+ [value]="choice.value"
2133
+ [checked]="isSelected(choice.value)"
2134
+ (change)="onCheckChange(choice.value, $event)"
2135
+ class="a2ui-option-input"
2136
+ />
2137
+ <span class="a2ui-option-text">{{ choice.label }}</span>
2138
+ </label>
2139
+ }
2140
+ </div>
2141
+ }
2142
+ </div>
2143
+ `, isInline: true, styles: [".a2ui-choice-picker{width:100%;padding:var(--a2ui-choicepicker-padding, 0)}.a2ui-options-group{display:flex;flex-direction:column;gap:var(--a2ui-choicepicker-gap, var(--a2ui-spacing-xs, .25rem))}.a2ui-option-label{display:flex;align-items:center;gap:var(--a2ui-choicepicker-gap, var(--a2ui-spacing-xs, .25rem));cursor:pointer;color:var(--a2ui-text-color-text, var(--a2ui-color-on-background, #333))}.a2ui-option-input{width:var(--a2ui-choicepicker-checkbox-size, 1rem);height:var(--a2ui-choicepicker-checkbox-size, 1rem)}.a2ui-chips-group{display:flex;flex-wrap:wrap;gap:var(--a2ui-choicepicker-gap, var(--a2ui-spacing-xs, .25rem))}.a2ui-chip{padding:var(--a2ui-choicepicker-chip-padding, var(--a2ui-spacing-s, .5rem) var(--a2ui-spacing-m, 1rem));border-radius:var(--a2ui-choicepicker-chip-border-radius, 100px);border:var(--a2ui-choicepicker-chip-border, 1px solid var(--a2ui-color-border, #ccc));background:var(--a2ui-choicepicker-chip-background, var(--a2ui-color-surface, #fff));cursor:pointer;transition:all .2s}.a2ui-chip.active{background-color:var(--a2ui-choicepicker-chip-background-selected, var(--a2ui-color-primary, #17e));color:var(--a2ui-color-on-primary, #fff);border-color:var(--a2ui-choicepicker-chip-background-selected, var(--a2ui-color-primary, #17e))}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2144
+ }
2145
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ChoicePickerComponent, decorators: [{
2146
+ type: Component,
2147
+ args: [{ selector: 'a2ui-v09-choice-picker', standalone: true, imports: [], template: `
2148
+ <div class="a2ui-choice-picker">
2149
+ <!-- Chips Variant -->
2150
+ @if (displayStyle() === 'chips') {
2151
+ <div class="a2ui-chips-group">
2152
+ @for (choice of choices(); track choice.value) {
2153
+ <button
2154
+ class="a2ui-chip"
2155
+ [class.active]="isSelected(choice.value)"
2156
+ (click)="toggleActive(choice.value)"
2157
+ >
2158
+ {{ choice.label }}
2159
+ </button>
2160
+ }
2161
+ </div>
2162
+ } @else {
2163
+ <!-- Checkbox/Radio Variant -->
2164
+ <div class="a2ui-options-group">
2165
+ @for (choice of choices(); track choice.value) {
2166
+ <label class="a2ui-option-label">
2167
+ <input
2168
+ [type]="isMultiple() ? 'checkbox' : 'radio'"
2169
+ [name]="componentId()"
2170
+ [value]="choice.value"
2171
+ [checked]="isSelected(choice.value)"
2172
+ (change)="onCheckChange(choice.value, $event)"
2173
+ class="a2ui-option-input"
2174
+ />
2175
+ <span class="a2ui-option-text">{{ choice.label }}</span>
2176
+ </label>
2177
+ }
2178
+ </div>
2179
+ }
2180
+ </div>
2181
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".a2ui-choice-picker{width:100%;padding:var(--a2ui-choicepicker-padding, 0)}.a2ui-options-group{display:flex;flex-direction:column;gap:var(--a2ui-choicepicker-gap, var(--a2ui-spacing-xs, .25rem))}.a2ui-option-label{display:flex;align-items:center;gap:var(--a2ui-choicepicker-gap, var(--a2ui-spacing-xs, .25rem));cursor:pointer;color:var(--a2ui-text-color-text, var(--a2ui-color-on-background, #333))}.a2ui-option-input{width:var(--a2ui-choicepicker-checkbox-size, 1rem);height:var(--a2ui-choicepicker-checkbox-size, 1rem)}.a2ui-chips-group{display:flex;flex-wrap:wrap;gap:var(--a2ui-choicepicker-gap, var(--a2ui-spacing-xs, .25rem))}.a2ui-chip{padding:var(--a2ui-choicepicker-chip-padding, var(--a2ui-spacing-s, .5rem) var(--a2ui-spacing-m, 1rem));border-radius:var(--a2ui-choicepicker-chip-border-radius, 100px);border:var(--a2ui-choicepicker-chip-border, 1px solid var(--a2ui-color-border, #ccc));background:var(--a2ui-choicepicker-chip-background, var(--a2ui-color-surface, #fff));cursor:pointer;transition:all .2s}.a2ui-chip.active{background-color:var(--a2ui-choicepicker-chip-background-selected, var(--a2ui-color-primary, #17e));color:var(--a2ui-color-on-primary, #fff);border-color:var(--a2ui-choicepicker-chip-background-selected, var(--a2ui-color-primary, #17e))}\n"] }]
2182
+ }], propDecorators: { props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], surfaceId: [{ type: i0.Input, args: [{ isSignal: true, alias: "surfaceId", required: true }] }], componentId: [{ type: i0.Input, args: [{ isSignal: true, alias: "componentId", required: false }] }], dataContextPath: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataContextPath", required: false }] }] } });
2183
+
2184
+ /**
2185
+ * Copyright 2026 Google LLC
2186
+ *
2187
+ * Licensed under the Apache License, Version 2.0 (the "License");
2188
+ * you may not use this file except in compliance with the License.
2189
+ * You may obtain a copy of the License at
2190
+ *
2191
+ * http://www.apache.org/licenses/LICENSE-2.0
2192
+ *
2193
+ * Unless required by applicable law or agreed to in writing, software
2194
+ * distributed under the License is distributed on an "AS IS" BASIS,
2195
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2196
+ * See the License for the specific language governing permissions and
2197
+ * limitations under the License.
2198
+ */
2199
+ /**
2200
+ * Angular implementation of the A2UI Slider component (v0.9).
2201
+ *
2202
+ * Renders a range input slider with a label and its current value.
2203
+ *
2204
+ * Supported CSS variables:
2205
+ * - `--a2ui-slider-margin`: Controls the margin of the container.
2206
+ * - `--a2ui-slider-label-font-size`: Controls the font size of the label.
2207
+ * - `--a2ui-slider-label-font-weight`: Controls the font weight of the label.
2208
+ * - `--a2ui-slider-thumb-color`: Controls the accent color of the thumb.
2209
+ * - `--a2ui-slider-track-color`: Controls the background of the track.
2210
+ */
2211
+ class SliderComponent extends BasicCatalogComponent {
2212
+ /**
2213
+ * Reactive properties resolved from the A2UI {@link ComponentModel}.
2214
+ *
2215
+ * Expected properties:
2216
+ * - `value`: The current numeric value.
2217
+ * - `label`: Label text to display.
2218
+ * - `min`: Minimum value (default: 0).
2219
+ * - `max`: Maximum value (default: 100).
2220
+ * - `step`: Increment step (default: 1).
2221
+ */
2222
+ props = input({}, ...(ngDevMode ? [{ debugName: "props" }] : /* istanbul ignore next */ []));
2223
+ surfaceId = input.required(...(ngDevMode ? [{ debugName: "surfaceId" }] : /* istanbul ignore next */ []));
2224
+ componentId = input(...(ngDevMode ? [undefined, { debugName: "componentId" }] : /* istanbul ignore next */ []));
2225
+ dataContextPath = input('/', ...(ngDevMode ? [{ debugName: "dataContextPath" }] : /* istanbul ignore next */ []));
2226
+ label = computed$1(() => this.props()['label']?.value(), ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
2227
+ value = computed$1(() => this.props()['value']?.value(), ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
2228
+ min = computed$1(() => this.props()['min']?.value() ?? 0, ...(ngDevMode ? [{ debugName: "min" }] : /* istanbul ignore next */ []));
2229
+ max = computed$1(() => this.props()['max']?.value() ?? 100, ...(ngDevMode ? [{ debugName: "max" }] : /* istanbul ignore next */ []));
2230
+ step = computed$1(() => this.props()['step']?.value() ?? 1, ...(ngDevMode ? [{ debugName: "step" }] : /* istanbul ignore next */ []));
2231
+ handleInput(event) {
2232
+ const val = Number(event.target.value);
2233
+ this.props()['value']?.onUpdate(val);
2234
+ }
2235
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SliderComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
2236
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.5", type: SliderComponent, isStandalone: true, selector: "a2ui-v09-slider", inputs: { props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null }, surfaceId: { classPropertyName: "surfaceId", publicName: "surfaceId", isSignal: true, isRequired: true, transformFunction: null }, componentId: { classPropertyName: "componentId", publicName: "componentId", isSignal: true, isRequired: false, transformFunction: null }, dataContextPath: { classPropertyName: "dataContextPath", publicName: "dataContextPath", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: `
2237
+ <div class="a2ui-slider-container">
2238
+ <div class="a2ui-slider-header">
2239
+ <span class="a2ui-slider-label">{{ label() }}</span>
2240
+ <span class="a2ui-slider-value">{{ value() }}</span>
2241
+ </div>
2242
+ <input
2243
+ type="range"
2244
+ [min]="min()"
2245
+ [max]="max()"
2246
+ [step]="step()"
2247
+ [value]="value() ?? min()"
2248
+ (input)="handleInput($event)"
2249
+ class="a2ui-slider"
2250
+ />
2251
+ </div>
2252
+ `, isInline: true, styles: [".a2ui-slider-container{width:100%;display:flex;flex-direction:column;gap:var(--a2ui-spacing-xs, 4px);margin:var(--a2ui-slider-margin, var(--a2ui-spacing-m, 16px))}.a2ui-slider-header{display:flex;justify-content:space-between;font-size:var(--a2ui-slider-label-font-size, var(--a2ui-label-font-size, var(--a2ui-font-size-s, 14px)));font-weight:var(--a2ui-slider-label-font-weight, bold);color:var(--a2ui-text-color-text, var(--a2ui-color-on-background, #333))}.a2ui-slider{width:100%;cursor:pointer;accent-color:var(--a2ui-slider-thumb-color, var(--a2ui-color-primary, #007bff));background:var(--a2ui-slider-track-color, var(--a2ui-color-secondary, #e9ecef))}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2253
+ }
2254
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SliderComponent, decorators: [{
2255
+ type: Component,
2256
+ args: [{ selector: 'a2ui-v09-slider', standalone: true, imports: [], template: `
2257
+ <div class="a2ui-slider-container">
2258
+ <div class="a2ui-slider-header">
2259
+ <span class="a2ui-slider-label">{{ label() }}</span>
2260
+ <span class="a2ui-slider-value">{{ value() }}</span>
2261
+ </div>
2262
+ <input
2263
+ type="range"
2264
+ [min]="min()"
2265
+ [max]="max()"
2266
+ [step]="step()"
2267
+ [value]="value() ?? min()"
2268
+ (input)="handleInput($event)"
2269
+ class="a2ui-slider"
2270
+ />
2271
+ </div>
2272
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".a2ui-slider-container{width:100%;display:flex;flex-direction:column;gap:var(--a2ui-spacing-xs, 4px);margin:var(--a2ui-slider-margin, var(--a2ui-spacing-m, 16px))}.a2ui-slider-header{display:flex;justify-content:space-between;font-size:var(--a2ui-slider-label-font-size, var(--a2ui-label-font-size, var(--a2ui-font-size-s, 14px)));font-weight:var(--a2ui-slider-label-font-weight, bold);color:var(--a2ui-text-color-text, var(--a2ui-color-on-background, #333))}.a2ui-slider{width:100%;cursor:pointer;accent-color:var(--a2ui-slider-thumb-color, var(--a2ui-color-primary, #007bff));background:var(--a2ui-slider-track-color, var(--a2ui-color-secondary, #e9ecef))}\n"] }]
2273
+ }], propDecorators: { props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], surfaceId: [{ type: i0.Input, args: [{ isSignal: true, alias: "surfaceId", required: true }] }], componentId: [{ type: i0.Input, args: [{ isSignal: true, alias: "componentId", required: false }] }], dataContextPath: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataContextPath", required: false }] }] } });
2274
+
2275
+ /**
2276
+ * Copyright 2026 Google LLC
2277
+ *
2278
+ * Licensed under the Apache License, Version 2.0 (the "License");
2279
+ * you may not use this file except in compliance with the License.
2280
+ * You may obtain a copy of the License at
2281
+ *
2282
+ * http://www.apache.org/licenses/LICENSE-2.0
2283
+ *
2284
+ * Unless required by applicable law or agreed to in writing, software
2285
+ * distributed under the License is distributed on an "AS IS" BASIS,
2286
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2287
+ * See the License for the specific language governing permissions and
2288
+ * limitations under the License.
2289
+ */
2290
+ /**
2291
+ * Angular implementation of the A2UI DateTimeInput component (v0.9).
2292
+ *
2293
+ * Renders date and/or time input fields. Combines them into an ISO string
2294
+ * for the bound data model property.
2295
+ *
2296
+ * Supported CSS variables:
2297
+ * - `--a2ui-datetimeinput-background`: Controls the background of inputs.
2298
+ * - `--a2ui-datetimeinput-color`: Controls the text color of inputs.
2299
+ * - `--a2ui-datetimeinput-border`: Controls the border of inputs.
2300
+ * - `--a2ui-datetimeinput-border-radius`: Controls the border radius of inputs.
2301
+ * - `--a2ui-datetimeinput-padding`: Controls the padding of inputs.
2302
+ * - `--a2ui-datetimeinput-label-font-size`: Controls the font size of the label.
2303
+ * - `--a2ui-datetimeinput-label-font-weight`: Controls the font weight of the label.
2304
+ */
2305
+ class DateTimeInputComponent extends BasicCatalogComponent {
2306
+ /**
2307
+ * Reactive properties resolved from the A2UI {@link ComponentModel}.
2308
+ *
2309
+ * Expected properties:
2310
+ * - `value`: The current ISO date/time string.
2311
+ * - `label`: Optional label text.
2312
+ * - `enableDate`: Whether to show the date picker (default: true).
2313
+ * - `enableTime`: Whether to show the time picker (default: false).
2314
+ */
2315
+ props = input({}, ...(ngDevMode ? [{ debugName: "props" }] : /* istanbul ignore next */ []));
2316
+ surfaceId = input.required(...(ngDevMode ? [{ debugName: "surfaceId" }] : /* istanbul ignore next */ []));
2317
+ componentId = input(...(ngDevMode ? [undefined, { debugName: "componentId" }] : /* istanbul ignore next */ []));
2318
+ dataContextPath = input('/', ...(ngDevMode ? [{ debugName: "dataContextPath" }] : /* istanbul ignore next */ []));
2319
+ label = computed$1(() => this.props()['label']?.value(), ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
2320
+ enableDate = computed$1(() => this.props()['enableDate']?.value() ?? true, ...(ngDevMode ? [{ debugName: "enableDate" }] : /* istanbul ignore next */ []));
2321
+ enableTime = computed$1(() => this.props()['enableTime']?.value() ?? false, ...(ngDevMode ? [{ debugName: "enableTime" }] : /* istanbul ignore next */ []));
2322
+ rawValue = computed$1(() => this.props()['value']?.value() || '', ...(ngDevMode ? [{ debugName: "rawValue" }] : /* istanbul ignore next */ []));
2323
+ dateValue = computed$1(() => {
2324
+ const val = this.rawValue();
2325
+ if (!val)
2326
+ return '';
2327
+ return val.includes('T') ? val.split('T')[0] : val;
2328
+ }, ...(ngDevMode ? [{ debugName: "dateValue" }] : /* istanbul ignore next */ []));
2329
+ timeValue = computed$1(() => {
2330
+ const val = this.rawValue();
2331
+ if (!val || !val.includes('T'))
2332
+ return '';
2333
+ return val.split('T')[1].substring(0, 5);
2334
+ }, ...(ngDevMode ? [{ debugName: "timeValue" }] : /* istanbul ignore next */ []));
2335
+ handleDateChange(event) {
2336
+ const date = event.target.value;
2337
+ const current = this.rawValue();
2338
+ if (this.enableTime()) {
2339
+ const time = current.includes('T') ? current.split('T')[1] : '00:00:00';
2340
+ this.props()['value']?.onUpdate(`${date}T${time}`);
2341
+ }
2342
+ else {
2343
+ this.props()['value']?.onUpdate(date);
2344
+ }
2345
+ }
2346
+ handleTimeChange(event) {
2347
+ const time = event.target.value;
2348
+ const current = this.rawValue();
2349
+ const date = current.includes('T')
2350
+ ? current.split('T')[0]
2351
+ : current || new Date().toISOString().split('T')[0];
2352
+ this.props()['value']?.onUpdate(`${date}T${time}:00`);
2353
+ }
2354
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: DateTimeInputComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
2355
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: DateTimeInputComponent, isStandalone: true, selector: "a2ui-v09-date-time-input", inputs: { props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null }, surfaceId: { classPropertyName: "surfaceId", publicName: "surfaceId", isSignal: true, isRequired: true, transformFunction: null }, componentId: { classPropertyName: "componentId", publicName: "componentId", isSignal: true, isRequired: false, transformFunction: null }, dataContextPath: { classPropertyName: "dataContextPath", publicName: "dataContextPath", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: `
2356
+ <div class="a2ui-date-time-container">
2357
+ @if (label()) {
2358
+ <label class="a2ui-date-time-label">
2359
+ {{ label() }}
2360
+ </label>
2361
+ }
2362
+ <div class="a2ui-date-time-inputs">
2363
+ @if (enableDate()) {
2364
+ <input
2365
+ type="date"
2366
+ [value]="dateValue()"
2367
+ (change)="handleDateChange($event)"
2368
+ class="a2ui-date-time-input"
2369
+ />
2370
+ }
2371
+ @if (enableTime()) {
2372
+ <input
2373
+ type="time"
2374
+ [value]="timeValue()"
2375
+ (change)="handleTimeChange($event)"
2376
+ class="a2ui-date-time-input"
2377
+ />
2378
+ }
2379
+ </div>
2380
+ </div>
2381
+ `, isInline: true, styles: [".a2ui-date-time-container{display:flex;flex-direction:column;gap:var(--a2ui-spacing-xs, 4px);width:100%}.a2ui-date-time-label{font-size:var(--a2ui-datetimeinput-label-font-size, var(--a2ui-label-font-size, var(--a2ui-font-size-s, 14px)));font-weight:var(--a2ui-datetimeinput-label-font-weight, bold);color:var(--a2ui-text-color-text, var(--a2ui-color-on-background, #333))}.a2ui-date-time-inputs{display:flex;gap:var(--a2ui-spacing-s, 8px);width:100%}.a2ui-date-time-input{padding:var(--a2ui-datetimeinput-padding, 8px);border-radius:var(--a2ui-datetimeinput-border-radius, 4px);border:var(--a2ui-datetimeinput-border, 1px solid var(--a2ui-color-border, #ccc));background-color:var(--a2ui-datetimeinput-background, var(--a2ui-color-input, #fff));color:var(--a2ui-datetimeinput-color, var(--a2ui-color-on-input, #333));font-family:inherit;flex:1}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2382
+ }
2383
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: DateTimeInputComponent, decorators: [{
2384
+ type: Component,
2385
+ args: [{ selector: 'a2ui-v09-date-time-input', standalone: true, imports: [], template: `
2386
+ <div class="a2ui-date-time-container">
2387
+ @if (label()) {
2388
+ <label class="a2ui-date-time-label">
2389
+ {{ label() }}
2390
+ </label>
2391
+ }
2392
+ <div class="a2ui-date-time-inputs">
2393
+ @if (enableDate()) {
2394
+ <input
2395
+ type="date"
2396
+ [value]="dateValue()"
2397
+ (change)="handleDateChange($event)"
2398
+ class="a2ui-date-time-input"
2399
+ />
2400
+ }
2401
+ @if (enableTime()) {
2402
+ <input
2403
+ type="time"
2404
+ [value]="timeValue()"
2405
+ (change)="handleTimeChange($event)"
2406
+ class="a2ui-date-time-input"
2407
+ />
2408
+ }
2409
+ </div>
2410
+ </div>
2411
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".a2ui-date-time-container{display:flex;flex-direction:column;gap:var(--a2ui-spacing-xs, 4px);width:100%}.a2ui-date-time-label{font-size:var(--a2ui-datetimeinput-label-font-size, var(--a2ui-label-font-size, var(--a2ui-font-size-s, 14px)));font-weight:var(--a2ui-datetimeinput-label-font-weight, bold);color:var(--a2ui-text-color-text, var(--a2ui-color-on-background, #333))}.a2ui-date-time-inputs{display:flex;gap:var(--a2ui-spacing-s, 8px);width:100%}.a2ui-date-time-input{padding:var(--a2ui-datetimeinput-padding, 8px);border-radius:var(--a2ui-datetimeinput-border-radius, 4px);border:var(--a2ui-datetimeinput-border, 1px solid var(--a2ui-color-border, #ccc));background-color:var(--a2ui-datetimeinput-background, var(--a2ui-color-input, #fff));color:var(--a2ui-datetimeinput-color, var(--a2ui-color-on-input, #333));font-family:inherit;flex:1}\n"] }]
2412
+ }], propDecorators: { props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], surfaceId: [{ type: i0.Input, args: [{ isSignal: true, alias: "surfaceId", required: true }] }], componentId: [{ type: i0.Input, args: [{ isSignal: true, alias: "componentId", required: false }] }], dataContextPath: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataContextPath", required: false }] }] } });
2413
+
2414
+ /**
2415
+ * Copyright 2026 Google LLC
2416
+ *
2417
+ * Licensed under the Apache License, Version 2.0 (the "License");
2418
+ * you may not use this file except in compliance with the License.
2419
+ * You may obtain a copy of the License at
2420
+ *
2421
+ * http://www.apache.org/licenses/LICENSE-2.0
2422
+ *
2423
+ * Unless required by applicable law or agreed to in writing, software
2424
+ * distributed under the License is distributed on an "AS IS" BASIS,
2425
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2426
+ * See the License for the specific language governing permissions and
2427
+ * limitations under the License.
2428
+ */
2429
+ /**
2430
+ * The set of default Angular implementations for each component in the basic catalog.
2431
+ */
2432
+ const DEFAULT_COMPONENT_IMPLEMENTATIONS = {
2433
+ text: { ...TextApi, component: TextComponent },
2434
+ row: { ...RowApi, component: RowComponent },
2435
+ column: { ...ColumnApi, component: ColumnComponent },
2436
+ button: { ...ButtonApi, component: ButtonComponent },
2437
+ textField: { ...TextFieldApi, component: TextFieldComponent },
2438
+ image: { ...ImageApi, component: ImageComponent },
2439
+ icon: { ...IconApi, component: IconComponent },
2440
+ video: { ...VideoApi, component: VideoComponent },
2441
+ audioPlayer: { ...AudioPlayerApi, component: AudioPlayerComponent },
2442
+ list: { ...ListApi, component: ListComponent },
2443
+ card: { ...CardApi, component: CardComponent },
2444
+ tabs: { ...TabsApi, component: TabsComponent },
2445
+ modal: { ...ModalApi, component: ModalComponent },
2446
+ divider: { ...DividerApi, component: DividerComponent },
2447
+ checkBox: { ...CheckBoxApi, component: CheckBoxComponent },
2448
+ choicePicker: { ...ChoicePickerApi, component: ChoicePickerComponent },
2449
+ slider: { ...SliderApi, component: SliderComponent },
2450
+ dateTimeInput: { ...DateTimeInputApi, component: DateTimeInputComponent },
2451
+ };
2452
+ /**
2453
+ * The set of Angular UI components provided by the basic catalog.
2454
+ */
2455
+ const BASIC_COMPONENTS = Object.values(DEFAULT_COMPONENT_IMPLEMENTATIONS);
2456
+ /**
2457
+ * A base class for basic catalogs, providing extensibility for non-DI use cases.
2458
+ */
2459
+ class BasicCatalogBase extends AngularCatalog {
2460
+ constructor(options = {}) {
2461
+ const id = options.id ?? 'https://a2ui.org/specification/v0_9/basic_catalog.json';
2462
+ const functions = options.functions ?? BASIC_FUNCTIONS;
2463
+ const overrides = options.components ?? {};
2464
+ const components = [
2465
+ ...Object.entries(DEFAULT_COMPONENT_IMPLEMENTATIONS).map(([key, defaultValue]) => {
2466
+ const impl = overrides[key] ?? defaultValue;
2467
+ return { ...impl, name: impl.name || key };
2468
+ }),
2469
+ ...(options.extraComponents ?? []),
2470
+ ];
2471
+ super(id, components, functions);
2472
+ }
2473
+ }
2474
+ /**
2475
+ * A basic catalog of components and functions for v0.9 verification.
2476
+ *
2477
+ * This catalog includes a wide range of UI components (Text, Button, Row, etc.)
2478
+ * and utility functions (capitalize, formatString) defined in the A2UI v0.9
2479
+ * basic catalog specification.
2480
+ */
2481
+ class BasicCatalog extends BasicCatalogBase {
2482
+ constructor() {
2483
+ super();
2484
+ }
2485
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: BasicCatalog, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
2486
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: BasicCatalog, providedIn: 'root' });
2487
+ }
2488
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: BasicCatalog, decorators: [{
2489
+ type: Injectable,
2490
+ args: [{
2491
+ providedIn: 'root',
2492
+ }]
2493
+ }], ctorParameters: () => [] });
2494
+
2495
+ /*
2496
+ * Copyright 2026 Google LLC
2497
+ *
2498
+ * Licensed under the Apache License, Version 2.0 (the "License");
2499
+ * you may not use this file except in compliance with the License.
2500
+ * You may obtain a copy of the License at
2501
+ *
2502
+ * http://www.apache.org/licenses/LICENSE-2.0
2503
+ *
2504
+ * Unless required by applicable law or agreed to in writing, software
2505
+ * distributed under the License is distributed on an "AS IS" BASIS,
2506
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2507
+ * See the License for the specific language governing permissions and
2508
+ * limitations under the License.
2509
+ */
2510
+ /**
2511
+ * Public API surface for A2UI Angular Renderer v0.9.
2512
+ *
2513
+ * This module provides the core services, components, and catalogs required
2514
+ * to render A2UI surfaces using the v0.9 protocol.
2515
+ *
2516
+ * @module v0.9
2517
+ */
2518
+ // Core Services and Components
2519
+
2520
+ /**
2521
+ * Generated bundle index. Do not edit.
2522
+ */
2523
+
2524
+ export { A2UI_RENDERER_CONFIG, A2uiRendererService, AngularCatalog, AudioPlayerComponent, BASIC_COMPONENTS, BasicCatalog, BasicCatalogBase, ButtonComponent, CardComponent, CheckBoxComponent, ChoicePickerComponent, ColumnComponent, ComponentBinder, ComponentHostComponent, DateTimeInputComponent, DividerComponent, IconComponent, ImageComponent, ListComponent, ModalComponent, RowComponent, SliderComponent, SurfaceComponent, TabsComponent, TextComponent, TextFieldComponent, VideoComponent, getNormalizedPath, toAngularSignal };
2525
+ //# sourceMappingURL=a2ui-angular-src-v0_9.mjs.map