@weasel-js/core 1.0.3 → 1.1.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.
- package/CHANGELOG.md +251 -0
- package/dist/{chunk-SMCZRSYB.js → chunk-3B4QEB2G.js} +810 -228
- package/dist/chunk-3B4QEB2G.js.map +1 -0
- package/dist/{chunk-U45SODC2.js → chunk-4Z6J4IVH.js} +43 -27
- package/dist/chunk-4Z6J4IVH.js.map +1 -0
- package/dist/{chunk-3KGMJMOS.js → chunk-CSMF654J.js} +3 -3
- package/dist/{chunk-3KGMJMOS.js.map → chunk-CSMF654J.js.map} +1 -1
- package/dist/{chunk-TR3HZN34.js → chunk-J3YC3GVF.js} +5 -4
- package/dist/chunk-J3YC3GVF.js.map +1 -0
- package/dist/{chunk-3JYFAQIB.js → chunk-J7LUY47N.js} +3 -3
- package/dist/{chunk-3JYFAQIB.js.map → chunk-J7LUY47N.js.map} +1 -1
- package/dist/clipboard.d.ts +1 -1
- package/dist/clone.d.ts +2 -2
- package/dist/{geometry-5X6TrAkX.d.ts → geometry-C56YbnfD.d.ts} +1 -1
- package/dist/{grid-sfilv5HP.d.ts → grid-DqOi0Vgi.d.ts} +1 -1
- package/dist/index.d.ts +179 -59
- package/dist/index.js +5 -5
- package/dist/insert.d.ts +3 -3
- package/dist/insert.js +1 -1
- package/dist/move.d.ts +4 -4
- package/dist/move.js +3 -3
- package/dist/move.js.map +1 -1
- package/dist/{options-CbsIgQci.d.ts → options-C6HYCKP7.d.ts} +1 -1
- package/dist/{pointSnapToGrid-C3wowsQy.d.ts → pointSnapToGrid-BBtn5bus.d.ts} +2 -2
- package/dist/{registry-CxnkXbG8.d.ts → registry-DGBrjGbB.d.ts} +4 -4
- package/dist/renderer.d.ts +29 -13
- package/dist/renderer.js +5 -5
- package/dist/resize.d.ts +4 -4
- package/dist/resize.js +2 -2
- package/dist/routing.d.ts +4 -4
- package/dist/routing.js +1 -1
- package/dist/{types-ByZxoD6P.d.ts → types-BhrifbZ1.d.ts} +1 -1
- package/dist/{types-DpQ0cWYC.d.ts → types-DbysOO-2.d.ts} +10 -3
- package/package.json +6 -6
- package/dist/chunk-SMCZRSYB.js.map +0 -1
- package/dist/chunk-TR3HZN34.js.map +0 -1
- package/dist/chunk-U45SODC2.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,256 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.1.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 27dd91b: <!-- bump-approved: minor: Mike — new public API across two arcs (timeline + rig, and the @weasel-js/audio package); called explicitly in conversation on 2026-08-22: "the next version we push will be 1.1.0" -->
|
|
8
|
+
|
|
9
|
+
Add a keyframe timeline primitive and a hierarchical rig.
|
|
10
|
+
|
|
11
|
+
This adds public API surface.
|
|
12
|
+
|
|
13
|
+
`animator.timeline(opts)` registers like any other animation, so its playhead
|
|
14
|
+
responds to `pause`, `setTimeScale` and `cancelKey`. Sampled tracks are a pure
|
|
15
|
+
function of the playhead and reuse the tween interpolation contract; event
|
|
16
|
+
tracks fire only on forward playback and stay silent under `seek`; timeline
|
|
17
|
+
tracks nest, evaluated at the parent's playhead minus their offset.
|
|
18
|
+
|
|
19
|
+
The rig ships as `blendPoses` and `resolveSkeleton` over a `Skeleton` of joints
|
|
20
|
+
carrying their own TRS — not the scene's consumer-defined `TPose`, which may be
|
|
21
|
+
a bare AABB with no rotation term a joint chain can compose through. A pose is
|
|
22
|
+
local deltas from bind, so an absent joint or field means "no change".
|
|
23
|
+
Animating a rig is a `SampledTrack<Pose>` whose `interpolate` is `blendPoses` —
|
|
24
|
+
no rig-specific timeline machinery.
|
|
25
|
+
|
|
26
|
+
### Patch Changes
|
|
27
|
+
|
|
28
|
+
- 0763205: Export the `mat3` namespace from the package entry
|
|
29
|
+
|
|
30
|
+
`resolveSkeleton` returns `Map<string, Mat3>` and `Mat3` was exported as a
|
|
31
|
+
type, but the operations that read one were not. Placing a bone tip meant
|
|
32
|
+
indexing the `Float32Array` by hand — `[m[0] * length + m[6], m[1] * length +
|
|
33
|
+
m[7]]` — which is the matrix layout leaking into consumer code.
|
|
34
|
+
|
|
35
|
+
`mat3` is now importable from `@weasel-js/core`, so that line is
|
|
36
|
+
`mat3.apply(m, length, 0)`. Alongside `apply` the namespace carries
|
|
37
|
+
`identity`, `multiply`, `translate`, `scale`, `invert` and `screenToClip`.
|
|
38
|
+
|
|
39
|
+
This is the renderer's 9-element column-major form, matching what
|
|
40
|
+
`uniformMatrix3fv` uploads. `@weasel-js/geom` exports its own `Mat3` — a
|
|
41
|
+
6-element affine — with the same logical element order but a different array
|
|
42
|
+
shape; the two are not interchangeable.
|
|
43
|
+
|
|
44
|
+
- b65aadd: Undo restores z-order, and reorder ops survive a reload
|
|
45
|
+
|
|
46
|
+
Two defects in the op layer, found reviewing `core/ops` and `core/adapters`.
|
|
47
|
+
|
|
48
|
+
`createDeleteOp` captures the node's z-index and forwards it through
|
|
49
|
+
`invert()` so undo puts the node back where it was — but `SceneAdapter`
|
|
50
|
+
declared `insertNode(node)` with no index parameter, so the only
|
|
51
|
+
implementation that honored it was the one that had gone off-contract to
|
|
52
|
+
accept it. `arrayAdapter` appended unconditionally and `animateLifecycle`
|
|
53
|
+
dropped the argument while wrapping. Deleting a node and undoing therefore
|
|
54
|
+
moved it to the top of the paint order, and undoing a multi-delete reversed
|
|
55
|
+
the stack. The parameter is now part of the interface and both
|
|
56
|
+
implementations honor it.
|
|
57
|
+
|
|
58
|
+
`createReorderOp` — bring forward, send backward, bring to front, send to
|
|
59
|
+
back — built an op with no `name` and registered no factory, though `Op`'s
|
|
60
|
+
contract says kit-emitted ops always carry one. `History.serialize()` drops
|
|
61
|
+
any entry holding a nameless op, so all four silently vanished from the
|
|
62
|
+
persisted undo stack on reload while `moveToIndex`, which does register,
|
|
63
|
+
survived. They now serialize, with the per-parent before-order carried in
|
|
64
|
+
the op's args so a rebuilt op can still invert.
|
|
65
|
+
|
|
66
|
+
- 0c13967: An empty container no longer draws selection chrome at its own stored pose
|
|
67
|
+
|
|
68
|
+
`composeSelectionPose` and the overlay's container-aware bounds resolver both
|
|
69
|
+
document that a container with no leaves resolves to `null`. Neither could
|
|
70
|
+
return it: the leaf walk pushed any childless node, so an empty container
|
|
71
|
+
pushed _itself_, and the `leaves.length === 0` guard was unreachable. The
|
|
72
|
+
container's own stored pose then became the overlay bounds — the one value
|
|
73
|
+
this resolver exists to avoid, and at its most stale when nothing is left
|
|
74
|
+
inside to have moved it.
|
|
75
|
+
|
|
76
|
+
A childless node now counts as a leaf only when it is not itself a container.
|
|
77
|
+
|
|
78
|
+
- 83ba8b0: A finished timeline can be scrubbed back instead of going inert
|
|
79
|
+
|
|
80
|
+
A non-looping timeline that reached `duration` returned `finished` from its
|
|
81
|
+
tick and left the animator's table, but its handle kept answering `time()` and
|
|
82
|
+
`duration()` as though it were live. `seek()` moved a playhead nothing ticked —
|
|
83
|
+
no error, no state change. The only recovery was to build a new timeline.
|
|
84
|
+
|
|
85
|
+
`seek`, and an `edit` that extends the duration past the playhead, now
|
|
86
|
+
re-register the timeline and it plays on. It still finishes: an entry that
|
|
87
|
+
never retires would hold a slot, and the frame loop, open for every timeline
|
|
88
|
+
ever created.
|
|
89
|
+
|
|
90
|
+
- `onDone` fires once per arrival at the end, and again for a replay. A handler
|
|
91
|
+
that seeks back from inside `onDone` keeps the entry live rather than
|
|
92
|
+
stranding the replay it just started.
|
|
93
|
+
- Reviving re-registers under the same `cancelKey` without cancelling whoever
|
|
94
|
+
claimed that key meanwhile, and the revived timeline is still cancellable by
|
|
95
|
+
it.
|
|
96
|
+
- `cancel()` is final, including on a timeline that had already finished. No
|
|
97
|
+
seek or edit revives a cancelled one.
|
|
98
|
+
- A `pause()` or `setTimeScale()` taken while the timeline was off the table
|
|
99
|
+
applies when it comes back, so scrubbing a paused transport does not silently
|
|
100
|
+
start playback.
|
|
101
|
+
- @weasel-js/font@1.1.0
|
|
102
|
+
- @weasel-js/geom@1.1.0
|
|
103
|
+
- @weasel-js/gestures@1.1.0
|
|
104
|
+
- @weasel-js/history@1.1.0
|
|
105
|
+
- @weasel-js/modes@1.1.0
|
|
106
|
+
|
|
107
|
+
## 1.0.4
|
|
108
|
+
|
|
109
|
+
### Patch Changes
|
|
110
|
+
|
|
111
|
+
- da7c150: The solid batch stops re-sending index data a ring slot already holds, and
|
|
112
|
+
`u_color` / `u_alpha` join the per-frame uniform cache.
|
|
113
|
+
|
|
114
|
+
A run of rects has indices that are a pure function of the rect count, so a
|
|
115
|
+
slot coming round to the same count already holds the right bytes. A mesh's
|
|
116
|
+
indices are rebased onto the staged vertices and a respecified buffer keeps
|
|
117
|
+
nothing, so both mark the slot as holding no pattern and the next flush writes.
|
|
118
|
+
|
|
119
|
+
`u_color` and `u_alpha` were excluded from `UploadedUniforms` because several
|
|
120
|
+
places wrote them directly. All of those now go through `setColorUniform` /
|
|
121
|
+
`setAlphaUniform`, which makes the cache correct per program rather than
|
|
122
|
+
dependent on knowing which caller uses which — the batch holds `u_color` at
|
|
123
|
+
white forever and was re-sending it once per flush.
|
|
124
|
+
|
|
125
|
+
Measured together on an M2 Max via ANGLE (`tests/perf/clip-cost.spec.ts`): a
|
|
126
|
+
flush 5.39 -> 3.22 us, entering a clip 12.47 -> 9.53. Read the difference, not
|
|
127
|
+
the absolutes — the same spec measured a 4.35 us flush earlier on a cooler
|
|
128
|
+
machine, and only the two halves of one A/B are comparable.
|
|
129
|
+
|
|
130
|
+
- f7df982: Path booleans keep holes, and Bezier flattening terminates on degenerate input
|
|
131
|
+
|
|
132
|
+
`pathToMultiPolygon` emitted every contour of a path as its own polygon.
|
|
133
|
+
`polygon-clipping` unions the polygons of a MultiPolygon, so a donut lost its
|
|
134
|
+
hole the moment it entered any boolean op — `pathUnion`, `pathIntersect`,
|
|
135
|
+
`pathSubtract`, `pathExclude`, `pathDivide` and `pathCrop` all returned a
|
|
136
|
+
filled disc. The path's `fillRule` was never read. Contours are now resolved
|
|
137
|
+
into outer + hole rings by nesting depth, honoring both `nonzero` and
|
|
138
|
+
`evenodd`, before the clipper sees them.
|
|
139
|
+
|
|
140
|
+
Results of a boolean op on a path with holes change shape, so this can move
|
|
141
|
+
pixels.
|
|
142
|
+
|
|
143
|
+
`flattenCubic`, `flattenQuadratic` and their arc-length variants recursed
|
|
144
|
+
forever on a non-finite control point and on a tolerance of `0`, `NaN`, or a
|
|
145
|
+
negative number — the flatness test can never be satisfied, so a stroke or a
|
|
146
|
+
hit-test on a path carrying a `NaN` coordinate blew the stack. Non-finite
|
|
147
|
+
input now emits the segment endpoint and stops; a non-positive tolerance is
|
|
148
|
+
floored at `1e-6`.
|
|
149
|
+
|
|
150
|
+
- 85be764: Fix four renderer bugs found in a review of `packages/core/src/renderer`.
|
|
151
|
+
|
|
152
|
+
- A stroke carrying per-anchor `vertexColors` never set the stencil test
|
|
153
|
+
before its draw. Inside a clipped group it ignored the clip and wrote clip
|
|
154
|
+
bits of its own; drawn after a clipped group it was tested against a bit
|
|
155
|
+
that had just been cleared and disappeared entirely.
|
|
156
|
+
- `GroupState` was never reset between frames, so a frame that threw part-way
|
|
157
|
+
down the tree (the max-7 clip nesting error, for one) left every enclosing
|
|
158
|
+
group's transform, alpha and color matrix on the stack and shifted every
|
|
159
|
+
later frame.
|
|
160
|
+
- `dispose()` never deleted the pattern-fill program.
|
|
161
|
+
- `GLTextureCache` applied a texture's wrap mode on first upload only, so a
|
|
162
|
+
registered image used as both a clamped shader texture and a repeating
|
|
163
|
+
pattern tile got whichever mode reached it first.
|
|
164
|
+
|
|
165
|
+
Also: re-registering a custom shader program on a renderer now deletes the
|
|
166
|
+
program it replaces instead of orphaning it.
|
|
167
|
+
|
|
168
|
+
- a3db906: Correctness pass over the tools, canvas, interactions and affordances layers.
|
|
169
|
+
|
|
170
|
+
Fixed, each with a test: a UI-driven ongoing action (color/opacity pickers)
|
|
171
|
+
committed a second time when `cancelAll` had already ended its handle; the
|
|
172
|
+
`align.*` and `distribute.*` descriptors reported themselves permanently
|
|
173
|
+
disabled, greying out every `<ActionBar>` entry; `reorder.backward`,
|
|
174
|
+
`align.*`, `distribute.*` and `pathfinder.*` read deps they never declared in
|
|
175
|
+
`requires`, which throws in dev builds and silently bypasses a consumer's
|
|
176
|
+
history in production; `ActionsRegistry.begin` ignored `requires` and so never
|
|
177
|
+
passed the paint actions their `applyOps`; `Canvas.hitTestExtras` handed
|
|
178
|
+
registered layers `undefined` where `draw` gets live data, making
|
|
179
|
+
`composeAffordanceLayer`'s hit-test throw; `<Canvas>` never disposed its GL
|
|
180
|
+
renderer on unmount; `useTools` returned a stale registry when a tool was
|
|
181
|
+
added after mount; an `actions` prop override deleted the default action it
|
|
182
|
+
merged onto when the prop object was rebuilt; picking and marquee selected
|
|
183
|
+
nodes on hidden layers; a throwing drop-zone `onDrop` stranded every later
|
|
184
|
+
pointer drag; `snapBackOrDelete`'s `'snap-back'` policy left the node where it
|
|
185
|
+
was dropped; a cancelled pen handle-drag left the anchor it placed; and anchor
|
|
186
|
+
affordances on a second selected path routed their drag into the path actually
|
|
187
|
+
being edited.
|
|
188
|
+
|
|
189
|
+
Removed as unreachable: `useViewportTools`, `Canvas.previewBoundsExtra`,
|
|
190
|
+
`marqueeDrawCommands`, `applyHitExistingGate`, and the `enableKeyboard` options
|
|
191
|
+
on `useAlign` / `useDistribute`, which documented a registration those hooks do
|
|
192
|
+
not perform — `useStandardActions` owns it. The public `InsertOverlayStyle`
|
|
193
|
+
type `marqueeDrawCommands` carried is unchanged and still exported.
|
|
194
|
+
|
|
195
|
+
- 12303bc: The solid batch no longer rewrites one pair of GL buffers on every flush. It
|
|
196
|
+
cycles a ring of buffer sets instead — 64 slot-sized ones, plus 4 growable ones
|
|
197
|
+
for a flush too big for a slot — so a write lands that many draws behind the
|
|
198
|
+
draw that read the same buffer. On an M2 Max via ANGLE a flush goes from ~54 us
|
|
199
|
+
to ~4.4, which is the cost anything that breaks a run of solid geometry was
|
|
200
|
+
paying: entering a clip is 64.9 us -> 10.2, and a boundary between solid and any
|
|
201
|
+
other command kind is 28.4 us -> 2.5. Measured by `tests/perf/clip-cost.spec.ts`
|
|
202
|
+
and `tests/perf/transition-matrix.spec.ts`.
|
|
203
|
+
|
|
204
|
+
The driver tracks a write hazard per buffer object, so a flush that overwrote
|
|
205
|
+
its buffers from offset 0 waited on the draw still reading them. Writing
|
|
206
|
+
disjoint ranges of one buffer does not escape that — the hazard is per object,
|
|
207
|
+
not per range.
|
|
208
|
+
|
|
209
|
+
Nothing about the API or the pixels changes. Buffers are taken on first use
|
|
210
|
+
rather than at construction, so a renderer that never draws solid geometry
|
|
211
|
+
allocates none, and every set is freed in `WeaselRenderer.dispose`.
|
|
212
|
+
|
|
213
|
+
- d36953e: SVG import and export lose less on the way through, and installed fonts pick
|
|
214
|
+
one face per variant slot.
|
|
215
|
+
|
|
216
|
+
Paint servers are now found wherever they are declared, not just as direct
|
|
217
|
+
children of `<defs>`, and a gradient that inherits another's stops or geometry
|
|
218
|
+
through `href` / `xlink:href` resolves instead of coming back empty.
|
|
219
|
+
Percentages are read as ratios, so `x2="100%"` no longer means 100 bounds
|
|
220
|
+
units, and `gradientTransform` warns rather than silently painting elsewhere.
|
|
221
|
+
|
|
222
|
+
Three fidelity bugs in the round trip itself. A leaf's own `transform` was
|
|
223
|
+
decomposed against bounds that had already been through the inherited matrix,
|
|
224
|
+
so a rotation inside a translated `<g>` lost its rotation and moved. Any
|
|
225
|
+
stroke carrying `stroke-opacity` re-serialized with the attribute written
|
|
226
|
+
twice, which is not well-formed XML. And the computed `viewBox` was taken from
|
|
227
|
+
unrotated, untransformed geometry, cropping rotated content out of the export.
|
|
228
|
+
|
|
229
|
+
`<text>` now follows SVG's whitespace rules, so importing a pretty-printed
|
|
230
|
+
file no longer drags the source indentation into the document text; weasel's
|
|
231
|
+
own `<text>` carries `xml:space="preserve"` to keep real line breaks. A nested
|
|
232
|
+
`<svg x= y=>` places its children at that origin.
|
|
233
|
+
|
|
234
|
+
In the shared `d=` grammar, exponent coordinates (`M1e2 1e2`) no longer read
|
|
235
|
+
the `e` as a command, and arc flags written without separators
|
|
236
|
+
(`A5 5 0 0110 0`) no longer drop the arc.
|
|
237
|
+
|
|
238
|
+
`enableLocalFontOutlines` picks the least-qualified face when several installed
|
|
239
|
+
faces reduce to one (weight, style) slot, so "Helvetica Neue Condensed Bold"
|
|
240
|
+
stops displacing "Helvetica Neue Bold" depending on query order.
|
|
241
|
+
|
|
242
|
+
**Exported SVG bytes change**: `<text>` gains `xml:space="preserve"`, a stroke
|
|
243
|
+
writes `stroke-opacity` once, and a document containing rotated or
|
|
244
|
+
group-transformed content gets a larger computed `viewBox`.
|
|
245
|
+
|
|
246
|
+
- Updated dependencies [bd42540]
|
|
247
|
+
- Updated dependencies [d36953e]
|
|
248
|
+
- @weasel-js/geom@1.0.4
|
|
249
|
+
- @weasel-js/history@1.0.4
|
|
250
|
+
- @weasel-js/gestures@1.0.4
|
|
251
|
+
- @weasel-js/font@1.0.4
|
|
252
|
+
- @weasel-js/modes@1.0.4
|
|
253
|
+
|
|
3
254
|
## 1.0.3
|
|
4
255
|
|
|
5
256
|
### Patch Changes
|