shadcn@4.20.0
- #11728
51f3e12203b0026ea106cafb4f770bda9abead87Thanks @shadcn! - addnpx shadcn migrate cnto replaceclsx,tailwind-mergeandcnfastin Tailwind CSS v4 projects.
@astrojs/starlight@0.42.0
-
#3572
292fb17Thanks @HiDeoo! - Distributes package as JavaScript files with dedicated type declaration files instead of TypeScript source files. -
#4121
2623ae6Thanks @delucis! - Simplifies markup for Starlight’s mobile menu toggle⚠️ Potentially breaking change: If you use a theme plugin, custom styles, or component overrides targeting theMobileMenuTogglebutton orPageFramecomponents, you may need to adjust these for the new markup. The button is no longer wrapped in a<starlight-menu-button>custom element and no longer uses thearia-expandedattribute. Instead, you can use the.sl-menu-buttonclass name to target the button and the:popover-openpseudo-class to style the menu open state specifically.In the following example, custom styles for the menu button are updated for the new approach:
- starlight-menu-button button { + .sl-menu-button { color: var(--sl-color-text); } - starlight-menu-button[aria-expanded='true'] button { + .sl-menu-button:has(~ :popover-open) { color: var(--sl-color-text-accent-high); }
See
MobileMenuToggle.astroandPageFrame.astroon GitHub for the full source code of the updated components. -
#3572
292fb17Thanks @HiDeoo! - Removes thetaglineconfiguration option, which was never used.If your configuration included a
taglineoption, you can safely remove it without any replacement. -
#4134
6135f01Thanks @HiDeoo! - Updates internal@astrojs/mdx,@astrojs/markdown-satteri, andsatteridependencies.⚠️ BREAKING CHANGE: The following minimum versions are now required:astrov7.2.10 or later@astrojs/markdown-satteri0.4.0 or later (if you use it)@astrojs/markdown-remark7.3.0 or later (if you use it)
Please update Starlight and Astro together:
npx @astrojs/upgrade
-
#4121
2623ae6Thanks @delucis! - Refactors Starlight’s mobile menu toggle to work when JavaScript fails or is disabled⚠️ BREAKING CHANGE: This release drops official support for Chromium-based browsers prior to version 116 (released August 2023), Safari-based browsers prior to version 17.0 (released September 2023), and Firefox prior to version 125 (released April 2024). You can find a list of currently supported browsers and their versions using this browserslist query.This change also removes the
data-mobile-menu-expandedattribute, which was previously added to<body>while the mobile menu is open. If you have custom code that was depending on this attribute, you will need to update it to use a new selector to check if the mobile menu is open.In the following example, a custom background colour for the site header while the menu is open is updated for the new approach:
- [data-mobile-menu-expanded] header { + body:has(sl-sidebar-pane:popover-open) header { background-color: var(--sl-color-bg); }
v5.4.0
This release adds a center operation to Editor.alignShapes, a tleditors registry of mounted editors, iterateGraphemes to @tldraw/utils, and two new reactive methods on AtomMap. It also deprecates useViewportHeight, speeds up the signals and store layers, and lands a broad reliability pass across the SDK, with over a hundred fixes to undo history, selection and tool interactions, cropping, arrows, the signals and store layers, sync, and local persistence.
-
🔜
useViewportHeight()is deprecated. Readwindow.visualViewportdirectly instead. The hook returns only the visible viewport's bottom edge, and keeping a panel clear of the software keyboard generally needs the whole visible rectangle. (#9826) -
Add
'center'as anEditor.alignShapesoperation. It applies the existing'center-horizontal'and'center-vertical'operations together, so shapes center on both axes in one command. (#9074) -
Add
tleditors, a reactive global registry of currently mounted editors. Use it to reach live editors from outside the React tree, for example from sidebar chrome or a keyboard shortcut handler. (#9904)import { tleditors, useValue } from 'tldraw' const mounted = useValue('mounted editors', () => tleditors.getMounted(), [])
-
Add
getOrInsert(key, defaultValue)andgetOrInsertComputed(key, callback)toAtomMap, matching theMapmethods added in newer JavaScript runtimes. Both are reactive, and the callback only runs when the key is absent. (#9752) -
Add
isPage(record)to@tldraw/tlschema, a type guard that narrows an unknown record toTLPage, matching the guards already exported for the other record types. (#9774) -
Add
iterateGraphemes(str)to@tldraw/utils. It iterates a string's grapheme clusters, usingIntl.Segmenterwhen it's available and falling back to code-point iteration when it isn't. (#9896) -
EmojiPickerProps.onSelectnow receives the originating event as an optional second argument. Custom reaction palettes can forward it to opt into shift multi-select. (#9999)
- Shift-click an emoji in a comment's reaction palette to add several reactions without the palette closing. A plain click still applies the reaction and closes the palette. (#9999)
- Keyboard input now counts as collaborator presence activity, so peers no longer fade out and disappear while someone is typing. (#9929)
- Reduce per-pointer-event allocations in
Group2dandEditorhit-testing. (#8600) - Speed up editor hot paths: set lookups replace array scans in the selection side effect and the erasing check,
getCollaboratorsmakes a single pass over the presence records, andgetShapeUtilonly builds its assert message when the lookup fails. (#10358) - Speed up signal reads in
@tldraw/state. Capturing a parent used to scan the capturing signal's parent set twice, once to check for the parent and again to add it. (#9690) - Reduce per-signal memory use and per-flush allocations in
@tldraw/state. (#10155) - Reduce the work and allocations in
@tldraw/storehistory bookkeeping, so squashing record diffs and filtering query history no longer build intermediate copies on every tick. (#9689, #9869) - Move the
exportBackgrounddefault (true) into theTLInstancerecord type in@tldraw/tlschema, so every code path that creates the instance record gets the same value. (#10534)
- Fix the editor failing to load on older browsers that lack
Intl.Segmenter, such as Firefox before 125. (#9896) - Fix the frame loop stopping permanently when a
tickorframelistener threw, which silently disabled camera animations, edge scrolling, and other frame-driven behavior for the rest of the session. (#9946) - Fix a crash when computing a frame's geometry if its heading text couldn't be measured yet. (#9496)
- Fix a crash in hit testing when a custom frame-like shape uses a plain, non-group geometry. (#10328)
- Fix a crash when pressing Enter with a frame, video, or embed selected while the geo, arrow, or text tool is active. (#10195)
- Fix undo after a cut also reverting the change made before it. (#9920)
- Fix several actions merging into the previous undo step instead of creating their own: Unlock all, changing an arrowhead, keyboard changes to the opacity and image zoom sliders, alt+double-clicking a rectangle into a check-box, saving alt text, and dropping a file or url onto the canvas. (#10468, #10469, #10470, #10473, #10474, #10478)
- Fix exiting an empty text shape leaving a phantom undo entry: document changes made by
onEditEndare now recorded in history. (#10369) - Fix undo after
bailToMarkremoving records that were not part of the undone change. (#10207) - Fix undo/redo not removing an optional record property that the change had deleted. (#10215)
- Fix collaboration-mode readonly syncs ending up in the user's undo history. (#10372)
- Fix changes made by
operationCompletehandlers after a remote merge being attributed to the remote source. (#10229)
- Fix Escape being ignored while pressing on the canvas with the select tool. (#10175)
- Fix Escape during a scribble selection dropping the prior selection. (#10489)
- Fix Space+arrow and Alt+arrow also nudging the selected shapes. (#10453)
- Fix Alt not suppressing Shift/Ctrl additive selection when releasing the pointer over a selected shape. (#10510)
- Fix bookmarks and other non-resizable shapes being left behind when resizing a multi-selection. (#10491)
- Fix alt-cloning mid-drag reparenting the original shape instead of the clone when dropping into a frame. (#10186)
- Fix the cursor staying as a resize or rotate arrow when Ctrl/Cmd+dragging a selection handle to brush-select. (#10487)
- Fix handle snapping on rotated shapes landing off the snap target. (#10168)
- Fix an interrupted press with the geo, frame, or note tool (undo, opening a menu, or changing page before releasing) creating a default-size shape. (#10506)
- Fix an invisible empty text shape being left behind when switching tools while dragging out a text box. (#10457)
- Fix the text tool undoing earlier work when cancelling a pointer-down after a drag-created text shape. (#10194)
- Fix shift-click with the draw, highlight, and line tools editing a shape on the previous page after a page change. (#10455)
- Fix the draw tool's shift segment threshold depending on the zoom level. (#10240)
- Fix the first point of a pen stroke losing its pressure value. (#10243)
- Fix small, slowly drawn loops sometimes failing to close, because dense input sampling made the stroke measure shorter than it was. (#9930)
- Fix the eraser dropping a frame it was pressed on once the drag begins. (#10507)
- Fix a camera jump when a second finger touches down during a one-finger zoom with the hand tool. (#10178)
- Fix Escape ending a spacebar pan while Space is still held. (#10504)
- Fix tools whose
onEntertransitions to a child state ending up with two active children. (#10354) - Fix double clicks being cancelled by small pointer movements when the editor container is offset from the page origin. (#10349)
- Fix modifier keys (Shift, Alt, Ctrl, Cmd) briefly being treated as held at the start of a new click or drag right after being released, which could momentarily affect snapping and other modifier-dependent behavior. (#9523)
- Fix held keys, including Space panning, staying active after the window loses focus. (#10500)
- Fix stale crop state after leaving crop mode by switching tools. (#10167)
- Fix Escape during a crop drag reverting the whole crop session instead of only the drag in progress. (#10462)
- Fix Escape in image crop mode clearing the selection. (#10463)
- Fix crop mode staying active when the cropping shape is deleted. (#10370)
- Fix pressing Enter on a selected image entering crop mode in a readonly editor. (#10492)
- Fix arrows bound to custom shapes with non-standard
sizevalues rendering asNaN. (#10214) - Fix elbow arrows with a free terminal sometimes routing through the bound shape. (#10219)
- Fix arrow geometry ignoring a custom stroke width from
getCustomDisplayValues. (#10230) - Fix the arrow binding target highlight staying visible after clicking an arrow handle without dragging. (#10191)
- Fix a stub arrow being left on the canvas when switching tools during an arrow press. (#10461)
- Fix arrow label drag reverting when a menu opens or undo is pressed mid-drag. (#10493)
- Fix Cmd+Enter / Tab on a note creating a duplicate on top of an existing neighbour. (#10199)
- Fix adjacent-note snapping under a scaled, grown note. (#10204)
- Fix the note tool not snapping a new note beside the note it just created when tool lock is on. (#10484)
- Fix attributed notes losing their font in exports. (#10249)
- Fix shift-extending a line inside a rotated frame placing the point incorrectly. (#10238)
- Fix the second diagonal of an x-box shape being treated as an outer edge. (#10245)
- Fix a replaced image being zoomed when the original had an explicit default crop. (#10234)
- Fix video shapes showing a floating spinner with no bounding box while their asset uploads or loads. They now show the same loading plate as image shapes. (#9994)
- Fix Flatten to image producing different groupings depending on selection order, and not merging clusters that were only connected through a bridging shape. (#8661)
- Fix dragging a frame out of its parent when grabbed over a nested child, and restore a child's original z-order when dragged back into a frame. (#10329)
- Fix camera constraints for bounds away from the page origin, and clamp padding against the correct viewport axis. (#10337)
- Fix
setCameraOptions({ zoomSteps: undefined })breaking every later camera move. (#10387) - Fix
slideCamerazoom momentum driving the zoom to zero on a long frame. (#10388) - Fix malformed viewport deep links moving the camera to the origin instead of falling back to fitting the page content. (#10508)
- Fix following a user whose own leader has left or has no presence yet. (#10389)
- Fix
getSelectionRotatedScreenBoundsgoing stale when the editor container moves. (#10390) - Fix
duplicateShapesthrowing on unknown ids and offsetting nested duplicates twice. (#10355) - Fix
packShapespacking shapes of different heights into a single column. (#10381) - Fix
stackShapesreordering shapes when a gap is given. (#10383) - Fix nested 270° shapes being dropped from axis-aligned shape clustering. (#10384)
- Fix
putContentOntoCurrentPagemutating the content passed to it. (#10367) - Fix
setErasingShapesmutating its input array, so it accepts store-owned (frozen) arrays. (#10371) - Fix the teardown returned by the
createTLStoreonMountoption never running when the editor unmounts. (#10375) - Fix drop events inside the canvas never reaching React drop handlers, and keep Safari gesture suppression working with multiple editors on a page. (#10360)
- Fix object URLs for locally persisted assets leaking across remounts. (#10361)
- Fix the click-capture overlay staying over the canvas after right-click panning with a menu open. (#10359)
- Fix hiding and showing menus by context id, and tolerate corrupt user-preference data in localStorage. (#10344)
- Fix
Vec.Slope,Vec.cross, andareAnglesCompatiblefor negative angles,rotateSelectionHandlefor negative rotations, and dotted dash arrays for very short paths. (#10352) - Fix laser trails staying visible after changing page. (#10509)
- Fix locking a mixed selection of locked and unlocked shapes leaving the shapes selected. (#10480)
- Fix wheel event normalization passing through non-finite delta values. (#9586)
- Fix the Frame selection shortcut (Ctrl+Alt+G) not working on Windows and Linux. (#10481)
- Fix pasted text shapes and bookmarks not being selected after paste. (#10485)
- Fix context-menu paste landing under the pointer instead of at the right-click point. (#10488)
- Fix file drops and pastes silently doing nothing when one of the files is an image that can't be decoded. The bad file is now skipped with an error toast and the other files are placed. (#10495)
- Fix the Edit link dialog staying open as an empty panel when its shape is deleted or deselected. (#10496)
- Fix wheel and trackpad scrolling over the minimap moving the camera at double rate. (#10499)
- Fix the actions menu button appearing, and opening empty, in readonly mode with the hand and zoom tools. (#10503)
- Fix closing a stacked dialog by touch also closing the dialog beneath it. (#10002)
- Fix the loading screen not honoring the system theme on a dark OS, and the reduce motion preference not following the OS setting until a reload. (#10528)
- Fix the storage read-failure alert promising a reload that never happened. (#10530)
- Fix the casing of the error fallback's refresh button. (#10362)
- Fix pasted links showing a broken preview image when the linked page has no Open Graph image. (#9909)
- Fix the counterclockwise rotation tooltip not showing its comma key. (#9772)
- Fix the spacing around the cursor chat item in the context menu. (#9921)
- Fix the people menu's collaborator rows not lining up with your own row above them: the follow icon sat too close to the right edge, and collaborator names sat slightly left of your own. (#9900)
- Fix the comment thread popover briefly rendering with a doubled shadow the first time a thread is opened. (#9886)
- Fix edits made in the last 350 ms before closing or reloading a tab being lost from local persistence. (#10526)
- Fix background tabs repeatedly dropping and re-establishing their sync connection when the browser throttles timers. (#9964)
- Fix
useSyncDemocreating assets for uploads the server rejected. (#10109) - Fix
loadSnapshotfailing on better-sqlite3, andNodeSqliteWrappergetting stuck in a transaction whenCOMMITfails. (#10111, #10113)
- Fix computeds returning stale values when read inside a transaction during an effect, from a deferred effect, or after a reactor restarts. (#10145)
- Fix effects with no signal dependencies re-running on every
start(). (#10148) - Fix nested transactions inside effects not rolling back with their parent. (#10149)
- Fix effects observing half-restored state when a
deferAsyncEffectscall throws. (#10150) - Fix
@computedon a subclass override that callssuper, and@computed()with no arguments. (#10151) - Fix computeds re-running their compute function on every read after their first derive throws. (#10152)
- Fix computeds read inside an atom's
computeDiffnever seeing that change, and an explicitnulldiff passed toatom.set()or returned fromwithDiff()clearing history. (#10153) - Fix
localStorageAtomthrowing outside the browser. (#10154) - Fix a stack overflow in
ImmutableMapandAtomMapfor keys named afterObject.prototypemembers, and makeNaNand-0key equality match nativeMap. (#10202) - Fix
AtomMapthrowing when an entry is deleted mid-iteration. (#10209) - Fix
StoreSchema.createreporting a redundant migration dependency as circular. (#10213) - Fix the
store.query.ids()query creator being called with a computed's(previousValue, epoch)arguments. (#10218) - Fix
CollectionDiffs fromstore.query.ids()andindex()containing an emptyaddedorremovedset after an add/remove round trip. (#10221)
v8.3.0-beta.0
- accept Rolldown watch options in
server.watch(#23133) (1b5cfe3) - add closeServer and closePreviewServer hooks (#23110) (e17d2d5)
- add top-level
tsconfigoption (#23310) (93164c3) - add warning for unsupported hooks in plugin returned from
applyToEnvironmenthook (#23191) (fdef04f) - cli: support naming the CPU profile via --profile [name] (#23042) (a500dee)
- config: warn on named imports from JSON modules (#23378) (472385e)
- css: minify style tag (#23183) (8156684)
- searched params attached to workers are now preserved (#22280) (517b97f)
- support subpath imports in dynamic import statements (#23185) (b78e2f1)
- use
import.meta.ROLLDOWN_FILE_URL_*for assets in JS (#22888) (4366ac4) - use
import.meta.ROLLDOWN_FILE_URL_*for other plugins (#22894) (e38f29e) - worker: remove worker chunk if it's detected that it's not referenced (#22473) (924997a)
- config: close bundles when generation fails (#23256) (6bacc95)
- css: keep newline-separated srcset candidates intact (#23265) (4f9d2f4)
- deps: update all non-major dependencies (#23337) (d550815)
- deps: update all non-major dependencies (#23404) (238ad81)
- deps: update rolldown-related dependencies (#23338) (76e8082)
- deps: update rolldown-related dependencies (#23405) (b882566)
- dev: run closeBundle after buildEnd failure (#23165) (8cb872e)
- hmr: handle
import.meta.hot.invalidatein virtual module (#23171) (6162968) - utils: handle dot in srcset density descriptor (#23346) (b50e1b4)
- utils: match timestamp query parameter with proper delimiters (#23364) (41f3c6f)
4.1.0-next.2
4.1.0-next.2 (2026-09-02)
v4.2.0
[!IMPORTANT] Vuetify Needs Your Support! The OpenCollective funds are running low. The team needed to scale down and is barely able to compensate the contributors for their work on the framework and the ecosystem tools.
If Vuetify is part of your stack, please consider sponsoring the project so we can continue delivering updates and fixes.
Every contribution helps us keep Vuetify alive and signals to maintainers that their effort is appreciated.
Thank you.
The following components have been promoted to the core framework from labs:
- inputs: add open-on-focus to inputs with VMenu (#23126) (44e789f), closes #22934
- rules: promote from labs (2871f71)
- util: consume @vuetify/v0 utilities in core (#23039) (94b72d5)
- VAutocomplete,VCombobox: add
close-on-input-clickprop (#23023) (5dfeb32), closes #23021 - VBtnGroup: add
sizeprop to align with standalone buttons (9b46baa), closes #16054 - VCombobox: add
trim-valuesprop (#22895) (2614f43), closes #14874 - VDateInput: auto-fill separators while typing (#23052) (6225a83), closes #23051
- VDatePicker: correct range selection background for RTL (5448a61)
- VFileInput: add placeholder support (#23048) (988ffd1), closes #19837
- VFileInput,VFileUpload: unify dragging effect (#22909) (0440f63), closes #20576
- VNavigationDrawer: support percentage width (8f8def5), closes #16150
- VProgress,+Linear,+Circular: add duration control for value transition (9d4da1b), closes #22442
- VProgressLinear: add
revealprop (7764b49) - VRadio: v-model should work normally without VRadioGroup (92643be), closes #16245
- VSelect/VAutocomplete/VCombobox: allow persistent menu (#23008) (71d38a6), closes #20590
- VSelect/VAutocomplete/VCombobox: new events for multi-selection (#23038) (45079af), closes #4054 #5682
- VSkeletonLoader: add
chip-grouptype (06cbc10), closes #20695 - VSkeletonLoader: add
typesprop & reintroducetable-cell(#23037) (b5d380b), closes #20942 #17506 - VSlideGroup: emit when reaching an edge (62dbe20), closes #11364
- VSlideGroup: add
slidefunction (c3d2ce2), closes #21250 - VSlideGroup: add
scroll-snapandscroll-distanceprops (3f24ffe), closes #15916 - VVirtualScroll: add optional position parameter to scrollTo method (#18574) (405cd92)
- defaults: let user defaults override hardcoded subcomponent props (#23108) (bb09f8b), closes #21279 #21420 #21490
- defaults: avoid parent config leaking into menu and dialog content (#23016) (fc3e32e), closes #18123
- v-tooltip: correctly handle
trueandundefined(cef88bf), closes #20463 - v-touch: ignore scroll within (19ee74e), closes #21888
- v-touch: react to binding value changes (937a471)
- variant: clip underlay and overlay with overflow (#22992) (10d0b28), closes #22868
- VAutocomplete,VCombobox,VSelect: improvements for native form submissions (#23022) (2c51006), closes #21938 #22270
- VBtn: no letter-spacing for RTL locales (3956c08), closes #19627
- VBtnGroup: correct height for x-large size (b2294cd)
- VIconBtn: align default color with VBtn (1695a49), closes #23085
- VInput: do not animate details when mounting the whole field (c55238f), closes #23049
- VInput: consistent transitions of details/messages/counter (#23049) (9d7e741)
- VMenu: submenu a11y/navigation improvements (#22904) (e2a12c1)
- VMenu: avoid close cascading through non-menu overlays (e30eb47), closes #20468
- VMenu: custom overlays and tooltips should not prevent closing (#22993) (d01d4ac)
- VSelect/VAutocomplete/VCombobox: stable focus navigation in the virtual window (aae8fc4)
- VSelect/VAutocomplete/VCombobox: resilient navigation when seaching (#23031) (7a33ea9), closes #18383 #22770
- VSliderGroup: reliably select partially visible items (55d8e80), closes #21806
- VTextField: keep caret/selection when changing field type (47c9cc1), closes #16109
- VTreeview: improved open state when searching (#22983) (53afa91), closes #22035 #22392
- VTreeview: more aria attributes and correct keyboard navigation (#22903) (bad201d), closes #10796 #21585
v16.4.0-canary.14
- turbo-tasks-malloc: report memory from mimalloc: #97761
- Remove Edge runtime handling in use-cache-wrapper: #98139
- Skip discussions in the
issue_lockworkflow: #98146 - [ci] Fix
issue_lock: #97755 - docs: document preloading with Cache Components: #97864
- chore: Remove expired sharp release age exclusions: #98120
Huge thanks to @lukesandberg, @mischnic, @eps1lon, @aurorascharff, and @styfle for helping!
Release Next v3.0.0-next.11
-
#793 by @bobsingor – Introduces the PDF action engine: one policy-gated dispatcher for the payload-carrying
/Aaction trees (execute/canExecute,dispatch/canDispatchby annotation ref). Domain plugins register executors and sinks through the/contract/hostlens (stage: goto/named; form: javascript/reset-form; annotation: the session-visibility sink), the framework installs a URI/Print UI adapter viasetUiAdapter, andonAction/onDiagnosticevent hooks report every dispatch. Chains walk in PDF/Nextorder with document-lifetime work first and navigation/external effects deferred until it succeeds;launch/goto-remote/media stay never-executable and incomplete trees are refused whole.Phase 2 adds annotation
/AAevents, ordered page lifecycle events, and the document-open sequence. Dispatch now submits synchronously into the serial queue, returns per-step trigger results, derives origin centrally, and never rejects. The lifecycle coordinator buffers initial page state behind the open barrier and caps programmatic cascades;/Ashadows/AA U. The shared hover pump coalesces Exit→Enter pairs, and configuration can gate triggers and the open sequence.The package now publishes bundle-safe
/contractand/contract/hostentries. They expose the public and sibling-host protocols over the same token without pulling in dispatcher or plugin wiring; the package root remains the explicit implementation opt-in.
-
#793 by @bobsingor – Document lifecycle events + the submit sink chain (Phase 4). The five catalog
/AAverbs (ISO 32000-2 Table 200 — WC/WS/DS/WP/DP) dispatch through the trigger spine ({scope:'document', event:'will-save'|…}), with the open-ordering law: catalogOpenActioncan never run AFTER a lifecycle verb. NEWrunDocumentVerb('save'|'print', operation)— before-event → operation → after-event as ONE serialized queue op (two saves can never interleave; a before-event failure never cancels the verb; an operation throw skips the after-event and rethrows) — andprepareClose()(the cooperative WC door; scripts never run in teardown). The Print door fires WP → adapter EXACTLY once → DP under one latch: a nested print request (a WillPrint script callingdoc.print()) is suppressed with areentrant-printdiagnostic, never a second dialog; an adapter throw skips DP. SubmitForm graduates from hard-blocked to the SINK CHAIN — embeddersetSubmitHandler(consent = installation; detached-promise contract:executedmeans handed to the embedder) → the document's home (doc.forms.submit, engine-asserted, awaited) → blocked withno-submit-sink; the form plugin registers the ONE dataset resolver (registerSubmitResolver), both action nodes and scriptdoc.submitForm()effects normalize to oneSubmitIntent, and policy gains a'submit-form'row (user-origin only by default). The catalog read is memoized per document with rejection eviction. ShipssubmitEntriesToUrlEncodedfor handlers. The plugin still never touches a network. -
#793 by @bobsingor – THE JavaScript switch lives here now:
actionsPlugin({ javascript })owns the per-document ScriptHost realm, registers the realjavascriptexecutor (page-scoped world prefetch → boot → run → owner-sink commits → surface, ALL inside the host transaction — the commit-inside-the-boundary law), and exposes the transaction port +surfaceScriptResultoncontract/host. Owner commit sinks replace direct engine writes (registerFormCommitSink/registerAnnotCommitSink— each plugin commits AND reconciles its own model, so the PDF and the pixels can never diverge). Trigger provenance reaches executors (ActionContext.event+eventOf), and — full ISO — the Hide action routes by OWNING plane: field names and widget object numbers become formsetDisplayeffects, plain annotations become document flag patches; the session-visibility sink (SessionEffectSink/registerSessionSink) is REMOVED.ActionUiAdaptergainsalert/gotoPage(+ print context) as the ONE UI port for every script effect, with thedoc.printauthority gate upstream andonScriptDiagnostic/onScriptErrorhooks. A deterministic per-dispatch JS node cap (maxScriptNodesPerDispatch) bounds/Nextchains.
- #793 by @bobsingor – The annotation and form response schemas now describe action nodes as a payload-carrying discriminated union exposed through reusable OpenAPI components. Recursive
/Nextelements intentionally remain open ({}) for Fern compatibility, so generated SDK types showunknown[]for nested chains without duplicating the action model for every response path.
- #793 by @bobsingor – Action trees parsed from the hosted engine now carry full interpreter payloads (the discriminated
PdfActionNodeunion) andDocumentActionsSnapshot.openDestination; the snapshot schema defaultsopenDestinationso responses from older deployments still parse. Cloud actions conformance now gates the payload matrix and the destination-form/OpenActionon the HTTP + native-runtime path.
- #793 by @bobsingor – Action trees now use shared generated types for their payload-carrying union (destinations, URIs, named actions, Hide targets, ResetForm state, file specs) instead of repeating the same models for every annotation and form response path. Recursive
/Nextchain elements remainunknown[]— a Fern limitation of the emitted recursive schema, not missing data.
- #793 by @bobsingor – Action reads served by
/v1/docs/:docId/actions@:token(and the layer-scoped variant) now include interpreter payloads on every executable node and the destination-form/OpenActionasopenDestination, via the shared engine-services reader. The wire representation of action nodes changed shape (payload-carrying discriminated union); deploy server and clients from the same prerelease train.
-
#793 by @bobsingor – Complete the Acrobat AF forms support library in the scripting prelude:
AFNumber_Keystroke,AFPercent_Keystroke,AFDate_Format/AFDate_Keystroke(Ex),AFTime_Format(Ex)/AFTime_Keystroke,AFSpecial_Format/AFSpecial_Keystroke,AFRange_Validate,AFMergeChange,AFMakeNumber, andAFExtractNums, with Acrobat-compatible rejection alerts, a lenient scand-style date parser, and newh/hh/tt12-hour tokens inutil.printd. Forms built with Acrobat's standard number/date/time/special formats (for example the Apryse demo form) now validate, format, and auto-calculate instead of failing on missing globals.javaScriptSourcesFromActionTreenow narrows on the payload-carrying action-node union and collects onlyjavascriptarms; rendition/JSremains represented but is deliberately not executed. A newui-effect-suppresseddiagnostic also makes permission-withheld script UI effects observable. -
#793 by @bobsingor –
doc.submitForm(...)emits a submit INTENT (Phase 4): both Acrobat forms — positional(cURL, bFDF, bEmpty, aFields)and the argument object (cURL/aFields/bEmpty/cSubmitAs/bGet) — become a{kind:'submitForm'}UI effect (include-mode field names;cSubmitAsbeatsbFDF; nothing in the VM ever touches a network — resolution and the sink chain live outside). Doc-typed events now carryevent.target = the Doc object(Acrobat's WillSave boilerplate doesevent.target.getField(...)). The v1-frozen posture constants are honest again:submitForm: 'sink-chain',catalogLifecycleActions: 'execute-on-verb', page/annotation eventsexecute-*— the actions plugin's policy is the live authority these document. -
#793 by @bobsingor – The ScriptHost and the annots plane.
createScriptHostowns the ONE realm per document (its own serialized transaction port; lazy name-tree boot delivered exactly once to the first transaction; resource faults poison and lazily rebuild the realm; per-run and caller-sliced budgets). The script world grows the curated annotation plane:this.getAnnots({nPage})/getAnnot(nPage, name)over a caller-prefetched, page-scoped input (null when nothing matches — Acrobat parity; unfetched pages are a NAMED compatibility deviation),Annotwrappers with a per-subtype validity matrix (ANNOT_WRITABLE_KEYS, drift-guarded against the kind registry; no dictionary access — the Acrobat model),setProps/getProps, and diff-derived canonicalannotEffectsbesideformEffects(declared cross-plane commit order: form first, then annot). Ships the standardcolorobject (constants +convert/equalwith the documented G/RGB/CMYK vectors), Acrobat{type, name}event overrides, and — cycle fix — theScriptSandbox/ScriptSandboxFactorystructural contract now lives HERE (core-js-sandboximplements and re-exports it).
-
#793 by @bobsingor – Session-visibility overlay:
Model.sessionHiddenwithsetSessionHidden/forgetSessionHidden/clearSessionHiddenmessages, composed through the neweffFlags/effBearerlenses so Hide actions and scripts flip presentation-only visibility (paint, hit-testing, selectability, handles) without ever touching the document/Fflags — and a session-SHOWN annotation is live, not painted-but-dead. The overlay survives page reloads and is forgotten only on true deletes. -
#793 by @bobsingor –
sessionHidden,effFlags/effBearer, and the session-visibility messages are REMOVED — visibility is document truth again (/Fflags, mutated through the normal write path), and every paint/hit/selection gate reads the annotation's own flags.
- #793 by @bobsingor – Adds
createEventHook(the one capability-event primitive: subscribe-onlyEventHook<T>face, snapshot fan-out, listener error isolation, inert after dispose) andcreateSerialQueue(promise-tail serialization) to the core toolkit.
-
#793 by @bobsingor – The SubmitForm intent and the document's-home submit contract (Phase 4). The
submit-formnode grows an ATOMIC optionalpayload(url+fields+ decodedSubmitFormFlags+charSet?; absent = older-runtime extraction, the node stays recognized-inert — partial states are unrepresentable).decodeSubmitFormFlagsis the ONE ISO Table-240 decode (excludederived from bit 1, never duplicated; bit 12 isExclFKey, bit 13 reserved,EmbedFormis bit 14; bit 9 SubmitPDF dominates format with GetMethod kept alive). NEW:doc.forms.submit?(request)— the optional delivery-to-the-document's-HOME capability (present only where a home exists; the local engine truthfully lacks it), gated by the NEW grant-minteddoc.forms.submitscope (no PDF permission bit exists for submission, sopdf.permissionsnever expands it);FormSubmissionRequest/ReceiptDTOs + wire schemas fix the record shape (dataset entries + declared intent as METADATA — the home derives WHO submitted from its own verified session, and never fetches the PDF's URL). Conformance pins the payload extraction (/UFprecedence, flag decode, both degrade shapes) in both flavors. -
#793 by @bobsingor –
PdfActionNodeis now a discriminated union carrying full interpreter payloads — agotowithout its destination or auriwithout its URI is unrepresentable. Executable arms:javascript(script),goto(destination),uri(+isMap),named,hide(targets +/H),reset-form(fields: PdfActionTargetRef[] | null— null means/Fieldswas absent and every field resets — plus the exclude flag), the file-spec arms, andrenditionwith its optional/JS. Unreadable payloads degrade that node tounknownwith the newpayload-droppedtree warning.DocumentActionsSnapshotgainsopenDestination(the destination-form/OpenAction, schema-defaulted and mutually exclusive withopenAction),ActionReadBudgetgains target-entry and payload-text limits, andPdfDestinationSchemamoved to a neutraldto/module (re-exported from its old home). The wire entry now also exposesPdfActionWireComponents, the stable named-schema registry used by API generators. This is a breaking source-level contract for code that constructed or narrowed action nodes, recorded as minor only because the3.0.0-nexttrain is prerelease.
-
#793 by @bobsingor – SubmitForm payload getters (Phase 4).
EPDFAction_GetNodeSubmitForm(has-fields + the raw ISO Table-240 flag word; returns true only when the REQUIRED/Fresolved to a URL — a<< /FS /URL >>file specification with/UFpreferred over/Fper 7.11.2, or a bare string/Faccepted as a producer-compat extension),EPDFAction_GetNodeSubmitFormURL, andEPDFAction_GetNodeSubmitFormCharSet(PDF 2.0/CharSet, extracted not encoded)./Fieldsentries ride the existing shared target storage (GetNodeTargetCount/TargetName/TargetObjectNumbernow also answer for submit-form nodes) and the aggregate payload/target budgets. An unresolvable required component withholds the WHOLE payload — the reader degrades the node; never a half payload. -
#793 by @bobsingor – Add action-payload getters to the fork's detached action model: unified Hide
/T/ ResetForm/Fieldstarget accessors (EPDFAction_GetNodeTargetCount/Name/ObjectNumber, with-1marking a target list that could not be fully represented — a partial list must never execute),EPDFAction_GetNodeHideFlag(/H, spec default hide),EPDFAction_GetNodeResetForm(/Fieldspresence +/Flagsexclude bit — absent and empty are different states),EPDFAction_GetNodeURIIsMap, andEPDFDoc_GetOpenActionDestfor the destination-form catalog/OpenAction. Payload capture stays inside the build-time snapshot (nothing lazy, nothing stateful), guarded by new cumulative per-model budgets for target entries and payload bytes plus a destination-array element cap.
-
#793 by @bobsingor – The action model reader extracts the SubmitForm payload atomically (feature-detecting the Phase-4 runtime getters: an older runtime payload yields the bare recognized-inert node — the pin-lag skew case, unit-pinned; a NEW runtime withholding an unresolvable
/Fdegrades the whole node tounknown+payload-dropped)./Fieldstargets and the URL/CharSet strings charge the existing aggregate budgets. -
#793 by @bobsingor – The action-model walker now materialises interpreter payloads (destinations, URIs +
/IsMap, named-action names, Hide targets +/H, ResetForm three-state fields + exclude, file specs) with reserve-before-allocate budgeting — payload lengths are charged against the aggregate read budget before any scratch buffer is allocated, and name-tree script names ride the same budget.readActionModeland the annotation/form field readers take the owning document pointer;readDestinationmoved to a sharedfeatures/destinations/home. The link target is now a pure projection of the payload-carrying activate tree (linkTargetFromActionTree) — the duplicate native root-read is gone, anincompletetree projectsunsupported, and a malformed/Ano longer silently falls back to/Dest.
- #793 by @bobsingor – NEW
@embedpdf/angular/actionsentry:injectActionsUiAdapter(handlers?)— Angular's spelling of React'suseActionsUiAdapter(theinject*law), installing the SHARED default policy from@embedpdf/webso the two bindings can never drift; re-exports the@embedpdf/plugin-actionscontract. The parity gate goes green (actionsported;anchoredconsciously added to PENDING).
- #793 by @bobsingor – Route the Stage adapter's interaction dependency through the bundle-safe plugin contract entry instead of the interaction implementation root.
-
#793 by @bobsingor – New
@embedpdf/react/actionsentry withuseActionsUiAdapter(browser-default URI open throughsanitizeExternalUri+ print dialog, overridable per handler), auseCapabilityEventhook for capability event subscriptions, and link-layer delegation: chain-bearing URI links drop the nativehreffast path so the dispatcher runs the whole chain (the'dispatched'outcome opens nothing itself — the adapter owns it).Widget fill controls become always-active
/AAevent surfaces, link anchors feed link hover events, and scripting-provider defaults use the dispatch origin when deciding whether to suppress lifecycle/boot UI effects.Route sibling feature dependencies through plugin contract/helper entries. Annotation selection hooks and anchor equality helpers are split into leaf modules so form and annotation-menu entries no longer import the full annotation feature implementation.
Render PDF list boxes as visible native scrolling controls in both form surfaces, with stable optimistic selection and wheel isolation so row hit-testing, selection, and scrolling stay synchronized while engine writes complete. Combo boxes retain their baked resting appearance and native popup behavior.
Keep keyboard focus indicators above baked PDF appearances so checkboxes and choice controls display the same clear blue focus ring as text fields and radio buttons.
-
#793 by @bobsingor –
useActionsUiAdapteris the ONE script UI port: it gainsalertandgotoPagedefaults with the origin×phase visibility matrix (lifecycle/boot alerts and non-user print suppressed unless the embedder passes handlers — which receive everything, context attached).useFormScriptingProviderandFormScriptingUiHandlersare DELETED.
-
#793 by @bobsingor –
useActionsUiAdapteris now glue over@embedpdf/web'screateDefaultActionsUiAdapter— behavior-identical (the corpus alert matrix pins it); the default policy lives in ONE place for every binding. -
#793 by @bobsingor – Widget activation is a WIDGET behavior, not a push-button behavior: clicking ANY form widget now dispatches its
/Athroughform.activateWidget— text, toggle, and choice widgets (both the annotation-backed renderers and the standalone fill layer) join the button path. This makes real-world "fake buttons" work: producers ship Reset/Next/Hide controls as READ-ONLY text fields carrying a widget/A(ISO puts the activate action on the annotation dictionary, any field type), which previously died in the viewer because only push buttons routed clicks to activation while the pointer feed's mouseUp was — correctly — shadowed by/Aprecedence. Disabled controls become pointer-transparent so their clicks reach the activation surface (a disabled form control suppresses click events entirely); toggles keep Acrobat's order (the value change first, THEN the/A); push buttons keep their gated door (disabledstill blocks activation there). Proven end-to-end by a real-DOM regression test (rendered FormLayer over a real engine — the gap every prioractivateWidget()-direct test masked) and a read-only fake-button fixture in the plugin e2e.
- #793 by @bobsingor –
createDefaultActionsUiAdapter— the actions UI adapter's DEFAULT policy (the origin×phase visibility matrix: hover/lifecycle prints suppressed, boot/lifecycle alerts suppressed, sanitizeExternalUri URI opens, browser fallbacks), hoisted here and written ONCE so every framework binding (react, angular) ships the same behavior instead of forking it. Structural twins keep this package plugin-free per the layering law;overridesaccepts a getter for late-bound handlers.
-
#793 by @bobsingor – Registers the action engine's session-visibility sink (
applySessionVisibilityon the host lens) when@embedpdf/plugin-actionsis present, and carries the full activate action tree + annotation ref onLinkNavItemso the nav layer can delegate chains to the dispatcher.The pointer-driven hover diff feeds annotation
/AAcursorEnter/cursorExit through the shared hover pump while reducer-side clears, widgets, links, and tree-less items stay inert.LinkNavItemalso carries hover-event presence flags for the link plane.Publish bundle-safe
/contractand/contract/hostentries over the same annotation token, plus the focused/authoringhelper entry./internalkeeps its implementation-helper meaning and no longer serves as the sibling bundle boundary. -
#793 by @bobsingor – The session-visibility overlay is RETIRED —
applySessionVisibilityis replaced bycommitScriptEffects, the annotation DOCUMENT-commit sink: script/Hide effects become engineannotations.updatepatches (colors crossing the Acrobat-array → engine boundary,/APregenerated engine-side), authority-enforced, stop-on-failure, with the owner reconciling its own model per touched page.
- #793 by @bobsingor – Publish a bundle-safe
/contractentry for command tokens, definitions, resolved-command equality, and capability types without command plugin wiring.
-
#793 by @bobsingor – Widget activation joins the action engine: with
@embedpdf/plugin-actionsinstalled,activateWidgetdelegates the full/Atree to the dispatcher (return type is nowWidgetActivationResult, discriminating the two worlds), so Hide/ResetForm push buttons work with scripting disabled. The host lens exposes the interim executors' doors:runActivationScript(one JS node as a widget transaction) andresetFormAction(three-state target resolution, one batch reset skipping non-resettable families, recalculate after). Executor-driven form mutations ride the same serial mutation queue as user commits — strictly actions-queue → form-queue, never the reverse.The widget DOM-event door dispatches widget
/AAtrees, including coalesced hover events. Activation now submits synchronously through the dispatcher, and script UI effects carry their dispatch origin; print requests without document permission are withheld with an observable diagnostic.Form scripting is fault-tolerant per event: Keystroke, Validate, Calculate, and Format exceptions degrade to diagnostics while explicit
event.rc = falseremains a rejection and resource-budget faults still fail the transaction. Keystroke actions now run Acrobat's typing and commit passes so standard AF validators and custom transforms see the expected event shape.Publish bundle-safe
/contractand/contract/hostentries over the same form token, plus a focused/scriptinghelper entry./internalremains an implementation visibility surface rather than the sibling bundle boundary. -
#793 by @bobsingor – The submit dataset resolver + the reset() symmetry fix (Phase 4).
resolveSubmitDataset(registered as THE actions submit resolver) does a FRESH engine read and applies the ISO Table-239/240 semantics through the new sharedfield-selectionmodule: include-mode NAMES select descendants by FQN dot-prefix (fixing the ResetForm exact-match conformance bug too — Tables 241/242 want subtrees), the NoExport veto is unconditional (diagnosed when explicitly listed), explicitly listed push-buttons/signatures and unsupported/Vshapes are DIAGNOSED (submit-entry-unsupported), never silently dropped, and IncludeNoValueFields yields name-only entries.resetFormActiongains an origin parameter threaded from the executor's ActionContext — a lifecycle/hover ResetForm can no longer launder its recalculation alerts into user origin — and the publicform.reset(key)now rides the SAME shared reset core (one effects batch → refresh → V/C/F recalculation), so a dependent calculated field can no longer go stale through the API door. -
#793 by @bobsingor – The K/V/C/F pipeline rides the shared realm:
FormScriptingControllerkeeps its ordering,event.rcsemantics, two-pass keystroke, overlay, and fault ladder UNCHANGED, but acquires the realm through a transaction port — the actions plugin's per-document host in viewers, or a self-owned standalone host (createFormScriptingHost/ the{ config }constructor arm) for stamp and tests. The snapshot moves INSIDE the transaction boundary (commit(ref, value)/activate(ref, action)/recalculate()— no snapshot parameters).formPlugin({ scripting })is DELETED (the switch isactionsPlugin({ javascript })); the interimrunActivationScriptexecutor and the form-side UI-effect provider (setUiEffectProvider/FormUiEffectProvider) are gone — every script surface flows through the actions port with origin/phase attached, and the newcommitScriptFormEffectssink commits script form effects with engine write + snapshot AND annotation-plane reconciliation in one place.
- #793 by @bobsingor – Publish a bundle-safe
/contractentry for the translation token, locale vocabulary, and capability types without i18n plugin wiring.
- #793 by @bobsingor – Publish a bundle-safe
/contractentry for interaction and platform-feedback tokens, pointer/tool protocols, and capability types without either plugin implementation.
-
#793 by @bobsingor –
activate()accepts an optionalLinkActivateContext; when the actions plugin is installed and the item carries its/Atree, activation delegates to the dispatcher and returns the new{ outcome: 'dispatched', dispatch }arm — named verbs execute and mixed/Nextchains behind links finally run. Without the actions plugin the classic root-projection path is unchanged.Link
/AAhover presence flags now rideLinkNavItemfrom the standalone source so the navigation layer can deliver cursorEnter/cursorExit without waking the annotation behavior plane.Publish a bundle-safe
/contractentry so navigation consumers can depend on the link protocol without pulling in source/effect/plugin wiring.
- #793 by @bobsingor – Publish a bundle-safe
/contractentry for the metadata token, state, and capability types without event, reducer, or plugin wiring.
- #793 by @bobsingor – Publish a bundle-safe
/contractentry for the page-edit token and capability type without mutation or plugin wiring.
- #793 by @bobsingor – Publish a bundle-safe
/contractentry for the redaction token, state, pending-item, and capability protocols without destructive-apply plugin wiring.
- #793 by @bobsingor – Publish a bundle-safe
/contractentry for the render token, paint-plan vocabulary, settings, and capability types without raster or plugin wiring.
- #793 by @bobsingor – Publish a bundle-safe
/contractentry for the search token, query validation, results, and capability types without scan, effect, or plugin wiring.
- #793 by @bobsingor – Publish bundle-safe
/contractand/contract/hostentries over the same selection token so sibling features can use selection protocols without gesture, reducer, or plugin wiring./internalretains its framework implementation helpers and makes no bundle-purity promise.
- #793 by @bobsingor – Publish a bundle-safe
/contractentry for the shell token, surface state, options, and capability types without reducer or plugin wiring.
-
#793 by @bobsingor – The main stage lens registers
gotoandnamedaction executors with the action engine when present: GoTo destinations reveal through the camera, NextPage/PrevPage/FirstPage/LastPage execute, unknown named verbs report inert.The stage lens also reports placed/current/visible page state and user-versus-programmatic motion causes to the action lifecycle coordinator.
Publish a bundle-safe
/contractentry and a focused/destinationhelper entry so camera consumers do not pull in stage reducer/effect/plugin wiring.
- #793 by @bobsingor – Publish a bundle-safe
/contractentry for stamp-library tokens, assets, previews, configuration, and capability types without import, render, or plugin wiring.
- #793 by @bobsingor – Dynamic stamp evaluation constructs its OWN standalone realm per detached stamp-asset document (
StampScriptingOptions— the opt-in and script observers stay stamp-config; the viewer document's shared host is never involved).
- #793 by @bobsingor – Publish a bundle-safe
/contractentry for view-registry tokens, view state, and capability types without reducer or plugin wiring.
- #793 by @bobsingor – The
ScriptSandbox/ScriptSandboxFactorystructural contract moved to@embedpdf/core-acrojs(cycle fix); this package implements and re-exports it, and threads the new annots plane +annotEffectsthrough the QuickJS bridge unchanged.
-
#793 by @bobsingor – The viewer wires the action engine in:
actionsPlugin()joins the plugin set and the Shell installs the default URI/Print UI adapter. -
#793 by @bobsingor – The chrome save/print commands become the Phase-4 verb owners:
document:downloadruns WS → serialize → DS as ONE queued operation (the WillSave mutations are IN the downloaded bytes; two rapid saves can never interleave) anddocument:printruns WP →window.print()→ DP under the reentrancy latch — both degrading to today's behavior when the actions plugin is absent. -
#793 by @bobsingor – Scripting migrates to
actionsPlugin({ javascript: { enabled: true } })with a bareformPlugin(); the Shell's form scripting provider hook is gone —useActionsUiAdaptercarries everything.