canvu-react 0.3.39 → 0.3.40
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/dist/{asset-hydration-DowNdaOJ.d.cts → asset-hydration-B7yMDQE-.d.cts} +2 -2
- package/dist/{asset-hydration-DdFLdlqX.d.ts → asset-hydration-CbwQVAwh.d.ts} +2 -2
- package/dist/{camera-Di5R_Rwl.d.cts → camera-CVVG7z56.d.cts} +1 -1
- package/dist/{camera-AoTwBSoE.d.ts → camera-CoRYN_IV.d.ts} +1 -1
- package/dist/chatbot.d.cts +4 -4
- package/dist/chatbot.d.ts +4 -4
- package/dist/index.cjs +59 -15
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -6
- package/dist/index.d.ts +6 -6
- package/dist/index.js +59 -15
- package/dist/index.js.map +1 -1
- package/dist/native.cjs +57 -14
- package/dist/native.cjs.map +1 -1
- package/dist/native.d.cts +2 -2
- package/dist/native.d.ts +2 -2
- package/dist/native.js +57 -14
- package/dist/native.js.map +1 -1
- package/dist/react.cjs +699 -255
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +10 -10
- package/dist/react.d.ts +10 -10
- package/dist/react.js +699 -255
- package/dist/react.js.map +1 -1
- package/dist/realtime.cjs +36 -0
- package/dist/realtime.cjs.map +1 -1
- package/dist/realtime.d.cts +6 -6
- package/dist/realtime.d.ts +6 -6
- package/dist/realtime.js +36 -0
- package/dist/realtime.js.map +1 -1
- package/dist/{shape-builders-Dedcl6tw.d.cts → shape-builders-BAWu-PxX.d.cts} +7 -3
- package/dist/{shape-builders-C7bxJBGR.d.ts → shape-builders-ClKv9tz9.d.ts} +7 -3
- package/dist/tldraw.cjs +56 -14
- package/dist/tldraw.cjs.map +1 -1
- package/dist/tldraw.d.cts +1 -1
- package/dist/tldraw.d.ts +1 -1
- package/dist/tldraw.js +56 -14
- package/dist/tldraw.js.map +1 -1
- package/dist/{types-DUW61Tjy.d.cts → types-BC9Xgfu6.d.cts} +11 -6
- package/dist/{types-Bnq2HtHQ.d.cts → types-BCCvY6ie.d.cts} +2 -0
- package/dist/{types-Bnq2HtHQ.d.ts → types-BCCvY6ie.d.ts} +2 -0
- package/dist/{types-B2Na677H.d.cts → types-BUPc2Zgw.d.cts} +1 -1
- package/dist/{types-zmUah-vP.d.ts → types-CYtq9Pr9.d.ts} +1 -1
- package/dist/{types-BBb8KoyW.d.ts → types-DlSVGX0w.d.ts} +11 -6
- package/package.json +1 -1
package/dist/react.js
CHANGED
|
@@ -84,6 +84,12 @@ function lineHeightFor(fontSize) {
|
|
|
84
84
|
function firstLineBaselineY(fontSize) {
|
|
85
85
|
return fontSize * FIRST_LINE_BASELINE_RATIO;
|
|
86
86
|
}
|
|
87
|
+
function textBaselineYFor(fontSize) {
|
|
88
|
+
return firstLineBaselineY(fontSize);
|
|
89
|
+
}
|
|
90
|
+
function textLineHeightFor(fontSize) {
|
|
91
|
+
return lineHeightFor(fontSize);
|
|
92
|
+
}
|
|
87
93
|
function measureTextBoundsLocal(content, fontSize = DEFAULT_TEXT_FONT_SIZE) {
|
|
88
94
|
const cacheKey = textMeasureCacheKey(content, fontSize);
|
|
89
95
|
const cached = textMeasureCache.get(cacheKey);
|
|
@@ -97,7 +103,7 @@ function measureTextBoundsLocal(content, fontSize = DEFAULT_TEXT_FONT_SIZE) {
|
|
|
97
103
|
let maxInnerW = 0;
|
|
98
104
|
const ctx = getSharedMeasureContext();
|
|
99
105
|
if (ctx) {
|
|
100
|
-
ctx.font = `${fontSize}px
|
|
106
|
+
ctx.font = `${fontSize}px ${TEXT_FONT_FAMILY}`;
|
|
101
107
|
for (const line of lines) {
|
|
102
108
|
const toMeasure = trimmed.length === 0 ? PLACEHOLDER : line.length === 0 ? " " : line;
|
|
103
109
|
maxInnerW = Math.max(maxInnerW, ctx.measureText(toMeasure).width);
|
|
@@ -113,22 +119,22 @@ function measureTextBoundsLocal(content, fontSize = DEFAULT_TEXT_FONT_SIZE) {
|
|
|
113
119
|
const width = Math.max(minW, TEXT_PAD_X * 2 + maxInnerW);
|
|
114
120
|
const height = Math.max(
|
|
115
121
|
MIN_TEXT_BOX_H,
|
|
116
|
-
baselineY + (lines.length - 1) * lh + Math.max(
|
|
122
|
+
baselineY + (lines.length - 1) * lh + Math.max(4, fontSize * BOTTOM_PAD_RATIO)
|
|
117
123
|
);
|
|
118
124
|
const measured = { width, height };
|
|
119
125
|
cacheMeasuredBounds(cacheKey, measured);
|
|
120
126
|
return measured;
|
|
121
127
|
}
|
|
122
|
-
function buildTextSvg(content, _width, _height, fillColor = "#
|
|
128
|
+
function buildTextSvg(content, _width, _height, fillColor = "#1d1d1d", fontSize = DEFAULT_TEXT_FONT_SIZE) {
|
|
123
129
|
const lh = lineHeightFor(fontSize);
|
|
124
130
|
const y0 = firstLineBaselineY(fontSize);
|
|
125
131
|
const trimmed = content.trim();
|
|
126
132
|
if (trimmed.length === 0) {
|
|
127
|
-
return `<text x="4" y="${y0}" font-size="${fontSize}" font-family="
|
|
133
|
+
return `<text x="4" y="${y0}" font-size="${fontSize}" font-family="${TEXT_FONT_FAMILY}" fill="#94a3b8" font-style="italic">${escapeSvgTextContent(PLACEHOLDER)}</text>`;
|
|
128
134
|
}
|
|
129
135
|
const lines = content.split("\n");
|
|
130
136
|
if (lines.length === 1) {
|
|
131
|
-
return `<text x="4" y="${y0}" font-size="${fontSize}" font-family="
|
|
137
|
+
return `<text x="4" y="${y0}" font-size="${fontSize}" font-family="${TEXT_FONT_FAMILY}" fill="${fillColor}">${escapeSvgTextContent(lines[0] ?? "")}</text>`;
|
|
132
138
|
}
|
|
133
139
|
const parts = [];
|
|
134
140
|
for (let i = 0; i < lines.length; i++) {
|
|
@@ -139,28 +145,32 @@ function buildTextSvg(content, _width, _height, fillColor = "#2563eb", fontSize
|
|
|
139
145
|
parts.push(`<tspan x="4" dy="${lh}">${escapeSvgTextContent(line)}</tspan>`);
|
|
140
146
|
}
|
|
141
147
|
}
|
|
142
|
-
return `<text x="4" y="${y0}" font-size="${fontSize}" font-family="
|
|
148
|
+
return `<text x="4" y="${y0}" font-size="${fontSize}" font-family="${TEXT_FONT_FAMILY}" fill="${fillColor}">${parts.join("")}</text>`;
|
|
143
149
|
}
|
|
144
|
-
function buildTextFixedBoundsSvg(content, width, height, fillColor = "#
|
|
150
|
+
function buildTextFixedBoundsSvg(content, width, height, fillColor = "#1d1d1d", fontSize = DEFAULT_TEXT_FONT_SIZE) {
|
|
145
151
|
const w = Math.max(1, width);
|
|
146
152
|
const h = Math.max(1, height);
|
|
147
153
|
const lh = lineHeightFor(fontSize);
|
|
148
154
|
const trimmed = content.trim();
|
|
155
|
+
const padTop = EDIT_TOP_PAD_RATIO * fontSize;
|
|
149
156
|
if (trimmed.length === 0) {
|
|
150
|
-
return `<foreignObject width="${w}" height="${h}"><div xmlns="http://www.w3.org/1999/xhtml" style="box-sizing:border-box;width:100%;height:100%;margin:0;padding
|
|
157
|
+
return `<foreignObject width="${w}" height="${h}"><div xmlns="http://www.w3.org/1999/xhtml" style="box-sizing:border-box;width:100%;height:100%;margin:0;padding:${padTop}px 4px 0 4px;font-size:${fontSize}px;line-height:${lh}px;font-family:${TEXT_FONT_FAMILY};white-space:pre-wrap;word-wrap:break-word;overflow:hidden;color:#94a3b8;font-style:italic">${escapeHtmlText(PLACEHOLDER)}</div></foreignObject>`;
|
|
151
158
|
}
|
|
152
159
|
const body = escapeHtmlText(content);
|
|
153
|
-
return `<foreignObject width="${w}" height="${h}"><div xmlns="http://www.w3.org/1999/xhtml" style="box-sizing:border-box;width:100%;height:100%;margin:0;padding
|
|
160
|
+
return `<foreignObject width="${w}" height="${h}"><div xmlns="http://www.w3.org/1999/xhtml" style="box-sizing:border-box;width:100%;height:100%;margin:0;padding:${padTop}px 4px 0 4px;font-size:${fontSize}px;line-height:${lh}px;font-family:${TEXT_FONT_FAMILY};white-space:pre-wrap;word-wrap:break-word;overflow:hidden;color:${fillColor}">${body}</div></foreignObject>`;
|
|
154
161
|
}
|
|
155
|
-
var DEFAULT_TEXT_FONT_SIZE, LINE_HEIGHT_RATIO, FIRST_LINE_BASELINE_RATIO, PLACEHOLDER, MIN_TEXT_BOX_W, MIN_TEXT_BOX_H, TEXT_PAD_X, MAX_TEXT_MEASURE_CACHE_ENTRIES, sharedMeasureContext, textMeasureCache;
|
|
162
|
+
var DEFAULT_TEXT_FONT_SIZE, TEXT_FONT_FAMILY, LINE_HEIGHT_RATIO, FIRST_LINE_BASELINE_RATIO, EDIT_TOP_PAD_RATIO, BOTTOM_PAD_RATIO, PLACEHOLDER, MIN_TEXT_BOX_W, MIN_TEXT_BOX_H, TEXT_PAD_X, MAX_TEXT_MEASURE_CACHE_ENTRIES, sharedMeasureContext, textMeasureCache;
|
|
156
163
|
var init_text_svg = __esm({
|
|
157
164
|
"src/scene/text-svg.ts"() {
|
|
158
165
|
DEFAULT_TEXT_FONT_SIZE = 18;
|
|
166
|
+
TEXT_FONT_FAMILY = "Inter, -apple-system, BlinkMacSystemFont, ui-sans-serif, system-ui, sans-serif";
|
|
159
167
|
LINE_HEIGHT_RATIO = 22 / 18;
|
|
160
|
-
FIRST_LINE_BASELINE_RATIO =
|
|
168
|
+
FIRST_LINE_BASELINE_RATIO = 20 / 18;
|
|
169
|
+
EDIT_TOP_PAD_RATIO = 4 / 18;
|
|
170
|
+
BOTTOM_PAD_RATIO = 4 / 18;
|
|
161
171
|
PLACEHOLDER = "Tap to type";
|
|
162
172
|
MIN_TEXT_BOX_W = 40;
|
|
163
|
-
MIN_TEXT_BOX_H =
|
|
173
|
+
MIN_TEXT_BOX_H = 26;
|
|
164
174
|
TEXT_PAD_X = 4;
|
|
165
175
|
MAX_TEXT_MEASURE_CACHE_ENTRIES = 2e3;
|
|
166
176
|
textMeasureCache = /* @__PURE__ */ new Map();
|
|
@@ -273,7 +283,8 @@ function resolveStrokeStyle(item) {
|
|
|
273
283
|
return {
|
|
274
284
|
stroke: item.stroke ?? DEFAULT_STROKE_STYLE.stroke,
|
|
275
285
|
strokeWidth: item.strokeWidth ?? DEFAULT_STROKE_STYLE.strokeWidth,
|
|
276
|
-
strokeOpacity: item.strokeOpacity
|
|
286
|
+
strokeOpacity: item.strokeOpacity,
|
|
287
|
+
strokeDash: item.strokeDash
|
|
277
288
|
};
|
|
278
289
|
}
|
|
279
290
|
function strokeOpacityAttr(style) {
|
|
@@ -596,6 +607,30 @@ function buildDrawDotSvg(r, style = DEFAULT_STROKE_STYLE) {
|
|
|
596
607
|
const op = style.strokeOpacity != null ? ` fill-opacity="${style.strokeOpacity}"` : "";
|
|
597
608
|
return `<circle cx="${r}" cy="${r}" r="${r}" fill="${style.stroke}" shape-rendering="geometricPrecision"${op} />`;
|
|
598
609
|
}
|
|
610
|
+
function dashArrayForDrawStroke(strokeWidth) {
|
|
611
|
+
const dash = Math.max(strokeWidth * 1.8, 4);
|
|
612
|
+
const gap = Math.max(strokeWidth * 1.4, 3);
|
|
613
|
+
return `${dash} ${gap}`;
|
|
614
|
+
}
|
|
615
|
+
function buildSmoothedCenterlinePath(points) {
|
|
616
|
+
if (points.length < 2) return null;
|
|
617
|
+
const first = points[0];
|
|
618
|
+
if (!first) return null;
|
|
619
|
+
let d = `M ${first.x} ${first.y}`;
|
|
620
|
+
for (let i = 1; i < points.length - 1; i++) {
|
|
621
|
+
const a = points[i];
|
|
622
|
+
const b = points[i + 1];
|
|
623
|
+
if (!a || !b) continue;
|
|
624
|
+
const midX = (a.x + b.x) / 2;
|
|
625
|
+
const midY = (a.y + b.y) / 2;
|
|
626
|
+
d += ` Q ${a.x} ${a.y} ${midX} ${midY}`;
|
|
627
|
+
}
|
|
628
|
+
const last = points[points.length - 1];
|
|
629
|
+
if (last) {
|
|
630
|
+
d += ` L ${last.x} ${last.y}`;
|
|
631
|
+
}
|
|
632
|
+
return d;
|
|
633
|
+
}
|
|
599
634
|
function computeFreehandSvgPayload(pathPointsLocal, style, toolKind, strokeComplete = true) {
|
|
600
635
|
if (pathPointsLocal.length === 0) return null;
|
|
601
636
|
if (pathPointsLocal.length === 1) {
|
|
@@ -610,6 +645,18 @@ function computeFreehandSvgPayload(pathPointsLocal, style, toolKind, strokeCompl
|
|
|
610
645
|
fillOpacity: style.strokeOpacity
|
|
611
646
|
};
|
|
612
647
|
}
|
|
648
|
+
if (style.strokeDash === "dashed" && (toolKind === "draw" || toolKind === "pencil")) {
|
|
649
|
+
const d2 = buildSmoothedCenterlinePath(pathPointsLocal);
|
|
650
|
+
if (!d2) return null;
|
|
651
|
+
return {
|
|
652
|
+
kind: "strokePath",
|
|
653
|
+
d: d2,
|
|
654
|
+
stroke: style.stroke,
|
|
655
|
+
strokeWidth: style.strokeWidth,
|
|
656
|
+
strokeOpacity: style.strokeOpacity,
|
|
657
|
+
strokeDasharray: dashArrayForDrawStroke(style.strokeWidth)
|
|
658
|
+
};
|
|
659
|
+
}
|
|
613
660
|
const hasPressure = pathPointsLocal.some(
|
|
614
661
|
(p) => p.pressure != null && Number.isFinite(p.pressure)
|
|
615
662
|
);
|
|
@@ -652,7 +699,8 @@ function freehandPayloadToSvgString(payload) {
|
|
|
652
699
|
strokeWidth: payload.strokeWidth,
|
|
653
700
|
strokeOpacity: payload.strokeOpacity
|
|
654
701
|
});
|
|
655
|
-
|
|
702
|
+
const dash = payload.strokeDasharray ? ` stroke-dasharray="${payload.strokeDasharray}"` : "";
|
|
703
|
+
return `<path d="${payload.d}" fill="none" stroke="${payload.stroke}" stroke-width="${payload.strokeWidth}" stroke-linecap="round" stroke-linejoin="round" shape-rendering="geometricPrecision"${op}${dash} />`;
|
|
656
704
|
}
|
|
657
705
|
function buildFreehandPathSvg(pathPointsLocal, style, toolKind, strokeComplete = true) {
|
|
658
706
|
const payload = computeFreehandSvgPayload(
|
|
@@ -864,7 +912,7 @@ function createDrawDotItem(id, worldX, worldY, radius, style) {
|
|
|
864
912
|
childrenSvg: ""
|
|
865
913
|
});
|
|
866
914
|
}
|
|
867
|
-
function createTextItem(id, bounds, text = "", style) {
|
|
915
|
+
function createTextItem(id, bounds, text = "", style, textFontSize) {
|
|
868
916
|
const r = normalizeRect(bounds);
|
|
869
917
|
const s = { ...DEFAULT_STROKE_STYLE, ...style };
|
|
870
918
|
return rebuildItemSvg({
|
|
@@ -877,6 +925,7 @@ function createTextItem(id, bounds, text = "", style) {
|
|
|
877
925
|
stroke: s.stroke,
|
|
878
926
|
strokeWidth: s.strokeWidth,
|
|
879
927
|
...s.strokeOpacity != null ? { strokeOpacity: s.strokeOpacity } : {},
|
|
928
|
+
...textFontSize != null ? { textFontSize } : {},
|
|
880
929
|
childrenSvg: ""
|
|
881
930
|
});
|
|
882
931
|
}
|
|
@@ -913,6 +962,7 @@ function createFreehandStrokeItem(id, pointsWorld, toolKind, style) {
|
|
|
913
962
|
stroke: merged.stroke,
|
|
914
963
|
strokeWidth: merged.strokeWidth,
|
|
915
964
|
...merged.strokeOpacity != null ? { strokeOpacity: merged.strokeOpacity } : {},
|
|
965
|
+
...merged.strokeDash != null ? { strokeDash: merged.strokeDash } : {},
|
|
916
966
|
pathPointsLocal,
|
|
917
967
|
childrenSvg: ""
|
|
918
968
|
});
|
|
@@ -989,7 +1039,7 @@ var init_shape_builders = __esm({
|
|
|
989
1039
|
init_custom_shape();
|
|
990
1040
|
init_text_svg();
|
|
991
1041
|
DEFAULT_STROKE_STYLE = {
|
|
992
|
-
stroke: "#
|
|
1042
|
+
stroke: "#1d1d1d",
|
|
993
1043
|
strokeWidth: 2
|
|
994
1044
|
};
|
|
995
1045
|
TOOL_FREEHAND_DEFAULTS = {
|
|
@@ -3481,33 +3531,416 @@ var DEFAULT_VECTOR_TOOLS = [
|
|
|
3481
3531
|
shortcutHint: "I"
|
|
3482
3532
|
}
|
|
3483
3533
|
];
|
|
3534
|
+
|
|
3535
|
+
// src/react/VectorSelectionInspector.tsx
|
|
3536
|
+
init_text_svg();
|
|
3484
3537
|
var shellLook = {
|
|
3485
3538
|
display: "flex",
|
|
3486
3539
|
flexDirection: "column",
|
|
3487
|
-
gap:
|
|
3488
|
-
minWidth:
|
|
3489
|
-
padding: "
|
|
3490
|
-
borderRadius:
|
|
3491
|
-
border: "1px solid rgba(0,0,0,0.
|
|
3492
|
-
background: "rgba(255,255,255,0.
|
|
3493
|
-
boxShadow: "0 1px 3px rgba(0,0,0,0.08)",
|
|
3540
|
+
gap: 10,
|
|
3541
|
+
minWidth: 200,
|
|
3542
|
+
padding: "12px 14px",
|
|
3543
|
+
borderRadius: 10,
|
|
3544
|
+
border: "1px solid rgba(0,0,0,0.1)",
|
|
3545
|
+
background: "rgba(255,255,255,0.97)",
|
|
3546
|
+
boxShadow: "0 4px 16px rgba(0,0,0,0.06), 0 1px 3px rgba(0,0,0,0.08)",
|
|
3494
3547
|
pointerEvents: "auto"
|
|
3495
3548
|
};
|
|
3496
|
-
var
|
|
3549
|
+
var sectionLabelStyle = {
|
|
3497
3550
|
display: "flex",
|
|
3498
3551
|
flexDirection: "column",
|
|
3499
|
-
gap:
|
|
3552
|
+
gap: 6,
|
|
3500
3553
|
fontSize: 11,
|
|
3501
3554
|
fontWeight: 600,
|
|
3502
|
-
color: "#52525b"
|
|
3555
|
+
color: "#52525b",
|
|
3556
|
+
letterSpacing: "0.02em",
|
|
3557
|
+
textTransform: "uppercase"
|
|
3503
3558
|
};
|
|
3559
|
+
var mixedHintStyle = {
|
|
3560
|
+
fontWeight: 400,
|
|
3561
|
+
color: "#a1a1aa",
|
|
3562
|
+
textTransform: "none",
|
|
3563
|
+
letterSpacing: 0
|
|
3564
|
+
};
|
|
3565
|
+
var TLDRAW_PALETTE = [
|
|
3566
|
+
{ name: "black", hex: "#1d1d1d" },
|
|
3567
|
+
{ name: "grey", hex: "#9fa8b2" },
|
|
3568
|
+
{ name: "light-violet", hex: "#e085f4" },
|
|
3569
|
+
{ name: "violet", hex: "#ae3ec9" },
|
|
3570
|
+
{ name: "blue", hex: "#4263eb" },
|
|
3571
|
+
{ name: "light-blue", hex: "#4dabf7" },
|
|
3572
|
+
{ name: "yellow", hex: "#ffc078" },
|
|
3573
|
+
{ name: "orange", hex: "#f76707" },
|
|
3574
|
+
{ name: "green", hex: "#099268" },
|
|
3575
|
+
{ name: "light-green", hex: "#40c057" },
|
|
3576
|
+
{ name: "light-red", hex: "#ff8787" },
|
|
3577
|
+
{ name: "red", hex: "#e03131" }
|
|
3578
|
+
];
|
|
3504
3579
|
function normalizeHex(stroke) {
|
|
3505
3580
|
if (/^#[0-9A-Fa-f]{6}$/.test(stroke)) return stroke;
|
|
3506
|
-
return "#
|
|
3581
|
+
return "#1d1d1d";
|
|
3582
|
+
}
|
|
3583
|
+
function hexesEqual(a, b) {
|
|
3584
|
+
return a.toLowerCase() === b.toLowerCase();
|
|
3507
3585
|
}
|
|
3508
3586
|
function isStylableKind(tk) {
|
|
3509
3587
|
return tk === "rect" || tk === "ellipse" || tk === "architectural-cloud" || tk === "line" || tk === "arrow" || tk === "draw" || tk === "pencil" || tk === "brush" || tk === "marker" || tk === "text";
|
|
3510
3588
|
}
|
|
3589
|
+
var FONT_SIZE_PRESETS = [
|
|
3590
|
+
{ label: "S", size: 14 },
|
|
3591
|
+
{ label: "M", size: 18 },
|
|
3592
|
+
{ label: "L", size: 28 },
|
|
3593
|
+
{ label: "XL", size: 44 }
|
|
3594
|
+
];
|
|
3595
|
+
function ColorSwatch({ color, selected, onSelect }) {
|
|
3596
|
+
return /* @__PURE__ */ jsx(
|
|
3597
|
+
"button",
|
|
3598
|
+
{
|
|
3599
|
+
type: "button",
|
|
3600
|
+
"aria-label": color.name,
|
|
3601
|
+
"aria-pressed": selected,
|
|
3602
|
+
onClick: onSelect,
|
|
3603
|
+
onPointerDown: (e) => {
|
|
3604
|
+
if (e.pointerType === "mouse") e.preventDefault();
|
|
3605
|
+
},
|
|
3606
|
+
style: {
|
|
3607
|
+
width: 24,
|
|
3608
|
+
height: 24,
|
|
3609
|
+
padding: 0,
|
|
3610
|
+
borderRadius: "50%",
|
|
3611
|
+
border: selected ? "2px solid #18181b" : "1px solid rgba(0,0,0,0.12)",
|
|
3612
|
+
background: color.hex,
|
|
3613
|
+
cursor: "pointer",
|
|
3614
|
+
outline: "none",
|
|
3615
|
+
boxShadow: selected ? "0 0 0 2px rgba(255,255,255,0.95) inset" : "none",
|
|
3616
|
+
transition: "transform 0.08s ease",
|
|
3617
|
+
transform: selected ? "scale(1.08)" : "scale(1)",
|
|
3618
|
+
WebkitTapHighlightColor: "transparent"
|
|
3619
|
+
}
|
|
3620
|
+
}
|
|
3621
|
+
);
|
|
3622
|
+
}
|
|
3623
|
+
function ColorPalette({ value, onChange }) {
|
|
3624
|
+
const [showCustom, setShowCustom] = useState(false);
|
|
3625
|
+
const normalized = normalizeHex(value);
|
|
3626
|
+
const inPalette = TLDRAW_PALETTE.some((c) => hexesEqual(c.hex, normalized));
|
|
3627
|
+
return /* @__PURE__ */ jsxs(
|
|
3628
|
+
"div",
|
|
3629
|
+
{
|
|
3630
|
+
style: {
|
|
3631
|
+
display: "grid",
|
|
3632
|
+
gridTemplateColumns: "repeat(6, 24px)",
|
|
3633
|
+
gap: 6,
|
|
3634
|
+
rowGap: 6,
|
|
3635
|
+
alignItems: "center"
|
|
3636
|
+
},
|
|
3637
|
+
children: [
|
|
3638
|
+
TLDRAW_PALETTE.map((c) => /* @__PURE__ */ jsx(
|
|
3639
|
+
ColorSwatch,
|
|
3640
|
+
{
|
|
3641
|
+
color: c,
|
|
3642
|
+
selected: hexesEqual(c.hex, normalized),
|
|
3643
|
+
onSelect: () => onChange(c.hex)
|
|
3644
|
+
},
|
|
3645
|
+
c.name
|
|
3646
|
+
)),
|
|
3647
|
+
/* @__PURE__ */ jsx(
|
|
3648
|
+
"button",
|
|
3649
|
+
{
|
|
3650
|
+
type: "button",
|
|
3651
|
+
"aria-label": "Cor personalizada",
|
|
3652
|
+
"aria-pressed": showCustom || !inPalette,
|
|
3653
|
+
onClick: () => setShowCustom((v) => !v),
|
|
3654
|
+
onPointerDown: (e) => {
|
|
3655
|
+
if (e.pointerType === "mouse") e.preventDefault();
|
|
3656
|
+
},
|
|
3657
|
+
style: {
|
|
3658
|
+
width: 24,
|
|
3659
|
+
height: 24,
|
|
3660
|
+
padding: 0,
|
|
3661
|
+
borderRadius: "50%",
|
|
3662
|
+
border: !inPalette || showCustom ? "2px solid #18181b" : "1px solid rgba(0,0,0,0.12)",
|
|
3663
|
+
background: "conic-gradient(from 0deg, #ff5757, #ffbd59, #59ff7e, #59ddff, #b259ff, #ff59c1, #ff5757)",
|
|
3664
|
+
cursor: "pointer",
|
|
3665
|
+
outline: "none",
|
|
3666
|
+
WebkitTapHighlightColor: "transparent"
|
|
3667
|
+
}
|
|
3668
|
+
}
|
|
3669
|
+
),
|
|
3670
|
+
showCustom || !inPalette ? /* @__PURE__ */ jsxs(
|
|
3671
|
+
"label",
|
|
3672
|
+
{
|
|
3673
|
+
style: {
|
|
3674
|
+
gridColumn: "1 / -1",
|
|
3675
|
+
display: "flex",
|
|
3676
|
+
alignItems: "center",
|
|
3677
|
+
gap: 6,
|
|
3678
|
+
fontSize: 11,
|
|
3679
|
+
fontWeight: 500,
|
|
3680
|
+
color: "#71717a",
|
|
3681
|
+
textTransform: "none",
|
|
3682
|
+
letterSpacing: 0
|
|
3683
|
+
},
|
|
3684
|
+
children: [
|
|
3685
|
+
/* @__PURE__ */ jsx(
|
|
3686
|
+
"input",
|
|
3687
|
+
{
|
|
3688
|
+
type: "color",
|
|
3689
|
+
value: normalized,
|
|
3690
|
+
onChange: (e) => onChange(e.target.value),
|
|
3691
|
+
style: {
|
|
3692
|
+
width: 28,
|
|
3693
|
+
height: 28,
|
|
3694
|
+
padding: 0,
|
|
3695
|
+
border: "1px solid rgba(0,0,0,0.12)",
|
|
3696
|
+
borderRadius: 6,
|
|
3697
|
+
cursor: "pointer",
|
|
3698
|
+
background: "transparent"
|
|
3699
|
+
}
|
|
3700
|
+
}
|
|
3701
|
+
),
|
|
3702
|
+
/* @__PURE__ */ jsx("span", { style: { fontVariantNumeric: "tabular-nums" }, children: normalized.toUpperCase() })
|
|
3703
|
+
]
|
|
3704
|
+
}
|
|
3705
|
+
) : null
|
|
3706
|
+
]
|
|
3707
|
+
}
|
|
3708
|
+
);
|
|
3709
|
+
}
|
|
3710
|
+
function DashTabs({ value, onChange }) {
|
|
3711
|
+
const tabs = [
|
|
3712
|
+
{ id: "solid", label: "Cont\xEDnuo" },
|
|
3713
|
+
{ id: "dashed", label: "Tracejado" }
|
|
3714
|
+
];
|
|
3715
|
+
return /* @__PURE__ */ jsx(
|
|
3716
|
+
"div",
|
|
3717
|
+
{
|
|
3718
|
+
role: "radiogroup",
|
|
3719
|
+
"aria-label": "Estilo do tra\xE7o",
|
|
3720
|
+
style: {
|
|
3721
|
+
display: "flex",
|
|
3722
|
+
background: "rgba(24,24,27,0.06)",
|
|
3723
|
+
borderRadius: 7,
|
|
3724
|
+
padding: 2,
|
|
3725
|
+
gap: 2
|
|
3726
|
+
},
|
|
3727
|
+
children: tabs.map((t) => {
|
|
3728
|
+
const selected = value === t.id;
|
|
3729
|
+
return (
|
|
3730
|
+
// biome-ignore lint/a11y/useSemanticElements: styled segmented control needs button, not input[type=radio]
|
|
3731
|
+
/* @__PURE__ */ jsxs(
|
|
3732
|
+
"button",
|
|
3733
|
+
{
|
|
3734
|
+
type: "button",
|
|
3735
|
+
role: "radio",
|
|
3736
|
+
"aria-checked": selected,
|
|
3737
|
+
onClick: () => onChange(t.id),
|
|
3738
|
+
onPointerDown: (e) => {
|
|
3739
|
+
if (e.pointerType === "mouse") e.preventDefault();
|
|
3740
|
+
},
|
|
3741
|
+
style: {
|
|
3742
|
+
flex: 1,
|
|
3743
|
+
display: "inline-flex",
|
|
3744
|
+
alignItems: "center",
|
|
3745
|
+
justifyContent: "center",
|
|
3746
|
+
padding: "5px 8px",
|
|
3747
|
+
fontSize: 11,
|
|
3748
|
+
fontWeight: 600,
|
|
3749
|
+
color: selected ? "#18181b" : "#71717a",
|
|
3750
|
+
background: selected ? "#fff" : "transparent",
|
|
3751
|
+
borderRadius: 5,
|
|
3752
|
+
border: "none",
|
|
3753
|
+
cursor: "pointer",
|
|
3754
|
+
boxShadow: selected ? "0 1px 2px rgba(0,0,0,0.1)" : "none",
|
|
3755
|
+
outline: "none",
|
|
3756
|
+
WebkitTapHighlightColor: "transparent"
|
|
3757
|
+
},
|
|
3758
|
+
children: [
|
|
3759
|
+
/* @__PURE__ */ jsx(DashTabSwatch, { dashed: t.id === "dashed" }),
|
|
3760
|
+
/* @__PURE__ */ jsx("span", { style: { marginLeft: 6 }, children: t.label })
|
|
3761
|
+
]
|
|
3762
|
+
},
|
|
3763
|
+
t.id
|
|
3764
|
+
)
|
|
3765
|
+
);
|
|
3766
|
+
})
|
|
3767
|
+
}
|
|
3768
|
+
);
|
|
3769
|
+
}
|
|
3770
|
+
function DashTabSwatch({ dashed }) {
|
|
3771
|
+
return /* @__PURE__ */ jsxs(
|
|
3772
|
+
"svg",
|
|
3773
|
+
{
|
|
3774
|
+
width: 26,
|
|
3775
|
+
height: 6,
|
|
3776
|
+
"aria-hidden": true,
|
|
3777
|
+
style: { flexShrink: 0, display: "block" },
|
|
3778
|
+
children: [
|
|
3779
|
+
/* @__PURE__ */ jsx("title", { children: dashed ? "dashed" : "solid" }),
|
|
3780
|
+
/* @__PURE__ */ jsx(
|
|
3781
|
+
"line",
|
|
3782
|
+
{
|
|
3783
|
+
x1: 1,
|
|
3784
|
+
y1: 3,
|
|
3785
|
+
x2: 25,
|
|
3786
|
+
y2: 3,
|
|
3787
|
+
stroke: "currentColor",
|
|
3788
|
+
strokeWidth: 2,
|
|
3789
|
+
strokeLinecap: "round",
|
|
3790
|
+
strokeDasharray: dashed ? "4 3" : void 0
|
|
3791
|
+
}
|
|
3792
|
+
)
|
|
3793
|
+
]
|
|
3794
|
+
}
|
|
3795
|
+
);
|
|
3796
|
+
}
|
|
3797
|
+
function FontSizeTabs({ value, onChange }) {
|
|
3798
|
+
return /* @__PURE__ */ jsx(
|
|
3799
|
+
"div",
|
|
3800
|
+
{
|
|
3801
|
+
role: "radiogroup",
|
|
3802
|
+
"aria-label": "Tamanho do texto",
|
|
3803
|
+
style: {
|
|
3804
|
+
display: "flex",
|
|
3805
|
+
background: "rgba(24,24,27,0.06)",
|
|
3806
|
+
borderRadius: 7,
|
|
3807
|
+
padding: 2,
|
|
3808
|
+
gap: 2
|
|
3809
|
+
},
|
|
3810
|
+
children: FONT_SIZE_PRESETS.map((p) => {
|
|
3811
|
+
const selected = Math.abs(value - p.size) < 0.5;
|
|
3812
|
+
return (
|
|
3813
|
+
// biome-ignore lint/a11y/useSemanticElements: styled segmented control needs button, not input[type=radio]
|
|
3814
|
+
/* @__PURE__ */ jsx(
|
|
3815
|
+
"button",
|
|
3816
|
+
{
|
|
3817
|
+
type: "button",
|
|
3818
|
+
role: "radio",
|
|
3819
|
+
"aria-checked": selected,
|
|
3820
|
+
"aria-label": `${p.label} (${p.size}px)`,
|
|
3821
|
+
onClick: () => onChange(p.size),
|
|
3822
|
+
onPointerDown: (e) => {
|
|
3823
|
+
if (e.pointerType === "mouse") e.preventDefault();
|
|
3824
|
+
},
|
|
3825
|
+
style: {
|
|
3826
|
+
flex: 1,
|
|
3827
|
+
padding: "5px 0",
|
|
3828
|
+
fontSize: p.label === "XL" ? 14 : p.label === "L" ? 13 : 12,
|
|
3829
|
+
fontWeight: 700,
|
|
3830
|
+
color: selected ? "#18181b" : "#71717a",
|
|
3831
|
+
background: selected ? "#fff" : "transparent",
|
|
3832
|
+
borderRadius: 5,
|
|
3833
|
+
border: "none",
|
|
3834
|
+
cursor: "pointer",
|
|
3835
|
+
boxShadow: selected ? "0 1px 2px rgba(0,0,0,0.1)" : "none",
|
|
3836
|
+
outline: "none",
|
|
3837
|
+
WebkitTapHighlightColor: "transparent",
|
|
3838
|
+
lineHeight: 1
|
|
3839
|
+
},
|
|
3840
|
+
children: p.label
|
|
3841
|
+
},
|
|
3842
|
+
p.label
|
|
3843
|
+
)
|
|
3844
|
+
);
|
|
3845
|
+
})
|
|
3846
|
+
}
|
|
3847
|
+
);
|
|
3848
|
+
}
|
|
3849
|
+
function viewModelFromActiveTool(activeToolStyle) {
|
|
3850
|
+
const hex = normalizeHex(activeToolStyle.stroke);
|
|
3851
|
+
const strokeWidth = activeToolStyle.strokeWidth;
|
|
3852
|
+
const strokeOpacity = activeToolStyle.strokeOpacity ?? 1;
|
|
3853
|
+
const strokeDash = activeToolStyle.strokeDash === "dashed" ? "dashed" : "solid";
|
|
3854
|
+
const textFontSize = activeToolStyle.textFontSize ?? DEFAULT_TEXT_FONT_SIZE;
|
|
3855
|
+
const isText = activeToolStyle.toolKind === "text";
|
|
3856
|
+
const isDraw = activeToolStyle.toolKind === "draw";
|
|
3857
|
+
const isMarker = activeToolStyle.toolKind === "marker";
|
|
3858
|
+
const current = {
|
|
3859
|
+
stroke: hex,
|
|
3860
|
+
strokeWidth,
|
|
3861
|
+
...activeToolStyle.strokeOpacity != null ? { strokeOpacity: activeToolStyle.strokeOpacity } : {},
|
|
3862
|
+
...activeToolStyle.strokeDash != null ? { strokeDash: activeToolStyle.strokeDash } : {},
|
|
3863
|
+
...isText ? { textFontSize } : {}
|
|
3864
|
+
};
|
|
3865
|
+
return {
|
|
3866
|
+
label: activeToolStyle.label ?? "Estilo da ferramenta",
|
|
3867
|
+
count: 0,
|
|
3868
|
+
hex,
|
|
3869
|
+
strokeWidth,
|
|
3870
|
+
strokeOpacity,
|
|
3871
|
+
strokeDash,
|
|
3872
|
+
textFontSize,
|
|
3873
|
+
showStrokeWidth: !isText,
|
|
3874
|
+
showDash: isDraw,
|
|
3875
|
+
showFontSize: isText,
|
|
3876
|
+
showMarkerOpacity: isMarker,
|
|
3877
|
+
mixedStroke: false,
|
|
3878
|
+
mixedWidth: false,
|
|
3879
|
+
mixedDash: false,
|
|
3880
|
+
mixedFontSize: false,
|
|
3881
|
+
mixedOpacity: false,
|
|
3882
|
+
current
|
|
3883
|
+
};
|
|
3884
|
+
}
|
|
3885
|
+
function viewModelFromSelection(stylable) {
|
|
3886
|
+
const first = stylable[0];
|
|
3887
|
+
if (!first) return null;
|
|
3888
|
+
const hex = normalizeHex(first.stroke ?? "#1d1d1d");
|
|
3889
|
+
const strokeWidth = first.strokeWidth ?? 2;
|
|
3890
|
+
const allSameStroke = stylable.every(
|
|
3891
|
+
(it) => (it.stroke ?? "#1d1d1d") === (first.stroke ?? "#1d1d1d")
|
|
3892
|
+
);
|
|
3893
|
+
const allSameWidth = stylable.every(
|
|
3894
|
+
(it) => (it.strokeWidth ?? 2) === (first.strokeWidth ?? 2)
|
|
3895
|
+
);
|
|
3896
|
+
const draws = stylable.filter(
|
|
3897
|
+
(it) => it.toolKind === "draw" || it.toolKind === "pencil"
|
|
3898
|
+
);
|
|
3899
|
+
const showDash = draws.length > 0;
|
|
3900
|
+
const firstDraw = draws[0];
|
|
3901
|
+
const strokeDash = firstDraw?.strokeDash === "dashed" ? "dashed" : "solid";
|
|
3902
|
+
const allSameDash = draws.length === 0 || draws.every((it) => (it.strokeDash ?? "solid") === strokeDash);
|
|
3903
|
+
const markers = stylable.filter((it) => it.toolKind === "marker");
|
|
3904
|
+
const showMarkerOpacity = markers.length > 0;
|
|
3905
|
+
const firstMarker = markers[0];
|
|
3906
|
+
const strokeOpacity = firstMarker?.strokeOpacity ?? 1;
|
|
3907
|
+
const allSameOpacity = markers.length === 0 || markers.every(
|
|
3908
|
+
(it) => (it.strokeOpacity ?? 1) === (firstMarker?.strokeOpacity ?? 1)
|
|
3909
|
+
);
|
|
3910
|
+
const texts = stylable.filter((it) => it.toolKind === "text");
|
|
3911
|
+
const showFontSize = texts.length > 0;
|
|
3912
|
+
const firstText = texts[0];
|
|
3913
|
+
const textFontSize = firstText?.textFontSize ?? DEFAULT_TEXT_FONT_SIZE;
|
|
3914
|
+
const allSameFontSize = texts.length === 0 || texts.every(
|
|
3915
|
+
(it) => (it.textFontSize ?? DEFAULT_TEXT_FONT_SIZE) === textFontSize
|
|
3916
|
+
);
|
|
3917
|
+
const current = {
|
|
3918
|
+
stroke: hex,
|
|
3919
|
+
strokeWidth,
|
|
3920
|
+
...showMarkerOpacity ? { strokeOpacity } : {},
|
|
3921
|
+
...showDash ? { strokeDash } : {},
|
|
3922
|
+
...showFontSize ? { textFontSize } : {}
|
|
3923
|
+
};
|
|
3924
|
+
return {
|
|
3925
|
+
label: "Estilo da sele\xE7\xE3o",
|
|
3926
|
+
count: stylable.length,
|
|
3927
|
+
hex,
|
|
3928
|
+
strokeWidth,
|
|
3929
|
+
strokeOpacity,
|
|
3930
|
+
strokeDash,
|
|
3931
|
+
textFontSize,
|
|
3932
|
+
showStrokeWidth: true,
|
|
3933
|
+
showDash,
|
|
3934
|
+
showFontSize,
|
|
3935
|
+
showMarkerOpacity,
|
|
3936
|
+
mixedStroke: !allSameStroke,
|
|
3937
|
+
mixedWidth: !allSameWidth,
|
|
3938
|
+
mixedDash: !allSameDash,
|
|
3939
|
+
mixedFontSize: !allSameFontSize,
|
|
3940
|
+
mixedOpacity: !allSameOpacity,
|
|
3941
|
+
current
|
|
3942
|
+
};
|
|
3943
|
+
}
|
|
3511
3944
|
function VectorSelectionInspector({
|
|
3512
3945
|
items: itemsProp,
|
|
3513
3946
|
activeToolStyle: activeToolStyleProp,
|
|
@@ -3523,175 +3956,93 @@ function VectorSelectionInspector({
|
|
|
3523
3956
|
const activeToolStyle = activeToolStyleProp === void 0 ? ctx?.activeToolStyle ?? null : activeToolStyleProp;
|
|
3524
3957
|
const onChange = onChangeProp ?? ctx?.onSelectionStyleChange ?? null;
|
|
3525
3958
|
if (!onChange) return null;
|
|
3959
|
+
let vm = null;
|
|
3960
|
+
if (activeToolStyle) {
|
|
3961
|
+
vm = viewModelFromActiveTool(activeToolStyle);
|
|
3962
|
+
} else {
|
|
3963
|
+
const stylable = items.filter(
|
|
3964
|
+
(it) => !it.locked && it.toolKind && isStylableKind(it.toolKind)
|
|
3965
|
+
);
|
|
3966
|
+
if (stylable.length === 0) return null;
|
|
3967
|
+
vm = viewModelFromSelection(stylable);
|
|
3968
|
+
}
|
|
3969
|
+
if (!vm) return null;
|
|
3970
|
+
const apply = (changes) => onChange({ ...vm.current, ...changes });
|
|
3526
3971
|
const shell = {
|
|
3527
3972
|
...getBoardPositionStyle(position, inset, zIndex),
|
|
3528
3973
|
...shellLook,
|
|
3529
3974
|
...style
|
|
3530
3975
|
};
|
|
3531
|
-
|
|
3532
|
-
const stroke2 = activeToolStyle.stroke;
|
|
3533
|
-
const strokeWidth2 = activeToolStyle.strokeWidth;
|
|
3534
|
-
const hex2 = normalizeHex(stroke2);
|
|
3535
|
-
const showMarkerOpacity2 = activeToolStyle.toolKind === "marker";
|
|
3536
|
-
const opacityPct2 = Math.round((activeToolStyle.strokeOpacity ?? 1) * 100);
|
|
3537
|
-
return /* @__PURE__ */ jsxs(
|
|
3538
|
-
"section",
|
|
3539
|
-
{
|
|
3540
|
-
"data-slot": "vector-selection-inspector",
|
|
3541
|
-
"data-position": position,
|
|
3542
|
-
className,
|
|
3543
|
-
"aria-label": activeToolStyle.label ?? "Estilo da ferramenta",
|
|
3544
|
-
style: shell,
|
|
3545
|
-
children: [
|
|
3546
|
-
/* @__PURE__ */ jsxs("label", { style: labelStyle2, children: [
|
|
3547
|
-
"Cor",
|
|
3548
|
-
/* @__PURE__ */ jsx(
|
|
3549
|
-
"input",
|
|
3550
|
-
{
|
|
3551
|
-
type: "color",
|
|
3552
|
-
value: hex2,
|
|
3553
|
-
onChange: (e) => onChange({
|
|
3554
|
-
stroke: e.target.value,
|
|
3555
|
-
strokeWidth: strokeWidth2,
|
|
3556
|
-
...activeToolStyle.strokeOpacity != null ? { strokeOpacity: activeToolStyle.strokeOpacity } : {}
|
|
3557
|
-
}),
|
|
3558
|
-
style: {
|
|
3559
|
-
width: "100%",
|
|
3560
|
-
height: 32,
|
|
3561
|
-
padding: 0,
|
|
3562
|
-
border: "none",
|
|
3563
|
-
cursor: "pointer",
|
|
3564
|
-
background: "transparent"
|
|
3565
|
-
}
|
|
3566
|
-
}
|
|
3567
|
-
)
|
|
3568
|
-
] }),
|
|
3569
|
-
/* @__PURE__ */ jsxs("label", { style: labelStyle2, children: [
|
|
3570
|
-
"Grossura",
|
|
3571
|
-
/* @__PURE__ */ jsx(
|
|
3572
|
-
"input",
|
|
3573
|
-
{
|
|
3574
|
-
type: "range",
|
|
3575
|
-
min: 1,
|
|
3576
|
-
max: 48,
|
|
3577
|
-
value: strokeWidth2,
|
|
3578
|
-
onChange: (e) => onChange({
|
|
3579
|
-
stroke: hex2,
|
|
3580
|
-
strokeWidth: Number(e.target.value),
|
|
3581
|
-
...activeToolStyle.strokeOpacity != null ? { strokeOpacity: activeToolStyle.strokeOpacity } : {}
|
|
3582
|
-
})
|
|
3583
|
-
}
|
|
3584
|
-
)
|
|
3585
|
-
] }),
|
|
3586
|
-
showMarkerOpacity2 && /* @__PURE__ */ jsxs("label", { style: labelStyle2, children: [
|
|
3587
|
-
"Opacidade (marcador)",
|
|
3588
|
-
/* @__PURE__ */ jsx(
|
|
3589
|
-
"input",
|
|
3590
|
-
{
|
|
3591
|
-
type: "range",
|
|
3592
|
-
min: 10,
|
|
3593
|
-
max: 100,
|
|
3594
|
-
value: opacityPct2,
|
|
3595
|
-
onChange: (e) => {
|
|
3596
|
-
const v = Number(e.target.value) / 100;
|
|
3597
|
-
onChange({
|
|
3598
|
-
stroke: hex2,
|
|
3599
|
-
strokeWidth: strokeWidth2,
|
|
3600
|
-
strokeOpacity: v
|
|
3601
|
-
});
|
|
3602
|
-
}
|
|
3603
|
-
}
|
|
3604
|
-
),
|
|
3605
|
-
/* @__PURE__ */ jsxs("span", { style: { fontWeight: 500, color: "#71717a" }, children: [
|
|
3606
|
-
opacityPct2,
|
|
3607
|
-
"%"
|
|
3608
|
-
] })
|
|
3609
|
-
] })
|
|
3610
|
-
]
|
|
3611
|
-
}
|
|
3612
|
-
);
|
|
3613
|
-
}
|
|
3614
|
-
const stylable = items.filter(
|
|
3615
|
-
(it) => !it.locked && it.toolKind && isStylableKind(it.toolKind)
|
|
3616
|
-
);
|
|
3617
|
-
if (stylable.length === 0) return null;
|
|
3618
|
-
const first = stylable[0];
|
|
3619
|
-
if (!first) return null;
|
|
3620
|
-
const allSameStroke = stylable.every(
|
|
3621
|
-
(it) => (it.stroke ?? "#2563eb") === (first.stroke ?? "#2563eb")
|
|
3622
|
-
);
|
|
3623
|
-
const allSameWidth = stylable.every(
|
|
3624
|
-
(it) => (it.strokeWidth ?? 2) === (first.strokeWidth ?? 2)
|
|
3625
|
-
);
|
|
3626
|
-
const stroke = first.stroke ?? "#2563eb";
|
|
3627
|
-
const strokeWidth = first.strokeWidth ?? 2;
|
|
3628
|
-
const hex = normalizeHex(stroke);
|
|
3629
|
-
const markers = stylable.filter((it) => it.toolKind === "marker");
|
|
3630
|
-
const showMarkerOpacity = markers.length > 0;
|
|
3631
|
-
const firstMarker = markers[0];
|
|
3632
|
-
const allSameMarkerOpacity = markers.length > 0 && markers.every(
|
|
3633
|
-
(it) => (it.strokeOpacity ?? 1) === (firstMarker?.strokeOpacity ?? 1)
|
|
3634
|
-
);
|
|
3635
|
-
const opacityPct = firstMarker ? Math.round((firstMarker.strokeOpacity ?? 1) * 100) : 100;
|
|
3976
|
+
const opacityPct = Math.round(vm.strokeOpacity * 100);
|
|
3636
3977
|
return /* @__PURE__ */ jsxs(
|
|
3637
3978
|
"section",
|
|
3638
3979
|
{
|
|
3639
3980
|
"data-slot": "vector-selection-inspector",
|
|
3640
3981
|
"data-position": position,
|
|
3641
3982
|
className,
|
|
3642
|
-
"aria-label":
|
|
3983
|
+
"aria-label": vm.label,
|
|
3643
3984
|
style: shell,
|
|
3644
3985
|
children: [
|
|
3645
|
-
|
|
3646
|
-
|
|
3986
|
+
vm.count > 1 ? /* @__PURE__ */ jsxs("p", { style: { margin: 0, fontSize: 11, color: "#71717a" }, children: [
|
|
3987
|
+
vm.count,
|
|
3647
3988
|
" objetos selecionados"
|
|
3648
|
-
] }),
|
|
3649
|
-
/* @__PURE__ */ jsxs("
|
|
3650
|
-
"
|
|
3651
|
-
|
|
3652
|
-
" "
|
|
3653
|
-
"(valores misturados \u2014 novo valor aplica a todos)"
|
|
3989
|
+
] }) : null,
|
|
3990
|
+
/* @__PURE__ */ jsxs("div", { role: "group", "aria-label": "Cor", style: sectionLabelStyle, children: [
|
|
3991
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
3992
|
+
"Cor",
|
|
3993
|
+
vm.mixedStroke ? /* @__PURE__ */ jsx("span", { style: mixedHintStyle, children: " (valores misturados)" }) : null
|
|
3654
3994
|
] }),
|
|
3655
|
-
/* @__PURE__ */ jsx(
|
|
3656
|
-
"input",
|
|
3657
|
-
{
|
|
3658
|
-
type: "color",
|
|
3659
|
-
value: hex,
|
|
3660
|
-
onChange: (e) => onChange({
|
|
3661
|
-
stroke: e.target.value,
|
|
3662
|
-
strokeWidth
|
|
3663
|
-
}),
|
|
3664
|
-
style: {
|
|
3665
|
-
width: "100%",
|
|
3666
|
-
height: 32,
|
|
3667
|
-
padding: 0,
|
|
3668
|
-
border: "none",
|
|
3669
|
-
cursor: "pointer",
|
|
3670
|
-
background: "transparent"
|
|
3671
|
-
}
|
|
3672
|
-
}
|
|
3673
|
-
)
|
|
3995
|
+
/* @__PURE__ */ jsx(ColorPalette, { value: vm.hex, onChange: (h) => apply({ stroke: h }) })
|
|
3674
3996
|
] }),
|
|
3675
|
-
/* @__PURE__ */ jsxs("label", { style:
|
|
3997
|
+
vm.showStrokeWidth ? /* @__PURE__ */ jsxs("label", { style: sectionLabelStyle, children: [
|
|
3676
3998
|
"Grossura",
|
|
3677
|
-
|
|
3999
|
+
vm.mixedWidth ? /* @__PURE__ */ jsx("span", { style: mixedHintStyle, children: " (misturado)" }) : null,
|
|
3678
4000
|
/* @__PURE__ */ jsx(
|
|
3679
4001
|
"input",
|
|
3680
4002
|
{
|
|
3681
4003
|
type: "range",
|
|
3682
4004
|
min: 1,
|
|
3683
4005
|
max: 48,
|
|
3684
|
-
value: strokeWidth,
|
|
3685
|
-
onChange: (e) =>
|
|
3686
|
-
stroke: hex,
|
|
3687
|
-
strokeWidth: Number(e.target.value)
|
|
3688
|
-
})
|
|
4006
|
+
value: vm.strokeWidth,
|
|
4007
|
+
onChange: (e) => apply({ strokeWidth: Number(e.target.value) })
|
|
3689
4008
|
}
|
|
3690
4009
|
)
|
|
3691
|
-
] }),
|
|
3692
|
-
|
|
3693
|
-
|
|
3694
|
-
|
|
4010
|
+
] }) : null,
|
|
4011
|
+
vm.showDash ? (
|
|
4012
|
+
// biome-ignore lint/a11y/useSemanticElements: fieldset would impose default browser styling that breaks the inspector layout
|
|
4013
|
+
/* @__PURE__ */ jsxs("div", { role: "group", "aria-label": "Tra\xE7o", style: sectionLabelStyle, children: [
|
|
4014
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
4015
|
+
"Tra\xE7o",
|
|
4016
|
+
vm.mixedDash ? /* @__PURE__ */ jsx("span", { style: mixedHintStyle, children: " (misturado)" }) : null
|
|
4017
|
+
] }),
|
|
4018
|
+
/* @__PURE__ */ jsx(
|
|
4019
|
+
DashTabs,
|
|
4020
|
+
{
|
|
4021
|
+
value: vm.strokeDash,
|
|
4022
|
+
onChange: (next) => apply({ strokeDash: next })
|
|
4023
|
+
}
|
|
4024
|
+
)
|
|
4025
|
+
] })
|
|
4026
|
+
) : null,
|
|
4027
|
+
vm.showFontSize ? (
|
|
4028
|
+
// biome-ignore lint/a11y/useSemanticElements: fieldset would impose default browser styling that breaks the inspector layout
|
|
4029
|
+
/* @__PURE__ */ jsxs("div", { role: "group", "aria-label": "Tamanho", style: sectionLabelStyle, children: [
|
|
4030
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
4031
|
+
"Tamanho",
|
|
4032
|
+
vm.mixedFontSize ? /* @__PURE__ */ jsx("span", { style: mixedHintStyle, children: " (misturado)" }) : null
|
|
4033
|
+
] }),
|
|
4034
|
+
/* @__PURE__ */ jsx(
|
|
4035
|
+
FontSizeTabs,
|
|
4036
|
+
{
|
|
4037
|
+
value: vm.textFontSize,
|
|
4038
|
+
onChange: (size) => apply({ textFontSize: size })
|
|
4039
|
+
}
|
|
4040
|
+
)
|
|
4041
|
+
] })
|
|
4042
|
+
) : null,
|
|
4043
|
+
vm.showMarkerOpacity ? /* @__PURE__ */ jsxs("label", { style: sectionLabelStyle, children: [
|
|
4044
|
+
"Opacidade",
|
|
4045
|
+
vm.mixedOpacity ? /* @__PURE__ */ jsx("span", { style: mixedHintStyle, children: " (misturado)" }) : null,
|
|
3695
4046
|
/* @__PURE__ */ jsx(
|
|
3696
4047
|
"input",
|
|
3697
4048
|
{
|
|
@@ -3699,21 +4050,14 @@ function VectorSelectionInspector({
|
|
|
3699
4050
|
min: 10,
|
|
3700
4051
|
max: 100,
|
|
3701
4052
|
value: opacityPct,
|
|
3702
|
-
onChange: (e) => {
|
|
3703
|
-
const v = Number(e.target.value) / 100;
|
|
3704
|
-
onChange({
|
|
3705
|
-
stroke: hex,
|
|
3706
|
-
strokeWidth,
|
|
3707
|
-
strokeOpacity: v
|
|
3708
|
-
});
|
|
3709
|
-
}
|
|
4053
|
+
onChange: (e) => apply({ strokeOpacity: Number(e.target.value) / 100 })
|
|
3710
4054
|
}
|
|
3711
4055
|
),
|
|
3712
4056
|
/* @__PURE__ */ jsxs("span", { style: { fontWeight: 500, color: "#71717a" }, children: [
|
|
3713
4057
|
opacityPct,
|
|
3714
4058
|
"%"
|
|
3715
4059
|
] })
|
|
3716
|
-
] })
|
|
4060
|
+
] }) : null
|
|
3717
4061
|
]
|
|
3718
4062
|
}
|
|
3719
4063
|
);
|
|
@@ -4192,6 +4536,24 @@ function splitToolbarTools(tools, overflowIds) {
|
|
|
4192
4536
|
const overflow = overflowIds.map((id) => tools.find((t) => t.id === id)).filter((t) => Boolean(t));
|
|
4193
4537
|
return { primary, overflow };
|
|
4194
4538
|
}
|
|
4539
|
+
function usePromotedOverflowTool({
|
|
4540
|
+
overflowTools,
|
|
4541
|
+
selectedId,
|
|
4542
|
+
initialPromotedId
|
|
4543
|
+
}) {
|
|
4544
|
+
const [lastOverflowToolId, setLastOverflowToolId] = useState(() => {
|
|
4545
|
+
if (initialPromotedId == null) return null;
|
|
4546
|
+
return overflowTools.some((t) => t.id === initialPromotedId) ? initialPromotedId : null;
|
|
4547
|
+
});
|
|
4548
|
+
useEffect(() => {
|
|
4549
|
+
if (overflowTools.some((t) => t.id === selectedId)) {
|
|
4550
|
+
setLastOverflowToolId(selectedId);
|
|
4551
|
+
}
|
|
4552
|
+
}, [selectedId, overflowTools]);
|
|
4553
|
+
const promotedTool = lastOverflowToolId ? overflowTools.find((t) => t.id === lastOverflowToolId) : void 0;
|
|
4554
|
+
const remainingOverflowTools = promotedTool ? overflowTools.filter((t) => t.id !== promotedTool.id) : overflowTools;
|
|
4555
|
+
return { promotedTool, remainingOverflowTools };
|
|
4556
|
+
}
|
|
4195
4557
|
var icOverflow = { size: 18, strokeWidth: 2 };
|
|
4196
4558
|
function useOverflowDropdown() {
|
|
4197
4559
|
const [open, setOpen] = useState(false);
|
|
@@ -4726,6 +5088,15 @@ function VectorToolbarComponent({
|
|
|
4726
5088
|
const pluginContext = useContext(CanvuPluginContext);
|
|
4727
5089
|
const runtimeTools = pluginContext?.resolvedTools;
|
|
4728
5090
|
const resolvedTools = tools ?? runtimeTools ?? DEFAULT_VECTOR_TOOLS;
|
|
5091
|
+
const { primary: primaryTools, overflow: overflowTools } = splitToolbarTools(
|
|
5092
|
+
resolvedTools,
|
|
5093
|
+
overflowToolIds
|
|
5094
|
+
);
|
|
5095
|
+
const { promotedTool, remainingOverflowTools } = usePromotedOverflowTool({
|
|
5096
|
+
overflowTools,
|
|
5097
|
+
selectedId: value,
|
|
5098
|
+
initialPromotedId: overflowToolIds[0] ?? null
|
|
5099
|
+
});
|
|
4729
5100
|
if (typeof children === "function") {
|
|
4730
5101
|
const ctx = {
|
|
4731
5102
|
tools: resolvedTools,
|
|
@@ -4770,11 +5141,8 @@ function VectorToolbarComponent({
|
|
|
4770
5141
|
)
|
|
4771
5142
|
] });
|
|
4772
5143
|
}
|
|
4773
|
-
const { primary: primaryTools, overflow: overflowTools } = splitToolbarTools(
|
|
4774
|
-
resolvedTools,
|
|
4775
|
-
overflowToolIds
|
|
4776
|
-
);
|
|
4777
5144
|
const showOverflowMenu = overflowTools.length > 0;
|
|
5145
|
+
const showOverflowDropdown = remainingOverflowTools.length > 0;
|
|
4778
5146
|
const inlineCtx = {
|
|
4779
5147
|
selectedId: value,
|
|
4780
5148
|
selectTool: onChange,
|
|
@@ -4825,6 +5193,7 @@ function VectorToolbarComponent({
|
|
|
4825
5193
|
/* @__PURE__ */ jsx("span", { "aria-hidden": true, style: toolLockDividerStyle })
|
|
4826
5194
|
] }) : null,
|
|
4827
5195
|
primaryTools.map((tool) => renderInlineToolButton(tool, inlineCtx)),
|
|
5196
|
+
promotedTool ? renderInlineToolButton(promotedTool, inlineCtx) : null,
|
|
4828
5197
|
showOverflowMenu && orientation === "horizontal" ? /* @__PURE__ */ jsx(
|
|
4829
5198
|
"span",
|
|
4830
5199
|
{
|
|
@@ -4833,10 +5202,10 @@ function VectorToolbarComponent({
|
|
|
4833
5202
|
style: overflowSpacerStyle
|
|
4834
5203
|
}
|
|
4835
5204
|
) : null,
|
|
4836
|
-
|
|
5205
|
+
showOverflowDropdown ? /* @__PURE__ */ jsx(
|
|
4837
5206
|
ToolbarOverflowMenu,
|
|
4838
5207
|
{
|
|
4839
|
-
tools:
|
|
5208
|
+
tools: remainingOverflowTools,
|
|
4840
5209
|
selectedId: value,
|
|
4841
5210
|
onSelect: onChange,
|
|
4842
5211
|
density,
|
|
@@ -6487,6 +6856,7 @@ var VectorScene = class {
|
|
|
6487
6856
|
|
|
6488
6857
|
// src/react/VectorViewport.tsx
|
|
6489
6858
|
init_shape_builders();
|
|
6859
|
+
init_text_svg();
|
|
6490
6860
|
|
|
6491
6861
|
// src/react/blob-url-lifecycle.ts
|
|
6492
6862
|
var SVG_BLOB_HREF_PATTERN = /\b(?:href|xlink:href)=["'](blob:[^"']+)["']/g;
|
|
@@ -6692,6 +7062,9 @@ function InteractionOverlay({
|
|
|
6692
7062
|
);
|
|
6693
7063
|
} else if (placementPreview.kind === "rect" || placementPreview.kind === "ellipse" || placementPreview.kind === "architectural-cloud") {
|
|
6694
7064
|
const r = normalizeRect(placementPreview.rect);
|
|
7065
|
+
const shapeStroke = previewStrokeStyle?.stroke ?? "#1d1d1d";
|
|
7066
|
+
const shapeWidth = previewStrokeStyle?.strokeWidth ?? 2;
|
|
7067
|
+
const shapeOpacity = previewStrokeStyle?.strokeOpacity;
|
|
6695
7068
|
preview = placementPreview.kind === "rect" ? /* @__PURE__ */ jsx(
|
|
6696
7069
|
"rect",
|
|
6697
7070
|
{
|
|
@@ -6699,11 +7072,11 @@ function InteractionOverlay({
|
|
|
6699
7072
|
y: r.y,
|
|
6700
7073
|
width: r.width,
|
|
6701
7074
|
height: r.height,
|
|
7075
|
+
rx: 4,
|
|
6702
7076
|
fill: "none",
|
|
6703
|
-
stroke:
|
|
6704
|
-
strokeWidth:
|
|
6705
|
-
|
|
6706
|
-
vectorEffect: "non-scaling-stroke"
|
|
7077
|
+
stroke: shapeStroke,
|
|
7078
|
+
strokeWidth: shapeWidth,
|
|
7079
|
+
strokeOpacity: shapeOpacity
|
|
6707
7080
|
}
|
|
6708
7081
|
) : placementPreview.kind === "ellipse" ? /* @__PURE__ */ jsx(
|
|
6709
7082
|
"ellipse",
|
|
@@ -6713,29 +7086,30 @@ function InteractionOverlay({
|
|
|
6713
7086
|
rx: r.width / 2,
|
|
6714
7087
|
ry: r.height / 2,
|
|
6715
7088
|
fill: "none",
|
|
6716
|
-
stroke:
|
|
6717
|
-
strokeWidth:
|
|
6718
|
-
|
|
6719
|
-
vectorEffect: "non-scaling-stroke"
|
|
7089
|
+
stroke: shapeStroke,
|
|
7090
|
+
strokeWidth: shapeWidth,
|
|
7091
|
+
strokeOpacity: shapeOpacity
|
|
6720
7092
|
}
|
|
6721
7093
|
) : /* @__PURE__ */ jsx("g", { transform: `translate(${r.x}, ${r.y})`, children: /* @__PURE__ */ jsx(
|
|
6722
7094
|
"path",
|
|
6723
7095
|
{
|
|
6724
|
-
d: buildArchitecturalCloudPathD(r.width, r.height,
|
|
7096
|
+
d: buildArchitecturalCloudPathD(r.width, r.height, shapeWidth),
|
|
6725
7097
|
fill: "none",
|
|
6726
|
-
stroke:
|
|
6727
|
-
strokeWidth:
|
|
6728
|
-
|
|
7098
|
+
stroke: shapeStroke,
|
|
7099
|
+
strokeWidth: shapeWidth,
|
|
7100
|
+
strokeOpacity: shapeOpacity,
|
|
6729
7101
|
strokeLinecap: "round",
|
|
6730
|
-
strokeLinejoin: "round"
|
|
6731
|
-
vectorEffect: "non-scaling-stroke"
|
|
7102
|
+
strokeLinejoin: "round"
|
|
6732
7103
|
}
|
|
6733
7104
|
) });
|
|
6734
7105
|
} else if (placementPreview.kind === "line" || placementPreview.kind === "arrow") {
|
|
6735
7106
|
const { start, end } = placementPreview;
|
|
7107
|
+
const shapeStroke = previewStrokeStyle?.stroke ?? "#1d1d1d";
|
|
7108
|
+
const shapeWidth = previewStrokeStyle?.strokeWidth ?? 2;
|
|
7109
|
+
const shapeOpacity = previewStrokeStyle?.strokeOpacity;
|
|
6736
7110
|
const geometry = placementPreview.kind === "arrow" ? computeStraightArrowGeometry(
|
|
6737
7111
|
{ x1: start.x, y1: start.y, x2: end.x, y2: end.y },
|
|
6738
|
-
|
|
7112
|
+
shapeWidth
|
|
6739
7113
|
) : null;
|
|
6740
7114
|
preview = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
6741
7115
|
/* @__PURE__ */ jsx(
|
|
@@ -6745,11 +7119,10 @@ function InteractionOverlay({
|
|
|
6745
7119
|
y1: start.y,
|
|
6746
7120
|
x2: geometry?.shaftEndX ?? end.x,
|
|
6747
7121
|
y2: geometry?.shaftEndY ?? end.y,
|
|
6748
|
-
stroke:
|
|
6749
|
-
strokeWidth:
|
|
6750
|
-
|
|
6751
|
-
strokeLinecap: "round"
|
|
6752
|
-
vectorEffect: "non-scaling-stroke"
|
|
7122
|
+
stroke: shapeStroke,
|
|
7123
|
+
strokeWidth: shapeWidth,
|
|
7124
|
+
strokeOpacity: shapeOpacity,
|
|
7125
|
+
strokeLinecap: "round"
|
|
6753
7126
|
}
|
|
6754
7127
|
),
|
|
6755
7128
|
placementPreview.kind === "arrow" && geometry ? /* @__PURE__ */ jsx(
|
|
@@ -6757,10 +7130,9 @@ function InteractionOverlay({
|
|
|
6757
7130
|
{
|
|
6758
7131
|
d: `M ${geometry.headLeftX} ${geometry.headLeftY} L ${geometry.headTipX} ${geometry.headTipY} L ${geometry.headRightX} ${geometry.headRightY}`,
|
|
6759
7132
|
fill: "none",
|
|
6760
|
-
stroke:
|
|
6761
|
-
strokeWidth:
|
|
6762
|
-
strokeOpacity:
|
|
6763
|
-
strokeDasharray: dashPattern,
|
|
7133
|
+
stroke: shapeStroke,
|
|
7134
|
+
strokeWidth: shapeWidth,
|
|
7135
|
+
strokeOpacity: shapeOpacity,
|
|
6764
7136
|
strokeLinecap: "round",
|
|
6765
7137
|
strokeLinejoin: "round"
|
|
6766
7138
|
}
|
|
@@ -6774,7 +7146,8 @@ function InteractionOverlay({
|
|
|
6774
7146
|
const previewStyle = {
|
|
6775
7147
|
stroke: isLaser ? "#f43f5e" : previewStrokeStyle?.stroke ?? "#64748b",
|
|
6776
7148
|
strokeWidth: isLaser ? 4 : previewStrokeStyle?.strokeWidth ?? (tool === "marker" ? 16 : 3),
|
|
6777
|
-
...previewStrokeStyle?.strokeOpacity != null && !isLaser ? { strokeOpacity: previewStrokeStyle.strokeOpacity } : {}
|
|
7149
|
+
...previewStrokeStyle?.strokeOpacity != null && !isLaser ? { strokeOpacity: previewStrokeStyle.strokeOpacity } : {},
|
|
7150
|
+
...previewStrokeStyle?.strokeDash != null && !isLaser ? { strokeDash: previewStrokeStyle.strokeDash } : {}
|
|
6778
7151
|
};
|
|
6779
7152
|
const payload = computeFreehandSvgPayload(
|
|
6780
7153
|
raw,
|
|
@@ -6818,6 +7191,7 @@ function InteractionOverlay({
|
|
|
6818
7191
|
strokeOpacity: isLaser ? 0.85 : payload.strokeOpacity,
|
|
6819
7192
|
strokeLinecap: "round",
|
|
6820
7193
|
strokeLinejoin: "round",
|
|
7194
|
+
strokeDasharray: payload.strokeDasharray,
|
|
6821
7195
|
shapeRendering: "geometricPrecision"
|
|
6822
7196
|
}
|
|
6823
7197
|
);
|
|
@@ -7223,6 +7597,9 @@ function TextEditOverlay({
|
|
|
7223
7597
|
const fontSize = fsWorld * z;
|
|
7224
7598
|
const lineHeight = fsWorld * (22 / 18) * z;
|
|
7225
7599
|
const fixedBox = !!item.textFixedBounds;
|
|
7600
|
+
const padTop = EDIT_TOP_PAD_RATIO * fsWorld * z;
|
|
7601
|
+
const padX = 4 * z;
|
|
7602
|
+
const textColor = item.stroke ?? "#1d1d1d";
|
|
7226
7603
|
return /* @__PURE__ */ jsx(
|
|
7227
7604
|
"div",
|
|
7228
7605
|
{
|
|
@@ -7253,14 +7630,14 @@ function TextEditOverlay({
|
|
|
7253
7630
|
width: "100%",
|
|
7254
7631
|
height: "100%",
|
|
7255
7632
|
margin: 0,
|
|
7256
|
-
padding:
|
|
7633
|
+
padding: `${padTop}px ${padX}px 0px ${padX}px`,
|
|
7257
7634
|
border: "none",
|
|
7258
7635
|
borderRadius: 0,
|
|
7259
7636
|
resize: "none",
|
|
7260
|
-
fontFamily:
|
|
7637
|
+
fontFamily: TEXT_FONT_FAMILY,
|
|
7261
7638
|
fontSize,
|
|
7262
7639
|
lineHeight: `${lineHeight}px`,
|
|
7263
|
-
color:
|
|
7640
|
+
color: textColor,
|
|
7264
7641
|
background: "transparent",
|
|
7265
7642
|
backgroundColor: "transparent",
|
|
7266
7643
|
outline: "none",
|
|
@@ -7268,7 +7645,6 @@ function TextEditOverlay({
|
|
|
7268
7645
|
appearance: "none",
|
|
7269
7646
|
WebkitAppearance: "none",
|
|
7270
7647
|
WebkitTapHighlightColor: "transparent",
|
|
7271
|
-
/* Auto-sized text: no soft wrap / scrollbar; fixed box: wrap like the SVG. */
|
|
7272
7648
|
whiteSpace: fixedBox ? "pre-wrap" : "pre",
|
|
7273
7649
|
overflow: fixedBox ? "auto" : "hidden",
|
|
7274
7650
|
overflowX: fixedBox ? "hidden" : "hidden",
|
|
@@ -7958,14 +8334,32 @@ var VectorViewport = forwardRef(
|
|
|
7958
8334
|
imageStoreRef.current = new IndexedDbImageStore();
|
|
7959
8335
|
}
|
|
7960
8336
|
const rememberedImageBlobHrefsRef = useRef(/* @__PURE__ */ new Set());
|
|
7961
|
-
const strokeStyleRef = useRef({
|
|
8337
|
+
const strokeStyleRef = useRef({
|
|
8338
|
+
...DEFAULT_STROKE_STYLE,
|
|
8339
|
+
textFontSize: DEFAULT_TEXT_FONT_SIZE
|
|
8340
|
+
});
|
|
7962
8341
|
const [strokeStyleState, setStrokeStyleState] = useState({
|
|
7963
|
-
...DEFAULT_STROKE_STYLE
|
|
8342
|
+
...DEFAULT_STROKE_STYLE,
|
|
8343
|
+
textFontSize: DEFAULT_TEXT_FONT_SIZE
|
|
7964
8344
|
});
|
|
7965
8345
|
const setCurrentStrokeStyle = useCallback((next) => {
|
|
7966
8346
|
strokeStyleRef.current = next;
|
|
7967
8347
|
setStrokeStyleState(next);
|
|
7968
8348
|
}, []);
|
|
8349
|
+
const patchCurrentStrokeStyle = useCallback(
|
|
8350
|
+
(patch) => {
|
|
8351
|
+
const merged = { ...strokeStyleRef.current };
|
|
8352
|
+
for (const key of Object.keys(patch)) {
|
|
8353
|
+
const v = patch[key];
|
|
8354
|
+
if (v !== void 0) {
|
|
8355
|
+
merged[key] = v;
|
|
8356
|
+
}
|
|
8357
|
+
}
|
|
8358
|
+
strokeStyleRef.current = merged;
|
|
8359
|
+
setStrokeStyleState(merged);
|
|
8360
|
+
},
|
|
8361
|
+
[]
|
|
8362
|
+
);
|
|
7969
8363
|
const progressiveQueueRef = useRef(/* @__PURE__ */ new Set());
|
|
7970
8364
|
useEffect(() => {
|
|
7971
8365
|
const store = imageStoreRef.current;
|
|
@@ -8114,10 +8508,11 @@ var VectorViewport = forwardRef(
|
|
|
8114
8508
|
change(
|
|
8115
8509
|
exists ? replaceItem(itemsRef.current, id, item) : [...itemsRef.current, item]
|
|
8116
8510
|
);
|
|
8117
|
-
|
|
8511
|
+
patchCurrentStrokeStyle({
|
|
8118
8512
|
stroke: item.stroke ?? DEFAULT_STROKE_STYLE.stroke,
|
|
8119
8513
|
strokeWidth: item.strokeWidth ?? DEFAULT_STROKE_STYLE.strokeWidth,
|
|
8120
|
-
|
|
8514
|
+
strokeOpacity: item.strokeOpacity,
|
|
8515
|
+
strokeDash: item.strokeDash
|
|
8121
8516
|
});
|
|
8122
8517
|
}
|
|
8123
8518
|
if (!shouldKeepToolForContinuousPenInput(args.tool, args.pointerType)) {
|
|
@@ -8125,8 +8520,8 @@ var VectorViewport = forwardRef(
|
|
|
8125
8520
|
}
|
|
8126
8521
|
},
|
|
8127
8522
|
[
|
|
8523
|
+
patchCurrentStrokeStyle,
|
|
8128
8524
|
requestAutoResetTool,
|
|
8129
|
-
setCurrentStrokeStyle,
|
|
8130
8525
|
shouldKeepToolForContinuousPenInput
|
|
8131
8526
|
]
|
|
8132
8527
|
);
|
|
@@ -8862,24 +9257,28 @@ var VectorViewport = forwardRef(
|
|
|
8862
9257
|
renderFrame();
|
|
8863
9258
|
}, [renderFrame]);
|
|
8864
9259
|
useEffect(() => {
|
|
9260
|
+
const current = strokeStyleRef.current;
|
|
8865
9261
|
if (toolId === "marker") {
|
|
8866
9262
|
setCurrentStrokeStyle({
|
|
8867
|
-
...
|
|
9263
|
+
...current,
|
|
8868
9264
|
...MARKER_TOOL_STYLE
|
|
8869
9265
|
});
|
|
8870
9266
|
return;
|
|
8871
9267
|
}
|
|
8872
|
-
const current = strokeStyleRef.current;
|
|
8873
9268
|
if (isDefaultMarkerToolStyle(current)) {
|
|
8874
9269
|
setCurrentStrokeStyle({
|
|
8875
9270
|
stroke: DEFAULT_STROKE_STYLE.stroke,
|
|
8876
|
-
strokeWidth: toolId === "draw" ? 10 : DEFAULT_STROKE_STYLE.strokeWidth
|
|
9271
|
+
strokeWidth: toolId === "draw" ? 10 : DEFAULT_STROKE_STYLE.strokeWidth,
|
|
9272
|
+
strokeDash: current.strokeDash,
|
|
9273
|
+
textFontSize: current.textFontSize
|
|
8877
9274
|
});
|
|
8878
9275
|
return;
|
|
8879
9276
|
}
|
|
8880
9277
|
setCurrentStrokeStyle({
|
|
8881
9278
|
stroke: current.stroke,
|
|
8882
|
-
strokeWidth: toolId === "draw" ? 10 : current.strokeWidth
|
|
9279
|
+
strokeWidth: toolId === "draw" ? 10 : current.strokeWidth,
|
|
9280
|
+
strokeDash: current.strokeDash,
|
|
9281
|
+
textFontSize: current.textFontSize
|
|
8883
9282
|
});
|
|
8884
9283
|
}, [setCurrentStrokeStyle, toolId]);
|
|
8885
9284
|
useEffect(() => {
|
|
@@ -8888,15 +9287,14 @@ var VectorViewport = forwardRef(
|
|
|
8888
9287
|
const it = items.find((i) => i.id === primaryId);
|
|
8889
9288
|
if (!it || it.locked) return;
|
|
8890
9289
|
if (it.toolKind === "image") return;
|
|
8891
|
-
|
|
9290
|
+
patchCurrentStrokeStyle({
|
|
8892
9291
|
stroke: it.stroke ?? DEFAULT_STROKE_STYLE.stroke,
|
|
8893
|
-
strokeWidth: it.strokeWidth ?? DEFAULT_STROKE_STYLE.strokeWidth
|
|
8894
|
-
|
|
8895
|
-
|
|
8896
|
-
|
|
8897
|
-
}
|
|
8898
|
-
|
|
8899
|
-
}, [effectiveSelectedIds, items, setCurrentStrokeStyle]);
|
|
9292
|
+
strokeWidth: it.strokeWidth ?? DEFAULT_STROKE_STYLE.strokeWidth,
|
|
9293
|
+
strokeOpacity: it.strokeOpacity,
|
|
9294
|
+
strokeDash: it.strokeDash,
|
|
9295
|
+
...it.toolKind === "text" && it.textFontSize != null ? { textFontSize: it.textFontSize } : {}
|
|
9296
|
+
});
|
|
9297
|
+
}, [effectiveSelectedIds, items, patchCurrentStrokeStyle]);
|
|
8900
9298
|
const handleSelectionStyleChange = useCallback(
|
|
8901
9299
|
(patch) => {
|
|
8902
9300
|
const change = onItemsChangeRef.current;
|
|
@@ -8912,25 +9310,15 @@ var VectorViewport = forwardRef(
|
|
|
8912
9310
|
nextList = replaceItem(nextList, id, out);
|
|
8913
9311
|
}
|
|
8914
9312
|
change(nextList);
|
|
8915
|
-
|
|
8916
|
-
...strokeStyleRef.current,
|
|
8917
|
-
stroke: patch.stroke,
|
|
8918
|
-
strokeWidth: patch.strokeWidth,
|
|
8919
|
-
...patch.strokeOpacity != null ? { strokeOpacity: patch.strokeOpacity } : {}
|
|
8920
|
-
});
|
|
9313
|
+
patchCurrentStrokeStyle(patch);
|
|
8921
9314
|
},
|
|
8922
|
-
[
|
|
9315
|
+
[patchCurrentStrokeStyle]
|
|
8923
9316
|
);
|
|
8924
9317
|
const handleActiveToolStyleChange = useCallback(
|
|
8925
9318
|
(patch) => {
|
|
8926
|
-
|
|
8927
|
-
setCurrentStrokeStyle({
|
|
8928
|
-
stroke: patch.stroke,
|
|
8929
|
-
strokeWidth: patch.strokeWidth,
|
|
8930
|
-
...patch.strokeOpacity != null ? { strokeOpacity: patch.strokeOpacity } : current.strokeOpacity != null ? { strokeOpacity: current.strokeOpacity } : {}
|
|
8931
|
-
});
|
|
9319
|
+
patchCurrentStrokeStyle(patch);
|
|
8932
9320
|
},
|
|
8933
|
-
[
|
|
9321
|
+
[patchCurrentStrokeStyle]
|
|
8934
9322
|
);
|
|
8935
9323
|
const commitTextEdit = useCallback(() => {
|
|
8936
9324
|
const id = editingTextIdRef.current;
|
|
@@ -10063,16 +10451,21 @@ var VectorViewport = forwardRef(
|
|
|
10063
10451
|
const id = createShapeId();
|
|
10064
10452
|
const { x: worldX, y: worldY } = st.startWorld;
|
|
10065
10453
|
if (st.tool === "text") {
|
|
10454
|
+
const fs = strokeStyleRef.current.textFontSize;
|
|
10455
|
+
const baseline = textBaselineYFor(fs);
|
|
10456
|
+
const lh = textLineHeightFor(fs);
|
|
10457
|
+
const minH = Math.max(26, baseline + Math.max(4, lh * 0.2));
|
|
10066
10458
|
const newItem = createTextItem(
|
|
10067
10459
|
id,
|
|
10068
10460
|
{
|
|
10069
10461
|
x: worldX - 4,
|
|
10070
|
-
y: worldY -
|
|
10462
|
+
y: worldY - baseline,
|
|
10071
10463
|
width: 160,
|
|
10072
|
-
height:
|
|
10464
|
+
height: minH
|
|
10073
10465
|
},
|
|
10074
10466
|
"",
|
|
10075
|
-
strokeStyleRef.current
|
|
10467
|
+
strokeStyleRef.current,
|
|
10468
|
+
fs
|
|
10076
10469
|
);
|
|
10077
10470
|
editingTextSnapshotRef.current = {
|
|
10078
10471
|
...newItem,
|
|
@@ -10223,12 +10616,63 @@ var VectorViewport = forwardRef(
|
|
|
10223
10616
|
return effectiveSelectedIds.map((id) => resolvedItems.find((i) => i.id === id)).filter((i) => i != null);
|
|
10224
10617
|
}, [effectiveSelectedIds, resolvedItems]);
|
|
10225
10618
|
const activeToolInspectorStyle = useMemo(() => {
|
|
10226
|
-
if (toolId
|
|
10227
|
-
|
|
10228
|
-
|
|
10229
|
-
|
|
10230
|
-
|
|
10231
|
-
|
|
10619
|
+
if (toolId === "draw") {
|
|
10620
|
+
return {
|
|
10621
|
+
toolKind: "draw",
|
|
10622
|
+
label: "Caneta",
|
|
10623
|
+
...strokeStyleState
|
|
10624
|
+
};
|
|
10625
|
+
}
|
|
10626
|
+
if (toolId === "marker") {
|
|
10627
|
+
return {
|
|
10628
|
+
toolKind: "marker",
|
|
10629
|
+
label: "Marcador",
|
|
10630
|
+
...strokeStyleState
|
|
10631
|
+
};
|
|
10632
|
+
}
|
|
10633
|
+
if (toolId === "text") {
|
|
10634
|
+
return {
|
|
10635
|
+
toolKind: "text",
|
|
10636
|
+
label: "Texto",
|
|
10637
|
+
...strokeStyleState
|
|
10638
|
+
};
|
|
10639
|
+
}
|
|
10640
|
+
if (toolId === "rect") {
|
|
10641
|
+
return {
|
|
10642
|
+
toolKind: "rect",
|
|
10643
|
+
label: "Ret\xE2ngulo",
|
|
10644
|
+
...strokeStyleState
|
|
10645
|
+
};
|
|
10646
|
+
}
|
|
10647
|
+
if (toolId === "ellipse") {
|
|
10648
|
+
return {
|
|
10649
|
+
toolKind: "ellipse",
|
|
10650
|
+
label: "Elipse",
|
|
10651
|
+
...strokeStyleState
|
|
10652
|
+
};
|
|
10653
|
+
}
|
|
10654
|
+
if (toolId === "architectural-cloud") {
|
|
10655
|
+
return {
|
|
10656
|
+
toolKind: "architectural-cloud",
|
|
10657
|
+
label: "Nuvem",
|
|
10658
|
+
...strokeStyleState
|
|
10659
|
+
};
|
|
10660
|
+
}
|
|
10661
|
+
if (toolId === "line") {
|
|
10662
|
+
return {
|
|
10663
|
+
toolKind: "line",
|
|
10664
|
+
label: "Linha",
|
|
10665
|
+
...strokeStyleState
|
|
10666
|
+
};
|
|
10667
|
+
}
|
|
10668
|
+
if (toolId === "arrow") {
|
|
10669
|
+
return {
|
|
10670
|
+
toolKind: "arrow",
|
|
10671
|
+
label: "Seta",
|
|
10672
|
+
...strokeStyleState
|
|
10673
|
+
};
|
|
10674
|
+
}
|
|
10675
|
+
return void 0;
|
|
10232
10676
|
}, [strokeStyleState, toolId]);
|
|
10233
10677
|
const eraserPreviewItemsForOverlay = useMemo(() => {
|
|
10234
10678
|
return eraserPreviewIds.map((id) => resolvedItems.find((i) => i.id === id)).filter((i) => i != null);
|