UNPKG

tiptap-extension-resize-image

Version:

A tiptap image resizing extension for React, Vue, Next, and VanillaJS. Additionally, it can align the image position.

234 lines (175 loc) 7.85 kB
# `tiptap-extension-resize-image` [![npm version](https://img.shields.io/npm/v/tiptap-extension-resize-image.svg)](https://www.npmjs.com/package/tiptap-extension-resize-image) [![npm downloads](https://img.shields.io/npm/dm/tiptap-extension-resize-image.svg)](https://www.npmjs.com/package/tiptap-extension-resize-image) [![license](https://img.shields.io/npm/l/tiptap-extension-resize-image.svg)](https://github.com/bae-sh/tiptap-extension-resize-image/blob/main/LICENSE) [![GitHub stars](https://img.shields.io/github/stars/bae-sh/tiptap-extension-resize-image.svg?style=social)](https://github.com/bae-sh/tiptap-extension-resize-image) ![tiptap-extension-resize-image](https://github.com/bae-sh/tiptap-extension-resize-image/assets/37887690/e79f3d2a-c2df-4506-ac4a-fb71918569b4) [Tiptap](https://tiptap.dev/) is a suite of open source content editing and real-time collaboration tools for developers building apps like Notion or Google Docs. This package provides the ability to adjust the size of the tip tab image. It has been tested in [React](https://codesandbox.io/p/devbox/react-tiptap-image-extension-3ztv5s?file=%2Fsrc%2Ftiptap.tsx%3A5%2C26-5%2C55), [Vue](https://codesandbox.io/p/devbox/vue-tiptap-image-extension-tvxx62?file=%2Fsrc%2FTiptap.vue%3A9%2C1), and [NextJS](https://codesandbox.io/p/devbox/nextjs-tiptap-image-extension-nk6v7p?file=%2Fapp%2Ftiptap.tsx%3A17%2C1), and stability in VanillaJS may not be guaranteed. Additionally, it can align the image position. ## Compatibility | tiptap-extension-resize-image | Supported TipTap Versions | | ----------------------------- | ------------------------- | | ≤ 1.2.2 | v2 only | | ≥ 1.2.3 | v2 and v3 | ## Installation You can install it using npm: ```bash $ npm install tiptap-extension-resize-image ``` ## Usage ```javascript import StarterKit from '@tiptap/starter-kit'; import ImageResize from 'tiptap-extension-resize-image'; import { EditorContent, useEditor } from '@tiptap/react'; const editor = useEditor({ extensions: [StarterKit, ImageResize], content: `<img src="https://source.unsplash.com/8xznAGy4HcY/800x400" />`, }); ``` ### Use as inline If you want to render images as inline elements, you can configure the extension like this: ```javascript const editor = useEditor({ extensions: [ StarterKit, ImageResize.configure({ inline: true, }), ], content: `<img src="..."/>`, }); ``` ### Resize limits You can set minimum and maximum width constraints to limit how small or large images can be resized: ```javascript const editor = useEditor({ extensions: [ StarterKit, ImageResize.configure({ minWidth: 100, // Minimum width in pixels maxWidth: 800, // Maximum width in pixels }), ], content: `<img src="..."/>`, }); ``` Both `minWidth` and `maxWidth` are optional. You can set one, both, or neither: ```javascript // Only set a minimum width ImageResize.configure({ minWidth: 50 }); // Only set a maximum width ImageResize.configure({ maxWidth: 1200 }); // Set both constraints ImageResize.configure({ minWidth: 100, maxWidth: 800 }); ``` ## Options | Option | Type | Default | Description | | ---------- | --------- | ----------- | ----------------------------------------------- | | `inline` | `boolean` | `false` | Render images as inline elements | | `minWidth` | `number` | `undefined` | Minimum width in pixels (cannot resize smaller) | | `maxWidth` | `number` | `undefined` | Maximum width in pixels (cannot resize larger) | <br/> ## Figure with caption `Figure` and `Figcaption` extensions allow you to add a caption to an image. The `Figure` node wraps an image with a `figcaption` element, and provides commands to add, remove, or toggle captions. ```javascript import StarterKit from '@tiptap/starter-kit'; import { ImageResize, Figure, Figcaption } from 'tiptap-extension-resize-image'; const editor = useEditor({ extensions: [StarterKit, ImageResize, Figure, Figcaption], }); ``` ### Commands | Command | Description | | ----------------- | ---------------------------------------------------------- | | `addCaption()` | Converts a selected `imageResize` node to a `figure` node | | `removeCaption()` | Converts a selected `figure` node to an `imageResize` node | | `toggleCaption()` | Toggles between `imageResize` and `figure` node | ```javascript // Add a caption to a selected image editor.commands.addCaption(); // Add a caption with initial text editor.commands.addCaption('My caption'); // Remove a caption from a selected figure editor.commands.removeCaption(); // Toggle between imageResize and figure editor.commands.toggleCaption(); ``` ### Captions are not available in inline mode When `ImageResize` is configured with `inline: true`, the image becomes an inline node that lives inside paragraphs (or other inline containers). A `figure`, on the other hand, is a block-level node by HTML spec and cannot be nested inside such inline containers without breaking the document structure. For this reason, `addCaption()` (and `toggleCaption()` when the current node is an inline image) will return `false` and do nothing in this case. You can use this return value to disable the caption button in your UI: ```javascript <button onClick={() => editor.chain().focus().addCaption().run()} disabled={!editor.can().addCaption()} > Add Caption </button> ``` If you need both inline images and captions in the same editor, configure `ImageResize` without `inline` (the default) so that all images are block nodes and can be converted into a `figure` with a caption. ### Additional Setup Figcaption placeholders are displayed with the help of CSS. Add the following styles to your project. You can customize these styles to match your design: ```css /* Basic figcaption styles */ figcaption { text-align: left; font-size: 0.875rem; color: #666; } /* Placeholder styles - displayed when figcaption is empty */ /* Uses the data-placeholder attribute set by the Figcaption extension */ figcaption.is-empty::before { color: #adb5bd; content: attr(data-placeholder); float: left; height: 0; pointer-events: none; } ``` ### Figcaption Options | Option | Type | Default | Description | | ------------- | -------- | ---------------------- | ---------------------------------- | | `placeholder` | `string` | `'Write a caption...'` | Placeholder text for empty caption | ```javascript Figcaption.configure({ placeholder: 'placeholder text as you want', }); ``` ### Tiptap v3 Notice In Tiptap v3, `shouldRerenderOnTransaction` defaults to `false`, which means components won't automatically re-render on editor state changes. To reactively update button states (e.g., `disabled`), use one of the following approaches: **Option 1: Enable `shouldRerenderOnTransaction`** ```javascript const editor = useEditor({ shouldRerenderOnTransaction: true, extensions: [...], }); // Now you can use editor.can() directly <button onClick={() => editor.commands.addCaption()} disabled={!editor.can().addCaption()} > Add Caption </button> ``` **Option 2: Use `useEditorState` (recommended)** ```javascript import { useEditorState } from '@tiptap/react'; const { canAddCaption, canRemoveCaption } = useEditorState({ editor, selector: (ctx) => ({ canAddCaption: ctx.editor.can().addCaption(), }), }); <button onClick={() => editor.commands.addCaption()} disabled={!canAddCaption}> Add Caption </button>; ``` ## Contributing Contributions are welcome! Please read our [Contributing Guide](./CONTRIBUTING.md) before submitting a Pull Request.