@solidrt/core 0.0.23 → 0.0.24

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/jsx-runtime.d.ts CHANGED
@@ -7,7 +7,6 @@ import type {
7
7
  ViewProps,
8
8
  TextProps,
9
9
  TextureProps,
10
- AudioProps,
11
10
  LayoutProps,
12
11
  Element as CoreElement,
13
12
  ElementChildrenAttribute as CoreElementChildrenAttribute
@@ -40,7 +39,6 @@ export namespace JSX {
40
39
  path: PathProps & LayoutProps & ElementRef
41
40
  svg: SvgProps & LayoutProps & ElementRef
42
41
  texture: TextureProps & LayoutProps & ElementRef
43
- audio: AudioProps & ElementRef
44
42
  "d-view": ViewProps & ElementRef
45
43
  "d-rect": RectProps & ElementRef
46
44
  "d-oval": OvalProps & ElementRef
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solidrt/core",
3
- "version": "0.0.23",
3
+ "version": "0.0.24",
4
4
  "license": "MIT",
5
5
  "author": "Antoine van Wel",
6
6
  "type": "module",
@@ -26,7 +26,7 @@
26
26
  "colord": "^2.9.3"
27
27
  },
28
28
  "devDependencies": {
29
- "@solidrt/flux-types": "0.0.23"
29
+ "@solidrt/flux-types": "0.0.24"
30
30
  },
31
31
  "peerDependencies": {
32
32
  "@solidjs/signals": "2.0.0-beta.15",
package/src/color.ts CHANGED
@@ -43,6 +43,11 @@ type Stop = { offset: number; color: number }
43
43
  // element's box), so one gradient can be reused on elements of any size. Branded
44
44
  // so the renderer can tell it from a solid color string. The object crosses to
45
45
  // the runtime as-is and is decoded by key (see properties/paint.rs).
46
+ //
47
+ // These 0..1 coords are deliberately their own normalized space, NOT the pixel/
48
+ // `pct()` length vocabulary used by layout and transformOrigin: a gradient's
49
+ // position is naturally a fraction (like a stop offset), so 0..1 reads cleaner
50
+ // than pct(0)..pct(100). Do not "unify" them onto pct().
46
51
  export type Gradient =
47
52
  | { readonly __gradient: "linear"; x0: number; y0: number; x1: number; y1: number; stops: Stop[] }
48
53
  | { readonly __gradient: "radial"; cx: number; cy: number; r: number; circle: boolean; stops: Stop[] }
@@ -10,6 +10,14 @@ import { windowSize, safeArea, displayScale, windowFocused, keyboardHeight } fro
10
10
  // been seen this session. Seen-flags only ever go from false to true, so a
11
11
  // capability derived from them can appear mid-session (e.g. the first mouse
12
12
  // move) but never flickers away.
13
+ //
14
+ // `ownedWrite: true` on the signals below: each is lazily created the first
15
+ // time its ensure* function runs, which can happen inside a tracked scope
16
+ // (e.g. a memo's first read of env.inputDevices). Sticky events replay their
17
+ // cached value synchronously on subscribe (srt:events' on()), so that same
18
+ // call can immediately write the signal it just created. That's a legitimate
19
+ // internal-state write, not a stray write escaping a computation, so it opts
20
+ // out of the write-in-owned-scope guard.
13
21
 
14
22
  /** Connected input device classes, as reported by the runtime. */
15
23
  export interface InputDevices {
@@ -26,7 +34,7 @@ let devicesAccessor: (() => InputDevices | undefined) | undefined
26
34
 
27
35
  function ensureDevicesState() {
28
36
  if (devicesAccessor) return
29
- let [devices, setDevices] = createSignal<InputDevices | undefined>(undefined)
37
+ let [devices, setDevices] = createSignal<InputDevices | undefined>(undefined, { ownedWrite: true })
30
38
  // Sticky: the current state replays on subscribe, so the first read already
31
39
  // sees it on runtimes that report devices.
32
40
  on("inputDevices", (d: InputDevices) => {
@@ -39,7 +47,7 @@ let systemThemeAccessor: (() => SystemTheme) | undefined
39
47
 
40
48
  function ensureSystemThemeState() {
41
49
  if (systemThemeAccessor) return
42
- let [theme, setTheme] = createSignal<SystemTheme>("unknown")
50
+ let [theme, setTheme] = createSignal<SystemTheme>("unknown", { ownedWrite: true })
43
51
  on("systemTheme", (e: { theme?: SystemTheme }) => setTheme(e.theme ?? "unknown"))
44
52
  systemThemeAccessor = theme
45
53
  }
@@ -48,7 +56,7 @@ let orientationAccessor: (() => Orientation) | undefined
48
56
 
49
57
  function ensureOrientationState() {
50
58
  if (orientationAccessor) return
51
- let [orientation, setOrientation] = createSignal<Orientation>("unknown")
59
+ let [orientation, setOrientation] = createSignal<Orientation>("unknown", { ownedWrite: true })
52
60
  on("displayOrientation", (e: { orientation?: Orientation }) => {
53
61
  setOrientation(e.orientation ?? "unknown")
54
62
  })
@@ -59,7 +67,7 @@ let textScaleAccessor: (() => number) | undefined
59
67
 
60
68
  function ensureTextScaleState() {
61
69
  if (textScaleAccessor) return
62
- let [scale, setScale] = createSignal(1)
70
+ let [scale, setScale] = createSignal(1, { ownedWrite: true })
63
71
  // Sticky, like systemTheme. Guard nonsense values: a runtime bug reporting
64
72
  // 0 or a negative would otherwise collapse all text.
65
73
  on("textScale", (e: { scale?: number }) => {
package/src/index.ts CHANGED
@@ -32,11 +32,16 @@ export type {
32
32
  PathProps,
33
33
  TextProps,
34
34
  TextureProps,
35
- AudioProps,
36
35
  Color,
36
+ Pct,
37
37
  } from "./types"
38
38
  export type { MeasureTextOptions } from "flux:rendertree"
39
39
 
40
+ // A percentage value for dimensional props (e.g. transformOrigin): `pct(50)` is
41
+ // half the element box. Keeps percentages a first-class branded value rather
42
+ // than a string that has to be parsed - a bare number stays pixels.
43
+ export let pct = (v: number): import("./types").Pct => ({ __unit: "pct", v })
44
+
40
45
  // --- Authoring-surface re-exports -------------------------------------------
41
46
  // A SolidRT app is built from three substrate packages: @solidjs/signals
42
47
  // (reactivity), solid-js (control-flow components), and @solidjs/universal (the
package/src/types.d.ts CHANGED
@@ -44,9 +44,9 @@ type Children = Element
44
44
  // alone (e.g. shorthand-vs-longhand precedence, a subsetted value range).
45
45
 
46
46
  interface FlexboxProps {
47
- gap?: number
48
- rowGap?: number
49
- columnGap?: number
47
+ gap?: LengthPercentage
48
+ rowGap?: LengthPercentage
49
+ columnGap?: LengthPercentage
50
50
  /** Shorthand; overridden by flexGrow/flexShrink/flexBasis when they're also set. */
51
51
  flex?: number | "none" | "auto" | (string & {})
52
52
  flexGrow?: number
@@ -74,8 +74,14 @@ interface GridProps {
74
74
  gridTemplateRows?: string
75
75
  }
76
76
 
77
- /** A layout length: a bare number is pixels, plus "auto" and percent strings. */
78
- type Dimension = number | "auto" | `${number}%`
77
+ /**
78
+ * A layout length: a bare number is pixels, `pct(n)` is a percentage of the
79
+ * containing block, plus "auto" and the `"50%"` string form (kept for paste).
80
+ */
81
+ type Dimension = number | Pct | "auto" | `${number}%`
82
+
83
+ /** Like {@link Dimension} without "auto" (e.g. gap, which has no auto value). */
84
+ type LengthPercentage = number | Pct | `${number}%`
79
85
 
80
86
  export interface LayoutProps extends FlexboxProps, GridProps {
81
87
  display?: "block" | "flex" | "grid" | "none"
@@ -131,6 +137,16 @@ export interface PaintProps {
131
137
  strokeWidth?: number
132
138
  }
133
139
 
140
+ /** A percentage value, from `pct(50)`. Resolves against the element box. */
141
+ export type Pct = { readonly __unit: "pct"; v: number }
142
+
143
+ // One axis of the transform origin (the point rotate/scale/3D pivot around),
144
+ // split per axis to match the engine's x/y prop convention. A bare number is
145
+ // pixels; `pct(50)` is a fraction of the box, so a percentage origin tracks the
146
+ // layout size with no reactive wiring. Unset defaults to the axis center.
147
+ type OriginX = number | Pct | "left" | "center" | "right"
148
+ type OriginY = number | Pct | "top" | "center" | "bottom"
149
+
134
150
  export interface TransformProps {
135
151
  rotate?: number
136
152
  scale?: number
@@ -149,8 +165,8 @@ export interface TransformProps {
149
165
  perspective?: number
150
166
  x?: number
151
167
  y?: number
152
- cx?: number
153
- cy?: number
168
+ originX?: OriginX
169
+ originY?: OriginY
154
170
  // Group opacity in 0..1: children are composited together, then faded as a
155
171
  // whole (CSS `opacity`). Does not affect hit testing.
156
172
  opacity?: number
@@ -212,7 +228,7 @@ interface Position {
212
228
 
213
229
  // Primitives
214
230
 
215
- export interface WindowProps extends LayoutProps {
231
+ export interface WindowProps extends LayoutProps, PointerProps {
216
232
  children?: Children
217
233
  title?: string
218
234
  fullscreen?: boolean
@@ -242,16 +258,6 @@ export interface ViewProps extends LayoutProps, TransformProps, PointerProps {
242
258
  repaintBoundary?: boolean | "snapshot"
243
259
  }
244
260
 
245
- /**
246
- * Not implemented: there is no native `audio` element kind yet, so using
247
- * `<audio>` panics ("unknown node kind: audio"). Typed ahead of the backing
248
- * work; treat this interface as a plan, not a working API.
249
- */
250
- export interface AudioProps {
251
- src?: Uint8Array
252
- play?: number
253
- }
254
-
255
261
  // draw primitives
256
262
 
257
263
  export interface RectProps extends Position, PaintProps, PointerProps {
@@ -309,7 +315,7 @@ export interface TextProps extends Position, PaintProps, PointerProps {
309
315
  maxLines?: number
310
316
  }
311
317
 
312
- export interface TextureProps extends Position {
318
+ export interface TextureProps extends Position, PointerProps {
313
319
  src?: number
314
320
  w?: number
315
321
  h?: number
package/src/window.ts CHANGED
@@ -93,7 +93,9 @@ export function onResize(fn: (data: ResizeEvent) => void) {
93
93
  // Singleton accessors over the same events as onResize / onWindowFocus. There
94
94
  // is one window, so these are bare accessors rather than a createX instance.
95
95
  // Lazily subscribed on first read (resize is sticky, so the first read sees the
96
- // current value); app-lifetime, so no onCleanup.
96
+ // current value); app-lifetime, so no onCleanup. `ownedWrite: true` on the
97
+ // signals below is the sticky-replay-into-a-tracked-scope case explained on
98
+ // the ensure* functions in environment.ts.
97
99
 
98
100
  let sizeAccessor: (() => { width: number; height: number }) | undefined
99
101
  let safeAreaAccessor: (() => SafeArea) | undefined
@@ -101,9 +103,9 @@ let displayScaleAccessor: (() => number) | undefined
101
103
 
102
104
  function ensureResizeState() {
103
105
  if (sizeAccessor) return
104
- let [size, setSize] = createSignal({ width: 0, height: 0 })
105
- let [safe, setSafe] = createSignal<SafeArea>({ top: 0, left: 0, right: 0, bottom: 0 })
106
- let [scale, setScale] = createSignal(1)
106
+ let [size, setSize] = createSignal({ width: 0, height: 0 }, { ownedWrite: true })
107
+ let [safe, setSafe] = createSignal<SafeArea>({ top: 0, left: 0, right: 0, bottom: 0 }, { ownedWrite: true })
108
+ let [scale, setScale] = createSignal(1, { ownedWrite: true })
107
109
  on("resize", (e: ResizeEvent) => {
108
110
  setSize({ width: e.width, height: e.height })
109
111
  setSafe(e.safeArea)