neuphlo-editor 0.2.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 +126 -0
- package/dist/chunk-XABVYDNO.js +14 -0
- package/dist/chunk-XABVYDNO.js.map +1 -0
- package/dist/index.cjs +20 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +5 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/react/index.cjs +64 -0
- package/dist/react/index.cjs.map +1 -0
- package/dist/react/index.d.cts +13 -0
- package/dist/react/index.d.ts +13 -0
- package/dist/react/index.js +50 -0
- package/dist/react/index.js.map +1 -0
- package/dist/styles.css +119 -0
- package/package.json +70 -0
package/README.md
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# neuphlo-editor
|
|
2
|
+
|
|
3
|
+
A lightweight Tiptap preset with a React wrapper.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm i neuphlo-editor
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Requires `react` and `react-dom` 18+ in your app.
|
|
12
|
+
|
|
13
|
+
## Usage (React)
|
|
14
|
+
|
|
15
|
+
```tsx
|
|
16
|
+
import { Editor } from "neuphlo-editor/react"
|
|
17
|
+
|
|
18
|
+
export default function Page() {
|
|
19
|
+
return <Editor content="<p>Hello</p>" />
|
|
20
|
+
}
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
The React Editor includes the Neuphlo preset by default. Add more TipTap extensions when needed:
|
|
24
|
+
|
|
25
|
+
```tsx
|
|
26
|
+
import Placeholder from "@tiptap/extension-placeholder"
|
|
27
|
+
|
|
28
|
+
<Editor
|
|
29
|
+
content="<p>Hello</p>"
|
|
30
|
+
extensions={[Placeholder.configure({ placeholder: "Write something…" })]}
|
|
31
|
+
/>
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Styling
|
|
35
|
+
|
|
36
|
+
- Default behavior:
|
|
37
|
+
|
|
38
|
+
- The component adds the `nph-editor` class by default.
|
|
39
|
+
- Import our minimal stylesheet in your app to activate defaults: `import 'neuphlo-editor/styles.css'` (or `@import 'neuphlo-editor/styles.css';`).
|
|
40
|
+
- Next.js App Router: `app/layout.tsx` or `app/globals.css`
|
|
41
|
+
- Vite/CRA: `src/main.tsx`/`src/index.tsx`
|
|
42
|
+
- The base CSS does not add a border or background; add your own if desired.
|
|
43
|
+
|
|
44
|
+
- Opt out per instance:
|
|
45
|
+
|
|
46
|
+
- `<Editor styled={false} />`
|
|
47
|
+
|
|
48
|
+
- Bring your own styles (Tailwind or CSS):
|
|
49
|
+
- Use `className` to style the content container; use `editorContainerProps` for other DOM props (e.g., `id`, `role`). No styles are injected by the package.
|
|
50
|
+
- You can combine your own classes with the optional stylesheet if you want.
|
|
51
|
+
|
|
52
|
+
Examples:
|
|
53
|
+
|
|
54
|
+
```tsx
|
|
55
|
+
// Default stylesheet (minimal — no border/background by default)
|
|
56
|
+
import 'neuphlo-editor/styles.css'
|
|
57
|
+
|
|
58
|
+
<Editor />
|
|
59
|
+
|
|
60
|
+
// Tailwind utilities
|
|
61
|
+
<Editor className="min-h-[200px] border rounded-md p-3 outline-none" />
|
|
62
|
+
|
|
63
|
+
// Plain CSS
|
|
64
|
+
<Editor className="my-editor" />
|
|
65
|
+
|
|
66
|
+
/* then in your CSS */
|
|
67
|
+
.my-editor { min-height: 200px; border: 1px solid #e5e7eb; border-radius: 8px; padding: 12px; outline: none; }
|
|
68
|
+
.my-editor:focus-within { border-color: #2563eb; box-shadow: 0 0 0 3px rgba(37,99,235,0.15); }
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Advanced: pass TipTap options directly (everything maps to TipTap’s `EditorProvider`). Use `className` to style the content container, and `editorContainerProps` for additional DOM attributes:
|
|
72
|
+
|
|
73
|
+
```tsx
|
|
74
|
+
<Editor
|
|
75
|
+
autofocus
|
|
76
|
+
editable={false}
|
|
77
|
+
editorProps={{ attributes: { spellcheck: 'true' } }}
|
|
78
|
+
editorContainerProps={{ id: 'editor', role: 'textbox' }}
|
|
79
|
+
/>
|
|
80
|
+
|
|
81
|
+
// Alternatively, add the class manually via props
|
|
82
|
+
<Editor className="nph-editor" />
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Editable
|
|
86
|
+
|
|
87
|
+
Control whether the editor is editable (matches TipTap’s `editable` option). When not editable, helpful attributes are added for styling.
|
|
88
|
+
|
|
89
|
+
```tsx
|
|
90
|
+
<Editor editable={false} />
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
// With default stylesheet + a visual cue
|
|
94
|
+
import 'neuphlo-editor/styles.css'
|
|
95
|
+
|
|
96
|
+
<Editor editable={false} className="opacity-60" />
|
|
97
|
+
|
|
98
|
+
// You can target the state in CSS if you prefer
|
|
99
|
+
.nph-editor[data-disabled="true"] {
|
|
100
|
+
/_ e.g., make it look disabled _/
|
|
101
|
+
opacity: 0.6;
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Notes:
|
|
106
|
+
|
|
107
|
+
- `editable` is forwarded to TipTap.
|
|
108
|
+
- When `editable={false}`, the content element receives `aria-disabled="true"` and `data-disabled="true"`.
|
|
109
|
+
|
|
110
|
+
## Usage (Core/Headless)
|
|
111
|
+
|
|
112
|
+
Using TipTap core directly? Compose your editor with the preset, then add your own extensions on top:
|
|
113
|
+
|
|
114
|
+
```ts
|
|
115
|
+
import { Editor } from "@tiptap/core"
|
|
116
|
+
import { NeuphloPreset } from "neuphlo-editor"
|
|
117
|
+
import Placeholder from "@tiptap/extension-placeholder"
|
|
118
|
+
|
|
119
|
+
const editor = new Editor({
|
|
120
|
+
content: "<p>Hello</p>",
|
|
121
|
+
extensions: [
|
|
122
|
+
...NeuphloPreset,
|
|
123
|
+
Placeholder.configure({ placeholder: "Write something…" }),
|
|
124
|
+
],
|
|
125
|
+
})
|
|
126
|
+
```
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import StarterKit from '@tiptap/starter-kit';
|
|
2
|
+
|
|
3
|
+
// src/preset.ts
|
|
4
|
+
var Preset = [
|
|
5
|
+
StarterKit.configure({
|
|
6
|
+
bulletList: { keepMarks: true },
|
|
7
|
+
orderedList: { keepMarks: true },
|
|
8
|
+
heading: { levels: [1, 2, 3, 4] }
|
|
9
|
+
})
|
|
10
|
+
];
|
|
11
|
+
|
|
12
|
+
export { Preset };
|
|
13
|
+
//# sourceMappingURL=chunk-XABVYDNO.js.map
|
|
14
|
+
//# sourceMappingURL=chunk-XABVYDNO.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/preset.ts"],"names":[],"mappings":";;;AAGO,IAAM,MAAA,GAAsB;AAAA,EACjC,WAAW,SAAA,CAAU;AAAA,IACnB,UAAA,EAAY,EAAE,SAAA,EAAW,IAAA,EAAK;AAAA,IAC9B,WAAA,EAAa,EAAE,SAAA,EAAW,IAAA,EAAK;AAAA,IAC/B,OAAA,EAAS,EAAE,MAAA,EAAQ,CAAC,GAAG,CAAA,EAAG,CAAA,EAAG,CAAC,CAAA;AAAE,GACjC;AACH","file":"chunk-XABVYDNO.js","sourcesContent":["import type { Extension } from \"@tiptap/core\"\nimport StarterKit from \"@tiptap/starter-kit\"\n\nexport const Preset: Extension[] = [\n StarterKit.configure({\n bulletList: { keepMarks: true },\n orderedList: { keepMarks: true },\n heading: { levels: [1, 2, 3, 4] },\n }),\n]\n"]}
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var StarterKit = require('@tiptap/starter-kit');
|
|
4
|
+
|
|
5
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
6
|
+
|
|
7
|
+
var StarterKit__default = /*#__PURE__*/_interopDefault(StarterKit);
|
|
8
|
+
|
|
9
|
+
// src/preset.ts
|
|
10
|
+
var Preset = [
|
|
11
|
+
StarterKit__default.default.configure({
|
|
12
|
+
bulletList: { keepMarks: true },
|
|
13
|
+
orderedList: { keepMarks: true },
|
|
14
|
+
heading: { levels: [1, 2, 3, 4] }
|
|
15
|
+
})
|
|
16
|
+
];
|
|
17
|
+
|
|
18
|
+
exports.Preset = Preset;
|
|
19
|
+
//# sourceMappingURL=index.cjs.map
|
|
20
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/preset.ts"],"names":["StarterKit"],"mappings":";;;;;;;;;AAGO,IAAM,MAAA,GAAsB;AAAA,EACjCA,4BAAW,SAAA,CAAU;AAAA,IACnB,UAAA,EAAY,EAAE,SAAA,EAAW,IAAA,EAAK;AAAA,IAC9B,WAAA,EAAa,EAAE,SAAA,EAAW,IAAA,EAAK;AAAA,IAC/B,OAAA,EAAS,EAAE,MAAA,EAAQ,CAAC,GAAG,CAAA,EAAG,CAAA,EAAG,CAAC,CAAA;AAAE,GACjC;AACH","file":"index.cjs","sourcesContent":["import type { Extension } from \"@tiptap/core\"\nimport StarterKit from \"@tiptap/starter-kit\"\n\nexport const Preset: Extension[] = [\n StarterKit.configure({\n bulletList: { keepMarks: true },\n orderedList: { keepMarks: true },\n heading: { levels: [1, 2, 3, 4] },\n }),\n]\n"]}
|
package/dist/index.d.cts
ADDED
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var react = require('@tiptap/react');
|
|
4
|
+
var StarterKit = require('@tiptap/starter-kit');
|
|
5
|
+
var clsx = require('clsx');
|
|
6
|
+
var tailwindMerge = require('tailwind-merge');
|
|
7
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
8
|
+
|
|
9
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
10
|
+
|
|
11
|
+
var StarterKit__default = /*#__PURE__*/_interopDefault(StarterKit);
|
|
12
|
+
|
|
13
|
+
// src/react/Editor.tsx
|
|
14
|
+
var Preset = [
|
|
15
|
+
StarterKit__default.default.configure({
|
|
16
|
+
bulletList: { keepMarks: true },
|
|
17
|
+
orderedList: { keepMarks: true },
|
|
18
|
+
heading: { levels: [1, 2, 3, 4] }
|
|
19
|
+
})
|
|
20
|
+
];
|
|
21
|
+
function cn(...inputs) {
|
|
22
|
+
return tailwindMerge.twMerge(clsx.clsx(inputs));
|
|
23
|
+
}
|
|
24
|
+
function Editor({
|
|
25
|
+
styled = true,
|
|
26
|
+
className,
|
|
27
|
+
editorContainerProps,
|
|
28
|
+
extensions = [],
|
|
29
|
+
content,
|
|
30
|
+
onUpdate,
|
|
31
|
+
editorProps,
|
|
32
|
+
editable = true,
|
|
33
|
+
children,
|
|
34
|
+
...rest
|
|
35
|
+
}) {
|
|
36
|
+
const mergedContainerProps = {
|
|
37
|
+
...editorContainerProps,
|
|
38
|
+
className: cn(styled && "nph-editor", className)
|
|
39
|
+
};
|
|
40
|
+
const mergedEditorProps = {
|
|
41
|
+
...editorProps,
|
|
42
|
+
attributes: {
|
|
43
|
+
...editorProps?.attributes,
|
|
44
|
+
...!editable ? { "aria-disabled": "true", "data-disabled": "true" } : {}
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
48
|
+
react.EditorProvider,
|
|
49
|
+
{
|
|
50
|
+
content,
|
|
51
|
+
extensions: [...Preset, ...extensions ?? []],
|
|
52
|
+
onUpdate,
|
|
53
|
+
editorProps: mergedEditorProps,
|
|
54
|
+
editable,
|
|
55
|
+
editorContainerProps: mergedContainerProps,
|
|
56
|
+
...rest,
|
|
57
|
+
children
|
|
58
|
+
}
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
exports.Editor = Editor;
|
|
63
|
+
//# sourceMappingURL=index.cjs.map
|
|
64
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/preset.ts","../../src/react/utils/cn.ts","../../src/react/Editor.tsx"],"names":["StarterKit","twMerge","clsx","jsx","EditorProvider"],"mappings":";;;;;;;;;;;;;AAGO,IAAM,MAAA,GAAsB;AAAA,EACjCA,4BAAW,SAAA,CAAU;AAAA,IACnB,UAAA,EAAY,EAAE,SAAA,EAAW,IAAA,EAAK;AAAA,IAC9B,WAAA,EAAa,EAAE,SAAA,EAAW,IAAA,EAAK;AAAA,IAC/B,OAAA,EAAS,EAAE,MAAA,EAAQ,CAAC,GAAG,CAAA,EAAG,CAAA,EAAG,CAAC,CAAA;AAAE,GACjC;AACH,CAAA;ACNO,SAAS,MAAM,MAAA,EAAsB;AAC1C,EAAA,OAAOC,qBAAA,CAAQC,SAAA,CAAK,MAAM,CAAC,CAAA;AAC7B;ACWO,SAAS,MAAA,CAAO;AAAA,EACrB,MAAA,GAAS,IAAA;AAAA,EACT,SAAA;AAAA,EACA,oBAAA;AAAA,EACA,aAAa,EAAC;AAAA,EACd,OAAA;AAAA,EACA,QAAA;AAAA,EACA,WAAA;AAAA,EACA,QAAA,GAAW,IAAA;AAAA,EACX,QAAA;AAAA,EACA,GAAG;AACL,CAAA,EAAgB;AACd,EAAA,MAAM,oBAAA,GAAuB;AAAA,IAC3B,GAAG,oBAAA;AAAA,IACH,SAAA,EAAW,EAAA,CAAG,MAAA,IAAU,YAAA,EAAc,SAAS;AAAA,GACjD;AAEA,EAAA,MAAM,iBAAA,GAAoB;AAAA,IACxB,GAAG,WAAA;AAAA,IACH,UAAA,EAAY;AAAA,MACV,GAAG,WAAA,EAAa,UAAA;AAAA,MAChB,GAAI,CAAC,QAAA,GACD,EAAE,iBAAiB,MAAA,EAAQ,eAAA,EAAiB,MAAA,EAAO,GACnD;AAAC;AACP,GACF;AAEA,EAAA,uBACEC,cAAA;AAAA,IAACC,oBAAA;AAAA,IAAA;AAAA,MACC,OAAA;AAAA,MACA,YAAY,CAAC,GAAG,QAAQ,GAAI,UAAA,IAAc,EAAG,CAAA;AAAA,MAC7C,QAAA;AAAA,MACA,WAAA,EAAa,iBAAA;AAAA,MACb,QAAA;AAAA,MACA,oBAAA,EAAsB,oBAAA;AAAA,MACrB,GAAG,IAAA;AAAA,MAEH;AAAA;AAAA,GACH;AAEJ","file":"index.cjs","sourcesContent":["import type { Extension } from \"@tiptap/core\"\nimport StarterKit from \"@tiptap/starter-kit\"\n\nexport const Preset: Extension[] = [\n StarterKit.configure({\n bulletList: { keepMarks: true },\n orderedList: { keepMarks: true },\n heading: { levels: [1, 2, 3, 4] },\n }),\n]\n","import { clsx, type ClassValue } from 'clsx'\nimport { twMerge } from 'tailwind-merge'\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n\n","import * as React from \"react\"\nimport { EditorProvider } from \"@tiptap/react\"\nimport type { EditorProviderProps } from \"@tiptap/react\"\nimport { Preset } from \"../preset\"\nimport { cn } from \"./utils/cn\"\n\nexport type EditorProps = Omit<\n EditorProviderProps,\n \"children\" | \"slotBefore\" | \"slotAfter\" | \"editorContainerProps\"\n> & {\n styled?: boolean\n className?: string\n editorContainerProps?: Omit<React.HTMLAttributes<HTMLDivElement>, \"className\">\n children?: React.ReactNode\n}\n\nexport function Editor({\n styled = true,\n className,\n editorContainerProps,\n extensions = [],\n content,\n onUpdate,\n editorProps,\n editable = true,\n children,\n ...rest\n}: EditorProps) {\n const mergedContainerProps = {\n ...editorContainerProps,\n className: cn(styled && \"nph-editor\", className),\n }\n\n const mergedEditorProps = {\n ...editorProps,\n attributes: {\n ...editorProps?.attributes,\n ...(!editable\n ? { \"aria-disabled\": \"true\", \"data-disabled\": \"true\" }\n : {}),\n } as Record<string, string>,\n }\n\n return (\n <EditorProvider\n content={content}\n extensions={[...Preset, ...(extensions ?? [])]}\n onUpdate={onUpdate}\n editorProps={mergedEditorProps}\n editable={editable}\n editorContainerProps={mergedContainerProps}\n {...rest}\n >\n {children}\n </EditorProvider>\n )\n}\n"]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { EditorProviderProps } from '@tiptap/react';
|
|
4
|
+
|
|
5
|
+
type EditorProps = Omit<EditorProviderProps, "children" | "slotBefore" | "slotAfter" | "editorContainerProps"> & {
|
|
6
|
+
styled?: boolean;
|
|
7
|
+
className?: string;
|
|
8
|
+
editorContainerProps?: Omit<React.HTMLAttributes<HTMLDivElement>, "className">;
|
|
9
|
+
children?: React.ReactNode;
|
|
10
|
+
};
|
|
11
|
+
declare function Editor({ styled, className, editorContainerProps, extensions, content, onUpdate, editorProps, editable, children, ...rest }: EditorProps): react_jsx_runtime.JSX.Element;
|
|
12
|
+
|
|
13
|
+
export { Editor, type EditorProps };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { EditorProviderProps } from '@tiptap/react';
|
|
4
|
+
|
|
5
|
+
type EditorProps = Omit<EditorProviderProps, "children" | "slotBefore" | "slotAfter" | "editorContainerProps"> & {
|
|
6
|
+
styled?: boolean;
|
|
7
|
+
className?: string;
|
|
8
|
+
editorContainerProps?: Omit<React.HTMLAttributes<HTMLDivElement>, "className">;
|
|
9
|
+
children?: React.ReactNode;
|
|
10
|
+
};
|
|
11
|
+
declare function Editor({ styled, className, editorContainerProps, extensions, content, onUpdate, editorProps, editable, children, ...rest }: EditorProps): react_jsx_runtime.JSX.Element;
|
|
12
|
+
|
|
13
|
+
export { Editor, type EditorProps };
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { Preset } from '../chunk-XABVYDNO.js';
|
|
2
|
+
import { EditorProvider } from '@tiptap/react';
|
|
3
|
+
import { clsx } from 'clsx';
|
|
4
|
+
import { twMerge } from 'tailwind-merge';
|
|
5
|
+
import { jsx } from 'react/jsx-runtime';
|
|
6
|
+
|
|
7
|
+
function cn(...inputs) {
|
|
8
|
+
return twMerge(clsx(inputs));
|
|
9
|
+
}
|
|
10
|
+
function Editor({
|
|
11
|
+
styled = true,
|
|
12
|
+
className,
|
|
13
|
+
editorContainerProps,
|
|
14
|
+
extensions = [],
|
|
15
|
+
content,
|
|
16
|
+
onUpdate,
|
|
17
|
+
editorProps,
|
|
18
|
+
editable = true,
|
|
19
|
+
children,
|
|
20
|
+
...rest
|
|
21
|
+
}) {
|
|
22
|
+
const mergedContainerProps = {
|
|
23
|
+
...editorContainerProps,
|
|
24
|
+
className: cn(styled && "nph-editor", className)
|
|
25
|
+
};
|
|
26
|
+
const mergedEditorProps = {
|
|
27
|
+
...editorProps,
|
|
28
|
+
attributes: {
|
|
29
|
+
...editorProps?.attributes,
|
|
30
|
+
...!editable ? { "aria-disabled": "true", "data-disabled": "true" } : {}
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
return /* @__PURE__ */ jsx(
|
|
34
|
+
EditorProvider,
|
|
35
|
+
{
|
|
36
|
+
content,
|
|
37
|
+
extensions: [...Preset, ...extensions ?? []],
|
|
38
|
+
onUpdate,
|
|
39
|
+
editorProps: mergedEditorProps,
|
|
40
|
+
editable,
|
|
41
|
+
editorContainerProps: mergedContainerProps,
|
|
42
|
+
...rest,
|
|
43
|
+
children
|
|
44
|
+
}
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export { Editor };
|
|
49
|
+
//# sourceMappingURL=index.js.map
|
|
50
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/react/utils/cn.ts","../../src/react/Editor.tsx"],"names":[],"mappings":";;;;;;AAGO,SAAS,MAAM,MAAA,EAAsB;AAC1C,EAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,MAAM,CAAC,CAAA;AAC7B;ACWO,SAAS,MAAA,CAAO;AAAA,EACrB,MAAA,GAAS,IAAA;AAAA,EACT,SAAA;AAAA,EACA,oBAAA;AAAA,EACA,aAAa,EAAC;AAAA,EACd,OAAA;AAAA,EACA,QAAA;AAAA,EACA,WAAA;AAAA,EACA,QAAA,GAAW,IAAA;AAAA,EACX,QAAA;AAAA,EACA,GAAG;AACL,CAAA,EAAgB;AACd,EAAA,MAAM,oBAAA,GAAuB;AAAA,IAC3B,GAAG,oBAAA;AAAA,IACH,SAAA,EAAW,EAAA,CAAG,MAAA,IAAU,YAAA,EAAc,SAAS;AAAA,GACjD;AAEA,EAAA,MAAM,iBAAA,GAAoB;AAAA,IACxB,GAAG,WAAA;AAAA,IACH,UAAA,EAAY;AAAA,MACV,GAAG,WAAA,EAAa,UAAA;AAAA,MAChB,GAAI,CAAC,QAAA,GACD,EAAE,iBAAiB,MAAA,EAAQ,eAAA,EAAiB,MAAA,EAAO,GACnD;AAAC;AACP,GACF;AAEA,EAAA,uBACE,GAAA;AAAA,IAAC,cAAA;AAAA,IAAA;AAAA,MACC,OAAA;AAAA,MACA,YAAY,CAAC,GAAG,QAAQ,GAAI,UAAA,IAAc,EAAG,CAAA;AAAA,MAC7C,QAAA;AAAA,MACA,WAAA,EAAa,iBAAA;AAAA,MACb,QAAA;AAAA,MACA,oBAAA,EAAsB,oBAAA;AAAA,MACrB,GAAG,IAAA;AAAA,MAEH;AAAA;AAAA,GACH;AAEJ","file":"index.js","sourcesContent":["import { clsx, type ClassValue } from 'clsx'\nimport { twMerge } from 'tailwind-merge'\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n\n","import * as React from \"react\"\nimport { EditorProvider } from \"@tiptap/react\"\nimport type { EditorProviderProps } from \"@tiptap/react\"\nimport { Preset } from \"../preset\"\nimport { cn } from \"./utils/cn\"\n\nexport type EditorProps = Omit<\n EditorProviderProps,\n \"children\" | \"slotBefore\" | \"slotAfter\" | \"editorContainerProps\"\n> & {\n styled?: boolean\n className?: string\n editorContainerProps?: Omit<React.HTMLAttributes<HTMLDivElement>, \"className\">\n children?: React.ReactNode\n}\n\nexport function Editor({\n styled = true,\n className,\n editorContainerProps,\n extensions = [],\n content,\n onUpdate,\n editorProps,\n editable = true,\n children,\n ...rest\n}: EditorProps) {\n const mergedContainerProps = {\n ...editorContainerProps,\n className: cn(styled && \"nph-editor\", className),\n }\n\n const mergedEditorProps = {\n ...editorProps,\n attributes: {\n ...editorProps?.attributes,\n ...(!editable\n ? { \"aria-disabled\": \"true\", \"data-disabled\": \"true\" }\n : {}),\n } as Record<string, string>,\n }\n\n return (\n <EditorProvider\n content={content}\n extensions={[...Preset, ...(extensions ?? [])]}\n onUpdate={onUpdate}\n editorProps={mergedEditorProps}\n editable={editable}\n editorContainerProps={mergedContainerProps}\n {...rest}\n >\n {children}\n </EditorProvider>\n )\n}\n"]}
|
package/dist/styles.css
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
.nph-editor {
|
|
2
|
+
--nph-radius: 8px;
|
|
3
|
+
--nph-text: #111827;
|
|
4
|
+
--nph-text-muted: #6b7280;
|
|
5
|
+
--nph-accent: #2563eb;
|
|
6
|
+
|
|
7
|
+
min-height: 160px;
|
|
8
|
+
border-radius: var(--nph-radius);
|
|
9
|
+
color: var(--nph-text);
|
|
10
|
+
padding: 12px;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
@media (prefers-color-scheme: dark) {
|
|
14
|
+
.nph-editor {
|
|
15
|
+
--nph-text: #fafafa;
|
|
16
|
+
--nph-text-muted: #a3a3a3;
|
|
17
|
+
--nph-accent: #60a5fa;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/* Typography */
|
|
22
|
+
.nph-editor p {
|
|
23
|
+
margin: 0.75em 0;
|
|
24
|
+
}
|
|
25
|
+
.nph-editor h1,
|
|
26
|
+
.nph-editor h2,
|
|
27
|
+
.nph-editor h3,
|
|
28
|
+
.nph-editor h4 {
|
|
29
|
+
margin: 1.2em 0 0.5em;
|
|
30
|
+
line-height: 1.2;
|
|
31
|
+
}
|
|
32
|
+
.nph-editor h1 {
|
|
33
|
+
font-size: 1.875rem;
|
|
34
|
+
font-weight: 700;
|
|
35
|
+
}
|
|
36
|
+
.nph-editor h2 {
|
|
37
|
+
font-size: 1.5rem;
|
|
38
|
+
font-weight: 700;
|
|
39
|
+
}
|
|
40
|
+
.nph-editor h3 {
|
|
41
|
+
font-size: 1.25rem;
|
|
42
|
+
font-weight: 600;
|
|
43
|
+
}
|
|
44
|
+
.nph-editor h4 {
|
|
45
|
+
font-size: 1.125rem;
|
|
46
|
+
font-weight: 600;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.nph-editor ul,
|
|
50
|
+
.nph-editor ol {
|
|
51
|
+
padding-left: 1.25rem;
|
|
52
|
+
margin: 0.75em 0;
|
|
53
|
+
}
|
|
54
|
+
.nph-editor ul {
|
|
55
|
+
list-style: disc;
|
|
56
|
+
}
|
|
57
|
+
.nph-editor ol {
|
|
58
|
+
list-style: decimal;
|
|
59
|
+
}
|
|
60
|
+
.nph-editor li {
|
|
61
|
+
margin: 0.25em 0;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.nph-editor a {
|
|
65
|
+
color: var(--nph-accent);
|
|
66
|
+
text-decoration: underline;
|
|
67
|
+
}
|
|
68
|
+
.nph-editor strong {
|
|
69
|
+
font-weight: 600;
|
|
70
|
+
}
|
|
71
|
+
.nph-editor em {
|
|
72
|
+
font-style: italic;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.nph-editor blockquote {
|
|
76
|
+
margin: 1em 0;
|
|
77
|
+
padding: 0.75em 1em;
|
|
78
|
+
color: var(--nph-text-muted);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.nph-editor code {
|
|
82
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,
|
|
83
|
+
"Liberation Mono", "Courier New", monospace;
|
|
84
|
+
font-size: 0.95em;
|
|
85
|
+
padding: 0.15em 0.35em;
|
|
86
|
+
border-radius: 4px;
|
|
87
|
+
}
|
|
88
|
+
.nph-editor pre {
|
|
89
|
+
padding: 0.75em 1em;
|
|
90
|
+
border-radius: 6px;
|
|
91
|
+
overflow: auto;
|
|
92
|
+
}
|
|
93
|
+
.nph-editor pre code {
|
|
94
|
+
padding: 0;
|
|
95
|
+
background: transparent;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.nph-editor hr {
|
|
99
|
+
border: none;
|
|
100
|
+
margin: 1.25em 0;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.nph-editor table {
|
|
104
|
+
border-collapse: collapse;
|
|
105
|
+
width: 100%;
|
|
106
|
+
margin: 1em 0;
|
|
107
|
+
}
|
|
108
|
+
.nph-editor th,
|
|
109
|
+
.nph-editor td {
|
|
110
|
+
padding: 0.5em 0.75em;
|
|
111
|
+
text-align: left;
|
|
112
|
+
}
|
|
113
|
+
.nph-editor th {
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.nph-editor img {
|
|
117
|
+
max-width: 100%;
|
|
118
|
+
height: auto;
|
|
119
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "neuphlo-editor",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"private": false,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.cjs",
|
|
7
|
+
"module": "dist/index.js",
|
|
8
|
+
"types": "dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js",
|
|
13
|
+
"require": "./dist/index.cjs"
|
|
14
|
+
},
|
|
15
|
+
"./react": {
|
|
16
|
+
"types": "./dist/react/index.d.ts",
|
|
17
|
+
"import": "./dist/react/index.js",
|
|
18
|
+
"require": "./dist/react/index.cjs"
|
|
19
|
+
},
|
|
20
|
+
"./styles.css": {
|
|
21
|
+
"default": "./dist/styles.css"
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"files": [
|
|
25
|
+
"dist"
|
|
26
|
+
],
|
|
27
|
+
"sideEffects": [
|
|
28
|
+
"dist/styles.css"
|
|
29
|
+
],
|
|
30
|
+
"scripts": {
|
|
31
|
+
"build": "tsup src/index.ts src/react/index.ts --dts --format esm,cjs --clean && npm run build:css",
|
|
32
|
+
"build:css": "cp src/styles.css dist/styles.css",
|
|
33
|
+
"dev": "tsup --watch",
|
|
34
|
+
"publish:dry": "npm publish --dry-run",
|
|
35
|
+
"prepack": "npm run build",
|
|
36
|
+
"prepare": "npm run build"
|
|
37
|
+
},
|
|
38
|
+
"publishConfig": {
|
|
39
|
+
"access": "public"
|
|
40
|
+
},
|
|
41
|
+
"repository": {
|
|
42
|
+
"type": "git",
|
|
43
|
+
"url": "git+https://github.com/Neuphlo/neuphlo-editor.git"
|
|
44
|
+
},
|
|
45
|
+
"bugs": {
|
|
46
|
+
"url": "https://github.com/Neuphlo/neuphlo-editor/issues"
|
|
47
|
+
},
|
|
48
|
+
"homepage": "https://github.com/Neuphlo/neuphlo-editor#readme",
|
|
49
|
+
"peerDependencies": {
|
|
50
|
+
"react": ">=18",
|
|
51
|
+
"react-dom": ">=18"
|
|
52
|
+
},
|
|
53
|
+
"dependencies": {
|
|
54
|
+
"@tiptap/core": "^2.4.0",
|
|
55
|
+
"@tiptap/pm": "^2.4.0",
|
|
56
|
+
"@tiptap/react": "^2.4.0",
|
|
57
|
+
"@tiptap/starter-kit": "^2.4.0",
|
|
58
|
+
"clsx": "^2.1.1",
|
|
59
|
+
"tailwind-merge": "^3.3.1"
|
|
60
|
+
},
|
|
61
|
+
"devDependencies": {
|
|
62
|
+
"@types/node": "^22.0.0",
|
|
63
|
+
"@types/react": "^19.1.12",
|
|
64
|
+
"@types/react-dom": "^19.1.9",
|
|
65
|
+
"react": "^18.3.1",
|
|
66
|
+
"react-dom": "^18.3.1",
|
|
67
|
+
"tsup": "^8.1.0",
|
|
68
|
+
"typescript": "^5.6.2"
|
|
69
|
+
}
|
|
70
|
+
}
|