@bendyline/squisq-editor-react 0.1.0 → 1.0.0

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 ADDED
@@ -0,0 +1,76 @@
1
+ # @bendyline/squisq-editor-react
2
+
3
+ React editor shell for Squisq documents with three integrated views: a Monaco-powered raw Markdown editor, a Tiptap WYSIWYG rich text editor, and a live block preview. Switching between views keeps the document in sync automatically.
4
+
5
+ Part of the [Squisq](https://github.com/bendyline/squisq) monorepo.
6
+
7
+ [![npm](https://img.shields.io/npm/v/@bendyline/squisq-editor-react)](https://www.npmjs.com/package/@bendyline/squisq-editor-react)
8
+ [![MIT License](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/bendyline/squisq/blob/main/LICENSE)
9
+
10
+ ## Install
11
+
12
+ ```bash
13
+ npm install @bendyline/squisq-editor-react @bendyline/squisq @bendyline/squisq-react
14
+ ```
15
+
16
+ **Peer dependencies:** `react` and `react-dom` (v18 or v19).
17
+
18
+ ## Quick Start
19
+
20
+ ```tsx
21
+ import { EditorShell } from '@bendyline/squisq-editor-react';
22
+ import '@bendyline/squisq-editor-react/styles';
23
+
24
+ function App() {
25
+ return <EditorShell initialMarkdown="# Hello World" />;
26
+ }
27
+ ```
28
+
29
+ ## Editor Views
30
+
31
+ | View | Powered By | Description |
32
+ | ----------- | ------------- | ----------------------------------------------------- |
33
+ | **Raw** | Monaco Editor | Full Markdown source editing with syntax highlighting |
34
+ | **WYSIWYG** | Tiptap | Rich text editing with a formatting toolbar |
35
+ | **Preview** | DocPlayer | Live rendered block preview with theme selection |
36
+
37
+ ## Components
38
+
39
+ | Component | Description |
40
+ | ---------------- | ---------------------------------------------------------------- |
41
+ | `EditorShell` | Top-level editor — combines all three views with a view switcher |
42
+ | `EditorProvider` | Context provider for editor state management |
43
+
44
+ ## Context API
45
+
46
+ Use `useEditorContext()` to access editor state and actions from child components:
47
+
48
+ ```tsx
49
+ import { EditorProvider, useEditorContext } from '@bendyline/squisq-editor-react';
50
+
51
+ function MyComponent() {
52
+ const { state, actions } = useEditorContext();
53
+ // state.markdown, state.view, state.doc
54
+ // actions.setMarkdown(), actions.setView()
55
+ }
56
+ ```
57
+
58
+ ## Styles
59
+
60
+ Import the editor CSS:
61
+
62
+ ```ts
63
+ import '@bendyline/squisq-editor-react/styles';
64
+ ```
65
+
66
+ ## Related Packages
67
+
68
+ | Package | Description |
69
+ | ------------------------------------------------------------------------------------ | -------------------------------------------------------------- |
70
+ | [@bendyline/squisq](https://www.npmjs.com/package/@bendyline/squisq) | Headless core — schemas, templates, spatial, markdown, storage |
71
+ | [@bendyline/squisq-react](https://www.npmjs.com/package/@bendyline/squisq-react) | React components for rendering docs |
72
+ | [@bendyline/squisq-formats](https://www.npmjs.com/package/@bendyline/squisq-formats) | DOCX, PDF, HTML import/export |
73
+
74
+ ## License
75
+
76
+ [MIT](https://github.com/bendyline/squisq/blob/main/LICENSE)
package/dist/index.js CHANGED
@@ -472,43 +472,51 @@ function Toolbar({ className }) {
472
472
  },
473
473
  view.id
474
474
  )) }),
475
- !isPreview && /* @__PURE__ */ jsx2("div", { className: "squisq-toolbar-separator" }),
476
- !isPreview && groups.map((group, gi) => /* @__PURE__ */ jsxs("div", { className: "squisq-toolbar-group", children: [
477
- gi > 0 && /* @__PURE__ */ jsx2("div", { className: "squisq-toolbar-separator" }),
478
- BUTTONS.filter((b) => b.group === group).map((btn) => {
479
- const active = isWysiwyg ? isTiptapActive(tiptapEditor, btn.id) : false;
480
- return /* @__PURE__ */ jsx2(
481
- "button",
482
- {
483
- className: `squisq-toolbar-button${active ? " squisq-toolbar-button--active" : ""}`,
484
- title: btn.title,
485
- onClick: () => handleAction(btn.id),
486
- "aria-label": btn.title,
487
- "aria-pressed": active,
488
- style: btn.iconStyle,
489
- children: btn.icon
490
- },
491
- btn.id
492
- );
493
- })
494
- ] }, group)),
495
- !isPreview && currentTemplate !== null && /* @__PURE__ */ jsxs(Fragment, { children: [
496
- /* @__PURE__ */ jsx2("div", { className: "squisq-toolbar-separator" }),
497
- /* @__PURE__ */ jsx2("div", { className: "squisq-toolbar-group squisq-template-picker", children: /* @__PURE__ */ jsxs("label", { className: "squisq-template-picker-label", title: "Block template for this heading", children: [
498
- "Template:",
499
- /* @__PURE__ */ jsxs(
500
- "select",
475
+ !isPreview && /* @__PURE__ */ jsxs("div", { className: "squisq-toolbar-actions", children: [
476
+ groups.map((group, gi) => /* @__PURE__ */ jsxs("div", { className: "squisq-toolbar-group", children: [
477
+ gi > 0 && /* @__PURE__ */ jsx2("div", { className: "squisq-toolbar-separator" }),
478
+ BUTTONS.filter((b) => b.group === group).map((btn) => {
479
+ const active = isWysiwyg ? isTiptapActive(tiptapEditor, btn.id) : false;
480
+ return /* @__PURE__ */ jsx2(
481
+ "button",
482
+ {
483
+ className: `squisq-toolbar-button${active ? " squisq-toolbar-button--active" : ""}`,
484
+ title: btn.title,
485
+ onClick: () => handleAction(btn.id),
486
+ "aria-label": btn.title,
487
+ "aria-pressed": active,
488
+ style: btn.iconStyle,
489
+ children: btn.icon
490
+ },
491
+ btn.id
492
+ );
493
+ })
494
+ ] }, group)),
495
+ currentTemplate !== null && /* @__PURE__ */ jsxs(Fragment, { children: [
496
+ /* @__PURE__ */ jsx2("div", { className: "squisq-toolbar-separator" }),
497
+ /* @__PURE__ */ jsx2("div", { className: "squisq-toolbar-group squisq-template-picker", children: /* @__PURE__ */ jsxs(
498
+ "label",
501
499
  {
502
- className: "squisq-template-picker-select",
503
- value: currentTemplate,
504
- onChange: (e) => handleTemplatePick(e.target.value),
500
+ className: "squisq-template-picker-label",
501
+ title: "Block template for this heading",
505
502
  children: [
506
- /* @__PURE__ */ jsx2("option", { value: "", children: "\u2014 none \u2014" }),
507
- templateNames.map((name) => /* @__PURE__ */ jsx2("option", { value: name, children: name }, name))
503
+ "Template:",
504
+ /* @__PURE__ */ jsxs(
505
+ "select",
506
+ {
507
+ className: "squisq-template-picker-select",
508
+ value: currentTemplate,
509
+ onChange: (e) => handleTemplatePick(e.target.value),
510
+ children: [
511
+ /* @__PURE__ */ jsx2("option", { value: "", children: "\u2014 none \u2014" }),
512
+ templateNames.map((name) => /* @__PURE__ */ jsx2("option", { value: name, children: name }, name))
513
+ ]
514
+ }
515
+ )
508
516
  ]
509
517
  }
510
- )
511
- ] }) })
518
+ ) })
519
+ ] })
512
520
  ] })
513
521
  ]
514
522
  }