@czap/astro 0.1.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 (159) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +19 -0
  3. package/dist/Satellite.d.ts +42 -0
  4. package/dist/Satellite.d.ts.map +1 -0
  5. package/dist/Satellite.js +55 -0
  6. package/dist/Satellite.js.map +1 -0
  7. package/dist/client-directives/gpu.d.ts +3 -0
  8. package/dist/client-directives/gpu.d.ts.map +1 -0
  9. package/dist/client-directives/gpu.js +5 -0
  10. package/dist/client-directives/gpu.js.map +1 -0
  11. package/dist/client-directives/llm.d.ts +3 -0
  12. package/dist/client-directives/llm.d.ts.map +1 -0
  13. package/dist/client-directives/llm.js +5 -0
  14. package/dist/client-directives/llm.js.map +1 -0
  15. package/dist/client-directives/satellite.d.ts +3 -0
  16. package/dist/client-directives/satellite.d.ts.map +1 -0
  17. package/dist/client-directives/satellite.js +5 -0
  18. package/dist/client-directives/satellite.js.map +1 -0
  19. package/dist/client-directives/stream.d.ts +3 -0
  20. package/dist/client-directives/stream.d.ts.map +1 -0
  21. package/dist/client-directives/stream.js +5 -0
  22. package/dist/client-directives/stream.js.map +1 -0
  23. package/dist/client-directives/wasm.d.ts +3 -0
  24. package/dist/client-directives/wasm.d.ts.map +1 -0
  25. package/dist/client-directives/wasm.js +6 -0
  26. package/dist/client-directives/wasm.js.map +1 -0
  27. package/dist/client-directives/worker.d.ts +3 -0
  28. package/dist/client-directives/worker.d.ts.map +1 -0
  29. package/dist/client-directives/worker.js +5 -0
  30. package/dist/client-directives/worker.js.map +1 -0
  31. package/dist/detect-upgrade.d.ts +16 -0
  32. package/dist/detect-upgrade.d.ts.map +1 -0
  33. package/dist/detect-upgrade.js +105 -0
  34. package/dist/detect-upgrade.js.map +1 -0
  35. package/dist/headers.d.ts +45 -0
  36. package/dist/headers.d.ts.map +1 -0
  37. package/dist/headers.js +64 -0
  38. package/dist/headers.js.map +1 -0
  39. package/dist/index.d.ts +30 -0
  40. package/dist/index.d.ts.map +1 -0
  41. package/dist/index.js +26 -0
  42. package/dist/index.js.map +1 -0
  43. package/dist/integration.d.ts +76 -0
  44. package/dist/integration.d.ts.map +1 -0
  45. package/dist/integration.js +240 -0
  46. package/dist/integration.js.map +1 -0
  47. package/dist/middleware.d.ts +69 -0
  48. package/dist/middleware.d.ts.map +1 -0
  49. package/dist/middleware.js +75 -0
  50. package/dist/middleware.js.map +1 -0
  51. package/dist/quantize.d.ts +50 -0
  52. package/dist/quantize.d.ts.map +1 -0
  53. package/dist/quantize.js +122 -0
  54. package/dist/quantize.js.map +1 -0
  55. package/dist/runtime/boundary.d.ts +123 -0
  56. package/dist/runtime/boundary.d.ts.map +1 -0
  57. package/dist/runtime/boundary.js +164 -0
  58. package/dist/runtime/boundary.js.map +1 -0
  59. package/dist/runtime/globals.d.ts +32 -0
  60. package/dist/runtime/globals.d.ts.map +1 -0
  61. package/dist/runtime/globals.js +45 -0
  62. package/dist/runtime/globals.js.map +1 -0
  63. package/dist/runtime/gpu.d.ts +15 -0
  64. package/dist/runtime/gpu.d.ts.map +1 -0
  65. package/dist/runtime/gpu.js +266 -0
  66. package/dist/runtime/gpu.js.map +1 -0
  67. package/dist/runtime/index.d.ts +7 -0
  68. package/dist/runtime/index.d.ts.map +1 -0
  69. package/dist/runtime/index.js +5 -0
  70. package/dist/runtime/index.js.map +1 -0
  71. package/dist/runtime/llm-receipt-tracker.d.ts +21 -0
  72. package/dist/runtime/llm-receipt-tracker.d.ts.map +1 -0
  73. package/dist/runtime/llm-receipt-tracker.js +60 -0
  74. package/dist/runtime/llm-receipt-tracker.js.map +1 -0
  75. package/dist/runtime/llm-render-pipeline.d.ts +89 -0
  76. package/dist/runtime/llm-render-pipeline.d.ts.map +1 -0
  77. package/dist/runtime/llm-render-pipeline.js +241 -0
  78. package/dist/runtime/llm-render-pipeline.js.map +1 -0
  79. package/dist/runtime/llm-session.d.ts +126 -0
  80. package/dist/runtime/llm-session.d.ts.map +1 -0
  81. package/dist/runtime/llm-session.js +385 -0
  82. package/dist/runtime/llm-session.js.map +1 -0
  83. package/dist/runtime/llm.d.ts +16 -0
  84. package/dist/runtime/llm.d.ts.map +1 -0
  85. package/dist/runtime/llm.js +273 -0
  86. package/dist/runtime/llm.js.map +1 -0
  87. package/dist/runtime/policy.d.ts +100 -0
  88. package/dist/runtime/policy.d.ts.map +1 -0
  89. package/dist/runtime/policy.js +147 -0
  90. package/dist/runtime/policy.js.map +1 -0
  91. package/dist/runtime/receipt-chain.d.ts +22 -0
  92. package/dist/runtime/receipt-chain.d.ts.map +1 -0
  93. package/dist/runtime/receipt-chain.js +80 -0
  94. package/dist/runtime/receipt-chain.js.map +1 -0
  95. package/dist/runtime/runtime-session.d.ts +34 -0
  96. package/dist/runtime/runtime-session.d.ts.map +1 -0
  97. package/dist/runtime/runtime-session.js +102 -0
  98. package/dist/runtime/runtime-session.js.map +1 -0
  99. package/dist/runtime/satellite.d.ts +13 -0
  100. package/dist/runtime/satellite.d.ts.map +1 -0
  101. package/dist/runtime/satellite.js +59 -0
  102. package/dist/runtime/satellite.js.map +1 -0
  103. package/dist/runtime/slots.d.ts +34 -0
  104. package/dist/runtime/slots.d.ts.map +1 -0
  105. package/dist/runtime/slots.js +108 -0
  106. package/dist/runtime/slots.js.map +1 -0
  107. package/dist/runtime/stream-session.d.ts +47 -0
  108. package/dist/runtime/stream-session.d.ts.map +1 -0
  109. package/dist/runtime/stream-session.js +82 -0
  110. package/dist/runtime/stream-session.js.map +1 -0
  111. package/dist/runtime/stream.d.ts +9 -0
  112. package/dist/runtime/stream.d.ts.map +1 -0
  113. package/dist/runtime/stream.js +308 -0
  114. package/dist/runtime/stream.js.map +1 -0
  115. package/dist/runtime/url-policy.d.ts +28 -0
  116. package/dist/runtime/url-policy.d.ts.map +1 -0
  117. package/dist/runtime/url-policy.js +87 -0
  118. package/dist/runtime/url-policy.js.map +1 -0
  119. package/dist/runtime/wasm.d.ts +20 -0
  120. package/dist/runtime/wasm.d.ts.map +1 -0
  121. package/dist/runtime/wasm.js +70 -0
  122. package/dist/runtime/wasm.js.map +1 -0
  123. package/dist/runtime/worker.d.ts +11 -0
  124. package/dist/runtime/worker.d.ts.map +1 -0
  125. package/dist/runtime/worker.js +249 -0
  126. package/dist/runtime/worker.js.map +1 -0
  127. package/package.json +106 -0
  128. package/src/Satellite.astro +39 -0
  129. package/src/Satellite.ts +84 -0
  130. package/src/client-directives/gpu.ts +5 -0
  131. package/src/client-directives/llm.ts +5 -0
  132. package/src/client-directives/satellite.ts +5 -0
  133. package/src/client-directives/stream.ts +5 -0
  134. package/src/client-directives/wasm.ts +6 -0
  135. package/src/client-directives/worker.ts +5 -0
  136. package/src/detect-upgrade.ts +105 -0
  137. package/src/headers.ts +84 -0
  138. package/src/index.ts +30 -0
  139. package/src/integration.ts +309 -0
  140. package/src/middleware.ts +133 -0
  141. package/src/quantize.ts +173 -0
  142. package/src/runtime/boundary.ts +263 -0
  143. package/src/runtime/globals.ts +57 -0
  144. package/src/runtime/gpu.ts +291 -0
  145. package/src/runtime/index.ts +12 -0
  146. package/src/runtime/llm-receipt-tracker.ts +88 -0
  147. package/src/runtime/llm-render-pipeline.ts +366 -0
  148. package/src/runtime/llm-session.ts +548 -0
  149. package/src/runtime/llm.ts +344 -0
  150. package/src/runtime/policy.ts +229 -0
  151. package/src/runtime/receipt-chain.ts +106 -0
  152. package/src/runtime/runtime-session.ts +139 -0
  153. package/src/runtime/satellite.ts +80 -0
  154. package/src/runtime/slots.ts +136 -0
  155. package/src/runtime/stream-session.ts +125 -0
  156. package/src/runtime/stream.ts +407 -0
  157. package/src/runtime/url-policy.ts +107 -0
  158. package/src/runtime/wasm.ts +85 -0
  159. package/src/runtime/worker.ts +307 -0
