@solidrt/core 0.0.54 → 0.0.56
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 +100 -22
- package/agents/painting.md +36 -12
- package/agents/performance.md +36 -6
- package/docs/reference/detached.md +20 -10
- package/docs/reference/drawing.md +10 -3
- package/docs/reference/elements.md +3 -1
- package/docs/reference/gpu.md +12 -1
- package/docs/reference/layout.md +28 -0
- package/docs/reference/text.md +34 -0
- package/examples/README.md +5 -0
- package/examples/detached-positioning.tsx +3 -1
- package/examples/line-points.tsx +21 -0
- package/examples/stagger.tsx +45 -0
- package/examples/text-flow.tsx +90 -0
- package/examples/text-glyphs.tsx +73 -0
- package/examples/view-design-size.tsx +5 -0
- package/package.json +6 -5
- package/src/color.ts +17 -0
- package/src/core.ts +28 -7
- package/src/environment.ts +87 -69
- package/src/gamepad.ts +10 -8
- package/src/gpu.ts +130 -21
- package/src/index.ts +14 -4
- package/src/pan.ts +20 -5
- package/src/renderer.ts +16 -2
- package/src/runtime-modules.d.ts +7 -7
- package/src/svg.ts +3 -2
- package/src/text-input.ts +43 -8
- package/src/transform.ts +52 -23
- package/src/types.d.ts +158 -44
- package/src/window.ts +54 -38
package/src/transform.ts
CHANGED
|
@@ -26,14 +26,18 @@ const ENGAGE = 0.6
|
|
|
26
26
|
const QUIET_SMOOTH = 0.19
|
|
27
27
|
|
|
28
28
|
export type TransformDelta = {
|
|
29
|
-
/** Focal-point movement since the previous frame,
|
|
29
|
+
/** Focal-point movement since the previous frame, in the handler node's
|
|
30
|
+
* PARENT frame (the frame its own x/y live in: window pixels under no
|
|
31
|
+
* scaling ancestor, design pixels under a designSize fit), so it applies
|
|
32
|
+
* 1:1 to the node or to content inside it. */
|
|
30
33
|
dx: number
|
|
31
34
|
dy: number
|
|
32
35
|
/** Multiplicative span change since the previous frame (1 = unchanged, >1 = fingers spreading). */
|
|
33
36
|
scale: number
|
|
34
37
|
/** Rotation of the pointer pair since the previous frame, radians (0 with a single pointer). */
|
|
35
38
|
rotation: number
|
|
36
|
-
/** Current focal point in
|
|
39
|
+
/** Current focal point in the handler node's LOCAL frame (its own
|
|
40
|
+
* pixels) - the zoom-about anchor for content inside it. */
|
|
37
41
|
x: number
|
|
38
42
|
y: number
|
|
39
43
|
/** How many pointers are down right now. Consumers that give one- and
|
|
@@ -106,12 +110,25 @@ export interface TransformOptions {
|
|
|
106
110
|
// path, so an active transform survives leaving the node or the window.
|
|
107
111
|
// cancel() is the external-cancel hook; it ends an active gesture without
|
|
108
112
|
// onTransformEnd. Options are read at event time.
|
|
113
|
+
//
|
|
114
|
+
// Frames: the slop, the span filter and its rate gates are finger-travel
|
|
115
|
+
// thresholds, so they are measured in window pixels (clientX/clientY);
|
|
116
|
+
// the focal movement (dx/dy) and the pair angle are measured in the node's
|
|
117
|
+
// parent frame (parentX/parentY), the frame the node's own coordinates
|
|
118
|
+
// live in, so a scaled ancestor (a designSize fit) is accounted for and
|
|
119
|
+
// the delta applies unchanged to the node or to content inside it; the
|
|
120
|
+
// focal point (x/y) is reported in the node's local frame (localX/localY),
|
|
121
|
+
// the anchor a zoom-about-the-fingers needs. Scale and rotation are ratios
|
|
122
|
+
// and angles, the same in every uniformly scaled frame. The event carries
|
|
123
|
+
// all three frames exactly, on and off the node.
|
|
109
124
|
export function createTransform(options: TransformOptions) {
|
|
125
|
+
type Tracked = { cx: number; cy: number; px: number; py: number; lx: number; ly: number }
|
|
126
|
+
let at = (e: PointerEvent): Tracked => ({ cx: e.clientX, cy: e.clientY, px: e.parentX, py: e.parentY, lx: e.localX, ly: e.localY })
|
|
110
127
|
// All tracked pointers, in down order (the first two define the rotation pair).
|
|
111
|
-
let pointers = new Map<number,
|
|
128
|
+
let pointers = new Map<number, Tracked>()
|
|
112
129
|
let active = false
|
|
113
130
|
// Slop baseline while armed; last delivered configuration while active.
|
|
114
|
-
let ref: {
|
|
131
|
+
let ref: { cx: number; cy: number; px: number; py: number; span: number; angle: number } | null = null
|
|
115
132
|
// The zoom gate and filter (see the zoom-noise note above): scale stays 1
|
|
116
133
|
// until the SMOOTHED span leaves spanBase by SLOP, then streams smoothed
|
|
117
134
|
// ratios for the rest of the gesture.
|
|
@@ -128,27 +145,41 @@ export function createTransform(options: TransformOptions) {
|
|
|
128
145
|
// emits nothing.
|
|
129
146
|
let rebase = false
|
|
130
147
|
|
|
148
|
+
// Centroids in all three frames, the span in window pixels (it feeds the
|
|
149
|
+
// finger-travel gates), the pair angle in the parent frame.
|
|
131
150
|
let measure = () => {
|
|
132
151
|
let n = pointers.size
|
|
133
|
-
let
|
|
134
|
-
let
|
|
152
|
+
let cx = 0
|
|
153
|
+
let cy = 0
|
|
154
|
+
let px = 0
|
|
155
|
+
let py = 0
|
|
156
|
+
let lx = 0
|
|
157
|
+
let ly = 0
|
|
135
158
|
for (let p of pointers.values()) {
|
|
136
|
-
|
|
137
|
-
|
|
159
|
+
cx += p.cx
|
|
160
|
+
cy += p.cy
|
|
161
|
+
px += p.px
|
|
162
|
+
py += p.py
|
|
163
|
+
lx += p.lx
|
|
164
|
+
ly += p.ly
|
|
138
165
|
}
|
|
139
|
-
|
|
140
|
-
|
|
166
|
+
cx /= n
|
|
167
|
+
cy /= n
|
|
168
|
+
px /= n
|
|
169
|
+
py /= n
|
|
170
|
+
lx /= n
|
|
171
|
+
ly /= n
|
|
141
172
|
let span = 0
|
|
142
|
-
for (let p of pointers.values()) span += Math.hypot(p.
|
|
173
|
+
for (let p of pointers.values()) span += Math.hypot(p.cx - cx, p.cy - cy)
|
|
143
174
|
span /= n
|
|
144
175
|
let angle = 0
|
|
145
176
|
if (n >= 2) {
|
|
146
177
|
let pair = pointers.values()
|
|
147
178
|
let a = pair.next().value!
|
|
148
179
|
let b = pair.next().value!
|
|
149
|
-
angle = Math.atan2(b.
|
|
180
|
+
angle = Math.atan2(b.py - a.py, b.px - a.px)
|
|
150
181
|
}
|
|
151
|
-
return {
|
|
182
|
+
return { cx, cy, px, py, lx, ly, span, angle }
|
|
152
183
|
}
|
|
153
184
|
|
|
154
185
|
let reset = () => {
|
|
@@ -202,10 +233,10 @@ export function createTransform(options: TransformOptions) {
|
|
|
202
233
|
if (rotation > Math.PI) rotation -= 2 * Math.PI
|
|
203
234
|
else if (rotation < -Math.PI) rotation += 2 * Math.PI
|
|
204
235
|
}
|
|
205
|
-
let dx = m.
|
|
206
|
-
let dy = m.
|
|
236
|
+
let dx = m.px - ref.px
|
|
237
|
+
let dy = m.py - ref.py
|
|
207
238
|
ref = m
|
|
208
|
-
options.onTransformMove?.({ dx, dy, scale, rotation, x: m.
|
|
239
|
+
options.onTransformMove?.({ dx, dy, scale, rotation, x: m.lx, y: m.ly, pointers: pointers.size })
|
|
209
240
|
}
|
|
210
241
|
|
|
211
242
|
// An unmount mid-gesture must not leave resolved claims behind (or a live
|
|
@@ -226,24 +257,22 @@ export function createTransform(options: TransformOptions) {
|
|
|
226
257
|
// A finger joining an established gesture belongs to it outright; if
|
|
227
258
|
// the arena refuses (resolved elsewhere) the finger stays out.
|
|
228
259
|
if (!arena.steal(e.pointerId, owner)) return
|
|
229
|
-
pointers.set(e.pointerId,
|
|
260
|
+
pointers.set(e.pointerId, at(e))
|
|
230
261
|
rebase = true
|
|
231
262
|
return
|
|
232
263
|
}
|
|
233
|
-
pointers.set(e.pointerId,
|
|
264
|
+
pointers.set(e.pointerId, at(e))
|
|
234
265
|
ref = measure()
|
|
235
266
|
},
|
|
236
267
|
onPointerMove: (e: PointerEvent) => {
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
p.x = e.clientX
|
|
240
|
-
p.y = e.clientY
|
|
268
|
+
if (!pointers.has(e.pointerId) || !ref) return
|
|
269
|
+
pointers.set(e.pointerId, at(e))
|
|
241
270
|
if (!active) {
|
|
242
271
|
// Arming runs per event: the slop test tolerates a mixed-age
|
|
243
272
|
// measure (8px against <=1 frame of staleness), and the arena
|
|
244
273
|
// steal must happen synchronously inside the dispatch walk.
|
|
245
274
|
let m = measure()
|
|
246
|
-
let travel = Math.hypot(m.
|
|
275
|
+
let travel = Math.hypot(m.cx - ref.cx, m.cy - ref.cy)
|
|
247
276
|
if (travel < SLOP && Math.abs(m.span - ref.span) < SLOP) return
|
|
248
277
|
let taken: number[] = []
|
|
249
278
|
let refused = false
|
package/src/types.d.ts
CHANGED
|
@@ -148,21 +148,75 @@ export interface LayoutProps extends FlexboxProps, GridProps {
|
|
|
148
148
|
clear?: "left" | "right" | "both"
|
|
149
149
|
}
|
|
150
150
|
|
|
151
|
-
/**
|
|
151
|
+
/**
|
|
152
|
+
* A CSS color string: hex (`#rgb`, `#rrggbb`, `#rrggbbaa`), `rgb()`/`rgba()`,
|
|
153
|
+
* `hsl()`/`hsla()`, `hwb()`, or a named color. The CSS Color 4 functions -
|
|
154
|
+
* `color-mix()`, `oklch()`, `lab()`, `color()` - are not parsed and throw
|
|
155
|
+
* `Invalid color`. To mix two colors, `mixColors(a, b, t)` (oklab, returns
|
|
156
|
+
* hex); for a color at a given opacity, `withAlpha(color, a)` (returns
|
|
157
|
+
* `#rrggbbaa`); `parseColor` gives the packed u32 the prop also accepts.
|
|
158
|
+
*/
|
|
152
159
|
export type Color = string
|
|
153
160
|
|
|
161
|
+
export type BlendMode = "clear" | "source" | "destination" | "source-over" | "destination-over" | "source-in" | "destination-in" | "source-out" | "destination-out" | "source-atop" | "destination-atop" | "xor" | "plus" | "modulate" | "screen" | "overlay" | "darken" | "lighten" | "color-dodge" | "color-burn" | "hard-light" | "soft-light" | "difference" | "exclusion" | "multiply" | "hue" | "saturation" | "color" | "luminosity"
|
|
162
|
+
export type DrawStyle = "fill" | "stroke" | "stroke-and-fill"
|
|
163
|
+
export type StrokeCap = "butt" | "round" | "square"
|
|
164
|
+
export type StrokeJoin = "miter" | "round" | "bevel"
|
|
165
|
+
|
|
154
166
|
export interface PaintProps {
|
|
155
167
|
// A solid color, or a gradient from createLinearGradient/createRadialGradient.
|
|
156
168
|
color?: Color | Gradient
|
|
157
|
-
blendMode?:
|
|
169
|
+
blendMode?: BlendMode
|
|
158
170
|
/** Default "fill"; "stroke" on line, whose segment has no interior (see LineProps). */
|
|
159
|
-
drawStyle?:
|
|
160
|
-
strokeCap?:
|
|
161
|
-
strokeJoin?:
|
|
171
|
+
drawStyle?: DrawStyle
|
|
172
|
+
strokeCap?: StrokeCap
|
|
173
|
+
strokeJoin?: StrokeJoin
|
|
162
174
|
strokeMiter?: number
|
|
163
175
|
strokeWidth?: number
|
|
164
176
|
}
|
|
165
177
|
|
|
178
|
+
/**
|
|
179
|
+
* A drop shadow behind a shape (CSS box-shadow field semantics, one shadow):
|
|
180
|
+
* the shape's outer geometry, offset by x/y, grown by `spread`, softened by
|
|
181
|
+
* `blur` (a CSS-style radius in logical px), painted in `color` under the
|
|
182
|
+
* shape. It casts from the shape's outer box whatever the draw style (strokes
|
|
183
|
+
* paint inside, so the box is the outer edge) - except on `path`, where the
|
|
184
|
+
* shadow mirrors the element's own fill/stroke silhouette and `spread` is
|
|
185
|
+
* rejected (an arbitrary path cannot be inflated exactly). `color` is
|
|
186
|
+
* required; there is no currentColor to inherit.
|
|
187
|
+
*/
|
|
188
|
+
export interface ShadowProps {
|
|
189
|
+
x?: number
|
|
190
|
+
y?: number
|
|
191
|
+
blur?: number
|
|
192
|
+
spread?: number
|
|
193
|
+
color: Color
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* A subtree filter (the CSS filter functions, object form): the view's
|
|
198
|
+
* children are composited together, run through the set color operations -
|
|
199
|
+
* fused into one color matrix, applied in the fixed order grayscale, sepia,
|
|
200
|
+
* saturate, hueRotate, brightness, contrast, invert - and then blurred.
|
|
201
|
+
* `blur` is a CSS-style radius in logical px; `hueRotate` is radians (this
|
|
202
|
+
* API's angle convention); the rest are the CSS amounts (1 = unchanged for
|
|
203
|
+
* saturate/brightness/contrast, 0 = unchanged for the others; grayscale,
|
|
204
|
+
* sepia and invert saturate at 1). There is no `opacity` key - the view's
|
|
205
|
+
* own `opacity` prop is the same compositing layer. Like opacity, a filter
|
|
206
|
+
* on a non-boundary view costs a save_layer; on a repaintBoundary view it
|
|
207
|
+
* rides the composite for free. Hit testing is unaffected.
|
|
208
|
+
*/
|
|
209
|
+
export interface FilterProps {
|
|
210
|
+
blur?: number
|
|
211
|
+
grayscale?: number
|
|
212
|
+
sepia?: number
|
|
213
|
+
saturate?: number
|
|
214
|
+
hueRotate?: number
|
|
215
|
+
brightness?: number
|
|
216
|
+
contrast?: number
|
|
217
|
+
invert?: number
|
|
218
|
+
}
|
|
219
|
+
|
|
166
220
|
/** A percentage value, from `pct(50)`. Resolves against the element box. */
|
|
167
221
|
export type Pct = { readonly __unit: "pct"; v: number }
|
|
168
222
|
|
|
@@ -357,22 +411,41 @@ export interface OvalGeometryProps extends PositionProps {
|
|
|
357
411
|
h?: number
|
|
358
412
|
}
|
|
359
413
|
|
|
360
|
-
/**
|
|
414
|
+
/**
|
|
415
|
+
* See {@link PositionProps}: detached-only, never affects layout. A d-text
|
|
416
|
+
* is boxed or anchored. Boxed (no `anchor`): it wraps at `w`, or at the box
|
|
417
|
+
* inherited from the nearest laid-out ancestor, and `textAlign` aligns
|
|
418
|
+
* lines inside that width - so a right-aligned label needs a `w`. Anchored:
|
|
419
|
+
* `x` is a point on the line (SVG's text-anchor), which is what a label on a
|
|
420
|
+
* chart, an axis or a diagram wants. Either way the reported bounds
|
|
421
|
+
* (getBoundingBox, the tree) are the laid-out paragraph - widest line by
|
|
422
|
+
* line stack - unless `w`/`h` override a side.
|
|
423
|
+
*/
|
|
361
424
|
export interface TextGeometryProps extends PositionProps {
|
|
362
|
-
|
|
363
|
-
|
|
425
|
+
/**
|
|
426
|
+
* Where `x` sits on each line: its start, middle or end. With `w` unset
|
|
427
|
+
* the text shapes at its natural width (no wrap; `\n` still breaks), and
|
|
428
|
+
* `textAlign` defaults to the anchor's side. With `w` set, the `w`-wide
|
|
429
|
+
* box is what gets anchored at `x`.
|
|
430
|
+
*/
|
|
431
|
+
anchor?: "start" | "middle" | "end"
|
|
432
|
+
// Shaping (wrap) width; unset, boxed text wraps at the inherited box and
|
|
433
|
+
// anchored text does not wrap.
|
|
364
434
|
w?: number
|
|
365
|
-
// Reported-bounds height only; paragraph height always falls out
|
|
435
|
+
// Reported-bounds height override only; paragraph height always falls out
|
|
436
|
+
// of the text.
|
|
366
437
|
h?: number
|
|
367
438
|
}
|
|
368
439
|
|
|
369
440
|
/**
|
|
370
|
-
* See {@link PositionProps}: detached-only, never affects layout.
|
|
371
|
-
*
|
|
372
|
-
*
|
|
441
|
+
* See {@link PositionProps}: detached-only, never affects layout. The
|
|
442
|
+
* endpoints (or `points`) are the line's own geometry; `x`/`y` offset all of
|
|
443
|
+
* it, the way a `d-path`'s offset its `d`, so one write moves a polyline. A
|
|
444
|
+
* line's reported bounds (getBoundingBox, the tree, a detached capture) are
|
|
445
|
+
* its painted box: the geometry's extent plus the stroke's reach, not the
|
|
373
446
|
* inherited box.
|
|
374
447
|
*/
|
|
375
|
-
export interface LineGeometryProps {
|
|
448
|
+
export interface LineGeometryProps extends PositionProps {
|
|
376
449
|
/** Endpoints default to spanning the box: (0,0) to (box width, box height). */
|
|
377
450
|
x1?: number
|
|
378
451
|
y1?: number
|
|
@@ -520,7 +593,9 @@ export interface TransitionProps {
|
|
|
520
593
|
* its transform); the initial value never animates unless the entry sets
|
|
521
594
|
* `from` (an enter animation), and a non-numeric write (e.g. null)
|
|
522
595
|
* cancels the running animation and snaps. `null` clears the
|
|
523
|
-
* declaration; already-running animations finish.
|
|
596
|
+
* declaration; already-running animations finish. A spec built in a
|
|
597
|
+
* conditional widens `curve` to `string` for TypeScript; write
|
|
598
|
+
* `satisfies Transition` on the branch.
|
|
524
599
|
*/
|
|
525
600
|
transition?:
|
|
526
601
|
| ({
|
|
@@ -543,7 +618,7 @@ export interface TransitionProps {
|
|
|
543
618
|
|
|
544
619
|
// Primitives
|
|
545
620
|
|
|
546
|
-
export interface WindowProps extends LayoutProps, PointerProps {
|
|
621
|
+
export interface WindowProps extends LayoutProps, PointerProps, TransitionProps {
|
|
547
622
|
children?: Children
|
|
548
623
|
title?: string
|
|
549
624
|
fullscreen?: boolean
|
|
@@ -563,21 +638,24 @@ export interface WindowProps extends LayoutProps, PointerProps {
|
|
|
563
638
|
* `uniform sampler2D uSource` (top-left origin, like every sampled texture -
|
|
564
639
|
* so a vertex stage mapping it onto the window flips the v coordinate) and
|
|
565
640
|
* is drawn attributeless as triangles, `vertexCount` vertices fetched via
|
|
566
|
-
* gl_VertexID. `iResolution`,
|
|
567
|
-
*
|
|
568
|
-
*
|
|
569
|
-
*
|
|
641
|
+
* gl_VertexID. `iResolution`, the window size in physical pixels (the pass
|
|
642
|
+
* covers exactly that), is filled by name into a uniform the program declares
|
|
643
|
+
* itself or gets from compileShader's `header` option. The window is cleared
|
|
644
|
+
* to opaque black first, so geometry that does not cover it still presents a
|
|
645
|
+
* defined frame.
|
|
570
646
|
*/
|
|
571
647
|
export interface WindowShaderProps {
|
|
572
648
|
/** Linked program handle from linkProgram. */
|
|
573
649
|
program: ProgramId
|
|
574
650
|
/**
|
|
575
651
|
* Uniforms filled by name, paced to the next real repaint. A number drives
|
|
576
|
-
* a scalar (`float`/`int`); a flat number array
|
|
577
|
-
* type: 2/3/4 for
|
|
652
|
+
* a scalar (`float`/`int`); a flat number array (or a Float32Array /
|
|
653
|
+
* Float64Array) drives the declared GLSL type: 2/3/4 for
|
|
654
|
+
* `vec2`/`vec3`/`vec4`, 16 (column-major) for `mat4`. An undefined or null
|
|
655
|
+
* entry is skipped.
|
|
578
656
|
*/
|
|
579
|
-
params?: Record<string, number | number[]>
|
|
580
|
-
/** Extra sampler2D inputs: uniform name to texture id, or `{ id, filter?, wrap? }` for a per-binding sampling override. */
|
|
657
|
+
params?: Record<string, number | number[] | Float32Array | Float64Array>
|
|
658
|
+
/** Extra sampler2D inputs: uniform name to texture id, or `{ id, filter?, wrap? }` for a per-binding sampling override. An undefined or null entry is skipped. */
|
|
581
659
|
textures?: TextureBindings
|
|
582
660
|
/** Vertices drawn (attributeless triangles). Default 3, the covering triangle. */
|
|
583
661
|
vertexCount?: number
|
|
@@ -637,7 +715,9 @@ export interface ViewOwnProps extends TransformProps, PointerProps {
|
|
|
637
715
|
* skipping rasterization entirely. Costs texture memory and re-rasterizes
|
|
638
716
|
* on layout-size or display-scale changes. Content painted outside the
|
|
639
717
|
* element's layout box is cropped, and ancestor scale animations smear the
|
|
640
|
-
* bitmap; best for screen-aligned, static, raster-expensive content.
|
|
718
|
+
* bitmap; best for screen-aligned, static, raster-expensive content. On a
|
|
719
|
+
* d-view the box is the inherited frame (the nearest laid-out ancestor's
|
|
720
|
+
* box, or the design size under a designSize view), same as a capture.
|
|
641
721
|
*
|
|
642
722
|
* "snapshot-no-aa" is "snapshot" rasterized without anti-aliasing: cheaper
|
|
643
723
|
* (no multisampled scratch, one render pass), but vector content - svg
|
|
@@ -667,25 +747,41 @@ export interface ViewOwnProps extends TransformProps, PointerProps {
|
|
|
667
747
|
* unrotated, opaque content.
|
|
668
748
|
*/
|
|
669
749
|
shader?: ViewShaderProps | null
|
|
750
|
+
filter?: FilterProps
|
|
751
|
+
/**
|
|
752
|
+
* Filters the pixels already painted BENEATH the view's box, in place,
|
|
753
|
+
* before the view's own content draws - frosted glass over live content
|
|
754
|
+
* (CSS `backdrop-filter`). Same keys and semantics as `filter`. The
|
|
755
|
+
* region is the layout box; give the view an overflow clip with
|
|
756
|
+
* `clipRadius` for rounded glass. Costs an offscreen capture of the
|
|
757
|
+
* pixels beneath at that point in the frame, so treat it as a deliberate
|
|
758
|
+
* panel, not a casual style. Inside a `repaintBoundary="snapshot"`
|
|
759
|
+
* subtree it sees only that boundary's own offscreen content, never what
|
|
760
|
+
* is behind the boundary (the same containment `blendMode` has there).
|
|
761
|
+
*/
|
|
762
|
+
backdropFilter?: FilterProps
|
|
670
763
|
}
|
|
671
764
|
|
|
672
765
|
/**
|
|
673
766
|
* A boundary shader declaration. The program contract matches shader targets,
|
|
674
767
|
* not the window pass: the subtree's rasterization binds as
|
|
675
768
|
* `uniform sampler2D uSource` (top-left origin, like every sampled texture)
|
|
676
|
-
* and the pass draws the covering triangle attributeless. `iResolution`,
|
|
677
|
-
* filled by name
|
|
769
|
+
* and the pass draws the covering triangle attributeless. `iResolution`, the
|
|
770
|
+
* boundary in physical pixels, is filled by name into a uniform the program
|
|
771
|
+
* declares itself or gets from compileShader's `header` option.
|
|
678
772
|
*/
|
|
679
773
|
export interface ViewShaderProps {
|
|
680
774
|
/** Linked program handle from linkProgram. */
|
|
681
775
|
program: ProgramId
|
|
682
776
|
/**
|
|
683
777
|
* Uniforms filled by name, paced to the next real repaint. A number drives
|
|
684
|
-
* a scalar (`float`/`int`); a flat number array
|
|
685
|
-
* type: 2/3/4 for
|
|
778
|
+
* a scalar (`float`/`int`); a flat number array (or a Float32Array /
|
|
779
|
+
* Float64Array) drives the declared GLSL type: 2/3/4 for
|
|
780
|
+
* `vec2`/`vec3`/`vec4`, 16 (column-major) for `mat4`. An undefined or null
|
|
781
|
+
* entry is skipped.
|
|
686
782
|
*/
|
|
687
|
-
params?: Record<string, number | number[]>
|
|
688
|
-
/** Extra sampler2D inputs: uniform name to texture id, or `{ id, filter?, wrap? }` for a per-binding sampling override. */
|
|
783
|
+
params?: Record<string, number | number[] | Float32Array | Float64Array>
|
|
784
|
+
/** Extra sampler2D inputs: uniform name to texture id, or `{ id, filter?, wrap? }` for a per-binding sampling override. An undefined or null entry is skipped. */
|
|
689
785
|
textures?: TextureBindings
|
|
690
786
|
/**
|
|
691
787
|
* Transparent margin in logical px on every side of the layout box, for
|
|
@@ -719,20 +815,28 @@ export interface ViewProps extends ViewOwnProps, LayoutProps {}
|
|
|
719
815
|
// A stroked rect paints inside its box, like a CSS border: the stroke's outer
|
|
720
816
|
// edge sits on the box edge rather than straddling it, so nothing bleeds past
|
|
721
817
|
// the box for a clip to cut. `path` and `line` strokes stay centered on their
|
|
722
|
-
// geometry - there the geometry is the stroke, not a box.
|
|
723
|
-
|
|
818
|
+
// geometry - there the geometry is the stroke, not a box. A dashed stroke
|
|
819
|
+
// dashes that same inset outline (see DashProps).
|
|
820
|
+
export interface RectProps extends PaintProps, PointerProps, DashProps {
|
|
724
821
|
// Corner radius, measured on the box (the stroke's outer edge). A single
|
|
725
822
|
// number applies to all four corners; an array is [top-left, top-right,
|
|
726
823
|
// bottom-right, bottom-left] (CSS border-radius order).
|
|
727
824
|
radius?: number | [number, number, number, number]
|
|
825
|
+
shadow?: ShadowProps
|
|
728
826
|
}
|
|
729
827
|
|
|
730
828
|
// Strokes paint inside the box, same as `RectProps`.
|
|
731
|
-
export interface OvalProps extends PaintProps, PointerProps {
|
|
829
|
+
export interface OvalProps extends PaintProps, PointerProps, DashProps {
|
|
830
|
+
shadow?: ShadowProps
|
|
831
|
+
}
|
|
732
832
|
|
|
733
833
|
/**
|
|
734
|
-
* A stroke's dash pattern, on
|
|
735
|
-
* to dash; with either unset, or
|
|
834
|
+
* A stroke's dash pattern, on every stroked primitive (`rect`, `oval`,
|
|
835
|
+
* `line`, `path`). Both lengths must be set to dash; with either unset, or
|
|
836
|
+
* a gap of 0, the stroke is solid. A box primitive dashes its inset
|
|
837
|
+
* outline, the pattern starting where SVG's does (a rect on the top edge
|
|
838
|
+
* after the top-left corner, an oval at 3 o'clock) and running clockwise;
|
|
839
|
+
* its dashes stay inside the box like the solid stroke.
|
|
736
840
|
*/
|
|
737
841
|
export interface DashProps {
|
|
738
842
|
/**
|
|
@@ -807,15 +911,24 @@ export interface LineProps extends PaintProps, PointerProps, DashProps {
|
|
|
807
911
|
export interface PathProps extends PaintProps, PointerProps, DashProps {
|
|
808
912
|
d?: string
|
|
809
913
|
fillRule?: "nonzero" | "evenodd"
|
|
914
|
+
/** Shadows the drawn silhouette (fill and/or stroke); `spread` is rejected here. */
|
|
915
|
+
shadow?: ShadowProps
|
|
810
916
|
}
|
|
811
917
|
|
|
918
|
+
export type FontFamily = "sans" | "serif" | "mono" | (string & {})
|
|
919
|
+
export type FontStyle = "normal" | "italic"
|
|
920
|
+
export type FontWeight = 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900
|
|
921
|
+
export type TextDecoration = "none" | "underline"
|
|
922
|
+
export type TextAlign = "left" | "right" | "center" | "justify"
|
|
923
|
+
export type TextOverflow = "clip" | "ellipsis" | (string & {})
|
|
924
|
+
|
|
812
925
|
/**
|
|
813
926
|
* Per-run text style: the paragraph default on <text>, an override on <span>.
|
|
814
927
|
* The cascade is intra-paragraph only: a span inherits from its enclosing
|
|
815
928
|
* span, then from the <text>; nothing inherits across the tree.
|
|
816
929
|
*/
|
|
817
930
|
export interface TextRunProps {
|
|
818
|
-
fontFamily?:
|
|
931
|
+
fontFamily?: FontFamily
|
|
819
932
|
fontSize?: number
|
|
820
933
|
/**
|
|
821
934
|
* Line height as a MULTIPLIER of fontSize, not pixels (the theme uses
|
|
@@ -823,15 +936,15 @@ export interface TextRunProps {
|
|
|
823
936
|
* font size, rendering the text as blank space.
|
|
824
937
|
*/
|
|
825
938
|
lineHeight?: number
|
|
826
|
-
fontStyle?:
|
|
827
|
-
fontWeight?:
|
|
939
|
+
fontStyle?: FontStyle
|
|
940
|
+
fontWeight?: FontWeight
|
|
828
941
|
/**
|
|
829
942
|
* Underline in the run's own color, drawn straight through descenders
|
|
830
943
|
* (no skip-ink). Position and thickness come from the font's own metrics
|
|
831
944
|
* unless overridden; a font Impeller resolves through the system fallback
|
|
832
945
|
* gets the shipped Noto values.
|
|
833
946
|
*/
|
|
834
|
-
textDecoration?:
|
|
947
|
+
textDecoration?: TextDecoration
|
|
835
948
|
/** Pixels from the baseline to the top of the underline. */
|
|
836
949
|
textUnderlineOffset?: number
|
|
837
950
|
/** Underline thickness in pixels. */
|
|
@@ -851,14 +964,14 @@ export interface SpanProps extends TextRunProps, PointerProps {
|
|
|
851
964
|
|
|
852
965
|
export interface TextProps extends PaintProps, PointerProps, TextRunProps {
|
|
853
966
|
children?: Children
|
|
854
|
-
textAlign?:
|
|
967
|
+
textAlign?: TextAlign
|
|
855
968
|
maxLines?: number
|
|
856
969
|
/**
|
|
857
970
|
* What happens to text cut off by maxLines: "clip" (default), "ellipsis"
|
|
858
971
|
* (a U+2026 at the end of the last line), or any other string to use as
|
|
859
972
|
* the ellipsis. Drawn in the paragraph's default style.
|
|
860
973
|
*/
|
|
861
|
-
textOverflow?:
|
|
974
|
+
textOverflow?: TextOverflow
|
|
862
975
|
/**
|
|
863
976
|
* A word (wrap unit) wider than the line: "anywhere" (default) splits it
|
|
864
977
|
* at grapheme boundaries so it stays inside the box, "normal" keeps it
|
|
@@ -910,7 +1023,8 @@ export interface TextureProps extends PaintProps, PointerProps {
|
|
|
910
1023
|
// throws, and set src before params: a write with no src to route to
|
|
911
1024
|
// throws). However often a signal writes, the target renders once per
|
|
912
1025
|
// frame at the raster flush. A number drives a scalar (`float`/`int`); a
|
|
913
|
-
// flat number array
|
|
914
|
-
// `vec2`/`vec3`/`vec4`, 16 (column-major) for `mat4`.
|
|
915
|
-
|
|
1026
|
+
// flat number array (or a Float32Array / Float64Array) drives the declared
|
|
1027
|
+
// GLSL type: 2/3/4 for `vec2`/`vec3`/`vec4`, 16 (column-major) for `mat4`.
|
|
1028
|
+
// An undefined or null entry is skipped.
|
|
1029
|
+
params?: Record<string, number | number[] | Float32Array | Float64Array>
|
|
916
1030
|
}
|