@zuilib/text-editor 0.5.0 → 0.7.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.
- package/CHANGELOG.md +71 -0
- package/DRAWING_FORMAT.md +11 -5
- package/README.md +122 -26
- package/dist/index.d.ts +108 -24
- package/dist/index.js +302 -181
- package/dist/styles.css +190 -163
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
// src/EditorRoot.tsx
|
|
2
2
|
import {
|
|
3
|
-
createContext,
|
|
4
3
|
useCallback as useCallback2,
|
|
5
|
-
useContext,
|
|
6
4
|
useEffect as useEffect8,
|
|
7
5
|
useMemo as useMemo2,
|
|
8
6
|
useRef as useRef5,
|
|
@@ -308,6 +306,18 @@ import { $getNodeByKey as $getNodeByKey2 } from "lexical";
|
|
|
308
306
|
import { useLexicalComposerContext as useLexicalComposerContext5 } from "@lexical/react/LexicalComposerContext";
|
|
309
307
|
import { useLexicalEditable } from "@lexical/react/useLexicalEditable";
|
|
310
308
|
|
|
309
|
+
// src/drawing/focusCommand.ts
|
|
310
|
+
import { createCommand } from "lexical";
|
|
311
|
+
var DRAWING_FOCUS_COMMAND = createCommand(
|
|
312
|
+
"DRAWING_FOCUS_COMMAND"
|
|
313
|
+
);
|
|
314
|
+
|
|
315
|
+
// src/blockWidth.ts
|
|
316
|
+
var BLOCK_WIDTHS = ["full", "text", "content"];
|
|
317
|
+
function isBlockWidth(value) {
|
|
318
|
+
return typeof value === "string" && BLOCK_WIDTHS.includes(value);
|
|
319
|
+
}
|
|
320
|
+
|
|
311
321
|
// src/drawing/types.ts
|
|
312
322
|
var BOX_TYPES = [
|
|
313
323
|
"rect",
|
|
@@ -393,8 +403,9 @@ function normalizeDrawingData(parsed) {
|
|
|
393
403
|
version: 2,
|
|
394
404
|
canvasHeight: Number.isFinite(height) && height >= MIN_CANVAS_HEIGHT ? height : DEFAULT_CANVAS_HEIGHT,
|
|
395
405
|
...Number.isFinite(canvasWidth) && canvasWidth >= 120 ? { canvasWidth } : {},
|
|
396
|
-
// `full`
|
|
397
|
-
|
|
406
|
+
// `full` stays implicit unless the payload spells it out; unknown
|
|
407
|
+
// values (newer versions) are dropped rather than rejected
|
|
408
|
+
...isBlockWidth(parsed.width) ? { width: parsed.width } : {},
|
|
398
409
|
// Bindings to ids that don't exist (or aren't boxes) are dropped
|
|
399
410
|
shapes: shapes.map((shape) => {
|
|
400
411
|
if (!isConnectorType(shape.type)) return shape;
|
|
@@ -1641,7 +1652,6 @@ function PropertyBar({
|
|
|
1641
1652
|
|
|
1642
1653
|
// src/drawing/canvas/SelectionOverlay.tsx
|
|
1643
1654
|
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
1644
|
-
var SELECTION_COLOR = "#6965db";
|
|
1645
1655
|
var HANDLE = 7;
|
|
1646
1656
|
function Handle({
|
|
1647
1657
|
x,
|
|
@@ -1653,8 +1663,6 @@ function Handle({
|
|
|
1653
1663
|
}) {
|
|
1654
1664
|
const props = {
|
|
1655
1665
|
className: "zui-drawing-handle",
|
|
1656
|
-
fill: "#fff",
|
|
1657
|
-
stroke: SELECTION_COLOR,
|
|
1658
1666
|
strokeWidth: 1.5,
|
|
1659
1667
|
style: { cursor },
|
|
1660
1668
|
onPointerDown
|
|
@@ -1683,12 +1691,10 @@ function SelectionOverlay({
|
|
|
1683
1691
|
ghosts.map(({ index, x, y }) => /* @__PURE__ */ jsx3(
|
|
1684
1692
|
"circle",
|
|
1685
1693
|
{
|
|
1686
|
-
className: "zui-drawing-ghost",
|
|
1694
|
+
className: "zui-drawing-handle zui-drawing-ghost",
|
|
1687
1695
|
cx: x,
|
|
1688
1696
|
cy: y,
|
|
1689
1697
|
r: 4.5,
|
|
1690
|
-
fill: "#fff",
|
|
1691
|
-
stroke: SELECTION_COLOR,
|
|
1692
1698
|
strokeWidth: 1.5,
|
|
1693
1699
|
strokeDasharray: "2 2",
|
|
1694
1700
|
style: { cursor: "copy" },
|
|
@@ -1784,7 +1790,7 @@ function SelectionFrame({ rect, pad }) {
|
|
|
1784
1790
|
height: rect.h + pad * 2,
|
|
1785
1791
|
rx: 6,
|
|
1786
1792
|
fill: "none",
|
|
1787
|
-
stroke:
|
|
1793
|
+
stroke: "currentColor",
|
|
1788
1794
|
strokeWidth: 1,
|
|
1789
1795
|
strokeDasharray: "5 4",
|
|
1790
1796
|
pointerEvents: "none"
|
|
@@ -1815,7 +1821,7 @@ function GroupSelectionOverlay({
|
|
|
1815
1821
|
height: r.h + 6,
|
|
1816
1822
|
rx: 4,
|
|
1817
1823
|
fill: "none",
|
|
1818
|
-
stroke:
|
|
1824
|
+
stroke: "currentColor",
|
|
1819
1825
|
strokeWidth: 1,
|
|
1820
1826
|
opacity: 0.45
|
|
1821
1827
|
},
|
|
@@ -1828,14 +1834,15 @@ function MarqueeOverlay({ rect }) {
|
|
|
1828
1834
|
return /* @__PURE__ */ jsx3(
|
|
1829
1835
|
"rect",
|
|
1830
1836
|
{
|
|
1837
|
+
className: "zui-drawing-selection",
|
|
1831
1838
|
x: rect.x,
|
|
1832
1839
|
y: rect.y,
|
|
1833
1840
|
width: rect.w,
|
|
1834
1841
|
height: rect.h,
|
|
1835
1842
|
rx: 3,
|
|
1836
|
-
fill:
|
|
1843
|
+
fill: "currentColor",
|
|
1837
1844
|
fillOpacity: 0.08,
|
|
1838
|
-
stroke:
|
|
1845
|
+
stroke: "currentColor",
|
|
1839
1846
|
strokeWidth: 1,
|
|
1840
1847
|
pointerEvents: "none"
|
|
1841
1848
|
}
|
|
@@ -1989,7 +1996,6 @@ function BoxGeometry({
|
|
|
1989
1996
|
// src/drawing/canvas/ShapeView.tsx
|
|
1990
1997
|
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1991
1998
|
import { createElement } from "react";
|
|
1992
|
-
var FONT_FAMILY = "ui-sans-serif, system-ui, sans-serif";
|
|
1993
1999
|
var CONNECTOR_FONT_SIZE = 12;
|
|
1994
2000
|
var CONNECTOR_LABEL_MAX_WIDTH = 160;
|
|
1995
2001
|
function slotLayout(shape) {
|
|
@@ -2025,7 +2031,6 @@ function BoxTexts({
|
|
|
2025
2031
|
const mainStart = area.y + area.h / 2 - (mainLines.length - 1) * mainLineH / 2 + FONT_SIZE * 0.35;
|
|
2026
2032
|
const common = {
|
|
2027
2033
|
fill: shape.stroke,
|
|
2028
|
-
fontFamily: FONT_FAMILY,
|
|
2029
2034
|
textAnchor: "middle"
|
|
2030
2035
|
};
|
|
2031
2036
|
return /* @__PURE__ */ jsxs5("g", { children: [
|
|
@@ -2123,7 +2128,7 @@ function ConnectorLabel({
|
|
|
2123
2128
|
width: size.w + 10,
|
|
2124
2129
|
height: size.h + 6,
|
|
2125
2130
|
rx: 5,
|
|
2126
|
-
|
|
2131
|
+
className: "zui-drawing-label-plate",
|
|
2127
2132
|
opacity: 0.94
|
|
2128
2133
|
}
|
|
2129
2134
|
),
|
|
@@ -2134,7 +2139,6 @@ function ConnectorLabel({
|
|
|
2134
2139
|
y: startY + i * lineH,
|
|
2135
2140
|
fill: shape.stroke,
|
|
2136
2141
|
fontSize: CONNECTOR_FONT_SIZE,
|
|
2137
|
-
fontFamily: FONT_FAMILY,
|
|
2138
2142
|
textAnchor: "middle",
|
|
2139
2143
|
style: textStyle,
|
|
2140
2144
|
children: line
|
|
@@ -2179,7 +2183,6 @@ function ShapeView({
|
|
|
2179
2183
|
y: shape.y + FONT_SIZE,
|
|
2180
2184
|
fill: shape.stroke,
|
|
2181
2185
|
fontSize: FONT_SIZE,
|
|
2182
|
-
fontFamily: FONT_FAMILY,
|
|
2183
2186
|
style: { userSelect: "none", whiteSpace: "pre" },
|
|
2184
2187
|
children: (shape.text ?? "").split("\n").map((line, i) => /* @__PURE__ */ jsx5("tspan", { x: shape.x, dy: i === 0 ? 0 : FONT_SIZE * LINE_HEIGHT, children: line }, i))
|
|
2185
2188
|
}
|
|
@@ -2251,7 +2254,7 @@ function TextEditOverlay({
|
|
|
2251
2254
|
}, []);
|
|
2252
2255
|
const style = {
|
|
2253
2256
|
color: shape.stroke,
|
|
2254
|
-
fontFamily:
|
|
2257
|
+
fontFamily: "var(--zui-drawing-font)",
|
|
2255
2258
|
lineHeight: LINE_HEIGHT
|
|
2256
2259
|
};
|
|
2257
2260
|
if (shape.type === "text") {
|
|
@@ -2335,6 +2338,14 @@ var BLOCK_WIDTH_OPTIONS = [
|
|
|
2335
2338
|
/* @__PURE__ */ jsx7("path", { d: "M6 10h8M8.5 7.5L6 10l2.5 2.5M11.5 7.5L14 10l-2.5 2.5" })
|
|
2336
2339
|
] })
|
|
2337
2340
|
},
|
|
2341
|
+
{
|
|
2342
|
+
width: "text",
|
|
2343
|
+
label: "Text width",
|
|
2344
|
+
icon: /* @__PURE__ */ jsxs6(Fragment, { children: [
|
|
2345
|
+
/* @__PURE__ */ jsx7("path", { d: "M3 4v12M17 4v12" }),
|
|
2346
|
+
/* @__PURE__ */ jsx7("path", { d: "M6.5 7h7M6.5 10h7M6.5 13h4.5" })
|
|
2347
|
+
] })
|
|
2348
|
+
},
|
|
2338
2349
|
{
|
|
2339
2350
|
width: "content",
|
|
2340
2351
|
label: "Content width",
|
|
@@ -2482,6 +2493,11 @@ function DrawingToolbar({
|
|
|
2482
2493
|
import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
2483
2494
|
var MIN_HEIGHT = 120;
|
|
2484
2495
|
var MAX_HEIGHT = 1200;
|
|
2496
|
+
var WIDTH_CLASS = {
|
|
2497
|
+
full: "",
|
|
2498
|
+
text: "is-text-width",
|
|
2499
|
+
content: "is-content-width"
|
|
2500
|
+
};
|
|
2485
2501
|
var MIN_CONTENT_WIDTH = 240;
|
|
2486
2502
|
var CONTENT_WIDTH_PADDING = 40;
|
|
2487
2503
|
var EMPTY_SET = /* @__PURE__ */ new Set();
|
|
@@ -2564,11 +2580,12 @@ function DrawingCanvas({ nodeKey, data }) {
|
|
|
2564
2580
|
const commit = useCallback(
|
|
2565
2581
|
(nextShapes, options) => {
|
|
2566
2582
|
const nextWidth = options?.width ?? widthRef.current;
|
|
2583
|
+
const explicitFull = options?.width === void 0 && data.width !== void 0;
|
|
2567
2584
|
const payload = {
|
|
2568
2585
|
version: 2,
|
|
2569
2586
|
...canvasWidth ? { canvasWidth } : {},
|
|
2570
2587
|
canvasHeight: options?.height ?? heightRef.current,
|
|
2571
|
-
...nextWidth
|
|
2588
|
+
...nextWidth !== "full" || explicitFull ? { width: nextWidth } : {},
|
|
2572
2589
|
shapes: nextShapes
|
|
2573
2590
|
};
|
|
2574
2591
|
const json = serializeDrawingData(payload);
|
|
@@ -2579,7 +2596,7 @@ function DrawingCanvas({ nodeKey, data }) {
|
|
|
2579
2596
|
if ($isDrawingNode(node)) node.setData(payload);
|
|
2580
2597
|
});
|
|
2581
2598
|
},
|
|
2582
|
-
[editor, nodeKey, canvasWidth]
|
|
2599
|
+
[editor, nodeKey, canvasWidth, data.width]
|
|
2583
2600
|
);
|
|
2584
2601
|
const updateShapes = useCallback(
|
|
2585
2602
|
(updater, options) => {
|
|
@@ -2965,8 +2982,13 @@ function DrawingCanvas({ nodeKey, data }) {
|
|
|
2965
2982
|
"div",
|
|
2966
2983
|
{
|
|
2967
2984
|
ref: rootRef,
|
|
2968
|
-
className: `zui-drawing-canvas ${width
|
|
2985
|
+
className: `zui-drawing-canvas ${WIDTH_CLASS[width]} ${isEditable ? "is-editable" : ""}`,
|
|
2969
2986
|
tabIndex: isEditable ? 0 : void 0,
|
|
2987
|
+
onFocus: () => editor.dispatchCommand(DRAWING_FOCUS_COMMAND, nodeKey),
|
|
2988
|
+
onBlur: (e) => {
|
|
2989
|
+
if (rootRef.current?.contains(e.relatedTarget)) return;
|
|
2990
|
+
editor.dispatchCommand(DRAWING_FOCUS_COMMAND, null);
|
|
2991
|
+
},
|
|
2970
2992
|
children: [
|
|
2971
2993
|
isEditable && /* @__PURE__ */ jsxs8("div", { className: "zui-drawing-toolbar", onPointerDown: (e) => e.stopPropagation(), children: [
|
|
2972
2994
|
/* @__PURE__ */ jsx9(
|
|
@@ -2997,118 +3019,120 @@ function DrawingCanvas({ nodeKey, data }) {
|
|
|
2997
3019
|
}
|
|
2998
3020
|
) })
|
|
2999
3021
|
] }),
|
|
3000
|
-
/* @__PURE__ */ jsxs8(
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
|
|
3005
|
-
|
|
3006
|
-
|
|
3007
|
-
|
|
3008
|
-
|
|
3009
|
-
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
|
|
3015
|
-
|
|
3016
|
-
|
|
3017
|
-
|
|
3018
|
-
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
|
|
3023
|
-
|
|
3024
|
-
|
|
3025
|
-
|
|
3026
|
-
|
|
3027
|
-
|
|
3028
|
-
|
|
3029
|
-
},
|
|
3030
|
-
children: [
|
|
3031
|
-
shapes.map((shape) => /* @__PURE__ */ jsxs8(
|
|
3032
|
-
"g",
|
|
3033
|
-
{
|
|
3034
|
-
"data-shape-id": shape.id,
|
|
3035
|
-
className: `zui-drawing-shape ${selectedIds.has(shape.id) ? "is-selected" : ""}`,
|
|
3036
|
-
style: { cursor: isEditable && tool === "select" ? "move" : void 0 },
|
|
3037
|
-
onPointerDown: (e) => handleShapePointerDown(e, shape),
|
|
3038
|
-
children: [
|
|
3039
|
-
/* @__PURE__ */ jsx9(HitArea, { shape, points: paths.get(shape.id) }),
|
|
3040
|
-
shape.id === editingText?.id && shape.type === "text" ? null : /* @__PURE__ */ jsx9(
|
|
3041
|
-
ShapeView,
|
|
3042
|
-
{
|
|
3043
|
-
shape,
|
|
3044
|
-
points: paths.get(shape.id),
|
|
3045
|
-
hideField: shape.id === editingText?.id ? editingText.field : null,
|
|
3046
|
-
showHints: isEditable && tool === "select" && single?.id === shape.id && shape.id !== editingText?.id
|
|
3047
|
-
}
|
|
3048
|
-
)
|
|
3049
|
-
]
|
|
3050
|
-
},
|
|
3051
|
-
shape.id
|
|
3052
|
-
)),
|
|
3053
|
-
hoverBox && /* @__PURE__ */ jsx9(
|
|
3054
|
-
"polygon",
|
|
3055
|
-
{
|
|
3056
|
-
className: "zui-drawing-bind-target",
|
|
3057
|
-
points: boxOutline(hoverBox).map((p) => `${p.x},${p.y}`).join(" "),
|
|
3058
|
-
fill: SELECTION_COLOR,
|
|
3059
|
-
fillOpacity: 0.06,
|
|
3060
|
-
stroke: SELECTION_COLOR,
|
|
3061
|
-
strokeWidth: 2,
|
|
3062
|
-
strokeLinejoin: "round",
|
|
3063
|
-
pointerEvents: "none"
|
|
3064
|
-
}
|
|
3065
|
-
),
|
|
3066
|
-
single && isEditable && !editingText && /* @__PURE__ */ jsx9(
|
|
3067
|
-
SelectionOverlay,
|
|
3068
|
-
{
|
|
3069
|
-
shape: single,
|
|
3070
|
-
points: paths.get(single.id) ?? [],
|
|
3071
|
-
onHandlePointerDown: handleHandlePointerDown,
|
|
3072
|
-
onWaypointAdd: addWaypoint,
|
|
3073
|
-
onWaypointRemove: removeWaypoint
|
|
3022
|
+
/* @__PURE__ */ jsxs8("div", { className: "zui-drawing-stage", children: [
|
|
3023
|
+
/* @__PURE__ */ jsxs8(
|
|
3024
|
+
"svg",
|
|
3025
|
+
{
|
|
3026
|
+
ref: svgRef,
|
|
3027
|
+
className: "zui-drawing-surface",
|
|
3028
|
+
style: {
|
|
3029
|
+
height: logicalWidth ? void 0 : canvasHeight,
|
|
3030
|
+
width: logicalWidth ?? void 0,
|
|
3031
|
+
maxWidth: "100%",
|
|
3032
|
+
aspectRatio: logicalWidth ? `${logicalWidth} / ${canvasHeight}` : void 0,
|
|
3033
|
+
cursor: canvasCursor
|
|
3034
|
+
},
|
|
3035
|
+
viewBox: logicalWidth ? `0 0 ${logicalWidth} ${canvasHeight}` : void 0,
|
|
3036
|
+
preserveAspectRatio: "xMinYMin meet",
|
|
3037
|
+
onPointerDown: handleBackgroundPointerDown,
|
|
3038
|
+
onPointerMove: handlePointerMove,
|
|
3039
|
+
onPointerUp: handlePointerUp,
|
|
3040
|
+
onPointerCancel: handlePointerUp,
|
|
3041
|
+
onDoubleClick: (e) => {
|
|
3042
|
+
if (!isEditable) return;
|
|
3043
|
+
const target = e.target.closest("[data-shape-id]");
|
|
3044
|
+
const id = target?.getAttribute("data-shape-id");
|
|
3045
|
+
const shape = id ? shapes.find((s) => s.id === id) : null;
|
|
3046
|
+
if (!shape) return;
|
|
3047
|
+
if (shape.type === "text" || isConnectorType(shape.type)) {
|
|
3048
|
+
startTextEditing(shape.id, "text");
|
|
3049
|
+
} else {
|
|
3050
|
+
startTextEditing(shape.id, slotAt(shape, getPoint(e).y));
|
|
3074
3051
|
}
|
|
3075
|
-
),
|
|
3076
|
-
selection.length > 1 && isEditable && /* @__PURE__ */ jsx9(GroupSelectionOverlay, { shapes: selection, paths }),
|
|
3077
|
-
marquee && /* @__PURE__ */ jsx9(MarqueeOverlay, { rect: marqueeRect(marquee.origin, marquee.current) })
|
|
3078
|
-
]
|
|
3079
|
-
}
|
|
3080
|
-
),
|
|
3081
|
-
isEditable && shapes.length === 0 && /* @__PURE__ */ jsx9("div", { className: "zui-drawing-empty", "aria-hidden": "true", children: "Pick a shape above, then click or drag on the canvas" }),
|
|
3082
|
-
editingShape && editingText && /* @__PURE__ */ jsx9(
|
|
3083
|
-
"div",
|
|
3084
|
-
{
|
|
3085
|
-
className: "zui-drawing-overlay",
|
|
3086
|
-
style: {
|
|
3087
|
-
transform: `scale(${scale})`,
|
|
3088
|
-
width: logicalWidth ?? void 0,
|
|
3089
|
-
height: logicalWidth ? canvasHeight : void 0
|
|
3090
|
-
},
|
|
3091
|
-
children: /* @__PURE__ */ jsx9(
|
|
3092
|
-
TextEditOverlay,
|
|
3093
|
-
{
|
|
3094
|
-
shape: editingShape,
|
|
3095
|
-
field: editingText.field,
|
|
3096
|
-
points: paths.get(editingShape.id),
|
|
3097
|
-
onCommit: commitText
|
|
3098
3052
|
},
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
-
|
|
3110
|
-
|
|
3111
|
-
|
|
3053
|
+
children: [
|
|
3054
|
+
shapes.map((shape) => /* @__PURE__ */ jsxs8(
|
|
3055
|
+
"g",
|
|
3056
|
+
{
|
|
3057
|
+
"data-shape-id": shape.id,
|
|
3058
|
+
className: `zui-drawing-shape ${selectedIds.has(shape.id) ? "is-selected" : ""}`,
|
|
3059
|
+
style: { cursor: isEditable && tool === "select" ? "move" : void 0 },
|
|
3060
|
+
onPointerDown: (e) => handleShapePointerDown(e, shape),
|
|
3061
|
+
children: [
|
|
3062
|
+
/* @__PURE__ */ jsx9(HitArea, { shape, points: paths.get(shape.id) }),
|
|
3063
|
+
shape.id === editingText?.id && shape.type === "text" ? null : /* @__PURE__ */ jsx9(
|
|
3064
|
+
ShapeView,
|
|
3065
|
+
{
|
|
3066
|
+
shape,
|
|
3067
|
+
points: paths.get(shape.id),
|
|
3068
|
+
hideField: shape.id === editingText?.id ? editingText.field : null,
|
|
3069
|
+
showHints: isEditable && tool === "select" && single?.id === shape.id && shape.id !== editingText?.id
|
|
3070
|
+
}
|
|
3071
|
+
)
|
|
3072
|
+
]
|
|
3073
|
+
},
|
|
3074
|
+
shape.id
|
|
3075
|
+
)),
|
|
3076
|
+
hoverBox && /* @__PURE__ */ jsx9(
|
|
3077
|
+
"polygon",
|
|
3078
|
+
{
|
|
3079
|
+
className: "zui-drawing-selection zui-drawing-bind-target",
|
|
3080
|
+
points: boxOutline(hoverBox).map((p) => `${p.x},${p.y}`).join(" "),
|
|
3081
|
+
fill: "currentColor",
|
|
3082
|
+
fillOpacity: 0.06,
|
|
3083
|
+
stroke: "currentColor",
|
|
3084
|
+
strokeWidth: 2,
|
|
3085
|
+
strokeLinejoin: "round",
|
|
3086
|
+
pointerEvents: "none"
|
|
3087
|
+
}
|
|
3088
|
+
),
|
|
3089
|
+
single && isEditable && !editingText && /* @__PURE__ */ jsx9(
|
|
3090
|
+
SelectionOverlay,
|
|
3091
|
+
{
|
|
3092
|
+
shape: single,
|
|
3093
|
+
points: paths.get(single.id) ?? [],
|
|
3094
|
+
onHandlePointerDown: handleHandlePointerDown,
|
|
3095
|
+
onWaypointAdd: addWaypoint,
|
|
3096
|
+
onWaypointRemove: removeWaypoint
|
|
3097
|
+
}
|
|
3098
|
+
),
|
|
3099
|
+
selection.length > 1 && isEditable && /* @__PURE__ */ jsx9(GroupSelectionOverlay, { shapes: selection, paths }),
|
|
3100
|
+
marquee && /* @__PURE__ */ jsx9(MarqueeOverlay, { rect: marqueeRect(marquee.origin, marquee.current) })
|
|
3101
|
+
]
|
|
3102
|
+
}
|
|
3103
|
+
),
|
|
3104
|
+
isEditable && shapes.length === 0 && /* @__PURE__ */ jsx9("div", { className: "zui-drawing-empty", "aria-hidden": "true", children: "Pick a shape above, then click or drag on the canvas" }),
|
|
3105
|
+
editingShape && editingText && /* @__PURE__ */ jsx9(
|
|
3106
|
+
"div",
|
|
3107
|
+
{
|
|
3108
|
+
className: "zui-drawing-overlay",
|
|
3109
|
+
style: {
|
|
3110
|
+
transform: `scale(${scale})`,
|
|
3111
|
+
width: logicalWidth ?? void 0,
|
|
3112
|
+
height: logicalWidth ? canvasHeight : void 0
|
|
3113
|
+
},
|
|
3114
|
+
children: /* @__PURE__ */ jsx9(
|
|
3115
|
+
TextEditOverlay,
|
|
3116
|
+
{
|
|
3117
|
+
shape: editingShape,
|
|
3118
|
+
field: editingText.field,
|
|
3119
|
+
points: paths.get(editingShape.id),
|
|
3120
|
+
onCommit: commitText
|
|
3121
|
+
},
|
|
3122
|
+
`${editingShape.id}:${editingText.field}`
|
|
3123
|
+
)
|
|
3124
|
+
}
|
|
3125
|
+
),
|
|
3126
|
+
isEditable && /* @__PURE__ */ jsx9(
|
|
3127
|
+
HeightHandle,
|
|
3128
|
+
{
|
|
3129
|
+
height: canvasHeight,
|
|
3130
|
+
scale,
|
|
3131
|
+
onChange: setCanvasHeight,
|
|
3132
|
+
onCommit: (h) => commit(shapesRef.current, { height: h })
|
|
3133
|
+
}
|
|
3134
|
+
)
|
|
3135
|
+
] })
|
|
3112
3136
|
]
|
|
3113
3137
|
}
|
|
3114
3138
|
);
|
|
@@ -3214,7 +3238,7 @@ function expandSkeleton(skeleton) {
|
|
|
3214
3238
|
version: 2,
|
|
3215
3239
|
...skeleton.canvasWidth !== void 0 ? { canvasWidth: skeleton.canvasWidth } : {},
|
|
3216
3240
|
canvasHeight: skeleton.canvasHeight ?? Math.max(MIN_AUTO_CANVAS_HEIGHT, Math.ceil(bottom + CANVAS_MARGIN)),
|
|
3217
|
-
...skeleton.width
|
|
3241
|
+
...skeleton.width !== void 0 ? { width: skeleton.width } : {},
|
|
3218
3242
|
shapes
|
|
3219
3243
|
});
|
|
3220
3244
|
}
|
|
@@ -3418,7 +3442,7 @@ function normalizeSkeleton(raw) {
|
|
|
3418
3442
|
direction: value.direction === "down" ? "down" : "right",
|
|
3419
3443
|
...canvasWidth !== void 0 ? { canvasWidth } : {},
|
|
3420
3444
|
...canvasHeight !== void 0 ? { canvasHeight } : {},
|
|
3421
|
-
...value.width
|
|
3445
|
+
...isBlockWidth(value.width) ? { width: value.width } : {},
|
|
3422
3446
|
boxes,
|
|
3423
3447
|
connectors,
|
|
3424
3448
|
texts
|
|
@@ -3551,8 +3575,8 @@ var DRAWING_SKELETON_JSON_SCHEMA = {
|
|
|
3551
3575
|
description: "Canvas height in px. Omit to fit the content"
|
|
3552
3576
|
},
|
|
3553
3577
|
width: {
|
|
3554
|
-
enum: ["content"],
|
|
3555
|
-
description: 'Block width: "content" fits the drawing to its shapes and left-aligns it with the text; omit to span the editor'
|
|
3578
|
+
enum: ["full", "text", "content"],
|
|
3579
|
+
description: 'Block width: "text" aligns the drawing with the text column (same as "full" unless the app sets a text measure); "content" fits the drawing to its shapes and left-aligns it with the text; omit to span the editor'
|
|
3556
3580
|
},
|
|
3557
3581
|
boxes: {
|
|
3558
3582
|
type: "array",
|
|
@@ -3788,10 +3812,12 @@ var DEFAULT_TABLE_SETTINGS = {
|
|
|
3788
3812
|
width: "full",
|
|
3789
3813
|
density: "comfortable"
|
|
3790
3814
|
};
|
|
3815
|
+
var BLOCK_BLEED_PROPERTY = "--zui-text-editor-block-bleed";
|
|
3791
3816
|
var OPTION_DECLARATIONS = {
|
|
3792
3817
|
width: {
|
|
3793
3818
|
full: {},
|
|
3794
|
-
content: { width: "auto", "table-layout": "auto" }
|
|
3819
|
+
content: { width: "auto", "table-layout": "auto", [BLOCK_BLEED_PROPERTY]: "0px" },
|
|
3820
|
+
text: { [BLOCK_BLEED_PROPERTY]: "0px" }
|
|
3795
3821
|
},
|
|
3796
3822
|
density: {
|
|
3797
3823
|
comfortable: {},
|
|
@@ -3806,6 +3832,7 @@ var OPTION_DECLARATIONS = {
|
|
|
3806
3832
|
}
|
|
3807
3833
|
};
|
|
3808
3834
|
var SETTING_KEYS = Object.keys(OPTION_DECLARATIONS);
|
|
3835
|
+
var EXPLICIT_WIDTH_PROPERTY = "--zui-table-width";
|
|
3809
3836
|
function parseStyle(style) {
|
|
3810
3837
|
const declarations = /* @__PURE__ */ new Map();
|
|
3811
3838
|
for (const part of style.split(";")) {
|
|
@@ -3848,14 +3875,22 @@ function $getTableSettings(table) {
|
|
|
3848
3875
|
density: readSetting(declarations, "density")
|
|
3849
3876
|
};
|
|
3850
3877
|
}
|
|
3851
|
-
function $setTableSettings(table, settings) {
|
|
3878
|
+
function $setTableSettings(table, settings, options = {}) {
|
|
3852
3879
|
const declarations = parseStyle(table.getStyle());
|
|
3853
3880
|
for (const key of SETTING_KEYS) {
|
|
3854
3881
|
const option = settings[key];
|
|
3855
3882
|
if (option !== void 0) writeSetting(declarations, key, option);
|
|
3856
3883
|
}
|
|
3884
|
+
if (settings.width !== void 0) {
|
|
3885
|
+
if (options.explicitWidth) declarations.set(EXPLICIT_WIDTH_PROPERTY, settings.width);
|
|
3886
|
+
else declarations.delete(EXPLICIT_WIDTH_PROPERTY);
|
|
3887
|
+
}
|
|
3857
3888
|
table.setStyle(serializeStyle(declarations));
|
|
3858
3889
|
}
|
|
3890
|
+
function $isTableWidthExplicit(table) {
|
|
3891
|
+
const declarations = parseStyle(table.getStyle());
|
|
3892
|
+
return declarations.get(EXPLICIT_WIDTH_PROPERTY) === readSetting(declarations, "width");
|
|
3893
|
+
}
|
|
3859
3894
|
function $getTableWidth(table) {
|
|
3860
3895
|
return $getTableSettings(table).width;
|
|
3861
3896
|
}
|
|
@@ -3890,16 +3925,19 @@ function parseTableSettingsMarker(text) {
|
|
|
3890
3925
|
const match = MARKER_REG_EXP.exec(text);
|
|
3891
3926
|
if (!match) return null;
|
|
3892
3927
|
const settings = {};
|
|
3928
|
+
let recognised = false;
|
|
3893
3929
|
for (const pair of match[1].split(";")) {
|
|
3894
3930
|
const [key, value] = pair.split(":").map((s) => s.trim());
|
|
3931
|
+
if (key !== "width" && key !== "density") continue;
|
|
3932
|
+
recognised = true;
|
|
3895
3933
|
if (key === "width" && isOption("width", value)) settings.width = value;
|
|
3896
3934
|
if (key === "density" && isOption("density", value)) settings.density = value;
|
|
3897
3935
|
}
|
|
3898
|
-
return
|
|
3936
|
+
return recognised ? settings : null;
|
|
3899
3937
|
}
|
|
3900
|
-
function formatTableSettingsMarker(settings) {
|
|
3938
|
+
function formatTableSettingsMarker(settings, options = {}) {
|
|
3901
3939
|
const pairs = SETTING_KEYS.filter(
|
|
3902
|
-
(key) => settings[key] !== DEFAULT_TABLE_SETTINGS[key]
|
|
3940
|
+
(key) => settings[key] !== DEFAULT_TABLE_SETTINGS[key] || key === "width" && options.explicitWidth
|
|
3903
3941
|
).map((key) => `${key}: ${settings[key]}`);
|
|
3904
3942
|
return pairs.length > 0 ? `<!-- ${pairs.join("; ")} -->` : null;
|
|
3905
3943
|
}
|
|
@@ -3932,7 +3970,9 @@ var TABLE = {
|
|
|
3932
3970
|
export: (node) => {
|
|
3933
3971
|
if (!$isTableNode2(node)) return null;
|
|
3934
3972
|
const output = [];
|
|
3935
|
-
const marker = formatTableSettingsMarker($getTableSettings(node)
|
|
3973
|
+
const marker = formatTableSettingsMarker($getTableSettings(node), {
|
|
3974
|
+
explicitWidth: $isTableWidthExplicit(node)
|
|
3975
|
+
});
|
|
3936
3976
|
if (marker) output.push(marker);
|
|
3937
3977
|
for (const row of node.getChildren()) {
|
|
3938
3978
|
if (!$isTableRowNode(row)) continue;
|
|
@@ -4001,7 +4041,7 @@ var TABLE = {
|
|
|
4001
4041
|
} else {
|
|
4002
4042
|
const markerSettings = $getMarkerSettings(previousSibling);
|
|
4003
4043
|
if (markerSettings) {
|
|
4004
|
-
$setTableSettings(table, markerSettings);
|
|
4044
|
+
$setTableSettings(table, markerSettings, { explicitWidth: true });
|
|
4005
4045
|
previousSibling?.remove();
|
|
4006
4046
|
}
|
|
4007
4047
|
parentNode.replace(table);
|
|
@@ -4016,14 +4056,14 @@ var editorTheme = {
|
|
|
4016
4056
|
ltr: "text-left",
|
|
4017
4057
|
rtl: "text-right",
|
|
4018
4058
|
placeholder: "text-muted-foreground opacity-50",
|
|
4019
|
-
paragraph: "mb-2",
|
|
4059
|
+
paragraph: "zui-paragraph mb-2",
|
|
4020
4060
|
heading: {
|
|
4021
|
-
h1: "text-4xl font-bold mb-4",
|
|
4022
|
-
h2: "text-3xl font-bold mb-3",
|
|
4023
|
-
h3: "text-2xl font-bold mb-2",
|
|
4024
|
-
h4: "text-xl font-bold mb-2",
|
|
4025
|
-
h5: "text-lg font-bold mb-1",
|
|
4026
|
-
h6: "text-base font-bold mb-1"
|
|
4061
|
+
h1: "zui-heading zui-heading-1 text-4xl font-bold mb-4",
|
|
4062
|
+
h2: "zui-heading zui-heading-2 text-3xl font-bold mb-3",
|
|
4063
|
+
h3: "zui-heading zui-heading-3 text-2xl font-bold mb-2",
|
|
4064
|
+
h4: "zui-heading zui-heading-4 text-xl font-bold mb-2",
|
|
4065
|
+
h5: "zui-heading zui-heading-5 text-lg font-bold mb-1",
|
|
4066
|
+
h6: "zui-heading zui-heading-6 text-base font-bold mb-1"
|
|
4027
4067
|
},
|
|
4028
4068
|
list: {
|
|
4029
4069
|
listitem: "ml-8",
|
|
@@ -4033,8 +4073,8 @@ var editorTheme = {
|
|
|
4033
4073
|
listitem: "ml-8"
|
|
4034
4074
|
},
|
|
4035
4075
|
checklist: "zui-checklist",
|
|
4036
|
-
ol: "list-decimal ml-4",
|
|
4037
|
-
ul: "list-disc ml-4"
|
|
4076
|
+
ol: "zui-list zui-list-ordered list-decimal ml-4",
|
|
4077
|
+
ul: "zui-list zui-list-unordered list-disc ml-4"
|
|
4038
4078
|
},
|
|
4039
4079
|
link: "text-primary underline hover:opacity-80 cursor-pointer",
|
|
4040
4080
|
text: {
|
|
@@ -4047,7 +4087,7 @@ var editorTheme = {
|
|
|
4047
4087
|
underline: "underline",
|
|
4048
4088
|
underlineStrikethrough: "underline line-through"
|
|
4049
4089
|
},
|
|
4050
|
-
code: "bg-muted rounded-md p-4 font-mono text-sm block my-2 overflow-x-auto",
|
|
4090
|
+
code: "zui-code bg-muted rounded-md p-4 font-mono text-sm block my-2 overflow-x-auto",
|
|
4051
4091
|
codeHighlight: {
|
|
4052
4092
|
atrule: "text-blue-500",
|
|
4053
4093
|
attr: "text-yellow-500",
|
|
@@ -4080,7 +4120,7 @@ var editorTheme = {
|
|
|
4080
4120
|
url: "text-blue-500",
|
|
4081
4121
|
variable: "text-blue-500"
|
|
4082
4122
|
},
|
|
4083
|
-
quote: "border-l-4 border-border pl-4 italic",
|
|
4123
|
+
quote: "zui-quote border-l-4 border-border pl-4 italic",
|
|
4084
4124
|
frontmatter: "zui-frontmatter",
|
|
4085
4125
|
table: "zui-table",
|
|
4086
4126
|
tableCell: "zui-table-cell",
|
|
@@ -4090,10 +4130,8 @@ var editorTheme = {
|
|
|
4090
4130
|
drawing: "zui-drawing"
|
|
4091
4131
|
};
|
|
4092
4132
|
|
|
4093
|
-
// src/
|
|
4094
|
-
import {
|
|
4095
|
-
var SYNC_TRANSFORMERS = [FRONTMATTER, DRAWING, DIAGRAM, CHECK_LIST, TABLE, ...TRANSFORMERS2];
|
|
4096
|
-
var SHORTCUT_TRANSFORMERS = [TABLE, ...TRANSFORMERS2.filter((t) => t !== CODE)];
|
|
4133
|
+
// src/editorContext.ts
|
|
4134
|
+
import { createContext, useContext } from "react";
|
|
4097
4135
|
var EditorContext = createContext(null);
|
|
4098
4136
|
function useEditorContext() {
|
|
4099
4137
|
const ctx = useContext(EditorContext);
|
|
@@ -4104,6 +4142,12 @@ function useEditorContext() {
|
|
|
4104
4142
|
}
|
|
4105
4143
|
return ctx;
|
|
4106
4144
|
}
|
|
4145
|
+
|
|
4146
|
+
// src/EditorRoot.tsx
|
|
4147
|
+
import { Fragment as Fragment3, jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
4148
|
+
var SYNC_TRANSFORMERS = [FRONTMATTER, DRAWING, DIAGRAM, CHECK_LIST, TABLE, ...TRANSFORMERS2];
|
|
4149
|
+
var SHORTCUT_TRANSFORMERS = [TABLE, ...TRANSFORMERS2.filter((t) => t !== CODE)];
|
|
4150
|
+
var NO_DEFAULT_BLOCK_WIDTH = {};
|
|
4107
4151
|
function onError(error) {
|
|
4108
4152
|
console.error(error);
|
|
4109
4153
|
}
|
|
@@ -4136,6 +4180,8 @@ function EditorRoot({
|
|
|
4136
4180
|
className,
|
|
4137
4181
|
mode = "edit-md",
|
|
4138
4182
|
autoFocus = false,
|
|
4183
|
+
measure,
|
|
4184
|
+
defaultBlockWidth = NO_DEFAULT_BLOCK_WIDTH,
|
|
4139
4185
|
children
|
|
4140
4186
|
}) {
|
|
4141
4187
|
const latestValueRef = useRef5(value ?? "");
|
|
@@ -4176,12 +4222,17 @@ function EditorRoot({
|
|
|
4176
4222
|
readOnly,
|
|
4177
4223
|
autoFocus,
|
|
4178
4224
|
rawValue: value ?? "",
|
|
4179
|
-
onRawChange: handleChange
|
|
4225
|
+
onRawChange: handleChange,
|
|
4226
|
+
defaultBlockWidth
|
|
4180
4227
|
}),
|
|
4181
|
-
[mode, readOnly, autoFocus, value, handleChange]
|
|
4228
|
+
[mode, readOnly, autoFocus, value, handleChange, defaultBlockWidth]
|
|
4182
4229
|
);
|
|
4183
4230
|
const isRaw = mode === "edit-raw";
|
|
4184
|
-
|
|
4231
|
+
const rootStyle = useMemo2(
|
|
4232
|
+
() => measure !== void 0 ? { "--zui-text-editor-measure": measure } : void 0,
|
|
4233
|
+
[measure]
|
|
4234
|
+
);
|
|
4235
|
+
return /* @__PURE__ */ jsx11(LexicalComposer, { initialConfig, children: /* @__PURE__ */ jsx11(EditorContext.Provider, { value: context, children: /* @__PURE__ */ jsxs9("div", { className: `zui-text-editor ${className ?? ""}`, style: rootStyle, children: [
|
|
4185
4236
|
children,
|
|
4186
4237
|
!isRaw && /* @__PURE__ */ jsxs9(Fragment3, { children: [
|
|
4187
4238
|
/* @__PURE__ */ jsx11(
|
|
@@ -4355,8 +4406,9 @@ import { useLexicalComposerContext as useLexicalComposerContext9 } from "@lexica
|
|
|
4355
4406
|
import { useLexicalEditable as useLexicalEditable2 } from "@lexical/react/useLexicalEditable";
|
|
4356
4407
|
|
|
4357
4408
|
// src/useMarkdownEditor.ts
|
|
4358
|
-
import { useCallback as useCallback4, useEffect as useEffect10, useState as useState6 } from "react";
|
|
4409
|
+
import { useCallback as useCallback4, useEffect as useEffect10, useRef as useRef7, useState as useState6 } from "react";
|
|
4359
4410
|
import {
|
|
4411
|
+
$getNodeByKey as $getNodeByKey4,
|
|
4360
4412
|
$getSelection as $getSelection4,
|
|
4361
4413
|
$isRangeSelection as $isRangeSelection4,
|
|
4362
4414
|
CAN_REDO_COMMAND,
|
|
@@ -4376,20 +4428,29 @@ var TRACKED_FORMATS = [
|
|
|
4376
4428
|
"strikethrough",
|
|
4377
4429
|
"code"
|
|
4378
4430
|
];
|
|
4431
|
+
function $readDrawingWidth(key) {
|
|
4432
|
+
if (key === null) return null;
|
|
4433
|
+
const node = $getNodeByKey4(key);
|
|
4434
|
+
return $isDrawingNode(node) ? node.getData().width ?? "full" : null;
|
|
4435
|
+
}
|
|
4379
4436
|
function useMarkdownEditor() {
|
|
4380
4437
|
const [editor] = useLexicalComposerContext8();
|
|
4438
|
+
const { defaultBlockWidth } = useEditorContext();
|
|
4381
4439
|
const [activeFormats, setActiveFormats] = useState6(
|
|
4382
4440
|
/* @__PURE__ */ new Set()
|
|
4383
4441
|
);
|
|
4384
4442
|
const [canUndo, setCanUndo] = useState6(false);
|
|
4385
4443
|
const [canRedo, setCanRedo] = useState6(false);
|
|
4386
4444
|
const [tableSettings, setTableSettingsState] = useState6(null);
|
|
4445
|
+
const activeDrawingRef = useRef7(null);
|
|
4446
|
+
const [drawingWidth, setDrawingWidth] = useState6(null);
|
|
4387
4447
|
useEffect10(
|
|
4388
4448
|
() => mergeRegister(
|
|
4389
4449
|
editor.registerUpdateListener(({ editorState }) => {
|
|
4390
4450
|
editorState.read(() => {
|
|
4391
4451
|
const table = $getSelectedTable();
|
|
4392
4452
|
setTableSettingsState(table ? $getTableSettings(table) : null);
|
|
4453
|
+
setDrawingWidth($readDrawingWidth(activeDrawingRef.current));
|
|
4393
4454
|
const selection = $getSelection4();
|
|
4394
4455
|
if (!$isRangeSelection4(selection)) {
|
|
4395
4456
|
setActiveFormats(/* @__PURE__ */ new Set());
|
|
@@ -4402,6 +4463,15 @@ function useMarkdownEditor() {
|
|
|
4402
4463
|
setActiveFormats(next);
|
|
4403
4464
|
});
|
|
4404
4465
|
}),
|
|
4466
|
+
editor.registerCommand(
|
|
4467
|
+
DRAWING_FOCUS_COMMAND,
|
|
4468
|
+
(key) => {
|
|
4469
|
+
activeDrawingRef.current = key;
|
|
4470
|
+
setDrawingWidth(editor.getEditorState().read(() => $readDrawingWidth(key)));
|
|
4471
|
+
return false;
|
|
4472
|
+
},
|
|
4473
|
+
COMMAND_PRIORITY_LOW2
|
|
4474
|
+
),
|
|
4405
4475
|
editor.registerCommand(
|
|
4406
4476
|
CAN_UNDO_COMMAND,
|
|
4407
4477
|
(payload) => {
|
|
@@ -4428,20 +4498,36 @@ function useMarkdownEditor() {
|
|
|
4428
4498
|
[editor]
|
|
4429
4499
|
);
|
|
4430
4500
|
const insertTable = useCallback4(
|
|
4431
|
-
({
|
|
4501
|
+
({
|
|
4502
|
+
rows = 3,
|
|
4503
|
+
columns = 3,
|
|
4504
|
+
width = defaultBlockWidth.table
|
|
4505
|
+
} = {}) => {
|
|
4506
|
+
const before = editor.getEditorState().read(() => $getSelectedTable()?.getKey());
|
|
4432
4507
|
editor.dispatchCommand(INSERT_TABLE_COMMAND, {
|
|
4433
4508
|
columns: String(columns),
|
|
4434
4509
|
rows: String(rows),
|
|
4435
4510
|
includeHeaders: { rows: true, columns: false }
|
|
4436
4511
|
});
|
|
4512
|
+
if (width === void 0) return;
|
|
4513
|
+
editor.update(() => {
|
|
4514
|
+
const table = $getSelectedTable();
|
|
4515
|
+
if (table && table.getKey() !== before) {
|
|
4516
|
+
$setTableSettings(table, { width }, { explicitWidth: true });
|
|
4517
|
+
}
|
|
4518
|
+
});
|
|
4437
4519
|
},
|
|
4438
|
-
[editor]
|
|
4520
|
+
[editor, defaultBlockWidth.table]
|
|
4521
|
+
);
|
|
4522
|
+
const insertDrawing = useCallback4(
|
|
4523
|
+
({ width = defaultBlockWidth.drawing } = {}) => {
|
|
4524
|
+
editor.update(() => {
|
|
4525
|
+
const data = width === void 0 ? EMPTY_DRAWING : { version: 2, canvasHeight: EMPTY_DRAWING.canvasHeight, width, shapes: [] };
|
|
4526
|
+
$insertNodeToNearestRoot($createDrawingNode(serializeDrawingData(data)));
|
|
4527
|
+
});
|
|
4528
|
+
},
|
|
4529
|
+
[editor, defaultBlockWidth.drawing]
|
|
4439
4530
|
);
|
|
4440
|
-
const insertDrawing = useCallback4(() => {
|
|
4441
|
-
editor.update(() => {
|
|
4442
|
-
$insertNodeToNearestRoot($createDrawingNode());
|
|
4443
|
-
});
|
|
4444
|
-
}, [editor]);
|
|
4445
4531
|
const updateTableSettings = useCallback4(
|
|
4446
4532
|
(settings) => {
|
|
4447
4533
|
editor.update(() => {
|
|
@@ -4459,6 +4545,22 @@ function useMarkdownEditor() {
|
|
|
4459
4545
|
(density) => updateTableSettings({ density }),
|
|
4460
4546
|
[updateTableSettings]
|
|
4461
4547
|
);
|
|
4548
|
+
const setBlockWidth = useCallback4(
|
|
4549
|
+
(width) => {
|
|
4550
|
+
const key = activeDrawingRef.current;
|
|
4551
|
+
if (key === null) {
|
|
4552
|
+
updateTableSettings({ width });
|
|
4553
|
+
return;
|
|
4554
|
+
}
|
|
4555
|
+
editor.update(() => {
|
|
4556
|
+
const node = $getNodeByKey4(key);
|
|
4557
|
+
if (!$isDrawingNode(node)) return;
|
|
4558
|
+
const { width: _previous, ...data } = node.getData();
|
|
4559
|
+
node.setData(width === "full" ? data : { ...data, width });
|
|
4560
|
+
});
|
|
4561
|
+
},
|
|
4562
|
+
[editor, updateTableSettings]
|
|
4563
|
+
);
|
|
4462
4564
|
const undo = useCallback4(() => {
|
|
4463
4565
|
editor.dispatchCommand(UNDO_COMMAND, void 0);
|
|
4464
4566
|
}, [editor]);
|
|
@@ -4471,6 +4573,8 @@ function useMarkdownEditor() {
|
|
|
4471
4573
|
toggleFormat,
|
|
4472
4574
|
insertTable,
|
|
4473
4575
|
insertDrawing,
|
|
4576
|
+
blockWidth: drawingWidth ?? tableSettings?.width ?? null,
|
|
4577
|
+
setBlockWidth,
|
|
4474
4578
|
tableWidth: tableSettings?.width ?? null,
|
|
4475
4579
|
setTableWidth,
|
|
4476
4580
|
tableDensity: tableSettings?.density ?? null,
|
|
@@ -4641,14 +4745,18 @@ function Icon3({ children }) {
|
|
|
4641
4745
|
function TableSettingsPlugin() {
|
|
4642
4746
|
const [editor] = useLexicalComposerContext9();
|
|
4643
4747
|
const isEditable = useLexicalEditable2();
|
|
4644
|
-
const { tableWidth, setTableWidth, tableDensity, setTableDensity } = useMarkdownEditor();
|
|
4645
4748
|
const [anchor, setAnchor] = useState7(null);
|
|
4749
|
+
const [settings, setSettings] = useState7(null);
|
|
4646
4750
|
const sync = useCallback5(() => {
|
|
4647
|
-
const
|
|
4648
|
-
|
|
4751
|
+
const table = editor.getEditorState().read(() => {
|
|
4752
|
+
const node = $getSelectedTable();
|
|
4753
|
+
return node ? { key: node.getKey(), settings: $getTableSettings(node) } : null;
|
|
4754
|
+
});
|
|
4755
|
+
const element = table ? editor.getElementByKey(table.key) : null;
|
|
4649
4756
|
const main = editor.getRootElement()?.parentElement;
|
|
4650
|
-
if (!element || !main) {
|
|
4757
|
+
if (!table || !element || !main) {
|
|
4651
4758
|
setAnchor(null);
|
|
4759
|
+
setSettings(null);
|
|
4652
4760
|
return;
|
|
4653
4761
|
}
|
|
4654
4762
|
const rect = element.getBoundingClientRect();
|
|
@@ -4657,6 +4765,7 @@ function TableSettingsPlugin() {
|
|
|
4657
4765
|
top: rect.top - mainRect.top,
|
|
4658
4766
|
right: mainRect.right - rect.right + 8
|
|
4659
4767
|
});
|
|
4768
|
+
setSettings(table.settings);
|
|
4660
4769
|
}, [editor]);
|
|
4661
4770
|
useEffect11(() => {
|
|
4662
4771
|
sync();
|
|
@@ -4669,7 +4778,16 @@ function TableSettingsPlugin() {
|
|
|
4669
4778
|
observer?.disconnect();
|
|
4670
4779
|
};
|
|
4671
4780
|
}, [editor, sync]);
|
|
4672
|
-
|
|
4781
|
+
const update = useCallback5(
|
|
4782
|
+
(next) => {
|
|
4783
|
+
editor.update(() => {
|
|
4784
|
+
const table = $getSelectedTable();
|
|
4785
|
+
if (table) $setTableSettings(table, next);
|
|
4786
|
+
});
|
|
4787
|
+
},
|
|
4788
|
+
[editor]
|
|
4789
|
+
);
|
|
4790
|
+
if (!isEditable || !anchor || !settings) return null;
|
|
4673
4791
|
return /* @__PURE__ */ jsxs11(
|
|
4674
4792
|
"div",
|
|
4675
4793
|
{
|
|
@@ -4682,8 +4800,8 @@ function TableSettingsPlugin() {
|
|
|
4682
4800
|
ToolbarButton,
|
|
4683
4801
|
{
|
|
4684
4802
|
label,
|
|
4685
|
-
active:
|
|
4686
|
-
onClick: () =>
|
|
4803
|
+
active: settings.width === width,
|
|
4804
|
+
onClick: () => update({ width }),
|
|
4687
4805
|
children: /* @__PURE__ */ jsx14(Icon3, { children: icon })
|
|
4688
4806
|
},
|
|
4689
4807
|
width
|
|
@@ -4693,8 +4811,8 @@ function TableSettingsPlugin() {
|
|
|
4693
4811
|
ToolbarButton,
|
|
4694
4812
|
{
|
|
4695
4813
|
label,
|
|
4696
|
-
active:
|
|
4697
|
-
onClick: () =>
|
|
4814
|
+
active: settings.density === density,
|
|
4815
|
+
onClick: () => update({ density }),
|
|
4698
4816
|
children: /* @__PURE__ */ jsx14(Icon3, { children: icon })
|
|
4699
4817
|
},
|
|
4700
4818
|
density
|
|
@@ -4923,8 +5041,8 @@ var DRAWING_DATA_JSON_SCHEMA = {
|
|
|
4923
5041
|
description: "Optional logical canvas width in pixels. When set, the drawing is scaled down to fit narrower layouts (SVG viewBox) so coordinates can assume this width. When omitted the canvas is fluid and coordinates are CSS pixels."
|
|
4924
5042
|
},
|
|
4925
5043
|
width: {
|
|
4926
|
-
enum: ["full", "content"],
|
|
4927
|
-
description: `Block width: "full" (default, omit it) spans the editor; "content" fits the shapes' horizontal extent and left-aligns with the text`
|
|
5044
|
+
enum: ["full", "text", "content"],
|
|
5045
|
+
description: `Block width: "full" (default, omit it) spans the editor; "text" aligns the block with the text column (same as "full" unless the app sets a text measure); "content" fits the shapes' horizontal extent and left-aligns with the text`
|
|
4928
5046
|
},
|
|
4929
5047
|
shapes: {
|
|
4930
5048
|
type: "array",
|
|
@@ -5067,9 +5185,11 @@ export {
|
|
|
5067
5185
|
$getTableWidth,
|
|
5068
5186
|
$isDrawingNode,
|
|
5069
5187
|
$isFrontmatterNode,
|
|
5188
|
+
$isTableWidthExplicit,
|
|
5070
5189
|
$setTableDensity,
|
|
5071
5190
|
$setTableSettings,
|
|
5072
5191
|
$setTableWidth,
|
|
5192
|
+
BLOCK_WIDTHS,
|
|
5073
5193
|
BOX_DEFINITIONS,
|
|
5074
5194
|
BOX_TYPES,
|
|
5075
5195
|
COLOR_PRESETS,
|
|
@@ -5105,6 +5225,7 @@ export {
|
|
|
5105
5225
|
findBoxAt,
|
|
5106
5226
|
fixedPointFor,
|
|
5107
5227
|
formatTableSettingsMarker,
|
|
5228
|
+
isBlockWidth,
|
|
5108
5229
|
isDrawingSkeleton,
|
|
5109
5230
|
makeBinding,
|
|
5110
5231
|
normalizeDrawingData,
|