1.12.1
- A new popover focuses Next instead of the close button, so Enter no longer ends the tour.
- Your CSS can hide or restyle popover parts without
!important.
- The popover shows above a dialog that opens mid-step instead of behind it.
pointer-events: noneinside the highlighted element is no longer overridden.
1.12.1
- A new popover focuses Next instead of the close button, so Enter no longer ends the tour.
- Your CSS can hide or restyle popover parts without
!important.
- The popover shows above a dialog that opens mid-step instead of behind it.
pointer-events: noneinside the highlighted element is no longer overridden.
electron v46.0.0-alpha.10
Note: This is an alpha release. Please file new issues for any bugs you find in it.
This release is published to npm under the alpha tag and can be installed via npm install electron@alpha, or npm install electron@46.0.0-alpha.10.
- Added
dynamicIdto theExtensionstructure, exposing the extension's per-load ID used byuse_dynamic_urlweb accessible resources. #55639
1.12.0
popover.instructionmakes a step an action step: the user has to do what it says. Next looks disabled until they do.advanceOn: { event, strict: true }lets only that gesture through on the highlighted element.advanceDelaypauses on a completed step before moving on. Action steps show a done state meanwhile.driverObj.advance()completes the current step from your code, likeadvanceOndoes.driverObj.nudge("message")shows a line of feedback in the popover and shakes it.onElementMissingtakes"stay","previous"or"previousAction"as well as a function.disableActiveInteraction: "clicks"blocks clicks on the highlighted element but keeps hover working.onHighlightStartedgets the samesignalasonHighlighted.- A console warning when
disableActiveInteractionmakes a step'sadvanceOnimpossible. - A highlighted element inside an allowed element, like an item in an open menu, gets a ring instead of a hidden cutout.
- CSS variables for the instruction row, the feedback line and that ring. See Theming.
- Clicks on the padding around the highlighted element, or on an element with
disableActiveInteraction, no longer reach your app'sdocumentandbodylisteners. UseonInteractionto see them. disableActiveInteraction: truealso blocks Enter and Space on the highlighted element.- A highlighted element that your framework re-renders is followed automatically.
overlayClickBehavior: "nextStep"does nothing while the popover waits for an element.onDestroyStartedgets the step being entered when the tour is closed during its first animation, notundefined.- The
Statetype no longer lists the internal__keys added in 1.11.0.
- Steps inside a modal
<dialog>now dim the dialog and cut out the highlighted element. moveNext(),drive()anddestroy()now work when called fromonHighlightStarted,onHighlightedoronDeselected.moveTo()starts the tour if it isn't running.setSteps()on a running tour ends it cleanly. Calldrive()to start the new steps.- A step's
showProgress: falsenow wins overshowProgress: trueon the driver. - A fast double-click no longer skips a step that advances on click.
advanceOnClickignores clicks while a step animates in, as before 1.11.0. - The key that completes a step, like Enter, no longer presses a button in the next popover.
- The highlight and popover stay on their element when it changes size, when a framework rewrites its
className, and when the page resizes mid-step. - A highlighted element that is removed from the page no longer keeps driver.js classes and aria attributes.
drive()without steps no longer locks the page whenonDestroyStartedis set.- Less layout work while scrolling with hints or a tour, and
waitForElementchecks the page at most once a frame.
1.12.0
popover.instructionmakes a step an action step: the user has to do what it says. Next looks disabled until they do.advanceOn: { event, strict: true }lets only that gesture through on the highlighted element.advanceDelaypauses on a completed step before moving on. Action steps show a done state meanwhile.driverObj.advance()completes the current step from your code, likeadvanceOndoes.driverObj.nudge("message")shows a line of feedback in the popover and shakes it.onElementMissingtakes"stay","previous"or"previousAction"as well as a function.disableActiveInteraction: "clicks"blocks clicks on the highlighted element but keeps hover working.onHighlightStartedgets the samesignalasonHighlighted.- A console warning when
disableActiveInteractionmakes a step'sadvanceOnimpossible. - A highlighted element inside an allowed element, like an item in an open menu, gets a ring instead of a hidden cutout.
- CSS variables for the instruction row, the feedback line and that ring. See Theming.
- Clicks on the padding around the highlighted element, or on an element with
disableActiveInteraction, no longer reach your app'sdocumentandbodylisteners. UseonInteractionto see them. disableActiveInteraction: truealso blocks Enter and Space on the highlighted element.- A highlighted element that your framework re-renders is followed automatically.
overlayClickBehavior: "nextStep"does nothing while the popover waits for an element.onDestroyStartedgets the step being entered when the tour is closed during its first animation, notundefined.- The
Statetype no longer lists the internal__keys added in 1.11.0.
- Steps inside a modal
<dialog>now dim the dialog and cut out the highlighted element. moveNext(),drive()anddestroy()now work when called fromonHighlightStarted,onHighlightedoronDeselected.moveTo()starts the tour if it isn't running.setSteps()on a running tour ends it cleanly. Calldrive()to start the new steps.- A step's
showProgress: falsenow wins overshowProgress: trueon the driver. - A fast double-click no longer skips a step that advances on click.
advanceOnClickignores clicks while a step animates in, as before 1.11.0. - The key that completes a step, like Enter, no longer presses a button in the next popover.
- The highlight and popover stay on their element when it changes size, when a framework rewrites its
className, and when the page resizes mid-step. - A highlighted element that is removed from the page no longer keeps driver.js classes and aria attributes.
drive()without steps no longer locks the page whenonDestroyStartedis set.- Less layout work while scrolling with hints or a tour, and
waitForElementchecks the page at most once a frame.
v16.5.0-canary.48
- Prerender route handlers that await immediates: #101593
- Fix orphaned detached telemetry flush processes: #101588
- Upgrade React from
e84e1492-20261031to1620f7b9-20261111: #101587 - docs: clarify tag invalidation client effects: #101504
- Keep dev overlay errors across no-op webpack hot updates: #101532
- Turbopack: don't grow effect vectors inside the analyzer arena: #101480
- Fix metadata route selection with
--debug-build-paths: #101585 - eval: generate the docs pointer from the tested Next.js package: #101558
- Turbopack: scale default disk write concurrency: #101519
- eval: correct graders for Proxy, instant navigation, and category prefetching: #101523
- docs: clarify Server Actions configuration: #101549
- Turbopack: add build cache portability e2e test and fix location-dependent tasks: #100780
- Turbopack: replace SwcComments with a lightweight MutableComments store: #101543
- turbo-tasks-backend: merge aggregated data updates for new followers: #100435
- test: fix keep-alive socket reuse in CSS HMR race helper: #101530
- turbo-tasks: count task executions in task statistics: #101025
- test: fix repeated-slashes router push navigation race: #101528
- next-core: deserialize next.config env and output file tracing globs into typed maps: #100971
- turbo-tasks: add OrderedJsonValue/OrderedJsonMap with key-order-sensitive equality: #100964
- turbo-tasks: use OrderedAutoMap/OrderedAutoSet for order-observing values: #100940
- auto-hash-map: add positional access and IndexMap/IndexSet conversions for ordered maps: #101497
- test: close lingering prerender-export server connections: #101527
- test: fix flaky app-root-params-getters/simple: #101525
- test: fix flaky dev-validation-worker-source-maps: #101524
- turbo-tasks-malloc: use official mimalloc Rust bindings (v3.6.1): #101518
- docs: explain complementary Web Vitals and custom metrics APIs: #98968
Huge thanks to @unstubbable, @timneutkens, @jimmyhmiller, @aurorascharff, @sokra, @lukesandberg, and @adityareddy-dev for helping!
Release v3.2.0
-
#1071 by @bobsingor – The contract has the change op
annotations.copy(refs,page,offset,objectNumbers) and its result item (annotations,refMap,dropped,meta).openapi.jsondescribes both. -
#1075 by @bobsingor – The contract has the change op
forms.copy(fields,widgets,page,offset,values,objectNumbers) and its result item (fields,widgets,refMap,dropped,calculationOrder,meta).openapi.jsondescribes both.
-
#1071 by @bobsingor – The cloud engine has
doc.annotations.copy(refs, { page?, offset?, objectNumbers? }), anddoc.applytakes the opannotations.copy. The copies are made on the server in one request, so nothing is downloaded. Against a server older than 3.2 the change is refused withNotImplementedbefore anything is sent. -
#1056 by @bobsingor – The cloud engine works with a server that is older or newer than it for change kinds. A change with a kind of op the server doesn't have yet is refused on its own, before anything is sent, with
NotImplemented; itsdetailsname the op (kind), the version that has it (needs) and the server's (serverVersion). The changes called beside it still go out. A change from another session of a kind this version doesn't know now reads asstream.desyncedwithreason: 'unknown-change', so everything is read again; before, it became an event without a type and reads stayed stale. -
#1075 by @bobsingor – The cloud engine has
doc.forms.copy(fields, { page?, offset?, values?, widgets?, objectNumbers? }), anddoc.applytakes the opforms.copy. The copies are made on the server in one request. Against a server older than 3.2 the change is refused withNotImplementedbefore anything is sent.
-
#1071 by @bobsingor – The SDK has the change op
annotations.copyand its result item:ChangeOp.AnnotationsCopyandChangeItem.AnnotationsCopy. -
#1075 by @bobsingor – The SDK has the change op
forms.copyand its result item:ChangeOp.FormsCopyandChangeItem.FormsCopy.
-
#1071 by @bobsingor –
POST …/changestakes the new opannotations.copy: copies of annotations in the same document, with a stamp's drawing and an attachment's file copied on the server. It needsdoc.annotate.readand the right to create each kind, notdoc.download. A ref the document doesn't have refuses the change withNotFound. On the event stream, a client that says a version before 3.2 getsfull-refreshin place of a change with this op. A copy stays within the server'sbundleLimits: past one, its change is refused withPayloadTooLarge, anddetails.limitnames the limit. -
#1056 by @bobsingor – The event stream answers each client as its version reads. A change with a kind that arrived after the client's
EmbedPDF-Versiongoes out asfull-refreshin the row's place, and the stream carries on with the rows after it; afull-refreshnow says why in its data (reason). An op ofPOST …/changeswith a field the server doesn't know refuses the request withInvalidArg, naming the field, where the field used to be dropped and the op applied without it. An item of a kind the server doesn't know is withheld from a connection that may not read everything. -
#1075 by @bobsingor –
POST …/changestakes the new opforms.copy: a new field from each field named, with its widgets, made on the server. It needsdoc.forms.modify, anddoc.forms.scriptto keep scripts, submits and links. A field the form doesn't have refuses the change withNotFound. On the event stream, a client that says a version before 3.2 getsfull-refreshin place of a change with this op. A copy stays within the server'sbundleLimits: more fields thanitemsrefuses its change withPayloadTooLarge.
- #1071 by @bobsingor – New
isMovable(record): whether an annotation is one people move at all. Its kind moves, and it isn't bound to text, as a highlight or a redaction of words is.canMove(model, id)uses it, and adds the lock, the session's rights and itseditablerule.
- #1054 by @bobsingor – A plugin can stage a change that one of the engine's own verbs makes, such as an import:
ctx.changes.stage({ label, send }). The queue callssend(doc, { opId })when it sends the change, so the verb keeps its place among the other changes, and the history records it as one step.opIdnames the change when the caller of the verb chose an id, andhistory: falsekeeps it out of the history. The newHistoryOptionstype is thehistory?: falseoption a verb takes from its caller.
- #1056 by @bobsingor – The page list is read again when the event stream skipped events (
stream.desynced). A page inserted or deleted by someone else while a viewer was too far behind used to show only after the document was opened again.
-
#1071 by @bobsingor – New change op
annotations.copy, anddoc.annotations.copy(refs, { page?, offset?, objectNumbers? })for it: copies of annotations inside one document, made as one change that one undo takes away. A copy carries every field of its kind,lockedincluded, and a stamp's drawing or an attachment's file, sodoc.downloadisn't needed. It gets its own ref and a freshnm, and the session is its author. Links between copies stay: a reply to an annotation that is copied too replies to that one's copy, so a copied group is a group of its own. The result holds the copies,refMapanddropped, with the reasons an import uses.planAnnotationCopies(sources, placement)is the rule itself, without zod, for a viewer that shows the copies before the engine answers. The op arrived in 3.2 (CHANGE_KIND_SINCE), so an older server is never sent it and an older client reads everything again.runAnnotationCopyConformancechecks an engine against it. A copy stays within the bundle limits (items,resources,resourceBytesandbundleBytes); past one it is refused withPayloadTooLarge, anddetails.limitnames the limit. -
#1056 by @bobsingor – Every kind of change op and result item says the version it arrived in, so a client and a server of different versions can tell which kinds the other has.
CHANGE_KIND_SINCElists the kinds that arrived after 3.0 (pages.setScalein 3.1),changeKindsUnknownTo(version, kinds)names the kinds a side of that version lacks, andlacksWhatArrivedIn(version, since)makes the comparison for anything else that arrived in a version.stream.desyncedhas a secondreason,'unknown-change': a change of a kind this version doesn't know arrived. Each op of aPOST …/changesrequest is now strict about its own fields: an op with a field the schema doesn't name is refused, where the field used to be dropped. -
#1075 by @bobsingor – New change op
forms.copy, anddoc.forms.copy(fields, { page?, offset?, values?, widgets?, objectNumbers? })for it: a new field from each field named, made as one change that one undo takes away. A copy has its source's settings, scripts and default value, and each widget's place, look, flags and actions, moved byoffsetor put onpage. It is named after its source with the next free number (emailbecomesemail_2,billing.namebecomesbilling.name_2), and it has its source's value unlessvaluesisfalse; a signature never comes along.widgetsnames the widgets to copy when it isn't all of them. The result holds the new fields, their widgets,refMapanddropped, with the reasons a form import uses, and its events are oneforms.createdper field.planFormCopiesis the rule itself, without zod, for a viewer that shows the copies before the engine answers;copyNameOfandfieldNameTakenname a copy. The op arrived in 3.2 (CHANGE_KIND_SINCE), so an older server is never sent it and an older client reads everything again.runFormCopyConformancechecks an engine against it. A form import and a copy now also carry a widget's check style and its dash pattern.fieldsnames at most as many fields as the bundle limits'items; more is refused withPayloadTooLarge, anddetails.limitnames the limit. -
#1049 by @bobsingor – An annotation update can change
nm. A new name renames the annotation in place, andnm: nullremoves its name. A new name must be free on its page, checked against the page as the change's earlier ops left it; an undo puts back the name the annotation had. The conformance suites check renames, andrunChangeConformance'sopenoption takes the PDF to open, such asNAMES_FIXTURE_PDF, a file with missing and shared names.
-
#1071 by @bobsingor – The local engine has
doc.annotations.copy(refs, { page?, offset?, objectNumbers? }): copies of annotations in the same document, as one change that one undo takes away. In a change of your own it is the opannotations.copy. -
#1075 by @bobsingor – The local engine has
doc.forms.copy(fields, { page?, offset?, values?, widgets?, objectNumbers? }): a new field from each field named, as one change that one undo takes away. In a change of your own it is the opforms.copy.
-
#1071 by @bobsingor – The worker applies the new op
annotations.copy. It reads each named annotation, creates the copies as one change, all or nothing, and records the reverse, so an undo deletes them. A copied stamp places the drawing its original places, so the document gets no second drawing, and a copied attachment gets the same file bytes with its dates. Every create is checked before the first write: the session needsdoc.annotate.readand the right to create each kind. A copy carries what a bundle may: as many annotations, and as many drawings and files, of that size each and together. A drawing counts once however many copies place it. Past a limit the copy is refused withPayloadTooLargebefore anything is written.document.applyChangestakes the deployment'slimits; without them the defaults apply. -
#1075 by @bobsingor – The worker applies the new op
forms.copy. It reads the form, plans the copies before the first write, and creates each new field as a design import creates one: with its widgets, their flags, its value when asked, and its place in the calculation order. Its reverse deletes the fields it made, the last first. It needsdoc.forms.modify; a script, a submit or a link is left out and reported withoutdoc.forms.script. A copy names at most as many fields as the bundle limits'items; more is refused withPayloadTooLargebefore the form is read. -
#1049 by @bobsingor –
annotations.updateandforms.updateWidgetwrite a newnmto the annotation's own/NM, or remove it fornull. The object, its replies, its appearance and its other keys stay as they are. A name another annotation on the page has is refused withInvalidArg. An empty name removes/NM, as a create given one writes none.
-
#1071 by @bobsingor –
EpdfAnnotationhasduplicate(refs, options),canDuplicate(refs),isMovable(ref),selection.duplicate(options)andselection.canDuplicate(). -
#1075 by @bobsingor –
EpdfFormhasduplicate(fields, options)andduplicateWidgets(widgets, options).
- #1074 by @bobsingor –
<epdf-form-layer>draws a field's picture where the field is now. A field that was moved, in Form design or withupdateWidget(), kept its picture at the old place until the page's pictures were loaded again: the field showed in one place and took clicks in another.
- #1051 by @bobsingor – The Stage's wheel handling asks the Stage whether a wheel is its own, through the host's new
wheelBy, and cancels only the wheels the Stage takes. A wheel the Stage leaves alone reaches the browser, which scrolls the page around the viewer with it. A zoom wheel (Ctrl or Cmd) is always cancelled. A wheel event that isn't cancelable is ignored: the browser is already scrolling the page with it. A test that sends its own wheel events needscancelable: trueon them.
-
#1071 by @bobsingor – New
duplicate(refs, { page?, offset?, select? })copies annotations in the same document. The copies show at once, it is one step to undo, labelledannotation.duplicate, and it resolves{ annotations, dropped }. A stamp keeps its drawing and an attachment its file, with nothing to download, and an annotation keeps its link.selection.duplicate({ offset? })copies the selection 10 points right and down, or left or up near the page's edge, and selects the copies.canDuplicate(refs)andselection.canDuplicate()are false without the right to create and for a locked annotation, whose copy would be locked too; code can still copy one.isMovable(ref)says whether an annotation is one people move: false for one that sits on text, such as a highlight. Past the engine's bundle limits (10,000 annotations by default)duplicate()is refused withinvalid-input, and nothing is copied. -
#1075 by @bobsingor –
selection.duplicate()copies a form's widgets too, in design mode: their owner says how (a radio button's copy joins its group, any other widget's is a new field), and the copies are made in the same change as the annotations', so a selection of both is one step to undo.selection.canDuplicate()asks the owner for them.duplicate(refs)still refuses a widget. For a plugin that lends records (AnnotationLender):copyOps(refs, placement)gives the ops that copy its records, andgetAuthority()also sayscopy. -
#1054 by @bobsingor –
import()is now one step to undo: an undo takes away every annotation the import added, and a redo brings them back under the same refs. It is sent after the changes staged before it, typed text included. An app that imports by itself, such as loading stored annotations when a document opens, passeshistory: falseto keep the import out of undo and redo:annotation.import(bundle, { history: false }).
-
#1075 by @bobsingor – New
duplicate(fields, { page?, offset?, values? })copies whole fields: each copy is a new field named after its original (email_2), with its settings, scripts and widgets, and no answer unlessvaluesis true. NewduplicateWidgets(widgets, options)copies widgets as Duplicate does in a form designer: a radio button's copy is another button of its group, with the next freeChoice<n>, and any other widget's copy is a new field; widgets of one field copied together become one new field. Both show their copies at once, are one step to undo, and resolve{ fields, widgets, dropped }. In design mode the annotation plugin'sselection.duplicate()copies the selected widgets through this plugin.addWidget()now shows its new widget before the engine answers.getSelectedField()is also the field when several of its widgets are selected, such as a radio group's buttons. Past the engine's item limit (10,000 fields by default) the call is refused withinvalid-input, and nothing is copied. -
#1054 by @bobsingor –
import()is now one step to undo: an undo takes away the fields the import added, and a redo brings them back. An app that adds fields by itself passeshistory: falseto keep the import out of undo and redo:form.import(bundle, { history: false }).
- #1051 by @bobsingor – A wheel or trackpad scroll over the Stage no longer gets stuck at the end of the pages. A scroll that begins where the pages can't scroll any further the way it pushes now scrolls the page around the viewer, as it does at the end of any scrolling element. A scroll that reaches the end stops there, momentum included, and the next one scrolls the page. On a trackpad the next swipe is the next one, also while the last still coasts. In paged flow a push past the edge still turns the page while there is one to turn to, and on a trackpad every swipe now turns one: a swipe that began while the last one still coasted turned nothing. The new
scrollChainingsetting is on by default. Set it tofalsein an app where the viewer fills the window, and the Stage keeps every wheel over it, as before: a sideways swipe the pages can't follow then never reaches the browser's back gesture.
-
#1071 by @bobsingor – New command
annotation:duplicate, withCtrl/Cmd+Dand a button in the bar over a selection. It copies the selected annotations beside the originals and selects the copies, as one step to undo. The button shows for annotations people move, so not for a highlight, and is greyed out while a locked annotation is selected. New iconduplicateand labelcommands.annotate.duplicate, in all 15 languages. -
#1075 by @bobsingor – Duplicate (
annotation:duplicate,Ctrl/Cmd+D) now copies form fields in Form design: a radio button's copy joins its group as a new choice, and any other field's copy is a new field named after the original. The form design sidebar has Duplicate group for a radio group, which copies the whole group as a new one. New labelformDesign.duplicateGroup, in all 15 languages.
- #1069 by @TbhVishal – A comment and a reply show their time as well as their day, with the year once it isn't this year's, and the whole date and time in a tooltip. Dates, times and file sizes are written in the language the viewer shows, the way the reader's region writes them: an English viewer reads
14 Sept, 17:30in a British browser andSep 14, 5:30 PMin an American one, and alocalethat names a region, such as'en-GB', writes them that way for everyone. A language whose code the browser can't read is written in the browser's own formats.
- #1070 by @bobsingor – The package's page on npm says what the fonts are and which packages bring them, with the fonts' license notice under it. The notice is a file of the package too,
NOTICE.md.
- #1070 by @bobsingor – The package's page on npm shows how to give the three fonts to the stamp plugin, with the fonts' license notice under it. The notice is a file of the package too,
NOTICE.md.
- #1074 by @bobsingor –
<FormLayer>draws a field's picture where the field is now. A field that was moved, in Form design or withupdateWidget(), kept its picture at the old place until the page's pictures were loaded again: the field showed in one place and took clicks in another.
-
#1074 by @bobsingor –
<FormLayer>draws a field's picture where the field is now. A field that was moved, in Form design or withupdateWidget(), kept its picture at the old place until the page's pictures were loaded again: the field showed in one place and took clicks in another. -
#1073 by @bobsingor – Opening another document while one is shown in a
<Stage>, or closing the shown one, no longer throwsCannot read properties of null (reading 'getLensId')(in Safari,null is not an object (evaluating '$$props.stage.getLensId')) and leaves the Stage blank. A page stays readable until its layers are gone: a layer that readsusePage()in a cleanup gets the page as it last was.
- #1074 by @bobsingor –
<FormLayer>draws a field's picture where the field is now. A field that was moved, in Form design or withupdateWidget(), kept its picture at the old place until the page's pictures were loaded again: the field showed in one place and took clicks in another.