create-octane-xplat 0.7.3 → 0.10.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 (30) hide show
  1. package/README.md +28 -8
  2. package/index.mjs +112 -14
  3. package/package.json +15 -8
  4. package/scaffold.mjs +531 -0
  5. package/template/.agents/skills/xplat/SKILL.md +109 -40
  6. package/template/.agents/skills/xplat/references/components.md +149 -96
  7. package/template/.agents/skills/xplat/references/navigation.md +81 -31
  8. package/template/.agents/skills/xplat/references/platform.md +74 -35
  9. package/template/.agents/skills/xplat/references/styling.md +80 -27
  10. package/template/AGENTS.md +1 -1
  11. package/template/package.json +11 -9
  12. package/template/pnpm-workspace.yaml +66 -33
  13. package/template/src/App.tsrx +17 -8
  14. package/template/src/process.d.ts +7 -0
  15. package/template/src/style.css +24 -6
  16. package/template/tsconfig.json +1 -1
  17. package/template/vite.config.native.mts +3 -2
  18. package/template/vite.config.ts +5 -3
  19. package/template/App_Resources/iOS/src/OctaneShaders.metal +0 -128
  20. package/template/App_Resources/iOS/src/ShaderEffectRegistration.swift +0 -31
  21. package/template/patches/@nativescript-community__octane@0.2.1.patch +0 -16
  22. package/template/patches/@nativescript-community__vite-octane@0.2.1.patch +0 -41
  23. package/template/patches/@nativescript__core@9.1.2.patch +0 -794
  24. package/template/patches/@nativescript__core@9.1.3-next.2.patch +0 -428
  25. package/template/patches/@nativescript__vite@8.0.11.patch +0 -569
  26. package/template/patches/@nativescript__vite@8.0.13.patch +0 -233
  27. package/template/patches/@tsrx__typescript-plugin@0.4.11.patch +0 -11
  28. package/template/patches/css@3.0.0.patch +0 -52
  29. package/template/patches/octane@0.6.3.patch +0 -1149
  30. /package/template/src/{index.ts → main.ts} +0 -0
