pathland_core/constants.rs
1//! Protocol constants: categories, commands, component types, value types, flags.
2//!
3//! These constants are part of the wire protocol (see `spec/OPCODE.md`) and MUST
4//! NOT be renumbered once released. Component types were renumbered pre-release
5//! to the grouped ranges in `spec/PRIMITIVES.md` (wire version stays 1).
6
7/// Opcode categories (`Category` field, u8).
8pub mod category {
9 /// Tree mutations (guest → host): node create/delete/insert/remove/move.
10 pub const TREE: u8 = 0x01;
11 /// Parameters and design tokens (guest → host): the constraint properties
12 /// (spacing, padding, alignment, …) and content that native renderers use
13 /// to lay out and style native elements. The engine does NOT emit rects.
14 pub const PARAMETER: u8 = 0x02;
15 /// Raw input events (host → guest): pointer down/move/up, key down/up.
16 pub const EVENT: u8 = 0x03;
17 /// Control (both directions): reset, environment, custom data.
18 pub const META: u8 = 0x04;
19}
20
21/// Commands within the `TREE` category.
22pub mod tree {
23 /// `A=nodeId, B=componentType (u16, low)`
24 pub const CREATE_NODE: u8 = 0x01;
25 /// `A=nodeId`
26 pub const DELETE_NODE: u8 = 0x02;
27 /// `A=parentId, B=childId, C=index` (append is `C = u32::MAX`, see [`crate::APPEND`])
28 pub const INSERT_CHILD: u8 = 0x03;
29 /// `A=parentId, B=childId`
30 pub const REMOVE_CHILD: u8 = 0x04;
31 /// `A=parentId, B=childId, C=newIndex` (append is `C = u32::MAX`, see [`crate::APPEND`])
32 pub const MOVE_CHILD: u8 = 0x05;
33}
34
35/// Commands within the `PARAMETER` category.
36pub mod parameter {
37 /// `A=nodeId, B=(valueType << 16) | propertyId, C=value`
38 pub const SET_PROPERTY: u8 = 0x01;
39 /// `A=arenaRef (path), B=valueType (u8), C=value`
40 pub const SET_DESIGN_TOKEN: u8 = 0x02;
41 /// `A=nodeId, B=arenaRef (utf8)`
42 pub const SET_TEXT: u8 = 0x03;
43 /// **Draft.** `A=nodeId, B=days since epoch (I32), C=millis of day (U32)` —
44 /// set a node's date value (e.g. a `DATE_PICKER`); see
45 /// `spec/PRIMITIVES.md` / `spec/OPCODE.md`.
46 pub const SET_DATE: u8 = 0x04;
47}
48
49/// Commands within the `EVENT` category.
50///
51/// Events are **raw inputs** (host → guest), each carrying a host-resolved
52/// `targetId`. High-level interpretations (tap, drag, long-press) are built by
53/// the guest/app from these raw inputs and are NOT part of the protocol.
54pub mod event {
55 /// `A=targetId, B=x (f32), C=y (f32)` (Flags `POINTER_SECONDARY`)
56 pub const POINTER_DOWN: u8 = 0x01;
57 /// `A=targetId, B=x (f32), C=y (f32)` (Flags `HOVER_ENTER` / `HOVER_LEAVE`)
58 pub const POINTER_MOVE: u8 = 0x02;
59 /// `A=targetId, B=x (f32), C=y (f32)` (Flags `POINTER_SECONDARY`)
60 pub const POINTER_UP: u8 = 0x03;
61 /// `A=targetId, B=keyCode (u16, low), C=modifiers (u8, low)` (Flags `KEY_REPEAT`)
62 pub const KEY_DOWN: u8 = 0x04;
63 /// `A=targetId, B=keyCode (u16, low), C=modifiers (u8, low)`
64 pub const KEY_UP: u8 = 0x05;
65 /// `A=targetId, B=value (f32)` — a control's value changed (host → guest).
66 /// The renderer resolves the control's semantic value (e.g. a slider thumb
67 /// dragged to a point on its track); the guest/app writes it into its state.
68 pub const VALUE_CHANGED: u8 = 0x06;
69 /// `A=targetId, B=string offset` — a text field's value changed (host →
70 /// guest). The new text lives in the batch's string section, referenced by
71 /// the *relative* offset in `B` (the same convention as `PARAMETER::SET_TEXT`).
72 pub const TEXT_CHANGED: u8 = 0x07;
73 /// **Draft.** `A=targetId, B=focused (0/1)` — a node gained/lost focus.
74 pub const FOCUS_CHANGED: u8 = 0x08;
75 /// **Draft.** `A=targetId, B=editing (0/1)` — an editing session began/ended.
76 pub const EDITING_CHANGED: u8 = 0x09;
77 /// **Draft.** `A=targetId, B=0` — the user committed a field (onSubmit).
78 pub const SUBMIT: u8 = 0x0A;
79 /// **Draft.** `A=targetId, B=offsetX (f32), C=offsetY (f32)` — scroll offset.
80 pub const SCROLL: u8 = 0x0B;
81 /// **Draft.** `A=targetId, B=deltaX (f32), C=deltaY (f32)` — wheel/trackpad.
82 pub const WHEEL: u8 = 0x0C;
83 /// **Draft.** `A=targetId, B=days since epoch (I32), C=millis of day (U32)`
84 /// — a `DATE_PICKER`'s value changed (matches `PARAMETER::SET_DATE`).
85 pub const DATE_CHANGED: u8 = 0x0D;
86 /// **Draft.** Global navigation request (host → guest), never node-keyed.
87 /// With the `NAVIGATE_URL` flag, `B` is a string offset (event arena /
88 /// batch string section) to the destination URL; without it, the event means
89 /// "back one step" (native back affordance) and `B`/`C` are ignored.
90 pub const NAVIGATE: u8 = 0x0E;
91 /// **Draft.** A bound `AUDIO`/`VIDEO` node's playback state changed
92 /// (host → guest); `B` = 0/1. Reported only when `PLAYBACK_STATE` is bound.
93 pub const MEDIA_PLAY_STATE_CHANGED: u8 = 0x0F;
94 /// **Draft.** A bound media node's current position (host → guest); `B` =
95 /// seconds (f32). Reported while playing; an app-initiated seek is not echoed.
96 pub const MEDIA_TIME_UPDATED: u8 = 0x10;
97 /// **Draft.** A bound media node reached the end of its media (host → guest).
98 pub const MEDIA_ENDED: u8 = 0x11;
99 /// **Draft.** A bound media node's volume changed (host → guest); `B` =
100 /// volume (f32, 0..1).
101 pub const MEDIA_VOLUME_CHANGED: u8 = 0x12;
102 /// **Draft.** A `SIZE_THAT_FITS` slot's selected candidate index changed
103 /// (host → guest); `B` = index (f32). Reported once after the first measure,
104 /// then only when the derived fit index changes.
105 pub const FIT_CHANGED: u8 = 0x13;
106}
107
108/// Commands within the `META` category.
109pub mod meta {
110 /// Host must clear all rendered output.
111 pub const RESET: u8 = 0x01;
112 /// `A=fieldId (u16, low), B=field value` — a platform environment field
113 /// (host → guest); see [`crate::environment`]. An extensible field family:
114 /// each opcode sets one field (viewport, initial route, …).
115 pub const ENVIRONMENT: u8 = 0x02;
116 /// The host (renderer) requests a full snapshot of the current tree
117 /// (host → guest). `A/B/C = 0`. Used for reconnect/gap recovery.
118 pub const RESYNC: u8 = 0x03;
119 /// A transport-liveness heartbeat probe (guest → host). `A/B/C = 0`, no
120 /// payload. **Network batch transport only** (spec/OPCODE.md §Transport —
121 /// heartbeat): the shared-memory ring MUST NOT emit, expect, or relay it.
122 pub const PING: u8 = 0x04;
123 /// The reply to `META::PING` (host → guest). `A/B/C = 0`, no payload.
124 /// Network batch transport only (see [`PING`]).
125 pub const PONG: u8 = 0x05;
126}
127
128/// Environment field ids for `META::ENVIRONMENT` (host → guest).
129///
130/// Each opcode sets one platform environment field; new fields are new ids, never
131/// new commands (spec/OPCODE.md §Environment fields).
132pub mod environment {
133 /// Viewport width in logical points (f32 in `B`).
134 pub const VIEWPORT_WIDTH: u16 = 0x0001;
135 /// Viewport height in logical points (f32 in `B`).
136 pub const VIEWPORT_HEIGHT: u16 = 0x0002;
137 /// The initial route/deep-link path (STRING: `B` is a string-section/event-arena
138 /// offset — the `TEXT_CHANGED`/`NAVIGATE` dual convention).
139 pub const ROUTE: u16 = 0x0003;
140}
141
142/// Flag bits used across categories.
143pub mod flag {
144 /// `POINTER_DOWN` / `POINTER_UP`: secondary button (bit 0).
145 pub const POINTER_SECONDARY: u16 = 0x0001;
146 /// `POINTER_MOVE`: pointer is entering/hovering (bit 0).
147 pub const HOVER_ENTER: u16 = 0x0001;
148 /// `POINTER_MOVE`: pointer is leaving (bit 1).
149 pub const HOVER_LEAVE: u16 = 0x0002;
150 /// `KEY_DOWN`: key repeat (bit 1).
151 pub const KEY_REPEAT: u16 = 0x0002;
152 /// `NAVIGATE`: `B` is a URL string offset (bit 0). Without this flag the
153 /// event is a back request.
154 pub const NAVIGATE_URL: u16 = 0x0001;
155}
156
157/// Bits for the `EVENT_LISTENERS` semantic property (a u32 bitmask).
158///
159/// Each bit requests that a renderer attach native input recognition for the
160/// matching raw-input event and report it for that node — so any element (not
161/// just a button) can emit raw events. Bits are independent of the `EVENT`
162/// command ids; more event kinds can be added later.
163pub mod listener {
164 /// `POINTER_DOWN` events (bit 0).
165 pub const POINTER_DOWN: u32 = 1 << 0;
166 /// `POINTER_MOVE` events (bit 1).
167 pub const POINTER_MOVE: u32 = 1 << 1;
168 /// `POINTER_UP` events (bit 2).
169 pub const POINTER_UP: u32 = 1 << 2;
170 /// `KEY_DOWN` events (bit 3).
171 pub const KEY_DOWN: u32 = 1 << 3;
172 /// `KEY_UP` events (bit 4).
173 pub const KEY_UP: u32 = 1 << 4;
174 /// **Draft.** `FOCUS_CHANGED` events (bit 5).
175 pub const FOCUS: u32 = 1 << 5;
176 /// **Draft.** `EDITING_CHANGED` events (bit 6).
177 pub const EDITING: u32 = 1 << 6;
178 /// **Draft.** `SUBMIT` events (bit 7).
179 pub const SUBMIT: u32 = 1 << 7;
180 /// **Draft.** `SCROLL` events (bit 8).
181 pub const SCROLL: u32 = 1 << 8;
182 /// **Draft.** `WHEEL` events (bit 9).
183 pub const WHEEL: u32 = 1 << 9;
184
185 /// All pointer events (down + move + up).
186 pub const POINTER: u32 = POINTER_DOWN | POINTER_MOVE | POINTER_UP;
187}
188
189/// Bits for the `BORDER_EDGES` style property (a u32 bitmask).
190///
191/// Each bit selects one edge of a node's border. `LEADING`/`TRAILING` are
192/// direction-aware; a renderer resolves them to physical `left`/`right`
193/// according to its layout direction (LTR by default).
194pub mod border_edges {
195 /// Top edge (bit 0).
196 pub const TOP: u32 = 1 << 0;
197 /// Leading edge (bit 1) — physical left in LTR.
198 pub const LEADING: u32 = 1 << 1;
199 /// Bottom edge (bit 2).
200 pub const BOTTOM: u32 = 1 << 2;
201 /// Trailing edge (bit 3) — physical right in LTR.
202 pub const TRAILING: u32 = 1 << 3;
203
204 /// All four edges.
205 pub const ALL: u32 = TOP | LEADING | BOTTOM | TRAILING;
206}
207
208/// Value types for `PARAMETER` properties (u8, encoded in the high byte of `B`).
209pub mod value_type {
210 pub const U8: u8 = 0x01;
211 pub const U32: u8 = 0x02;
212 pub const I32: u8 = 0x03;
213 pub const F32: u8 = 0x04;
214 pub const STRING: u8 = 0x05;
215 pub const ENUM: u8 = 0x06;
216 pub const COLOR: u8 = 0x07;
217 pub const DESIGN_TOKEN: u8 = 0x08;
218 /// **Draft.** Arena-backed length-prefixed array: `[u32 count][element × count]`
219 /// in the string arena (each element holds the value-type's bit pattern —
220 /// today `F32`s, e.g. the `FIT_QUERY` threshold table).
221 pub const LIST: u8 = 0x09;
222}
223
224/// Component types (u16, encoded in the low half of `B` of `TREE::CREATE_NODE`).
225///
226/// IDs are grouped into three definitive ranges (see `spec/PRIMITIVES.md`):
227/// Primitive Drawing `0x01`–`0x0F`, Layout & Container `0x10`–`0x1F`, Semantic
228/// Control `0x20`–`0x2F`, plus the utility `COMMENT` at `0x7F`. Renumbered
229/// pre-release (wire version stays 1).
230pub mod component_type {
231 // ── Primitive Drawing & Visual Nodes (0x01–0x0F) ────────────────────────
232 /// Standard styled text display.
233 pub const TEXT: u16 = 0x01;
234 /// Raster, vector, or system icon asset.
235 pub const IMAGE: u16 = 0x02;
236 /// **Draft.** Solid color / layout-filling background view.
237 pub const COLOR: u16 = 0x03;
238 /// **Draft.** Vector geometry (`SHAPE_KIND` selects the shape).
239 pub const SHAPE: u16 = 0x04;
240 /// **Draft.** Axis-aligned separator line.
241 pub const DIVIDER: u16 = 0x05;
242 /// Flexible expanding layout filler.
243 pub const SPACER: u16 = 0x06;
244 /// **Draft.** Determinate progress or activity indicator.
245 pub const PROGRESS_VIEW: u16 = 0x07;
246 /// **Draft.** Range meter against a scale (read-only).
247 pub const GAUGE: u16 = 0x08;
248 /// **Draft.** Audio playback node (`AUDIO_SOURCE` references the media;
249 /// playback interaction is renderer-native).
250 pub const AUDIO: u16 = 0x09;
251 /// **Draft.** Video playback node (`VIDEO_SOURCE` references the media;
252 /// playback interaction is renderer-native).
253 pub const VIDEO: u16 = 0x0A;
254 /// **Draft.** Semantic icon (`ICON_NAME` selects a renderer-native symbol —
255 /// Adwaita on GTK, Lucide on the web; spec/ICONS.md).
256 pub const ICON: u16 = 0x0B;
257 // 0x0C–0x0F reserved (future drawing nodes).
258
259 // ── Layout & Container Primitives (0x10–0x1F) ───────────────────────────
260 /// Vertical flex stack.
261 pub const VSTACK: u16 = 0x10;
262 /// Horizontal flex stack.
263 pub const HSTACK: u16 = 0x11;
264 /// **Draft.** Depth-overlapping layer stack.
265 pub const ZSTACK: u16 = 0x12;
266 /// Static 2D matrix grid (eagerly rendered).
267 pub const GRID: u16 = 0x13;
268 /// Scrollable content container.
269 pub const SCROLLVIEW: u16 = 0x14;
270 /// **Draft.** Virtualized vertical grid.
271 pub const LAZY_VGRID: u16 = 0x15;
272 /// **Draft.** Virtualized horizontal grid.
273 pub const LAZY_HGRID: u16 = 0x16;
274 /// **Draft.** Fit slot (`SizeThatFits`): shows its single selected child —
275 /// only the selected candidate is ever transmitted. The renderer measures
276 /// its own allocated width against `FIT_QUERY` and reports `FIT_CHANGED`.
277 pub const SIZE_THAT_FITS: u16 = 0x17;
278 // 0x18–0x1A reserved (formerly composite views, removed).
279 /// **Draft.** Virtualized vertical stack.
280 pub const LAZY_VSTACK: u16 = 0x1B;
281 /// **Draft.** Virtualized horizontal stack.
282 pub const LAZY_HSTACK: u16 = 0x1C;
283 /// **Draft.** Explicit row grouping for a `GRID`: a grid child whose children
284 /// are one row's cells (the SwiftUI `GridRow` surface). Renders nothing
285 /// outside a `GRID`.
286 pub const GRID_ROW: u16 = 0x1D;
287 // 0x1E–0x1F reserved (future layout nodes).
288
289 // ── Semantic Control Nodes (0x20–0x2F) ──────────────────────────────────
290 /// Action trigger control.
291 pub const BUTTON: u16 = 0x20;
292 /// Single-line text input (secure variant via `IS_SECURE`).
293 pub const TEXT_FIELD: u16 = 0x21;
294 /// **Draft.** Multi-line text editing area.
295 pub const TEXT_EDITOR: u16 = 0x22;
296 // 0x23 reserved.
297 /// Boolean control; the visual variant is `TOGGLE_STYLE`
298 /// (`Switch`/`Checkbox`/`Button`).
299 pub const TOGGLE: u16 = 0x24;
300 /// Continuous or stepped numeric range control.
301 pub const SLIDER: u16 = 0x25;
302 /// **Draft.** Discrete increment/decrement control.
303 pub const STEPPER: u16 = 0x26;
304 /// **Draft.** Date & time selection control (`PARAMETER::SET_DATE` value).
305 pub const DATE_PICKER: u16 = 0x27;
306 /// **Draft.** Selection control (options are child nodes).
307 pub const PICKER: u16 = 0x28;
308 /// **Draft.** Contextual action trigger + popover container.
309 pub const MENU: u16 = 0x29;
310 /// **Draft.** Native system color picker control.
311 pub const COLOR_PICKER: u16 = 0x2A;
312 // 0x2B–0x2F reserved (future semantic controls).
313
314 /// Opaque/debug node; renderers ignore it (no native element).
315 pub const COMMENT: u16 = 0x7F;
316}
317
318/// Property IDs (u16, encoded in the low half of `B` of `PARAMETER::SET_PROPERTY`).
319///
320/// IDs are specified in `spec/OPCODE.md` (carried forward from the historical protocol).
321pub mod property_id {
322 // Stack
323 pub const SPACING: u16 = 0x0001;
324 pub const ALIGNMENT: u16 = 0x0002;
325 // 0x0003 reserved (formerly JUSTIFICATION; main-axis distribution is
326 // expressed via a spacer element instead).
327 // 0x0004 reserved (formerly PADDING; now a styling modifier at 0x1011).
328 pub const CONTENT_MARGINS: u16 = 0x0005;
329 // Text
330 pub const TEXT: u16 = 0x000A;
331 pub const LINE_LIMIT: u16 = 0x000B;
332 pub const TEXT_ALIGNMENT: u16 = 0x000C;
333 pub const TRUNCATION_MODE: u16 = 0x000D;
334 /// **Draft.** `SHAPE` geometry kind (F32 enum): `Circle`=0, `Rectangle`=1,
335 /// `RoundedRectangle`=2, `Capsule`=3, `Ellipse`=4, `Path`=5.
336 pub const SHAPE_KIND: u16 = 0x0006;
337 // Layout modifiers (draft, 0x000E–0x001D)
338 /// **Draft.** Post-layout translation, x (F32). `.offset(x:y:)`.
339 pub const OFFSET_X: u16 = 0x000E;
340 /// **Draft.** Post-layout translation, y (F32).
341 pub const OFFSET_Y: u16 = 0x000F;
342 /// **Draft.** Absolute position within the parent, x (F32). `.position(x:y:)`.
343 pub const POSITION_X: u16 = 0x0010;
344 /// **Draft.** Absolute position within the parent, y (F32).
345 pub const POSITION_Y: u16 = 0x0011;
346 /// **Draft.** Minimum width (F32). `.frame(minWidth:...)`.
347 pub const MIN_WIDTH: u16 = 0x0012;
348 /// **Draft.** Ideal width (F32).
349 pub const IDEAL_WIDTH: u16 = 0x0013;
350 /// **Draft.** Maximum width (F32).
351 pub const MAX_WIDTH: u16 = 0x0014;
352 /// **Draft.** Minimum height (F32).
353 pub const MIN_HEIGHT: u16 = 0x0015;
354 /// **Draft.** Ideal height (F32).
355 pub const IDEAL_HEIGHT: u16 = 0x0016;
356 /// **Draft.** Maximum height (F32).
357 pub const MAX_HEIGHT: u16 = 0x0017;
358 /// **Draft.** Fixed-size hint, horizontal (U8 0/1). `.fixedSize()`.
359 pub const FIXED_SIZE_HORIZONTAL: u16 = 0x0018;
360 /// **Draft.** Fixed-size hint, vertical (U8 0/1).
361 pub const FIXED_SIZE_VERTICAL: u16 = 0x0019;
362 /// **Draft.** Layout priority (F32). `.layoutPriority(_:)`.
363 pub const LAYOUT_PRIORITY: u16 = 0x001A;
364 /// **Draft.** Aspect ratio (F32). `.aspectRatio(_:)`.
365 pub const ASPECT_RATIO: u16 = 0x001B;
366 /// **Draft.** Content mode (F32 enum): `Fit`=0, `Fill`=1.
367 pub const CONTENT_MODE: u16 = 0x001C;
368 /// **Draft.** Minimum scale factor (F32). `.minimumScaleFactor(_:)`.
369 pub const MINIMUM_SCALE_FACTOR: u16 = 0x001D;
370 /// **Draft.** Grid column count (F32, constructor property): a positive value
371 /// pins the count (equal `1fr` tracks); `FILL`/absent = auto-fit. Never a
372 /// pixel width — the grid's box comes from `WIDTH`/`HEIGHT`.
373 pub const GRID_COLUMNS: u16 = 0x001E;
374 /// **Draft.** Grid row count (F32, constructor property): the `LAZY_HGRID`
375 /// fixed track; positive = count, `FILL`/absent = auto-fit.
376 pub const GRID_ROWS: u16 = 0x001F;
377 /// **Draft.** Grid track spec (STRING, constructor property): a comma-
378 /// separated list of per-track sizes — `flex` | `fixed:<points>` |
379 /// `adaptive:<points>` — taking precedence over `GRID_COLUMNS`/`GRID_ROWS`
380 /// (the equal-`1fr` count is `N`×`flex` sugar). CSS-grid-native: renderers
381 /// without a native equivalent (GTK `GtkGrid`) fall back to natural sizing.
382 pub const GRID_TRACKS: u16 = 0x0020;
383 // Style (0x1000 range)
384 pub const BACKGROUND_COLOR: u16 = 0x1001;
385 /// **Draft.** Image source (STRING: a resource name, file path, or URL —
386 /// an **asset reference**, resolved and loaded by the renderer/host; never
387 /// embedded in the opcode stream).
388 pub const IMAGE_SOURCE: u16 = 0x1002;
389 /// **Draft.** Audio source (STRING asset reference, see `IMAGE_SOURCE`).
390 pub const AUDIO_SOURCE: u16 = 0x1033;
391 /// **Draft.** Video source (STRING asset reference, see `IMAGE_SOURCE`).
392 pub const VIDEO_SOURCE: u16 = 0x1034;
393 /// **Draft.** Media playback state (U32 0=pause, 1=play) on an `AUDIO`/`VIDEO`
394 /// node. When bound, the renderer reports `MEDIA_PLAY_STATE_CHANGED`.
395 pub const PLAYBACK_STATE: u16 = 0x1035;
396 /// **Draft.** Media position in seconds (F32) on an `AUDIO`/`VIDEO` node; a
397 /// change seeks. When bound, the renderer reports `MEDIA_TIME_UPDATED`.
398 pub const MEDIA_POSITION: u16 = 0x1036;
399 /// **Draft.** Media volume (F32 0..1) on an `AUDIO`/`VIDEO` node. When bound,
400 /// the renderer reports `MEDIA_VOLUME_CHANGED`.
401 pub const MEDIA_VOLUME: u16 = 0x1037;
402 /// **Draft.** Semantic icon name (STRING, canonical; spec/ICONS.md) on an
403 /// `ICON` node. The renderer maps it to its native icon set and falls back
404 /// to a renderer-default visual for unknown names.
405 pub const ICON_NAME: u16 = 0x1038;
406 pub const BORDER_WIDTH: u16 = 0x1003;
407 pub const BORDER_COLOR: u16 = 0x1004;
408 pub const BORDER_RADIUS: u16 = 0x1005;
409 pub const PADDING_STYLE: u16 = 0x1006;
410 pub const FONT_SIZE: u16 = 0x1007;
411 pub const FONT_WEIGHT: u16 = 0x1008;
412 pub const FONT_FAMILY: u16 = 0x1009;
413 pub const COLOR: u16 = 0x100A;
414 pub const WIDTH: u16 = 0x100B;
415 pub const HEIGHT: u16 = 0x100C;
416 pub const OPACITY: u16 = 0x100D;
417 pub const VISIBLE: u16 = 0x100E;
418 pub const Z_INDEX: u16 = 0x100F;
419 pub const CLIPS_TO_BOUNDS: u16 = 0x1010;
420 pub const PADDING: u16 = 0x1011;
421 pub const PADDING_TOP: u16 = 0x1012;
422 pub const PADDING_RIGHT: u16 = 0x1013;
423 pub const PADDING_BOTTOM: u16 = 0x1014;
424 pub const PADDING_LEFT: u16 = 0x1015;
425 /// `BORDER_EDGES` — a u32 bitmask (see [`crate::border_edges`]) selecting
426 /// which edges of a node's border are drawn.
427 pub const BORDER_EDGES: u16 = 0x1016;
428 // Text-format modifiers (draft, 0x1017–0x1020)
429 /// **Draft.** Font style (F32 enum): `Normal`=0, `Italic`=1.
430 pub const FONT_STYLE: u16 = 0x1017;
431 /// **Draft.** Font design (F32 enum): `Default`=0, `Serif`=1, `Rounded`=2,
432 /// `Monospaced`=3.
433 pub const FONT_DESIGN: u16 = 0x1018;
434 /// **Draft.** Font width (F32, 0.5–1.5, 1.0 default).
435 pub const FONT_WIDTH: u16 = 0x1019;
436 /// **Draft.** Kerning (F32 points). `.kerning(_:)`.
437 pub const KERNING: u16 = 0x101A;
438 /// **Draft.** Tracking (F32 points). `.tracking(_:)`.
439 pub const TRACKING: u16 = 0x101B;
440 /// **Draft.** Baseline offset (F32 points). `.baselineOffset(_:)`.
441 pub const BASELINE_OFFSET: u16 = 0x101C;
442 /// **Draft.** Line spacing (F32 points). `.lineSpacing(_:)`.
443 pub const LINE_SPACING: u16 = 0x101D;
444 /// **Draft.** Text case (F32 enum): `None`=0, `Uppercase`=1, `Lowercase`=2.
445 pub const TEXT_CASE: u16 = 0x101E;
446 /// **Draft.** Underline (U8 0/1). `.underline()`.
447 pub const UNDERLINE: u16 = 0x101F;
448 /// **Draft.** Strikethrough (U8 0/1). `.strikethrough()`.
449 pub const STRIKETHROUGH: u16 = 0x1020;
450 // Effect modifiers (draft, 0x1021–0x102C)
451 /// **Draft.** Shadow color (COLOR). `.shadow(color:...)`.
452 pub const SHADOW_COLOR: u16 = 0x1021;
453 /// **Draft.** Shadow radius (F32).
454 pub const SHADOW_RADIUS: u16 = 0x1022;
455 /// **Draft.** Shadow x offset (F32).
456 pub const SHADOW_X: u16 = 0x1023;
457 /// **Draft.** Shadow y offset (F32).
458 pub const SHADOW_Y: u16 = 0x1024;
459 /// **Draft.** Blur radius (F32). `.blur(radius:)`.
460 pub const BLUR_RADIUS: u16 = 0x1025;
461 /// **Draft.** Saturation (F32 0–1). `.saturation(_:)`.
462 pub const SATURATION: u16 = 0x1026;
463 /// **Draft.** Contrast (F32 0–1). `.contrast(_:)`.
464 pub const CONTRAST: u16 = 0x1027;
465 /// **Draft.** Brightness (F32 −1–1). `.brightness(_:)`.
466 pub const BRIGHTNESS: u16 = 0x1028;
467 /// **Draft.** Grayscale (F32 0–1). `.grayscale(_:)`.
468 pub const GRAYSCALE: u16 = 0x1029;
469 /// **Draft.** Hue rotation (F32 degrees). `.hueRotation(_:)`.
470 pub const HUE_ROTATION: u16 = 0x102A;
471 /// **Draft.** Color multiply (COLOR). `.colorMultiply(_:)`.
472 pub const COLOR_MULTIPLY: u16 = 0x102B;
473 /// **Draft.** Color invert (U8 0/1). `.colorInvert()`.
474 pub const COLOR_INVERT: u16 = 0x102C;
475 // Transform (draft)
476 /// **Draft.** Rotation (F32 degrees, counter-clockwise). `.rotationEffect(_:)`.
477 pub const ROTATION_DEGREES: u16 = 0x102D;
478 /// **Draft.** Uniform scale (F32). `.scaleEffect(_:)`.
479 pub const SCALE: u16 = 0x102E;
480 /// **Draft.** Whether the element participates in hit testing (U8 0/1).
481 /// `.allowsHitTesting(_:)`.
482 pub const ALLOWS_HIT_TESTING: u16 = 0x102F;
483 /// **Draft.** Accent/tint color (COLOR). `.tint(_:)`.
484 pub const TINT: u16 = 0x1030;
485 /// **Draft.** Presentation hint for structural swaps (F32 enum code):
486 /// `None`=0, `PlatformDefault`=1, `Fade`=2, `Slide`=3, `Scale`=4 — emitted
487 /// by a `NavigationContainer`/`Conditional.when` slot; the renderer may
488 /// animate the swap and must render normally when it ignores the hint.
489 pub const TRANSITION: u16 = 0x1031;
490 /// **Draft.** A `SIZE_THAT_FITS` slot's candidate fit-query (LIST): the
491 /// candidates' `minWidth` thresholds, ascending. The renderer measures its
492 /// allocated width and reports the derived fit index (`FIT_CHANGED`).
493 pub const FIT_QUERY: u16 = 0x1039;
494 /// **Draft.** Predefined typography (ENUM code, see [`crate::text_style`]):
495 /// `.font(.title2)` picks a whole design-system typography; the heading
496 /// styles (LargeTitle…Headline) imply a heading element on a `TEXT`.
497 /// Raw font modifiers (`FONT_SIZE`/`FONT_WEIGHT`/`FONT_FAMILY`/…) override
498 /// the visual on top and never imply a heading.
499 pub const TEXT_STYLE: u16 = 0x1032;
500 // Semantic (0x2000 range)
501 pub const ROLE: u16 = 0x2001;
502 pub const STATE: u16 = 0x2002;
503 pub const ENABLED: u16 = 0x2003;
504 pub const SELECTED: u16 = 0x2004;
505 /// `EVENT_LISTENERS` — a u32 bitmask (see [`crate::listener`]) declaring
506 /// which raw-input events a node wants the renderer to report. This is the
507 /// declarative signal the application sets so a renderer attaches native
508 /// input recognition to any element — not just buttons.
509 pub const EVENT_LISTENERS: u16 = 0x2005;
510 /// The current value of a value-bearing control (e.g. a `SLIDER`).
511 pub const VALUE: u16 = 0x2006;
512 /// The inclusive minimum of a value-bearing control's range (e.g. a `SLIDER`).
513 pub const MIN_VALUE: u16 = 0x2007;
514 /// The inclusive maximum of a value-bearing control's range (e.g. a `SLIDER`).
515 pub const MAX_VALUE: u16 = 0x2008;
516 /// The caption label of a `TEXT_FIELD` (a `STRING` property).
517 pub const LABEL: u16 = 0x200A;
518 /// The placeholder text of a `TEXT_FIELD` (a `STRING` property).
519 pub const PROMPT: u16 = 0x200B;
520 /// **Draft.** Stepper increment per press (F32).
521 pub const STEP_VALUE: u16 = 0x2009;
522 /// **Draft.** Control size (F32 enum): `Small`=0, `Regular`=1, `Large`=2.
523 pub const CONTROL_SIZE: u16 = 0x200C;
524 /// **Draft.** Masked-input token for a `TEXT_FIELD` (U8 0/1).
525 pub const IS_SECURE: u16 = 0x200D;
526 /// **Draft.** Determinate progress fraction of a `PROGRESS_VIEW` (F32).
527 pub const PROGRESS: u16 = 0x200E;
528 /// **Draft.** Indeterminate (activity) token of a `PROGRESS_VIEW` (U8 0/1).
529 pub const IS_INDETERMINATE: u16 = 0x200F;
530 /// **Draft.** Selected child index of a `PICKER`/`MENU` (U32).
531 pub const SELECTION: u16 = 0x2010;
532 /// **Draft.** Current color of a `COLOR_PICKER` (COLOR).
533 pub const COLOR_VALUE: u16 = 0x2012;
534 /// **Draft.** `DATE_PICKER` presentation (F32 enum): `Date`=0, `Time`=1,
535 /// `DateAndTime`=2.
536 pub const DATE_PICKER_MODE: u16 = 0x2013;
537 /// **Draft.** `PICKER` presentation (F32 enum): `Menu`=0, `Segmented`=1,
538 /// `Wheel`=2, `RadioGroup`=3.
539 pub const PICKER_STYLE: u16 = 0x2014;
540 /// **Draft.** Bound callback id; gates event delivery for this node.
541 pub const ACTION_ID: u16 = 0x2016;
542 /// **Draft.** Two-way binding id (control value ↔ app state).
543 pub const BINDING_ID: u16 = 0x2017;
544 /// **Draft.** Visual style token for a `TOGGLE` (F32 enum code):
545 /// `Switch`=0, `Checkbox`=1, `Button`=2.
546 pub const TOGGLE_STYLE: u16 = 0x2018;
547 /// **Draft.** Current navigation path (STRING, arenaRef), emitted by a
548 /// `NavigationContainer` slot; drives web URL sync.
549 pub const ROUTE: u16 = 0x2019;
550 /// **Draft.** Navigation back-stack depth (U32: number of destinations in
551 /// the app's path, including the current one — `push` increments, `pop`
552 /// decrements, `replace` leaves it unchanged). Emitted by a
553 /// `NavigationContainer` slot so native navigation adapters can reconcile
554 /// their page stack by depth (push/pop/replace/reset) instead of route
555 /// tags alone. See `spec/DSL.md §4.5` and `spec/MODIFIERS.md §6`.
556 pub const NAV_DEPTH: u16 = 0x201A;
557 /// **Draft.** Navigation chrome mode (F32 enum code) on a
558 /// `NavigationContainer` slot: `PlatformDefault`=0 (the renderer supplies
559 /// the navigation chrome — the native container where one exists, a
560 /// renderer-drawn back affordance on DOM), `Custom`=1 (the developer owns
561 /// all navigation UI and the renderer adds none). A container emits this
562 /// once at mount (it never varies per destination). See `spec/DSL.md §4.5`
563 /// and `spec/MODIFIERS.md §6`.
564 pub const NAV_CHROME: u16 = 0x201B;
565}
566
567/// The protocol value type for a property id.
568///
569/// Color-valued properties (COLOR, BACKGROUND_COLOR, BORDER_COLOR) are emitted
570/// with the `COLOR` value type; `EVENT_LISTENERS` and `BORDER_EDGES` are raw
571/// `U32` bitmasks; `LABEL`/`PROMPT`/`FONT_FAMILY` are `STRING`; `LINE_LIMIT`,
572/// `ACTION_ID`, and `BINDING_ID` are `U32`; all other constraint/style
573/// properties are `F32` (enum-valued properties like `ALIGNMENT`/`TOGGLE_STYLE`
574/// carry their numeric code as an `F32`). See `spec/MODIFIERS.md` for the
575/// canonical mapping.
576pub fn value_type_for(prop: u16) -> u8 {
577 match prop {
578 property_id::COLOR
579 | property_id::BACKGROUND_COLOR
580 | property_id::BORDER_COLOR
581 | property_id::COLOR_VALUE
582 | property_id::COLOR_MULTIPLY
583 | property_id::SHADOW_COLOR
584 | property_id::TINT => value_type::COLOR,
585 property_id::EVENT_LISTENERS | property_id::BORDER_EDGES => value_type::U32,
586 property_id::SELECTED
587 | property_id::IS_SECURE
588 | property_id::IS_INDETERMINATE
589 | property_id::VISIBLE
590 | property_id::ENABLED
591 | property_id::CLIPS_TO_BOUNDS
592 | property_id::UNDERLINE
593 | property_id::STRIKETHROUGH
594 | property_id::COLOR_INVERT
595 | property_id::ALLOWS_HIT_TESTING
596 | property_id::FIXED_SIZE_HORIZONTAL
597 | property_id::FIXED_SIZE_VERTICAL => value_type::U8,
598 property_id::LABEL
599 | property_id::PROMPT
600 | property_id::FONT_FAMILY
601 | property_id::IMAGE_SOURCE
602 | property_id::AUDIO_SOURCE
603 | property_id::VIDEO_SOURCE
604 | property_id::ICON_NAME
605 | property_id::ROUTE => value_type::STRING,
606 property_id::LINE_LIMIT
607 | property_id::SELECTION
608 | property_id::ACTION_ID
609 | property_id::BINDING_ID
610 | property_id::NAV_DEPTH => value_type::U32,
611 _ => value_type::F32,
612 }
613}
614
615/// Special size constants for `WIDTH` / `HEIGHT`.
616pub mod size {
617 /// Fill the available space (parent main-axis remainder).
618 pub const FILL: f32 = -1.0;
619 /// Hug content (size to the intrinsic content).
620 pub const HUG_CONTENT: f32 = -2.0;
621}
622
623/// Semantic-role codes for the `ROLE` semantic property (`0x2001`).
624///
625/// Roles are protocol-semantic (carried as an `F32` enum code; see
626/// `spec/OPCODE.md` §semantic properties). The catalog is **semantic structure
627/// only** — interactive/control roles (button, link, checkbox, …) are NOT roles:
628/// they are intrinsic to the control components (a `BUTTON` renders as
629/// `<button>`, a `TOGGLE` as `<input type="checkbox">`, a `MENU` as
630/// `role="menu"`), and a custom-looking button is expressed with `Button` +
631/// `ButtonStyle`. The web renderer maps each semantic role onto its native
632/// element. Values MUST NOT be renumbered once released (wire version stays 1).
633pub mod role {
634 /// No semantic role (the default).
635 pub const NONE: u8 = 0;
636 /// A heading (ARIA `heading`; the HTML renderer uses `<hN>`, the level
637 /// driven by a `TEXT_STYLE` typography when present, default `<h2>`).
638 pub const HEADER: u8 = 1;
639 /// A paragraph (HTML `<p>`).
640 pub const PARAGRAPH: u8 = 2;
641 /// A list container (the HTML renderer uses `<ul>`).
642 pub const LIST: u8 = 3;
643 /// An item within a list (HTML `<li>`).
644 pub const LIST_ITEM: u8 = 4;
645 /// A summarising/complementary region (HTML `<section>`).
646 pub const SUMMARY: u8 = 5;
647 /// Site banner (HTML `<header>`).
648 pub const BANNER: u8 = 6;
649 /// Site navigation (HTML `<nav>`).
650 pub const NAVIGATION: u8 = 7;
651 /// The page's main content (HTML `<main>`).
652 pub const MAIN: u8 = 8;
653 /// Site footer / content info (HTML `<footer>`).
654 pub const CONTENT_INFO: u8 = 9;
655 /// Complementary/aside content (HTML `<aside>`).
656 pub const COMPLEMENTARY: u8 = 10;
657 /// A self-contained article (HTML `<article>`).
658 pub const ARTICLE: u8 = 11;
659 /// A thematically grouped section (HTML `<section>`).
660 pub const SECTION: u8 = 12;
661 /// A search region (HTML `<search>`).
662 pub const SEARCH: u8 = 13;
663}
664
665/// Predefined typography codes for the `TEXT_STYLE` property (see
666/// `spec/MODIFIERS.md`). Each value selects a whole typography from the design
667/// system (font size/weight/design). The **heading** styles (LargeTitle through
668/// Headline) imply a heading element when applied to a `TEXT`: the renderer
669/// emits `<h1>`–`<h5>` (the level comes from the style — no `ROLE` needed). The
670/// non-heading styles render as plain `<span>` text. A raw font modifier
671/// (`FONT_SIZE`, `FONT_WEIGHT`, `FONT_FAMILY`, …) never implies a heading — it
672/// only overrides the typography's visual.
673pub mod text_style {
674 /// The largest title style (heading level 1).
675 pub const LARGE_TITLE: u8 = 0;
676 /// A primary title (heading level 2).
677 pub const TITLE: u8 = 1;
678 /// A secondary title (heading level 3).
679 pub const TITLE2: u8 = 2;
680 /// A tertiary title (heading level 4).
681 pub const TITLE3: u8 = 3;
682 /// A headline (heading level 5).
683 pub const HEADLINE: u8 = 4;
684 /// A sub-headline (NOT a heading — plain `<span>` text).
685 pub const SUBHEADLINE: u8 = 5;
686 /// Body text (the default).
687 pub const BODY: u8 = 6;
688 /// A callout (slightly larger than body).
689 pub const CALLOUT: u8 = 7;
690 /// Footnote text.
691 pub const FOOTNOTE: u8 = 8;
692 /// Caption text.
693 pub const CAPTION: u8 = 9;
694 /// A second, smaller caption.
695 pub const CAPTION2: u8 = 10;
696}
697
698/// Canonical icon names (`ICON_NAME` values; spec/ICONS.md).
699///
700/// The spec is the **vocabulary contract only**: these names are the protocol
701/// `ICON_NAME` surface every renderer understands. The canonical-name →
702/// native-glyph mapping is **renderer-owned** (Adwaita on GTK, Remix filled on
703/// the web, SF Symbols on Apple) and lives in each renderer — never here, never
704/// in the spec.
705pub mod icon {
706 pub const HOME: &str = "home";
707 pub const SETTINGS: &str = "settings";
708 pub const SEARCH: &str = "search";
709 pub const MENU: &str = "menu";
710 pub const CLOSE: &str = "close";
711 pub const CLOUD: &str = "cloud";
712 pub const CHEVRON_LEFT: &str = "chevron-left";
713 pub const CHEVRON_RIGHT: &str = "chevron-right";
714 pub const CHEVRON_UP: &str = "chevron-up";
715 pub const CHEVRON_DOWN: &str = "chevron-down";
716 pub const ARROW_LEFT: &str = "arrow-left";
717 pub const ARROW_RIGHT: &str = "arrow-right";
718 pub const ADD: &str = "add";
719 pub const REMOVE: &str = "remove";
720 pub const CHECK: &str = "check";
721 pub const EDIT: &str = "edit";
722 pub const DELETE: &str = "delete";
723 pub const SAVE: &str = "save";
724 pub const SHARE: &str = "share";
725 pub const DOWNLOAD: &str = "download";
726 pub const UPLOAD: &str = "upload";
727 pub const REFRESH: &str = "refresh";
728 pub const PLAY: &str = "play";
729 pub const PAUSE: &str = "pause";
730 pub const STOP: &str = "stop";
731 pub const SKIP_BACK: &str = "skip-back";
732 pub const SKIP_FORWARD: &str = "skip-forward";
733 pub const VOLUME: &str = "volume";
734 pub const VOLUME_MUTE: &str = "volume-mute";
735 pub const SHUFFLE: &str = "shuffle";
736 pub const REPEAT: &str = "repeat";
737 pub const INFO: &str = "info";
738 pub const WARNING: &str = "warning";
739 pub const ERROR: &str = "error";
740 pub const SUCCESS: &str = "success";
741 pub const HEART: &str = "heart";
742 pub const STAR: &str = "star";
743 pub const USER: &str = "user";
744 pub const USERS: &str = "users";
745 pub const LOCK: &str = "lock";
746 pub const LOGOUT: &str = "logout";
747 pub const BELL: &str = "bell";
748 pub const FOLDER: &str = "folder";
749 pub const FILE: &str = "file";
750 pub const IMAGE: &str = "image";
751 pub const MUSIC: &str = "music";
752 pub const GRID: &str = "grid";
753 pub const LIST: &str = "list";
754 pub const FILTER: &str = "filter";
755
756 /// Every canonical name, in deterministic (spec, spec/ICONS.md) order.
757 pub const NAMES: &[&str] = &[
758 HOME, SETTINGS, SEARCH, MENU, CLOSE, CLOUD, CHEVRON_LEFT, CHEVRON_RIGHT,
759 CHEVRON_UP, CHEVRON_DOWN, ARROW_LEFT, ARROW_RIGHT, ADD, REMOVE, CHECK,
760 EDIT, DELETE, SAVE, SHARE, DOWNLOAD, UPLOAD, REFRESH, PLAY, PAUSE, STOP,
761 SKIP_BACK, SKIP_FORWARD, VOLUME, VOLUME_MUTE, SHUFFLE, REPEAT, INFO,
762 WARNING, ERROR, SUCCESS, HEART, STAR, USER, USERS, LOCK, LOGOUT, BELL,
763 FOLDER, FILE, IMAGE, MUSIC, GRID, LIST, FILTER,
764 ];
765
766 /// Whether `name` is a canonical `ICON_NAME` in the spec vocabulary.
767 pub fn is_canonical(name: &str) -> bool {
768 NAMES.contains(&name)
769 }
770}
771
772/// Sentinel for append positions (`index = u32::MAX`).
773pub const APPEND: u32 = u32::MAX;