@a2ui/angular 0.8.1 → 0.8.3

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 (71) hide show
  1. package/fesm2022/a2ui-angular-audio-DoZb9mn_.mjs +48 -0
  2. package/fesm2022/a2ui-angular-audio-DoZb9mn_.mjs.map +1 -0
  3. package/fesm2022/a2ui-angular-button-CvH0kAtN.mjs +61 -0
  4. package/fesm2022/a2ui-angular-button-CvH0kAtN.mjs.map +1 -0
  5. package/fesm2022/a2ui-angular-card-Ix6OIdUv.mjs +48 -0
  6. package/fesm2022/a2ui-angular-card-Ix6OIdUv.mjs.map +1 -0
  7. package/fesm2022/a2ui-angular-checkbox-BN4EF2Ci.mjs +78 -0
  8. package/fesm2022/a2ui-angular-checkbox-BN4EF2Ci.mjs.map +1 -0
  9. package/fesm2022/a2ui-angular-datetime-input-dmZAjvrF.mjs +120 -0
  10. package/fesm2022/a2ui-angular-datetime-input-dmZAjvrF.mjs.map +1 -0
  11. package/fesm2022/a2ui-angular-divider-BizPl3qL.mjs +30 -0
  12. package/fesm2022/a2ui-angular-divider-BizPl3qL.mjs.map +1 -0
  13. package/fesm2022/a2ui-angular-icon-BE9Hj9V6.mjs +48 -0
  14. package/fesm2022/a2ui-angular-icon-BE9Hj9V6.mjs.map +1 -0
  15. package/fesm2022/a2ui-angular-image-BWzAw0rh.mjs +54 -0
  16. package/fesm2022/a2ui-angular-image-BWzAw0rh.mjs.map +1 -0
  17. package/fesm2022/a2ui-angular-list-nEeT59V3.mjs +45 -0
  18. package/fesm2022/a2ui-angular-list-nEeT59V3.mjs.map +1 -0
  19. package/fesm2022/a2ui-angular-modal-mr9LmczA.mjs +108 -0
  20. package/fesm2022/a2ui-angular-modal-mr9LmczA.mjs.map +1 -0
  21. package/fesm2022/a2ui-angular-multiple-choice-Bry7X74i.mjs +78 -0
  22. package/fesm2022/a2ui-angular-multiple-choice-Bry7X74i.mjs.map +1 -0
  23. package/fesm2022/a2ui-angular-slider-BgseUbN2.mjs +79 -0
  24. package/fesm2022/a2ui-angular-slider-BgseUbN2.mjs.map +1 -0
  25. package/fesm2022/a2ui-angular-tabs-q5Mn9vgq.mjs +87 -0
  26. package/fesm2022/a2ui-angular-tabs-q5Mn9vgq.mjs.map +1 -0
  27. package/fesm2022/a2ui-angular-text-field-Deokh07j.mjs +85 -0
  28. package/fesm2022/a2ui-angular-text-field-Deokh07j.mjs.map +1 -0
  29. package/fesm2022/a2ui-angular-video-DuFTfN0B.mjs +48 -0
  30. package/fesm2022/a2ui-angular-video-DuFTfN0B.mjs.map +1 -0
  31. package/fesm2022/a2ui-angular.mjs +872 -0
  32. package/fesm2022/a2ui-angular.mjs.map +1 -0
  33. package/package.json +13 -46
  34. package/types/a2ui-angular.d.ts +90 -0
  35. package/angular.json +0 -35
  36. package/ng-package.json +0 -8
  37. package/src/lib/catalog/audio.ts +0 -50
  38. package/src/lib/catalog/button.ts +0 -56
  39. package/src/lib/catalog/card.ts +0 -57
  40. package/src/lib/catalog/checkbox.ts +0 -73
  41. package/src/lib/catalog/column.ts +0 -96
  42. package/src/lib/catalog/datetime-input.ts +0 -127
  43. package/src/lib/catalog/default.ts +0 -185
  44. package/src/lib/catalog/divider.ts +0 -37
  45. package/src/lib/catalog/icon.ts +0 -44
  46. package/src/lib/catalog/image.ts +0 -62
  47. package/src/lib/catalog/list.ts +0 -63
  48. package/src/lib/catalog/modal.ts +0 -113
  49. package/src/lib/catalog/multiple-choice.ts +0 -77
  50. package/src/lib/catalog/row.ts +0 -100
  51. package/src/lib/catalog/slider.ts +0 -73
  52. package/src/lib/catalog/surface.ts +0 -82
  53. package/src/lib/catalog/tabs.ts +0 -72
  54. package/src/lib/catalog/text-field.ts +0 -86
  55. package/src/lib/catalog/text.ts +0 -137
  56. package/src/lib/catalog/video.ts +0 -50
  57. package/src/lib/config.ts +0 -25
  58. package/src/lib/data/index.ts +0 -18
  59. package/src/lib/data/markdown.ts +0 -114
  60. package/src/lib/data/processor.ts +0 -47
  61. package/src/lib/data/types.ts +0 -29
  62. package/src/lib/rendering/catalog.ts +0 -36
  63. package/src/lib/rendering/dynamic-component.ts +0 -100
  64. package/src/lib/rendering/index.ts +0 -20
  65. package/src/lib/rendering/renderer.ts +0 -109
  66. package/src/lib/rendering/theming.ts +0 -22
  67. package/src/public-api.ts +0 -21
  68. package/tsconfig.json +0 -23
  69. package/tsconfig.lib.json +0 -16
  70. package/tsconfig.lib.prod.json +0 -9
  71. package/tsconfig.spec.json +0 -12
