@a2ui/angular 0.8.2 → 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,1797 @@
1
+ import * as i0 from '@angular/core';
2
+ import { signal, Injectable, inject, input, Directive, computed, ChangeDetectionStrategy, Component, InjectionToken, ViewContainerRef, PLATFORM_ID, effect, ViewEncapsulation, makeEnvironmentProviders } from '@angular/core';
3
+ import { Subject } from 'rxjs';
4
+ import * as WebCore from '@a2ui/web_core/v0_8';
5
+ import { DOCUMENT, isPlatformBrowser, AsyncPipe } from '@angular/common';
6
+ import * as Styles from '@a2ui/web_core/styles/index';
7
+ import { structuralStyles } from '@a2ui/web_core/styles/index';
8
+
9
+ /*
10
+ * Copyright 2025 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
+ * https://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
+ class MessageProcessor {
25
+ baseProcessor;
26
+ eventsSubject = new Subject();
27
+ events = this.eventsSubject.asObservable();
28
+ // Signal to track the version of the data in the MessageProcessor. Since the base processor updates
29
+ // surfaces in-place (mutating the Map), we use this to force Angular's change detection to
30
+ // re-evaluate any components or effects that depend on getSurfaces().
31
+ versionSignal = signal(0, ...(ngDevMode ? [{ debugName: "versionSignal" }] : /* istanbul ignore next */ []));
32
+ version = this.versionSignal.asReadonly();
33
+ constructor() {
34
+ this.baseProcessor = new WebCore.A2uiMessageProcessor();
35
+ }
36
+ /**
37
+ * Increments the version signal to notify Angular that the data model has changed.
38
+ * This should be called after any update to the underlying base processor's surfaces.
39
+ */
40
+ notify() {
41
+ this.versionSignal.update((v) => v + 1);
42
+ }
43
+ processMessages(messages) {
44
+ this.baseProcessor.processMessages(messages);
45
+ this.notify();
46
+ }
47
+ dispatch(message) {
48
+ const completion = new Subject();
49
+ const promise = new Promise((resolve, reject) => {
50
+ completion.subscribe({
51
+ next: (msgs) => resolve(msgs),
52
+ error: (err) => reject(err),
53
+ });
54
+ });
55
+ this.eventsSubject.next({ message, completion });
56
+ return promise;
57
+ }
58
+ getData(node, path, surfaceId) {
59
+ return this.baseProcessor.getData(node, path, surfaceId ?? undefined);
60
+ }
61
+ setData(node, path, value, surfaceId) {
62
+ this.baseProcessor.setData(node, path, value, surfaceId);
63
+ this.notify();
64
+ }
65
+ resolvePath(path, dataContextPath) {
66
+ return this.baseProcessor.resolvePath(path, dataContextPath);
67
+ }
68
+ getSurfaces() {
69
+ this.versionSignal(); // Track dependency
70
+ const allSurfaces = this.baseProcessor.getSurfaces();
71
+ const readySurfaces = new Map();
72
+ for (const [id, surface] of allSurfaces.entries()) {
73
+ if (surface.rootComponentId != null) {
74
+ readySurfaces.set(id, surface);
75
+ }
76
+ }
77
+ return readySurfaces;
78
+ }
79
+ clearSurfaces() {
80
+ this.baseProcessor.clearSurfaces();
81
+ this.notify();
82
+ }
83
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: MessageProcessor, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
84
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: MessageProcessor, providedIn: 'root' });
85
+ }
86
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: MessageProcessor, decorators: [{
87
+ type: Injectable,
88
+ args: [{
89
+ providedIn: 'root',
90
+ }]
91
+ }], ctorParameters: () => [] });
92
+
93
+ /*
94
+ * Copyright 2025 Google LLC
95
+ *
96
+ * Licensed under the Apache License, Version 2.0 (the "License");
97
+ * you may not use this file except in compliance with the License.
98
+ * You may obtain a copy of the License at
99
+ *
100
+ * https://www.apache.org/licenses/LICENSE-2.0
101
+ *
102
+ * Unless required by applicable law or agreed to in writing, software
103
+ * distributed under the License is distributed on an "AS IS" BASIS,
104
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
105
+ * See the License for the specific language governing permissions and
106
+ * limitations under the License.
107
+ */
108
+
109
+ /*
110
+ * Copyright 2025 Google LLC
111
+ *
112
+ * Licensed under the Apache License, Version 2.0 (the "License");
113
+ * you may not use this file except in compliance with the License.
114
+ * You may obtain a copy of the License at
115
+ *
116
+ * https://www.apache.org/licenses/LICENSE-2.0
117
+ *
118
+ * Unless required by applicable law or agreed to in writing, software
119
+ * distributed under the License is distributed on an "AS IS" BASIS,
120
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
121
+ * See the License for the specific language governing permissions and
122
+ * limitations under the License.
123
+ */
124
+ class MarkdownRenderer {
125
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: MarkdownRenderer, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
126
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: MarkdownRenderer, providedIn: 'root' });
127
+ }
128
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: MarkdownRenderer, decorators: [{
129
+ type: Injectable,
130
+ args: [{
131
+ providedIn: 'root',
132
+ }]
133
+ }] });
134
+ class DefaultMarkdownRenderer extends MarkdownRenderer {
135
+ static warningLogged = false;
136
+ async render(markdown, options) {
137
+ try {
138
+ // @ts-ignore - optional peer dependency
139
+ const { renderMarkdown } = await import('@a2ui/markdown-it');
140
+ return await renderMarkdown(markdown, options);
141
+ }
142
+ catch (e) {
143
+ if (!DefaultMarkdownRenderer.warningLogged) {
144
+ console.warn("[DefaultMarkdownRenderer] Failed to load optional `@a2ui/markdown-it` renderer. Using fallback regex.");
145
+ DefaultMarkdownRenderer.warningLogged = true;
146
+ }
147
+ // Basic implementation for v0.8
148
+ return markdown;
149
+ }
150
+ }
151
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: DefaultMarkdownRenderer, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
152
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: DefaultMarkdownRenderer, providedIn: 'root' });
153
+ }
154
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: DefaultMarkdownRenderer, decorators: [{
155
+ type: Injectable,
156
+ args: [{
157
+ providedIn: 'root',
158
+ }]
159
+ }] });
160
+ function provideMarkdownRenderer(renderFn) {
161
+ if (renderFn) {
162
+ return {
163
+ provide: MarkdownRenderer,
164
+ useValue: {
165
+ render: renderFn,
166
+ },
167
+ };
168
+ }
169
+ return { provide: MarkdownRenderer, useClass: DefaultMarkdownRenderer };
170
+ }
171
+
172
+ /*
173
+ * Copyright 2025 Google LLC
174
+ *
175
+ * Licensed under the Apache License, Version 2.0 (the "License");
176
+ * you may not use this file except in compliance with the License.
177
+ * You may obtain a copy of the License at
178
+ *
179
+ * https://www.apache.org/licenses/LICENSE-2.0
180
+ *
181
+ * Unless required by applicable law or agreed to in writing, software
182
+ * distributed under the License is distributed on an "AS IS" BASIS,
183
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
184
+ * See the License for the specific language governing permissions and
185
+ * limitations under the License.
186
+ */
187
+
188
+ /*
189
+ * Copyright 2025 Google LLC
190
+ *
191
+ * Licensed under the Apache License, Version 2.0 (the "License");
192
+ * you may not use this file except in compliance with the License.
193
+ * You may obtain a copy of the License at
194
+ *
195
+ * https://www.apache.org/licenses/LICENSE-2.0
196
+ *
197
+ * Unless required by applicable law or agreed to in writing, software
198
+ * distributed under the License is distributed on an "AS IS" BASIS,
199
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
+ * See the License for the specific language governing permissions and
201
+ * limitations under the License.
202
+ */
203
+ class Theme {
204
+ components = {};
205
+ elements = {};
206
+ markdown = {
207
+ p: [],
208
+ h1: [],
209
+ h2: [],
210
+ h3: [],
211
+ h4: [],
212
+ h5: [],
213
+ ul: [],
214
+ ol: [],
215
+ li: [],
216
+ a: [],
217
+ strong: [],
218
+ em: [],
219
+ };
220
+ additionalStyles;
221
+ update(theme) {
222
+ this.components = theme.components;
223
+ this.elements = theme.elements;
224
+ this.markdown = theme.markdown;
225
+ this.additionalStyles = theme.additionalStyles;
226
+ }
227
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: Theme, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
228
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: Theme, providedIn: 'root' });
229
+ }
230
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: Theme, decorators: [{
231
+ type: Injectable,
232
+ args: [{
233
+ providedIn: 'root',
234
+ }]
235
+ }] });
236
+
237
+ /*
238
+ * Copyright 2025 Google LLC
239
+ *
240
+ * Licensed under the Apache License, Version 2.0 (the "License");
241
+ * you may not use this file except in compliance with the License.
242
+ * You may obtain a copy of the License at
243
+ *
244
+ * https://www.apache.org/licenses/LICENSE-2.0
245
+ *
246
+ * Unless required by applicable law or agreed to in writing, software
247
+ * distributed under the License is distributed on an "AS IS" BASIS,
248
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
249
+ * See the License for the specific language governing permissions and
250
+ * limitations under the License.
251
+ */
252
+ let idCounter = 0;
253
+ class DynamicComponent {
254
+ processor = inject(MessageProcessor);
255
+ theme = inject(Theme);
256
+ surfaceId = input.required(...(ngDevMode ? [{ debugName: "surfaceId" }] : /* istanbul ignore next */ []));
257
+ component = input.required(...(ngDevMode ? [{ debugName: "component" }] : /* istanbul ignore next */ []));
258
+ weight = input.required(...(ngDevMode ? [{ debugName: "weight" }] : /* istanbul ignore next */ []));
259
+ sendAction(action) {
260
+ const component = this.component();
261
+ const surfaceId = this.surfaceId() ?? undefined;
262
+ const context = {};
263
+ if (action.context) {
264
+ for (const item of action.context) {
265
+ if (item.value.literalBoolean !== undefined) {
266
+ context[item.key] = item.value.literalBoolean;
267
+ }
268
+ else if (item.value.literalNumber !== undefined) {
269
+ context[item.key] = item.value.literalNumber;
270
+ }
271
+ else if (item.value.literalString !== undefined) {
272
+ context[item.key] = item.value.literalString;
273
+ }
274
+ else if (item.value.path) {
275
+ const path = this.processor.resolvePath(item.value.path, component.dataContextPath);
276
+ const value = this.processor.getData(component, path, surfaceId);
277
+ context[item.key] = value;
278
+ }
279
+ }
280
+ }
281
+ const message = {
282
+ userAction: {
283
+ name: action.name,
284
+ sourceComponentId: component.id,
285
+ surfaceId: surfaceId,
286
+ timestamp: new Date().toISOString(),
287
+ context,
288
+ },
289
+ };
290
+ return this.processor.dispatch(message);
291
+ }
292
+ resolvePrimitive(value) {
293
+ const component = this.component();
294
+ const surfaceId = this.surfaceId();
295
+ if (!value || typeof value !== 'object') {
296
+ return null;
297
+ }
298
+ else if ('literal' in value && value.literal != null) {
299
+ return value.literal;
300
+ }
301
+ else if (value.path) {
302
+ return this.processor.getData(component, value.path, surfaceId ?? undefined);
303
+ }
304
+ else if ('literalString' in value) {
305
+ return value.literalString;
306
+ }
307
+ else if ('literalNumber' in value) {
308
+ return value.literalNumber;
309
+ }
310
+ else if ('literalBoolean' in value) {
311
+ return value.literalBoolean;
312
+ }
313
+ return null;
314
+ }
315
+ getUniqueId(prefix) {
316
+ return `${prefix}-${idCounter++}`;
317
+ }
318
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: DynamicComponent, deps: [], target: i0.ɵɵFactoryTarget.Directive });
319
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.5", type: DynamicComponent, isStandalone: true, inputs: { surfaceId: { classPropertyName: "surfaceId", publicName: "surfaceId", isSignal: true, isRequired: true, transformFunction: null }, component: { classPropertyName: "component", publicName: "component", isSignal: true, isRequired: true, transformFunction: null }, weight: { classPropertyName: "weight", publicName: "weight", isSignal: true, isRequired: true, transformFunction: null } }, host: { properties: { "style.--weight": "weight()" } }, ngImport: i0 });
320
+ }
321
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: DynamicComponent, decorators: [{
322
+ type: Directive,
323
+ args: [{
324
+ host: {
325
+ '[style.--weight]': 'weight()',
326
+ },
327
+ }]
328
+ }], propDecorators: { surfaceId: [{ type: i0.Input, args: [{ isSignal: true, alias: "surfaceId", required: true }] }], component: [{ type: i0.Input, args: [{ isSignal: true, alias: "component", required: true }] }], weight: [{ type: i0.Input, args: [{ isSignal: true, alias: "weight", required: true }] }] } });
329
+
330
+ /*
331
+ * Copyright 2025 Google LLC
332
+ *
333
+ * Licensed under the Apache License, Version 2.0 (the "License");
334
+ * you may not use this file except in compliance with the License.
335
+ * You may obtain a copy of the License at
336
+ *
337
+ * https://www.apache.org/licenses/LICENSE-2.0
338
+ *
339
+ * Unless required by applicable law or agreed to in writing, software
340
+ * distributed under the License is distributed on an "AS IS" BASIS,
341
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
342
+ * See the License for the specific language governing permissions and
343
+ * limitations under the License.
344
+ */
345
+ class AudioPlayer extends DynamicComponent {
346
+ url = input.required(...(ngDevMode ? [{ debugName: "url" }] : /* istanbul ignore next */ []));
347
+ resolvedUrl = computed(() => this.resolvePrimitive(this.url()), ...(ngDevMode ? [{ debugName: "resolvedUrl" }] : /* istanbul ignore next */ []));
348
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: AudioPlayer, deps: null, target: i0.ɵɵFactoryTarget.Component });
349
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.5", type: AudioPlayer, isStandalone: true, selector: "a2ui-audio", inputs: { url: { classPropertyName: "url", publicName: "url", isSignal: true, isRequired: true, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: `
350
+ <audio controls [src]="resolvedUrl()" [style]="theme.additionalStyles?.AudioPlayer"></audio>
351
+ `, isInline: true, styles: [":host{display:flex}audio{width:100%}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
352
+ }
353
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: AudioPlayer, decorators: [{
354
+ type: Component,
355
+ args: [{ selector: 'a2ui-audio', template: `
356
+ <audio controls [src]="resolvedUrl()" [style]="theme.additionalStyles?.AudioPlayer"></audio>
357
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:flex}audio{width:100%}\n"] }]
358
+ }], propDecorators: { url: [{ type: i0.Input, args: [{ isSignal: true, alias: "url", required: true }] }] } });
359
+
360
+ /*
361
+ * Copyright 2025 Google LLC
362
+ *
363
+ * Licensed under the Apache License, Version 2.0 (the "License");
364
+ * you may not use this file except in compliance with the License.
365
+ * You may obtain a copy of the License at
366
+ *
367
+ * https://www.apache.org/licenses/LICENSE-2.0
368
+ *
369
+ * Unless required by applicable law or agreed to in writing, software
370
+ * distributed under the License is distributed on an "AS IS" BASIS,
371
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
372
+ * See the License for the specific language governing permissions and
373
+ * limitations under the License.
374
+ */
375
+ const Catalog = new InjectionToken('Catalog');
376
+
377
+ /*
378
+ * Copyright 2025 Google LLC
379
+ *
380
+ * Licensed under the Apache License, Version 2.0 (the "License");
381
+ * you may not use this file except in compliance with the License.
382
+ * You may obtain a copy of the License at
383
+ *
384
+ * https://www.apache.org/licenses/LICENSE-2.0
385
+ *
386
+ * Unless required by applicable law or agreed to in writing, software
387
+ * distributed under the License is distributed on an "AS IS" BASIS,
388
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
389
+ * See the License for the specific language governing permissions and
390
+ * limitations under the License.
391
+ */
392
+ class Renderer {
393
+ static hasInsertedStyles = false;
394
+ catalog = inject(Catalog);
395
+ container = inject(ViewContainerRef);
396
+ processor = inject(MessageProcessor);
397
+ surfaceId = input.required(...(ngDevMode ? [{ debugName: "surfaceId" }] : /* istanbul ignore next */ []));
398
+ component = input.required(...(ngDevMode ? [{ debugName: "component" }] : /* istanbul ignore next */ []));
399
+ currentId = null;
400
+ currentType = null;
401
+ currentComponentRef = null;
402
+ constructor() {
403
+ const platformId = inject(PLATFORM_ID);
404
+ const document = inject(DOCUMENT);
405
+ if (!Renderer.hasInsertedStyles && isPlatformBrowser(platformId)) {
406
+ const styleElement = document.createElement('style');
407
+ styleElement.textContent = structuralStyles;
408
+ document.head.appendChild(styleElement);
409
+ Renderer.hasInsertedStyles = true;
410
+ }
411
+ effect(() => {
412
+ // Explicitly depend on the MessageProcessor's version signal. This ensures that the effect re-runs
413
+ // whenever data model changes occur, even if the node's object reference remains identical
414
+ // (as in the case of in-place mutations from local updates).
415
+ this.processor.version();
416
+ let node = this.component();
417
+ const surfaceId = this.surfaceId();
418
+ // Handle v0.8 wrapped component format
419
+ if (!node.type && node.component) {
420
+ const wrapped = node.component;
421
+ const type = Object.keys(wrapped)[0];
422
+ if (type) {
423
+ node = {
424
+ ...node,
425
+ type: type,
426
+ properties: wrapped[type],
427
+ };
428
+ }
429
+ }
430
+ const id = node.id;
431
+ const type = node.type;
432
+ // Focus Loss Prevention:
433
+ // If we have an existing component and its unique identity (ID and Type) hasn't changed,
434
+ // we update its @Input() values in-place. This preserves the underlying DOM element,
435
+ // maintaining focus, text selection, and cursor position.
436
+ if (this.currentComponentRef && this.currentId === id && this.currentType === type) {
437
+ this.updateInputs(this.currentComponentRef, node, surfaceId);
438
+ return;
439
+ }
440
+ // Otherwise, clear and re-create the component because its identity has changed.
441
+ const container = this.container;
442
+ container.clear();
443
+ this.currentComponentRef = null;
444
+ this.currentId = id;
445
+ this.currentType = type;
446
+ const config = this.catalog[node.type];
447
+ if (!config) {
448
+ console.error(`Unknown component type: ${node.type}`);
449
+ return;
450
+ }
451
+ this.render(container, node, surfaceId, config);
452
+ });
453
+ }
454
+ render(container, node, surfaceId, config) {
455
+ const componentTypeOrPromise = this.resolveComponentType(config);
456
+ if (componentTypeOrPromise instanceof Promise) {
457
+ componentTypeOrPromise.then((componentType) => {
458
+ // Ensure we are still supposed to render this component
459
+ if (this.currentId === node.id && this.currentType === node.type) {
460
+ const componentRef = container.createComponent(componentType);
461
+ this.currentComponentRef = componentRef;
462
+ this.updateInputs(componentRef, node, surfaceId);
463
+ }
464
+ });
465
+ }
466
+ else if (componentTypeOrPromise) {
467
+ const componentRef = container.createComponent(componentTypeOrPromise);
468
+ this.currentComponentRef = componentRef;
469
+ this.updateInputs(componentRef, node, surfaceId);
470
+ }
471
+ }
472
+ resolveComponentType(config) {
473
+ if (typeof config === 'function') {
474
+ return config();
475
+ }
476
+ else if (typeof config === 'object' && config !== null) {
477
+ if (typeof config.type === 'function') {
478
+ return config.type();
479
+ }
480
+ else {
481
+ return config.type;
482
+ }
483
+ }
484
+ return null;
485
+ }
486
+ /**
487
+ * Updates the inputs of an existing component instance with the latest data from the node.
488
+ * This is called during component reuse to keep the UI in sync without losing DOM state (like focus).
489
+ */
490
+ updateInputs(componentRef, node, surfaceId) {
491
+ componentRef.setInput('surfaceId', surfaceId);
492
+ componentRef.setInput('component', node);
493
+ componentRef.setInput('weight', node.weight ?? 0);
494
+ const props = node.properties;
495
+ for (const [key, value] of Object.entries(props)) {
496
+ try {
497
+ componentRef.setInput(key, value);
498
+ }
499
+ catch (e) {
500
+ console.warn(`[Renderer] Property "${key}" could not be set on component ${node.type}. If this property is required by the specification, ensure the component declares it as an input.`);
501
+ }
502
+ }
503
+ componentRef.changeDetectorRef.markForCheck();
504
+ }
505
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: Renderer, deps: [], target: i0.ɵɵFactoryTarget.Directive });
506
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.5", type: Renderer, isStandalone: true, selector: "[a2ui-renderer]", inputs: { surfaceId: { classPropertyName: "surfaceId", publicName: "surfaceId", isSignal: true, isRequired: true, transformFunction: null }, component: { classPropertyName: "component", publicName: "component", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0 });
507
+ }
508
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: Renderer, decorators: [{
509
+ type: Directive,
510
+ args: [{
511
+ selector: '[a2ui-renderer]',
512
+ standalone: true,
513
+ }]
514
+ }], ctorParameters: () => [], propDecorators: { surfaceId: [{ type: i0.Input, args: [{ isSignal: true, alias: "surfaceId", required: true }] }], component: [{ type: i0.Input, args: [{ isSignal: true, alias: "component", required: true }] }] } });
515
+
516
+ /*
517
+ * Copyright 2025 Google LLC
518
+ *
519
+ * Licensed under the Apache License, Version 2.0 (the "License");
520
+ * you may not use this file except in compliance with the License.
521
+ * You may obtain a copy of the License at
522
+ *
523
+ * https://www.apache.org/licenses/LICENSE-2.0
524
+ *
525
+ * Unless required by applicable law or agreed to in writing, software
526
+ * distributed under the License is distributed on an "AS IS" BASIS,
527
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
528
+ * See the License for the specific language governing permissions and
529
+ * limitations under the License.
530
+ */
531
+ class Button extends DynamicComponent {
532
+ action = input(null, ...(ngDevMode ? [{ debugName: "action" }] : /* istanbul ignore next */ []));
533
+ child = input(null, ...(ngDevMode ? [{ debugName: "child" }] : /* istanbul ignore next */ []));
534
+ // This is currently not handled by the template.
535
+ primary = input(false, ...(ngDevMode ? [{ debugName: "primary" }] : /* istanbul ignore next */ []));
536
+ handleClick() {
537
+ const action = this.action();
538
+ if (action) {
539
+ super.sendAction(action);
540
+ }
541
+ }
542
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: Button, deps: null, target: i0.ɵɵFactoryTarget.Component });
543
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: Button, isStandalone: true, selector: "a2ui-button", inputs: { action: { classPropertyName: "action", publicName: "action", isSignal: true, isRequired: false, transformFunction: null }, child: { classPropertyName: "child", publicName: "child", isSignal: true, isRequired: false, transformFunction: null }, primary: { classPropertyName: "primary", publicName: "primary", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: `
544
+ <button
545
+ [class]="theme.components.Button"
546
+ [style]="theme.additionalStyles?.Button"
547
+ (click)="handleClick()"
548
+ >
549
+ @if (child()) {
550
+ <ng-container
551
+ a2ui-renderer
552
+ [surfaceId]="surfaceId()!"
553
+ [component]="child() ?? component().properties.child"
554
+ />
555
+ }
556
+ </button>
557
+ `, isInline: true, styles: [":host{display:block;flex:var(--weight);min-height:0}\n"], dependencies: [{ kind: "directive", type: Renderer, selector: "[a2ui-renderer]", inputs: ["surfaceId", "component"] }], changeDetection: i0.ChangeDetectionStrategy.Eager });
558
+ }
559
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: Button, decorators: [{
560
+ type: Component,
561
+ args: [{ selector: 'a2ui-button', imports: [Renderer], changeDetection: ChangeDetectionStrategy.Eager, template: `
562
+ <button
563
+ [class]="theme.components.Button"
564
+ [style]="theme.additionalStyles?.Button"
565
+ (click)="handleClick()"
566
+ >
567
+ @if (child()) {
568
+ <ng-container
569
+ a2ui-renderer
570
+ [surfaceId]="surfaceId()!"
571
+ [component]="child() ?? component().properties.child"
572
+ />
573
+ }
574
+ </button>
575
+ `, styles: [":host{display:block;flex:var(--weight);min-height:0}\n"] }]
576
+ }], propDecorators: { action: [{ type: i0.Input, args: [{ isSignal: true, alias: "action", required: false }] }], child: [{ type: i0.Input, args: [{ isSignal: true, alias: "child", required: false }] }], primary: [{ type: i0.Input, args: [{ isSignal: true, alias: "primary", required: false }] }] } });
577
+
578
+ /*
579
+ * Copyright 2025 Google LLC
580
+ *
581
+ * Licensed under the Apache License, Version 2.0 (the "License");
582
+ * you may not use this file except in compliance with the License.
583
+ * You may obtain a copy of the License at
584
+ *
585
+ * https://www.apache.org/licenses/LICENSE-2.0
586
+ *
587
+ * Unless required by applicable law or agreed to in writing, software
588
+ * distributed under the License is distributed on an "AS IS" BASIS,
589
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
590
+ * See the License for the specific language governing permissions and
591
+ * limitations under the License.
592
+ */
593
+ class Card extends DynamicComponent {
594
+ child = input(null, ...(ngDevMode ? [{ debugName: "child" }] : /* istanbul ignore next */ []));
595
+ children = input([], ...(ngDevMode ? [{ debugName: "children" }] : /* istanbul ignore next */ []));
596
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: Card, deps: null, target: i0.ɵɵFactoryTarget.Component });
597
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: Card, isStandalone: true, selector: "a2ui-card", inputs: { child: { classPropertyName: "child", publicName: "child", isSignal: true, isRequired: false, transformFunction: null }, children: { classPropertyName: "children", publicName: "children", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: `
598
+ <div [class]="theme.components.Card" [style]="theme.additionalStyles?.Card">
599
+ @if (child()) {
600
+ <ng-container a2ui-renderer [surfaceId]="surfaceId()!" [component]="child()!" />
601
+ }
602
+
603
+ @for (comp of children(); track comp.id) {
604
+ <ng-container a2ui-renderer [surfaceId]="surfaceId()!" [component]="comp" />
605
+ }
606
+ </div>
607
+ `, isInline: true, styles: [":host{display:block}\n"], dependencies: [{ kind: "directive", type: Renderer, selector: "[a2ui-renderer]", inputs: ["surfaceId", "component"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
608
+ }
609
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: Card, decorators: [{
610
+ type: Component,
611
+ args: [{ selector: 'a2ui-card', imports: [Renderer], template: `
612
+ <div [class]="theme.components.Card" [style]="theme.additionalStyles?.Card">
613
+ @if (child()) {
614
+ <ng-container a2ui-renderer [surfaceId]="surfaceId()!" [component]="child()!" />
615
+ }
616
+
617
+ @for (comp of children(); track comp.id) {
618
+ <ng-container a2ui-renderer [surfaceId]="surfaceId()!" [component]="comp" />
619
+ }
620
+ </div>
621
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block}\n"] }]
622
+ }], propDecorators: { child: [{ type: i0.Input, args: [{ isSignal: true, alias: "child", required: false }] }], children: [{ type: i0.Input, args: [{ isSignal: true, alias: "children", required: false }] }] } });
623
+
624
+ /*
625
+ * Copyright 2025 Google LLC
626
+ *
627
+ * Licensed under the Apache License, Version 2.0 (the "License");
628
+ * you may not use this file except in compliance with the License.
629
+ * You may obtain a copy of the License at
630
+ *
631
+ * https://www.apache.org/licenses/LICENSE-2.0
632
+ *
633
+ * Unless required by applicable law or agreed to in writing, software
634
+ * distributed under the License is distributed on an "AS IS" BASIS,
635
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
636
+ * See the License for the specific language governing permissions and
637
+ * limitations under the License.
638
+ */
639
+ class Checkbox extends DynamicComponent {
640
+ label = input.required(...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
641
+ checked = input.required(...(ngDevMode ? [{ debugName: "checked" }] : /* istanbul ignore next */ []));
642
+ inputChecked = computed(() => super.resolvePrimitive(this.checked()) ?? false, ...(ngDevMode ? [{ debugName: "inputChecked" }] : /* istanbul ignore next */ []));
643
+ resolvedLabel = computed(() => super.resolvePrimitive(this.label()), ...(ngDevMode ? [{ debugName: "resolvedLabel" }] : /* istanbul ignore next */ []));
644
+ inputId = super.getUniqueId('a2ui-checkbox');
645
+ onToggle(event) {
646
+ const checked = event.target.checked;
647
+ const checkedNode = this.checked();
648
+ if (checkedNode && typeof checkedNode === 'object' && 'path' in checkedNode && checkedNode.path) {
649
+ // Update the local data model directly to ensure immediate UI feedback and avoid unnecessary network requests.
650
+ this.processor.processMessages([{
651
+ dataModelUpdate: {
652
+ surfaceId: this.surfaceId(),
653
+ path: this.processor.resolvePath(checkedNode.path, this.component().dataContextPath),
654
+ contents: [{ key: '.', valueBoolean: checked }],
655
+ },
656
+ }]);
657
+ }
658
+ else {
659
+ this.sendAction({
660
+ name: 'toggle',
661
+ context: [{ key: 'checked', value: { literalBoolean: checked } }],
662
+ });
663
+ }
664
+ }
665
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: Checkbox, deps: null, target: i0.ɵɵFactoryTarget.Component });
666
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.5", type: Checkbox, isStandalone: true, selector: "a2ui-checkbox", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, checked: { classPropertyName: "checked", publicName: "checked", isSignal: true, isRequired: true, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: `
667
+ <label>
668
+ <input
669
+ type="checkbox"
670
+ [id]="inputId"
671
+ [checked]="inputChecked()"
672
+ (change)="onToggle($event)"
673
+ />
674
+ {{ resolvedLabel() }}
675
+ </label>
676
+ `, isInline: true, styles: [":host{display:flex;align-items:center;gap:.5rem}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
677
+ }
678
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: Checkbox, decorators: [{
679
+ type: Component,
680
+ args: [{ selector: 'a2ui-checkbox', template: `
681
+ <label>
682
+ <input
683
+ type="checkbox"
684
+ [id]="inputId"
685
+ [checked]="inputChecked()"
686
+ (change)="onToggle($event)"
687
+ />
688
+ {{ resolvedLabel() }}
689
+ </label>
690
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:flex;align-items:center;gap:.5rem}\n"] }]
691
+ }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], checked: [{ type: i0.Input, args: [{ isSignal: true, alias: "checked", required: true }] }] } });
692
+
693
+ /*
694
+ * Copyright 2025 Google LLC
695
+ *
696
+ * Licensed under the Apache License, Version 2.0 (the "License");
697
+ * you may not use this file except in compliance with the License.
698
+ * You may obtain a copy of the License at
699
+ *
700
+ * https://www.apache.org/licenses/LICENSE-2.0
701
+ *
702
+ * Unless required by applicable law or agreed to in writing, software
703
+ * distributed under the License is distributed on an "AS IS" BASIS,
704
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
705
+ * See the License for the specific language governing permissions and
706
+ * limitations under the License.
707
+ */
708
+ class Column extends DynamicComponent {
709
+ alignment = input('stretch', ...(ngDevMode ? [{ debugName: "alignment" }] : /* istanbul ignore next */ []));
710
+ distribution = input('start', ...(ngDevMode ? [{ debugName: "distribution" }] : /* istanbul ignore next */ []));
711
+ children = input(...(ngDevMode ? [undefined, { debugName: "children" }] : /* istanbul ignore next */ []));
712
+ classes = computed(() => ({
713
+ ...this.theme.components.Column,
714
+ [`align-${this.alignment()}`]: true,
715
+ [`distribute-${this.distribution()}`]: true,
716
+ }), ...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
717
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: Column, deps: null, target: i0.ɵɵFactoryTarget.Component });
718
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: Column, isStandalone: true, selector: "a2ui-column", inputs: { alignment: { classPropertyName: "alignment", publicName: "alignment", isSignal: true, isRequired: false, transformFunction: null }, distribution: { classPropertyName: "distribution", publicName: "distribution", isSignal: true, isRequired: false, transformFunction: null }, children: { classPropertyName: "children", publicName: "children", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: `
719
+ <section [class]="classes()" [style]="theme.additionalStyles?.Column">
720
+ @for (child of children() ?? component().properties.children; track child?.id ?? child) {
721
+ @if (child) {
722
+ <ng-container a2ui-renderer [surfaceId]="surfaceId()!" [component]="child" />
723
+ }
724
+ }
725
+ </section>
726
+ `, isInline: true, styles: [":host{display:flex;flex:var(--weight)}section{display:flex;flex-direction:column;min-width:100%;height:100%;box-sizing:border-box}.align-start{align-items:start}.align-center{align-items:center}.align-end{align-items:end}.align-stretch{align-items:stretch}.distribute-start{justify-content:start}.distribute-center{justify-content:center}.distribute-end{justify-content:end}.distribute-spaceBetween{justify-content:space-between}.distribute-spaceAround{justify-content:space-around}.distribute-spaceEvenly{justify-content:space-evenly}\n"], dependencies: [{ kind: "directive", type: Renderer, selector: "[a2ui-renderer]", inputs: ["surfaceId", "component"] }], changeDetection: i0.ChangeDetectionStrategy.Eager });
727
+ }
728
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: Column, decorators: [{
729
+ type: Component,
730
+ args: [{ selector: 'a2ui-column', imports: [Renderer], changeDetection: ChangeDetectionStrategy.Eager, template: `
731
+ <section [class]="classes()" [style]="theme.additionalStyles?.Column">
732
+ @for (child of children() ?? component().properties.children; track child?.id ?? child) {
733
+ @if (child) {
734
+ <ng-container a2ui-renderer [surfaceId]="surfaceId()!" [component]="child" />
735
+ }
736
+ }
737
+ </section>
738
+ `, styles: [":host{display:flex;flex:var(--weight)}section{display:flex;flex-direction:column;min-width:100%;height:100%;box-sizing:border-box}.align-start{align-items:start}.align-center{align-items:center}.align-end{align-items:end}.align-stretch{align-items:stretch}.distribute-start{justify-content:start}.distribute-center{justify-content:center}.distribute-end{justify-content:end}.distribute-spaceBetween{justify-content:space-between}.distribute-spaceAround{justify-content:space-around}.distribute-spaceEvenly{justify-content:space-evenly}\n"] }]
739
+ }], propDecorators: { alignment: [{ type: i0.Input, args: [{ isSignal: true, alias: "alignment", required: false }] }], distribution: [{ type: i0.Input, args: [{ isSignal: true, alias: "distribution", required: false }] }], children: [{ type: i0.Input, args: [{ isSignal: true, alias: "children", required: false }] }] } });
740
+
741
+ /*
742
+ * Copyright 2025 Google LLC
743
+ *
744
+ * Licensed under the Apache License, Version 2.0 (the "License");
745
+ * you may not use this file except in compliance with the License.
746
+ * You may obtain a copy of the License at
747
+ *
748
+ * https://www.apache.org/licenses/LICENSE-2.0
749
+ *
750
+ * Unless required by applicable law or agreed to in writing, software
751
+ * distributed under the License is distributed on an "AS IS" BASIS,
752
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
753
+ * See the License for the specific language governing permissions and
754
+ * limitations under the License.
755
+ */
756
+ class DateTimeInput extends DynamicComponent {
757
+ label = input(null, ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
758
+ value = input.required(...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
759
+ enableDate = input(true, ...(ngDevMode ? [{ debugName: "enableDate" }] : /* istanbul ignore next */ []));
760
+ enableTime = input(false, ...(ngDevMode ? [{ debugName: "enableTime" }] : /* istanbul ignore next */ []));
761
+ inputId = super.getUniqueId('a2ui-datetime-input');
762
+ inputType = computed(() => {
763
+ if (this.enableDate() && this.enableTime())
764
+ return 'datetime-local';
765
+ if (this.enableTime())
766
+ return 'time';
767
+ return 'date';
768
+ }, ...(ngDevMode ? [{ debugName: "inputType" }] : /* istanbul ignore next */ []));
769
+ resolvedLabel = computed(() => super.resolvePrimitive(this.label()), ...(ngDevMode ? [{ debugName: "resolvedLabel" }] : /* istanbul ignore next */ []));
770
+ resolvedValue = computed(() => super.resolvePrimitive(this.value()), ...(ngDevMode ? [{ debugName: "resolvedValue" }] : /* istanbul ignore next */ []));
771
+ onChange(event) {
772
+ const value = event.target.value;
773
+ const valueNode = this.value();
774
+ if (valueNode && typeof valueNode === 'object' && 'path' in valueNode && valueNode.path) {
775
+ // Update the local data model directly to ensure immediate UI feedback and avoid unnecessary network requests.
776
+ this.processor.processMessages([{
777
+ dataModelUpdate: {
778
+ surfaceId: this.surfaceId(),
779
+ path: this.processor.resolvePath(valueNode.path, this.component().dataContextPath),
780
+ contents: [{ key: '.', valueString: value }],
781
+ },
782
+ }]);
783
+ }
784
+ else {
785
+ this.handleAction('change', { value });
786
+ }
787
+ }
788
+ handleAction(name, context) {
789
+ super.sendAction({
790
+ name,
791
+ context: Object.entries(context).map(([key, val]) => ({
792
+ key,
793
+ value: typeof val === 'number' ? { literalNumber: val } : { literalString: String(val) },
794
+ })),
795
+ });
796
+ }
797
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: DateTimeInput, deps: null, target: i0.ɵɵFactoryTarget.Component });
798
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.5", type: DateTimeInput, isStandalone: true, selector: "a2ui-datetime-input", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: true, transformFunction: null }, enableDate: { classPropertyName: "enableDate", publicName: "enableDate", isSignal: true, isRequired: false, transformFunction: null }, enableTime: { classPropertyName: "enableTime", publicName: "enableTime", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: `
799
+ <div
800
+ [class]="theme.components.DateTimeInput.container"
801
+ [style]="theme.additionalStyles?.DateTimeInput"
802
+ >
803
+ <label [class]="theme.components.DateTimeInput.label" [for]="inputId">
804
+ {{ resolvedLabel() }}
805
+ </label>
806
+ <input
807
+ [type]="inputType()"
808
+ [class]="theme.components.DateTimeInput.element"
809
+ [id]="inputId"
810
+ [value]="resolvedValue() ?? ''"
811
+ (change)="onChange($event)"
812
+ />
813
+ </div>
814
+ `, isInline: true, styles: [":host{display:block}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
815
+ }
816
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: DateTimeInput, decorators: [{
817
+ type: Component,
818
+ args: [{ selector: 'a2ui-datetime-input', template: `
819
+ <div
820
+ [class]="theme.components.DateTimeInput.container"
821
+ [style]="theme.additionalStyles?.DateTimeInput"
822
+ >
823
+ <label [class]="theme.components.DateTimeInput.label" [for]="inputId">
824
+ {{ resolvedLabel() }}
825
+ </label>
826
+ <input
827
+ [type]="inputType()"
828
+ [class]="theme.components.DateTimeInput.element"
829
+ [id]="inputId"
830
+ [value]="resolvedValue() ?? ''"
831
+ (change)="onChange($event)"
832
+ />
833
+ </div>
834
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block}\n"] }]
835
+ }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: true }] }], enableDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "enableDate", required: false }] }], enableTime: [{ type: i0.Input, args: [{ isSignal: true, alias: "enableTime", required: false }] }] } });
836
+
837
+ /*
838
+ * Copyright 2025 Google LLC
839
+ *
840
+ * Licensed under the Apache License, Version 2.0 (the "License");
841
+ * you may not use this file except in compliance with the License.
842
+ * You may obtain a copy of the License at
843
+ *
844
+ * https://www.apache.org/licenses/LICENSE-2.0
845
+ *
846
+ * Unless required by applicable law or agreed to in writing, software
847
+ * distributed under the License is distributed on an "AS IS" BASIS,
848
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
849
+ * See the License for the specific language governing permissions and
850
+ * limitations under the License.
851
+ */
852
+ class Divider extends DynamicComponent {
853
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: Divider, deps: null, target: i0.ɵɵFactoryTarget.Component });
854
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.5", type: Divider, isStandalone: true, selector: "a2ui-divider", usesInheritance: true, ngImport: i0, template: '<hr [class]="theme.components.Divider" [style]="theme.additionalStyles?.Divider"/>', isInline: true, styles: [":host{display:block;min-height:0;overflow:auto}hr{height:1px;background:#ccc;border:none}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
855
+ }
856
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: Divider, decorators: [{
857
+ type: Component,
858
+ args: [{ selector: 'a2ui-divider', changeDetection: ChangeDetectionStrategy.OnPush, template: '<hr [class]="theme.components.Divider" [style]="theme.additionalStyles?.Divider"/>', styles: [":host{display:block;min-height:0;overflow:auto}hr{height:1px;background:#ccc;border:none}\n"] }]
859
+ }] });
860
+
861
+ /*
862
+ * Copyright 2025 Google LLC
863
+ *
864
+ * Licensed under the Apache License, Version 2.0 (the "License");
865
+ * you may not use this file except in compliance with the License.
866
+ * You may obtain a copy of the License at
867
+ *
868
+ * https://www.apache.org/licenses/LICENSE-2.0
869
+ *
870
+ * Unless required by applicable law or agreed to in writing, software
871
+ * distributed under the License is distributed on an "AS IS" BASIS,
872
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
873
+ * See the License for the specific language governing permissions and
874
+ * limitations under the License.
875
+ */
876
+ class Icon extends DynamicComponent {
877
+ name = input(null, ...(ngDevMode ? [{ debugName: "name" }] : /* istanbul ignore next */ []));
878
+ resolvedName = computed(() => this.resolvePrimitive(this.name()), ...(ngDevMode ? [{ debugName: "resolvedName" }] : /* istanbul ignore next */ []));
879
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: Icon, deps: null, target: i0.ɵɵFactoryTarget.Component });
880
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: Icon, isStandalone: true, selector: "a2ui-icon", inputs: { name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "aria-hidden": "true", "tabindex": "-1" } }, usesInheritance: true, ngImport: i0, template: `
881
+ @let resolvedName = this.resolvedName();
882
+
883
+ @if (resolvedName) {
884
+ <section [class]="theme.components.Icon" [style]="theme.additionalStyles?.Icon">
885
+ <span class="g-icon">{{ resolvedName }}</span>
886
+ </section>
887
+ }
888
+ `, isInline: true, styles: [":host{display:block;flex:var(--weight);min-height:0;overflow:auto}\n"], changeDetection: i0.ChangeDetectionStrategy.Eager });
889
+ }
890
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: Icon, decorators: [{
891
+ type: Component,
892
+ args: [{ selector: 'a2ui-icon', host: {
893
+ 'aria-hidden': 'true',
894
+ tabindex: '-1',
895
+ }, changeDetection: ChangeDetectionStrategy.Eager, template: `
896
+ @let resolvedName = this.resolvedName();
897
+
898
+ @if (resolvedName) {
899
+ <section [class]="theme.components.Icon" [style]="theme.additionalStyles?.Icon">
900
+ <span class="g-icon">{{ resolvedName }}</span>
901
+ </section>
902
+ }
903
+ `, styles: [":host{display:block;flex:var(--weight);min-height:0;overflow:auto}\n"] }]
904
+ }], propDecorators: { name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }] } });
905
+
906
+ /*
907
+ * Copyright 2025 Google LLC
908
+ *
909
+ * Licensed under the Apache License, Version 2.0 (the "License");
910
+ * you may not use this file except in compliance with the License.
911
+ * You may obtain a copy of the License at
912
+ *
913
+ * https://www.apache.org/licenses/LICENSE-2.0
914
+ *
915
+ * Unless required by applicable law or agreed to in writing, software
916
+ * distributed under the License is distributed on an "AS IS" BASIS,
917
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
918
+ * See the License for the specific language governing permissions and
919
+ * limitations under the License.
920
+ */
921
+ class Image extends DynamicComponent {
922
+ url = input(null, ...(ngDevMode ? [{ debugName: "url" }] : /* istanbul ignore next */ []));
923
+ usageHint = input(null, ...(ngDevMode ? [{ debugName: "usageHint" }] : /* istanbul ignore next */ []));
924
+ fit = input(null, ...(ngDevMode ? [{ debugName: "fit" }] : /* istanbul ignore next */ []));
925
+ altText = input(null, ...(ngDevMode ? [{ debugName: "altText" }] : /* istanbul ignore next */ []));
926
+ resolvedUrl = computed(() => this.resolvePrimitive(this.url()), ...(ngDevMode ? [{ debugName: "resolvedUrl" }] : /* istanbul ignore next */ []));
927
+ resolvedAltText = computed(() => this.resolvePrimitive(this.altText()) || '', ...(ngDevMode ? [{ debugName: "resolvedAltText" }] : /* istanbul ignore next */ []));
928
+ classes = computed(() => {
929
+ const usageHint = this.usageHint();
930
+ return Styles.merge(this.theme.components.Image.all, usageHint ? this.theme.components.Image[usageHint] : {});
931
+ }, ...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
932
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: Image, deps: null, target: i0.ɵɵFactoryTarget.Component });
933
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: Image, isStandalone: true, selector: "a2ui-image", inputs: { url: { classPropertyName: "url", publicName: "url", isSignal: true, isRequired: false, transformFunction: null }, usageHint: { classPropertyName: "usageHint", publicName: "usageHint", isSignal: true, isRequired: false, transformFunction: null }, fit: { classPropertyName: "fit", publicName: "fit", isSignal: true, isRequired: false, transformFunction: null }, altText: { classPropertyName: "altText", publicName: "altText", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: `
934
+ @let resolvedUrl = this.resolvedUrl();
935
+ @let resolvedAltText = this.resolvedAltText();
936
+
937
+ @if (resolvedUrl) {
938
+ <section [class]="classes()" [style]="theme.additionalStyles?.Image">
939
+ <img [src]="resolvedUrl" [alt]="resolvedAltText" />
940
+ </section>
941
+ }
942
+ `, isInline: true, styles: [":host{display:block;flex:var(--weight);min-height:0;overflow:auto}img{display:block;width:100%;height:100%;box-sizing:border-box}\n"], changeDetection: i0.ChangeDetectionStrategy.Eager });
943
+ }
944
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: Image, decorators: [{
945
+ type: Component,
946
+ args: [{ selector: 'a2ui-image', changeDetection: ChangeDetectionStrategy.Eager, template: `
947
+ @let resolvedUrl = this.resolvedUrl();
948
+ @let resolvedAltText = this.resolvedAltText();
949
+
950
+ @if (resolvedUrl) {
951
+ <section [class]="classes()" [style]="theme.additionalStyles?.Image">
952
+ <img [src]="resolvedUrl" [alt]="resolvedAltText" />
953
+ </section>
954
+ }
955
+ `, styles: [":host{display:block;flex:var(--weight);min-height:0;overflow:auto}img{display:block;width:100%;height:100%;box-sizing:border-box}\n"] }]
956
+ }], propDecorators: { url: [{ type: i0.Input, args: [{ isSignal: true, alias: "url", required: false }] }], usageHint: [{ type: i0.Input, args: [{ isSignal: true, alias: "usageHint", required: false }] }], fit: [{ type: i0.Input, args: [{ isSignal: true, alias: "fit", required: false }] }], altText: [{ type: i0.Input, args: [{ isSignal: true, alias: "altText", required: false }] }] } });
957
+
958
+ /*
959
+ * Copyright 2025 Google LLC
960
+ *
961
+ * Licensed under the Apache License, Version 2.0 (the "License");
962
+ * you may not use this file except in compliance with the License.
963
+ * You may obtain a copy of the License at
964
+ *
965
+ * https://www.apache.org/licenses/LICENSE-2.0
966
+ *
967
+ * Unless required by applicable law or agreed to in writing, software
968
+ * distributed under the License is distributed on an "AS IS" BASIS,
969
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
970
+ * See the License for the specific language governing permissions and
971
+ * limitations under the License.
972
+ */
973
+ class List extends DynamicComponent {
974
+ alignment = input('stretch', ...(ngDevMode ? [{ debugName: "alignment" }] : /* istanbul ignore next */ []));
975
+ direction = input('vertical', ...(ngDevMode ? [{ debugName: "direction" }] : /* istanbul ignore next */ []));
976
+ children = input(null, ...(ngDevMode ? [{ debugName: "children" }] : /* istanbul ignore next */ []));
977
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: List, deps: null, target: i0.ɵɵFactoryTarget.Component });
978
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: List, isStandalone: true, selector: "a2ui-list", inputs: { alignment: { classPropertyName: "alignment", publicName: "alignment", isSignal: true, isRequired: false, transformFunction: null }, direction: { classPropertyName: "direction", publicName: "direction", isSignal: true, isRequired: false, transformFunction: null }, children: { classPropertyName: "children", publicName: "children", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.direction": "direction()" } }, usesInheritance: true, ngImport: i0, template: `
979
+ <section [class]="theme.components.List" [style]="theme.additionalStyles?.List">
980
+ @for (child of children() ?? component().properties.children; track child?.id ?? child) {
981
+ @if (child) {
982
+ <div class="a2ui-list-item">
983
+ <ng-container a2ui-renderer [surfaceId]="surfaceId()!" [component]="child" />
984
+ </div>
985
+ }
986
+ }
987
+ </section>
988
+ `, isInline: true, styles: [":host{display:block;flex:var(--weight);min-height:0}:host([direction=\"vertical\"]) section{display:flex;flex-direction:column;max-height:100%;overflow-y:auto}:host([direction=\"horizontal\"]) section{display:flex;max-width:100%;overflow-x:auto;overflow-y:hidden;scrollbar-width:none}.a2ui-list-item{display:flex;cursor:pointer;box-sizing:border-box}\n"], dependencies: [{ kind: "directive", type: Renderer, selector: "[a2ui-renderer]", inputs: ["surfaceId", "component"] }], changeDetection: i0.ChangeDetectionStrategy.Eager });
989
+ }
990
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: List, decorators: [{
991
+ type: Component,
992
+ args: [{ selector: 'a2ui-list', imports: [Renderer], changeDetection: ChangeDetectionStrategy.Eager, host: {
993
+ '[attr.direction]': 'direction()',
994
+ }, template: `
995
+ <section [class]="theme.components.List" [style]="theme.additionalStyles?.List">
996
+ @for (child of children() ?? component().properties.children; track child?.id ?? child) {
997
+ @if (child) {
998
+ <div class="a2ui-list-item">
999
+ <ng-container a2ui-renderer [surfaceId]="surfaceId()!" [component]="child" />
1000
+ </div>
1001
+ }
1002
+ }
1003
+ </section>
1004
+ `, styles: [":host{display:block;flex:var(--weight);min-height:0}:host([direction=\"vertical\"]) section{display:flex;flex-direction:column;max-height:100%;overflow-y:auto}:host([direction=\"horizontal\"]) section{display:flex;max-width:100%;overflow-x:auto;overflow-y:hidden;scrollbar-width:none}.a2ui-list-item{display:flex;cursor:pointer;box-sizing:border-box}\n"] }]
1005
+ }], propDecorators: { alignment: [{ type: i0.Input, args: [{ isSignal: true, alias: "alignment", required: false }] }], direction: [{ type: i0.Input, args: [{ isSignal: true, alias: "direction", required: false }] }], children: [{ type: i0.Input, args: [{ isSignal: true, alias: "children", required: false }] }] } });
1006
+
1007
+ /*
1008
+ * Copyright 2025 Google LLC
1009
+ *
1010
+ * Licensed under the Apache License, Version 2.0 (the "License");
1011
+ * you may not use this file except in compliance with the License.
1012
+ * You may obtain a copy of the License at
1013
+ *
1014
+ * https://www.apache.org/licenses/LICENSE-2.0
1015
+ *
1016
+ * Unless required by applicable law or agreed to in writing, software
1017
+ * distributed under the License is distributed on an "AS IS" BASIS,
1018
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1019
+ * See the License for the specific language governing permissions and
1020
+ * limitations under the License.
1021
+ */
1022
+ class Modal extends DynamicComponent {
1023
+ entryPointChild = input.required(...(ngDevMode ? [{ debugName: "entryPointChild" }] : /* istanbul ignore next */ []));
1024
+ contentChild = input.required(...(ngDevMode ? [{ debugName: "contentChild" }] : /* istanbul ignore next */ []));
1025
+ isOpen = signal(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : /* istanbul ignore next */ []));
1026
+ openModal() {
1027
+ this.isOpen.set(true);
1028
+ }
1029
+ closeModal() {
1030
+ this.isOpen.set(false);
1031
+ }
1032
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: Modal, deps: null, target: i0.ɵɵFactoryTarget.Component });
1033
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: Modal, isStandalone: true, selector: "a2ui-modal", inputs: { entryPointChild: { classPropertyName: "entryPointChild", publicName: "entryPointChild", isSignal: true, isRequired: true, transformFunction: null }, contentChild: { classPropertyName: "contentChild", publicName: "contentChild", isSignal: true, isRequired: true, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: `
1034
+ <div class="a2ui-modal-entry-point" (click)="openModal()">
1035
+ @if (entryPointChild()) {
1036
+ <ng-container
1037
+ a2ui-renderer
1038
+ [surfaceId]="surfaceId()!"
1039
+ [component]="entryPointChild()!"
1040
+ />
1041
+ }
1042
+ </div>
1043
+
1044
+ @if (isOpen()) {
1045
+ <div [class]="theme.components.Modal.backdrop" (click)="closeModal()">
1046
+ <div [class]="theme.components.Modal.element" (click)="$event.stopPropagation()">
1047
+ @if (contentChild()) {
1048
+ <ng-container
1049
+ a2ui-renderer
1050
+ [surfaceId]="surfaceId()!"
1051
+ [component]="contentChild()!"
1052
+ />
1053
+ }
1054
+ </div>
1055
+ </div>
1056
+ }
1057
+ `, isInline: true, styles: [":host{display:inline-block}.a2ui-modal-entry-point{cursor:pointer}\n"], dependencies: [{ kind: "directive", type: Renderer, selector: "[a2ui-renderer]", inputs: ["surfaceId", "component"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1058
+ }
1059
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: Modal, decorators: [{
1060
+ type: Component,
1061
+ args: [{ selector: 'a2ui-modal', imports: [Renderer], template: `
1062
+ <div class="a2ui-modal-entry-point" (click)="openModal()">
1063
+ @if (entryPointChild()) {
1064
+ <ng-container
1065
+ a2ui-renderer
1066
+ [surfaceId]="surfaceId()!"
1067
+ [component]="entryPointChild()!"
1068
+ />
1069
+ }
1070
+ </div>
1071
+
1072
+ @if (isOpen()) {
1073
+ <div [class]="theme.components.Modal.backdrop" (click)="closeModal()">
1074
+ <div [class]="theme.components.Modal.element" (click)="$event.stopPropagation()">
1075
+ @if (contentChild()) {
1076
+ <ng-container
1077
+ a2ui-renderer
1078
+ [surfaceId]="surfaceId()!"
1079
+ [component]="contentChild()!"
1080
+ />
1081
+ }
1082
+ </div>
1083
+ </div>
1084
+ }
1085
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:inline-block}.a2ui-modal-entry-point{cursor:pointer}\n"] }]
1086
+ }], propDecorators: { entryPointChild: [{ type: i0.Input, args: [{ isSignal: true, alias: "entryPointChild", required: true }] }], contentChild: [{ type: i0.Input, args: [{ isSignal: true, alias: "contentChild", required: true }] }] } });
1087
+
1088
+ /*
1089
+ * Copyright 2025 Google LLC
1090
+ *
1091
+ * Licensed under the Apache License, Version 2.0 (the "License");
1092
+ * you may not use this file except in compliance with the License.
1093
+ * You may obtain a copy of the License at
1094
+ *
1095
+ * https://www.apache.org/licenses/LICENSE-2.0
1096
+ *
1097
+ * Unless required by applicable law or agreed to in writing, software
1098
+ * distributed under the License is distributed on an "AS IS" BASIS,
1099
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1100
+ * See the License for the specific language governing permissions and
1101
+ * limitations under the License.
1102
+ */
1103
+ class MultipleChoice extends DynamicComponent {
1104
+ label = input(null, ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
1105
+ options = input.required(...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
1106
+ selections = input.required(...(ngDevMode ? [{ debugName: "selections" }] : /* istanbul ignore next */ []));
1107
+ selectId = super.getUniqueId('a2ui-multiple-choice');
1108
+ resolvedLabel = computed(() => this.resolvePrimitive(this.label()), ...(ngDevMode ? [{ debugName: "resolvedLabel" }] : /* istanbul ignore next */ []));
1109
+ resolvedOptions = computed(() => this.options().map((opt) => ({
1110
+ label: this.resolvePrimitive(opt.label),
1111
+ value: opt.value,
1112
+ })), ...(ngDevMode ? [{ debugName: "resolvedOptions" }] : /* istanbul ignore next */ []));
1113
+ resolvedSelections = computed(() => {
1114
+ const s = this.selections();
1115
+ if (s && typeof s === 'object' && 'literalArray' in s) {
1116
+ return s.literalArray;
1117
+ }
1118
+ return [];
1119
+ }, ...(ngDevMode ? [{ debugName: "resolvedSelections" }] : /* istanbul ignore next */ []));
1120
+ onChange(event) {
1121
+ const value = event.target.value;
1122
+ const selectionsNode = this.selections();
1123
+ if (selectionsNode && typeof selectionsNode === 'object' && 'path' in selectionsNode && selectionsNode.path) {
1124
+ // Update the local data model directly to ensure immediate UI feedback and avoid unnecessary network requests.
1125
+ this.processor.processMessages([{
1126
+ dataModelUpdate: {
1127
+ surfaceId: this.surfaceId(),
1128
+ path: this.processor.resolvePath(selectionsNode.path, this.component().dataContextPath),
1129
+ contents: [{ key: '.', valueString: JSON.stringify({ literalArray: [value] }) }],
1130
+ },
1131
+ }]);
1132
+ }
1133
+ else {
1134
+ this.handleAction('change', { value });
1135
+ }
1136
+ }
1137
+ handleAction(name, context) {
1138
+ super.sendAction({
1139
+ name,
1140
+ context: Object.entries(context).map(([key, val]) => ({
1141
+ key,
1142
+ value: typeof val === 'number' ? { literalNumber: val } : { literalString: String(val) },
1143
+ })),
1144
+ });
1145
+ }
1146
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: MultipleChoice, deps: null, target: i0.ɵɵFactoryTarget.Component });
1147
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: MultipleChoice, isStandalone: true, selector: "a2ui-multiple-choice", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: true, transformFunction: null }, selections: { classPropertyName: "selections", publicName: "selections", isSignal: true, isRequired: true, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: `
1148
+ <div
1149
+ [class]="theme.components.MultipleChoice.container"
1150
+ [style]="theme.additionalStyles?.MultipleChoice"
1151
+ >
1152
+ <label [class]="theme.components.MultipleChoice.label" [for]="selectId">
1153
+ {{ resolvedLabel() }}
1154
+ </label>
1155
+ <select
1156
+ [class]="theme.components.MultipleChoice.element"
1157
+ [id]="selectId"
1158
+ [value]="resolvedSelections()[0] || ''"
1159
+ (change)="onChange($event)"
1160
+ >
1161
+ @for (option of resolvedOptions(); track option.value) {
1162
+ <option [value]="option.value">{{ option.label }}</option>
1163
+ }
1164
+ </select>
1165
+ </div>
1166
+ `, isInline: true, styles: [":host{display:block}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1167
+ }
1168
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: MultipleChoice, decorators: [{
1169
+ type: Component,
1170
+ args: [{ selector: 'a2ui-multiple-choice', template: `
1171
+ <div
1172
+ [class]="theme.components.MultipleChoice.container"
1173
+ [style]="theme.additionalStyles?.MultipleChoice"
1174
+ >
1175
+ <label [class]="theme.components.MultipleChoice.label" [for]="selectId">
1176
+ {{ resolvedLabel() }}
1177
+ </label>
1178
+ <select
1179
+ [class]="theme.components.MultipleChoice.element"
1180
+ [id]="selectId"
1181
+ [value]="resolvedSelections()[0] || ''"
1182
+ (change)="onChange($event)"
1183
+ >
1184
+ @for (option of resolvedOptions(); track option.value) {
1185
+ <option [value]="option.value">{{ option.label }}</option>
1186
+ }
1187
+ </select>
1188
+ </div>
1189
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block}\n"] }]
1190
+ }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: true }] }], selections: [{ type: i0.Input, args: [{ isSignal: true, alias: "selections", required: true }] }] } });
1191
+
1192
+ /*
1193
+ * Copyright 2025 Google LLC
1194
+ *
1195
+ * Licensed under the Apache License, Version 2.0 (the "License");
1196
+ * you may not use this file except in compliance with the License.
1197
+ * You may obtain a copy of the License at
1198
+ *
1199
+ * https://www.apache.org/licenses/LICENSE-2.0
1200
+ *
1201
+ * Unless required by applicable law or agreed to in writing, software
1202
+ * distributed under the License is distributed on an "AS IS" BASIS,
1203
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1204
+ * See the License for the specific language governing permissions and
1205
+ * limitations under the License.
1206
+ */
1207
+ class Row extends DynamicComponent {
1208
+ alignment = input('stretch', ...(ngDevMode ? [{ debugName: "alignment" }] : /* istanbul ignore next */ []));
1209
+ distribution = input('start', ...(ngDevMode ? [{ debugName: "distribution" }] : /* istanbul ignore next */ []));
1210
+ children = input(...(ngDevMode ? [undefined, { debugName: "children" }] : /* istanbul ignore next */ []));
1211
+ classes = computed(() => ({
1212
+ ...this.theme.components.Row,
1213
+ [`align-${this.alignment()}`]: true,
1214
+ [`distribute-${this.distribution()}`]: true,
1215
+ }), ...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
1216
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: Row, deps: null, target: i0.ɵɵFactoryTarget.Component });
1217
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: Row, isStandalone: true, selector: "a2ui-row", inputs: { alignment: { classPropertyName: "alignment", publicName: "alignment", isSignal: true, isRequired: false, transformFunction: null }, distribution: { classPropertyName: "distribution", publicName: "distribution", isSignal: true, isRequired: false, transformFunction: null }, children: { classPropertyName: "children", publicName: "children", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.alignment": "alignment()", "attr.distribution": "distribution()" } }, usesInheritance: true, ngImport: i0, template: `
1218
+ <section [class]="classes()" [style]="theme.additionalStyles?.Row">
1219
+ @for (child of children() ?? component().properties.children; track child?.id ?? child) {
1220
+ @if (child) {
1221
+ <ng-container a2ui-renderer [surfaceId]="surfaceId()!" [component]="child" />
1222
+ }
1223
+ }
1224
+ </section>
1225
+ `, isInline: true, styles: [":host{display:flex;flex:var(--weight)}section{display:flex;flex-direction:row;width:100%;min-height:100%;box-sizing:border-box}.align-start{align-items:start}.align-center{align-items:center}.align-end{align-items:end}.align-stretch{align-items:stretch}.distribute-start{justify-content:start}.distribute-center{justify-content:center}.distribute-end{justify-content:end}.distribute-spaceBetween{justify-content:space-between}.distribute-spaceAround{justify-content:space-around}.distribute-spaceEvenly{justify-content:space-evenly}\n"], dependencies: [{ kind: "directive", type: Renderer, selector: "[a2ui-renderer]", inputs: ["surfaceId", "component"] }], changeDetection: i0.ChangeDetectionStrategy.Eager });
1226
+ }
1227
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: Row, decorators: [{
1228
+ type: Component,
1229
+ args: [{ selector: 'a2ui-row', imports: [Renderer], changeDetection: ChangeDetectionStrategy.Eager, host: {
1230
+ '[attr.alignment]': 'alignment()',
1231
+ '[attr.distribution]': 'distribution()',
1232
+ }, template: `
1233
+ <section [class]="classes()" [style]="theme.additionalStyles?.Row">
1234
+ @for (child of children() ?? component().properties.children; track child?.id ?? child) {
1235
+ @if (child) {
1236
+ <ng-container a2ui-renderer [surfaceId]="surfaceId()!" [component]="child" />
1237
+ }
1238
+ }
1239
+ </section>
1240
+ `, styles: [":host{display:flex;flex:var(--weight)}section{display:flex;flex-direction:row;width:100%;min-height:100%;box-sizing:border-box}.align-start{align-items:start}.align-center{align-items:center}.align-end{align-items:end}.align-stretch{align-items:stretch}.distribute-start{justify-content:start}.distribute-center{justify-content:center}.distribute-end{justify-content:end}.distribute-spaceBetween{justify-content:space-between}.distribute-spaceAround{justify-content:space-around}.distribute-spaceEvenly{justify-content:space-evenly}\n"] }]
1241
+ }], propDecorators: { alignment: [{ type: i0.Input, args: [{ isSignal: true, alias: "alignment", required: false }] }], distribution: [{ type: i0.Input, args: [{ isSignal: true, alias: "distribution", required: false }] }], children: [{ type: i0.Input, args: [{ isSignal: true, alias: "children", required: false }] }] } });
1242
+
1243
+ /*
1244
+ * Copyright 2025 Google LLC
1245
+ *
1246
+ * Licensed under the Apache License, Version 2.0 (the "License");
1247
+ * you may not use this file except in compliance with the License.
1248
+ * You may obtain a copy of the License at
1249
+ *
1250
+ * https://www.apache.org/licenses/LICENSE-2.0
1251
+ *
1252
+ * Unless required by applicable law or agreed to in writing, software
1253
+ * distributed under the License is distributed on an "AS IS" BASIS,
1254
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1255
+ * See the License for the specific language governing permissions and
1256
+ * limitations under the License.
1257
+ */
1258
+ class Slider extends DynamicComponent {
1259
+ label = input(null, ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
1260
+ value = input.required(...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
1261
+ minValue = input(0, ...(ngDevMode ? [{ debugName: "minValue" }] : /* istanbul ignore next */ []));
1262
+ maxValue = input(100, ...(ngDevMode ? [{ debugName: "maxValue" }] : /* istanbul ignore next */ []));
1263
+ inputId = super.getUniqueId('a2ui-slider-input');
1264
+ labelId = super.getUniqueId('a2ui-slider-label');
1265
+ resolvedLabel = computed(() => super.resolvePrimitive(this.label()), ...(ngDevMode ? [{ debugName: "resolvedLabel" }] : /* istanbul ignore next */ []));
1266
+ resolvedValue = computed(() => super.resolvePrimitive(this.value()), ...(ngDevMode ? [{ debugName: "resolvedValue" }] : /* istanbul ignore next */ []));
1267
+ onInput(event) {
1268
+ const value = Number(event.target.value);
1269
+ const valueNode = this.value();
1270
+ if (valueNode && typeof valueNode === 'object' && 'path' in valueNode && valueNode.path) {
1271
+ // Update the local data model directly to ensure immediate UI feedback and avoid unnecessary network requests.
1272
+ this.processor.processMessages([{
1273
+ dataModelUpdate: {
1274
+ surfaceId: this.surfaceId(),
1275
+ path: this.processor.resolvePath(valueNode.path, this.component().dataContextPath),
1276
+ contents: [{ key: '.', valueNumber: value }],
1277
+ },
1278
+ }]);
1279
+ }
1280
+ else {
1281
+ this.handleAction('change', { value });
1282
+ }
1283
+ }
1284
+ handleAction(name, context) {
1285
+ super.sendAction({
1286
+ name,
1287
+ context: Object.entries(context).map(([key, val]) => ({
1288
+ key,
1289
+ value: typeof val === 'number' ? { literalNumber: val } : { literalString: String(val) },
1290
+ })),
1291
+ });
1292
+ }
1293
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: Slider, deps: null, target: i0.ɵɵFactoryTarget.Component });
1294
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: Slider, isStandalone: true, selector: "a2ui-slider", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: true, transformFunction: null }, minValue: { classPropertyName: "minValue", publicName: "minValue", isSignal: true, isRequired: false, transformFunction: null }, maxValue: { classPropertyName: "maxValue", publicName: "maxValue", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: `
1295
+ <div [class]="theme.components.Slider.container" [style]="theme.additionalStyles?.Slider">
1296
+ @if (resolvedLabel()) {
1297
+ <label [class]="theme.components.Slider.label" [id]="labelId">{{ resolvedLabel() }}</label>
1298
+ }
1299
+ <input
1300
+ type="range"
1301
+ [class]="theme.components.Slider.element"
1302
+ [id]="inputId"
1303
+ [attr.aria-labelledby]="labelId"
1304
+ [min]="minValue()"
1305
+ [max]="maxValue()"
1306
+ [value]="resolvedValue() ?? 0"
1307
+ (input)="onInput($event)"
1308
+ />
1309
+ </div>
1310
+ `, isInline: true, styles: [":host{display:block}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1311
+ }
1312
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: Slider, decorators: [{
1313
+ type: Component,
1314
+ args: [{ selector: 'a2ui-slider', template: `
1315
+ <div [class]="theme.components.Slider.container" [style]="theme.additionalStyles?.Slider">
1316
+ @if (resolvedLabel()) {
1317
+ <label [class]="theme.components.Slider.label" [id]="labelId">{{ resolvedLabel() }}</label>
1318
+ }
1319
+ <input
1320
+ type="range"
1321
+ [class]="theme.components.Slider.element"
1322
+ [id]="inputId"
1323
+ [attr.aria-labelledby]="labelId"
1324
+ [min]="minValue()"
1325
+ [max]="maxValue()"
1326
+ [value]="resolvedValue() ?? 0"
1327
+ (input)="onInput($event)"
1328
+ />
1329
+ </div>
1330
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block}\n"] }]
1331
+ }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: true }] }], minValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "minValue", required: false }] }], maxValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxValue", required: false }] }] } });
1332
+
1333
+ /*
1334
+ * Copyright 2025 Google LLC
1335
+ *
1336
+ * Licensed under the Apache License, Version 2.0 (the "License");
1337
+ * you may not use this file except in compliance with the License.
1338
+ * You may obtain a copy of the License at
1339
+ *
1340
+ * https://www.apache.org/licenses/LICENSE-2.0
1341
+ *
1342
+ * Unless required by applicable law or agreed to in writing, software
1343
+ * distributed under the License is distributed on an "AS IS" BASIS,
1344
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1345
+ * See the License for the specific language governing permissions and
1346
+ * limitations under the License.
1347
+ */
1348
+ class Tabs extends DynamicComponent {
1349
+ tabItems = input.required(...(ngDevMode ? [{ debugName: "tabItems" }] : /* istanbul ignore next */ []));
1350
+ selectedIndex = signal(0, ...(ngDevMode ? [{ debugName: "selectedIndex" }] : /* istanbul ignore next */ []));
1351
+ selectTab(index) {
1352
+ this.selectedIndex.set(index);
1353
+ }
1354
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: Tabs, deps: null, target: i0.ɵɵFactoryTarget.Component });
1355
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: Tabs, isStandalone: true, selector: "a2ui-tabs", inputs: { tabItems: { classPropertyName: "tabItems", publicName: "tabItems", isSignal: true, isRequired: true, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: `
1356
+ <div [class]="theme.components.Tabs.container" [style]="theme.additionalStyles?.Tabs">
1357
+ <div [class]="theme.components.Tabs.controls.all">
1358
+ @for (item of tabItems(); track item.child; let i = $index) {
1359
+ <button
1360
+ [class]="selectedIndex() === i ? theme.components.Tabs.controls.selected : {}"
1361
+ (click)="selectTab(i)"
1362
+ >
1363
+ {{ resolvePrimitive(item.title) }}
1364
+ </button>
1365
+ }
1366
+ </div>
1367
+ <div class="a2ui-tabs-content">
1368
+ @if (tabItems()[selectedIndex()]; as selectedTab) {
1369
+ <ng-container a2ui-renderer [surfaceId]="surfaceId()!" [component]="selectedTab.child" />
1370
+ }
1371
+ </div>
1372
+ </div>
1373
+ `, isInline: true, styles: [":host{display:block}.a2ui-tabs-content{flex:1;min-height:0}\n"], dependencies: [{ kind: "directive", type: Renderer, selector: "[a2ui-renderer]", inputs: ["surfaceId", "component"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1374
+ }
1375
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: Tabs, decorators: [{
1376
+ type: Component,
1377
+ args: [{ selector: 'a2ui-tabs', imports: [Renderer], template: `
1378
+ <div [class]="theme.components.Tabs.container" [style]="theme.additionalStyles?.Tabs">
1379
+ <div [class]="theme.components.Tabs.controls.all">
1380
+ @for (item of tabItems(); track item.child; let i = $index) {
1381
+ <button
1382
+ [class]="selectedIndex() === i ? theme.components.Tabs.controls.selected : {}"
1383
+ (click)="selectTab(i)"
1384
+ >
1385
+ {{ resolvePrimitive(item.title) }}
1386
+ </button>
1387
+ }
1388
+ </div>
1389
+ <div class="a2ui-tabs-content">
1390
+ @if (tabItems()[selectedIndex()]; as selectedTab) {
1391
+ <ng-container a2ui-renderer [surfaceId]="surfaceId()!" [component]="selectedTab.child" />
1392
+ }
1393
+ </div>
1394
+ </div>
1395
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block}.a2ui-tabs-content{flex:1;min-height:0}\n"] }]
1396
+ }], propDecorators: { tabItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabItems", required: true }] }] } });
1397
+
1398
+ /*
1399
+ * Copyright 2025 Google LLC
1400
+ *
1401
+ * Licensed under the Apache License, Version 2.0 (the "License");
1402
+ * you may not use this file except in compliance with the License.
1403
+ * You may obtain a copy of the License at
1404
+ *
1405
+ * https://www.apache.org/licenses/LICENSE-2.0
1406
+ *
1407
+ * Unless required by applicable law or agreed to in writing, software
1408
+ * distributed under the License is distributed on an "AS IS" BASIS,
1409
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1410
+ * See the License for the specific language governing permissions and
1411
+ * limitations under the License.
1412
+ */
1413
+ class Text extends DynamicComponent {
1414
+ markdownRenderer = inject(MarkdownRenderer);
1415
+ text = input.required(...(ngDevMode ? [{ debugName: "text" }] : /* istanbul ignore next */ []));
1416
+ usageHint = input(null, ...(ngDevMode ? [{ debugName: "usageHint" }] : /* istanbul ignore next */ []));
1417
+ resolvedText = computed(() => {
1418
+ const usageHint = this.usageHint();
1419
+ let value = super.resolvePrimitive(this.text());
1420
+ if (value == null) {
1421
+ return Promise.resolve('');
1422
+ }
1423
+ switch (usageHint) {
1424
+ case 'h1':
1425
+ value = `# ${value}`;
1426
+ break;
1427
+ case 'h2':
1428
+ value = `## ${value}`;
1429
+ break;
1430
+ case 'h3':
1431
+ value = `### ${value}`;
1432
+ break;
1433
+ case 'h4':
1434
+ value = `#### ${value}`;
1435
+ break;
1436
+ case 'h5':
1437
+ value = `##### ${value}`;
1438
+ break;
1439
+ case 'caption':
1440
+ value = `*${value}*`;
1441
+ break;
1442
+ default:
1443
+ value = String(value);
1444
+ break;
1445
+ }
1446
+ return this.markdownRenderer.render(value, {
1447
+ tagClassMap: Styles.appendToAll(this.theme.markdown, ['ol', 'ul', 'li'], {}),
1448
+ });
1449
+ }, ...(ngDevMode ? [{ debugName: "resolvedText" }] : /* istanbul ignore next */ []));
1450
+ classes = computed(() => {
1451
+ const usageHint = this.usageHint();
1452
+ return Styles.merge(this.theme.components.Text.all, usageHint ? this.theme.components.Text[usageHint] : {});
1453
+ }, ...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
1454
+ additionalStyles = computed(() => {
1455
+ const usageHint = this.usageHint();
1456
+ const styles = this.theme.additionalStyles?.Text;
1457
+ if (!styles) {
1458
+ return null;
1459
+ }
1460
+ let additionalStyles = {};
1461
+ if (this.areHintedStyles(styles)) {
1462
+ additionalStyles = styles[usageHint ?? 'body'] || {};
1463
+ }
1464
+ else if (typeof styles === 'object' && styles !== null) {
1465
+ additionalStyles = styles;
1466
+ }
1467
+ return additionalStyles;
1468
+ }, ...(ngDevMode ? [{ debugName: "additionalStyles" }] : /* istanbul ignore next */ []));
1469
+ areHintedStyles(styles) {
1470
+ if (typeof styles !== 'object' || !styles || Array.isArray(styles)) {
1471
+ return false;
1472
+ }
1473
+ const expected = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'caption', 'body'];
1474
+ return expected.every((v) => v in styles);
1475
+ }
1476
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: Text, deps: null, target: i0.ɵɵFactoryTarget.Component });
1477
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.5", type: Text, isStandalone: true, selector: "a2ui-text", inputs: { text: { classPropertyName: "text", publicName: "text", isSignal: true, isRequired: true, transformFunction: null }, usageHint: { classPropertyName: "usageHint", publicName: "usageHint", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: `
1478
+ <section
1479
+ [class]="classes()"
1480
+ [style]="additionalStyles()"
1481
+ [innerHTML]="resolvedText() | async"
1482
+ ></section>
1483
+ `, isInline: true, styles: ["a2ui-text{display:block;flex:var(--weight)}a2ui-text h1,a2ui-text h2,a2ui-text h3,a2ui-text h4,a2ui-text h5{line-height:inherit;font:inherit}\n"], dependencies: [{ kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.Eager, encapsulation: i0.ViewEncapsulation.None });
1484
+ }
1485
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: Text, decorators: [{
1486
+ type: Component,
1487
+ args: [{ selector: 'a2ui-text', changeDetection: ChangeDetectionStrategy.Eager, template: `
1488
+ <section
1489
+ [class]="classes()"
1490
+ [style]="additionalStyles()"
1491
+ [innerHTML]="resolvedText() | async"
1492
+ ></section>
1493
+ `, encapsulation: ViewEncapsulation.None, imports: [AsyncPipe], styles: ["a2ui-text{display:block;flex:var(--weight)}a2ui-text h1,a2ui-text h2,a2ui-text h3,a2ui-text h4,a2ui-text h5{line-height:inherit;font:inherit}\n"] }]
1494
+ }], propDecorators: { text: [{ type: i0.Input, args: [{ isSignal: true, alias: "text", required: true }] }], usageHint: [{ type: i0.Input, args: [{ isSignal: true, alias: "usageHint", required: false }] }] } });
1495
+
1496
+ /*
1497
+ * Copyright 2025 Google LLC
1498
+ *
1499
+ * Licensed under the Apache License, Version 2.0 (the "License");
1500
+ * you may not use this file except in compliance with the License.
1501
+ * You may obtain a copy of the License at
1502
+ *
1503
+ * https://www.apache.org/licenses/LICENSE-2.0
1504
+ *
1505
+ * Unless required by applicable law or agreed to in writing, software
1506
+ * distributed under the License is distributed on an "AS IS" BASIS,
1507
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1508
+ * See the License for the specific language governing permissions and
1509
+ * limitations under the License.
1510
+ */
1511
+ class TextField extends DynamicComponent {
1512
+ label = input.required(...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
1513
+ text = input(null, ...(ngDevMode ? [{ debugName: "text" }] : /* istanbul ignore next */ []));
1514
+ textFieldType = input('shortText', ...(ngDevMode ? [{ debugName: "textFieldType" }] : /* istanbul ignore next */ []));
1515
+ inputId = super.getUniqueId('a2ui-text-field');
1516
+ resolvedLabel = computed(() => super.resolvePrimitive(this.label()), ...(ngDevMode ? [{ debugName: "resolvedLabel" }] : /* istanbul ignore next */ []));
1517
+ resolvedText = computed(() => super.resolvePrimitive(this.text()), ...(ngDevMode ? [{ debugName: "resolvedText" }] : /* istanbul ignore next */ []));
1518
+ htmlInputType = computed(() => {
1519
+ switch (this.textFieldType()) {
1520
+ case 'number':
1521
+ return 'number';
1522
+ case 'date':
1523
+ return 'date';
1524
+ default:
1525
+ return 'text';
1526
+ }
1527
+ }, ...(ngDevMode ? [{ debugName: "htmlInputType" }] : /* istanbul ignore next */ []));
1528
+ onInput(event) {
1529
+ const value = event.target.value;
1530
+ const textNode = this.text();
1531
+ if (textNode && typeof textNode === 'object' && 'path' in textNode && textNode.path) {
1532
+ // Update the local data model directly to ensure immediate UI feedback and avoid unnecessary network requests.
1533
+ this.processor.processMessages([{
1534
+ dataModelUpdate: {
1535
+ surfaceId: this.surfaceId(),
1536
+ path: this.processor.resolvePath(textNode.path, this.component().dataContextPath),
1537
+ contents: [{ key: '.', valueString: value }],
1538
+ },
1539
+ }]);
1540
+ }
1541
+ else {
1542
+ this.handleAction('input', { value });
1543
+ }
1544
+ }
1545
+ handleAction(name, context) {
1546
+ super.sendAction({
1547
+ name,
1548
+ context: Object.entries(context).map(([key, val]) => ({
1549
+ key,
1550
+ value: typeof val === 'number' ? { literalNumber: val } : { literalString: String(val) },
1551
+ })),
1552
+ });
1553
+ }
1554
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: TextField, deps: null, target: i0.ɵɵFactoryTarget.Component });
1555
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.5", type: TextField, isStandalone: true, selector: "a2ui-text-field", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, text: { classPropertyName: "text", publicName: "text", isSignal: true, isRequired: false, transformFunction: null }, textFieldType: { classPropertyName: "textFieldType", publicName: "textFieldType", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: `
1556
+ <div [class]="theme.components.TextField.container" [style]="theme.additionalStyles?.TextField">
1557
+ <label [class]="theme.components.TextField.label" [for]="inputId">
1558
+ {{ resolvedLabel() }}
1559
+ </label>
1560
+ <input
1561
+ [type]="htmlInputType()"
1562
+ [class]="theme.components.TextField.element"
1563
+ [id]="inputId"
1564
+ [value]="resolvedText() ?? ''"
1565
+ (input)="onInput($event)"
1566
+ />
1567
+ </div>
1568
+ `, isInline: true, styles: [":host{display:block}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1569
+ }
1570
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: TextField, decorators: [{
1571
+ type: Component,
1572
+ args: [{ selector: 'a2ui-text-field', template: `
1573
+ <div [class]="theme.components.TextField.container" [style]="theme.additionalStyles?.TextField">
1574
+ <label [class]="theme.components.TextField.label" [for]="inputId">
1575
+ {{ resolvedLabel() }}
1576
+ </label>
1577
+ <input
1578
+ [type]="htmlInputType()"
1579
+ [class]="theme.components.TextField.element"
1580
+ [id]="inputId"
1581
+ [value]="resolvedText() ?? ''"
1582
+ (input)="onInput($event)"
1583
+ />
1584
+ </div>
1585
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block}\n"] }]
1586
+ }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], text: [{ type: i0.Input, args: [{ isSignal: true, alias: "text", required: false }] }], textFieldType: [{ type: i0.Input, args: [{ isSignal: true, alias: "textFieldType", required: false }] }] } });
1587
+
1588
+ /*
1589
+ * Copyright 2025 Google LLC
1590
+ *
1591
+ * Licensed under the Apache License, Version 2.0 (the "License");
1592
+ * you may not use this file except in compliance with the License.
1593
+ * You may obtain a copy of the License at
1594
+ *
1595
+ * https://www.apache.org/licenses/LICENSE-2.0
1596
+ *
1597
+ * Unless required by applicable law or agreed to in writing, software
1598
+ * distributed under the License is distributed on an "AS IS" BASIS,
1599
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1600
+ * See the License for the specific language governing permissions and
1601
+ * limitations under the License.
1602
+ */
1603
+ class Video extends DynamicComponent {
1604
+ url = input.required(...(ngDevMode ? [{ debugName: "url" }] : /* istanbul ignore next */ []));
1605
+ resolvedUrl = computed(() => this.resolvePrimitive(this.url()), ...(ngDevMode ? [{ debugName: "resolvedUrl" }] : /* istanbul ignore next */ []));
1606
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: Video, deps: null, target: i0.ɵɵFactoryTarget.Component });
1607
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: Video, isStandalone: true, selector: "a2ui-video", inputs: { url: { classPropertyName: "url", publicName: "url", isSignal: true, isRequired: true, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: `
1608
+ @let resolvedUrl = this.resolvedUrl();
1609
+
1610
+ @if (resolvedUrl) {
1611
+ <section [class]="theme.components.Video" [style]="theme.additionalStyles?.Video">
1612
+ <video controls [src]="resolvedUrl"></video>
1613
+ </section>
1614
+ }
1615
+ `, isInline: true, styles: [":host{display:block;flex:var(--weight);min-height:0;overflow:auto}video{display:block;width:100%;box-sizing:border-box}\n"], changeDetection: i0.ChangeDetectionStrategy.Eager });
1616
+ }
1617
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: Video, decorators: [{
1618
+ type: Component,
1619
+ args: [{ selector: 'a2ui-video', changeDetection: ChangeDetectionStrategy.Eager, template: `
1620
+ @let resolvedUrl = this.resolvedUrl();
1621
+
1622
+ @if (resolvedUrl) {
1623
+ <section [class]="theme.components.Video" [style]="theme.additionalStyles?.Video">
1624
+ <video controls [src]="resolvedUrl"></video>
1625
+ </section>
1626
+ }
1627
+ `, styles: [":host{display:block;flex:var(--weight);min-height:0;overflow:auto}video{display:block;width:100%;box-sizing:border-box}\n"] }]
1628
+ }], propDecorators: { url: [{ type: i0.Input, args: [{ isSignal: true, alias: "url", required: true }] }] } });
1629
+
1630
+ /*
1631
+ * Copyright 2025 Google LLC
1632
+ *
1633
+ * Licensed under the Apache License, Version 2.0 (the "License");
1634
+ * you may not use this file except in compliance with the License.
1635
+ * You may obtain a copy of the License at
1636
+ *
1637
+ * https://www.apache.org/licenses/LICENSE-2.0
1638
+ *
1639
+ * Unless required by applicable law or agreed to in writing, software
1640
+ * distributed under the License is distributed on an "AS IS" BASIS,
1641
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1642
+ * See the License for the specific language governing permissions and
1643
+ * limitations under the License.
1644
+ */
1645
+ // Components
1646
+ const DEFAULT_CATALOG = {
1647
+ AudioPlayer: () => AudioPlayer,
1648
+ Button: () => Button,
1649
+ Card: () => Card,
1650
+ CheckBox: () => Checkbox,
1651
+ Column: () => Column,
1652
+ DateTimeInput: () => DateTimeInput,
1653
+ Divider: () => Divider,
1654
+ Icon: () => Icon,
1655
+ Image: () => Image,
1656
+ List: () => List,
1657
+ Modal: () => Modal,
1658
+ MultipleChoice: () => MultipleChoice,
1659
+ Row: () => Row,
1660
+ Slider: () => Slider,
1661
+ Tabs: () => Tabs,
1662
+ Text: () => Text,
1663
+ TextField: () => TextField,
1664
+ Video: () => Video,
1665
+ };
1666
+ function registerStandardComponents(catalog) {
1667
+ for (const [key, value] of Object.entries(DEFAULT_CATALOG)) {
1668
+ catalog[key] = value;
1669
+ }
1670
+ }
1671
+
1672
+ /*
1673
+ * Copyright 2025 Google LLC
1674
+ *
1675
+ * Licensed under the Apache License, Version 2.0 (the "License");
1676
+ * you may not use this file except in compliance with the License.
1677
+ * You may obtain a copy of the License at
1678
+ *
1679
+ * https://www.apache.org/licenses/LICENSE-2.0
1680
+ *
1681
+ * Unless required by applicable law or agreed to in writing, software
1682
+ * distributed under the License is distributed on an "AS IS" BASIS,
1683
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1684
+ * See the License for the specific language governing permissions and
1685
+ * limitations under the License.
1686
+ */
1687
+ class Surface {
1688
+ processor = inject(MessageProcessor);
1689
+ surfaceId = input.required(...(ngDevMode ? [{ debugName: "surfaceId" }] : /* istanbul ignore next */ []));
1690
+ surfaceInput = input(null, { ...(ngDevMode ? { debugName: "surfaceInput" } : /* istanbul ignore next */ {}), alias: 'surface' });
1691
+ surface = computed(() => {
1692
+ this.processor.version(); // Track dependency on in-place mutations
1693
+ return this.surfaceInput() ?? this.processor.getSurfaces().get(this.surfaceId()) ?? null;
1694
+ }, ...(ngDevMode ? [{ debugName: "surface" }] : /* istanbul ignore next */ []));
1695
+ rootComponent = computed(() => {
1696
+ this.processor.version(); // Track dependency on in-place mutations
1697
+ return this.surface()?.componentTree ?? null;
1698
+ }, ...(ngDevMode ? [{ debugName: "rootComponent" }] : /* istanbul ignore next */ []));
1699
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: Surface, deps: [], target: i0.ɵɵFactoryTarget.Component });
1700
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: Surface, isStandalone: true, selector: "a2ui-surface", inputs: { surfaceId: { classPropertyName: "surfaceId", publicName: "surfaceId", isSignal: true, isRequired: true, transformFunction: null }, surfaceInput: { classPropertyName: "surfaceInput", publicName: "surface", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
1701
+ @if (rootComponent()) {
1702
+ <ng-container a2ui-renderer [surfaceId]="surfaceId()" [component]="rootComponent()!" />
1703
+ }
1704
+ `, isInline: true, styles: [":host{display:block;width:100%;height:100%}\n"], dependencies: [{ kind: "directive", type: Renderer, selector: "[a2ui-renderer]", inputs: ["surfaceId", "component"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1705
+ }
1706
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: Surface, decorators: [{
1707
+ type: Component,
1708
+ args: [{ selector: 'a2ui-surface', imports: [Renderer], template: `
1709
+ @if (rootComponent()) {
1710
+ <ng-container a2ui-renderer [surfaceId]="surfaceId()" [component]="rootComponent()!" />
1711
+ }
1712
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block;width:100%;height:100%}\n"] }]
1713
+ }], propDecorators: { surfaceId: [{ type: i0.Input, args: [{ isSignal: true, alias: "surfaceId", required: true }] }], surfaceInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "surface", required: false }] }] } });
1714
+
1715
+ /*
1716
+ * Copyright 2025 Google LLC
1717
+ *
1718
+ * Licensed under the Apache License, Version 2.0 (the "License");
1719
+ * you may not use this file except in compliance with the License.
1720
+ * You may obtain a copy of the License at
1721
+ *
1722
+ * https://www.apache.org/licenses/LICENSE-2.0
1723
+ *
1724
+ * Unless required by applicable law or agreed to in writing, software
1725
+ * distributed under the License is distributed on an "AS IS" BASIS,
1726
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1727
+ * See the License for the specific language governing permissions and
1728
+ * limitations under the License.
1729
+ */
1730
+
1731
+ /*
1732
+ * Copyright 2025 Google LLC
1733
+ *
1734
+ * Licensed under the Apache License, Version 2.0 (the "License");
1735
+ * you may not use this file except in compliance with the License.
1736
+ * You may obtain a copy of the License at
1737
+ *
1738
+ * https://www.apache.org/licenses/LICENSE-2.0
1739
+ *
1740
+ * Unless required by applicable law or agreed to in writing, software
1741
+ * distributed under the License is distributed on an "AS IS" BASIS,
1742
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1743
+ * See the License for the specific language governing permissions and
1744
+ * limitations under the License.
1745
+ */
1746
+ function provideA2UI(config) {
1747
+ return makeEnvironmentProviders([
1748
+ { provide: Catalog, useValue: config.catalog },
1749
+ {
1750
+ provide: Theme,
1751
+ useFactory: () => {
1752
+ const theme = new Theme();
1753
+ theme.update(config.theme);
1754
+ return theme;
1755
+ },
1756
+ },
1757
+ ]);
1758
+ }
1759
+
1760
+ /*
1761
+ * Copyright 2025 Google LLC
1762
+ *
1763
+ * Licensed under the Apache License, Version 2.0 (the "License");
1764
+ * you may not use this file except in compliance with the License.
1765
+ * You may obtain a copy of the License at
1766
+ *
1767
+ * https://www.apache.org/licenses/LICENSE-2.0
1768
+ *
1769
+ * Unless required by applicable law or agreed to in writing, software
1770
+ * distributed under the License is distributed on an "AS IS" BASIS,
1771
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1772
+ * See the License for the specific language governing permissions and
1773
+ * limitations under the License.
1774
+ */
1775
+
1776
+ /**
1777
+ * Copyright 2026 Google LLC
1778
+ *
1779
+ * Licensed under the Apache License, Version 2.0 (the "License");
1780
+ * you may not use this file except in compliance with the License.
1781
+ * You may obtain a copy of the License at
1782
+ *
1783
+ * http://www.apache.org/licenses/LICENSE-2.0
1784
+ *
1785
+ * Unless required by applicable law or agreed to in writing, software
1786
+ * distributed under the License is distributed on an "AS IS" BASIS,
1787
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1788
+ * See the License for the specific language governing permissions and
1789
+ * limitations under the License.
1790
+ */
1791
+
1792
+ /**
1793
+ * Generated bundle index. Do not edit.
1794
+ */
1795
+
1796
+ export { AudioPlayer, Button, Card, Catalog, Checkbox, Column, DEFAULT_CATALOG, DateTimeInput, Divider, DynamicComponent, Icon, Image, List, MessageProcessor, Modal, MultipleChoice, Renderer, Row, Slider, Surface, Tabs, Text, TextField, Theme, Video, provideA2UI, provideMarkdownRenderer, registerStandardComponents };
1797
+ //# sourceMappingURL=a2ui-angular-src-v0_8.mjs.map