@a2ui/angular 0.8.3 → 0.9.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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 +2330 -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 +2330 -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 +813 -0
  16. package/types/a2ui-angular-v0_8.d.ts +400 -0
  17. package/types/a2ui-angular-v0_9.d.ts +813 -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,2330 @@
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 { 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 } }, 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
+ template: `
361
+ @if (componentType) {
362
+ <ng-container
363
+ *ngComponentOutlet="
364
+ componentType;
365
+ inputs: {
366
+ props: props,
367
+ surfaceId: surfaceId(),
368
+ componentId: resolvedComponentId,
369
+ dataContextPath: resolvedDataContextPath,
370
+ }
371
+ "
372
+ ></ng-container>
373
+ }
374
+ `,
375
+ changeDetection: ChangeDetectionStrategy.OnPush,
376
+ }]
377
+ }], propDecorators: { componentKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "componentKey", required: false }] }], surfaceId: [{ type: i0.Input, args: [{ isSignal: true, alias: "surfaceId", required: true }] }] } });
378
+
379
+ /**
380
+ * Copyright 2026 Google LLC
381
+ *
382
+ * Licensed under the Apache License, Version 2.0 (the "License");
383
+ * you may not use this file except in compliance with the License.
384
+ * You may obtain a copy of the License at
385
+ *
386
+ * http://www.apache.org/licenses/LICENSE-2.0
387
+ *
388
+ * Unless required by applicable law or agreed to in writing, software
389
+ * distributed under the License is distributed on an "AS IS" BASIS,
390
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
391
+ * See the License for the specific language governing permissions and
392
+ * limitations under the License.
393
+ */
394
+ /**
395
+ * High-level component for rendering an entire A2UI surface.
396
+ *
397
+ * This component handles the boilerplate of setting up a {@link ComponentHostComponent}
398
+ * for the 'root' component of a surface. It is the recommended way to embed an
399
+ * A2UI surface in an Angular application.
400
+ */
401
+ class SurfaceComponent {
402
+ /** The unique identifier of the surface to render. */
403
+ surfaceId = input.required(...(ngDevMode ? [{ debugName: "surfaceId" }] : /* istanbul ignore next */ []));
404
+ /**
405
+ * The path within the surface's data model that represents the current state.
406
+ * Defaults to the root ('/').
407
+ */
408
+ dataContextPath = input('/', ...(ngDevMode ? [{ debugName: "dataContextPath" }] : /* istanbul ignore next */ []));
409
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SurfaceComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
410
+ 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 } }, ngImport: i0, template: `
411
+ <a2ui-v09-component-host
412
+ [componentKey]="{ id: 'root', basePath: dataContextPath() }"
413
+ [surfaceId]="surfaceId()"
414
+ >
415
+ </a2ui-v09-component-host>
416
+ `, isInline: true, dependencies: [{ kind: "component", type: ComponentHostComponent, selector: "a2ui-v09-component-host", inputs: ["componentKey", "surfaceId"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
417
+ }
418
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SurfaceComponent, decorators: [{
419
+ type: Component,
420
+ args: [{
421
+ selector: 'a2ui-v09-surface',
422
+ standalone: true,
423
+ imports: [ComponentHostComponent],
424
+ template: `
425
+ <a2ui-v09-component-host
426
+ [componentKey]="{ id: 'root', basePath: dataContextPath() }"
427
+ [surfaceId]="surfaceId()"
428
+ >
429
+ </a2ui-v09-component-host>
430
+ `,
431
+ changeDetection: ChangeDetectionStrategy.OnPush,
432
+ }]
433
+ }], propDecorators: { surfaceId: [{ type: i0.Input, args: [{ isSignal: true, alias: "surfaceId", required: true }] }], dataContextPath: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataContextPath", required: false }] }] } });
434
+
435
+ /**
436
+ * Copyright 2026 Google LLC
437
+ *
438
+ * Licensed under the Apache License, Version 2.0 (the "License");
439
+ * you may not use this file except in compliance with the License.
440
+ * You may obtain a copy of the License at
441
+ *
442
+ * http://www.apache.org/licenses/LICENSE-2.0
443
+ *
444
+ * Unless required by applicable law or agreed to in writing, software
445
+ * distributed under the License is distributed on an "AS IS" BASIS,
446
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
447
+ * See the License for the specific language governing permissions and
448
+ * limitations under the License.
449
+ */
450
+
451
+ /**
452
+ * Copyright 2026 Google LLC
453
+ *
454
+ * Licensed under the Apache License, Version 2.0 (the "License");
455
+ * you may not use this file except in compliance with the License.
456
+ * You may obtain a copy of the License at
457
+ *
458
+ * http://www.apache.org/licenses/LICENSE-2.0
459
+ *
460
+ * Unless required by applicable law or agreed to in writing, software
461
+ * distributed under the License is distributed on an "AS IS" BASIS,
462
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
463
+ * See the License for the specific language governing permissions and
464
+ * limitations under the License.
465
+ */
466
+ /**
467
+ * A collection of Angular component and function implementations mapped to
468
+ * A2UI protocol types.
469
+ *
470
+ * Catalogs are used by the {@link MessageProcessor} to resolve component
471
+ * definitions and by {@link ComponentHostComponent} to instantiate the
472
+ * correct Angular components.
473
+ */
474
+ class AngularCatalog extends Catalog {
475
+ }
476
+
477
+ /**
478
+ * Copyright 2026 Google LLC
479
+ *
480
+ * Licensed under the Apache License, Version 2.0 (the "License");
481
+ * you may not use this file except in compliance with the License.
482
+ * You may obtain a copy of the License at
483
+ *
484
+ * http://www.apache.org/licenses/LICENSE-2.0
485
+ *
486
+ * Unless required by applicable law or agreed to in writing, software
487
+ * distributed under the License is distributed on an "AS IS" BASIS,
488
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
489
+ * See the License for the specific language governing permissions and
490
+ * limitations under the License.
491
+ */
492
+ class MarkdownRenderer {
493
+ }
494
+ class DefaultMarkdownRenderer extends MarkdownRenderer {
495
+ static warningLogged = false;
496
+ async render(markdown, options) {
497
+ try {
498
+ // @ts-ignore - optional peer dependency
499
+ const { renderMarkdown } = await import('@a2ui/markdown-it');
500
+ return await renderMarkdown(markdown, options);
501
+ }
502
+ catch (e) {
503
+ if (!DefaultMarkdownRenderer.warningLogged) {
504
+ console.warn("[DefaultMarkdownRenderer] Failed to load optional `@a2ui/markdown-it` renderer. Using fallback.");
505
+ DefaultMarkdownRenderer.warningLogged = true;
506
+ }
507
+ return markdown;
508
+ }
509
+ }
510
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: DefaultMarkdownRenderer, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
511
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: DefaultMarkdownRenderer, providedIn: 'root' });
512
+ }
513
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: DefaultMarkdownRenderer, decorators: [{
514
+ type: Injectable,
515
+ args: [{
516
+ providedIn: 'root',
517
+ }]
518
+ }] });
519
+ function provideMarkdownRenderer(renderFn) {
520
+ if (renderFn) {
521
+ return {
522
+ provide: MarkdownRenderer,
523
+ useValue: {
524
+ render: renderFn,
525
+ },
526
+ };
527
+ }
528
+ return { provide: MarkdownRenderer, useClass: DefaultMarkdownRenderer };
529
+ }
530
+
531
+ /**
532
+ * Copyright 2026 Google LLC
533
+ *
534
+ * Licensed under the Apache License, Version 2.0 (the "License");
535
+ * you may not use this file except in compliance with the License.
536
+ * You may obtain a copy of the License at
537
+ *
538
+ * http://www.apache.org/licenses/LICENSE-2.0
539
+ *
540
+ * Unless required by applicable law or agreed to in writing, software
541
+ * distributed under the License is distributed on an "AS IS" BASIS,
542
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
543
+ * See the License for the specific language governing permissions and
544
+ * limitations under the License.
545
+ */
546
+ /**
547
+ * Angular implementation of the A2UI Text component (v0.9).
548
+ *
549
+ * Renders text with support for simple Markdown.
550
+ */
551
+ class TextComponent {
552
+ /**
553
+ * Reactive properties resolved from the A2UI {@link ComponentModel}.
554
+ *
555
+ * Expected properties:
556
+ * - `text`: The string content to display.
557
+ * - `variant`: A hint for the base text style ('h1', 'h2', 'h3', 'h4', 'h5', 'caption', 'body').
558
+ */
559
+ props = input({}, ...(ngDevMode ? [{ debugName: "props" }] : /* istanbul ignore next */ []));
560
+ surfaceId = input.required(...(ngDevMode ? [{ debugName: "surfaceId" }] : /* istanbul ignore next */ []));
561
+ componentId = input(...(ngDevMode ? [undefined, { debugName: "componentId" }] : /* istanbul ignore next */ []));
562
+ dataContextPath = input('/', ...(ngDevMode ? [{ debugName: "dataContextPath" }] : /* istanbul ignore next */ []));
563
+ markdownRenderer = inject(MarkdownRenderer);
564
+ variant = computed$1(() => this.props()['variant']?.value() || 'body', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
565
+ text = computed$1(() => this.props()['text']?.value() || '', ...(ngDevMode ? [{ debugName: "text" }] : /* istanbul ignore next */ []));
566
+ resolvedText = signal('', ...(ngDevMode ? [{ debugName: "resolvedText" }] : /* istanbul ignore next */ []));
567
+ renderRequestId = 0;
568
+ constructor() {
569
+ effect$1(() => {
570
+ const text = this.text();
571
+ const variant = this.variant();
572
+ let value = text;
573
+ switch (variant) {
574
+ case 'h1':
575
+ value = `# ${text}`;
576
+ break;
577
+ case 'h2':
578
+ value = `## ${text}`;
579
+ break;
580
+ case 'h3':
581
+ value = `### ${text}`;
582
+ break;
583
+ case 'h4':
584
+ value = `#### ${text}`;
585
+ break;
586
+ case 'h5':
587
+ value = `##### ${text}`;
588
+ break;
589
+ case 'caption':
590
+ value = `*${text}*`;
591
+ break;
592
+ }
593
+ const requestId = ++this.renderRequestId;
594
+ this.markdownRenderer.render(value).then(rendered => {
595
+ if (requestId === this.renderRequestId) {
596
+ this.resolvedText.set(rendered);
597
+ }
598
+ });
599
+ });
600
+ }
601
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: TextComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
602
+ 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 } }, ngImport: i0, template: `
603
+ <span [class]="'a2ui-text ' + variant()" [innerHTML]="resolvedText()">
604
+ </span>
605
+ `, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
606
+ }
607
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: TextComponent, decorators: [{
608
+ type: Component,
609
+ args: [{
610
+ selector: 'a2ui-v09-text',
611
+ standalone: true,
612
+ template: `
613
+ <span [class]="'a2ui-text ' + variant()" [innerHTML]="resolvedText()">
614
+ </span>
615
+ `,
616
+ changeDetection: ChangeDetectionStrategy.OnPush,
617
+ }]
618
+ }], 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 }] }] } });
619
+
620
+ /**
621
+ * Copyright 2026 Google LLC
622
+ *
623
+ * Licensed under the Apache License, Version 2.0 (the "License");
624
+ * you may not use this file except in compliance with the License.
625
+ * You may obtain a copy of the License at
626
+ *
627
+ * http://www.apache.org/licenses/LICENSE-2.0
628
+ *
629
+ * Unless required by applicable law or agreed to in writing, software
630
+ * distributed under the License is distributed on an "AS IS" BASIS,
631
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
632
+ * See the License for the specific language governing permissions and
633
+ * limitations under the License.
634
+ */
635
+ /**
636
+ * Angular implementation of the A2UI Row component (v0.9).
637
+ *
638
+ * Arranges child components in a horizontal flex layout. Supports both static
639
+ * lists of children and repeating templates bound to a data collection.
640
+ */
641
+ class RowComponent {
642
+ /**
643
+ * Reactive properties resolved from the A2UI {@link ComponentModel}.
644
+ *
645
+ * Expected properties:
646
+ * - `children`: A list of component IDs OR a repeating collection definition.
647
+ * - `justify`: Flexbox justify-content value (e.g., 'flex-start', 'center').
648
+ * - `align`: Flexbox align-items value (e.g., 'flex-start', 'center').
649
+ */
650
+ props = input({}, ...(ngDevMode ? [{ debugName: "props" }] : /* istanbul ignore next */ []));
651
+ surfaceId = input.required(...(ngDevMode ? [{ debugName: "surfaceId" }] : /* istanbul ignore next */ []));
652
+ componentId = input(...(ngDevMode ? [undefined, { debugName: "componentId" }] : /* istanbul ignore next */ []));
653
+ dataContextPath = input('/', ...(ngDevMode ? [{ debugName: "dataContextPath" }] : /* istanbul ignore next */ []));
654
+ justify = computed$1(() => this.props()['justify']?.value(), ...(ngDevMode ? [{ debugName: "justify" }] : /* istanbul ignore next */ []));
655
+ align = computed$1(() => this.props()['align']?.value(), ...(ngDevMode ? [{ debugName: "align" }] : /* istanbul ignore next */ []));
656
+ children = computed$1(() => {
657
+ const raw = this.props()['children']?.value() || [];
658
+ return Array.isArray(raw) ? raw : [];
659
+ }, ...(ngDevMode ? [{ debugName: "children" }] : /* istanbul ignore next */ []));
660
+ isRepeating = computed$1(() => {
661
+ return !!this.props()['children']?.raw?.componentId;
662
+ }, ...(ngDevMode ? [{ debugName: "isRepeating" }] : /* istanbul ignore next */ []));
663
+ templateId = computed$1(() => {
664
+ return this.props()['children']?.raw?.componentId;
665
+ }, ...(ngDevMode ? [{ debugName: "templateId" }] : /* istanbul ignore next */ []));
666
+ normalizedChildren = computed$1(() => {
667
+ if (this.isRepeating())
668
+ return [];
669
+ return this.children().map(child => {
670
+ if (typeof child === 'object' && child !== null && 'id' in child) {
671
+ return child;
672
+ }
673
+ return { id: child, basePath: this.dataContextPath() };
674
+ });
675
+ }, ...(ngDevMode ? [{ debugName: "normalizedChildren" }] : /* istanbul ignore next */ []));
676
+ getNormalizedPath(index) {
677
+ return getNormalizedPath(this.props()['children']?.raw?.path, this.dataContextPath(), index);
678
+ }
679
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: RowComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
680
+ 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 } }, ngImport: i0, template: `
681
+ <div
682
+ class="a2ui-row"
683
+ [style.justify-content]="justify()"
684
+ [style.align-items]="align()"
685
+ style="display: flex; flex-direction: row; width: 100%; gap: 4px;"
686
+ >
687
+ @if (!isRepeating()) {
688
+ @for (child of normalizedChildren(); track child.id) {
689
+ <a2ui-v09-component-host
690
+ [componentKey]="child"
691
+ [surfaceId]="surfaceId()"
692
+ >
693
+ </a2ui-v09-component-host>
694
+ }
695
+ }
696
+
697
+ @if (isRepeating()) {
698
+ @for (item of children(); track item; let i = $index) {
699
+ <a2ui-v09-component-host
700
+ [componentKey]="{ id: templateId()!, basePath: getNormalizedPath(i) }"
701
+ [surfaceId]="surfaceId()"
702
+ >
703
+ </a2ui-v09-component-host>
704
+ }
705
+ }
706
+ </div>
707
+ `, isInline: true, dependencies: [{ kind: "component", type: ComponentHostComponent, selector: "a2ui-v09-component-host", inputs: ["componentKey", "surfaceId"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
708
+ }
709
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: RowComponent, decorators: [{
710
+ type: Component,
711
+ args: [{
712
+ selector: 'a2ui-v09-row',
713
+ standalone: true,
714
+ imports: [ComponentHostComponent],
715
+ template: `
716
+ <div
717
+ class="a2ui-row"
718
+ [style.justify-content]="justify()"
719
+ [style.align-items]="align()"
720
+ style="display: flex; flex-direction: row; width: 100%; gap: 4px;"
721
+ >
722
+ @if (!isRepeating()) {
723
+ @for (child of normalizedChildren(); track child.id) {
724
+ <a2ui-v09-component-host
725
+ [componentKey]="child"
726
+ [surfaceId]="surfaceId()"
727
+ >
728
+ </a2ui-v09-component-host>
729
+ }
730
+ }
731
+
732
+ @if (isRepeating()) {
733
+ @for (item of children(); track item; let i = $index) {
734
+ <a2ui-v09-component-host
735
+ [componentKey]="{ id: templateId()!, basePath: getNormalizedPath(i) }"
736
+ [surfaceId]="surfaceId()"
737
+ >
738
+ </a2ui-v09-component-host>
739
+ }
740
+ }
741
+ </div>
742
+ `,
743
+ changeDetection: ChangeDetectionStrategy.OnPush,
744
+ }]
745
+ }], 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 }] }] } });
746
+
747
+ /**
748
+ * Copyright 2026 Google LLC
749
+ *
750
+ * Licensed under the Apache License, Version 2.0 (the "License");
751
+ * you may not use this file except in compliance with the License.
752
+ * You may obtain a copy of the License at
753
+ *
754
+ * http://www.apache.org/licenses/LICENSE-2.0
755
+ *
756
+ * Unless required by applicable law or agreed to in writing, software
757
+ * distributed under the License is distributed on an "AS IS" BASIS,
758
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
759
+ * See the License for the specific language governing permissions and
760
+ * limitations under the License.
761
+ */
762
+ /**
763
+ * Angular implementation of the A2UI Column component (v0.9).
764
+ *
765
+ * Arranges child components in a vertical flex layout. Supports both static
766
+ * lists of children and repeating templates bound to a data collection.
767
+ */
768
+ class ColumnComponent {
769
+ /**
770
+ * Reactive properties resolved from the A2UI {@link ComponentModel}.
771
+ *
772
+ * Expected properties:
773
+ * - `children`: A list of component IDs OR a repeating collection definition.
774
+ * - `justify`: Flexbox justify-content value (e.g., 'flex-start', 'center').
775
+ * - `align`: Flexbox align-items value (e.g., 'flex-start', 'center').
776
+ */
777
+ props = input({}, ...(ngDevMode ? [{ debugName: "props" }] : /* istanbul ignore next */ []));
778
+ surfaceId = input.required(...(ngDevMode ? [{ debugName: "surfaceId" }] : /* istanbul ignore next */ []));
779
+ componentId = input(...(ngDevMode ? [undefined, { debugName: "componentId" }] : /* istanbul ignore next */ []));
780
+ dataContextPath = input('/', ...(ngDevMode ? [{ debugName: "dataContextPath" }] : /* istanbul ignore next */ []));
781
+ justify = computed$1(() => this.props()['justify']?.value(), ...(ngDevMode ? [{ debugName: "justify" }] : /* istanbul ignore next */ []));
782
+ align = computed$1(() => this.props()['align']?.value(), ...(ngDevMode ? [{ debugName: "align" }] : /* istanbul ignore next */ []));
783
+ children = computed$1(() => {
784
+ const raw = this.props()['children']?.value() || [];
785
+ return Array.isArray(raw) ? raw : [];
786
+ }, ...(ngDevMode ? [{ debugName: "children" }] : /* istanbul ignore next */ []));
787
+ isRepeating = computed$1(() => {
788
+ return !!this.props()['children']?.raw?.componentId;
789
+ }, ...(ngDevMode ? [{ debugName: "isRepeating" }] : /* istanbul ignore next */ []));
790
+ templateId = computed$1(() => {
791
+ return this.props()['children']?.raw?.componentId;
792
+ }, ...(ngDevMode ? [{ debugName: "templateId" }] : /* istanbul ignore next */ []));
793
+ normalizedChildren = computed$1(() => {
794
+ if (this.isRepeating())
795
+ return [];
796
+ return this.children().map(child => {
797
+ if (typeof child === 'object' && child !== null && 'id' in child) {
798
+ return child;
799
+ }
800
+ return { id: child, basePath: this.dataContextPath() };
801
+ });
802
+ }, ...(ngDevMode ? [{ debugName: "normalizedChildren" }] : /* istanbul ignore next */ []));
803
+ getNormalizedPath(index) {
804
+ return getNormalizedPath(this.props()['children']?.raw?.path, this.dataContextPath(), index);
805
+ }
806
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ColumnComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
807
+ 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 } }, ngImport: i0, template: `
808
+ <div
809
+ class="a2ui-column"
810
+ [style.justify-content]="justify()"
811
+ [style.align-items]="align()"
812
+ style="display: flex; flex-direction: column; width: 100%; gap: 4px;"
813
+ >
814
+ @if (!isRepeating()) {
815
+ @for (child of normalizedChildren(); track child.id) {
816
+ <a2ui-v09-component-host
817
+ [componentKey]="child"
818
+ [surfaceId]="surfaceId()"
819
+ >
820
+ </a2ui-v09-component-host>
821
+ }
822
+ }
823
+
824
+ @if (isRepeating()) {
825
+ @for (item of children(); track item; let i = $index) {
826
+ <a2ui-v09-component-host
827
+ [componentKey]="{ id: templateId()!, basePath: getNormalizedPath(i) }"
828
+ [surfaceId]="surfaceId()"
829
+ >
830
+ </a2ui-v09-component-host>
831
+ }
832
+ }
833
+ </div>
834
+ `, isInline: true, dependencies: [{ kind: "component", type: ComponentHostComponent, selector: "a2ui-v09-component-host", inputs: ["componentKey", "surfaceId"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
835
+ }
836
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ColumnComponent, decorators: [{
837
+ type: Component,
838
+ args: [{
839
+ selector: 'a2ui-v09-column',
840
+ standalone: true,
841
+ imports: [ComponentHostComponent],
842
+ template: `
843
+ <div
844
+ class="a2ui-column"
845
+ [style.justify-content]="justify()"
846
+ [style.align-items]="align()"
847
+ style="display: flex; flex-direction: column; width: 100%; gap: 4px;"
848
+ >
849
+ @if (!isRepeating()) {
850
+ @for (child of normalizedChildren(); track child.id) {
851
+ <a2ui-v09-component-host
852
+ [componentKey]="child"
853
+ [surfaceId]="surfaceId()"
854
+ >
855
+ </a2ui-v09-component-host>
856
+ }
857
+ }
858
+
859
+ @if (isRepeating()) {
860
+ @for (item of children(); track item; let i = $index) {
861
+ <a2ui-v09-component-host
862
+ [componentKey]="{ id: templateId()!, basePath: getNormalizedPath(i) }"
863
+ [surfaceId]="surfaceId()"
864
+ >
865
+ </a2ui-v09-component-host>
866
+ }
867
+ }
868
+ </div>
869
+ `,
870
+ changeDetection: ChangeDetectionStrategy.OnPush,
871
+ }]
872
+ }], 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 }] }] } });
873
+
874
+ /**
875
+ * Copyright 2026 Google LLC
876
+ *
877
+ * Licensed under the Apache License, Version 2.0 (the "License");
878
+ * you may not use this file except in compliance with the License.
879
+ * You may obtain a copy of the License at
880
+ *
881
+ * http://www.apache.org/licenses/LICENSE-2.0
882
+ *
883
+ * Unless required by applicable law or agreed to in writing, software
884
+ * distributed under the License is distributed on an "AS IS" BASIS,
885
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
886
+ * See the License for the specific language governing permissions and
887
+ * limitations under the License.
888
+ */
889
+ /**
890
+ * Angular implementation of the A2UI Button component (v0.9).
891
+ *
892
+ * Renders a clickable button with a single child component (usually Text).
893
+ * Dispatches an action when clicked if an `action` property is provided.
894
+ */
895
+ class ButtonComponent {
896
+ /**
897
+ * Reactive properties resolved from the A2UI {@link ComponentModel}.
898
+ *
899
+ * Expected properties:
900
+ * - `child`: The ID of the component to render inside the button.
901
+ * - `variant`: Button style variant ('default', 'primary', 'borderless').
902
+ * - `action`: The A2UI action to dispatch on click.
903
+ * - `checks`: Optional validation rules.
904
+ */
905
+ props = input({}, ...(ngDevMode ? [{ debugName: "props" }] : /* istanbul ignore next */ []));
906
+ surfaceId = input.required(...(ngDevMode ? [{ debugName: "surfaceId" }] : /* istanbul ignore next */ []));
907
+ componentId = input.required(...(ngDevMode ? [{ debugName: "componentId" }] : /* istanbul ignore next */ []));
908
+ dataContextPath = input('/', ...(ngDevMode ? [{ debugName: "dataContextPath" }] : /* istanbul ignore next */ []));
909
+ rendererService = inject(A2uiRendererService);
910
+ variant = computed$1(() => this.props()['variant']?.value() ?? 'default', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
911
+ child = computed$1(() => this.props()['child']?.value(), ...(ngDevMode ? [{ debugName: "child" }] : /* istanbul ignore next */ []));
912
+ action = computed$1(() => this.props()['action']?.value(), ...(ngDevMode ? [{ debugName: "action" }] : /* istanbul ignore next */ []));
913
+ handleClick() {
914
+ const action = this.action();
915
+ if (action) {
916
+ const surface = this.rendererService.surfaceGroup?.getSurface(this.surfaceId());
917
+ if (surface) {
918
+ const dataContext = new DataContext(surface, this.dataContextPath());
919
+ const resolvedAction = dataContext.resolveAction(action);
920
+ surface.dispatchAction(resolvedAction, this.componentId());
921
+ }
922
+ }
923
+ }
924
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
925
+ 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 } }, ngImport: i0, template: `
926
+ <button
927
+ [type]="variant() === 'primary' ? 'submit' : 'button'"
928
+ [class]="'a2ui-button ' + variant()"
929
+ (click)="handleClick()"
930
+ [disabled]="props()['isValid']?.value() === false"
931
+ >
932
+ @if (child()) {
933
+ <a2ui-v09-component-host
934
+ [componentKey]="child()!"
935
+ [surfaceId]="surfaceId()"
936
+ >
937
+ </a2ui-v09-component-host>
938
+ }
939
+ </button>
940
+ `, isInline: true, styles: [".a2ui-button{padding:8px 16px;border-radius:4px;border:1px solid #ccc;cursor:pointer}.a2ui-button.primary{background-color:#007bff;color:#fff;border-color:#0069d9}.a2ui-button.borderless{background:none;border:none;padding:0;color:#007bff}.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 });
941
+ }
942
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ButtonComponent, decorators: [{
943
+ type: Component,
944
+ args: [{ selector: 'a2ui-v09-button', standalone: true, imports: [ComponentHostComponent], template: `
945
+ <button
946
+ [type]="variant() === 'primary' ? 'submit' : 'button'"
947
+ [class]="'a2ui-button ' + variant()"
948
+ (click)="handleClick()"
949
+ [disabled]="props()['isValid']?.value() === false"
950
+ >
951
+ @if (child()) {
952
+ <a2ui-v09-component-host
953
+ [componentKey]="child()!"
954
+ [surfaceId]="surfaceId()"
955
+ >
956
+ </a2ui-v09-component-host>
957
+ }
958
+ </button>
959
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".a2ui-button{padding:8px 16px;border-radius:4px;border:1px solid #ccc;cursor:pointer}.a2ui-button.primary{background-color:#007bff;color:#fff;border-color:#0069d9}.a2ui-button.borderless{background:none;border:none;padding:0;color:#007bff}.a2ui-button:disabled{background-color:#e9ecef;color:#6c757d;border-color:#ced4da;cursor:not-allowed}\n"] }]
960
+ }], 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 }] }] } });
961
+
962
+ /**
963
+ * Copyright 2026 Google LLC
964
+ *
965
+ * Licensed under the Apache License, Version 2.0 (the "License");
966
+ * you may not use this file except in compliance with the License.
967
+ * You may obtain a copy of the License at
968
+ *
969
+ * http://www.apache.org/licenses/LICENSE-2.0
970
+ *
971
+ * Unless required by applicable law or agreed to in writing, software
972
+ * distributed under the License is distributed on an "AS IS" BASIS,
973
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
974
+ * See the License for the specific language governing permissions and
975
+ * limitations under the License.
976
+ */
977
+ /**
978
+ * Angular implementation of the A2UI TextField component (v0.9).
979
+ *
980
+ * Renders a text input field with an optional label and placeholder.
981
+ * Updates the bound data model property on every input change.
982
+ */
983
+ class TextFieldComponent {
984
+ /**
985
+ * Reactive properties resolved from the A2UI {@link ComponentModel}.
986
+ *
987
+ * Expected properties:
988
+ * - `value`: The current string value of the input.
989
+ * - `label`: Optional label text to display above the input.
990
+ * - `placeholder`: Hint text shown when the input is empty.
991
+ * - `variant`: Input type variant ('default', 'obscured' (password), 'number').
992
+ * - `checks`: Optional validation rules.
993
+ */
994
+ props = input({}, ...(ngDevMode ? [{ debugName: "props" }] : /* istanbul ignore next */ []));
995
+ surfaceId = input.required(...(ngDevMode ? [{ debugName: "surfaceId" }] : /* istanbul ignore next */ []));
996
+ componentId = input(...(ngDevMode ? [undefined, { debugName: "componentId" }] : /* istanbul ignore next */ []));
997
+ dataContextPath = input('/', ...(ngDevMode ? [{ debugName: "dataContextPath" }] : /* istanbul ignore next */ []));
998
+ label = computed$1(() => this.props()['label']?.value(), ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
999
+ value = computed$1(() => this.props()['value']?.value() || '', ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
1000
+ placeholder = computed$1(() => this.props()['placeholder']?.value() || '', ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
1001
+ variant = computed$1(() => this.props()['variant']?.value(), ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
1002
+ inputType = computed$1(() => {
1003
+ switch (this.variant()) {
1004
+ case 'obscured':
1005
+ return 'password';
1006
+ case 'number':
1007
+ return 'number';
1008
+ default:
1009
+ return 'text';
1010
+ }
1011
+ }, ...(ngDevMode ? [{ debugName: "inputType" }] : /* istanbul ignore next */ []));
1012
+ handleInput(event) {
1013
+ const value = event.target.value;
1014
+ // Update the data path. If anything is listening to this path, it will be
1015
+ // notified.
1016
+ this.props()['value']?.onUpdate(value);
1017
+ }
1018
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: TextFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1019
+ 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 } }, ngImport: i0, template: `
1020
+ <div class="a2ui-text-field-container">
1021
+ @if (label()) {
1022
+ <label>{{ label() }}</label>
1023
+ }
1024
+ <input
1025
+ [type]="inputType()"
1026
+ [value]="value()"
1027
+ (input)="handleInput($event)"
1028
+ [placeholder]="placeholder()"
1029
+ [class.invalid]="props()['isValid']?.value() === false"
1030
+ />
1031
+ @for (message of props()['validationErrors']?.value(); track message) {
1032
+ <div class="a2ui-error-message">{{ message }}</div>
1033
+ }
1034
+ </div>
1035
+ `, isInline: true, styles: [":host{display:block;flex:1;width:100%}.a2ui-text-field-container{display:flex;flex-direction:column;gap:4px;margin:4px}input{padding:8px;border:1px solid #ccc;border-radius:4px}input.invalid{border-color:red}.a2ui-error-message{color:red;font-size:12px}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1036
+ }
1037
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: TextFieldComponent, decorators: [{
1038
+ type: Component,
1039
+ args: [{ selector: 'a2ui-v09-text-field', standalone: true, imports: [], template: `
1040
+ <div class="a2ui-text-field-container">
1041
+ @if (label()) {
1042
+ <label>{{ label() }}</label>
1043
+ }
1044
+ <input
1045
+ [type]="inputType()"
1046
+ [value]="value()"
1047
+ (input)="handleInput($event)"
1048
+ [placeholder]="placeholder()"
1049
+ [class.invalid]="props()['isValid']?.value() === false"
1050
+ />
1051
+ @for (message of props()['validationErrors']?.value(); track message) {
1052
+ <div class="a2ui-error-message">{{ message }}</div>
1053
+ }
1054
+ </div>
1055
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block;flex:1;width:100%}.a2ui-text-field-container{display:flex;flex-direction:column;gap:4px;margin:4px}input{padding:8px;border:1px solid #ccc;border-radius:4px}input.invalid{border-color:red}.a2ui-error-message{color:red;font-size:12px}\n"] }]
1056
+ }], 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 }] }] } });
1057
+
1058
+ /**
1059
+ * Copyright 2026 Google LLC
1060
+ *
1061
+ * Licensed under the Apache License, Version 2.0 (the "License");
1062
+ * you may not use this file except in compliance with the License.
1063
+ * You may obtain a copy of the License at
1064
+ *
1065
+ * http://www.apache.org/licenses/LICENSE-2.0
1066
+ *
1067
+ * Unless required by applicable law or agreed to in writing, software
1068
+ * distributed under the License is distributed on an "AS IS" BASIS,
1069
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1070
+ * See the License for the specific language governing permissions and
1071
+ * limitations under the License.
1072
+ */
1073
+ /**
1074
+ * Angular implementation of the A2UI Image component (v0.9).
1075
+ *
1076
+ * Renders an image with configurable fit and shape variants.
1077
+ */
1078
+ class ImageComponent {
1079
+ /**
1080
+ * Reactive properties resolved from the A2UI {@link ComponentModel}.
1081
+ *
1082
+ * Expected properties:
1083
+ * - `url`: The absolute URL of the image.
1084
+ * - `description`: Accessibility text for the image.
1085
+ * - `fit`: Object-fit mode ('cover', 'contain', 'fill', 'none', 'scale-down').
1086
+ * - `variant`: Style variant ('default', 'circle', 'rounded', 'icon', 'avatar', 'smallFeature', 'mediumFeature', 'largeFeature', 'header').
1087
+ */
1088
+ props = input({}, ...(ngDevMode ? [{ debugName: "props" }] : /* istanbul ignore next */ []));
1089
+ surfaceId = input.required(...(ngDevMode ? [{ debugName: "surfaceId" }] : /* istanbul ignore next */ []));
1090
+ componentId = input(...(ngDevMode ? [undefined, { debugName: "componentId" }] : /* istanbul ignore next */ []));
1091
+ dataContextPath = input('/', ...(ngDevMode ? [{ debugName: "dataContextPath" }] : /* istanbul ignore next */ []));
1092
+ url = computed$1(() => this.props()['url']?.value(), ...(ngDevMode ? [{ debugName: "url" }] : /* istanbul ignore next */ []));
1093
+ description = computed$1(() => this.props()['description']?.value() || '', ...(ngDevMode ? [{ debugName: "description" }] : /* istanbul ignore next */ []));
1094
+ fit = computed$1(() => this.props()['fit']?.value() || 'cover', ...(ngDevMode ? [{ debugName: "fit" }] : /* istanbul ignore next */ []));
1095
+ variant = computed$1(() => this.props()['variant']?.value() || 'default', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
1096
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ImageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1097
+ 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 } }, ngImport: i0, template: `
1098
+ <img
1099
+ [src]="url()"
1100
+ [alt]="description()"
1101
+ [style.object-fit]="fit()"
1102
+ [class]="'a2ui-image ' + variant()"
1103
+ />
1104
+ `, 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:8px}.a2ui-image.icon{width:24px;height:24px}.a2ui-image.avatar{width:40px;height:40px;border-radius:50%}.a2ui-image.smallFeature{width:100px;height:100px}.a2ui-image.mediumFeature{max-width:300px;height:auto}.a2ui-image.largeFeature{width:100%;max-height:400px}.a2ui-image.header{width:100%;height:200px}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1105
+ }
1106
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ImageComponent, decorators: [{
1107
+ type: Component,
1108
+ args: [{ selector: 'a2ui-v09-image', standalone: true, imports: [], template: `
1109
+ <img
1110
+ [src]="url()"
1111
+ [alt]="description()"
1112
+ [style.object-fit]="fit()"
1113
+ [class]="'a2ui-image ' + variant()"
1114
+ />
1115
+ `, 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:8px}.a2ui-image.icon{width:24px;height:24px}.a2ui-image.avatar{width:40px;height:40px;border-radius:50%}.a2ui-image.smallFeature{width:100px;height:100px}.a2ui-image.mediumFeature{max-width:300px;height:auto}.a2ui-image.largeFeature{width:100%;max-height:400px}.a2ui-image.header{width:100%;height:200px}\n"] }]
1116
+ }], 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 }] }] } });
1117
+
1118
+ /**
1119
+ * Copyright 2026 Google LLC
1120
+ *
1121
+ * Licensed under the Apache License, Version 2.0 (the "License");
1122
+ * you may not use this file except in compliance with the License.
1123
+ * You may obtain a copy of the License at
1124
+ *
1125
+ * http://www.apache.org/licenses/LICENSE-2.0
1126
+ *
1127
+ * Unless required by applicable law or agreed to in writing, software
1128
+ * distributed under the License is distributed on an "AS IS" BASIS,
1129
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1130
+ * See the License for the specific language governing permissions and
1131
+ * limitations under the License.
1132
+ */
1133
+ /**
1134
+ * Angular implementation of the A2UI Icon component (v0.9).
1135
+ *
1136
+ * Supports both Material Icons (by name) and custom SVG icons (by path).
1137
+ */
1138
+ class IconComponent {
1139
+ /**
1140
+ * Reactive properties resolved from the A2UI {@link ComponentModel}.
1141
+ *
1142
+ * Expected properties:
1143
+ * - `name`: The name of the icon (e.g., 'home', 'settings') OR an object
1144
+ * with a `path` property for SVG icons.
1145
+ * - `color`: The CSS color to apply to the icon.
1146
+ */
1147
+ props = input({}, ...(ngDevMode ? [{ debugName: "props" }] : /* istanbul ignore next */ []));
1148
+ surfaceId = input.required(...(ngDevMode ? [{ debugName: "surfaceId" }] : /* istanbul ignore next */ []));
1149
+ componentId = input(...(ngDevMode ? [undefined, { debugName: "componentId" }] : /* istanbul ignore next */ []));
1150
+ dataContextPath = input('/', ...(ngDevMode ? [{ debugName: "dataContextPath" }] : /* istanbul ignore next */ []));
1151
+ color = computed$1(() => this.props()['color']?.value(), ...(ngDevMode ? [{ debugName: "color" }] : /* istanbul ignore next */ []));
1152
+ iconNameRaw = computed$1(() => this.props()['name']?.value(), ...(ngDevMode ? [{ debugName: "iconNameRaw" }] : /* istanbul ignore next */ []));
1153
+ isPath = computed$1(() => {
1154
+ const name = this.iconNameRaw();
1155
+ return typeof name === 'object' && name !== null && 'path' in name;
1156
+ }, ...(ngDevMode ? [{ debugName: "isPath" }] : /* istanbul ignore next */ []));
1157
+ path = computed$1(() => {
1158
+ const name = this.iconNameRaw();
1159
+ return name?.path || '';
1160
+ }, ...(ngDevMode ? [{ debugName: "path" }] : /* istanbul ignore next */ []));
1161
+ iconName = computed$1(() => {
1162
+ const name = this.iconNameRaw();
1163
+ if (typeof name !== 'string')
1164
+ return '';
1165
+ // Convert camelCase to snake_case for Material Icons
1166
+ return name.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);
1167
+ }, ...(ngDevMode ? [{ debugName: "iconName" }] : /* istanbul ignore next */ []));
1168
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: IconComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1169
+ 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 } }, ngImport: i0, template: `
1170
+ @if (isPath()) {
1171
+ <svg class="a2ui-icon svg" viewBox="0 0 24 24" [style.fill]="color() || 'currentColor'">
1172
+ <path [attr.d]="path()"></path>
1173
+ </svg>
1174
+ } @else {
1175
+ <i class="material-icons a2ui-icon" [style.color]="color()">
1176
+ {{ iconName() }}
1177
+ </i>
1178
+ }
1179
+ `, isInline: true, styles: [".a2ui-icon{display:inline-block;width:24px;height:24px;font-size:24px;font-family:Material Icons;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 });
1180
+ }
1181
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: IconComponent, decorators: [{
1182
+ type: Component,
1183
+ args: [{ selector: 'a2ui-v09-icon', standalone: true, imports: [], template: `
1184
+ @if (isPath()) {
1185
+ <svg class="a2ui-icon svg" viewBox="0 0 24 24" [style.fill]="color() || 'currentColor'">
1186
+ <path [attr.d]="path()"></path>
1187
+ </svg>
1188
+ } @else {
1189
+ <i class="material-icons a2ui-icon" [style.color]="color()">
1190
+ {{ iconName() }}
1191
+ </i>
1192
+ }
1193
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".a2ui-icon{display:inline-block;width:24px;height:24px;font-size:24px;font-family:Material Icons;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"] }]
1194
+ }], 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 }] }] } });
1195
+
1196
+ /**
1197
+ * Copyright 2026 Google LLC
1198
+ *
1199
+ * Licensed under the Apache License, Version 2.0 (the "License");
1200
+ * you may not use this file except in compliance with the License.
1201
+ * You may obtain a copy of the License at
1202
+ *
1203
+ * http://www.apache.org/licenses/LICENSE-2.0
1204
+ *
1205
+ * Unless required by applicable law or agreed to in writing, software
1206
+ * distributed under the License is distributed on an "AS IS" BASIS,
1207
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1208
+ * See the License for the specific language governing permissions and
1209
+ * limitations under the License.
1210
+ */
1211
+ /**
1212
+ * Angular implementation of the A2UI Video component (v0.9).
1213
+ *
1214
+ * Renders a video player with standard controls and an optional poster image.
1215
+ */
1216
+ class VideoComponent {
1217
+ /**
1218
+ * Reactive properties resolved from the A2UI {@link ComponentModel}.
1219
+ *
1220
+ * Expected properties:
1221
+ * - `url`: The absolute URL of the video file.
1222
+ * - `posterUrl`: The URL of an image to show before the video starts.
1223
+ */
1224
+ props = input({}, ...(ngDevMode ? [{ debugName: "props" }] : /* istanbul ignore next */ []));
1225
+ surfaceId = input.required(...(ngDevMode ? [{ debugName: "surfaceId" }] : /* istanbul ignore next */ []));
1226
+ componentId = input(...(ngDevMode ? [undefined, { debugName: "componentId" }] : /* istanbul ignore next */ []));
1227
+ dataContextPath = input('/', ...(ngDevMode ? [{ debugName: "dataContextPath" }] : /* istanbul ignore next */ []));
1228
+ url = computed$1(() => this.props()['url']?.value(), ...(ngDevMode ? [{ debugName: "url" }] : /* istanbul ignore next */ []));
1229
+ posterUrl = computed$1(() => this.props()['posterUrl']?.value(), ...(ngDevMode ? [{ debugName: "posterUrl" }] : /* istanbul ignore next */ []));
1230
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: VideoComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1231
+ 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 } }, ngImport: i0, template: `
1232
+ <div class="a2ui-video-container">
1233
+ <video
1234
+ [attr.src]="url() || null"
1235
+ controls
1236
+ [attr.poster]="posterUrl() || null"
1237
+ class="a2ui-video"
1238
+ >
1239
+ Your browser does not support the video tag.
1240
+ </video>
1241
+ </div>
1242
+ `, isInline: true, styles: [".a2ui-video-container{width:100%;max-width:100%}.a2ui-video{width:100%;height:auto;display:block}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1243
+ }
1244
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: VideoComponent, decorators: [{
1245
+ type: Component,
1246
+ args: [{ selector: 'a2ui-v09-video', standalone: true, imports: [], template: `
1247
+ <div class="a2ui-video-container">
1248
+ <video
1249
+ [attr.src]="url() || null"
1250
+ controls
1251
+ [attr.poster]="posterUrl() || null"
1252
+ class="a2ui-video"
1253
+ >
1254
+ Your browser does not support the video tag.
1255
+ </video>
1256
+ </div>
1257
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".a2ui-video-container{width:100%;max-width:100%}.a2ui-video{width:100%;height:auto;display:block}\n"] }]
1258
+ }], 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 }] }] } });
1259
+
1260
+ /**
1261
+ * Copyright 2026 Google LLC
1262
+ *
1263
+ * Licensed under the Apache License, Version 2.0 (the "License");
1264
+ * you may not use this file except in compliance with the License.
1265
+ * You may obtain a copy of the License at
1266
+ *
1267
+ * http://www.apache.org/licenses/LICENSE-2.0
1268
+ *
1269
+ * Unless required by applicable law or agreed to in writing, software
1270
+ * distributed under the License is distributed on an "AS IS" BASIS,
1271
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1272
+ * See the License for the specific language governing permissions and
1273
+ * limitations under the License.
1274
+ */
1275
+ /**
1276
+ * Angular implementation of the A2UI AudioPlayer component (v0.9).
1277
+ *
1278
+ * Renders an audio player with standard controls and an optional description.
1279
+ */
1280
+ class AudioPlayerComponent {
1281
+ /**
1282
+ * Reactive properties resolved from the A2UI {@link ComponentModel}.
1283
+ *
1284
+ * Expected properties:
1285
+ * - `url`: The absolute URL of the audio file.
1286
+ * - `description`: Optional text to display above the player.
1287
+ */
1288
+ props = input({}, ...(ngDevMode ? [{ debugName: "props" }] : /* istanbul ignore next */ []));
1289
+ surfaceId = input(...(ngDevMode ? [undefined, { debugName: "surfaceId" }] : /* istanbul ignore next */ []));
1290
+ componentId = input(...(ngDevMode ? [undefined, { debugName: "componentId" }] : /* istanbul ignore next */ []));
1291
+ dataContextPath = input(...(ngDevMode ? [undefined, { debugName: "dataContextPath" }] : /* istanbul ignore next */ []));
1292
+ description = computed$1(() => this.props()['description']?.value(), ...(ngDevMode ? [{ debugName: "description" }] : /* istanbul ignore next */ []));
1293
+ url = computed$1(() => this.props()['url']?.value(), ...(ngDevMode ? [{ debugName: "url" }] : /* istanbul ignore next */ []));
1294
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: AudioPlayerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1295
+ 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 } }, ngImport: i0, template: `
1296
+ <div class="a2ui-audio-player">
1297
+ @if (description()) {
1298
+ <div class="a2ui-audio-description">
1299
+ {{ description() }}
1300
+ </div>
1301
+ }
1302
+ <audio [attr.src]="url() || null" controls class="a2ui-audio">
1303
+ Your browser does not support the audio tag.
1304
+ </audio>
1305
+ </div>
1306
+ `, isInline: true, styles: [".a2ui-audio-player{display:flex;flex-direction:column;gap:8px;width:100%}.a2ui-audio-description{font-size:14px;color:#666}.a2ui-audio{width:100%}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1307
+ }
1308
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: AudioPlayerComponent, decorators: [{
1309
+ type: Component,
1310
+ args: [{ selector: 'a2ui-v09-audio-player', standalone: true, imports: [], template: `
1311
+ <div class="a2ui-audio-player">
1312
+ @if (description()) {
1313
+ <div class="a2ui-audio-description">
1314
+ {{ description() }}
1315
+ </div>
1316
+ }
1317
+ <audio [attr.src]="url() || null" controls class="a2ui-audio">
1318
+ Your browser does not support the audio tag.
1319
+ </audio>
1320
+ </div>
1321
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".a2ui-audio-player{display:flex;flex-direction:column;gap:8px;width:100%}.a2ui-audio-description{font-size:14px;color:#666}.a2ui-audio{width:100%}\n"] }]
1322
+ }], 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 }] }] } });
1323
+
1324
+ /**
1325
+ * Copyright 2026 Google LLC
1326
+ *
1327
+ * Licensed under the Apache License, Version 2.0 (the "License");
1328
+ * you may not use this file except in compliance with the License.
1329
+ * You may obtain a copy of the License at
1330
+ *
1331
+ * http://www.apache.org/licenses/LICENSE-2.0
1332
+ *
1333
+ * Unless required by applicable law or agreed to in writing, software
1334
+ * distributed under the License is distributed on an "AS IS" BASIS,
1335
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1336
+ * See the License for the specific language governing permissions and
1337
+ * limitations under the License.
1338
+ */
1339
+ /**
1340
+ * Angular implementation of the A2UI List component (v0.9).
1341
+ *
1342
+ * Renders a list of child components with support for ordered, unordered,
1343
+ * and unstyled layouts in both vertical and horizontal orientations.
1344
+ */
1345
+ class ListComponent {
1346
+ /**
1347
+ * Reactive properties resolved from the A2UI {@link ComponentModel}.
1348
+ *
1349
+ * Expected properties:
1350
+ * - `children`: A list of component IDs to render as list items.
1351
+ * - `listStyle`: The type of list ('ordered', 'unordered', 'none').
1352
+ * - `orientation`: The layout direction ('vertical', 'horizontal').
1353
+ */
1354
+ props = input({}, ...(ngDevMode ? [{ debugName: "props" }] : /* istanbul ignore next */ []));
1355
+ surfaceId = input.required(...(ngDevMode ? [{ debugName: "surfaceId" }] : /* istanbul ignore next */ []));
1356
+ componentId = input(...(ngDevMode ? [undefined, { debugName: "componentId" }] : /* istanbul ignore next */ []));
1357
+ dataContextPath = input('/', ...(ngDevMode ? [{ debugName: "dataContextPath" }] : /* istanbul ignore next */ []));
1358
+ listStyle = computed$1(() => this.props()['listStyle']?.value(), ...(ngDevMode ? [{ debugName: "listStyle" }] : /* istanbul ignore next */ []));
1359
+ orientation = computed$1(() => this.props()['orientation']?.value() || 'vertical', ...(ngDevMode ? [{ debugName: "orientation" }] : /* istanbul ignore next */ []));
1360
+ children = computed$1(() => {
1361
+ const raw = this.props()['children']?.value();
1362
+ return Array.isArray(raw) ? raw : [];
1363
+ }, ...(ngDevMode ? [{ debugName: "children" }] : /* istanbul ignore next */ []));
1364
+ listTag = computed$1(() => {
1365
+ const style = this.listStyle();
1366
+ if (style === 'ordered')
1367
+ return 'ol';
1368
+ if (style === 'unordered')
1369
+ return 'ul';
1370
+ return 'div';
1371
+ }, ...(ngDevMode ? [{ debugName: "listTag" }] : /* istanbul ignore next */ []));
1372
+ styleType = computed$1(() => {
1373
+ const style = this.listStyle();
1374
+ if (style === 'none')
1375
+ return 'none';
1376
+ return '';
1377
+ }, ...(ngDevMode ? [{ debugName: "styleType" }] : /* istanbul ignore next */ []));
1378
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1379
+ 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 } }, ngImport: i0, template: `
1380
+ @switch (listTag()) {
1381
+ @case ('ol') {
1382
+ <ol [class]="'a2ui-list ' + orientation()" [style.list-style-type]="styleType()">
1383
+ @for (child of children(); track child.id) {
1384
+ <li>
1385
+ <a2ui-v09-component-host
1386
+ [componentKey]="child"
1387
+ [surfaceId]="surfaceId()"
1388
+ >
1389
+ </a2ui-v09-component-host>
1390
+ </li>
1391
+ }
1392
+ </ol>
1393
+ }
1394
+ @case ('ul') {
1395
+ <ul [class]="'a2ui-list ' + orientation()" [style.list-style-type]="styleType()">
1396
+ @for (child of children(); track child.id) {
1397
+ <li>
1398
+ <a2ui-v09-component-host
1399
+ [componentKey]="child"
1400
+ [surfaceId]="surfaceId()"
1401
+ >
1402
+ </a2ui-v09-component-host>
1403
+ </li>
1404
+ }
1405
+ </ul>
1406
+ }
1407
+ @default {
1408
+ <div [class]="'a2ui-list ' + orientation()" style="list-style-type: none;">
1409
+ @for (child of children(); track child.id) {
1410
+ <div class="a2ui-list-item-none">
1411
+ <a2ui-v09-component-host
1412
+ [componentKey]="child"
1413
+ [surfaceId]="surfaceId()"
1414
+ >
1415
+ </a2ui-v09-component-host>
1416
+ </div>
1417
+ }
1418
+ </div>
1419
+ }
1420
+ }
1421
+ `, isInline: true, styles: [".a2ui-list{display:flex;padding-inline-start:24px;margin:0}.a2ui-list.vertical{flex-direction:column;gap:8px}.a2ui-list.horizontal{flex-direction:row;gap: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 });
1422
+ }
1423
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ListComponent, decorators: [{
1424
+ type: Component,
1425
+ args: [{ selector: 'a2ui-v09-list', standalone: true, imports: [ComponentHostComponent], template: `
1426
+ @switch (listTag()) {
1427
+ @case ('ol') {
1428
+ <ol [class]="'a2ui-list ' + orientation()" [style.list-style-type]="styleType()">
1429
+ @for (child of children(); track child.id) {
1430
+ <li>
1431
+ <a2ui-v09-component-host
1432
+ [componentKey]="child"
1433
+ [surfaceId]="surfaceId()"
1434
+ >
1435
+ </a2ui-v09-component-host>
1436
+ </li>
1437
+ }
1438
+ </ol>
1439
+ }
1440
+ @case ('ul') {
1441
+ <ul [class]="'a2ui-list ' + orientation()" [style.list-style-type]="styleType()">
1442
+ @for (child of children(); track child.id) {
1443
+ <li>
1444
+ <a2ui-v09-component-host
1445
+ [componentKey]="child"
1446
+ [surfaceId]="surfaceId()"
1447
+ >
1448
+ </a2ui-v09-component-host>
1449
+ </li>
1450
+ }
1451
+ </ul>
1452
+ }
1453
+ @default {
1454
+ <div [class]="'a2ui-list ' + orientation()" style="list-style-type: none;">
1455
+ @for (child of children(); track child.id) {
1456
+ <div class="a2ui-list-item-none">
1457
+ <a2ui-v09-component-host
1458
+ [componentKey]="child"
1459
+ [surfaceId]="surfaceId()"
1460
+ >
1461
+ </a2ui-v09-component-host>
1462
+ </div>
1463
+ }
1464
+ </div>
1465
+ }
1466
+ }
1467
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".a2ui-list{display:flex;padding-inline-start:24px;margin:0}.a2ui-list.vertical{flex-direction:column;gap:8px}.a2ui-list.horizontal{flex-direction:row;gap:16px;list-style-position:inside}.a2ui-list-item-none{display:block}.horizontal .a2ui-list-item-none{display:inline-block}\n"] }]
1468
+ }], 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 }] }] } });
1469
+
1470
+ /**
1471
+ * Copyright 2026 Google LLC
1472
+ *
1473
+ * Licensed under the Apache License, Version 2.0 (the "License");
1474
+ * you may not use this file except in compliance with the License.
1475
+ * You may obtain a copy of the License at
1476
+ *
1477
+ * http://www.apache.org/licenses/LICENSE-2.0
1478
+ *
1479
+ * Unless required by applicable law or agreed to in writing, software
1480
+ * distributed under the License is distributed on an "AS IS" BASIS,
1481
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1482
+ * See the License for the specific language governing permissions and
1483
+ * limitations under the License.
1484
+ */
1485
+ /**
1486
+ * Angular implementation of the A2UI Card component (v0.9).
1487
+ *
1488
+ * Renders a container with a shadow and rounded corners for grouping related content.
1489
+ */
1490
+ class CardComponent {
1491
+ /**
1492
+ * Reactive properties resolved from the A2UI {@link ComponentModel}.
1493
+ *
1494
+ * Expected properties:
1495
+ * - `child`: The component ID to render inside the card.
1496
+ */
1497
+ props = input({}, ...(ngDevMode ? [{ debugName: "props" }] : /* istanbul ignore next */ []));
1498
+ surfaceId = input.required(...(ngDevMode ? [{ debugName: "surfaceId" }] : /* istanbul ignore next */ []));
1499
+ componentId = input(...(ngDevMode ? [undefined, { debugName: "componentId" }] : /* istanbul ignore next */ []));
1500
+ dataContextPath = input('/', ...(ngDevMode ? [{ debugName: "dataContextPath" }] : /* istanbul ignore next */ []));
1501
+ child = computed$1(() => this.props()['child']?.value(), ...(ngDevMode ? [{ debugName: "child" }] : /* istanbul ignore next */ []));
1502
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: CardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1503
+ 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 } }, ngImport: i0, template: `
1504
+ <div class="a2ui-card">
1505
+ @if (child()) {
1506
+ <a2ui-v09-component-host
1507
+ [componentKey]="child()!"
1508
+ [surfaceId]="surfaceId()"
1509
+ >
1510
+ </a2ui-v09-component-host>
1511
+ }
1512
+ </div>
1513
+ `, isInline: true, styles: [".a2ui-card{padding:16px;border-radius:8px;box-shadow:0 4px 6px #0000001a;background-color:#fff;border:1px solid #eee}\n"], dependencies: [{ kind: "component", type: ComponentHostComponent, selector: "a2ui-v09-component-host", inputs: ["componentKey", "surfaceId"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1514
+ }
1515
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: CardComponent, decorators: [{
1516
+ type: Component,
1517
+ args: [{ selector: 'a2ui-v09-card', standalone: true, imports: [ComponentHostComponent], template: `
1518
+ <div class="a2ui-card">
1519
+ @if (child()) {
1520
+ <a2ui-v09-component-host
1521
+ [componentKey]="child()!"
1522
+ [surfaceId]="surfaceId()"
1523
+ >
1524
+ </a2ui-v09-component-host>
1525
+ }
1526
+ </div>
1527
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".a2ui-card{padding:16px;border-radius:8px;box-shadow:0 4px 6px #0000001a;background-color:#fff;border:1px solid #eee}\n"] }]
1528
+ }], 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 }] }] } });
1529
+
1530
+ /**
1531
+ * Copyright 2026 Google LLC
1532
+ *
1533
+ * Licensed under the Apache License, Version 2.0 (the "License");
1534
+ * you may not use this file except in compliance with the License.
1535
+ * You may obtain a copy of the License at
1536
+ *
1537
+ * http://www.apache.org/licenses/LICENSE-2.0
1538
+ *
1539
+ * Unless required by applicable law or agreed to in writing, software
1540
+ * distributed under the License is distributed on an "AS IS" BASIS,
1541
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1542
+ * See the License for the specific language governing permissions and
1543
+ * limitations under the License.
1544
+ */
1545
+ /**
1546
+ * Angular implementation of the A2UI Tabs component (v0.9).
1547
+ *
1548
+ * Renders a set of tabs where each tab has a label and associated content.
1549
+ * Manages the active tab state internally.
1550
+ */
1551
+ class TabsComponent {
1552
+ /**
1553
+ * Reactive properties resolved from the A2UI {@link ComponentModel}.
1554
+ *
1555
+ * Expected properties:
1556
+ * - `tabs`: A list of tab objects, each containing a `label` and `content` ID.
1557
+ */
1558
+ props = input({}, ...(ngDevMode ? [{ debugName: "props" }] : /* istanbul ignore next */ []));
1559
+ surfaceId = input.required(...(ngDevMode ? [{ debugName: "surfaceId" }] : /* istanbul ignore next */ []));
1560
+ componentId = input(...(ngDevMode ? [undefined, { debugName: "componentId" }] : /* istanbul ignore next */ []));
1561
+ dataContextPath = input('/', ...(ngDevMode ? [{ debugName: "dataContextPath" }] : /* istanbul ignore next */ []));
1562
+ activeTabIndex = signal(0, ...(ngDevMode ? [{ debugName: "activeTabIndex" }] : /* istanbul ignore next */ []));
1563
+ tabs = computed$1(() => this.props()['tabs']?.value() || [], ...(ngDevMode ? [{ debugName: "tabs" }] : /* istanbul ignore next */ []));
1564
+ activeTab = computed$1(() => this.tabs()[this.activeTabIndex()], ...(ngDevMode ? [{ debugName: "activeTab" }] : /* istanbul ignore next */ []));
1565
+ normalizedActiveTabContent = computed$1(() => {
1566
+ const content = this.activeTab()?.content;
1567
+ if (!content)
1568
+ return null;
1569
+ if (typeof content === 'object' && content !== null && 'id' in content) {
1570
+ return content;
1571
+ }
1572
+ return { id: content, basePath: this.dataContextPath() };
1573
+ }, ...(ngDevMode ? [{ debugName: "normalizedActiveTabContent" }] : /* istanbul ignore next */ []));
1574
+ setActiveTab(index) {
1575
+ this.activeTabIndex.set(index);
1576
+ }
1577
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: TabsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1578
+ 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 } }, ngImport: i0, template: `
1579
+ <div class="a2ui-tabs">
1580
+ <div class="a2ui-tab-bar">
1581
+ @for (tab of tabs(); track tab; let i = $index) {
1582
+ <button
1583
+ class="a2ui-tab-button"
1584
+ [class.active]="activeTabIndex() === i"
1585
+ (click)="setActiveTab(i)"
1586
+ >
1587
+ {{ tab.label }}
1588
+ </button>
1589
+ }
1590
+ </div>
1591
+ @if (normalizedActiveTabContent()) {
1592
+ <div class="a2ui-tab-content">
1593
+ <a2ui-v09-component-host
1594
+ [componentKey]="normalizedActiveTabContent()!"
1595
+ [surfaceId]="surfaceId()"
1596
+ >
1597
+ </a2ui-v09-component-host>
1598
+ </div>
1599
+ }
1600
+ </div>
1601
+ `, isInline: true, styles: [".a2ui-tabs{display:flex;flex-direction:column;width:100%}.a2ui-tab-bar{display:flex;border-bottom:2px solid #eee;gap:16px}.a2ui-tab-button{padding:8px 16px;border:none;background:none;cursor:pointer;font-weight:500;color:#666;border-bottom:2px solid transparent;margin-bottom:-2px}.a2ui-tab-button.active{color:#007bff;border-bottom:2px solid #007bff}.a2ui-tab-content{padding:16px 0}\n"], dependencies: [{ kind: "component", type: ComponentHostComponent, selector: "a2ui-v09-component-host", inputs: ["componentKey", "surfaceId"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1602
+ }
1603
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: TabsComponent, decorators: [{
1604
+ type: Component,
1605
+ args: [{ selector: 'a2ui-v09-tabs', standalone: true, imports: [ComponentHostComponent], template: `
1606
+ <div class="a2ui-tabs">
1607
+ <div class="a2ui-tab-bar">
1608
+ @for (tab of tabs(); track tab; let i = $index) {
1609
+ <button
1610
+ class="a2ui-tab-button"
1611
+ [class.active]="activeTabIndex() === i"
1612
+ (click)="setActiveTab(i)"
1613
+ >
1614
+ {{ tab.label }}
1615
+ </button>
1616
+ }
1617
+ </div>
1618
+ @if (normalizedActiveTabContent()) {
1619
+ <div class="a2ui-tab-content">
1620
+ <a2ui-v09-component-host
1621
+ [componentKey]="normalizedActiveTabContent()!"
1622
+ [surfaceId]="surfaceId()"
1623
+ >
1624
+ </a2ui-v09-component-host>
1625
+ </div>
1626
+ }
1627
+ </div>
1628
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".a2ui-tabs{display:flex;flex-direction:column;width:100%}.a2ui-tab-bar{display:flex;border-bottom:2px solid #eee;gap:16px}.a2ui-tab-button{padding:8px 16px;border:none;background:none;cursor:pointer;font-weight:500;color:#666;border-bottom:2px solid transparent;margin-bottom:-2px}.a2ui-tab-button.active{color:#007bff;border-bottom:2px solid #007bff}.a2ui-tab-content{padding:16px 0}\n"] }]
1629
+ }], 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 }] }] } });
1630
+
1631
+ /**
1632
+ * Copyright 2026 Google LLC
1633
+ *
1634
+ * Licensed under the Apache License, Version 2.0 (the "License");
1635
+ * you may not use this file except in compliance with the License.
1636
+ * You may obtain a copy of the License at
1637
+ *
1638
+ * http://www.apache.org/licenses/LICENSE-2.0
1639
+ *
1640
+ * Unless required by applicable law or agreed to in writing, software
1641
+ * distributed under the License is distributed on an "AS IS" BASIS,
1642
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1643
+ * See the License for the specific language governing permissions and
1644
+ * limitations under the License.
1645
+ */
1646
+ /**
1647
+ * Angular implementation of the A2UI Modal component (v0.9).
1648
+ *
1649
+ * Renders a trigger component that opening an overlay containing a content component.
1650
+ */
1651
+ class ModalComponent {
1652
+ /**
1653
+ * Reactive properties resolved from the A2UI {@link ComponentModel}.
1654
+ *
1655
+ * Expected properties:
1656
+ * - `trigger`: The ID of the component that opens the modal.
1657
+ * - `content`: The ID of the component to display inside the modal.
1658
+ */
1659
+ props = input({}, ...(ngDevMode ? [{ debugName: "props" }] : /* istanbul ignore next */ []));
1660
+ surfaceId = input.required(...(ngDevMode ? [{ debugName: "surfaceId" }] : /* istanbul ignore next */ []));
1661
+ componentId = input(...(ngDevMode ? [undefined, { debugName: "componentId" }] : /* istanbul ignore next */ []));
1662
+ dataContextPath = input('/', ...(ngDevMode ? [{ debugName: "dataContextPath" }] : /* istanbul ignore next */ []));
1663
+ isOpen = signal(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : /* istanbul ignore next */ []));
1664
+ trigger = computed$1(() => this.props()['trigger']?.value(), ...(ngDevMode ? [{ debugName: "trigger" }] : /* istanbul ignore next */ []));
1665
+ content = computed$1(() => this.props()['content']?.value(), ...(ngDevMode ? [{ debugName: "content" }] : /* istanbul ignore next */ []));
1666
+ openModal() {
1667
+ this.isOpen.set(true);
1668
+ }
1669
+ closeModal() {
1670
+ this.isOpen.set(false);
1671
+ }
1672
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1673
+ 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 } }, ngImport: i0, template: `
1674
+ <div class="a2ui-modal-wrapper">
1675
+ <div (click)="openModal()" class="a2ui-modal-trigger">
1676
+ @if (trigger()) {
1677
+ <a2ui-v09-component-host
1678
+ [componentKey]="trigger()!"
1679
+ [surfaceId]="surfaceId()"
1680
+ >
1681
+ </a2ui-v09-component-host>
1682
+ }
1683
+ </div>
1684
+
1685
+ @if (isOpen()) {
1686
+ <div class="a2ui-modal-overlay" (click)="closeModal()">
1687
+ <div class="a2ui-modal-content" (click)="$event.stopPropagation()">
1688
+ <button class="a2ui-modal-close" (click)="closeModal()">&times;</button>
1689
+ @if (content()) {
1690
+ <a2ui-v09-component-host
1691
+ [componentKey]="content()!"
1692
+ [surfaceId]="surfaceId()"
1693
+ >
1694
+ </a2ui-v09-component-host>
1695
+ }
1696
+ </div>
1697
+ </div>
1698
+ }
1699
+ </div>
1700
+ `, 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:#00000080;display:flex;justify-content:center;align-items:center;z-index:1000}.a2ui-modal-content{background:#fff;padding:32px;border-radius:8px;position:relative;min-width:300px;max-width:80%;max-height:80%;overflow-y:auto;box-shadow:0 10px 25px #0003}.a2ui-modal-close{position:absolute;top:10px;right:15px;border:none;background:none;font-size:24px;cursor:pointer;color:#999}.a2ui-modal-close:hover{color:#333}\n"], dependencies: [{ kind: "component", type: ComponentHostComponent, selector: "a2ui-v09-component-host", inputs: ["componentKey", "surfaceId"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1701
+ }
1702
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ModalComponent, decorators: [{
1703
+ type: Component,
1704
+ args: [{ selector: 'a2ui-v09-modal', standalone: true, imports: [ComponentHostComponent], template: `
1705
+ <div class="a2ui-modal-wrapper">
1706
+ <div (click)="openModal()" class="a2ui-modal-trigger">
1707
+ @if (trigger()) {
1708
+ <a2ui-v09-component-host
1709
+ [componentKey]="trigger()!"
1710
+ [surfaceId]="surfaceId()"
1711
+ >
1712
+ </a2ui-v09-component-host>
1713
+ }
1714
+ </div>
1715
+
1716
+ @if (isOpen()) {
1717
+ <div class="a2ui-modal-overlay" (click)="closeModal()">
1718
+ <div class="a2ui-modal-content" (click)="$event.stopPropagation()">
1719
+ <button class="a2ui-modal-close" (click)="closeModal()">&times;</button>
1720
+ @if (content()) {
1721
+ <a2ui-v09-component-host
1722
+ [componentKey]="content()!"
1723
+ [surfaceId]="surfaceId()"
1724
+ >
1725
+ </a2ui-v09-component-host>
1726
+ }
1727
+ </div>
1728
+ </div>
1729
+ }
1730
+ </div>
1731
+ `, 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:#00000080;display:flex;justify-content:center;align-items:center;z-index:1000}.a2ui-modal-content{background:#fff;padding:32px;border-radius:8px;position:relative;min-width:300px;max-width:80%;max-height:80%;overflow-y:auto;box-shadow:0 10px 25px #0003}.a2ui-modal-close{position:absolute;top:10px;right:15px;border:none;background:none;font-size:24px;cursor:pointer;color:#999}.a2ui-modal-close:hover{color:#333}\n"] }]
1732
+ }], 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 }] }] } });
1733
+
1734
+ /**
1735
+ * Copyright 2026 Google LLC
1736
+ *
1737
+ * Licensed under the Apache License, Version 2.0 (the "License");
1738
+ * you may not use this file except in compliance with the License.
1739
+ * You may obtain a copy of the License at
1740
+ *
1741
+ * http://www.apache.org/licenses/LICENSE-2.0
1742
+ *
1743
+ * Unless required by applicable law or agreed to in writing, software
1744
+ * distributed under the License is distributed on an "AS IS" BASIS,
1745
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1746
+ * See the License for the specific language governing permissions and
1747
+ * limitations under the License.
1748
+ */
1749
+ /**
1750
+ * Angular implementation of the A2UI Divider component (v0.9).
1751
+ *
1752
+ * Renders a horizontal or vertical line to separate content.
1753
+ */
1754
+ class DividerComponent {
1755
+ /**
1756
+ * Reactive properties resolved from the A2UI {@link ComponentModel}.
1757
+ *
1758
+ * Expected properties:
1759
+ * - `axis`: The orientation of the divider ('horizontal' (default) or 'vertical').
1760
+ */
1761
+ props = input({}, ...(ngDevMode ? [{ debugName: "props" }] : /* istanbul ignore next */ []));
1762
+ surfaceId = input.required(...(ngDevMode ? [{ debugName: "surfaceId" }] : /* istanbul ignore next */ []));
1763
+ componentId = input(...(ngDevMode ? [undefined, { debugName: "componentId" }] : /* istanbul ignore next */ []));
1764
+ dataContextPath = input('/', ...(ngDevMode ? [{ debugName: "dataContextPath" }] : /* istanbul ignore next */ []));
1765
+ axis = computed$1(() => this.props()['axis']?.value() ?? 'horizontal', ...(ngDevMode ? [{ debugName: "axis" }] : /* istanbul ignore next */ []));
1766
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: DividerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1767
+ 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 } }, ngImport: i0, template: `
1768
+ <hr
1769
+ class="a2ui-divider"
1770
+ [class.horizontal]="axis() === 'horizontal'"
1771
+ [class.vertical]="axis() === 'vertical'"
1772
+ />
1773
+ `, isInline: true, styles: [".a2ui-divider{border:0;border-top:1px solid #eee;margin:16px 0;width:100%}.a2ui-divider.vertical{width:1px;height:100%;margin:0 16px;border-top:0;border-left:1px solid #eee}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1774
+ }
1775
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: DividerComponent, decorators: [{
1776
+ type: Component,
1777
+ args: [{ selector: 'a2ui-v09-divider', standalone: true, imports: [], template: `
1778
+ <hr
1779
+ class="a2ui-divider"
1780
+ [class.horizontal]="axis() === 'horizontal'"
1781
+ [class.vertical]="axis() === 'vertical'"
1782
+ />
1783
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".a2ui-divider{border:0;border-top:1px solid #eee;margin:16px 0;width:100%}.a2ui-divider.vertical{width:1px;height:100%;margin:0 16px;border-top:0;border-left:1px solid #eee}\n"] }]
1784
+ }], 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 }] }] } });
1785
+
1786
+ /**
1787
+ * Copyright 2026 Google LLC
1788
+ *
1789
+ * Licensed under the Apache License, Version 2.0 (the "License");
1790
+ * you may not use this file except in compliance with the License.
1791
+ * You may obtain a copy of the License at
1792
+ *
1793
+ * http://www.apache.org/licenses/LICENSE-2.0
1794
+ *
1795
+ * Unless required by applicable law or agreed to in writing, software
1796
+ * distributed under the License is distributed on an "AS IS" BASIS,
1797
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1798
+ * See the License for the specific language governing permissions and
1799
+ * limitations under the License.
1800
+ */
1801
+ /**
1802
+ * Angular implementation of the A2UI CheckBox component (v0.9).
1803
+ *
1804
+ * Renders a checkbox with a label. Updates the bound data model property
1805
+ * when the checked state changes.
1806
+ */
1807
+ class CheckBoxComponent {
1808
+ /**
1809
+ * Reactive properties resolved from the A2UI {@link ComponentModel}.
1810
+ *
1811
+ * Expected properties:
1812
+ * - `label`: The text to display next to the checkbox.
1813
+ * - `value`: Boolean indicating whether the checkbox is checked.
1814
+ */
1815
+ props = input({}, ...(ngDevMode ? [{ debugName: "props" }] : /* istanbul ignore next */ []));
1816
+ surfaceId = input.required(...(ngDevMode ? [{ debugName: "surfaceId" }] : /* istanbul ignore next */ []));
1817
+ componentId = input(...(ngDevMode ? [undefined, { debugName: "componentId" }] : /* istanbul ignore next */ []));
1818
+ dataContextPath = input('/', ...(ngDevMode ? [{ debugName: "dataContextPath" }] : /* istanbul ignore next */ []));
1819
+ value = computed$1(() => this.props()['value']?.value() === true, ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
1820
+ label = computed$1(() => this.props()['label']?.value(), ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
1821
+ handleChange(event) {
1822
+ const checked = event.target.checked;
1823
+ this.props()['value']?.onUpdate(checked);
1824
+ }
1825
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: CheckBoxComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1826
+ 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 } }, ngImport: i0, template: `
1827
+ <label class="a2ui-check-box-label">
1828
+ <input
1829
+ type="checkbox"
1830
+ [checked]="value()"
1831
+ (change)="handleChange($event)"
1832
+ class="a2ui-check-box-input"
1833
+ />
1834
+ <span class="a2ui-check-box-text">{{ label() }}</span>
1835
+ </label>
1836
+ `, isInline: true, styles: [".a2ui-check-box-label{display:flex;align-items:center;gap:8px;cursor:pointer;padding:4px 0}.a2ui-check-box-input{width:18px;height:18px;cursor:pointer}.a2ui-check-box-text{font-size:16px}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1837
+ }
1838
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: CheckBoxComponent, decorators: [{
1839
+ type: Component,
1840
+ args: [{ selector: 'a2ui-v09-check-box', standalone: true, imports: [], template: `
1841
+ <label class="a2ui-check-box-label">
1842
+ <input
1843
+ type="checkbox"
1844
+ [checked]="value()"
1845
+ (change)="handleChange($event)"
1846
+ class="a2ui-check-box-input"
1847
+ />
1848
+ <span class="a2ui-check-box-text">{{ label() }}</span>
1849
+ </label>
1850
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".a2ui-check-box-label{display:flex;align-items:center;gap:8px;cursor:pointer;padding:4px 0}.a2ui-check-box-input{width:18px;height:18px;cursor:pointer}.a2ui-check-box-text{font-size:16px}\n"] }]
1851
+ }], 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 }] }] } });
1852
+
1853
+ /**
1854
+ * Copyright 2026 Google LLC
1855
+ *
1856
+ * Licensed under the Apache License, Version 2.0 (the "License");
1857
+ * you may not use this file except in compliance with the License.
1858
+ * You may obtain a copy of the License at
1859
+ *
1860
+ * http://www.apache.org/licenses/LICENSE-2.0
1861
+ *
1862
+ * Unless required by applicable law or agreed to in writing, software
1863
+ * distributed under the License is distributed on an "AS IS" BASIS,
1864
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1865
+ * See the License for the specific language governing permissions and
1866
+ * limitations under the License.
1867
+ */
1868
+ /**
1869
+ * Angular implementation of the A2UI ChoicePicker component (v0.9).
1870
+ *
1871
+ * Renders a set of options as either radio buttons/checkboxes or chips.
1872
+ * Supports both single and multiple selection.
1873
+ */
1874
+ class ChoicePickerComponent {
1875
+ /**
1876
+ * Reactive properties resolved from the A2UI {@link ComponentModel}.
1877
+ *
1878
+ * Expected properties:
1879
+ * - `value`: The currently selected value(s).
1880
+ * - `choices` or `options`: List of choice objects (label and value).
1881
+ * - `displayStyle`: How to render the choices ('default' or 'chips').
1882
+ * - `variant`: Selection mode ('singleSelection' or 'multipleSelection').
1883
+ */
1884
+ props = input({}, ...(ngDevMode ? [{ debugName: "props" }] : /* istanbul ignore next */ []));
1885
+ surfaceId = input.required(...(ngDevMode ? [{ debugName: "surfaceId" }] : /* istanbul ignore next */ []));
1886
+ componentId = input(...(ngDevMode ? [undefined, { debugName: "componentId" }] : /* istanbul ignore next */ []));
1887
+ dataContextPath = input('/', ...(ngDevMode ? [{ debugName: "dataContextPath" }] : /* istanbul ignore next */ []));
1888
+ displayStyle = computed$1(() => this.props()['displayStyle']?.value(), ...(ngDevMode ? [{ debugName: "displayStyle" }] : /* istanbul ignore next */ []));
1889
+ choices = computed$1(() => this.props()['choices']?.value() || this.props()['options']?.value() || [], ...(ngDevMode ? [{ debugName: "choices" }] : /* istanbul ignore next */ []));
1890
+ variant = computed$1(() => this.props()['variant']?.value(), ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
1891
+ selectedValue = computed$1(() => this.props()['value']?.value(), ...(ngDevMode ? [{ debugName: "selectedValue" }] : /* istanbul ignore next */ []));
1892
+ isMultiple() {
1893
+ return this.variant() === 'multipleSelection';
1894
+ }
1895
+ isSelected(value) {
1896
+ const selected = this.selectedValue();
1897
+ if (Array.isArray(selected)) {
1898
+ return selected.includes(value);
1899
+ }
1900
+ return selected === value;
1901
+ }
1902
+ onCheckChange(value, event) {
1903
+ const checked = event.target.checked;
1904
+ this.updateValue(value, checked);
1905
+ }
1906
+ toggleActive(value) {
1907
+ const current = this.isSelected(value);
1908
+ this.updateValue(value, !current);
1909
+ }
1910
+ updateValue(value, active) {
1911
+ const current = this.selectedValue();
1912
+ if (this.isMultiple()) {
1913
+ let next = Array.isArray(current) ? [...current] : [];
1914
+ if (active) {
1915
+ if (!next.includes(value))
1916
+ next.push(value);
1917
+ }
1918
+ else {
1919
+ next = next.filter((v) => v !== value);
1920
+ }
1921
+ this.props()['value']?.onUpdate(next);
1922
+ }
1923
+ else {
1924
+ if (active) {
1925
+ this.props()['value']?.onUpdate(value);
1926
+ }
1927
+ }
1928
+ }
1929
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ChoicePickerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1930
+ 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 } }, ngImport: i0, template: `
1931
+ <div class="a2ui-choice-picker">
1932
+ <!-- Chips Variant -->
1933
+ @if (displayStyle() === 'chips') {
1934
+ <div class="a2ui-chips-group">
1935
+ @for (choice of choices(); track choice.value) {
1936
+ <button
1937
+ class="a2ui-chip"
1938
+ [class.active]="isSelected(choice.value)"
1939
+ (click)="toggleActive(choice.value)"
1940
+ >
1941
+ {{ choice.label }}
1942
+ </button>
1943
+ }
1944
+ </div>
1945
+ } @else {
1946
+ <!-- Checkbox/Radio Variant -->
1947
+ <div class="a2ui-options-group">
1948
+ @for (choice of choices(); track choice.value) {
1949
+ <label class="a2ui-option-label">
1950
+ <input
1951
+ [type]="isMultiple() ? 'checkbox' : 'radio'"
1952
+ [name]="componentId()"
1953
+ [value]="choice.value"
1954
+ [checked]="isSelected(choice.value)"
1955
+ (change)="onCheckChange(choice.value, $event)"
1956
+ class="a2ui-option-input"
1957
+ />
1958
+ <span class="a2ui-option-text">{{ choice.label }}</span>
1959
+ </label>
1960
+ }
1961
+ </div>
1962
+ }
1963
+ </div>
1964
+ `, isInline: true, styles: [".a2ui-choice-picker{width:100%}.a2ui-options-group{display:flex;flex-direction:column;gap:8px}.a2ui-option-label{display:flex;align-items:center;gap:8px;cursor:pointer}.a2ui-option-input{width:18px;height:18px}.a2ui-chips-group{display:flex;flex-wrap:wrap;gap:8px}.a2ui-chip{padding:4px 12px;border-radius:16px;border:1px solid #ccc;background:#fff;cursor:pointer;transition:all .2s}.a2ui-chip.active{background-color:#007bff;color:#fff;border-color:#007bff}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1965
+ }
1966
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ChoicePickerComponent, decorators: [{
1967
+ type: Component,
1968
+ args: [{ selector: 'a2ui-v09-choice-picker', standalone: true, imports: [], template: `
1969
+ <div class="a2ui-choice-picker">
1970
+ <!-- Chips Variant -->
1971
+ @if (displayStyle() === 'chips') {
1972
+ <div class="a2ui-chips-group">
1973
+ @for (choice of choices(); track choice.value) {
1974
+ <button
1975
+ class="a2ui-chip"
1976
+ [class.active]="isSelected(choice.value)"
1977
+ (click)="toggleActive(choice.value)"
1978
+ >
1979
+ {{ choice.label }}
1980
+ </button>
1981
+ }
1982
+ </div>
1983
+ } @else {
1984
+ <!-- Checkbox/Radio Variant -->
1985
+ <div class="a2ui-options-group">
1986
+ @for (choice of choices(); track choice.value) {
1987
+ <label class="a2ui-option-label">
1988
+ <input
1989
+ [type]="isMultiple() ? 'checkbox' : 'radio'"
1990
+ [name]="componentId()"
1991
+ [value]="choice.value"
1992
+ [checked]="isSelected(choice.value)"
1993
+ (change)="onCheckChange(choice.value, $event)"
1994
+ class="a2ui-option-input"
1995
+ />
1996
+ <span class="a2ui-option-text">{{ choice.label }}</span>
1997
+ </label>
1998
+ }
1999
+ </div>
2000
+ }
2001
+ </div>
2002
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".a2ui-choice-picker{width:100%}.a2ui-options-group{display:flex;flex-direction:column;gap:8px}.a2ui-option-label{display:flex;align-items:center;gap:8px;cursor:pointer}.a2ui-option-input{width:18px;height:18px}.a2ui-chips-group{display:flex;flex-wrap:wrap;gap:8px}.a2ui-chip{padding:4px 12px;border-radius:16px;border:1px solid #ccc;background:#fff;cursor:pointer;transition:all .2s}.a2ui-chip.active{background-color:#007bff;color:#fff;border-color:#007bff}\n"] }]
2003
+ }], 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 }] }] } });
2004
+
2005
+ /**
2006
+ * Copyright 2026 Google LLC
2007
+ *
2008
+ * Licensed under the Apache License, Version 2.0 (the "License");
2009
+ * you may not use this file except in compliance with the License.
2010
+ * You may obtain a copy of the License at
2011
+ *
2012
+ * http://www.apache.org/licenses/LICENSE-2.0
2013
+ *
2014
+ * Unless required by applicable law or agreed to in writing, software
2015
+ * distributed under the License is distributed on an "AS IS" BASIS,
2016
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2017
+ * See the License for the specific language governing permissions and
2018
+ * limitations under the License.
2019
+ */
2020
+ /**
2021
+ * Angular implementation of the A2UI Slider component (v0.9).
2022
+ *
2023
+ * Renders a range input slider with a label and its current value.
2024
+ */
2025
+ class SliderComponent {
2026
+ /**
2027
+ * Reactive properties resolved from the A2UI {@link ComponentModel}.
2028
+ *
2029
+ * Expected properties:
2030
+ * - `value`: The current numeric value.
2031
+ * - `label`: Label text to display.
2032
+ * - `min`: Minimum value (default: 0).
2033
+ * - `max`: Maximum value (default: 100).
2034
+ * - `step`: Increment step (default: 1).
2035
+ */
2036
+ props = input({}, ...(ngDevMode ? [{ debugName: "props" }] : /* istanbul ignore next */ []));
2037
+ surfaceId = input.required(...(ngDevMode ? [{ debugName: "surfaceId" }] : /* istanbul ignore next */ []));
2038
+ componentId = input(...(ngDevMode ? [undefined, { debugName: "componentId" }] : /* istanbul ignore next */ []));
2039
+ dataContextPath = input('/', ...(ngDevMode ? [{ debugName: "dataContextPath" }] : /* istanbul ignore next */ []));
2040
+ label = computed$1(() => this.props()['label']?.value(), ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
2041
+ value = computed$1(() => this.props()['value']?.value(), ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
2042
+ min = computed$1(() => this.props()['min']?.value() ?? 0, ...(ngDevMode ? [{ debugName: "min" }] : /* istanbul ignore next */ []));
2043
+ max = computed$1(() => this.props()['max']?.value() ?? 100, ...(ngDevMode ? [{ debugName: "max" }] : /* istanbul ignore next */ []));
2044
+ step = computed$1(() => this.props()['step']?.value() ?? 1, ...(ngDevMode ? [{ debugName: "step" }] : /* istanbul ignore next */ []));
2045
+ handleInput(event) {
2046
+ const val = Number(event.target.value);
2047
+ this.props()['value']?.onUpdate(val);
2048
+ }
2049
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SliderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2050
+ 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 } }, ngImport: i0, template: `
2051
+ <div class="a2ui-slider-container">
2052
+ <div class="a2ui-slider-header">
2053
+ <span class="a2ui-slider-label">{{ label() }}</span>
2054
+ <span class="a2ui-slider-value">{{ value() }}</span>
2055
+ </div>
2056
+ <input
2057
+ type="range"
2058
+ [min]="min()"
2059
+ [max]="max()"
2060
+ [step]="step()"
2061
+ [value]="value() ?? min()"
2062
+ (input)="handleInput($event)"
2063
+ class="a2ui-slider"
2064
+ />
2065
+ </div>
2066
+ `, isInline: true, styles: [".a2ui-slider-container{width:100%;display:flex;flex-direction:column;gap:4px}.a2ui-slider-header{display:flex;justify-content:space-between;font-size:14px}.a2ui-slider{width:100%;cursor:pointer}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2067
+ }
2068
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SliderComponent, decorators: [{
2069
+ type: Component,
2070
+ args: [{ selector: 'a2ui-v09-slider', standalone: true, imports: [], template: `
2071
+ <div class="a2ui-slider-container">
2072
+ <div class="a2ui-slider-header">
2073
+ <span class="a2ui-slider-label">{{ label() }}</span>
2074
+ <span class="a2ui-slider-value">{{ value() }}</span>
2075
+ </div>
2076
+ <input
2077
+ type="range"
2078
+ [min]="min()"
2079
+ [max]="max()"
2080
+ [step]="step()"
2081
+ [value]="value() ?? min()"
2082
+ (input)="handleInput($event)"
2083
+ class="a2ui-slider"
2084
+ />
2085
+ </div>
2086
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".a2ui-slider-container{width:100%;display:flex;flex-direction:column;gap:4px}.a2ui-slider-header{display:flex;justify-content:space-between;font-size:14px}.a2ui-slider{width:100%;cursor:pointer}\n"] }]
2087
+ }], 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 }] }] } });
2088
+
2089
+ /**
2090
+ * Copyright 2026 Google LLC
2091
+ *
2092
+ * Licensed under the Apache License, Version 2.0 (the "License");
2093
+ * you may not use this file except in compliance with the License.
2094
+ * You may obtain a copy of the License at
2095
+ *
2096
+ * http://www.apache.org/licenses/LICENSE-2.0
2097
+ *
2098
+ * Unless required by applicable law or agreed to in writing, software
2099
+ * distributed under the License is distributed on an "AS IS" BASIS,
2100
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2101
+ * See the License for the specific language governing permissions and
2102
+ * limitations under the License.
2103
+ */
2104
+ /**
2105
+ * Angular implementation of the A2UI DateTimeInput component (v0.9).
2106
+ *
2107
+ * Renders date and/or time input fields. Combines them into an ISO string
2108
+ * for the bound data model property.
2109
+ */
2110
+ class DateTimeInputComponent {
2111
+ /**
2112
+ * Reactive properties resolved from the A2UI {@link ComponentModel}.
2113
+ *
2114
+ * Expected properties:
2115
+ * - `value`: The current ISO date/time string.
2116
+ * - `label`: Optional label text.
2117
+ * - `enableDate`: Whether to show the date picker (default: true).
2118
+ * - `enableTime`: Whether to show the time picker (default: false).
2119
+ */
2120
+ props = input({}, ...(ngDevMode ? [{ debugName: "props" }] : /* istanbul ignore next */ []));
2121
+ surfaceId = input.required(...(ngDevMode ? [{ debugName: "surfaceId" }] : /* istanbul ignore next */ []));
2122
+ componentId = input(...(ngDevMode ? [undefined, { debugName: "componentId" }] : /* istanbul ignore next */ []));
2123
+ dataContextPath = input('/', ...(ngDevMode ? [{ debugName: "dataContextPath" }] : /* istanbul ignore next */ []));
2124
+ label = computed$1(() => this.props()['label']?.value(), ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
2125
+ enableDate = computed$1(() => this.props()['enableDate']?.value() ?? true, ...(ngDevMode ? [{ debugName: "enableDate" }] : /* istanbul ignore next */ []));
2126
+ enableTime = computed$1(() => this.props()['enableTime']?.value() ?? false, ...(ngDevMode ? [{ debugName: "enableTime" }] : /* istanbul ignore next */ []));
2127
+ rawValue = computed$1(() => this.props()['value']?.value() || '', ...(ngDevMode ? [{ debugName: "rawValue" }] : /* istanbul ignore next */ []));
2128
+ dateValue = computed$1(() => {
2129
+ const val = this.rawValue();
2130
+ if (!val)
2131
+ return '';
2132
+ return val.includes('T') ? val.split('T')[0] : val;
2133
+ }, ...(ngDevMode ? [{ debugName: "dateValue" }] : /* istanbul ignore next */ []));
2134
+ timeValue = computed$1(() => {
2135
+ const val = this.rawValue();
2136
+ if (!val || !val.includes('T'))
2137
+ return '';
2138
+ return val.split('T')[1].substring(0, 5);
2139
+ }, ...(ngDevMode ? [{ debugName: "timeValue" }] : /* istanbul ignore next */ []));
2140
+ handleDateChange(event) {
2141
+ const date = event.target.value;
2142
+ const current = this.rawValue();
2143
+ if (this.enableTime()) {
2144
+ const time = current.includes('T') ? current.split('T')[1] : '00:00:00';
2145
+ this.props()['value']?.onUpdate(`${date}T${time}`);
2146
+ }
2147
+ else {
2148
+ this.props()['value']?.onUpdate(date);
2149
+ }
2150
+ }
2151
+ handleTimeChange(event) {
2152
+ const time = event.target.value;
2153
+ const current = this.rawValue();
2154
+ const date = current.includes('T')
2155
+ ? current.split('T')[0]
2156
+ : current || new Date().toISOString().split('T')[0];
2157
+ this.props()['value']?.onUpdate(`${date}T${time}:00`);
2158
+ }
2159
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: DateTimeInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2160
+ 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 } }, ngImport: i0, template: `
2161
+ <div class="a2ui-date-time-container">
2162
+ @if (label()) {
2163
+ <label class="a2ui-date-time-label">
2164
+ {{ label() }}
2165
+ </label>
2166
+ }
2167
+ <div class="a2ui-date-time-inputs">
2168
+ @if (enableDate()) {
2169
+ <input
2170
+ type="date"
2171
+ [value]="dateValue()"
2172
+ (change)="handleDateChange($event)"
2173
+ class="a2ui-date-time-input"
2174
+ />
2175
+ }
2176
+ @if (enableTime()) {
2177
+ <input
2178
+ type="time"
2179
+ [value]="timeValue()"
2180
+ (change)="handleTimeChange($event)"
2181
+ class="a2ui-date-time-input"
2182
+ />
2183
+ }
2184
+ </div>
2185
+ </div>
2186
+ `, isInline: true, styles: [".a2ui-date-time-container{display:flex;flex-direction:column;gap:4px;width:100%}.a2ui-date-time-label{font-size:14px;color:#666}.a2ui-date-time-inputs{display:flex;gap:8px;width:100%}.a2ui-date-time-input{padding:8px;border-radius:4px;border:1px solid #ccc;font-family:inherit;flex:1}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2187
+ }
2188
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: DateTimeInputComponent, decorators: [{
2189
+ type: Component,
2190
+ args: [{ selector: 'a2ui-v09-date-time-input', standalone: true, imports: [], template: `
2191
+ <div class="a2ui-date-time-container">
2192
+ @if (label()) {
2193
+ <label class="a2ui-date-time-label">
2194
+ {{ label() }}
2195
+ </label>
2196
+ }
2197
+ <div class="a2ui-date-time-inputs">
2198
+ @if (enableDate()) {
2199
+ <input
2200
+ type="date"
2201
+ [value]="dateValue()"
2202
+ (change)="handleDateChange($event)"
2203
+ class="a2ui-date-time-input"
2204
+ />
2205
+ }
2206
+ @if (enableTime()) {
2207
+ <input
2208
+ type="time"
2209
+ [value]="timeValue()"
2210
+ (change)="handleTimeChange($event)"
2211
+ class="a2ui-date-time-input"
2212
+ />
2213
+ }
2214
+ </div>
2215
+ </div>
2216
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".a2ui-date-time-container{display:flex;flex-direction:column;gap:4px;width:100%}.a2ui-date-time-label{font-size:14px;color:#666}.a2ui-date-time-inputs{display:flex;gap:8px;width:100%}.a2ui-date-time-input{padding:8px;border-radius:4px;border:1px solid #ccc;font-family:inherit;flex:1}\n"] }]
2217
+ }], 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 }] }] } });
2218
+
2219
+ /**
2220
+ * Copyright 2026 Google LLC
2221
+ *
2222
+ * Licensed under the Apache License, Version 2.0 (the "License");
2223
+ * you may not use this file except in compliance with the License.
2224
+ * You may obtain a copy of the License at
2225
+ *
2226
+ * http://www.apache.org/licenses/LICENSE-2.0
2227
+ *
2228
+ * Unless required by applicable law or agreed to in writing, software
2229
+ * distributed under the License is distributed on an "AS IS" BASIS,
2230
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2231
+ * See the License for the specific language governing permissions and
2232
+ * limitations under the License.
2233
+ */
2234
+ /**
2235
+ * The set of default Angular implementations for each component in the basic catalog.
2236
+ */
2237
+ const DEFAULT_COMPONENT_IMPLEMENTATIONS = {
2238
+ text: { ...TextApi, component: TextComponent },
2239
+ row: { ...RowApi, component: RowComponent },
2240
+ column: { ...ColumnApi, component: ColumnComponent },
2241
+ button: { ...ButtonApi, component: ButtonComponent },
2242
+ textField: { ...TextFieldApi, component: TextFieldComponent },
2243
+ image: { ...ImageApi, component: ImageComponent },
2244
+ icon: { ...IconApi, component: IconComponent },
2245
+ video: { ...VideoApi, component: VideoComponent },
2246
+ audioPlayer: { ...AudioPlayerApi, component: AudioPlayerComponent },
2247
+ list: { ...ListApi, component: ListComponent },
2248
+ card: { ...CardApi, component: CardComponent },
2249
+ tabs: { ...TabsApi, component: TabsComponent },
2250
+ modal: { ...ModalApi, component: ModalComponent },
2251
+ divider: { ...DividerApi, component: DividerComponent },
2252
+ checkBox: { ...CheckBoxApi, component: CheckBoxComponent },
2253
+ choicePicker: { ...ChoicePickerApi, component: ChoicePickerComponent },
2254
+ slider: { ...SliderApi, component: SliderComponent },
2255
+ dateTimeInput: { ...DateTimeInputApi, component: DateTimeInputComponent },
2256
+ };
2257
+ /**
2258
+ * The set of Angular UI components provided by the basic catalog.
2259
+ */
2260
+ const BASIC_COMPONENTS = Object.values(DEFAULT_COMPONENT_IMPLEMENTATIONS);
2261
+ /**
2262
+ * A base class for basic catalogs, providing extensibility for non-DI use cases.
2263
+ */
2264
+ class BasicCatalogBase extends AngularCatalog {
2265
+ constructor(options = {}) {
2266
+ const id = options.id ?? 'https://a2ui.org/specification/v0_9/basic_catalog.json';
2267
+ const functions = options.functions ?? BASIC_FUNCTIONS;
2268
+ const overrides = options.components ?? {};
2269
+ const components = [
2270
+ ...Object.entries(DEFAULT_COMPONENT_IMPLEMENTATIONS).map(([key, defaultValue]) => {
2271
+ const impl = overrides[key] ?? defaultValue;
2272
+ return { ...impl, name: impl.name || key };
2273
+ }),
2274
+ ...(options.extraComponents ?? []),
2275
+ ];
2276
+ super(id, components, functions);
2277
+ }
2278
+ }
2279
+ /**
2280
+ * A basic catalog of components and functions for v0.9 verification.
2281
+ *
2282
+ * This catalog includes a wide range of UI components (Text, Button, Row, etc.)
2283
+ * and utility functions (capitalize, formatString) defined in the A2UI v0.9
2284
+ * basic catalog specification.
2285
+ */
2286
+ class BasicCatalog extends BasicCatalogBase {
2287
+ constructor() {
2288
+ super();
2289
+ }
2290
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: BasicCatalog, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
2291
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: BasicCatalog, providedIn: 'root' });
2292
+ }
2293
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: BasicCatalog, decorators: [{
2294
+ type: Injectable,
2295
+ args: [{
2296
+ providedIn: 'root',
2297
+ }]
2298
+ }], ctorParameters: () => [] });
2299
+
2300
+ /*
2301
+ * Copyright 2026 Google LLC
2302
+ *
2303
+ * Licensed under the Apache License, Version 2.0 (the "License");
2304
+ * you may not use this file except in compliance with the License.
2305
+ * You may obtain a copy of the License at
2306
+ *
2307
+ * http://www.apache.org/licenses/LICENSE-2.0
2308
+ *
2309
+ * Unless required by applicable law or agreed to in writing, software
2310
+ * distributed under the License is distributed on an "AS IS" BASIS,
2311
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2312
+ * See the License for the specific language governing permissions and
2313
+ * limitations under the License.
2314
+ */
2315
+ /**
2316
+ * Public API surface for A2UI Angular Renderer v0.9.
2317
+ *
2318
+ * This module provides the core services, components, and catalogs required
2319
+ * to render A2UI surfaces using the v0.9 protocol.
2320
+ *
2321
+ * @module v0.9
2322
+ */
2323
+ // Core Services and Components
2324
+
2325
+ /**
2326
+ * Generated bundle index. Do not edit.
2327
+ */
2328
+
2329
+ 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 };
2330
+ //# sourceMappingURL=a2ui-angular-v0_9.mjs.map