@notectl/angular 2.0.1 → 2.0.3

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
@@ -4,12 +4,9 @@
4
4
 
5
5
  # notectl
6
6
 
7
- ### Drop one tag. Get a full editor.
7
+ ### Rich text editing as a Web Component
8
8
 
9
- `<notectl-editor>` the rich text editor that works everywhere.<br />
10
- React, Vue, Angular, Svelte, or plain HTML. Zero config, full power.
11
-
12
- <br />
9
+ Build a real editor in plain HTML, React, Vue, Svelte, or Angular without locking yourself into a framework-specific editor runtime.
13
10
 
14
11
  [![TypeScript](https://img.shields.io/badge/TypeScript-strict-blue?logo=typescript&logoColor=white)](https://www.typescriptlang.org/)
15
12
  [![Web Component](https://img.shields.io/badge/Web_Component-%3Cnotectl--editor%3E-purple)](https://developer.mozilla.org/en-US/docs/Web/API/Web_components)
@@ -23,185 +20,325 @@ React, Vue, Angular, Svelte, or plain HTML. Zero config, full power.
23
20
 
24
21
  <br />
25
22
 
26
- [**Try the Playground**](https://samyssmile.github.io/notectl/playground/) &nbsp;&middot;&nbsp; [Documentation](https://samyssmile.github.io/notectl/) &nbsp;&middot;&nbsp; [npm](https://www.npmjs.com/package/@notectl/core)
23
+ [Documentation](https://samyssmile.github.io/notectl/) &nbsp;&middot;&nbsp;
24
+ [Playground](https://samyssmile.github.io/notectl/playground/) &nbsp;&middot;&nbsp;
25
+ [npm: @notectl/core](https://www.npmjs.com/package/@notectl/core) &nbsp;&middot;&nbsp;
26
+ [npm: @notectl/angular](https://www.npmjs.com/package/@notectl/angular)
27
27
 
28
28
  </div>
29
29
 
30
- <br />
30
+ ## What you get
31
31
 
32
- ## Quick Start
32
+ - A framework-agnostic editor shipped as the `notectl-editor` custom element
33
+ - Immutable editor state and transaction-based updates
34
+ - A plugin system for headings, lists, links, tables, code blocks, images, fonts, and more
35
+ - CSP-safe styling with `adoptedStyleSheets`
36
+ - A fast path for "just give me a full editor" and a granular path for "I only want these plugins"
37
+
38
+ ## Install
33
39
 
34
40
  ```bash
35
41
  npm install @notectl/core
36
42
  ```
37
43
 
38
- ### Preset — full editor in 5 lines
44
+ Requirements:
45
+
46
+ - Modern browser with Custom Elements support
47
+ - Node.js 18+ for build tooling
48
+ - Angular 21+ if you use `@notectl/angular`
49
+
50
+ ## Quick start
51
+
52
+ The normal way to embed notectl is to create the Web Component with `createEditor(...)` and mount it into your app.
53
+
54
+ ### 1. Add a host element
55
+
56
+ ```html
57
+ <div id="app"></div>
58
+ ```
59
+
60
+ ### 2. Create the editor
61
+
62
+ Start with one of the shipped presets:
63
+
64
+ Minimal preset:
39
65
 
40
66
  ```ts
41
- import { createEditor, createFullPreset, ThemePreset } from '@notectl/core';
67
+ import { createEditor } from '@notectl/core';
68
+ import { createMinimalPreset } from '@notectl/core/presets/minimal';
42
69
 
43
70
  const editor = await createEditor({
44
- ...createFullPreset(),
45
- theme: ThemePreset.Light,
71
+ ...createMinimalPreset(),
46
72
  placeholder: 'Start typing...',
73
+ autofocus: true,
47
74
  });
48
75
 
49
- document.body.appendChild(editor);
76
+ document.getElementById('app')!.appendChild(editor);
50
77
  ```
51
78
 
52
- All 19 plugins, toolbar groups, and keyboard shortcuts ready to go.
53
-
54
- ### Custom — pick exactly what you need
79
+ Full preset (toolbar, headings, lists, links, tables, code blocks, images, fonts, and more):
55
80
 
56
81
  ```ts
57
- import {
58
- createEditor,
59
- ThemePreset,
60
- TextFormattingPlugin,
61
- HeadingPlugin,
62
- ListPlugin,
63
- LinkPlugin,
64
- TablePlugin,
65
- } from '@notectl/core';
82
+ import { ThemePreset, createEditor } from '@notectl/core';
83
+ import { STARTER_FONTS } from '@notectl/core/fonts';
84
+ import { ToolbarOverflowBehavior } from '@notectl/core/plugins/toolbar';
85
+ import { createFullPreset } from '@notectl/core/presets/full';
86
+
87
+ const preset = createFullPreset({
88
+ font: { fonts: STARTER_FONTS },
89
+ });
66
90
 
67
91
  const editor = await createEditor({
92
+ ...preset,
93
+ toolbar: {
94
+ groups: preset.toolbar,
95
+ overflow: ToolbarOverflowBehavior.Flow,
96
+ },
68
97
  theme: ThemePreset.Light,
69
- toolbar: [
70
- [new TextFormattingPlugin({ bold: true, italic: true, underline: true })],
71
- [new HeadingPlugin()],
72
- [new ListPlugin()],
73
- [new LinkPlugin(), new TablePlugin()],
74
- ],
75
98
  placeholder: 'Start typing...',
76
99
  autofocus: true,
77
100
  });
78
101
 
79
- document.body.appendChild(editor);
102
+ document.getElementById('app')!.appendChild(editor);
80
103
  ```
81
104
 
82
- <br />
105
+ Use `createMinimalPreset()` when you want a lean starting point. Use `createFullPreset()` when you want the standard toolbar and plugin set immediately, including responsive toolbar overflow.
106
+
107
+ ## Add notectl to your app
108
+
109
+ ### Plain HTML / Vite / Vanilla JS
110
+
111
+ ```html
112
+ <!doctype html>
113
+ <html lang="en">
114
+ <head>
115
+ <meta charset="UTF-8" />
116
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
117
+ <title>My editor</title>
118
+ <style>
119
+ #app {
120
+ max-width: 800px;
121
+ margin: 2rem auto;
122
+ }
123
+
124
+ notectl-editor {
125
+ --notectl-content-min-height: 320px;
126
+ }
127
+ </style>
128
+ </head>
129
+ <body>
130
+ <div id="app"></div>
131
+
132
+ <script type="module">
133
+ import { createEditor } from '@notectl/core';
134
+ import { createMinimalPreset } from '@notectl/core/presets/minimal';
135
+
136
+ const editor = await createEditor({
137
+ ...createMinimalPreset(),
138
+ placeholder: 'Write something...',
139
+ autofocus: true,
140
+ });
141
+
142
+ document.getElementById('app').appendChild(editor);
143
+ </script>
144
+ </body>
145
+ </html>
146
+ ```
147
+
148
+ ### React
83
149
 
84
- ## Why notectl
150
+ ```tsx
151
+ import { useEffect, useRef } from 'react';
152
+ import { createEditor, type NotectlEditor } from '@notectl/core';
85
153
 
86
- <table>
87
- <tr>
88
- <td width="50%">
154
+ export function Editor() {
155
+ const containerRef = useRef<HTMLDivElement>(null);
156
+ const editorRef = useRef<NotectlEditor | null>(null);
89
157
 
90
- **CSP-compliant zero inline styles**
158
+ useEffect(() => {
159
+ let mounted = true;
91
160
 
92
- The only editor with a built-in CSP-safe rendering pipeline. All styles go through `adoptedStyleSheets` with reference-counted token management. Works with `style-src 'self'` — no `unsafe-inline` needed. ProseMirror, TipTap, Slate, Lexical, Quill all write inline styles.
161
+ createEditor({
162
+ placeholder: 'Start typing...',
163
+ autofocus: true,
164
+ }).then((editor) => {
165
+ if (!mounted || !containerRef.current) return;
166
+ containerRef.current.appendChild(editor);
167
+ editorRef.current = editor;
168
+ });
93
169
 
94
- </td>
95
- <td width="50%">
170
+ return () => {
171
+ mounted = false;
172
+ void editorRef.current?.destroy();
173
+ };
174
+ }, []);
96
175
 
97
- **One dependency**
176
+ return <div ref={containerRef} />;
177
+ }
178
+ ```
98
179
 
99
- The entire editor state engine, reconciler, plugin system, toolbar, undo/redo, selection sync is built from scratch with a single production dependency (DOMPurify for HTML sanitization). Tree-shakeable plugin architecture: bundle only what you use.
180
+ Vue and Svelte use the same pattern: create the editor on mount, append it to a host element, and call `destroy()` on unmount.
100
181
 
101
- </td>
102
- </tr>
103
- <tr>
104
- <td>
182
+ ### Angular
105
183
 
106
- **True Web Component**
184
+ Use the Angular wrapper if you want template bindings, forms integration, and DI-based defaults.
185
+
186
+ ```bash
187
+ npm install @notectl/core @notectl/angular
188
+ ```
107
189
 
108
- Shadow DOM encapsulation, reactive attributes, framework-agnostic by design. One `<notectl-editor>` tag works in React, Vue, Angular, Svelte, or plain HTML. No wrappers, no adapters, no version lock-in.
190
+ ```ts
191
+ // app.config.ts
192
+ import { type ApplicationConfig } from '@angular/core';
193
+ import { provideNotectl } from '@notectl/angular';
109
194
 
110
- </td>
111
- <td>
195
+ export const appConfig: ApplicationConfig = {
196
+ providers: [provideNotectl()],
197
+ };
198
+ ```
112
199
 
113
- **Plugin system with full lifecycle**
200
+ ```ts
201
+ // editor.component.ts
202
+ import { ChangeDetectionStrategy, Component, signal } from '@angular/core';
203
+ import {
204
+ NotectlEditorComponent,
205
+ type Plugin,
206
+ HeadingPlugin,
207
+ LinkPlugin,
208
+ ListPlugin,
209
+ TextFormattingPlugin,
210
+ ThemePreset,
211
+ } from '@notectl/angular';
212
+
213
+ @Component({
214
+ selector: 'app-editor',
215
+ standalone: true,
216
+ imports: [NotectlEditorComponent],
217
+ template: `
218
+ <ntl-editor
219
+ [toolbar]="toolbar"
220
+ [theme]="theme()"
221
+ [autofocus]="true"
222
+ />
223
+ `,
224
+ changeDetection: ChangeDetectionStrategy.OnPush,
225
+ })
226
+ export class EditorComponent {
227
+ protected readonly theme = signal<ThemePreset>(ThemePreset.Light);
228
+
229
+ protected readonly toolbar: ReadonlyArray<ReadonlyArray<Plugin>> = [
230
+ [new TextFormattingPlugin({ bold: true, italic: true, underline: true })],
231
+ [new HeadingPlugin()],
232
+ [new ListPlugin()],
233
+ [new LinkPlugin()],
234
+ ];
235
+ }
236
+ ```
114
237
 
115
- Dependency-resolved initialization (topological sort), per-plugin teardown tracking, type-safe inter-plugin services via `ServiceKey<T>`, priority-ordered middleware, error isolation. Plugins can't crash the editor or leak memory.
238
+ Full Angular guide: https://samyssmile.github.io/notectl/guides/angular/
116
239
 
117
- </td>
118
- </tr>
119
- </table>
240
+ ## Build your own toolbar
120
241
 
121
- <br />
242
+ If you only want a small editor, import the plugins you need and group them in the toolbar:
122
243
 
123
- ## Plugin Ecosystem
124
-
125
- Every capability is a plugin. Compose exactly the editor you need.
126
-
127
- | Plugin | What you get |
128
- |---|---|
129
- | **TextFormattingPlugin** | Bold, italic, underline |
130
- | **StrikethroughPlugin** | ~~Strikethrough~~ text |
131
- | **SuperSubPlugin** | Superscript and subscript |
132
- | **HeadingPlugin** | H1 – H6 headings with block type picker |
133
- | **BlockquotePlugin** | Block quotes |
134
- | **ListPlugin** | Bullet, ordered, and checklists |
135
- | **LinkPlugin** | Hyperlink insertion and editing |
136
- | **TablePlugin** | Full table support with row/column controls |
137
- | **CodeBlockPlugin** | Code blocks with syntax highlighting |
138
- | **ImagePlugin** | Image upload, resize, and drag-and-drop |
139
- | **TextColorPlugin** | Text color picker |
140
- | **HighlightPlugin** | Text highlighting / background color |
141
- | **AlignmentPlugin** | Left, center, right, justify |
142
- | **FontPlugin** | Font family selection with custom web fonts |
143
- | **FontSizePlugin** | Configurable font sizes |
144
- | **HorizontalRulePlugin** | Horizontal dividers |
145
- | **PrintPlugin** | Print editor content with configurable paper sizes |
146
-
147
- See the [plugin documentation](https://samyssmile.github.io/notectl/plugins/overview/) for configuration and examples.
244
+ ```ts
245
+ import { ThemePreset, createEditor } from '@notectl/core';
246
+ import { HeadingPlugin } from '@notectl/core/plugins/heading';
247
+ import { LinkPlugin } from '@notectl/core/plugins/link';
248
+ import { ListPlugin } from '@notectl/core/plugins/list';
249
+ import { TablePlugin } from '@notectl/core/plugins/table';
250
+ import { TextFormattingPlugin } from '@notectl/core/plugins/text-formatting';
148
251
 
149
- <br />
252
+ const editor = await createEditor({
253
+ theme: ThemePreset.Light,
254
+ toolbar: [
255
+ [new TextFormattingPlugin({ bold: true, italic: true, underline: true })],
256
+ [new HeadingPlugin()],
257
+ [new ListPlugin()],
258
+ [new LinkPlugin(), new TablePlugin()],
259
+ ],
260
+ placeholder: 'Start typing...',
261
+ autofocus: true,
262
+ });
263
+ ```
150
264
 
151
- ## Built-in Features
265
+ Each inner array is one visible toolbar group.
152
266
 
153
- - **Themes** — Dark and Light presets, or create fully custom themes
154
- - **i18n** — 8 languages: English, German, Spanish, French, Chinese, Russian, Arabic, Hindi + auto-detect via `Locale.BROWSER`
155
- - **Paper sizes** — DIN A4, DIN A5, US Letter, US Legal for WYSIWYG page layout
156
- - **CSP-compliant** — Style delivery via `adoptedStyleSheets`, no inline styles required
157
- - **Markdown shortcuts** — `#` → H1, `##` → H2, `-` → bullet list, `1.` → ordered list, `>` → blockquote
158
- - **Syntax highlighting** — Pluggable highlighter for code blocks
267
+ ## Read and write content
159
268
 
160
- <br />
269
+ ```ts
270
+ await editor.setContentHTML('<p>Hello <strong>world</strong></p>');
161
271
 
162
- ## Content API
272
+ const html = await editor.getContentHTML();
273
+ const json = editor.getJSON();
274
+ const text = editor.getText();
275
+ const empty = editor.isEmpty();
276
+ ```
163
277
 
164
- Read and write content in any format:
278
+ You can also react to lifecycle and state events:
165
279
 
166
280
  ```ts
167
- await editor.getContentHTML(); // export as HTML
168
- editor.setContentHTML('<p>Hello <strong>world</strong></p>'); // import HTML
169
- editor.getJSON(); // structured JSON
170
- editor.setJSON(doc); // import JSON
171
- editor.getText(); // plain text
172
- editor.isEmpty(); // check if empty
281
+ editor.on('ready', () => {
282
+ console.log('Editor is ready');
283
+ });
284
+
285
+ editor.on('stateChange', ({ newState }) => {
286
+ console.log('Document changed:', newState.doc);
287
+ });
173
288
  ```
174
289
 
175
- <br />
290
+ ## Built-in plugins
176
291
 
177
- ## Works with your stack
292
+ notectl ships plugins for:
178
293
 
179
- | | Framework | How |
180
- |---|---|---|
181
- | **Any** | Vanilla JS, React, Vue, Svelte | `<notectl-editor>` Web Component |
182
- | **Angular** | Angular 21+ | [`@notectl/angular`](https://www.npmjs.com/package/@notectl/angular) native integration |
294
+ - Text formatting
295
+ - Headings
296
+ - Blockquotes
297
+ - Bullet, ordered, and checklist lists
298
+ - Links
299
+ - Tables
300
+ - Code blocks
301
+ - Images
302
+ - Text color and highlight
303
+ - Alignment and text direction
304
+ - Fonts and font sizes
305
+ - Horizontal rules
306
+ - Print layouts
183
307
 
184
- See [`examples/vanillajs`](examples/vanillajs) and [`examples/angular`](examples/angular) for full working demos.
308
+ Full plugin reference: https://samyssmile.github.io/notectl/plugins/overview/
185
309
 
186
- <br />
310
+ ## Why teams pick notectl
187
311
 
188
- ## Contributing
312
+ - Works across frameworks because the editor is a Web Component at the core
313
+ - Strong default path for quick setup, without giving up fine-grained plugin control later
314
+ - CSP-friendly by design, without relying on inline styles
315
+ - Single production dependency: `dompurify`
316
+ - Immutable state and transaction-based updates make behavior predictable and testable
189
317
 
190
- ```bash
191
- git clone https://github.com/Samyssmile/notectl.git
192
- cd notectl && pnpm install
193
- pnpm build # build all packages
194
- pnpm test # run unit tests
195
- pnpm test:e2e # run e2e tests
196
- pnpm lint # lint
197
- ```
318
+ ## Examples
198
319
 
199
- <br />
320
+ - Vanilla example: https://github.com/Samyssmile/notectl/tree/main/examples/vanillajs
321
+ - Angular example: https://github.com/Samyssmile/notectl/tree/main/examples/angular
200
322
 
201
- <div align="center">
323
+ ## Documentation
202
324
 
203
- **[Get started](https://samyssmile.github.io/notectl/)** &nbsp;&middot;&nbsp; **[Open the playground](https://samyssmile.github.io/notectl/playground/)** &nbsp;&middot;&nbsp; **[View on npm](https://www.npmjs.com/package/@notectl/core)**
325
+ - Getting started: https://samyssmile.github.io/notectl/getting-started/installation/
326
+ - Quick start: https://samyssmile.github.io/notectl/getting-started/quick-start/
327
+ - Angular guide: https://samyssmile.github.io/notectl/guides/angular/
328
+ - Plugin docs: https://samyssmile.github.io/notectl/plugins/overview/
329
+ - Architecture overview: https://samyssmile.github.io/notectl/architecture/overview/
204
330
 
205
- MIT License
331
+ ## Development
206
332
 
207
- </div>
333
+ ```bash
334
+ pnpm install
335
+ pnpm build
336
+ pnpm test
337
+ pnpm test:e2e
338
+ pnpm lint
339
+ pnpm typecheck
340
+ ```
341
+
342
+ ## License
343
+
344
+ MIT