@weasel-js/core 0.5.1 → 0.7.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.
Files changed (35) hide show
  1. package/CHANGELOG.md +148 -0
  2. package/dist/{DrawCommand-Dl0bXNfS.d.ts → DrawCommand-CJtqqt8H.d.ts} +26 -2
  3. package/dist/{chunk-7V6JEOXE.js → chunk-7F3SDUJ4.js} +7884 -9167
  4. package/dist/chunk-7F3SDUJ4.js.map +1 -0
  5. package/dist/chunk-FSZEXVCR.js +171 -0
  6. package/dist/chunk-FSZEXVCR.js.map +1 -0
  7. package/dist/clone.d.ts +1 -1
  8. package/dist/geometry-D9BDMiQi.d.ts +114 -0
  9. package/dist/{grid-Cf87knjU.d.ts → grid-CaSK9bHV.d.ts} +1 -1
  10. package/dist/index-D31EADQG.d.ts +2847 -0
  11. package/dist/index.css +0 -35
  12. package/dist/index.css.map +1 -1
  13. package/dist/index.d.ts +913 -2546
  14. package/dist/index.js +2 -2
  15. package/dist/insert.d.ts +2 -2
  16. package/dist/move.d.ts +3 -3
  17. package/dist/{options-BPPBWMa7.d.ts → options-DMWeTELe.d.ts} +1 -1
  18. package/dist/{pointSnapToGrid-D7s7QmOF.d.ts → pointSnapToGrid-C3EruUwt.d.ts} +3 -54
  19. package/dist/renderer.css +0 -35
  20. package/dist/renderer.css.map +1 -1
  21. package/dist/renderer.d.ts +5 -4
  22. package/dist/renderer.js +2 -2
  23. package/dist/resize.d.ts +3 -3
  24. package/dist/routing.d.ts +10 -8
  25. package/dist/routing.js +1 -1
  26. package/dist/{types-BjUi2vA-.d.ts → types-Dcaa0tPq.d.ts} +1 -25
  27. package/dist/{registerFont-CP-wCsrz.d.ts → viewToMat3-D4lrBigW.d.ts} +2 -44
  28. package/package.json +6 -5
  29. package/dist/chunk-7V6JEOXE.js.map +0 -1
  30. package/dist/chunk-AM6ARSPN.js +0 -517
  31. package/dist/chunk-AM6ARSPN.js.map +0 -1
  32. package/dist/fitViewToBounds-evGsnR8Q.d.ts +0 -62
  33. package/dist/index-DZBYMsHI.d.ts +0 -1555
  34. package/dist/routing.css +0 -35
  35. package/dist/routing.css.map +0 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,153 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.7.0
