@portabletext/plugin-dnd 1.0.34 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -44,6 +44,7 @@ function DropIndicator({edge}: {edge: 'start' | 'end'}) {
44
44
  <div
45
45
  contentEditable={false}
46
46
  style={{
47
+ pointerEvents: 'none',
47
48
  position: 'absolute',
48
49
  left: 0,
49
50
  right: 0,
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { ReactNode } from "react";
2
1
  import { Path } from "@portabletext/editor";
2
+ import { ReactNode } from "react";
3
3
  /**
4
4
  * The block-relative position a drop would land at.
5
5
  *
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../src/plugin.dnd.tsx"],"mappings":";;;;;;;KA8BY;EACV,MAAM;EACN;;;;;;;;;;;;;;;;;;;;iBAwMc,YAAY;EAAQ,WAAW;oBAAU,IAAA;;;;;;;;;;;iBAiCzC,gBACd,MAAM,OACL"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/plugin.dnd.tsx"],"mappings":";;;;;;;KAwCY;EACV,MAAM;EACN;;;;;;;;;;;;;;;;;;;;iBA4Qc,YAAY;EAAQ,WAAW;oBAAU,IAAA;;;;;;;;;;;iBAyCzC,gBACd,MAAM,OACL"}
package/dist/index.js CHANGED
@@ -1,8 +1,9 @@
1
1
  import { c } from "react/compiler-runtime";
2
+ import { useEditor } from "@portabletext/editor";
2
3
  import { defineBehavior, effect, forward } from "@portabletext/editor/behaviors";
3
4
  import { BehaviorPlugin } from "@portabletext/editor/plugins";
4
5
  import { getFocusBlock, getFocusInlineObject, getFocusSpan, getFocusTextBlock, getFragment, getSelectedBlocks, getSelectionEndBlock, getSelectionStartBlock, isOverlappingSelection, isSelectingEntireBlocks, isSelectionCollapsed, isSelectionExpanded } from "@portabletext/editor/selectors";
5
- import { getBlockEndPoint, getBlockStartPoint, isKeyedSegment } from "@portabletext/editor/utils";
6
+ import { getBlockEndPoint, getBlockStartPoint, isEmptyTextBlock, isEqualPaths, isEqualSelectionPoints, isKeyedSegment, isSelectionCollapsed as isSelectionCollapsed$1 } from "@portabletext/editor/utils";
6
7
  import { createContext, useContext, useEffect, useSyncExternalStore } from "react";
7
8
  import { jsx, jsxs } from "react/jsx-runtime";
8
9
  /**
@@ -81,8 +82,8 @@ function getDragSelection({ eventSelection, snapshot }) {
81
82
  }
82
83
  return dragSelection;
83
84
  }
84
- function createDropPositionStore() {
85
- let current, subscribers = /* @__PURE__ */ new Map();
85
+ function createDropPositionStore(getEditorElement) {
86
+ let current, restoreCaretColor, subscribers = /* @__PURE__ */ new Map();
86
87
  function notify(serializedPath) {
87
88
  if (serializedPath === void 0) return;
88
89
  let bucket = subscribers.get(serializedPath);
@@ -101,7 +102,15 @@ function createDropPositionStore() {
101
102
  current = next ? {
102
103
  serializedPath: serializePath(next.path),
103
104
  position: next.position
104
- } : void 0, (previous?.serializedPath !== current?.serializedPath || previous?.position !== current?.position) && (previous?.serializedPath !== current?.serializedPath && notify(previous?.serializedPath), notify(current?.serializedPath));
105
+ } : void 0;
106
+ let editorElement = getEditorElement();
107
+ if (editorElement) if (current && !restoreCaretColor) {
108
+ let previousCaretColor = editorElement.style.caretColor;
109
+ restoreCaretColor = () => {
110
+ editorElement.style.caretColor = previousCaretColor;
111
+ }, editorElement.style.caretColor = "transparent";
112
+ } else !current && restoreCaretColor && (restoreCaretColor(), restoreCaretColor = void 0);
113
+ (previous?.serializedPath !== current?.serializedPath || previous?.position !== current?.position) && (previous?.serializedPath !== current?.serializedPath && notify(previous?.serializedPath), notify(current?.serializedPath));
105
114
  }
106
115
  };
107
116
  }
@@ -129,23 +138,46 @@ function createDropPositionBehaviors(setDropPosition) {
129
138
  let dragSelection = getDragSelection({
130
139
  eventSelection: dragOrigin.selection,
131
140
  snapshot
132
- });
133
- return getSelectedBlocks({
141
+ }), dragSnapshot = {
134
142
  ...snapshot,
135
143
  context: {
136
144
  ...snapshot.context,
137
145
  selection: dragSelection
138
146
  }
139
- }).some((draggedBlock) => draggedBlock.node._key === dropFocusBlock.node._key) || !isSelectingEntireBlocks({
147
+ }, draggedBlocks = getSelectedBlocks(dragSnapshot), draggedFocusBlock = getFocusBlock(dragSnapshot);
148
+ if (draggedBlocks.some((draggedBlock) => draggedBlock.node._key === dropFocusBlock.node._key) || draggedFocusBlock !== void 0 && isEqualPaths(draggedFocusBlock.path, dropFocusBlock.path)) return {
149
+ dropFocusBlock,
150
+ droppedInsideTextBlock: !1,
151
+ clear: !0
152
+ };
153
+ if (!isSelectingEntireBlocks({
140
154
  ...snapshot,
141
155
  context: {
142
156
  ...snapshot.context,
143
157
  selection: dragSelection
144
158
  }
145
- }) ? !1 : { dropFocusBlock };
159
+ })) return !1;
160
+ let dropSnapshot = {
161
+ ...snapshot,
162
+ context: {
163
+ ...snapshot.context,
164
+ selection: event.position.selection
165
+ }
166
+ }, focusTextBlock = getFocusTextBlock(dropSnapshot);
167
+ return {
168
+ dropFocusBlock,
169
+ droppedInsideTextBlock: isSelectionCollapsed$1(event.position.selection) && focusTextBlock !== void 0 && !isEmptyTextBlock(snapshot.context, focusTextBlock.node) && getFocusInlineObject(dropSnapshot) === void 0 && !isEqualSelectionPoints(event.position.selection.focus, getBlockStartPoint({
170
+ context: snapshot.context,
171
+ block: focusTextBlock
172
+ })) && !isEqualSelectionPoints(event.position.selection.focus, getBlockEndPoint({
173
+ context: snapshot.context,
174
+ block: focusTextBlock
175
+ })),
176
+ clear: !1
177
+ };
146
178
  },
