@solidrt/components 0.0.9 → 0.0.11

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/AGENTS.md ADDED
@@ -0,0 +1,67 @@
1
+ # @solidrt/components - agent notes
2
+
3
+ Higher-level components built on @solidrt/core primitives. Optional: an app can
4
+ be built with core primitives alone. For the underlying element model, events,
5
+ reactivity, and how to run/verify, see @solidrt/core and @solidrt/cli (their
6
+ AGENTS.md). Full prop tables are in this package's README.
7
+
8
+ ## Install
9
+
10
+ ```sh
11
+ bun add @solidrt/components # peers: @solidrt/core, @solidjs/signals
12
+ ```
13
+
14
+ ## Props: layout vs style (the non-obvious split)
15
+
16
+ Most components group props into two objects, plus top-level event handlers:
17
+
18
+ - `layout={{...}}` - the core LayoutProps: flex/grid, sizing, padding/margin,
19
+ position. For `Text`, also the font fields (fontSize, fontWeight, ...).
20
+ Changing these relayouts.
21
+ - `style={{...}}` - paint only, never affects layout: `backgroundColor`,
22
+ `borderColor`, `borderWidth`, `borderRadius`, `color` (Text), and the
23
+ transform `x`/`y`/`rotate`/`scale`.
24
+ - Event handlers (`onPointerDown`, `onKeyDown`, ...) are top-level props, NOT
25
+ inside `layout`/`style`.
26
+
27
+ ## Exports
28
+
29
+ - `Window` - root surface; renders a core `<window>`, so `render()` accepts it.
30
+ Applies `layout` and `style.backgroundColor` only (a window cannot be
31
+ transformed or bordered). Also: `title`, `fullscreen`, `vsync`, `fps`.
32
+ - `View` - general box; draws a background/border when the matching `style`
33
+ props are set.
34
+ - `Text` - text in a layout box; font fields go in `layout`, `color` in `style`.
35
+ - `Image` - fetches/decodes/uploads an image: `src: string | Uint8Array`.
36
+ - `TextInput` - single-line input; `value`/`onInput`/`onSubmit`, controlled or
37
+ uncontrolled, plus `placeholder`, `maxLength`, `autoFocus`, `disabled`.
38
+ - `SafeArea` - pads children clear of system UI (notches, status bars); top and
39
+ bottom on by default, pass `false`/a number per edge.
40
+ - `theme` / `setTheme` - shared appearance (colors, spacing, radii, font sizes);
41
+ call `setTheme({...})` to override defaults.
42
+
43
+ ## Minimal app (verified to render)
44
+
45
+ ```tsx
46
+ import { render } from "@solidrt/core"
47
+ import { Window, View, Text } from "@solidrt/components"
48
+ import { createSignal } from "@solidjs/signals"
49
+
50
+ function App() {
51
+ let [count, setCount] = createSignal(0)
52
+ return (
53
+ <Window title="App" style={{ backgroundColor: "#0b0f17" }}
54
+ layout={{ flexDirection: "column", alignItems: "center", justifyContent: "center", gap: 24 }}>
55
+ <Text layout={{ fontSize: 48, fontWeight: 800 }} style={{ color: "#1f6feb" }}>
56
+ {count()}
57
+ </Text>
58
+ <View onPointerDown={() => setCount((c) => c + 1)}
59
+ layout={{ padding: 16 }} style={{ backgroundColor: "#1f6feb", borderRadius: 12 }}>
60
+ <Text style={{ color: "#ffffff" }}>increment</Text>
61
+ </View>
62
+ </Window>
63
+ )
64
+ }
65
+
66
+ render(() => <App />)
67
+ ```
package/README.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  A collection of components for [SolidRT](https://github.com/wellawaretech/solidrt) apps.
4
4
 
5
+ > LLM agents: see [AGENTS.md](./AGENTS.md) for a dense, self-contained quickstart.
6
+
5
7
  ## Installation
6
8
 
7
9
  ```sh
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solidrt/components",
3
- "version": "0.0.9",
3
+ "version": "0.0.11",
4
4
  "license": "MIT",
5
5
  "author": "Antoine van Wel",
6
6
  "type": "module",
@@ -10,11 +10,10 @@
10
10
  },
11
11
  "files": [
12
12
  "src/",
13
- "README.md",
14
- "LICENSE"
13
+ "AGENTS.md"
15
14
  ],
16
15
  "peerDependencies": {
17
16
  "@solidjs/signals": "2.0.0-beta.14",
18
- "@solidrt/core": "0.0.9"
17
+ "@solidrt/core": "0.0.11"
19
18
  }
20
19
  }
package/src/image.tsx CHANGED
@@ -1,4 +1,4 @@
1
- import { createSignal, onCleanup } from "@solidjs/signals"
1
+ import { createSignal, createEffect, onCleanup } from "@solidjs/signals"
2
2
  import { decodeImage, createTexture } from "@solidrt/core/gpu"
3
3
  import type { LayoutProps, PointerProps } from "@solidrt/core"
4
4
  import type { StyleProps } from "./types"
@@ -12,22 +12,45 @@ export interface ImageProps extends PointerProps {
12
12
  //TODO onLoad, onError
13
13
  //TODO release texture in onCleanup
14
14
  export function Image(props: ImageProps) {
15
- let [res] = createSignal(async () => {
16
- let bytes: Uint8Array
17
- if (typeof props.src === "string") {
18
- let response = await fetch(props.src)
19
- bytes = await response.bytes()
20
- } else {
21
- bytes = props.src
22
- }
23
- let { data, width, height } = decodeImage(bytes)
24
- let id = createTexture(data, width, height)
25
- return { id, width, height }
26
- })
15
+ let [res, setRes] = createSignal<{ id: number; width: number; height: number }>()
16
+
17
+ // Load (and decode) whenever src changes. A url is fetched; bytes are used
18
+ // directly. The async result is pushed into the signal so the texture shows
19
+ // once ready; a stale flag drops results from a superseded src.
20
+ createEffect(
21
+ () => props.src,
22
+ (source) => {
23
+ let stale = false
24
+
25
+ ;(async () => {
26
+ let bytes: Uint8Array
27
+ if (typeof source === "string") {
28
+ let response = await fetch(source)
29
+ bytes = await response.bytes()
30
+ } else {
31
+ bytes = source
32
+ }
33
+ if (stale) return
34
+ let { data, width, height } = decodeImage(bytes)
35
+ let id = createTexture(data, width, height)
36
+ setRes({ id, width, height })
37
+ })()
38
+
39
+ return () => {
40
+ stale = true
41
+ }
42
+ },
43
+ )
27
44
 
28
45
  let src = () => res()?.id
29
46
  let hasBorder = () => (props.style?.borderWidth ?? 0) > 0
30
47
 
48
+ // A texture sizes from its own width/height (not the box around it), so the
49
+ // numeric layout dimensions are forwarded to it. Omitting height lets the
50
+ // texture follow the image's intrinsic aspect ratio.
51
+ let texW = () => (typeof props.layout?.width === "number" ? props.layout.width : undefined)
52
+ let texH = () => (typeof props.layout?.height === "number" ? props.layout.height : undefined)
53
+
31
54
  onCleanup(() => {
32
55
  //TODO release texture
33
56
  })
@@ -35,6 +58,8 @@ export function Image(props: ImageProps) {
35
58
  return (
36
59
  <view
37
60
  {...props.layout}
61
+ overflow={props.style?.borderRadius != null ? "hidden" : props.layout?.overflow}
62
+ clipRadius={props.style?.borderRadius}
38
63
  x={props.style?.x}
39
64
  y={props.style?.y}
40
65
  scale={props.style?.scale}
@@ -53,9 +78,9 @@ export function Image(props: ImageProps) {
53
78
  pointerEvents={props.pointerEvents}
54
79
  >
55
80
  {props.style?.backgroundColor != null ? (
56
- <d-rect color={props.style.backgroundColor} radius={props.style?.borderRadius} />
81
+ <d-rect color={props.style?.backgroundColor} radius={props.style?.borderRadius} />
57
82
  ) : null}
58
- <texture src={src()} />
83
+ <texture src={src()} width={texW()} height={texH()} />
59
84
  {hasBorder() ? (
60
85
  <d-rect
61
86
  drawStyle="stroke"