4
+
5
+ ### Minor Changes
6
+
7
+ - d3e5597: Extract the MSDF glyph tier into a new `@weasel-js/font` package: font
8
+ registry, atlas parsing, glyph layout, runtime rasterization, and the SDF
9
+ text shader source. `@weasel-js/core` depends on it; `registerFont` is still
10
+ re-exported from `@weasel-js/core/renderer`, so existing call sites keep
11
+ working.
12
+
13
+ Unregistered font families now render in the default family with a one-time
14
+ warning instead of rendering nothing. Configure with
15
+ `setFontFallbackPolicy('substitute' | 'canvas' | 'none')` — `'none'`
16
+ restores the previous hard-miss behavior, and `'canvas'` rasterizes the real
17
+ typeface at runtime when the browser has it. A family the `'canvas'` policy
18
+ enrolled for itself stops being canvas-served once the policy changes; one
19
+ you name with `registerCanvasFont` is served under every policy, and
20
+ `isCanvasFont` reports that distinction — it answers "will the dynamic tier
21
+ serve this family right now", so an auto-enrolled family reads `false` under
22
+ `'substitute'` and `'none'`. The default
23
+ family may be a canvas-registered family, and when it cannot serve the
24
+ request either, the resulting blank text is reported with its own warning
25
+ naming the default family rather than failing silently. Requesting the
26
+ default family itself also warns — whether it is registered at a variant it
27
+ can't serve, or `setDefaultFontFamily` named a family that was never
28
+ registered at all; either way there is nothing left to fall back to. An app
29
+ that has registered no fonts and set no default stays silent, since that is
30
+ not a misconfiguration.
31
+
32
+ `ResolveResult.substituted` reports the substitution structurally, and
33
+ `ResolveResult.resolved` now
34
+ carries the matched `family` alongside `weight` and `style` — the full atlas
35
+ identity to pass to `getFont` / `textureCacheKey`.
36
+
37
+ Adds `listFonts()` for enumerating registered families.
38
+
39
+ - a925117: Text antialiasing is derived from the screen-space derivative instead of a
40
+ constant.
41
+
42
+ Both SDF text shaders computed their smoothstep band from a fixed `u_aaWidth`
43
+ (0.05, set once per draw). A constant band cannot be correct at more than one
44
+ scale: at 16px it collapsed to well under a screen pixel, so glyph coverage
45
+ quantized to all-or-nothing and edges rendered as hard stair-steps; at display
46
+ sizes the same constant read mushy. `TEXT_FRAG_SRC` and `TEXT_FRAG_R8_SRC` now
47
+ take the band from `fwidth(sdfVal)`, which folds in font size, zoom, and DPR
48
+ together, with a small floor so a degenerate derivative can't reproduce the
49
+ aliased behavior.
50
+
51
+ This changes how all GL-rendered text looks — most visibly at UI sizes, where
52
+ it is the difference between binary and antialiased edges.
53
+
54
+ Breaking, for anyone driving the shaders directly:
55
+
56
+ - `u_aaWidth` is gone from both fragment sources and from `TEXT_SDF_UNIFORMS`.
57
+ There is no CPU-side AA knob to set; the shader derives it. Setting the
58
+ uniform was never useful — the kit only ever wrote 0.05 to it.
59
+
60
+ - eeae450: A codepoint the atlas never baked now falls back to a real glyph instead of a
61
+ literal `?`.
62
+
63
+ Font fallback resolved at family granularity: `resolveFontVariant` picks one
64
+ tier for a whole run. But a baked MSDF atlas covers a fixed charset, so a run
65
+ served by a perfectly good atlas can still contain a character that atlas has
66
+ no glyph for — an em dash, a curly quote, anything outside the subset. Those
67
+ drew codepoint 63. That fabricates a character the author never wrote and is
68
+ indistinguishable from one they did; the committed text baseline read "Themed
69
+ editing ? magenta caret" for a full commit without anyone noticing.
70
+
71
+ `layoutRuns` now escalates the individual codepoint to the dynamic canvas
72
+ tier, which rasterizes from installed fonts and can usually serve it for real.
73
+ The escalated glyph gets its own draw group (different texture and shader) and
74
+ is scaled by its own atlas's bake size. When escalation isn't available the
75
+ character is skipped with a warning naming it, rather than substituted —
76
+ `.notdef` is what a text stack should draw here, and the BmFont format has no
77
+ such glyph.
78
+
79
+ New in `@weasel-js/font`:
80
+
81
+ - `resolveGlyphFallback(family, weight, style)` returns a canvas-tier
82
+ `ResolveResult` for per-codepoint escalation, or `null` when it isn't
83
+ available. Declines under the `'none'` fallback policy, which documents a
84
+ miss as a hard miss, and when there is no canvas to rasterize into (SSR)
85
+ rather than throwing into the layout pass.
86
+
87
+ - e7d71c9: Text properties: node-level typography through the schema-driven panel, and
88
+ caret-range styling through a new tool options bar.
89
+
90
+ `TextStyle` and `StyledRun` gain `letterSpacing`, `underline`, and
91
+ `strikethrough`, with GL rendering, DOM-overlay, and SVG round-trips for all
92
+ three. `styleAtRange` / `applyStyleToRange` expose the run algebra publicly,
93
+ and `useTextEdit` gains `selection`, `rangeStyle`, and
94
+ `applyStyleToSelection`. Text nodes get Character and Paragraph schema
95
+ groups. New `ToolOptionsBar` component; `ToggleBar` renders indeterminate
96
+ segments via `mixedValues`.
97
+
98
+ Behavior changes worth knowing about:
99
+
100
+ - **`SelectionPanel` reads and writes node paths of any depth** (two or more
101
+ segments). It previously split at the first dot and read exactly one level,
102
+ so `data.style.fontSize` resolved to `data['style.fontSize']`.
103
+ - **The default `kit:text` painter paints a node's `runs`** when it has them,
104
+ instead of re-flattening `data.text`. Run styling was previously invisible
105
+ to anything drawn by the default scene layer.
106
+ - **`useTextEdit` no longer commits when focus moves into editing chrome**
107
+ (`isEditorChrome`), and commits on a pointerdown outside both the overlay
108
+ and that chrome. Its published `selection` survives focus leaving the
109
+ overlay — it clears on `startEdit` and when the edit ends. Without this a
110
+ character bar could not exist: clicking its controls ended the edit they
111
+ were there to change.
112
+ - **The edit overlay can scale with the view** (`TextEditScreenPose.zoom`),
113
+ keeping every metric on it — including run-level `fontSize` and
114
+ `letterSpacing` — in world units. Omitting `zoom` keeps the old
115
+ screen-pixel contract.
116
+ - **The canvas-2D measurement path counts tracking**, as the GL path already
117
+ did, so wrap points, `caretIndexAt`, and `fitTextPose` agree on tracked
118
+ text. This moves wrap points on any text with a non-zero `letterSpacing`.
119
+ - **The text tool enters edit on the box it inserts.**
120
+
121
+ Breaking-ish, in packages that have not been published with these paths:
122
+
123
+ - `splitNodePath` is removed from `@weasel-js/ui`'s public API — it was dead
124
+ and encoded the superseded one-level path model. `nodeValueAt` and
125
+ `setAtPath` are exported in its place.
126
+ - A text node's color leaf is now `data.style.fill` of the new `paint` kind
127
+ rather than `data.style.fill.color` of the `color` kind. `TextStyle.fill`
128
+ is a tagged union, so the old leaf read `undefined` off a gradient and
129
+ wrote a hybrid the renderer painted flat solid.
130
+
131
+ ### Patch Changes
132
+
133
+ - Updated dependencies [d3e5597]
134
+ - Updated dependencies [a925117]
135
+ - Updated dependencies [eeae450]
136
+ - @weasel-js/font@0.7.0
137
+ - @weasel-js/geom@0.7.0
138
+ - @weasel-js/gestures@0.7.0
139
+ - @weasel-js/history@0.7.0
140
+ - @weasel-js/modes@0.7.0
141
+
142
+ ## 0.6.0
143
+
144
+ ### Patch Changes
145
+
146
+ - @weasel-js/geom@0.6.0
147
+ - @weasel-js/gestures@0.6.0
148
+ - @weasel-js/history@0.6.0
149
+ - @weasel-js/modes@0.6.0
150
+
3
151
  ## 0.5.1