147
- actions: [({ event }, { dropFocusBlock }) => [effect(() => {
148
- setDropPosition({
179
+ actions: [({ event }, { dropFocusBlock, droppedInsideTextBlock, clear }) => [effect(() => {
180
+ setDropPosition(clear || droppedInsideTextBlock ? void 0 : {
149
181
  path: dropFocusBlock.path,
150
182
  position: event.position.block
151
183
  });
@@ -178,21 +210,24 @@ const DndContext = createContext(void 0);
178
210
  * @beta
179
211
  */
180
212
  function DndProvider(props) {
181
- let $ = c(7), t0;
182
- $[0] === Symbol.for("react.memo_cache_sentinel") ? (t0 = createDropPositionStore(), $[0] = t0) : t0 = $[0];
213
+ let $ = c(13), editor = useEditor(), t0;
214
+ $[0] === editor ? t0 = $[1] : (t0 = createDropPositionStore(() => {
215
+ let editorElement = editor.dom.getEditorElement();
216
+ return editorElement instanceof HTMLElement ? editorElement : void 0;
217
+ }), $[0] = editor, $[1] = t0);
183
218
  let store = t0, t1;
184
- $[1] === Symbol.for("react.memo_cache_sentinel") ? (t1 = createDropPositionBehaviors(store.set), $[1] = t1) : t1 = $[1];
219
+ $[2] === store.set ? t1 = $[3] : (t1 = createDropPositionBehaviors(store.set), $[2] = store.set, $[3] = t1);
185
220
  let behaviors = t1, t2, t3;
186
- $[2] === Symbol.for("react.memo_cache_sentinel") ? (t2 = () => () => {
221
+ $[4] === store ? (t2 = $[5], t3 = $[6]) : (t2 = () => () => {
187
222
  store.set(void 0);
188
- }, t3 = [store], $[2] = t2, $[3] = t3) : (t2 = $[2], t3 = $[3]), useEffect(t2, t3);
223
+ }, t3 = [store], $[4] = store, $[5] = t2, $[6] = t3), useEffect(t2, t3);
189
224
  let t4;
190
- $[4] === Symbol.for("react.memo_cache_sentinel") ? (t4 = /* @__PURE__ */ jsx(BehaviorPlugin, { behaviors }), $[4] = t4) : t4 = $[4];
225
+ $[7] === behaviors ? t4 = $[8] : (t4 = /* @__PURE__ */ jsx(BehaviorPlugin, { behaviors }), $[7] = behaviors, $[8] = t4);
191
226
  let t5;
192
- return $[5] === props.children ? t5 = $[6] : (t5 = /* @__PURE__ */ jsxs(DndContext.Provider, {
227
+ return $[9] !== props.children || $[10] !== store || $[11] !== t4 ? (t5 = /* @__PURE__ */ jsxs(DndContext.Provider, {
193
228
  value: store,
194
229
  children: [t4, props.children]
195
- }), $[5] = props.children, $[6] = t5), t5;
230
+ }), $[9] = props.children, $[10] = store, $[11] = t4, $[12] = t5) : t5 = $[12], t5;
196
231
  }
197
232
  /**
198
233
  * Read where a drop would land relative to the block at `path`: `'start'`,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["EditorSelection","EditorSnapshot","getFocusInlineObject","getFocusSpan","getFocusTextBlock","getFragment","getSelectionEndBlock","getSelectionStartBlock","isOverlappingSelection","isSelectionCollapsed","isSelectionExpanded","getBlockEndPoint","getBlockStartPoint","getDragSelection","eventSelection","snapshot","NonNullable","dragSelection","draggedInlineObject","context","selection","draggingCollapsedSelection","draggedTextBlock","draggedSpan","anchor","block","focus","selectedBlocks","length","selectionStartBlock","selectionEndBlock","selectionStartPoint","selectionEndPoint","eventSelectionInsideBlocks","Path","defineBehavior","effect","forward","Behavior","BehaviorPlugin","getFocusBlock","getSelectedBlocks","isSelectingEntireBlocks","isKeyedSegment","createContext","useCallback","useContext","useEffect","useMemo","useSyncExternalStore","ReactNode","getDragSelection","DropPosition","path","position","DropPositionStore","get","serializedPath","subscribeKey","callback","set","next","createDropPositionStore","current","subscribers","Map","Set","notify","undefined","bucket","add","delete","size","previous","serializePath","createDropPositionBehaviors","setDropPosition","Array","on","guard","snapshot","event","dropFocusBlock","context","selection","dragOrigin","dragSelection","eventSelection","draggedBlocks","some","draggedBlock","node","_key","draggingEntireBlocks","actions","block","type","DndContext","DndProvider","props","$","_c","t0","Symbol","for","store","t1","behaviors","t2","t3","t4","t5","children","useDropPosition","Error","subscribe","getSnapshot","reduce","result","segment","index","separator"],"sources":["../src/drag-selection.ts","../src/plugin.dnd.tsx"],"sourcesContent":["import type {EditorSelection, EditorSnapshot} from '@portabletext/editor'\nimport {\n getFocusInlineObject,\n getFocusSpan,\n getFocusTextBlock,\n getFragment,\n getSelectionEndBlock,\n getSelectionStartBlock,\n isOverlappingSelection,\n isSelectionCollapsed,\n isSelectionExpanded,\n} from '@portabletext/editor/selectors'\nimport {getBlockEndPoint, getBlockStartPoint} from '@portabletext/editor/utils'\n\n/**\n * Given the current editor `snapshot` and an `eventSelection` representing\n * where the drag event originates from, calculate the selection in the\n * editor that should be dragged.\n *\n * Duplicated from the editor's internal `getDragSelection` rather than\n * imported: exporting it from core would add permanent public API for what\n * is an implementation detail of this plugin. Built on public selectors\n * only. Keep in sync with\n * `packages/editor/src/selectors/drag-selection.ts`.\n */\nexport function getDragSelection({\n eventSelection,\n snapshot,\n}: {\n eventSelection: NonNullable<EditorSelection>\n snapshot: EditorSnapshot\n}): NonNullable<EditorSelection> {\n let dragSelection = eventSelection\n\n const draggedInlineObject = getFocusInlineObject({\n ...snapshot,\n context: {\n ...snapshot.context,\n selection: eventSelection,\n },\n })\n\n if (draggedInlineObject) {\n return dragSelection\n }\n\n const draggingCollapsedSelection = isSelectionCollapsed({\n ...snapshot,\n context: {\n ...snapshot.context,\n selection: eventSelection,\n },\n })\n const draggedTextBlock = getFocusTextBlock({\n ...snapshot,\n context: {\n ...snapshot.context,\n selection: eventSelection,\n },\n })\n const draggedSpan = getFocusSpan({\n ...snapshot,\n context: {\n ...snapshot.context,\n selection: eventSelection,\n },\n })\n\n if (draggingCollapsedSelection && draggedTextBlock && draggedSpan) {\n // Looks like we are dragging an empty span\n // Let's drag the entire block instead\n dragSelection = {\n anchor: getBlockStartPoint({\n context: snapshot.context,\n block: draggedTextBlock,\n }),\n focus: getBlockEndPoint({\n context: snapshot.context,\n block: draggedTextBlock,\n }),\n }\n }\n\n const selectedBlocks = getFragment(snapshot)\n\n if (\n snapshot.context.selection &&\n isSelectionExpanded(snapshot) &&\n selectedBlocks.length > 1\n ) {\n const selectionStartBlock = getSelectionStartBlock(snapshot)\n const selectionEndBlock = getSelectionEndBlock(snapshot)\n\n if (!selectionStartBlock || !selectionEndBlock) {\n return dragSelection\n }\n\n const selectionStartPoint = getBlockStartPoint({\n context: snapshot.context,\n block: selectionStartBlock,\n })\n const selectionEndPoint = getBlockEndPoint({\n context: snapshot.context,\n block: selectionEndBlock,\n })\n\n const eventSelectionInsideBlocks = isOverlappingSelection(eventSelection)({\n ...snapshot,\n context: {\n ...snapshot.context,\n selection: {anchor: selectionStartPoint, focus: selectionEndPoint},\n },\n })\n\n if (eventSelectionInsideBlocks) {\n dragSelection = {\n anchor: selectionStartPoint,\n focus: selectionEndPoint,\n }\n }\n }\n\n return dragSelection\n}\n","import type {Path} from '@portabletext/editor'\nimport {\n defineBehavior,\n effect,\n forward,\n type Behavior,\n} from '@portabletext/editor/behaviors'\nimport {BehaviorPlugin} from '@portabletext/editor/plugins'\nimport {\n getFocusBlock,\n getSelectedBlocks,\n isSelectingEntireBlocks,\n} from '@portabletext/editor/selectors'\nimport {isKeyedSegment} from '@portabletext/editor/utils'\nimport {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useSyncExternalStore,\n type ReactNode,\n} from 'react'\nimport {getDragSelection} from './drag-selection'\n\n/**\n * The block-relative position a drop would land at.\n *\n * @beta\n */\nexport type DropPosition = {\n path: Path\n position: 'start' | 'end'\n}\n\n/**\n * One store per editor: the drag behaviors below maintain the current drop\n * position, and per-path subscriber buckets make notification O(changed\n * paths) rather than O(subscribers). `dragover` fires at mousemove\n * frequency, so only the block losing and the block gaining the indicator\n * re-render.\n */\ntype DropPositionStore = {\n get: (serializedPath: string) => DropPosition['position'] | undefined\n subscribeKey: (serializedPath: string, callback: () => void) => () => void\n set: (next: DropPosition | undefined) => void\n}\n\nfunction createDropPositionStore(): DropPositionStore {\n let current:\n | {serializedPath: string; position: DropPosition['position']}\n | undefined\n const subscribers = new Map<string, Set<() => void>>()\n\n function notify(serializedPath: string | undefined) {\n if (serializedPath === undefined) {\n return\n }\n\n const bucket = subscribers.get(serializedPath)\n\n if (bucket === undefined) {\n return\n }\n\n for (const callback of bucket) {\n callback()\n }\n }\n\n return {\n get: (serializedPath) =>\n current?.serializedPath === serializedPath ? current.position : undefined,\n subscribeKey: (serializedPath, callback) => {\n let bucket = subscribers.get(serializedPath)\n\n if (bucket === undefined) {\n bucket = new Set()\n subscribers.set(serializedPath, bucket)\n }\n\n bucket.add(callback)\n\n return () => {\n bucket.delete(callback)\n\n if (bucket.size === 0) {\n subscribers.delete(serializedPath)\n }\n }\n },\n set: (next) => {\n const previous = current\n\n // Swap before notifying: `useSyncExternalStore` re-reads the snapshot\n // synchronously on notification and skips the re-render when it reads\n // an unchanged (stale) value.\n current = next\n ? {serializedPath: serializePath(next.path), position: next.position}\n : undefined\n\n if (\n previous?.serializedPath === current?.serializedPath &&\n previous?.position === current?.position\n ) {\n return\n }\n\n if (previous?.serializedPath !== current?.serializedPath) {\n notify(previous?.serializedPath)\n }\n\n notify(current?.serializedPath)\n },\n }\n}\n\n/**\n * The behaviors observe the public `drag.*` events and `forward` every\n * event they handle: consumer behaviors run before the editor's own drag\n * handling, so omitting the forward would swallow the event and break the\n * drag itself. (The editor's internal drop-position tracking gets away\n * without forwarding because it registers below core priority.)\n */\nfunction createDropPositionBehaviors(\n setDropPosition: (next: DropPosition | undefined) => void,\n): Array<Behavior> {\n return [\n defineBehavior({\n on: 'drag.dragover',\n guard: ({snapshot, event}) => {\n const dropFocusBlock = getFocusBlock({\n ...snapshot,\n context: {\n ...snapshot.context,\n selection: event.position.selection,\n },\n })\n\n if (!dropFocusBlock) {\n return false\n }\n\n const dragOrigin = event.dragOrigin\n\n if (!dragOrigin) {\n return false\n }\n\n const dragSelection = getDragSelection({\n eventSelection: dragOrigin.selection,\n snapshot,\n })\n\n const draggedBlocks = getSelectedBlocks({\n ...snapshot,\n context: {\n ...snapshot.context,\n selection: dragSelection,\n },\n })\n\n if (\n draggedBlocks.some(\n (draggedBlock) =>\n draggedBlock.node._key === dropFocusBlock.node._key,\n )\n ) {\n return false\n }\n\n const draggingEntireBlocks = isSelectingEntireBlocks({\n ...snapshot,\n context: {\n ...snapshot.context,\n selection: dragSelection,\n },\n })\n\n if (!draggingEntireBlocks) {\n return false\n }\n\n return {dropFocusBlock}\n },\n actions: [\n ({event}, {dropFocusBlock}) => [\n effect(() => {\n setDropPosition({\n path: dropFocusBlock.path,\n position: event.position.block,\n })\n }),\n forward(event),\n ],\n ],\n }),\n defineBehavior({\n on: 'drag.*',\n guard: ({event}) => event.type !== 'drag.dragover',\n actions: [\n ({event}) => [\n effect(() => {\n setDropPosition(undefined)\n }),\n forward(event),\n ],\n ],\n }),\n ]\n}\n\nconst DndContext = createContext<DropPositionStore | undefined>(undefined)\n\n/**\n * Tracks the drop position during drag and drop and serves it through\n * context. Mount inside `EditorProvider`, wrapping whatever reads the\n * position:\n *\n * ```tsx\n * <EditorProvider initialConfig={...}>\n * <DndProvider>\n * <PortableTextEditable />\n * </DndProvider>\n * </EditorProvider>\n * ```\n *\n * Reads via {@link useDropPosition} only re-render when the drop position\n * at their own path changes.\n *\n * @beta\n */\nexport function DndProvider(props: {children?: ReactNode}) {\n const store = useMemo(() => createDropPositionStore(), [])\n const behaviors = useMemo(\n () => createDropPositionBehaviors(store.set),\n [store],\n )\n\n useEffect(() => {\n return () => {\n // A drag in progress when the provider unmounts never delivers its\n // clearing event.\n store.set(undefined)\n }\n }, [store])\n\n return (\n <DndContext.Provider value={store}>\n <BehaviorPlugin behaviors={behaviors} />\n {props.children}\n </DndContext.Provider>\n )\n}\n\n/**\n * Read where a drop would land relative to the block at `path`: `'start'`,\n * `'end'`, or `undefined` when no drag is hovering this block. Re-renders\n * only when the position at this path changes.\n *\n * `path` is the keyed block path render callbacks receive, e.g.\n * `[{_key: 'b0'}]`.\n *\n * @beta\n */\nexport function useDropPosition(\n path: Path,\n): DropPosition['position'] | undefined {\n const store = useContext(DndContext)\n\n if (store === undefined) {\n throw new Error('useDropPosition must be used below a <DndProvider>')\n }\n\n // Callers typically pass a fresh `path` array every render, so the\n // serialized string, not the array, is what keeps `subscribe` stable\n // below.\n const serializedPath = serializePath(path)\n\n const subscribe = useCallback(\n (callback: () => void) => store.subscribeKey(serializedPath, callback),\n [store, serializedPath],\n )\n\n const getSnapshot = () => store.get(serializedPath)\n\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot)\n}\n\n/**\n * Serialize a keyed path to a string using Sanity's bracket notation.\n * Duplicated from the editor's internal `serializePath`; see\n * `drag-selection.ts` for the duplication rationale.\n */\nfunction serializePath(path: Path): string {\n return path.reduce<string>((result, segment, index) => {\n if (isKeyedSegment(segment)) {\n return `${result}[_key==\"${segment._key}\"]`\n }\n\n const separator = index === 0 ? '' : '.'\n return `${result}${separator}${segment}`\n }, '')\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAyBA,SAAgBa,iBAAiB,EAC/BC,gBACAC,YAI+B;CAC/B,IAAIE,gBAAgBH;CAUpB,IAR4BZ,qBAAqB;EAC/C,GAAGa;EACHI,SAAS;GACP,GAAGJ,SAASI;GACZC,WAAWN;EACb;CACF,CAEII,GACF,OAAOD;CAGT,IAAMI,6BAA6BZ,qBAAqB;EACtD,GAAGM;EACHI,SAAS;GACP,GAAGJ,SAASI;GACZC,WAAWN;EACb;CACF,CAAC,GACKQ,mBAAmBlB,kBAAkB;EACzC,GAAGW;EACHI,SAAS;GACP,GAAGJ,SAASI;GACZC,WAAWN;EACb;CACF,CAAC,GACKS,cAAcpB,aAAa;EAC/B,GAAGY;EACHI,SAAS;GACP,GAAGJ,SAASI;GACZC,WAAWN;EACb;CACF,CAAC;CAED,AAAIO,8BAA8BC,oBAAoBC,gBAGpDN,gBAAgB;EACdO,QAAQZ,mBAAmB;GACzBO,SAASJ,SAASI;GAClBM,OAAOH;EACT,CAAC;EACDI,OAAOf,iBAAiB;GACtBQ,SAASJ,SAASI;GAClBM,OAAOH;EACT,CAAC;CACH;CAGF,IAAMK,iBAAiBtB,YAAYU,QAAQ;CAE3C,IACEA,SAASI,QAAQC,aACjBV,oBAAoBK,QAAQ,KAC5BY,eAAeC,SAAS,GACxB;EACA,IAAMC,sBAAsBtB,uBAAuBQ,QAAQ,GACrDe,oBAAoBxB,qBAAqBS,QAAQ;EAEvD,IAAI,CAACc,uBAAuB,CAACC,mBAC3B,OAAOb;EAGT,IAAMc,sBAAsBnB,mBAAmB;GAC7CO,SAASJ,SAASI;GAClBM,OAAOI;EACT,CAAC,GACKG,oBAAoBrB,iBAAiB;GACzCQ,SAASJ,SAASI;GAClBM,OAAOK;EACT,CAAC;EAUD,AARmCtB,uBAAuBM,cAAc,CAAC,CAAC;GACxE,GAAGC;GACHI,SAAS;IACP,GAAGJ,SAASI;IACZC,WAAW;KAACI,QAAQO;KAAqBL,OAAOM;IAAiB;GACnE;EACF,CAEIC,MACFhB,gBAAgB;GACdO,QAAQO;GACRL,OAAOM;EACT;CAEJ;CAEA,OAAOf;AACT;AC3EA,SAAS6C,0BAA6C;CACpD,IAAIC,SAGEC,8BAAc,IAAIC,IAA6B;CAErD,SAASE,OAAOV,gBAAoC;EAClD,IAAIA,mBAAmBW,KAAAA,GACrB;EAGF,IAAMC,SAASL,YAAYR,IAAIC,cAAc;EAEzCY,eAAWD,KAAAA,GAIf,KAAK,IAAMT,YAAYU,QACrBV,SAAS;CAEb;CAEA,OAAO;EACLH,MAAMC,mBACJM,SAASN,mBAAmBA,iBAAiBM,QAAQT,WAAWc,KAAAA;EAClEV,eAAeD,gBAAgBE,aAAa;GAC1C,IAAIU,SAASL,YAAYR,IAAIC,cAAc;GAS3C,OAPIY,WAAWD,KAAAA,MACbC,yBAAS,IAAIH,IAAI,GACjBF,YAAYJ,IAAIH,gBAAgBY,MAAM,IAGxCA,OAAOC,IAAIX,QAAQ,SAEN;IAGX,AAFAU,OAAOE,OAAOZ,QAAQ,GAElBU,OAAOG,SAAS,KAClBR,YAAYO,OAAOd,cAAc;GAErC;EACF;EACAG,MAAMC,SAAS;GACb,IAAMY,WAAWV;GAKjBA,UAAUF,OACN;IAACJ,gBAAgBiB,cAAcb,KAAKR,IAAI;IAAGC,UAAUO,KAAKP;GAAQ,IAClEc,KAAAA,IAGFK,UAAUhB,mBAAmBM,SAASN,kBACtCgB,UAAUnB,aAAaS,SAAST,cAK9BmB,UAAUhB,mBAAmBM,SAASN,kBACxCU,OAAOM,UAAUhB,cAAc,GAGjCU,OAAOJ,SAASN,cAAc;EAChC;CACF;AACF;;;;;;;;AASA,SAASkB,4BACPC,iBACiB;CACjB,OAAO,CACLzC,eAAe;EACb2C,IAAI;EACJC,QAAQ,EAACC,UAAUC,YAAW;GAC5B,IAAMC,iBAAiB1C,cAAc;IACnC,GAAGwC;IACHG,SAAS;KACP,GAAGH,SAASG;KACZC,WAAWH,MAAM3B,SAAS8B;IAC5B;GACF,CAAC;GAED,IAAI,CAACF,gBACH,OAAO;GAGT,IAAMG,aAAaJ,MAAMI;GAEzB,IAAI,CAACA,YACH,OAAO;GAGT,IAAMC,gBAAgBnC,iBAAiB;IACrCoC,gBAAgBF,WAAWD;IAC3BJ;GACF,CAAC;GA+BD,OA7BsBvC,kBAAkB;IACtC,GAAGuC;IACHG,SAAS;KACP,GAAGH,SAASG;KACZC,WAAWE;IACb;GACF,CAGEE,CAAa,CAACC,MACXC,iBACCA,aAAaC,KAAKC,SAASV,eAAeS,KAAKC,IACnD,KAaE,CARyBlD,wBAAwB;IACnD,GAAGsC;IACHG,SAAS;KACP,GAAGH,SAASG;KACZC,WAAWE;IACb;GACF,CAEKO,IACI,KAGF,EAACX,eAAc;EACxB;EACAY,SAAS,EACN,EAACb,SAAQ,EAACC,qBAAoB,CAC7B9C,aAAa;GACXwC,gBAAgB;IACdvB,MAAM6B,eAAe7B;IACrBC,UAAU2B,MAAM3B,SAASyC;GAC3B,CAAC;EACH,CAAC,GACD1D,QAAQ4C,KAAK,CAAC,CACf;CAEL,CAAC,GACD9C,eAAe;EACb2C,IAAI;EACJC,QAAQ,EAACE,YAAWA,MAAMe,SAAS;EACnCF,SAAS,EACN,EAACb,YAAW,CACX7C,aAAa;GACXwC,gBAAgBR,KAAAA,CAAS;EAC3B,CAAC,GACD/B,QAAQ4C,KAAK,CAAC,CACf;CAEL,CAAC,CAAC;AAEN;AAEA,MAAMgB,aAAarD,cAA6CwB,KAAAA,CAAS;;;;;;;;;;;;;;;;;;;AAoBzE,SAAO8B,YAAAC,OAAA;CAAA,IAAAC,IAAAC,EAAA,CAAA,GAAAC;CAAA,AAAAF,EAAA,OAAAG,OAAAC,IAAA,2BAAA,KACuBF,KAAAxC,wBAAwB,GAACsC,EAAA,KAAAE,MAAAA,KAAAF,EAAA;CAArD,IAAAK,QAA4BH,IAA8BI;CAAA,AAAAN,EAAA,OAAAG,OAAAC,IAAA,2BAAA,KAElDE,KAAA/B,4BAA4B8B,MAAK7C,GAAI,GAACwC,EAAA,KAAAM,MAAAA,KAAAN,EAAA;CAD9C,IAAAO,YACQD,IAEPE,IAAAC;CAED9D,AAFCqD,EAAA,OAAAG,OAAAC,IAAA,2BAAA,KAESI,iBACD;EAGLH,MAAK7C,IAAKQ,KAAAA,CAAS;CAAC,GAErByC,KAAA,CAACJ,KAAK,GAACL,EAAA,KAAAQ,IAAAR,EAAA,KAAAS,OAAAD,KAAAR,EAAA,IAAAS,KAAAT,EAAA,KANVrD,UAAU6D,IAMPC,EAAO;CAAC,IAAAC;CAAA,AAAAV,EAAA,OAAAG,OAAAC,IAAA,2BAAA,KAIPM,KAAA,oBAAC,gBAAD,EAA2BH,UAAS,CAAA,GAAIP,EAAA,KAAAU,MAAAA,KAAAV,EAAA;CAAA,IAAAW;CAEpB,OAFoBX,EAAA,OAAAD,MAAAa,WAEpBD,KAAAX,EAAA,MAHtBW,KAAA,qBAAA,WAAA,UAAA;EAA4BN,OAAAA;EAA5B,UAAA,CACEK,IACCX,MAAKa,QACR;KAAsBZ,EAAA,KAAAD,MAAAa,UAAAZ,EAAA,KAAAW,KAHtBA;AAGsB;;;;;;;;;;;AAc1B,SAAOE,gBAAA5D,MAAA;CAAA,IAAA+C,IAAAC,EAAA,CAAA,GAGLI,QAAc3D,WAAWmD,UAAU;CAEnC,IAAIQ,UAAUrC,KAAAA,GACZ,MAAU8C,MAAM,oDAAoD;CACrE,IAAAZ;CAAA,AAAAF,EAAA,OAAA/C,OAKyCiD,KAAAF,EAAA,MAAnBE,KAAA5B,cAAcrB,IAAI,GAAC+C,EAAA,KAAA/C,MAAA+C,EAAA,KAAAE;CAA1C,IAAA7C,iBAAuB6C,IAAmBI;CAAA,AAAAN,EAAA,OAAA3C,kBAAA2C,EAAA,OAAAK,SAGxCC,MAAA/C,aAA0B8C,MAAK/C,aAAcD,gBAAgBE,QAAQ,GAACyC,EAAA,KAAA3C,gBAAA2C,EAAA,KAAAK,OAAAL,EAAA,KAAAM,MAAAA,KAAAN,EAAA;CADxE,IAAAe,YAAkBT,IAGjBE;CAAA,AAAAR,EAAA,OAAA3C,kBAAA2C,EAAA,OAAAK,SAEmBG,WAAMH,MAAKjD,IAAKC,cAAc,GAAC2C,EAAA,KAAA3C,gBAAA2C,EAAA,KAAAK,OAAAL,EAAA,KAAAQ,MAAAA,KAAAR,EAAA;CAAnD,IAAAgB,cAAoBR;CAA+B,OAE5C3D,qBAAqBkE,WAAWC,aAAaA,WAAW;AAAC;;;;;;AAQlE,SAAS1C,cAAcrB,MAAoB;CACzC,OAAOA,KAAKgE,QAAgBC,QAAQC,SAASC,UACvC7E,eAAe4E,OAAO,IACjB,GAAGD,OAAM,UAAWC,QAAQ3B,KAAI,MAIlC,GAAG0B,SADQE,UAAU,IAAI,KAAK,MACND,WAC9B,EAAE;AACP"}
1
+ {"version":3,"file":"index.js","names":["createDropPositionStore(() => {\n const editorElement = editor.dom.getEditorElement()\n return editorElement instanceof HTMLElement ? editorElement : undefined\n })","editor.dom","useMemo(\n () =>\n createDropPositionStore(() => {\n const editorElement = editor.dom.getEditorElement()\n return editorElement instanceof HTMLElement ? editorElement : undefined\n }),\n [editor],\n )","createDropPositionBehaviors(store.set)","set","useMemo(\n () => createDropPositionBehaviors(store.set),\n [store],\n )","() => {\n return () => {\n // A drag in progress when the provider unmounts never delivers its\n // clearing event.\n store.set(undefined)\n }\n }","[store]","<BehaviorPlugin behaviors={behaviors} />","<DndContext.Provider value={store}>\n <BehaviorPlugin behaviors={behaviors} />\n {props.children}\n </DndContext.Provider>","children","DndContext.Provider","serializePath(path)","(callback: () => void) => store.subscribeKey(serializedPath, callback)","useCallback(\n (callback: () => void) => store.subscribeKey(serializedPath, callback),\n [store, serializedPath],\n )","() => store.get(serializedPath)"],"sources":["../src/drag-selection.ts","../src/plugin.dnd.tsx"],"sourcesContent":["import type {EditorSelection, EditorSnapshot} from '@portabletext/editor'\nimport {\n getFocusInlineObject,\n getFocusSpan,\n getFocusTextBlock,\n getFragment,\n getSelectionEndBlock,\n getSelectionStartBlock,\n isOverlappingSelection,\n isSelectionCollapsed,\n isSelectionExpanded,\n} from '@portabletext/editor/selectors'\nimport {getBlockEndPoint, getBlockStartPoint} from '@portabletext/editor/utils'\n\n/**\n * Given the current editor `snapshot` and an `eventSelection` representing\n * where the drag event originates from, calculate the selection in the\n * editor that should be dragged.\n *\n * Duplicated from the editor's internal `getDragSelection` rather than\n * imported: exporting it from core would add permanent public API for what\n * is an implementation detail of this plugin. Built on public selectors\n * only. Keep in sync with\n * `packages/editor/src/selectors/drag-selection.ts`.\n */\nexport function getDragSelection({\n eventSelection,\n snapshot,\n}: {\n eventSelection: NonNullable<EditorSelection>\n snapshot: EditorSnapshot\n}): NonNullable<EditorSelection> {\n let dragSelection = eventSelection\n\n const draggedInlineObject = getFocusInlineObject({\n ...snapshot,\n context: {\n ...snapshot.context,\n selection: eventSelection,\n },\n })\n\n if (draggedInlineObject) {\n return dragSelection\n }\n\n const draggingCollapsedSelection = isSelectionCollapsed({\n ...snapshot,\n context: {\n ...snapshot.context,\n selection: eventSelection,\n },\n })\n const draggedTextBlock = getFocusTextBlock({\n ...snapshot,\n context: {\n ...snapshot.context,\n selection: eventSelection,\n },\n })\n const draggedSpan = getFocusSpan({\n ...snapshot,\n context: {\n ...snapshot.context,\n selection: eventSelection,\n },\n })\n\n if (draggingCollapsedSelection && draggedTextBlock && draggedSpan) {\n // Looks like we are dragging an empty span\n // Let's drag the entire block instead\n dragSelection = {\n anchor: getBlockStartPoint({\n context: snapshot.context,\n block: draggedTextBlock,\n }),\n focus: getBlockEndPoint({\n context: snapshot.context,\n block: draggedTextBlock,\n }),\n }\n }\n\n const selectedBlocks = getFragment(snapshot)\n\n if (\n snapshot.context.selection &&\n isSelectionExpanded(snapshot) &&\n selectedBlocks.length > 1\n ) {\n const selectionStartBlock = getSelectionStartBlock(snapshot)\n const selectionEndBlock = getSelectionEndBlock(snapshot)\n\n if (!selectionStartBlock || !selectionEndBlock) {\n return dragSelection\n }\n\n const selectionStartPoint = getBlockStartPoint({\n context: snapshot.context,\n block: selectionStartBlock,\n })\n const selectionEndPoint = getBlockEndPoint({\n context: snapshot.context,\n block: selectionEndBlock,\n })\n\n const eventSelectionInsideBlocks = isOverlappingSelection(eventSelection)({\n ...snapshot,\n context: {\n ...snapshot.context,\n selection: {anchor: selectionStartPoint, focus: selectionEndPoint},\n },\n })\n\n if (eventSelectionInsideBlocks) {\n dragSelection = {\n anchor: selectionStartPoint,\n focus: selectionEndPoint,\n }\n }\n }\n\n return dragSelection\n}\n","import {useEditor, type Path} from '@portabletext/editor'\nimport {\n defineBehavior,\n effect,\n forward,\n type Behavior,\n} from '@portabletext/editor/behaviors'\nimport {BehaviorPlugin} from '@portabletext/editor/plugins'\nimport {\n getFocusBlock,\n getFocusInlineObject,\n getFocusTextBlock,\n getSelectedBlocks,\n isSelectingEntireBlocks,\n} from '@portabletext/editor/selectors'\nimport {\n getBlockEndPoint,\n getBlockStartPoint,\n isEmptyTextBlock,\n isEqualPaths,\n isEqualSelectionPoints,\n isKeyedSegment,\n isSelectionCollapsed,\n} from '@portabletext/editor/utils'\nimport {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useSyncExternalStore,\n type ReactNode,\n} from 'react'\nimport {getDragSelection} from './drag-selection'\n\n/**\n * The block-relative position a drop would land at.\n *\n * @beta\n */\nexport type DropPosition = {\n path: Path\n position: 'start' | 'end'\n}\n\n/**\n * One store per editor: the drag behaviors below maintain the current drop\n * position, and per-path subscriber buckets make notification O(changed\n * paths) rather than O(subscribers). `dragover` fires at mousemove\n * frequency, so only the block losing and the block gaining the indicator\n * re-render.\n */\ntype DropPositionStore = {\n get: (serializedPath: string) => DropPosition['position'] | undefined\n subscribeKey: (serializedPath: string, callback: () => void) => () => void\n set: (next: DropPosition | undefined) => void\n}\n\nfunction createDropPositionStore(\n getEditorElement: () => HTMLElement | undefined,\n): DropPositionStore {\n let current:\n | {serializedPath: string; position: DropPosition['position']}\n | undefined\n let restoreCaretColor: (() => void) | undefined\n const subscribers = new Map<string, Set<() => void>>()\n\n function notify(serializedPath: string | undefined) {\n if (serializedPath === undefined) {\n return\n }\n\n const bucket = subscribers.get(serializedPath)\n\n if (bucket === undefined) {\n return\n }\n\n for (const callback of bucket) {\n callback()\n }\n }\n\n return {\n get: (serializedPath) =>\n current?.serializedPath === serializedPath ? current.position : undefined,\n subscribeKey: (serializedPath, callback) => {\n let bucket = subscribers.get(serializedPath)\n\n if (bucket === undefined) {\n bucket = new Set()\n subscribers.set(serializedPath, bucket)\n }\n\n bucket.add(callback)\n\n return () => {\n bucket.delete(callback)\n\n if (bucket.size === 0) {\n subscribers.delete(serializedPath)\n }\n }\n },\n set: (next) => {\n const previous = current\n\n // Swap before notifying: `useSyncExternalStore` re-reads the snapshot\n // synchronously on notification and skips the re-render when it reads\n // an unchanged (stale) value.\n current = next\n ? {serializedPath: serializePath(next.path), position: next.position}\n : undefined\n\n const editorElement = getEditorElement()\n\n if (editorElement) {\n if (current && !restoreCaretColor) {\n const previousCaretColor = editorElement.style.caretColor\n restoreCaretColor = () => {\n editorElement.style.caretColor = previousCaretColor\n }\n // The native drop caret renders at the hovered text position and\n // promises a mid-text split, but an edge indicator means the drop\n // will snap to the block edge instead.\n editorElement.style.caretColor = 'transparent'\n } else if (!current && restoreCaretColor) {\n restoreCaretColor()\n restoreCaretColor = undefined\n }\n }\n\n if (\n previous?.serializedPath === current?.serializedPath &&\n previous?.position === current?.position\n ) {\n return\n }\n\n if (previous?.serializedPath !== current?.serializedPath) {\n notify(previous?.serializedPath)\n }\n\n notify(current?.serializedPath)\n },\n }\n}\n\n/**\n * The behaviors observe the public `drag.*` events and `forward` every\n * event they handle: consumer behaviors run before the editor's own drag\n * handling, so omitting the forward would swallow the event and break the\n * drag itself. (The editor's internal drop-position tracking gets away\n * without forwarding because it registers below core priority.)\n */\nfunction createDropPositionBehaviors(\n setDropPosition: (next: DropPosition | undefined) => void,\n): Array<Behavior> {\n return [\n defineBehavior({\n on: 'drag.dragover',\n guard: ({snapshot, event}) => {\n const dropFocusBlock = getFocusBlock({\n ...snapshot,\n context: {\n ...snapshot.context,\n selection: event.position.selection,\n },\n })\n\n if (!dropFocusBlock) {\n return false\n }\n\n const dragOrigin = event.dragOrigin\n\n if (!dragOrigin) {\n return false\n }\n\n const dragSelection = getDragSelection({\n eventSelection: dragOrigin.selection,\n snapshot,\n })\n const dragSnapshot = {\n ...snapshot,\n context: {\n ...snapshot.context,\n selection: dragSelection,\n },\n }\n\n const draggedBlocks = getSelectedBlocks(dragSnapshot)\n // `getSelectedBlocks` only looks at root-level children, so a drag\n // origin nested inside a container (a callout paragraph, a table\n // cell) resolves to the container, not the nested block actually\n // being dragged. `getFocusBlock` resolves the origin's own focus to\n // the same depth `dropFocusBlock` was resolved to, so comparing the\n // two catches a nested block dragged over itself too.\n const draggedFocusBlock = getFocusBlock(dragSnapshot)\n\n const selfDrop =\n draggedBlocks.some(\n (draggedBlock) =>\n draggedBlock.node._key === dropFocusBlock.node._key,\n ) ||\n (draggedFocusBlock !== undefined &&\n isEqualPaths(draggedFocusBlock.path, dropFocusBlock.path))\n\n if (selfDrop) {\n // Core cancels the drop, so no position is valid here, including\n // one left over from the previous hover.\n return {dropFocusBlock, droppedInsideTextBlock: false, clear: true}\n }\n\n const draggingEntireBlocks = isSelectingEntireBlocks({\n ...snapshot,\n context: {\n ...snapshot.context,\n selection: dragSelection,\n },\n })\n\n if (!draggingEntireBlocks) {\n return false\n }\n\n const dropSnapshot = {\n ...snapshot,\n context: {\n ...snapshot.context,\n selection: event.position.selection,\n },\n }\n const focusTextBlock = getFocusTextBlock(dropSnapshot)\n // A collapsed drop strictly inside a non-empty text block already\n // shows the browser's own drop caret there.\n const droppedInsideTextBlock =\n isSelectionCollapsed(event.position.selection) &&\n focusTextBlock !== undefined &&\n !isEmptyTextBlock(snapshot.context, focusTextBlock.node) &&\n getFocusInlineObject(dropSnapshot) === undefined &&\n !isEqualSelectionPoints(\n event.position.selection.focus,\n getBlockStartPoint({\n context: snapshot.context,\n block: focusTextBlock,\n }),\n ) &&\n !isEqualSelectionPoints(\n event.position.selection.focus,\n getBlockEndPoint({\n context: snapshot.context,\n block: focusTextBlock,\n }),\n )\n\n return {dropFocusBlock, droppedInsideTextBlock, clear: false}\n },\n actions: [\n ({event}, {dropFocusBlock, droppedInsideTextBlock, clear}) => [\n effect(() => {\n setDropPosition(\n clear || droppedInsideTextBlock\n ? undefined\n : {\n path: dropFocusBlock.path,\n position: event.position.block,\n },\n )\n }),\n forward(event),\n ],\n ],\n }),\n defineBehavior({\n on: 'drag.*',\n guard: ({event}) => event.type !== 'drag.dragover',\n actions: [\n ({event}) => [\n effect(() => {\n setDropPosition(undefined)\n }),\n forward(event),\n ],\n ],\n }),\n ]\n}\n\nconst DndContext = createContext<DropPositionStore | undefined>(undefined)\n\n/**\n * Tracks the drop position during drag and drop and serves it through\n * context. Mount inside `EditorProvider`, wrapping whatever reads the\n * position:\n *\n * ```tsx\n * <EditorProvider initialConfig={...}>\n * <DndProvider>\n * <PortableTextEditable />\n * </DndProvider>\n * </EditorProvider>\n * ```\n *\n * Reads via {@link useDropPosition} only re-render when the drop position\n * at their own path changes.\n *\n * @beta\n */\nexport function DndProvider(props: {children?: ReactNode}) {\n const editor = useEditor()\n const store = useMemo(\n () =>\n createDropPositionStore(() => {\n const editorElement = editor.dom.getEditorElement()\n return editorElement instanceof HTMLElement ? editorElement : undefined\n }),\n [editor],\n )\n const behaviors = useMemo(\n () => createDropPositionBehaviors(store.set),\n [store],\n )\n\n useEffect(() => {\n return () => {\n // A drag in progress when the provider unmounts never delivers its\n // clearing event.\n store.set(undefined)\n }\n }, [store])\n\n return (\n <DndContext.Provider value={store}>\n <BehaviorPlugin behaviors={behaviors} />\n {props.children}\n </DndContext.Provider>\n )\n}\n\n/**\n * Read where a drop would land relative to the block at `path`: `'start'`,\n * `'end'`, or `undefined` when no drag is hovering this block. Re-renders\n * only when the position at this path changes.\n *\n * `path` is the keyed block path render callbacks receive, e.g.\n * `[{_key: 'b0'}]`.\n *\n * @beta\n */\nexport function useDropPosition(\n path: Path,\n): DropPosition['position'] | undefined {\n const store = useContext(DndContext)\n\n if (store === undefined) {\n throw new Error('useDropPosition must be used below a <DndProvider>')\n }\n\n // Callers typically pass a fresh `path` array every render, so the\n // serialized string, not the array, is what keeps `subscribe` stable\n // below.\n const serializedPath = serializePath(path)\n\n const subscribe = useCallback(\n (callback: () => void) => store.subscribeKey(serializedPath, callback),\n [store, serializedPath],\n )\n\n const getSnapshot = () => store.get(serializedPath)\n\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot)\n}\n\n/**\n * Serialize a keyed path to a string using Sanity's bracket notation.\n * Duplicated from the editor's internal `serializePath`; see\n * `drag-selection.ts` for the duplication rationale.\n */\nfunction serializePath(path: Path): string {\n return path.reduce<string>((result, segment, index) => {\n if (isKeyedSegment(segment)) {\n return `${result}[_key==\"${segment._key}\"]`\n }\n\n const separator = index === 0 ? '' : '.'\n return `${result}${separator}${segment}`\n }, '')\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@portabletext/plugin-dnd",
3
- "version": "1.0.34",
3
+ "version": "2.0.0",
4
4
  "description": "Track the drop position during drag and drop for custom drop indicators",
5
5
  "keywords": [
6
6
  "dnd",
@@ -25,50 +25,41 @@
25
25
  ],
26
26
  "type": "module",
27
27
  "sideEffects": false,
28
- "main": "./dist/index.js",
29
- "module": "./dist/index.js",
30
28
  "types": "./dist/index.d.ts",
31
29
  "exports": {
32
30
  ".": "./dist/index.js",
33
31
  "./package.json": "./package.json"
34
32
  },
35
33
  "devDependencies": {
36
- "@rolldown/plugin-babel": "^0.2.3",
37
- "@sanity/pkg-utils": "^12.1.0",
34
+ "@sanity/pkg-utils": "^12.3.0",
38
35
  "@sanity/tsconfig": "^2.1.0",
39
36
  "@types/react": "^19.2.17",
40
37
  "@types/react-dom": "^19.2.3",
41
- "@vitejs/plugin-react": "^6.0.5",
38
+ "@vitejs/plugin-react": "^6.1.0",
42
39
  "@vitest/browser": "^4.1.10",
43
40
  "@vitest/browser-playwright": "^4.1.10",
44
- "babel-plugin-react-compiler": "^1.0.0",
45
- "eslint": "^9.39.4",
46
- "eslint-plugin-react-hooks": "^7.1.1",
41
+ "oxc-transform-react": "^0.145.0",
47
42
  "react": "^19.2.8",
48
- "typescript": "6.0.3",
49
- "typescript-eslint": "^8.62.0",
43
+ "typescript": "^7.0.2",
50
44
  "vite": "^8.2.0",
51
45
  "vitest": "^4.1.10",
52
- "@portabletext/editor": "^7.12.1",
53
- "@portabletext/schema": "^2.2.4",
54
- "@portabletext/test": "^1.0.5"
46
+ "@portabletext/editor": "^8.0.0",
47
+ "@portabletext/schema": "^3.0.0",
48
+ "@portabletext/test": "^2.0.0"
55
49
  },
56
50
  "peerDependencies": {
57
51
  "react": "^19.2",
58
- "@portabletext/editor": "^7.12.1"
52
+ "@portabletext/editor": "^8.0.0"
59
53
  },
60
54
  "engines": {
61
- "node": ">=20.19 <22 || >=22.12"
55
+ "node": ">=22.12"
62
56
  },
63
57
  "scripts": {
64
58
  "build": "pkg-utils build --strict --check",
65
- "check:lint": "biome lint .",
66
- "check:react-compiler": "eslint .",
67
59
  "check:types": "tsc",
68
60
  "check:types:watch": "tsc --watch",
69
61
  "clean": "del .turbo && del dist && del node_modules",
70
62
  "dev": "pkg-utils watch",
71
- "lint:fix": "biome lint --write .",
72
63
  "test:browser": "vitest --run --project browser",
73
64
  "test:browser:chromium": "vitest --run --project \"browser (chromium)\"",
74
65
  "test:unit": "vitest --run --project unit",