tiptap-editor-custom-stg 1.0.4 → 1.0.6

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
@@ -52,48 +52,48 @@ import { TiptapEditor } from 'tiptap-editor-custom-stg';
52
52
  import 'tiptap-editor-custom-stg/styles'; // required
53
53
 
54
54
  function MyComponent() {
55
- const [content, setContent] = React.useState('<p>Hello World!</p>');
56
-
57
- return (
58
- <TiptapEditor
59
- elementId="my-editor"
60
- content={content}
61
- editMode={true}
62
- docNum="DOC-001"
63
- placeholder="Start typing..."
64
- toolbarConfig={{
65
- groups: ['history', 'font', 'fontSize', 'textColor', 'list', 'link', 'insert'],
66
- showDividers: true,
67
- }}
68
- receiveData={(id, html) => setContent(html)}
69
- onUploadFile={async (file, docNum) => {
70
- const url = await uploadToYourStorage(file, docNum);
71
- return url;
72
- }}
73
- onAlert={(msg) => alert(msg)}
74
- onLoadingChange={(isLoading) => setLoading(isLoading)}
75
- />
76
- );
55
+ const [content, setContent] = React.useState('<p>Hello World!</p>');
56
+
57
+ return (
58
+ <TiptapEditor
59
+ elementId='my-editor'
60
+ content={content}
61
+ editMode={true}
62
+ docNum='DOC-001'
63
+ placeholder='Start typing...'
64
+ toolbarConfig={{
65
+ groups: ['history', 'font', 'fontSize', 'textColor', 'list', 'link', 'insert'],
66
+ showDividers: true,
67
+ }}
68
+ receiveData={(id, html) => setContent(html)}
69
+ onUploadFile={async (file, docNum) => {
70
+ const url = await uploadToYourStorage(file, docNum);
71
+ return url;
72
+ }}
73
+ onAlert={(msg) => alert(msg)}
74
+ onLoadingChange={(isLoading) => setLoading(isLoading)}
75
+ />
76
+ );
77
77
  }
78
78
  ```
79
79
 
80
80
  ### Props
81
81
 
82
- | Prop | Type | Required | Default | Description |
83
- |------|------|----------|---------|-------------|
84
- | `elementId` | `string` | ✅ | — | Unique ID for the editor instance |
85
- | `content` | `string` | ✅ | — | HTML content |
86
- | `editMode` | `boolean` | ✅ | — | `true` = editable, `false` = read-only |
87
- | `docNum` | `string` | ✅ | — | Document number passed to `onUploadFile` |
88
- | `receiveData` | `(id, html) => void` | — | — | Called on every content change |
89
- | `receiveStatus` | `(id, loading) => void` | — | — | Called when per-editor upload status changes |
90
- | `onUploadFile` | `(file, docNum) => Promise<string>` | — | — | Upload handler, must return the file URL |
91
- | `onAlert` | `(message) => void` | — | `window.alert` | Custom alert/notification function |
92
- | `onLoadingChange` | `(isLoading) => void` | — | — | Global loading state callback |
93
- | `onRegisterReset` | `(callback) => () => void` | — | — | Register a reset callback, returns cleanup fn |
94
- | `placeholder` | `string` | — | `'Start typing...'` | Editor placeholder text. This value is passed into Tiptap's `Placeholder` extension and is shown when the editor is empty |
95
- | `toolbarConfig` | `{ groups?: ToolbarGroup[]; showDividers?: boolean }` | — | default toolbar config | Customize which toolbar groups are shown and whether dividers are rendered |
96
- | `customValidationFn` | `(files: File[]) => Promise<boolean>` | — | — | Custom async function to validate selected files before upload. Return `true` to proceed or `false` to abort. |
82
+ | Prop | Type | Required | Default | Description |
83
+ | -------------------- | ----------------------------------------------------- | -------- | ---------------------- | ------------------------------------------------------------------------------------------------------------------------- |
84
+ | `elementId` | `string` | ✅ | — | Unique ID for the editor instance |
85
+ | `content` | `string` | ✅ | — | HTML content |
86
+ | `editMode` | `boolean` | ✅ | — | `true` = editable, `false` = read-only |
87
+ | `docNum` | `string` | ✅ | — | Document number passed to `onUploadFile` |
88
+ | `receiveData` | `(id, html) => void` | — | — | Called on every content change |
89
+ | `receiveStatus` | `(id, loading) => void` | — | — | Called when per-editor upload status changes |
90
+ | `onUploadFile` | `(file, docNum) => Promise<string>` | — | — | Upload handler, must return the file URL |
91
+ | `onAlert` | `(message) => void` | — | `window.alert` | Custom alert/notification function |
92
+ | `onLoadingChange` | `(isLoading) => void` | — | — | Global loading state callback |
93
+ | `onRegisterReset` | `(callback) => () => void` | — | — | Register a reset callback, returns cleanup fn |
94
+ | `placeholder` | `string` | — | `'Start typing...'` | Editor placeholder text. This value is passed into Tiptap's `Placeholder` extension and is shown when the editor is empty |
95
+ | `toolbarConfig` | `{ groups?: ToolbarGroup[]; showDividers?: boolean }` | — | default toolbar config | Customize which toolbar groups are shown and whether dividers are rendered |
96
+ | `customValidationFn` | `(files: File[]) => Promise<boolean>` | — | — | Custom async function to validate selected files before upload. Return `true` to proceed or `false` to abort. |
97
97
 
98
98
  ### Styling
99
99
 
@@ -106,9 +106,15 @@ import 'tiptap-editor-custom-stg/styles';
106
106
  To override default styles, target these CSS classes:
107
107
 
108
108
  ```css
109
- .tiptap-editor-wrapper { /* outer container */ }
110
- .tiptap-toolbar { /* toolbar */ }
111
- .ProseMirror { /* editor content area */ }
109
+ .tiptap-editor-wrapper {
110
+ /* outer container */
111
+ }
112
+ .tiptap-toolbar {
113
+ /* toolbar */
114
+ }
115
+ .ProseMirror {
116
+ /* editor content area */
117
+ }
112
118
  ```
113
119
 
114
120
  ### Toolbar Configuration
@@ -117,14 +123,14 @@ Use `toolbarConfig` to control which toolbar groups are displayed and whether di
117
123
 
118
124
  ```tsx
119
125
  <TiptapEditor
120
- elementId="my-editor"
121
- content={content}
122
- editMode={true}
123
- docNum="DOC-001"
124
- toolbarConfig={{
125
- groups: ['history', 'font', 'fontSize', 'textColor', 'list', 'link', 'insert'],
126
- showDividers: true,
127
- }}
126
+ elementId='my-editor'
127
+ content={content}
128
+ editMode={true}
129
+ docNum='DOC-001'
130
+ toolbarConfig={{
131
+ groups: ['history', 'font', 'fontSize', 'textColor', 'list', 'link', 'insert'],
132
+ showDividers: true,
133
+ }}
128
134
  />
129
135
  ```
130
136
 
@@ -145,33 +151,21 @@ Available toolbar groups:
145
151
  Default toolbar groups:
146
152
 
147
153
  ```ts