4
152
 
5
153
  ### Patch Changes
@@ -242,6 +242,12 @@ interface TextStyle {
242
242
  selectionBackground?: string;
243
243
  /** Selection text color paired with `selectionBackground`. Default: inherits text color. */
244
244
  selectionColor?: string;
245
+ /** Extra advance added after each glyph, in world units. Default 0. */
246
+ letterSpacing?: number;
247
+ /** Default `false`. */
248
+ underline?: boolean;
249
+ /** Default `false`. */
250
+ strikethrough?: boolean;
245
251
  }
246
252
  /** `TextStyle` with all fields filled in from defaults — what the renderer actually consumes. */
247
253
  interface ResolvedTextStyle {
@@ -255,6 +261,9 @@ interface ResolvedTextStyle {
255
261
  caretColor: string;
256
262
  selectionBackground: string | null;
257
263
  selectionColor: string | null;
264
+ letterSpacing: number;
265
+ underline: boolean;
266
+ strikethrough: boolean;
258
267
  }
259
268
  /** Default resolved style used when a `TextPose` omits `style`. */
260
269
  declare const DEFAULT_TEXT_STYLE: ResolvedTextStyle;
@@ -281,6 +290,9 @@ interface StyledRun {
281
290
  fontFamily?: string;
282
291
  fontSize?: number;
283
292
  fill?: FillStyle;
293
+ letterSpacing?: number;
294
+ underline?: boolean;
295
+ strikethrough?: boolean;
284
296
  }
285
297
  declare function toRuns(input: string | StyledRun[]): StyledRun[];
286
298
  declare function runsToPlainText(runs: readonly StyledRun[]): string;
@@ -301,8 +313,14 @@ declare function markdownToRuns(input: string): StyledRun[];
301
313
  *
302
314
  * `bold`/`italic` toggles on a run are folded into `fontWeight`/`fontStyle`:
303
315
  * `bold: true` → fontWeight 700, `italic: true` → fontStyle 'italic'.
304
- * Explicit `fontFamily` / `fontSize` / `fill` on the run override the
305
- * node-level value.
316
+ * Explicit `fontFamily` / `fontSize` / `fill` / `letterSpacing` on the run
317
+ * override the node-level value (`letterSpacing: 0` on a run is an override,
318
+ * not an absence — it zeroes inherited tracking).
319
+ *
320
+ * `underline` / `strikethrough` are *additive*, like `bold`/`italic`: a run
321
+ * can turn a decoration on but never off, so they resolve as
322
+ * `run.x || style.x` and not `run.x ?? style.x`. See the header of
323
+ * `runs/rangeStyle.ts` for why the model collapses the tri-state.
306
324
  */
307
325
 
308
326
  interface ResolvedRun {
@@ -312,6 +330,12 @@ interface ResolvedRun {
312
330
  fontWeight: number;
313
331
  fontStyle: 'normal' | 'italic';
314
332
  fill: FillStyle;
333
+ /** Extra advance added after each glyph of this run, in world units. */
334
+ letterSpacing: number;
335
+ /** Draw a rule below this run's baseline. Additive over the node style. */
336
+ underline: boolean;
337
+ /** Draw a rule through this run's x-height. Additive over the node style. */
338
+ strikethrough: boolean;
315
339
  }
316
340
  declare function resolveRuns(runs: readonly StyledRun[], style: ResolvedTextStyle): ResolvedRun[];
317
341