@haklex/rich-renderer-image 0.22.0 → 0.23.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.
@@ -1 +1 @@
1
- {"version":3,"file":"ImageEditContext.d.ts","sourceRoot":"","sources":["../src/ImageEditContext.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAExE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAoBvC,wBAAgB,iBAAiB,CAAC,EAChC,KAAK,EACL,QAAQ,GACT,EAAE;IACD,KAAK,EAAE,kBAAkB,CAAC;IAC1B,QAAQ,EAAE,SAAS,CAAC;CACrB,2CAsDA"}
1
+ {"version":3,"file":"ImageEditContext.d.ts","sourceRoot":"","sources":["../src/ImageEditContext.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAExE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAsBvC,wBAAgB,iBAAiB,CAAC,EAChC,KAAK,EACL,QAAQ,GACT,EAAE;IACD,KAAK,EAAE,kBAAkB,CAAC;IAC1B,QAAQ,EAAE,SAAS,CAAC;CACrB,2CA4DA"}
@@ -1 +1 @@
1
- {"version":3,"file":"ImageEditRenderer.d.ts","sourceRoot":"","sources":["../src/ImageEditRenderer.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAgCxE,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,kBAAkB,2CAQ1D"}
1
+ {"version":3,"file":"ImageEditRenderer.d.ts","sourceRoot":"","sources":["../src/ImageEditRenderer.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAoCxE,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,kBAAkB,2CAQ1D"}
@@ -1 +1 @@
1
- {"version":3,"file":"ImageEditToolbar.d.ts","sourceRoot":"","sources":["../src/ImageEditToolbar.tsx"],"names":[],"mappings":"AAyBA,wBAAgB,gBAAgB,4CA0J/B"}
1
+ {"version":3,"file":"ImageEditToolbar.d.ts","sourceRoot":"","sources":["../src/ImageEditToolbar.tsx"],"names":[],"mappings":"AA0BA,wBAAgB,gBAAgB,4CA6J/B"}
@@ -0,0 +1,3 @@
1
+ export declare function ImageSizeControl(): import("react/jsx-runtime").JSX.Element;
2
+ export declare function ImageLayoutControl(): import("react/jsx-runtime").JSX.Element;
3
+ //# sourceMappingURL=ImageLayoutControls.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ImageLayoutControls.d.ts","sourceRoot":"","sources":["../src/ImageLayoutControls.tsx"],"names":[],"mappings":"AAkCA,wBAAgB,gBAAgB,4CAyC/B;AAED,wBAAgB,kBAAkB,4CAmCjC"}
@@ -25,7 +25,8 @@ var semanticClassNames = {
25
25
  editInput: "rr-image-edit-input",
26
26
  replaceUploadArea: "rr-image-replace-upload-area",
27
27
  replacePreview: "rr-image-replace-preview",
28
- panelHint: "rr-image-panel-hint"
28
+ panelHint: "rr-image-panel-hint",
29
+ resizeHandle: "rr-image-resize-handle"
29
30
  };
30
31
  var root = "_1n94osf0";
31
32
  var image = "_1n94osf2";
@@ -54,6 +55,13 @@ var editInput = "_1n94osfu";
54
55
  var replaceUploadArea = "_1n94osfv";
55
56
  var replacePreview = "_1n94osfw";
56
57
  var panelHint = "_1n94osfx";
58
+ var resizeHandle = "_1n94osfy";
59
+ var resizeHandleLeft = "_1n94osfz";
60
+ var resizeHandleRight = "_1n94osf10";
61
+ var resizeHandleVisible = "_1n94osf11";
62
+ var controlPanel = "_1n94osf12";
63
+ var sizeOption = "_1n94osf13";
64
+ var editToolbarButtonActive = "_1n94osf14";
57
65
  //#endregion
58
66
  //#region src/ImageRenderer.tsx
59
67
  var frameStateSemanticClass = {
@@ -66,7 +74,7 @@ function getCaptionText(altText, caption) {
66
74
  if (!altText) return void 0;
67
75
  if (altText.startsWith("!") || altText.startsWith("¡")) return altText.slice(1);
68
76
  }
69
- function ImageRenderer({ src, altText, width, height, caption: caption$1, thumbhash, accent, onActivate, ref }) {
77
+ function ImageRenderer({ src, altText, width, height, caption: caption$1, thumbhash, accent, displayWidth, layout, onActivate, ref }) {
70
78
  const [state, setState] = useState("loading");
71
79
  const imgRef = useRef(null);
72
80
  const captionText = useMemo(() => getCaptionText(altText, caption$1), [altText, caption$1]);
@@ -89,9 +97,12 @@ function ImageRenderer({ src, altText, width, height, caption: caption$1, thumbh
89
97
  e.preventDefault();
90
98
  activate();
91
99
  };
100
+ const figureStyle = displayWidth ? { "--rich-image-display-width": `${displayWidth}%` } : void 0;
92
101
  return /* @__PURE__ */ jsxs("figure", {
93
102
  className: `${root} ${semanticClassNames.root}`,
103
+ "data-layout": layout,
94
104
  ref,
105
+ style: figureStyle,
95
106
  children: [/* @__PURE__ */ jsxs("div", {
96
107
  "aria-label": interactive ? `Open image: ${altText || "image"}` : void 0,
97
108
  className: `${frame} ${interactive ? "" : frameStatic} ${semanticClassNames.frame} ${imageState[state]} ${frameStateSemanticClass[state]}`.trim(),
@@ -130,4 +141,4 @@ function ImageRenderer({ src, altText, width, height, caption: caption$1, thumbh
130
141
  });
131
142
  }
132
143
  //#endregion
133
- export { root as C, replaceUploadArea as S, imageState as _, editInput as a, panelHint as b, editToolbar as c, editToolbarVisible as d, editTrigger as f, image as g, frameEditMode as h, editFieldIcon as i, editToolbarButton as l, frame as m, caption as n, editPanel as o, errorBadge as p, editField as r, editPlaceholder as s, ImageRenderer as t, editToolbarButtonDanger as u, imageVisible as v, semanticClassNames as w, replacePreview as x, loader as y };
144
+ export { semanticClassNames as A, replacePreview as C, resizeHandleRight as D, resizeHandleLeft as E, resizeHandleVisible as O, panelHint as S, resizeHandle as T, frameEditMode as _, editFieldIcon as a, imageVisible as b, editPlaceholder as c, editToolbarButtonActive as d, editToolbarButtonDanger as f, frame as g, errorBadge as h, editField as i, sizeOption as j, root as k, editToolbar as l, editTrigger as m, caption as n, editInput as o, editToolbarVisible as p, controlPanel as r, editPanel as s, ImageRenderer as t, editToolbarButton as u, image as v, replaceUploadArea as w, loader as x, imageState as y };
@@ -4,5 +4,5 @@ export interface ImageRendererInteractiveProps extends ImageRendererProps {
4
4
  onActivate?: (target: HTMLElement) => void;
5
5
  ref?: Ref<HTMLElement>;
6
6
  }
7
- export declare function ImageRenderer({ src, altText, width, height, caption, thumbhash, accent, onActivate, ref, }: ImageRendererInteractiveProps): import("react/jsx-runtime").JSX.Element | null;
7
+ export declare function ImageRenderer({ src, altText, width, height, caption, thumbhash, accent, displayWidth, layout, onActivate, ref, }: ImageRendererInteractiveProps): import("react/jsx-runtime").JSX.Element | null;
8
8
  //# sourceMappingURL=ImageRenderer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ImageRenderer.d.ts","sourceRoot":"","sources":["../src/ImageRenderer.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAmB,KAAK,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAEzF,OAAO,KAAK,EAAgC,GAAG,EAAE,MAAM,OAAO,CAAC;AAsB/D,MAAM,WAAW,6BAA8B,SAAQ,kBAAkB;IACvE,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,IAAI,CAAC;IAC3C,GAAG,CAAC,EAAE,GAAG,CAAC,WAAW,CAAC,CAAC;CACxB;AAED,wBAAgB,aAAa,CAAC,EAC5B,GAAG,EACH,OAAO,EACP,KAAK,EACL,MAAM,EACN,OAAO,EACP,SAAS,EACT,MAAM,EACN,UAAU,EACV,GAAG,GACJ,EAAE,6BAA6B,kDA8E/B"}
1
+ {"version":3,"file":"ImageRenderer.d.ts","sourceRoot":"","sources":["../src/ImageRenderer.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAmB,KAAK,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAEzF,OAAO,KAAK,EAAgC,GAAG,EAAE,MAAM,OAAO,CAAC;AAsB/D,MAAM,WAAW,6BAA8B,SAAQ,kBAAkB;IACvE,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,IAAI,CAAC;IAC3C,GAAG,CAAC,EAAE,GAAG,CAAC,WAAW,CAAC,CAAC;CACxB;AAED,wBAAgB,aAAa,CAAC,EAC5B,GAAG,EACH,OAAO,EACP,KAAK,EACL,MAAM,EACN,OAAO,EACP,SAAS,EACT,MAAM,EACN,YAAY,EACZ,MAAM,EACN,UAAU,EACV,GAAG,GACJ,EAAE,6BAA6B,kDAuF/B"}
@@ -0,0 +1,2 @@
1
+ export declare function ResizeHandles(): import("react/jsx-runtime").JSX.Element;
2
+ //# sourceMappingURL=ResizeHandles.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ResizeHandles.d.ts","sourceRoot":"","sources":["../src/ResizeHandles.tsx"],"names":[],"mappings":"AAMA,wBAAgB,aAAa,4CAiB5B"}
package/dist/atoms.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { ImageLayout } from '@haklex/rich-editor/nodes';
1
2
  import { CSSProperties, RefObject } from 'react';
2
3
  export type ImageLoadState = 'loading' | 'loaded' | 'error';
3
4
  export type ReplaceMode = 'upload' | 'url';
@@ -22,6 +23,12 @@ export declare const thumbhashAtom: import('jotai').PrimitiveAtom<string | undef
22
23
  export declare const accentAtom: import('jotai').PrimitiveAtom<string | undefined> & {
23
24
  init: string | undefined;
24
25
  };
26
+ export declare const displayWidthAtom: import('jotai').PrimitiveAtom<number | undefined> & {
27
+ init: number | undefined;
28
+ };
29
+ export declare const layoutAtom: import('jotai').PrimitiveAtom<ImageLayout | undefined> & {
30
+ init: ImageLayout | undefined;
31
+ };
25
32
  export declare const loadStateAtom: import('jotai').PrimitiveAtom<ImageLoadState> & {
26
33
  init: ImageLoadState;
27
34
  };
@@ -34,6 +41,15 @@ export declare const metaOpenAtom: import('jotai').PrimitiveAtom<boolean> & {
34
41
  export declare const replaceOpenAtom: import('jotai').PrimitiveAtom<boolean> & {
35
42
  init: boolean;
36
43
  };
44
+ export declare const sizeOpenAtom: import('jotai').PrimitiveAtom<boolean> & {
45
+ init: boolean;
46
+ };
47
+ export declare const layoutOpenAtom: import('jotai').PrimitiveAtom<boolean> & {
48
+ init: boolean;
49
+ };
50
+ export declare const resizingAtom: import('jotai').PrimitiveAtom<boolean> & {
51
+ init: boolean;
52
+ };
37
53
  export declare const toolbarVisibleAtom: import('jotai').Atom<boolean>;
38
54
  export declare const focusCaptionOnOpenAtom: import('jotai').PrimitiveAtom<boolean> & {
39
55
  init: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"atoms.d.ts","sourceRoot":"","sources":["../src/atoms.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEtD,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,QAAQ,GAAG,OAAO,CAAC;AAC5D,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,KAAK,CAAC;AAY3C,eAAO,MAAM,OAAO;;CAAW,CAAC;AAChC,eAAO,MAAM,WAAW;;CAAW,CAAC;AACpC,eAAO,MAAM,SAAS;;CAA6B,CAAC;AACpD,eAAO,MAAM,UAAU;;CAA6B,CAAC;AACrD,eAAO,MAAM,WAAW;;CAA6B,CAAC;AACtD,eAAO,MAAM,aAAa;;CAA6B,CAAC;AACxD,eAAO,MAAM,UAAU;;CAA6B,CAAC;AAGrD,eAAO,MAAM,aAAa;;CAAkC,CAAC;AAC7D,eAAO,MAAM,YAAY;;CAAc,CAAC;AACxC,eAAO,MAAM,YAAY;;CAAc,CAAC;AACxC,eAAO,MAAM,eAAe;;CAAc,CAAC;AAC3C,eAAO,MAAM,kBAAkB,+BAE9B,CAAC;AAEF,eAAO,MAAM,sBAAsB;;CAAc,CAAC;AAGlD,eAAO,MAAM,WAAW;;CAAW,CAAC;AACpC,eAAO,MAAM,eAAe;;CAAW,CAAC;AACxC,eAAO,MAAM,eAAe;;CAAW,CAAC;AAGxC,eAAO,MAAM,eAAe;;CAA8B,CAAC;AAC3D,eAAO,MAAM,cAAc;;CAAW,CAAC;AACvC,eAAO,MAAM,kBAAkB;;CAA4B,CAAC;AAC5D,eAAO,MAAM,eAAe;WACnB,MAAM;YACL,MAAM;;;eADP,MAAM;gBACL,MAAM;;CACD,CAAC;AAChB,eAAO,MAAM,kBAAkB;;CAAc,CAAC;AAC9C,eAAO,MAAM,gBAAgB;;CAA4B,CAAC;AAG1D,eAAO,MAAM,cAAc;;CAEzB,CAAC;AACH,eAAO,MAAM,gBAAgB;;CAE3B,CAAC;AAGH,eAAO,MAAM,kBAAkB,0CAG7B,CAAC;AAEH,eAAO,MAAM,eAAe,0CAAoE,CAAC;AAEjG,eAAO,MAAM,cAAc,qCAgBzB,CAAC"}
1
+ {"version":3,"file":"atoms.d.ts","sourceRoot":"","sources":["../src/atoms.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAG7D,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEtD,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,QAAQ,GAAG,OAAO,CAAC;AAC5D,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,KAAK,CAAC;AAY3C,eAAO,MAAM,OAAO;;CAAW,CAAC;AAChC,eAAO,MAAM,WAAW;;CAAW,CAAC;AACpC,eAAO,MAAM,SAAS;;CAA6B,CAAC;AACpD,eAAO,MAAM,UAAU;;CAA6B,CAAC;AACrD,eAAO,MAAM,WAAW;;CAA6B,CAAC;AACtD,eAAO,MAAM,aAAa;;CAA6B,CAAC;AACxD,eAAO,MAAM,UAAU;;CAA6B,CAAC;AACrD,eAAO,MAAM,gBAAgB;;CAA6B,CAAC;AAC3D,eAAO,MAAM,UAAU;;CAAkC,CAAC;AAG1D,eAAO,MAAM,aAAa;;CAAkC,CAAC;AAC7D,eAAO,MAAM,YAAY;;CAAc,CAAC;AACxC,eAAO,MAAM,YAAY;;CAAc,CAAC;AACxC,eAAO,MAAM,eAAe;;CAAc,CAAC;AAC3C,eAAO,MAAM,YAAY;;CAAc,CAAC;AACxC,eAAO,MAAM,cAAc;;CAAc,CAAC;AAC1C,eAAO,MAAM,YAAY;;CAAc,CAAC;AACxC,eAAO,MAAM,kBAAkB,+BAQ9B,CAAC;AAEF,eAAO,MAAM,sBAAsB;;CAAc,CAAC;AAGlD,eAAO,MAAM,WAAW;;CAAW,CAAC;AACpC,eAAO,MAAM,eAAe;;CAAW,CAAC;AACxC,eAAO,MAAM,eAAe;;CAAW,CAAC;AAGxC,eAAO,MAAM,eAAe;;CAA8B,CAAC;AAC3D,eAAO,MAAM,cAAc;;CAAW,CAAC;AACvC,eAAO,MAAM,kBAAkB;;CAA4B,CAAC;AAC5D,eAAO,MAAM,eAAe;WACnB,MAAM;YACL,MAAM;;;eADP,MAAM;gBACL,MAAM;;CACD,CAAC;AAChB,eAAO,MAAM,kBAAkB;;CAAc,CAAC;AAC9C,eAAO,MAAM,gBAAgB;;CAA4B,CAAC;AAG1D,eAAO,MAAM,cAAc;;CAEzB,CAAC;AACH,eAAO,MAAM,gBAAgB;;CAE3B,CAAC;AAGH,eAAO,MAAM,kBAAkB,0CAG7B,CAAC;AAEH,eAAO,MAAM,eAAe,0CAAoE,CAAC;AAEjG,eAAO,MAAM,cAAc,qCAgBzB,CAAC"}
package/dist/index.mjs CHANGED
@@ -1,14 +1,14 @@
1
- import { C as root, S as replaceUploadArea, _ as imageState, a as editInput, c as editToolbar, d as editToolbarVisible, f as editTrigger, g as image, h as frameEditMode, i as editFieldIcon, l as editToolbarButton, m as frame, o as editPanel, r as editField, s as editPlaceholder, t as ImageRenderer, u as editToolbarButtonDanger, v as imageVisible, w as semanticClassNames } from "./ImageRenderer-BihkEC_w.js";
1
+ import { A as semanticClassNames, D as resizeHandleRight, E as resizeHandleLeft, O as resizeHandleVisible, T as resizeHandle, _ as frameEditMode, a as editFieldIcon, b as imageVisible, c as editPlaceholder, d as editToolbarButtonActive, f as editToolbarButtonDanger, g as frame, i as editField, j as sizeOption, k as root, l as editToolbar, m as editTrigger, o as editInput, p as editToolbarVisible, r as controlPanel, s as editPanel, t as ImageRenderer, u as editToolbarButton, v as image, w as replaceUploadArea, y as imageState } from "./ImageRenderer-DGTS4o75.js";
2
2
  import { useRendererMode } from "@haklex/rich-editor/static";
3
3
  import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext";
4
- import { Provider, atom, createStore, useAtomValue, useSetAtom, useStore } from "jotai";
4
+ import { Provider, atom, createStore, useAtom, useAtomValue, useSetAtom, useStore } from "jotai";
5
5
  import { useCallback, useEffect, useRef, useState } from "react";
6
6
  import { computeImageMeta, decodeThumbHash } from "@haklex/rich-editor/renderers";
7
7
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
8
8
  import { ActionBar, ActionButton, Popover, PopoverPanel, PopoverTrigger, SegmentedControl } from "@haklex/rich-editor-ui";
9
9
  import { $getNearestNodeFromDOMNode, REDO_COMMAND, UNDO_COMMAND } from "lexical";
10
- import { Captions, Copy, Download, ExternalLink, ImageIcon, Loader2, Replace, Trash2, Type, Upload } from "lucide-react";
11
- import { $createImageNode, $isImageNode } from "@haklex/rich-editor/nodes";
10
+ import { AlignCenterVertical, AlignEndVertical, AlignStartVertical, ArrowLeftToLine, ArrowRightToLine, Captions, Copy, Download, ExternalLink, ImageIcon, Loader2, Replace, Scaling, Trash2, Type, Upload } from "lucide-react";
11
+ import { $createImageNode, $isImageNode, sanitizeImageDisplayWidth } from "@haklex/rich-editor/nodes";
12
12
  import { useImageUpload } from "@haklex/rich-editor/plugins";
13
13
  //#region src/atoms.ts
14
14
  function getCaptionText(altText, caption) {
@@ -23,11 +23,16 @@ var heightAtom = atom();
23
23
  var captionAtom = atom();
24
24
  var thumbhashAtom = atom();
25
25
  var accentAtom = atom();
26
+ var displayWidthAtom = atom();
27
+ var layoutAtom = atom();
26
28
  var loadStateAtom = atom("loading");
27
29
  var hoveringAtom = atom(false);
28
30
  var metaOpenAtom = atom(false);
29
31
  var replaceOpenAtom = atom(false);
30
- var toolbarVisibleAtom = atom((get) => get(hoveringAtom) || get(metaOpenAtom) || get(replaceOpenAtom));
32
+ var sizeOpenAtom = atom(false);
33
+ var layoutOpenAtom = atom(false);
34
+ var resizingAtom = atom(false);
35
+ var toolbarVisibleAtom = atom((get) => get(hoveringAtom) || get(metaOpenAtom) || get(replaceOpenAtom) || get(sizeOpenAtom) || get(layoutOpenAtom) || get(resizingAtom));
31
36
  var focusCaptionOnOpenAtom = atom(false);
32
37
  var editSrcAtom = atom("");
33
38
  var editAltTextAtom = atom("");
@@ -74,6 +79,8 @@ function ImageEditProvider({ props, children }) {
74
79
  s.set(captionAtom, props.caption);
75
80
  s.set(thumbhashAtom, props.thumbhash);
76
81
  s.set(accentAtom, props.accent);
82
+ s.set(displayWidthAtom, props.displayWidth);
83
+ s.set(layoutAtom, props.layout);
77
84
  s.set(editSrcAtom, props.src);
78
85
  s.set(editAltTextAtom, props.altText);
79
86
  s.set(editCaptionAtom, props.caption || "");
@@ -91,6 +98,8 @@ function ImageEditProvider({ props, children }) {
91
98
  store.set(captionAtom, props.caption);
92
99
  store.set(thumbhashAtom, props.thumbhash);
93
100
  store.set(accentAtom, props.accent);
101
+ store.set(displayWidthAtom, props.displayWidth);
102
+ store.set(layoutAtom, props.layout);
94
103
  }, [
95
104
  store,
96
105
  props.src,
@@ -99,7 +108,9 @@ function ImageEditProvider({ props, children }) {
99
108
  props.height,
100
109
  props.caption,
101
110
  props.thumbhash,
102
- props.accent
111
+ props.accent,
112
+ props.displayWidth,
113
+ props.layout
103
114
  ]);
104
115
  useEffect(() => {
105
116
  store.set(editSrcAtom, props.src);
@@ -212,11 +223,23 @@ function useImageActions() {
212
223
  height: node.getHeight(),
213
224
  caption: node.getCaption(),
214
225
  thumbhash: node.getThumbhash(),
215
- accent: node.getAccent()
226
+ accent: node.getAccent(),
227
+ displayWidth: node.getDisplayWidth(),
228
+ layout: node.getLayout()
216
229
  });
217
230
  node.insertAfter(copy);
218
231
  });
219
232
  }, [withImageNode]);
233
+ const handleSetDisplayWidth = useCallback((width) => {
234
+ withImageNode((node) => {
235
+ node.setDisplayWidth(width);
236
+ });
237
+ }, [withImageNode]);
238
+ const handleSetLayout = useCallback((layout) => {
239
+ withImageNode((node) => {
240
+ node.setLayout(layout);
241
+ });
242
+ }, [withImageNode]);
220
243
  return {
221
244
  commitMeta,
222
245
  closeReplacePanel,
@@ -291,7 +314,9 @@ function useImageActions() {
291
314
  handleOpen,
292
315
  handleDuplicate,
293
316
  handleDownload,
294
- handleDelete
317
+ handleDelete,
318
+ handleSetDisplayWidth,
319
+ handleSetLayout
295
320
  };
296
321
  }
297
322
  //#endregion
@@ -378,6 +403,116 @@ function getEditorHistoryShortcut(event, options = {}) {
378
403
  return null;
379
404
  }
380
405
  //#endregion
406
+ //#region src/ImageLayoutControls.tsx
407
+ var SIZE_PRESETS = [
408
+ 25,
409
+ 50,
410
+ 75,
411
+ 100
412
+ ];
413
+ var LAYOUT_OPTIONS = [
414
+ {
415
+ value: void 0,
416
+ label: "Center",
417
+ Icon: AlignCenterVertical
418
+ },
419
+ {
420
+ value: "align-left",
421
+ label: "Align left",
422
+ Icon: AlignStartVertical
423
+ },
424
+ {
425
+ value: "align-right",
426
+ label: "Align right",
427
+ Icon: AlignEndVertical
428
+ },
429
+ {
430
+ value: "float-left",
431
+ label: "Float left, text wraps right",
432
+ Icon: ArrowLeftToLine
433
+ },
434
+ {
435
+ value: "float-right",
436
+ label: "Float right, text wraps left",
437
+ Icon: ArrowRightToLine
438
+ }
439
+ ];
440
+ var toolbarButtonClass = `${editToolbarButton} ${semanticClassNames.editToolbarButton}`;
441
+ var stopMouseDown = (e) => {
442
+ e.preventDefault();
443
+ e.stopPropagation();
444
+ };
445
+ function ImageSizeControl() {
446
+ const [sizeOpen, setSizeOpen] = useAtom(sizeOpenAtom);
447
+ const displayWidth = useAtomValue(displayWidthAtom);
448
+ const { handleSetDisplayWidth } = useImageActions();
449
+ return /* @__PURE__ */ jsxs(Popover, {
450
+ open: sizeOpen,
451
+ onOpenChange: setSizeOpen,
452
+ children: [/* @__PURE__ */ jsx(PopoverTrigger, {
453
+ className: toolbarButtonClass,
454
+ title: "Image size",
455
+ onMouseDown: stopMouseDown,
456
+ children: /* @__PURE__ */ jsx(Scaling, { size: 14 })
457
+ }), /* @__PURE__ */ jsxs(PopoverPanel, {
458
+ className: controlPanel,
459
+ side: "bottom",
460
+ sideOffset: 8,
461
+ children: [/* @__PURE__ */ jsx("button", {
462
+ className: `${sizeOption} ${displayWidth === void 0 ? editToolbarButtonActive : ""}`.trim(),
463
+ title: "Natural size",
464
+ type: "button",
465
+ onMouseDown: stopMouseDown,
466
+ onClick: () => {
467
+ handleSetDisplayWidth(void 0);
468
+ setSizeOpen(false);
469
+ },
470
+ children: "Auto"
471
+ }), SIZE_PRESETS.map((preset) => /* @__PURE__ */ jsxs("button", {
472
+ className: `${sizeOption} ${displayWidth === preset ? editToolbarButtonActive : ""}`.trim(),
473
+ title: `${preset}% of content width`,
474
+ type: "button",
475
+ onMouseDown: stopMouseDown,
476
+ onClick: () => {
477
+ handleSetDisplayWidth(preset);
478
+ setSizeOpen(false);
479
+ },
480
+ children: [preset, "%"]
481
+ }, preset))]
482
+ })]
483
+ });
484
+ }
485
+ function ImageLayoutControl() {
486
+ const [layoutOpen, setLayoutOpen] = useAtom(layoutOpenAtom);
487
+ const layout = useAtomValue(layoutAtom);
488
+ const { handleSetLayout } = useImageActions();
489
+ return /* @__PURE__ */ jsxs(Popover, {
490
+ open: layoutOpen,
491
+ onOpenChange: setLayoutOpen,
492
+ children: [/* @__PURE__ */ jsx(PopoverTrigger, {
493
+ className: toolbarButtonClass,
494
+ title: "Image layout",
495
+ onMouseDown: stopMouseDown,
496
+ children: /* @__PURE__ */ jsx((LAYOUT_OPTIONS.find((option) => option.value === layout) ?? LAYOUT_OPTIONS[0]).Icon, { size: 14 })
497
+ }), /* @__PURE__ */ jsx(PopoverPanel, {
498
+ className: controlPanel,
499
+ side: "bottom",
500
+ sideOffset: 8,
501
+ children: LAYOUT_OPTIONS.map(({ value, label, Icon }) => /* @__PURE__ */ jsx("button", {
502
+ className: `${toolbarButtonClass} ${layout === value ? editToolbarButtonActive : ""}`.trim(),
503
+ title: label,
504
+ type: "button",
505
+ onMouseDown: stopMouseDown,
506
+ onClick: () => {
507
+ handleSetLayout(value);
508
+ setLayoutOpen(false);
509
+ },
510
+ children: /* @__PURE__ */ jsx(Icon, { size: 14 })
511
+ }, value ?? "center"))
512
+ })]
513
+ });
514
+ }
515
+ //#endregion
381
516
  //#region src/ReplacePanel.tsx
382
517
  var replaceModeItems = [{
383
518
  value: "upload",
@@ -539,6 +674,8 @@ function ImageEditToolbar() {
539
674
  children: /* @__PURE__ */ jsx(ReplacePanel, {})
540
675
  })]
541
676
  }),
677
+ /* @__PURE__ */ jsx(ImageSizeControl, {}),
678
+ /* @__PURE__ */ jsx(ImageLayoutControl, {}),
542
679
  /* @__PURE__ */ jsx("button", {
543
680
  className: `${editToolbarButton} ${semanticClassNames.editToolbarButton}`,
544
681
  title: "Open source",
@@ -621,6 +758,84 @@ function ReplacePopover() {
621
758
  });
622
759
  }
623
760
  //#endregion
761
+ //#region src/useImageResize.ts
762
+ var MOVE_THRESHOLD_PX = 3;
763
+ function useImageResize() {
764
+ const store = useStore();
765
+ const [editor] = useLexicalComposerContext();
766
+ const finishRef = useRef(null);
767
+ useEffect(() => () => finishRef.current?.(false), []);
768
+ return { handlePointerDown: useCallback((event, side) => {
769
+ const trigger = store.get(wrapperRefAtom).current;
770
+ if (!trigger) return;
771
+ const frame = trigger.querySelector(`.${semanticClassNames.frame}`);
772
+ const figure = trigger.querySelector("figure");
773
+ const blockWrapper = trigger.closest(".rich-image-wrapper");
774
+ const container = blockWrapper?.parentElement ?? trigger.parentElement;
775
+ if (!frame || !figure || !container) return;
776
+ const containerStyle = getComputedStyle(container);
777
+ const containerWidth = container.clientWidth - Number.parseFloat(containerStyle.paddingLeft) - Number.parseFloat(containerStyle.paddingRight);
778
+ const startWidth = frame.getBoundingClientRect().width;
779
+ if (!containerWidth || containerWidth <= 0 || !startWidth) return;
780
+ event.preventDefault();
781
+ event.stopPropagation();
782
+ const layout = store.get(layoutAtom);
783
+ const factor = layout === void 0 ? 2 : 1;
784
+ const isFloat = layout === "float-left" || layout === "float-right";
785
+ const startX = event.clientX;
786
+ const handle = event.currentTarget;
787
+ try {
788
+ handle.setPointerCapture(event.pointerId);
789
+ } catch {}
790
+ store.set(resizingAtom, true);
791
+ const prevUserSelect = document.body.style.userSelect;
792
+ document.body.style.userSelect = "none";
793
+ let percent = sanitizeImageDisplayWidth(startWidth / containerWidth * 100) ?? 100;
794
+ let moved = false;
795
+ const handleMove = (moveEvent) => {
796
+ const rawDelta = moveEvent.clientX - startX;
797
+ if (!moved && Math.abs(rawDelta) < MOVE_THRESHOLD_PX) return;
798
+ moved = true;
799
+ percent = sanitizeImageDisplayWidth((startWidth + (side === "left" ? -rawDelta : rawDelta) * factor) / containerWidth * 100) ?? percent;
800
+ if (isFloat && blockWrapper) blockWrapper.style.width = `${percent}%`;
801
+ else figure.style.setProperty("--rich-image-display-width", `${percent}%`);
802
+ };
803
+ const finish = (commit) => {
804
+ if (finishRef.current !== finish) return;
805
+ finishRef.current = null;
806
+ handle.removeEventListener("pointermove", handleMove);
807
+ handle.removeEventListener("pointerup", handleEnd);
808
+ handle.removeEventListener("pointercancel", handleEnd);
809
+ document.body.style.userSelect = prevUserSelect;
810
+ store.set(resizingAtom, false);
811
+ if (!commit || !moved) return;
812
+ editor.update(() => {
813
+ const node = $getNearestNodeFromDOMNode(trigger);
814
+ if ($isImageNode(node)) node.setDisplayWidth(percent);
815
+ });
816
+ };
817
+ const handleEnd = () => finish(true);
818
+ finishRef.current = finish;
819
+ handle.addEventListener("pointermove", handleMove);
820
+ handle.addEventListener("pointerup", handleEnd);
821
+ handle.addEventListener("pointercancel", handleEnd);
822
+ }, [editor, store]) };
823
+ }
824
+ //#endregion
825
+ //#region src/ResizeHandles.tsx
826
+ function ResizeHandles() {
827
+ const visible = useAtomValue(toolbarVisibleAtom);
828
+ const { handlePointerDown } = useImageResize();
829
+ const visibleClass = visible ? resizeHandleVisible : "";
830
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("span", {
831
+ className: `${resizeHandle} ${resizeHandleLeft} ${visibleClass} ${semanticClassNames.resizeHandle}`.trim(),
832
+ onPointerDown: (e) => handlePointerDown(e, "left")
833
+ }), /* @__PURE__ */ jsx("span", {
834
+ className: `${resizeHandle} ${resizeHandleRight} ${visibleClass} ${semanticClassNames.resizeHandle}`.trim(),
835
+ onPointerDown: (e) => handlePointerDown(e, "right")
836
+ })] });
837
+ }
838
+ //#endregion
624
839
  //#region src/ImageEditRenderer.tsx
625
840
  var frameStateSemanticClass = {
626
841
  loading: semanticClassNames.frameLoading,
@@ -653,6 +868,8 @@ function ImageEditContent() {
653
868
  const setMetaOpen = useSetAtom(metaOpenAtom);
654
869
  const setReplaceOpen = useSetAtom(replaceOpenAtom);
655
870
  const setFocusCaptionOnOpen = useSetAtom(focusCaptionOnOpenAtom);
871
+ const displayWidth = useAtomValue(displayWidthAtom);
872
+ const layout = useAtomValue(layoutAtom);
656
873
  const handleCaptionClick = useCallback((e) => {
657
874
  e.stopPropagation();
658
875
  const scrollY = window.scrollY;
@@ -667,6 +884,7 @@ function ImageEditContent() {
667
884
  setReplaceOpen,
668
885
  setFocusCaptionOnOpen
669
886
  ]);
887
+ const figureStyle = displayWidth ? { "--rich-image-display-width": `${displayWidth}%` } : void 0;
670
888
  return /* @__PURE__ */ jsxs("div", {
671
889
  className: `${editTrigger} ${semanticClassNames.editTrigger}`,
672
890
  ref: wrapperRef,
@@ -674,6 +892,8 @@ function ImageEditContent() {
674
892
  onMouseLeave: () => setHovering(false),
675
893
  children: [src ? /* @__PURE__ */ jsxs("figure", {
676
894
  className: `${root} ${semanticClassNames.root}`,
895
+ "data-layout": layout,
896
+ style: figureStyle,
677
897
  children: [/* @__PURE__ */ jsxs("div", {
678
898
  className: `${frame} ${semanticClassNames.frame} ${frameEditMode} ${imageState[loadState]} ${frameStateSemanticClass[loadState]}`.trim(),
679
899
  style: frameStyle,
@@ -692,7 +912,8 @@ function ImageEditContent() {
692
912
  loadState === "error" && /* @__PURE__ */ jsx("span", {
693
913
  className: `_1n94osfc ${semanticClassNames.errorBadge}`,
694
914
  children: "Image failed to load"
695
- })
915
+ }),
916
+ /* @__PURE__ */ jsx(ResizeHandles, {})
696
917
  ]
697
918
  }), captionText && /* @__PURE__ */ jsx("figcaption", {
698
919
  className: `_1n94osfd ${semanticClassNames.caption}`,
@@ -1,2 +1,2 @@
1
- :root{--rc-text:#000;--rc-text-secondary:#262626;--rc-text-tertiary:#737373;--rc-text-quaternary:#a3a3a3;--rc-bg:#fff;--rc-bg-secondary:#fafafa;--rc-bg-tertiary:#f5f5f5;--rc-fill:#e8e8e8;--rc-fill-secondary:#eee;--rc-fill-tertiary:#f5f5f5;--rc-fill-quaternary:#fafafa;--rc-border:#f5f5f5;--rc-accent:#2563eb;--rc-accent-light:#2563eb20;--rc-link:#2563eb;--rc-code-text:#404040;--rc-code-bg:#f5f5f5;--rc-hr-border:#e5e5e5;--rc-quote-border:#2563eb;--rc-quote-bg:#f5f5f5;--rc-alert-info:#006bb7;--rc-alert-warning:#c50;--rc-alert-tip:#1c0;--rc-alert-caution:#c01;--rc-alert-important:#50c;--rc-max-width:700px;--rc-shadow-top-bar:0 8px 30px #0000001f, 0 2px 8px #0000000f;--rc-shadow-modal:0 10px 15px -3px #0000001a, 0 4px 6px -4px #0000001a;--rc-shadow-menu:0 1px 4px #0000000a, 0 4px 16px #00000014;--rc-space-xs:4px;--rc-space-sm:8px;--rc-space-md:16px;--rc-space-lg:24px;--rc-space-xl:32px;--rc-font-family-sans:"PingFang SC", "Microsoft YaHei", "Segoe UI", Roboto, Helvetica, "noto sans sc", "hiragino sans gb", -apple-system, system-ui, sans-serif, Apple Color Emoji, Segoe UI Emoji, Not Color Emoji;--rc-font-family-serif:"Noto Serif CJK SC", "Source Han Serif SC", "Source Han Serif", "source-han-serif-sc", "Songti SC", STSong, "华文宋体", serif;--rc-font-family-kai:"楷体", KaiTi, STKaiti, "Kaiti SC", "LXGW WenKai", "霞鹜文楷", "Noto Serif CJK SC", serif;--rc-font-mono:"SF Mono", SFMono-Regular, ui-monospace, "DejaVu Sans Mono", Menlo, Consolas, monospace;--rc-font-size-2xs:.625em;--rc-font-size-xs:.75em;--rc-font-size-sm:.8125em;--rc-font-size-md:.875em;--rc-font-size-lg:1.25em;--rc-font-size-base:16px;--rc-font-size-small:14px;--rc-line-height:1.7;--rc-line-height-tight:1.4;--rc-font-family:"PingFang SC", "Microsoft YaHei", "Segoe UI", Roboto, Helvetica, "noto sans sc", "hiragino sans gb", -apple-system, system-ui, sans-serif, Apple Color Emoji, Segoe UI Emoji, Not Color Emoji;--rc-radius-sm:4px;--rc-radius-md:8px;--rc-radius-lg:12px}:root.dark,[data-theme=dark]{--rc-text:#fafafa;--rc-text-secondary:#a3a3a3;--rc-text-tertiary:#737373;--rc-text-quaternary:#525252;--rc-bg:#0a0a0a;--rc-bg-secondary:#171717;--rc-bg-tertiary:#262626;--rc-fill:#2a2a2a;--rc-fill-secondary:#222;--rc-fill-tertiary:#1a1a1a;--rc-fill-quaternary:#141414;--rc-border:#262626;--rc-accent:#60a5fa;--rc-accent-light:#60a5fa20;--rc-link:#60a5fa;--rc-code-text:#d4d4d4;--rc-code-bg:#262626;--rc-hr-border:#262626;--rc-quote-border:#60a5fa;--rc-quote-bg:#262626;--rc-alert-info:#7db9e5;--rc-alert-warning:#da864a;--rc-alert-tip:#54da48;--rc-alert-caution:#e16973;--rc-alert-important:#9966e0;--rc-shadow-top-bar:0 8px 30px #00000073, 0 2px 8px #0000004d;--rc-shadow-modal:0 10px 15px -3px #0006, 0 4px 6px -4px #00000059;--rc-shadow-menu:0 1px 4px #00000040, 0 4px 16px #0006}._7eow1s0{--rc-text:#000;--rc-text-secondary:#262626;--rc-text-tertiary:#737373;--rc-text-quaternary:#a3a3a3;--rc-bg:#fff;--rc-bg-secondary:#fafafa;--rc-bg-tertiary:#f5f5f5;--rc-fill:#e8e8e8;--rc-fill-secondary:#eee;--rc-fill-tertiary:#f5f5f5;--rc-fill-quaternary:#fafafa;--rc-border:#f5f5f5;--rc-accent:#2563eb;--rc-accent-light:#2563eb20;--rc-link:#2563eb;--rc-code-text:#404040;--rc-code-bg:#f5f5f5;--rc-hr-border:#e5e5e5;--rc-quote-border:#2563eb;--rc-quote-bg:#f5f5f5;--rc-alert-info:#006bb7;--rc-alert-warning:#c50;--rc-alert-tip:#1c0;--rc-alert-caution:#c01;--rc-alert-important:#50c;--rc-max-width:700px;--rc-shadow-top-bar:0 8px 30px #0000001f, 0 2px 8px #0000000f;--rc-shadow-modal:0 10px 15px -3px #0000001a, 0 4px 6px -4px #0000001a;--rc-shadow-menu:0 1px 4px #0000000a, 0 4px 16px #00000014;--rc-space-xs:4px;--rc-space-sm:8px;--rc-space-md:16px;--rc-space-lg:24px;--rc-space-xl:32px;--rc-font-family-sans:"PingFang SC", "Microsoft YaHei", "Segoe UI", Roboto, Helvetica, "noto sans sc", "hiragino sans gb", -apple-system, system-ui, sans-serif, Apple Color Emoji, Segoe UI Emoji, Not Color Emoji;--rc-font-family-serif:"Noto Serif CJK SC", "Source Han Serif SC", "Source Han Serif", "source-han-serif-sc", "Songti SC", STSong, "华文宋体", serif;--rc-font-family-kai:"楷体", KaiTi, STKaiti, "Kaiti SC", "LXGW WenKai", "霞鹜文楷", "Noto Serif CJK SC", serif;--rc-font-mono:"SF Mono", SFMono-Regular, ui-monospace, "DejaVu Sans Mono", Menlo, Consolas, monospace;--rc-font-size-2xs:.625em;--rc-font-size-xs:.75em;--rc-font-size-sm:.8125em;--rc-font-size-md:.875em;--rc-font-size-lg:1.25em;--rc-font-size-base:16px;--rc-font-size-small:14px;--rc-line-height:1.7;--rc-line-height-tight:1.4;--rc-font-family:"PingFang SC", "Microsoft YaHei", "Segoe UI", Roboto, Helvetica, "noto sans sc", "hiragino sans gb", -apple-system, system-ui, sans-serif, Apple Color Emoji, Segoe UI Emoji, Not Color Emoji;--rc-radius-sm:4px;--rc-radius-md:8px;--rc-radius-lg:12px}._7eow1s1{--rc-text:#000;--rc-text-secondary:#262626;--rc-text-tertiary:#737373;--rc-text-quaternary:#a3a3a3;--rc-bg:#fff;--rc-bg-secondary:#fafafa;--rc-bg-tertiary:#f5f5f5;--rc-fill:#e8e8e8;--rc-fill-secondary:#eee;--rc-fill-tertiary:#f5f5f5;--rc-fill-quaternary:#fafafa;--rc-border:#f5f5f5;--rc-accent:#2563eb;--rc-accent-light:#2563eb20;--rc-link:#2563eb;--rc-code-text:#404040;--rc-code-bg:#f5f5f5;--rc-hr-border:#e5e5e5;--rc-quote-border:#2563eb;--rc-quote-bg:#f5f5f5;--rc-alert-info:#006bb7;--rc-alert-warning:#c50;--rc-alert-tip:#1c0;--rc-alert-caution:#c01;--rc-alert-important:#50c;--rc-max-width:700px;--rc-shadow-top-bar:0 8px 30px #0000001f, 0 2px 8px #0000000f;--rc-shadow-modal:0 10px 15px -3px #0000001a, 0 4px 6px -4px #0000001a;--rc-shadow-menu:0 1px 4px #0000000a, 0 4px 16px #00000014;--rc-space-xs:4px;--rc-space-sm:8px;--rc-space-md:16px;--rc-space-lg:24px;--rc-space-xl:32px;--rc-font-family-sans:"PingFang SC", "Microsoft YaHei", "Segoe UI", Roboto, Helvetica, "noto sans sc", "hiragino sans gb", -apple-system, system-ui, sans-serif, Apple Color Emoji, Segoe UI Emoji, Not Color Emoji;--rc-font-family-serif:"Noto Serif CJK SC", "Source Han Serif SC", "Source Han Serif", "source-han-serif-sc", "Songti SC", STSong, "华文宋体", serif;--rc-font-family-kai:"楷体", KaiTi, STKaiti, "Kaiti SC", "LXGW WenKai", "霞鹜文楷", "Noto Serif CJK SC", serif;--rc-font-mono:"SF Mono", SFMono-Regular, ui-monospace, "DejaVu Sans Mono", Menlo, Consolas, monospace;--rc-font-size-2xs:.625em;--rc-font-size-xs:.75em;--rc-font-size-sm:.8125em;--rc-font-size-md:.875em;--rc-font-size-lg:1.25em;--rc-font-size-base:16px;--rc-font-size-small:14px;--rc-line-height:1.8;--rc-line-height-tight:1.4;--rc-font-family:"Noto Serif CJK SC", "Source Han Serif SC", "Source Han Serif", "source-han-serif-sc", "Songti SC", STSong, "华文宋体", serif;--rc-radius-sm:4px;--rc-radius-md:8px;--rc-radius-lg:12px}._7eow1s2{--rc-text:#000;--rc-text-secondary:#262626;--rc-text-tertiary:#737373;--rc-text-quaternary:#a3a3a3;--rc-bg:#fff;--rc-bg-secondary:#fafafa;--rc-bg-tertiary:#f5f5f5;--rc-fill:#e8e8e8;--rc-fill-secondary:#eee;--rc-fill-tertiary:#f5f5f5;--rc-fill-quaternary:#fafafa;--rc-border:#f5f5f5;--rc-accent:#2563eb;--rc-accent-light:#2563eb20;--rc-link:#2563eb;--rc-code-text:#404040;--rc-code-bg:#f5f5f5;--rc-hr-border:#e5e5e5;--rc-quote-border:#a3a3a3;--rc-quote-bg:#fafafa;--rc-alert-info:#006bb7;--rc-alert-warning:#c50;--rc-alert-tip:#1c0;--rc-alert-caution:#c01;--rc-alert-important:#50c;--rc-max-width:none;--rc-shadow-top-bar:0 8px 30px #0000001f, 0 2px 8px #0000000f;--rc-shadow-modal:0 10px 15px -3px #0000001a, 0 4px 6px -4px #0000001a;--rc-shadow-menu:0 1px 4px #0000000a, 0 4px 16px #00000014;--rc-space-xs:2px;--rc-space-sm:4px;--rc-space-md:10px;--rc-space-lg:16px;--rc-space-xl:20px;--rc-font-family-sans:"PingFang SC", "Microsoft YaHei", "Segoe UI", Roboto, Helvetica, "noto sans sc", "hiragino sans gb", -apple-system, system-ui, sans-serif, Apple Color Emoji, Segoe UI Emoji, Not Color Emoji;--rc-font-family-serif:"Noto Serif CJK SC", "Source Han Serif SC", "Source Han Serif", "source-han-serif-sc", "Songti SC", STSong, "华文宋体", serif;--rc-font-family-kai:"楷体", KaiTi, STKaiti, "Kaiti SC", "LXGW WenKai", "霞鹜文楷", "Noto Serif CJK SC", serif;--rc-font-mono:"SF Mono", SFMono-Regular, ui-monospace, "DejaVu Sans Mono", Menlo, Consolas, monospace;--rc-font-size-2xs:.625em;--rc-font-size-xs:.75em;--rc-font-size-sm:.8125em;--rc-font-size-md:.875em;--rc-font-size-lg:1.25em;--rc-font-size-base:14px;--rc-font-size-small:12px;--rc-line-height:1.5;--rc-line-height-tight:1.3;--rc-font-family:"PingFang SC", "Microsoft YaHei", "Segoe UI", Roboto, Helvetica, "noto sans sc", "hiragino sans gb", -apple-system, system-ui, sans-serif, Apple Color Emoji, Segoe UI Emoji, Not Color Emoji;--rc-radius-sm:3px;--rc-radius-md:6px;--rc-radius-lg:12px}.dark ._7eow1s0,[data-theme=dark] ._7eow1s0,.dark._7eow1s0,[data-theme=dark]._7eow1s0,.dark ._7eow1s1,[data-theme=dark] ._7eow1s1,.dark._7eow1s1,[data-theme=dark]._7eow1s1,.dark ._7eow1s2,[data-theme=dark] ._7eow1s2,.dark._7eow1s2,[data-theme=dark]._7eow1s2{--rc-text:#fafafa;--rc-text-secondary:#a3a3a3;--rc-text-tertiary:#737373;--rc-text-quaternary:#525252;--rc-bg:#0a0a0a;--rc-bg-secondary:#171717;--rc-bg-tertiary:#262626;--rc-fill:#2a2a2a;--rc-fill-secondary:#222;--rc-fill-tertiary:#1a1a1a;--rc-fill-quaternary:#141414;--rc-border:#262626;--rc-accent:#60a5fa;--rc-accent-light:#60a5fa20;--rc-link:#60a5fa;--rc-code-text:#d4d4d4;--rc-code-bg:#262626;--rc-hr-border:#262626;--rc-quote-border:#60a5fa;--rc-quote-bg:#262626;--rc-alert-info:#7db9e5;--rc-alert-warning:#da864a;--rc-alert-tip:#54da48;--rc-alert-caution:#e16973;--rc-alert-important:#9966e0;--rc-shadow-top-bar:0 8px 30px #00000073, 0 2px 8px #0000004d;--rc-shadow-modal:0 10px 15px -3px #0006, 0 4px 6px -4px #00000059;--rc-shadow-menu:0 1px 4px #00000040, 0 4px 16px #0006}@keyframes _1n94osf1{0%{opacity:.16;-webkit-mask:linear-gradient(90deg,#000 25%,#000000e6 50%,#0000) 150% 0/400% no-repeat;mask:linear-gradient(90deg,#000 25%,#000000e6 50%,#0000) 150% 0/400% no-repeat}to{opacity:1;-webkit-mask:linear-gradient(90deg,#000 25%,#000000e6 50%,#0000) 0/400% no-repeat;mask:linear-gradient(90deg,#000 25%,#000000e6 50%,#0000) 0/400% no-repeat}}@keyframes _1n94osfa{to{transform:rotate(360deg)}}@keyframes _1n94osfi{0%{opacity:0}to{opacity:1}}._1n94osf0{text-align:center;margin:1.25rem 0}._1n94osf2{opacity:0;width:100%;max-width:100%;height:auto;display:block;border-radius:0!important}._1n94osf6{opacity:1;animation:.42s _1n94osf1}._1n94osf7{border-radius:var(--rc-radius-md);cursor:zoom-in;justify-content:center;align-items:center;min-height:3rem;transition:transform .25s;display:inline-flex;position:relative;overflow:hidden}._1n94osf7:hover{transform:translateY(-1px)}._1n94osf8{cursor:default}._1n94osf8:hover{transform:none}._1n94osf9{cursor:default}._1n94osf9:hover{transform:none}._1n94osfb{border:2px solid color-mix(in srgb, var(--rc-text-secondary) 45%, transparent);border-top-color:color-mix(in srgb, var(--rc-text) 65%, transparent);border-radius:50%;width:1.65rem;height:1.65rem;animation:.75s linear infinite _1n94osfa;position:absolute}._1n94osfc{white-space:nowrap;font-size:var(--rc-font-size-sm);letter-spacing:-.005em;color:#fff;-webkit-backdrop-filter:blur(20px)saturate(180%);background:#ff3b30a6;border-radius:6px;padding:.3rem .7rem;font-weight:500;position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)}._1n94osfd{color:var(--rc-text-tertiary);font-size:var(--rc-font-size-md);margin-top:.5rem;line-height:1.5}._1n94osfe{margin:var(--rc-space-md) 0;text-align:center}._1n94osff{border-radius:var(--rc-radius-md);transition:background-color .3s;display:inline-block;position:relative;overflow:hidden}._1n94osfg{opacity:0;transition:opacity .3s}._1n94osfh{opacity:1;transition:opacity .3s}._1n94osfj{z-index:9999;cursor:zoom-out;background-color:#000000d9;justify-content:center;align-items:center;animation:.2s _1n94osfi;display:flex;position:fixed;top:0;bottom:0;left:0;right:0}._1n94osfk{object-fit:contain;border-radius:0;max-width:90vw;max-height:90vh}.rich-image{margin:var(--rc-space-md) 0;text-align:center}.rich-image figcaption{font-size:var(--rc-font-size-md);color:var(--rc-text-secondary);margin-top:var(--rc-space-sm);line-height:var(--rc-line-height-tight)}.rich-image-container{border-radius:var(--rc-radius-md);transition:background-color .3s;display:inline-block;position:relative;overflow:hidden}.rich-image-hidden{opacity:0;transition:opacity .3s}.rich-image-visible{opacity:1;transition:opacity .3s}.rich-image-zoom-overlay{z-index:9999;cursor:zoom-out;background-color:#000000d9;justify-content:center;align-items:center;animation:.2s _1n94osfi;display:flex;position:fixed;top:0;bottom:0;left:0;right:0}.rich-image-zoom-img{object-fit:contain;border-radius:0;max-width:90vw;max-height:90vh}._1n94osfl{cursor:default;display:block;position:relative}._1n94osfm{border:2px dashed var(--rc-border);border-radius:var(--rc-radius-md);color:var(--rc-text-secondary);font-size:var(--rc-font-size-md);cursor:pointer;flex-direction:column;justify-content:center;align-items:center;gap:8px;padding:2rem;transition:border-color .2s,color .2s,background-color .2s;display:flex}._1n94osfm:hover{border-color:var(--rc-accent);color:var(--rc-text);background-color:color-mix(in srgb, var(--rc-accent) 8%, transparent)}._1n94osfn{z-index:20;border:1px solid var(--rc-border);background:color-mix(in srgb, var(--rc-bg) 96%, transparent);box-shadow:var(--rc-shadow-top-bar);opacity:0;pointer-events:none;border-radius:10px;align-items:center;gap:4px;padding:4px;transition:opacity .15s;display:inline-flex;position:absolute;top:-2.5rem;left:50%;transform:translate(-50%)}._1n94osfo{opacity:1;pointer-events:auto}._1n94osfp{width:30px;height:30px;color:var(--rc-text-secondary);cursor:pointer;background:0 0;border:none;border-radius:8px;justify-content:center;align-items:center;transition:background-color .15s,color .15s;display:inline-flex}._1n94osfp:hover{color:var(--rc-text);background-color:var(--rc-fill-secondary)}._1n94osfq:hover{color:var(--rc-alert-caution);background-color:color-mix(in srgb, var(--rc-alert-caution) 12%, transparent)}._1n94osfr{width:360px;font-size:var(--rc-font-size-base);font-family:var(--rc-font-family);z-index:30;flex-direction:column;gap:8px;padding:12px;display:flex;position:relative}._1n94osfs{background-color:var(--rc-bg-secondary);border-radius:6px;align-items:center;gap:8px;min-width:0;padding:6px 10px;display:flex}._1n94osft{color:var(--rc-text-secondary);flex-shrink:0}._1n94osfu{-webkit-appearance:none;appearance:none;color:inherit;font-size:var(--rc-font-size-sm);background-color:#0000;border:none;outline:none;flex:1;min-width:0;padding:0}._1n94osfu::placeholder{color:var(--rc-text-secondary)}._1n94osfv{border-radius:var(--rc-radius-md);border:1.5px dashed var(--rc-border);min-height:138px;color:var(--rc-text-secondary);cursor:pointer;flex-direction:column;justify-content:center;align-items:center;gap:.45rem;transition:border-color .15s,background-color .15s;display:flex}._1n94osfv:hover{border-color:color-mix(in srgb, var(--rc-accent) 45%, transparent);color:var(--rc-text);background-color:color-mix(in srgb, var(--rc-accent) 7%, transparent)}._1n94osfw{border-radius:var(--rc-radius-md);border:1px solid var(--rc-border);background-color:color-mix(in srgb, var(--rc-text) 2%, transparent);overflow:hidden}._1n94osfw img{object-fit:cover;width:100%;max-height:188px;display:block}._1n94osfx{color:var(--rc-text-secondary);font-size:var(--rc-font-size-xs);align-items:center;gap:.4rem;display:inline-flex}
1
+ :root{--rc-text:#000;--rc-text-secondary:#262626;--rc-text-tertiary:#737373;--rc-text-quaternary:#a3a3a3;--rc-bg:#fff;--rc-bg-secondary:#fafafa;--rc-bg-tertiary:#f5f5f5;--rc-fill:#e8e8e8;--rc-fill-secondary:#eee;--rc-fill-tertiary:#f5f5f5;--rc-fill-quaternary:#fafafa;--rc-border:#f5f5f5;--rc-accent:#2563eb;--rc-accent-light:#2563eb20;--rc-link:#2563eb;--rc-code-text:#404040;--rc-code-bg:#f5f5f5;--rc-hr-border:#e5e5e5;--rc-quote-border:#2563eb;--rc-quote-bg:#f5f5f5;--rc-alert-info:#006bb7;--rc-alert-warning:#c50;--rc-alert-tip:#1c0;--rc-alert-caution:#c01;--rc-alert-important:#50c;--rc-max-width:700px;--rc-shadow-top-bar:0 8px 30px #0000001f, 0 2px 8px #0000000f;--rc-shadow-modal:0 10px 15px -3px #0000001a, 0 4px 6px -4px #0000001a;--rc-shadow-menu:0 1px 4px #0000000a, 0 4px 16px #00000014;--rc-space-xs:4px;--rc-space-sm:8px;--rc-space-md:16px;--rc-space-lg:24px;--rc-space-xl:32px;--rc-font-family-sans:"PingFang SC", "Microsoft YaHei", "Segoe UI", Roboto, Helvetica, "noto sans sc", "hiragino sans gb", -apple-system, system-ui, sans-serif, Apple Color Emoji, Segoe UI Emoji, Not Color Emoji;--rc-font-family-serif:"Noto Serif CJK SC", "Source Han Serif SC", "Source Han Serif", "source-han-serif-sc", "Songti SC", STSong, "华文宋体", serif;--rc-font-family-kai:"楷体", KaiTi, STKaiti, "Kaiti SC", "LXGW WenKai", "霞鹜文楷", "Noto Serif CJK SC", serif;--rc-font-mono:"SF Mono", SFMono-Regular, ui-monospace, "DejaVu Sans Mono", Menlo, Consolas, monospace;--rc-font-size-2xs:.625em;--rc-font-size-xs:.75em;--rc-font-size-sm:.8125em;--rc-font-size-md:.875em;--rc-font-size-lg:1.25em;--rc-font-size-base:16px;--rc-font-size-small:14px;--rc-line-height:1.7;--rc-line-height-tight:1.4;--rc-font-family:"PingFang SC", "Microsoft YaHei", "Segoe UI", Roboto, Helvetica, "noto sans sc", "hiragino sans gb", -apple-system, system-ui, sans-serif, Apple Color Emoji, Segoe UI Emoji, Not Color Emoji;--rc-radius-sm:4px;--rc-radius-md:8px;--rc-radius-lg:12px}:root.dark,[data-theme=dark]{--rc-text:#fafafa;--rc-text-secondary:#a3a3a3;--rc-text-tertiary:#737373;--rc-text-quaternary:#525252;--rc-bg:#0a0a0a;--rc-bg-secondary:#171717;--rc-bg-tertiary:#262626;--rc-fill:#2a2a2a;--rc-fill-secondary:#222;--rc-fill-tertiary:#1a1a1a;--rc-fill-quaternary:#141414;--rc-border:#262626;--rc-accent:#60a5fa;--rc-accent-light:#60a5fa20;--rc-link:#60a5fa;--rc-code-text:#d4d4d4;--rc-code-bg:#262626;--rc-hr-border:#262626;--rc-quote-border:#60a5fa;--rc-quote-bg:#262626;--rc-alert-info:#7db9e5;--rc-alert-warning:#da864a;--rc-alert-tip:#54da48;--rc-alert-caution:#e16973;--rc-alert-important:#9966e0;--rc-shadow-top-bar:0 8px 30px #00000073, 0 2px 8px #0000004d;--rc-shadow-modal:0 10px 15px -3px #0006, 0 4px 6px -4px #00000059;--rc-shadow-menu:0 1px 4px #00000040, 0 4px 16px #0006}._7eow1s0{--rc-text:#000;--rc-text-secondary:#262626;--rc-text-tertiary:#737373;--rc-text-quaternary:#a3a3a3;--rc-bg:#fff;--rc-bg-secondary:#fafafa;--rc-bg-tertiary:#f5f5f5;--rc-fill:#e8e8e8;--rc-fill-secondary:#eee;--rc-fill-tertiary:#f5f5f5;--rc-fill-quaternary:#fafafa;--rc-border:#f5f5f5;--rc-accent:#2563eb;--rc-accent-light:#2563eb20;--rc-link:#2563eb;--rc-code-text:#404040;--rc-code-bg:#f5f5f5;--rc-hr-border:#e5e5e5;--rc-quote-border:#2563eb;--rc-quote-bg:#f5f5f5;--rc-alert-info:#006bb7;--rc-alert-warning:#c50;--rc-alert-tip:#1c0;--rc-alert-caution:#c01;--rc-alert-important:#50c;--rc-max-width:700px;--rc-shadow-top-bar:0 8px 30px #0000001f, 0 2px 8px #0000000f;--rc-shadow-modal:0 10px 15px -3px #0000001a, 0 4px 6px -4px #0000001a;--rc-shadow-menu:0 1px 4px #0000000a, 0 4px 16px #00000014;--rc-space-xs:4px;--rc-space-sm:8px;--rc-space-md:16px;--rc-space-lg:24px;--rc-space-xl:32px;--rc-font-family-sans:"PingFang SC", "Microsoft YaHei", "Segoe UI", Roboto, Helvetica, "noto sans sc", "hiragino sans gb", -apple-system, system-ui, sans-serif, Apple Color Emoji, Segoe UI Emoji, Not Color Emoji;--rc-font-family-serif:"Noto Serif CJK SC", "Source Han Serif SC", "Source Han Serif", "source-han-serif-sc", "Songti SC", STSong, "华文宋体", serif;--rc-font-family-kai:"楷体", KaiTi, STKaiti, "Kaiti SC", "LXGW WenKai", "霞鹜文楷", "Noto Serif CJK SC", serif;--rc-font-mono:"SF Mono", SFMono-Regular, ui-monospace, "DejaVu Sans Mono", Menlo, Consolas, monospace;--rc-font-size-2xs:.625em;--rc-font-size-xs:.75em;--rc-font-size-sm:.8125em;--rc-font-size-md:.875em;--rc-font-size-lg:1.25em;--rc-font-size-base:16px;--rc-font-size-small:14px;--rc-line-height:1.7;--rc-line-height-tight:1.4;--rc-font-family:"PingFang SC", "Microsoft YaHei", "Segoe UI", Roboto, Helvetica, "noto sans sc", "hiragino sans gb", -apple-system, system-ui, sans-serif, Apple Color Emoji, Segoe UI Emoji, Not Color Emoji;--rc-radius-sm:4px;--rc-radius-md:8px;--rc-radius-lg:12px}._7eow1s1{--rc-text:#000;--rc-text-secondary:#262626;--rc-text-tertiary:#737373;--rc-text-quaternary:#a3a3a3;--rc-bg:#fff;--rc-bg-secondary:#fafafa;--rc-bg-tertiary:#f5f5f5;--rc-fill:#e8e8e8;--rc-fill-secondary:#eee;--rc-fill-tertiary:#f5f5f5;--rc-fill-quaternary:#fafafa;--rc-border:#f5f5f5;--rc-accent:#2563eb;--rc-accent-light:#2563eb20;--rc-link:#2563eb;--rc-code-text:#404040;--rc-code-bg:#f5f5f5;--rc-hr-border:#e5e5e5;--rc-quote-border:#2563eb;--rc-quote-bg:#f5f5f5;--rc-alert-info:#006bb7;--rc-alert-warning:#c50;--rc-alert-tip:#1c0;--rc-alert-caution:#c01;--rc-alert-important:#50c;--rc-max-width:700px;--rc-shadow-top-bar:0 8px 30px #0000001f, 0 2px 8px #0000000f;--rc-shadow-modal:0 10px 15px -3px #0000001a, 0 4px 6px -4px #0000001a;--rc-shadow-menu:0 1px 4px #0000000a, 0 4px 16px #00000014;--rc-space-xs:4px;--rc-space-sm:8px;--rc-space-md:16px;--rc-space-lg:24px;--rc-space-xl:32px;--rc-font-family-sans:"PingFang SC", "Microsoft YaHei", "Segoe UI", Roboto, Helvetica, "noto sans sc", "hiragino sans gb", -apple-system, system-ui, sans-serif, Apple Color Emoji, Segoe UI Emoji, Not Color Emoji;--rc-font-family-serif:"Noto Serif CJK SC", "Source Han Serif SC", "Source Han Serif", "source-han-serif-sc", "Songti SC", STSong, "华文宋体", serif;--rc-font-family-kai:"楷体", KaiTi, STKaiti, "Kaiti SC", "LXGW WenKai", "霞鹜文楷", "Noto Serif CJK SC", serif;--rc-font-mono:"SF Mono", SFMono-Regular, ui-monospace, "DejaVu Sans Mono", Menlo, Consolas, monospace;--rc-font-size-2xs:.625em;--rc-font-size-xs:.75em;--rc-font-size-sm:.8125em;--rc-font-size-md:.875em;--rc-font-size-lg:1.25em;--rc-font-size-base:16px;--rc-font-size-small:14px;--rc-line-height:1.8;--rc-line-height-tight:1.4;--rc-font-family:"Noto Serif CJK SC", "Source Han Serif SC", "Source Han Serif", "source-han-serif-sc", "Songti SC", STSong, "华文宋体", serif;--rc-radius-sm:4px;--rc-radius-md:8px;--rc-radius-lg:12px}._7eow1s2{--rc-text:#000;--rc-text-secondary:#262626;--rc-text-tertiary:#737373;--rc-text-quaternary:#a3a3a3;--rc-bg:#fff;--rc-bg-secondary:#fafafa;--rc-bg-tertiary:#f5f5f5;--rc-fill:#e8e8e8;--rc-fill-secondary:#eee;--rc-fill-tertiary:#f5f5f5;--rc-fill-quaternary:#fafafa;--rc-border:#f5f5f5;--rc-accent:#2563eb;--rc-accent-light:#2563eb20;--rc-link:#2563eb;--rc-code-text:#404040;--rc-code-bg:#f5f5f5;--rc-hr-border:#e5e5e5;--rc-quote-border:#a3a3a3;--rc-quote-bg:#fafafa;--rc-alert-info:#006bb7;--rc-alert-warning:#c50;--rc-alert-tip:#1c0;--rc-alert-caution:#c01;--rc-alert-important:#50c;--rc-max-width:none;--rc-shadow-top-bar:0 8px 30px #0000001f, 0 2px 8px #0000000f;--rc-shadow-modal:0 10px 15px -3px #0000001a, 0 4px 6px -4px #0000001a;--rc-shadow-menu:0 1px 4px #0000000a, 0 4px 16px #00000014;--rc-space-xs:2px;--rc-space-sm:4px;--rc-space-md:10px;--rc-space-lg:16px;--rc-space-xl:20px;--rc-font-family-sans:"PingFang SC", "Microsoft YaHei", "Segoe UI", Roboto, Helvetica, "noto sans sc", "hiragino sans gb", -apple-system, system-ui, sans-serif, Apple Color Emoji, Segoe UI Emoji, Not Color Emoji;--rc-font-family-serif:"Noto Serif CJK SC", "Source Han Serif SC", "Source Han Serif", "source-han-serif-sc", "Songti SC", STSong, "华文宋体", serif;--rc-font-family-kai:"楷体", KaiTi, STKaiti, "Kaiti SC", "LXGW WenKai", "霞鹜文楷", "Noto Serif CJK SC", serif;--rc-font-mono:"SF Mono", SFMono-Regular, ui-monospace, "DejaVu Sans Mono", Menlo, Consolas, monospace;--rc-font-size-2xs:.625em;--rc-font-size-xs:.75em;--rc-font-size-sm:.8125em;--rc-font-size-md:.875em;--rc-font-size-lg:1.25em;--rc-font-size-base:14px;--rc-font-size-small:12px;--rc-line-height:1.5;--rc-line-height-tight:1.3;--rc-font-family:"PingFang SC", "Microsoft YaHei", "Segoe UI", Roboto, Helvetica, "noto sans sc", "hiragino sans gb", -apple-system, system-ui, sans-serif, Apple Color Emoji, Segoe UI Emoji, Not Color Emoji;--rc-radius-sm:3px;--rc-radius-md:6px;--rc-radius-lg:12px}.dark ._7eow1s0,[data-theme=dark] ._7eow1s0,.dark._7eow1s0,[data-theme=dark]._7eow1s0,.dark ._7eow1s1,[data-theme=dark] ._7eow1s1,.dark._7eow1s1,[data-theme=dark]._7eow1s1,.dark ._7eow1s2,[data-theme=dark] ._7eow1s2,.dark._7eow1s2,[data-theme=dark]._7eow1s2{--rc-text:#fafafa;--rc-text-secondary:#a3a3a3;--rc-text-tertiary:#737373;--rc-text-quaternary:#525252;--rc-bg:#0a0a0a;--rc-bg-secondary:#171717;--rc-bg-tertiary:#262626;--rc-fill:#2a2a2a;--rc-fill-secondary:#222;--rc-fill-tertiary:#1a1a1a;--rc-fill-quaternary:#141414;--rc-border:#262626;--rc-accent:#60a5fa;--rc-accent-light:#60a5fa20;--rc-link:#60a5fa;--rc-code-text:#d4d4d4;--rc-code-bg:#262626;--rc-hr-border:#262626;--rc-quote-border:#60a5fa;--rc-quote-bg:#262626;--rc-alert-info:#7db9e5;--rc-alert-warning:#da864a;--rc-alert-tip:#54da48;--rc-alert-caution:#e16973;--rc-alert-important:#9966e0;--rc-shadow-top-bar:0 8px 30px #00000073, 0 2px 8px #0000004d;--rc-shadow-modal:0 10px 15px -3px #0006, 0 4px 6px -4px #00000059;--rc-shadow-menu:0 1px 4px #00000040, 0 4px 16px #0006}@keyframes _1n94osf1{0%{opacity:.16;-webkit-mask:linear-gradient(90deg,#000 25%,#000000e6 50%,#0000) 150% 0/400% no-repeat;mask:linear-gradient(90deg,#000 25%,#000000e6 50%,#0000) 150% 0/400% no-repeat}to{opacity:1;-webkit-mask:linear-gradient(90deg,#000 25%,#000000e6 50%,#0000) 0/400% no-repeat;mask:linear-gradient(90deg,#000 25%,#000000e6 50%,#0000) 0/400% no-repeat}}@keyframes _1n94osfa{to{transform:rotate(360deg)}}@keyframes _1n94osfi{0%{opacity:0}to{opacity:1}}._1n94osf0{text-align:center;width:var(--rich-image-display-width,auto);max-width:100%;margin:1.25rem auto}._1n94osf0[data-layout=align-left]{text-align:left;margin-left:0;margin-right:auto}._1n94osf0[data-layout=align-right]{text-align:right;margin-left:auto;margin-right:0}._1n94osf0[data-layout=float-left]{float:left;width:var(--rich-image-display-width,50%);margin:.25rem 1.5rem 1rem 0}._1n94osf0[data-layout=float-right]{float:right;width:var(--rich-image-display-width,50%);margin:.25rem 0 1rem 1.5rem}.rich-image-wrapper[data-layout^=float] ._1n94osf0{float:none;width:auto;margin:0}._1n94osf2{opacity:0;width:100%;max-width:100%;height:auto;display:block;border-radius:0!important}._1n94osf6{opacity:1;animation:.42s _1n94osf1}._1n94osf7{border-radius:var(--rc-radius-md);cursor:zoom-in;justify-content:center;align-items:center;min-height:3rem;transition:transform .25s;display:inline-flex;position:relative;overflow:hidden}._1n94osf7:hover{transform:translateY(-1px)}._1n94osf8{cursor:default}._1n94osf8:hover{transform:none}._1n94osf9{cursor:default}._1n94osf9:hover{transform:none}._1n94osfb{border:2px solid color-mix(in srgb, var(--rc-text-secondary) 45%, transparent);border-top-color:color-mix(in srgb, var(--rc-text) 65%, transparent);border-radius:50%;width:1.65rem;height:1.65rem;animation:.75s linear infinite _1n94osfa;position:absolute}._1n94osfc{white-space:nowrap;font-size:var(--rc-font-size-sm);letter-spacing:-.005em;color:#fff;-webkit-backdrop-filter:blur(20px)saturate(180%);background:#ff3b30a6;border-radius:6px;padding:.3rem .7rem;font-weight:500;position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)}._1n94osfd{color:var(--rc-text-tertiary);font-size:var(--rc-font-size-md);margin-top:.5rem;line-height:1.5}._1n94osfe{margin:var(--rc-space-md) 0;text-align:center}._1n94osff{border-radius:var(--rc-radius-md);transition:background-color .3s;display:inline-block;position:relative;overflow:hidden}._1n94osfg{opacity:0;transition:opacity .3s}._1n94osfh{opacity:1;transition:opacity .3s}._1n94osfj{z-index:9999;cursor:zoom-out;background-color:#000000d9;justify-content:center;align-items:center;animation:.2s _1n94osfi;display:flex;position:fixed;top:0;bottom:0;left:0;right:0}._1n94osfk{object-fit:contain;border-radius:0;max-width:90vw;max-height:90vh}.rich-image{margin:var(--rc-space-md) 0;text-align:center}.rich-image figcaption{font-size:var(--rc-font-size-md);color:var(--rc-text-secondary);margin-top:var(--rc-space-sm);line-height:var(--rc-line-height-tight)}.rich-image-container{border-radius:var(--rc-radius-md);transition:background-color .3s;display:inline-block;position:relative;overflow:hidden}.rich-image-hidden{opacity:0;transition:opacity .3s}.rich-image-visible{opacity:1;transition:opacity .3s}.rich-image-zoom-overlay{z-index:9999;cursor:zoom-out;background-color:#000000d9;justify-content:center;align-items:center;animation:.2s _1n94osfi;display:flex;position:fixed;top:0;bottom:0;left:0;right:0}.rich-image-zoom-img{object-fit:contain;border-radius:0;max-width:90vw;max-height:90vh}._1n94osfl{cursor:default;display:block;position:relative}._1n94osfm{border:2px dashed var(--rc-border);border-radius:var(--rc-radius-md);color:var(--rc-text-secondary);font-size:var(--rc-font-size-md);cursor:pointer;flex-direction:column;justify-content:center;align-items:center;gap:8px;padding:2rem;transition:border-color .2s,color .2s,background-color .2s;display:flex}._1n94osfm:hover{border-color:var(--rc-accent);color:var(--rc-text);background-color:color-mix(in srgb, var(--rc-accent) 8%, transparent)}._1n94osfn{z-index:20;border:1px solid var(--rc-border);background:color-mix(in srgb, var(--rc-bg) 96%, transparent);box-shadow:var(--rc-shadow-top-bar);opacity:0;pointer-events:none;border-radius:10px;align-items:center;gap:4px;padding:4px;transition:opacity .15s;display:inline-flex;position:absolute;top:-2.5rem;left:50%;transform:translate(-50%)}._1n94osfo{opacity:1;pointer-events:auto}._1n94osfp{width:30px;height:30px;color:var(--rc-text-secondary);cursor:pointer;background:0 0;border:none;border-radius:8px;justify-content:center;align-items:center;transition:background-color .15s,color .15s;display:inline-flex}._1n94osfp:hover{color:var(--rc-text);background-color:var(--rc-fill-secondary)}._1n94osfq:hover{color:var(--rc-alert-caution);background-color:color-mix(in srgb, var(--rc-alert-caution) 12%, transparent)}._1n94osfr{width:360px;font-size:var(--rc-font-size-base);font-family:var(--rc-font-family);z-index:30;flex-direction:column;gap:8px;padding:12px;display:flex;position:relative}._1n94osfs{background-color:var(--rc-bg-secondary);border-radius:6px;align-items:center;gap:8px;min-width:0;padding:6px 10px;display:flex}._1n94osft{color:var(--rc-text-secondary);flex-shrink:0}._1n94osfu{-webkit-appearance:none;appearance:none;color:inherit;font-size:var(--rc-font-size-sm);background-color:#0000;border:none;outline:none;flex:1;min-width:0;padding:0}._1n94osfu::placeholder{color:var(--rc-text-secondary)}._1n94osfv{border-radius:var(--rc-radius-md);border:1.5px dashed var(--rc-border);min-height:138px;color:var(--rc-text-secondary);cursor:pointer;flex-direction:column;justify-content:center;align-items:center;gap:.45rem;transition:border-color .15s,background-color .15s;display:flex}._1n94osfv:hover{border-color:color-mix(in srgb, var(--rc-accent) 45%, transparent);color:var(--rc-text);background-color:color-mix(in srgb, var(--rc-accent) 7%, transparent)}._1n94osfw{border-radius:var(--rc-radius-md);border:1px solid var(--rc-border);background-color:color-mix(in srgb, var(--rc-text) 2%, transparent);overflow:hidden}._1n94osfw img{object-fit:cover;width:100%;max-height:188px;display:block}._1n94osfx{color:var(--rc-text-secondary);font-size:var(--rc-font-size-xs);align-items:center;gap:.4rem;display:inline-flex}._1n94osfy{cursor:ew-resize;touch-action:none;opacity:0;z-index:10;background:#ffffffeb;border:1px solid #0000002e;border-radius:9999px;width:6px;height:36px;max-height:50%;transition:opacity .15s;position:absolute;top:50%;transform:translateY(-50%);box-shadow:0 1px 3px #00000040}._1n94osfz{left:6px}._1n94osf10{right:6px}._1n94osf11{opacity:1}._1n94osf12{font-family:var(--rc-font-family);z-index:30;align-items:center;gap:4px;padding:4px;display:flex}._1n94osf13{height:26px;color:var(--rc-text-secondary);font-size:var(--rc-font-size-xs);cursor:pointer;background:0 0;border:none;border-radius:6px;justify-content:center;align-items:center;padding:0 8px;font-weight:500;transition:background-color .15s,color .15s;display:inline-flex}._1n94osf13:hover,._1n94osf14{color:var(--rc-text);background-color:var(--rc-fill-secondary)}@media (max-width:640px){._1n94osf0[data-layout=float-left],._1n94osf0[data-layout=float-right]{float:none;width:auto;margin:1.25rem auto}}
2
2
  /*$vite$:1*/
package/dist/static.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import { t as ImageRenderer } from "./ImageRenderer-BihkEC_w.js";
1
+ import { t as ImageRenderer } from "./ImageRenderer-DGTS4o75.js";
2
2
  export { ImageRenderer };
@@ -21,6 +21,7 @@ export declare const semanticClassNames: {
21
21
  readonly replaceUploadArea: "rr-image-replace-upload-area";
22
22
  readonly replacePreview: "rr-image-replace-preview";
23
23
  readonly panelHint: "rr-image-panel-hint";
24
+ readonly resizeHandle: "rr-image-resize-handle";
24
25
  };
25
26
  export declare const root: string;
26
27
  export declare const image: string;
@@ -59,4 +60,11 @@ export declare const editInput: string;
59
60
  export declare const replaceUploadArea: string;
60
61
  export declare const replacePreview: string;
61
62
  export declare const panelHint: string;
63
+ export declare const resizeHandle: string;
64
+ export declare const resizeHandleLeft: string;
65
+ export declare const resizeHandleRight: string;
66
+ export declare const resizeHandleVisible: string;
67
+ export declare const controlPanel: string;
68
+ export declare const sizeOption: string;
69
+ export declare const editToolbarButtonActive: string;
62
70
  //# sourceMappingURL=styles.css.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"styles.css.d.ts","sourceRoot":"","sources":["../src/styles.css.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;CAuBrB,CAAC;AAEX,eAAO,MAAM,IAAI,QAGf,CAAC;AAaH,eAAO,MAAM,KAAK,QAOhB,CAAC;AAEH,eAAO,MAAM,UAAU,gDAIrB,CAAC;AAEH,eAAO,MAAM,YAAY,QAGvB,CAAC;AAEH,eAAO,MAAM,KAAK,QAehB,CAAC;AAEH,eAAO,MAAM,aAAa,QAOxB,CAAC;AAEH,eAAO,MAAM,WAAW,QAOtB,CAAC;AAIH,eAAO,MAAM,MAAM,QAQjB,CAAC;AAEH,eAAO,MAAM,UAAU,QAerB,CAAC;AAEH,eAAO,MAAM,OAAO,QAKlB,CAAC;AAEH,eAAO,MAAM,yBAAyB;;;;;;;CAO5B,CAAC;AAgCX,eAAO,MAAM,WAAW,QAA2B,CAAC;AACpD,eAAO,MAAM,gBAAgB,QAAgC,CAAC;AAC9D,eAAO,MAAM,aAAa,QAA6B,CAAC;AACxD,eAAO,MAAM,cAAc,QAA8B,CAAC;AA0B1D,eAAO,MAAM,kBAAkB,QAAkC,CAAC;AAClE,eAAO,MAAM,gBAAgB,QAAgC,CAAC;AAU9D,eAAO,MAAM,WAAW,QAItB,CAAC;AAEH,eAAO,MAAM,eAAe,QAoB1B,CAAC;AAEH,eAAO,MAAM,WAAW,QAiBtB,CAAC;AAEH,eAAO,MAAM,kBAAkB,QAG7B,CAAC;AAEH,eAAO,MAAM,iBAAiB,QAkB5B,CAAC;AAEH,eAAO,MAAM,uBAAuB,QAOlC,CAAC;AAEH,eAAO,MAAM,SAAS,QAUpB,CAAC;AAEH,eAAO,MAAM,SAAS,QAQpB,CAAC;AAEH,eAAO,MAAM,aAAa,QAGxB,CAAC;AAEH,eAAO,MAAM,SAAS,QAepB,CAAC;AAEH,eAAO,MAAM,iBAAiB,QAmB5B,CAAC;AAEH,eAAO,MAAM,cAAc,QAKzB,CAAC;AASH,eAAO,MAAM,SAAS,QAMpB,CAAC"}
1
+ {"version":3,"file":"styles.css.d.ts","sourceRoot":"","sources":["../src/styles.css.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;CAwBrB,CAAC;AAEX,eAAO,MAAM,IAAI,QAsCf,CAAC;AAsBH,eAAO,MAAM,KAAK,QAOhB,CAAC;AAEH,eAAO,MAAM,UAAU,gDAIrB,CAAC;AAEH,eAAO,MAAM,YAAY,QAGvB,CAAC;AAEH,eAAO,MAAM,KAAK,QAehB,CAAC;AAEH,eAAO,MAAM,aAAa,QAOxB,CAAC;AAEH,eAAO,MAAM,WAAW,QAOtB,CAAC;AAIH,eAAO,MAAM,MAAM,QAQjB,CAAC;AAEH,eAAO,MAAM,UAAU,QAerB,CAAC;AAEH,eAAO,MAAM,OAAO,QAKlB,CAAC;AAEH,eAAO,MAAM,yBAAyB;;;;;;;CAO5B,CAAC;AAgCX,eAAO,MAAM,WAAW,QAA2B,CAAC;AACpD,eAAO,MAAM,gBAAgB,QAAgC,CAAC;AAC9D,eAAO,MAAM,aAAa,QAA6B,CAAC;AACxD,eAAO,MAAM,cAAc,QAA8B,CAAC;AA0B1D,eAAO,MAAM,kBAAkB,QAAkC,CAAC;AAClE,eAAO,MAAM,gBAAgB,QAAgC,CAAC;AAU9D,eAAO,MAAM,WAAW,QAItB,CAAC;AAEH,eAAO,MAAM,eAAe,QAoB1B,CAAC;AAEH,eAAO,MAAM,WAAW,QAiBtB,CAAC;AAEH,eAAO,MAAM,kBAAkB,QAG7B,CAAC;AAEH,eAAO,MAAM,iBAAiB,QAkB5B,CAAC;AAEH,eAAO,MAAM,uBAAuB,QAOlC,CAAC;AAEH,eAAO,MAAM,SAAS,QAUpB,CAAC;AAEH,eAAO,MAAM,SAAS,QAQpB,CAAC;AAEH,eAAO,MAAM,aAAa,QAGxB,CAAC;AAEH,eAAO,MAAM,SAAS,QAepB,CAAC;AAEH,eAAO,MAAM,iBAAiB,QAmB5B,CAAC;AAEH,eAAO,MAAM,cAAc,QAKzB,CAAC;AASH,eAAO,MAAM,SAAS,QAMpB,CAAC;AAEH,eAAO,MAAM,YAAY,QAgBvB,CAAC;AAEH,eAAO,MAAM,gBAAgB,QAAqB,CAAC;AACnD,eAAO,MAAM,iBAAiB,QAAsB,CAAC;AAErD,eAAO,MAAM,mBAAmB,QAE9B,CAAC;AAEH,eAAO,MAAM,YAAY,QAOvB,CAAC;AAEH,eAAO,MAAM,UAAU,QAoBrB,CAAC;AAEH,eAAO,MAAM,uBAAuB,QAGlC,CAAC"}
@@ -1,3 +1,4 @@
1
+ import { ImageLayout } from '@haklex/rich-editor/nodes';
1
2
  export declare function useImageActions(): {
2
3
  commitMeta: () => void;
3
4
  closeReplacePanel: () => void;
@@ -9,5 +10,7 @@ export declare function useImageActions(): {
9
10
  handleDuplicate: () => void;
10
11
  handleDownload: () => void;
11
12
  handleDelete: () => void;
13
+ handleSetDisplayWidth: (width?: number) => void;
14
+ handleSetLayout: (layout?: ImageLayout) => void;
12
15
  };
13
16
  //# sourceMappingURL=useImageActions.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useImageActions.d.ts","sourceRoot":"","sources":["../src/useImageActions.ts"],"names":[],"mappings":"AAoDA,wBAAgB,eAAe;;;8BA+Ed,IAAI,GAAG,IAAI;;;wCA6Db,OAAO;;;;;EAmBrB"}
1
+ {"version":3,"file":"useImageActions.d.ts","sourceRoot":"","sources":["../src/useImageActions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAqD7D,wBAAgB,eAAe;;;8BAmGd,IAAI,GAAG,IAAI;;;wCA6Db,OAAO;;;;;oCA/ET,MAAM;+BASL,WAAW;EA2FxB"}
@@ -0,0 +1,5 @@
1
+ export type ResizeSide = 'left' | 'right';
2
+ export declare function useImageResize(): {
3
+ handlePointerDown: (event: React.PointerEvent<HTMLElement>, side: ResizeSide) => void;
4
+ };
5
+ //# sourceMappingURL=useImageResize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useImageResize.d.ts","sourceRoot":"","sources":["../src/useImageResize.ts"],"names":[],"mappings":"AASA,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,OAAO,CAAC;AAI1C,wBAAgB,cAAc;+BAQlB,KAAK,CAAC,YAAY,CAAC,WAAW,CAAC,QAAQ,UAAU;EAgF5D"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@haklex/rich-renderer-image",
3
- "version": "0.22.0",
3
+ "version": "0.23.0",
4
4
  "description": "Image renderer with blurhash",
5
5
  "repository": {
6
6
  "type": "git",
@@ -46,9 +46,9 @@
46
46
  "lucide-react": "^1.0.0",
47
47
  "react": ">=19",
48
48
  "react-dom": ">=19",
49
- "@haklex/rich-editor": "0.22.0",
50
- "@haklex/rich-editor-ui": "0.22.0",
51
- "@haklex/rich-style-token": "0.22.0"
49
+ "@haklex/rich-editor": "0.23.0",
50
+ "@haklex/rich-editor-ui": "0.23.0",
51
+ "@haklex/rich-style-token": "0.23.0"
52
52
  },
53
53
  "publishConfig": {
54
54
  "access": "public"