@threenative/core 0.1.0 → 0.3.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.
@@ -0,0 +1,175 @@
1
+ import { ReactNode } from 'react';
2
+ import { C as CanvasLayer } from './canvas-layer-CtrZHgIh.js';
3
+ import 'three';
4
+ import 'three/webgpu';
5
+
6
+ /**
7
+ * Every character this glyph set can draw, for error messages and for the templates' AGENTS.md.
8
+ * @situation discover which characters a native React HUD can draw
9
+ * @example supportedGlyphs().includes("A")
10
+ */
11
+ declare function supportedGlyphs(): string;
12
+
13
+ /**
14
+ * The layout model behind the native React overlay: pure TypeScript, no WASM, no Yoga, no CSS
15
+ * parser. `TN_NATIVE_WASM_ON_MOBILE` refuses WebAssembly in mobile bundles, which rules out Yoga;
16
+ * writing a CSS engine here would be writing a browser, one ticket at a time.
17
+ *
18
+ * That last clause used to read "which is the thing this whole path exists to avoid", and PRD-217
19
+ * corrected it: the thing to avoid is *shipping* a browser, and every platform already provides
20
+ * one at the composition layer for free. So `ui.renderer: "web"` is now the default — the same
21
+ * React DOM, Tailwind, CSS and SVG on every target — and this renderer is the opt-in for a UI that
22
+ * is part of the rendered frame, a target with no web view, or zero extra processes. Growing this
23
+ * vocabulary toward CSS is still the wrong move; a game that needs CSS should ask for the web
24
+ * renderer instead.
25
+ *
26
+ * **The supported subset is exactly the fields on {@link IOverlayStyle} and nothing else.** A style
27
+ * key that is not on that interface is not "ignored for now" — {@link assertKnownStyle} throws
28
+ * `TN_REACT_UNKNOWN_STYLE` naming the key, because a convention discovered by failure is worse than
29
+ * one that does not exist.
30
+ *
31
+ * Units are screen pixels throughout, matching `CanvasLayer`'s orthographic camera. The origin is
32
+ * the top-left of the parent's content box, y increasing downwards, like a screen and unlike Three.
33
+ */
34
+ /** `#rrggbb`, `#rgb`, or a packed `0xrrggbb` number. Alpha is `opacity`, kept separate on purpose. */
35
+ type OverlayColor = string | number;
36
+ interface IOverlayStyle {
37
+ /** Distance from the parent's left content edge. Ignored when the parent lays out in flow. */
38
+ left?: number;
39
+ /** Distance from the parent's right content edge. Applied only when `left` is absent. */
40
+ right?: number;
41
+ /** Distance from the parent's top content edge. Ignored when the parent lays out in flow. */
42
+ top?: number;
43
+ /** Distance from the parent's bottom content edge. Applied only when `top` is absent. */
44
+ bottom?: number;
45
+ /** Centre horizontally in the parent's content box. Wins over `left`/`right`. */
46
+ centerX?: boolean;
47
+ /** Centre vertically in the parent's content box. Wins over `top`/`bottom`. */
48
+ centerY?: boolean;
49
+ /** Fixed width. Without one, a box shrink-wraps its children and text measures its glyphs. */
50
+ width?: number;
51
+ /** Fixed height. Without one, a box shrink-wraps its children and text is one line tall. */
52
+ height?: number;
53
+ /** Uniform inset between this box's edges and its content box. */
54
+ padding?: number;
55
+ /** Lay children out in flow along this axis. Absent means children are placed absolutely. */
56
+ direction?: "row" | "column";
57
+ /** Space between flow children, in pixels. Only meaningful with `direction`. */
58
+ gap?: number;
59
+ /** Cross-axis placement of flow children. */
60
+ align?: "start" | "center" | "end";
61
+ /** Fill colour. Absent means the box draws nothing and only positions its children. */
62
+ background?: OverlayColor;
63
+ /** Glyph colour on a `text` element. */
64
+ color?: OverlayColor;
65
+ /** 0-1, multiplied into whatever this element draws. Children carry their own. */
66
+ opacity?: number;
67
+ /** Cell height of one glyph in pixels; the 5x7 grid scales to it. Inherited by descendants. */
68
+ fontSize?: number;
69
+ /** Extra pixels between glyph cells, on top of the 5x7 grid's one-column gap. */
70
+ letterSpacing?: number;
71
+ /** Horizontal placement of the glyph run inside a `text` box that has a `width`. */
72
+ textAlign?: "left" | "center" | "right";
73
+ /** Paint order among siblings. Higher paints later. Ties fall back to tree order. */
74
+ zIndex?: number;
75
+ }
76
+ /**
77
+ * Every style key the overlay implements, for the templates' AGENTS.md and for error messages.
78
+ * @situation discover which React HUD style properties work on native
79
+ * @example supportedStyleKeys().includes("centerX")
80
+ */
81
+ declare function supportedStyleKeys(): readonly string[];
82
+ /** A resolved rectangle in screen pixels, origin top-left of the framebuffer. */
83
+ interface IOverlayBox {
84
+ x: number;
85
+ y: number;
86
+ width: number;
87
+ height: number;
88
+ }
89
+ /**
90
+ * Width in pixels of a glyph run at a given cell height.
91
+ * @situation measure native React HUD text before laying it out
92
+ * @example const scoreWidth = measureText("SCORE 10", 24)
93
+ */
94
+ declare function measureText(text: string, fontSize: number, letterSpacing?: number): number;
95
+
96
+ /**
97
+ * A React renderer that commits to `CanvasLayer` instead of the DOM.
98
+ *
99
+ * `react` is the component model and has no DOM in it; `react-dom` is one renderer among several,
100
+ * and `react-reconciler` is the supported way to write another. The native host has no DOM to
101
+ * render into and no rasteriser to paint one with, so this maps React elements straight onto
102
+ * Three.js objects inside the orthographic, screen-pixel `CanvasLayer` that `renderOverlay` already
103
+ * draws on every platform. Nothing here imports `react-dom`, which is what keeps
104
+ * `TN_NATIVE_WEB_ONLY_UI` satisfied on a native bundle.
105
+ *
106
+ * There are exactly two element types, and that is the whole vocabulary:
107
+ *
108
+ * - `<view>` — a rectangle. Draws when it has a `background`; otherwise it only positions children.
109
+ * - `<text>` — a run of bitmap glyphs. Its children must be strings or numbers.
110
+ *
111
+ * Anything else throws `TN_REACT_UNKNOWN_ELEMENT` naming the tag. Tailwind class names cannot cross
112
+ * — they are CSS — so styling is the `style` prop, whose supported keys are named exhaustively on
113
+ * `IOverlayStyle` and enforced by `assertKnownStyle`.
114
+ */
115
+ /** The two host element types, as strings React sees. Namespaced so no DOM or SVG tag can collide. */
116
+ declare const VIEW_ELEMENT = "tn-view";
117
+ /** @see VIEW_ELEMENT */
118
+ declare const TEXT_ELEMENT = "tn-text";
119
+ interface IReactOverlayOptions {
120
+ /** Where the tree is drawn. `ctx.canvasLayer` in a game. */
121
+ canvasLayer: Pick<CanvasLayer, "scene" | "camera" | "onResize">;
122
+ /**
123
+ * Called with any error React could not recover from, before the overlay draws its own named
124
+ * failure banner. The default logs it; nothing swallows it, because a blank HUD and a broken HUD
125
+ * must never look the same.
126
+ */
127
+ onError?: (error: Error) => void;
128
+ }
129
+ interface IReactOverlay {
130
+ /** Mount or update the tree. Synchronous, so a caller can assert on the result immediately. */
131
+ render(element: ReactNode): void;
132
+ /** Re-run layout — call after a resize. Cheap and idempotent; it no-ops when nothing moved. */
133
+ refresh(): void;
134
+ /** Unmount the tree and release every Three.js object it created. */
135
+ dispose(): void;
136
+ /** How many Three.js objects the last commit produced. For budgets and tests. */
137
+ readonly objectCount: number;
138
+ /** Number of hook/store updates that changed host nodes during `refresh()`. */
139
+ readonly commitCount: number;
140
+ /** Flush plus draw cost of the latest state-changing `refresh()`, in milliseconds. */
141
+ readonly lastCommitMs: number | undefined;
142
+ }
143
+ /**
144
+ * Mount React into a `CanvasLayer`.
145
+ *
146
+ * @situation show a React HUD on Android, iOS or desktop native
147
+ * @situation render the same React component on web and on a phone without a WebView
148
+ * @constraint import `react`, never `react-dom`, from a native entry
149
+ * @example const overlay = createReactOverlay({ canvasLayer: ctx.canvasLayer });
150
+ */
151
+ declare function createReactOverlay(options: IReactOverlayOptions): IReactOverlay;
152
+
153
+ interface IViewProps {
154
+ style?: IOverlayStyle;
155
+ children?: ReactNode;
156
+ }
157
+ interface ITextProps {
158
+ style?: IOverlayStyle;
159
+ /** Strings and numbers only. Nesting an element inside `Text` has nothing to draw it with. */
160
+ children?: ReactNode;
161
+ }
162
+ /**
163
+ * A rectangle. Paints when its style has a `background`; otherwise it only positions children.
164
+ * @situation group and position native React HUD elements
165
+ * @example <View style={{ centerX: 0, top: 24 }}><Text>READY</Text></View>
166
+ */
167
+ declare function View(props: IViewProps): ReactNode;
168
+ /**
169
+ * A run of bitmap glyphs, drawn as one instanced quad per lit pixel.
170
+ * @situation show text in a native React HUD without a DOM
171
+ * @example <Text style={{ color: "#ffffff", fontSize: 24 }}>SCORE 10</Text>
172
+ */
173
+ declare function Text(props: ITextProps): ReactNode;
174
+
175
+ export { type IOverlayBox, type IOverlayStyle, type IReactOverlay, type IReactOverlayOptions, type ITextProps, type IViewProps, type OverlayColor, TEXT_ELEMENT, Text, VIEW_ELEMENT, View, createReactOverlay, measureText, supportedGlyphs, supportedStyleKeys };