Track the scrollport element in state instead of reading
`scrollportRef.current` during render. The ref was always null on the
render that mounts the `.tableScrollport` div, so `useVirtualizer`'s
`_willUpdate` saw `scrollElement=null`, skipped observer attachment, and
`calculateRange` returned null — rendering zero rows even though the
`/rows` response was already in the React-Query cache.
The bug surfaced after a filter change (the `rowsLoading` skeleton path
remounts the scrollport, and no follow-on render is guaranteed once
`/rows` settles) but not on first base load (slower side queries forced
an extra render that coincidentally re-bound the virtualizer). Switching
views also masked it: the re-render triggered `_willUpdate` with a now-
populated ref.
Using a callback-ref-backed `useState` triggers a render the moment the
div attaches, so the virtualizer picks it up on the next pass — no
view-switch workaround needed.
* fix(editor): hide transclusion borders and reset spacing in read-only mode
* feat(share): add full width toggle for shared pages
* feat(share): support resizing sidebar on shared pages
* fix: auto redirect if there is only one SSO provider.
- fix tighten sso redirect
- fix share tree margin
* sync
* package overrides
* feat(tree): replace react-arborist with custom tree implementation
* feat(tree): keyboard arrow navigation between rows
* feat(emoji-picker): focus search input on open
* refactor(emoji): switch to @slidoapp/emoji-mart fork for accessibility
* feat(tree): Home/End and typeahead keyboard navigation
* feat(tree): roving tabindex and * to expand sibling subtrees
* feat(tree): Space activation and ARIA refinements
* fix(tree): move treeitem role to focusable row + aria-current
Adds SAML_DISABLE_REQUESTED_AUTHN_CONTEXT env var, passed through
to the SAML strategy's disableRequestedAuthnContext option.
Defaults to existing behavior (element sent). Set to true to omit
the element when the IdP authenticates the user with a method that
does not match (e.g. MFA, FIDO, passwordless), which would
otherwise cause AADSTS75011 with Microsoft Entra ID.
The sticky-headers refactor (cd8d1e0e) moved the header row's sticky
behavior up to .stickyBand and dropped the position rule from
.headerCell entirely — but the cell still has two absolutely-positioned
children that need it as their containing block:
- .resizeHandle (right: 0) — without a per-cell containing block, all
handles resolve up to .stickyBand and stack at the band's right
edge, so only one is visible.
- Popover.Target (inset: 0) — every header's popover anchor collapses
to the same band-relative box, so the property menu opens at one
fixed spot regardless of which header was clicked.
.headerCellPinned still establishes a containing block via position:
sticky, which is why the primary Title column kept working. Re-adding
position: relative on the base .headerCell fixes both the resize handle
and the property-menu popover for non-pinned columns; pinned cells are
unaffected because position: sticky later in the cascade still wins.
The inline-embed endpoint was a thin wrapper around baseService.create:
its only differences from /bases/create were that it derived the
spaceId/workspaceId from a parent page, gated permission via
pageAccessService.validateCanEdit on that parent, and seeded inline
defaults (Title + Text 1 + Text 2 + one row). All of that fits
naturally on /bases/create as a parentPageId branch.
- CreateBaseDto: spaceId is now optional. Either spaceId or
parentPageId must be supplied; the controller validates the
cross-field requirement and 400s otherwise.
- /bases/create: with parentPageId, derive workspaceId/spaceId from
the parent, validateCanEdit on the parent, apply inline defaults.
Without parentPageId, gate on space-level Create, Page (the
standalone path).
- InlineEmbedBaseDto + createInlineEmbed deleted.
- Slash command in the editor now POSTs /bases/create with
{ parentPageId } — the server picks up the inline branch.