@editneo/core 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +231 -0
- package/dist/store.d.ts +31 -4
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +350 -139
- package/dist/store.js.map +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +10 -3
package/README.md
ADDED
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
# @editneo/core
|
|
2
|
+
|
|
3
|
+
The headless engine behind EditNeo. This package contains the type definitions for the block-based document model, and a Zustand-powered state store with built-in undo/redo history. It has no dependency on React or any UI framework — you can use it anywhere.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @editneo/core
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Concepts
|
|
12
|
+
|
|
13
|
+
An EditNeo document is a flat map of **blocks**, each identified by a unique ID. A separate ordered array called `rootBlocks` determines the visual order. Every block contains an array of **spans** — small chunks of text that carry inline formatting metadata like bold, italic, or links.
|
|
14
|
+
|
|
15
|
+
This flat structure (rather than a deeply nested tree) makes CRDT-based collaboration straightforward, because each block can be individually addressed and merged.
|
|
16
|
+
|
|
17
|
+
## Types
|
|
18
|
+
|
|
19
|
+
### `BlockType`
|
|
20
|
+
|
|
21
|
+
All supported block types:
|
|
22
|
+
|
|
23
|
+
```typescript
|
|
24
|
+
type BlockType =
|
|
25
|
+
| "paragraph"
|
|
26
|
+
| "heading-1"
|
|
27
|
+
| "heading-2"
|
|
28
|
+
| "heading-3"
|
|
29
|
+
| "bullet-list"
|
|
30
|
+
| "ordered-list"
|
|
31
|
+
| "todo-list"
|
|
32
|
+
| "code-block"
|
|
33
|
+
| "image"
|
|
34
|
+
| "video"
|
|
35
|
+
| "quote"
|
|
36
|
+
| "divider"
|
|
37
|
+
| "callout";
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### `Span`
|
|
41
|
+
|
|
42
|
+
A span is a run of text with optional inline formatting. A single block's content is an array of spans, so mixed formatting within a block is represented by multiple spans side by side.
|
|
43
|
+
|
|
44
|
+
```typescript
|
|
45
|
+
interface Span {
|
|
46
|
+
text: string;
|
|
47
|
+
bold?: boolean;
|
|
48
|
+
italic?: boolean;
|
|
49
|
+
code?: boolean;
|
|
50
|
+
underline?: boolean;
|
|
51
|
+
strike?: boolean;
|
|
52
|
+
color?: string; // CSS color value, e.g. "#ef4444"
|
|
53
|
+
highlight?: string; // Background highlight color
|
|
54
|
+
link?: string; // URL the text links to
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
For example, the sentence "Hello **world**" would be represented as:
|
|
59
|
+
|
|
60
|
+
```typescript
|
|
61
|
+
[{ text: "Hello " }, { text: "world", bold: true }];
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### `NeoBlock`
|
|
65
|
+
|
|
66
|
+
The fundamental unit of the document:
|
|
67
|
+
|
|
68
|
+
```typescript
|
|
69
|
+
interface NeoBlock {
|
|
70
|
+
id: string; // UUID
|
|
71
|
+
type: BlockType;
|
|
72
|
+
content: Span[]; // The text content with formatting
|
|
73
|
+
props: Record<string, any>; // Block-specific metadata (e.g. image src, language for code)
|
|
74
|
+
children: string[]; // IDs of nested child blocks
|
|
75
|
+
parentId: string | null; // ID of parent block, or null if root-level
|
|
76
|
+
createdAt: number; // Unix timestamp
|
|
77
|
+
updatedAt: number;
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### `EditorState`
|
|
82
|
+
|
|
83
|
+
The complete editor state at any point in time:
|
|
84
|
+
|
|
85
|
+
```typescript
|
|
86
|
+
interface EditorState {
|
|
87
|
+
blocks: Record<string, NeoBlock>; // All blocks, keyed by ID
|
|
88
|
+
rootBlocks: string[]; // Ordered IDs of top-level blocks
|
|
89
|
+
history: Partial<EditorState>[]; // Undo stack
|
|
90
|
+
historyIndex: number; // Current position in history
|
|
91
|
+
selection: {
|
|
92
|
+
blockId: string | null; // Currently focused block
|
|
93
|
+
startOffset: number;
|
|
94
|
+
endOffset: number;
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Editor Store
|
|
100
|
+
|
|
101
|
+
The store uses [Zustand](https://zustand-demo.pmnd.rs/) and follows a **per-instance factory pattern**. Each editor creates its own isolated store via `createEditorStore()`, so multiple editors on the same page don't share state. The store is seeded with an initial empty paragraph block.
|
|
102
|
+
|
|
103
|
+
### Creating a store instance
|
|
104
|
+
|
|
105
|
+
```typescript
|
|
106
|
+
import { createEditorStore } from "@editneo/core";
|
|
107
|
+
|
|
108
|
+
const store = createEditorStore();
|
|
109
|
+
// Each call returns a new, independent store
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Accessing state
|
|
113
|
+
|
|
114
|
+
```typescript
|
|
115
|
+
const state = store.getState();
|
|
116
|
+
const { blocks, rootBlocks, selection } = state;
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Actions
|
|
120
|
+
|
|
121
|
+
#### `addBlock(type, afterId?)`
|
|
122
|
+
|
|
123
|
+
Creates a new empty block and inserts it into the document. If `afterId` is provided and exists in `rootBlocks`, the new block is placed immediately after it. Otherwise it is appended to the end. The previous state is pushed onto the undo stack.
|
|
124
|
+
|
|
125
|
+
```typescript
|
|
126
|
+
addBlock("paragraph"); // Appends a paragraph at the end
|
|
127
|
+
addBlock("heading-1", "block-abc"); // Inserts a heading after block-abc
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
#### `insertFullBlock(block, afterId?)`
|
|
131
|
+
|
|
132
|
+
Inserts a complete `NeoBlock` object (e.g. one created by PDF extraction or imported data). Unlike `addBlock`, this accepts a fully formed block rather than just a type.
|
|
133
|
+
|
|
134
|
+
```typescript
|
|
135
|
+
insertFullBlock(myBlock, "block-abc");
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
#### `insertFullBlocks(blocks, afterId?)`
|
|
139
|
+
|
|
140
|
+
Batch-inserts multiple complete blocks at once.
|
|
141
|
+
|
|
142
|
+
```typescript
|
|
143
|
+
insertFullBlocks(pdfBlocks, "block-abc");
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
#### `updateBlock(id, partial)`
|
|
147
|
+
|
|
148
|
+
Merges partial data into an existing block. The `updatedAt` timestamp is set automatically. History is debounced — rapid edits to the same block within 300ms are grouped into a single undo step.
|
|
149
|
+
|
|
150
|
+
```typescript
|
|
151
|
+
updateBlock("block-abc", {
|
|
152
|
+
content: [{ text: "Updated text", bold: true }],
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
updateBlock("block-xyz", {
|
|
156
|
+
props: { language: "typescript" }, // For a code block
|
|
157
|
+
});
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
#### `deleteBlock(id)`
|
|
161
|
+
|
|
162
|
+
Removes a block from the document. If the block has children, those children are promoted to the root level in the same position with their `parentId` cleared. History is recorded.
|
|
163
|
+
|
|
164
|
+
```typescript
|
|
165
|
+
deleteBlock("block-abc");
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
#### `moveBlock(id, afterId)`
|
|
169
|
+
|
|
170
|
+
Moves a block to a new position. If `afterId` is `null`, the block is moved to the beginning.
|
|
171
|
+
|
|
172
|
+
```typescript
|
|
173
|
+
moveBlock("block-abc", "block-xyz"); // Move abc after xyz
|
|
174
|
+
moveBlock("block-abc", null); // Move abc to the start
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
#### `setBlockType(id, newType)`
|
|
178
|
+
|
|
179
|
+
Changes a block's type without altering its content.
|
|
180
|
+
|
|
181
|
+
```typescript
|
|
182
|
+
setBlockType("block-abc", "heading-1");
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
#### `toggleMark(mark)`
|
|
186
|
+
|
|
187
|
+
Toggles an inline formatting mark on the currently selected range. The mark is applied precisely within the selection's `startOffset`/`endOffset`, splitting spans as needed. Supported marks: `'bold'`, `'italic'`, `'underline'`, `'strike'`, `'code'`.
|
|
188
|
+
|
|
189
|
+
```typescript
|
|
190
|
+
toggleMark("bold");
|
|
191
|
+
toggleMark("italic");
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
#### `setLink(url)`
|
|
195
|
+
|
|
196
|
+
Sets (or removes) a hyperlink on the selected text range. Pass `null` to remove a link.
|
|
197
|
+
|
|
198
|
+
```typescript
|
|
199
|
+
setLink("https://editneo.dev");
|
|
200
|
+
setLink(null); // Remove link
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
#### `exportJSON()` / `importJSON(data)`
|
|
204
|
+
|
|
205
|
+
Serialize and restore the document.
|
|
206
|
+
|
|
207
|
+
```typescript
|
|
208
|
+
const data = exportJSON();
|
|
209
|
+
// data: { blocks: Record<string, NeoBlock>, rootBlocks: string[] }
|
|
210
|
+
|
|
211
|
+
importJSON(data); // Replaces the current document
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
#### `undo()` / `redo()`
|
|
215
|
+
|
|
216
|
+
Navigates through the history stack. `undo()` restores the previous state, `redo()` moves forward. Both are no-ops at the boundaries of history.
|
|
217
|
+
|
|
218
|
+
```typescript
|
|
219
|
+
undo();
|
|
220
|
+
redo();
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
## History Model
|
|
224
|
+
|
|
225
|
+
Every mutating action captures a snapshot of `blocks`, `rootBlocks`, and `selection` before applying the change. `updateBlock` uses a 300ms debounce window — rapid edits to the same block within that window are grouped into a single undo step, preventing every keystroke from creating a snapshot.
|
|
226
|
+
|
|
227
|
+
If a new action is performed after undoing, the forward history is discarded (standard undo stack behavior).
|
|
228
|
+
|
|
229
|
+
## License
|
|
230
|
+
|
|
231
|
+
MIT
|
package/dist/store.d.ts
CHANGED
|
@@ -1,13 +1,40 @@
|
|
|
1
1
|
import { NeoBlock, EditorState, BlockType, Span } from './types';
|
|
2
|
-
interface EditorActions {
|
|
2
|
+
export interface EditorActions {
|
|
3
3
|
addBlock: (type: BlockType, afterId?: string | null) => void;
|
|
4
|
+
insertFullBlock: (block: NeoBlock, afterId?: string | null) => void;
|
|
5
|
+
insertFullBlocks: (blocks: NeoBlock[], afterId?: string | null) => void;
|
|
4
6
|
updateBlock: (id: string, partial: Partial<NeoBlock>) => void;
|
|
5
7
|
deleteBlock: (id: string) => void;
|
|
8
|
+
moveBlock: (id: string, afterId: string | null) => void;
|
|
9
|
+
setBlockType: (id: string, newType: BlockType) => void;
|
|
6
10
|
toggleMark: (mark: keyof Pick<Span, 'bold' | 'italic' | 'underline' | 'strike' | 'code'>) => void;
|
|
11
|
+
setLink: (url: string | null) => void;
|
|
7
12
|
undo: () => void;
|
|
8
13
|
redo: () => void;
|
|
14
|
+
exportJSON: () => {
|
|
15
|
+
blocks: Record<string, NeoBlock>;
|
|
16
|
+
rootBlocks: string[];
|
|
17
|
+
};
|
|
18
|
+
importJSON: (data: {
|
|
19
|
+
blocks: Record<string, NeoBlock>;
|
|
20
|
+
rootBlocks: string[];
|
|
21
|
+
}) => void;
|
|
9
22
|
}
|
|
10
|
-
type EditorStore = EditorState & EditorActions;
|
|
11
|
-
|
|
12
|
-
|
|
23
|
+
export type EditorStore = EditorState & EditorActions;
|
|
24
|
+
/**
|
|
25
|
+
* Creates a new, isolated editor store instance.
|
|
26
|
+
* Each NeoEditor should have its own store so multiple editors
|
|
27
|
+
* on the same page don't share state.
|
|
28
|
+
*
|
|
29
|
+
* The store is seeded with one empty paragraph so the editor
|
|
30
|
+
* is never completely blank.
|
|
31
|
+
*/
|
|
32
|
+
export declare function createEditorStore(): import("zustand/vanilla").StoreApi<EditorStore>;
|
|
33
|
+
/** The type returned by createEditorStore() */
|
|
34
|
+
export type EditorStoreInstance = ReturnType<typeof createEditorStore>;
|
|
35
|
+
/**
|
|
36
|
+
* @deprecated Use createEditorStore() + context pattern instead.
|
|
37
|
+
* Kept for backward compatibility — this is a global singleton.
|
|
38
|
+
*/
|
|
39
|
+
export declare const useEditorStore: import("zustand/vanilla").StoreApi<EditorStore>;
|
|
13
40
|
//# sourceMappingURL=store.d.ts.map
|
package/dist/store.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AA2FjE,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IAC7D,eAAe,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IACpE,gBAAgB,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IACxE,WAAW,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,QAAQ,CAAC,KAAK,IAAI,CAAC;IAC9D,WAAW,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,SAAS,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IACxD,YAAY,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,KAAK,IAAI,CAAC;IACvD,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,GAAG,WAAW,GAAG,QAAQ,GAAG,MAAM,CAAC,KAAK,IAAI,CAAC;IAClG,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IACtC,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,UAAU,EAAE,MAAM;QAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QAAC,UAAU,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IAC7E,UAAU,EAAE,CAAC,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QAAC,UAAU,EAAE,MAAM,EAAE,CAAA;KAAE,KAAK,IAAI,CAAC;CACxF;AAED,MAAM,MAAM,WAAW,GAAG,WAAW,GAAG,aAAa,CAAC;AAItD;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,oDAiThC;AAED,+CAA+C;AAC/C,MAAM,MAAM,mBAAmB,GAAG,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAEvE;;;GAGG;AACH,eAAO,MAAM,cAAc,iDAAsB,CAAC"}
|
package/dist/store.js
CHANGED
|
@@ -1,145 +1,356 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createStore } from 'zustand/vanilla';
|
|
2
2
|
import { v4 as uuid } from 'uuid';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
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
|
-
const
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
if (afterId && state.rootBlocks.includes(afterId)) {
|
|
57
|
-
const index = newRootBlocks.indexOf(afterId);
|
|
58
|
-
newRootBlocks.splice(index + 1, 0, newId);
|
|
3
|
+
// ── Helpers ──────────────────────────────────────────────────────────
|
|
4
|
+
/** Create a blank block with sensible defaults. */
|
|
5
|
+
function makeBlock(type, content = [], props = {}) {
|
|
6
|
+
return {
|
|
7
|
+
id: uuid(),
|
|
8
|
+
type,
|
|
9
|
+
content,
|
|
10
|
+
props,
|
|
11
|
+
children: [],
|
|
12
|
+
parentId: null,
|
|
13
|
+
createdAt: Date.now(),
|
|
14
|
+
updatedAt: Date.now(),
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
/** Capture a snapshot of the mutable state fields for undo history. */
|
|
18
|
+
function snapshot(state) {
|
|
19
|
+
return {
|
|
20
|
+
blocks: state.blocks,
|
|
21
|
+
rootBlocks: state.rootBlocks,
|
|
22
|
+
selection: state.selection,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Slice spans by character offsets and toggle a mark on the selected range.
|
|
27
|
+
* Returns the new content array with the mark toggled only within [start, end).
|
|
28
|
+
*/
|
|
29
|
+
function toggleMarkInRange(spans, start, end, mark) {
|
|
30
|
+
if (spans.length === 0 || start >= end)
|
|
31
|
+
return spans;
|
|
32
|
+
const ranges = [];
|
|
33
|
+
let offset = 0;
|
|
34
|
+
for (const span of spans) {
|
|
35
|
+
ranges.push({ span, from: offset, to: offset + span.text.length });
|
|
36
|
+
offset += span.text.length;
|
|
37
|
+
}
|
|
38
|
+
// Clamp selection to content length
|
|
39
|
+
const selStart = Math.max(0, start);
|
|
40
|
+
const selEnd = Math.min(offset, end);
|
|
41
|
+
// If selection covers the entire block, fall back to the old toggle-all behavior
|
|
42
|
+
if (selStart === 0 && selEnd === offset) {
|
|
43
|
+
const allMarked = spans.length > 0 && spans.every((s) => s[mark]);
|
|
44
|
+
return spans.map((s) => ({ ...s, [mark]: !allMarked }));
|
|
45
|
+
}
|
|
46
|
+
// Check if every span within the selection range already has the mark
|
|
47
|
+
const selectedSpans = ranges.filter((r) => r.to > selStart && r.from < selEnd);
|
|
48
|
+
const allMarked = selectedSpans.every((r) => r.span[mark]);
|
|
49
|
+
const newValue = !allMarked;
|
|
50
|
+
// Split and rebuild
|
|
51
|
+
const result = [];
|
|
52
|
+
for (const { span, from, to } of ranges) {
|
|
53
|
+
if (to <= selStart || from >= selEnd) {
|
|
54
|
+
// Entirely outside selection — keep as-is
|
|
55
|
+
result.push(span);
|
|
59
56
|
}
|
|
60
|
-
else {
|
|
61
|
-
|
|
57
|
+
else if (from >= selStart && to <= selEnd) {
|
|
58
|
+
// Entirely inside selection — toggle
|
|
59
|
+
result.push({ ...span, [mark]: newValue });
|
|
62
60
|
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
if (!block)
|
|
74
|
-
return state;
|
|
75
|
-
// naive history push for every update (might need debouncing for text)
|
|
76
|
-
const historyEntry = {
|
|
77
|
-
blocks: state.blocks,
|
|
78
|
-
rootBlocks: state.rootBlocks,
|
|
79
|
-
selection: state.selection
|
|
80
|
-
};
|
|
81
|
-
const newHistory = [...state.history.slice(0, state.historyIndex + 1), historyEntry];
|
|
82
|
-
return {
|
|
83
|
-
blocks: {
|
|
84
|
-
...state.blocks,
|
|
85
|
-
[id]: { ...block, ...partial, updatedAt: Date.now() },
|
|
86
|
-
},
|
|
87
|
-
history: newHistory,
|
|
88
|
-
historyIndex: newHistory.length - 1
|
|
89
|
-
};
|
|
90
|
-
}),
|
|
91
|
-
deleteBlock: (id) => set((state) => {
|
|
92
|
-
const block = state.blocks[id];
|
|
93
|
-
if (!block)
|
|
94
|
-
return state;
|
|
95
|
-
const historyEntry = {
|
|
96
|
-
blocks: state.blocks,
|
|
97
|
-
rootBlocks: state.rootBlocks,
|
|
98
|
-
selection: state.selection
|
|
99
|
-
};
|
|
100
|
-
const newHistory = [...state.history.slice(0, state.historyIndex + 1), historyEntry];
|
|
101
|
-
const { [id]: deleted, ...remainingBlocks } = state.blocks;
|
|
102
|
-
const newRootBlocks = state.rootBlocks.filter((blockId) => blockId !== id);
|
|
103
|
-
if (block.children.length > 0) {
|
|
104
|
-
const index = state.rootBlocks.indexOf(id);
|
|
105
|
-
if (index !== -1) {
|
|
106
|
-
newRootBlocks.splice(index, 0, ...block.children);
|
|
61
|
+
else {
|
|
62
|
+
// Partially overlaps — split the span
|
|
63
|
+
if (from < selStart) {
|
|
64
|
+
result.push({ ...span, text: span.text.slice(0, selStart - from) });
|
|
65
|
+
}
|
|
66
|
+
const overlapStart = Math.max(from, selStart);
|
|
67
|
+
const overlapEnd = Math.min(to, selEnd);
|
|
68
|
+
result.push({ ...span, text: span.text.slice(overlapStart - from, overlapEnd - from), [mark]: newValue });
|
|
69
|
+
if (to > selEnd) {
|
|
70
|
+
result.push({ ...span, text: span.text.slice(selEnd - from) });
|
|
107
71
|
}
|
|
108
72
|
}
|
|
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
|
-
})
|
|
73
|
+
}
|
|
74
|
+
return result;
|
|
75
|
+
}
|
|
76
|
+
// ── Store factory ────────────────────────────────────────────────────
|
|
77
|
+
/**
|
|
78
|
+
* Creates a new, isolated editor store instance.
|
|
79
|
+
* Each NeoEditor should have its own store so multiple editors
|
|
80
|
+
* on the same page don't share state.
|
|
81
|
+
*
|
|
82
|
+
* The store is seeded with one empty paragraph so the editor
|
|
83
|
+
* is never completely blank.
|
|
84
|
+
*/
|
|
85
|
+
export function createEditorStore() {
|
|
86
|
+
// Seed with one empty paragraph (#1)
|
|
87
|
+
const initialBlock = makeBlock('paragraph');
|
|
88
|
+
return createStore((set, get) => ({
|
|
89
|
+
blocks: { [initialBlock.id]: initialBlock },
|
|
90
|
+
rootBlocks: [initialBlock.id],
|
|
91
|
+
selection: {
|
|
92
|
+
blockId: initialBlock.id,
|
|
93
|
+
startOffset: 0,
|
|
94
|
+
endOffset: 0,
|
|
95
|
+
},
|
|
96
|
+
history: [],
|
|
97
|
+
historyIndex: -1,
|
|
98
|
+
// ── History navigation ─────────────────────────────────────────
|
|
99
|
+
undo: () => set((state) => {
|
|
100
|
+
if (state.historyIndex < 0)
|
|
101
|
+
return state;
|
|
102
|
+
const prev = state.history[state.historyIndex];
|
|
103
|
+
return {
|
|
104
|
+
...prev,
|
|
105
|
+
historyIndex: state.historyIndex - 1,
|
|
106
|
+
history: state.history,
|
|
107
|
+
};
|
|
108
|
+
}),
|
|
109
|
+
redo: () => set((state) => {
|
|
110
|
+
if (state.historyIndex >= state.history.length - 1)
|
|
111
|
+
return state;
|
|
112
|
+
const next = state.history[state.historyIndex + 1];
|
|
113
|
+
return {
|
|
114
|
+
...next,
|
|
115
|
+
historyIndex: state.historyIndex + 1,
|
|
116
|
+
history: state.history,
|
|
117
|
+
};
|
|
118
|
+
}),
|
|
119
|
+
// ── Block CRUD ─────────────────────────────────────────────────
|
|
120
|
+
addBlock: (type, afterId = null) => set((state) => {
|
|
121
|
+
const newHistory = [...state.history.slice(0, state.historyIndex + 1), snapshot(state)];
|
|
122
|
+
const newBlock = makeBlock(type);
|
|
123
|
+
const newRootBlocks = [...state.rootBlocks];
|
|
124
|
+
if (afterId && state.rootBlocks.includes(afterId)) {
|
|
125
|
+
const index = newRootBlocks.indexOf(afterId);
|
|
126
|
+
newRootBlocks.splice(index + 1, 0, newBlock.id);
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
newRootBlocks.push(newBlock.id);
|
|
130
|
+
}
|
|
131
|
+
return {
|
|
132
|
+
blocks: { ...state.blocks, [newBlock.id]: newBlock },
|
|
133
|
+
rootBlocks: newRootBlocks,
|
|
134
|
+
history: newHistory,
|
|
135
|
+
historyIndex: newHistory.length - 1,
|
|
136
|
+
selection: { blockId: newBlock.id, startOffset: 0, endOffset: 0 },
|
|
137
|
+
};
|
|
138
|
+
}),
|
|
139
|
+
/** Insert a complete NeoBlock object (e.g. from PDF extraction). (#2) */
|
|
140
|
+
insertFullBlock: (block, afterId = null) => set((state) => {
|
|
141
|
+
const newHistory = [...state.history.slice(0, state.historyIndex + 1), snapshot(state)];
|
|
142
|
+
const newRootBlocks = [...state.rootBlocks];
|
|
143
|
+
if (afterId && state.rootBlocks.includes(afterId)) {
|
|
144
|
+
const index = newRootBlocks.indexOf(afterId);
|
|
145
|
+
newRootBlocks.splice(index + 1, 0, block.id);
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
newRootBlocks.push(block.id);
|
|
149
|
+
}
|
|
150
|
+
return {
|
|
151
|
+
blocks: { ...state.blocks, [block.id]: block },
|
|
152
|
+
rootBlocks: newRootBlocks,
|
|
153
|
+
history: newHistory,
|
|
154
|
+
historyIndex: newHistory.length - 1,
|
|
155
|
+
selection: { blockId: block.id, startOffset: 0, endOffset: 0 },
|
|
156
|
+
};
|
|
157
|
+
}),
|
|
158
|
+
/** Insert multiple complete blocks at once (batch insert). */
|
|
159
|
+
insertFullBlocks: (blocks, afterId = null) => set((state) => {
|
|
160
|
+
const newHistory = [...state.history.slice(0, state.historyIndex + 1), snapshot(state)];
|
|
161
|
+
const newBlocks = { ...state.blocks };
|
|
162
|
+
const newRootBlocks = [...state.rootBlocks];
|
|
163
|
+
const insertIndex = afterId && state.rootBlocks.includes(afterId)
|
|
164
|
+
? newRootBlocks.indexOf(afterId) + 1
|
|
165
|
+
: newRootBlocks.length;
|
|
166
|
+
const ids = [];
|
|
167
|
+
for (const block of blocks) {
|
|
168
|
+
newBlocks[block.id] = block;
|
|
169
|
+
ids.push(block.id);
|
|
170
|
+
}
|
|
171
|
+
newRootBlocks.splice(insertIndex, 0, ...ids);
|
|
172
|
+
const lastId = ids[ids.length - 1] || null;
|
|
173
|
+
return {
|
|
174
|
+
blocks: newBlocks,
|
|
175
|
+
rootBlocks: newRootBlocks,
|
|
176
|
+
history: newHistory,
|
|
177
|
+
historyIndex: newHistory.length - 1,
|
|
178
|
+
selection: { blockId: lastId, startOffset: 0, endOffset: 0 },
|
|
179
|
+
};
|
|
180
|
+
}),
|
|
181
|
+
updateBlock: (id, partial) => {
|
|
182
|
+
const now = Date.now();
|
|
183
|
+
const DEBOUNCE_MS = 300;
|
|
184
|
+
set((state) => {
|
|
185
|
+
const block = state.blocks[id];
|
|
186
|
+
if (!block)
|
|
187
|
+
return state;
|
|
188
|
+
// (#5) Debounce: only push history if >300ms since last update to this block,
|
|
189
|
+
// or if a different block is being updated
|
|
190
|
+
const timeSinceLastUpdate = now - (block.updatedAt || 0);
|
|
191
|
+
const shouldPushHistory = timeSinceLastUpdate > DEBOUNCE_MS;
|
|
192
|
+
let newHistory = state.history;
|
|
193
|
+
let newHistoryIndex = state.historyIndex;
|
|
194
|
+
if (shouldPushHistory) {
|
|
195
|
+
newHistory = [...state.history.slice(0, state.historyIndex + 1), snapshot(state)];
|
|
196
|
+
newHistoryIndex = newHistory.length - 1;
|
|
197
|
+
}
|
|
198
|
+
return {
|
|
199
|
+
blocks: {
|
|
200
|
+
...state.blocks,
|
|
201
|
+
[id]: { ...block, ...partial, updatedAt: now },
|
|
202
|
+
},
|
|
203
|
+
history: newHistory,
|
|
204
|
+
historyIndex: newHistoryIndex,
|
|
205
|
+
};
|
|
206
|
+
});
|
|
207
|
+
},
|
|
208
|
+
/** Delete a block. Children are promoted to root with parentId cleared. (#4) */
|
|
209
|
+
deleteBlock: (id) => set((state) => {
|
|
210
|
+
const block = state.blocks[id];
|
|
211
|
+
if (!block)
|
|
212
|
+
return state;
|
|
213
|
+
const newHistory = [...state.history.slice(0, state.historyIndex + 1), snapshot(state)];
|
|
214
|
+
const { [id]: _deleted, ...remainingBlocks } = state.blocks;
|
|
215
|
+
const newRootBlocks = state.rootBlocks.filter((blockId) => blockId !== id);
|
|
216
|
+
// Promote children to root and clear their parentId
|
|
217
|
+
if (block.children.length > 0) {
|
|
218
|
+
const index = state.rootBlocks.indexOf(id);
|
|
219
|
+
if (index !== -1) {
|
|
220
|
+
newRootBlocks.splice(index, 0, ...block.children);
|
|
221
|
+
}
|
|
222
|
+
for (const childId of block.children) {
|
|
223
|
+
if (remainingBlocks[childId]) {
|
|
224
|
+
remainingBlocks[childId] = { ...remainingBlocks[childId], parentId: null };
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
return {
|
|
229
|
+
blocks: remainingBlocks,
|
|
230
|
+
rootBlocks: newRootBlocks,
|
|
231
|
+
history: newHistory,
|
|
232
|
+
historyIndex: newHistory.length - 1,
|
|
233
|
+
};
|
|
234
|
+
}),
|
|
235
|
+
/** Move a block to a new position (after afterId, or to the start if null). (#6) */
|
|
236
|
+
moveBlock: (id, afterId) => set((state) => {
|
|
237
|
+
if (!state.blocks[id])
|
|
238
|
+
return state;
|
|
239
|
+
const newHistory = [...state.history.slice(0, state.historyIndex + 1), snapshot(state)];
|
|
240
|
+
const newRootBlocks = state.rootBlocks.filter((bid) => bid !== id);
|
|
241
|
+
if (afterId && newRootBlocks.includes(afterId)) {
|
|
242
|
+
const idx = newRootBlocks.indexOf(afterId);
|
|
243
|
+
newRootBlocks.splice(idx + 1, 0, id);
|
|
244
|
+
}
|
|
245
|
+
else {
|
|
246
|
+
newRootBlocks.unshift(id);
|
|
247
|
+
}
|
|
248
|
+
return {
|
|
249
|
+
rootBlocks: newRootBlocks,
|
|
250
|
+
history: newHistory,
|
|
251
|
+
historyIndex: newHistory.length - 1,
|
|
252
|
+
};
|
|
253
|
+
}),
|
|
254
|
+
/** Change a block's type without losing content. (#6) */
|
|
255
|
+
setBlockType: (id, newType) => set((state) => {
|
|
256
|
+
const block = state.blocks[id];
|
|
257
|
+
if (!block)
|
|
258
|
+
return state;
|
|
259
|
+
const newHistory = [...state.history.slice(0, state.historyIndex + 1), snapshot(state)];
|
|
260
|
+
return {
|
|
261
|
+
blocks: {
|
|
262
|
+
...state.blocks,
|
|
263
|
+
[id]: { ...block, type: newType, updatedAt: Date.now() },
|
|
264
|
+
},
|
|
265
|
+
history: newHistory,
|
|
266
|
+
historyIndex: newHistory.length - 1,
|
|
267
|
+
};
|
|
268
|
+
}),
|
|
269
|
+
// ── Inline formatting ──────────────────────────────────────────
|
|
270
|
+
/** Toggle a mark on the selected range only (#3). */
|
|
271
|
+
toggleMark: (mark) => set((state) => {
|
|
272
|
+
const blockId = state.selection.blockId;
|
|
273
|
+
if (!blockId)
|
|
274
|
+
return state;
|
|
275
|
+
const block = state.blocks[blockId];
|
|
276
|
+
if (!block)
|
|
277
|
+
return state;
|
|
278
|
+
const { startOffset, endOffset } = state.selection;
|
|
279
|
+
const newContent = toggleMarkInRange(block.content, startOffset, endOffset, mark);
|
|
280
|
+
const newHistory = [...state.history.slice(0, state.historyIndex + 1), snapshot(state)];
|
|
281
|
+
return {
|
|
282
|
+
blocks: {
|
|
283
|
+
...state.blocks,
|
|
284
|
+
[blockId]: { ...block, content: newContent, updatedAt: Date.now() },
|
|
285
|
+
},
|
|
286
|
+
history: newHistory,
|
|
287
|
+
historyIndex: newHistory.length - 1,
|
|
288
|
+
};
|
|
289
|
+
}),
|
|
290
|
+
/** Set or clear a link on the selected range. (#19 support) */
|
|
291
|
+
setLink: (url) => set((state) => {
|
|
292
|
+
const blockId = state.selection.blockId;
|
|
293
|
+
if (!blockId)
|
|
294
|
+
return state;
|
|
295
|
+
const block = state.blocks[blockId];
|
|
296
|
+
if (!block || block.content.length === 0)
|
|
297
|
+
return state;
|
|
298
|
+
const { startOffset, endOffset } = state.selection;
|
|
299
|
+
const newHistory = [...state.history.slice(0, state.historyIndex + 1), snapshot(state)];
|
|
300
|
+
// Apply link to spans in the selection range
|
|
301
|
+
const result = [];
|
|
302
|
+
let offset = 0;
|
|
303
|
+
for (const span of block.content) {
|
|
304
|
+
const from = offset;
|
|
305
|
+
const to = offset + span.text.length;
|
|
306
|
+
offset = to;
|
|
307
|
+
if (to <= startOffset || from >= endOffset) {
|
|
308
|
+
result.push(span);
|
|
309
|
+
}
|
|
310
|
+
else if (from >= startOffset && to <= endOffset) {
|
|
311
|
+
result.push({ ...span, link: url || undefined });
|
|
312
|
+
}
|
|
313
|
+
else {
|
|
314
|
+
if (from < startOffset) {
|
|
315
|
+
result.push({ ...span, text: span.text.slice(0, startOffset - from) });
|
|
316
|
+
}
|
|
317
|
+
const overlapStart = Math.max(from, startOffset);
|
|
318
|
+
const overlapEnd = Math.min(to, endOffset);
|
|
319
|
+
result.push({ ...span, text: span.text.slice(overlapStart - from, overlapEnd - from), link: url || undefined });
|
|
320
|
+
if (to > endOffset) {
|
|
321
|
+
result.push({ ...span, text: span.text.slice(endOffset - from) });
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
return {
|
|
326
|
+
blocks: {
|
|
327
|
+
...state.blocks,
|
|
328
|
+
[blockId]: { ...block, content: result, updatedAt: Date.now() },
|
|
329
|
+
},
|
|
330
|
+
history: newHistory,
|
|
331
|
+
historyIndex: newHistory.length - 1,
|
|
332
|
+
};
|
|
333
|
+
}),
|
|
334
|
+
// ── Serialization (#45) ────────────────────────────────────────
|
|
335
|
+
exportJSON: () => {
|
|
336
|
+
const state = get();
|
|
337
|
+
return { blocks: state.blocks, rootBlocks: state.rootBlocks };
|
|
338
|
+
},
|
|
339
|
+
importJSON: (data) => set((state) => {
|
|
340
|
+
const newHistory = [...state.history.slice(0, state.historyIndex + 1), snapshot(state)];
|
|
341
|
+
return {
|
|
342
|
+
blocks: data.blocks,
|
|
343
|
+
rootBlocks: data.rootBlocks,
|
|
344
|
+
history: newHistory,
|
|
345
|
+
historyIndex: newHistory.length - 1,
|
|
346
|
+
selection: { blockId: data.rootBlocks[0] || null, startOffset: 0, endOffset: 0 },
|
|
347
|
+
};
|
|
348
|
+
}),
|
|
349
|
+
}));
|
|
350
|
+
}
|
|
351
|
+
/**
|
|
352
|
+
* @deprecated Use createEditorStore() + context pattern instead.
|
|
353
|
+
* Kept for backward compatibility — this is a global singleton.
|
|
354
|
+
*/
|
|
355
|
+
export const useEditorStore = createEditorStore();
|
|
145
356
|
//# sourceMappingURL=store.js.map
|
package/dist/store.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.js","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type BlockType = 'paragraph' | 'heading-1' | 'heading-2' | 'heading-3' | 'bullet-list' | 'ordered-list' | 'todo-list' | 'code-block' | 'image' | 'video' | '
|
|
1
|
+
export type BlockType = 'paragraph' | 'heading-1' | 'heading-2' | 'heading-3' | 'bullet-list' | 'ordered-list' | 'todo-list' | 'code-block' | 'image' | 'video' | 'quote' | 'divider' | 'callout';
|
|
2
2
|
export interface Span {
|
|
3
3
|
text: string;
|
|
4
4
|
bold?: boolean;
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,SAAS,GACjB,WAAW,GACX,WAAW,GAAG,WAAW,GAAG,WAAW,GACvC,aAAa,GAAG,cAAc,GAAG,WAAW,GAC5C,YAAY,GACZ,OAAO,GAAG,OAAO,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,SAAS,GACjB,WAAW,GACX,WAAW,GAAG,WAAW,GAAG,WAAW,GACvC,aAAa,GAAG,cAAc,GAAG,WAAW,GAC5C,YAAY,GACZ,OAAO,GAAG,OAAO,GACjB,OAAO,GAAG,SAAS,GAAG,SAAS,CAAC;AAEpC,MAAM,WAAW,IAAI;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,EAAE,IAAI,EAAE,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC3B,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACjC,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,OAAO,EAAE,OAAO,CAAC,WAAW,CAAC,EAAE,CAAC;IAChC,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE;QACT,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;QACvB,WAAW,EAAE,MAAM,CAAC;QACpB,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;CACH"}
|
package/package.json
CHANGED
|
@@ -1,9 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@editneo/core",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Core engine for EditNeo — block-based editor with CRDT sync",
|
|
5
|
+
"type": "module",
|
|
5
6
|
"main": "./dist/index.js",
|
|
6
7
|
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js",
|
|
12
|
+
"default": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
7
15
|
"files": ["dist"],
|
|
8
16
|
"scripts": {
|
|
9
17
|
"build": "tsc",
|
|
@@ -14,8 +22,7 @@
|
|
|
14
22
|
},
|
|
15
23
|
"dependencies": {
|
|
16
24
|
"zustand": "^4.5.1",
|
|
17
|
-
"uuid": "^9.0.1"
|
|
18
|
-
"immer": "^10.0.3"
|
|
25
|
+
"uuid": "^9.0.1"
|
|
19
26
|
},
|
|
20
27
|
"devDependencies": {
|
|
21
28
|
"typescript": "^5.3.3",
|