@portabletext/editor 7.10.15 → 7.10.17

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.
Files changed (63) hide show
  1. package/lib/{_chunks-dts/behavior.types.action.d.ts → behavior.types.action-CYtiRDck.d.ts} +260 -59
  2. package/lib/behavior.types.action-CYtiRDck.d.ts.map +1 -0
  3. package/lib/behavior.types.behavior-B_77VtQR.js +159 -0
  4. package/lib/behavior.types.behavior-B_77VtQR.js.map +1 -0
  5. package/lib/behaviors/index.d.ts +1 -1
  6. package/lib/behaviors/index.js +2 -35
  7. package/lib/get-container-BeXYKpoi.js +222 -0
  8. package/lib/get-container-BeXYKpoi.js.map +1 -0
  9. package/lib/get-parent-51Kzgaf9.js +237 -0
  10. package/lib/get-parent-51Kzgaf9.js.map +1 -0
  11. package/lib/get-path-sub-schema--2I4NJbG.js +513 -0
  12. package/lib/get-path-sub-schema--2I4NJbG.js.map +1 -0
  13. package/lib/index.d.ts +2 -67
  14. package/lib/index.js +16743 -18963
  15. package/lib/index.js.map +1 -1
  16. package/lib/plugins/index.d.ts +1 -2
  17. package/lib/plugins/index.d.ts.map +1 -1
  18. package/lib/plugins/index.js +103 -41
  19. package/lib/plugins/index.js.map +1 -1
  20. package/lib/selector.is-at-the-start-of-block-gJIMWRpU.js +822 -0
  21. package/lib/selector.is-at-the-start-of-block-gJIMWRpU.js.map +1 -0
  22. package/lib/selectors/index.d.ts +1 -3
  23. package/lib/selectors/index.d.ts.map +1 -1
  24. package/lib/selectors/index.js +256 -215
  25. package/lib/selectors/index.js.map +1 -1
  26. package/lib/traversal/index.d.ts +1 -1
  27. package/lib/traversal/index.d.ts.map +1 -1
  28. package/lib/traversal/index.js +33 -52
  29. package/lib/traversal/index.js.map +1 -1
  30. package/lib/use-editor-CwNeVwVC.js +47 -0
  31. package/lib/use-editor-CwNeVwVC.js.map +1 -0
  32. package/lib/util.is-equal-selections-BF4WJtz5.js +25 -0
  33. package/lib/util.is-equal-selections-BF4WJtz5.js.map +1 -0
  34. package/lib/util.slice-blocks-DQnr9X2s.js +633 -0
  35. package/lib/util.slice-blocks-DQnr9X2s.js.map +1 -0
  36. package/lib/utils/index.d.ts +11 -39
  37. package/lib/utils/index.d.ts.map +1 -1
  38. package/lib/utils/index.js +87 -123
  39. package/lib/utils/index.js.map +1 -1
  40. package/package.json +18 -15
  41. package/lib/_chunks-dts/behavior.types.action.d.ts.map +0 -1
  42. package/lib/_chunks-dts/block-offset.d.ts +0 -10
  43. package/lib/_chunks-dts/block-offset.d.ts.map +0 -1
  44. package/lib/_chunks-dts/editor-selector.d.ts +0 -33
  45. package/lib/_chunks-dts/editor-selector.d.ts.map +0 -1
  46. package/lib/_chunks-dts/editor.d.ts +0 -99
  47. package/lib/_chunks-dts/editor.d.ts.map +0 -1
  48. package/lib/_chunks-es/get-container.js +0 -187
  49. package/lib/_chunks-es/get-container.js.map +0 -1
  50. package/lib/_chunks-es/get-parent.js +0 -195
  51. package/lib/_chunks-es/get-parent.js.map +0 -1
  52. package/lib/_chunks-es/get-path-sub-schema.js +0 -399
  53. package/lib/_chunks-es/get-path-sub-schema.js.map +0 -1
  54. package/lib/_chunks-es/selector.is-at-the-start-of-block.js +0 -947
  55. package/lib/_chunks-es/selector.is-at-the-start-of-block.js.map +0 -1
  56. package/lib/_chunks-es/use-editor.js +0 -20
  57. package/lib/_chunks-es/use-editor.js.map +0 -1
  58. package/lib/_chunks-es/util.is-equal-selections.js +0 -20
  59. package/lib/_chunks-es/util.is-equal-selections.js.map +0 -1
  60. package/lib/_chunks-es/util.slice-blocks.js +0 -720
  61. package/lib/_chunks-es/util.slice-blocks.js.map +0 -1
  62. package/lib/behaviors/index.js.map +0 -1
  63. package/lib/index.d.ts.map +0 -1
