Skip to content

Migrate @sanity/hierarchical-document-list to the monorepo#985

Open
stipsan wants to merge 191 commits into
mainfrom
cursor/migrate-hierarchical-document-list-efdc
Open

Migrate @sanity/hierarchical-document-list to the monorepo#985
stipsan wants to merge 191 commits into
mainfrom
cursor/migrate-hierarchical-document-list-efdc

Conversation

@stipsan

@stipsan stipsan commented Jun 12, 2026

Copy link
Copy Markdown
Member

Migrates @sanity/hierarchical-document-list into the monorepo using the copy plugin generator (git subtree with full history preserved).

Highlights

  • Fixes the long-standing react-dnd 16 breakage (hierarchical-document-list#33, #16): @nosferatu500/react-sortable-tree is upgraded from the bundled v4.4.0 to v5.0.0 (react-dnd 16 / React 19 compatible) and declared as a regular dependency instead of being inlined into the bundle.
  • v5 adaptations: named SortableTreeWithoutDndContext export with the plugin's scoped DndProvider, ref-based DnD connectors, in-house flatDataToTree (v5's getTreeFromFlatData returns an empty tree for rootKey: null), definite pixel height for the new virtua-based virtualized list, and stable _key-based getNodeKey.
  • Modernized for Sanity v5/v6: sanity/desksanity/structure, useTimeAgouseRelativeTime, spacegap on @sanity/ui primitives, React Compiler lint fixes, type-only imports, and dependency alignment with the workspace catalog.
  • Kept in sync with main: merged the Studio v6 upgrade (Upgrade to Sanity Studio v6 and add opt-in Vite DevTools for the test studio #964/Bump @sanity/pkg-utils to ^10.5.4 and add per-plugin release notes for DTS fix #980, @sanity/mutator^6.0.0) and the later linter upgrade (fix(deps): Update linters to ^1.69.0 #1015), and re-verified build/lint/tests + a manual studio smoke test against Sanity v6.
  • Dedicated test-studio workspace (hierarchical-document-list-example) with createDeskHierarchy wired into a structure, plus schema registration in the kitchen-sink workspace.

Demo

Tree editing in the test studio (collapse/expand, remove from list, re-add):

hierarchical_document_list_tree_demo.mp4

Tree rendering and interactivity re-verified on Sanity v6:

Tree rendering on Sanity v6 after merge

Nested structure persisted to the dataset after a full page reload:

Nested tree persisted after reload

Removing an item moves it to the "Add more items" section:

Removed item in unadded list

Note: drag-to-nest was verified end-to-end by dispatching the browser's native drag events (the patch pipeline onMoveNode → patches → Content Lake persisted the nesting shown above). OS-level drag gestures don't complete in the headless test VM, so the recorded demo uses the menu/add flows for real-mouse interactions.

Transfer verification

  • Trusted publishing configured: npm trust github @sanity/hierarchical-document-list --file=release.yml --repository=sanity-io/plugins
  • package.json dependencies/peerDependencies/exports verified against original repo (v2.1.3 on npm)
  • Test studio example wired and manually verified (pnpm dev)
  • pnpm format, pnpm knip, pnpm lint, pnpm build, pnpm test run all pass (merged up to current main)
  • Major changeset added with validated breaking changes

Maintainer follow-up

To show artifacts inline, enable in settings.

Open in Web Open in Cursor 

Resolved pnpm-lock.yaml (generated file) by letting pnpm auto-merge and
reinstall against the union of both manifests.
Aligns the migrated plugin with the Sanity Studio v6 dependency bumps
applied to all other plugins on main (#964/#980).
@stipsan stipsan marked this pull request as ready for review June 12, 2026 15:21
@stipsan stipsan requested a review from a team as a code owner June 12, 2026 15:21
@stipsan stipsan requested review from bjoerge and Copilot and removed request for a team June 12, 2026 15:21

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Migrates @sanity/hierarchical-document-list into the sanity-io/plugins monorepo, modernizing it for current Sanity Studio/React/React DnD versions and wiring a dedicated test-studio workspace for verification.

Changes:

  • Added the @sanity/hierarchical-document-list package (source, build config, docs, changelog, changeset) to the monorepo.
  • Updated the test studio to include a dedicated hierarchical document list workspace and also register it in the kitchen-sink workspace.
  • Updated repo-level metadata/config to recognize the new workspace (lockfile, knip, oxlint, root README plugin list).

Reviewed changes

Copilot reviewed 47 out of 48 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
README.md Adds the plugin to the monorepo’s plugin list.
pnpm-lock.yaml Adds the new workspace and resolves new dependency graph entries.
plugins/@sanity/hierarchical-document-list/vitest.config.ts Vitest config for the plugin (exports test).
plugins/@sanity/hierarchical-document-list/tsconfig.json Type-check TS config for the plugin workspace.
plugins/@sanity/hierarchical-document-list/tsconfig.build.json Build TS config for emitting types/bundles.
plugins/@sanity/hierarchical-document-list/src/utils/treePatches.ts Patch generation for add/move/remove/duplicate operations.
plugins/@sanity/hierarchical-document-list/src/utils/treeData.tsx Transforms stored flat data into editor tree data + derives “unadded” items.
plugins/@sanity/hierarchical-document-list/src/utils/throwError.ts Centralized error messages helper.
plugins/@sanity/hierarchical-document-list/src/utils/moveItemInArray.ts Utility to reorder items by index.
plugins/@sanity/hierarchical-document-list/src/utils/injectNodeTypeInPatches.ts Injects user schema types into patches for persistence.
plugins/@sanity/hierarchical-document-list/src/utils/idUtils.ts Draft/published ID helpers.
plugins/@sanity/hierarchical-document-list/src/utils/gradientPatchAdapter.ts Converts PatchEvent patches into gradient patches for document ops.
plugins/@sanity/hierarchical-document-list/src/utils/getTreeHeight.ts Computes a deterministic pixel height for the virtualized tree.
plugins/@sanity/hierarchical-document-list/src/utils/getCommonTreeProps.tsx Centralizes common react-sortable-tree prop/theme configuration.
plugins/@sanity/hierarchical-document-list/src/utils/getAdjescentNodes.ts Finds neighboring nodes for stable insert anchoring.
plugins/@sanity/hierarchical-document-list/src/utils/flatDataToTree.ts Converts stored flat parent-key array into nested tree structure.
plugins/@sanity/hierarchical-document-list/src/types.ts Shared types for stored/enhanced/local tree nodes and options.
plugins/@sanity/hierarchical-document-list/src/TreeInputComponent.tsx Schema field input component wiring patches into Sanity form system.
plugins/@sanity/hierarchical-document-list/src/TreeDeskStructure.tsx Desk-structure component that edits a live document tree.
plugins/@sanity/hierarchical-document-list/src/schemas/hierarchy.tree.ts Default live-edit document schema for storing trees.
plugins/@sanity/hierarchical-document-list/src/index.ts Public entrypoint exports + plugin definition.
plugins/@sanity/hierarchical-document-list/src/index.test.ts Ensures package exports are correct in dist.
plugins/@sanity/hierarchical-document-list/src/hooks/useTreeOperationsProvider.ts Provides operations that translate UI actions into PatchEvents.
plugins/@sanity/hierarchical-document-list/src/hooks/useTreeOperations.ts Context hook for tree operations and item-load status.
plugins/@sanity/hierarchical-document-list/src/hooks/useLocalTree.ts Keeps local expand/collapse state and builds editor tree.
plugins/@sanity/hierarchical-document-list/src/hooks/useAllItems.ts Fetches/listens for all eligible documents and maintains lookup state.
plugins/@sanity/hierarchical-document-list/src/createHierarchicalSchemas.tsx Generates GraphQL-friendly schema types for tree documents/fields.
plugins/@sanity/hierarchical-document-list/src/createDeskHierarchy.tsx Structure-builder helper that mounts the hierarchy editor in Desk.
plugins/@sanity/hierarchical-document-list/src/components/TreeNodeRendererScaffold.tsx Custom scaffold line rendering for the tree.
plugins/@sanity/hierarchical-document-list/src/components/TreeNodeRenderer.tsx Custom node wrapper that applies indentation/padding and scaffold.
plugins/@sanity/hierarchical-document-list/src/components/TreeEditorErrorBoundary.tsx Wrapper intended to suppress noisy drag errors.
plugins/@sanity/hierarchical-document-list/src/components/TreeEditor.tsx Main editor UI with DnD provider and “unadded items” list.
plugins/@sanity/hierarchical-document-list/src/components/PlaceholderDropzone.tsx Placeholder/drop target UI.
plugins/@sanity/hierarchical-document-list/src/components/NodeContentRenderer.tsx Custom node content renderer (Sanity UI + drag handle).
plugins/@sanity/hierarchical-document-list/src/components/NodeActions.tsx Per-node action menu (remove/duplicate/open).
plugins/@sanity/hierarchical-document-list/src/components/DocumentPreviewStatus.tsx Draft/published status indicators + relative timestamps.
plugins/@sanity/hierarchical-document-list/src/components/DocumentInNode.tsx Document preview/link rendering inside a tree node.
plugins/@sanity/hierarchical-document-list/src/components/DeskWarning.tsx Shared warning UI used by desk structure component.
plugins/@sanity/hierarchical-document-list/README.md Plugin documentation (installation/usage/querying/GraphQL notes).
plugins/@sanity/hierarchical-document-list/package.json Package metadata, exports, dependencies/peers, Node engine range.
plugins/@sanity/hierarchical-document-list/package.config.ts @sanity/pkg-utils build configuration (React Compiler + styled-components).
plugins/@sanity/hierarchical-document-list/CHANGELOG.md Imported changelog history from the original repo.
knip.jsonc Adds knip workspace config for the new plugin.
dev/test-studio/src/hierarchical-document-list/index.tsx Adds a dedicated test-studio example plugin + structure wiring.
dev/test-studio/sanity.config.ts Registers the new test-studio workspace and kitchen-sink plugin list entry.
dev/test-studio/package.json Adds workspace dependency on @sanity/hierarchical-document-list.
.oxlintrc.json Adds lint rule overrides for the plugin’s legacy/loose typing areas.
.changeset/hierarchical-document-list-port.md Adds a major changeset describing the migration and breaking changes.
Files not reviewed (1)
  • pnpm-lock.yaml: Generated file

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +35 to +38
const {documentId, referenceTo} = props
if (typeof documentId !== 'string' && !documentId) {
throwError('invalidDocumentId')
}
Comment on lines +58 to +61
const safelyCreatableTypes =
creatableTypes && !creatableTypes.some((type) => referenceTo.indexOf(type))
? creatableTypes
: referenceTo
Comment on lines +27 to +32
{props.subtitle &&
props.subtitle.split('\\n').map((line: string) => (
<Text size={1} key={line}>
<WrapCodeBlocks text={line} />
</Text>
))}
Comment on lines +46 to +49
<DeskWarning
title="Invalid configuration"
subtitle="The `documentType` passed to `createDeskHiearchy` isn't live editable. \nTo continue using this plugin, add `liveEdit: true` to your custom schema type or unset `documentType` in your hierarchy configuration."
/>
Comment on lines +55 to +59
<DeskWarning
title="This hierarchy tree contains a draft"
subtitle="Click on the button below to publish your draft in order to continue editing the live
published document."
/>
Comment on lines +8 to +12

![Screenshot of the plugin](/screenshot-1.jpg)

⚠️ **Compatibility:** This plugin requires Sanity Studio [version 3.3.0](https://github.com/sanity-io/sanity/releases/tag/v3.3.0) or higher.

Comment on lines +49 to +63
import {defineConfig} from 'sanity'
import {deskTool} from 'sanity/desk'
import {
createDeskHierarchy,
hierarchicalDocumentList,
hierarchyTree,
} from '@sanity/hierarchical-document-list'

export default defineConfig({
// ...
plugins: [
deskTool({
// NOTE: I'n V3 you MUST pass S and Context along to createDeskHierarchy as props
structure: (S, context) =>
S.list()
Comment on lines +344 to +350
## License

MIT-licensed. See LICENSE.

## License

[MIT](LICENSE) © Sanity
Comment on lines +72 to +74
"engines": {
"node": ">=20.19 <22 || >=22.12"
}
Resolved conflicts:
- dev/test-studio/sanity.config.ts: kept both the new hierarchical-document-list
  and the incoming hotspot-array example imports/registrations
- knip.jsonc: kept both new plugin workspace entries
- pnpm-lock.yaml: regenerated via pnpm install against the union of manifests

Also disabled react/no-unstable-nested-components for the plugin's legacy
memoized forwardRef link wrappers, now flagged by main's upgraded linter.
@socket-security

socket-security Bot commented Jun 15, 2026

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addednpm/​react-dnd@​16.0.1991007885100
Addednpm/​react-dnd-html5-backend@​16.0.11001008085100
Addednpm/​@​nosferatu500/​react-sortable-tree@​5.0.09410010085100
Addednpm/​sanity-plugin-internationalized-array@​5.1.099100100100100

View full report

@socket-security

socket-security Bot commented Jun 15, 2026

Copy link
Copy Markdown

All alerts resolved. Learn more about Socket for GitHub.

This PR previously contained dependency changes with security issues that have been resolved, removed, or ignored.

View full report

Resolved conflicts:
- .oxlintrc.json: kept both the hierarchical-document-list override and the
  incoming dashboard-widget-vercel XState override as separate entries
- README.md: adopted main's widened plugins table (incl. new @sanity/dashboard
  family) and reinserted the hierarchical-document-list row alphabetically
- knip.jsonc: kept the hierarchical-document-list workspace entry alongside the
  incoming dashboard-widget-{vercel,netlify,document-list} entries
- pnpm-lock.yaml: regenerated via pnpm install against the union of manifests

Main's Version Packages (#1022) release consumed several changesets; the
hierarchical-document-list major changeset is retained.
Resolved conflicts:
- dev/test-studio/sanity.config.ts: kept both the hierarchical-document-list
  and the incoming @sanity/table kitchen-sink entries
- knip.jsonc: kept both new plugin workspace entries
- pnpm-lock.yaml: regenerated via pnpm install against the union of manifests
Add author: directives crediting everyone who built the original
@sanity/hierarchical-document-list plugin, so the release notes thank
them instead of the bot that opened the transfer PR (per AGENTS.md and
plugin-transfer/SKILL.md crediting instructions).
Resolved pnpm-lock.yaml (generated file) via pnpm install against the
union of both manifests. No source conflicts.
Resolved conflicts:
- dev/test-studio/sanity.config.ts: kept both the hierarchical-document-list
  and the incoming async-list kitchen-sink entries
- knip.jsonc: kept both new plugin workspace entries
- pnpm-lock.yaml: regenerated via pnpm install against the union of manifests

Note: a pre-existing @repo/generators build failure (tsdown 0.22.2 cannot
resolve its optional 'unrun' peer, which is absent from the lockfile)
reproduces identically on a clean origin/main checkout and is unrelated to
this merge.
bjoerge
bjoerge previously approved these changes Jun 17, 2026
Resolved conflicts:
- .oxlintrc.json: kept both the hierarchical-document-list override and the
  incoming @sanity/plugin-kit override as separate entries
- dev/test-studio/sanity.config.ts: kept both the hierarchical-document-list
  and the incoming mux-input kitchen-sink entries
- pnpm-lock.yaml: regenerated via pnpm install against the union of manifests

Note: the pre-existing @repo/generators build failure (tsdown 0.22.2's
unresolved optional 'unrun' peer) persists on main and is unrelated to
this merge.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.