148
- [
149
- 'history',
150
- 'font',
151
- 'fontSize',
152
- 'textColor',
153
- 'highlight',
154
- 'list',
155
- 'alignment',
156
- 'table',
157
- 'inline',
158
- 'link',
159
- 'insert',
160
- ]
154
+ ['history', 'font', 'fontSize', 'textColor', 'highlight', 'list', 'alignment', 'table', 'inline', 'link', 'insert'];
161
155
  ```
162
156
 
163
157
  Example: minimal toolbar without dividers
164
158
 
165
159
  ```tsx
166
160
  <TiptapEditor
167
- elementId="my-editor"
168
- content={content}
169
- editMode={true}
170
- docNum="DOC-001"
171
- toolbarConfig={{
172
- groups: ['history', 'inline', 'link'],
173
- showDividers: false,
174
- }}
161
+ elementId='my-editor'
162
+ content={content}
163
+ editMode={true}
164
+ docNum='DOC-001'
165
+ toolbarConfig={{
166
+ groups: ['history', 'inline', 'link'],
167
+ showDividers: false,
168
+ }}
175
169
  />
176
170
  ```
177
171
 
@@ -180,13 +174,7 @@ Example: minimal toolbar without dividers
180
174
  You can customize the empty-state placeholder text with the `placeholder` prop:
181
175
 
182
176
  ```tsx
183
- <TiptapEditor
184
- elementId="my-editor"
185
- content=""
186
- editMode={true}
187
- docNum="DOC-001"
188
- placeholder="Start typing..."
189
- />
177
+ <TiptapEditor elementId='my-editor' content='' editMode={true} docNum='DOC-001' placeholder='Start typing...' />
190
178
  ```
191
179
 
192
180
  The placeholder is driven by Tiptap's `Placeholder` extension configuration, so the `placeholder` prop is the source of truth for the text shown in the editor.
@@ -199,11 +187,13 @@ Use `onRegisterReset` to let a parent component reset the editor content program
199
187
  const resetRef = React.useRef<((content: string) => void) | null>(null);
200
188
 
201
189
  <TiptapEditor
202
- onRegisterReset={(callback) => {
203
- resetRef.current = callback;
204
- return () => { resetRef.current = null; };
205
- }}
206
- />
190
+ onRegisterReset={(callback) => {
191
+ resetRef.current = callback;
192
+ return () => {
193
+ resetRef.current = null;
194
+ };
195
+ }}
196
+ />;
207
197
 
208
198
  // Reset from anywhere:
209
199
  resetRef.current?.('<p>New content</p>');
@@ -244,6 +234,7 @@ npm run build
244
234
  ```
245
235
 
246
236
  This runs two steps:
237
+
247
238
  1. `build:js` — compiles TypeScript via tsup → `dist/index.js`, `dist/index.mjs`, `dist/index.d.ts`
248
239
  2. `build:css` — compiles SCSS via sass → `dist/index.css`, copies `dist/styles.d.ts`
249
240
 
@@ -267,6 +258,7 @@ So `npm pack` is not packing the entire repository by default. It is packing the
267
258
  cd tiptap-editor-custom-stg
268
259
  npm run build
269
260
  npm pack
261
+ 或者: npm run build && npm pack
270
262
  # Creates: tiptap-editor-custom-stg-1.0.0.tgz
271
263
 
272
264
  # 2. Install into your project
