@portabletext/plugin-dnd 1.0.28 → 1.0.30
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/dist/index.d.ts +17 -21
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +213 -194
- package/dist/index.js.map +1 -1
- package/package.json +12 -10
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,14 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import { ReactNode } from "react";
|
|
2
|
+
import { Path } from "@portabletext/editor";
|
|
3
|
+
/**
|
|
4
|
+
* The block-relative position a drop would land at.
|
|
5
|
+
*
|
|
6
|
+
* @beta
|
|
7
|
+
*/
|
|
8
|
+
type DropPosition = {
|
|
9
|
+
path: Path;
|
|
10
|
+
position: 'start' | 'end';
|
|
11
|
+
};
|
|
5
12
|
/**
|
|
6
13
|
* Tracks the drop position during drag and drop and serves it through
|
|
7
14
|
* context. Mount inside `EditorProvider`, wrapping whatever reads the
|
|
@@ -20,18 +27,9 @@ import {ReactNode} from 'react'
|
|
|
20
27
|
*
|
|
21
28
|
* @beta
|
|
22
29
|
*/
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
* The block-relative position a drop would land at.
|
|
27
|
-
*
|
|
28
|
-
* @beta
|
|
29
|
-
*/
|
|
30
|
-
export declare type DropPosition = {
|
|
31
|
-
path: Path
|
|
32
|
-
position: 'start' | 'end'
|
|
33
|
-
}
|
|
34
|
-
|
|
30
|
+
declare function DndProvider(props: {
|
|
31
|
+
children?: ReactNode;
|
|
32
|
+
}): import("react").JSX.Element;
|
|
35
33
|
/**
|
|
36
34
|
* Read where a drop would land relative to the block at `path`: `'start'`,
|
|
37
35
|
* `'end'`, or `undefined` when no drag is hovering this block. Re-renders
|
|
@@ -42,8 +40,6 @@ export declare type DropPosition = {
|
|
|
42
40
|
*
|
|
43
41
|
* @beta
|
|
44
42
|
*/
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
export {}
|
|
43
|
+
declare function useDropPosition(path: Path): DropPosition['position'] | undefined;
|
|
44
|
+
export { DndProvider, type DropPosition, useDropPosition };
|
|
45
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +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"}
|
package/dist/index.js
CHANGED
|
@@ -1,210 +1,229 @@
|
|
|
1
|
-
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
1
|
import { c } from "react/compiler-runtime";
|
|
3
2
|
import { defineBehavior, effect, forward } from "@portabletext/editor/behaviors";
|
|
4
3
|
import { BehaviorPlugin } from "@portabletext/editor/plugins";
|
|
5
|
-
import { getFocusInlineObject,
|
|
4
|
+
import { getFocusBlock, getFocusInlineObject, getFocusSpan, getFocusTextBlock, getFragment, getSelectedBlocks, getSelectionEndBlock, getSelectionStartBlock, isOverlappingSelection, isSelectingEntireBlocks, isSelectionCollapsed, isSelectionExpanded } from "@portabletext/editor/selectors";
|
|
6
5
|
import { getBlockEndPoint, getBlockStartPoint, isKeyedSegment } from "@portabletext/editor/utils";
|
|
7
|
-
import { createContext,
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
6
|
+
import { createContext, useContext, useEffect, useSyncExternalStore } from "react";
|
|
7
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
8
|
+
/**
|
|
9
|
+
* Given the current editor `snapshot` and an `eventSelection` representing
|
|
10
|
+
* where the drag event originates from, calculate the selection in the
|
|
11
|
+
* editor that should be dragged.
|
|
12
|
+
*
|
|
13
|
+
* Duplicated from the editor's internal `getDragSelection` rather than
|
|
14
|
+
* imported: exporting it from core would add permanent public API for what
|
|
15
|
+
* is an implementation detail of this plugin. Built on public selectors
|
|
16
|
+
* only. Keep in sync with
|
|
17
|
+
* `packages/editor/src/selectors/drag-selection.ts`.
|
|
18
|
+
*/
|
|
19
|
+
function getDragSelection({ eventSelection, snapshot }) {
|
|
20
|
+
let dragSelection = eventSelection;
|
|
21
|
+
if (getFocusInlineObject({
|
|
22
|
+
...snapshot,
|
|
23
|
+
context: {
|
|
24
|
+
...snapshot.context,
|
|
25
|
+
selection: eventSelection
|
|
26
|
+
}
|
|
27
|
+
})) return dragSelection;
|
|
28
|
+
let draggingCollapsedSelection = isSelectionCollapsed({
|
|
29
|
+
...snapshot,
|
|
30
|
+
context: {
|
|
31
|
+
...snapshot.context,
|
|
32
|
+
selection: eventSelection
|
|
33
|
+
}
|
|
34
|
+
}), draggedTextBlock = getFocusTextBlock({
|
|
35
|
+
...snapshot,
|
|
36
|
+
context: {
|
|
37
|
+
...snapshot.context,
|
|
38
|
+
selection: eventSelection
|
|
39
|
+
}
|
|
40
|
+
}), draggedSpan = getFocusSpan({
|
|
41
|
+
...snapshot,
|
|
42
|
+
context: {
|
|
43
|
+
...snapshot.context,
|
|
44
|
+
selection: eventSelection
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
draggingCollapsedSelection && draggedTextBlock && draggedSpan && (dragSelection = {
|
|
48
|
+
anchor: getBlockStartPoint({
|
|
49
|
+
context: snapshot.context,
|
|
50
|
+
block: draggedTextBlock
|
|
51
|
+
}),
|
|
52
|
+
focus: getBlockEndPoint({
|
|
53
|
+
context: snapshot.context,
|
|
54
|
+
block: draggedTextBlock
|
|
55
|
+
})
|
|
56
|
+
});
|
|
57
|
+
let selectedBlocks = getFragment(snapshot);
|
|
58
|
+
if (snapshot.context.selection && isSelectionExpanded(snapshot) && selectedBlocks.length > 1) {
|
|
59
|
+
let selectionStartBlock = getSelectionStartBlock(snapshot), selectionEndBlock = getSelectionEndBlock(snapshot);
|
|
60
|
+
if (!selectionStartBlock || !selectionEndBlock) return dragSelection;
|
|
61
|
+
let selectionStartPoint = getBlockStartPoint({
|
|
62
|
+
context: snapshot.context,
|
|
63
|
+
block: selectionStartBlock
|
|
64
|
+
}), selectionEndPoint = getBlockEndPoint({
|
|
65
|
+
context: snapshot.context,
|
|
66
|
+
block: selectionEndBlock
|
|
67
|
+
});
|
|
68
|
+
isOverlappingSelection(eventSelection)({
|
|
69
|
+
...snapshot,
|
|
70
|
+
context: {
|
|
71
|
+
...snapshot.context,
|
|
72
|
+
selection: {
|
|
73
|
+
anchor: selectionStartPoint,
|
|
74
|
+
focus: selectionEndPoint
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}) && (dragSelection = {
|
|
78
|
+
anchor: selectionStartPoint,
|
|
79
|
+
focus: selectionEndPoint
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
return dragSelection;
|
|
77
83
|
}
|
|
78
84
|
function createDropPositionStore() {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
position: next.position
|
|
102
|
-
} : void 0, !(previous?.serializedPath === current?.serializedPath && previous?.position === current?.position) && (previous?.serializedPath !== current?.serializedPath && notify(previous?.serializedPath), notify(current?.serializedPath));
|
|
103
|
-
}
|
|
104
|
-
};
|
|
85
|
+
let current, subscribers = /* @__PURE__ */ new Map();
|
|
86
|
+
function notify(serializedPath) {
|
|
87
|
+
if (serializedPath === void 0) return;
|
|
88
|
+
let bucket = subscribers.get(serializedPath);
|
|
89
|
+
if (bucket !== void 0) for (let callback of bucket) callback();
|
|
90
|
+
}
|
|
91
|
+
return {
|
|
92
|
+
get: (serializedPath) => current?.serializedPath === serializedPath ? current.position : void 0,
|
|
93
|
+
subscribeKey: (serializedPath, callback) => {
|
|
94
|
+
let bucket = subscribers.get(serializedPath);
|
|
95
|
+
return bucket === void 0 && (bucket = /* @__PURE__ */ new Set(), subscribers.set(serializedPath, bucket)), bucket.add(callback), () => {
|
|
96
|
+
bucket.delete(callback), bucket.size === 0 && subscribers.delete(serializedPath);
|
|
97
|
+
};
|
|
98
|
+
},
|
|
99
|
+
set: (next) => {
|
|
100
|
+
let previous = current;
|
|
101
|
+
current = next ? {
|
|
102
|
+
serializedPath: serializePath(next.path),
|
|
103
|
+
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
|
+
}
|
|
106
|
+
};
|
|
105
107
|
}
|
|
108
|
+
/**
|
|
109
|
+
* The behaviors observe the public `drag.*` events and `forward` every
|
|
110
|
+
* event they handle: consumer behaviors run before the editor's own drag
|
|
111
|
+
* handling, so omitting the forward would swallow the event and break the
|
|
112
|
+
* drag itself. (The editor's internal drop-position tracking gets away
|
|
113
|
+
* without forwarding because it registers below core priority.)
|
|
114
|
+
*/
|
|
106
115
|
function createDropPositionBehaviors(setDropPosition) {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
path: dropFocusBlock.path,
|
|
152
|
-
position: event.position.block
|
|
153
|
-
});
|
|
154
|
-
}), forward(event)]]
|
|
155
|
-
}), defineBehavior({
|
|
156
|
-
on: "drag.*",
|
|
157
|
-
guard: ({
|
|
158
|
-
event
|
|
159
|
-
}) => event.type !== "drag.dragover",
|
|
160
|
-
actions: [({
|
|
161
|
-
event
|
|
162
|
-
}) => [effect(() => {
|
|
163
|
-
setDropPosition(void 0);
|
|
164
|
-
}), forward(event)]]
|
|
165
|
-
})];
|
|
116
|
+
return [defineBehavior({
|
|
117
|
+
on: "drag.dragover",
|
|
118
|
+
guard: ({ snapshot, event }) => {
|
|
119
|
+
let dropFocusBlock = getFocusBlock({
|
|
120
|
+
...snapshot,
|
|
121
|
+
context: {
|
|
122
|
+
...snapshot.context,
|
|
123
|
+
selection: event.position.selection
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
if (!dropFocusBlock) return !1;
|
|
127
|
+
let dragOrigin = event.dragOrigin;
|
|
128
|
+
if (!dragOrigin) return !1;
|
|
129
|
+
let dragSelection = getDragSelection({
|
|
130
|
+
eventSelection: dragOrigin.selection,
|
|
131
|
+
snapshot
|
|
132
|
+
});
|
|
133
|
+
return getSelectedBlocks({
|
|
134
|
+
...snapshot,
|
|
135
|
+
context: {
|
|
136
|
+
...snapshot.context,
|
|
137
|
+
selection: dragSelection
|
|
138
|
+
}
|
|
139
|
+
}).some((draggedBlock) => draggedBlock.node._key === dropFocusBlock.node._key) || !isSelectingEntireBlocks({
|
|
140
|
+
...snapshot,
|
|
141
|
+
context: {
|
|
142
|
+
...snapshot.context,
|
|
143
|
+
selection: dragSelection
|
|
144
|
+
}
|
|
145
|
+
}) ? !1 : { dropFocusBlock };
|
|
146
|
+
},
|
|
147
|
+
actions: [({ event }, { dropFocusBlock }) => [effect(() => {
|
|
148
|
+
setDropPosition({
|
|
149
|
+
path: dropFocusBlock.path,
|
|
150
|
+
position: event.position.block
|
|
151
|
+
});
|
|
152
|
+
}), forward(event)]]
|
|
153
|
+
}), defineBehavior({
|
|
154
|
+
on: "drag.*",
|
|
155
|
+
guard: ({ event }) => event.type !== "drag.dragover",
|
|
156
|
+
actions: [({ event }) => [effect(() => {
|
|
157
|
+
setDropPosition(void 0);
|
|
158
|
+
}), forward(event)]]
|
|
159
|
+
})];
|
|
166
160
|
}
|
|
167
161
|
const DndContext = createContext(void 0);
|
|
162
|
+
/**
|
|
163
|
+
* Tracks the drop position during drag and drop and serves it through
|
|
164
|
+
* context. Mount inside `EditorProvider`, wrapping whatever reads the
|
|
165
|
+
* position:
|
|
166
|
+
*
|
|
167
|
+
* ```tsx
|
|
168
|
+
* <EditorProvider initialConfig={...}>
|
|
169
|
+
* <DndProvider>
|
|
170
|
+
* <PortableTextEditable />
|
|
171
|
+
* </DndProvider>
|
|
172
|
+
* </EditorProvider>
|
|
173
|
+
* ```
|
|
174
|
+
*
|
|
175
|
+
* Reads via {@link useDropPosition} only re-render when the drop position
|
|
176
|
+
* at their own path changes.
|
|
177
|
+
*
|
|
178
|
+
* @beta
|
|
179
|
+
*/
|
|
168
180
|
function DndProvider(props) {
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
t4,
|
|
185
|
-
props.children
|
|
186
|
-
] }), $[5] = props.children, $[6] = t5) : t5 = $[6], t5;
|
|
181
|
+
let $ = c(7), t0;
|
|
182
|
+
$[0] === Symbol.for("react.memo_cache_sentinel") ? (t0 = createDropPositionStore(), $[0] = t0) : t0 = $[0];
|
|
183
|
+
let store = t0, t1;
|
|
184
|
+
$[1] === Symbol.for("react.memo_cache_sentinel") ? (t1 = createDropPositionBehaviors(store.set), $[1] = t1) : t1 = $[1];
|
|
185
|
+
let behaviors = t1, t2, t3;
|
|
186
|
+
$[2] === Symbol.for("react.memo_cache_sentinel") ? (t2 = () => () => {
|
|
187
|
+
store.set(void 0);
|
|
188
|
+
}, t3 = [store], $[2] = t2, $[3] = t3) : (t2 = $[2], t3 = $[3]), useEffect(t2, t3);
|
|
189
|
+
let t4;
|
|
190
|
+
$[4] === Symbol.for("react.memo_cache_sentinel") ? (t4 = /* @__PURE__ */ jsx(BehaviorPlugin, { behaviors }), $[4] = t4) : t4 = $[4];
|
|
191
|
+
let t5;
|
|
192
|
+
return $[5] === props.children ? t5 = $[6] : (t5 = /* @__PURE__ */ jsxs(DndContext.Provider, {
|
|
193
|
+
value: store,
|
|
194
|
+
children: [t4, props.children]
|
|
195
|
+
}), $[5] = props.children, $[6] = t5), t5;
|
|
187
196
|
}
|
|
197
|
+
/**
|
|
198
|
+
* Read where a drop would land relative to the block at `path`: `'start'`,
|
|
199
|
+
* `'end'`, or `undefined` when no drag is hovering this block. Re-renders
|
|
200
|
+
* only when the position at this path changes.
|
|
201
|
+
*
|
|
202
|
+
* `path` is the keyed block path render callbacks receive, e.g.
|
|
203
|
+
* `[{_key: 'b0'}]`.
|
|
204
|
+
*
|
|
205
|
+
* @beta
|
|
206
|
+
*/
|
|
188
207
|
function useDropPosition(path) {
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
$[5] !== serializedPath || $[6] !== store ? (t2 = () => store.get(serializedPath), $[5] = serializedPath, $[6] = store, $[7] = t2) : t2 = $[7];
|
|
200
|
-
const getSnapshot = t2;
|
|
201
|
-
return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
|
|
208
|
+
let $ = c(8), store = useContext(DndContext);
|
|
209
|
+
if (store === void 0) throw Error("useDropPosition must be used below a <DndProvider>");
|
|
210
|
+
let t0;
|
|
211
|
+
$[0] === path ? t0 = $[1] : (t0 = serializePath(path), $[0] = path, $[1] = t0);
|
|
212
|
+
let serializedPath = t0, t1;
|
|
213
|
+
$[2] !== serializedPath || $[3] !== store ? (t1 = (callback) => store.subscribeKey(serializedPath, callback), $[2] = serializedPath, $[3] = store, $[4] = t1) : t1 = $[4];
|
|
214
|
+
let subscribe = t1, t2;
|
|
215
|
+
$[5] !== serializedPath || $[6] !== store ? (t2 = () => store.get(serializedPath), $[5] = serializedPath, $[6] = store, $[7] = t2) : t2 = $[7];
|
|
216
|
+
let getSnapshot = t2;
|
|
217
|
+
return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
|
|
202
218
|
}
|
|
219
|
+
/**
|
|
220
|
+
* Serialize a keyed path to a string using Sanity's bracket notation.
|
|
221
|
+
* Duplicated from the editor's internal `serializePath`; see
|
|
222
|
+
* `drag-selection.ts` for the duplication rationale.
|
|
223
|
+
*/
|
|
203
224
|
function serializePath(path) {
|
|
204
|
-
|
|
225
|
+
return path.reduce((result, segment, index) => isKeyedSegment(segment) ? `${result}[_key=="${segment._key}"]` : `${result}${index === 0 ? "" : "."}${segment}`, "");
|
|
205
226
|
}
|
|
206
|
-
export {
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
};
|
|
210
|
-
//# sourceMappingURL=index.js.map
|
|
227
|
+
export { DndProvider, useDropPosition };
|
|
228
|
+
|
|
229
|
+
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","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"],"names":["getDragSelection","eventSelection","snapshot","dragSelection","getFocusInlineObject","context","selection","draggingCollapsedSelection","isSelectionCollapsed","draggedTextBlock","getFocusTextBlock","draggedSpan","getFocusSpan","anchor","getBlockStartPoint","block","focus","getBlockEndPoint","selectedBlocks","getFragment","isSelectionExpanded","length","selectionStartBlock","getSelectionStartBlock","selectionEndBlock","getSelectionEndBlock","selectionStartPoint","selectionEndPoint","isOverlappingSelection","createDropPositionStore","current","subscribers","Map","notify","serializedPath","undefined","bucket","get","callback","position","subscribeKey","Set","set","add","delete","size","next","previous","serializePath","path","createDropPositionBehaviors","setDropPosition","defineBehavior","on","guard","event","dropFocusBlock","getFocusBlock","dragOrigin","getSelectedBlocks","some","draggedBlock","node","_key","isSelectingEntireBlocks","actions","effect","forward","type","DndContext","createContext","DndProvider","props","$","_c","t0","Symbol","for","store","t1","behaviors","t2","t3","useEffect","t4","t5","children","useDropPosition","useContext","Error","subscribe","getSnapshot","useSyncExternalStore","reduce","result","segment","index","isKeyedSegment"],"mappings":"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"}
|
|
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":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@portabletext/plugin-dnd",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.30",
|
|
4
4
|
"description": "Track the drop position during drag and drop for custom drop indicators",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"dnd",
|
|
@@ -26,40 +26,42 @@
|
|
|
26
26
|
"type": "module",
|
|
27
27
|
"sideEffects": false,
|
|
28
28
|
"main": "./dist/index.js",
|
|
29
|
+
"module": "./dist/index.js",
|
|
29
30
|
"types": "./dist/index.d.ts",
|
|
30
31
|
"exports": {
|
|
31
32
|
".": "./dist/index.js",
|
|
32
33
|
"./package.json": "./package.json"
|
|
33
34
|
},
|
|
34
35
|
"devDependencies": {
|
|
35
|
-
"@
|
|
36
|
+
"@rolldown/plugin-babel": "^0.2.3",
|
|
37
|
+
"@sanity/pkg-utils": "^12.1.0",
|
|
36
38
|
"@sanity/tsconfig": "^2.1.0",
|
|
37
39
|
"@types/react": "^19.2.17",
|
|
38
40
|
"@types/react-dom": "^19.2.3",
|
|
39
|
-
"@vitejs/plugin-react": "^
|
|
41
|
+
"@vitejs/plugin-react": "^6.0.5",
|
|
40
42
|
"@vitest/browser": "^4.1.10",
|
|
41
43
|
"@vitest/browser-playwright": "^4.1.10",
|
|
42
44
|
"babel-plugin-react-compiler": "^1.0.0",
|
|
43
45
|
"eslint": "^9.39.4",
|
|
44
46
|
"eslint-plugin-react-hooks": "^7.1.1",
|
|
45
|
-
"react": "^19.2.
|
|
47
|
+
"react": "^19.2.8",
|
|
46
48
|
"typescript": "6.0.3",
|
|
47
49
|
"typescript-eslint": "^8.62.0",
|
|
48
|
-
"vite": "^
|
|
50
|
+
"vite": "^8.2.0",
|
|
49
51
|
"vitest": "^4.1.10",
|
|
50
|
-
"@portabletext/editor": "^7.10.
|
|
51
|
-
"@portabletext/schema": "^2.2.
|
|
52
|
-
"@portabletext/test": "^1.0.
|
|
52
|
+
"@portabletext/editor": "^7.10.18",
|
|
53
|
+
"@portabletext/schema": "^2.2.4",
|
|
54
|
+
"@portabletext/test": "^1.0.5"
|
|
53
55
|
},
|
|
54
56
|
"peerDependencies": {
|
|
55
57
|
"react": "^19.2",
|
|
56
|
-
"@portabletext/editor": "^7.10.
|
|
58
|
+
"@portabletext/editor": "^7.10.18"
|
|
57
59
|
},
|
|
58
60
|
"engines": {
|
|
59
61
|
"node": ">=20.19 <22 || >=22.12"
|
|
60
62
|
},
|
|
61
63
|
"scripts": {
|
|
62
|
-
"build": "pkg-utils build --strict --check
|
|
64
|
+
"build": "pkg-utils build --strict --check",
|
|
63
65
|
"check:lint": "biome lint .",
|
|
64
66
|
"check:react-compiler": "eslint .",
|
|
65
67
|
"check:types": "tsc",
|