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.
- package/README.md +28 -8
- package/index.mjs +112 -14
- package/package.json +15 -8
- package/scaffold.mjs +531 -0
- package/template/.agents/skills/xplat/SKILL.md +109 -40
- package/template/.agents/skills/xplat/references/components.md +149 -96
- package/template/.agents/skills/xplat/references/navigation.md +81 -31
- package/template/.agents/skills/xplat/references/platform.md +74 -35
- package/template/.agents/skills/xplat/references/styling.md +80 -27
- package/template/AGENTS.md +1 -1
- package/template/package.json +11 -9
- package/template/pnpm-workspace.yaml +66 -33
- package/template/src/App.tsrx +17 -8
- package/template/src/process.d.ts +7 -0
- package/template/src/style.css +24 -6
- package/template/tsconfig.json +1 -1
- package/template/vite.config.native.mts +3 -2
- package/template/vite.config.ts +5 -3
- package/template/App_Resources/iOS/src/OctaneShaders.metal +0 -128
- package/template/App_Resources/iOS/src/ShaderEffectRegistration.swift +0 -31
- package/template/patches/@nativescript-community__octane@0.2.1.patch +0 -16
- package/template/patches/@nativescript-community__vite-octane@0.2.1.patch +0 -41
- package/template/patches/@nativescript__core@9.1.2.patch +0 -794
- package/template/patches/@nativescript__core@9.1.3-next.2.patch +0 -428
- package/template/patches/@nativescript__vite@8.0.11.patch +0 -569
- package/template/patches/@nativescript__vite@8.0.13.patch +0 -233
- package/template/patches/@tsrx__typescript-plugin@0.4.11.patch +0 -11
- package/template/patches/css@3.0.0.patch +0 -52
- package/template/patches/octane@0.6.3.patch +0 -1149
- /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)
|