@@ -1,137 +0,0 @@
1
- /*
2
- Copyright 2025 Google LLC
3
-
4
- Licensed under the Apache License, Version 2.0 (the "License");
5
- you may not use this file except in compliance with the License.
6
- You may obtain a copy of the License at
7
-
8
- https://www.apache.org/licenses/LICENSE-2.0
9
-
10
- Unless required by applicable law or agreed to in writing, software
11
- distributed under the License is distributed on an "AS IS" BASIS,
12
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- See the License for the specific language governing permissions and
14
- limitations under the License.
15
- */
16
-
17
- import { Component, computed, inject, input, ViewEncapsulation } from '@angular/core';
18
- import { DynamicComponent } from '../rendering/dynamic-component';
19
- import { Primitives, Styles, Types } from '@a2ui/lit/0.8';
20
- import { MarkdownRenderer } from '../data/markdown';
21
-
22
- interface HintedStyles {
23
- h1: Record<string, string>;
24
- h2: Record<string, string>;
25
- h3: Record<string, string>;
26
- h4: Record<string, string>;
27
- h5: Record<string, string>;
28
- body: Record<string, string>;
29
- caption: Record<string, string>;
30
- }
31
-
32
- @Component({
33
- selector: 'a2ui-text',
34
- template: `
35
- <section
36
- [class]="classes()"
37
- [style]="additionalStyles()"
38
- [innerHTML]="resolvedText()"
39
- ></section>
40
- `,
41
- encapsulation: ViewEncapsulation.None,
42
- styles: `
43
- a2ui-text {
44
- display: block;
45
- flex: var(--weight);
46
- }
47
-
48
- a2ui-text h1,
49
- a2ui-text h2,
50
- a2ui-text h3,
51
- a2ui-text h4,
52
- a2ui-text h5 {
53
- line-height: inherit;
54
- font: inherit;
55
- }
56
- `,
57
- })
58
- export class Text extends DynamicComponent {
59
- private markdownRenderer = inject(MarkdownRenderer);
60
- readonly text = input.required<Primitives.StringValue | null>();
61
- readonly usageHint = input.required<Types.ResolvedText['usageHint'] | null>();
62
-
63
- protected resolvedText = computed(() => {
64
- const usageHint = this.usageHint();
65
- let value = super.resolvePrimitive(this.text());
66
-
67
- if (value == null) {
68
- return '(empty)';
69
- }
70
-
71
- switch (usageHint) {
72
- case 'h1':
73
- value = `# ${value}`;
74
- break;
75
- case 'h2':
76
- value = `## ${value}`;
77
- break;
78
- case 'h3':
79
- value = `### ${value}`;
80
- break;
81
- case 'h4':
82
- value = `#### ${value}`;
83
- break;
84
- case 'h5':
85
- value = `##### ${value}`;
86
- break;
87
- case 'caption':
88
- value = `*${value}*`;
89
- break;
90
- default:
91
- value = String(value);
92
- break;
93
- }
94
-
95
- return this.markdownRenderer.render(
96
- value,
97
- Styles.appendToAll(this.theme.markdown, ['ol', 'ul', 'li'], {}),
98
- );
99
- });
100
-
101
- protected classes = computed(() => {
102
- const usageHint = this.usageHint();
103
-
104
- return Styles.merge(
105
- this.theme.components.Text.all,
106
- usageHint ? this.theme.components.Text[usageHint] : {},
107
- );
108
- });
109
-
110
- protected additionalStyles = computed(() => {
111
- const usageHint = this.usageHint();
112
- const styles = this.theme.additionalStyles?.Text;
113
-
114
- if (!styles) {
115
- return null;
116
- }
117
-
118
- let additionalStyles: Record<string, string> = {};
119
-
120
- if (this.areHintedStyles(styles)) {
121
- additionalStyles = styles[usageHint ?? 'body'];
122
- } else {
123
- additionalStyles = styles;
124
- }
125
-
126
- return additionalStyles;
127
- });
128
-
129
- private areHintedStyles(styles: unknown): styles is HintedStyles {
130
- if (typeof styles !== 'object' || !styles || Array.isArray(styles)) {
131
- return false;
132
- }
133
-
134
- const expected = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'caption', 'body'];
135
- return expected.every((v) => v in styles);
136
- }
137
- }
@@ -1,50 +0,0 @@
1
- /*
2
- Copyright 2025 Google LLC
3
-
4
- Licensed under the Apache License, Version 2.0 (the "License");
5
- you may not use this file except in compliance with the License.
6
- You may obtain a copy of the License at
7
-
8
- https://www.apache.org/licenses/LICENSE-2.0
9
-
10
- Unless required by applicable law or agreed to in writing, software
11
- distributed under the License is distributed on an "AS IS" BASIS,
12
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- See the License for the specific language governing permissions and
14
- limitations under the License.
15
- */
16
-
17
- import { Component, computed, input } from '@angular/core';
18
- import { DynamicComponent } from '../rendering/dynamic-component';
19
- import { Primitives } from '@a2ui/lit/0.8';
20
-
21
- @Component({
22
- selector: 'a2ui-video',
23
- template: `
24
- @let resolvedUrl = this.resolvedUrl();
25
-
26
- @if (resolvedUrl) {
27
- <section [class]="theme.components.Video" [style]="theme.additionalStyles?.Video">
28
- <video controls [src]="resolvedUrl"></video>
29
- </section>
30
- }
31
- `,
32
- styles: `
33
- :host {
34
- display: block;
35
- flex: var(--weight);
36
- min-height: 0;
37
- overflow: auto;
38
- }
39
-
40
- video {
41
- display: block;
42
- width: 100%;
43
- box-sizing: border-box;
44
- }
45
- `,
46
- })
47
- export class Video extends DynamicComponent {
48
- readonly url = input.required<Primitives.StringValue | null>();
49
- protected readonly resolvedUrl = computed(() => this.resolvePrimitive(this.url()));
50
- }
package/src/lib/config.ts DELETED
@@ -1,25 +0,0 @@
1
- /*
2
- Copyright 2025 Google LLC
3
-
4
- Licensed under the Apache License, Version 2.0 (the "License");
5
- you may not use this file except in compliance with the License.
6
- You may obtain a copy of the License at
7
-
8
- https://www.apache.org/licenses/LICENSE-2.0
9
-
10
- Unless required by applicable law or agreed to in writing, software
11
- distributed under the License is distributed on an "AS IS" BASIS,
12
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- See the License for the specific language governing permissions and
14
- limitations under the License.
15
- */
16
-
17
- import { EnvironmentProviders, makeEnvironmentProviders } from '@angular/core';
18
- import { Catalog, Theme } from './rendering';
19
-
20
- export function provideA2UI(config: { catalog: Catalog; theme: Theme }): EnvironmentProviders {
21
- return makeEnvironmentProviders([
22
- { provide: Catalog, useValue: config.catalog },
23
- { provide: Theme, useValue: config.theme },
24
- ]);
25
- }
@@ -1,18 +0,0 @@
1
- /*
2
- Copyright 2025 Google LLC
3
-
4
- Licensed under the Apache License, Version 2.0 (the "License");
5
- you may not use this file except in compliance with the License.
6
- You may obtain a copy of the License at
7
-
8
- https://www.apache.org/licenses/LICENSE-2.0
9
-
10
- Unless required by applicable law or agreed to in writing, software
11
- distributed under the License is distributed on an "AS IS" BASIS,
12
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- See the License for the specific language governing permissions and
14
- limitations under the License.
15
- */
16
-
17
- export * from './processor';
18
- export * from './types';
@@ -1,114 +0,0 @@
1
- /*
2
- Copyright 2025 Google LLC
3
-
4
- Licensed under the Apache License, Version 2.0 (the "License");
5
- you may not use this file except in compliance with the License.
6
- You may obtain a copy of the License at
7
-
8
- https://www.apache.org/licenses/LICENSE-2.0
9
-
10
- Unless required by applicable law or agreed to in writing, software
11
- distributed under the License is distributed on an "AS IS" BASIS,
12
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- See the License for the specific language governing permissions and
14
- limitations under the License.
15
- */
16
-
17
- import { inject, Injectable, SecurityContext } from '@angular/core';
18
- import { DomSanitizer } from '@angular/platform-browser';
19
- import MarkdownIt from 'markdown-it';
20
-
21
- @Injectable({ providedIn: 'root' })
22
- export class MarkdownRenderer {
23
- private originalClassMap = new Map<string, any>();
24
- private sanitizer = inject(DomSanitizer);
25
-
26
- private markdownIt = MarkdownIt({
27
- highlight: (str, lang) => {
28
- if (lang === 'html') {
29
- const iframe = document.createElement('iframe');
30
- iframe.classList.add('html-view');
31
- iframe.srcdoc = str;
32
- iframe.sandbox = '';
33
- return iframe.innerHTML;
34
- }
35
-
36
- return str;
37
- },
38
- });
39
-
40
- render(value: string, tagClassMap?: Record<string, string[]>) {
41
- if (tagClassMap) {
42
- this.applyTagClassMap(tagClassMap);
43
- }
44
- const htmlString = this.markdownIt.render(value);
45
- this.unapplyTagClassMap();
46
- return this.sanitizer.sanitize(SecurityContext.HTML, htmlString);
47
- }
48
-
49
- private applyTagClassMap(tagClassMap: Record<string, string[]>) {
50
- Object.entries(tagClassMap).forEach(([tag, classes]) => {
51
- let tokenName;
52
- switch (tag) {
53
- case 'p':
54
- tokenName = 'paragraph';
55
- break;
56
- case 'h1':
57
- case 'h2':
58
- case 'h3':
59
- case 'h4':
60
- case 'h5':
61
- case 'h6':
62
- tokenName = 'heading';
63
- break;
64
- case 'ul':
65
- tokenName = 'bullet_list';
66
- break;
67
- case 'ol':
68
- tokenName = 'ordered_list';
69
- break;
70
- case 'li':
71
- tokenName = 'list_item';
72
- break;
73
- case 'a':
74
- tokenName = 'link';
75
- break;
76
- case 'strong':
77
- tokenName = 'strong';
78
- break;
79
- case 'em':
80
- tokenName = 'em';
81
- break;
82
- }
83
-
84
- if (!tokenName) {
85
- return;
86
- }
87
-
88
- const key = `${tokenName}_open`;
89
- const original = this.markdownIt.renderer.rules[key];
90
- this.originalClassMap.set(key, original);
91
-
92
- this.markdownIt.renderer.rules[key] = (tokens, idx, options, env, self) => {
93
- const token = tokens[idx];
94
- for (const clazz of classes) {
95
- token.attrJoin('class', clazz);
96
- }
97
-
98
- if (original) {
99
- return original.call(this, tokens, idx, options, env, self);
100
- } else {
101
- return self.renderToken(tokens, idx, options);
102
- }
103
- };
104
- });
105
- }
106
-
107
- private unapplyTagClassMap() {
108
- for (const [key, original] of this.originalClassMap) {
109
- this.markdownIt.renderer.rules[key] = original;
110
- }
111
-
112
- this.originalClassMap.clear();
113
- }
114
- }
@@ -1,47 +0,0 @@
1
- /*
2
- Copyright 2025 Google LLC
3
-
4
- Licensed under the Apache License, Version 2.0 (the "License");
5
- you may not use this file except in compliance with the License.
6
- You may obtain a copy of the License at
7
-
8
- https://www.apache.org/licenses/LICENSE-2.0
9
-
10
- Unless required by applicable law or agreed to in writing, software
11
- distributed under the License is distributed on an "AS IS" BASIS,
12
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- See the License for the specific language governing permissions and
14
- limitations under the License.
15
- */
16
-
17
- import { Data, Types } from '@a2ui/lit/0.8';
18
- import { Injectable } from '@angular/core';
19
- import { firstValueFrom, Subject } from 'rxjs';
20
-
21
- export interface DispatchedEvent {
22
- message: Types.A2UIClientEventMessage;
23
- completion: Subject<Types.ServerToClientMessage[]>;
24
- }
25
-
26
- @Injectable({ providedIn: 'root' })
27
- export class MessageProcessor extends Data.A2uiMessageProcessor {
28
- readonly events = new Subject<DispatchedEvent>();
29
-
30
- override setData(
31
- node: Types.AnyComponentNode,
32
- relativePath: string,
33
- value: Types.DataValue,
34
- surfaceId?: Types.SurfaceID | null,
35
- ) {
36
- // Override setData to convert from optional inputs (which can be null)
37
- // to undefined so that this correctly falls back to the default value for
38
- // surfaceId.
39
- return super.setData(node, relativePath, value, surfaceId ?? undefined);
40
- }
41
-
42
- dispatch(message: Types.A2UIClientEventMessage): Promise<Types.ServerToClientMessage[]> {
43
- const completion = new Subject<Types.ServerToClientMessage[]>();
44
- this.events.next({ message, completion });
45
- return firstValueFrom(completion);
46
- }
47
- }
@@ -1,29 +0,0 @@
1
- /*
2
- Copyright 2025 Google LLC
3
-
4
- Licensed under the Apache License, Version 2.0 (the "License");
5
- you may not use this file except in compliance with the License.
6
- You may obtain a copy of the License at
7
-
8
- https://www.apache.org/licenses/LICENSE-2.0
9
-
10
- Unless required by applicable law or agreed to in writing, software
11
- distributed under the License is distributed on an "AS IS" BASIS,
12
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- See the License for the specific language governing permissions and
14
- limitations under the License.
15
- */
16
-
17
- import { Types } from '@a2ui/lit/0.8';
18
-
19
- export interface A2TextPayload {
20
- kind: 'text';
21
- text: string;
22
- }
23
-
24
- export interface A2DataPayload {
25
- kind: 'data';
26
- data: Types.ServerToClientMessage;
27
- }
28
-
29
- export type A2AServerPayload = Array<A2DataPayload | A2TextPayload> | { error: string };
@@ -1,36 +0,0 @@
1
- /*
2
- Copyright 2025 Google LLC
3
-
4
- Licensed under the Apache License, Version 2.0 (the "License");
5
- you may not use this file except in compliance with the License.
6
- You may obtain a copy of the License at
7
-
8
- https://www.apache.org/licenses/LICENSE-2.0
9
-
10
- Unless required by applicable law or agreed to in writing, software
11
- distributed under the License is distributed on an "AS IS" BASIS,
12
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- See the License for the specific language governing permissions and
14
- limitations under the License.
15
- */
16
-
17
- import { Binding, InjectionToken, Type } from '@angular/core';
18
- import { DynamicComponent } from './dynamic-component';
19
- import { Types } from '@a2ui/lit/0.8';
20
-
21
- export type CatalogLoader = () =>
22
- | Promise<Type<DynamicComponent<any>>>
23
- | Type<DynamicComponent<any>>;
24
-
25
- export type CatalogEntry<T extends Types.AnyComponentNode> =
26
- | CatalogLoader
27
- | {
28
- type: CatalogLoader;
29
- bindings: (data: T) => Binding[];
30
- };
31
-
32
- export interface Catalog {
33
- [key: string]: CatalogEntry<Types.AnyComponentNode>;
34
- }
35
-
36
- export const Catalog = new InjectionToken<Catalog>('Catalog');
@@ -1,100 +0,0 @@
1
- /*
2
- Copyright 2025 Google LLC
3
-
4
- Licensed under the Apache License, Version 2.0 (the "License");
5
- you may not use this file except in compliance with the License.
6
- You may obtain a copy of the License at
7
-
8
- https://www.apache.org/licenses/LICENSE-2.0
9
-
10
- Unless required by applicable law or agreed to in writing, software
11
- distributed under the License is distributed on an "AS IS" BASIS,
12
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- See the License for the specific language governing permissions and
14
- limitations under the License.
15
- */
16
-
17
- import { Types, Primitives } from '@a2ui/lit/0.8';
18
- import { Directive, inject, input } from '@angular/core';
19
- import { MessageProcessor } from '../data';
20
- import { Theme } from './theming';
21
-
22
- let idCounter = 0;
23
-
24
- @Directive({
25
- host: {
26
- '[style.--weight]': 'weight()',
27
- },
28
- })
29
- export abstract class DynamicComponent<T extends Types.AnyComponentNode = Types.AnyComponentNode> {
30
- protected readonly processor = inject(MessageProcessor);
31
- protected readonly theme = inject(Theme);
32
-
33
- readonly surfaceId = input.required<Types.SurfaceID | null>();
34
- readonly component = input.required<T>();
35
- readonly weight = input.required<string | number>();
36
-
37
- protected sendAction(action: Types.Action): Promise<Types.ServerToClientMessage[]> {
38
- const component = this.component();
39
- const surfaceId = this.surfaceId() ?? undefined;
40
- const context: Record<string, unknown> = {};
41
-
42
- if (action.context) {
43
- for (const item of action.context) {
44
- if (item.value.literalBoolean) {
45
- context[item.key] = item.value.literalBoolean;
46
- } else if (item.value.literalNumber) {
47
- context[item.key] = item.value.literalNumber;
48
- } else if (item.value.literalString) {
49
- context[item.key] = item.value.literalString;
50
- } else if (item.value.path) {
51
- const path = this.processor.resolvePath(item.value.path, component.dataContextPath);
52
- const value = this.processor.getData(component, path, surfaceId);
53
- context[item.key] = value;
54
- }
55
- }
56
- }
57
-
58
- const message: Types.A2UIClientEventMessage = {
59
- userAction: {
60
- name: action.name,
61
- sourceComponentId: component.id,
62
- surfaceId: surfaceId!,
63
- timestamp: new Date().toISOString(),
64
- context,
65
- },
66
- };
67
-
68
- return this.processor.dispatch(message);
69
- }
70
-
71
- protected resolvePrimitive(value: Primitives.StringValue | null): string | null;
72
- protected resolvePrimitive(value: Primitives.BooleanValue | null): boolean | null;
73
- protected resolvePrimitive(value: Primitives.NumberValue | null): number | null;
74
- protected resolvePrimitive(
75
- value: Primitives.StringValue | Primitives.BooleanValue | Primitives.NumberValue | null,
76
- ) {
77
- const component = this.component();
78
- const surfaceId = this.surfaceId();
79
-
80
- if (!value || typeof value !== 'object') {
81
- return null;
82
- } else if (value.literal != null) {
83
- return value.literal;
84
- } else if (value.path) {
85
- return this.processor.getData(component, value.path, surfaceId ?? undefined);
86
- } else if ('literalString' in value) {
87
- return value.literalString;
88
- } else if ('literalNumber' in value) {
89
- return value.literalNumber;
90
- } else if ('literalBoolean' in value) {
91
- return value.literalBoolean;
92
- }
93
-
94
- return null;
95
- }
96
-
97
- protected getUniqueId(prefix: string) {
98
- return `${prefix}-${idCounter++}`;
99
- }
100
- }
@@ -1,20 +0,0 @@
1
- /*
2
- Copyright 2025 Google LLC
3
-
4
- Licensed under the Apache License, Version 2.0 (the "License");
5
- you may not use this file except in compliance with the License.
6
- You may obtain a copy of the License at
7
-
8
- https://www.apache.org/licenses/LICENSE-2.0
9
-
10
- Unless required by applicable law or agreed to in writing, software
11
- distributed under the License is distributed on an "AS IS" BASIS,
12
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- See the License for the specific language governing permissions and
14
- limitations under the License.
15
- */
16
-
17
- export * from './catalog';
18
- export * from './dynamic-component';
19
- export * from './renderer';
20
- export * from './theming';
@@ -1,109 +0,0 @@
1
- /*
2
- Copyright 2025 Google LLC
3
-
4
- Licensed under the Apache License, Version 2.0 (the "License");
5
- you may not use this file except in compliance with the License.
6
- You may obtain a copy of the License at
7
-
8
- https://www.apache.org/licenses/LICENSE-2.0
9
-
10
- Unless required by applicable law or agreed to in writing, software
11
- distributed under the License is distributed on an "AS IS" BASIS,
12
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- See the License for the specific language governing permissions and
14
- limitations under the License.
15
- */
16
-
17
- import {
18
- Binding,
19
- ComponentRef,
20
- Directive,
21
- DOCUMENT,
22
- effect,
23
- inject,
24
- input,
25
- inputBinding,
26
- OnDestroy,
27
- PLATFORM_ID,
28
- Type,
29
- untracked,
30
- ViewContainerRef,
31
- } from '@angular/core';
32
- import { Types, Styles } from '@a2ui/lit/0.8';
33
- import { Catalog } from './catalog';
34
- import { isPlatformBrowser } from '@angular/common';
35
-
36
- @Directive({
37
- selector: 'ng-container[a2ui-renderer]',
38
- })
39
- export class Renderer implements OnDestroy {
40
- private viewContainerRef = inject(ViewContainerRef);
41
- private catalog = inject(Catalog);
42
- private static hasInsertedStyles = false;
43
-
44
- private currentRef: ComponentRef<unknown> | null = null;
45
- private isDestroyed = false;
46
-
47
- readonly surfaceId = input.required<Types.SurfaceID>();
48
- readonly component = input.required<Types.AnyComponentNode>();
49
-
50
- constructor() {
51
- effect(() => {
52
- const surfaceId = this.surfaceId();
53
- const component = this.component();
54
- untracked(() => this.render(surfaceId, component));
55
- });
56
-
57
- const platformId = inject(PLATFORM_ID);
58
- const document = inject(DOCUMENT);
59
-
60
- if (!Renderer.hasInsertedStyles && isPlatformBrowser(platformId)) {
61
- const styles = document.createElement('style');
62
- styles.textContent = Styles.structuralStyles;
63
- document.head.appendChild(styles);
64
- Renderer.hasInsertedStyles = true;
65
- }
66
- }
67
-
68
- ngOnDestroy(): void {
69
- this.isDestroyed = true;
70
- this.clear();
71
- }
72
-
73
- private async render(surfaceId: Types.SurfaceID, component: Types.AnyComponentNode) {
74
- const config = this.catalog[component.type];
75
- let newComponent: Type<unknown> | null = null;
76
- let componentBindings: Binding[] | null = null;
77
-
78
- if (typeof config === 'function') {
79
- newComponent = await config();
80
- } else if (typeof config === 'object') {
81
- newComponent = await config.type();
82
- componentBindings = config.bindings(component as any);
83
- }
84
-
85
- this.clear();
86
-
87
- if (newComponent && !this.isDestroyed) {
88
- const bindings = [
89
- inputBinding('surfaceId', () => surfaceId),
90
- inputBinding('component', () => component),
91
- inputBinding('weight', () => component.weight ?? 'initial'),
92
- ];
93
-
94
- if (componentBindings) {
95
- bindings.push(...componentBindings);
96
- }
97
-
98
- this.currentRef = this.viewContainerRef.createComponent(newComponent, {
99
- bindings,
100
- injector: this.viewContainerRef.injector,
101
- });
102
- }
103
- }
104
-
105
- private clear() {
106
- this.currentRef?.destroy();
107
- this.currentRef = null;
108
- }
109
- }