@noseberry/nbd-editor 1.0.2 → 1.1.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
@@ -11,7 +11,7 @@ Works seamlessly with **vanilla JavaScript**, **React**, and **Next.js**.
11
11
  - **Drop-in ready** — one import, one line of code, and you have a full block editor
12
12
  - **Framework agnostic** — works with any frontend stack; optional React wrapper included
13
13
  - **20+ block types** — paragraphs, headings, images, video, audio, tables, columns, code, embeds, and more
14
- - **Rich editing** — inline formatting toolbar, slash commands (`/`), drag-and-drop reordering, undo/redo
14
+ - **Rich editing** — inline formatting toolbar (draggable), slash commands (`/`), drag-and-drop reordering, undo/redo
15
15
  - **Media support** — upload images, video, audio, and files with drag-and-drop or file picker
16
16
  - **Simple data model** — `getData()` returns `{ content: '<p>...</p>' }` — just store one HTML string
17
17
  - **TypeScript support** — full type definitions included for autocomplete and type safety
@@ -77,8 +77,10 @@ The editor manages its own state internally. You interact with it through callba
77
77
  - [Data Contract](#data-contract)
78
78
  - [Block Types](#block-types)
79
79
  - [Media Handling](#media-handling)
80
+ - [Theming](#theming)
80
81
  - [Keyboard Shortcuts](#keyboard-shortcuts)
81
82
  - [Events](#events)
83
+ - [Changelog](#changelog)
82
84
  - [Build from Source](#build-from-source)
83
85
  - [License](#license)
84
86
 
@@ -253,21 +255,40 @@ export default function EditorPage() {
253
255
  | `redo(opts?)` | Redo last undone action |
254
256
  | `destroy()` | Destroys the editor instance and cleans up |
255
257
 
256
- ### Important: Avoid Re-controlling Content
258
+ ### Controlled Mode (like React Quill)
257
259
 
258
- The `content` prop is treated as an **initial/external value**. Do NOT bind it to state that updates on every keystroke:
260
+ NBD Editor supports the controlled component pattern bind `content` to state and update it via `onChange`:
259
261
 
260
262
  ```jsx
261
- // BAD causes infinite re-render loop
262
- const [content, setContent] = useState('<p>Hello</p>');
263
- <ReactNBDEditor content={content} onChange={(d) => setContent(d.content)} />
263
+ import React, { useState } from 'react';
264
+ import { ReactNBDEditor } from '@noseberry/nbd-editor';
265
+ import '@noseberry/nbd-editor/style.css';
266
+
267
+ export default function EditorPage() {
268
+ const [content, setContent] = useState('<p>Hello World</p>');
269
+
270
+ return (
271
+ <ReactNBDEditor
272
+ content={content}
273
+ onChange={(data) => setContent(data.content)}
274
+ siteName="My App"
275
+ authorName="Harshit"
276
+ />
277
+ );
278
+ }
279
+ ```
280
+
281
+ For heavy content or frequent updates, use `debounceMs` to limit how often `onChange` fires:
264
282
 
265
- // GOOD — use content only for initial value or external resets
266
- const [initialContent] = useState('<p>Hello</p>');
267
- <ReactNBDEditor content={initialContent} onChange={(d) => console.log(d)} />
283
+ ```jsx
284
+ <ReactNBDEditor
285
+ content={content}
286
+ onChange={(data) => setContent(data.content)}
287
+ debounceMs={300} // fires onChange at most every 300ms
288
+ />
268
289
  ```
269
290
 
270
- If you need to update the editor's content programmatically from the parent, use the ref:
291
+ You can also use `content` as a one-time initial value and use the ref for everything else:
271
292
 
272
293
  ```jsx
273
294
  editorRef.current?.setData({ content: '<p>New content from server</p>' });
@@ -410,6 +431,7 @@ Pass these as the second argument to `new NBDEditor(selector, options)` or as pr
410
431
  | `className` | `string` | CSS class for the wrapper `div` |
411
432
  | `style` | `object` | Inline styles for the wrapper `div` |
412
433
  | `onReady` | `(editor) => void` | Called once the editor instance is initialized |
434
+ | `debounceMs` | `number` | Debounce delay (ms) for `onChange` — reduces re-renders in controlled mode |
413
435
 
414
436
  ---
415
437
 
@@ -520,6 +542,49 @@ Files exceeding `maxFileSize` are blocked from uploading. Users can also drag an
520
542
 
521
543
  ---
522
544
 
545
+ ## Theming
546
+
547
+ NBD Editor exposes a set of CSS custom properties on `.fe-root` that you can override to match your brand. Set them on `.fe-root` or any ancestor element:
548
+
549
+ ```css
550
+ .fe-root {
551
+ --fe-blue: #8b5cf6; /* accent / primary colour */
552
+ --fe-blue-hover: #7c3aed;
553
+ --fe-bg: #fafafa; /* editor shell background */
554
+ --fe-canvas-bg: #f9fafb; /* writing canvas background */
555
+ --fe-text: #111827; /* primary text colour */
556
+ --fe-font: 'Inter', sans-serif;
557
+ --fe-radius: 8px; /* border radius */
558
+ --fe-content-font-size: 16px; /* body text size inside blocks */
559
+ --fe-content-line-height: 1.7;
560
+ }
561
+ ```
562
+
563
+ All available tokens:
564
+
565
+ | Variable | Default | Description |
566
+ |---|---|---|
567
+ | `--fe-blue` | `#3b82f6` | Accent / primary colour |
568
+ | `--fe-blue-hover` | `#2563eb` | Accent hover state |
569
+ | `--fe-text` | `#1e1e1e` | Primary text colour |
570
+ | `--fe-light-text` | `#6b7280` | Secondary / muted text |
571
+ | `--fe-bg` | `#f8f9fb` | Editor shell background |
572
+ | `--fe-canvas-bg` | `#ffffff` | Writing canvas background |
573
+ | `--fe-hover-bg` | `#f3f4f6` | Hover / subtle highlight |
574
+ | `--fe-border` | `#e2e4e9` | Border colour |
575
+ | `--fe-success` | `#10b981` | Success state colour |
576
+ | `--fe-danger` | `#ef4444` | Destructive / error colour |
577
+ | `--fe-radius` | `6px` | Border radius |
578
+ | `--fe-font` | system-ui stack | Font family |
579
+ | `--fe-shadow-sm` | subtle shadow | Subtle shadow — used on cards and panels |
580
+ | `--fe-shadow-md` | medium shadow | Medium shadow — used on dropdowns and modals |
581
+ | `--fe-header-height` | `60px` | Height of the sticky header bar |
582
+ | `--fe-status-bar-height` | `32px` | Height of the bottom status bar |
583
+ | `--fe-content-font-size` | `15px` | Body text size inside blocks |
584
+ | `--fe-content-line-height` | `1.65` | Body line height inside blocks |
585
+
586
+ ---
587
+
523
588
  ## Keyboard Shortcuts
524
589
 
525
590
  | Shortcut | Action |
@@ -554,6 +619,22 @@ editor.on('input', (block) => { }); // Block content input
554
619
 
555
620
  ---
556
621
 
622
+ ## Changelog
623
+
624
+ ### v1.1.1
625
+
626
+ **Bug fixes**
627
+
628
+ - **List blocks** — bullet and ordered-list blocks now initialize with the correct `<ul><li>` / `<ol><li>` structure. Previously, empty list blocks rendered a bare `<br>`, which caused broken list editing behavior on first interaction.
629
+ - **Focus reliability** — block focus and caret positioning after clicking a block now uses double `requestAnimationFrame` instead of `setTimeout(0)`, preventing occasional cases where the caret landed in the wrong position before the DOM had fully painted.
630
+
631
+ **Improvements**
632
+
633
+ - **Click-to-deselect** — clicking anywhere on the editor canvas outside a block now deselects the active block and returns the editor to its idle state.
634
+ - **Theme tokens** — two new elevation CSS variables are available: `--fe-shadow-sm` and `--fe-shadow-md`. All CSS variable defaults have been refreshed to a cleaner, more neutral palette (new accent `#3b82f6`, updated greys, semantic colours, and layout tokens).
635
+
636
+ ---
637
+
557
638
  ## Build from Source
558
639
 
559
640
  ```bash