Repository navigation
Migrate plugin-kit and the monorepo from prettier/eslint to oxfmt/oxlint - #1565
Conversation
- Ship the monorepo's oxfmt settings as a @sanity/plugin-kit/oxfmt preset - Re-export the preset from the root oxfmt.config.ts (replaces .oxfmtrc.json) - init/inject scaffold oxfmt (config, devDependency, format script) instead of prettier; --no-prettier is now --no-oxfmt - verify-package: replace the duplicate-prettier-config check with a monorepo-aware oxfmt check that expects the config at the workspace root (or next to package.json outside monorepos) and flags leftover prettier configuration with migration instructions
🦋 Changeset detectedLatest commit: 9f0868d The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
- Ship the monorepo's oxlint settings as @sanity/plugin-kit/oxlint-config.json (type-aware rules, type checking via oxlint-tsgolint, warnings denied); the root .oxlintrc.json extends it and keeps only workspace-specific ignores and overrides - init/inject scaffold oxlint (.oxlintrc.json, oxlint + oxlint-tsgolint devDependencies, lint script) instead of eslint; --no-eslint is now --no-oxlint, and the typescript flag now controls TypeScript scaffolding instead of piggybacking on the eslint flag - verify-package: drop the tsc run (oxlint type-checks as part of linting) and the duplicate-eslint-config check; add a monorepo-aware oxlint config check with legacy eslint detection; the v2-imports check (eslintImports -> imports) now runs a bundled oxlint pass instead of the package's eslint - pin typescript in dev/test-studio so the sanity peer keeps resolving to the catalog version now that plugin-kit no longer pulls eslint/typescript peers
oxlint auto-switches to GitHub annotations format on CI; --format=agent keeps the compact per-diagnostic output (including help: messages) everywhere
… pattern)
Replaces the oxlint-config.json + .oxlintrc.json extends-by-file-path setup
with a TS config module, mirroring the oxfmt preset: the shared config is
authored in src/oxlint.ts (typed OxlintConfig, built to plain JS in dist), the
root and scaffolded configs are oxlint.config.ts files that re-export or extend
it via defineConfig({extends: [...]})
v2-era imports are no longer linted for; with the bundled oxlint pass gone, oxlint moves from a runtime dependency of plugin-kit to a dev/peer dependency (it is only needed by consumers, which the scaffolding already installs)
…mt-migration-99d1 # Conflicts: # pnpm-lock.yaml
…figs detected - init/inject with --no-oxfmt/--no-oxlint now write the matching sanityPlugin.verifyPackage opt-outs, so the scaffolded build script (which runs verify-package) works out of the box - the oxfmt/oxlint checks now also flag leftover prettier/eslint configs at the detected workspace root, not only next to the plugin's package.json
There was a problem hiding this comment.
Pull request overview
This PR migrates @sanity/plugin-kit (and this monorepo’s scaffolding + verification workflows) from the Prettier/ESLint + tsc --build model to the Oxc toolchain (oxfmt + oxlint with type-aware/type-checking via oxlint-tsgolint). It also makes the monorepo’s formatter/linter settings reusable by publishing them as @sanity/plugin-kit/oxfmt and @sanity/plugin-kit/oxlint, then reusing those across scaffolds and monorepo configs.
Changes:
- Add shared, published
@sanity/plugin-kit/oxfmtpreset and@sanity/plugin-kit/oxlintconfig; wire them into build/exports and scaffolded configs. - Replace
verify-package/verify-studiochecks that previously relied on Prettier/ESLint and a post-checktsc --buildstep with new monorepo-awareoxfmt/oxlintconfig validation and legacy-config detection. - Update fixtures/tests/snapshots and the semver-workflow preset templates to reflect the new formatting/linting toolchain and ESM config files.
Reviewed changes
Copilot reviewed 60 out of 61 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| packages/@sanity/plugin-kit/tsdown.config.ts | Adds build entrypoints for the new exported oxfmt/oxlint configs. |
| packages/@sanity/plugin-kit/test/verify-package.test.ts | Updates verify-package tests for the new check set and removes the old invalid-eslint fixture test. |
| packages/@sanity/plugin-kit/test/verify-oxlint.test.ts | Adds dedicated tests for oxlint config discovery/validation (standalone + monorepo). |
| packages/@sanity/plugin-kit/test/verify-oxfmt.test.ts | Adds dedicated tests for oxfmt config discovery/validation (standalone + monorepo). |
| packages/@sanity/plugin-kit/test/inject.test.ts | Verifies injected preset files align with ESM + oxlint constraints. |
| packages/@sanity/plugin-kit/test/init.test.ts | Updates init scaffolding expectations to generate oxlint/oxfmt config and deps. |
| packages/@sanity/plugin-kit/test/init-verify-build.test.ts | Updates integration flow from tsc --build to oxlint, including resolving local plugin-kit import. |
| packages/@sanity/plugin-kit/test/fixtures/verify-package/valid/package.json | Updates fixture scripts/devDependencies to oxfmt/oxlint. |
| packages/@sanity/plugin-kit/test/fixtures/verify-package/valid/oxlint.config.ts | Adds fixture oxlint config re-exporting the shared plugin-kit config. |
| packages/@sanity/plugin-kit/test/fixtures/verify-package/valid/.prettierrc.json | Removes legacy prettier config fixture. |
| packages/@sanity/plugin-kit/test/fixtures/verify-package/valid/.eslintrc | Removes legacy eslint config fixture. |
| packages/@sanity/plugin-kit/test/fixtures/verify-package/invalid-eslint/tsconfig.json | Removes obsolete invalid-eslint fixture content. |
| packages/@sanity/plugin-kit/test/fixtures/verify-package/invalid-eslint/src/index.ts | Removes obsolete invalid-eslint fixture content. |
| packages/@sanity/plugin-kit/test/fixtures/verify-package/invalid-eslint/README.md | Removes obsolete invalid-eslint fixture content. |
| packages/@sanity/plugin-kit/test/fixtures/verify-package/invalid-eslint/package.json | Removes obsolete invalid-eslint fixture content. |
| packages/@sanity/plugin-kit/test/fixtures/verify-package/invalid-eslint/LICENSE | Removes obsolete invalid-eslint fixture content. |
| packages/@sanity/plugin-kit/test/fixtures/verify-package/invalid-eslint/.prettierrc.json | Removes obsolete invalid-eslint fixture content. |
| packages/@sanity/plugin-kit/test/fixtures/verify-package/invalid-eslint/.gitignore | Removes obsolete invalid-eslint fixture content. |
| packages/@sanity/plugin-kit/test/fixtures/verify-package/invalid-eslint/.eslintrc | Removes obsolete invalid-eslint fixture content. |
| packages/@sanity/plugin-kit/test/fixtures/verify-package/invalid-eslint/.editorconfig | Removes obsolete invalid-eslint fixture content. |
| packages/@sanity/plugin-kit/test/fixtures/inject/valid/package.json | Updates injected fixture to use oxfmt/oxlint scripts/deps. |
| packages/@sanity/plugin-kit/test/fixtures/inject/valid/oxlint.config.ts | Adds injected fixture oxlint config re-export. |
| packages/@sanity/plugin-kit/test/fixtures/inject/valid/.prettierrc.json | Removes injected legacy prettier config fixture. |
| packages/@sanity/plugin-kit/test/fixtures/inject/valid/.eslintrc | Removes injected legacy eslint config fixture. |
| packages/@sanity/plugin-kit/test/snapshots/verify-package.test.ts.snap | Updates snapshots for new oxfmt/oxlint + legacy-config error messaging and removed v2-import checks. |
| packages/@sanity/plugin-kit/src/util/command-parser.ts | Removes helper previously used to run tsc --build. |
| packages/@sanity/plugin-kit/src/oxlint.ts | Adds the shared published oxlint config used by monorepo + scaffolds. |
| packages/@sanity/plugin-kit/src/oxfmt.ts | Adds the shared published oxfmt preset used by monorepo + scaffolds. |
| packages/@sanity/plugin-kit/src/npm/package.ts | Updates scaffolding dependencies/scripts and adds verify-package opt-outs when oxfmt/oxlint are disabled. |
| packages/@sanity/plugin-kit/src/index.test.ts | Updates export manifest test to include ./oxfmt and ./oxlint. |
| packages/@sanity/plugin-kit/src/dependencies/import-linter.ts | Removes the ESLint-based v2 import linter module. |
| packages/@sanity/plugin-kit/src/constants.ts | Removes the now-unused link to the legacy v2 import linter package. |
| packages/@sanity/plugin-kit/src/configs/prettier.ts | Removes prettierignore templating (no longer scaffolded). |
| packages/@sanity/plugin-kit/src/configs/oxlint.ts | Adds oxlint config templating for init/inject. |
| packages/@sanity/plugin-kit/src/configs/oxfmt.ts | Adds oxfmt config templating for init/inject. |
| packages/@sanity/plugin-kit/src/configs/eslint.ts | Removes eslint templating (no longer scaffolded). |
| packages/@sanity/plugin-kit/src/configs/default-source.ts | Updates generated source to use oxlint-disable-next-line and avoids unused config param. |
| packages/@sanity/plugin-kit/src/cmds/inject.ts | Renames CLI flags to --no-oxlint / --no-oxfmt in help/docs. |
| packages/@sanity/plugin-kit/src/cmds/init.ts | Renames CLI flags to --no-oxlint / --no-oxfmt in help/docs. |
| packages/@sanity/plugin-kit/src/actions/verify/verify-common.ts | Removes tsc and eslintImports check keys and introduces oxfmt/oxlint keys. |
| packages/@sanity/plugin-kit/src/actions/verify/validations.ts | Implements monorepo-aware oxfmt/oxlint config validation and legacy prettier/eslint detection. |
| packages/@sanity/plugin-kit/src/actions/verify-studio.ts | Removes eslint import checks and post-check tsc --build from verify-studio. |
| packages/@sanity/plugin-kit/src/actions/verify-package.ts | Swaps duplicate-config and eslint import checks for new oxfmt/oxlint validations; removes post-check tsc --build. |
| packages/@sanity/plugin-kit/src/actions/inject.ts | Updates injected assets to add oxfmt/oxlint configs and remove eslint/prettier templates. |
| packages/@sanity/plugin-kit/src/actions/init.ts | Renames init flags to oxlint/oxfmt. |
| packages/@sanity/plugin-kit/README.md | Documents new oxfmt/oxlint usage and updates verify-package docs to reflect new checks. |
| packages/@sanity/plugin-kit/package.json | Adds new exports for ./oxfmt and ./oxlint, and replaces eslint/typescript peers with oxfmt/oxlint peers. |
| packages/@sanity/plugin-kit/docs/semver-workflow.md | Updates semver-workflow preset docs to describe oxfmt/oxlint behavior. |
| packages/@sanity/plugin-kit/assets/inject/semver-workflow/lint-staged.template.js | Updates lint-staged template to run oxfmt/oxlint and switches to ESM export. |
| packages/@sanity/plugin-kit/assets/inject/semver-workflow/commitlint.template.js | Switches commitlint template to ESM export. |
| packages/@sanity/plugin-kit/assets/inject/prettierrc.json | Removes legacy prettier template asset. |
| package.json | Adds workspace dependency on @sanity/plugin-kit so root configs can import the shared presets. |
| oxlint.config.ts | Introduces root oxlint config extending @sanity/plugin-kit/oxlint with workspace-specific ignores/overrides. |
| oxfmt.config.ts | Introduces root oxfmt config re-exporting @sanity/plugin-kit/oxfmt. |
| knip.jsonc | Updates dependency ignore list to reflect removal of eslint/prettier runtime-resolved deps. |
| dev/test-studio/package.json | Pins TypeScript (catalog) to stabilize dependency resolution after peer changes. |
| AGENTS.md | Updates agent guide to reflect the new oxfmt/oxlint configs and Node requirements. |
| .oxlintrc.json | Removes old JSON-based oxlint config (replaced by TS config + shared config). |
| .oxfmtrc.json | Removes old JSON-based oxfmt config (replaced by TS config + shared preset). |
| .changeset/plugin-kit-oxfmt.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.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 417dd6a. Configure here.
plugin-kit's oxfmt/oxlint peers now reference the default catalog (catalog:) rather than catalog:peer or explicit ranges: the shared configs may rely on rules and features that ship in a new minor, so the peer range must stay in lockstep with the version the monorepo develops against.
Unlike @sanity/pkg-utils (a hard requirement, checked unconditionally by verify-package), the oxfmt/oxlint verify-package checks are individually opt-outable via sanityPlugin.verifyPackage.oxfmt/oxlint: false, and plugin-kit's own code only ever imports their types. So a consumer can legitimately use plugin-kit without oxfmt or oxlint installed; peerDependenciesMeta now reflects that.
Resolve the modify/delete conflict on .oxlintrc.json: main moved shared lint rules into @sanity/plugin-kit/oxlint (#1565). Accept the deletion and port the Component/PureComponent/createRef bans into packages/@sanity/plugin-kit/src/oxlint.ts alongside the existing createElement/forwardRef restrictions. Also rewrite OrderableDocumentList to use React 19 ref-as-prop instead of forwardRef so it complies with main's forwardRef ban, and update skill docs that still pointed at .oxlintrc.json.
Replace styled-components and inline style objects with colocated
vanilla-extract stylesheets, using assignInlineVars for dynamic
theme/color values. Builds on the function-component + useDrag
refactor from the ban-react-class-components branch.
fix: address review feedback on drag attach timing and imperative handle
- useDrag: attach the mousedown listener in useLayoutEffect so it exists
before paint (matches the previous synchronous JSX onMouseDown wiring).
- OrderableDocumentList: give useImperativeHandle a dependency list so a
new handle object is not installed on every render (the structure pane
stores the handle in state, so per-render handles could loop).
refactor(color-input): extract shared useDrag hook for picker surfaces
Replace the per-component propsRef/AbortController plumbing in
Alpha/Hue/Saturation/EditableInput with a single useDrag hook. It wires a
native mousedown listener via useEffect and keeps callbacks fresh with
useEffectEvent, so drag events always read the latest props. mousemove and
mouseup listeners attach per-gesture and abort on mouseup or unmount.
fix(color-input): address review feedback on drag listeners
- Keep latest props in a ref so window mousemove listeners registered on
mousedown see current values (matches class `this.props` behavior).
- Normalize EditableInput value comparisons to avoid number/string mismatch.
- Correct orderable-document-list changeset wording (ref-as-prop, not forwardRef).
Merge origin/main into cursor/ban-react-class-components-ca2a
Resolve color-input conflicts from #1673 (simplify components, remove
CustomPicker HOC). Main kept Alpha/Hue/Saturation/EditableInput as class
components pending a follow-up conversion; this PR is that follow-up:
- Accept ColorWrap.tsx deletion (HOC replaced by ColorInput state).
- Re-apply function-component conversions on top of main's AbortController
listener cleanup, using useRef instead of createRef.
fix(color-input): simplify components, remove HOC (#1673)
Version Packages (#1668)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): dedupe pnpm-lock.yaml (#1671)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
Migrate sanity-plugin-workflow styling to vanilla-extract (#1450)
* Migrate sanity-plugin-workflow styling to vanilla-extract
* Keep styled-components catalog:devDependency for peer alignment
After the vanilla-extract migration, the peer can go, but the catalog
devDependency must remain so pnpm resolves the workspace
@sanity/styled-components override (same as google-maps-input).
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Merge origin/main into cursor/ban-react-class-components-ca2a
Resolve the modify/delete conflict on .oxlintrc.json: main moved shared
lint rules into @sanity/plugin-kit/oxlint (#1565). Accept the deletion
and port the Component/PureComponent/createRef bans into
packages/@sanity/plugin-kit/src/oxlint.ts alongside the existing
createElement/forwardRef restrictions.
Also rewrite OrderableDocumentList to use React 19 ref-as-prop instead
of forwardRef so it complies with main's forwardRef ban, and update
skill docs that still pointed at .oxlintrc.json.
ci: request workflows permission for typegen app token (#935)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Cody Olsen <81981+stipsan@users.noreply.github.com>
feat(@sanity/plugin-kit)!: remove Studio v2 upgrade and compatibility tooling (#1588)
* feat(@sanity/plugin-kit)!: remove Studio v2 upgrade and compatibility tooling
Drop verify-studio and all verify-package checks that existed to migrate from
or stay compatible with Sanity Studio v2 (incompatible-plugin shim, part:/config:
imports, merged @sanity/* packages, sanity.json parts validation). Package
verification now focuses on current plugin-kit conventions.
* chore(@sanity/plugin-kit): drop unused json5/knip ignores and refresh snapshots
Remove the json5 dependency and readJson5File helper that only served v2
sanity.json parsing, prune stale eslint knip ignoreDependencies, and update
verify-package snapshots after removing v2-upgrade checks.
* fix(@sanity/plugin-kit): address review feedback on path validation and studio detection
Drop the dist-hardcoded path existence check in getPackage entirely: compiled
entry points legitimately don't exist pre-build regardless of outDir, and
verify-package's esmOnly check already bans main/module fields. Also detect
sanity.cli.(js|ts) in findStudioConfig so init/inject refuse cli-config-only
studio directories too.
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
chore(deps): dedupe pnpm-lock.yaml (#1669)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(sanity-plugin-markdown): declare @sanity/client as a regular dependency (#1667)
* fix(sanity-plugin-markdown): declare @sanity/client and rxjs as regular deps
Move @sanity/client and rxjs out of inlinedDependencies into dependencies
so they are resolved at runtime instead of bundled into the package.
* chore: update lockfile for sanity-plugin-markdown deps
* fix(sanity-plugin-markdown): declare @sanity/client as a regular dependency
Move @sanity/client from devDependencies to dependencies so tsdown
externalizes it instead of writing it (and transitive rxjs) to
inlinedDependencies. rxjs is not imported by the plugin and is not
needed as a direct dependency once client is externalized.
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
fix(typegen): 🤖 ✨ (#1666)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @tanstack/react-virtual to ^3.14.7 (#1664)
* fix(deps): update dependency @tanstack/react-virtual to ^3.14.7
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): dedupe pnpm-lock.yaml (#1665)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
Version Packages (#1663)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
feat: add @sanity/block-insert-picker (#1601)
* feat(block-insert-picker): add @sanity/block-insert-picker
Slash-command block-insert picker and markdown input rules for Portable
Text fields, extracted from the sanity-io/www-sanity-io docs Studio
(apps/studio/src/plugins/pte, PR #4003 there parameterized the docs
knowledge out in preparation).
Public API: blockInsertPicker({arrayTypeName, items?, inputRules?,
onItemInserted?}) returning the component for an array type's
components.portableText.plugins, plus the codeFenceRule/blockquoteRule
config factories and fence-language helpers. Items derive from the host
array's members with metadata-driven curation (triggers, keywords,
grouping, rank); inserts resolve member initial values, land as one
undo step, and open for editing.
Ported against sanity 6.5.0 / @portabletext/editor 7.10.7 /
@portabletext/plugin-input-rule 6.0.4 (peer editor ^7.10.7 to match the
input-rule plugin's requirement; editor stays a peer, never bundled).
112 tests ported with the source; test-studio example wired under
Home > Block Insert Picker.
* refactor(block-insert-picker): zero-config detection and reviewed v1 API
Applies the pre-publication design review (DESIGN-REVIEW.md in the
pte-plugin-extraction research):
- blockInsertPicker() now works with zero config: the containing array and
its members are detected via PortableTextMemberSchemaTypesContext
(quarantined in memberSchemaTypes.ts); arrayTypeName becomes an escape
hatch. Peer narrowed to sanity ^5.6 (the context export's floor).
- Text blocks are excluded by resolved type chain, fixing aliased
{name, type: 'block'} members being offered as object inserts (picker and
input-rule allow-list both).
- New options: labels (translatable chrome), shortcut, openOnInsert
(global + per-item), presets (well-known-type triggers/keywords),
filter (receives the bare query in both modes), resolveItems middleware
with custom item actions (query cleanup included); onItemInserted renamed
onInsert, events carry mode/query.
- Presentation matches core: icon fallback chain, upperFirst titles, and
curated descriptions now win over schema descriptions.
- New exports: BlockInsertPicker, MarkdownInputRules, derivePickerItems,
filterPickerItems, standardBlockPresets, wellKnownInputRules, PickerMode.
- Input rules resolve blockType through member type chains, so
wellKnownInputRules serves aliased code-input members.
- Review fixes: host-callback errors surface as toasts instead of unhandled
rejections; anchor-deletion mid-insert shows a warning toast; positional
row indices tolerate duplicate item ids; replacement-pattern-safe label
formatting; screen-reader position announcement is translatable.
Deliberate deviations from the review doc: presets carry no description
(avoids a three-way precedence chain).
* test(block-insert-picker): lift cold-start timeout on first picker popover test
* docs: add @sanity/block-insert-picker to Current Plugins table
* chore: trigger pkg.pr.new preview publish
* refactor(block-insert-picker): address Copilot review comments
- insertPickerItem: spread the resolved initialValue before `_key`/`_type`
so the generated key and target type always win. Sanity's initial-value
resolver sets `_type` on object values; the values coincide by
construction here, but ordering keeps the insert correct regardless.
- openBlockOnInsert: correct the stale rationale comment. The package
enables the React Compiler, so the old "not active" claim was wrong; the
point is the empty-dep useCallback keeps a stable reference for consumers.
- blockInsertPicker: fix the comment naming the wrong mouse events. Rows
select via onClick and highlight via onMouseMove (not onMouseDown /
onMouseEnter), passing an explicit idx to avoid a not-yet-flushed
highlightedIndex.
* fix(block-insert-picker): case-insensitive fence language table match; trim README install
- normalizeFenceLanguage now compares the typed token to language-table
`value`/`aliases` case-insensitively, returning the canonical value
(casing preserved). Previously a table with mixed-case entries never
matched and the mapped filename was skipped (Cursor Bugbot, low severity).
Built-in rules and code-input's lowercase table were unaffected; this
hardens host-supplied custom tables. Adds a mixed-case-table test.
- README: collapse the three install commands to a single `npm install`
(no --save), matching @sanity/code-input's install section.
* Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* fix(block-insert-picker): restore bracket notation for process.env access
The Copilot Autofix commit rewrote `process.env['NODE_ENV']` to dot
notation, which fails this repo's type-aware lint: `noPropertyAccessFrom
IndexSignature` (TS4111) requires index-signature properties like
`process.env.NODE_ENV` to be accessed with brackets. Restore the bracket
form so `pnpm lint` passes.
* fix(block-insert-picker): address Cursor Bugbot findings
- inputRules: preserve case for unknown fence tokens (`return token`, not the
lowercased form) so the "pass through as typed" contract holds — e.g.
`GraphQL` stays `GraphQL` for wellKnownInputRules' no-table path.
- inputRules: spread host `buildValue` before `_key`/`_type` in createInsertRule
so a stray `_key`/`_type` can't hijack block identity (mirrors the
insertPickerItem fix).
- blockInsertPicker: close the picker when a select bails on an in-flight
insert, so a menu reopened during a slow initial-value resolution can't get
stuck swallowing Enter.
- blockInsertPicker: key sections on the namespaced raw group instead of the
display label, so a curated group named like `ungroupedSection` can't collide
with the null-group section's React key.
Two other Bugbot findings need no change: the text-block exclusion
(`isTextBlockMember`) already mirrors Sanity's own `findBlockType` (walk the
type chain to root, match `name === 'block'`), and the initial-value spread in
insertPickerItem was already reordered in an earlier commit.
---------
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
feat(code-input): export SUPPORTED_LANGUAGES and LANGUAGE_ALIASES (#1600)
Downstream tooling that resolves external language tokens (markdown
fence infostrings, paste/import pipelines) onto code field values has
had to vendor this list and hand-sync it with the Language selector.
Exporting the canonical table (and the alias map) removes the drift.
Version Packages (#1662)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(changeset): note npm provenance re-enabled for sanity-plugin-utils (#1661)
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Version Packages (#1660)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(changeset): bump google maps input for css dts cleanup (#1659)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
chore(deps): dedupe pnpm-lock.yaml (#1658)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @sanity/client to ^7.24.0 (#1581)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): lock file maintenance (#1657)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
Version Packages (#1640)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(test-studio): use turbo transit for build cache invalidation (#1655)
Replace empty dependsOn with a transit node so sanity build still skips
workspace package builds while Turbo invalidates when dependency source changes.
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
chore(deps): bump pkg-utils, tsdown-config, and vanilla-extract plugins (#1656)
Update catalog entries to @sanity/pkg-utils ^11.0.13,
@sanity/tsdown-config ^0.19.6, and @sanity/vanilla-extract-vite-plugin
^0.2.5. Exclude lightningcss@1.33.0 (and platform packages) from
minimumReleaseAge so pnpm update/dedupe can resolve the new transitive
deps, and align turbo/generators tsdown with the workspace catalog.
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
chore(deps): dedupe pnpm-lock.yaml (#1653)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore: remove @typescript/native-preview (use TypeScript 7 native tsc) (#1650)
* chore: remove @typescript/native-preview now that TypeScript 7 ships native tsc
TypeScript 7.0.2 includes the native compiler as `tsc`, so the preview package
and its `tsgo` binary are no longer needed. VS Code settings now point the
TypeScript 7 extension at the workspace `typescript` install.
* Update settings.json
* Update settings.json
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
chore(deps): lock file maintenance (#1651)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(test-studio): stop waiting on dependency builds (#1652)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Delete dependencies-GH-1642.md
Migrate to date-fns v4 and official @date-fns/tz, matching sanity core (#1569)
chore(deps): dedupe pnpm-lock.yaml (#1649)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @sanity/pkg-utils to ^11.0.12 (#1647)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): dedupe pnpm-lock.yaml (#1645)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): update renovatebot/github-action action to v46.1.20 (#1646)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): bump @sanity/vanilla-extract-vite-plugin to ^0.2.4
Drop the Bynder Styles.css.js Vite workaround from the test studio —
0.2.4 keeps the compiler alive under unstable_bundledDev, so plain
*.css.js modules no longer hang processVanillaFile.
fix(deps): update dependency tsdown to ^0.22.12 (#1642)
fix(deps): update dependency styled-components to ^6.4.4 (#1566)
chore(deps): dedupe pnpm-lock.yaml (#1643)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency react-virtuoso to ^4.18.11 (#1641)
* fix(deps): update dependency react-virtuoso to ^4.18.11
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
docs(agents): catalog shared deps + enable pnpm catalogMode prefer (#1374)
chore(deps): dedupe pnpm-lock.yaml (#1637)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency react-hook-form to ^7.82.0 (#1639)
* fix(deps): update dependency react-hook-form to ^7.82.0
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): update davelosert/vitest-coverage-report-action action to v2.12.2 (#1638)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
Version Packages (#1612)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
ci: shard Vitest suite (#1584)
* ci: shard vitest suite
* ci: report sharded test coverage
* chore: ignore Vitest blob reports
* ci: require test shards to succeed in aggregate check
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
fix(typegen): 🤖 ✨ (#1634)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(format): 🤖 ✨ (#1633)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): dedupe pnpm-lock.yaml (#1632)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency tsdown to ^0.22.9 (#1622)
* fix(deps): update dependency tsdown to ^0.22.9
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
fix(assist): keep field group selection while editing AI Assist inputs (#1467)
* fix(assist): keep field group selection while editing AI Assist inputs
The AI Assist instruction inspector renders a nested document form that
reused the host document's pane router. Sanity's document pane mirrors the
router `path` param to programmatic focus, and focus drives the selected
field group. Navigating the instruction form therefore overwrote the host
`path`, re-focused the host document, and reset its field group tab.
Isolate the nested pane's `path` navigation in local state while still
forwarding other params (e.g. selected instruction) to the host router.
Co-authored-by: Cody Olsen <stipsan@users.noreply.github.com>
* test(test-studio): add AI Assist + field groups fixture (SAPP-3970)
Adds an 'AI Assist: Field groups' document type with Content/SEO field
group tabs so the field-group-reset behavior with AI Assist can be
manually reproduced and verified.
Co-authored-by: Cody Olsen <stipsan@users.noreply.github.com>
* refactor(assist): use react-fast-compare for param equality
Addresses PR review: the hand-rolled shallowEqualParams returned a false
positive when two param objects had the same key count but different keys
whose values were undefined (e.g. {foo: undefined} vs {bar: undefined}),
because it never verified the key existed on the other object. Reuse
react-fast-compare (already a plugin dependency, used in _lib/useListeningQuery)
instead of a custom check, and add a regression test.
Co-authored-by: Cody Olsen <stipsan@users.noreply.github.com>
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Cody Olsen <stipsan@users.noreply.github.com>
fix(bynder-input): restore Compact View modal visibility in Studio v6 (#1553)
* fix(bynder-input): restore Compact View modal visibility in Studio v6
Upgrade @bynder/compact-view from 5.1.2 to 5.4.0 and patch its shadow DOM
integration for Sanity Studio v6:
- disableCSSOMInjection on StyleSheetManager so styled-components injects
CSS into the shadow root instead of leaving empty style tags
- position:fixed + z-index on CompactViewContainer so the portal host
stacks above Studio UI layers
- widen React peer dependency range to support React 19
Also render BynderModalLayout outside the button flex row.
* fix: unmount bynder layout when not open
* fix(bynder-input): take @bynder/compact-view 5.4.0 as a regular pinned dependency
Implements review feedback on the patch-based approach:
- drop the pnpm patch and the bundling of @bynder/compact-view; pin it
as a regular dependency instead
- style the Compact View modal host from the plugin with a
vanilla-extract globalStyle instead of patching Modal.js
- document how to allow the stale react peer range (npm
--legacy-peer-deps, pnpm peerDependencyRules.allowedVersions) in the
README, and use the pnpm rule for the workspace itself
* fix(bynder-input): survive Compact View shadow-root re-attachment and fix dev-studio css.js crash
- append a <slot> fallback to Compact View's shadow root while the modal
is mounted: its attachShadow effect has no cleanup, so when React
reconnects passive effects on the same host (StrictMode, Activity),
the second attachShadow() throws and Compact View falls back to the
host's light DOM, which the slotless shadow tree kept invisible
- work around @bynder/compact-view's Styles.css.js (a plain JS module
whose name matches vanilla-extract's cssFileFilter and deadlocks the
compiler under sanity dev's bundled dev mode) in the test studio
- move the container globalStyle to BynderInput.css.ts so it loads with
the input instead of the lazy modal chunk
* chore(bynder-input): bump changeset to major
Taking @bynder/compact-view as an unbundled regular dependency with a
stale react peer range can fail npm installs without --legacy-peer-deps,
so it's a breaking change.
* chore(bynder-input): widen @bynder/compact-view to ^5.4.0
The exact pin was only needed while the package was patched and
inlined; as a plain regular dependency a caret range is fine.
* chore: merge main and regenerate lockfile
The PR lockfile was generated against a main where
@sanity/vanilla-extract-vite-plugin resolved to 0.2.1; main has since
bumped it to 0.2.2, and the git-merged lockfile on the PR merge ref was
internally inconsistent (ERR_PNPM_LOCKFILE_MISSING_DEPENDENCY in CI).
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Cody Olsen <stipsan@users.noreply.github.com>
fix(deps): update dependency @sanity/tsdown-config to ^0.19.3 (#1598)
* fix(deps): update dependency @sanity/tsdown-config to ^0.19.3
* chore: dedupe lockfile and add release-age excludes for tsdown transitive deps
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
Co-authored-by: Cody Olsen <81981+stipsan@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
chore(deps): dedupe pnpm-lock.yaml (#1631)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @sanity/vanilla-extract-vite-plugin to ^0.2.2 (#1614)
* fix(deps): update dependency @sanity/vanilla-extract-vite-plugin to ^0.2.2
* chore(deps): exempt yuku-parser from minimum release age for dedupe
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Move turbo/**/*.hbs oxfmt ignore to root config (#1604)
The turbo generator template ignore is monorepo-specific and should
not ship in the shared @sanity/plugin-kit/oxfmt preset consumed by
standalone plugins.
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
fix(deps): update dependency @sanity/pkg-utils to ^11.0.10 (#1630)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
docs(assist): fix README markdown formatting and document English-only image descriptions (#1628)
* fix(@sanity/assist): respect document language when generating image descriptions
Pass the configured translate.document.languageField as languagePath to the
generate-caption task (both the automatic generation triggered on image
change, and the manual 'Generate image description' field action), so
generated alt text/captions are written in the document's language instead
of always defaulting to English.
Fixes https://github.com/sanity-io/plugins/issues/1606
* docs(@sanity/assist): clarify caption generation language limitation
Testing against the live AI Assist backend confirms that the generate-caption
task currently always writes descriptions in English, regardless of the
languagePath sent from the client (this matches Sanity's own documentation,
which states the automatic image description feature is English-only today
and recommends the Transform Agent Action's image-description operation as a
workaround). Update the changeset and README to accurately describe the
change as forward-compatible plumbing rather than a full fix, and point users
at the documented workaround for non-English alt text today.
* refactor(assist): resolve languagePath inside useGenerateCaption
Compute languagePath from config.translate.document.languageField once
inside useGenerateCaption itself (via useAiAssistanceConfig), instead of
requiring every call site to read the config and thread it through as an
argument. This removes the duplicated config lookup from both
ImageContextProvider and generateCaptionsActions, and matches the cleaner
approach used in sanity-io/plugins#1627.
Also documents in translate/types.ts JSDoc that languageField is reused
for image description generation.
* docs(assist): fix README markdown formatting and add known limitations
The README relied on markdown block elements (headings, lists, code
fences, images) interrupting paragraphs without blank lines between
them. GitHub tolerates this, but stricter renderers (e.g. the plugin
listing on sanity.io) join everything into unreadable walls of text
with literal '### Heading' and '- list item' fragments inline.
- Separate all block elements with blank lines throughout
- Add a 'Known limitations' section documenting that image descriptions
are always generated in English regardless of
translate.document.languageField (backend limitation, see #1606),
with Transform Agent Action and translate-after workarounds
- Fix broken links: empty-href heading, HOW-TO-USE pointing at the old
standalone repo layout, LICENSE pointing at a non-existent file
- Fix broken bold markup in the 'Enabling the AI Assist API' steps and
the useExampleFieldActions TOC anchor
- Add missing TOC entries (Known limitations, Caveats, Third party
sub-processors)
Also reverts the languagePath client plumbing from this branch: the
backend ignores it, so the plugin change had no effect. This PR is now
docs-only.
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
chore(deps): dedupe pnpm-lock.yaml (#1619)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): update pnpm to v11.13.1 (#1624)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @sanity/pkg-utils to ^11.0.9 (#1625)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update turbo monorepo to v2.10.5 (#1626)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): update dependency knip to ^6.27.0
chore: fix css
fix(deps): update dependency @codemirror/lang-markdown to ^6.5.1 (#1610)
* fix(deps): update dependency @codemirror/lang-markdown to ^6.5.1
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency oxfmt to ^0.59.0 (#1599)
* fix(deps): update dependency oxfmt to ^0.59.0
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @sanity/pkg-utils to ^11.0.7 (#1594)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
Fix TypeGen workflow failure by pinning `@sanity/vanilla-extract-vite-plugin` to 0.1.1 (#1616)
* Initial plan
* fix(typegen): pin vanilla-extract vite plugin to 0.1.1
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
chore(deps): bump tsdown and vanilla-extract
fix(deps): update dependency oxlint to ^1.74.0 (#1603)
* fix(deps): update dependency oxlint to ^1.74.0
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): update zizmorcore/zizmor-action action to v0.6.0 (#1609)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): lock file maintenance (#1611)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): replace @vanilla-extract/vite-plugin with @sanity/vanilla-extract-vite-plugin (#1590)
* chore(deps): replace @vanilla-extract/vite-plugin with @sanity/vanilla-extract-vite-plugin
Swap the vanilla-extract Vite plugin used by the test studio and
@sanity/google-maps-input's vitest config to @sanity/vanilla-extract-vite-plugin,
a Vite 8 rewrite with plugin hook filters and a caching compiler on Vite's
Environment API / ModuleRunner instead of the legacy vite-node. Bump tsdown to
^0.22.8 and @sanity/tsdown-config to ^0.17.0 alongside it.
google-maps-input's vitest.config.ts also needed a small stub plugin: its
dist/bundle.css.js Node/SSR shim matches the upstream cssFileFilter by
filename alone (*.css.js), which made the new plugin try to evaluate it as
real .css.ts source and throw ReferenceError: require is not defined via
ModuleRunner (vite-node tolerated this). The stub renames that module id away
from a .css.js shape before vanillaExtractPlugin() ever sees it.
Documented both the plugin swap and the shim workaround in the
sanity-plugin-best-practices skill and the new-plugin generator templates so
future vanilla-extract plugins get this for free.
* chore(deps): bump @sanity/tsdown-config to ^0.17.1, drop bundle.css.js shim workaround
@sanity/tsdown-config 0.17.1 (via @sanity/vanilla-extract-tsdown-plugin
0.2.1 / @sanity/vanilla-extract-rolldown-plugin 0.1.1) renames the
vanilla-extract Node/SSR compat shim from bundle.css.js to bundle-css.js so
it no longer matches vanillaExtractPlugin()'s cssFileFilter by filename
alone (sanity-io/pkg-utils#3043). That was the root cause of the
require-is-not-defined regression worked around in the previous commit, so
the stub-bundle-css-js-shim plugin is no longer needed.
Rebuilding @sanity/google-maps-input picked up the renamed dist/bundle-css.js
shim and auto-rewrote its package.json ./bundle.css export map (adding a
types condition too). Reverted the vitest.config.ts workaround and the
matching documentation/generator-template changes back to the plain
vanillaExtractPlugin() registration, now noted as a historical gotcha
instead of a live workaround.
* docs(test-studio): note that unstable_bundledDev breaks .css.ts HMR
Document the trade-off discovered while testing the vanilla-extract Vite
plugin swap: with unstable_bundledDev: true, editing a .css.ts file doesn't
hot-reload (a sanity dev restart is required), while plain .ts/.tsx HMR is
unaffected. Comment out the line for a session if fast CSS HMR is needed
(confirmed sub-10ms with it unset).
* docs(styling skill): trim verbose vanilla-extract setup section
The ./bundle.css export map (and its dist/bundle-css.js shim/types) is
generated and kept in sync automatically by @sanity/tsdown-config's
vanillaExtract option, so it doesn't need explaining or a JSON example to
copy. Simplify the vitest.config.ts guidance to why (@sanity/vanilla-extract-
vite-plugin is faster than upstream) without the ModuleRunner/hook-filter/
sanity-build internals. Drop the sanity.cli.ts snippet, since the test studio
already registers the plugin globally in this repo and doesn't need to be
touched per-plugin. Drop the bundle.css.js->bundle-css.js rename history
note, a one-off gotcha now fixed upstream rather than evergreen guidance.
* chore(deps): bump @sanity/tsdown-config to ^0.17.2, @sanity/vanilla-extract-vite-plugin to ^0.1.1
Both are latest-available patch releases (0.17.1 -> 0.17.2 pulls in
@sanity/vanilla-extract-tsdown-plugin 0.2.2 / @sanity/vanilla-extract-
rolldown-plugin 0.1.2; 0.1.0 -> 0.1.1 is the vite plugin's own patch).
tsdown stays at ^0.22.8, already the latest. Benchmarked in the next commit's
message to confirm this doesn't regress anything.
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
fix(deps): update dependency @changesets/cli to ^2.31.1 (#1607)
* fix(deps): update dependency @changesets/cli to ^2.31.1
* chore(deps): exempt @changesets/cli and refresh lockfile with dedupe
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
chore(deps): update dependency @vitejs/devtools to ^0.4.1 (#1593)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
Version Packages (#1591)
chore(deps): dedupe pnpm-lock.yaml (#1602)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(media): use useMediaIndex so Tags panel works on wide viewports (#1592)
The home-rolled useBreakpointIndex returned -1 above 1920px, which
force-hid the Tags panel. Switch Items to @sanity/ui's useMediaIndex,
which includes a min-width catch-all and matches Controls breakpoints.
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
fix(deps): update dependency xstate to ^5.32.5 (#1597)
* fix(deps): update dependency xstate to ^5.32.5
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency tsdown to ^0.22.8 (#1596)
* fix(deps): update dependency tsdown to ^0.22.8
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @sanity/tsconfig to ^2.2.1 (#1595)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): update actions/setup-node action to v7 (#1586)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): update pnpm to v11 (#1579)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency nanoid to v6 (#1577)
* fix(deps): update dependency nanoid to v6
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency groq to ^6.5.0 (#1523)
* fix(deps): update dependency groq to ^6.5.0
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
Migrate plugin-kit and the monorepo from prettier/eslint to oxfmt/oxlint (#1565)
* Migrate plugin-kit and monorepo formatting from prettier to oxfmt
- Ship the monorepo's oxfmt settings as a @sanity/plugin-kit/oxfmt preset
- Re-export the preset from the root oxfmt.config.ts (replaces .oxfmtrc.json)
- init/inject scaffold oxfmt (config, devDependency, format script) instead
of prettier; --no-prettier is now --no-oxfmt
- verify-package: replace the duplicate-prettier-config check with a
monorepo-aware oxfmt check that expects the config at the workspace root
(or next to package.json outside monorepos) and flags leftover prettier
configuration with migration instructions
* Migrate plugin-kit and monorepo linting from eslint to oxlint, drop tsc
- Ship the monorepo's oxlint settings as @sanity/plugin-kit/oxlint-config.json
(type-aware rules, type checking via oxlint-tsgolint, warnings denied); the
root .oxlintrc.json extends it and keeps only workspace-specific ignores and
overrides
- init/inject scaffold oxlint (.oxlintrc.json, oxlint + oxlint-tsgolint
devDependencies, lint script) instead of eslint; --no-eslint is now
--no-oxlint, and the typescript flag now controls TypeScript scaffolding
instead of piggybacking on the eslint flag
- verify-package: drop the tsc run (oxlint type-checks as part of linting) and
the duplicate-eslint-config check; add a monorepo-aware oxlint config check
with legacy eslint detection; the v2-imports check (eslintImports -> imports)
now runs a bundled oxlint pass instead of the package's eslint
- pin typescript in dev/test-studio so the sanity peer keeps resolving to the
catalog version now that plugin-kit no longer pulls eslint/typescript peers
* Pin oxlint imports-check output format so CI matches snapshots
oxlint auto-switches to GitHub annotations format on CI; --format=agent keeps
the compact per-diagnostic output (including help: messages) everywhere
* Ship the oxlint config as @sanity/plugin-kit/oxlint (oxlint.config.ts pattern)
Replaces the oxlint-config.json + .oxlintrc.json extends-by-file-path setup
with a TS config module, mirroring the oxfmt preset: the shared config is
authored in src/oxlint.ts (typed OxlintConfig, built to plain JS in dist), the
root and scaffolded configs are oxlint.config.ts files that re-export or extend
it via defineConfig({extends: [...]})
* Drop the Sanity v2 imports check from verify-package/verify-studio
v2-era imports are no longer linted for; with the bundled oxlint pass gone,
oxlint moves from a runtime dependency of plugin-kit to a dev/peer dependency
(it is only needed by consumers, which the scaffolding already installs)
* Address Bugbot review: opt-out scaffolds must verify, root legacy configs detected
- init/inject with --no-oxfmt/--no-oxlint now write the matching
sanityPlugin.verifyPackage opt-outs, so the scaffolded build script
(which runs verify-package) works out of the box
- the oxfmt/oxlint checks now also flag leftover prettier/eslint configs at
the detected workspace root, not only next to the plugin's package.json
* Scaffold ESM semver-workflow configs so fresh presets pass oxlint
The preset's lint-staged.config.js and commitlint.config.js templates
still used module.exports, but scaffolded plugins are ESM
("type": "module") and the shared oxlint config bans CommonJS via
import/no-commonjs (the old .eslintignore that excluded these files is
gone). A fresh 'init --preset semver-workflow' failed 'oxlint' out of
the box; switch the templates to 'export default' and cover the preset
configs in the inject test.
* Validate package-local oxfmt/oxlint configs that override the workspace root
verify-package treated a valid workspace-root config as sufficient and only
looked at the plugin directory when the root check failed. But oxfmt/oxlint
discover nested configs, so a local oxfmt.config.ts / oxlint.config.ts
overrides the root for that package's files — verify could pass while the
package wasn't actually using the shared plugin-kit settings.
In a monorepo the validators now check the plugin directory first: when a
local config exists it must use the shared preset/config (the error notes it
overrides the root config), and only when no local config exists does the
workspace root config decide the result.
* Flag legacy prettier/eslintConfig keys in the workspace root package.json
The oxfmt/oxlint checks scanned the workspace root for leftover
prettier/eslint config files but only looked at the plugin's own
package.json for the prettier / eslintConfig keys. In monorepos those
keys often live in the root package.json, where they still configure
the whole workspace — verify-package now inspects the root manifest
too and reports them alongside the legacy config files.
* Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* Move oxfmt, oxlint and oxlint-tsgolint to the pnpm catalog
plugin-kit's oxfmt/oxlint peers now reference the default catalog
(catalog:) rather than catalog:peer or explicit ranges: the shared
configs may rely on rules and features that ship in a new minor, so
the peer range must stay in lockstep with the version the monorepo
develops against.
* Mark oxfmt/oxlint as optional peer dependencies of plugin-kit
Unlike @sanity/pkg-utils (a hard requirement, checked unconditionally
by verify-package), the oxfmt/oxlint verify-package checks are
individually opt-outable via sanityPlugin.verifyPackage.oxfmt/oxlint:
false, and plugin-kit's own code only ever imports their types. So a
consumer can legitimately use plugin-kit without oxfmt or oxlint
installed; peerDependenciesMeta now reflects that.
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
chore(deps): bump sanity to 6.5.0 and enable unstable_bundledDev (#1589)
* chore(deps): bump sanity to 6.5.0 and enable bundledDev
Align @sanity/client (7.23.2) and @sanity/eventsource (5.0.4) so
unstable_bundledDev can be enabled without EventSource2 crashes in Structure.
* chore(markdown): sync inlined @sanity/client to 7.23.2
* chore(deps): drop client/eventsource overrides after lockfile bump
Keep @sanity/client@7.23.2 and @sanity/eventsource@5.0.4 via the
lockfile after pnpm dedupe; remove the temporary overrides and markdown
changeset.
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
chore(deps): dedupe pnpm-lock.yaml (#1585)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): update dependency @vitejs/devtools to ^0.4.0 (#1578)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @sanity/pkg-utils to ^11.0.3 (#1582)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
Remove redundant `dts` option from tsdown configs (#1567)
* Remove redundant dts option from tsdown configs
Since typescript v7 (tsgo) landed, tsdown enables dts generation
automatically (packages declare types, or the resolved tsconfig sets
declaration: true) and rolldown-plugin-dts picks the tsgo generator
whenever the installed typescript major is >= 7. The explicit
dts: {tsgo: true} / dts: true options are therefore no-ops.
Verified: dist output across all 50 packages is byte-identical
before/after this change.
Co-authored-by: Cody Olsen <stipsan@users.noreply.github.com>
* Mention tsconfig declaration fallback in AGENTS.md dts note
Not all packages declare a types field (@repo/generators,
@sanity/form-toolkit); for those, tsdown enables dts generation via
declaration: true inherited from the @sanity/tsconfig presets.
Co-authored-by: Cody Olsen <stipsan@users.noreply.github.com>
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Cody Olsen <stipsan@users.noreply.github.com>
fix(deps): update dependency @sanity/tsdown-config to ^0.14.2 (#1583)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore: simplify, rely on default options
fix(deps): update build tooling dependencies (#1580)
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Version Packages (#1572)
chore(deps): dedupe pnpm-lock.yaml (#1575)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @tanstack/react-virtual to ^3.14.6 (#1573)
* fix(deps): update dependency @tanstack/react-virtual to ^3.14.6
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @sanity/icons to ^5.1.0 (#1574)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): update renovatebot/github-action action to v46.1.19 (#1570)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
Prevent Renovate from rewriting pnpm `peer` catalog ranges (#1568)
fix(deps): update tsdown to ^0.22.7 and @sanity/tsdown-config to ^0.14.0 (#1571)
Version Packages (#1563)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
Add pnpm `peer` catalog for peer dependency ranges (#1562)
Centralize all external peerDependencies ranges in a named `peer` catalog
in pnpm-workspace.yaml, referenced as `catalog:peer`. Conflicting ranges
resolve to the most-used one: react/react-dom `^19.2` and
styled-components `^6.1` (aligning sanity-plugin-media and
sanity-plugin-mux-input with what Sanity Studio v5+ already requires).
Peers on other workspace packages keep `workspace:^` (or an explicit
range in @sanity/sfcc) so changesets can keep tracking dependents.
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Version Packages (#1558)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
feat: enable React Compiler for media and mux-input (#1560)
* feat: enable React Compiler for media, mux-input and debug-preview-url-secret-plugin
Enables the reactCompiler tsdown option for the last three plugins that
were still built without it. For sanity-plugin-media and
sanity-plugin-mux-input the react peer dependency is tightened to ^19.2
(matching every other plugin) since the compiled output imports
react/compiler-runtime, which requires React 19. Their sanity peer
(^5 || ^6.0.0-0) already mandates React 19.2, so no supported setup is
dropped.
* chore: don't enable React Compiler for debug-preview-url-secret-plugin
This plugin has no React components, so running the build through React
Compiler is a no-op (its dist output is byte-identical with or without
it). Drop the reactCompiler flag, the babel-plugin-react-compiler devDep,
and the changeset; keep the change limited to the two plugins that
actually ship components (media and mux-input).
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Handle TS7 `@typescript-eslint` config crashes in plugin-kit import validation (#1561)
* Initial plan
* fix(plugin-kit): fallback eslint import check for TS7 parser crash
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
fix(deps): update dependency typescript to v7 (#1531)
* fix(deps): update dependency typescript to v7
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
refactor: simplify how the PKG_VERSION is handled in mjux
Version Packages (#1556)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): dedupe pnpm-lock.yaml (#1557)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update sanity monorepo to ^6.4.0 (#1555)
Bumps the workspace catalog (@sanity/mutator, @sanity/schema, @sanity/util, @sanity/vision, sanity) and groq in sanity-plugin-media from ^6.3.0 to ^6.4.0.
- mux-input: replace the DocumentPreviewLink render-function workaround with IntentLink passed directly to PreviewCard's as prop, dropping the FIXME cast and the react-compiler lint suppression.
- orderable-document-list: keep using useDocumentVersionInfo (the useDocumentVersions replacement would need the unexported getDocumentVersionInfoFromVersions util) with an oxlint suppression for the new deprecation, and drop a ts-expect-error made obsolete by the 6.4.0 PreviewCard typings.
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Version Packages (#1527)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
feat!: support TypeScript 7 in plugin-kit, require typescript 6.x || 7.x (#1554)
* feat!: support TypeScript 7, require typescript 6.x || 7.x in plugin-kit
* fix: scaffold typescript ^6 in plugin-kit init to avoid @typescript-eslint peer conflict
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
chore(deps): ts doesn't need to be a dep to plugin packages
fix(deps): update turbo monorepo to v2.10.4 (#1543)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): dedupe pnpm-lock.yaml (#1552)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @sanity/tsdown-config to ^0.13.1 (#1551)
fix(deps): update dependency vitest to ^4.1.10 (#1542)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @uiw/react-codemirror to ^4.25.11 (#1540)
* fix(deps): update dependency @uiw/react-codemirror to ^4.25.11
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @sanity/pkg-utils to ^11.0.1 (#1550)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): dedupe pnpm-lock.yaml (#1549)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update linters (#1548)
* fix(deps): update linters
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency get-it to ^9.1.0 (#1546)
* fix(deps): update dependency get-it to ^9.1.0
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency react-hook-form to ^7.81.0 (#1547)
* fix(deps): update dependency react-hook-form to ^7.81.0
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): update dependency knip to ^6.26.0 (#1545)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): update dependency @tsconfig/vite-react to ^8.1.1 (#1544)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency iso-639-1 to ^3.1.6 (#1541)
* fix(deps): update dependency iso-639-1 to ^3.1.6
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @uiw/codemirror-themes to ^4.25.11 (#1539)
* fix(deps): update dependency @uiw/codemirror-themes to ^4.25.11
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @types/node to ^24.13.3 (#1538)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @tanstack/react-virtual to ^3.14.5 (#1536)
* fix(deps): update dependency @tanstack/react-virtual to ^3.14.5
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): dedupe pnpm-lock.yaml (#1537)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @tanstack/react-query to ^5.101.2 (#1535)
* fix(deps): update dependency @tanstack/react-query to ^5.101.2
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): update pnpm to v10.34.5 (#1533)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @portabletext/block-tools to ^5.1.11 (#1534)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): dedupe pnpm-lock.yaml (#1532)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency tsdown to ^0.22.4 (#1519)
* fix(deps): update dependency tsdown to ^0.22.5
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @sanity/tsdown-config to ^0.13.0 (#1529)
fix(deps): update dependency @vanilla-extract/vite-plugin to ^5.2.4 (#1517)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @sanity/pkg-utils to v11 (#1530)
fix(deps): update dependency react-virtuoso to ^4.18.10 (#1518)
* fix(deps): update dependency react-virtuoso to ^4.18.10
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): update dependency knip to ^6.25.0 (#1520)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): dedupe pnpm-lock.yaml (#1526)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency react-icons to ^5.7.0 (#1486)
* fix(deps): update dependency react-icons to ^5.7.0
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @sanity/pkg-utils to ^10.9.1 (#1515)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): dedupe pnpm-lock.yaml (#1502)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
Merge pull request #1524 from sanity-io/actions/format-main
chore(format): 🤖 ✨
fix(deps): update dependency @sanity/tsdown-config to ^0.12.0 (#1521)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency oxfmt to ^0.58.0 (#1522)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @sanity/ui to ^3.3.5 (#1516)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): update renovatebot/github-action action to v46.1.18 (#1505)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(typegen): 🤖 ✨ (#1511)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore: disable automatic issue triage (#1514)
* chore: disable automatic issue triage
Version Packages (#1504)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
Merge pull request #1513 from sanity-io/cursor/orderable-intent-repro-1506-bf83
fix(orderable-document-list): scope canHandleIntent to list's own type (#1506)
test(test-studio): reframe issue #1506 repro as regression fixture
Now that canHandleIntent is scoped to the list's own type, update labels
and comments to describe regression verification rather than active repro.
chore: remove repro step, add fix
test(test-studio): add repro case for orderable-document-list issue #1506
Add dedicated schema types and structure section that mirrors the issue
report: a regular document list alongside an orderable list at the same
level. Creating a Page via the global create menu incorrectly routes into
the Team Members orderable list due to canHandleIntent claiming all types.
Includes REPRO.md with step-by-step verification instructions.
Add orderable document list readme (#1508)
fix(deps): update dependency react-rx to ^4.2.3 (#1493)
* fix(deps): update dependency react-rx to ^4.2.3
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @codemirror/view to ^6.43.5 (#1500)
* fix(deps): update codemirror
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
Version Packages (#1496)
chore(deps): update linters (#1499)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(@sanity/assist): render instruction preview icons from @sanity/icons v5 (#1503)
The instruction schema's prepare() returns a rendered <Icon symbol> element
for instructions with a custom icon (since the icons v5 lazy-map migration),
but the preview component still rendered props.icon as a component, crashing
the instruction list with 'Element type is invalid ... got: <Icon />'.
Handle both the element and the component (SparklesIcon fallback) shapes.
Also add a README troubleshooting section for MISSING_EXPORT icon build
errors, which come from code importing icons from the @sanity/icons package
root - a pattern removed in v5 (the plugin itself already uses the per-icon
export paths).
Fixes #1495
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Cody Olsen <stipsan@users.noreply.github.com>
fix(deps): update dependency @sanity/ui to ^3.3.1 (#1498)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @sanity/preview-url-secret to ^4.0.8 (#1492)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @vis.gl/react-google-maps to ^1.9.0 (#1501)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): dedupe pnpm-lock.yaml (#1497)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency xstate to ^5.32.4 (#1494)
* fix(deps): update dependency xstate to ^5.32.4
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
Upgrade oxlint-tsgolint to ^0.24.0 and fix new lint findings (#1476)
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Version Packages (#1489)
refactor: move all plugins and packages to tsdown (#1491)
refactor: move dbeug-live-sync-tags to tsdown (#1490)
Version Packages (#1487)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): dedupe pnpm-lock.yaml (#1488)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
Remove isolatedDeclarations and collapse to one tsconfig per plugin (#1460)
* Remove isolatedDeclarations and use a single tsconfig per plugin
Drop the @sanity/tsconfig/isolated-declarations preset from the shared
@repo/tsconfig/build.json (now removed) and @repo/package.config, and
delete every per-plugin tsconfig.build.json. @sanity/pkg-utils now builds
declarations from each plugin's single tsconfig.json; dts: 'rolldown' is
kept, so isolated declarations can be re-adopted later by re-adding the
preset.
Co-authored-by: Cody Olsen <stipsan@users.noreply.github.com>
* Scaffold a single tsconfig in the plugin generator
Remove the isolatedDeclarations prompt and the tsconfig.build.json
scaffolding action from both generators, and delete the now-unused
tsconfig.build.json.hbs template.
Co-authored-by: Cody Olsen <stipsan@users.noreply.github.com>
* Drop tsconfig.build.json from plugin-transfer docs
Co-authored-by: Cody Olsen <stipsan@users.noreply.github.com>
* Add changesets for plugins with regenerated declarations
Patch bumps for the 8 published packages whose dist declaration output
(.d.ts and/or .d.ts.map) changed when dts generation moved off
isolatedDeclarations. The differences are cosmetic (quote style, JSDoc
indentation, union member order); runtime JS is unchanged.
* Remove @repo/tsconfig and extend @sanity/tsconfig/strictest directly
With a single tsconfig per plugin the @repo/tsconfig wrapper package no
longer earns its keep. Each plugin now extends @sanity/tsconfig/strictest
directly and sets customConditions: ['development'] inline (temporarily
needed until the planned move to tsdown, which handles dev conditions
differently). Swaps the @repo/tsconfig workspace devDependency for
@sanity/tsconfig (catalog) in all 48 packages and updates the generator
templates and knip config. Built dist output is byte-identical.
* Generate declarations with tsgo
Enable the tsgo pipeline (@typescript/native-preview) in
@repo/package.config, the same engine oxlint's type-check runs on.
tsgo requires inferred exported types to be portable (TS2883), so a few
sites gain explicit annotations: the xstate form machine in
sanity-plugin-dashboard-widget-vercel, the schema test fixtures in
sanity-naive-html-serializer, and the render helper in
sanity-plugin-media's tests. Documents the TS2883 failure mode in
AGENTS.md.
* Add changesets for tsgo-regenerated declarations
Unifies the earlier isolatedDeclarations changesets and adds patch bumps
for the 21 additional published packages whose dist declaration output
changed when dts generation switched to tsgo (cosmetic quote-style and
union-ordering differences only).
* Relax minimumReleaseAge to the pnpm v11 default
Drops the release-age gate from 3 days to pnpm v11's default of 1440
minutes (1 day), unblocking resolution of @vitejs/devtools releases the
test studio tracks closely.
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Cody Olsen <stipsan@users.noreply.github.com>
Version Packages (#1484)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(@sanity/assist): open icon picker reliably with lazy-loaded icons (#1485)
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
chore(deps): update dependency @vitejs/devtools to ^0.3.4 (#1479)
* chore(deps): update dependency @vitejs/devtools to ^0.3.4
* chore: dedupe lockfile with pnpm
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
fix(deps): update dependency motion to ^12.42.2 (#1480)
* fix(deps): update dependency motion to ^12.42.2
* chore(deps): changeset for dependency update
* chore: run pnpm dedupe for motion update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Version Packages (#1483)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @vanilla-extract/css to ^1.21.1 (#1477)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
Add changesets for plugins using styledComponents tree-shaking upgrade (#1478) (#1481)
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
fix: update icon lazy loading
fix(deps): update dependency @sanity/icons to v5 (#1482)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @sanity/pkg-utils to ^10.9.0 (#1478)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
Version Packages (#1473)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency typescript to v6 (#1474)
* fix(deps): update dependency typescript to v6
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(document-internationalization): enable creating language copies for documents in releases (#1475)
* fix(document-internationalization): enable translations for documents in releases
When …
Knip flagged 12 types re-exported from the react-color barrel that nothing
outside the module imports. Keep only the types consumers actually use.
Merge branch 'cursor/ban-react-class-components-ca2a' into cursor/color-input-vanilla-extract-35df
Keep vanilla-extract styling for Alpha/Hue/Saturation/EditableInput;
ban branch still uses styled-components/inline styles for those files.
fix(color-input): convert vendored react-color components to function components
Convert Alpha/Hue/Saturation/EditableInput and centralize drag wiring in a
shared useDrag hook: a native mousedown listener attached in useLayoutEffect,
useEffectEvent so events always read the latest props, and per-gesture
mousemove/mouseup listeners cleaned up via AbortController. EditableInput
clears its pending blur-sync value once the prop catches up with the
displayed value, so blurring can't revert a typed value.
fix(sanity-plugin-media): convert ReduxProvider to a function component
Initialize the redux store once with a lazy useState initializer.
fix(orderable-document-list): convert OrderableDocumentList to a function component
Expose the structure menu actionHandlers via useImperativeHandle and the
React 19 ref-as-prop pattern, with a dependency list so the handle is not
re-created on every render (the pane stores it in state).
feat(plugin-kit): ban Component, PureComponent and createRef imports from react
Class components are not allowed in this repo — only function components.
createRef is only useful in class components; use the useRef hook instead.
Also point skill docs at the shared @sanity/plugin-kit/oxlint config.
chore: drop color-input oxlint override
Leave shared oxlint rules untouched; the vanilla-extract migration does
not need a package-specific no-restricted-imports lock-in.
Merge branch 'cursor/ban-react-class-components-ca2a' into cursor/color-input-vanilla-extract-35df
Resolve stack conflicts: keep vanilla-extract exports (drop EditableInputStyles),
bump @vanilla-extract/css catalog to ^1.21.2 while retaining @vanilla-extract/dynamic,
and regenerate the lockfile. Preserve EditableInput blur-sync fix from the base branch.
Version Packages (#1735)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
refactor(color-input): migrate styling to vanilla-extract
Replace styled-components and inline style objects with colocated
vanilla-extract stylesheets, using assignInlineVars for dynamic
theme/color values. Builds on the function-component + useDrag
refactor from the ban-react-class-components branch.
Merge remote-tracking branch 'origin/main' into cursor/ban-react-class-components-ca2a
fix(color-input): clear stale blur-sync value when prop catches up
The prop-sync effect early-returned when the normalized prop matched the
displayed value, leaving a blurValue captured from an older prop in place;
blurring would then restore that older value. Clear it (in a transition to
satisfy the React Compiler EffectSetState rule).
fix(deps): bump @sanity/pkg-utils, @sanity/tsdown-config and vanilla-extract plugins (#1769)
* fix(deps): bump @sanity/pkg-utils, @sanity/tsdown-config and vanilla-extract plugins
- @sanity/pkg-utils ^11.0.16 -> ^11.0.17
- @sanity/tsdown-config ^0.21.1 -> ^0.21.2
- @sanity/vanilla-extract-vite-plugin ^0.2.7 -> ^0.2.8
tsdown (^0.22.14) and @vanilla-extract/css (^1.21.2) were already on the
latest release; refreshing the lockfile picks up the transitive
@sanity/vanilla-extract-{integration,rolldown-plugin,tsdown-plugin} updates.
* fix(deps): public-hoist @vanilla-extract/css so node_modules .css.js files resolve it
`@sanity/vanilla-extract-vite-plugin` filters its transform hook on
/\.css\.(js|cjs|mjs|jsx|ts|tsx)/ with no node_modules exclusion, so it also
compiles `@bynder/compact-view/Styles.css.js` — a plain module exporting a CSS
string for a shadow root, not a vanilla-extract module. That package declares no
dependencies, so the compile only finds `@vanilla-extract/css/adapter` when pnpm
happens to hoist it into the hidden .pnpm/node_modules directory. On Vercel it
did not, failing `sanity build` for dev/test-studio with
"Cannot find module '@vanilla-extract/css/adapter'".
Public-hoisting puts @vanilla-extract/css on the root node_modules resolution
path, which is deterministic regardless of the implicit hoist layout.
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
chore(deps): dedupe pnpm-lock.yaml (#1766)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @sanity/pkg-utils to ^11.0.16 (#1768)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
feat(test-studio): add experimental @sanity/themer tool (#1738)
* feat(test-studio): add experimental @sanity/themer tool
Wire themerTool() into the Home workspace so theme presets and colors
can be previewed live against the plugins kitchen sink.
* chore(test-studio): bump @sanity/themer to 0.2.0
* chore(test-studio): use ^0.2.0 for @sanity/themer
Merge main and widen the themer dependency to a caret range.
* chore: dedupe lockfile to resolve @sanity/client type mismatch
pnpm dedupe collapses the 7.24.0 / 7.25.0 client split that broke
type-aware lint after merging main with themer.
* chore: handle lockfile
* chore(knip): ignore unused catalog entry reports in pnpm-workspace.yaml
The catalogued @sanity/types entry is referenced only by the overrides block
in pnpm-workspace.yaml, which knip does not read, so it was reported as an
unused catalog entry and failed `pnpm knip`.
Co-authored-by: Cursor <cursoragent@cursor.com>
* chore: fix lock
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
fix(deps): update dependency @vanilla-extract/css to ^1.21.2 (#1764)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): update renovatebot/github-action action to v46.1.21 (#1763)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @sanity/ui to ^3.5.0 (#1762)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): dedupe pnpm-lock.yaml (#1761)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
test(document-internationalization): expand Vitest + Playwright e2e coverage (#1712)
chore(deps): dedupe pnpm-lock.yaml (#1754)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): update dependency @playwright/test to ^1.62.0 (#1760)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update turbo monorepo to v2.10.7 (#1759)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency concurrently to ^10.0.4 (#1758)
* fix(deps): update dependency concurrently to ^10.0.4
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @portabletext/plugin-input-rule to ^6.0.10 (#1757)
* fix(deps): update dependency @portabletext/plugin-input-rule to ^6.0.10
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): update dependency @vitejs/devtools to ^0.4.8 (#1756)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): update dependency @portabletext/editor to ^7.10.13 (#1755)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): lock file maintenance (#1749)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore: fix lockfile
chore(deps): dedupe pnpm-lock.yaml (#1753)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @sanity/client to ^7.25.0 (#1747)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @sanity/ui to ^3.4.5 (#1745)
* fix(deps): update dependency @sanity/ui to ^3.4.5
* fix(knip): remove unused react-is devDependency from media plugin
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
fix(deps): update dependency @mux/mux-player to ^3.13.2 (#1751)
* fix(deps): update dependency @mux/mux-player to ^3.13.2
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): dedupe pnpm-lock.yaml (#1748)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency react-hook-form to ^7.83.0 (#1750)
* fix(deps): update dependency react-hook-form to ^7.83.0
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @mux/mux-player-react to ^3.13.2 (#1752)
* fix(deps): update dependency @mux/mux-player-react to ^3.13.2
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @sanity/preview-url-secret to ^4.1.2 (#1744)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): dedupe pnpm-lock.yaml (#1734)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
Delete dependencies-GH-1739.md
fix(deps): update dependency @sanity/color to ^3.0.8 (#1743)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @sanity/vanilla-extract-vite-plugin to ^0.2.7 (#1746)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @sanity/tsdown-config to ^0.21.1 (#1742)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @sanity/pkg-utils to ^11.0.15 (#1741)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): update zizmorcore/zizmor-action action to v0.6.1 (#1740)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency tsdown to ^0.22.14 (#1739)
* fix(deps): update dependency tsdown to ^0.22.14
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): update actions/cache action to v6 (#1731)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): update dependency @playwright/test to ^1.61.1 (#1737)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @sanity/tsdown-config to ^0.21.0 (#1736)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @sanity/vanilla-extract-vite-plugin to ^0.2.6 (#1733)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @sanity/pkg-utils to ^11.0.14 (#1732)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): update actions/cache action to v5 (#1730)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update turbo monorepo to v2.10.6 (#1729)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @tanstack/react-virtual to ^3.14.8 (#1728)
* fix(deps): update dependency @tanstack/react-virtual to ^3.14.8
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): update dependency knip to ^6.29.0 (#1727)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): update dependency @vitejs/devtools to ^0.4.5 (#1726)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
feat: add Playwright smoke e2e with ephemeral datasets (#1710)
* feat: add Playwright smoke e2e for test studio
Set up an e2e workspace with Chromium/Firefox smoke coverage,
storageState studio auth matching sanity-io/sanity, fail-fast
token validation, and a CI workflow that builds and previews
the test studio locally.
* fix(e2e): correct Playwright artifact gitignore paths
Paths in e2e/.gitignore are relative to that directory, so leading
/e2e/… never matched results or playwright-report.
* fix(e2e): require project id and dataset from env vars
Source SANITY_E2E_PROJECT_ID and SANITY_E2E_STUDIO_DATASET from
GitHub repository variables in CI (no hardcoding). Rename the
dataset env to SANITY_E2E_STUDIO_DATASET and map both onto the
test-studio SANITY_STUDIO_* vars when starting webServer.
* fix(e2e): stop knip from loading Playwright config
resolveE2eEnv() requires project id and dataset at config load time;
disable the knip Playwright plugin for the e2e workspace so analysis
does not need CI secrets.
* fix(e2e): drop token fallback and debug browser filter
Require only SANITY_E2E_SESSION_TOKEN for auth, and always run
Chromium and Firefox projects (filter via Playwright UI/CLI instead).
* docs(e2e): document plugins-e2e-testing sandbox project
Note that e2e uses Sanity sandbox org project plugins-e2e-testing
(a1psl692) and update .env.example accordingly.
* ci(e2e): post Sanity-style PR status comment
Add a Playwright summary reporter and update the E2E workflow to
post/refresh a pull request comment with pass/fail/flaky/skipped
counts and a link to the Actions run (HTML report as artifact until
Vercel report hosting lands).
* ci(e2e): deploy Playwright HTML report to Vercel
Host the report on a dedicated Vercel project and link pass/fail
counts in the PR status comment, matching sanity-io/sanity. Document
VERCEL_E2E_REPORT_* secret setup in e2e/README.md.
* feat(e2e): add ephemeral per-browser datasets like sanity-io/sanity
Create pr-*/main-* chromium and firefox datasets in CI, expose matching
studio workspaces, and schedule cleanup for closed PRs / stale main runs.
* fix(e2e): bump Sanity client apiVersion to 2026-07-23
* fix(ci): avoid env context in job-level e2e workflow env
GitHub Actions does not allow `env.*` when evaluating job `env:` maps.
Define dataset names at workflow level with inlined format expressions.
* ci(e2e): run chromium and firefox as a parallel matrix
Split setup / per-browser test / report-merge jobs. Each matrix job gets
its own SANITY_E2E_DATASET and runs playwright --project for that browser.
* fix(e2e): avoid pnpm setup command colliding with dataset script
`pnpm --filter e2e setup` invoked pnpm's built-in `setup`, so ephemeral
datasets were never created. Rename to `create-dataset` and call via
`pnpm run`. Fail the CI step if creation fails.
* ci(e2e): scope pull-requests write to jobs that post comments
Satisfy zizmor excessive-permissions: keep workflow at contents:read
and grant pull-requests:write only on setup/report jobs.
* ci(e2e): deploy studio preview to Vercel like sanity-io/sanity
Add deploy-preview job (vercel pull/build/deploy --prebuilt) with
ephemeral datasets baked in; matrix tests run against the preview URL
instead of a local sanity preview server. Adds vercel CLI as a root
devDependency and dev/test-studio/vercel.json build settings.
* ci(e2e): reuse VERCEL_E2E_REPORT_* secrets for the studio preview
The studio preview deploys with the same Vercel project/token as report
hosting, so only one set of Vercel secrets is required.
* fix(e2e): add SPA fallback rewrite to test-studio vercel.json
The deployed studio 404'd on /chromium and /firefox workspace routes,
so the studio never booted and globalSetup timed out waiting for
/users/me. Rewrite all paths to index.html (filesystem first), same as
sanity-io/sanity's studio deployments.
* fix(e2e): drop studio warm-up from globalSetup
The warm-up existed to pay the local dev-server cold-compile cost once
up front; CI now tests a deployed static studio, and the waitForResponse
race was flaky there. Keep the fast env + auth token preflight.
* feat(e2e): dedicated bare e2e-studio with chromium/firefox workspaces
Add dev/e2e-studio — a minimal studio used only by Playwright e2e:
structure tool, one smoke-test schema type, and per-browser workspaces
on the ephemeral datasets. No monorepo plugins yet; each plugin will be
added together with its e2e tests. Reverts the e2e wiring from
dev/test-studio so it stays a pure development studio.
* fix(e2e): address review feedback
- Create ephemeral datasets as private (tests auth via storageState)
- Add contents:read to the periodic cleanup workflow for checkout
- Strip all leading dashes in sanityIdify
- Fix stale e2e package description and report-hosting docs (shared
Vercel project, not a dedicated one)
* fix(e2e): keep ephemeral datasets public like sanity-io/sanity
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Make test-studio typegen idempotent in CI by forcing schema overwrite (#1725)
* Initial plan
* fix(test-studio): force schema extract during typegen
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
chore(deps): dedupe pnpm-lock.yaml (#1724)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
Version Packages (#1718)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @portabletext/plugin-input-rule to ^6.0.8 (#1723)
* fix(deps): update dependency @portabletext/plugin-input-rule to ^6.0.9
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): update dependency @types/google.maps to ^3.65.3 (#1722)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): update dependency @portabletext/editor to ^7.10.11 (#1721)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
Delete .changeset/dependencies-GH-1697.md
Delete .changeset/dependencies-GH-1692.md
fix(deps): update dependency @sanity/icons to ^5.2.1 (#1720)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency oxfmt to ^0.60.0 (#1697)
* fix(deps): update dependency oxfmt to ^0.60.0
* chore(deps): changeset for dependency update
* chore: dedupe lockfile with release age exemptions
* fix: resolve knip unused export errors
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
fix(deps): update dependency @testing-library/jest-dom to v7 (#1679)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update react monorepo to ^19.2.8 (#1692)
* fix(deps): update react monorepo to ^19.2.8
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
chore(deps): update dependency @vitejs/devtools to ^0.4.3 (#1704)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @tanstack/react-query to ^5.101.4 (#1706)
* fix(deps): update dependency @tanstack/react-query to ^5.101.4
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
feat(plugin-kit)!: require Node.js 24 and bump held-back CLI deps (#1696)
* feat(plugin-kit)!: require Node.js 24 and bump held-back CLI deps
- engines.node: >=20.19 <22 || >=22.12 -> >=24 (plugin-kit CLI only;
scaffolded/verified plugins keep the wider pkg-utils range)
- concurrently ^9 -> ^10, execa ^9 -> ^10, inquirer ^12 -> ^14 (all
previously held back by the permissive engine range)
- migrate the choices prompt from the 'list' type (removed in
inquirer 13) to 'select'
* fix(plugin-kit): report failed dependency install with the intended hint
execa rejects on non-zero exit, so the exitCode check in
installDependencies was unreachable and init surfaced npm/pnpm install
failures as an unhandled CLI error. Pass reject: false so the caller's
'Failed to install dependencies, try manually running `npm install`'
message is shown instead.
* refactor(plugin-kit): replace several deps with Node 24 builtins and local helpers
Drop chalk, get-it, git-remote-origin-url, github-url-to-object, xdg-basedir,
email-validator, p-props and outdent in favor of util.styleText, fetch, execa+git,
and small local helpers. All remaining CLI deps were already at latest.
* fix(plugin-kit): address review feedback on execa, styleText, and outdent
- catch spawn errors in installDependencies and git remote lookup
- join nodemon's files array before styleText (it requires a string)
- only strip spaces/tabs in outdent so under-indented lines keep content
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
fix(deps): upgrade Sanity monorepo to ^6.6.0 (#1717)
* fix(deps): upgrade Sanity monorepo to ^6.6.0
Bump catalog packages (sanity, @sanity/mutator/schema/util/vision) and
sanity-plugin-media's groq dependency. Map TARGET_NOT_FOUND to Sanity's
structure locale key for missing release/variant documents instead of
reusing the not-ready tooltip.
* fix(deps): force-dedupe Sanity monorepo packages to 6.6.0
Override transitive @sanity/types|mutator|schema|util and groq onto the
catalog version so the lockfile cannot keep a second 6.5.x copy (which
breaks media dts emit). Put groq in the catalog and document the upgrade
checklist in AGENTS.md.
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
fix(deps): update dependency @sanity/color to ^3.0.7 (#1716)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
feat(test-studio): enable React profiling on Vercel preview builds (#1713)
* feat(test-studio): enable React profiling on Vercel preview builds
Alias react-dom/client to react-dom/profiling when VERCEL_ENV is preview,
matching the Sanity monorepo test-studio setup, so PR deployments can be
profiled without imposing that overhead on production.
* fix(test-studio): disable auto-updates on preview for profiling
Auto-updates vendor builds hardcode react-dom-client.production.js, which
bypasses the react-dom/profiling alias. Turn auto-updates off when
VERCEL_ENV is preview so React DevTools profiling works on PR deployments.
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
fix(deps): update dependency @sanity/preview-url-secret to ^4.1.1 (#1714)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): dedupe pnpm-lock.yaml (#1709)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): update dependency @portabletext/editor to ^7.10.10 (#1703)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
Version Packages (#1708)
fix(deps): update dependency @portabletext/plugin-input-rule to ^6.0.7 (#1705)
Remove @sanity/styled-components override, move back to styled-components (#1693)
* Remove @sanity/styled-components override, move back to styled-components
* test: give first-mount UI tests timeout headroom on slow CI runners
* test: force styled-components speedy CSS injection under jsdom
Match sanity#13675 by setting SC_DISABLE_SPEEDY=false in the root
Vitest config so upstream styled-components keeps CSSOM injection in
tests. Revert the per-test timeout bumps that papered over the same
jsdom stylesheet reparse slowdown.
* chore: refresh PR head after merging main
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
fix(deps): upgrade oxlint and oxlint-tsgolint to latest (#1707)
Merge pull request #1702 from sanity-io/cursor/bump-sanity-ui-f3da
fix(deps): update dependency @portabletext/block-tools to ^5.1.12 (#1688)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @sanity/ui to ^3.4.3
Bump the catalog range and lockfile to @sanity/ui 3.4.3, and add a
patch changeset for all published plugins that depend on it.
Delete dependencies-GH-1691.md
Version Packages (#1694)
fix(deps): update dependency tsdown to ^0.22.13 (#1691)
* fix(deps): update dependency tsdown to ^0.22.13
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(plugin-kit): bump CLI dependencies to latest compatible majors (#1687)
- chalk ^4 -> ^5, concurrently ^8 -> ^9, execa ^5 -> ^9,
git-remote-origin-url ^3 -> ^4, inquirer ^8 -> ^12, meow ^9 -> ^14,
p-props ^4 -> ^6, xdg-basedir ^4 -> ^5, nodemon 3.1.0 -> 3.1.14
- drop @types/inquirer and @types/nodemon (both packages ship their own
types now)
- add the required meow importMeta option, switch to execa's named
export, use xdg-basedir's named xdgConfig export and
git-remote-origin-url's options object
- restore classic validate-on-filtered-value prompt semantics, which the
modern inquirer rewrite changed (fixes accepting scp-style git remote
URL defaults)
- concurrently 10, execa 10 and inquirer 13+ are held back as they
require Node versions beyond plugin-kit's supported engine range
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Version Packages (#1689)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(typegen): 🤖 ✨ (#1686)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore: add per-plugin changesets for latest @sanity/icons and @sanity/ui catalog bumps (#1684)
* chore: add plugin changesets for @sanity/icons and @sanity/ui bumps
* chore: consolidate icons/ui impacted plugin changesets
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Cody Olsen <81981+stipsan@users.noreply.github.com>
chore(deps): dedupe pnpm-lock.yaml (#1678)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency get-it to ^9.2.0 (#1675)
* fix(deps): update dependency get-it to ^9.2.0
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @sanity/ui to ^3.4.0 (#1677)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
fix(deps): update dependency @sanity/preview-url-secret to ^4.1.0 (#1680)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @sanity/icons to ^5.2.0 (#1676)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix: address review feedback on drag attach timing and imperative handle
- useDrag: attach the mousedown listener in useLayoutEffect so it exists
before paint (matches the previous synchronous JSX onMouseDown wiring).
- OrderableDocumentList: give useImperativeHandle a dependency list so a
new handle object is not installed on every render (the structure pane
stores the handle in state, so per-render handles could loop).
refactor(color-input): extract shared useDrag hook for picker surfaces
Replace the per-component propsRef/AbortController plumbing in
Alpha/Hue/Saturation/EditableInput with a single useDrag hook. It wires a
native mousedown listener via useEffect and keeps callbacks fresh with
useEffectEvent, so drag events always read the latest props. mousemove and
mouseup listeners attach per-gesture and abort on mouseup or unmount.
fix(color-input): address review feedback on drag listeners
- Keep latest props in a ref so window mousemove listeners registered on
mousedown see current values (matches class `this.props` behavior).
- Normalize EditableInput value comparisons to avoid number/string mismatch.
- Correct orderable-document-list changeset wording (ref-as-prop, not forwardRef).
Merge origin/main into cursor/ban-react-class-components-ca2a
Resolve color-input conflicts from #1673 (simplify components, remove
CustomPicker HOC). Main kept Alpha/Hue/Saturation/EditableInput as class
components pending a follow-up conversion; this PR is that follow-up:
- Accept ColorWrap.tsx deletion (HOC replaced by ColorInput state).
- Re-apply function-component conversions on top of main's AbortController
listener cleanup, using useRef instead of createRef.
Version Packages (#1674)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(color-input): simplify components, remove HOC (#1673)
Version Packages (#1668)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): dedupe pnpm-lock.yaml (#1671)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
Migrate sanity-plugin-workflow styling to vanilla-extract (#1450)
* Migrate sanity-plugin-workflow styling to vanilla-extract
* Keep styled-components catalog:devDependency for peer alignment
After the vanilla-extract migration, the peer can go, but the catalog
devDependency must remain so pnpm resolves the workspace
@sanity/styled-components override (same as google-maps-input).
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Merge origin/main into cursor/ban-react-class-components-ca2a
Resolve the modify/delete conflict on .oxlintrc.json: main moved shared
lint rules into @sanity/plugin-kit/oxlint (#1565). Accept the deletion
and port the Component/PureComponent/createRef bans into
packages/@sanity/plugin-kit/src/oxlint.ts alongside the existing
createElement/forwardRef restrictions.
Also rewrite OrderableDocumentList to use React 19 ref-as-prop instead
of forwardRef so it complies with main's forwardRef ban, and update
skill docs that still pointed at .oxlintrc.json.
ci: request workflows permission for typegen app token (#935)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Cody Olsen <81981+stipsan@users.noreply.github.com>
feat(@sanity/plugin-kit)!: remove Studio v2 upgrade and compatibility tooling (#1588)
* feat(@sanity/plugin-kit)!: remove Studio v2 upgrade and compatibility tooling
Drop verify-studio and all verify-package checks that existed to migrate from
or stay compatible with Sanity Studio v2 (incompatible-plugin shim, part:/config:
imports, merged @sanity/* packages, sanity.json parts validation). Package
verification now focuses on current plugin-kit conventions.
* chore(@sanity/plugin-kit): drop unused json5/knip ignores and refresh snapshots
Remove the json5 dependency and readJson5File helper that only served v2
sanity.json parsing, prune stale eslint knip ignoreDependencies, and update
verify-package snapshots after removing v2-upgrade checks.
* fix(@sanity/plugin-kit): address review feedback on path validation and studio detection
Drop the dist-hardcoded path existence check in getPackage entirely: compiled
entry points legitimately don't exist pre-build regardless of outDir, and
verify-package's esmOnly check already bans main/module fields. Also detect
sanity.cli.(js|ts) in findStudioConfig so init/inject refuse cli-config-only
studio directories too.
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
chore(deps): dedupe pnpm-lock.yaml (#1669)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(sanity-plugin-markdown): declare @sanity/client as a regular dependency (#1667)
* fix(sanity-plugin-markdown): declare @sanity/client and rxjs as regular deps
Move @sanity/client and rxjs out of inlinedDependencies into dependencies
so they are resolved at runtime instead of bundled into the package.
* chore: update lockfile for sanity-plugin-markdown deps
* fix(sanity-plugin-markdown): declare @sanity/client as a regular dependency
Move @sanity/client from devDependencies to dependencies so tsdown
externalizes it instead of writing it (and transitive rxjs) to
inlinedDependencies. rxjs is not imported by the plugin and is not
needed as a direct dependency once client is externalized.
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
fix(typegen): 🤖 ✨ (#1666)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @tanstack/react-virtual to ^3.14.7 (#1664)
* fix(deps): update dependency @tanstack/react-virtual to ^3.14.7
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): dedupe pnpm-lock.yaml (#1665)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
Version Packages (#1663)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
feat: add @sanity/block-insert-picker (#1601)
* feat(block-insert-picker): add @sanity/block-insert-picker
Slash-command block-insert picker and markdown input rules for Portable
Text fields, extracted from the sanity-io/www-sanity-io docs Studio
(apps/studio/src/plugins/pte, PR #4003 there parameterized the docs
knowledge out in preparation).
Public API: blockInsertPicker({arrayTypeName, items?, inputRules?,
onItemInserted?}) returning the component for an array type's
components.portableText.plugins, plus the codeFenceRule/blockquoteRule
config factories and fence-language helpers. Items derive from the host
array's members with metadata-driven curation (triggers, keywords,
grouping, rank); inserts resolve member initial values, land as one
undo step, and open for editing.
Ported against sanity 6.5.0 / @portabletext/editor 7.10.7 /
@portabletext/plugin-input-rule 6.0.4 (peer editor ^7.10.7 to match the
input-rule plugin's requirement; editor stays a peer, never bundled).
112 tests ported with the source; test-studio example wired under
Home > Block Insert Picker.
* refactor(block-insert-picker): zero-config detection and reviewed v1 API
Applies the pre-publication design review (DESIGN-REVIEW.md in the
pte-plugin-extraction research):
- blockInsertPicker() now works with zero config: the containing array and
its members are detected via PortableTextMemberSchemaTypesContext
(quarantined in memberSchemaTypes.ts); arrayTypeName becomes an escape
hatch. Peer narrowed to sanity ^5.6 (the context export's floor).
- Text blocks are excluded by resolved type chain, fixing aliased
{name, type: 'block'} members being offered as object inserts (picker and
input-rule allow-list both).
- New options: labels (translatable chrome), shortcut, openOnInsert
(global + per-item), presets (well-known-type triggers/keywords),
filter (receives the bare query in both modes), resolveItems middleware
with custom item actions (query cleanup included); onItemInserted renamed
onInsert, events carry mode/query.
- Presentation matches core: icon fallback chain, upperFirst titles, and
curated descriptions now win over schema descriptions.
- New exports: BlockInsertPicker, MarkdownInputRules, derivePickerItems,
filterPickerItems, standardBlockPresets, wellKnownInputRules, PickerMode.
- Input rules resolve blockType through member type chains, so
wellKnownInputRules serves aliased code-input members.
- Review fixes: host-callback errors surface as toasts instead of unhandled
rejections; anchor-deletion mid-insert shows a warning toast; positional
row indices tolerate duplicate item ids; replacement-pattern-safe label
formatting; screen-reader position announcement is translatable.
Deliberate deviations from the review doc: presets carry no description
(avoids a three-way precedence chain).
* test(block-insert-picker): lift cold-start timeout on first picker popover test
* docs: add @sanity/block-insert-picker to Current Plugins table
* chore: trigger pkg.pr.new preview publish
* refactor(block-insert-picker): address Copilot review comments
- insertPickerItem: spread the resolved initialValue before `_key`/`_type`
so the generated key and target type always win. Sanity's initial-value
resolver sets `_type` on object values; the values coincide by
construction here, but ordering keeps the insert correct regardless.
- openBlockOnInsert: correct the stale rationale comment. The package
enables the React Compiler, so the old "not active" claim was wrong; the
point is the empty-dep useCallback keeps a stable reference for consumers.
- blockInsertPicker: fix the comment naming the wrong mouse events. Rows
select via onClick and highlight via onMouseMove (not onMouseDown /
onMouseEnter), passing an explicit idx to avoid a not-yet-flushed
highlightedIndex.
* fix(block-insert-picker): case-insensitive fence language table match; trim README install
- normalizeFenceLanguage now compares the typed token to language-table
`value`/`aliases` case-insensitively, returning the canonical value
(casing preserved). Previously a table with mixed-case entries never
matched and the mapped filename was skipped (Cursor Bugbot, low severity).
Built-in rules and code-input's lowercase table were unaffected; this
hardens host-supplied custom tables. Adds a mixed-case-table test.
- README: collapse the three install commands to a single `npm install`
(no --save), matching @sanity/code-input's install section.
* Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* fix(block-insert-picker): restore bracket notation for process.env access
The Copilot Autofix commit rewrote `process.env['NODE_ENV']` to dot
notation, which fails this repo's type-aware lint: `noPropertyAccessFrom
IndexSignature` (TS4111) requires index-signature properties like
`process.env.NODE_ENV` to be accessed with brackets. Restore the bracket
form so `pnpm lint` passes.
* fix(block-insert-picker): address Cursor Bugbot findings
- inputRules: preserve case for unknown fence tokens (`return token`, not the
lowercased form) so the "pass through as typed" contract holds — e.g.
`GraphQL` stays `GraphQL` for wellKnownInputRules' no-table path.
- inputRules: spread host `buildValue` before `_key`/`_type` in createInsertRule
so a stray `_key`/`_type` can't hijack block identity (mirrors the
insertPickerItem fix).
- blockInsertPicker: close the picker when a select bails on an in-flight
insert, so a menu reopened during a slow initial-value resolution can't get
stuck swallowing Enter.
- blockInsertPicker: key sections on the namespaced raw group instead of the
display label, so a curated group named like `ungroupedSection` can't collide
with the null-group section's React key.
Two other Bugbot findings need no change: the text-block exclusion
(`isTextBlockMember`) already mirrors Sanity's own `findBlockType` (walk the
type chain to root, match `name === 'block'`), and the initial-value spread in
insertPickerItem was already reordered in an earlier commit.
---------
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
feat(code-input): export SUPPORTED_LANGUAGES and LANGUAGE_ALIASES (#1600)
Downstream tooling that resolves external language tokens (markdown
fence infostrings, paste/import pipelines) onto code field values has
had to vendor this list and hand-sync it with the Language selector.
Exporting the canonical table (and the alias map) removes the drift.
Version Packages (#1662)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(changeset): note npm provenance re-enabled for sanity-plugin-utils (#1661)
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Version Packages (#1660)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(changeset): bump google maps input for css dts cleanup (#1659)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
chore(deps): dedupe pnpm-lock.yaml (#1658)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @sanity/client to ^7.24.0 (#1581)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): lock file maintenance (#1657)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
Version Packages (#1640)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(test-studio): use turbo transit for build cache invalidation (#1655)
Replace empty dependsOn with a transit node so sanity build still skips
workspace package builds while Turbo invalidates when dependency source changes.
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
chore(deps): bump pkg-utils, tsdown-config, and vanilla-extract plugins (#1656)
Update catalog entries to @sanity/pkg-utils ^11.0.13,
@sanity/tsdown-config ^0.19.6, and @sanity/vanilla-extract-vite-plugin
^0.2.5. Exclude lightningcss@1.33.0 (and platform packages) from
minimumReleaseAge so pnpm update/dedupe can resolve the new transitive
deps, and align turbo/generators tsdown with the workspace catalog.
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
chore(deps): dedupe pnpm-lock.yaml (#1653)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore: remove @typescript/native-preview (use TypeScript 7 native tsc) (#1650)
* chore: remove @typescript/native-preview now that TypeScript 7 ships native tsc
TypeScript 7.0.2 includes the native compiler as `tsc`, so the preview package
and its `tsgo` binary are no longer needed. VS Code settings now point the
TypeScript 7 extension at the workspace `typescript` install.
* Update settings.json
* Update settings.json
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
chore(deps): lock file maintenance (#1651)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(test-studio): stop waiting on dependency builds (#1652)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Delete dependencies-GH-1642.md
Migrate to date-fns v4 and official @date-fns/tz, matching sanity core (#1569)
chore(deps): dedupe pnpm-lock.yaml (#1649)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @sanity/pkg-utils to ^11.0.12 (#1647)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): dedupe pnpm-lock.yaml (#1645)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): update renovatebot/github-action action to v46.1.20 (#1646)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): bump @sanity/vanilla-extract-vite-plugin to ^0.2.4
Drop the Bynder Styles.css.js Vite workaround from the test studio —
0.2.4 keeps the compiler alive under unstable_bundledDev, so plain
*.css.js modules no longer hang processVanillaFile.
fix(deps): update dependency tsdown to ^0.22.12 (#1642)
fix(deps): update dependency styled-components to ^6.4.4 (#1566)
chore(deps): dedupe pnpm-lock.yaml (#1643)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency react-virtuoso to ^4.18.11 (#1641)
* fix(deps): update dependency react-virtuoso to ^4.18.11
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
docs(agents): catalog shared deps + enable pnpm catalogMode prefer (#1374)
chore(deps): dedupe pnpm-lock.yaml (#1637)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency react-hook-form to ^7.82.0 (#1639)
* fix(deps): update dependency react-hook-form to ^7.82.0
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): update davelosert/vitest-coverage-report-action action to v2.12.2 (#1638)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
Version Packages (#1612)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
ci: shard Vitest suite (#1584)
* ci: shard vitest suite
* ci: report sharded test coverage
* chore: ignore Vitest blob reports
* ci: require test shards to succeed in aggregate check
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
fix(typegen): 🤖 ✨ (#1634)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(format): 🤖 ✨ (#1633)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): dedupe pnpm-lock.yaml (#1632)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency tsdown to ^0.22.9 (#1622)
* fix(deps): update dependency tsdown to ^0.22.9
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
fix(assist): keep field group selection while editing AI Assist inputs (#1467)
* fix(assist): keep field group selection while editing AI Assist inputs
The AI Assist instruction inspector renders a nested document form that
reused the host document's pane router. Sanity's document pane mirrors the
router `path` param to programmatic focus, and focus drives the selected
field group. Navigating the instruction form therefore overwrote the host
`path`, re-focused the host document, and reset its field group tab.
Isolate the nested pane's `path` navigation in local state while still
forwarding other params (e.g. selected instruction) to the host router.
Co-authored-by: Cody Olsen <stipsan@users.noreply.github.com>
* test(test-studio): add AI Assist + field groups fixture (SAPP-3970)
Adds an 'AI Assist: Field groups' document type with Content/SEO field
group tabs so the field-group-reset behavior with AI Assist can be
manually reproduced and verified.
Co-authored-by: Cody Olsen <stipsan@users.noreply.github.com>
* refactor(assist): use react-fast-compare for param equality
Addresses PR review: the hand-rolled shallowEqualParams returned a false
positive when two param objects had the same key count but different keys
whose values were undefined (e.g. {foo: undefined} vs {bar: undefined}),
because it never verified the key existed on the other object. Reuse
react-fast-compare (already a plugin dependency, used in _lib/useListeningQuery)
instead of a custom check, and add a regression test.
Co-authored-by: Cody Olsen <stipsan@users.noreply.github.com>
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Cody Olsen <stipsan@users.noreply.github.com>
fix(bynder-input): restore Compact View modal visibility in Studio v6 (#1553)
* fix(bynder-input): restore Compact View modal visibility in Studio v6
Upgrade @bynder/compact-view from 5.1.2 to 5.4.0 and patch its shadow DOM
integration for Sanity Studio v6:
- disableCSSOMInjection on StyleSheetManager so styled-components injects
CSS into the shadow root instead of leaving empty style tags
- position:fixed + z-index on CompactViewContainer so the portal host
stacks above Studio UI layers
- widen React peer dependency range to support React 19
Also render BynderModalLayout outside the button flex row.
* fix: unmount bynder layout when not open
* fix(bynder-input): take @bynder/compact-view 5.4.0 as a regular pinned dependency
Implements review feedback on the patch-based approach:
- drop the pnpm patch and the bundling of @bynder/compact-view; pin it
as a regular dependency instead
- style the Compact View modal host from the plugin with a
vanilla-extract globalStyle instead of patching Modal.js
- document how to allow the stale react peer range (npm
--legacy-peer-deps, pnpm peerDependencyRules.allowedVersions) in the
README, and use the pnpm rule for the workspace itself
* fix(bynder-input): survive Compact View shadow-root re-attachment and fix dev-studio css.js crash
- append a <slot> fallback to Compact View's shadow root while the modal
is mounted: its attachShadow effect has no cleanup, so when React
reconnects passive effects on the same host (StrictMode, Activity),
the second attachShadow() throws and Compact View falls back to the
host's light DOM, which the slotless shadow tree kept invisible
- work around @bynder/compact-view's Styles.css.js (a plain JS module
whose name matches vanilla-extract's cssFileFilter and deadlocks the
compiler under sanity dev's bundled dev mode) in the test studio
- move the container globalStyle to BynderInput.css.ts so it loads with
the input instead of the lazy modal chunk
* chore(bynder-input): bump changeset to major
Taking @bynder/compact-view as an unbundled regular dependency with a
stale react peer range can fail npm installs without --legacy-peer-deps,
so it's a breaking change.
* chore(bynder-input): widen @bynder/compact-view to ^5.4.0
The exact pin was only needed while the package was patched and
inlined; as a plain regular dependency a caret range is fine.
* chore: merge main and regenerate lockfile
The PR lockfile was generated against a main where
@sanity/vanilla-extract-vite-plugin resolved to 0.2.1; main has since
bumped it to 0.2.2, and the git-merged lockfile on the PR merge ref was
internally inconsistent (ERR_PNPM_LOCKFILE_MISSING_DEPENDENCY in CI).
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Cody Olsen <stipsan@users.noreply.github.com>
fix(deps): update dependency @sanity/tsdown-config to ^0.19.3 (#1598)
* fix(deps): update dependency @sanity/tsdown-config to ^0.19.3
* chore: dedupe lockfile and add release-age excludes for tsdown transitive deps
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
Co-authored-by: Cody Olsen <81981+stipsan@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
chore(deps): dedupe pnpm-lock.yaml (#1631)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @sanity/vanilla-extract-vite-plugin to ^0.2.2 (#1614)
* fix(deps): update dependency @sanity/vanilla-extract-vite-plugin to ^0.2.2
* chore(deps): exempt yuku-parser from minimum release age for dedupe
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Move turbo/**/*.hbs oxfmt ignore to root config (#1604)
The turbo generator template ignore is monorepo-specific and should
not ship in the shared @sanity/plugin-kit/oxfmt preset consumed by
standalone plugins.
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
fix(deps): update dependency @sanity/pkg-utils to ^11.0.10 (#1630)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
docs(assist): fix README markdown formatting and document English-only image descriptions (#1628)
* fix(@sanity/assist): respect document language when generating image descriptions
Pass the configured translate.document.languageField as languagePath to the
generate-caption task (both the automatic generation triggered on image
change, and the manual 'Generate image description' field action), so
generated alt text/captions are written in the document's language instead
of always defaulting to English.
Fixes https://github.com/sanity-io/plugins/issues/1606
* docs(@sanity/assist): clarify caption generation language limitation
Testing against the live AI Assist backend confirms that the generate-caption
task currently always writes descriptions in English, regardless of the
languagePath sent from the client (this matches Sanity's own documentation,
which states the automatic image description feature is English-only today
and recommends the Transform Agent Action's image-description operation as a
workaround). Update the changeset and README to accurately describe the
change as forward-compatible plumbing rather than a full fix, and point users
at the documented workaround for non-English alt text today.
* refactor(assist): resolve languagePath inside useGenerateCaption
Compute languagePath from config.translate.document.languageField once
inside useGenerateCaption itself (via useAiAssistanceConfig), instead of
requiring every call site to read the config and thread it through as an
argument. This removes the duplicated config lookup from both
ImageContextProvider and generateCaptionsActions, and matches the cleaner
approach used in sanity-io/plugins#1627.
Also documents in translate/types.ts JSDoc that languageField is reused
for image description generation.
* docs(assist): fix README markdown formatting and add known limitations
The README relied on markdown block elements (headings, lists, code
fences, images) interrupting paragraphs without blank lines between
them. GitHub tolerates this, but stricter renderers (e.g. the plugin
listing on sanity.io) join everything into unreadable walls of text
with literal '### Heading' and '- list item' fragments inline.
- Separate all block elements with blank lines throughout
- Add a 'Known limitations' section documenting that image descriptions
are always generated in English regardless of
translate.document.languageField (backend limitation, see #1606),
with Transform Agent Action and translate-after workarounds
- Fix broken links: empty-href heading, HOW-TO-USE pointing at the old
standalone repo layout, LICENSE pointing at a non-existent file
- Fix broken bold markup in the 'Enabling the AI Assist API' steps and
the useExampleFieldActions TOC anchor
- Add missing TOC entries (Known limitations, Caveats, Third party
sub-processors)
Also reverts the languagePath client plumbing from this branch: the
backend ignores it, so the plugin change had no effect. This PR is now
docs-only.
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
chore(deps): dedupe pnpm-lock.yaml (#1619)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): update pnpm to v11.13.1 (#1624)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @sanity/pkg-utils to ^11.0.9 (#1625)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update turbo monorepo to v2.10.5 (#1626)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): update dependency knip to ^6.27.0
chore: fix css
fix(deps): update dependency @codemirror/lang-markdown to ^6.5.1 (#1610)
* fix(deps): update dependency @codemirror/lang-markdown to ^6.5.1
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency oxfmt to ^0.59.0 (#1599)
* fix(deps): update dependency oxfmt to ^0.59.0
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @sanity/pkg-utils to ^11.0.7 (#1594)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
Fix TypeGen workflow failure by pinning `@sanity/vanilla-extract-vite-plugin` to 0.1.1 (#1616)
* Initial plan
* fix(typegen): pin vanilla-extract vite plugin to 0.1.1
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
chore(deps): bump tsdown and vanilla-extract
fix(deps): update dependency oxlint to ^1.74.0 (#1603)
* fix(deps): update dependency oxlint to ^1.74.0
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): update zizmorcore/zizmor-action action to v0.6.0 (#1609)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): lock file maintenance (#1611)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): replace @vanilla-extract/vite-plugin with @sanity/vanilla-extract-vite-plugin (#1590)
* chore(deps): replace @vanilla-extract/vite-plugin with @sanity/vanilla-extract-vite-plugin
Swap the vanilla-extract Vite plugin used by the test studio and
@sanity/google-maps-input's vitest config to @sanity/vanilla-extract-vite-plugin,
a Vite 8 rewrite with plugin hook filters and a caching compiler on Vite's
Environment API / ModuleRunner instead of the legacy vite-node. Bump tsdown to
^0.22.8 and @sanity/tsdown-config to ^0.17.0 alongside it.
google-maps-input's vitest.config.ts also needed a small stub plugin: its
dist/bundle.css.js Node/SSR shim matches the upstream cssFileFilter by
filename alone (*.css.js), which made the new plugin try to evaluate it as
real .css.ts source and throw ReferenceError: require is not defined via
ModuleRunner (vite-node tolerated this). The stub renames that module id away
from a .css.js shape before vanillaExtractPlugin() ever sees it.
Documented both the plugin swap and the shim workaround in the
sanity-plugin-best-practices skill and the new-plugin generator templates so
future vanilla-extract plugins get this for free.
* chore(deps): bump @sanity/tsdown-config to ^0.17.1, drop bundle.css.js shim workaround
@sanity/tsdown-config 0.17.1 (via @sanity/vanilla-extract-tsdown-plugin
0.2.1 / @sanity/vanilla-extract-rolldown-plugin 0.1.1) renames the
vanilla-extract Node/SSR compat shim from bundle.css.js to bundle-css.js so
it no longer matches vanillaExtractPlugin()'s cssFileFilter by filename
alone (sanity-io/pkg-utils#3043). That was the root cause of the
require-is-not-defined regression worked around in the previous commit, so
the stub-bundle-css-js-shim plugin is no longer needed.
Rebuilding @sanity/google-maps-input picked up the renamed dist/bundle-css.js
shim and auto-rewrote its package.json ./bundle.css export map (adding a
types condition too). Reverted the vitest.config.ts workaround and the
matching documentation/generator-template changes back to the plain
vanillaExtractPlugin() registration, now noted as a historical gotcha
instead of a live workaround.
* docs(test-studio): note that unstable_bundledDev breaks .css.ts HMR
Document the trade-off discovered while testing the vanilla-extract Vite
plugin swap: with unstable_bundledDev: true, editing a .css.ts file doesn't
hot-reload (a sanity dev restart is required), while plain .ts/.tsx HMR is
unaffected. Comment out the line for a session if fast CSS HMR is needed
(confirmed sub-10ms with it unset).
* docs(styling skill): trim verbose vanilla-extract setup section
The ./bundle.css export map (and its dist/bundle-css.js shim/types) is
generated and kept in sync automatically by @sanity/tsdown-config's
vanillaExtract option, so it doesn't need explaining or a JSON example to
copy. Simplify the vitest.config.ts guidance to why (@sanity/vanilla-extract-
vite-plugin is faster than upstream) without the ModuleRunner/hook-filter/
sanity-build internals. Drop the sanity.cli.ts snippet, since the test studio
already registers the plugin globally in this repo and doesn't need to be
touched per-plugin. Drop the bundle.css.js->bundle-css.js rename history
note, a one-off gotcha now fixed upstream rather than evergreen guidance.
* chore(deps): bump @sanity/tsdown-config to ^0.17.2, @sanity/vanilla-extract-vite-plugin to ^0.1.1
Both are latest-available patch releases (0.17.1 -> 0.17.2 pulls in
@sanity/vanilla-extract-tsdown-plugin 0.2.2 / @sanity/vanilla-extract-
rolldown-plugin 0.1.2; 0.1.0 -> 0.1.1 is the vite plugin's own patch).
tsdown stays at ^0.22.8, already the latest. Benchmarked in the next commit's
message to confirm this doesn't regress anything.
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
fix(deps): update dependency @changesets/cli to ^2.31.1 (#1607)
* fix(deps): update dependency @changesets/cli to ^2.31.1
* chore(deps): exempt @changesets/cli and refresh lockfile with dedupe
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
chore(deps): update dependency @vitejs/devtools to ^0.4.1 (#1593)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
Version Packages (#1591)
chore(deps): dedupe pnpm-lock.yaml (#1602)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(media): use useMediaIndex so Tags panel works on wide viewports (#1592)
The home-rolled useBreakpointIndex returned -1 above 1920px, which
force-hid the Tags panel. Switch Items to @sanity/ui's useMediaIndex,
which includes a min-width catch-all and matches Controls breakpoints.
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
fix(deps): update dependency xstate to ^5.32.5 (#1597)
* fix(deps): update dependency xstate to ^5.32.5
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency tsdown to ^0.22.8 (#1596)
* fix(deps): update dependency tsdown to ^0.22.8
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @sanity/tsconfig to ^2.2.1 (#1595)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): update actions/setup-node action to v7 (#1586)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): update pnpm to v11 (#1579)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency nanoid to v6 (#1577)
* fix(deps): update dependency nanoid to v6
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency groq to ^6.5.0 (#1523)
* fix(deps): update dependency groq to ^6.5.0
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
Migrate plugin-kit and the monorepo from prettier/eslint to oxfmt/oxlint (#1565)
* Migrate plugin-kit and monorepo formatting from prettier to oxfmt
- Ship the monorepo's oxfmt settings as a @sanity/plugin-kit/oxfmt preset
- Re-export the preset from the root oxfmt.config.ts (replaces .oxfmtrc.json)
- init/inject scaffold oxfmt (config, devDependency, format script) instead
of prettier; --no-prettier is now --no-oxfmt
- verify-package: replace the duplicate-prettier-config check with a
monorepo-aware oxfmt check that expects the config at the workspace root
(or next to package.json outside monorepos) and flags leftover prettier
configuration with migration instructions
* Migrate plugin-kit and monorepo linting from eslint to oxlint, drop tsc
- Ship the monorepo's oxlint settings as @sanity/plugin-kit/oxlint-config.json
(type-aware rules, type checking via oxlint-tsgolint, warnings denied); the
root .oxlintrc.json extends it and keeps only workspace-specific ignores and
overrides
- init/inject scaffold oxlint (.oxlintrc.json, oxlint + oxlint-tsgolint
devDependenc…
… property
Bump alphaCard/previewCard white background to doubled-class specificity so it
beats Card's own background (the old inline style always won); drop the no-op
content property carried over from the styled.div swatch.
fix(color-input): drop unused react-color type re-exports
Knip flagged 12 types re-exported from the react-color barrel that nothing
outside the module imports. Keep only the types consumers actually use.
Merge branch 'cursor/ban-react-class-components-ca2a' into cursor/color-input-vanilla-extract-35df
Keep vanilla-extract styling for Alpha/Hue/Saturation/EditableInput;
ban branch still uses styled-components/inline styles for those files.
fix(color-input): convert vendored react-color components to function components
Convert Alpha/Hue/Saturation/EditableInput and centralize drag wiring in a
shared useDrag hook: a native mousedown listener attached in useLayoutEffect,
useEffectEvent so events always read the latest props, and per-gesture
mousemove/mouseup listeners cleaned up via AbortController. EditableInput
clears its pending blur-sync value once the prop catches up with the
displayed value, so blurring can't revert a typed value.
fix(sanity-plugin-media): convert ReduxProvider to a function component
Initialize the redux store once with a lazy useState initializer.
fix(orderable-document-list): convert OrderableDocumentList to a function component
Expose the structure menu actionHandlers via useImperativeHandle and the
React 19 ref-as-prop pattern, with a dependency list so the handle is not
re-created on every render (the pane stores it in state).
feat(plugin-kit): ban Component, PureComponent and createRef imports from react
Class components are not allowed in this repo — only function components.
createRef is only useful in class components; use the useRef hook instead.
Also point skill docs at the shared @sanity/plugin-kit/oxlint config.
chore: drop color-input oxlint override
Leave shared oxlint rules untouched; the vanilla-extract migration does
not need a package-specific no-restricted-imports lock-in.
Merge branch 'cursor/ban-react-class-components-ca2a' into cursor/color-input-vanilla-extract-35df
Resolve stack conflicts: keep vanilla-extract exports (drop EditableInputStyles),
bump @vanilla-extract/css catalog to ^1.21.2 while retaining @vanilla-extract/dynamic,
and regenerate the lockfile. Preserve EditableInput blur-sync fix from the base branch.
Version Packages (#1735)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
refactor(color-input): migrate styling to vanilla-extract
Replace styled-components and inline style objects with colocated
vanilla-extract stylesheets, using assignInlineVars for dynamic
theme/color values. Builds on the function-component + useDrag
refactor from the ban-react-class-components branch.
Merge remote-tracking branch 'origin/main' into cursor/ban-react-class-components-ca2a
fix(color-input): clear stale blur-sync value when prop catches up
The prop-sync effect early-returned when the normalized prop matched the
displayed value, leaving a blurValue captured from an older prop in place;
blurring would then restore that older value. Clear it (in a transition to
satisfy the React Compiler EffectSetState rule).
fix(deps): bump @sanity/pkg-utils, @sanity/tsdown-config and vanilla-extract plugins (#1769)
* fix(deps): bump @sanity/pkg-utils, @sanity/tsdown-config and vanilla-extract plugins
- @sanity/pkg-utils ^11.0.16 -> ^11.0.17
- @sanity/tsdown-config ^0.21.1 -> ^0.21.2
- @sanity/vanilla-extract-vite-plugin ^0.2.7 -> ^0.2.8
tsdown (^0.22.14) and @vanilla-extract/css (^1.21.2) were already on the
latest release; refreshing the lockfile picks up the transitive
@sanity/vanilla-extract-{integration,rolldown-plugin,tsdown-plugin} updates.
* fix(deps): public-hoist @vanilla-extract/css so node_modules .css.js files resolve it
`@sanity/vanilla-extract-vite-plugin` filters its transform hook on
/\.css\.(js|cjs|mjs|jsx|ts|tsx)/ with no node_modules exclusion, so it also
compiles `@bynder/compact-view/Styles.css.js` — a plain module exporting a CSS
string for a shadow root, not a vanilla-extract module. That package declares no
dependencies, so the compile only finds `@vanilla-extract/css/adapter` when pnpm
happens to hoist it into the hidden .pnpm/node_modules directory. On Vercel it
did not, failing `sanity build` for dev/test-studio with
"Cannot find module '@vanilla-extract/css/adapter'".
Public-hoisting puts @vanilla-extract/css on the root node_modules resolution
path, which is deterministic regardless of the implicit hoist layout.
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
chore(deps): dedupe pnpm-lock.yaml (#1766)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @sanity/pkg-utils to ^11.0.16 (#1768)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
feat(test-studio): add experimental @sanity/themer tool (#1738)
* feat(test-studio): add experimental @sanity/themer tool
Wire themerTool() into the Home workspace so theme presets and colors
can be previewed live against the plugins kitchen sink.
* chore(test-studio): bump @sanity/themer to 0.2.0
* chore(test-studio): use ^0.2.0 for @sanity/themer
Merge main and widen the themer dependency to a caret range.
* chore: dedupe lockfile to resolve @sanity/client type mismatch
pnpm dedupe collapses the 7.24.0 / 7.25.0 client split that broke
type-aware lint after merging main with themer.
* chore: handle lockfile
* chore(knip): ignore unused catalog entry reports in pnpm-workspace.yaml
The catalogued @sanity/types entry is referenced only by the overrides block
in pnpm-workspace.yaml, which knip does not read, so it was reported as an
unused catalog entry and failed `pnpm knip`.
Co-authored-by: Cursor <cursoragent@cursor.com>
* chore: fix lock
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
fix(deps): update dependency @vanilla-extract/css to ^1.21.2 (#1764)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): update renovatebot/github-action action to v46.1.21 (#1763)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @sanity/ui to ^3.5.0 (#1762)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): dedupe pnpm-lock.yaml (#1761)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
test(document-internationalization): expand Vitest + Playwright e2e coverage (#1712)
chore(deps): dedupe pnpm-lock.yaml (#1754)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): update dependency @playwright/test to ^1.62.0 (#1760)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update turbo monorepo to v2.10.7 (#1759)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency concurrently to ^10.0.4 (#1758)
* fix(deps): update dependency concurrently to ^10.0.4
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @portabletext/plugin-input-rule to ^6.0.10 (#1757)
* fix(deps): update dependency @portabletext/plugin-input-rule to ^6.0.10
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): update dependency @vitejs/devtools to ^0.4.8 (#1756)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): update dependency @portabletext/editor to ^7.10.13 (#1755)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): lock file maintenance (#1749)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore: fix lockfile
chore(deps): dedupe pnpm-lock.yaml (#1753)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @sanity/client to ^7.25.0 (#1747)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @sanity/ui to ^3.4.5 (#1745)
* fix(deps): update dependency @sanity/ui to ^3.4.5
* fix(knip): remove unused react-is devDependency from media plugin
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
fix(deps): update dependency @mux/mux-player to ^3.13.2 (#1751)
* fix(deps): update dependency @mux/mux-player to ^3.13.2
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): dedupe pnpm-lock.yaml (#1748)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency react-hook-form to ^7.83.0 (#1750)
* fix(deps): update dependency react-hook-form to ^7.83.0
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @mux/mux-player-react to ^3.13.2 (#1752)
* fix(deps): update dependency @mux/mux-player-react to ^3.13.2
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @sanity/preview-url-secret to ^4.1.2 (#1744)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): dedupe pnpm-lock.yaml (#1734)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
Delete dependencies-GH-1739.md
fix(deps): update dependency @sanity/color to ^3.0.8 (#1743)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @sanity/vanilla-extract-vite-plugin to ^0.2.7 (#1746)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @sanity/tsdown-config to ^0.21.1 (#1742)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @sanity/pkg-utils to ^11.0.15 (#1741)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): update zizmorcore/zizmor-action action to v0.6.1 (#1740)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency tsdown to ^0.22.14 (#1739)
* fix(deps): update dependency tsdown to ^0.22.14
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): update actions/cache action to v6 (#1731)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): update dependency @playwright/test to ^1.61.1 (#1737)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @sanity/tsdown-config to ^0.21.0 (#1736)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @sanity/vanilla-extract-vite-plugin to ^0.2.6 (#1733)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @sanity/pkg-utils to ^11.0.14 (#1732)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): update actions/cache action to v5 (#1730)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update turbo monorepo to v2.10.6 (#1729)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @tanstack/react-virtual to ^3.14.8 (#1728)
* fix(deps): update dependency @tanstack/react-virtual to ^3.14.8
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): update dependency knip to ^6.29.0 (#1727)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): update dependency @vitejs/devtools to ^0.4.5 (#1726)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
feat: add Playwright smoke e2e with ephemeral datasets (#1710)
* feat: add Playwright smoke e2e for test studio
Set up an e2e workspace with Chromium/Firefox smoke coverage,
storageState studio auth matching sanity-io/sanity, fail-fast
token validation, and a CI workflow that builds and previews
the test studio locally.
* fix(e2e): correct Playwright artifact gitignore paths
Paths in e2e/.gitignore are relative to that directory, so leading
/e2e/… never matched results or playwright-report.
* fix(e2e): require project id and dataset from env vars
Source SANITY_E2E_PROJECT_ID and SANITY_E2E_STUDIO_DATASET from
GitHub repository variables in CI (no hardcoding). Rename the
dataset env to SANITY_E2E_STUDIO_DATASET and map both onto the
test-studio SANITY_STUDIO_* vars when starting webServer.
* fix(e2e): stop knip from loading Playwright config
resolveE2eEnv() requires project id and dataset at config load time;
disable the knip Playwright plugin for the e2e workspace so analysis
does not need CI secrets.
* fix(e2e): drop token fallback and debug browser filter
Require only SANITY_E2E_SESSION_TOKEN for auth, and always run
Chromium and Firefox projects (filter via Playwright UI/CLI instead).
* docs(e2e): document plugins-e2e-testing sandbox project
Note that e2e uses Sanity sandbox org project plugins-e2e-testing
(a1psl692) and update .env.example accordingly.
* ci(e2e): post Sanity-style PR status comment
Add a Playwright summary reporter and update the E2E workflow to
post/refresh a pull request comment with pass/fail/flaky/skipped
counts and a link to the Actions run (HTML report as artifact until
Vercel report hosting lands).
* ci(e2e): deploy Playwright HTML report to Vercel
Host the report on a dedicated Vercel project and link pass/fail
counts in the PR status comment, matching sanity-io/sanity. Document
VERCEL_E2E_REPORT_* secret setup in e2e/README.md.
* feat(e2e): add ephemeral per-browser datasets like sanity-io/sanity
Create pr-*/main-* chromium and firefox datasets in CI, expose matching
studio workspaces, and schedule cleanup for closed PRs / stale main runs.
* fix(e2e): bump Sanity client apiVersion to 2026-07-23
* fix(ci): avoid env context in job-level e2e workflow env
GitHub Actions does not allow `env.*` when evaluating job `env:` maps.
Define dataset names at workflow level with inlined format expressions.
* ci(e2e): run chromium and firefox as a parallel matrix
Split setup / per-browser test / report-merge jobs. Each matrix job gets
its own SANITY_E2E_DATASET and runs playwright --project for that browser.
* fix(e2e): avoid pnpm setup command colliding with dataset script
`pnpm --filter e2e setup` invoked pnpm's built-in `setup`, so ephemeral
datasets were never created. Rename to `create-dataset` and call via
`pnpm run`. Fail the CI step if creation fails.
* ci(e2e): scope pull-requests write to jobs that post comments
Satisfy zizmor excessive-permissions: keep workflow at contents:read
and grant pull-requests:write only on setup/report jobs.
* ci(e2e): deploy studio preview to Vercel like sanity-io/sanity
Add deploy-preview job (vercel pull/build/deploy --prebuilt) with
ephemeral datasets baked in; matrix tests run against the preview URL
instead of a local sanity preview server. Adds vercel CLI as a root
devDependency and dev/test-studio/vercel.json build settings.
* ci(e2e): reuse VERCEL_E2E_REPORT_* secrets for the studio preview
The studio preview deploys with the same Vercel project/token as report
hosting, so only one set of Vercel secrets is required.
* fix(e2e): add SPA fallback rewrite to test-studio vercel.json
The deployed studio 404'd on /chromium and /firefox workspace routes,
so the studio never booted and globalSetup timed out waiting for
/users/me. Rewrite all paths to index.html (filesystem first), same as
sanity-io/sanity's studio deployments.
* fix(e2e): drop studio warm-up from globalSetup
The warm-up existed to pay the local dev-server cold-compile cost once
up front; CI now tests a deployed static studio, and the waitForResponse
race was flaky there. Keep the fast env + auth token preflight.
* feat(e2e): dedicated bare e2e-studio with chromium/firefox workspaces
Add dev/e2e-studio — a minimal studio used only by Playwright e2e:
structure tool, one smoke-test schema type, and per-browser workspaces
on the ephemeral datasets. No monorepo plugins yet; each plugin will be
added together with its e2e tests. Reverts the e2e wiring from
dev/test-studio so it stays a pure development studio.
* fix(e2e): address review feedback
- Create ephemeral datasets as private (tests auth via storageState)
- Add contents:read to the periodic cleanup workflow for checkout
- Strip all leading dashes in sanityIdify
- Fix stale e2e package description and report-hosting docs (shared
Vercel project, not a dedicated one)
* fix(e2e): keep ephemeral datasets public like sanity-io/sanity
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Make test-studio typegen idempotent in CI by forcing schema overwrite (#1725)
* Initial plan
* fix(test-studio): force schema extract during typegen
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
chore(deps): dedupe pnpm-lock.yaml (#1724)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
Version Packages (#1718)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @portabletext/plugin-input-rule to ^6.0.8 (#1723)
* fix(deps): update dependency @portabletext/plugin-input-rule to ^6.0.9
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): update dependency @types/google.maps to ^3.65.3 (#1722)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): update dependency @portabletext/editor to ^7.10.11 (#1721)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
Delete .changeset/dependencies-GH-1697.md
Delete .changeset/dependencies-GH-1692.md
fix(deps): update dependency @sanity/icons to ^5.2.1 (#1720)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency oxfmt to ^0.60.0 (#1697)
* fix(deps): update dependency oxfmt to ^0.60.0
* chore(deps): changeset for dependency update
* chore: dedupe lockfile with release age exemptions
* fix: resolve knip unused export errors
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
fix(deps): update dependency @testing-library/jest-dom to v7 (#1679)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update react monorepo to ^19.2.8 (#1692)
* fix(deps): update react monorepo to ^19.2.8
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
chore(deps): update dependency @vitejs/devtools to ^0.4.3 (#1704)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @tanstack/react-query to ^5.101.4 (#1706)
* fix(deps): update dependency @tanstack/react-query to ^5.101.4
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
feat(plugin-kit)!: require Node.js 24 and bump held-back CLI deps (#1696)
* feat(plugin-kit)!: require Node.js 24 and bump held-back CLI deps
- engines.node: >=20.19 <22 || >=22.12 -> >=24 (plugin-kit CLI only;
scaffolded/verified plugins keep the wider pkg-utils range)
- concurrently ^9 -> ^10, execa ^9 -> ^10, inquirer ^12 -> ^14 (all
previously held back by the permissive engine range)
- migrate the choices prompt from the 'list' type (removed in
inquirer 13) to 'select'
* fix(plugin-kit): report failed dependency install with the intended hint
execa rejects on non-zero exit, so the exitCode check in
installDependencies was unreachable and init surfaced npm/pnpm install
failures as an unhandled CLI error. Pass reject: false so the caller's
'Failed to install dependencies, try manually running `npm install`'
message is shown instead.
* refactor(plugin-kit): replace several deps with Node 24 builtins and local helpers
Drop chalk, get-it, git-remote-origin-url, github-url-to-object, xdg-basedir,
email-validator, p-props and outdent in favor of util.styleText, fetch, execa+git,
and small local helpers. All remaining CLI deps were already at latest.
* fix(plugin-kit): address review feedback on execa, styleText, and outdent
- catch spawn errors in installDependencies and git remote lookup
- join nodemon's files array before styleText (it requires a string)
- only strip spaces/tabs in outdent so under-indented lines keep content
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
fix(deps): upgrade Sanity monorepo to ^6.6.0 (#1717)
* fix(deps): upgrade Sanity monorepo to ^6.6.0
Bump catalog packages (sanity, @sanity/mutator/schema/util/vision) and
sanity-plugin-media's groq dependency. Map TARGET_NOT_FOUND to Sanity's
structure locale key for missing release/variant documents instead of
reusing the not-ready tooltip.
* fix(deps): force-dedupe Sanity monorepo packages to 6.6.0
Override transitive @sanity/types|mutator|schema|util and groq onto the
catalog version so the lockfile cannot keep a second 6.5.x copy (which
breaks media dts emit). Put groq in the catalog and document the upgrade
checklist in AGENTS.md.
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
fix(deps): update dependency @sanity/color to ^3.0.7 (#1716)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
feat(test-studio): enable React profiling on Vercel preview builds (#1713)
* feat(test-studio): enable React profiling on Vercel preview builds
Alias react-dom/client to react-dom/profiling when VERCEL_ENV is preview,
matching the Sanity monorepo test-studio setup, so PR deployments can be
profiled without imposing that overhead on production.
* fix(test-studio): disable auto-updates on preview for profiling
Auto-updates vendor builds hardcode react-dom-client.production.js, which
bypasses the react-dom/profiling alias. Turn auto-updates off when
VERCEL_ENV is preview so React DevTools profiling works on PR deployments.
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
fix(deps): update dependency @sanity/preview-url-secret to ^4.1.1 (#1714)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): dedupe pnpm-lock.yaml (#1709)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): update dependency @portabletext/editor to ^7.10.10 (#1703)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
Version Packages (#1708)
fix(deps): update dependency @portabletext/plugin-input-rule to ^6.0.7 (#1705)
Remove @sanity/styled-components override, move back to styled-components (#1693)
* Remove @sanity/styled-components override, move back to styled-components
* test: give first-mount UI tests timeout headroom on slow CI runners
* test: force styled-components speedy CSS injection under jsdom
Match sanity#13675 by setting SC_DISABLE_SPEEDY=false in the root
Vitest config so upstream styled-components keeps CSSOM injection in
tests. Revert the per-test timeout bumps that papered over the same
jsdom stylesheet reparse slowdown.
* chore: refresh PR head after merging main
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
fix(deps): upgrade oxlint and oxlint-tsgolint to latest (#1707)
Merge pull request #1702 from sanity-io/cursor/bump-sanity-ui-f3da
fix(deps): update dependency @portabletext/block-tools to ^5.1.12 (#1688)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @sanity/ui to ^3.4.3
Bump the catalog range and lockfile to @sanity/ui 3.4.3, and add a
patch changeset for all published plugins that depend on it.
Delete dependencies-GH-1691.md
Version Packages (#1694)
fix(deps): update dependency tsdown to ^0.22.13 (#1691)
* fix(deps): update dependency tsdown to ^0.22.13
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(plugin-kit): bump CLI dependencies to latest compatible majors (#1687)
- chalk ^4 -> ^5, concurrently ^8 -> ^9, execa ^5 -> ^9,
git-remote-origin-url ^3 -> ^4, inquirer ^8 -> ^12, meow ^9 -> ^14,
p-props ^4 -> ^6, xdg-basedir ^4 -> ^5, nodemon 3.1.0 -> 3.1.14
- drop @types/inquirer and @types/nodemon (both packages ship their own
types now)
- add the required meow importMeta option, switch to execa's named
export, use xdg-basedir's named xdgConfig export and
git-remote-origin-url's options object
- restore classic validate-on-filtered-value prompt semantics, which the
modern inquirer rewrite changed (fixes accepting scp-style git remote
URL defaults)
- concurrently 10, execa 10 and inquirer 13+ are held back as they
require Node versions beyond plugin-kit's supported engine range
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Version Packages (#1689)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(typegen): 🤖 ✨ (#1686)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore: add per-plugin changesets for latest @sanity/icons and @sanity/ui catalog bumps (#1684)
* chore: add plugin changesets for @sanity/icons and @sanity/ui bumps
* chore: consolidate icons/ui impacted plugin changesets
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Cody Olsen <81981+stipsan@users.noreply.github.com>
chore(deps): dedupe pnpm-lock.yaml (#1678)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency get-it to ^9.2.0 (#1675)
* fix(deps): update dependency get-it to ^9.2.0
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @sanity/ui to ^3.4.0 (#1677)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
fix(deps): update dependency @sanity/preview-url-secret to ^4.1.0 (#1680)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @sanity/icons to ^5.2.0 (#1676)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix: address review feedback on drag attach timing and imperative handle
- useDrag: attach the mousedown listener in useLayoutEffect so it exists
before paint (matches the previous synchronous JSX onMouseDown wiring).
- OrderableDocumentList: give useImperativeHandle a dependency list so a
new handle object is not installed on every render (the structure pane
stores the handle in state, so per-render handles could loop).
refactor(color-input): extract shared useDrag hook for picker surfaces
Replace the per-component propsRef/AbortController plumbing in
Alpha/Hue/Saturation/EditableInput with a single useDrag hook. It wires a
native mousedown listener via useEffect and keeps callbacks fresh with
useEffectEvent, so drag events always read the latest props. mousemove and
mouseup listeners attach per-gesture and abort on mouseup or unmount.
fix(color-input): address review feedback on drag listeners
- Keep latest props in a ref so window mousemove listeners registered on
mousedown see current values (matches class `this.props` behavior).
- Normalize EditableInput value comparisons to avoid number/string mismatch.
- Correct orderable-document-list changeset wording (ref-as-prop, not forwardRef).
Merge origin/main into cursor/ban-react-class-components-ca2a
Resolve color-input conflicts from #1673 (simplify components, remove
CustomPicker HOC). Main kept Alpha/Hue/Saturation/EditableInput as class
components pending a follow-up conversion; this PR is that follow-up:
- Accept ColorWrap.tsx deletion (HOC replaced by ColorInput state).
- Re-apply function-component conversions on top of main's AbortController
listener cleanup, using useRef instead of createRef.
Version Packages (#1674)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(color-input): simplify components, remove HOC (#1673)
Version Packages (#1668)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): dedupe pnpm-lock.yaml (#1671)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
Migrate sanity-plugin-workflow styling to vanilla-extract (#1450)
* Migrate sanity-plugin-workflow styling to vanilla-extract
* Keep styled-components catalog:devDependency for peer alignment
After the vanilla-extract migration, the peer can go, but the catalog
devDependency must remain so pnpm resolves the workspace
@sanity/styled-components override (same as google-maps-input).
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Merge origin/main into cursor/ban-react-class-components-ca2a
Resolve the modify/delete conflict on .oxlintrc.json: main moved shared
lint rules into @sanity/plugin-kit/oxlint (#1565). Accept the deletion
and port the Component/PureComponent/createRef bans into
packages/@sanity/plugin-kit/src/oxlint.ts alongside the existing
createElement/forwardRef restrictions.
Also rewrite OrderableDocumentList to use React 19 ref-as-prop instead
of forwardRef so it complies with main's forwardRef ban, and update
skill docs that still pointed at .oxlintrc.json.
ci: request workflows permission for typegen app token (#935)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Cody Olsen <81981+stipsan@users.noreply.github.com>
feat(@sanity/plugin-kit)!: remove Studio v2 upgrade and compatibility tooling (#1588)
* feat(@sanity/plugin-kit)!: remove Studio v2 upgrade and compatibility tooling
Drop verify-studio and all verify-package checks that existed to migrate from
or stay compatible with Sanity Studio v2 (incompatible-plugin shim, part:/config:
imports, merged @sanity/* packages, sanity.json parts validation). Package
verification now focuses on current plugin-kit conventions.
* chore(@sanity/plugin-kit): drop unused json5/knip ignores and refresh snapshots
Remove the json5 dependency and readJson5File helper that only served v2
sanity.json parsing, prune stale eslint knip ignoreDependencies, and update
verify-package snapshots after removing v2-upgrade checks.
* fix(@sanity/plugin-kit): address review feedback on path validation and studio detection
Drop the dist-hardcoded path existence check in getPackage entirely: compiled
entry points legitimately don't exist pre-build regardless of outDir, and
verify-package's esmOnly check already bans main/module fields. Also detect
sanity.cli.(js|ts) in findStudioConfig so init/inject refuse cli-config-only
studio directories too.
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
chore(deps): dedupe pnpm-lock.yaml (#1669)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(sanity-plugin-markdown): declare @sanity/client as a regular dependency (#1667)
* fix(sanity-plugin-markdown): declare @sanity/client and rxjs as regular deps
Move @sanity/client and rxjs out of inlinedDependencies into dependencies
so they are resolved at runtime instead of bundled into the package.
* chore: update lockfile for sanity-plugin-markdown deps
* fix(sanity-plugin-markdown): declare @sanity/client as a regular dependency
Move @sanity/client from devDependencies to dependencies so tsdown
externalizes it instead of writing it (and transitive rxjs) to
inlinedDependencies. rxjs is not imported by the plugin and is not
needed as a direct dependency once client is externalized.
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
fix(typegen): 🤖 ✨ (#1666)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @tanstack/react-virtual to ^3.14.7 (#1664)
* fix(deps): update dependency @tanstack/react-virtual to ^3.14.7
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): dedupe pnpm-lock.yaml (#1665)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
Version Packages (#1663)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
feat: add @sanity/block-insert-picker (#1601)
* feat(block-insert-picker): add @sanity/block-insert-picker
Slash-command block-insert picker and markdown input rules for Portable
Text fields, extracted from the sanity-io/www-sanity-io docs Studio
(apps/studio/src/plugins/pte, PR #4003 there parameterized the docs
knowledge out in preparation).
Public API: blockInsertPicker({arrayTypeName, items?, inputRules?,
onItemInserted?}) returning the component for an array type's
components.portableText.plugins, plus the codeFenceRule/blockquoteRule
config factories and fence-language helpers. Items derive from the host
array's members with metadata-driven curation (triggers, keywords,
grouping, rank); inserts resolve member initial values, land as one
undo step, and open for editing.
Ported against sanity 6.5.0 / @portabletext/editor 7.10.7 /
@portabletext/plugin-input-rule 6.0.4 (peer editor ^7.10.7 to match the
input-rule plugin's requirement; editor stays a peer, never bundled).
112 tests ported with the source; test-studio example wired under
Home > Block Insert Picker.
* refactor(block-insert-picker): zero-config detection and reviewed v1 API
Applies the pre-publication design review (DESIGN-REVIEW.md in the
pte-plugin-extraction research):
- blockInsertPicker() now works with zero config: the containing array and
its members are detected via PortableTextMemberSchemaTypesContext
(quarantined in memberSchemaTypes.ts); arrayTypeName becomes an escape
hatch. Peer narrowed to sanity ^5.6 (the context export's floor).
- Text blocks are excluded by resolved type chain, fixing aliased
{name, type: 'block'} members being offered as object inserts (picker and
input-rule allow-list both).
- New options: labels (translatable chrome), shortcut, openOnInsert
(global + per-item), presets (well-known-type triggers/keywords),
filter (receives the bare query in both modes), resolveItems middleware
with custom item actions (query cleanup included); onItemInserted renamed
onInsert, events carry mode/query.
- Presentation matches core: icon fallback chain, upperFirst titles, and
curated descriptions now win over schema descriptions.
- New exports: BlockInsertPicker, MarkdownInputRules, derivePickerItems,
filterPickerItems, standardBlockPresets, wellKnownInputRules, PickerMode.
- Input rules resolve blockType through member type chains, so
wellKnownInputRules serves aliased code-input members.
- Review fixes: host-callback errors surface as toasts instead of unhandled
rejections; anchor-deletion mid-insert shows a warning toast; positional
row indices tolerate duplicate item ids; replacement-pattern-safe label
formatting; screen-reader position announcement is translatable.
Deliberate deviations from the review doc: presets carry no description
(avoids a three-way precedence chain).
* test(block-insert-picker): lift cold-start timeout on first picker popover test
* docs: add @sanity/block-insert-picker to Current Plugins table
* chore: trigger pkg.pr.new preview publish
* refactor(block-insert-picker): address Copilot review comments
- insertPickerItem: spread the resolved initialValue before `_key`/`_type`
so the generated key and target type always win. Sanity's initial-value
resolver sets `_type` on object values; the values coincide by
construction here, but ordering keeps the insert correct regardless.
- openBlockOnInsert: correct the stale rationale comment. The package
enables the React Compiler, so the old "not active" claim was wrong; the
point is the empty-dep useCallback keeps a stable reference for consumers.
- blockInsertPicker: fix the comment naming the wrong mouse events. Rows
select via onClick and highlight via onMouseMove (not onMouseDown /
onMouseEnter), passing an explicit idx to avoid a not-yet-flushed
highlightedIndex.
* fix(block-insert-picker): case-insensitive fence language table match; trim README install
- normalizeFenceLanguage now compares the typed token to language-table
`value`/`aliases` case-insensitively, returning the canonical value
(casing preserved). Previously a table with mixed-case entries never
matched and the mapped filename was skipped (Cursor Bugbot, low severity).
Built-in rules and code-input's lowercase table were unaffected; this
hardens host-supplied custom tables. Adds a mixed-case-table test.
- README: collapse the three install commands to a single `npm install`
(no --save), matching @sanity/code-input's install section.
* Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* fix(block-insert-picker): restore bracket notation for process.env access
The Copilot Autofix commit rewrote `process.env['NODE_ENV']` to dot
notation, which fails this repo's type-aware lint: `noPropertyAccessFrom
IndexSignature` (TS4111) requires index-signature properties like
`process.env.NODE_ENV` to be accessed with brackets. Restore the bracket
form so `pnpm lint` passes.
* fix(block-insert-picker): address Cursor Bugbot findings
- inputRules: preserve case for unknown fence tokens (`return token`, not the
lowercased form) so the "pass through as typed" contract holds — e.g.
`GraphQL` stays `GraphQL` for wellKnownInputRules' no-table path.
- inputRules: spread host `buildValue` before `_key`/`_type` in createInsertRule
so a stray `_key`/`_type` can't hijack block identity (mirrors the
insertPickerItem fix).
- blockInsertPicker: close the picker when a select bails on an in-flight
insert, so a menu reopened during a slow initial-value resolution can't get
stuck swallowing Enter.
- blockInsertPicker: key sections on the namespaced raw group instead of the
display label, so a curated group named like `ungroupedSection` can't collide
with the null-group section's React key.
Two other Bugbot findings need no change: the text-block exclusion
(`isTextBlockMember`) already mirrors Sanity's own `findBlockType` (walk the
type chain to root, match `name === 'block'`), and the initial-value spread in
insertPickerItem was already reordered in an earlier commit.
---------
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
feat(code-input): export SUPPORTED_LANGUAGES and LANGUAGE_ALIASES (#1600)
Downstream tooling that resolves external language tokens (markdown
fence infostrings, paste/import pipelines) onto code field values has
had to vendor this list and hand-sync it with the Language selector.
Exporting the canonical table (and the alias map) removes the drift.
Version Packages (#1662)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(changeset): note npm provenance re-enabled for sanity-plugin-utils (#1661)
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Version Packages (#1660)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(changeset): bump google maps input for css dts cleanup (#1659)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
chore(deps): dedupe pnpm-lock.yaml (#1658)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @sanity/client to ^7.24.0 (#1581)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): lock file maintenance (#1657)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
Version Packages (#1640)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(test-studio): use turbo transit for build cache invalidation (#1655)
Replace empty dependsOn with a transit node so sanity build still skips
workspace package builds while Turbo invalidates when dependency source changes.
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
chore(deps): bump pkg-utils, tsdown-config, and vanilla-extract plugins (#1656)
Update catalog entries to @sanity/pkg-utils ^11.0.13,
@sanity/tsdown-config ^0.19.6, and @sanity/vanilla-extract-vite-plugin
^0.2.5. Exclude lightningcss@1.33.0 (and platform packages) from
minimumReleaseAge so pnpm update/dedupe can resolve the new transitive
deps, and align turbo/generators tsdown with the workspace catalog.
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
chore(deps): dedupe pnpm-lock.yaml (#1653)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore: remove @typescript/native-preview (use TypeScript 7 native tsc) (#1650)
* chore: remove @typescript/native-preview now that TypeScript 7 ships native tsc
TypeScript 7.0.2 includes the native compiler as `tsc`, so the preview package
and its `tsgo` binary are no longer needed. VS Code settings now point the
TypeScript 7 extension at the workspace `typescript` install.
* Update settings.json
* Update settings.json
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
chore(deps): lock file maintenance (#1651)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(test-studio): stop waiting on dependency builds (#1652)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Delete dependencies-GH-1642.md
Migrate to date-fns v4 and official @date-fns/tz, matching sanity core (#1569)
chore(deps): dedupe pnpm-lock.yaml (#1649)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @sanity/pkg-utils to ^11.0.12 (#1647)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): dedupe pnpm-lock.yaml (#1645)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): update renovatebot/github-action action to v46.1.20 (#1646)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): bump @sanity/vanilla-extract-vite-plugin to ^0.2.4
Drop the Bynder Styles.css.js Vite workaround from the test studio —
0.2.4 keeps the compiler alive under unstable_bundledDev, so plain
*.css.js modules no longer hang processVanillaFile.
fix(deps): update dependency tsdown to ^0.22.12 (#1642)
fix(deps): update dependency styled-components to ^6.4.4 (#1566)
chore(deps): dedupe pnpm-lock.yaml (#1643)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency react-virtuoso to ^4.18.11 (#1641)
* fix(deps): update dependency react-virtuoso to ^4.18.11
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
docs(agents): catalog shared deps + enable pnpm catalogMode prefer (#1374)
chore(deps): dedupe pnpm-lock.yaml (#1637)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency react-hook-form to ^7.82.0 (#1639)
* fix(deps): update dependency react-hook-form to ^7.82.0
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): update davelosert/vitest-coverage-report-action action to v2.12.2 (#1638)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
Version Packages (#1612)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
ci: shard Vitest suite (#1584)
* ci: shard vitest suite
* ci: report sharded test coverage
* chore: ignore Vitest blob reports
* ci: require test shards to succeed in aggregate check
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
fix(typegen): 🤖 ✨ (#1634)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(format): 🤖 ✨ (#1633)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): dedupe pnpm-lock.yaml (#1632)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency tsdown to ^0.22.9 (#1622)
* fix(deps): update dependency tsdown to ^0.22.9
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
fix(assist): keep field group selection while editing AI Assist inputs (#1467)
* fix(assist): keep field group selection while editing AI Assist inputs
The AI Assist instruction inspector renders a nested document form that
reused the host document's pane router. Sanity's document pane mirrors the
router `path` param to programmatic focus, and focus drives the selected
field group. Navigating the instruction form therefore overwrote the host
`path`, re-focused the host document, and reset its field group tab.
Isolate the nested pane's `path` navigation in local state while still
forwarding other params (e.g. selected instruction) to the host router.
Co-authored-by: Cody Olsen <stipsan@users.noreply.github.com>
* test(test-studio): add AI Assist + field groups fixture (SAPP-3970)
Adds an 'AI Assist: Field groups' document type with Content/SEO field
group tabs so the field-group-reset behavior with AI Assist can be
manually reproduced and verified.
Co-authored-by: Cody Olsen <stipsan@users.noreply.github.com>
* refactor(assist): use react-fast-compare for param equality
Addresses PR review: the hand-rolled shallowEqualParams returned a false
positive when two param objects had the same key count but different keys
whose values were undefined (e.g. {foo: undefined} vs {bar: undefined}),
because it never verified the key existed on the other object. Reuse
react-fast-compare (already a plugin dependency, used in _lib/useListeningQuery)
instead of a custom check, and add a regression test.
Co-authored-by: Cody Olsen <stipsan@users.noreply.github.com>
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Cody Olsen <stipsan@users.noreply.github.com>
fix(bynder-input): restore Compact View modal visibility in Studio v6 (#1553)
* fix(bynder-input): restore Compact View modal visibility in Studio v6
Upgrade @bynder/compact-view from 5.1.2 to 5.4.0 and patch its shadow DOM
integration for Sanity Studio v6:
- disableCSSOMInjection on StyleSheetManager so styled-components injects
CSS into the shadow root instead of leaving empty style tags
- position:fixed + z-index on CompactViewContainer so the portal host
stacks above Studio UI layers
- widen React peer dependency range to support React 19
Also render BynderModalLayout outside the button flex row.
* fix: unmount bynder layout when not open
* fix(bynder-input): take @bynder/compact-view 5.4.0 as a regular pinned dependency
Implements review feedback on the patch-based approach:
- drop the pnpm patch and the bundling of @bynder/compact-view; pin it
as a regular dependency instead
- style the Compact View modal host from the plugin with a
vanilla-extract globalStyle instead of patching Modal.js
- document how to allow the stale react peer range (npm
--legacy-peer-deps, pnpm peerDependencyRules.allowedVersions) in the
README, and use the pnpm rule for the workspace itself
* fix(bynder-input): survive Compact View shadow-root re-attachment and fix dev-studio css.js crash
- append a <slot> fallback to Compact View's shadow root while the modal
is mounted: its attachShadow effect has no cleanup, so when React
reconnects passive effects on the same host (StrictMode, Activity),
the second attachShadow() throws and Compact View falls back to the
host's light DOM, which the slotless shadow tree kept invisible
- work around @bynder/compact-view's Styles.css.js (a plain JS module
whose name matches vanilla-extract's cssFileFilter and deadlocks the
compiler under sanity dev's bundled dev mode) in the test studio
- move the container globalStyle to BynderInput.css.ts so it loads with
the input instead of the lazy modal chunk
* chore(bynder-input): bump changeset to major
Taking @bynder/compact-view as an unbundled regular dependency with a
stale react peer range can fail npm installs without --legacy-peer-deps,
so it's a breaking change.
* chore(bynder-input): widen @bynder/compact-view to ^5.4.0
The exact pin was only needed while the package was patched and
inlined; as a plain regular dependency a caret range is fine.
* chore: merge main and regenerate lockfile
The PR lockfile was generated against a main where
@sanity/vanilla-extract-vite-plugin resolved to 0.2.1; main has since
bumped it to 0.2.2, and the git-merged lockfile on the PR merge ref was
internally inconsistent (ERR_PNPM_LOCKFILE_MISSING_DEPENDENCY in CI).
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Cody Olsen <stipsan@users.noreply.github.com>
fix(deps): update dependency @sanity/tsdown-config to ^0.19.3 (#1598)
* fix(deps): update dependency @sanity/tsdown-config to ^0.19.3
* chore: dedupe lockfile and add release-age excludes for tsdown transitive deps
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
Co-authored-by: Cody Olsen <81981+stipsan@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
chore(deps): dedupe pnpm-lock.yaml (#1631)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @sanity/vanilla-extract-vite-plugin to ^0.2.2 (#1614)
* fix(deps): update dependency @sanity/vanilla-extract-vite-plugin to ^0.2.2
* chore(deps): exempt yuku-parser from minimum release age for dedupe
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Move turbo/**/*.hbs oxfmt ignore to root config (#1604)
The turbo generator template ignore is monorepo-specific and should
not ship in the shared @sanity/plugin-kit/oxfmt preset consumed by
standalone plugins.
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
fix(deps): update dependency @sanity/pkg-utils to ^11.0.10 (#1630)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
docs(assist): fix README markdown formatting and document English-only image descriptions (#1628)
* fix(@sanity/assist): respect document language when generating image descriptions
Pass the configured translate.document.languageField as languagePath to the
generate-caption task (both the automatic generation triggered on image
change, and the manual 'Generate image description' field action), so
generated alt text/captions are written in the document's language instead
of always defaulting to English.
Fixes https://github.com/sanity-io/plugins/issues/1606
* docs(@sanity/assist): clarify caption generation language limitation
Testing against the live AI Assist backend confirms that the generate-caption
task currently always writes descriptions in English, regardless of the
languagePath sent from the client (this matches Sanity's own documentation,
which states the automatic image description feature is English-only today
and recommends the Transform Agent Action's image-description operation as a
workaround). Update the changeset and README to accurately describe the
change as forward-compatible plumbing rather than a full fix, and point users
at the documented workaround for non-English alt text today.
* refactor(assist): resolve languagePath inside useGenerateCaption
Compute languagePath from config.translate.document.languageField once
inside useGenerateCaption itself (via useAiAssistanceConfig), instead of
requiring every call site to read the config and thread it through as an
argument. This removes the duplicated config lookup from both
ImageContextProvider and generateCaptionsActions, and matches the cleaner
approach used in sanity-io/plugins#1627.
Also documents in translate/types.ts JSDoc that languageField is reused
for image description generation.
* docs(assist): fix README markdown formatting and add known limitations
The README relied on markdown block elements (headings, lists, code
fences, images) interrupting paragraphs without blank lines between
them. GitHub tolerates this, but stricter renderers (e.g. the plugin
listing on sanity.io) join everything into unreadable walls of text
with literal '### Heading' and '- list item' fragments inline.
- Separate all block elements with blank lines throughout
- Add a 'Known limitations' section documenting that image descriptions
are always generated in English regardless of
translate.document.languageField (backend limitation, see #1606),
with Transform Agent Action and translate-after workarounds
- Fix broken links: empty-href heading, HOW-TO-USE pointing at the old
standalone repo layout, LICENSE pointing at a non-existent file
- Fix broken bold markup in the 'Enabling the AI Assist API' steps and
the useExampleFieldActions TOC anchor
- Add missing TOC entries (Known limitations, Caveats, Third party
sub-processors)
Also reverts the languagePath client plumbing from this branch: the
backend ignores it, so the plugin change had no effect. This PR is now
docs-only.
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
chore(deps): dedupe pnpm-lock.yaml (#1619)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): update pnpm to v11.13.1 (#1624)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @sanity/pkg-utils to ^11.0.9 (#1625)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update turbo monorepo to v2.10.5 (#1626)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): update dependency knip to ^6.27.0
chore: fix css
fix(deps): update dependency @codemirror/lang-markdown to ^6.5.1 (#1610)
* fix(deps): update dependency @codemirror/lang-markdown to ^6.5.1
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency oxfmt to ^0.59.0 (#1599)
* fix(deps): update dependency oxfmt to ^0.59.0
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @sanity/pkg-utils to ^11.0.7 (#1594)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
Fix TypeGen workflow failure by pinning `@sanity/vanilla-extract-vite-plugin` to 0.1.1 (#1616)
* Initial plan
* fix(typegen): pin vanilla-extract vite plugin to 0.1.1
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
chore(deps): bump tsdown and vanilla-extract
fix(deps): update dependency oxlint to ^1.74.0 (#1603)
* fix(deps): update dependency oxlint to ^1.74.0
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): update zizmorcore/zizmor-action action to v0.6.0 (#1609)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): lock file maintenance (#1611)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): replace @vanilla-extract/vite-plugin with @sanity/vanilla-extract-vite-plugin (#1590)
* chore(deps): replace @vanilla-extract/vite-plugin with @sanity/vanilla-extract-vite-plugin
Swap the vanilla-extract Vite plugin used by the test studio and
@sanity/google-maps-input's vitest config to @sanity/vanilla-extract-vite-plugin,
a Vite 8 rewrite with plugin hook filters and a caching compiler on Vite's
Environment API / ModuleRunner instead of the legacy vite-node. Bump tsdown to
^0.22.8 and @sanity/tsdown-config to ^0.17.0 alongside it.
google-maps-input's vitest.config.ts also needed a small stub plugin: its
dist/bundle.css.js Node/SSR shim matches the upstream cssFileFilter by
filename alone (*.css.js), which made the new plugin try to evaluate it as
real .css.ts source and throw ReferenceError: require is not defined via
ModuleRunner (vite-node tolerated this). The stub renames that module id away
from a .css.js shape before vanillaExtractPlugin() ever sees it.
Documented both the plugin swap and the shim workaround in the
sanity-plugin-best-practices skill and the new-plugin generator templates so
future vanilla-extract plugins get this for free.
* chore(deps): bump @sanity/tsdown-config to ^0.17.1, drop bundle.css.js shim workaround
@sanity/tsdown-config 0.17.1 (via @sanity/vanilla-extract-tsdown-plugin
0.2.1 / @sanity/vanilla-extract-rolldown-plugin 0.1.1) renames the
vanilla-extract Node/SSR compat shim from bundle.css.js to bundle-css.js so
it no longer matches vanillaExtractPlugin()'s cssFileFilter by filename
alone (sanity-io/pkg-utils#3043). That was the root cause of the
require-is-not-defined regression worked around in the previous commit, so
the stub-bundle-css-js-shim plugin is no longer needed.
Rebuilding @sanity/google-maps-input picked up the renamed dist/bundle-css.js
shim and auto-rewrote its package.json ./bundle.css export map (adding a
types condition too). Reverted the vitest.config.ts workaround and the
matching documentation/generator-template changes back to the plain
vanillaExtractPlugin() registration, now noted as a historical gotcha
instead of a live workaround.
* docs(test-studio): note that unstable_bundledDev breaks .css.ts HMR
Document the trade-off discovered while testing the vanilla-extract Vite
plugin swap: with unstable_bundledDev: true, editing a .css.ts file doesn't
hot-reload (a sanity dev restart is required), while plain .ts/.tsx HMR is
unaffected. Comment out the line for a session if fast CSS HMR is needed
(confirmed sub-10ms with it unset).
* docs(styling skill): trim verbose vanilla-extract setup section
The ./bundle.css export map (and its dist/bundle-css.js shim/types) is
generated and kept in sync automatically by @sanity/tsdown-config's
vanillaExtract option, so it doesn't need explaining or a JSON example to
copy. Simplify the vitest.config.ts guidance to why (@sanity/vanilla-extract-
vite-plugin is faster than upstream) without the ModuleRunner/hook-filter/
sanity-build internals. Drop the sanity.cli.ts snippet, since the test studio
already registers the plugin globally in this repo and doesn't need to be
touched per-plugin. Drop the bundle.css.js->bundle-css.js rename history
note, a one-off gotcha now fixed upstream rather than evergreen guidance.
* chore(deps): bump @sanity/tsdown-config to ^0.17.2, @sanity/vanilla-extract-vite-plugin to ^0.1.1
Both are latest-available patch releases (0.17.1 -> 0.17.2 pulls in
@sanity/vanilla-extract-tsdown-plugin 0.2.2 / @sanity/vanilla-extract-
rolldown-plugin 0.1.2; 0.1.0 -> 0.1.1 is the vite plugin's own patch).
tsdown stays at ^0.22.8, already the latest. Benchmarked in the next commit's
message to confirm this doesn't regress anything.
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
fix(deps): update dependency @changesets/cli to ^2.31.1 (#1607)
* fix(deps): update dependency @changesets/cli to ^2.31.1
* chore(deps): exempt @changesets/cli and refresh lockfile with dedupe
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
chore(deps): update dependency @vitejs/devtools to ^0.4.1 (#1593)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
Version Packages (#1591)
chore(deps): dedupe pnpm-lock.yaml (#1602)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(media): use useMediaIndex so Tags panel works on wide viewports (#1592)
The home-rolled useBreakpointIndex returned -1 above 1920px, which
force-hid the Tags panel. Switch Items to @sanity/ui's useMediaIndex,
which includes a min-width catch-all and matches Controls breakpoints.
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
fix(deps): update dependency xstate to ^5.32.5 (#1597)
* fix(deps): update dependency xstate to ^5.32.5
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency tsdown to ^0.22.8 (#1596)
* fix(deps): update dependency tsdown to ^0.22.8
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency @sanity/tsconfig to ^2.2.1 (#1595)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): update actions/setup-node action to v7 (#1586)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
chore(deps): update pnpm to v11 (#1579)
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency nanoid to v6 (#1577)
* fix(deps): update dependency nanoid to v6
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
fix(deps): update dependency groq to ^6.5.0 (#1523)
* fix(deps): update dependency groq to ^6.5.0
* chore(deps): changeset for dependency update
---------
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
Migrate plugin-kit and the monorepo from prettier/eslint to oxfmt/oxlint (#1565)
* Migrate plugin-kit and monorepo formatting from prettier to oxfmt
- Ship the monorepo's oxfmt settings as a @sanity/plugin-kit/oxfmt preset
- Re-export the preset from the root oxfmt.config.ts (replaces .oxfmtrc.json)
- init/inject scaffold oxfmt (config, devDependency, format script) instead
of prettier; --no-prettier is now --no-oxfmt
- verify-package: replace the duplicate-prettier-config check with a
monorepo-aware oxfmt check that expects the config at the workspace root
(or next to package.json outside monorepos) and flags leftover prettier
configuration with migration instructions
* Migrate plugin-kit and monorepo linting from eslint to oxlint, drop tsc
- Ship the monorepo's oxlint settings …
…ommit hook on lefthook (#2047) <!-- CURSOR_AGENT_PR_BODY_BEGIN --> Brings oxfmt in line with sanity-io/ui's `main`: the same version, the same config, and the same scripts and CI wiring. The pre-commit hook moves from husky and lint-staged to lefthook, set up like sanity-io/sanity's. Supersedes #1919. ## Commits 1. **`chore(deps): update oxfmt to ^0.71.0`**: the catalog goes from ^0.63.0 to ui's ^0.71.0, with ui's oxfmt resolution: oxfmt 0.71.0 and `tinypool` 2.2.0, the same versions and integrity hashes as ui's lockfile. There's a patch changeset for `@sanity/plugin-kit`, whose optional `oxfmt` peer uses the catalog. 2. **`chore(format): align the oxfmt config with sanity-io/ui`**: root `oxfmt.config.ts` now ignores `storybook-static/**` and `CHANGELOG.md`, like ui's `.oxfmtrc.json`. `.vscode/settings.json` points `oxc.fmt.configPath` at `oxfmt.config.ts` instead of the `.oxfmtrc.json` that #1565 deleted. AGENTS.md records the parity with ui and the exceptions. 3. **`chore: drop the husky and lint-staged pre-commit hook, like sanity-io/ui`**: superseded by commit 6, which brings the hook back on lefthook. 4. **`chore(format): drop the oxfmt preset's .changeset/*.md override, like sanity-io/ui`**: the `@sanity/plugin-kit/oxfmt` preset loses its Prettier-era `singleQuote: false` override for `.changeset/*.md`, as ui's `.oxfmtrc.json` did when ui switched Changesets to oxfmt formatting (sanity-io/ui#2957). It gets a patch changeset for `@sanity/plugin-kit`, since the preset is published. This part moved here from #2046 because it's formatter config. AGENTS.md now explains how changesets get quoted. 5. **`chore(format): run pnpm format`**: requotes this PR's own changeset from commit 1. Everything else already passed under oxfmt 0.71. 6. **`chore: run oxfmt on staged files with lefthook, like sanity-io/sanity`**: see below. ## Pre-commit hook: husky and lint-staged → lefthook This mirrors how sanity-io/sanity replaced husky and lint-staged (sanity-io/sanity#12755, then sanity-io/sanity#12767 and sanity-io/sanity#12953): - **`lefthook` ^2.1.14** as a root devDependency, sanity's range. It resolves to 2.1.14, as in sanity's lockfile. - **`allowBuilds: lefthook: true`** in `pnpm-workspace.yaml`, as in sanity. Lefthook's own install script runs `lefthook install` during `pnpm install`, and it skips when `CI` is set, which covers GitHub Actions and Vercel. There's no root `postinstall` script: sanity dropped its `lefthook install --reset-hooks-path` postinstall in #12767 for this package build. - **`lefthook.yml`** with sanity's layout: a parallel `pre-commit` with two jobs that run oxfmt on staged files with `stage_fixed: true`. The jobs are `format-scripts` (`*.{js,jsx,ts,tsx,mjs,cjs,mts,cts}`) and `format-other` (`*.{md,yml,yaml,css,json,jsonc}`). - `mts`, `cts` and `jsonc` are additions to sanity's globs. They cover this repo's `.mts`, `turbo.jsonc` and `knip.jsonc` files, which the old lint-staged glob partly covered. - sanity's `oxlint --fix` line is left to the oxlint alignment (#2049). - **Direct binary calls:** the jobs call `node_modules/.bin/oxfmt` instead of sanity's `pnpm oxfmt`. Running pnpm in a hook triggers pnpm 12's implicit install, which flips the lockfile's peer toggle (see AGENTS.md). sanity switched to `pnpm oxfmt` in #12953 because lefthook doesn't put `node_modules/.bin` on `PATH`; the path solves that too. - **Lockfile:** `pnpm-lock.yaml` gains only lefthook 2.1.14 and its platform packages (100 lines). A plain install would also have bumped the Studio's `next` overrides from `6.17.0-next.108` to `6.17.0-next.112`, so I resolved it through a local registry proxy that served the locked versions as `next`, as AGENTS.md describes. The lockfile has no `localhost` or `tarball:` entries. - **Docs:** AGENTS.md documents the hook, `LEFTHOOK=0`, the one-time reset for clones that ran husky, and `pnpm --config.verify-deps-before-run=false <script>` for local runs. README's note that formatting also runs in a pre-commit hook is back. ## Merges with `main` `main` is merged in, not rebased, so nothing was force-pushed. After each merge, `pnpm-lock.yaml` is `main`'s lockfile regenerated with pnpm 12.6.0, invoked directly so `packageManagerDependencies` stays, minus the peer toggle that AGENTS.md describes. - **#2039 (lock file maintenance):** only the lockfile conflicted. - **#2048 (pnpm 12.6.0):** `package.json` conflicted next to the removed `lint-staged` block. The resolution keeps both sides: `main`'s `packageManager: pnpm@12.6.0` and `vercel` ^60.1.3, without the block. A follow-up commit restores `main`'s side of the peer toggle, which the regeneration had flipped. - **#2046 (themer move):** only the lockfile conflicted. `pnpm format` then requoted #2046's three changesets in a separate commit: `dashboard-widget-vercel-xstate`, `shared-deps-sanity-ui-icons-motion` and `themer-plugins-monorepo`, 45 frontmatter lines, quote-only. The new `plugins/@sanity/themer` package and `dev/storybook` already passed. - **#2053 (Version Packages):** it released and deleted those three changesets, so the modify/delete conflicts resolve to `main`'s deletions. It didn't change the lockfile, and `pnpm format` changes nothing after the merge. `pnpm-lock.yaml` differs from `main` only by this PR's own changes: - oxfmt and its bindings go from 0.63.0 to 0.71.0, and `tinypool` from 2.1.0 to 2.2.0. - husky, lint-staged and their four exclusive dependencies are removed. - lefthook 2.1.14 and its platform packages are added. No other version moves, and the Studio stays on `6.17.0-next.108`. ## How it compares with ui - **Options:** identical, overrides included (`printWidth`, `semi`, `singleQuote`, `bracketSpacing`, `quoteProps`, `sortImports`, `sortPackageJson`). They come from the `@sanity/plugin-kit/oxfmt` preset. - **Ignore patterns:** `dist/**`, `storybook-static/**`, `pnpm-lock.yaml` and `CHANGELOG.md` in both. Two differences remain: - `turbo/**/*.hbs` is plugins-only (the turbo generator templates). - ui's `**/sanity.types.ts` is left out. In ui it was for `apps/docs/sanity.types.ts` and has matched nothing since the docs app went static. Here, `pnpm typegen` formats `dev/test-studio/sanity.types.ts` on purpose: the test studio runs typegen with `formatGeneratedCode: false` and then `pnpm format`. Ignoring the file would make the next TypeGen PR unformat it. - **Config file:** plugins keeps `oxfmt.config.ts` re-exporting the published preset instead of ui's `.oxfmtrc.json`. #1565 made that switch so the preset is exactly what the monorepo formats with, and plugin-kit's `verify-package` expects plugins to use it. oxfmt, the Oxc extension and Changesets' formatter detection all read `oxfmt.config.ts`. See the open question. - **Scripts and CI:** the `format` script is identical to ui's (`oxfmt . --no-error-on-unmatched-pattern`). Neither repo checks formatting on PRs, and both run the same shared `format-if-needed.yml` on `main`, so no workflow changes are needed. `oxfmt .` also formats `.github/workflows/*.yml`, which that workflow can't push, and 0.71 changes none of them. ui has no pre-commit hook; this repo keeps one, on lefthook. - **VS Code:** ui points `oxc.fmt.configPath` at its config file, but plugins pointed it at a file that doesn't exist. I drove `oxfmt --lsp` directly: with the old setting, the editor silently formats with oxfmt's defaults (double quotes, semicolons, bracket spacing, unsorted imports), and with `oxfmt.config.ts` it matches `pnpm format`. ## Changesets - **Changesets formats what it writes with oxfmt.** `.changeset/config.json` sets `"format": "oxfmt"` (from #2046). I called `@changesets/write` (what `changeset add` uses) directly. With the override it writes `"@sanity/plugin-kit": patch`; without it, `'@sanity/plugin-kit': patch`, the same as `pnpm format`. - **`changeset version` is unaffected.** It only hands `CHANGELOG.md` files to the formatter. This PR ignores those, and oxfmt skips them and exits 0 thanks to `--no-error-on-unmatched-pattern`. - **`changeset status` parses the single-quoted frontmatter.** It lists this PR's two changesets for `@sanity/plugin-kit` 10.0.11. ## What to expect after merging - **Renovate changesets get a follow-up format PR, as in ui.** The shared Renovate changesets workflow uses `mscharley/dependency-changesets-action`, which always writes double quotes and has no formatting option. After a Renovate PR merges, the Auto format workflow opens (or updates) a `chore(format): 🤖 ✨` PR that requotes the changeset. ui has had one after most Renovate merges since sanity-io/ui#2957: sanity-io/ui#2971, sanity-io/ui#2980, sanity-io/ui#2986, sanity-io/ui#2998, sanity-io/ui#3002, sanity-io/ui#3013 and sanity-io/ui#3024. - **Clones that ran husky need a one-time reset.** They still have `core.hooksPath=.husky/_`. There, `lefthook install` refuses to install and prints how to fix it, and `pnpm install` continues. Until the reset, husky's leftover runner does nothing, so commits simply aren't formatted. `git config --unset core.hooksPath && pnpm install` fixes it. ## Related PRs - **#1919** (Renovate, oxfmt ^0.71.0): superseded. This PR has the same bump, with the lockfile regenerated on current `main`, plus the config alignment. Close it if Renovate doesn't once this merges. - **#2046** (themer move) and **#2048** (pnpm 12): merged, and merged into this PR. - **#2049** (oxlint) conflicts with this PR in `pnpm-workspace.yaml`, where its `oxlint` catalog lines sit next to `oxfmt`. Keep both sides. It could also add sanity's `oxlint --fix` line to the `format-scripts` job, calling `node_modules/.bin/oxlint` directly. - **#2050** (vitest 5) conflicts only in `pnpm-lock.yaml`. - **#2051** (tsdown) doesn't conflict. - Whichever PR lands later merges `main` and regenerates the lockfile without committing the peer toggle. ## What Cody needs to do - Add the `🤖 bot` label: the agent's label tool couldn't edit PRs in this repository. - Triage Socket's alert. It flags `lefthook@2.1.14`'s install script (`node postinstall.js`) as a low-priority warning. That script is what installs the hook: `allowBuilds: lefthook: true` enables it, as in sanity-io/sanity, and it skips when `CI` is set. Mark it as acceptable risk if you agree. Socket's required checks pass either way. - After merging, tell contributors to run `git config --unset core.hooksPath && pnpm install` once, so lefthook replaces husky's hook. - Merge the Renovate follow-up format PRs as they come, as in ui. - No Vercel, secrets or ruleset changes, and no new secrets or env vars. ## Open question **`.oxfmtrc.json`:** should plugins switch to ui's JSON config file, too? That would mean no longer re-exporting the plugin-kit preset, and it would reverse #1565. I kept `oxfmt.config.ts`, since the formatting result is already the same as ui's. ## Verification - **The hook**, tested on throwaway commits, with `pnpm-lock.yaml` untouched each time: - Staged TS and JSON files get formatted and re-staged. - A tracked `.vscode/settings.json` (its folder is gitignored) is re-staged without the `[FAILED]` that lint-staged printed. - A staged `CHANGELOG.md`, which oxfmt ignores, passes as-is. - In a partially staged file, only the staged hunk is formatted and the unstaged hunk is kept. - The commit that adds the hook ran it on its own files in 0.4 seconds. - **Clones that ran husky:** with `core.hooksPath=.husky/_`, `lefthook install` exits 1 with instructions and installs nothing, as described above. - **Local checks** at the head commit, with pnpm 12.6.0 on Node 24.21 and `CI=true` (lefthook's install script skips): - `pnpm install --frozen-lockfile`, which leaves `pnpm-lock.yaml` untouched - `oxfmt --check` (2,018 files) - `oxlint` and `knip` - the full turbo build (54 tasks) - `vitest run` (235 files, 1,509 tests) - `pnpm test:browser` (4 files, 7 stories) - **CI** is fully green at the head commit (`123af257`): build, lint, knip, all four test shards, coverage, `storybook-test`, both e2e browsers, Bugbot, and both Vercel checks, whose installs run lefthook's install script. The branch is up to date with `main`. <!-- CURSOR_AGENT_PR_BODY_END --> <div><a href="https://cursor.com/agents/bc-0b8c4f47-d9af-5929-8254-d25847e7e2dd?cursor_ref=pr_footer&cursor_cta=open_in_web"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/open-in-web-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/open-in-web-light.png"><img alt="Open in Web" width="114" height="28" src="https://cursor.com/assets/images/open-in-web-dark.png"></picture></a> <a href="https://cursor.com/background-agent?bcId=bc-0b8c4f47-d9af-5929-8254-d25847e7e2dd&cursor_ref=pr_footer&cursor_cta=open_in_cursor"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/open-in-cursor-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/open-in-cursor-light.png"><img alt="Open in Cursor" width="131" height="28" src="https://cursor.com/assets/images/open-in-cursor-dark.png"></picture></a> </div> --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com>

Description
Drops prettier and eslint support from
@sanity/plugin-kitentirely, replacing them with oxfmt and oxlint, shipping the monorepo's own settings as reusable configs (inspired by@epic-web/config). plugin-kit also stops pushingtsctype-check runs (the shared oxlint config has type-aware rules and TypeScript type checking viaoxlint-tsgolintenabled, with warnings denied), and the Sanity v2 imports check is removed entirely — v2-era imports are no longer linted for.Shared configs shipped by plugin-kit (both authored in
src/, typed, built to plain JS indist/so Node never type-strips undernode_modules)@sanity/plugin-kit/oxfmt: oxfmt preset with the exact settings previously in the root.oxfmtrc.json.@sanity/plugin-kit/oxlint: oxlint config (typedOxlintConfig) matching the monorepo's previous.oxlintrc.jsonminus workspace-specific ignores/overrides — same plugins,typeAware/typeCheck/denyWarnings/reportUnusedDisableDirectivesoptions, categories and rules (verified semantically identical, plus identical lint file lists and diagnostics before/after).extendssupports imported config objects inoxlint.config.ts):oxfmt.config.ts:export {default} from '@sanity/plugin-kit/oxfmt'oxlint.config.ts:defineConfig({extends: [sanityPluginKitOxlint], ignorePatterns: [...shared, ...workspace], overrides: [...workspace]})Scaffolding (
init/inject)oxfmt.config.ts+oxlint.config.ts(both plain re-exports of the shared configs),oxfmt/oxlint/oxlint-tsgolintdevDependencies andformat/lintscripts. No prettier or eslint packages at all.--no-prettier→--no-oxfmt,--no-eslint→--no-oxlint; the--no-typescriptflag now actually controls TypeScript scaffolding (it previously piggybacked on the eslint flag).semver-workflowpreset's lint-staged config runsoxfmt+oxlintinstead ofeslint+tsc --build.verify-package / verify-studio
tsc --buildrun is gone (tsccheck key removed) — oxlint type-checks as part of linting.eslintImports) is removed entirely, along with the import-linter module;verify-studionow checks studio config and dependencies only.oxfmtandoxlintchecks: walk up for a workspace root (pnpm-workspace.yaml/workspacesfield); the config is expected there (or next to the plugin'spackage.jsonoutside monorepos) and must use the shared plugin-kit config. Leftover prettier/eslint configuration fails with migration instructions;.oxfmtrc.json/.oxlintrc.jsonfiles are flagged since JSON configs cannot import the shared configs.@sanity/pkg-utils,oxfmtandoxlint(theeslintandtypescriptpeers are gone, and oxlint is not a runtime dependency of plugin-kit).Housekeeping
dev/test-studionow pinstypescript(catalog) so thesanitypeer keeps resolving to the catalog version now that plugin-kit no longer contributes eslint/typescript peers to the graph.invalid-eslintfixture removed; the init→verify→build integration test now runs type-awareoxlintin the scaffold instead oftsc --build), unit tests for both config-location checks, snapshots regenerated.knip.jsonc,AGENTS.md, plugin-kit README updated; single major changeset.pnpm formatandpnpm lintnow require Node>=22.18(^20.19also works for oxfmt) to load the TypeScript configs. CI useslts/*, so it is unaffected.Testing
pnpm format,pnpm lint,pnpm knip,pnpm build,pnpm test run(169 files / 917 tests) all pass..oxlintrc.json→ shared-config →oxlint.config.tsrefactors; semantic JSON diff of rules/options/categories/overrides is empty.npm run lint(provedtypescript(TS2322)type errors andno-floating-promisesfire through the publisheddist/oxlint.jsre-export) →npm run format→verify-package(pass + legacy-eslint / JSON-config / multiple-config / missing-config failure modes) →npm run build; in the monorepo layout, proved rootdefineConfig({extends})merges shared rules with workspace overrides.Notes