@@ -1,128 +0,0 @@
1
- #include <metal_stdlib>
2
- #include <SwiftUI/SwiftUI_Metal.h>
3
- using namespace metal;
4
-
5
- // Stitchable shaders for SwiftUI's `.distortionEffect` / `.colorEffect` (iOS 17+).
6
- // SwiftUI supplies the leading parameters — `position` for a distortion, plus
7
- // `color` for a colour effect — and appends the arguments passed at the call
8
- // site in `OctaneLogo.swift`.
9
-
10
- /// Rising heat haze.
11
- ///
12
- /// A distortion shader maps a destination pixel back to the source pixel it
13
- /// should sample, so the returned offset reads as the image bending. Amplitude
14
- /// is weighted by `base^2` (1 at the bottom, 0 at the top) so the mark shimmers
15
- /// like air over hot metal instead of wobbling as a rigid block, and the two
16
- /// waves use incommensurate frequencies so the pattern never visibly repeats.
17
- [[ stitchable ]] float2 octaneHeatHaze(float2 position, float time, float2 size, float intensity) {
18
- float2 uv = position / size;
19
- float base = 1.0 - uv.y;
20
- float wave = sin(uv.y * 26.0 - time * 3.1) * 0.6
21
- + sin(uv.y * 11.0 - time * 1.9 + uv.x * 4.0) * 0.4;
22
- float amp = 2.4 * base * base * intensity;
23
- return position + float2(wave * amp, 0.0);
24
- }
25
-
26
- /// Ember sheen sweeping diagonally across the ink.
27
- ///
28
- /// SwiftUI hands colour effects premultiplied alpha, so the colour has to be
29
- /// un-premultiplied before mixing and re-premultiplied on the way out —
30
- /// blending straight into premultiplied RGB would bleed the highlight into the
31
- /// transparent surround and halo the glyph edges.
32
- [[ stitchable ]] half4 octaneSheen(float2 position, half4 color, float time, float2 size, float intensity) {
33
- if (color.a < 0.004h) {
34
- return color;
35
- }
36
- half3 rgb = color.rgb / color.a;
37
-
38
- float2 uv = position / size;
39
- float sweep = fract(time * 0.22);
40
- float d = (uv.x * 0.85 + (1.0 - uv.y) * 0.35) - (sweep * 1.8 - 0.4);
41
- float band = exp(-(d * d) * 42.0);
42
-
43
- half3 ember = half3(1.0h, 0.255h, 0.353h); // the logo's #FF415A accent
44
- half3 gold = half3(1.0h, 0.72h, 0.36h);
45
- half3 hot = mix(ember, gold, half(band));
46
-
47
- half glow = half(band) * half(intensity);
48
- rgb = mix(rgb, hot, glow * 0.9h);
49
- rgb += half3(glow * 0.25h);
50
-
51
- return half4(saturate(rgb) * color.a, color.a);
52
- }
53
-
54
- /// Per-shard pseudo-random pair. Deterministic in the cell index, so a shard
55
- /// keeps the same trajectory for the whole burst instead of jittering per frame.
56
- static inline float2 shardNoise(float2 cell) {
57
- float3 a = fract(float3(cell.xyx) * float3(0.1031, 0.1030, 0.0973));
58
- a += dot(a, a.yzx + 33.33);
59
- return fract(float2((a.x + a.y) * a.z, (a.x + a.z) * a.y));
60
- }
61
-
62
- /// Ignition burst: the mark shatters outward and reassembles.
63
- ///
64
- /// A layer effect (rather than a distortion) because each shard has to read
65
- /// from somewhere else in the image: sampling `position - offset` with an
66
- /// offset that is constant across a grid cell translates that whole cell as a
67
- /// rigid chip, which is what reads as breaking apart. A distortion shader can
68
- /// only nudge its own pixel, so it smears instead of shattering.
69
- ///
70
- /// `progress` runs 0 -> 1 once per burst and the displacement rides
71
- /// `sin(p * pi)`, so the shards fly out and land back exactly where they
72
- /// started — no separate reassembly pass, and the mark cannot get stranded
73
- /// mid-explosion if a frame is dropped.
74
- [[ stitchable ]] half4 octaneShatter(float2 position, SwiftUI::Layer layer, float2 size, float progress) {
75
- if (progress <= 0.0001) {
76
- return layer.sample(position);
77
- }
78
-
79
- float p = clamp(progress, 0.0, 1.0);
80
- float fly = sin(p * M_PI_F);
81
- float ease = fly * fly;
82
-
83
- float2 cells = float2(22.0, 5.0);
84
- float2 cellSize = size / cells;
85
- float2 rnd = shardNoise(floor(position / cellSize));
86
-
87
- float2 centre = size * 0.5;
88
- float2 radial = (position - centre) / max(size.x * 0.5, 1.0);
89
- float2 dir = radial + (rnd - 0.5) * 0.9;
90
- float len = max(length(dir), 0.0001);
91
- dir /= len;
92
-
93
- // Capped so the outermost shards stay inside the host view; anything
94
- // travelling further is clipped by its bounds rather than fading out.
95
- float2 offset = dir * mix(22.0, 70.0, rnd.x) * ease;
96
- offset.y += (rnd.y - 0.5) * 42.0 * ease;
97
- float2 src = position - offset;
98
-
99
- // Chromatic split along the flight path — the shards read as moving fast
100
- // rather than merely being displaced.
101
- float split = ease * 3.5;
102
- half4 cr = layer.sample(src + dir * split);
103
- half4 cg = layer.sample(src);
104
- half4 cb = layer.sample(src - dir * split);
105
- half alpha = max(max(cr.a, cg.a), cb.a);
106
- if (alpha < 0.004h) {
107
- return half4(0.0h);
108
- }
109
- half3 rgb = half3(cr.r, cg.g, cb.b) / alpha;
110
-
111
- // Expanding shockwave ring, brightest just after the tap.
112
- float ring = exp(-pow((length(radial) - p * 1.5) * 5.0, 2.0)) * (1.0 - p);
113
-
114
- half3 ember = half3(1.0h, 0.255h, 0.353h);
115
- half3 gold = half3(1.0h, 0.78h, 0.35h);
116
- half heat = half(ease);
117
- // Ember-leaning, and only a partial mix: pushing all the way to `hot` turns
118
- // every shard the same flat gold and the mark stops being recognisable
119
- // mid-flight. Holding some ink back keeps them reading as burning pieces
120
- // of the logo.
121
- half3 hot = mix(ember, gold, heat * 0.75h);
122
-
123
- rgb = mix(rgb, hot, heat * 0.6h);
124
- rgb += half3(heat * 0.18h * half(rnd.x) + half(ring) * 0.45h);
125
-
126
- alpha *= 1.0h - heat * 0.2h;
127
- return half4(saturate(rgb) * alpha, alpha);
128
- }
@@ -1,31 +0,0 @@
1
- import SwiftUI
2
-
3
- // Registers the app's stitchable shaders (OctaneShaders.metal) by name for
4
- // @octane-xplat/effects' <ShaderEffect>. Names are runtime strings because
5
- // ShaderLibrary lookups are compile-time — registration is the dispatch
6
- // table. Call `OctaneShaderEffects.install()` from JS before rendering a
7
- // ShaderEffect (`declare const OctaneShaderEffects: any`).
8
- //
9
- // Pair-bound: this file + OctaneShaders.metal + the @octane-xplat/effects
10
- // dependency go together — delete all three if you don't want shader
11
- // effects.
12
- @objc(OctaneShaderEffects)
13
- public final class OctaneShaderEffects: NSObject {
14
- @objc public static func install() {
15
- XplatShaderEffectRegistry.register("heatHaze", kind: .distortion) { args in
16
- ShaderLibrary.octaneHeatHaze(
17
- .float(args.f("time")), .float2(args.size), .float(args.f("intensity"))
18
- )
19
- }
20
- XplatShaderEffectRegistry.register("sheen", kind: .color) { args in
21
- ShaderLibrary.octaneSheen(
22
- .float(args.f("time")), .float2(args.size), .float(args.f("intensity"))
23
- )
24
- }
25
- XplatShaderEffectRegistry.register("shatter", kind: .layer) { args in
26
- ShaderLibrary.octaneShatter(
27
- .float2(args.size), .float(args.f("progress"))
28
- )
29
- }
30
- }
31
- }
@@ -1,16 +0,0 @@
1
- diff --git a/dist/driver.js b/dist/driver.js
2
- index f485f992282c05c58fed810458303be3141f51c0..9b5a654cf0c32be5fc6da4ae5fec04a58560925f 100644
3
- --- a/dist/driver.js
4
- +++ b/dist/driver.js
5
- @@ -83,6 +83,11 @@ function setProp(node, view, name, value) {
6
- setRenderItem(view, value ?? null, createNativeScriptRoot);
7
- return;
8
- }
9
- + // `undefined` means "prop not supplied" — skip the write. NativeScript
10
- + // native setters coerce it (e.g. editable → ios.userInteractionEnabled =
11
- + // NO) leaving dead UI that still has its JS listeners.
12
- + if (value === undefined)
13
- + return;
14
- // Core raises `<name>Change` for a script write exactly as for a user
15
- // edit; a controlled input must not see its own value come back as one.
16
- const echo = `${name}Change`;
@@ -1,41 +0,0 @@
1
- diff --git a/dist/server/strategy.js b/dist/server/strategy.js
2
- index 7d84b37e2ed3a026da5b31c8a11027e0580877b2..f6594a913ba64837135e994cb183add13c6a0530 100644
3
- --- a/dist/server/strategy.js
4
- +++ b/dist/server/strategy.js
5
- @@ -14,7 +14,9 @@ import { purgeTransformCachesForHotUpdate, runHotUpdatePrologue, typescriptServe
6
- * otherwise the re-fetch can be served from the previous save's transform and
7
- * the screen ends up one save behind.
8
- */
9
- -const SCRIPT_FILE_RE = /\.(?:[mc]?[jt]sx?)$/i;
10
- +// `.tsrx` is Octane's component extension — without it the deferred delta is
11
- +// never emitted and component edits silently never reach the device.
12
- +const SCRIPT_FILE_RE = /\.(?:[mc]?[jt]sx?|tsrx)$/i;
13
- export const octaneServerStrategy = {
14
- ...typescriptServerStrategy,
15
- flavor: 'octane',
16
- @@ -24,7 +26,7 @@ export const octaneServerStrategy = {
17
- if (!state)
18
- return;
19
- const { root, metrics, emitSummary } = state;
20
- - const { moduleGraph, verbose, sharedTransformRequest } = deps;
21
- + const { moduleGraph, verbose, sharedTransformRequest, wss, isSocketClientOpen } = deps;
22
- const { file, server } = ctx;
23
- if (!SCRIPT_FILE_RE.test(file)) {
24
- emitSummary();
25
- @@ -71,6 +73,16 @@ export const octaneServerStrategy = {
26
- const gm = moduleGraph.get(normalizedId);
27
- if (gm)
28
- moduleGraph.emitDelta([gm], []);
29
- + // The ns:hmr-delta broadcast IS the update delivery for this flavor —
30
- + // count open sockets so the always-on summary reflects reality
31
- + // instead of reporting recipients=0 for a delivered update.
32
- + try {
33
- + wss?.clients?.forEach((client) => {
34
- + if (isSocketClientOpen?.(client))
35
- + metrics.recipients += 1;
36
- + });
37
- + }
38
- + catch { }
39
- }
40
- catch (e) {
41
- if (verbose)