@liquid-glass-forge/angular 0.0.0-stage → 0.1.0-rc.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/NOTICE +7 -0
- package/README.md +47 -2
- package/fesm2022/liquid-glass-forge-angular.mjs +474 -0
- package/fesm2022/liquid-glass-forge-angular.mjs.map +1 -0
- package/package.json +37 -3
- package/types/liquid-glass-forge-angular.d.ts +102 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Nami Poursafargholi
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/NOTICE
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
Liquid Glass Forge
|
|
2
|
+
Copyright (c) 2026 Nami Poursafargholi. MIT licensed.
|
|
3
|
+
|
|
4
|
+
Independent implementation inspired by Apple's Liquid Glass design.
|
|
5
|
+
Not affiliated with, sponsored by or endorsed by Apple Inc.
|
|
6
|
+
Apple and its design/assets remain subject to their respective rights.
|
|
7
|
+
No Apple assets or upstream Liquid Glass/Sileo implementation is included.
|
package/README.md
CHANGED
|
@@ -1,3 +1,48 @@
|
|
|
1
|
-
#
|
|
1
|
+
# <img src="https://raw.githubusercontent.com/namipsg/liquid-glass-forge/main/showcase/public/frameworks/angular.svg" width="20" height="20" alt=""> @liquid-glass-forge/angular
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Use standalone Angular glass surfaces and a shared scene directive.
|
|
4
|
+
|
|
5
|
+
[Live showcase](https://namipsg.github.io/liquid-glass-forge/?framework=angular#developers) · [Examples](https://namipsg.github.io/liquid-glass-forge/examples.html) · [Documentation](https://github.com/namipsg/liquid-glass-forge/blob/main/docs/PHASE-9.md) · [Support](https://namipsg.github.io/liquid-glass-forge/support.html)
|
|
6
|
+
|
|
7
|
+
## Install in Angular
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
npm install @liquid-glass-forge/angular@next @liquid-glass-forge/dom@next
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
The starter uses CSS glass and expects Angular core/common 22.2.4 and RxJS 7.8.2. Keep the Forge packages at matching versions.
|
|
14
|
+
The [live installer](https://namipsg.github.io/liquid-glass-forge/?framework=angular#developers)
|
|
15
|
+
shows verified exact versions and has a copy button.
|
|
16
|
+
|
|
17
|
+
[Open the Angular starter](https://github.com/namipsg/liquid-glass-forge/blob/main/docs/QUICKSTART.md#angular) · [Add WebGL refraction](https://github.com/namipsg/liquid-glass-forge/blob/main/docs/QUICKSTART.md#add-webgl-refraction)
|
|
18
|
+
|
|
19
|
+
[](https://namipsg.github.io/liquid-glass-forge/?framework=angular#developers)
|
|
20
|
+
|
|
21
|
+
## Usage
|
|
22
|
+
|
|
23
|
+
Experimental preview `0.1.0-rc.2`. Pinned peers: Angular core/common22.2.4
|
|
24
|
+
and RxJS7.8.2. The ng-packagr output uses Angular Package Format, partial
|
|
25
|
+
compilation, FESM2022 and bundled declarations. Angular/RxJS remain external.
|
|
26
|
+
|
|
27
|
+
Import `GlassSceneDirective`, `GlassSurfaceComponent`, `GlassSurfaceDirective`
|
|
28
|
+
from `@liquid-glass-forge/angular` in standalone component imports. Load
|
|
29
|
+
`@liquid-glass-forge/dom/styles.css` through the application stylesheet pipeline.
|
|
30
|
+
|
|
31
|
+
`lgf-surface` owns its decorative template canvas and projects normal content.
|
|
32
|
+
`[lgfSurface]` binds a caller-template-owned direct canvas via required `lgfTarget`.
|
|
33
|
+
Both expose `element`, `target` and `invalidate`; the component target is undefined
|
|
34
|
+
before its view query resolves. Native controls remain Angular-owned.
|
|
35
|
+
|
|
36
|
+
`[lgfScene]` shares an engine across descendants, accepting `lgfSource`,
|
|
37
|
+
`lgfRenderer`, `lgfPaused` and `lgfTimeoutMs`, with errors emitted by `lgfError`.
|
|
38
|
+
The caller owns reusable source/renderer objects. DestroyRef cleanup aborts work
|
|
39
|
+
and disposes the scene/attachments without terminally disposing those objects.
|
|
40
|
+
|
|
41
|
+
Browser activation requires local view readiness and application stability after
|
|
42
|
+
a render callback. The callback alone is not treated as hydration completion.
|
|
43
|
+
Only eager SSR hydration is qualified by current consumers; deferred/incremental
|
|
44
|
+
hydration remains unqualified. Bitmap work runs outside Angular and does not
|
|
45
|
+
write framework signals per frame. SSR import/render starts no engine.
|
|
46
|
+
|
|
47
|
+
See the [integration guide](https://github.com/namipsg/liquid-glass-forge/blob/main/docs/PHASE-9.md) for the exact Angular/Node/TypeScript matrix,
|
|
48
|
+
APF/linker evidence, ownership, and remaining qualification boundaries.
|
|
@@ -0,0 +1,474 @@
|
|
|
1
|
+
import { isPlatformBrowser } from "@angular/common";
|
|
2
|
+
import * as i0 from "@angular/core";
|
|
3
|
+
import { ApplicationRef, Component, DestroyRef, Directive, ElementRef, InjectionToken, NgZone, PLATFORM_ID, afterNextRender, effect, forwardRef, inject, input, output, signal, untracked, viewChild } from "@angular/core";
|
|
4
|
+
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
|
|
5
|
+
import { filter, take } from "rxjs";
|
|
6
|
+
import { createGlassScene } from "@liquid-glass-forge/dom";
|
|
7
|
+
const SCENE = new InjectionToken("LiquidGlassForgeScene");
|
|
8
|
+
function afterStableView(action) {
|
|
9
|
+
const destroy = inject(DestroyRef), app = inject(ApplicationRef), zone = inject(NgZone);
|
|
10
|
+
if (!isPlatformBrowser(inject(PLATFORM_ID))) return;
|
|
11
|
+
const render = afterNextRender(() => zone.runOutsideAngular(() => {
|
|
12
|
+
app.isStable.pipe(filter(Boolean), take(1), takeUntilDestroyed(destroy)).subscribe(() => {
|
|
13
|
+
if (!destroy.destroyed) action();
|
|
14
|
+
});
|
|
15
|
+
}));
|
|
16
|
+
destroy.onDestroy(() => render.destroy());
|
|
17
|
+
}
|
|
18
|
+
var GlassSceneDirective = class GlassSceneDirective {
|
|
19
|
+
lgfSource = input(...ngDevMode ? [void 0, { debugName: "lgfSource" }] : /* istanbul ignore next */ []);
|
|
20
|
+
lgfRenderer = input(...ngDevMode ? [void 0, { debugName: "lgfRenderer" }] : /* istanbul ignore next */ []);
|
|
21
|
+
lgfTimeoutMs = input(...ngDevMode ? [void 0, { debugName: "lgfTimeoutMs" }] : /* istanbul ignore next */ []);
|
|
22
|
+
lgfPaused = input(false, ...ngDevMode ? [{ debugName: "lgfPaused" }] : /* istanbul ignore next */ []);
|
|
23
|
+
lgfError = output();
|
|
24
|
+
state = signal(null, ...ngDevMode ? [{ debugName: "state" }] : /* istanbul ignore next */ []);
|
|
25
|
+
scene = this.state.asReadonly();
|
|
26
|
+
zone = inject(NgZone);
|
|
27
|
+
destroy = inject(DestroyRef);
|
|
28
|
+
ready = false;
|
|
29
|
+
viewReady = false;
|
|
30
|
+
previous;
|
|
31
|
+
constructor() {
|
|
32
|
+
afterStableView(() => {
|
|
33
|
+
this.ready = true;
|
|
34
|
+
this.apply();
|
|
35
|
+
});
|
|
36
|
+
effect(() => {
|
|
37
|
+
this.lgfSource();
|
|
38
|
+
this.lgfRenderer();
|
|
39
|
+
this.lgfTimeoutMs();
|
|
40
|
+
this.lgfPaused();
|
|
41
|
+
untracked(() => this.apply());
|
|
42
|
+
});
|
|
43
|
+
this.destroy.onDestroy(() => {
|
|
44
|
+
this.ready = false;
|
|
45
|
+
this.state()?.dispose();
|
|
46
|
+
this.state.set(null);
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
ngAfterViewInit() {
|
|
50
|
+
this.viewReady = true;
|
|
51
|
+
this.apply();
|
|
52
|
+
}
|
|
53
|
+
apply() {
|
|
54
|
+
if (!this.ready || !this.viewReady || this.destroy.destroyed) return;
|
|
55
|
+
this.zone.runOutsideAngular(() => {
|
|
56
|
+
const source = this.lgfSource(), renderer = this.lgfRenderer(), timeout = this.lgfTimeoutMs();
|
|
57
|
+
if (!this.previous || source !== this.previous[0] || renderer !== this.previous[1] || timeout !== this.previous[2]) {
|
|
58
|
+
this.state()?.dispose();
|
|
59
|
+
const outside = source ? {
|
|
60
|
+
read: (options) => this.zone.runOutsideAngular(() => source.read(options)),
|
|
61
|
+
...source.subscribe ? { subscribe: (listener) => this.zone.runOutsideAngular(() => source.subscribe(() => this.zone.runOutsideAngular(listener))) } : {}
|
|
62
|
+
} : void 0;
|
|
63
|
+
const next = createGlassScene({
|
|
64
|
+
...outside ? { source: outside } : {},
|
|
65
|
+
...renderer ? { renderer } : {},
|
|
66
|
+
...timeout === void 0 ? {} : { timeoutMs: timeout },
|
|
67
|
+
onError: (cause) => {
|
|
68
|
+
if (!this.destroy.destroyed) this.zone.run(() => this.lgfError.emit(cause));
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
if (this.lgfPaused()) next.pause();
|
|
72
|
+
this.previous = [
|
|
73
|
+
source,
|
|
74
|
+
renderer,
|
|
75
|
+
timeout
|
|
76
|
+
];
|
|
77
|
+
this.state.set(next);
|
|
78
|
+
} else {
|
|
79
|
+
const current = this.state();
|
|
80
|
+
if (this.lgfPaused()) current?.pause();
|
|
81
|
+
else if (current?.state === "paused") current.resume();
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
static ɵfac = i0.ɵɵngDeclareFactory({
|
|
86
|
+
minVersion: "12.0.0",
|
|
87
|
+
version: "22.2.4",
|
|
88
|
+
ngImport: i0,
|
|
89
|
+
type: GlassSceneDirective,
|
|
90
|
+
deps: [],
|
|
91
|
+
target: i0.ɵɵFactoryTarget.Directive
|
|
92
|
+
});
|
|
93
|
+
static ɵdir = i0.ɵɵngDeclareDirective({
|
|
94
|
+
minVersion: "17.1.0",
|
|
95
|
+
version: "22.2.4",
|
|
96
|
+
type: GlassSceneDirective,
|
|
97
|
+
isStandalone: true,
|
|
98
|
+
selector: "[lgfScene]",
|
|
99
|
+
inputs: {
|
|
100
|
+
lgfSource: {
|
|
101
|
+
classPropertyName: "lgfSource",
|
|
102
|
+
publicName: "lgfSource",
|
|
103
|
+
isSignal: true,
|
|
104
|
+
isRequired: false,
|
|
105
|
+
transformFunction: null
|
|
106
|
+
},
|
|
107
|
+
lgfRenderer: {
|
|
108
|
+
classPropertyName: "lgfRenderer",
|
|
109
|
+
publicName: "lgfRenderer",
|
|
110
|
+
isSignal: true,
|
|
111
|
+
isRequired: false,
|
|
112
|
+
transformFunction: null
|
|
113
|
+
},
|
|
114
|
+
lgfTimeoutMs: {
|
|
115
|
+
classPropertyName: "lgfTimeoutMs",
|
|
116
|
+
publicName: "lgfTimeoutMs",
|
|
117
|
+
isSignal: true,
|
|
118
|
+
isRequired: false,
|
|
119
|
+
transformFunction: null
|
|
120
|
+
},
|
|
121
|
+
lgfPaused: {
|
|
122
|
+
classPropertyName: "lgfPaused",
|
|
123
|
+
publicName: "lgfPaused",
|
|
124
|
+
isSignal: true,
|
|
125
|
+
isRequired: false,
|
|
126
|
+
transformFunction: null
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
outputs: { lgfError: "lgfError" },
|
|
130
|
+
providers: [{
|
|
131
|
+
provide: SCENE,
|
|
132
|
+
useExisting: forwardRef(() => GlassSceneDirective)
|
|
133
|
+
}],
|
|
134
|
+
exportAs: ["lgfScene"],
|
|
135
|
+
ngImport: i0
|
|
136
|
+
});
|
|
137
|
+
};
|
|
138
|
+
i0.ɵɵngDeclareClassMetadata({
|
|
139
|
+
minVersion: "12.0.0",
|
|
140
|
+
version: "22.2.4",
|
|
141
|
+
ngImport: i0,
|
|
142
|
+
type: GlassSceneDirective,
|
|
143
|
+
decorators: [{
|
|
144
|
+
type: Directive,
|
|
145
|
+
args: [{
|
|
146
|
+
selector: "[lgfScene]",
|
|
147
|
+
standalone: true,
|
|
148
|
+
exportAs: "lgfScene",
|
|
149
|
+
providers: [{
|
|
150
|
+
provide: SCENE,
|
|
151
|
+
useExisting: forwardRef(() => GlassSceneDirective)
|
|
152
|
+
}]
|
|
153
|
+
}]
|
|
154
|
+
}],
|
|
155
|
+
ctorParameters: () => [],
|
|
156
|
+
propDecorators: {
|
|
157
|
+
lgfSource: [{
|
|
158
|
+
type: i0.Input,
|
|
159
|
+
args: [{
|
|
160
|
+
isSignal: true,
|
|
161
|
+
alias: "lgfSource",
|
|
162
|
+
required: false
|
|
163
|
+
}]
|
|
164
|
+
}],
|
|
165
|
+
lgfRenderer: [{
|
|
166
|
+
type: i0.Input,
|
|
167
|
+
args: [{
|
|
168
|
+
isSignal: true,
|
|
169
|
+
alias: "lgfRenderer",
|
|
170
|
+
required: false
|
|
171
|
+
}]
|
|
172
|
+
}],
|
|
173
|
+
lgfTimeoutMs: [{
|
|
174
|
+
type: i0.Input,
|
|
175
|
+
args: [{
|
|
176
|
+
isSignal: true,
|
|
177
|
+
alias: "lgfTimeoutMs",
|
|
178
|
+
required: false
|
|
179
|
+
}]
|
|
180
|
+
}],
|
|
181
|
+
lgfPaused: [{
|
|
182
|
+
type: i0.Input,
|
|
183
|
+
args: [{
|
|
184
|
+
isSignal: true,
|
|
185
|
+
alias: "lgfPaused",
|
|
186
|
+
required: false
|
|
187
|
+
}]
|
|
188
|
+
}],
|
|
189
|
+
lgfError: [{
|
|
190
|
+
type: i0.Output,
|
|
191
|
+
args: ["lgfError"]
|
|
192
|
+
}]
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
var SurfaceBinding = class {
|
|
196
|
+
element;
|
|
197
|
+
shared;
|
|
198
|
+
attachment;
|
|
199
|
+
owned;
|
|
200
|
+
lastScene;
|
|
201
|
+
lastTarget;
|
|
202
|
+
lastMaterial;
|
|
203
|
+
constructor(element, shared) {
|
|
204
|
+
this.element = element;
|
|
205
|
+
this.shared = shared;
|
|
206
|
+
}
|
|
207
|
+
update(target, scene, material) {
|
|
208
|
+
if (this.shared && !scene) {
|
|
209
|
+
this.detach();
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
if (!this.shared) this.owned ??= createGlassScene();
|
|
213
|
+
const current = scene ?? this.owned;
|
|
214
|
+
if (current.state === "destroyed") {
|
|
215
|
+
this.detach();
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
if (this.attachment && this.lastScene === current && this.lastTarget === target) {
|
|
219
|
+
if (this.lastMaterial !== material) this.attachment.update({ material });
|
|
220
|
+
} else {
|
|
221
|
+
this.detach();
|
|
222
|
+
this.attachment = current.attach(this.element, {
|
|
223
|
+
target,
|
|
224
|
+
material
|
|
225
|
+
});
|
|
226
|
+
this.lastScene = current;
|
|
227
|
+
this.lastTarget = target;
|
|
228
|
+
}
|
|
229
|
+
this.lastMaterial = material;
|
|
230
|
+
}
|
|
231
|
+
invalidate() {
|
|
232
|
+
this.attachment?.invalidate();
|
|
233
|
+
}
|
|
234
|
+
detach() {
|
|
235
|
+
this.attachment?.dispose();
|
|
236
|
+
this.attachment = void 0;
|
|
237
|
+
this.lastScene = void 0;
|
|
238
|
+
this.lastTarget = void 0;
|
|
239
|
+
this.lastMaterial = void 0;
|
|
240
|
+
}
|
|
241
|
+
destroy() {
|
|
242
|
+
this.detach();
|
|
243
|
+
this.owned?.dispose();
|
|
244
|
+
this.owned = void 0;
|
|
245
|
+
}
|
|
246
|
+
};
|
|
247
|
+
var GlassSurfaceComponent = class GlassSurfaceComponent {
|
|
248
|
+
material = input("glass", ...ngDevMode ? [{ debugName: "material" }] : /* istanbul ignore next */ []);
|
|
249
|
+
canvas = viewChild("glassTarget", ...ngDevMode ? [{ debugName: "canvas" }] : /* istanbul ignore next */ []);
|
|
250
|
+
host = inject(ElementRef);
|
|
251
|
+
parent = inject(SCENE, { optional: true });
|
|
252
|
+
zone = inject(NgZone);
|
|
253
|
+
destroy = inject(DestroyRef);
|
|
254
|
+
binding = new SurfaceBinding(this.host.nativeElement, !!this.parent);
|
|
255
|
+
ready = false;
|
|
256
|
+
viewReady = false;
|
|
257
|
+
constructor() {
|
|
258
|
+
afterStableView(() => {
|
|
259
|
+
this.ready = true;
|
|
260
|
+
this.refresh();
|
|
261
|
+
});
|
|
262
|
+
effect(() => {
|
|
263
|
+
this.material();
|
|
264
|
+
this.canvas();
|
|
265
|
+
this.parent?.scene();
|
|
266
|
+
untracked(() => this.refresh());
|
|
267
|
+
});
|
|
268
|
+
this.destroy.onDestroy(() => {
|
|
269
|
+
this.ready = false;
|
|
270
|
+
this.binding.destroy();
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
ngAfterViewInit() {
|
|
274
|
+
this.viewReady = true;
|
|
275
|
+
this.refresh();
|
|
276
|
+
}
|
|
277
|
+
get element() {
|
|
278
|
+
return this.host.nativeElement;
|
|
279
|
+
}
|
|
280
|
+
get target() {
|
|
281
|
+
return this.canvas()?.nativeElement;
|
|
282
|
+
}
|
|
283
|
+
invalidate() {
|
|
284
|
+
this.zone.runOutsideAngular(() => this.binding.invalidate());
|
|
285
|
+
}
|
|
286
|
+
refresh() {
|
|
287
|
+
if (!this.ready || !this.viewReady || this.destroy.destroyed) return;
|
|
288
|
+
const target = this.target;
|
|
289
|
+
if (!target) return;
|
|
290
|
+
this.zone.runOutsideAngular(() => this.binding.update(target, this.parent?.scene() ?? null, this.material()));
|
|
291
|
+
}
|
|
292
|
+
static ɵfac = i0.ɵɵngDeclareFactory({
|
|
293
|
+
minVersion: "12.0.0",
|
|
294
|
+
version: "22.2.4",
|
|
295
|
+
ngImport: i0,
|
|
296
|
+
type: GlassSurfaceComponent,
|
|
297
|
+
deps: [],
|
|
298
|
+
target: i0.ɵɵFactoryTarget.Component
|
|
299
|
+
});
|
|
300
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({
|
|
301
|
+
minVersion: "17.2.0",
|
|
302
|
+
version: "22.2.4",
|
|
303
|
+
type: GlassSurfaceComponent,
|
|
304
|
+
isStandalone: true,
|
|
305
|
+
selector: "lgf-surface",
|
|
306
|
+
inputs: { material: {
|
|
307
|
+
classPropertyName: "material",
|
|
308
|
+
publicName: "material",
|
|
309
|
+
isSignal: true,
|
|
310
|
+
isRequired: false,
|
|
311
|
+
transformFunction: null
|
|
312
|
+
} },
|
|
313
|
+
host: { classAttribute: "lgf-host" },
|
|
314
|
+
viewQueries: [{
|
|
315
|
+
propertyName: "canvas",
|
|
316
|
+
first: true,
|
|
317
|
+
predicate: ["glassTarget"],
|
|
318
|
+
descendants: true,
|
|
319
|
+
isSignal: true
|
|
320
|
+
}],
|
|
321
|
+
exportAs: ["lgfSurface"],
|
|
322
|
+
ngImport: i0,
|
|
323
|
+
template: "<canvas #glassTarget class=\"lgf-surface\" [attr.data-lgf-material]=\"material()\" aria-hidden=\"true\" role=\"presentation\" tabindex=\"-1\"></canvas><ng-content />",
|
|
324
|
+
isInline: true,
|
|
325
|
+
styles: [":host{display:block}\n"]
|
|
326
|
+
});
|
|
327
|
+
};
|
|
328
|
+
i0.ɵɵngDeclareClassMetadata({
|
|
329
|
+
minVersion: "12.0.0",
|
|
330
|
+
version: "22.2.4",
|
|
331
|
+
ngImport: i0,
|
|
332
|
+
type: GlassSurfaceComponent,
|
|
333
|
+
decorators: [{
|
|
334
|
+
type: Component,
|
|
335
|
+
args: [{
|
|
336
|
+
selector: "lgf-surface",
|
|
337
|
+
standalone: true,
|
|
338
|
+
exportAs: "lgfSurface",
|
|
339
|
+
host: { class: "lgf-host" },
|
|
340
|
+
template: "<canvas #glassTarget class=\"lgf-surface\" [attr.data-lgf-material]=\"material()\" aria-hidden=\"true\" role=\"presentation\" tabindex=\"-1\"></canvas><ng-content />",
|
|
341
|
+
styles: [":host{display:block}\n"]
|
|
342
|
+
}]
|
|
343
|
+
}],
|
|
344
|
+
ctorParameters: () => [],
|
|
345
|
+
propDecorators: {
|
|
346
|
+
material: [{
|
|
347
|
+
type: i0.Input,
|
|
348
|
+
args: [{
|
|
349
|
+
isSignal: true,
|
|
350
|
+
alias: "material",
|
|
351
|
+
required: false
|
|
352
|
+
}]
|
|
353
|
+
}],
|
|
354
|
+
canvas: [{
|
|
355
|
+
type: i0.ViewChild,
|
|
356
|
+
args: ["glassTarget", { isSignal: true }]
|
|
357
|
+
}]
|
|
358
|
+
}
|
|
359
|
+
});
|
|
360
|
+
var GlassSurfaceDirective = class GlassSurfaceDirective {
|
|
361
|
+
lgfTarget = input.required(...ngDevMode ? [{ debugName: "lgfTarget" }] : /* istanbul ignore next */ []);
|
|
362
|
+
lgfMaterial = input("glass", ...ngDevMode ? [{ debugName: "lgfMaterial" }] : /* istanbul ignore next */ []);
|
|
363
|
+
host = inject(ElementRef);
|
|
364
|
+
parent = inject(SCENE, { optional: true });
|
|
365
|
+
zone = inject(NgZone);
|
|
366
|
+
destroy = inject(DestroyRef);
|
|
367
|
+
binding = new SurfaceBinding(this.host.nativeElement, !!this.parent);
|
|
368
|
+
ready = false;
|
|
369
|
+
viewReady = false;
|
|
370
|
+
constructor() {
|
|
371
|
+
afterStableView(() => {
|
|
372
|
+
this.ready = true;
|
|
373
|
+
this.refresh();
|
|
374
|
+
});
|
|
375
|
+
effect(() => {
|
|
376
|
+
this.lgfTarget();
|
|
377
|
+
this.lgfMaterial();
|
|
378
|
+
this.parent?.scene();
|
|
379
|
+
untracked(() => this.refresh());
|
|
380
|
+
});
|
|
381
|
+
this.destroy.onDestroy(() => {
|
|
382
|
+
this.ready = false;
|
|
383
|
+
this.binding.destroy();
|
|
384
|
+
});
|
|
385
|
+
}
|
|
386
|
+
ngAfterViewInit() {
|
|
387
|
+
this.viewReady = true;
|
|
388
|
+
this.refresh();
|
|
389
|
+
}
|
|
390
|
+
get element() {
|
|
391
|
+
return this.host.nativeElement;
|
|
392
|
+
}
|
|
393
|
+
get target() {
|
|
394
|
+
return this.lgfTarget();
|
|
395
|
+
}
|
|
396
|
+
invalidate() {
|
|
397
|
+
this.zone.runOutsideAngular(() => this.binding.invalidate());
|
|
398
|
+
}
|
|
399
|
+
refresh() {
|
|
400
|
+
if (!this.ready || !this.viewReady || this.destroy.destroyed) return;
|
|
401
|
+
this.zone.runOutsideAngular(() => this.binding.update(this.target, this.parent?.scene() ?? null, this.lgfMaterial()));
|
|
402
|
+
}
|
|
403
|
+
static ɵfac = i0.ɵɵngDeclareFactory({
|
|
404
|
+
minVersion: "12.0.0",
|
|
405
|
+
version: "22.2.4",
|
|
406
|
+
ngImport: i0,
|
|
407
|
+
type: GlassSurfaceDirective,
|
|
408
|
+
deps: [],
|
|
409
|
+
target: i0.ɵɵFactoryTarget.Directive
|
|
410
|
+
});
|
|
411
|
+
static ɵdir = i0.ɵɵngDeclareDirective({
|
|
412
|
+
minVersion: "17.1.0",
|
|
413
|
+
version: "22.2.4",
|
|
414
|
+
type: GlassSurfaceDirective,
|
|
415
|
+
isStandalone: true,
|
|
416
|
+
selector: "[lgfSurface]",
|
|
417
|
+
inputs: {
|
|
418
|
+
lgfTarget: {
|
|
419
|
+
classPropertyName: "lgfTarget",
|
|
420
|
+
publicName: "lgfTarget",
|
|
421
|
+
isSignal: true,
|
|
422
|
+
isRequired: true,
|
|
423
|
+
transformFunction: null
|
|
424
|
+
},
|
|
425
|
+
lgfMaterial: {
|
|
426
|
+
classPropertyName: "lgfMaterial",
|
|
427
|
+
publicName: "lgfMaterial",
|
|
428
|
+
isSignal: true,
|
|
429
|
+
isRequired: false,
|
|
430
|
+
transformFunction: null
|
|
431
|
+
}
|
|
432
|
+
},
|
|
433
|
+
host: { classAttribute: "lgf-host" },
|
|
434
|
+
exportAs: ["lgfSurface"],
|
|
435
|
+
ngImport: i0
|
|
436
|
+
});
|
|
437
|
+
};
|
|
438
|
+
i0.ɵɵngDeclareClassMetadata({
|
|
439
|
+
minVersion: "12.0.0",
|
|
440
|
+
version: "22.2.4",
|
|
441
|
+
ngImport: i0,
|
|
442
|
+
type: GlassSurfaceDirective,
|
|
443
|
+
decorators: [{
|
|
444
|
+
type: Directive,
|
|
445
|
+
args: [{
|
|
446
|
+
selector: "[lgfSurface]",
|
|
447
|
+
standalone: true,
|
|
448
|
+
exportAs: "lgfSurface",
|
|
449
|
+
host: { class: "lgf-host" }
|
|
450
|
+
}]
|
|
451
|
+
}],
|
|
452
|
+
ctorParameters: () => [],
|
|
453
|
+
propDecorators: {
|
|
454
|
+
lgfTarget: [{
|
|
455
|
+
type: i0.Input,
|
|
456
|
+
args: [{
|
|
457
|
+
isSignal: true,
|
|
458
|
+
alias: "lgfTarget",
|
|
459
|
+
required: true
|
|
460
|
+
}]
|
|
461
|
+
}],
|
|
462
|
+
lgfMaterial: [{
|
|
463
|
+
type: i0.Input,
|
|
464
|
+
args: [{
|
|
465
|
+
isSignal: true,
|
|
466
|
+
alias: "lgfMaterial",
|
|
467
|
+
required: false
|
|
468
|
+
}]
|
|
469
|
+
}]
|
|
470
|
+
}
|
|
471
|
+
});
|
|
472
|
+
export { GlassSceneDirective, GlassSurfaceComponent, GlassSurfaceDirective };
|
|
473
|
+
|
|
474
|
+
//# sourceMappingURL=liquid-glass-forge-angular.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"liquid-glass-forge-angular.mjs","names":[],"sources":["../../src/public-api.ts"],"sourcesContent":["import { isPlatformBrowser } from '@angular/common';\nimport { afterNextRender, ApplicationRef, Component, DestroyRef, Directive, effect, ElementRef, forwardRef, inject, InjectionToken, input, NgZone, output, PLATFORM_ID, signal, untracked, viewChild } from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { filter, take } from 'rxjs';\nimport { createGlassScene } from '@liquid-glass-forge/dom';\nimport type { GlassAttachment, GlassMaterial, GlassRenderer, GlassScene, SceneSource } from '@liquid-glass-forge/dom';\n\n/** Private per-provider context; scenes never become Angular application globals. */\nconst SCENE = new InjectionToken<GlassSceneDirective>('LiquidGlassForgeScene');\n\n/** Local view readiness plus application stability, not a global hydration claim.\n * Incremental/deferred hydration is outside this package's tested support matrix. */\nfunction afterStableView(action: () => void): void {\n const destroy = inject(DestroyRef), app = inject(ApplicationRef), zone = inject(NgZone);\n if (!isPlatformBrowser(inject(PLATFORM_ID))) return;\n const render = afterNextRender(() => zone.runOutsideAngular(() => {\n app.isStable.pipe(filter(Boolean), take(1), takeUntilDestroyed(destroy)).subscribe(() => {\n if (!destroy.destroyed) action();\n });\n }));\n destroy.onDestroy(() => render.destroy());\n}\n\n/** Borrowed inputs; this directive owns one cancellable scene lifetime. */\n@Directive({ selector: '[lgfScene]', standalone: true, exportAs: 'lgfScene', providers: [{ provide: SCENE, useExisting: forwardRef(() => GlassSceneDirective) }] })\nexport class GlassSceneDirective {\n readonly lgfSource = input<SceneSource>();\n readonly lgfRenderer = input<GlassRenderer>();\n readonly lgfTimeoutMs = input<number>();\n readonly lgfPaused = input(false);\n readonly lgfError = output<unknown>();\n private readonly state = signal<GlassScene | null>(null);\n readonly scene = this.state.asReadonly();\n private readonly zone = inject(NgZone);\n private readonly destroy = inject(DestroyRef);\n private ready = false;\n private viewReady = false;\n private previous: readonly [SceneSource | undefined, GlassRenderer | undefined, number | undefined] | undefined;\n constructor() {\n afterStableView(() => { this.ready = true; this.apply(); });\n effect(() => {\n this.lgfSource(); this.lgfRenderer(); this.lgfTimeoutMs(); this.lgfPaused();\n untracked(() => this.apply());\n });\n this.destroy.onDestroy(() => { this.ready = false; this.state()?.dispose(); this.state.set(null); });\n }\n ngAfterViewInit(): void { this.viewReady = true; this.apply(); }\n private apply(): void {\n if (!this.ready || !this.viewReady || this.destroy.destroyed) return;\n this.zone.runOutsideAngular(() => {\n const source = this.lgfSource(), renderer = this.lgfRenderer(), timeout = this.lgfTimeoutMs();\n if (!this.previous || source !== this.previous[0] || renderer !== this.previous[1] || timeout !== this.previous[2]) {\n this.state()?.dispose();\n // Source callbacks can be invoked from a zoned application event. Keep\n // acquisition, invalidation and renderer work outside Angular scheduling.\n const outside: SceneSource | undefined = source ? {\n read: options => this.zone.runOutsideAngular(() => source.read(options)),\n ...(source.subscribe ? { subscribe: (listener: () => void) => this.zone.runOutsideAngular(() => source.subscribe!(() => this.zone.runOutsideAngular(listener))) } : {}),\n } : undefined;\n const next = createGlassScene({ ...(outside ? { source: outside } : {}), ...(renderer ? { renderer } : {}),\n ...(timeout === undefined ? {} : { timeoutMs: timeout }), onError: cause => { if (!this.destroy.destroyed) this.zone.run(() => this.lgfError.emit(cause)); } });\n if (this.lgfPaused()) next.pause();\n this.previous = [source, renderer, timeout]; this.state.set(next);\n } else {\n const current = this.state();\n if (this.lgfPaused()) current?.pause(); else if (current?.state === 'paused') current.resume();\n }\n });\n }\n}\n\n/** Engine state is ordinary data; bitmap completion never writes Angular signals. */\nclass SurfaceBinding {\n private attachment: GlassAttachment | undefined;\n private owned: GlassScene | undefined;\n private lastScene: GlassScene | undefined;\n private lastTarget: HTMLCanvasElement | undefined;\n private lastMaterial: GlassMaterial | undefined;\n constructor(private readonly element: HTMLElement, private readonly shared: boolean) {}\n update(target: HTMLCanvasElement, scene: GlassScene | null, material: GlassMaterial): void {\n if (this.shared && !scene) { this.detach(); return; }\n if (!this.shared) this.owned ??= createGlassScene();\n const current = scene ?? this.owned!;\n if (current.state === 'destroyed') { this.detach(); return; }\n if (this.attachment && this.lastScene === current && this.lastTarget === target) {\n if (this.lastMaterial !== material) this.attachment.update({ material });\n } else {\n this.detach();\n this.attachment = current.attach(this.element, { target, material });\n this.lastScene = current; this.lastTarget = target;\n }\n this.lastMaterial = material;\n }\n invalidate(): void { this.attachment?.invalidate(); }\n private detach(): void { this.attachment?.dispose(); this.attachment = undefined; this.lastScene = undefined; this.lastTarget = undefined; this.lastMaterial = undefined; }\n destroy(): void { this.detach(); this.owned?.dispose(); this.owned = undefined; }\n}\n\n/** Angular owns the custom host, decorative canvas and projected semantic DOM. */\n@Component({\n selector: 'lgf-surface', standalone: true, exportAs: 'lgfSurface',\n host: { class: 'lgf-host' }, styles: [':host { display: block; }'],\n template: '<canvas #glassTarget class=\"lgf-surface\" [attr.data-lgf-material]=\"material()\" aria-hidden=\"true\" role=\"presentation\" tabindex=\"-1\"></canvas><ng-content />',\n})\nexport class GlassSurfaceComponent {\n readonly material = input<GlassMaterial>('glass');\n private readonly canvas = viewChild<ElementRef<HTMLCanvasElement>>('glassTarget');\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef);\n private readonly parent = inject(SCENE, { optional: true });\n private readonly zone = inject(NgZone);\n private readonly destroy = inject(DestroyRef);\n private readonly binding = new SurfaceBinding(this.host.nativeElement, !!this.parent);\n private ready = false;\n private viewReady = false;\n constructor() {\n afterStableView(() => { this.ready = true; this.refresh(); });\n effect(() => { this.material(); this.canvas(); this.parent?.scene(); untracked(() => this.refresh()); });\n this.destroy.onDestroy(() => { this.ready = false; this.binding.destroy(); });\n }\n ngAfterViewInit(): void { this.viewReady = true; this.refresh(); }\n get element(): HTMLElement { return this.host.nativeElement; }\n get target(): HTMLCanvasElement | undefined { return this.canvas()?.nativeElement; }\n invalidate(): void { this.zone.runOutsideAngular(() => this.binding.invalidate()); }\n private refresh(): void {\n if (!this.ready || !this.viewReady || this.destroy.destroyed) return;\n const target = this.target; if (!target) return;\n this.zone.runOutsideAngular(() => this.binding.update(target, this.parent?.scene() ?? null, this.material()));\n }\n}\n\n/** Bind a caller-template-owned direct canvas child; never create or move nodes. */\n@Directive({ selector: '[lgfSurface]', standalone: true, exportAs: 'lgfSurface', host: { class: 'lgf-host' } })\nexport class GlassSurfaceDirective {\n readonly lgfTarget = input.required<HTMLCanvasElement>();\n readonly lgfMaterial = input<GlassMaterial>('glass');\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef);\n private readonly parent = inject(SCENE, { optional: true });\n private readonly zone = inject(NgZone);\n private readonly destroy = inject(DestroyRef);\n private readonly binding = new SurfaceBinding(this.host.nativeElement, !!this.parent);\n private ready = false;\n private viewReady = false;\n constructor() {\n afterStableView(() => { this.ready = true; this.refresh(); });\n effect(() => { this.lgfTarget(); this.lgfMaterial(); this.parent?.scene(); untracked(() => this.refresh()); });\n this.destroy.onDestroy(() => { this.ready = false; this.binding.destroy(); });\n }\n ngAfterViewInit(): void { this.viewReady = true; this.refresh(); }\n get element(): HTMLElement { return this.host.nativeElement; }\n get target(): HTMLCanvasElement { return this.lgfTarget(); }\n invalidate(): void { this.zone.runOutsideAngular(() => this.binding.invalidate()); }\n private refresh(): void {\n if (!this.ready || !this.viewReady || this.destroy.destroyed) return;\n this.zone.runOutsideAngular(() => this.binding.update(this.target, this.parent?.scene() ?? null, this.lgfMaterial()));\n }\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,40 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@liquid-glass-forge/angular",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "0.1.0-rc.2",
|
|
4
|
+
"private": false,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"sideEffects": false,
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"engines": {
|
|
9
|
+
"node": "^22.22.3 || ^24.15.0 || >=26.0.0"
|
|
10
|
+
},
|
|
11
|
+
"peerDependencies": {
|
|
12
|
+
"@angular/core": "22.2.4",
|
|
13
|
+
"@angular/common": "22.2.4",
|
|
14
|
+
"rxjs": "7.8.2"
|
|
15
|
+
},
|
|
16
|
+
"dependencies": {
|
|
17
|
+
"@liquid-glass-forge/dom": "0.1.0-rc.2",
|
|
18
|
+
"tslib": "2.9.1"
|
|
19
|
+
},
|
|
20
|
+
"homepage": "https://namipsg.github.io/liquid-glass-forge/?framework=angular#developers",
|
|
21
|
+
"repository": {
|
|
22
|
+
"type": "git",
|
|
23
|
+
"url": "git+https://github.com/namipsg/liquid-glass-forge.git",
|
|
24
|
+
"directory": "packages/angular"
|
|
25
|
+
},
|
|
26
|
+
"publishConfig": {
|
|
27
|
+
"access": "public"
|
|
28
|
+
},
|
|
29
|
+
"module": "fesm2022/liquid-glass-forge-angular.mjs",
|
|
30
|
+
"typings": "types/liquid-glass-forge-angular.d.ts",
|
|
31
|
+
"exports": {
|
|
32
|
+
"./package.json": {
|
|
33
|
+
"default": "./package.json"
|
|
34
|
+
},
|
|
35
|
+
".": {
|
|
36
|
+
"types": "./types/liquid-glass-forge-angular.d.ts",
|
|
37
|
+
"default": "./fesm2022/liquid-glass-forge-angular.mjs"
|
|
38
|
+
}
|
|
39
|
+
}
|
|
6
40
|
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { GlassMaterial, GlassRenderer, GlassScene, SceneSource } from "@liquid-glass-forge/dom";
|
|
2
|
+
import * as i0 from "@angular/core";
|
|
3
|
+
/** Borrowed inputs; this directive owns one cancellable scene lifetime. */
|
|
4
|
+
export declare class GlassSceneDirective {
|
|
5
|
+
readonly lgfSource: import("@angular/core").InputSignal<SceneSource | undefined>;
|
|
6
|
+
readonly lgfRenderer: import("@angular/core").InputSignal<GlassRenderer | undefined>;
|
|
7
|
+
readonly lgfTimeoutMs: import("@angular/core").InputSignal<number | undefined>;
|
|
8
|
+
readonly lgfPaused: import("@angular/core").InputSignal<boolean>;
|
|
9
|
+
readonly lgfError: import("@angular/core").OutputEmitterRef<unknown>;
|
|
10
|
+
private readonly state;
|
|
11
|
+
readonly scene: import("@angular/core").Signal<GlassScene | null>;
|
|
12
|
+
private readonly zone;
|
|
13
|
+
private readonly destroy;
|
|
14
|
+
private ready;
|
|
15
|
+
private viewReady;
|
|
16
|
+
private previous;
|
|
17
|
+
constructor();
|
|
18
|
+
ngAfterViewInit(): void;
|
|
19
|
+
private apply;
|
|
20
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<GlassSceneDirective, never>;
|
|
21
|
+
static ɵdir: i0.ɵɵDirectiveDeclaration<GlassSceneDirective, "[lgfScene]", ["lgfScene"], {
|
|
22
|
+
"lgfSource": {
|
|
23
|
+
"alias": "lgfSource";
|
|
24
|
+
"required": false;
|
|
25
|
+
"isSignal": true;
|
|
26
|
+
};
|
|
27
|
+
"lgfRenderer": {
|
|
28
|
+
"alias": "lgfRenderer";
|
|
29
|
+
"required": false;
|
|
30
|
+
"isSignal": true;
|
|
31
|
+
};
|
|
32
|
+
"lgfTimeoutMs": {
|
|
33
|
+
"alias": "lgfTimeoutMs";
|
|
34
|
+
"required": false;
|
|
35
|
+
"isSignal": true;
|
|
36
|
+
};
|
|
37
|
+
"lgfPaused": {
|
|
38
|
+
"alias": "lgfPaused";
|
|
39
|
+
"required": false;
|
|
40
|
+
"isSignal": true;
|
|
41
|
+
};
|
|
42
|
+
}, {
|
|
43
|
+
"lgfError": "lgfError";
|
|
44
|
+
}, never, never, true, never>;
|
|
45
|
+
}
|
|
46
|
+
/** Angular owns the custom host, decorative canvas and projected semantic DOM. */
|
|
47
|
+
export declare class GlassSurfaceComponent {
|
|
48
|
+
readonly material: import("@angular/core").InputSignal<GlassMaterial>;
|
|
49
|
+
private readonly canvas;
|
|
50
|
+
private readonly host;
|
|
51
|
+
private readonly parent;
|
|
52
|
+
private readonly zone;
|
|
53
|
+
private readonly destroy;
|
|
54
|
+
private readonly binding;
|
|
55
|
+
private ready;
|
|
56
|
+
private viewReady;
|
|
57
|
+
constructor();
|
|
58
|
+
ngAfterViewInit(): void;
|
|
59
|
+
get element(): HTMLElement;
|
|
60
|
+
get target(): HTMLCanvasElement | undefined;
|
|
61
|
+
invalidate(): void;
|
|
62
|
+
private refresh;
|
|
63
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<GlassSurfaceComponent, never>;
|
|
64
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<GlassSurfaceComponent, "lgf-surface", ["lgfSurface"], {
|
|
65
|
+
"material": {
|
|
66
|
+
"alias": "material";
|
|
67
|
+
"required": false;
|
|
68
|
+
"isSignal": true;
|
|
69
|
+
};
|
|
70
|
+
}, {}, never, ["*"], true, never>;
|
|
71
|
+
}
|
|
72
|
+
/** Bind a caller-template-owned direct canvas child; never create or move nodes. */
|
|
73
|
+
export declare class GlassSurfaceDirective {
|
|
74
|
+
readonly lgfTarget: import("@angular/core").InputSignal<HTMLCanvasElement>;
|
|
75
|
+
readonly lgfMaterial: import("@angular/core").InputSignal<GlassMaterial>;
|
|
76
|
+
private readonly host;
|
|
77
|
+
private readonly parent;
|
|
78
|
+
private readonly zone;
|
|
79
|
+
private readonly destroy;
|
|
80
|
+
private readonly binding;
|
|
81
|
+
private ready;
|
|
82
|
+
private viewReady;
|
|
83
|
+
constructor();
|
|
84
|
+
ngAfterViewInit(): void;
|
|
85
|
+
get element(): HTMLElement;
|
|
86
|
+
get target(): HTMLCanvasElement;
|
|
87
|
+
invalidate(): void;
|
|
88
|
+
private refresh;
|
|
89
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<GlassSurfaceDirective, never>;
|
|
90
|
+
static ɵdir: i0.ɵɵDirectiveDeclaration<GlassSurfaceDirective, "[lgfSurface]", ["lgfSurface"], {
|
|
91
|
+
"lgfTarget": {
|
|
92
|
+
"alias": "lgfTarget";
|
|
93
|
+
"required": true;
|
|
94
|
+
"isSignal": true;
|
|
95
|
+
};
|
|
96
|
+
"lgfMaterial": {
|
|
97
|
+
"alias": "lgfMaterial";
|
|
98
|
+
"required": false;
|
|
99
|
+
"isSignal": true;
|
|
100
|
+
};
|
|
101
|
+
}, {}, never, never, true, never>;
|
|
102
|
+
}
|