tiptap-extension-izzy-resizable-image 0.1.2 → 0.1.3

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
@@ -75,10 +75,11 @@ const editor = new Editor({
75
75
  showAlignMenu: true,
76
76
  alignMenuPosition: 'below',
77
77
  alignMenuIcons: {
78
- left: '<i class="bi bi-text-left"></i>',
79
- center: '<i class="bi bi-text-center"></i>',
80
- right: '<i class="bi bi-text-right"></i>',
78
+ left: '⟸',
79
+ center: '⇔',
80
+ right: '⟹',
81
81
  clear: 'x',
82
+ preview: '🔍',
82
83
  },
83
84
  };
84
85
  },
@@ -95,7 +96,7 @@ editor.commands.insertResizableImage({ src: 'https://picsum.photos/300/200', wid
95
96
  - `height: number | null` — default height in pixels when node `height` attr is missing.
96
97
  - `showAlignMenu: boolean` — whether the inline alignment menu is shown by default.
97
98
  - `alignMenuPosition: 'above' | 'below'` — where the menu appears relative to the image.
98
- - `alignMenuIcons: { left: string, center: string, right: string, clear: string }` — HTML strings for menu buttons.
99
+ - `alignMenuIcons: { left: string, center: string, right: string, clear: string, preview: string }` — HTML strings for menu buttons.
99
100
 
100
101
  Reference:
101
102
  - Defined in `resizable-image.js:387-394`
@@ -116,8 +117,9 @@ These can be set per-node, overriding options.
116
117
  - `alignMenuPosition: 'above' | 'below' | null`
117
118
  - `iconLeft: string | null` — HTML or text for the left button.
118
119
  - `iconCenter: string | null`
119
- - `iconRight: string | null`
120
- - `iconClear: string | null`
120
+ - `iconRight: string | null`
121
+ - `iconClear: string | null`
122
+ - `iconView: string | null` — HTML or text for the preview (lightbox) button.
121
123
 
122
124
  Reference: `resizable-image.js:358-372`
123
125
 
package/npm/index.js CHANGED
@@ -84,21 +84,25 @@ class ResizableImageView {
84
84
  this.btnCenter = document.createElement('button')
85
85
  this.btnRight = document.createElement('button')
86
86
  this.btnClear = document.createElement('button')
87
+ this.btnView = document.createElement('button')
87
88
 
88
89
  this.btnLeft.innerHTML = (node.attrs.iconLeft != null ? node.attrs.iconLeft : (this.options.alignMenuIcons?.left ?? '⟸'))
89
90
  this.btnCenter.innerHTML = (node.attrs.iconCenter != null ? node.attrs.iconCenter : (this.options.alignMenuIcons?.center ?? '⇔'))
90
91
  this.btnRight.innerHTML = (node.attrs.iconRight != null ? node.attrs.iconRight : (this.options.alignMenuIcons?.right ?? '⟹'))
91
92
  this.btnClear.innerHTML = (node.attrs.iconClear != null ? node.attrs.iconClear : (this.options.alignMenuIcons?.clear ?? 'x'))
93
+ this.btnView.innerHTML = (this.options.alignMenuIcons?.preview ?? '🔍')
92
94
 
93
95
  this.btnLeft.addEventListener('click', () => this.applyAlignAttr('left'))
94
96
  this.btnCenter.addEventListener('click', () => this.applyAlignAttr('center'))
95
97
  this.btnRight.addEventListener('click', () => this.applyAlignAttr('right'))
96
98
  this.btnClear.addEventListener('click', () => this.applyAlignAttr(null))
99
+ this.btnView.addEventListener('click', () => this.openModal())
97
100
 
98
101
  this.menu.appendChild(this.btnLeft)
99
102
  this.menu.appendChild(this.btnCenter)
100
103
  this.menu.appendChild(this.btnRight)
101
104
  this.menu.appendChild(this.btnClear)
105
+ this.menu.appendChild(this.btnView)
102
106
 
103
107
  this.updateMenuPosition(node.attrs.alignMenuPosition != null ? node.attrs.alignMenuPosition : (this.options && this.options.alignMenuPosition != null ? this.options.alignMenuPosition : 'below'))
104
108
 
@@ -111,6 +115,38 @@ class ResizableImageView {
111
115
 
112
116
  this.dragging = null
113
117
  this.applyAlignment(node.attrs.align)
118
+
119
+ this.modalOverlay = document.createElement('div')
120
+ this.modalOverlay.style.position = 'fixed'
121
+ this.modalOverlay.style.inset = '0'
122
+ this.modalOverlay.style.background = 'rgba(0,0,0,0.8)'
123
+ this.modalOverlay.style.display = 'flex'
124
+ this.modalOverlay.style.alignItems = 'center'
125
+ this.modalOverlay.style.justifyContent = 'center'
126
+ this.modalOverlay.style.zIndex = '9999'
127
+ this.modalOverlay.style.cursor = 'zoom-out'
128
+ this.modalImg = document.createElement('img')
129
+ this.modalImg.src = this.img.src
130
+ this.modalImg.style.maxWidth = '90vw'
131
+ this.modalImg.style.maxHeight = '90vh'
132
+ this.modalImg.style.boxShadow = '0 8px 24px rgba(0,0,0,0.5)'
133
+ const modalClose = document.createElement('button')
134
+ modalClose.textContent = '✕'
135
+ modalClose.style.position = 'absolute'
136
+ modalClose.style.top = '16px'
137
+ modalClose.style.right = '16px'
138
+ modalClose.style.background = '#fff'
139
+ modalClose.style.border = 'none'
140
+ modalClose.style.borderRadius = '6px'
141
+ modalClose.style.padding = '6px 8px'
142
+ modalClose.style.cursor = 'pointer'
143
+ this.modalOverlay.appendChild(this.modalImg)
144
+ this.modalOverlay.appendChild(modalClose)
145
+ this.modalOverlay.addEventListener('click', (ev) => {
146
+ if (ev.target === this.modalOverlay) this.closeModal()
147
+ })
148
+ modalClose.addEventListener('click', () => this.closeModal())
149
+
114
150
  }
115
151
 
116
152
  updateMenuPosition(pos) {
@@ -224,6 +260,8 @@ class ResizableImageView {
224
260
  this.btnCenter.innerHTML = (node.attrs.iconCenter != null ? node.attrs.iconCenter : (this.options && this.options.alignMenuIcons ? this.options.alignMenuIcons.center : '⇔'))
225
261
  this.btnRight.innerHTML = (node.attrs.iconRight != null ? node.attrs.iconRight : (this.options && this.options.alignMenuIcons ? this.options.alignMenuIcons.right : '⟹'))
226
262
  this.btnClear.innerHTML = (node.attrs.iconClear != null ? node.attrs.iconClear : (this.options && this.options.alignMenuIcons ? this.options.alignMenuIcons.clear : 'x'))
263
+ if (this.btnView) this.btnView.innerHTML = (this.options && this.options.alignMenuIcons ? this.options.alignMenuIcons.preview : '🔍')
264
+ this.btnView.innerHTML = this.options.iconView ?? '🔍'
227
265
  this.aspect = (node.attrs.height && node.attrs.width) ? node.attrs.width / node.attrs.height : this.aspect
228
266
  return true
229
267
  }
@@ -271,6 +309,15 @@ class ResizableImageView {
271
309
  destroy() {
272
310
  window.removeEventListener('pointermove', this._moveHandler)
273
311
  window.removeEventListener('pointerup', this._upHandler)
312
+ if (this.modalOverlay && this.modalOverlay.parentNode) this.modalOverlay.parentNode.removeChild(this.modalOverlay)
313
+ }
314
+
315
+ openModal() {
316
+ if (!this.modalOverlay.parentNode) document.body.appendChild(this.modalOverlay)
317
+ }
318
+
319
+ closeModal() {
320
+ if (this.modalOverlay && this.modalOverlay.parentNode) this.modalOverlay.parentNode.removeChild(this.modalOverlay)
274
321
  }
275
322
  }
276
323
 
@@ -316,12 +363,7 @@ export const TiptapIzzyExtensionResizableImage = Node.create({
316
363
  height: null,
317
364
  showAlignMenu: true,
318
365
  alignMenuPosition: 'below',
319
- alignMenuIcons: {
320
- left: '<i class="bi bi-text-left"></i>',
321
- center: '<i class="bi bi-text-center"></i>',
322
- right: '<i class="bi bi-text-right"></i>',
323
- clear: 'x'
324
- },
366
+ alignMenuIcons: { left: '⟸', center: '⇔', right: '⟹', clear: 'x', preview: '🔍' },
325
367
  }
326
368
  },
327
369
 
@@ -343,6 +385,7 @@ export const TiptapIzzyExtensionResizableImage = Node.create({
343
385
  iconCenter: this.options.alignMenuIcons?.center,
344
386
  iconRight: this.options.alignMenuIcons?.right,
345
387
  iconClear: this.options.alignMenuIcons?.clear,
388
+ iconView: this.options.alignMenuIcons?.preview,
346
389
  },
347
390
  })
348
391
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tiptap-extension-izzy-resizable-image",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Resizable image NodeView for TipTap v2 with alignment menu and defaults",
5
5
  "license": "MIT",
6
6
  "type": "module",