@@ -0,0 +1,159 @@
1
+ /**
2
+ * Directly executes an event, bypassing all Behavior matching.
3
+ *
4
+ * Use `execute` when you want to perform an action without triggering any
5
+ * Behaviors. The event is executed immediately as a direct operation.
6
+ *
7
+ * @example
8
+ * ```ts
9
+ * defineBehavior({
10
+ * on: 'insert.text',
11
+ * guard: ({event}) => event.text === 'a',
12
+ * actions: [() => [execute({type: 'insert.text', text: 'b'})]],
13
+ * })
14
+ * ```
15
+ *
16
+ * @beta
17
+ */
18
+ function execute(event) {
19
+ return {
20
+ type: "execute",
21
+ event
22
+ };
23
+ }
24
+ /**
25
+ * Forwards an event to the next Behavior(s) in the current chain.
26
+ *
27
+ * Use `forward` to pass an event to succeeding Behaviors without starting a
28
+ * fresh lookup. This is useful for intercepting events, performing side
29
+ * effects, and then letting the default handling continue.
30
+ *
31
+ * **Key rule:** When forwarding to a different event type, only Behaviors that
32
+ * were already in the remaining chain AND match the new type will run. This
33
+ * means cross-type `forward` is mostly useful for falling through to default
34
+ * Behaviors, not for triggering user-defined Behaviors of a different type.
35
+ *
36
+ * To trigger all Behaviors for a different event type, use {@link raise}
37
+ * instead.
38
+ *
39
+ * @example
40
+ * ```ts
41
+ * // Intercept and forward same event type
42
+ * defineBehavior({
43
+ * on: 'insert.text',
44
+ * actions: [({event}) => [effect(logEvent), forward(event)]],
45
+ * })
46
+ *
47
+ * // Forward to default handling of different event type
48
+ * defineBehavior({
49
+ * on: 'clipboard.paste',
50
+ * actions: [
51
+ * ({event}) => {
52
+ * const text = event.originEvent.dataTransfer?.getData('text/plain')
53
+ * return text ? [forward({type: 'insert.text', text})] : []
54
+ * },
55
+ * ],
56
+ * })
57
+ * ```
58
+ *
59
+ * @beta
60
+ */
61
+ function forward(event) {
62
+ return {
63
+ type: "forward",
64
+ event
65
+ };
66
+ }
67
+ /**
68
+ * Raises an event, triggering a fresh lookup of all Behaviors.
69
+ *
70
+ * Use `raise` when you want to trigger an event "from scratch", including all
71
+ * Behaviors that match the event type. This is the appropriate action when you
72
+ * want to trigger Behaviors for a different event type.
73
+ *
74
+ * If no Behavior matches the raised event, synthetic events will fall through
75
+ * to their default operation.
76
+ *
77
+ * @example
78
+ * ```ts
79
+ * // Raise a custom event that triggers other Behaviors
80
+ * defineBehavior({
81
+ * on: 'insert.text',
82
+ * guard: ({event}) => event.text === 'a',
83
+ * actions: [() => [raise({type: 'custom.specialInsert'})]],
84
+ * })
85
+ *
86
+ * // Raise a different event type (fresh lookup includes all Behaviors)
87
+ * defineBehavior({
88
+ * on: 'clipboard.paste',
89
+ * actions: [
90
+ * ({event}) => {
91
+ * const text = event.originEvent.dataTransfer?.getData('text/plain')
92
+ * return text ? [raise({type: 'insert.text', text})] : []
93
+ * },
94
+ * ],
95
+ * })
96
+ * ```
97
+ *
98
+ * @beta
99
+ */
100
+ function raise(event) {
101
+ return {
102
+ type: "raise",
103
+ event
104
+ };
105
+ }
106
+ /**
107
+ * Performs a side effect.
108
+ *
109
+ * Use `effect` for logging, analytics, async operations, or other side effects.
110
+ *
111
+ * **Note:** Using `effect` alone (without `forward`) will stop event
112
+ * propagation. To perform a side effect while allowing the default Behavior
113
+ * to continue, combine `effect` with `forward`.
114
+ *
115
+ * The effect callback receives a `send` function that can be used to send
116
+ * events back to the editor asynchronously.
117
+ *
118
+ * @example
119
+ * ```ts
120
+ * // Log events while preserving default Behavior
121
+ * defineBehavior({
122
+ * on: 'insert.text',
123
+ * actions: [({event}) => [effect(() => console.log(event)), forward(event)]],
124
+ * })
125
+ *
126
+ * // Effect alone stops propagation (native event is cancelled)
127
+ * defineBehavior({
128
+ * on: 'keyboard.keydown',
129
+ * actions: [() => [effect(() => console.log('key pressed'))]],
130
+ * })
131
+ *
132
+ * // Async effect that sends an event later
133
+ * defineBehavior({
134
+ * on: 'custom.save',
135
+ * actions: [
136
+ * () => [
137
+ * effect(async ({send}) => {
138
+ * await saveDocument()
139
+ * send({type: 'custom.saved'})
140
+ * }),
141
+ * ],
142
+ * ],
143
+ * })
144
+ * ```
145
+ *
146
+ * @beta
147
+ */
148
+ function effect(effect) {
149
+ return {
150
+ type: "effect",
151
+ effect
152
+ };
153
+ }
154
+ function defineBehavior(behavior) {
155
+ return behavior;
156
+ }
157
+ export { raise as a, forward as i, effect as n, execute as r, defineBehavior as t };
158
+
159
+ //# sourceMappingURL=behavior.types.behavior-B_77VtQR.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"behavior.types.behavior-B_77VtQR.js","names":["EditorDom","EditorSnapshot","PickFromUnion","CustomBehaviorEvent","ExternalBehaviorEvent","NativeBehaviorEvent","SyntheticBehaviorEvent","BehaviorAction","type","event","effect","payload","send","execute","forward","raise","BehaviorActionSet","snapshot","TBehaviorEvent","dom","guardResponse","TGuardResponse","Array","BehaviorActionSet","BehaviorEvent","BehaviorEventTypeNamespace","CustomBehaviorEvent","ResolveBehaviorEvent","BehaviorGuard","Behavior","TBehaviorEventType","on","guard","TBehaviorEvent","TGuardResponse","actions","Array","defineBehavior","Record","behavior","TPayload"],"sources":["../src/behaviors/behavior.types.action.ts","../src/behaviors/behavior.types.behavior.ts"],"sourcesContent":["import type {EditorDom} from '../editor/editor-dom'\nimport type {EditorSnapshot} from '../editor/editor-snapshot'\nimport type {PickFromUnion} from '../type-utils'\nimport type {\n CustomBehaviorEvent,\n ExternalBehaviorEvent,\n NativeBehaviorEvent,\n SyntheticBehaviorEvent,\n} from './behavior.types.event'\n\n/**\n * @beta\n */\nexport type BehaviorAction =\n | {\n type: 'execute'\n event: SyntheticBehaviorEvent\n }\n | {\n type: 'forward'\n event: NativeBehaviorEvent | SyntheticBehaviorEvent | CustomBehaviorEvent\n }\n | {\n type: 'raise'\n event: SyntheticBehaviorEvent | CustomBehaviorEvent\n }\n | {\n type: 'effect'\n effect: (payload: {\n /**\n * Send a Behavior Event back into the Editor.\n *\n * @example\n * ```ts\n * defineBehavior({\n * on: '...',\n * actions: [\n * () => [\n * effect(({send}) => {\n * doSomethingAsync()\n * .then(() => {\n * send({\n * type: '...',\n * })\n * })\n * })\n * ],\n * ],\n * })\n * ```\n */\n send: (event: ExternalBehaviorEvent) => void\n }) => void\n }\n\n/**\n * Directly executes an event, bypassing all Behavior matching.\n *\n * Use `execute` when you want to perform an action without triggering any\n * Behaviors. The event is executed immediately as a direct operation.\n *\n * @example\n * ```ts\n * defineBehavior({\n * on: 'insert.text',\n * guard: ({event}) => event.text === 'a',\n * actions: [() => [execute({type: 'insert.text', text: 'b'})]],\n * })\n * ```\n *\n * @beta\n */\nexport function execute(\n event: SyntheticBehaviorEvent,\n): PickFromUnion<BehaviorAction, 'type', 'execute'> {\n return {type: 'execute', event}\n}\n\n/**\n * Forwards an event to the next Behavior(s) in the current chain.\n *\n * Use `forward` to pass an event to succeeding Behaviors without starting a\n * fresh lookup. This is useful for intercepting events, performing side\n * effects, and then letting the default handling continue.\n *\n * **Key rule:** When forwarding to a different event type, only Behaviors that\n * were already in the remaining chain AND match the new type will run. This\n * means cross-type `forward` is mostly useful for falling through to default\n * Behaviors, not for triggering user-defined Behaviors of a different type.\n *\n * To trigger all Behaviors for a different event type, use {@link raise}\n * instead.\n *\n * @example\n * ```ts\n * // Intercept and forward same event type\n * defineBehavior({\n * on: 'insert.text',\n * actions: [({event}) => [effect(logEvent), forward(event)]],\n * })\n *\n * // Forward to default handling of different event type\n * defineBehavior({\n * on: 'clipboard.paste',\n * actions: [\n * ({event}) => {\n * const text = event.originEvent.dataTransfer?.getData('text/plain')\n * return text ? [forward({type: 'insert.text', text})] : []\n * },\n * ],\n * })\n * ```\n *\n * @beta\n */\nexport function forward(\n event: NativeBehaviorEvent | SyntheticBehaviorEvent | CustomBehaviorEvent,\n): PickFromUnion<BehaviorAction, 'type', 'forward'> {\n return {type: 'forward', event}\n}\n\n/**\n * Raises an event, triggering a fresh lookup of all Behaviors.\n *\n * Use `raise` when you want to trigger an event \"from scratch\", including all\n * Behaviors that match the event type. This is the appropriate action when you\n * want to trigger Behaviors for a different event type.\n *\n * If no Behavior matches the raised event, synthetic events will fall through\n * to their default operation.\n *\n * @example\n * ```ts\n * // Raise a custom event that triggers other Behaviors\n * defineBehavior({\n * on: 'insert.text',\n * guard: ({event}) => event.text === 'a',\n * actions: [() => [raise({type: 'custom.specialInsert'})]],\n * })\n *\n * // Raise a different event type (fresh lookup includes all Behaviors)\n * defineBehavior({\n * on: 'clipboard.paste',\n * actions: [\n * ({event}) => {\n * const text = event.originEvent.dataTransfer?.getData('text/plain')\n * return text ? [raise({type: 'insert.text', text})] : []\n * },\n * ],\n * })\n * ```\n *\n * @beta\n */\nexport function raise(\n event: SyntheticBehaviorEvent | CustomBehaviorEvent,\n): PickFromUnion<BehaviorAction, 'type', 'raise'> {\n return {type: 'raise', event}\n}\n\n/**\n * Performs a side effect.\n *\n * Use `effect` for logging, analytics, async operations, or other side effects.\n *\n * **Note:** Using `effect` alone (without `forward`) will stop event\n * propagation. To perform a side effect while allowing the default Behavior\n * to continue, combine `effect` with `forward`.\n *\n * The effect callback receives a `send` function that can be used to send\n * events back to the editor asynchronously.\n *\n * @example\n * ```ts\n * // Log events while preserving default Behavior\n * defineBehavior({\n * on: 'insert.text',\n * actions: [({event}) => [effect(() => console.log(event)), forward(event)]],\n * })\n *\n * // Effect alone stops propagation (native event is cancelled)\n * defineBehavior({\n * on: 'keyboard.keydown',\n * actions: [() => [effect(() => console.log('key pressed'))]],\n * })\n *\n * // Async effect that sends an event later\n * defineBehavior({\n * on: 'custom.save',\n * actions: [\n * () => [\n * effect(async ({send}) => {\n * await saveDocument()\n * send({type: 'custom.saved'})\n * }),\n * ],\n * ],\n * })\n * ```\n *\n * @beta\n */\nexport function effect(\n effect: PickFromUnion<BehaviorAction, 'type', 'effect'>['effect'],\n): PickFromUnion<BehaviorAction, 'type', 'effect'> {\n return {type: 'effect', effect}\n}\n\n/**\n * @beta\n */\nexport type BehaviorActionSet<TBehaviorEvent, TGuardResponse> = (\n payload: {\n snapshot: EditorSnapshot\n event: TBehaviorEvent\n dom: EditorDom\n },\n guardResponse: TGuardResponse,\n) => Array<BehaviorAction>\n","import type {BehaviorActionSet} from './behavior.types.action'\nimport type {\n BehaviorEvent,\n BehaviorEventTypeNamespace,\n CustomBehaviorEvent,\n ResolveBehaviorEvent,\n} from './behavior.types.event'\nimport type {BehaviorGuard} from './behavior.types.guard'\n\n/**\n * @beta\n */\nexport type Behavior<\n TBehaviorEventType extends\n | '*'\n | `${BehaviorEventTypeNamespace}.*`\n | BehaviorEvent['type'] =\n | '*'\n | `${BehaviorEventTypeNamespace}.*`\n | BehaviorEvent['type'],\n TGuardResponse = true,\n TBehaviorEvent extends ResolveBehaviorEvent<TBehaviorEventType> =\n ResolveBehaviorEvent<TBehaviorEventType>,\n> = {\n /**\n * Editor Event that triggers this Behavior.\n */\n on: TBehaviorEventType\n /**\n * Predicate function that determines if the Behavior should be executed.\n * Returning a non-nullable value from the guard will pass the value to the\n * actions and execute them.\n */\n guard?: BehaviorGuard<TBehaviorEvent, TGuardResponse>\n /**\n * Array of Behavior Action sets.\n * Each set represents a step in the history stack.\n */\n actions: Array<BehaviorActionSet<TBehaviorEvent, TGuardResponse>>\n}\n\n/**\n * @beta\n *\n * @example\n *\n * ```tsx\n * const noLowerCaseA = defineBehavior({\n * on: 'insert.text',\n * guard: ({event, snapshot}) => event.text === 'a',\n * actions: [({event, snapshot}) => [{type: 'insert.text', text: 'A'}]],\n * })\n * ```\n *\n */\nexport function defineBehavior<\n TPayload extends Record<string, unknown>,\n TBehaviorEventType extends\n | '*'\n | `${BehaviorEventTypeNamespace}.*`\n | BehaviorEvent['type'] = CustomBehaviorEvent['type'],\n TGuardResponse = true,\n>(\n behavior: Behavior<\n TBehaviorEventType,\n TGuardResponse,\n ResolveBehaviorEvent<TBehaviorEventType, TPayload>\n >,\n): Behavior\nexport function defineBehavior<\n TPayload extends never = never,\n TBehaviorEventType extends\n | '*'\n | `${BehaviorEventTypeNamespace}.*`\n | BehaviorEvent['type'] = BehaviorEvent['type'],\n TGuardResponse = true,\n TBehaviorEvent extends ResolveBehaviorEvent<TBehaviorEventType, TPayload> =\n ResolveBehaviorEvent<TBehaviorEventType, TPayload>,\n>(\n behavior: Behavior<TBehaviorEventType, TGuardResponse, TBehaviorEvent>,\n): Behavior {\n return behavior as unknown as Behavior\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAwEA,SAAgBa,QACdJ,OACkD;CAClD,OAAO;EAACD,MAAM;EAAWC;CAAK;AAChC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuCA,SAAgBK,QACdL,OACkD;CAClD,OAAO;EAACD,MAAM;EAAWC;CAAK;AAChC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmCA,SAAgBM,MACdN,OACgD;CAChD,OAAO;EAACD,MAAM;EAASC;CAAK;AAC9B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4CA,SAAgBC,OACdA,QACiD;CACjD,OAAO;EAACF,MAAM;EAAUE;CAAM;AAChC;ACzIA,SAAgB2B,eAUdE,UACU;CACV,OAAOA;AACT"}
@@ -1,2 +1,2 @@
1
- import { a as forward, b as defineBehavior, c as BehaviorEvent, d as InsertPlacement, f as NativeBehaviorEvent, i as execute, l as CustomBehaviorEvent, n as BehaviorActionSet, o as raise, p as SyntheticBehaviorEvent, r as effect, t as BehaviorAction, x as BehaviorGuard, y as Behavior } from "../_chunks-dts/behavior.types.action.js";
1
+ import { Q as BehaviorGuard, X as Behavior, Z as defineBehavior, a as forward, c as CustomBehaviorEvent, d as SyntheticBehaviorEvent, i as execute, l as InsertPlacement, n as BehaviorActionSet, o as raise, r as effect, s as BehaviorEvent, t as BehaviorAction, u as NativeBehaviorEvent } from "../behavior.types.action-CYtiRDck.js";
2
2
  export { type Behavior, type BehaviorAction, type BehaviorActionSet, type BehaviorEvent, type BehaviorGuard, type CustomBehaviorEvent, type InsertPlacement, type NativeBehaviorEvent, type SyntheticBehaviorEvent, defineBehavior, effect, execute, forward, raise };
