gesso-core 0.4.1 → 0.5.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 +92 -0
- package/dist/{CanvasSurface-CaNWsAlm.js → CanvasSurface-CDjWI3EH.js} +4539 -2722
- package/dist/CanvasSurface-CDjWI3EH.js.map +1 -0
- package/dist/{index-CfUSbphd.d.ts → index-DBnLGexp.d.ts} +1389 -485
- package/dist/index.d.ts +2 -2
- package/dist/index.js +610 -88
- package/dist/index.js.map +1 -1
- package/dist/testing.d.ts +13 -1
- package/dist/testing.js +46 -8
- package/dist/testing.js.map +1 -1
- package/package.json +1 -1
- package/dist/CanvasSurface-CaNWsAlm.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,97 @@
|
|
|
1
1
|
# gesso-core
|
|
2
2
|
|
|
3
|
+
## 0.5.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 5a27b40: `activeDescendant` names the node that's active while another keeps focus, such as the highlighted option of a combobox whose field holds the caret, or the cell a grid's cursor is on. The semantics record carries it as the node's id, and the accessibility mirror writes `aria-activedescendant` from it, both on the node's element and on the editing proxy while a field has focus. Every mirrored element now has a DOM id for it to point at. The proxy also says `aria-expanded` for a field whose record is expanded or collapsed.
|
|
8
|
+
- 20ac739: A `<button>` centres its children both ways by default, as an HTML button and the `Button` component do. A box still starts its children at the top left. A button that relied on the old top-left placement says `x="start" y="start"`.
|
|
9
|
+
- 8fb3607: A `current` semantic state, mirrored as `aria-current`, for the current item of a set such as the navigation link to the open page. `selected` was the only way to say it, and on a link or a button a screen reader ignores `aria-selected`, so which page was open went unsaid.
|
|
10
|
+
|
|
11
|
+
`Pagination` marks the page you're on `current` instead of `selected`.
|
|
12
|
+
|
|
13
|
+
- 53b4c46: A copy can put HTML on the clipboard beside the text. An editing group's new `copyHtml(start, end)` gives it, for a selection across fields or inside one field of the group, and `EditingState.html` carries it to the shell, whose copy and cut set `text/html` as well as `text/plain`. A rich editor's copy into a document or an email keeps its formatting. What a group makes of a selection is kept until the selection or its text changes, so `copyText` and `copyHtml` are no longer asked every frame.
|
|
14
|
+
- d356006: A press inside an editing group that lands on none of its fields (its padding, the gap between two fields, a list item's bullet) goes to the nearest field by height, with the caret at the nearest position, as a document does. A press on something that answers presses itself, a button or anything with a click or pointer listener, is left to it. `UiEditingController.fieldNear` is the lookup.
|
|
15
|
+
- 101ea8a: An editing group can follow its selection: `onSelectionChange` hears a selection across fields begin, move and end, so an application can run its own commands, such as bold or indent, over all of it.
|
|
16
|
+
- 839011e: An editing group's fields are one Tab stop, at the first field: Tab from any of them moves past the group, and Tab back in lands on the field last focused. A document of many blocks was a stop per block, and a screen-reader user walking a page with Tab went through every paragraph of a description to reach the controls after it. Other focusable nodes inside the group, a task's checkbox, keep their own stops.
|
|
17
|
+
- f0ade22: Editables can select as one. Set `editingGroup` on a container and a selection can start in one field and end in another: arrows move between fields at their edges (up and down keep the column), Shift extends across them, a drag or a Shift and press reaches into other fields, and select all takes the whole group. Every field in the range draws its part. Typing, deleting, Enter, paste and cut over such a selection go to the group's `onEdit` with both ends, since only the application knows how its blocks join, and copy and cut take the whole selection, as the group's `copyText` if it gives one.
|
|
18
|
+
- 29a36ac: `EditingService.select(anchor, focus)` sets a selection from code, in one field or across the fields of an editing group, and focuses the field its focus end is in. An editor needs it to leave a selection selected after a command over it, since its fields can only select their own text.
|
|
19
|
+
- fac08c0: Focus from code can leave the page where it is, as `element.focus({ preventScroll: true })` does: `autoFocus({ preventScroll: true })`, `FocusService.focus(node, { preventScroll: true })` and `UiFocusManager.focus(node, source, { preventScroll: true })`. For focus placed for a screen reader, such as a page's content region focused as it opens, which a reveal scrolled to a few pixels short of its own top. The options reach `onFocusChange` listeners as a third argument, and a key pressed later that makes the focus visible doesn't scroll to it either. The default is unchanged.
|
|
20
|
+
- 5b3508d: `gridcell` is a role: the cell of an interactive `grid`, such as a calendar's day, and the cell that can be `selected`. `cell` stays for a table's cells.
|
|
21
|
+
- b502e0e: A text run can be `hidden`: it stays in the text, with its offsets, its place in a copy and in undo, but takes no room, is left out of line breaking and the line box, and neither renderer draws it. In a field the caret steps over each stretch of hidden text as one unit: arrows cross one visible character or word and the hidden text in the way, Backspace and Delete remove the visible character next to the caret and keep the hidden text beside it, a press resolves to the side of hidden text it lands on, and a double click selects the word as drawn. While an IME composes, a field's runs are moved to make room for the composing text instead of being dropped, so styling and hidden text survive the composition. Caret and selection geometry in a field with runs is now measured run by run, so a caret after a bold or larger run sits after its glyphs.
|
|
22
|
+
- 979053a: A layout listener that changes layout is painted on the same frame. `breakpoint`, `sizeContainer` (and so `Responsive`), `autoFocus` and anything else on `host.onLayout` hear a box after layout, and what they wrote used to be laid out on the next frame, so a page whose breakpoint gave it wide padding was drawn with its narrow padding first and jumped. The runtime now lays out again before it paints, as a browser does after a `ResizeObserver` callback: only what the listeners dirtied, telling only the listeners whose boxes then changed, until they write nothing more that lays out. The loop is bounded at 8 layout passes a frame; past it the frame paints what it has and a warning says so once. A frame whose listeners write nothing that lays out runs one pass. A scroll into view asked for while the listeners run (an `autoFocus` revealing its node) waits until the boxes are final. `FrameMetrics.layoutPasses` counts the passes, and `measured` and `relayoutRoots` count every pass. A geometry `sharedElement` morph lands on the frame of the change instead of being covered by a transform for one frame. `UiScheduler.recollect`, `UiFrame.merged` and `DirtyNodeSet.anyFlags` are what the runtime builds this from.
|
|
23
|
+
- 47aba08: The stock theme is drawn the way current interfaces are. Text is set in `system-ui, sans-serif`, the platform's own face, on line heights from a 4-point grid (body is 14 on 20, not 14 on 16.8), and in a blue-black ink rather than black. The palettes use cool-tinted neutrals and a deeper accent, so white on `primary` and `controlAccent` clears WCAG AA, which the old bright blue did not; every stock text pair in both palettes is now held to AA by a test. A medium button is 36 high with 16 either side. Select, DatePicker, Accordion and Tree draw their disclosure arrows as Heroicons chevrons rather than as `▾` and `▸`, which every face set at a different size. An application on the stock theme reflows: text that names no size is taller, and a layout measured against 16.8 moves. A theme that sets its own typography and palette is unaffected except for the button padding, which is a `controlTokens` value it can set back.
|
|
24
|
+
- 99538fa: A `multiselectable` semantic state, mirrored as `aria-multiselectable`. A list whose rows are selected as a set had no way to say so, and Chrome took the option under its active descendant to be the selected one: a screen reader announced a row as selected that wasn't.
|
|
25
|
+
- fb2a6d8: A precision device's wheel steps are paced over frames. A trackpad sends on its own clock, so a frame got one, two or three of its steps and a steady flick moved unevenly; the runtime now moves each frame by the rate the steps have been arriving at, never more than a frame behind, and applies the rest when the input stops. `UiWheelController` takes a `pace` option and an `advance()` a host calls once a frame; the runtime turns it on.
|
|
26
|
+
- 94a9f13: Both renderers paint `boxShadows`, with CSS `box-shadow` semantics: offset, blur, spread, colour and `inset`, following the node's corner radius, with the first shadow on top. Until now the prop resolved and nothing drew it, so every theme's `shadows` scale did nothing. Canvas2D draws a shadow with the canvas's own blur, cast from a shape thrown outside the clip; WebGPU evaluates the blurred rounded rectangle in the fragment shader, one quad per shadow. A shadow's colour may now be a palette name (`boxShadow(0, 4, 8, 0, 'shadow')`), resolved against the node's theme like any other colour, so `UiBoxShadow.color` widens from `UiColor` to `UiColorValue` and `PaintState.boxShadows` holds the resolved `PaintBoxShadow`. A node's paint extent now takes in its outer shadows, so a card just off screen still casts its shadow on, and changing a shadow updates it without a layout pass. The WebGPU primitive instance grows from 20 to 24 floats, and its kind is read as the float it is written as.
|
|
27
|
+
- b7c9514: A paste carries the clipboard's HTML along with its text. The shell read only the plain text, so a copy from a web page or a document arrived without its headings, lists and links. `UiBeforeInputEvent`, `UiPasteEvent` and an editing group's edit now have `html` (null when the clipboard had none); the field still inserts the plain text, and an editor that keeps structure can cancel that and convert the HTML. `fireEvent.paste` takes the HTML as a second argument.
|
|
28
|
+
- 6f03f61: A shortcut prints the way the platform writes its own: `⇧⌘K` on a Mac and `Ctrl+Shift+K` elsewhere, in `formatShortcut` and every binding's `display`. It printed `Ctrl` everywhere, on the grounds that the render worker couldn't see the platform; it can, from the user agent, and the editing keys already follow it. `formatShortcut(steps, platform)` prints for a platform of the caller's choosing.
|
|
29
|
+
|
|
30
|
+
### Patch Changes
|
|
31
|
+
|
|
32
|
+
- 8d25c04: A drop target with `autoScroll` now scrolls while a drag is held near its edge even when a deeper drop zone, such as a row inside the list, is the one that would take the drop. Before, auto-scroll ran only on the winning zone, so a list whose rows were drop targets never scrolled during a drag. Drop zones can implement the new optional `UiDropZone.hover(state)`, which is called for every accepting zone under the pointer, and `dropTarget` uses it for auto-scroll.
|
|
33
|
+
- 303e85a: Canvas2D draws a row millions of pixels down a scroll container on its pixel. Skia keeps the canvas transform and every coordinate in 32-bit floats, so a scroll offset of a hundred million pixels and a row at the same depth were each rounded to the nearest eight pixels, and the rows of a five-million-row grid came out with gaps and overlaps near the bottom. A translation of a million pixels or more is now held in a double and added to each coordinate before the canvas sees it. Nothing changes below that.
|
|
34
|
+
- 0f02fc2: A frame clamps the text scroll of the fields it laid out or scrolled, rather than of every field ever laid out. In the issue tracker's 5,000-line document that was five thousand clamps for each keystroke.
|
|
35
|
+
- 4450c5c: A re-render that stops declaring a property takes it off the node. Only bindings were torn down before, so a plain value stayed: a conditional that swapped `<scrollview padding={20}>` for a `<scrollview>` reused the node and kept the padding. What modifiers and the runtime write on a node is left alone, and a modifier overriding the property keeps its value. `UiGraph.removeNodeProperty` is the removal, through the same cascade as a write.
|
|
36
|
+
- 7753bdc: A bare Enter or Space is no longer a shortcut while a button or link has focus, unless the shortcut is that control's own. Pressing a button is a default action applied after the key has been through the registry, so an application-wide Enter took the key from the focused button: in the issue tracker, Enter on "Clear selection" opened the issue under the list's cursor instead of clearing.
|
|
37
|
+
- 47aba08: A flex line that fits to within float noise no longer flexes. A container sized to its content sums its items in one order and the line sums them in another, so "exactly enough room" could arrive as -3e-14 and shrink an item with a fixed `width: 28` to 27.99999999999997.
|
|
38
|
+
- fe0c1e0: Text without runs is broken into lines one hard line at a time and remembered per line. A keystroke in a long multiline field re-wraps only the line it changed instead of the whole text: typing into a 5,000-line field went from about 19 ms of layout to about 3.5 ms. Text with `spans` keeps the previous path, because its widths are measured by offsets into the whole text.
|
|
39
|
+
- 2ce079c: A hidden (`visible={false}`) or disabled subtree has no Tab stops and refuses focus, as `display: none` and a disabled fieldset do in a page. Only the node's own `visible` and `disabled` were checked, so the buttons of a toolbar hidden until something was selected were Tab stops nobody could see, and a screen reader heard nothing at them.
|
|
40
|
+
- be3e274: An IME commit that is what the composition already showed now fires `onInput`. The commit was compared with the text that already held the composition, so picking the candidate on screen (the usual case) changed nothing as far as the field could tell, and an application holding the text never heard of it.
|
|
41
|
+
- b2dddbc: A window resized to a size it had been at before now lays out at that size. Two things went wrong. A node sized in percent was handed back the size it had under a different container, because the container's size was not part of what layout remembered. And a stack whose measurement came from that memory placed its children at whatever size they had last been measured, which could be the other window's. An application shell with a percentage-width sidebar kept its sidebar at the old height, with the footer off screen or floating above the bottom, until something else changed.
|
|
42
|
+
- ab0c1a6: A line's only flex item, growing and shrinking to fill a line of definite size with a minimum of its own, no longer marks its content as read: no base could change its size. Since a content basis started marking its subtree, an application region like that (the issue tracker's main pane) had every row its list mounted on a scroll laid out from the root.
|
|
43
|
+
- 80a3577: Layout remembers three measurements per node instead of two. A row holding a flexible scroller of auto-height blocks asks each block three questions per pass: unbounded for the flex basis, at the final width, and at the stretched height. With room for two, every pass evicted one, so editing one block of a 1,000-block document re-measured all 6,005 nodes. It now re-measures under 20.
|
|
44
|
+
- 427ce99: The renderers cull a node by where its subtree may paint rather than by its own box, so a child painting outside a parent that doesn't clip, as the docs say it may, is drawn when the parent's box is off screen or empty. The issue tracker's tour, an absolutely positioned panel inside an empty wrapper, was laid out and never drawn. Each layout record keeps that extent, the box whenever nothing reaches past it, so culling costs what it did.
|
|
45
|
+
- d3ab865: A predicted trackpad flick no longer springs off an edge it runs into, or steps back as it slows: room is judged from where the steps have really taken the container, each frame sets a clamped position, and a frame never moves against the latest step.
|
|
46
|
+
- 0bef08b: A precision device's scroll is predicted to the frame rather than paced behind it. Each frame puts the page where the input will have reached when the frame is shown, from the steps' velocity and their timestamps, which the shells now pass with each wheel event; the page stays as even as pacing made it without trailing the hand by a frame. `UiWheelController.wheel` takes the event's time, and `advance` the frame's.
|
|
47
|
+
- aa33728: A press in a field places the caret by the layout the press landed on. The offset is read before the press moves focus, so a field that draws itself differently once focused (one that shows hidden runs, or restyles its text) puts the caret where the person pressed in what they saw, not at the same x in the new layout.
|
|
48
|
+
- 6d51def: A `ref` is handed its node once the node's props are all written and it has the environment it will be under, wherever `ref` sits among the props. It used to fire as the builder reached it, so a node built this pass had the default environment: an overlay opened from a placeholder's ref, as a `Toast` mounted already open does, took the light theme in a dark app.
|
|
49
|
+
- 8c4f475: Revealing a node bigger than its scroll container brings it in by its start, unless it already fills the view, as CSSOM's `nearest` does. It was moved by its nearer edge, which for a tall node is its end: the issue tracker's issue page, which focuses the whole issue when it opens, opened scrolled to the bottom.
|
|
50
|
+
- 1d61bae: A scroll view with no size of its own along the axis it scrolls is its content's size, within its bounds, as the docs said and CSS does. A loose bound such as its own `maxHeight` was taken as its size, so a dropdown list capped at 280 pixels was 280 pixels of mostly empty panel when it held two options. A tight bound (a flexed or stretched size) still sizes it.
|
|
51
|
+
- 5d67836: The runtime keeps the accessibility tree as records by id plus each record's children in order, and works out a record's index only when it sends that record or the tree is asked for. A structural change used to renumber every record after it and rebuild the whole tree's order, a pass over the whole document on every Enter in a long editor. An Enter in a 5,000-line document now spends about 3 ms on semantics where it spent 7 to 10. The structural rebuild goes through `rewalkSemantics`, and `SemanticsMemory` is what each walk leaves for the next.
|
|
52
|
+
- 444371c: A change in the shape of the tree no longer rebuilds the whole accessibility tree, and no longer sends every later sibling an update. The tree is rebuilt from the nearest record above the change, and anything inside it that nothing touched is taken back as it was: renumbered if it moved, never described again, and a transparent subtree (a block of a long document) taken back as a run without being walked. Updates that only renumber a record whose siblings kept their order are no longer sent, since a mirror that applies removals and adds in order already has it in place: inserting a paragraph in a 5,000-line document sent 4,266 patches to the main thread, and now sends 2. `diffSemantics` gains a companion, `dropIndexShifts`.
|
|
53
|
+
- d617d34: A laid-out subtree that moves without changing size is shifted instead of placed again. Boxes are absolute, so inserting a row near the top of a long list moved every row below it, and each one was placed again all the way down: an Enter in a 5,000-line document placed 9,572 nodes and took 18 ms of layout. It now places 7 and takes about 3 ms. `LayoutStats` gains `shifted`, the number of subtrees moved this way.
|
|
54
|
+
- 2c572e3: Shortcuts can bind the space bar. `shortcut({ keys: 'Space', … })` never fired before: a shortcut string splits on whitespace, so the key can't be written as `' '`, and the name `Space` was kept as a literal key name that no press ever matched. `Space` (and `Spacebar`) now mean the space bar, with any modifiers, and `formatShortcut` prints it back as `Space`.
|
|
55
|
+
- 84fe6d5: A focused text field keeps its editing keys. An application-wide shortcut on `Mod+Z`, `Mod+A` or a word or line move no longer fires while keys go to a field, so undo in a field undoes the typing rather than the app's last change. Other modified keys, and Enter in a single-line field, still reach the registry.
|
|
56
|
+
- e73a5fc: Scrolled content is drawn on a whole device pixel. The offset keeps the fraction, so a trackpad's small steps still add up, but Canvas2D drew the content at the exact offset, and text between pixels rasterised differently each frame, shimmering as a flick slowed down.
|
|
57
|
+
- 1de054a: A frame's layout agrees with a fresh one when content arrives under a flex item whose basis is its content. The item's basis was read from a child whose `height: 100%` had nothing to resolve against yet, and the same child, resolved on the next measure, was then treated as a relayout boundary, so rows arriving in a list never reached the basis. The column kept sharing its height as it had while the list was empty, until something unrelated (a theme change, a resize) laid it out from the top, and an application's header then shrank under the reader. A scroll view with no size of its own passes the same on to its content, since under a loose bound its size is its content's.
|
|
58
|
+
- 9341d31: A trackpad's steps are no longer smoothed one at a time. Chrome on a Mac reports a trackpad's legacy `wheelDeltaY` as three times its pixel delta, so a 40-pixel step looked like a mouse wheel's detent and was animated while the steps around it weren't, which stuttered a flick, most of all as it slowed. Once an event that doesn't look notched arrives, the wheel is taken to be precise while events keep coming.
|
|
59
|
+
- 2e3e56d: A colour that's neither a palette name the node's theme carries nor a colour now warns on the console, once a name, instead of painting nothing in silence. The issue tracker used a `surfaceRaised` that no theme has, in six places; none of them ever painted.
|
|
60
|
+
- db1a6a1: A wrapping row's minimum height is all its lines, not its tallest item. In a column beside a sibling that grows, a wrapping row (a filter bar of chips, say) was squeezed to its first line and the rest spilled out over whatever came next. CSS counts every line, and so does this now.
|
|
61
|
+
|
|
62
|
+
## 0.4.2
|
|
63
|
+
|
|
64
|
+
### Patch Changes
|
|
65
|
+
|
|
66
|
+
- d27e076: **The wheel scrolls an editable that overflows.** A multiline field with a fixed
|
|
67
|
+
height, or an unwrapped one narrower than its line, followed the caret and
|
|
68
|
+
nothing else: a wheel over it did nothing. It now scrolls the field's text on
|
|
69
|
+
either axis, clamped where the caret-follow offset is and without moving the
|
|
70
|
+
caret, and a wheel the field has no room for chains to the scroll container
|
|
71
|
+
around it, as one from a scroll container's end does.
|
|
72
|
+
|
|
73
|
+
A multiline field also shows the overlay scrollbar a scroll container does,
|
|
74
|
+
fading when idle, revealed by hovering its edge, and draggable once it shows.
|
|
75
|
+
While hidden it takes no presses, so a click at the end of a line still places
|
|
76
|
+
the caret. A single-line field draws none.
|
|
77
|
+
|
|
78
|
+
`scrollRange(record, axis)` is the furthest a record can scroll, the one answer
|
|
79
|
+
the layout engine's clamp, the scrollbars and the scroll sinks now all read.
|
|
80
|
+
|
|
81
|
+
- d6c52da: **`scrollWith`: a container that scrolls in step with another node.** Binding a
|
|
82
|
+
container's `scrollY` to what `scrollPosition` reports leaves it a frame behind,
|
|
83
|
+
because the report arrives after the frame is laid out. A line-number gutter
|
|
84
|
+
beside a field, or a row header beside a grid, has to line up on every frame.
|
|
85
|
+
`scrollWith` names the node to follow and `scrollWithAxis` the axes (`both` by
|
|
86
|
+
default); the follower takes the leader's effective offset in the same layout
|
|
87
|
+
pass that settles it, whatever moved the leader. It ignores its own offset on a
|
|
88
|
+
followed axis, shows no scrollbar, and passes a wheel over it to the leader. An
|
|
89
|
+
`overflow="hidden"` box that follows is scrolled all the same, as script scrolls
|
|
90
|
+
one in CSS.
|
|
91
|
+
|
|
92
|
+
`scrollPosition` on an `<editabletext>` reports how far the field has scrolled
|
|
93
|
+
its own text, from the wheel, its scrollbar, the caret or a clamp.
|
|
94
|
+
|
|
3
95
|
## 0.4.1
|
|
4
96
|
|
|
5
97
|
### Patch Changes
|