@ixo/editor 0.2.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -12,7 +12,7 @@ A custom BlockNote editor wrapper built specifically for the IXO team's needs. T
|
|
|
12
12
|
- 🔗 **Custom Blocks**: Built-in custom blocks including dynamic List block for DID data
|
|
13
13
|
- 🖼️ **Media Support**: Image and file upload handling
|
|
14
14
|
- 🎯 **TypeScript**: Full TypeScript support with exported types
|
|
15
|
-
- 🤝 **Collaboration Ready**: Built-in
|
|
15
|
+
- 🤝 **Collaboration Ready**: Built-in Matrix-based collaborative editing with real-time synchronization
|
|
16
16
|
- 📱 **Responsive**: Mobile-friendly editor experience
|
|
17
17
|
|
|
18
18
|
## Installation
|
|
@@ -50,7 +50,6 @@ import '@ixo/editor/style.css'; // Import IXO custom styles
|
|
|
50
50
|
function MyEditor() {
|
|
51
51
|
const editor = useCreateIxoEditor({
|
|
52
52
|
theme: 'light',
|
|
53
|
-
placeholder: 'Start writing...',
|
|
54
53
|
initialContent: [
|
|
55
54
|
{
|
|
56
55
|
type: 'heading',
|
|
@@ -91,21 +90,15 @@ const editor = useCreateIxoEditor(options?: IxoEditorOptions);
|
|
|
91
90
|
| Option | Type | Default | Description |
|
|
92
91
|
|--------|------|---------|-------------|
|
|
93
92
|
| `theme` | `'light' \| 'dark'` | `'light'` | Editor color theme |
|
|
94
|
-
| `placeholder` | `string` | `'Start typing or press "/" for commands...'` | Placeholder text |
|
|
95
93
|
| `uploadFile` | `(file: File) => Promise<string>` | Data URL converter | File upload handler |
|
|
96
94
|
| `initialContent` | `PartialBlock[]` | `undefined` | Initial editor content |
|
|
97
95
|
| `editable` | `boolean` | `true` | Whether editor is editable |
|
|
98
|
-
| `animations` | `boolean` | `true` | Enable/disable animations |
|
|
99
96
|
| `sideMenu` | `boolean` | `true` | Show side menu (drag handle, plus button) |
|
|
100
97
|
| `slashMenu` | `boolean` | `true` | Enable slash commands menu |
|
|
101
98
|
| `formattingToolbar` | `boolean` | `true` | Show formatting toolbar |
|
|
102
99
|
| `linkToolbar` | `boolean` | `true` | Show link toolbar |
|
|
103
100
|
| `filePanel` | `boolean` | `true` | Show file panel |
|
|
104
101
|
| `tableHandles` | `boolean` | `true` | Show table manipulation handles |
|
|
105
|
-
| `trailingBlock` | `boolean` | `true` | Add trailing paragraph block |
|
|
106
|
-
| `placeholders` | `Record<string, string>` | `{}` | Custom placeholders for blocks |
|
|
107
|
-
| `dictionary` | `Record<string, string>` | `{}` | Custom translations |
|
|
108
|
-
| `collaboration` | `CollaborationConfig` | `undefined` | Collaboration settings |
|
|
109
102
|
|
|
110
103
|
### `IxoEditor` Component
|
|
111
104
|
|
|
@@ -151,20 +144,36 @@ const editor = useCreateIxoEditor({
|
|
|
151
144
|
});
|
|
152
145
|
```
|
|
153
146
|
|
|
154
|
-
###
|
|
147
|
+
### Collaborative Editing
|
|
148
|
+
|
|
149
|
+
For real-time collaborative editing, use the `useCreateCollaborativeIxoEditor` hook with Matrix protocol:
|
|
155
150
|
|
|
156
151
|
```tsx
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
152
|
+
import { useCreateCollaborativeIxoEditor, IxoEditor } from '@ixo/editor';
|
|
153
|
+
|
|
154
|
+
function CollaborativeEditor() {
|
|
155
|
+
const { editor, connectionStatus } = useCreateCollaborativeIxoEditor({
|
|
156
|
+
theme: 'light',
|
|
161
157
|
user: {
|
|
162
|
-
id: 'user-
|
|
158
|
+
id: 'user-123',
|
|
163
159
|
name: 'John Doe',
|
|
164
|
-
color: '#FF5733'
|
|
160
|
+
color: '#FF5733',
|
|
161
|
+
accessToken: 'your-matrix-access-token',
|
|
162
|
+
address: 'your-user-address'
|
|
163
|
+
},
|
|
164
|
+
matrix: {
|
|
165
|
+
roomId: '!roomId:matrix.org',
|
|
166
|
+
baseUrl: 'https://matrix.org'
|
|
165
167
|
}
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
return (
|
|
171
|
+
<div>
|
|
172
|
+
<div>Connection: {connectionStatus}</div>
|
|
173
|
+
<IxoEditor editor={editor} />
|
|
174
|
+
</div>
|
|
175
|
+
);
|
|
176
|
+
}
|
|
168
177
|
```
|
|
169
178
|
|
|
170
179
|
### Accessing Editor Content
|
|
@@ -211,9 +220,15 @@ const editor = useCreateIxoEditor({
|
|
|
211
220
|
|
|
212
221
|
## Custom Blocks
|
|
213
222
|
|
|
223
|
+
The IXO Editor includes two custom blocks for working with IXO ecosystem data:
|
|
224
|
+
|
|
214
225
|
### List Block
|
|
215
226
|
|
|
216
|
-
The
|
|
227
|
+
The List block displays dynamic data from DID and fragment identifiers, perfect for displaying data from your GraphQL API.
|
|
228
|
+
|
|
229
|
+
### Overview Block
|
|
230
|
+
|
|
231
|
+
The Overview block provides a comprehensive view of entity data from DID identifiers.
|
|
217
232
|
|
|
218
233
|
#### Features
|
|
219
234
|
|
|
@@ -227,10 +242,16 @@ The IXO Editor includes a custom List block for displaying dynamic data from DID
|
|
|
227
242
|
|
|
228
243
|
The List block can be inserted using the slash menu:
|
|
229
244
|
|
|
245
|
+
**List Block:**
|
|
230
246
|
1. Type `/list` in the editor
|
|
231
247
|
2. Or type `/` and search for "List", "data", or "dynamic"
|
|
232
248
|
3. Configure the DID and fragment identifier in the settings
|
|
233
249
|
|
|
250
|
+
**Overview Block:**
|
|
251
|
+
1. Type `/overview` in the editor
|
|
252
|
+
2. Or type `/` and search for "Overview", "overview-block", or "data-overview"
|
|
253
|
+
3. Configure the DID in the settings
|
|
254
|
+
|
|
234
255
|
#### Programmatic Usage
|
|
235
256
|
|
|
236
257
|
```tsx
|
|
@@ -243,6 +264,14 @@ editor.insertBlocks([{
|
|
|
243
264
|
fragmentIdentifier: 'claims-data'
|
|
244
265
|
}
|
|
245
266
|
}], editor.getTextCursorPosition().block, 'after');
|
|
267
|
+
|
|
268
|
+
// Insert an overview block programmatically
|
|
269
|
+
editor.insertBlocks([{
|
|
270
|
+
type: 'overview',
|
|
271
|
+
props: {
|
|
272
|
+
did: 'did:ixo:entity123'
|
|
273
|
+
}
|
|
274
|
+
}], editor.getTextCursorPosition().block, 'after');
|
|
246
275
|
```
|
|
247
276
|
|
|
248
277
|
#### Integration with GraphQL
|
|
@@ -299,15 +328,29 @@ npm run type-check
|
|
|
299
328
|
ixo-editor/
|
|
300
329
|
├── src/
|
|
301
330
|
│ ├── components/ # React components
|
|
302
|
-
│ │
|
|
331
|
+
│ │ ├── IxoEditor.tsx
|
|
332
|
+
│ │ ├── SettingsModal/
|
|
333
|
+
│ │ ├── ui/ # Shadcn/UI components
|
|
334
|
+
│ │ └── icons/ # Custom icon components
|
|
303
335
|
│ ├── hooks/ # Custom hooks
|
|
304
|
-
│ │
|
|
336
|
+
│ │ ├── useCreateIxoEditor.ts
|
|
337
|
+
│ │ ├── useCollaborativeIxoEditor.ts
|
|
338
|
+
│ │ └── useMatrixProvider.ts
|
|
339
|
+
│ ├── blocks/ # Custom block implementations
|
|
340
|
+
│ │ ├── list/ # List block
|
|
341
|
+
│ │ ├── overview/ # Overview block
|
|
342
|
+
│ │ └── index.ts
|
|
343
|
+
│ ├── lib/ # Utilities and GraphQL
|
|
344
|
+
│ │ ├── graphql-client.ts
|
|
345
|
+
│ │ ├── graphql-queries.ts
|
|
346
|
+
│ │ └── utils/
|
|
305
347
|
│ ├── styles/ # CSS styles
|
|
306
348
|
│ │ └── ixo-editor.css
|
|
307
349
|
│ ├── types/ # TypeScript types
|
|
308
|
-
│ │
|
|
350
|
+
│ │ ├── index.ts
|
|
351
|
+
│ │ └── Domain.ts
|
|
309
352
|
│ └── index.ts # Main entry point
|
|
310
|
-
├──
|
|
353
|
+
├── dist/ # Built output (generated)
|
|
311
354
|
├── package.json
|
|
312
355
|
├── tsconfig.json
|
|
313
356
|
└── README.md
|
|
@@ -318,6 +361,7 @@ ixo-editor/
|
|
|
318
361
|
- React 18.0.0 or higher
|
|
319
362
|
- React DOM 18.0.0 or higher
|
|
320
363
|
- Modern browser with ES2020 support
|
|
364
|
+
- For collaborative editing: Matrix server access
|
|
321
365
|
|
|
322
366
|
## License
|
|
323
367
|
|
|
@@ -38,7 +38,7 @@ exports.Button = Button;
|
|
|
38
38
|
const React = __importStar(require("react"));
|
|
39
39
|
const react_slot_1 = require("@radix-ui/react-slot");
|
|
40
40
|
const class_variance_authority_1 = require("class-variance-authority");
|
|
41
|
-
const utils_1 = require("
|
|
41
|
+
const utils_1 = require("../../lib/utils");
|
|
42
42
|
const buttonVariants = (0, class_variance_authority_1.cva)("inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", {
|
|
43
43
|
variants: {
|
|
44
44
|
variant: {
|
|
@@ -35,7 +35,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.CardContent = exports.CardDescription = exports.CardTitle = exports.CardFooter = exports.CardHeader = exports.Card = void 0;
|
|
37
37
|
const React = __importStar(require("react"));
|
|
38
|
-
const utils_1 = require("
|
|
38
|
+
const utils_1 = require("../../lib/utils");
|
|
39
39
|
const Card = React.forwardRef(({ className, ...props }, ref) => (React.createElement("div", { ref: ref, className: (0, utils_1.cn)("rounded-lg border bg-card text-card-foreground shadow-sm", className), ...props })));
|
|
40
40
|
exports.Card = Card;
|
|
41
41
|
Card.displayName = "Card";
|
|
@@ -46,7 +46,7 @@ exports.DialogTrigger = DialogTrigger;
|
|
|
46
46
|
const React = __importStar(require("react"));
|
|
47
47
|
const DialogPrimitive = __importStar(require("@radix-ui/react-dialog"));
|
|
48
48
|
const lucide_react_1 = require("lucide-react");
|
|
49
|
-
const utils_1 = require("
|
|
49
|
+
const utils_1 = require("../../lib/utils");
|
|
50
50
|
function Dialog({ ...props }) {
|
|
51
51
|
return React.createElement(DialogPrimitive.Root, { "data-slot": "dialog", ...props });
|
|
52
52
|
}
|
|
@@ -36,7 +36,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
36
36
|
exports.Label = Label;
|
|
37
37
|
const React = __importStar(require("react"));
|
|
38
38
|
const LabelPrimitive = __importStar(require("@radix-ui/react-label"));
|
|
39
|
-
const utils_1 = require("
|
|
39
|
+
const utils_1 = require("../../lib/utils");
|
|
40
40
|
function Label({ className, ...props }) {
|
|
41
41
|
return (React.createElement(LabelPrimitive.Root, { "data-slot": "label", className: (0, utils_1.cn)("flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50", className), ...props }));
|
|
42
42
|
}
|
|
@@ -38,7 +38,7 @@ exports.Toggle = Toggle;
|
|
|
38
38
|
const React = __importStar(require("react"));
|
|
39
39
|
const TogglePrimitive = __importStar(require("@radix-ui/react-toggle"));
|
|
40
40
|
const class_variance_authority_1 = require("class-variance-authority");
|
|
41
|
-
const utils_1 = require("
|
|
41
|
+
const utils_1 = require("../../lib/utils");
|
|
42
42
|
const toggleVariants = (0, class_variance_authority_1.cva)("inline-flex items-center justify-center gap-2 rounded-md text-sm font-medium hover:bg-muted hover:text-muted-foreground disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:shrink-0 focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] outline-none transition-[color,box-shadow] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive whitespace-nowrap", {
|
|
43
43
|
variants: {
|
|
44
44
|
variant: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ixo/editor",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "A custom BlockNote editor wrapper for IXO team",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -18,6 +18,16 @@
|
|
|
18
18
|
},
|
|
19
19
|
"./style.css": "./style.css"
|
|
20
20
|
},
|
|
21
|
+
"scripts": {
|
|
22
|
+
"build": "tsc && tsc-alias && npm run copy-css",
|
|
23
|
+
"copy-css": "node scripts/build-css.js",
|
|
24
|
+
"build:watch": "tsc --watch",
|
|
25
|
+
"dev": "tsc --watch",
|
|
26
|
+
"clean": "rimraf dist style.css",
|
|
27
|
+
"prepare": "npm run clean && npm run build",
|
|
28
|
+
"type-check": "tsc --noEmit",
|
|
29
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
30
|
+
},
|
|
21
31
|
"keywords": [
|
|
22
32
|
"editor",
|
|
23
33
|
"blocknote",
|
|
@@ -54,28 +64,26 @@
|
|
|
54
64
|
"yjs": "^13.6.27"
|
|
55
65
|
},
|
|
56
66
|
"devDependencies": {
|
|
67
|
+
"@semantic-release/changelog": "^6.0.3",
|
|
68
|
+
"@semantic-release/commit-analyzer": "^11.1.0",
|
|
69
|
+
"@semantic-release/git": "^10.0.1",
|
|
70
|
+
"@semantic-release/npm": "^11.0.2",
|
|
71
|
+
"@semantic-release/release-notes-generator": "^12.1.0",
|
|
57
72
|
"@types/react": "^18.2.0",
|
|
58
73
|
"@types/react-dom": "^18.2.0",
|
|
59
74
|
"react": "^18.2.0",
|
|
60
75
|
"react-dom": "^18.2.0",
|
|
61
76
|
"rimraf": "^5.0.0",
|
|
77
|
+
"semantic-release": "^22.0.12",
|
|
78
|
+
"tsc-alias": "^1.8.16",
|
|
62
79
|
"typescript": "^5.0.0"
|
|
63
80
|
},
|
|
64
81
|
"repository": {
|
|
65
82
|
"type": "git",
|
|
66
|
-
"url": "https://github.com/
|
|
83
|
+
"url": "https://github.com/ixoworld/editor.git"
|
|
67
84
|
},
|
|
68
|
-
"homepage": "https://github.com/
|
|
85
|
+
"homepage": "https://github.com/ixoworld/editor#readme",
|
|
69
86
|
"bugs": {
|
|
70
|
-
"url": "https://github.com/
|
|
71
|
-
},
|
|
72
|
-
"scripts": {
|
|
73
|
-
"build": "tsc && npm run copy-css",
|
|
74
|
-
"copy-css": "node scripts/build-css.js",
|
|
75
|
-
"build:watch": "tsc --watch",
|
|
76
|
-
"dev": "tsc --watch",
|
|
77
|
-
"clean": "rimraf dist style.css",
|
|
78
|
-
"type-check": "tsc --noEmit",
|
|
79
|
-
"test": "echo \"Error: no test specified\" && exit 1"
|
|
87
|
+
"url": "https://github.com/ixoworld/editor/issues"
|
|
80
88
|
}
|
|
81
|
-
}
|
|
89
|
+
}
|