@@ -1,35 +1,2 @@
1
- function execute(event) {
2
- return {
3
- type: "execute",
4
- event
5
- };
6
- }
7
- function forward(event) {
8
- return {
9
- type: "forward",
10
- event
11
- };
12
- }
13
- function raise(event) {
14
- return {
15
- type: "raise",
16
- event
17
- };
18
- }
19
- function effect(effect2) {
20
- return {
21
- type: "effect",
22
- effect: effect2
23
- };
24
- }
25
- function defineBehavior(behavior) {
26
- return behavior;
27
- }
28
- export {
29
- defineBehavior,
30
- effect,
31
- execute,
32
- forward,
33
- raise
34
- };
35
- //# sourceMappingURL=index.js.map
1
+ import { a as raise, i as forward, n as effect, r as execute, t as defineBehavior } from "../behavior.types.behavior-B_77VtQR.js";
2
+ export { defineBehavior, effect, execute, forward, raise };
@@ -0,0 +1,222 @@
1
+ import { i as getChildren, r as getNode, u as isKeyedSegment } from "./get-parent-51Kzgaf9.js";
2
+ import { C as getAncestors, _ as comparePoints, b as isEditableContainer, g as isAfterPoint, m as rangeEdges, r as comparePoints$1, u as getNodes, v as comparePaths, y as isObject$1 } from "./get-path-sub-schema--2I4NJbG.js";
3
+ import { getSubSchema, isSpan, isTextBlock } from "@portabletext/schema";
4
+ function getAncestor(snapshot, path, options) {
5
+ let { match, mode = "lowest" } = options, ancestors = getAncestors(snapshot, path);
6
+ if (mode === "highest") {
7
+ for (let ancestor of [...ancestors].reverse()) if (match(ancestor.node, ancestor.path)) return ancestor;
8
+ return;
9
+ }
10
+ for (let ancestor of ancestors) if (match(ancestor.node, ancestor.path)) return ancestor;
11
+ }
12
+ /**
13
+ * Check if a node is a leaf object: an object node that has no editable
14
+ * children (not a container).
15
+ * Returns true for block objects and inline objects that don't have
16
+ * registered editable content (containers).
17
+ *
18
+ * @beta
19
+ */
20
+ function isLeafObject(snapshot, node, path) {
21
+ return isObject$1(snapshot, node) && !isEditableContainer(snapshot, node, path);
22
+ }
23
+ /**
24
+ * Get the deepest leaf node starting from a path, walking toward either the
25
+ * start or end edge. A leaf is any node that has no children according to the
26
+ * traversal context.
27
+ *
28
+ * @beta
29
+ */
30
+ function getLeaf(snapshot, path, options) {
31
+ let { edge } = options, currentPath = path;
32
+ if (currentPath.length === 0) {
33
+ let children = getChildren(snapshot, []);
34
+ if (children.length === 0) return;
35
+ let firstOrLast = edge === "end" ? children.at(-1) : children.at(0);
36
+ if (getChildren(snapshot, firstOrLast.path).length === 0) return firstOrLast;
37
+ currentPath = firstOrLast.path;
38
+ } else {
39
+ let entry = getNode(snapshot, currentPath);
40
+ if (!entry) return;
41
+ if (getChildren(snapshot, currentPath).length === 0) return entry;
42
+ }
43
+ for (;;) {
44
+ let children = getChildren(snapshot, currentPath);
45
+ if (children.length === 0) return getNode(snapshot, currentPath) ?? void 0;
46
+ currentPath = (edge === "end" ? children.at(-1) : children.at(0)).path;
47
+ }
48
+ }
49
+ function isPath(value) {
50
+ return Array.isArray(value) && (value.length === 0 || typeof value[0] == "number" || typeof value[0] == "string" || isKeyedSegment(value[0]));
51
+ }
52
+ const isObject = (value) => typeof value == "object" && !!value;
53
+ function isPoint(value) {
54
+ return isObject(value) && typeof value.offset == "number" && isPath(value.path);
55
+ }
56
+ function isRange(value) {
57
+ return isObject(value) && isPoint(value.anchor) && isPoint(value.focus);
58
+ }
59
+ /**
60
+ * Get the concatenated text content of the node at a given path.
61
+ *
62
+ * @beta
63
+ */
64
+ function getText(snapshot, path) {
65
+ let entry = getNode(snapshot, path);
66
+ if (!entry) return;
67
+ if (isSpan({ schema: snapshot.context.schema }, entry.node)) return entry.node.text;
68
+ let text = "";
69
+ for (let descendant of getNodes(snapshot, { at: path })) isSpan({ schema: snapshot.context.schema }, descendant.node) && (text += descendant.node.text);
70
+ return text;
71
+ }
72
+ /**
73
+ * Get the span node at a given path.
74
+ *
75
+ * @beta
76
+ */
77
+ function getSpan(snapshot, path) {
78
+ let entry = getNode(snapshot, path);
79
+ if (entry && isSpan({ schema: snapshot.context.schema }, entry.node)) return {
80
+ node: entry.node,
81
+ path: entry.path
82
+ };
83
+ }
84
+ /**
85
+ * Returns true if `ancestor` is equal to `descendant`, or if `descendant`
86
+ * lives anywhere inside `ancestor`'s subtree.
87
+ *
88
+ * @beta
89
+ */
90
+ function pathContains(ancestor, descendant) {
91
+ if (ancestor.length > descendant.length) return !1;
92
+ for (let i = 0; i < ancestor.length; i++) {
93
+ let segment = ancestor[i], otherSegment = descendant[i];
94
+ if (isKeyedSegment(segment) && isKeyedSegment(otherSegment)) {
95
+ if (segment._key !== otherSegment._key) return !1;
96
+ } else if (segment !== otherSegment) return !1;
97
+ }
98
+ return !0;
99
+ }
100
+ function isBeforePoint(point, another, root) {
101
+ return comparePoints(point, another, root) === -1;
102
+ }
103
+ /**
104
+ * Returns true if `range` and the supplied `target` intersect. The target
105
+ * may be a `Path`, an `EditorSelectionPoint`, or another
106
+ * `EditorSelection`.
107
+ *
108
+ * For a `Path` or `EditorSelectionPoint` target, "intersect" means the
109
+ * target lies at or between `range`'s start and end edges (inclusive).
110
+ *
111
+ * For an `EditorSelection` target, "intersect" means either endpoint of
112
+ * `target` lies inside `range`, or `range` strictly encloses `target`.
113
+ *
114
+ * Pass `snapshot.context.selection` as `range` to ask the question against
115
+ * the editor's current selection.
116
+ *
117
+ * Returns `false` when either `range` or `target` is `null`.
118
+ *
119
+ * @beta
120
+ */
121
+ function rangeIntersects(snapshot, range, target) {
122
+ if (!range || target === null) return !1;
123
+ let root = { value: snapshot.context.value };
124
+ if (isRange(target)) {
125
+ if (rangeIntersects(snapshot, range, target.anchor) || rangeIntersects(snapshot, range, target.focus)) return !0;
126
+ let [rs, re] = rangeEdges(range, root), [ts, te] = rangeEdges(target, root);
127
+ return isBeforePoint(rs, ts, root) && isAfterPoint(re, te, root);
128
+ }
129
+ let [start, end] = rangeEdges(range, root), isAfterStart = !1, isBeforeEnd = !1;
130
+ return isPoint(target) ? (isAfterStart = comparePoints$1(snapshot, target, start) >= 0, isBeforeEnd = comparePoints$1(snapshot, target, end) <= 0) : (isAfterStart = comparePaths(target, start.path, root) >= 0, isBeforeEnd = comparePaths(target, end.path, root) <= 0), isAfterStart && isBeforeEnd;
131
+ }
132
+ /**
133
+ * Get the text block node at a given path.
134
+ *
135
+ * @beta
136
+ */
137
+ function getTextBlock(snapshot, path) {
138
+ let entry = getNode(snapshot, path);
139
+ if (entry && isTextBlock({ schema: snapshot.context.schema }, entry.node)) return {
140
+ node: entry.node,
141
+ path: entry.path
142
+ };
143
+ }
144
+ /**
145
+ * Get the first child of a node at a given path.
146
+ *
147
+ * @beta
148
+ */
149
+ function getFirstChild(snapshot, path) {
150
+ return getChildren(snapshot, path).at(0);
151
+ }
152
+ /**
153
+ * Get the last child of a node at a given path.
154
+ *
155
+ * @beta
156
+ */
157
+ function getLastChild(snapshot, path) {
158
+ return getChildren(snapshot, path).at(-1);
159
+ }
160
+ /**
161
+ * Return a `Schema` that contains every named member declared anywhere
162
+ * in the editor's schema graph that is reachable from a position where text
163
+ * is edited - the root schema merged with the sub-schema of every registered
164
+ * container whose field accepts text blocks, deduped by name. Useful for
165
+ * rendering a static toolbar whose buttons stay stable across selection
166
+ * moves while still reflecting everything that could plausibly be edited or
167
+ * inserted somewhere.
168
+ *
169
+ * Containers whose field does NOT accept text blocks (e.g. a `table`
170
+ * container whose `rows` field only accepts `row` objects, or a `row`
171
+ * container whose `cells` field only accepts `cell` objects) are
172
+ * **structural**: their immediate `of` types are organizational, not
173
+ * insertable user content. Those structural types are excluded from the
174
+ * union. Their nested text-block-accepting descendants (e.g. a `cell`
175
+ * that contains a `content` field of `{type: 'block'}`) are reached via
176
+ * those descendants' own container registration.
177
+ *
178
+ * Pair with `getPathSubSchema` (or a path-based intersection across a
179
+ * range) to determine which of the union's members are applicable at the
180
+ * current selection.
181
+ *
182
+ * @beta
183
+ */
184
+ function getUnionSchema(schema, containers) {
185
+ let decorators = mergeByName(schema.decorators, []), annotations = mergeByName(schema.annotations, []), lists = mergeByName(schema.lists, []), styles = mergeByName(schema.styles, []), inlineObjects = mergeByName(schema.inlineObjects, []), blockObjects = mergeByName(schema.blockObjects, []);
186
+ for (let container of containers.values()) {
187
+ if (!acceptsTextBlock(container.field.of, schema.block.name)) continue;
188
+ let sub = getSubSchema(schema, container.field.of);
189
+ mergeByName(sub.decorators, decorators), mergeByName(sub.annotations, annotations), mergeByName(sub.lists, lists), mergeByName(sub.styles, styles), mergeByName(sub.inlineObjects, inlineObjects), mergeByName(sub.blockObjects, blockObjects);
190
+ }
191
+ return {
192
+ ...schema,
193
+ decorators,
194
+ annotations,
195
+ lists,
196
+ styles,
197
+ inlineObjects,
198
+ blockObjects
199
+ };
200
+ }
201
+ function acceptsTextBlock(of, blockName) {
202
+ return of.some((member) => member.type === "block" || member.type === blockName);
203
+ }
204
+ function mergeByName(source, target) {
205
+ for (let entry of source) target.some((existing) => existing.name === entry.name) || target.push(entry);
206
+ return target;
207
+ }
208
+ /**
209
+ * Get the registered editable container at a given path.
210
+ *
211
+ * @beta
212
+ */
213
+ function getContainer(snapshot, path) {
214
+ let entry = getNode(snapshot, path);
215
+ if (entry && isEditableContainer(snapshot, entry.node, entry.path)) return {
216
+ node: entry.node,
217
+ path: entry.path
218
+ };
219
+ }
220
+ export { getAncestor as _, getTextBlock as a, pathContains as c, isRange as d, isPoint as f, isLeafObject as g, getLeaf as h, getFirstChild as i, getSpan as l, isPath as m, getUnionSchema as n, rangeIntersects as o, isObject as p, getLastChild as r, isBeforePoint as s, getContainer as t, getText as u };
221
+
222
+ //# sourceMappingURL=get-container-BeXYKpoi.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-container-BeXYKpoi.js","names":["PortableTextBlock","Path","getAncestors","TraversalSnapshot","getAncestor","snapshot","path","options","match","node","TMatch","mode","ancestors","ancestor","reverse","undefined","PortableTextObject","Path","isEditableContainer","isObject","TraversalSnapshot","isLeafObject","snapshot","node","path","Node","Path","getChildren","getNode","TraversalSnapshot","getLeaf","snapshot","path","options","edge","node","currentPath","length","children","undefined","firstOrLast","at","nodeChildren","entry","child","isKeyedSegment","Path","isPath","value","Array","isArray","length","Point","isPath","isObject","isPoint","value","offset","path","Range","isPoint","isObject","isRange","value","anchor","focus","isSpan","Path","getNode","getNodes","TraversalSnapshot","getText","snapshot","path","entry","undefined","schema","context","node","text","descendant","at","isSpan","PortableTextSpan","Path","getNode","TraversalSnapshot","getSpan","snapshot","path","node","entry","undefined","schema","context","Path","isKeyedSegment","pathContains","ancestor","descendant","length","i","segment","otherSegment","_key","Node","Point","comparePoints","isBeforePoint","point","another","root","value","Array","comparePaths","isAfterPoint","isBeforePoint","isPoint","isRange","rangeEdges","EditorSelection","EditorSelectionPoint","Path","comparePoints","TraversalSnapshot","rangeIntersects","snapshot","range","target","root","value","context","anchor","focus","rs","re","ts","te","start","end","isAfterStart","isBeforeEnd","path","isTextBlock","PortableTextTextBlock","Path","getNode","TraversalSnapshot","getTextBlock","snapshot","path","node","entry","undefined","schema","context","Node","Path","getChildren","TraversalSnapshot","getFirstChild","snapshot","path","node","at","Node","Path","getChildren","TraversalSnapshot","getLastChild","snapshot","path","node","children","at","getSubSchema","Schema","Containers","getUnionSchema","schema","containers","decorators","mergeByName","annotations","lists","styles","inlineObjects","blockObjects","container","values","acceptsTextBlock","field","of","block","name","sub","ReadonlyArray","type","blockName","some","member","source","T","target","Array","entry","existing","push","Node","Path","isEditableContainer","getNode","TraversalSnapshot","getContainer","snapshot","path","node","entry","undefined"],"sources":["../src/traversal/get-ancestor.ts","../src/traversal/is-leaf-object.ts","../src/traversal/get-leaf.ts","../src/engine/path/is-path.ts","../src/engine/utils/is-object.ts","../src/engine/point/is-point.ts","../src/engine/range/is-range.ts","../src/traversal/get-text.ts","../src/traversal/get-span.ts","../src/traversal/path-contains.ts","../src/engine/point/is-before-point.ts","../src/traversal/range-intersects.ts","../src/traversal/get-text-block.ts","../src/traversal/get-first-child.ts","../src/traversal/get-last-child.ts","../src/traversal/get-union-schema.ts","../src/traversal/get-container.ts"],"sourcesContent":["import type {PortableTextBlock} from '@portabletext/schema'\nimport type {Path} from '../engine/interfaces/path'\nimport {getAncestors} from './get-ancestors'\nimport type {TraversalSnapshot} from './traversal-snapshot'\n\n/**\n * Find an ancestor of the node at a given path that matches a predicate.\n * Does not check the node at the path itself, only its ancestors.\n *\n * `mode: 'lowest'` (default) returns the nearest matching ancestor.\n * `mode: 'highest'` returns the outermost matching ancestor.\n *\n * When `match` is a type predicate, the returned `node` narrows to that type.\n *\n * @beta\n */\nexport function getAncestor<TMatch extends PortableTextBlock>(\n snapshot: TraversalSnapshot,\n path: Path,\n options: {\n match: (node: PortableTextBlock, path: Path) => node is TMatch\n mode?: 'lowest' | 'highest'\n },\n): {node: TMatch; path: Path} | undefined\n/**\n * @beta\n */\nexport function getAncestor(\n snapshot: TraversalSnapshot,\n path: Path,\n options: {\n match: (node: PortableTextBlock, path: Path) => boolean\n mode?: 'lowest' | 'highest'\n },\n): {node: PortableTextBlock; path: Path} | undefined\nexport function getAncestor(\n snapshot: TraversalSnapshot,\n path: Path,\n options: {\n match: (node: PortableTextBlock, path: Path) => boolean\n mode?: 'lowest' | 'highest'\n },\n): {node: PortableTextBlock; path: Path} | undefined {\n const {match, mode = 'lowest'} = options\n const ancestors = getAncestors(snapshot, path)\n\n if (mode === 'highest') {\n for (const ancestor of [...ancestors].reverse()) {\n if (match(ancestor.node, ancestor.path)) {\n return ancestor\n }\n }\n return undefined\n }\n\n for (const ancestor of ancestors) {\n if (match(ancestor.node, ancestor.path)) {\n return ancestor\n }\n }\n\n return undefined\n}\n","import type {PortableTextObject} from '@portabletext/schema'\nimport type {Path} from '../engine/interfaces/path'\nimport {isEditableContainer} from '../schema/is-editable-container'\nimport {isObject} from './is-object'\nimport type {TraversalSnapshot} from './traversal-snapshot'\n\n/**\n * Check if a node is a leaf object: an object node that has no editable\n * children (not a container).\n * Returns true for block objects and inline objects that don't have\n * registered editable content (containers).\n *\n * @beta\n */\nexport function isLeafObject(\n snapshot: TraversalSnapshot,\n node: unknown,\n path: Path,\n): node is PortableTextObject {\n return isObject(snapshot, node) && !isEditableContainer(snapshot, node, path)\n}\n","import type {Node} from '../engine/interfaces/node'\nimport type {Path} from '../engine/interfaces/path'\nimport {getChildren} from './get-children'\nimport {getNode} from './get-node'\nimport type {TraversalSnapshot} from './traversal-snapshot'\n\n/**\n * Get the deepest leaf node starting from a path, walking toward either the\n * start or end edge. A leaf is any node that has no children according to the\n * traversal context.\n *\n * @beta\n */\nexport function getLeaf(\n snapshot: TraversalSnapshot,\n path: Path,\n options: {edge: 'start' | 'end'},\n): {node: Node; path: Path} | undefined {\n const {edge} = options\n\n let currentPath = path\n\n // If starting from root (empty path), descend into first/last child\n if (currentPath.length === 0) {\n const children = getChildren(snapshot, [])\n if (children.length === 0) {\n return undefined\n }\n const firstOrLast = edge === 'end' ? children.at(-1)! : children.at(0)!\n const nodeChildren = getChildren(snapshot, firstOrLast.path)\n if (nodeChildren.length === 0) {\n return firstOrLast\n }\n currentPath = firstOrLast.path\n } else {\n // Check if the node at path is already a leaf\n const entry = getNode(snapshot, currentPath)\n if (!entry) {\n return undefined\n }\n const children = getChildren(snapshot, currentPath)\n if (children.length === 0) {\n return entry\n }\n }\n\n // Descend to deepest leaf\n while (true) {\n const children = getChildren(snapshot, currentPath)\n if (children.length === 0) {\n const entry = getNode(snapshot, currentPath)\n return entry ?? undefined\n }\n const child = edge === 'end' ? children.at(-1)! : children.at(0)!\n currentPath = child.path\n }\n}\n","import {isKeyedSegment} from '../../utils/util.is-keyed-segment'\nimport type {Path} from '../interfaces/path'\n\nexport function isPath(value: any): value is Path {\n return (\n Array.isArray(value) &&\n (value.length === 0 ||\n typeof value[0] === 'number' ||\n typeof value[0] === 'string' ||\n isKeyedSegment(value[0]))\n )\n}\n","export const isObject = (value: any) =>\n typeof value === 'object' && value !== null\n","import type {Point} from '../interfaces/point'\nimport {isPath} from '../path/is-path'\nimport {isObject} from '../utils/is-object'\n\nexport function isPoint(value: any): value is Point {\n return (\n isObject(value) && typeof value.offset === 'number' && isPath(value.path)\n )\n}\n","import type {Range} from '../interfaces/range'\nimport {isPoint} from '../point/is-point'\nimport {isObject} from '../utils/is-object'\n\nexport function isRange(value: any): value is Range {\n return isObject(value) && isPoint(value.anchor) && isPoint(value.focus)\n}\n","import {isSpan} from '@portabletext/schema'\nimport type {Path} from '../engine/interfaces/path'\nimport {getNode} from './get-node'\nimport {getNodes} from './get-nodes'\nimport type {TraversalSnapshot} from './traversal-snapshot'\n\n/**\n * Get the concatenated text content of the node at a given path.\n *\n * @beta\n */\nexport function getText(\n snapshot: TraversalSnapshot,\n path: Path,\n): string | undefined {\n const entry = getNode(snapshot, path)\n\n if (!entry) {\n return undefined\n }\n\n if (isSpan({schema: snapshot.context.schema}, entry.node)) {\n return entry.node.text\n }\n\n let text = ''\n\n for (const descendant of getNodes(snapshot, {at: path})) {\n if (isSpan({schema: snapshot.context.schema}, descendant.node)) {\n text += descendant.node.text\n }\n }\n\n return text\n}\n","import {isSpan, type PortableTextSpan} from '@portabletext/schema'\nimport type {Path} from '../engine/interfaces/path'\nimport {getNode} from './get-node'\nimport type {TraversalSnapshot} from './traversal-snapshot'\n\n/**\n * Get the span node at a given path.\n *\n * @beta\n */\nexport function getSpan(\n snapshot: TraversalSnapshot,\n path: Path,\n): {node: PortableTextSpan; path: Path} | undefined {\n const entry = getNode(snapshot, path)\n\n if (!entry) {\n return undefined\n }\n\n if (!isSpan({schema: snapshot.context.schema}, entry.node)) {\n return undefined\n }\n\n return {node: entry.node, path: entry.path}\n}\n","import type {Path} from '../types/paths'\nimport {isKeyedSegment} from '../utils/util.is-keyed-segment'\n\n/**\n * Returns true if `ancestor` is equal to `descendant`, or if `descendant`\n * lives anywhere inside `ancestor`'s subtree.\n *\n * @beta\n */\nexport function pathContains(ancestor: Path, descendant: Path): boolean {\n if (ancestor.length > descendant.length) {\n return false\n }\n\n for (let i = 0; i < ancestor.length; i++) {\n const segment = ancestor[i]\n const otherSegment = descendant[i]\n\n if (isKeyedSegment(segment) && isKeyedSegment(otherSegment)) {\n if (segment._key !== otherSegment._key) {\n return false\n }\n } else if (segment !== otherSegment) {\n return false\n }\n }\n\n return true\n}\n","import type {Node} from '../interfaces/node'\nimport type {Point} from '../interfaces/point'\nimport {comparePoints} from './compare-points'\n\nexport function isBeforePoint(\n point: Point,\n another: Point,\n root: {value: Array<Node>},\n): boolean {\n return comparePoints(point, another, root) === -1\n}\n","import {comparePaths} from '../engine/path/compare-paths'\nimport {isAfterPoint} from '../engine/point/is-after-point'\nimport {isBeforePoint} from '../engine/point/is-before-point'\nimport {isPoint} from '../engine/point/is-point'\nimport {isRange} from '../engine/range/is-range'\nimport {rangeEdges} from '../engine/range/range-edges'\nimport type {EditorSelection, EditorSelectionPoint} from '../types/editor'\nimport type {Path} from '../types/paths'\nimport {comparePoints} from './compare-points'\nimport type {TraversalSnapshot} from './traversal-snapshot'\n\n/**\n * Returns true if `range` and the supplied `target` intersect. The target\n * may be a `Path`, an `EditorSelectionPoint`, or another\n * `EditorSelection`.\n *\n * For a `Path` or `EditorSelectionPoint` target, \"intersect\" means the\n * target lies at or between `range`'s start and end edges (inclusive).\n *\n * For an `EditorSelection` target, \"intersect\" means either endpoint of\n * `target` lies inside `range`, or `range` strictly encloses `target`.\n *\n * Pass `snapshot.context.selection` as `range` to ask the question against\n * the editor's current selection.\n *\n * Returns `false` when either `range` or `target` is `null`.\n *\n * @beta\n */\nexport function rangeIntersects(\n snapshot: TraversalSnapshot,\n range: EditorSelection,\n target: Path | EditorSelectionPoint | EditorSelection,\n): boolean {\n if (!range || target === null) {\n return false\n }\n\n const root = {value: snapshot.context.value}\n\n if (isRange(target)) {\n if (\n rangeIntersects(snapshot, range, target.anchor) ||\n rangeIntersects(snapshot, range, target.focus)\n ) {\n return true\n }\n const [rs, re] = rangeEdges(range, root)\n const [ts, te] = rangeEdges(target, root)\n return isBeforePoint(rs, ts, root) && isAfterPoint(re, te, root)\n }\n\n const [start, end] = rangeEdges(range, root)\n let isAfterStart = false\n let isBeforeEnd = false\n\n if (isPoint(target)) {\n isAfterStart = comparePoints(snapshot, target, start) >= 0\n isBeforeEnd = comparePoints(snapshot, target, end) <= 0\n } else {\n isAfterStart = comparePaths(target, start.path, root) >= 0\n isBeforeEnd = comparePaths(target, end.path, root) <= 0\n }\n\n return isAfterStart && isBeforeEnd\n}\n","import {isTextBlock, type PortableTextTextBlock} from '@portabletext/schema'\nimport type {Path} from '../engine/interfaces/path'\nimport {getNode} from './get-node'\nimport type {TraversalSnapshot} from './traversal-snapshot'\n\n/**\n * Get the text block node at a given path.\n *\n * @beta\n */\nexport function getTextBlock(\n snapshot: TraversalSnapshot,\n path: Path,\n): {node: PortableTextTextBlock; path: Path} | undefined {\n const entry = getNode(snapshot, path)\n\n if (!entry) {\n return undefined\n }\n\n if (!isTextBlock({schema: snapshot.context.schema}, entry.node)) {\n return undefined\n }\n\n return {node: entry.node, path: entry.path}\n}\n","import type {Node} from '../engine/interfaces/node'\nimport type {Path} from '../engine/interfaces/path'\nimport {getChildren} from './get-children'\nimport type {TraversalSnapshot} from './traversal-snapshot'\n\n/**\n * Get the first child of a node at a given path.\n *\n * @beta\n */\nexport function getFirstChild(\n snapshot: TraversalSnapshot,\n path: Path,\n): {node: Node; path: Path} | undefined {\n return getChildren(snapshot, path).at(0)\n}\n","import type {Node} from '../engine/interfaces/node'\nimport type {Path} from '../engine/interfaces/path'\nimport {getChildren} from './get-children'\nimport type {TraversalSnapshot} from './traversal-snapshot'\n\n/**\n * Get the last child of a node at a given path.\n *\n * @beta\n */\nexport function getLastChild(\n snapshot: TraversalSnapshot,\n path: Path,\n): {node: Node; path: Path} | undefined {\n const children = getChildren(snapshot, path)\n\n return children.at(-1)\n}\n","import {getSubSchema, type Schema} from '@portabletext/schema'\nimport type {Containers} from '../schema/resolve-containers'\n\n/**\n * Return a `Schema` that contains every named member declared anywhere\n * in the editor's schema graph that is reachable from a position where text\n * is edited - the root schema merged with the sub-schema of every registered\n * container whose field accepts text blocks, deduped by name. Useful for\n * rendering a static toolbar whose buttons stay stable across selection\n * moves while still reflecting everything that could plausibly be edited or\n * inserted somewhere.\n *\n * Containers whose field does NOT accept text blocks (e.g. a `table`\n * container whose `rows` field only accepts `row` objects, or a `row`\n * container whose `cells` field only accepts `cell` objects) are\n * **structural**: their immediate `of` types are organizational, not\n * insertable user content. Those structural types are excluded from the\n * union. Their nested text-block-accepting descendants (e.g. a `cell`\n * that contains a `content` field of `{type: 'block'}`) are reached via\n * those descendants' own container registration.\n *\n * Pair with `getPathSubSchema` (or a path-based intersection across a\n * range) to determine which of the union's members are applicable at the\n * current selection.\n *\n * @beta\n */\nexport function getUnionSchema(schema: Schema, containers: Containers): Schema {\n const decorators = mergeByName(schema.decorators, [])\n const annotations = mergeByName(schema.annotations, [])\n const lists = mergeByName(schema.lists, [])\n const styles = mergeByName(schema.styles, [])\n const inlineObjects = mergeByName(schema.inlineObjects, [])\n const blockObjects = mergeByName(schema.blockObjects, [])\n\n for (const container of containers.values()) {\n if (!acceptsTextBlock(container.field.of, schema.block.name)) {\n continue\n }\n const sub = getSubSchema(schema, container.field.of)\n mergeByName(sub.decorators, decorators)\n mergeByName(sub.annotations, annotations)\n mergeByName(sub.lists, lists)\n mergeByName(sub.styles, styles)\n mergeByName(sub.inlineObjects, inlineObjects)\n mergeByName(sub.blockObjects, blockObjects)\n }\n\n return {\n ...schema,\n decorators,\n annotations,\n lists,\n styles,\n inlineObjects,\n blockObjects,\n }\n}\n\nfunction acceptsTextBlock(\n of: ReadonlyArray<{type: string}>,\n blockName: string,\n): boolean {\n return of.some(\n (member) => member.type === 'block' || member.type === blockName,\n )\n}\n\nfunction mergeByName<T extends {name: string}>(\n source: ReadonlyArray<T>,\n target: Array<T>,\n): Array<T> {\n for (const entry of source) {\n if (target.some((existing) => existing.name === entry.name)) {\n continue\n }\n target.push(entry)\n }\n return target\n}\n","import type {Node} from '../engine/interfaces/node'\nimport type {Path} from '../engine/interfaces/path'\nimport {isEditableContainer} from '../schema/is-editable-container'\nimport {getNode} from './get-node'\nimport type {TraversalSnapshot} from './traversal-snapshot'\n\n/**\n * Get the registered editable container at a given path.\n *\n * @beta\n */\nexport function getContainer(\n snapshot: TraversalSnapshot,\n path: Path,\n): {node: Node; path: Path} | undefined {\n const entry = getNode(snapshot, path)\n\n if (!entry) {\n return undefined\n }\n\n if (!isEditableContainer(snapshot, entry.node, entry.path)) {\n return undefined\n }\n\n return {node: entry.node, path: entry.path}\n}\n"],"mappings":"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"}