tiptap-extension-izzy-resizable-image 0.1.13 → 0.1.15

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.
Files changed (3) hide show
  1. package/README.md +210 -203
  2. package/npm/index.js +843 -649
  3. package/package.json +38 -38
package/README.md CHANGED
@@ -1,203 +1,210 @@
1
- # TipTap Izzy Extension: Resizable Image
2
-
3
- Resizable inline image node for TipTap v2 with eight resize handles, optional alignment menu, drag-and-drop, and sensible defaults via `.extend()`.
4
-
5
- Demo: https://startinn.github.io/TipTap-Extension-Izzy-Resizable-Image/
6
-
7
- Download: https://www.npmjs.com/package/tiptap-extension-izzy-resizable-image
8
-
9
- ## Features
10
-
11
- - Inline resizable image with 8 handles (nw, n, ne, e, se, s, sw, w)
12
- - Drag-and-drop repositioning using browser native drag
13
- - Optional inline alignment menu (left, center, right, clear)
14
- - Menu position configurable (`above` or `below`)
15
- - Keeps aspect ratio while resizing
16
- - Menu icons accept HTML strings (e.g., `<i class="...">`)
17
- - Deselects image and hides UI when clicking outside
18
-
19
- ## Installation
20
-
21
- This demo loads TipTap and the extension via ESM in the browser. Include `resizable-image.js` next to your HTML file and import it.
22
-
23
- ```html
24
- <script type="module">
25
- import { Editor } from 'https://esm.sh/@tiptap/core@2';
26
- import StarterKit from 'https://esm.sh/@tiptap/starter-kit@2';
27
- import { TiptapIzzyExtensionResizableImage } from './resizable-image.js';
28
- // ...
29
- </script>
30
- ```
31
-
32
- ## Quick Start
33
-
34
- ```js
35
- const editor = new Editor({
36
- element: document.querySelector('#editor'),
37
- extensions: [StarterKit, TiptapIzzyExtensionResizableImage],
38
- });
39
-
40
- // Insert an image
41
- editor.commands.insertResizableImage({ src: 'https://picsum.photos/300/200', width: 300, height: 200 });
42
-
43
- // Align the selected image
44
- editor.commands.setResizableImageAlignment('center');
45
- ```
46
-
47
- ### Using from npm (bundler)
48
-
49
- ```bash
50
- npm install tiptap-extension-izzy-resizable-image @tiptap/core@^3 prosemirror-state
51
- ```
52
-
53
- ```js
54
- import { Editor } from '@tiptap/core';
55
- import StarterKit from '@tiptap/starter-kit';
56
- import { TiptapIzzyExtensionResizableImage } from 'tiptap-extension-izzy-resizable-image';
57
-
58
- const editor = new Editor({
59
- element: document.querySelector('#editor'),
60
- extensions: [StarterKit, TiptapIzzyExtensionResizableImage],
61
- });
62
- ```
63
-
64
- ## Defaults via `.extend()`
65
-
66
- You can set extension-wide defaults using `.extend()` to override `addOptions()`.
67
-
68
- ```js
69
- const editor = new Editor({
70
- element: document.querySelector('#editor'),
71
- extensions: [
72
- StarterKit,
73
- TiptapIzzyExtensionResizableImage.extend({
74
- addOptions() {
75
- return {
76
- height: 200,
77
- showAlignMenu: true,
78
- alignMenuPosition: 'below',
79
- alignMenuIcons: {
80
- left: '⟸',
81
- center: '⇔',
82
- right: '⟹',
83
- clear: 'x',
84
- preview: '🔍',
85
- },
86
- alignMenuButtonsHide: {
87
- // hide specific buttons if true
88
- // left: true,
89
- // right: true,
90
- // center: true,
91
- // clear: true,
92
- // preview: true,
93
- // size50: true,
94
- // size100: true,
95
- },
96
- fitToContainerSelector: '.tiptap',
97
- autoFitWhenOversized: true,
98
- maxAllowedWidth: null,
99
- };
100
- },
101
- }),
102
- ],
103
- });
104
-
105
- // With defaults set, you can omit height/menu attrs in insert:
106
- editor.commands.insertResizableImage({ src: 'https://picsum.photos/300/200', width: 300 });
107
- ```
108
-
109
- ## Options (via `.extend()`)
110
-
111
- - `height: number | null` — default height in pixels when node `height` attr is missing.
112
- - `showAlignMenu: boolean` — whether the inline alignment menu is shown by default.
113
- - `alignMenuPosition: 'above' | 'below'` — where the menu appears relative to the image.
114
- - `alignMenuIcons: { left: string, center: string, right: string, clear: string, preview: string }` — HTML strings for menu buttons.
115
- - `alignMenuButtonsHide: Record<string, boolean>` — hide specific buttons when `true` (supports `left`, `center`, `right`, `clear`, `preview`, `size50`, `size100`).
116
- - `fitToContainerSelector: string` — CSS selector used as width reference for the initial image fit (default: `.tiptap`).
117
- - `autoFitWhenOversized: boolean` — when `true`, oversized images inserted without explicit width are automatically set to `width: 100%` and `height: auto` (default: `true`).
118
- - `maxAllowedWidth: number | null` — maximum allowed width in pixels. If image width exceeds this value, it is forced to `width: 100%` and `height: auto`.
119
-
120
- Reference:
121
- - Defined in `resizable-image.js:387-394`
122
- - Passed into the NodeView in `resizable-image.js:383-385`
123
- - Used for insertion defaults in `resizable-image.js:402-414`
124
-
125
- ## Node Attributes
126
-
127
- These can be set per-node, overriding options.
128
-
129
- - `src: string` — image URL.
130
- - `alt: string | null`
131
- - `title: string | null`
132
- - `width: number | null` — width in px.
133
- - `height: number | null` — height in px.
134
- - `id: string | null` — applied to the `<img>` element.
135
- - `class: string | null` — applied to the `<img>` element.
136
- - `align: 'left' | 'center' | 'right' | null` — alignment.
137
- - `showAlignMenu: boolean | null` — show/hide menu per node.
138
- - `alignMenuPosition: 'above' | 'below' | null`
139
- - `iconLeft: string | null` — HTML or text for the left button.
140
- - `iconCenter: string | null`
141
- - `iconRight: string | null`
142
- - `iconClear: string | null`
143
- - `iconView: string | null` — HTML or text for the preview (lightbox) button.
144
-
145
- Reference: `resizable-image.js:358-372`
146
-
147
- ## Commands
148
-
149
- - `insertResizableImage({ src, alt, title, width, height, id, class })`
150
- - Inserts the resizable image node. Missing attrs fall back to options (e.g., `height`).
151
- - Reference: `resizable-image.js:398-416`
152
-
153
- - `setResizableImageAlignment(align)`
154
- - Sets `align` on the currently selected image node.
155
- - Reference: `resizable-image.js:417-433`
156
-
157
- ## Keyboard Shortcuts
158
-
159
- - `Enter` when an image is selected inserts a paragraph after it and moves the cursor there.
160
- - Reference: `resizable-image.js:412-431`
161
-
162
- ## Alignment Behavior
163
-
164
- - Alignment is applied via `text-align` on the wrapper and toggling wrapper display.
165
- - `left | center | right` set `text-align` accordingly; unaligned flows inline.
166
- - Reference: `resizable-image.js:172-193`
167
-
168
- ## Resizing Behavior
169
-
170
- - Eight handles adjust width/height; aspect ratio is preserved by default.
171
- - Live preview updates `style.width`/`style.height`; final size is persisted to node attrs on pointerup.
172
- - Reference: `resizable-image.js:195-271`
173
-
174
- ## Selection and Focus
175
-
176
- - Menu and handles overlay appear only when the image node is selected.
177
- - Clicking outside the image deselects it and hides menu/overlay.
178
- - Reference: show/hide logic `resizable-image.js:302-321`, `resizable-image.js:324-334`; outside-click handling `resizable-image.js:456-483`.
179
-
180
- ## HTML Icons
181
-
182
- - Menu buttons render using `innerHTML`, allowing HTML strings for icons or rich content.
183
- - Use trusted sources; avoid unsanitized user input to prevent XSS.
184
- - Reference: `resizable-image.js:120-123` and `resizable-image.js:291-294`.
185
-
186
- ## Demo Hooks
187
-
188
- - Example toolbar integration in the demo (`index.html:37-73`) shows inserting images and alignment controls.
189
-
190
- ## Notes
191
-
192
- - The extension is inline and draggable; selection toggles menu/handles.
193
- - Deselecting removes the overlay/menu from the DOM to keep markup clean.
194
- ### Example with `id` and `class`
195
-
196
- ```js
197
- editor.commands.insertResizableImage({
198
- src: 'https://picsum.photos/300/200',
199
- width: 300,
200
- id: 'hero-image',
201
- class: 'rounded shadow'
202
- });
203
- ```
1
+ # TipTap Izzy Extension: Resizable Image
2
+
3
+ Resizable inline image node for TipTap v2 with eight resize handles, optional alignment menu, drag-and-drop, and sensible defaults via `.extend()`.
4
+
5
+ Demo: https://startinn.github.io/TipTap-Extension-Izzy-Resizable-Image/
6
+
7
+ Download: https://www.npmjs.com/package/tiptap-extension-izzy-resizable-image
8
+
9
+ ## Features
10
+
11
+ - Inline resizable image with 8 handles (nw, n, ne, e, se, s, sw, w)
12
+ - Drag-and-drop repositioning using browser native drag
13
+ - Optional inline alignment menu (left, center, right, clear)
14
+ - Menu position configurable (`above` or `below`)
15
+ - Keeps aspect ratio while resizing
16
+ - Preview modal supports mouse-wheel zoom from 0.25x to 4x
17
+ - Copies the image as PNG or copies its URL from the alignment menu
18
+ - Menu icons accept HTML strings (e.g., `<i class="...">`)
19
+ - Deselects image and hides UI when clicking outside
20
+
21
+ ## Installation
22
+
23
+ This demo loads TipTap and the extension via ESM in the browser. Include `resizable-image.js` next to your HTML file and import it.
24
+
25
+ ```html
26
+ <script type="module">
27
+ import { Editor } from 'https://esm.sh/@tiptap/core@2';
28
+ import StarterKit from 'https://esm.sh/@tiptap/starter-kit@2';
29
+ import { TiptapIzzyExtensionResizableImage } from './resizable-image.js';
30
+ // ...
31
+ </script>
32
+ ```
33
+
34
+ ## Quick Start
35
+
36
+ ```js
37
+ const editor = new Editor({
38
+ element: document.querySelector('#editor'),
39
+ extensions: [StarterKit, TiptapIzzyExtensionResizableImage],
40
+ });
41
+
42
+ // Insert an image
43
+ editor.commands.insertResizableImage({ src: 'https://picsum.photos/300/200', width: 300, height: 200 });
44
+
45
+ // Align the selected image
46
+ editor.commands.setResizableImageAlignment('center');
47
+ ```
48
+
49
+ ### Using from npm (bundler)
50
+
51
+ ```bash
52
+ npm install tiptap-extension-izzy-resizable-image @tiptap/core@^3 prosemirror-state
53
+ ```
54
+
55
+ ```js
56
+ import { Editor } from '@tiptap/core';
57
+ import StarterKit from '@tiptap/starter-kit';
58
+ import { TiptapIzzyExtensionResizableImage } from 'tiptap-extension-izzy-resizable-image';
59
+
60
+ const editor = new Editor({
61
+ element: document.querySelector('#editor'),
62
+ extensions: [StarterKit, TiptapIzzyExtensionResizableImage],
63
+ });
64
+ ```
65
+
66
+ ## Defaults via `.extend()`
67
+
68
+ You can set extension-wide defaults using `.extend()` to override `addOptions()`.
69
+
70
+ ```js
71
+ const editor = new Editor({
72
+ element: document.querySelector('#editor'),
73
+ extensions: [
74
+ StarterKit,
75
+ TiptapIzzyExtensionResizableImage.extend({
76
+ addOptions() {
77
+ return {
78
+ height: 200,
79
+ showAlignMenu: true,
80
+ alignMenuPosition: 'below',
81
+ alignMenuIcons: {
82
+ left: '⟸',
83
+ center: '⇔',
84
+ right: '⟹',
85
+ clear: 'x',
86
+ preview: '🔍',
87
+ },
88
+ alignMenuOrder: ['left', 'center', 'right', 'clear', 'preview', 'size50', 'size100', 'copy', 'copyUrl'],
89
+ alignMenuButtonsHide: {
90
+ // hide specific buttons if true
91
+ // left: true,
92
+ // right: true,
93
+ // center: true,
94
+ // clear: true,
95
+ // preview: true,
96
+ // size50: true,
97
+ // size100: true,
98
+ },
99
+ fitToContainerSelector: '.tiptap',
100
+ autoFitWhenOversized: true,
101
+ maxAllowedWidth: null,
102
+ };
103
+ },
104
+ }),
105
+ ],
106
+ });
107
+
108
+ // With defaults set, you can omit height/menu attrs in insert:
109
+ editor.commands.insertResizableImage({ src: 'https://picsum.photos/300/200', width: 300 });
110
+ ```
111
+
112
+ ## Options (via `.extend()`)
113
+
114
+ - `height: number | null` — default height in pixels when node `height` attr is missing.
115
+ - `showAlignMenu: boolean` — whether the inline alignment menu is shown by default.
116
+ - `alignMenuPosition: 'above' | 'below'` — where the menu appears relative to the image.
117
+ - `alignMenuIcons: { left: string, center: string, right: string, clear: string, preview: string, copy: string, copyUrl: string, copied: string, copyError: string }` — HTML strings for menu buttons. `copied` and `copyError` are shown for 3 seconds after a copy succeeds or fails.
118
+ - `alignMenuLabels: Record<string, string>` — overrides the English tooltip and `aria-label` texts, merged over the defaults (supports `left`, `center`, `right`, `clear`, `preview`, `size50`, `size100`, `copy`, `copyUrl`, `copied`, `copyFailed`, `urlCopied`, `urlCopyFailed`).
119
+ - `alignMenuOrder: string[]` — order of buttons in the alignment menu (default: `['left', 'center', 'right', 'clear', 'preview', 'size50', 'size100', 'copy', 'copyUrl']`). Buttons are displayed in the order specified.
120
+ - `alignMenuButtonsHide: Record<string, boolean>` — hide specific buttons when `true` (supports `left`, `center`, `right`, `clear`, `preview`, `size50`, `size100`, `copy`, `copyUrl`).
121
+ - `fitToContainerSelector: string` — CSS selector used as width reference for the initial image fit (default: `.tiptap`).
122
+ - `autoFitWhenOversized: boolean` — when `true`, oversized images inserted without explicit width are automatically set to `width: 100%` and `height: auto` (default: `true`).
123
+ - `maxAllowedWidth: number | null` — maximum allowed width in pixels. If image width exceeds this value, it is forced to `width: 100%` and `height: auto`.
124
+
125
+ Clipboard operations require a secure context. Copying an image writes PNG and requires its host to allow cross-origin fetches (CORS).
126
+
127
+ Reference:
128
+ - Defined in `resizable-image.js:387-394`
129
+ - Passed into the NodeView in `resizable-image.js:383-385`
130
+ - Used for insertion defaults in `resizable-image.js:402-414`
131
+
132
+ ## Node Attributes
133
+
134
+ These can be set per-node, overriding options.
135
+
136
+ - `src: string` — image URL.
137
+ - `alt: string | null`
138
+ - `title: string | null`
139
+ - `width: number | null` — width in px.
140
+ - `height: number | null` — height in px.
141
+ - `id: string | null` — applied to the `<img>` element.
142
+ - `class: string | null` — applied to the `<img>` element.
143
+ - `align: 'left' | 'center' | 'right' | null` — alignment.
144
+ - `showAlignMenu: boolean | null` — show/hide menu per node.
145
+ - `alignMenuPosition: 'above' | 'below' | null`
146
+ - `iconLeft: string | null` — HTML or text for the left button.
147
+ - `iconCenter: string | null`
148
+ - `iconRight: string | null`
149
+ - `iconClear: string | null`
150
+ - `iconView: string | null` — HTML or text for the preview (lightbox) button.
151
+
152
+ Reference: `resizable-image.js:358-372`
153
+
154
+ ## Commands
155
+
156
+ - `insertResizableImage({ src, alt, title, width, height, id, class })`
157
+ - Inserts the resizable image node. Missing attrs fall back to options (e.g., `height`).
158
+ - Reference: `resizable-image.js:398-416`
159
+
160
+ - `setResizableImageAlignment(align)`
161
+ - Sets `align` on the currently selected image node.
162
+ - Reference: `resizable-image.js:417-433`
163
+
164
+ ## Keyboard Shortcuts
165
+
166
+ - `Enter` when an image is selected inserts a paragraph after it and moves the cursor there.
167
+ - Reference: `resizable-image.js:412-431`
168
+
169
+ ## Alignment Behavior
170
+
171
+ - Alignment is applied via `text-align` on the wrapper and toggling wrapper display.
172
+ - `left | center | right` set `text-align` accordingly; unaligned flows inline.
173
+ - Reference: `resizable-image.js:172-193`
174
+
175
+ ## Resizing Behavior
176
+
177
+ - Eight handles adjust width/height; aspect ratio is preserved by default.
178
+ - Live preview updates `style.width`/`style.height`; final size is persisted to node attrs on pointerup.
179
+ - Reference: `resizable-image.js:195-271`
180
+
181
+ ## Selection and Focus
182
+
183
+ - Menu and handles overlay appear only when the image node is selected.
184
+ - Clicking outside the image deselects it and hides menu/overlay.
185
+ - Reference: show/hide logic `resizable-image.js:302-321`, `resizable-image.js:324-334`; outside-click handling `resizable-image.js:456-483`.
186
+
187
+ ## HTML Icons
188
+
189
+ - Menu buttons render using `innerHTML`, allowing HTML strings for icons or rich content.
190
+ - Use trusted sources; avoid unsanitized user input to prevent XSS.
191
+ - Reference: `resizable-image.js:120-123` and `resizable-image.js:291-294`.
192
+
193
+ ## Demo Hooks
194
+
195
+ - Example toolbar integration in the demo (`index.html:37-73`) shows inserting images and alignment controls.
196
+
197
+ ## Notes
198
+
199
+ - The extension is inline and draggable; selection toggles menu/handles.
200
+ - Deselecting removes the overlay/menu from the DOM to keep markup clean.
201
+ ### Example with `id` and `class`
202
+
203
+ ```js
204
+ editor.commands.insertResizableImage({
205
+ src: 'https://picsum.photos/300/200',
206
+ width: 300,
207
+ id: 'hero-image',
208
+ class: 'rounded shadow'
209
+ });
210
+ ```