Skip to content

v6.3.0

Choose a tag to compare

@58bits 58bits released this 15 Sep 11:23
· 109 commits to develop since this release

Highlights

  • @byline/admin, @byline/host-tanstack-start, @byline/i18n — The relationship picker can now offer a link to create the related document. When a relation field's target collection has nothing in it yet — or nothing that fits — editors previously had to abandon the form, navigate to the other collection, create the document, and come back to an empty editor. The picker now renders a create link in its header, opening the target collection's create view in a new tab so the picker and the parent editor stay mounted and unsaved work survives. It is a real <a target="_blank" rel="noopener noreferrer">, not a scripted window.open, so keyboard activation and middle-click work unaided and popup blockers leave it alone.

  • @byline/admin — Two optional capabilities were added to the field-services contract, canCreateInCollection(collectionPath) and getCreateDocumentUrl(collectionPath), both exported as types (CanCreateInCollectionFn, GetCreateDocumentUrlFn) from @byline/admin/react. They are optional in the same way the tree operations are: a host that wires neither simply gets no create affordance, and the widget guards on their presence — so no host change is required by this release. The URL is root-relative because no origin exists during the server render and the admin base path is host configuration; @byline/admin must not assume /admin. The ability check is cosmetic only — the create view still enforces the ability server-side regardless of what canCreateInCollection returns.

  • @byline/host-tanstack-start — The admin layout route now supplies those capabilities from the viewer's route context. bylineFieldServices became buildBylineFieldServices(user), composed inside the route rather than imported as a module constant, because the create affordance depends on abilities that only exist per-request. It is memoised on an ability fingerprint rather than on the user object: route context can hand back a new user identity on a render where nothing about the viewer changed, and depending on that would rebuild the services object and refetch the relation picker, whose fetch effect lists getCollectionDocuments as a dependency.

  • @byline/admin, @byline/i18n — The relationship picker gained an explicit refresh button. After creating the related document in the new tab, editors need the already-open picker to pick it up; refresh does that without closing and reopening. It is implemented as a nonce dependency of the existing fetch effect rather than an imperative refetch, so a superseded in-flight request is discarded by the effect's cancelled cleanup instead of overwriting newer results. It is deliberately not disabled while loading — a request that never settles must not leave the reader with no way to retry. New keys for both affordances landed in all eight bundled locales.

Bug Fixes

  • @byline/admin — DOM ids in the document editor are now scoped per form instance. Rendering a second form on the page (the groundwork for creating a related document inline) produced duplicate element ids across field inputs, tab panels, and the checkbox and datetime widgets — which breaks <label for> association and the aria-controls / aria-labelledby wiring that assistive technology depends on, since an id must be unique in a document. A new per-instance scope (form-dom-scope.tsx, carried on the form context) prefixes ids for the field renderer, the tab strip, and every widget that builds its own. Single-form pages are unaffected in behaviour; the generated id strings themselves have changed, so any host CSS or test selector pinned to a literal editor field id should move to a class or role selector.

  • @byline/admin — A form nested inside a portalled child no longer submits its parent. React portals keep the React tree intact even when the DOM tree diverges, so a submit event raised inside a portalled child form propagated up the React tree to the parent editor's handler and triggered a save the editor never asked for. The form renderer now isolates submit events at its own boundary.

  • @byline/ai — Two AI plugin drawers open on the same page no longer collide. The plugin base derived its drawer element ids from a fixed string; they are now derived from useId, so each instance is unique.

  • @byline/admin — The tab strip stopped re-measuring on every form render. Measurement now runs when the tab set actually changes rather than on each render pass, removing a forced synchronous layout from the editor's render path.

Chores

  • @byline/host-tanstack-start — The breadcrumbs provider now compares its settings by value and no longer performs a redundant visibility reset, removing repeated provider-level re-renders in the admin chrome.
  • @byline/host-tanstack-start — The collection API view now expands only the document's first level initially, rather than the whole tree, cutting the initial node count on large documents.
  • monorepo — The embedded (in-place) relation-creation approach was paused and the scope narrowed to the new-tab create flow shipped here; the reasoning and the preserved editor forced-layout measurements and probe scripts are recorded under specs/.

All other @byline/* packages bumped to 6.3.0 in lockstep with no behavioural changes this cycle.