@@ -0,0 +1,123 @@
1
+ /**
2
+ * Client-runtime helpers for parsing serialized boundaries out of
3
+ * `data-czap-boundary` attributes, attaching viewport observers,
4
+ * evaluating boundaries live, and applying the resulting state to a
5
+ * satellite element.
6
+ *
7
+ * Consumed by the Astro `client:satellite` / `client:worker` directives
8
+ * when they hydrate a server-rendered `<div data-czap-boundary="...">`.
9
+ *
10
+ * @module
11
+ */
12
+ import { Boundary } from '@czap/core';
13
+ /**
14
+ * JSON shape produced on the server by `satelliteAttrs()` and read back
15
+ * on the client via {@link parseBoundary}. Every field corresponds
16
+ * directly to a {@link Boundary.Shape} input.
17
+ */
18
+ export interface SerializedBoundary {
19
+ /** Optional stable boundary id (becomes the runtime `name`). */
20
+ readonly id?: string;
21
+ /** Signal key this boundary consumes (e.g. `"viewport.width"`). */
22
+ readonly input: string;
23
+ /** Ordered ascending thresholds (`thresholds[i]` lower bound of `states[i]`). */
24
+ readonly thresholds: readonly number[];
25
+ /** Non-empty ordered state labels. */
26
+ readonly states: readonly [string, ...string[]];
27
+ /** Optional hysteresis band applied during evaluation. */
28
+ readonly hysteresis?: number;
29
+ }
30
+ /**
31
+ * Client-side representation of a parsed boundary plus its resolved
32
+ * runtime name, ready to be evaluated against a live signal.
33
+ */
34
+ export interface RuntimeBoundary {
35
+ /** Resolved boundary name (defaults to `"default"`). */
36
+ readonly name: string;
37
+ /** Signal key this boundary consumes. */
38
+ readonly input: string;
39
+ /** Fully-constructed `Boundary.Shape` ready for evaluation. */
40
+ readonly boundary: Boundary.Shape<string, readonly [string, ...string[]]>;
41
+ }
42
+ /**
43
+ * Normalised boundary-state payload used for `CustomEvent` dispatch and
44
+ * DOM application. CSS keys are filtered to `--czap-*`; ARIA keys to
45
+ * `role` / `aria-*`.
46
+ */
47
+ export interface BoundaryStateDetail {
48
+ /** Discrete state per quantizer name. */
49
+ readonly discrete: Record<string, string>;
50
+ /** Whitelisted `--czap-*` CSS variable map. */
51
+ readonly css: Record<string, string | number>;
52
+ /** GLSL uniform map (`u_*`). */
53
+ readonly glsl: Record<string, number>;
54
+ /** Whitelisted ARIA attribute map. */
55
+ readonly aria: Record<string, string>;
56
+ }
57
+ /**
58
+ * Parse a JSON-serialised boundary (as produced by
59
+ * `satelliteAttrs()`) into a {@link RuntimeBoundary}. Returns `null`
60
+ * for malformed or structurally invalid payloads so callers can fall
61
+ * back cleanly rather than throwing mid-hydration.
62
+ */
63
+ export declare function parseBoundary(boundaryJson: string | null): RuntimeBoundary | null;
64
+ /**
65
+ * Attach a ResizeObserver on `document.documentElement` that calls `callback`
66
+ * whenever the viewport resizes, but only when `input` is a viewport signal
67
+ * (i.e. starts with `"viewport."`) and `ResizeObserver` is available.
68
+ *
69
+ * Returns a cleanup function that disconnects the observer, or `null` when no
70
+ * observer was attached (non-viewport input or no ResizeObserver support).
71
+ *
72
+ * Centralises the identical `observeIfNeeded` blocks that previously lived in
73
+ * satellite.ts and worker.ts.
74
+ */
75
+ export declare function attachViewportObserver(input: string, callback: () => void): (() => void) | null;
76
+ /**
77
+ * Read the current numeric value for a signal `input` (e.g.
78
+ * `"viewport.width"`). Returns `undefined` for unknown inputs; returns
79
+ * `0` in non-DOM environments so callers can treat SSR and malformed
80
+ * signals uniformly.
81
+ */
82
+ export declare function readSignalValue(input: string): number | undefined;
83
+ /**
84
+ * Evaluate a {@link RuntimeBoundary} against a signal value, applying
85
+ * hysteresis when `previousState` is provided and the boundary has a
86
+ * hysteresis band.
87
+ */
88
+ export declare function evaluateBoundary(boundary: RuntimeBoundary, value: number, previousState?: string): string;
89
+ /**
90
+ * Merge `state.*` and `state.outputs.*` fields into a single
91
+ * {@link BoundaryStateDetail}, filtering CSS keys to `--czap-*` and
92
+ * ARIA keys to `role` / `aria-*`. Used as the `detail` of the
93
+ * `czap:state` custom event.
94
+ */
95
+ export declare function normalizeBoundaryState(state: {
96
+ readonly discrete?: Record<string, string>;
97
+ readonly css?: Record<string, string | number>;
98
+ readonly glsl?: Record<string, number>;
99
+ readonly aria?: Record<string, string>;
100
+ readonly outputs?: {
101
+ readonly css?: Record<string, string | number>;
102
+ readonly glsl?: Record<string, number>;
103
+ readonly aria?: Record<string, string>;
104
+ };
105
+ }): BoundaryStateDetail;
106
+ /**
107
+ * Apply a normalised state to a satellite element: sets
108
+ * `data-czap-state`, writes whitelisted CSS variables and ARIA
109
+ * attributes, and dispatches `eventName` + `czap:uniform-update`
110
+ * custom events for downstream listeners (GPU/WASM runtimes).
111
+ */
112
+ export declare function applyBoundaryState(element: HTMLElement, boundary: RuntimeBoundary, state: {
113
+ readonly discrete?: Record<string, string>;
114
+ readonly css?: Record<string, string | number>;
115
+ readonly glsl?: Record<string, number>;
116
+ readonly aria?: Record<string, string>;
117
+ readonly outputs?: {
118
+ readonly css?: Record<string, string | number>;
119
+ readonly glsl?: Record<string, number>;
120
+ readonly aria?: Record<string, string>;
121
+ };
122
+ }, eventName: string): void;
123
+ //# sourceMappingURL=boundary.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"boundary.d.ts","sourceRoot":"","sources":["../../src/runtime/boundary.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,164 @@
1
+ /**
2
+ * Client-runtime helpers for parsing serialized boundaries out of
3
+ * `data-czap-boundary` attributes, attaching viewport observers,
4
+ * evaluating boundaries live, and applying the resulting state to a
5
+ * satellite element.
6
+ *
7
+ * Consumed by the Astro `client:satellite` / `client:worker` directives
8
+ * when they hydrate a server-rendered `<div data-czap-boundary="...">`.
9
+ *
10
+ * @module
11
+ */
12
+ import { Boundary } from '@czap/core';
13
+ function isAllowedBoundaryCssProperty(property) {
14
+ return property.startsWith('--czap-');
15
+ }
16
+ // NOTE: This logic is intentionally duplicated from `isValidAriaKey` in
17
+ // packages/compiler/src/aria.ts. @czap/astro does not depend on @czap/compiler,
18
+ // so the check cannot be shared without introducing a new dependency. Keep the
19
+ // two implementations in sync if either changes.
20
+ function isAllowedBoundaryAttribute(attribute) {
21
+ return attribute === 'role' || attribute.startsWith('aria-');
22
+ }
23
+ function parseBoundaryPayload(boundaryJson) {
24
+ let parsed = null;
25
+ let malformed = false;
26
+ try {
27
+ parsed = JSON.parse(boundaryJson);
28
+ }
29
+ catch (error) {
30
+ if (error instanceof SyntaxError) {
31
+ malformed = true;
32
+ }
33
+ else {
34
+ throw error;
35
+ }
36
+ }
37
+ return malformed ? null : parsed;
38
+ }
39
+ /**
40
+ * Parse a JSON-serialised boundary (as produced by
41
+ * `satelliteAttrs()`) into a {@link RuntimeBoundary}. Returns `null`
42
+ * for malformed or structurally invalid payloads so callers can fall
43
+ * back cleanly rather than throwing mid-hydration.
44
+ */
45
+ export function parseBoundary(boundaryJson) {
46
+ if (!boundaryJson) {
47
+ return null;
48
+ }
49
+ const parsed = parseBoundaryPayload(boundaryJson);
50
+ if (!parsed) {
51
+ return null;
52
+ }
53
+ if (typeof parsed.input !== 'string' ||
54
+ !Array.isArray(parsed.thresholds) ||
55
+ parsed.thresholds.length === 0 ||
56
+ !Array.isArray(parsed.states) ||
57
+ parsed.states.length === 0 ||
58
+ !parsed.thresholds.every((value) => typeof value === 'number') ||
59
+ !parsed.states.every((value) => typeof value === 'string')) {
60
+ return null;
61
+ }
62
+ const states = parsed.states;
63
+ const first = [parsed.thresholds[0], states[0]];
64
+ const rest = parsed.thresholds.slice(1).map((threshold, index) => [threshold, states[index + 1]]);
65
+ const at = [first, ...rest];
66
+ return {
67
+ name: parsed.id ?? 'default',
68
+ input: parsed.input,
69
+ boundary: Boundary.make({
70
+ input: parsed.input,
71
+ at,
72
+ ...(typeof parsed.hysteresis === 'number' ? { hysteresis: parsed.hysteresis } : {}),
73
+ }),
74
+ };
75
+ }
76
+ /**
77
+ * Attach a ResizeObserver on `document.documentElement` that calls `callback`
78
+ * whenever the viewport resizes, but only when `input` is a viewport signal
79
+ * (i.e. starts with `"viewport."`) and `ResizeObserver` is available.
80
+ *
81
+ * Returns a cleanup function that disconnects the observer, or `null` when no
82
+ * observer was attached (non-viewport input or no ResizeObserver support).
83
+ *
84
+ * Centralises the identical `observeIfNeeded` blocks that previously lived in
85
+ * satellite.ts and worker.ts.
86
+ */
87
+ export function attachViewportObserver(input, callback) {
88
+ if (!input.startsWith('viewport.') || typeof ResizeObserver === 'undefined') {
89
+ return null;
90
+ }
91
+ const observer = new ResizeObserver(callback);
92
+ observer.observe(document.documentElement);
93
+ return () => observer.disconnect();
94
+ }
95
+ /**
96
+ * Read the current numeric value for a signal `input` (e.g.
97
+ * `"viewport.width"`). Returns `undefined` for unknown inputs; returns
98
+ * `0` in non-DOM environments so callers can treat SSR and malformed
99
+ * signals uniformly.
100
+ */
101
+ export function readSignalValue(input) {
102
+ if (typeof window === 'undefined')
103
+ return 0;
104
+ if (!input.startsWith('viewport.')) {
105
+ return undefined;
106
+ }
107
+ const axis = input.slice('viewport.'.length);
108
+ return axis === 'height' ? window.innerHeight : window.innerWidth;
109
+ }
110
+ /**
111
+ * Evaluate a {@link RuntimeBoundary} against a signal value, applying
112
+ * hysteresis when `previousState` is provided and the boundary has a
113
+ * hysteresis band.
114
+ */
115
+ export function evaluateBoundary(boundary, value, previousState) {
116
+ if (previousState && boundary.boundary.hysteresis) {
117
+ return Boundary.evaluateWithHysteresis(boundary.boundary, value, previousState);
118
+ }
119
+ return Boundary.evaluate(boundary.boundary, value);
120
+ }
121
+ /**
122
+ * Merge `state.*` and `state.outputs.*` fields into a single
123
+ * {@link BoundaryStateDetail}, filtering CSS keys to `--czap-*` and
124
+ * ARIA keys to `role` / `aria-*`. Used as the `detail` of the
125
+ * `czap:state` custom event.
126
+ */
127
+ export function normalizeBoundaryState(state) {
128
+ const css = { ...(state.outputs?.css ?? {}), ...(state.css ?? {}) };
129
+ const aria = { ...(state.outputs?.aria ?? {}), ...(state.aria ?? {}) };
130
+ return {
131
+ discrete: { ...(state.discrete ?? {}) },
132
+ css: Object.fromEntries(Object.entries(css).filter(([property]) => isAllowedBoundaryCssProperty(property))),
133
+ glsl: { ...(state.outputs?.glsl ?? {}), ...(state.glsl ?? {}) },
134
+ aria: Object.fromEntries(Object.entries(aria).filter(([attribute]) => isAllowedBoundaryAttribute(attribute))),
135
+ };
136
+ }
137
+ /**
138
+ * Apply a normalised state to a satellite element: sets
139
+ * `data-czap-state`, writes whitelisted CSS variables and ARIA
140
+ * attributes, and dispatches `eventName` + `czap:uniform-update`
141
+ * custom events for downstream listeners (GPU/WASM runtimes).
142
+ */
143
+ export function applyBoundaryState(element, boundary, state, eventName) {
144
+ const detail = normalizeBoundaryState(state);
145
+ const stateName = detail.discrete[boundary.name];
146
+ if (stateName && element.getAttribute('data-czap-state') !== stateName) {
147
+ element.setAttribute('data-czap-state', stateName);
148
+ }
149
+ for (const [property, value] of Object.entries(detail.css)) {
150
+ element.style.setProperty(property, String(value));
151
+ }
152
+ for (const [attribute, value] of Object.entries(detail.aria)) {
153
+ element.setAttribute(attribute, value);
154
+ }
155
+ element.dispatchEvent(new CustomEvent(eventName, {
156
+ detail,
157
+ bubbles: true,
158
+ }));
159
+ element.dispatchEvent(new CustomEvent('czap:uniform-update', {
160
+ detail,
161
+ bubbles: true,
162
+ }));
163
+ }
164
+ //# sourceMappingURL=boundary.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"boundary.js","sourceRoot":"","sources":["../../src/runtime/boundary.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAiDtC,SAAS,4BAA4B,CAAC,QAAgB;IACpD,OAAO,QAAQ,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;AACxC,CAAC;AAED,wEAAwE;AACxE,gFAAgF;AAChF,+EAA+E;AAC/E,iDAAiD;AACjD,SAAS,0BAA0B,CAAC,SAAiB;IACnD,OAAO,SAAS,KAAK,MAAM,IAAI,SAAS,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;AAC/D,CAAC;AAED,SAAS,oBAAoB,CAAC,YAAoB;IAChD,IAAI,MAAM,GAAuC,IAAI,CAAC;IACtD,IAAI,SAAS,GAAG,KAAK,CAAC;IAEtB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAgC,CAAC;IACnE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,WAAW,EAAE,CAAC;YACjC,SAAS,GAAG,IAAI,CAAC;QACnB,CAAC;aAAM,CAAC;YACN,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED,OAAO,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC;AACnC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,YAA2B;IACvD,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,MAAM,GAAG,oBAAoB,CAAC,YAAY,CAAC,CAAC;IAClD,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IACE,OAAO,MAAM,CAAC,KAAK,KAAK,QAAQ;QAChC,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC;QACjC,MAAM,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC;QAC9B,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC;QAC7B,MAAM,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC;QAC1B,CAAC,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC;QAC9D,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC,EAC1D,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,CAAC,MAAwC,CAAC;IAC/D,MAAM,KAAK,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAE,EAAE,MAAM,CAAC,CAAC,CAAC,CAAU,CAAC;IAC1D,MAAM,IAAI,GAAG,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,SAAS,EAAE,MAAM,CAAC,KAAK,GAAG,CAAC,CAAE,CAAU,CAAC,CAAC;IAC5G,MAAM,EAAE,GAAG,CAAC,KAAK,EAAE,GAAG,IAAI,CAAU,CAAC;IAErC,OAAO;QACL,IAAI,EAAE,MAAM,CAAC,EAAE,IAAI,SAAS;QAC5B,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,QAAQ,EAAE,QAAQ,CAAC,IAAI,CAAC;YACtB,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,EAAE;YACF,GAAG,CAAC,OAAO,MAAM,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACpF,CAAC;KACH,CAAC;AACJ,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,sBAAsB,CAAC,KAAa,EAAE,QAAoB;IACxE,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,WAAW,CAAC,IAAI,OAAO,cAAc,KAAK,WAAW,EAAE,CAAC;QAC5E,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,QAAQ,GAAG,IAAI,cAAc,CAAC,QAAQ,CAAC,CAAC;IAC9C,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC;IAC3C,OAAO,GAAG,EAAE,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC;AACrC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,KAAa;IAC3C,IAAI,OAAO,MAAM,KAAK,WAAW;QAAE,OAAO,CAAC,CAAC;IAE5C,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QACnC,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;IAC7C,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC;AACpE,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,QAAyB,EAAE,KAAa,EAAE,aAAsB;IAC/F,IAAI,aAAa,IAAI,QAAQ,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC;QAClD,OAAO,QAAQ,CAAC,sBAAsB,CAAC,QAAQ,CAAC,QAAQ,EAAE,KAAK,EAAE,aAAa,CAAC,CAAC;IAClF,CAAC;IAED,OAAO,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;AACrD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,sBAAsB,CAAC,KAUtC;IACC,MAAM,GAAG,GAAG,EAAE,GAAG,CAAC,KAAK,CAAC,OAAO,EAAE,GAAG,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,KAAK,CAAC,GAAG,IAAI,EAAE,CAAC,EAAE,CAAC;IACpE,MAAM,IAAI,GAAG,EAAE,GAAG,CAAC,KAAK,CAAC,OAAO,EAAE,IAAI,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,KAAK,CAAC,IAAI,IAAI,EAAE,CAAC,EAAE,CAAC;IAEvE,OAAO;QACL,QAAQ,EAAE,EAAE,GAAG,CAAC,KAAK,CAAC,QAAQ,IAAI,EAAE,CAAC,EAAE;QACvC,GAAG,EAAE,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC,4BAA4B,CAAC,QAAQ,CAAC,CAAC,CAAC;QAC3G,IAAI,EAAE,EAAE,GAAG,CAAC,KAAK,CAAC,OAAO,EAAE,IAAI,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,KAAK,CAAC,IAAI,IAAI,EAAE,CAAC,EAAE;QAC/D,IAAI,EAAE,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,EAAE,EAAE,CAAC,0BAA0B,CAAC,SAAS,CAAC,CAAC,CAAC;KAC9G,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAChC,OAAoB,EACpB,QAAyB,EACzB,KAUC,EACD,SAAiB;IAEjB,MAAM,MAAM,GAAG,sBAAsB,CAAC,KAAK,CAAC,CAAC;IAC7C,MAAM,SAAS,GAAG,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAEjD,IAAI,SAAS,IAAI,OAAO,CAAC,YAAY,CAAC,iBAAiB,CAAC,KAAK,SAAS,EAAE,CAAC;QACvE,OAAO,CAAC,YAAY,CAAC,iBAAiB,EAAE,SAAS,CAAC,CAAC;IACrD,CAAC;IAED,KAAK,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;QAC3D,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,QAAQ,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IACrD,CAAC;IAED,KAAK,MAAM,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;QAC7D,OAAO,CAAC,YAAY,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IACzC,CAAC;IAED,OAAO,CAAC,aAAa,CACnB,IAAI,WAAW,CAAC,SAAS,EAAE;QACzB,MAAM;QACN,OAAO,EAAE,IAAI;KACd,CAAC,CACH,CAAC;IAEF,OAAO,CAAC,aAAa,CACnB,IAAI,WAAW,CAAC,qBAAqB,EAAE;QACrC,MAAM;QACN,OAAO,EAAE,IAAI;KACd,CAAC,CACH,CAAC;AACJ,CAAC"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Safe read/write helpers for named `window` globals used as runtime
3
+ * handshake points between inline detect scripts and the hydrated
4
+ * runtime (e.g. `__CZAP_DETECT__`, `__CZAP_SLOTS__`). Works on both
5
+ * client and server entry paths -- returns `undefined` under SSR.
6
+ *
7
+ * @module
8
+ */
9
+ declare global {
10
+ interface Window {
11
+ [key: string]: unknown;
12
+ }
13
+ }
14
+ /**
15
+ * Read a named `window` global, narrowed through `guard`. Returns
16
+ * `undefined` under SSR or when the guard rejects the runtime value.
17
+ */
18
+ export declare function readRuntimeGlobal<T>(name: string, guard: (v: unknown) => v is T): T | undefined;
19
+ /**
20
+ * Write a named `window` global as a non-enumerable property.
21
+ *
22
+ * `options.writable` defaults to `false` so the value is lock-down by default.
23
+ * `options.configurable` defaults to `true` so HMR and bootstrap re-runs can
24
+ * replace the global; security-critical globals (e.g. `__CZAP_RUNTIME_POLICY__`)
25
+ * should pass `configurable: false` to prevent post-install redefinition by
26
+ * any later script on the page.
27
+ */
28
+ export declare function writeRuntimeGlobal<T>(name: string, value: T, options?: {
29
+ readonly writable?: boolean;
30
+ readonly configurable?: boolean;
31
+ }): T;
32
+ //# sourceMappingURL=globals.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"globals.d.ts","sourceRoot":"","sources":["../../src/runtime/globals.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;KACxB;CACF;AAMD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,SAAS,CAK/F;AAED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,EAClC,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,CAAC,EACR,OAAO,CAAC,EAAE;IAAE,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,CAAA;CAAE,GACzE,CAAC,CAaH"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Safe read/write helpers for named `window` globals used as runtime
3
+ * handshake points between inline detect scripts and the hydrated
4
+ * runtime (e.g. `__CZAP_DETECT__`, `__CZAP_SLOTS__`). Works on both
5
+ * client and server entry paths -- returns `undefined` under SSR.
6
+ *
7
+ * @module
8
+ */
9
+ function runtimeWindow() {
10
+ return typeof window === 'undefined' ? null : window;
11
+ }
12
+ /**
13
+ * Read a named `window` global, narrowed through `guard`. Returns
14
+ * `undefined` under SSR or when the guard rejects the runtime value.
15
+ */
16
+ export function readRuntimeGlobal(name, guard) {
17
+ const win = runtimeWindow();
18
+ if (!win)
19
+ return undefined;
20
+ const raw = win[name];
21
+ return guard(raw) ? raw : undefined;
22
+ }
23
+ /**
24
+ * Write a named `window` global as a non-enumerable property.
25
+ *
26
+ * `options.writable` defaults to `false` so the value is lock-down by default.
27
+ * `options.configurable` defaults to `true` so HMR and bootstrap re-runs can
28
+ * replace the global; security-critical globals (e.g. `__CZAP_RUNTIME_POLICY__`)
29
+ * should pass `configurable: false` to prevent post-install redefinition by
30
+ * any later script on the page.
31
+ */
32
+ export function writeRuntimeGlobal(name, value, options) {
33
+ const win = runtimeWindow();
34
+ if (!win) {
35
+ return value;
36
+ }
37
+ Object.defineProperty(win, name, {
38
+ value,
39
+ configurable: options?.configurable ?? true,
40
+ enumerable: false,
41
+ writable: options?.writable ?? false,
42
+ });
43
+ return value;
44
+ }
45
+ //# sourceMappingURL=globals.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"globals.js","sourceRoot":"","sources":["../../src/runtime/globals.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAQH,SAAS,aAAa;IACpB,OAAO,OAAO,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC;AACvD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAI,IAAY,EAAE,KAA6B;IAC9E,MAAM,GAAG,GAAG,aAAa,EAAE,CAAC;IAC5B,IAAI,CAAC,GAAG;QAAE,OAAO,SAAS,CAAC;IAC3B,MAAM,GAAG,GAAY,GAAG,CAAC,IAAI,CAAC,CAAC;IAC/B,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC;AACtC,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,kBAAkB,CAChC,IAAY,EACZ,KAAQ,EACR,OAA0E;IAE1E,MAAM,GAAG,GAAG,aAAa,EAAE,CAAC;IAC5B,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,CAAC,cAAc,CAAC,GAAG,EAAE,IAAI,EAAE;QAC/B,KAAK;QACL,YAAY,EAAE,OAAO,EAAE,YAAY,IAAI,IAAI;QAC3C,UAAU,EAAE,KAAK;QACjB,QAAQ,EAAE,OAAO,EAAE,QAAQ,IAAI,KAAK;KACrC,CAAC,CAAC;IACH,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Entry point used by the `client:gpu` directive to wire a
3
+ * satellite element to a WebGL shader.
4
+ *
5
+ * Reads `data-czap-shader-type` / `data-czap-shader-src` off the
6
+ * element, fetches and compiles the program, then subscribes to
7
+ * `czap:uniform-update` events so each boundary transition updates the
8
+ * shader uniforms.
9
+ *
10
+ * @param load - Dynamic-import factory the directive passes in (kept
11
+ * async so the expensive GPU module is code-split).
12
+ * @param el - Satellite element carrying the shader attributes.
13
+ */
14
+ export declare function initGPUDirective(load: () => Promise<unknown>, el: HTMLElement): void;
15
+ //# sourceMappingURL=gpu.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gpu.d.ts","sourceRoot":"","sources":["../../src/runtime/gpu.ts"],"names":[],"mappings":"AA0DA;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,EAAE,EAAE,EAAE,WAAW,GAAG,IAAI,CA2NpF"}
@@ -0,0 +1,266 @@
1
+ import { Diagnostics, CANVAS_FALLBACK_WIDTH, CANVAS_FALLBACK_HEIGHT } from '@czap/core';
2
+ import { readRuntimeEndpointPolicy } from './policy.js';
3
+ import { allowRuntimeEndpointUrl } from './url-policy.js';
4
+ const DEFAULT_VERTEX_SHADER = `#version 300 es
5
+ precision mediump float;
6
+ in vec2 a_position;
7
+ out vec2 v_uv;
8
+ void main() {
9
+ v_uv = a_position * 0.5 + 0.5;
10
+ gl_Position = vec4(a_position, 0.0, 1.0);
11
+ }`;
12
+ const FULLSCREEN_QUAD = new Float32Array([-1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1]);
13
+ function compileShader(gl, type, source) {
14
+ const shader = gl.createShader(type);
15
+ if (!shader)
16
+ return null;
17
+ gl.shaderSource(shader, source);
18
+ gl.compileShader(shader);
19
+ if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
20
+ Diagnostics.warn({
21
+ source: 'czap/astro.gpu',
22
+ code: 'shader-compile-failed',
23
+ message: 'Shader compilation failed.',
24
+ detail: gl.getShaderInfoLog(shader),
25
+ });
26
+ gl.deleteShader(shader);
27
+ return null;
28
+ }
29
+ return shader;
30
+ }
31
+ function createProgram(gl, vertSrc, fragSrc) {
32
+ const vert = compileShader(gl, gl.VERTEX_SHADER, vertSrc);
33
+ const frag = compileShader(gl, gl.FRAGMENT_SHADER, fragSrc);
34
+ if (!vert || !frag)
35
+ return null;
36
+ const program = gl.createProgram();
37
+ if (!program)
38
+ return null;
39
+ gl.attachShader(program, vert);
40
+ gl.attachShader(program, frag);
41
+ gl.linkProgram(program);
42
+ if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
43
+ Diagnostics.warn({
44
+ source: 'czap/astro.gpu',
45
+ code: 'program-link-failed',
46
+ message: 'Shader program linking failed.',
47
+ detail: gl.getProgramInfoLog(program),
48
+ });
49
+ gl.deleteProgram(program);
50
+ return null;
51
+ }
52
+ return program;
53
+ }
54
+ /**
55
+ * Entry point used by the `client:gpu` directive to wire a
56
+ * satellite element to a WebGL shader.
57
+ *
58
+ * Reads `data-czap-shader-type` / `data-czap-shader-src` off the
59
+ * element, fetches and compiles the program, then subscribes to
60
+ * `czap:uniform-update` events so each boundary transition updates the
61
+ * shader uniforms.
62
+ *
63
+ * @param load - Dynamic-import factory the directive passes in (kept
64
+ * async so the expensive GPU module is code-split).
65
+ * @param el - Satellite element carrying the shader attributes.
66
+ */
67
+ export function initGPUDirective(load, el) {
68
+ const shaderType = el.getAttribute('data-czap-shader-type') ?? 'glsl';
69
+ const shaderSrc = allowRuntimeEndpointUrl(el.getAttribute('data-czap-shader-src'), 'gpu-shader', 'czap/astro.gpu', {
70
+ crossOriginRejected: 'shader-cross-origin-url-rejected',
71
+ malformedUrl: 'shader-malformed-url-rejected',
72
+ originNotAllowed: 'shader-origin-not-allowed',
73
+ endpointKindNotPermitted: 'shader-endpoint-kind-not-permitted',
74
+ }, readRuntimeEndpointPolicy());
75
+ const tier = document.documentElement.getAttribute('data-czap-tier') ?? 'reactive';
76
+ if (tier === 'static' || tier === 'styled') {
77
+ load();
78
+ return;
79
+ }
80
+ if (shaderType === 'wgsl') {
81
+ Diagnostics.warnOnce({
82
+ source: 'czap/astro.gpu',
83
+ code: 'wgsl-not-yet-supported',
84
+ message: 'WGSL shader directives are not yet wired into the Astro GPU runtime. Use WGSLCompiler directly for WGSL output.',
85
+ });
86
+ load();
87
+ return;
88
+ }
89
+ let canvas;
90
+ if (el instanceof HTMLCanvasElement) {
91
+ canvas = el;
92
+ }
93
+ else {
94
+ canvas = document.createElement('canvas');
95
+ canvas.width = el.clientWidth || CANVAS_FALLBACK_WIDTH;
96
+ canvas.height = el.clientHeight || CANVAS_FALLBACK_HEIGHT;
97
+ canvas.style.width = '100%';
98
+ canvas.style.height = '100%';
99
+ el.appendChild(canvas);
100
+ }
101
+ const gl = canvas.getContext('webgl2');
102
+ if (!gl) {
103
+ Diagnostics.warnOnce({
104
+ source: 'czap/astro.gpu',
105
+ code: 'webgl2-unavailable',
106
+ message: 'WebGL2 is unavailable; falling back to CSS rendering.',
107
+ });
108
+ load();
109
+ return;
110
+ }
111
+ const webgl = gl;
112
+ async function initShader() {
113
+ let fragSource;
114
+ if (shaderSrc && (shaderSrc.startsWith('/') || shaderSrc.startsWith('http'))) {
115
+ try {
116
+ const response = await fetch(shaderSrc);
117
+ if (!response.ok) {
118
+ Diagnostics.warn({
119
+ source: 'czap/astro.gpu',
120
+ code: 'shader-fetch-failed',
121
+ message: 'Failed to fetch shader source.',
122
+ detail: response.statusText,
123
+ });
124
+ return;
125
+ }
126
+ fragSource = await response.text();
127
+ }
128
+ catch (err) {
129
+ Diagnostics.warn({
130
+ source: 'czap/astro.gpu',
131
+ code: 'shader-fetch-threw',
132
+ message: 'Fetching shader source threw an error.',
133
+ cause: err,
134
+ });
135
+ return;
136
+ }
137
+ }
138
+ else if (shaderSrc) {
139
+ fragSource = shaderSrc;
140
+ }
141
+ else {
142
+ fragSource = `#version 300 es
143
+ precision mediump float;
144
+ in vec2 v_uv;
145
+ out vec4 fragColor;
146
+ uniform float u_state;
147
+ uniform float u_time;
148
+ void main() {
149
+ vec3 color = mix(vec3(0.2, 0.3, 0.8), vec3(0.8, 0.3, 0.2), u_state);
150
+ float bands = 4.0;
151
+ color = floor(color * bands) / bands;
152
+ fragColor = vec4(color, 1.0);
153
+ }`;
154
+ }
155
+ const program = createProgram(webgl, DEFAULT_VERTEX_SHADER, fragSource);
156
+ if (!program)
157
+ return;
158
+ webgl.useProgram(program);
159
+ const vao = webgl.createVertexArray();
160
+ webgl.bindVertexArray(vao);
161
+ const buffer = webgl.createBuffer();
162
+ webgl.bindBuffer(webgl.ARRAY_BUFFER, buffer);
163
+ webgl.bufferData(webgl.ARRAY_BUFFER, FULLSCREEN_QUAD, webgl.STATIC_DRAW);
164
+ const posLoc = webgl.getAttribLocation(program, 'a_position');
165
+ webgl.enableVertexAttribArray(posLoc);
166
+ webgl.vertexAttribPointer(posLoc, 2, webgl.FLOAT, false, 0, 0);
167
+ const uniforms = new Map();
168
+ const numUniforms = webgl.getProgramParameter(program, webgl.ACTIVE_UNIFORMS);
169
+ for (let i = 0; i < numUniforms; i++) {
170
+ const info = webgl.getActiveUniform(program, i);
171
+ if (info) {
172
+ const loc = webgl.getUniformLocation(program, info.name);
173
+ if (loc)
174
+ uniforms.set(info.name, loc);
175
+ }
176
+ }
177
+ const startTime = performance.now();
178
+ let animFrame = 0;
179
+ function render() {
180
+ const w = canvas.clientWidth;
181
+ const h = canvas.clientHeight;
182
+ if (canvas.width !== w || canvas.height !== h) {
183
+ canvas.width = w;
184
+ canvas.height = h;
185
+ webgl.viewport(0, 0, w, h);
186
+ }
187
+ const timeLoc = uniforms.get('u_time');
188
+ if (timeLoc) {
189
+ webgl.uniform1f(timeLoc, (performance.now() - startTime) / 1000);
190
+ }
191
+ const resLoc = uniforms.get('u_resolution');
192
+ if (resLoc) {
193
+ webgl.uniform2f(resLoc, w, h);
194
+ }
195
+ webgl.drawArrays(webgl.TRIANGLES, 0, 6);
196
+ animFrame = requestAnimationFrame(render);
197
+ }
198
+ const onElementUniformUpdate = (event) => {
199
+ /* v8 ignore next — `czap:uniform-update` is always dispatched via `new CustomEvent(...)`;
200
+ the guard narrows the generic `Event` parameter for TypeScript's typed `.detail` access. */
201
+ if (!(event instanceof CustomEvent))
202
+ return;
203
+ const detail = event.detail;
204
+ if (!detail)
205
+ return;
206
+ const boundaryJson = el.getAttribute('data-czap-boundary');
207
+ if (boundaryJson && detail.discrete) {
208
+ try {
209
+ const boundary = JSON.parse(boundaryJson);
210
+ const stateName = detail.discrete[boundary.id ?? 'default'];
211
+ if (stateName) {
212
+ const idx = boundary.states.indexOf(stateName);
213
+ const stateLoc = uniforms.get('u_state');
214
+ if (stateLoc && idx >= 0) {
215
+ webgl.uniform1f(stateLoc, idx / Math.max(1, boundary.states.length - 1));
216
+ }
217
+ }
218
+ }
219
+ catch {
220
+ Diagnostics.warnOnce({
221
+ source: 'czap/astro.gpu',
222
+ code: 'uniform-update-parse-failed',
223
+ message: 'Failed to parse boundary JSON during uniform update.',
224
+ });
225
+ }
226
+ }
227
+ if (detail.css) {
228
+ for (const [key, value] of Object.entries(detail.css)) {
229
+ const uniformName = key.replace('--czap-', 'u_').replace(/-/g, '_');
230
+ const loc = uniforms.get(uniformName);
231
+ if (loc && typeof value === 'string') {
232
+ const num = parseFloat(value);
233
+ if (!Number.isNaN(num)) {
234
+ webgl.uniform1f(loc, num);
235
+ }
236
+ }
237
+ }
238
+ }
239
+ };
240
+ const onDocumentUniformUpdate = (event) => {
241
+ /* v8 ignore next — `czap:uniform-update` is always dispatched via `new CustomEvent(...)`;
242
+ the guard narrows the generic `Event` parameter for TypeScript's typed `.detail` access. */
243
+ if (!(event instanceof CustomEvent))
244
+ return;
245
+ if (event.detail?.uniform && event.detail?.value !== undefined) {
246
+ const loc = uniforms.get(event.detail.uniform);
247
+ if (loc) {
248
+ webgl.uniform1f(loc, event.detail.value);
249
+ }
250
+ }
251
+ };
252
+ el.addEventListener('czap:uniform-update', onElementUniformUpdate);
253
+ document.addEventListener('czap:uniform-update', onDocumentUniformUpdate);
254
+ el.dispatchEvent(new CustomEvent('czap:gpu-ready', { bubbles: true }));
255
+ render();
256
+ el.addEventListener('czap:reinit', () => {
257
+ cancelAnimationFrame(animFrame);
258
+ el.removeEventListener('czap:uniform-update', onElementUniformUpdate);
259
+ document.removeEventListener('czap:uniform-update', onDocumentUniformUpdate);
260
+ webgl.deleteProgram(program);
261
+ });
262
+ }
263
+ void initShader();
264
+ load();
265
+ }
266
+ //# sourceMappingURL=gpu.js.map