@portabletext/plugin-list-index 1.0.2 → 1.0.4
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.js +21 -19
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -2,29 +2,36 @@ import { jsx } from "react/jsx-runtime";
|
|
|
2
2
|
import { c } from "react/compiler-runtime";
|
|
3
3
|
import { useEditor } from "@portabletext/editor";
|
|
4
4
|
import { createContext, useEffect, useContext, useSyncExternalStore } from "react";
|
|
5
|
+
import { getContainerChildren } from "@portabletext/editor/traversal";
|
|
5
6
|
import { isKeyedSegment, isTextBlock } from "@portabletext/editor/utils";
|
|
6
7
|
function serializePath(path) {
|
|
7
8
|
return path.reduce((result, segment, index) => isKeyedSegment(segment) ? `${result}[_key=="${segment._key}"]` : `${result}${index === 0 ? "" : "."}${segment}`, "");
|
|
8
9
|
}
|
|
9
10
|
function buildListIndexMap(context) {
|
|
10
|
-
const listIndexMap = /* @__PURE__ */ new Map(),
|
|
11
|
+
const listIndexMap = /* @__PURE__ */ new Map(), traversalContext = {
|
|
12
|
+
schema: context.schema,
|
|
13
|
+
containers: context.containers ?? /* @__PURE__ */ new Map()
|
|
14
|
+
};
|
|
15
|
+
return collectListIndexes(traversalContext, context.value, [], void 0, listIndexMap), listIndexMap;
|
|
16
|
+
}
|
|
17
|
+
function collectListIndexes(context, blocks, basePath, parent, listIndexMap) {
|
|
18
|
+
const levelIndexMaps = /* @__PURE__ */ new Map();
|
|
11
19
|
let previousListItem;
|
|
12
|
-
for (const block of
|
|
13
|
-
if (block === void 0)
|
|
14
|
-
continue;
|
|
15
|
-
if (!isTextBlock(context, block)) {
|
|
16
|
-
levelIndexMaps.clear(), previousListItem = void 0;
|
|
20
|
+
for (const block of blocks) {
|
|
21
|
+
if (block === void 0 || block._key === void 0)
|
|
17
22
|
continue;
|
|
18
|
-
|
|
19
|
-
|
|
23
|
+
const blockPath = [...basePath, {
|
|
24
|
+
_key: block._key
|
|
25
|
+
}];
|
|
26
|
+
if (!isTextBlock(context, block) || block.listItem === void 0 || block.level === void 0) {
|
|
20
27
|
levelIndexMaps.clear(), previousListItem = void 0;
|
|
28
|
+
const childResult = getContainerChildren(context.containers, block, parent);
|
|
29
|
+
childResult && collectListIndexes(context, childResult.children, [...blockPath, childResult.container.field.name], childResult.container, listIndexMap);
|
|
21
30
|
continue;
|
|
22
31
|
}
|
|
23
32
|
if (!previousListItem) {
|
|
24
33
|
const levelIndexMap2 = levelIndexMaps.get(block.listItem) ?? /* @__PURE__ */ new Map();
|
|
25
|
-
levelIndexMap2.set(block.level, 1), levelIndexMaps.set(block.listItem, levelIndexMap2), listIndexMap.set(serializePath(
|
|
26
|
-
_key: block._key
|
|
27
|
-
}]), 1), previousListItem = {
|
|
34
|
+
levelIndexMap2.set(block.level, 1), levelIndexMaps.set(block.listItem, levelIndexMap2), listIndexMap.set(serializePath(blockPath), 1), previousListItem = {
|
|
28
35
|
listItem: block.listItem,
|
|
29
36
|
level: block.level
|
|
30
37
|
};
|
|
@@ -32,9 +39,7 @@ function buildListIndexMap(context) {
|
|
|
32
39
|
}
|
|
33
40
|
if (previousListItem.listItem === block.listItem && previousListItem.level < block.level) {
|
|
34
41
|
const levelIndexMap2 = levelIndexMaps.get(block.listItem) ?? /* @__PURE__ */ new Map();
|
|
35
|
-
levelIndexMap2.set(block.level, 1), levelIndexMaps.set(block.listItem, levelIndexMap2), listIndexMap.set(serializePath(
|
|
36
|
-
_key: block._key
|
|
37
|
-
}]), 1), previousListItem = {
|
|
42
|
+
levelIndexMap2.set(block.level, 1), levelIndexMaps.set(block.listItem, levelIndexMap2), listIndexMap.set(serializePath(blockPath), 1), previousListItem = {
|
|
38
43
|
listItem: block.listItem,
|
|
39
44
|
level: block.level
|
|
40
45
|
};
|
|
@@ -51,14 +56,11 @@ function buildListIndexMap(context) {
|
|
|
51
56
|
});
|
|
52
57
|
});
|
|
53
58
|
const levelIndexMap = levelIndexMaps.get(block.listItem) ?? /* @__PURE__ */ new Map(), levelCounter = levelIndexMap.get(block.level) ?? 0;
|
|
54
|
-
levelIndexMap.set(block.level, levelCounter + 1), levelIndexMaps.set(block.listItem, levelIndexMap), listIndexMap.set(serializePath(
|
|
55
|
-
_key: block._key
|
|
56
|
-
}]), levelCounter + 1), previousListItem = {
|
|
59
|
+
levelIndexMap.set(block.level, levelCounter + 1), levelIndexMaps.set(block.listItem, levelIndexMap), listIndexMap.set(serializePath(blockPath), levelCounter + 1), previousListItem = {
|
|
57
60
|
listItem: block.listItem,
|
|
58
61
|
level: block.level
|
|
59
62
|
};
|
|
60
63
|
}
|
|
61
|
-
return listIndexMap;
|
|
62
64
|
}
|
|
63
65
|
function createListIndexStore(editor) {
|
|
64
66
|
let listIndexMap = buildListIndexMap(editor.getSnapshot().context);
|
|
@@ -88,7 +90,7 @@ function createListIndexStore(editor) {
|
|
|
88
90
|
subscribe: () => {
|
|
89
91
|
subscribed = !0, rebuild();
|
|
90
92
|
const subscription = editor.on("operation", (event) => {
|
|
91
|
-
event.operation.type === "insert.text" || event.operation.type === "remove.text" ||
|
|
93
|
+
event.operation.type === "insert.text" || event.operation.type === "remove.text" || scheduleRebuild();
|
|
92
94
|
});
|
|
93
95
|
return () => {
|
|
94
96
|
subscribed = !1, subscription.unsubscribe();
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/build-list-index-map.ts","../src/plugin.list-index.tsx"],"sourcesContent":["import type {EditorContext, Path} from '@portabletext/editor'\nimport {isKeyedSegment, isTextBlock} from '@portabletext/editor/utils'\n\n/**\n * Serialize a keyed path to a string using Sanity's bracket notation,\n * e.g. `[{_key: 'k0'}]` becomes `[_key==\"k0\"]`.\n *\n * Duplicated from the editor's internal `serializePath` rather than\n * imported: exporting it from core would add permanent public API for what\n * is an implementation detail of this plugin.\n */\nexport function 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\n/**\n * Compute the list index for every list item block in the value.\n *\n * Returns a fresh `Map` keyed by serialized block path with the 1-based\n * index of the block within its list, honoring list type and indentation\n * level: same-type items count up across consecutive blocks on the same\n * level, deeper levels restart at 1, and non-list blocks break the\n * sequence.\n *\n * Duplicated from the editor's internal `buildIndexMaps` (the part that\n * fills `listIndexMap`) rather than imported, for the same reason as\n * `serializePath` above. Keep the list semantics in sync with\n * `packages/editor/src/internal-utils/build-index-maps.ts`.\n */\nexport function buildListIndexMap(\n context: Pick<EditorContext, 'schema' | 'value'>,\n): Map<string, number> {\n const listIndexMap = new Map<string, number>()\n\n // Maps for each list type, keeping track of the current list count for\n // each level.\n const levelIndexMaps = new Map<string, Map<number, number>>()\n\n let previousListItem:\n | {\n listItem: string\n level: number\n }\n | undefined\n\n for (const block of context.value) {\n if (block === undefined) {\n continue\n }\n\n // Clear the state if we encounter a non-text block. Unlike the engine's\n // internal check, `isTextBlock` also requires `children`, which holds\n // for the post-apply snapshot values this plugin reads.\n if (!isTextBlock(context, block)) {\n levelIndexMaps.clear()\n previousListItem = undefined\n\n continue\n }\n\n // Clear the state if we encounter a non-list text block\n if (block.listItem === undefined || block.level === undefined) {\n levelIndexMaps.clear()\n previousListItem = undefined\n\n continue\n }\n\n // If we encounter a new list item, we set the initial index to 1 for the\n // list type on that level.\n if (!previousListItem) {\n const listIndex = 1\n const levelIndexMap =\n levelIndexMaps.get(block.listItem) ?? new Map<number, number>()\n levelIndexMap.set(block.level, listIndex)\n levelIndexMaps.set(block.listItem, levelIndexMap)\n\n listIndexMap.set(serializePath([{_key: block._key}]), listIndex)\n\n previousListItem = {\n listItem: block.listItem,\n level: block.level,\n }\n\n continue\n }\n\n // If the previous list item is of the same type but on a lower level, we\n // need to reset the level index map for that type.\n if (\n previousListItem.listItem === block.listItem &&\n previousListItem.level < block.level\n ) {\n const listIndex = 1\n const levelIndexMap =\n levelIndexMaps.get(block.listItem) ?? new Map<number, number>()\n levelIndexMap.set(block.level, listIndex)\n levelIndexMaps.set(block.listItem, levelIndexMap)\n\n listIndexMap.set(serializePath([{_key: block._key}]), listIndex)\n\n previousListItem = {\n listItem: block.listItem,\n level: block.level,\n }\n\n continue\n }\n\n // Reset other list types at current level and deeper\n levelIndexMaps.forEach((levelIndexMap, listItem) => {\n if (listItem === block.listItem) {\n return\n }\n\n // Reset all levels that are >= current level\n const levelsToDelete: number[] = []\n\n levelIndexMap.forEach((_, level) => {\n if (block.level !== undefined && level >= block.level) {\n levelsToDelete.push(level)\n }\n })\n\n levelsToDelete.forEach((level) => {\n levelIndexMap.delete(level)\n })\n })\n\n const levelIndexMap =\n levelIndexMaps.get(block.listItem) ?? new Map<number, number>()\n const levelCounter = levelIndexMap.get(block.level) ?? 0\n levelIndexMap.set(block.level, levelCounter + 1)\n levelIndexMaps.set(block.listItem, levelIndexMap)\n\n listIndexMap.set(serializePath([{_key: block._key}]), levelCounter + 1)\n\n previousListItem = {\n listItem: block.listItem,\n level: block.level,\n }\n }\n\n return listIndexMap\n}\n","import {useEditor, type Editor, type Path} from '@portabletext/editor'\nimport {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useSyncExternalStore,\n type ReactNode,\n} from 'react'\nimport {buildListIndexMap, serializePath} from './build-list-index-map'\n\n/**\n * One store per editor: a single `operation` subscription maintains the\n * list index map, and per-path subscriber buckets make notification\n * O(changed paths) rather than O(subscribers).\n */\ntype ListIndexStore = {\n get: (serializedPath: string) => number | undefined\n subscribeKey: (serializedPath: string, callback: () => void) => () => void\n /**\n * Starts the `operation` subscription. Returns the unsubscribe.\n */\n subscribe: () => () => void\n}\n\nfunction createListIndexStore(editor: Editor): ListIndexStore {\n let listIndexMap = buildListIndexMap(editor.getSnapshot().context)\n const subscribers = new Map<string, Set<() => void>>()\n let rebuildScheduled = false\n let subscribed = false\n\n function scheduleRebuild() {\n if (rebuildScheduled) {\n return\n }\n\n rebuildScheduled = true\n\n // Coalesce per microtask: bulk transactions (value sync, multi-block\n // inserts) deliver one operation per affected block, and rebuilding per\n // operation would be O(blocks^2). The map has only React consumers and\n // they read post-commit, so deferring to the end of the JS turn is\n // safe; the microtask drains before React's commit.\n queueMicrotask(() => {\n rebuildScheduled = false\n\n if (subscribed) {\n rebuild()\n }\n })\n }\n\n function rebuild() {\n const previousListIndexMap = listIndexMap\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 listIndexMap = buildListIndexMap(editor.getSnapshot().context)\n\n for (const [serializedPath, callbacks] of subscribers) {\n if (\n previousListIndexMap.get(serializedPath) !==\n listIndexMap.get(serializedPath)\n ) {\n for (const callback of callbacks) {\n callback()\n }\n }\n }\n }\n\n return {\n get: (serializedPath) => listIndexMap.get(serializedPath),\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 subscribe: () => {\n subscribed = true\n\n // Operations applied between store creation (render) and subscription\n // (effect) are not observed, so reconcile once up front.\n rebuild()\n\n const subscription = editor.on('operation', (event) => {\n if (\n event.operation.type === 'insert.text' ||\n event.operation.type === 'remove.text'\n ) {\n // Inserting and removing text has no effect on list indices so\n // there is no need to rebuild those.\n return\n }\n\n if (event.operation.path.length > 2) {\n // Operations deep inside blocks only modify nested structure and\n // cannot affect root-level list indices.\n return\n }\n\n scheduleRebuild()\n })\n\n return () => {\n subscribed = false\n subscription.unsubscribe()\n }\n },\n }\n}\n\nconst ListIndexContext = createContext<ListIndexStore | undefined>(undefined)\n\n/**\n * Maintains a list index map for the editor and serves it through context.\n * Mount inside `EditorProvider`, wrapping whatever reads the indices:\n *\n * ```tsx\n * <EditorProvider initialConfig={...}>\n * <ListIndexProvider>\n * <PortableTextEditable />\n * </ListIndexProvider>\n * </EditorProvider>\n * ```\n *\n * The map is rebuilt at most once per editor operation, regardless of how\n * many components read it, and only for operations that can affect list\n * indices. Reads via {@link useListIndex} only re-render when the index at\n * their own path changes.\n *\n * @beta\n */\nexport function ListIndexProvider(props: {children?: ReactNode}) {\n const editor = useEditor()\n const store = useMemo(() => createListIndexStore(editor), [editor])\n\n useEffect(() => {\n return store.subscribe()\n }, [store])\n\n return (\n <ListIndexContext.Provider value={store}>\n {props.children}\n </ListIndexContext.Provider>\n )\n}\n\n/**\n * Read the 1-based list index of the block at `path`, or `undefined` when\n * the block is not a list item. Re-renders only when the index at this\n * path changes.\n *\n * `path` is the keyed block path render callbacks receive, e.g.\n * `[{_key: 'b0'}]`.\n *\n * @beta\n */\nexport function useListIndex(path: Path): number | undefined {\n const store = useContext(ListIndexContext)\n\n if (store === undefined) {\n throw new Error('useListIndex must be used below a <ListIndexProvider>')\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. Memoizing on the array would never hit.\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"],"names":["serializePath","path","reduce","result","segment","index","isKeyedSegment","_key","buildListIndexMap","context","listIndexMap","Map","levelIndexMaps","previousListItem","block","value","undefined","isTextBlock","clear","listItem","level","levelIndexMap","get","set","listIndex","forEach","levelsToDelete","_","push","delete","levelCounter","createListIndexStore","editor","getSnapshot","subscribers","rebuildScheduled","subscribed","scheduleRebuild","queueMicrotask","rebuild","previousListIndexMap","serializedPath","callbacks","callback","subscribeKey","bucket","Set","add","size","subscribe","subscription","on","event","operation","type","length","unsubscribe","ListIndexContext","createContext","ListIndexProvider","props","$","_c","useEditor","t0","store","t1","t2","useEffect","t3","children","useListIndex","useContext","Error","useSyncExternalStore"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/build-list-index-map.ts","../src/plugin.list-index.tsx"],"sourcesContent":["import type {\n EditorContext,\n Path,\n RegisteredContainer,\n} from '@portabletext/editor'\nimport {getContainerChildren} from '@portabletext/editor/traversal'\nimport {isKeyedSegment, isTextBlock} from '@portabletext/editor/utils'\n\n/**\n * Serialize a keyed path to a string using Sanity's bracket notation,\n * e.g. `[{_key: 'k0'}]` becomes `[_key==\"k0\"]`.\n *\n * Duplicated from the editor's internal `serializePath` rather than\n * imported: exporting it from core would add permanent public API for what\n * is an implementation detail of this plugin.\n */\nexport function 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\n// `containers` is optional: the production caller passes the full snapshot\n// context, while the flat (top-level only) test scenarios omit it. Without\n// containers, container blocks resolve to no children and are not descended,\n// the pre-container behavior.\ntype ListIndexInput = Pick<EditorContext, 'schema' | 'value'> &\n Partial<Pick<EditorContext, 'containers'>>\n\ntype TraversalContext = Pick<EditorContext, 'schema' | 'containers'>\n\n// The block type `getContainerChildren` yields. `Node` is not public, so\n// derive it from the (public) traversal primitive rather than naming it.\ntype Block = NonNullable<\n ReturnType<typeof getContainerChildren>\n>['children'][number]\n\n/**\n * Compute the list index for every list item block in the value, at any\n * depth.\n *\n * Returns a fresh `Map` keyed by the serialized full block path with the\n * 1-based index of the block within its list, honoring list type and\n * indentation level: same-type items count up across consecutive blocks on\n * the same level, deeper levels restart at 1, and non-list blocks break the\n * sequence. List items nested inside a container (e.g. a table cell) number\n * within their own array, independently of siblings and the enclosing array.\n *\n * Duplicated from the editor's internal `buildIndexMaps` (the part that fills\n * `listIndexMap`) rather than imported, for the same reason as `serializePath`\n * above. Descends containers with the public `getContainerChildren`, seeding\n * the document root from `context.value`. Keep the numbering semantics in sync\n * with `packages/editor/src/internal-utils/build-index-maps.ts`.\n */\nexport function buildListIndexMap(\n context: ListIndexInput,\n): Map<string, number> {\n const listIndexMap = new Map<string, number>()\n const traversalContext: TraversalContext = {\n schema: context.schema,\n containers: context.containers ?? new Map<string, RegisteredContainer>(),\n }\n collectListIndexes(\n traversalContext,\n context.value,\n [],\n undefined,\n listIndexMap,\n )\n return listIndexMap\n}\n\n/**\n * Walk one block array, numbering its list items, then descend into any\n * container blocks. List state is scoped per array: a list inside a container\n * numbers independently, so each array starts fresh from 1.\n */\nfunction collectListIndexes(\n context: TraversalContext,\n blocks: ReadonlyArray<Block | undefined>,\n basePath: Path,\n parent: RegisteredContainer | undefined,\n listIndexMap: Map<string, number>,\n): void {\n const levelIndexMaps = new Map<string, Map<number, number>>()\n\n let previousListItem:\n | {\n listItem: string\n level: number\n }\n | undefined\n\n for (const block of blocks) {\n if (block === undefined || block._key === undefined) {\n continue\n }\n\n const blockPath: Path = [...basePath, {_key: block._key}]\n\n // A non-list block breaks the list run for this array. Containers are\n // descended into; each nested array numbers independently.\n //\n // Unlike the engine's internal `isTextBlockNode`, `isTextBlock` also\n // requires `children`, which holds for the post-apply snapshot values\n // this plugin reads.\n if (\n !isTextBlock(context, block) ||\n block.listItem === undefined ||\n block.level === undefined\n ) {\n levelIndexMaps.clear()\n previousListItem = undefined\n\n const childResult = getContainerChildren(\n context.containers,\n block,\n parent,\n )\n if (childResult) {\n collectListIndexes(\n context,\n childResult.children,\n [...blockPath, childResult.container.field.name],\n childResult.container,\n listIndexMap,\n )\n }\n\n continue\n }\n\n // If we encounter a new list item, we set the initial index to 1 for the\n // list type on that level.\n if (!previousListItem) {\n const listIndex = 1\n const levelIndexMap =\n levelIndexMaps.get(block.listItem) ?? new Map<number, number>()\n levelIndexMap.set(block.level, listIndex)\n levelIndexMaps.set(block.listItem, levelIndexMap)\n\n listIndexMap.set(serializePath(blockPath), listIndex)\n\n previousListItem = {\n listItem: block.listItem,\n level: block.level,\n }\n\n continue\n }\n\n // If the previous list item is of the same type but on a lower level, we\n // need to reset the level index map for that type.\n if (\n previousListItem.listItem === block.listItem &&\n previousListItem.level < block.level\n ) {\n const listIndex = 1\n const levelIndexMap =\n levelIndexMaps.get(block.listItem) ?? new Map<number, number>()\n levelIndexMap.set(block.level, listIndex)\n levelIndexMaps.set(block.listItem, levelIndexMap)\n\n listIndexMap.set(serializePath(blockPath), listIndex)\n\n previousListItem = {\n listItem: block.listItem,\n level: block.level,\n }\n\n continue\n }\n\n // Reset other list types at current level and deeper\n levelIndexMaps.forEach((levelIndexMap, listItem) => {\n if (listItem === block.listItem) {\n return\n }\n\n // Reset all levels that are >= current level\n const levelsToDelete: number[] = []\n\n levelIndexMap.forEach((_, level) => {\n if (block.level !== undefined && level >= block.level) {\n levelsToDelete.push(level)\n }\n })\n\n levelsToDelete.forEach((level) => {\n levelIndexMap.delete(level)\n })\n })\n\n const levelIndexMap =\n levelIndexMaps.get(block.listItem) ?? new Map<number, number>()\n const levelCounter = levelIndexMap.get(block.level) ?? 0\n levelIndexMap.set(block.level, levelCounter + 1)\n levelIndexMaps.set(block.listItem, levelIndexMap)\n\n listIndexMap.set(serializePath(blockPath), levelCounter + 1)\n\n previousListItem = {\n listItem: block.listItem,\n level: block.level,\n }\n }\n}\n","import {useEditor, type Editor, type Path} from '@portabletext/editor'\nimport {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useSyncExternalStore,\n type ReactNode,\n} from 'react'\nimport {buildListIndexMap, serializePath} from './build-list-index-map'\n\n/**\n * One store per editor: a single `operation` subscription maintains the\n * list index map, and per-path subscriber buckets make notification\n * O(changed paths) rather than O(subscribers).\n */\ntype ListIndexStore = {\n get: (serializedPath: string) => number | undefined\n subscribeKey: (serializedPath: string, callback: () => void) => () => void\n /**\n * Starts the `operation` subscription. Returns the unsubscribe.\n */\n subscribe: () => () => void\n}\n\nfunction createListIndexStore(editor: Editor): ListIndexStore {\n let listIndexMap = buildListIndexMap(editor.getSnapshot().context)\n const subscribers = new Map<string, Set<() => void>>()\n let rebuildScheduled = false\n let subscribed = false\n\n function scheduleRebuild() {\n if (rebuildScheduled) {\n return\n }\n\n rebuildScheduled = true\n\n // Coalesce per microtask: bulk transactions (value sync, multi-block\n // inserts) deliver one operation per affected block, and rebuilding per\n // operation would be O(blocks^2). The map has only React consumers and\n // they read post-commit, so deferring to the end of the JS turn is\n // safe; the microtask drains before React's commit.\n queueMicrotask(() => {\n rebuildScheduled = false\n\n if (subscribed) {\n rebuild()\n }\n })\n }\n\n function rebuild() {\n const previousListIndexMap = listIndexMap\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 listIndexMap = buildListIndexMap(editor.getSnapshot().context)\n\n for (const [serializedPath, callbacks] of subscribers) {\n if (\n previousListIndexMap.get(serializedPath) !==\n listIndexMap.get(serializedPath)\n ) {\n for (const callback of callbacks) {\n callback()\n }\n }\n }\n }\n\n return {\n get: (serializedPath) => listIndexMap.get(serializedPath),\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 subscribe: () => {\n subscribed = true\n\n // Operations applied between store creation (render) and subscription\n // (effect) are not observed, so reconcile once up front.\n rebuild()\n\n const subscription = editor.on('operation', (event) => {\n // Text ops never change list structure; every other document-changing\n // op can (including deep edits inside a container), so rebuild. The\n // rebuild coalesces below and the diff drops no-op changes.\n if (\n event.operation.type === 'insert.text' ||\n event.operation.type === 'remove.text'\n ) {\n return\n }\n\n scheduleRebuild()\n })\n\n return () => {\n subscribed = false\n subscription.unsubscribe()\n }\n },\n }\n}\n\nconst ListIndexContext = createContext<ListIndexStore | undefined>(undefined)\n\n/**\n * Maintains a list index map for the editor and serves it through context.\n * Mount inside `EditorProvider`, wrapping whatever reads the indices:\n *\n * ```tsx\n * <EditorProvider initialConfig={...}>\n * <ListIndexProvider>\n * <PortableTextEditable />\n * </ListIndexProvider>\n * </EditorProvider>\n * ```\n *\n * The map is rebuilt at most once per editor operation, regardless of how\n * many components read it, and only for operations that can affect list\n * indices. Reads via {@link useListIndex} only re-render when the index at\n * their own path changes.\n *\n * @beta\n */\nexport function ListIndexProvider(props: {children?: ReactNode}) {\n const editor = useEditor()\n const store = useMemo(() => createListIndexStore(editor), [editor])\n\n useEffect(() => {\n return store.subscribe()\n }, [store])\n\n return (\n <ListIndexContext.Provider value={store}>\n {props.children}\n </ListIndexContext.Provider>\n )\n}\n\n/**\n * Read the 1-based list index of the block at `path`, or `undefined` when\n * the block is not a list item. Re-renders only when the index at this\n * path changes.\n *\n * `path` is the keyed block path render callbacks receive, e.g.\n * `[{_key: 'b0'}]`.\n *\n * @beta\n */\nexport function useListIndex(path: Path): number | undefined {\n const store = useContext(ListIndexContext)\n\n if (store === undefined) {\n throw new Error('useListIndex must be used below a <ListIndexProvider>')\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. Memoizing on the array would never hit.\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"],"names":["serializePath","path","reduce","result","segment","index","isKeyedSegment","_key","buildListIndexMap","context","listIndexMap","Map","traversalContext","schema","containers","collectListIndexes","value","undefined","blocks","basePath","parent","levelIndexMaps","previousListItem","block","blockPath","isTextBlock","listItem","level","clear","childResult","getContainerChildren","children","container","field","name","levelIndexMap","get","set","listIndex","forEach","levelsToDelete","_","push","delete","levelCounter","createListIndexStore","editor","getSnapshot","subscribers","rebuildScheduled","subscribed","scheduleRebuild","queueMicrotask","rebuild","previousListIndexMap","serializedPath","callbacks","callback","subscribeKey","bucket","Set","add","size","subscribe","subscription","on","event","operation","type","unsubscribe","ListIndexContext","createContext","ListIndexProvider","props","$","_c","useEditor","t0","store","t1","t2","useEffect","t3","useListIndex","useContext","Error","useSyncExternalStore"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@portabletext/plugin-list-index",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"description": "A helper plugin for calculating list indices for flat blocks based on listItem and level",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"portabletext",
|
|
@@ -46,13 +46,13 @@
|
|
|
46
46
|
"typescript-eslint": "^8.48.0",
|
|
47
47
|
"vitest": "^4.1.8",
|
|
48
48
|
"vitest-browser-react": "^2.2.0",
|
|
49
|
-
"@portabletext/editor": "^7.
|
|
49
|
+
"@portabletext/editor": "^7.6.0",
|
|
50
50
|
"@portabletext/schema": "^2.2.0",
|
|
51
51
|
"@portabletext/test": "^1.0.3"
|
|
52
52
|
},
|
|
53
53
|
"peerDependencies": {
|
|
54
54
|
"react": "^19.2",
|
|
55
|
-
"@portabletext/editor": "^7.
|
|
55
|
+
"@portabletext/editor": "^7.6.0"
|
|
56
56
|
},
|
|
57
57
|
"engines": {
|
|
58
58
|
"node": ">=20.19 <22 || >=22.12"
|