package/dist/index.css CHANGED
@@ -1 +1 @@
1
- .tiptap-editor-wrapper{border:1px solid #e5e7eb;border-radius:.75rem;overflow:hidden;font-size:15px;font-family:"Inter",-apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif;background:#fff;box-shadow:0 1px 3px 0 rgba(0,0,0,.05),0 1px 2px -1px rgba(0,0,0,.05)}.tiptap-editor-wrapper .tiptap-toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:.25rem;padding:.35rem .75rem;background:#fff;border-bottom:1px solid #f3f4f6}.tiptap-editor-wrapper .tiptap-toolbar button{display:inline-flex;align-items:center;justify-content:center;width:32px;height:32px;padding:0;border:none;border-radius:.375rem;background:rgba(0,0,0,0);cursor:pointer;color:#4b5563;font-size:14px;font-weight:500;transition:all .15s ease;line-height:1}.tiptap-editor-wrapper .tiptap-toolbar button:hover:not(:disabled){background:#f3f4f6;color:#111827}.tiptap-editor-wrapper .tiptap-toolbar button.is-active{background:#e5e7eb;color:#111827}.tiptap-editor-wrapper .tiptap-toolbar button:disabled{opacity:.4;cursor:not-allowed}.tiptap-editor-wrapper .tiptap-toolbar button.toolbar-button-dropdown{width:30px;padding:0 2px 0 4px;gap:1px}.tiptap-editor-wrapper .tiptap-toolbar button.toolbar-button-dropdown .dropdown-arrow{width:9px;height:9px;opacity:.6;margin-left:-2px}.tiptap-editor-wrapper .tiptap-toolbar button svg{width:18px;height:18px}.tiptap-editor-wrapper .tiptap-toolbar .toolbar-divider{width:1px;height:20px;background:#e5e7eb;margin:0 .5rem;flex-shrink:0}.tiptap-editor-wrapper .tiptap-toolbar .toolbar-select-wrapper{position:relative;display:inline-flex;align-items:center}.tiptap-editor-wrapper .tiptap-toolbar .toolbar-select{appearance:none;height:32px;border:none;border-radius:.375rem;background:rgba(0,0,0,0);font-size:14.5px;cursor:pointer;padding:0 1.5rem 0 .5rem;color:#4b5563;font-family:inherit;font-weight:500;transition:all .15s ease}.tiptap-editor-wrapper .tiptap-toolbar .toolbar-select:hover{background:#f3f4f6;color:#111827}.tiptap-editor-wrapper .tiptap-toolbar .toolbar-select:focus{outline:none;box-shadow:0 0 0 2px rgba(15,98,254,.2)}.tiptap-editor-wrapper .tiptap-toolbar .select-caret{position:absolute;right:.5rem;pointer-events:none;width:16px;height:16px;fill:#6b7280}.tiptap-editor-wrapper .tiptap-highlight-menu{position:absolute;top:110%;left:50%;transform:translateX(-50%);background:#fff;border:1px solid #e5e7eb;border-radius:9999px;padding:4px;display:flex;gap:6px;box-shadow:0 4px 6px -1px rgba(0,0,0,.1),0 2px 4px -1px rgba(0,0,0,.06);z-index:100}.tiptap-editor-wrapper .tiptap-highlight-menu .color-swatch{width:18px !important;height:18px !important;min-width:18px !important;min-height:18px !important;border-radius:50% !important;border:1px solid rgba(0,0,0,.1) !important;cursor:pointer;padding:0 !important;background-color:#fff;display:flex;align-items:center;justify-content:center;transition:transform .1s ease}.tiptap-editor-wrapper .tiptap-highlight-menu .color-swatch:hover{transform:scale(1.2)}.tiptap-editor-wrapper .tiptap-highlight-menu .color-swatch.clear-swatch{background-color:rgba(0,0,0,0) !important;border:1px solid #d1d5db !important}.tiptap-editor-wrapper .tiptap-highlight-menu .color-swatch svg{width:12px;height:12px;color:#6b7280}.tiptap-editor-wrapper .tiptap-font-menu{position:absolute;top:110%;left:0;background:#fff;border:1px solid #e5e7eb;border-radius:8px;padding:4px;box-shadow:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -2px rgba(0,0,0,.05);z-index:100;min-width:180px;max-height:300px;overflow-y:auto}.tiptap-editor-wrapper .tiptap-font-menu .font-option{width:100%;text-align:left;padding:8px 12px;border-radius:4px;background:none;border:none;font-size:14px;color:#374151;cursor:pointer;transition:all .15s ease}.tiptap-editor-wrapper .tiptap-font-menu .font-option:hover:not(.is-active){background:#f3f4f6;color:#111827}.tiptap-editor-wrapper .tiptap-font-menu .font-option.is-active{background:#0062ff;color:#fff;font-weight:500}.tiptap-editor-wrapper .tiptap-heading-menu{position:absolute;top:110%;left:0;background:#fff;border:1px solid #e5e7eb;border-radius:8px;padding:4px;box-shadow:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -2px rgba(0,0,0,.05);z-index:100;min-width:140px}.tiptap-editor-wrapper .tiptap-heading-menu .heading-option{width:100%;text-align:left;padding:6px 12px;border-radius:4px;background:none;border:none;font-size:14px;color:#374151;cursor:pointer;transition:all .15s ease}.tiptap-editor-wrapper .tiptap-heading-menu .heading-option:hover{background:#f3f4f6;color:#111827}.tiptap-editor-wrapper .tiptap-heading-menu .heading-option.is-active{background:#eff6ff;color:#2563eb;font-weight:600}.tiptap-editor-wrapper .tiptap-heading-menu .heading-option.h1{font-size:1.35rem;font-weight:700}.tiptap-editor-wrapper .tiptap-heading-menu .heading-option.h2{font-size:1.25rem;font-weight:600}.tiptap-editor-wrapper .tiptap-heading-menu .heading-option.h3{font-size:1.15rem;font-weight:600}.tiptap-editor-wrapper .tiptap-heading-menu .heading-option.h4{font-size:1.05rem;font-weight:600}.tiptap-editor-wrapper .tiptap-heading-menu .heading-option.h5{font-size:1rem;font-weight:600}.tiptap-editor-wrapper .tiptap-heading-menu .heading-option.h6{font-size:.9rem;font-weight:600}.tiptap-editor-wrapper .tiptap-color-picker{position:absolute;top:110%;left:50%;transform:translateX(-50%);background:#fff;border:1px solid #e5e7eb;border-radius:10px;padding:10px;box-shadow:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -2px rgba(0,0,0,.05);z-index:100;width:160px}.tiptap-editor-wrapper .tiptap-color-picker .color-remove-btn{width:100%;display:flex;align-items:center;justify-content:center;gap:8px;padding:8px;margin-bottom:8px;background:#fdfdfd;border:1px solid #e5e7eb;border-radius:6px;font-size:13px;color:#4b5563;cursor:pointer;transition:all .15s ease}.tiptap-editor-wrapper .tiptap-color-picker .color-remove-btn:hover{background:#f3f4f6;border-color:#d1d5db;color:#111827}.tiptap-editor-wrapper .tiptap-color-picker .color-remove-btn svg{width:14px;height:14px}.tiptap-editor-wrapper .tiptap-color-picker .color-grid{display:grid;grid-template-columns:repeat(5, 1fr);gap:4px}.tiptap-editor-wrapper .tiptap-color-picker .color-grid .color-swatch{width:24px !important;height:24px !important;min-width:24px !important;min-height:24px !important;border-radius:4px !important;border:1px solid rgba(0,0,0,.08) !important;padding:0 !important;cursor:pointer;transition:transform .15s ease,border-color .15s ease}.tiptap-editor-wrapper .tiptap-color-picker .color-grid .color-swatch:hover{transform:scale(1.15);border-color:rgba(0,0,0,.2) !important;z-index:2}.tiptap-editor-wrapper .tiptap-link-menu{position:absolute;top:110%;left:50%;transform:translateX(-50%);background:#fff;border:1px solid #e5e7eb;border-radius:8px;padding:4px;display:flex;align-items:center;gap:2px;box-shadow:0 4px 6px -1px rgba(0,0,0,.1),0 2px 4px -1px rgba(0,0,0,.06);z-index:100;width:300px}.tiptap-editor-wrapper .tiptap-link-menu input{flex:1;border:1px solid #d1d5db;border-radius:4px;padding:4px 8px;font-size:14px;outline:none;transition:border-color .15s ease}.tiptap-editor-wrapper .tiptap-link-menu input:focus{border-color:#3b82f6;box-shadow:0 0 0 1px #3b82f6}.tiptap-editor-wrapper .tiptap-link-menu button{width:28px !important;height:28px !important;padding:0 !important;min-width:28px !important;border-radius:4px !important;display:flex;align-items:center;justify-content:center}.tiptap-editor-wrapper .tiptap-link-menu button svg{width:14px;height:14px}.tiptap-editor-wrapper .tiptap-link-menu button.link-submit-btn{color:#22c55e}.tiptap-editor-wrapper .tiptap-link-menu button.link-submit-btn:hover{background:#dcfce7}.tiptap-editor-wrapper .tiptap-link-menu button.link-clear-btn{color:#ef4444}.tiptap-editor-wrapper .tiptap-link-menu button.link-clear-btn:hover{background:#fee2e2}.tiptap-editor-wrapper .tiptap-table-menu{position:absolute;top:110%;left:0;background:#fff;border:1px solid #e5e7eb;border-radius:8px;padding:8px;box-shadow:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -2px rgba(0,0,0,.05);z-index:100;min-width:200px}.tiptap-editor-wrapper .tiptap-table-menu .table-grid-picker-wrapper{padding:4px;background:#fff}.tiptap-editor-wrapper .tiptap-table-menu .table-grid-picker-wrapper .table-grid-picker{display:flex;flex-direction:column;gap:2px;padding-bottom:8px}.tiptap-editor-wrapper .tiptap-table-menu .table-grid-picker-wrapper .grid-row{display:flex;gap:2px}.tiptap-editor-wrapper .tiptap-table-menu .table-grid-picker-wrapper .grid-cell{width:16px;height:16px;border:1px solid #d1d5db;border-radius:1px;cursor:pointer;transition:background-color .1s,border-color .1s}.tiptap-editor-wrapper .tiptap-table-menu .table-grid-picker-wrapper .grid-cell:hover{border-color:#3b82f6}.tiptap-editor-wrapper .tiptap-table-menu .table-grid-picker-wrapper .grid-cell.is-active{background-color:#bfdbfe;border-color:#3b82f6}.tiptap-editor-wrapper .tiptap-table-menu .table-grid-picker-wrapper .table-grid-label{text-align:center;font-size:13px;color:#4b5563;font-weight:500;border-top:1px solid #f3f4f6;padding-top:8px;margin-top:2px}.tiptap-editor-wrapper .tiptap-table-menu .table-menu-item{width:100%;display:flex;align-items:center;gap:8px;padding:8px 12px;border-radius:4px;background:none;border:none;font-size:13px;color:#374151;transition:background .15s ease;white-space:nowrap;cursor:pointer}.tiptap-editor-wrapper .tiptap-table-menu .table-menu-item:hover{background:#f3f4f6}.tiptap-editor-wrapper .tiptap-table-menu .table-menu-item svg{width:16px;height:16px;color:#6b7280}.tiptap-editor-wrapper .tiptap-table-menu .table-menu-grid{display:grid;grid-template-columns:repeat(3, 1fr);gap:6px}.tiptap-editor-wrapper .tiptap-table-menu .table-menu-grid button{width:32px !important;height:32px !important;padding:0 !important;min-width:32px !important;display:flex;align-items:center;justify-content:center;border-radius:4px;background:#f9fafb !important;border:1px solid #e5e7eb !important;color:#4b5563 !important;cursor:pointer}.tiptap-editor-wrapper .tiptap-table-menu .table-menu-grid button:hover{background:#f3f4f6 !important;border-color:#d1d5db !important}.tiptap-editor-wrapper .tiptap-table-menu .table-menu-grid button.danger{color:#ef4444 !important}.tiptap-editor-wrapper .tiptap-table-menu .table-menu-grid button.danger:hover{background:#fee2e2 !important;border-color:#fca5a5 !important}.tiptap-editor-wrapper .tiptap-table-menu .table-menu-grid button svg{width:16px;height:16px}.tiptap-editor-wrapper .ProseMirror{min-height:300px;padding:1.5rem;color:#1f2937;outline:none;line-height:1.7}.tiptap-editor-wrapper .ProseMirror p.is-editor-empty:first-child::before{color:#9ca3af;content:attr(data-placeholder);float:left;height:0;pointer-events:none}.tiptap-editor-wrapper .ProseMirror h1,.tiptap-editor-wrapper .ProseMirror h2,.tiptap-editor-wrapper .ProseMirror h3,.tiptap-editor-wrapper .ProseMirror h4{line-height:1.2;color:#111827}.tiptap-editor-wrapper .ProseMirror h1{font-size:2.25rem;font-weight:700;margin:1em 0 .5em}.tiptap-editor-wrapper .ProseMirror h2{font-size:1.875rem;font-weight:600;margin:1em 0 .5em}.tiptap-editor-wrapper .ProseMirror h3{font-size:1.5rem;font-weight:600;margin:1em 0 .5em}.tiptap-editor-wrapper .ProseMirror h4{font-size:1.25rem;font-weight:600;margin:1em 0 .5em}.tiptap-editor-wrapper .ProseMirror [style*="font-size: 0.7em"],.tiptap-editor-wrapper .ProseMirror .text-tiny{font-size:.7em}.tiptap-editor-wrapper .ProseMirror [style*="font-size: 0.85em"],.tiptap-editor-wrapper .ProseMirror .text-small{font-size:.85em}.tiptap-editor-wrapper .ProseMirror [style*="font-size: 1.4em"],.tiptap-editor-wrapper .ProseMirror .text-big{font-size:1.4em}.tiptap-editor-wrapper .ProseMirror [style*="font-size: 1.8em"],.tiptap-editor-wrapper .ProseMirror .text-huge{font-size:1.8em}.tiptap-editor-wrapper .ProseMirror p{margin:.5em 0}.tiptap-editor-wrapper .ProseMirror ul{list-style-type:disc;padding-left:1.5rem;margin:.5em 0}.tiptap-editor-wrapper .ProseMirror ol{list-style-type:decimal;padding-left:1.5rem;margin:.5em 0}.tiptap-editor-wrapper .ProseMirror blockquote{border-left:4px solid #e5e7eb;padding-left:1rem;margin:1em 0;color:#4b5563;font-style:italic}.tiptap-editor-wrapper .ProseMirror code{background:#f3f4f6;border-radius:4px;padding:.2rem .4rem;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;font-size:.875em}.tiptap-editor-wrapper .ProseMirror pre{background:#111827;color:#f3f4f6;border-radius:.5rem;padding:1rem;overflow-x:auto;margin:1em 0}.tiptap-editor-wrapper .ProseMirror pre code{background:none;padding:0;color:inherit}.tiptap-editor-wrapper .ProseMirror img{max-width:100%;height:auto;display:block;margin:1rem 0;border-radius:.375rem;box-shadow:0 1px 3px 0 rgba(0,0,0,.1)}.tiptap-editor-wrapper .ProseMirror a{color:#2563eb;text-decoration:underline;text-underline-offset:2px;font-weight:500;cursor:pointer}.tiptap-editor-wrapper .ProseMirror a:hover{color:#1d4ed8}.tiptap-editor-wrapper .ProseMirror a[data-attachment=true]{display:inline-flex;align-items:center;gap:.375rem;padding:.25rem .6rem;background:#f3f4f6;border:1px solid #e5e7eb;border-radius:.375rem;font-size:14px;text-decoration:none;color:#111827;font-weight:500;transition:all .15s ease}.tiptap-editor-wrapper .ProseMirror a[data-attachment=true]::before{content:"📎";font-size:13px;opacity:.7}.tiptap-editor-wrapper .ProseMirror a[data-attachment=true]:hover{background:#e5e7eb;border-color:#d1d5db}.tiptap-editor-wrapper .ProseMirror mark{background-color:#fde047;border-radius:.125rem;padding:.125rem .25rem;color:#854d0e}.tiptap-editor-wrapper .ProseMirror sup{vertical-align:super;font-size:.75em}.tiptap-editor-wrapper .ProseMirror sub{vertical-align:sub;font-size:.75em}.tiptap-editor-wrapper .ProseMirror table{border-collapse:collapse;table-layout:fixed;width:100%;margin:1.5rem 0;overflow:hidden}.tiptap-editor-wrapper .ProseMirror table td,.tiptap-editor-wrapper .ProseMirror table th{min-width:1em;border:1px solid #ced4da;padding:8px 12px;vertical-align:top;box-sizing:border-box;position:relative}.tiptap-editor-wrapper .ProseMirror table td>*,.tiptap-editor-wrapper .ProseMirror table th>*{margin-bottom:0}.tiptap-editor-wrapper .ProseMirror table th{font-weight:bold;text-align:left;background-color:#f8f9fa}.tiptap-editor-wrapper .ProseMirror table .selectedCell:after{z-index:2;position:absolute;content:"";left:0;right:0;top:0;bottom:0;background:rgba(200,200,255,.4);pointer-events:none}.tiptap-editor-wrapper .ProseMirror table .column-resize-handle{position:absolute;right:-2px;top:0;bottom:-2px;width:4px;background-color:#adf;pointer-events:none}.tiptap-editor-wrapper .ProseMirror .tableWrapper{overflow-x:auto;margin:1.5rem 0}.tiptap-editor-wrapper.read-only .tiptap-toolbar{background:#f3f3f3;pointer-events:none}.tiptap-editor-wrapper.read-only .tiptap-toolbar button,.tiptap-editor-wrapper.read-only .tiptap-toolbar .toolbar-select{opacity:.5;filter:grayscale(1)}.tiptap-editor-wrapper.read-only .ProseMirror{background:#f3f3f3;color:#6b7280;cursor:default;min-height:100px}.tiptap-editor-wrapper .tiptap-toolbar.toolbar-disabled{background:#f3f3f3;border-bottom-color:#e5e7eb}.tiptap-editor-wrapper .tiptap-toolbar.toolbar-disabled *{cursor:not-allowed !important}.tiptap-editor-wrapper .tiptap-loading-bar{height:3px;background:linear-gradient(90deg, #0f62fe 0%, #4589ff 50%, #0f62fe 100%);background-size:200% 100%;animation:tiptap-loading-anim 1.2s linear infinite;border-radius:0}@keyframes tiptap-loading-anim{0%{background-position:200% 0}100%{background-position:-200% 0}}.tiptap-hidden-input{display:none !important}
1
+ .tiptap-editor-wrapper{border:1px solid #e5e7eb;border-radius:.75rem;overflow:hidden;font-size:15px;font-family:"Inter",-apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif;background:#fff;box-shadow:0 1px 3px 0 rgba(0,0,0,.05),0 1px 2px -1px rgba(0,0,0,.05)}.tiptap-editor-wrapper .tiptap-toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:.25rem;padding:.35rem .75rem;background:#fff;border-bottom:1px solid #f3f4f6}.tiptap-editor-wrapper .tiptap-toolbar button{display:inline-flex;align-items:center;justify-content:center;width:32px;height:32px;padding:0;border:none;border-radius:.375rem;background:rgba(0,0,0,0);cursor:pointer;color:#4b5563;font-size:14px;font-weight:500;transition:all .15s ease;line-height:1}.tiptap-editor-wrapper .tiptap-toolbar button:hover:not(:disabled){background:#f3f4f6;color:#111827}.tiptap-editor-wrapper .tiptap-toolbar button.is-active{background:#e5e7eb;color:#111827}.tiptap-editor-wrapper .tiptap-toolbar button:disabled{opacity:.4;cursor:not-allowed}.tiptap-editor-wrapper .tiptap-toolbar button.toolbar-button-dropdown{width:30px;padding:0 2px 0 4px;gap:1px}.tiptap-editor-wrapper .tiptap-toolbar button.toolbar-button-dropdown .dropdown-arrow{width:9px;height:9px;opacity:.6;margin-left:-2px}.tiptap-editor-wrapper .tiptap-toolbar button svg{width:18px;height:18px}.tiptap-editor-wrapper .tiptap-toolbar .toolbar-divider{width:1px;height:20px;background:#e5e7eb;margin:0 .5rem;flex-shrink:0}.tiptap-editor-wrapper .tiptap-toolbar .toolbar-select-wrapper{position:relative;display:inline-flex;align-items:center}.tiptap-editor-wrapper .tiptap-toolbar .toolbar-select{appearance:none;height:32px;border:none;border-radius:.375rem;background:rgba(0,0,0,0);font-size:14.5px;cursor:pointer;padding:0 1.5rem 0 .5rem;color:#4b5563;font-family:inherit;font-weight:500;transition:all .15s ease}.tiptap-editor-wrapper .tiptap-toolbar .toolbar-select:hover{background:#f3f4f6;color:#111827}.tiptap-editor-wrapper .tiptap-toolbar .toolbar-select:focus{outline:none;box-shadow:0 0 0 2px rgba(15,98,254,.2)}.tiptap-editor-wrapper .tiptap-toolbar .select-caret{position:absolute;right:.5rem;pointer-events:none;width:16px;height:16px;fill:#6b7280}.tiptap-editor-wrapper .tiptap-highlight-menu{position:absolute;top:110%;left:50%;transform:translateX(-50%);background:#fff;border:1px solid #e5e7eb;border-radius:9999px;padding:4px;display:flex;gap:6px;box-shadow:0 4px 6px -1px rgba(0,0,0,.1),0 2px 4px -1px rgba(0,0,0,.06);z-index:100}.tiptap-editor-wrapper .tiptap-highlight-menu .color-swatch{width:18px !important;height:18px !important;min-width:18px !important;min-height:18px !important;border-radius:50% !important;border:1px solid rgba(0,0,0,.1) !important;cursor:pointer;padding:0 !important;background-color:#fff;display:flex;align-items:center;justify-content:center;transition:transform .1s ease}.tiptap-editor-wrapper .tiptap-highlight-menu .color-swatch:hover{transform:scale(1.2)}.tiptap-editor-wrapper .tiptap-highlight-menu .color-swatch.clear-swatch{background-color:rgba(0,0,0,0) !important;border:1px solid #d1d5db !important}.tiptap-editor-wrapper .tiptap-highlight-menu .color-swatch svg{width:12px;height:12px;color:#6b7280}.tiptap-editor-wrapper .tiptap-font-menu{position:absolute;top:110%;left:0;background:#fff;border:1px solid #e5e7eb;border-radius:8px;padding:4px;box-shadow:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -2px rgba(0,0,0,.05);z-index:100;min-width:180px;max-height:300px;overflow-y:auto}.tiptap-editor-wrapper .tiptap-font-menu .font-option{width:100%;text-align:left;padding:8px 12px;border-radius:4px;background:none;border:none;font-size:14px;color:#374151;cursor:pointer;transition:all .15s ease}.tiptap-editor-wrapper .tiptap-font-menu .font-option:hover:not(.is-active){background:#f3f4f6;color:#111827}.tiptap-editor-wrapper .tiptap-font-menu .font-option.is-active{background:#0062ff;color:#fff;font-weight:500}.tiptap-editor-wrapper .tiptap-heading-menu{position:absolute;top:110%;left:0;background:#fff;border:1px solid #e5e7eb;border-radius:8px;padding:4px;box-shadow:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -2px rgba(0,0,0,.05);z-index:100;min-width:140px}.tiptap-editor-wrapper .tiptap-heading-menu .heading-option{width:100%;text-align:left;padding:6px 12px;border-radius:4px;background:none;border:none;font-size:14px;color:#374151;cursor:pointer;transition:all .15s ease}.tiptap-editor-wrapper .tiptap-heading-menu .heading-option:hover{background:#f3f4f6;color:#111827}.tiptap-editor-wrapper .tiptap-heading-menu .heading-option.is-active{background:#eff6ff;color:#2563eb;font-weight:600}.tiptap-editor-wrapper .tiptap-heading-menu .heading-option.h1{font-size:1.35rem;font-weight:700}.tiptap-editor-wrapper .tiptap-heading-menu .heading-option.h2{font-size:1.25rem;font-weight:600}.tiptap-editor-wrapper .tiptap-heading-menu .heading-option.h3{font-size:1.15rem;font-weight:600}.tiptap-editor-wrapper .tiptap-heading-menu .heading-option.h4{font-size:1.05rem;font-weight:600}.tiptap-editor-wrapper .tiptap-heading-menu .heading-option.h5{font-size:1rem;font-weight:600}.tiptap-editor-wrapper .tiptap-heading-menu .heading-option.h6{font-size:.9rem;font-weight:600}.tiptap-editor-wrapper .tiptap-color-picker{position:absolute;top:110%;left:50%;transform:translateX(-50%);background:#fff;border:1px solid #e5e7eb;border-radius:10px;padding:10px;box-shadow:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -2px rgba(0,0,0,.05);z-index:100;width:160px}.tiptap-editor-wrapper .tiptap-color-picker .color-remove-btn{width:100%;display:flex;align-items:center;justify-content:center;gap:8px;padding:8px;margin-bottom:8px;background:#fdfdfd;border:1px solid #e5e7eb;border-radius:6px;font-size:13px;color:#4b5563;cursor:pointer;transition:all .15s ease}.tiptap-editor-wrapper .tiptap-color-picker .color-remove-btn:hover{background:#f3f4f6;border-color:#d1d5db;color:#111827}.tiptap-editor-wrapper .tiptap-color-picker .color-remove-btn svg{width:14px;height:14px}.tiptap-editor-wrapper .tiptap-color-picker .color-grid{display:grid;grid-template-columns:repeat(5, 1fr);gap:4px}.tiptap-editor-wrapper .tiptap-color-picker .color-grid .color-swatch{width:24px !important;height:24px !important;min-width:24px !important;min-height:24px !important;border-radius:4px !important;border:1px solid rgba(0,0,0,.08) !important;padding:0 !important;cursor:pointer;transition:transform .15s ease,border-color .15s ease}.tiptap-editor-wrapper .tiptap-color-picker .color-grid .color-swatch:hover{transform:scale(1.15);border-color:rgba(0,0,0,.2) !important;z-index:2}.tiptap-editor-wrapper .tiptap-link-menu{position:absolute;top:110%;left:50%;transform:translateX(-50%);background:#fff;border:1px solid #e5e7eb;border-radius:8px;padding:4px;display:flex;align-items:center;gap:2px;box-shadow:0 4px 6px -1px rgba(0,0,0,.1),0 2px 4px -1px rgba(0,0,0,.06);z-index:100;width:300px}.tiptap-editor-wrapper .tiptap-link-menu input{flex:1;border:1px solid #d1d5db;border-radius:4px;padding:4px 8px;font-size:14px;outline:none;transition:border-color .15s ease}.tiptap-editor-wrapper .tiptap-link-menu input:focus{border-color:#3b82f6;box-shadow:0 0 0 1px #3b82f6}.tiptap-editor-wrapper .tiptap-link-menu button{width:28px !important;height:28px !important;padding:0 !important;min-width:28px !important;border-radius:4px !important;display:flex;align-items:center;justify-content:center}.tiptap-editor-wrapper .tiptap-link-menu button svg{width:14px;height:14px}.tiptap-editor-wrapper .tiptap-link-menu button.link-submit-btn{color:#22c55e}.tiptap-editor-wrapper .tiptap-link-menu button.link-submit-btn:hover{background:#dcfce7}.tiptap-editor-wrapper .tiptap-link-menu button.link-clear-btn{color:#ef4444}.tiptap-editor-wrapper .tiptap-link-menu button.link-clear-btn:hover{background:#fee2e2}.tiptap-editor-wrapper .tiptap-table-menu{position:absolute;top:110%;left:0;background:#fff;border:1px solid #e5e7eb;border-radius:8px;padding:8px;box-shadow:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -2px rgba(0,0,0,.05);z-index:100;min-width:200px}.tiptap-editor-wrapper .tiptap-table-menu .table-grid-picker-wrapper{padding:4px;background:#fff}.tiptap-editor-wrapper .tiptap-table-menu .table-grid-picker-wrapper .table-grid-picker{display:flex;flex-direction:column;gap:2px;padding-bottom:8px}.tiptap-editor-wrapper .tiptap-table-menu .table-grid-picker-wrapper .grid-row{display:flex;gap:2px}.tiptap-editor-wrapper .tiptap-table-menu .table-grid-picker-wrapper .grid-cell{width:16px;height:16px;border:1px solid #d1d5db;border-radius:1px;cursor:pointer;transition:background-color .1s,border-color .1s}.tiptap-editor-wrapper .tiptap-table-menu .table-grid-picker-wrapper .grid-cell:hover{border-color:#3b82f6}.tiptap-editor-wrapper .tiptap-table-menu .table-grid-picker-wrapper .grid-cell.is-active{background-color:#bfdbfe;border-color:#3b82f6}.tiptap-editor-wrapper .tiptap-table-menu .table-grid-picker-wrapper .table-grid-label{text-align:center;font-size:13px;color:#4b5563;font-weight:500;border-top:1px solid #f3f4f6;padding-top:8px;margin-top:2px}.tiptap-editor-wrapper .tiptap-table-menu .table-menu-item{width:100%;display:flex;align-items:center;gap:8px;padding:8px 12px;border-radius:4px;background:none;border:none;font-size:13px;color:#374151;transition:background .15s ease;white-space:nowrap;cursor:pointer}.tiptap-editor-wrapper .tiptap-table-menu .table-menu-item:hover{background:#f3f4f6}.tiptap-editor-wrapper .tiptap-table-menu .table-menu-item svg{width:16px;height:16px;color:#6b7280}.tiptap-editor-wrapper .tiptap-table-menu .table-menu-grid{display:grid;grid-template-columns:repeat(3, 1fr);gap:6px}.tiptap-editor-wrapper .tiptap-table-menu .table-menu-grid button{width:32px !important;height:32px !important;padding:0 !important;min-width:32px !important;display:flex;align-items:center;justify-content:center;border-radius:4px;background:#f9fafb !important;border:1px solid #e5e7eb !important;color:#4b5563 !important;cursor:pointer}.tiptap-editor-wrapper .tiptap-table-menu .table-menu-grid button:hover{background:#f3f4f6 !important;border-color:#d1d5db !important}.tiptap-editor-wrapper .tiptap-table-menu .table-menu-grid button.danger{color:#ef4444 !important}.tiptap-editor-wrapper .tiptap-table-menu .table-menu-grid button.danger:hover{background:#fee2e2 !important;border-color:#fca5a5 !important}.tiptap-editor-wrapper .tiptap-table-menu .table-menu-grid button svg{width:16px;height:16px}.tiptap-editor-wrapper .ProseMirror{min-height:300px;padding:1.5rem;color:#1f2937;outline:none;line-height:1.7}.tiptap-editor-wrapper .ProseMirror p.is-editor-empty:first-child::before{color:#9ca3af;content:attr(data-placeholder);float:left;height:0;pointer-events:none}.tiptap-editor-wrapper .ProseMirror h1,.tiptap-editor-wrapper .ProseMirror h2,.tiptap-editor-wrapper .ProseMirror h3,.tiptap-editor-wrapper .ProseMirror h4{line-height:1.2;color:#111827}.tiptap-editor-wrapper .ProseMirror h1{font-size:2.25rem;font-weight:700;margin:1em 0 .5em}.tiptap-editor-wrapper .ProseMirror h2{font-size:1.875rem;font-weight:600;margin:1em 0 .5em}.tiptap-editor-wrapper .ProseMirror h3{font-size:1.5rem;font-weight:600;margin:1em 0 .5em}.tiptap-editor-wrapper .ProseMirror h4{font-size:1.25rem;font-weight:600;margin:1em 0 .5em}.tiptap-editor-wrapper .ProseMirror [style*="font-size: 0.7em"],.tiptap-editor-wrapper .ProseMirror .text-tiny{font-size:.7em}.tiptap-editor-wrapper .ProseMirror [style*="font-size: 0.85em"],.tiptap-editor-wrapper .ProseMirror .text-small{font-size:.85em}.tiptap-editor-wrapper .ProseMirror [style*="font-size: 1.4em"],.tiptap-editor-wrapper .ProseMirror .text-big{font-size:1.4em}.tiptap-editor-wrapper .ProseMirror [style*="font-size: 1.8em"],.tiptap-editor-wrapper .ProseMirror .text-huge{font-size:1.8em}.tiptap-editor-wrapper .ProseMirror p:nth-child(1){margin:0 0}.tiptap-editor-wrapper .ProseMirror p{margin:.5em 0}.tiptap-editor-wrapper .ProseMirror ul{list-style-type:disc;padding-left:1.5rem;margin:.5em 0}.tiptap-editor-wrapper .ProseMirror ol{list-style-type:decimal;padding-left:1.5rem;margin:.5em 0}.tiptap-editor-wrapper .ProseMirror blockquote{border-left:4px solid #e5e7eb;padding-left:1rem;margin:1em 0;color:#4b5563;font-style:italic}.tiptap-editor-wrapper .ProseMirror code{background:#f3f4f6;border-radius:4px;padding:.2rem .4rem;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;font-size:.875em}.tiptap-editor-wrapper .ProseMirror pre{background:#111827;color:#f3f4f6;border-radius:.5rem;padding:1rem;overflow-x:auto;margin:1em 0}.tiptap-editor-wrapper .ProseMirror pre code{background:none;padding:0;color:inherit}.tiptap-editor-wrapper .ProseMirror img{max-width:100%;height:auto;display:block;margin:1rem 0;border-radius:.375rem;box-shadow:0 1px 3px 0 rgba(0,0,0,.1)}.tiptap-editor-wrapper .ProseMirror a{color:#2563eb;text-decoration:underline;text-underline-offset:2px;font-weight:500;cursor:pointer}.tiptap-editor-wrapper .ProseMirror a:hover{color:#1d4ed8}.tiptap-editor-wrapper .ProseMirror a[data-attachment=true]{display:inline-flex;align-items:center;gap:.375rem;padding:.25rem .6rem;background:#f3f4f6;border:1px solid #e5e7eb;border-radius:.375rem;font-size:14px;text-decoration:none;color:#111827;font-weight:500;transition:all .15s ease}.tiptap-editor-wrapper .ProseMirror a[data-attachment=true]::before{content:"📎";font-size:13px;opacity:.7}.tiptap-editor-wrapper .ProseMirror a[data-attachment=true]:hover{background:#e5e7eb;border-color:#d1d5db}.tiptap-editor-wrapper .ProseMirror mark{background-color:#fde047;border-radius:.125rem;padding:.125rem .25rem;color:#854d0e}.tiptap-editor-wrapper .ProseMirror sup{vertical-align:super;font-size:.75em}.tiptap-editor-wrapper .ProseMirror sub{vertical-align:sub;font-size:.75em}.tiptap-editor-wrapper .ProseMirror table{border-collapse:collapse;table-layout:fixed;width:100%;margin:1.5rem 0;overflow:hidden}.tiptap-editor-wrapper .ProseMirror table td,.tiptap-editor-wrapper .ProseMirror table th{min-width:1em;border:1px solid #ced4da;padding:8px 12px;vertical-align:top;box-sizing:border-box;position:relative}.tiptap-editor-wrapper .ProseMirror table td>*,.tiptap-editor-wrapper .ProseMirror table th>*{margin-bottom:0}.tiptap-editor-wrapper .ProseMirror table th{font-weight:bold;text-align:left;background-color:#f8f9fa}.tiptap-editor-wrapper .ProseMirror table .selectedCell:after{z-index:2;position:absolute;content:"";left:0;right:0;top:0;bottom:0;background:rgba(200,200,255,.4);pointer-events:none}.tiptap-editor-wrapper .ProseMirror table .column-resize-handle{position:absolute;right:-2px;top:0;bottom:-2px;width:4px;background-color:#adf;pointer-events:none}.tiptap-editor-wrapper .ProseMirror .tableWrapper{overflow-x:auto;margin:1.5rem 0}.tiptap-editor-wrapper.read-only .tiptap-toolbar{background:#f3f3f3;pointer-events:none}.tiptap-editor-wrapper.read-only .tiptap-toolbar button,.tiptap-editor-wrapper.read-only .tiptap-toolbar .toolbar-select{opacity:.5;filter:grayscale(1)}.tiptap-editor-wrapper.read-only .ProseMirror{background:#f3f3f3;color:#6b7280;cursor:default;min-height:300px}.tiptap-editor-wrapper .tiptap-toolbar.toolbar-disabled{background:#f3f3f3;border-bottom-color:#e5e7eb}.tiptap-editor-wrapper .tiptap-toolbar.toolbar-disabled *{cursor:not-allowed !important}.tiptap-editor-wrapper .tiptap-loading-bar{height:3px;background:linear-gradient(90deg, #0f62fe 0%, #4589ff 50%, #0f62fe 100%);background-size:200% 100%;animation:tiptap-loading-anim 1.2s linear infinite;border-radius:0}@keyframes tiptap-loading-anim{0%{background-position:200% 0}100%{background-position:-200% 0}}.tiptap-hidden-input{display:none !important}
package/dist/index.d.mts CHANGED
@@ -4,7 +4,7 @@ import * as _tiptap_extension_underline from '@tiptap/extension-underline';
4
4
  import * as _tiptap_core from '@tiptap/core';
5
5
  import { Extension } from '@tiptap/core';
6
6
 
7
- type ToolbarGroup = 'history' | 'font' | 'fontSize' | 'textColor' | 'highlight' | 'list' | 'alignment' | 'table' | 'inline' | 'link' | 'insert';
7
+ type ToolbarGroup = 'history' | 'heading' | 'font' | 'fontSize' | 'textColor' | 'highlight' | 'list' | 'alignment' | 'table' | 'inline' | 'link' | 'insert';
8
8
  interface ToolbarConfig {
9
9
  groups?: ToolbarGroup[];
10
10
  showDividers?: boolean;
package/dist/index.d.ts CHANGED
@@ -4,7 +4,7 @@ import * as _tiptap_extension_underline from '@tiptap/extension-underline';
4
4
  import * as _tiptap_core from '@tiptap/core';
5
5
  import { Extension } from '@tiptap/core';
6
6
 
7
- type ToolbarGroup = 'history' | 'font' | 'fontSize' | 'textColor' | 'highlight' | 'list' | 'alignment' | 'table' | 'inline' | 'link' | 'insert';
7
+ type ToolbarGroup = 'history' | 'heading' | 'font' | 'fontSize' | 'textColor' | 'highlight' | 'list' | 'alignment' | 'table' | 'inline' | 'link' | 'insert';
8
8
  interface ToolbarConfig {
9
9
  groups?: ToolbarGroup[];
10
10
  showDividers?: boolean;
package/dist/index.js CHANGED
@@ -398,6 +398,11 @@ var ClearIcon = () => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(LucideSvg, {
398
398
  ] });
399
399
  var SubmitIcon = () => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(LucideSvg, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("polyline", { points: "20 6 9 17 4 12" }) });
400
400
  var AttachIcon = () => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(LucideSvg, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "m21.44 11.05-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.82-2.82l8.49-8.48" }) });
401
+ var HeadingIcon = () => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(LucideSvg, { children: [
402
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M6 12h12" }),
403
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M6 20V4" }),
404
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M18 20V4" })
405
+ ] });
401
406
  var FontSizeIcon = () => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", xmlns: "http://www.w3.org/2000/svg", children: [
402
407
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "m3 7 5-5 5 5" }),
403
408
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M8 2v10" }),
@@ -447,6 +452,51 @@ var HistoryGroup = ({ editor, isReadOnly }) => /* @__PURE__ */ (0, import_jsx_ru
447
452
  }
448
453
  )
449
454
  ] });
455
+ var HeadingGroup = ({ editor, isReadOnly, showMenu, onToggle, onClose }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { position: "relative", display: "inline-flex" }, children: [
456
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
457
+ "button",
458
+ {
459
+ title: "Heading",
460
+ onClick: onToggle,
461
+ onMouseDown: (e) => e.preventDefault(),
462
+ disabled: isReadOnly,
463
+ className: `toolbar-button-dropdown ${showMenu ? "is-active" : ""}`,
464
+ "aria-label": "Heading selection",
465
+ children: [
466
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(HeadingIcon, {}),
467
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { className: "dropdown-arrow", viewBox: "0 0 24 24", width: "10", height: "10", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M7 10l5 5 5-5z", fill: "currentColor" }) })
468
+ ]
469
+ }
470
+ ),
471
+ showMenu && !isReadOnly && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "tiptap-heading-menu", children: [
472
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
473
+ "button",
474
+ {
475
+ className: `heading-option ${!editor.isActive("heading") ? "is-active" : ""}`,
476
+ onClick: () => {
477
+ editor.chain().focus().setParagraph().run();
478
+ onClose();
479
+ },
480
+ children: "Paragraph"
481
+ }
482
+ ),
483
+ [1, 2, 3, 4, 5, 6].map((level) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
484
+ "button",
485
+ {
486
+ className: `heading-option h${level} ${editor.isActive("heading", { level }) ? "is-active" : ""}`,
487
+ onClick: () => {
488
+ editor.chain().focus().toggleHeading({ level }).run();
489
+ onClose();
490
+ },
491
+ children: [
492
+ "Heading ",
493
+ level
494
+ ]
495
+ },
496
+ level
497
+ ))
498
+ ] })
499
+ ] });
450
500
  var FontGroup = ({ editor, isReadOnly, showMenu, onToggle, onClose }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { position: "relative", display: "inline-flex" }, children: [
451
501
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
452
502
  "button",
@@ -622,12 +672,12 @@ var ListGroup = ({ editor, isReadOnly }) => /* @__PURE__ */ (0, import_jsx_runti
622
672
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
623
673
  "button",
624
674
  {
625
- title: "Bullet list",
675
+ title: "Bulleted list",
626
676
  onClick: () => editor.chain().focus().toggleBulletList().run(),
627
677
  onMouseDown: (e) => e.preventDefault(),
628
678
  disabled: isReadOnly,
629
679
  className: editor.isActive("bulletList") ? "is-active" : "",
630
- "aria-label": "Bullet list",
680
+ "aria-label": "Bulleted list",
631
681
  children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(BulletListIcon, {})
632
682
  }
633
683
  ),
@@ -905,6 +955,7 @@ var TiptapEditor = ({
905
955
  const [showTextColorMenu, setShowTextColorMenu] = import_react.default.useState(false);
906
956
  const [showFontMenu, setShowFontMenu] = import_react.default.useState(false);
907
957
  const [showFontSizeMenu, setShowFontSizeMenu] = import_react.default.useState(false);
958
+ const [showHeadingMenu, setShowHeadingMenu] = import_react.default.useState(false);
908
959
  const [showLinkMenu, setShowLinkMenu] = import_react.default.useState(false);
909
960
  const [showTableMenu, setShowTableMenu] = import_react.default.useState(false);
910
961
  const [tableHoverSize, setTableHoverSize] = import_react.default.useState({ rows: 0, cols: 0 });
@@ -918,6 +969,7 @@ var TiptapEditor = ({
918
969
  setShowTextColorMenu(false);
919
970
  setShowFontMenu(false);
920
971
  setShowFontSizeMenu(false);
972
+ setShowHeadingMenu(false);
921
973
  setShowLinkMenu(false);
922
974
  setShowTableMenu(false);
923
975
  }, []);
@@ -1079,7 +1131,7 @@ var TiptapEditor = ({
1079
1131
  editor.chain().focus().run();
1080
1132
  const imagesHtml = uploadResults.map(
1081
1133
  (res) => `<img src="${res.url}" alt="${res.name}" />`
1082
- ).join("&nbsp;");
1134
+ ).join("<br/>");
1083
1135
  editor.chain().insertContent(imagesHtml).run();
1084
1136
  } catch (err) {
1085
1137
  alertFn(err.message || "Image upload failed");
@@ -1129,7 +1181,7 @@ var TiptapEditor = ({
1129
1181
  );
1130
1182
  const attachmentsHtml = uploadResults.map(
1131
1183
  (res) => `<a href="${res.url}" target="_blank" rel="noopener noreferrer" data-attachment="true">${res.name}</a>`
1132
- ).join("&nbsp;");
1184
+ ).join("<br/>");
1133
1185
  editor.chain().focus().insertContent(attachmentsHtml).run();
1134
1186
  } catch (err) {
1135
1187
  alertFn(err.message || "Attachment upload failed");
@@ -1161,7 +1213,13 @@ var TiptapEditor = ({
1161
1213
  editor.chain().focus().extendMarkRange("link").unsetLink().run();
1162
1214
  } else {
1163
1215
  const formattedUrl = /^https?:\/\//.test(linkUrl) ? linkUrl : `https://${linkUrl}`;
1164
- editor.chain().focus().extendMarkRange("link").setLink({ href: formattedUrl }).run();
1216
+ const { from, to } = editor.state.selection;
1217
+ const hasSelection = from !== to;
1218
+ if (hasSelection) {
1219
+ editor.chain().focus().extendMarkRange("link").setLink({ href: formattedUrl }).run();
1220
+ } else {
1221
+ editor.chain().focus().insertContent(`<a href="${formattedUrl}">${linkUrl}</a>`).run();
1222
+ }
1165
1223
  }
1166
1224
  setShowLinkMenu(false);
1167
1225
  }, [editor, linkUrl]);
@@ -1192,6 +1250,7 @@ var TiptapEditor = ({
1192
1250
  ] });
1193
1251
  const defaultGroups = [
1194
1252
  "history",
1253
+ "heading",
1195
1254
  "font",
1196
1255
  "fontSize",
1197
1256
  "textColor",
@@ -1208,6 +1267,20 @@ var TiptapEditor = ({
1208
1267
  const getToolbar = () => {
1209
1268
  const toolbarComponents = {
1210
1269
  history: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(HistoryGroup, { editor, isReadOnly }),
1270
+ heading: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1271
+ HeadingGroup,
1272
+ {
1273
+ editor,
1274
+ isReadOnly,
1275
+ showMenu: showHeadingMenu,
1276
+ onToggle: () => {
1277
+ const nextState = !showHeadingMenu;
1278
+ closeAllMenus();
1279
+ setShowHeadingMenu(nextState);
1280
+ },
1281
+ onClose: () => setShowHeadingMenu(false)
1282
+ }
1283
+ ),
1211
1284
  font: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1212
1285
  FontGroup,
1213
1286
  {