canvu-react 0.4.13 → 0.4.15
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/native.cjs +830 -149
- package/dist/native.cjs.map +1 -1
- package/dist/native.d.cts +34 -13
- package/dist/native.d.ts +34 -13
- package/dist/native.js +829 -152
- package/dist/native.js.map +1 -1
- package/dist/react.cjs +64 -0
- package/dist/react.cjs.map +1 -1
- package/dist/react.js +64 -0
- package/dist/react.js.map +1 -1
- package/package.json +1 -1
package/dist/native.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import getStroke from 'perfect-freehand';
|
|
2
|
-
import { Group, RoundedRect, Circle, Line, vec, Path, matchFont, Text, Canvas, Rect, Oval, useImage, Image } from '@shopify/react-native-skia';
|
|
2
|
+
import { Group, RoundedRect, Circle, Line, vec, Path, matchFont, Text, Canvas, Rect, Oval, DashPathEffect, useImage, Image } from '@shopify/react-native-skia';
|
|
3
3
|
import { memo, forwardRef, useState, useRef, useEffect, useCallback, useMemo, useImperativeHandle } from 'react';
|
|
4
4
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
5
|
-
import { StyleSheet, PanResponder, View,
|
|
5
|
+
import { StyleSheet, PanResponder, View, Pressable, Text as Text$1, ScrollView } from 'react-native';
|
|
6
6
|
|
|
7
7
|
// src/scene/shape-builders.ts
|
|
8
8
|
|
|
@@ -1816,13 +1816,52 @@ function NativeShapeRenderer({ item }) {
|
|
|
1816
1816
|
}
|
|
1817
1817
|
return null;
|
|
1818
1818
|
}
|
|
1819
|
+
|
|
1820
|
+
// src/native/native-overlay-style.ts
|
|
1821
|
+
var ERASER_TINT = "#cbd5e1";
|
|
1822
|
+
var ERASER_TINT_OPACITY = 0.95;
|
|
1823
|
+
var LASER_TINT = "#f43f5e";
|
|
1824
|
+
var LASER_TINT_OPACITY = 0.9;
|
|
1825
|
+
var ERASER_TRAIL_MAX_AGE_MS = 150;
|
|
1826
|
+
var LASER_TRAIL_MAX_AGE_MS = 650;
|
|
1827
|
+
function colorWithOpacity(hex, alpha) {
|
|
1828
|
+
if (alpha == null || alpha >= 1) return hex;
|
|
1829
|
+
const r = parseInt(hex.slice(1, 3), 16);
|
|
1830
|
+
const g = parseInt(hex.slice(3, 5), 16);
|
|
1831
|
+
const b = parseInt(hex.slice(5, 7), 16);
|
|
1832
|
+
if (Number.isNaN(r) || Number.isNaN(g) || Number.isNaN(b)) return hex;
|
|
1833
|
+
return `rgba(${r},${g},${b},${alpha})`;
|
|
1834
|
+
}
|
|
1835
|
+
function freshTimedTrailPoints(points, now, maxAgeMs) {
|
|
1836
|
+
return points.filter((point) => now - point.t <= maxAgeMs);
|
|
1837
|
+
}
|
|
1838
|
+
function timedTrailHeadOpacity(point, now, maxAgeMs) {
|
|
1839
|
+
if (!point) return 0;
|
|
1840
|
+
return Math.max(0, 1 - (now - point.t) / maxAgeMs);
|
|
1841
|
+
}
|
|
1842
|
+
function resolveNativeStrokePreviewStyle(tool, previewStrokeStyle) {
|
|
1843
|
+
const isLaser = tool === "laser";
|
|
1844
|
+
return {
|
|
1845
|
+
stroke: isLaser ? LASER_TINT : previewStrokeStyle?.stroke ?? "#64748b",
|
|
1846
|
+
strokeWidth: isLaser ? 4 : previewStrokeStyle?.strokeWidth ?? (tool === "marker" ? 16 : 3),
|
|
1847
|
+
...previewStrokeStyle?.strokeOpacity != null && !isLaser ? { strokeOpacity: previewStrokeStyle.strokeOpacity } : {},
|
|
1848
|
+
...previewStrokeStyle?.strokeDash != null && !isLaser ? { strokeDash: previewStrokeStyle.strokeDash } : {}
|
|
1849
|
+
};
|
|
1850
|
+
}
|
|
1819
1851
|
var HANDLE_ORDER = ["nw", "n", "ne", "e", "se", "s", "sw", "w"];
|
|
1820
1852
|
var ERASER_PREVIEW_OPACITY = 0.3;
|
|
1853
|
+
var OVERLAY_STROKE_PX = 1.25;
|
|
1854
|
+
var MARQUEE_DASH_PX = 4;
|
|
1821
1855
|
function pointsToSmoothPathD(points) {
|
|
1822
1856
|
if (points.length < 2) return null;
|
|
1823
1857
|
const d = smoothFreehandPointsToPathD(points);
|
|
1824
1858
|
return d || null;
|
|
1825
1859
|
}
|
|
1860
|
+
function dashIntervalsFromStrokeDasharray(strokeDasharray) {
|
|
1861
|
+
if (!strokeDasharray) return null;
|
|
1862
|
+
const intervals = strokeDasharray.split(/\s+/).map((part) => Number(part)).filter((part) => Number.isFinite(part) && part > 0);
|
|
1863
|
+
return intervals.length > 0 ? intervals : null;
|
|
1864
|
+
}
|
|
1826
1865
|
function NativeInteractionOverlay({
|
|
1827
1866
|
camera,
|
|
1828
1867
|
width,
|
|
@@ -1832,13 +1871,18 @@ function NativeInteractionOverlay({
|
|
|
1832
1871
|
placementPreview,
|
|
1833
1872
|
eraserTrail,
|
|
1834
1873
|
laserTrail,
|
|
1835
|
-
eraserPreviewItems = []
|
|
1874
|
+
eraserPreviewItems = [],
|
|
1875
|
+
previewStrokeStyle
|
|
1836
1876
|
}) {
|
|
1837
1877
|
const z = camera.zoom;
|
|
1838
1878
|
const camTransform = skiaCameraTransform(z, camera.x, camera.y);
|
|
1839
1879
|
const handleR = 5 / z;
|
|
1840
|
-
const
|
|
1880
|
+
const overlayStrokeWorld = OVERLAY_STROKE_PX / z;
|
|
1881
|
+
const marqueeDashWorld = MARQUEE_DASH_PX / z;
|
|
1841
1882
|
const rotateOffsetWorld = 24 / z;
|
|
1883
|
+
const rotateIconWorld = 16 / z;
|
|
1884
|
+
const rotateIconScale = rotateIconWorld / 24;
|
|
1885
|
+
const rotateIconStroke = OVERLAY_STROKE_PX / (z * rotateIconScale);
|
|
1842
1886
|
const selectionElements = useMemo(() => {
|
|
1843
1887
|
if (selectedItems.length === 0) return null;
|
|
1844
1888
|
const single = selectedItems.length === 1 ? selectedItems[0] : void 0;
|
|
@@ -1860,7 +1904,7 @@ function NativeInteractionOverlay({
|
|
|
1860
1904
|
height: b.height,
|
|
1861
1905
|
color: "#3b82f6",
|
|
1862
1906
|
style: "stroke",
|
|
1863
|
-
strokeWidth:
|
|
1907
|
+
strokeWidth: overlayStrokeWorld,
|
|
1864
1908
|
antiAlias: true
|
|
1865
1909
|
}
|
|
1866
1910
|
) }, it.id);
|
|
@@ -1868,83 +1912,167 @@ function NativeInteractionOverlay({
|
|
|
1868
1912
|
showResizeHandles && bSingle && single && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1869
1913
|
HANDLE_ORDER.map((hid) => {
|
|
1870
1914
|
const p = getHandleWorldPositionRotated(bSingle, hid, rotSingle);
|
|
1871
|
-
return /* @__PURE__ */
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1915
|
+
return /* @__PURE__ */ jsxs(Group, { children: [
|
|
1916
|
+
/* @__PURE__ */ jsx(
|
|
1917
|
+
Circle,
|
|
1918
|
+
{
|
|
1919
|
+
cx: p.x,
|
|
1920
|
+
cy: p.y,
|
|
1921
|
+
r: handleR,
|
|
1922
|
+
color: "#ffffff",
|
|
1923
|
+
style: "fill",
|
|
1924
|
+
antiAlias: true
|
|
1925
|
+
}
|
|
1926
|
+
),
|
|
1927
|
+
/* @__PURE__ */ jsx(
|
|
1928
|
+
Circle,
|
|
1929
|
+
{
|
|
1930
|
+
cx: p.x,
|
|
1931
|
+
cy: p.y,
|
|
1932
|
+
r: handleR,
|
|
1933
|
+
color: "#3b82f6",
|
|
1934
|
+
style: "stroke",
|
|
1935
|
+
strokeWidth: overlayStrokeWorld,
|
|
1936
|
+
antiAlias: true
|
|
1937
|
+
}
|
|
1938
|
+
)
|
|
1939
|
+
] }, hid);
|
|
1883
1940
|
}),
|
|
1884
|
-
rotHandlePos && /* @__PURE__ */
|
|
1885
|
-
|
|
1941
|
+
rotHandlePos && /* @__PURE__ */ jsxs(
|
|
1942
|
+
Group,
|
|
1886
1943
|
{
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1944
|
+
transform: [
|
|
1945
|
+
{ translateX: rotHandlePos.x },
|
|
1946
|
+
{ translateY: rotHandlePos.y },
|
|
1947
|
+
{ rotate: rotSingle },
|
|
1948
|
+
{ translateX: -rotateIconWorld / 2 },
|
|
1949
|
+
{ translateY: -rotateIconWorld / 2 },
|
|
1950
|
+
{ scale: rotateIconScale }
|
|
1951
|
+
],
|
|
1952
|
+
children: [
|
|
1953
|
+
/* @__PURE__ */ jsx(
|
|
1954
|
+
Path,
|
|
1955
|
+
{
|
|
1956
|
+
path: "M21 12a9 9 0 1 1-9-9c2.52 0 4.93 1 6.74 2.74L21 8",
|
|
1957
|
+
color: "#3b82f6",
|
|
1958
|
+
style: "stroke",
|
|
1959
|
+
strokeWidth: rotateIconStroke,
|
|
1960
|
+
strokeCap: "round",
|
|
1961
|
+
strokeJoin: "round",
|
|
1962
|
+
antiAlias: true
|
|
1963
|
+
}
|
|
1964
|
+
),
|
|
1965
|
+
/* @__PURE__ */ jsx(
|
|
1966
|
+
Path,
|
|
1967
|
+
{
|
|
1968
|
+
path: "M21 3v5h-5",
|
|
1969
|
+
color: "#3b82f6",
|
|
1970
|
+
style: "stroke",
|
|
1971
|
+
strokeWidth: rotateIconStroke,
|
|
1972
|
+
strokeCap: "round",
|
|
1973
|
+
strokeJoin: "round",
|
|
1974
|
+
antiAlias: true
|
|
1975
|
+
}
|
|
1976
|
+
)
|
|
1977
|
+
]
|
|
1894
1978
|
}
|
|
1895
1979
|
)
|
|
1896
1980
|
] })
|
|
1897
1981
|
] });
|
|
1898
|
-
}, [
|
|
1982
|
+
}, [
|
|
1983
|
+
selectedItems,
|
|
1984
|
+
showResizeHandles,
|
|
1985
|
+
rotateOffsetWorld,
|
|
1986
|
+
handleR,
|
|
1987
|
+
overlayStrokeWorld,
|
|
1988
|
+
rotateIconWorld,
|
|
1989
|
+
rotateIconScale,
|
|
1990
|
+
rotateIconStroke
|
|
1991
|
+
]);
|
|
1899
1992
|
const previewElements = useMemo(() => {
|
|
1900
1993
|
if (!placementPreview) return null;
|
|
1901
1994
|
const p = placementPreview;
|
|
1995
|
+
const shapeStroke = previewStrokeStyle?.stroke ?? "#1d1d1d";
|
|
1996
|
+
const shapeWidth = previewStrokeStyle?.strokeWidth ?? 2;
|
|
1997
|
+
const shapeColor = colorWithOpacity(
|
|
1998
|
+
shapeStroke,
|
|
1999
|
+
previewStrokeStyle?.strokeOpacity
|
|
2000
|
+
);
|
|
1902
2001
|
if (p.kind === "rect" || p.kind === "ellipse" || p.kind === "architectural-cloud") {
|
|
1903
2002
|
const r = normalizeRect(p.rect);
|
|
1904
|
-
return p.kind === "rect"
|
|
1905
|
-
|
|
2003
|
+
return p.kind === "rect" ? /* @__PURE__ */ jsx(
|
|
2004
|
+
RoundedRect,
|
|
1906
2005
|
{
|
|
1907
2006
|
x: r.x,
|
|
1908
2007
|
y: r.y,
|
|
1909
2008
|
width: r.width,
|
|
1910
2009
|
height: r.height,
|
|
1911
|
-
|
|
2010
|
+
r: 4,
|
|
2011
|
+
color: shapeColor,
|
|
1912
2012
|
style: "stroke",
|
|
1913
|
-
strokeWidth:
|
|
2013
|
+
strokeWidth: shapeWidth,
|
|
1914
2014
|
antiAlias: true
|
|
1915
2015
|
}
|
|
1916
|
-
) : /* @__PURE__ */ jsx(
|
|
1917
|
-
|
|
1918
|
-
{
|
|
1919
|
-
cx: r.x + r.width / 2,
|
|
1920
|
-
cy: r.y + r.height / 2,
|
|
1921
|
-
r: Math.max(0, r.width / 2),
|
|
1922
|
-
color: "#64748b",
|
|
1923
|
-
style: "stroke",
|
|
1924
|
-
strokeWidth: overlayStrokePx,
|
|
1925
|
-
antiAlias: true
|
|
1926
|
-
}
|
|
1927
|
-
);
|
|
1928
|
-
}
|
|
1929
|
-
if (p.kind === "marquee") {
|
|
1930
|
-
const r = normalizeRect(p.rect);
|
|
1931
|
-
return /* @__PURE__ */ jsx(
|
|
1932
|
-
Rect,
|
|
2016
|
+
) : p.kind === "ellipse" ? /* @__PURE__ */ jsx(
|
|
2017
|
+
Oval,
|
|
1933
2018
|
{
|
|
1934
2019
|
x: r.x,
|
|
1935
2020
|
y: r.y,
|
|
1936
2021
|
width: r.width,
|
|
1937
2022
|
height: r.height,
|
|
1938
|
-
color:
|
|
1939
|
-
style: "
|
|
2023
|
+
color: shapeColor,
|
|
2024
|
+
style: "stroke",
|
|
2025
|
+
strokeWidth: shapeWidth,
|
|
1940
2026
|
antiAlias: true
|
|
1941
2027
|
}
|
|
1942
|
-
)
|
|
2028
|
+
) : /* @__PURE__ */ jsx(Group, { transform: [{ translateX: r.x }, { translateY: r.y }], children: /* @__PURE__ */ jsx(
|
|
2029
|
+
Path,
|
|
2030
|
+
{
|
|
2031
|
+
path: buildArchitecturalCloudPathD(r.width, r.height, shapeWidth),
|
|
2032
|
+
color: shapeColor,
|
|
2033
|
+
style: "stroke",
|
|
2034
|
+
strokeWidth: shapeWidth,
|
|
2035
|
+
strokeCap: "round",
|
|
2036
|
+
strokeJoin: "round",
|
|
2037
|
+
antiAlias: true
|
|
2038
|
+
}
|
|
2039
|
+
) });
|
|
2040
|
+
}
|
|
2041
|
+
if (p.kind === "marquee") {
|
|
2042
|
+
const r = normalizeRect(p.rect);
|
|
2043
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2044
|
+
/* @__PURE__ */ jsx(
|
|
2045
|
+
Rect,
|
|
2046
|
+
{
|
|
2047
|
+
x: r.x,
|
|
2048
|
+
y: r.y,
|
|
2049
|
+
width: r.width,
|
|
2050
|
+
height: r.height,
|
|
2051
|
+
color: "rgba(59, 130, 246, 0.12)",
|
|
2052
|
+
style: "fill",
|
|
2053
|
+
antiAlias: true
|
|
2054
|
+
}
|
|
2055
|
+
),
|
|
2056
|
+
/* @__PURE__ */ jsx(
|
|
2057
|
+
Rect,
|
|
2058
|
+
{
|
|
2059
|
+
x: r.x,
|
|
2060
|
+
y: r.y,
|
|
2061
|
+
width: r.width,
|
|
2062
|
+
height: r.height,
|
|
2063
|
+
color: "#3b82f6",
|
|
2064
|
+
style: "stroke",
|
|
2065
|
+
strokeWidth: overlayStrokeWorld,
|
|
2066
|
+
antiAlias: true,
|
|
2067
|
+
children: /* @__PURE__ */ jsx(DashPathEffect, { intervals: [marqueeDashWorld, marqueeDashWorld] })
|
|
2068
|
+
}
|
|
2069
|
+
)
|
|
2070
|
+
] });
|
|
1943
2071
|
}
|
|
1944
2072
|
if (p.kind === "line" || p.kind === "arrow") {
|
|
1945
2073
|
const geometry = p.kind === "arrow" ? computeStraightArrowGeometry(
|
|
1946
2074
|
{ x1: p.start.x, y1: p.start.y, x2: p.end.x, y2: p.end.y },
|
|
1947
|
-
|
|
2075
|
+
shapeWidth
|
|
1948
2076
|
) : null;
|
|
1949
2077
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1950
2078
|
/* @__PURE__ */ jsx(
|
|
@@ -1952,9 +2080,9 @@ function NativeInteractionOverlay({
|
|
|
1952
2080
|
{
|
|
1953
2081
|
p1: vec(p.start.x, p.start.y),
|
|
1954
2082
|
p2: vec(geometry?.shaftEndX ?? p.end.x, geometry?.shaftEndY ?? p.end.y),
|
|
1955
|
-
color:
|
|
2083
|
+
color: shapeColor,
|
|
1956
2084
|
style: "stroke",
|
|
1957
|
-
strokeWidth:
|
|
2085
|
+
strokeWidth: shapeWidth,
|
|
1958
2086
|
strokeCap: "round",
|
|
1959
2087
|
antiAlias: true
|
|
1960
2088
|
}
|
|
@@ -1963,9 +2091,9 @@ function NativeInteractionOverlay({
|
|
|
1963
2091
|
Path,
|
|
1964
2092
|
{
|
|
1965
2093
|
path: `M ${geometry.headLeftX} ${geometry.headLeftY} L ${geometry.headTipX} ${geometry.headTipY} L ${geometry.headRightX} ${geometry.headRightY}`,
|
|
1966
|
-
color:
|
|
2094
|
+
color: shapeColor,
|
|
1967
2095
|
style: "stroke",
|
|
1968
|
-
strokeWidth:
|
|
2096
|
+
strokeWidth: shapeWidth,
|
|
1969
2097
|
strokeCap: "round",
|
|
1970
2098
|
strokeJoin: "round",
|
|
1971
2099
|
antiAlias: true
|
|
@@ -1974,10 +2102,15 @@ function NativeInteractionOverlay({
|
|
|
1974
2102
|
] });
|
|
1975
2103
|
}
|
|
1976
2104
|
if (p.kind === "stroke" && p.points.length >= 1) {
|
|
2105
|
+
const isLaser = p.tool === "laser";
|
|
2106
|
+
const style = resolveNativeStrokePreviewStyle(
|
|
2107
|
+
p.tool,
|
|
2108
|
+
p.style ?? previewStrokeStyle
|
|
2109
|
+
);
|
|
1977
2110
|
const payload = computeFreehandSvgPayload(
|
|
1978
2111
|
p.points,
|
|
1979
|
-
|
|
1980
|
-
"draw",
|
|
2112
|
+
style,
|
|
2113
|
+
isLaser ? "draw" : p.tool,
|
|
1981
2114
|
p.points.length === 2
|
|
1982
2115
|
);
|
|
1983
2116
|
if (!payload) return null;
|
|
@@ -1988,33 +2121,47 @@ function NativeInteractionOverlay({
|
|
|
1988
2121
|
cx: payload.cx,
|
|
1989
2122
|
cy: payload.cy,
|
|
1990
2123
|
r: payload.r,
|
|
1991
|
-
color: payload.fill,
|
|
2124
|
+
color: colorWithOpacity(payload.fill, payload.fillOpacity),
|
|
1992
2125
|
style: "fill",
|
|
1993
2126
|
antiAlias: true
|
|
1994
2127
|
}
|
|
1995
2128
|
);
|
|
1996
2129
|
}
|
|
1997
2130
|
if (payload.kind === "fillPath") {
|
|
1998
|
-
return /* @__PURE__ */ jsx(
|
|
2131
|
+
return /* @__PURE__ */ jsx(
|
|
2132
|
+
Path,
|
|
2133
|
+
{
|
|
2134
|
+
path: payload.d,
|
|
2135
|
+
color: colorWithOpacity(payload.fill, payload.fillOpacity),
|
|
2136
|
+
style: "fill",
|
|
2137
|
+
fillType: "winding",
|
|
2138
|
+
antiAlias: true
|
|
2139
|
+
}
|
|
2140
|
+
);
|
|
1999
2141
|
}
|
|
2000
2142
|
if (payload.kind === "strokePath") {
|
|
2143
|
+
const intervals = dashIntervalsFromStrokeDasharray(payload.strokeDasharray);
|
|
2001
2144
|
return /* @__PURE__ */ jsx(
|
|
2002
2145
|
Path,
|
|
2003
2146
|
{
|
|
2004
2147
|
path: payload.d,
|
|
2005
|
-
color:
|
|
2148
|
+
color: colorWithOpacity(
|
|
2149
|
+
payload.stroke,
|
|
2150
|
+
isLaser ? 0.85 : payload.strokeOpacity
|
|
2151
|
+
),
|
|
2006
2152
|
style: "stroke",
|
|
2007
|
-
strokeWidth:
|
|
2153
|
+
strokeWidth: payload.strokeWidth,
|
|
2008
2154
|
strokeCap: "round",
|
|
2009
2155
|
strokeJoin: "round",
|
|
2010
|
-
antiAlias: true
|
|
2156
|
+
antiAlias: true,
|
|
2157
|
+
children: intervals ? /* @__PURE__ */ jsx(DashPathEffect, { intervals }) : null
|
|
2011
2158
|
}
|
|
2012
2159
|
);
|
|
2013
2160
|
}
|
|
2014
2161
|
return null;
|
|
2015
2162
|
}
|
|
2016
2163
|
return null;
|
|
2017
|
-
}, [placementPreview]);
|
|
2164
|
+
}, [placementPreview, previewStrokeStyle, overlayStrokeWorld, marqueeDashWorld]);
|
|
2018
2165
|
const eraserPreviewElements = useMemo(() => {
|
|
2019
2166
|
if (eraserPreviewItems.length === 0) return null;
|
|
2020
2167
|
return /* @__PURE__ */ jsx(Fragment, { children: eraserPreviewItems.map((it) => {
|
|
@@ -2035,59 +2182,71 @@ function NativeInteractionOverlay({
|
|
|
2035
2182
|
}, [eraserPreviewItems]);
|
|
2036
2183
|
const eraserTrailElements = useMemo(() => {
|
|
2037
2184
|
if (!eraserTrail || eraserTrail.length < 1) return null;
|
|
2038
|
-
const
|
|
2039
|
-
|
|
2040
|
-
|
|
2185
|
+
const now = Date.now();
|
|
2186
|
+
const alive = freshTimedTrailPoints(eraserTrail, now, ERASER_TRAIL_MAX_AGE_MS);
|
|
2187
|
+
if (alive.length === 0) return null;
|
|
2188
|
+
const d = pointsToSmoothPathD(alive);
|
|
2189
|
+
const newest = alive[alive.length - 1];
|
|
2190
|
+
const headOpacity = timedTrailHeadOpacity(newest, now, ERASER_TRAIL_MAX_AGE_MS);
|
|
2191
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2192
|
+
alive.length >= 2 && d ? /* @__PURE__ */ jsx(
|
|
2193
|
+
Path,
|
|
2194
|
+
{
|
|
2195
|
+
path: d,
|
|
2196
|
+
color: colorWithOpacity(ERASER_TINT, ERASER_TINT_OPACITY),
|
|
2197
|
+
style: "stroke",
|
|
2198
|
+
strokeWidth: Math.max(3.5, OVERLAY_STROKE_PX) / z,
|
|
2199
|
+
strokeCap: "round",
|
|
2200
|
+
strokeJoin: "round",
|
|
2201
|
+
antiAlias: true
|
|
2202
|
+
}
|
|
2203
|
+
) : null,
|
|
2204
|
+
/* @__PURE__ */ jsx(
|
|
2041
2205
|
Circle,
|
|
2042
2206
|
{
|
|
2043
|
-
cx:
|
|
2044
|
-
cy:
|
|
2207
|
+
cx: newest?.x ?? alive[0]?.x ?? 0,
|
|
2208
|
+
cy: newest?.y ?? alive[0]?.y ?? 0,
|
|
2045
2209
|
r: Math.max(5 / z, 3),
|
|
2046
|
-
color:
|
|
2210
|
+
color: colorWithOpacity(ERASER_TINT, headOpacity),
|
|
2047
2211
|
style: "fill",
|
|
2048
2212
|
antiAlias: true
|
|
2049
2213
|
}
|
|
2050
|
-
)
|
|
2051
|
-
|
|
2052
|
-
Path,
|
|
2053
|
-
{
|
|
2054
|
-
path: d,
|
|
2055
|
-
color: "#cbd5e1",
|
|
2056
|
-
style: "stroke",
|
|
2057
|
-
strokeWidth: Math.max(3.5 / z, overlayStrokePx),
|
|
2058
|
-
strokeCap: "round",
|
|
2059
|
-
strokeJoin: "round",
|
|
2060
|
-
antiAlias: true
|
|
2061
|
-
}
|
|
2062
|
-
);
|
|
2214
|
+
)
|
|
2215
|
+
] });
|
|
2063
2216
|
}, [eraserTrail, z]);
|
|
2064
2217
|
const laserTrailElements = useMemo(() => {
|
|
2065
2218
|
if (!laserTrail || laserTrail.length < 1) return null;
|
|
2066
|
-
const
|
|
2067
|
-
|
|
2068
|
-
|
|
2219
|
+
const now = Date.now();
|
|
2220
|
+
const alive = freshTimedTrailPoints(laserTrail, now, LASER_TRAIL_MAX_AGE_MS);
|
|
2221
|
+
if (alive.length === 0) return null;
|
|
2222
|
+
const d = pointsToSmoothPathD(alive);
|
|
2223
|
+
const newest = alive[alive.length - 1];
|
|
2224
|
+
const headOpacity = timedTrailHeadOpacity(newest, now, LASER_TRAIL_MAX_AGE_MS);
|
|
2225
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2226
|
+
alive.length >= 2 && d ? /* @__PURE__ */ jsx(
|
|
2227
|
+
Path,
|
|
2228
|
+
{
|
|
2229
|
+
path: d,
|
|
2230
|
+
color: colorWithOpacity(LASER_TINT, LASER_TINT_OPACITY),
|
|
2231
|
+
style: "stroke",
|
|
2232
|
+
strokeWidth: Math.max(4, OVERLAY_STROKE_PX) / z,
|
|
2233
|
+
strokeCap: "round",
|
|
2234
|
+
strokeJoin: "round",
|
|
2235
|
+
antiAlias: true
|
|
2236
|
+
}
|
|
2237
|
+
) : null,
|
|
2238
|
+
/* @__PURE__ */ jsx(
|
|
2069
2239
|
Circle,
|
|
2070
2240
|
{
|
|
2071
|
-
cx:
|
|
2072
|
-
cy:
|
|
2241
|
+
cx: newest?.x ?? alive[0]?.x ?? 0,
|
|
2242
|
+
cy: newest?.y ?? alive[0]?.y ?? 0,
|
|
2073
2243
|
r: Math.max(5 / z, 3),
|
|
2074
|
-
color:
|
|
2244
|
+
color: colorWithOpacity(LASER_TINT, headOpacity),
|
|
2075
2245
|
style: "fill",
|
|
2076
2246
|
antiAlias: true
|
|
2077
2247
|
}
|
|
2078
|
-
)
|
|
2079
|
-
|
|
2080
|
-
Path,
|
|
2081
|
-
{
|
|
2082
|
-
path: d,
|
|
2083
|
-
color: "#f43f5e",
|
|
2084
|
-
style: "stroke",
|
|
2085
|
-
strokeWidth: Math.max(4 / z, overlayStrokePx),
|
|
2086
|
-
strokeCap: "round",
|
|
2087
|
-
strokeJoin: "round",
|
|
2088
|
-
antiAlias: true
|
|
2089
|
-
}
|
|
2090
|
-
);
|
|
2248
|
+
)
|
|
2249
|
+
] });
|
|
2091
2250
|
}, [laserTrail, z]);
|
|
2092
2251
|
if (width <= 0 || height <= 0) return null;
|
|
2093
2252
|
return /* @__PURE__ */ jsx(
|
|
@@ -2233,6 +2392,383 @@ function NativeSceneRenderer({
|
|
|
2233
2392
|
if (width <= 0 || height <= 0) return null;
|
|
2234
2393
|
return /* @__PURE__ */ jsx(Canvas, { style: { width, height }, children: /* @__PURE__ */ jsx(Group, { transform: cameraTransform, children: visible.map((item) => /* @__PURE__ */ jsx(MemoShape, { item }, item.id)) }) });
|
|
2235
2394
|
}
|
|
2395
|
+
|
|
2396
|
+
// src/native/native-style-inspector-values.ts
|
|
2397
|
+
var NATIVE_STYLE_PALETTE = [
|
|
2398
|
+
{ name: "black", hex: "#1d1d1d" },
|
|
2399
|
+
{ name: "grey", hex: "#9fa8b2" },
|
|
2400
|
+
{ name: "light-violet", hex: "#e085f4" },
|
|
2401
|
+
{ name: "violet", hex: "#ae3ec9" },
|
|
2402
|
+
{ name: "blue", hex: "#4263eb" },
|
|
2403
|
+
{ name: "light-blue", hex: "#4dabf7" },
|
|
2404
|
+
{ name: "yellow", hex: "#ffc078" },
|
|
2405
|
+
{ name: "orange", hex: "#f76707" },
|
|
2406
|
+
{ name: "green", hex: "#099268" },
|
|
2407
|
+
{ name: "light-green", hex: "#40c057" },
|
|
2408
|
+
{ name: "light-red", hex: "#ff8787" },
|
|
2409
|
+
{ name: "red", hex: "#e03131" }
|
|
2410
|
+
];
|
|
2411
|
+
function normalizeNativeStyleHex(stroke) {
|
|
2412
|
+
if (stroke && /^#[0-9A-Fa-f]{6}$/.test(stroke)) return stroke;
|
|
2413
|
+
return "#1d1d1d";
|
|
2414
|
+
}
|
|
2415
|
+
function nativeStyleColorWithOpacity(hex, opacity) {
|
|
2416
|
+
const alpha = opacity ?? 1;
|
|
2417
|
+
if (alpha >= 1) return hex;
|
|
2418
|
+
const r = Number.parseInt(hex.slice(1, 3), 16);
|
|
2419
|
+
const g = Number.parseInt(hex.slice(3, 5), 16);
|
|
2420
|
+
const b = Number.parseInt(hex.slice(5, 7), 16);
|
|
2421
|
+
return `rgba(${r},${g},${b},${alpha})`;
|
|
2422
|
+
}
|
|
2423
|
+
function hexesEqual(a, b) {
|
|
2424
|
+
return a.toLowerCase() === b.toLowerCase();
|
|
2425
|
+
}
|
|
2426
|
+
function DashPreview({
|
|
2427
|
+
color,
|
|
2428
|
+
width,
|
|
2429
|
+
dashed = false
|
|
2430
|
+
}) {
|
|
2431
|
+
const strokeHeight = Math.max(3, Math.min(6, width));
|
|
2432
|
+
return /* @__PURE__ */ jsxs(View, { style: styles.dashPreviewTrack, children: [
|
|
2433
|
+
/* @__PURE__ */ jsx(
|
|
2434
|
+
View,
|
|
2435
|
+
{
|
|
2436
|
+
style: [
|
|
2437
|
+
styles.dashPreviewStroke,
|
|
2438
|
+
{
|
|
2439
|
+
width: dashed ? 11 : 26,
|
|
2440
|
+
height: strokeHeight,
|
|
2441
|
+
borderRadius: strokeHeight / 2,
|
|
2442
|
+
backgroundColor: color
|
|
2443
|
+
}
|
|
2444
|
+
]
|
|
2445
|
+
}
|
|
2446
|
+
),
|
|
2447
|
+
dashed ? /* @__PURE__ */ jsx(
|
|
2448
|
+
View,
|
|
2449
|
+
{
|
|
2450
|
+
style: [
|
|
2451
|
+
styles.dashPreviewStroke,
|
|
2452
|
+
{
|
|
2453
|
+
width: 11,
|
|
2454
|
+
height: strokeHeight,
|
|
2455
|
+
borderRadius: strokeHeight / 2,
|
|
2456
|
+
backgroundColor: color
|
|
2457
|
+
}
|
|
2458
|
+
]
|
|
2459
|
+
}
|
|
2460
|
+
) : null
|
|
2461
|
+
] });
|
|
2462
|
+
}
|
|
2463
|
+
function clampValue(value, min, max) {
|
|
2464
|
+
return Math.min(max, Math.max(min, value));
|
|
2465
|
+
}
|
|
2466
|
+
function RangeControl({
|
|
2467
|
+
value,
|
|
2468
|
+
min,
|
|
2469
|
+
max,
|
|
2470
|
+
onChange,
|
|
2471
|
+
valueLabel
|
|
2472
|
+
}) {
|
|
2473
|
+
const [trackWidth, setTrackWidth] = useState(1);
|
|
2474
|
+
const normalized = (clampValue(value, min, max) - min) / (max - min);
|
|
2475
|
+
const updateFromX = useCallback(
|
|
2476
|
+
(x) => {
|
|
2477
|
+
const next = min + clampValue(x / trackWidth, 0, 1) * (max - min);
|
|
2478
|
+
onChange(Math.round(next));
|
|
2479
|
+
},
|
|
2480
|
+
[max, min, onChange, trackWidth]
|
|
2481
|
+
);
|
|
2482
|
+
const panResponder = useMemo(
|
|
2483
|
+
() => PanResponder.create({
|
|
2484
|
+
onMoveShouldSetPanResponder: () => true,
|
|
2485
|
+
onStartShouldSetPanResponder: () => true,
|
|
2486
|
+
onPanResponderGrant: (event) => {
|
|
2487
|
+
updateFromX(event.nativeEvent.locationX);
|
|
2488
|
+
},
|
|
2489
|
+
onPanResponderMove: (event) => {
|
|
2490
|
+
updateFromX(event.nativeEvent.locationX);
|
|
2491
|
+
}
|
|
2492
|
+
}),
|
|
2493
|
+
[updateFromX]
|
|
2494
|
+
);
|
|
2495
|
+
return /* @__PURE__ */ jsxs(View, { style: styles.rangeRow, children: [
|
|
2496
|
+
/* @__PURE__ */ jsxs(
|
|
2497
|
+
View,
|
|
2498
|
+
{
|
|
2499
|
+
style: styles.rangeTrack,
|
|
2500
|
+
onLayout: (event) => setTrackWidth(event.nativeEvent.layout.width),
|
|
2501
|
+
...panResponder.panHandlers,
|
|
2502
|
+
children: [
|
|
2503
|
+
/* @__PURE__ */ jsx(View, { style: styles.rangeBase }),
|
|
2504
|
+
/* @__PURE__ */ jsx(View, { style: [styles.rangeFill, { width: `${normalized * 100}%` }] }),
|
|
2505
|
+
/* @__PURE__ */ jsx(View, { style: [styles.rangeThumb, { left: `${normalized * 100}%` }] })
|
|
2506
|
+
]
|
|
2507
|
+
}
|
|
2508
|
+
),
|
|
2509
|
+
valueLabel ? /* @__PURE__ */ jsx(Text$1, { style: styles.rangeValue, children: valueLabel }) : null
|
|
2510
|
+
] });
|
|
2511
|
+
}
|
|
2512
|
+
function InspectorSection({
|
|
2513
|
+
label,
|
|
2514
|
+
children
|
|
2515
|
+
}) {
|
|
2516
|
+
return /* @__PURE__ */ jsxs(View, { style: styles.section, children: [
|
|
2517
|
+
/* @__PURE__ */ jsx(Text$1, { style: styles.sectionLabel, children: label }),
|
|
2518
|
+
children
|
|
2519
|
+
] });
|
|
2520
|
+
}
|
|
2521
|
+
function SegmentControl({
|
|
2522
|
+
segments,
|
|
2523
|
+
value,
|
|
2524
|
+
onChange
|
|
2525
|
+
}) {
|
|
2526
|
+
return /* @__PURE__ */ jsx(View, { style: styles.segmentGroup, children: segments.map((segment) => {
|
|
2527
|
+
const selected = segment.value === value;
|
|
2528
|
+
return /* @__PURE__ */ jsxs(
|
|
2529
|
+
Pressable,
|
|
2530
|
+
{
|
|
2531
|
+
accessibilityRole: "button",
|
|
2532
|
+
accessibilityState: { selected },
|
|
2533
|
+
accessibilityLabel: segment.label,
|
|
2534
|
+
onPress: () => onChange(segment.value),
|
|
2535
|
+
style: [styles.segment, selected ? styles.segmentSelected : null],
|
|
2536
|
+
children: [
|
|
2537
|
+
segment.preview,
|
|
2538
|
+
/* @__PURE__ */ jsx(
|
|
2539
|
+
Text$1,
|
|
2540
|
+
{
|
|
2541
|
+
style: [
|
|
2542
|
+
styles.segmentLabel,
|
|
2543
|
+
selected ? styles.segmentLabelSelected : null
|
|
2544
|
+
],
|
|
2545
|
+
children: segment.label
|
|
2546
|
+
}
|
|
2547
|
+
)
|
|
2548
|
+
]
|
|
2549
|
+
},
|
|
2550
|
+
String(segment.value)
|
|
2551
|
+
);
|
|
2552
|
+
}) });
|
|
2553
|
+
}
|
|
2554
|
+
function NativeVectorStyleInspector({
|
|
2555
|
+
toolId,
|
|
2556
|
+
value,
|
|
2557
|
+
onChange,
|
|
2558
|
+
style
|
|
2559
|
+
}) {
|
|
2560
|
+
const hex = normalizeNativeStyleHex(value.stroke);
|
|
2561
|
+
const opacity = toolId === "marker" ? value.strokeOpacity ?? 0.5 : void 0;
|
|
2562
|
+
const dashSegments = [
|
|
2563
|
+
{
|
|
2564
|
+
value: "solid",
|
|
2565
|
+
label: "Cont\xEDnuo",
|
|
2566
|
+
preview: /* @__PURE__ */ jsx(DashPreview, { color: "#18181b", width: 4 })
|
|
2567
|
+
},
|
|
2568
|
+
{
|
|
2569
|
+
value: "dashed",
|
|
2570
|
+
label: "Tracejado",
|
|
2571
|
+
preview: /* @__PURE__ */ jsx(DashPreview, { color: "#18181b", width: 4, dashed: true })
|
|
2572
|
+
}
|
|
2573
|
+
];
|
|
2574
|
+
const opacityPercent = Math.round((opacity ?? 1) * 100);
|
|
2575
|
+
return /* @__PURE__ */ jsxs(
|
|
2576
|
+
View,
|
|
2577
|
+
{
|
|
2578
|
+
pointerEvents: "auto",
|
|
2579
|
+
style: [styles.shell, style],
|
|
2580
|
+
accessibilityRole: "summary",
|
|
2581
|
+
accessibilityLabel: toolId === "marker" ? "Configura\xE7\xF5es do marcador" : "Configura\xE7\xF5es da caneta",
|
|
2582
|
+
children: [
|
|
2583
|
+
/* @__PURE__ */ jsx(InspectorSection, { label: "Cor", children: /* @__PURE__ */ jsx(View, { style: styles.palette, children: NATIVE_STYLE_PALETTE.map((color) => {
|
|
2584
|
+
const selected = hexesEqual(color.hex, hex);
|
|
2585
|
+
return /* @__PURE__ */ jsx(
|
|
2586
|
+
Pressable,
|
|
2587
|
+
{
|
|
2588
|
+
accessibilityRole: "button",
|
|
2589
|
+
accessibilityState: { selected },
|
|
2590
|
+
accessibilityLabel: color.name,
|
|
2591
|
+
onPress: () => onChange({ stroke: color.hex }),
|
|
2592
|
+
style: [
|
|
2593
|
+
styles.swatch,
|
|
2594
|
+
{
|
|
2595
|
+
backgroundColor: color.hex,
|
|
2596
|
+
borderWidth: selected ? 2 : 1,
|
|
2597
|
+
transform: [{ scale: selected ? 1.08 : 1 }],
|
|
2598
|
+
shadowOpacity: selected ? 0.08 : 0
|
|
2599
|
+
}
|
|
2600
|
+
]
|
|
2601
|
+
},
|
|
2602
|
+
color.name
|
|
2603
|
+
);
|
|
2604
|
+
}) }) }),
|
|
2605
|
+
/* @__PURE__ */ jsx(InspectorSection, { label: "Grossura", children: /* @__PURE__ */ jsx(
|
|
2606
|
+
RangeControl,
|
|
2607
|
+
{
|
|
2608
|
+
value: value.strokeWidth,
|
|
2609
|
+
min: 1,
|
|
2610
|
+
max: 48,
|
|
2611
|
+
onChange: (strokeWidth) => onChange({ strokeWidth })
|
|
2612
|
+
}
|
|
2613
|
+
) }),
|
|
2614
|
+
toolId === "draw" ? /* @__PURE__ */ jsx(InspectorSection, { label: "Tra\xE7o", children: /* @__PURE__ */ jsx(
|
|
2615
|
+
SegmentControl,
|
|
2616
|
+
{
|
|
2617
|
+
segments: dashSegments,
|
|
2618
|
+
value: value.strokeDash === "dashed" ? "dashed" : "solid",
|
|
2619
|
+
onChange: (strokeDash) => onChange({ strokeDash })
|
|
2620
|
+
}
|
|
2621
|
+
) }) : /* @__PURE__ */ jsx(InspectorSection, { label: "Opacidade", children: /* @__PURE__ */ jsx(
|
|
2622
|
+
RangeControl,
|
|
2623
|
+
{
|
|
2624
|
+
value: opacityPercent,
|
|
2625
|
+
min: 10,
|
|
2626
|
+
max: 100,
|
|
2627
|
+
valueLabel: `${opacityPercent}%`,
|
|
2628
|
+
onChange: (nextOpacity) => onChange({ strokeOpacity: nextOpacity / 100 })
|
|
2629
|
+
}
|
|
2630
|
+
) })
|
|
2631
|
+
]
|
|
2632
|
+
}
|
|
2633
|
+
);
|
|
2634
|
+
}
|
|
2635
|
+
var styles = StyleSheet.create({
|
|
2636
|
+
shell: {
|
|
2637
|
+
minWidth: 240,
|
|
2638
|
+
paddingHorizontal: 14,
|
|
2639
|
+
paddingVertical: 12,
|
|
2640
|
+
borderRadius: 10,
|
|
2641
|
+
borderWidth: 1,
|
|
2642
|
+
borderColor: "rgba(0,0,0,0.1)",
|
|
2643
|
+
backgroundColor: "rgba(255,255,255,0.97)",
|
|
2644
|
+
shadowColor: "#000000",
|
|
2645
|
+
shadowOpacity: 0.06,
|
|
2646
|
+
shadowRadius: 16,
|
|
2647
|
+
shadowOffset: { width: 0, height: 4 },
|
|
2648
|
+
gap: 10
|
|
2649
|
+
},
|
|
2650
|
+
section: {
|
|
2651
|
+
gap: 6
|
|
2652
|
+
},
|
|
2653
|
+
sectionLabel: {
|
|
2654
|
+
fontSize: 11,
|
|
2655
|
+
fontWeight: "600",
|
|
2656
|
+
color: "#52525b",
|
|
2657
|
+
textTransform: "uppercase",
|
|
2658
|
+
letterSpacing: 0.22
|
|
2659
|
+
},
|
|
2660
|
+
palette: {
|
|
2661
|
+
flexDirection: "row",
|
|
2662
|
+
flexWrap: "wrap",
|
|
2663
|
+
columnGap: 6,
|
|
2664
|
+
rowGap: 6,
|
|
2665
|
+
maxWidth: 174
|
|
2666
|
+
},
|
|
2667
|
+
swatch: {
|
|
2668
|
+
width: 24,
|
|
2669
|
+
height: 24,
|
|
2670
|
+
borderRadius: 12,
|
|
2671
|
+
borderColor: "rgba(0,0,0,0.12)",
|
|
2672
|
+
shadowColor: "#000000",
|
|
2673
|
+
shadowRadius: 2,
|
|
2674
|
+
shadowOffset: { width: 0, height: 1 }
|
|
2675
|
+
},
|
|
2676
|
+
rangeRow: {
|
|
2677
|
+
minHeight: 28,
|
|
2678
|
+
flexDirection: "row",
|
|
2679
|
+
alignItems: "center",
|
|
2680
|
+
gap: 8
|
|
2681
|
+
},
|
|
2682
|
+
rangeTrack: {
|
|
2683
|
+
position: "relative",
|
|
2684
|
+
flex: 1,
|
|
2685
|
+
height: 28,
|
|
2686
|
+
justifyContent: "center"
|
|
2687
|
+
},
|
|
2688
|
+
rangeBase: {
|
|
2689
|
+
position: "absolute",
|
|
2690
|
+
left: 0,
|
|
2691
|
+
right: 0,
|
|
2692
|
+
height: 3,
|
|
2693
|
+
borderRadius: 2,
|
|
2694
|
+
backgroundColor: "rgba(24,24,27,0.12)"
|
|
2695
|
+
},
|
|
2696
|
+
rangeFill: {
|
|
2697
|
+
position: "absolute",
|
|
2698
|
+
left: 0,
|
|
2699
|
+
height: 3,
|
|
2700
|
+
borderRadius: 2,
|
|
2701
|
+
backgroundColor: "#18181b"
|
|
2702
|
+
},
|
|
2703
|
+
rangeThumb: {
|
|
2704
|
+
position: "absolute",
|
|
2705
|
+
width: 18,
|
|
2706
|
+
height: 18,
|
|
2707
|
+
marginLeft: -9,
|
|
2708
|
+
borderRadius: 9,
|
|
2709
|
+
borderWidth: 2,
|
|
2710
|
+
borderColor: "#18181b",
|
|
2711
|
+
backgroundColor: "#ffffff",
|
|
2712
|
+
shadowColor: "#000000",
|
|
2713
|
+
shadowOpacity: 0.12,
|
|
2714
|
+
shadowRadius: 3,
|
|
2715
|
+
shadowOffset: { width: 0, height: 1 }
|
|
2716
|
+
},
|
|
2717
|
+
rangeValue: {
|
|
2718
|
+
minWidth: 34,
|
|
2719
|
+
textAlign: "right",
|
|
2720
|
+
fontSize: 11,
|
|
2721
|
+
fontWeight: "500",
|
|
2722
|
+
color: "#71717a"
|
|
2723
|
+
},
|
|
2724
|
+
segmentGroup: {
|
|
2725
|
+
flexDirection: "row",
|
|
2726
|
+
alignItems: "center",
|
|
2727
|
+
gap: 3,
|
|
2728
|
+
padding: 3,
|
|
2729
|
+
borderRadius: 8,
|
|
2730
|
+
backgroundColor: "rgba(24,24,27,0.06)"
|
|
2731
|
+
},
|
|
2732
|
+
segment: {
|
|
2733
|
+
flex: 1,
|
|
2734
|
+
minWidth: 96,
|
|
2735
|
+
minHeight: 32,
|
|
2736
|
+
flexDirection: "row",
|
|
2737
|
+
alignItems: "center",
|
|
2738
|
+
justifyContent: "center",
|
|
2739
|
+
gap: 6,
|
|
2740
|
+
paddingHorizontal: 8,
|
|
2741
|
+
paddingVertical: 5,
|
|
2742
|
+
borderRadius: 6
|
|
2743
|
+
},
|
|
2744
|
+
segmentSelected: {
|
|
2745
|
+
backgroundColor: "#ffffff",
|
|
2746
|
+
shadowColor: "#000000",
|
|
2747
|
+
shadowOpacity: 0.1,
|
|
2748
|
+
shadowRadius: 2,
|
|
2749
|
+
shadowOffset: { width: 0, height: 1 }
|
|
2750
|
+
},
|
|
2751
|
+
segmentLabel: {
|
|
2752
|
+
fontSize: 11,
|
|
2753
|
+
fontWeight: "600",
|
|
2754
|
+
color: "#71717a",
|
|
2755
|
+
flexShrink: 0
|
|
2756
|
+
},
|
|
2757
|
+
segmentLabelSelected: {
|
|
2758
|
+
color: "#18181b"
|
|
2759
|
+
},
|
|
2760
|
+
dashPreviewTrack: {
|
|
2761
|
+
width: 26,
|
|
2762
|
+
height: 6,
|
|
2763
|
+
flexDirection: "row",
|
|
2764
|
+
alignItems: "center",
|
|
2765
|
+
justifyContent: "center",
|
|
2766
|
+
gap: 3
|
|
2767
|
+
},
|
|
2768
|
+
dashPreviewStroke: {
|
|
2769
|
+
flexShrink: 0
|
|
2770
|
+
}
|
|
2771
|
+
});
|
|
2236
2772
|
var DEFAULT_NATIVE_OVERFLOW_TOOL_IDS = [
|
|
2237
2773
|
"rect",
|
|
2238
2774
|
"ellipse",
|
|
@@ -2364,7 +2900,7 @@ function NativeVectorToolbar({
|
|
|
2364
2900
|
View,
|
|
2365
2901
|
{
|
|
2366
2902
|
accessibilityLabel,
|
|
2367
|
-
style: [
|
|
2903
|
+
style: [styles2.shell, style],
|
|
2368
2904
|
pointerEvents: "box-none",
|
|
2369
2905
|
children: [
|
|
2370
2906
|
/* @__PURE__ */ jsxs(
|
|
@@ -2373,8 +2909,8 @@ function NativeVectorToolbar({
|
|
|
2373
2909
|
horizontal: true,
|
|
2374
2910
|
showsHorizontalScrollIndicator: false,
|
|
2375
2911
|
contentContainerStyle: [
|
|
2376
|
-
|
|
2377
|
-
density === "comfortable" ?
|
|
2912
|
+
styles2.content,
|
|
2913
|
+
density === "comfortable" ? styles2.comfortableContent : void 0,
|
|
2378
2914
|
contentContainerStyle
|
|
2379
2915
|
],
|
|
2380
2916
|
children: [
|
|
@@ -2391,21 +2927,21 @@ function NativeVectorToolbar({
|
|
|
2391
2927
|
disabled: toolLockDisabled,
|
|
2392
2928
|
onPress: toggleToolLock,
|
|
2393
2929
|
style: ({ pressed }) => [
|
|
2394
|
-
|
|
2395
|
-
density === "comfortable" ?
|
|
2396
|
-
toolLocked ?
|
|
2397
|
-
pressed && !toolLockDisabled ?
|
|
2398
|
-
toolLockDisabled ?
|
|
2930
|
+
styles2.toolButton,
|
|
2931
|
+
density === "comfortable" ? styles2.comfortableToolButton : void 0,
|
|
2932
|
+
toolLocked ? styles2.activeToolButton : void 0,
|
|
2933
|
+
pressed && !toolLockDisabled ? styles2.pressedToolButton : void 0,
|
|
2934
|
+
toolLockDisabled ? styles2.disabledToolButton : void 0
|
|
2399
2935
|
],
|
|
2400
2936
|
children: renderToolLockIcon?.({
|
|
2401
2937
|
locked: toolLocked,
|
|
2402
2938
|
disabled: toolLockDisabled,
|
|
2403
2939
|
foregroundColor: "#18181b",
|
|
2404
2940
|
onToggle: toggleToolLock
|
|
2405
|
-
}) ?? /* @__PURE__ */ jsx(Text$1, { style:
|
|
2941
|
+
}) ?? /* @__PURE__ */ jsx(Text$1, { style: styles2.lockGlyph, children: toolLocked ? "L" : "U" })
|
|
2406
2942
|
}
|
|
2407
2943
|
),
|
|
2408
|
-
/* @__PURE__ */ jsx(View, { style:
|
|
2944
|
+
/* @__PURE__ */ jsx(View, { style: styles2.toolLockDivider })
|
|
2409
2945
|
] }) : null,
|
|
2410
2946
|
toolbarTools.map(
|
|
2411
2947
|
(tool) => renderNativeToolButton({
|
|
@@ -2423,7 +2959,7 @@ function NativeVectorToolbar({
|
|
|
2423
2959
|
renderToolButton
|
|
2424
2960
|
})
|
|
2425
2961
|
),
|
|
2426
|
-
showOverflowMenu ? /* @__PURE__ */ jsx(View, { style:
|
|
2962
|
+
showOverflowMenu ? /* @__PURE__ */ jsx(View, { style: styles2.overflowSpacer }) : null,
|
|
2427
2963
|
showOverflowMenu ? /* @__PURE__ */ jsxs(
|
|
2428
2964
|
Pressable,
|
|
2429
2965
|
{
|
|
@@ -2437,27 +2973,27 @@ function NativeVectorToolbar({
|
|
|
2437
2973
|
disabled,
|
|
2438
2974
|
onPress: toggleOverflow,
|
|
2439
2975
|
style: ({ pressed }) => [
|
|
2440
|
-
|
|
2441
|
-
overflowOpen || activeOverflowTool ?
|
|
2442
|
-
pressed && !disabled ?
|
|
2443
|
-
disabled ?
|
|
2976
|
+
styles2.overflowTrigger,
|
|
2977
|
+
overflowOpen || activeOverflowTool ? styles2.activeToolButton : void 0,
|
|
2978
|
+
pressed && !disabled ? styles2.pressedToolButton : void 0,
|
|
2979
|
+
disabled ? styles2.disabledToolButton : void 0
|
|
2444
2980
|
],
|
|
2445
2981
|
children: [
|
|
2446
|
-
/* @__PURE__ */ jsx(View, { style:
|
|
2982
|
+
/* @__PURE__ */ jsx(View, { style: styles2.iconSlot, children: activeOverflowTool ? renderToolIcon?.({
|
|
2447
2983
|
tool: activeOverflowTool,
|
|
2448
2984
|
selected: true,
|
|
2449
2985
|
disabled,
|
|
2450
2986
|
foregroundColor: "#18181b",
|
|
2451
2987
|
onSelect: () => onChange(activeOverflowTool.id)
|
|
2452
|
-
}) ?? renderNativeToolFallback(activeOverflowTool, "#18181b") : renderOverflowIcon?.(overflowRenderInput) ?? /* @__PURE__ */ jsx(Text$1, { style:
|
|
2453
|
-
renderOverflowChevronIcon?.(overflowRenderInput) ?? /* @__PURE__ */ jsx(Text$1, { style:
|
|
2988
|
+
}) ?? renderNativeToolFallback(activeOverflowTool, "#18181b") : renderOverflowIcon?.(overflowRenderInput) ?? /* @__PURE__ */ jsx(Text$1, { style: styles2.shapesGlyph, children: "S" }) }),
|
|
2989
|
+
renderOverflowChevronIcon?.(overflowRenderInput) ?? /* @__PURE__ */ jsx(Text$1, { style: styles2.chevronGlyph, children: overflowOpen ? "^" : "v" })
|
|
2454
2990
|
]
|
|
2455
2991
|
}
|
|
2456
2992
|
) : null
|
|
2457
2993
|
]
|
|
2458
2994
|
}
|
|
2459
2995
|
),
|
|
2460
|
-
overflowOpen && showOverflowMenu ? /* @__PURE__ */ jsx(View, { style: [
|
|
2996
|
+
overflowOpen && showOverflowMenu ? /* @__PURE__ */ jsx(View, { style: [styles2.overflowPanel, overflowPanelStyle], children: remainingOverflowTools.map(
|
|
2461
2997
|
(tool) => renderNativeToolButton({
|
|
2462
2998
|
tool,
|
|
2463
2999
|
value,
|
|
@@ -2468,7 +3004,7 @@ function NativeVectorToolbar({
|
|
|
2468
3004
|
disabled,
|
|
2469
3005
|
disabledIds,
|
|
2470
3006
|
density: "compact",
|
|
2471
|
-
toolButtonStyle:
|
|
3007
|
+
toolButtonStyle: styles2.overflowToolButton,
|
|
2472
3008
|
activeToolButtonStyle,
|
|
2473
3009
|
toolLabelStyle,
|
|
2474
3010
|
activeToolLabelStyle,
|
|
@@ -2509,22 +3045,22 @@ function renderNativeToolButton(input) {
|
|
|
2509
3045
|
disabled: toolDisabled,
|
|
2510
3046
|
onPress: onSelect,
|
|
2511
3047
|
style: ({ pressed }) => [
|
|
2512
|
-
|
|
2513
|
-
input.density === "comfortable" ?
|
|
3048
|
+
styles2.toolButton,
|
|
3049
|
+
input.density === "comfortable" ? styles2.comfortableToolButton : void 0,
|
|
2514
3050
|
input.toolButtonStyle,
|
|
2515
|
-
selected ?
|
|
3051
|
+
selected ? styles2.activeToolButton : void 0,
|
|
2516
3052
|
selected ? input.activeToolButtonStyle : void 0,
|
|
2517
|
-
pressed && !toolDisabled ?
|
|
2518
|
-
toolDisabled ?
|
|
3053
|
+
pressed && !toolDisabled ? styles2.pressedToolButton : void 0,
|
|
3054
|
+
toolDisabled ? styles2.disabledToolButton : void 0
|
|
2519
3055
|
],
|
|
2520
3056
|
children: [
|
|
2521
|
-
/* @__PURE__ */ jsx(View, { style:
|
|
3057
|
+
/* @__PURE__ */ jsx(View, { style: styles2.iconSlot, children: icon }),
|
|
2522
3058
|
input.density === "comfortable" ? /* @__PURE__ */ jsx(
|
|
2523
3059
|
Text$1,
|
|
2524
3060
|
{
|
|
2525
3061
|
numberOfLines: 1,
|
|
2526
3062
|
style: [
|
|
2527
|
-
|
|
3063
|
+
styles2.toolLabel,
|
|
2528
3064
|
{ color: foregroundColor },
|
|
2529
3065
|
input.toolLabelStyle,
|
|
2530
3066
|
selected ? input.activeToolLabelStyle : void 0
|
|
@@ -2538,9 +3074,9 @@ function renderNativeToolButton(input) {
|
|
|
2538
3074
|
);
|
|
2539
3075
|
}
|
|
2540
3076
|
function renderNativeToolFallback(tool, foregroundColor, toolLabelStyle) {
|
|
2541
|
-
return /* @__PURE__ */ jsx(Text$1, { style: [
|
|
3077
|
+
return /* @__PURE__ */ jsx(Text$1, { style: [styles2.shortLabel, { color: foregroundColor }, toolLabelStyle], children: tool.shortLabel ?? tool.label.slice(0, 1).toUpperCase() });
|
|
2542
3078
|
}
|
|
2543
|
-
var
|
|
3079
|
+
var styles2 = StyleSheet.create({
|
|
2544
3080
|
shell: {
|
|
2545
3081
|
borderRadius: 8,
|
|
2546
3082
|
borderWidth: StyleSheet.hairlineWidth,
|
|
@@ -2865,9 +3401,27 @@ function collectEraserTargetsAtWorldPoint(items, worldX, worldY, options) {
|
|
|
2865
3401
|
var MIN_PLACE_SIZE = 8;
|
|
2866
3402
|
var MIN_ARROW_DRAG_PX = 8;
|
|
2867
3403
|
var TAP_PX = 20;
|
|
3404
|
+
var MARKER_TOOL_STYLE = {
|
|
3405
|
+
stroke: "#fde047",
|
|
3406
|
+
strokeWidth: 16,
|
|
3407
|
+
strokeOpacity: 0.5
|
|
3408
|
+
};
|
|
2868
3409
|
function isPlacementTool(toolId) {
|
|
2869
3410
|
return toolId === "rect" || toolId === "ellipse" || toolId === "architectural-cloud" || toolId === "line" || toolId === "arrow";
|
|
2870
3411
|
}
|
|
3412
|
+
function isDefaultMarkerToolStyle(style) {
|
|
3413
|
+
return style.stroke === MARKER_TOOL_STYLE.stroke && style.strokeWidth === MARKER_TOOL_STYLE.strokeWidth && style.strokeOpacity === MARKER_TOOL_STYLE.strokeOpacity;
|
|
3414
|
+
}
|
|
3415
|
+
function supportsNativeResizeHandles(item) {
|
|
3416
|
+
const k = item?.toolKind;
|
|
3417
|
+
if (k === "rect" || k === "ellipse" || k === "architectural-cloud" || k === "line" || k === "arrow" || k === "image" || k === "text") {
|
|
3418
|
+
return true;
|
|
3419
|
+
}
|
|
3420
|
+
if ((k === "draw" || k === "pencil" || k === "brush" || k === "marker") && item?.pathPointsLocal && item.pathPointsLocal.length > 0) {
|
|
3421
|
+
return true;
|
|
3422
|
+
}
|
|
3423
|
+
return k === "custom" && !!item?.customIntrinsicSize && !!item?.customInnerSvg;
|
|
3424
|
+
}
|
|
2871
3425
|
function placementPreviewForTool(toolId, start, end) {
|
|
2872
3426
|
if (toolId === "rect" || toolId === "ellipse" || toolId === "architectural-cloud") {
|
|
2873
3427
|
return { kind: toolId, rect: rectFromCorners(start, end) };
|
|
@@ -2930,7 +3484,9 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
2930
3484
|
onItemsChange,
|
|
2931
3485
|
onToolChangeRequest,
|
|
2932
3486
|
onCameraChange,
|
|
2933
|
-
toolbar
|
|
3487
|
+
toolbar,
|
|
3488
|
+
showStyleInspector = false,
|
|
3489
|
+
styleInspectorPlacement = "bottom"
|
|
2934
3490
|
}, ref) {
|
|
2935
3491
|
const [size, setSize] = useState({ width: 0, height: 0 });
|
|
2936
3492
|
const cameraRef = useRef(null);
|
|
@@ -2957,6 +3513,13 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
2957
3513
|
const [eraserTrail, setEraserTrail] = useState([]);
|
|
2958
3514
|
const [laserTrail, setLaserTrail] = useState([]);
|
|
2959
3515
|
const laserClearTimerRef = useRef(null);
|
|
3516
|
+
const strokeStyleRef = useRef({ ...DEFAULT_STROKE_STYLE });
|
|
3517
|
+
const markerStrokeStyleRef = useRef({ ...MARKER_TOOL_STYLE });
|
|
3518
|
+
const styleBeforeMarkerRef = useRef({ ...DEFAULT_STROKE_STYLE });
|
|
3519
|
+
const lastToolIdRef = useRef(toolId);
|
|
3520
|
+
const [strokeStyleState, setStrokeStyleState] = useState({
|
|
3521
|
+
...DEFAULT_STROKE_STYLE
|
|
3522
|
+
});
|
|
2960
3523
|
useEffect(
|
|
2961
3524
|
() => () => {
|
|
2962
3525
|
if (laserClearTimerRef.current) {
|
|
@@ -2965,6 +3528,60 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
2965
3528
|
},
|
|
2966
3529
|
[]
|
|
2967
3530
|
);
|
|
3531
|
+
useEffect(() => {
|
|
3532
|
+
if (eraserTrail.length === 0 && laserTrail.length === 0) return;
|
|
3533
|
+
const timer = setInterval(() => {
|
|
3534
|
+
const now = Date.now();
|
|
3535
|
+
setEraserTrail(
|
|
3536
|
+
(prev) => freshTimedTrailPoints(prev, now, ERASER_TRAIL_MAX_AGE_MS)
|
|
3537
|
+
);
|
|
3538
|
+
setLaserTrail(
|
|
3539
|
+
(prev) => freshTimedTrailPoints(prev, now, LASER_TRAIL_MAX_AGE_MS)
|
|
3540
|
+
);
|
|
3541
|
+
}, 50);
|
|
3542
|
+
return () => clearInterval(timer);
|
|
3543
|
+
}, [eraserTrail.length, laserTrail.length]);
|
|
3544
|
+
useEffect(() => {
|
|
3545
|
+
const previousToolId = lastToolIdRef.current;
|
|
3546
|
+
const current = strokeStyleRef.current;
|
|
3547
|
+
let next = current;
|
|
3548
|
+
if (toolId === "marker") {
|
|
3549
|
+
if (previousToolId !== "marker") {
|
|
3550
|
+
styleBeforeMarkerRef.current = current;
|
|
3551
|
+
}
|
|
3552
|
+
next = markerStrokeStyleRef.current;
|
|
3553
|
+
} else if (previousToolId === "marker") {
|
|
3554
|
+
markerStrokeStyleRef.current = current;
|
|
3555
|
+
const restored = styleBeforeMarkerRef.current;
|
|
3556
|
+
next = {
|
|
3557
|
+
stroke: restored.stroke,
|
|
3558
|
+
strokeWidth: toolId === "draw" && restored.strokeWidth === DEFAULT_STROKE_STYLE.strokeWidth ? 10 : restored.strokeWidth,
|
|
3559
|
+
...restored.strokeDash != null ? { strokeDash: restored.strokeDash } : {}
|
|
3560
|
+
};
|
|
3561
|
+
} else if (toolId === "draw") {
|
|
3562
|
+
next = {
|
|
3563
|
+
...current,
|
|
3564
|
+
strokeWidth: current.strokeWidth === DEFAULT_STROKE_STYLE.strokeWidth ? 10 : current.strokeWidth
|
|
3565
|
+
};
|
|
3566
|
+
} else if (isDefaultMarkerToolStyle(current)) {
|
|
3567
|
+
next = {
|
|
3568
|
+
stroke: DEFAULT_STROKE_STYLE.stroke,
|
|
3569
|
+
strokeWidth: DEFAULT_STROKE_STYLE.strokeWidth,
|
|
3570
|
+
...current.strokeDash != null ? { strokeDash: current.strokeDash } : {}
|
|
3571
|
+
};
|
|
3572
|
+
}
|
|
3573
|
+
strokeStyleRef.current = next;
|
|
3574
|
+
setStrokeStyleState(next);
|
|
3575
|
+
lastToolIdRef.current = toolId;
|
|
3576
|
+
}, [toolId]);
|
|
3577
|
+
const patchCurrentStrokeStyle = useCallback((patch) => {
|
|
3578
|
+
const next = { ...strokeStyleRef.current, ...patch };
|
|
3579
|
+
strokeStyleRef.current = next;
|
|
3580
|
+
if (toolIdRef.current === "marker") {
|
|
3581
|
+
markerStrokeStyleRef.current = next;
|
|
3582
|
+
}
|
|
3583
|
+
setStrokeStyleState(next);
|
|
3584
|
+
}, []);
|
|
2968
3585
|
const [eraserPreviewIds, setEraserPreviewIds] = useState([]);
|
|
2969
3586
|
const eraserPreviewIdSetRef = useRef(/* @__PURE__ */ new Set());
|
|
2970
3587
|
const requestSelectToolAfterUse = useCallback(() => {
|
|
@@ -3002,7 +3619,7 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
3002
3619
|
const hidden = new Set(eraserPreviewIds);
|
|
3003
3620
|
return items.filter((it) => !hidden.has(it.id));
|
|
3004
3621
|
}, [items, eraserPreviewIds]);
|
|
3005
|
-
const showResizeHandles = interactive && selectedItems.length === 1 && !selectedItems[0]?.locked;
|
|
3622
|
+
const showResizeHandles = interactive && selectedItems.length === 1 && !selectedItems[0]?.locked && supportsNativeResizeHandles(selectedItems[0]);
|
|
3006
3623
|
const lastPinchDist = useRef(null);
|
|
3007
3624
|
const lastPanPoint = useRef(null);
|
|
3008
3625
|
const panResponder = useMemo(
|
|
@@ -3077,7 +3694,14 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
3077
3694
|
clearTimeout(laserClearTimerRef.current);
|
|
3078
3695
|
laserClearTimerRef.current = null;
|
|
3079
3696
|
}
|
|
3080
|
-
setLaserTrail([{ x: worldX, y: worldY }]);
|
|
3697
|
+
setLaserTrail([{ x: worldX, y: worldY, t: Date.now() }]);
|
|
3698
|
+
} else {
|
|
3699
|
+
setPlacementPreview({
|
|
3700
|
+
kind: "stroke",
|
|
3701
|
+
tool,
|
|
3702
|
+
points: [{ x: worldX, y: worldY }],
|
|
3703
|
+
style: { ...strokeStyleRef.current }
|
|
3704
|
+
});
|
|
3081
3705
|
}
|
|
3082
3706
|
return;
|
|
3083
3707
|
}
|
|
@@ -3085,7 +3709,7 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
3085
3709
|
dragStateRef.current = { kind: "erase" };
|
|
3086
3710
|
eraserPreviewIdSetRef.current = /* @__PURE__ */ new Set();
|
|
3087
3711
|
setEraserPreviewIds([]);
|
|
3088
|
-
setEraserTrail([{ x: worldX, y: worldY }]);
|
|
3712
|
+
setEraserTrail([{ x: worldX, y: worldY, t: Date.now() }]);
|
|
3089
3713
|
const toErase = collectEraserTargetsAtWorldPoint(
|
|
3090
3714
|
itemsRef.current,
|
|
3091
3715
|
worldX,
|
|
@@ -3176,18 +3800,25 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
3176
3800
|
const last = pts[pts.length - 1];
|
|
3177
3801
|
const dx = worldX - (last?.x ?? worldX);
|
|
3178
3802
|
const dy = worldY - (last?.y ?? worldY);
|
|
3179
|
-
|
|
3803
|
+
const shouldAppendPoint = Math.hypot(dx, dy) > 0.5 / cam.zoom;
|
|
3804
|
+
if (shouldAppendPoint) {
|
|
3180
3805
|
pts.push({ x: worldX, y: worldY });
|
|
3181
3806
|
}
|
|
3182
3807
|
if (st.tool === "laser") {
|
|
3183
|
-
|
|
3184
|
-
|
|
3185
|
-
|
|
3186
|
-
|
|
3187
|
-
|
|
3188
|
-
|
|
3189
|
-
|
|
3808
|
+
if (shouldAppendPoint) {
|
|
3809
|
+
setLaserTrail((prev) => [
|
|
3810
|
+
...prev,
|
|
3811
|
+
{ x: worldX, y: worldY, t: Date.now() }
|
|
3812
|
+
]);
|
|
3813
|
+
}
|
|
3814
|
+
return;
|
|
3190
3815
|
}
|
|
3816
|
+
setPlacementPreview({
|
|
3817
|
+
kind: "stroke",
|
|
3818
|
+
tool: st.tool,
|
|
3819
|
+
points: [...pts],
|
|
3820
|
+
style: { ...strokeStyleRef.current }
|
|
3821
|
+
});
|
|
3191
3822
|
return;
|
|
3192
3823
|
}
|
|
3193
3824
|
if (st.kind === "move") {
|
|
@@ -3225,7 +3856,10 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
3225
3856
|
return;
|
|
3226
3857
|
}
|
|
3227
3858
|
if (st.kind === "erase") {
|
|
3228
|
-
setEraserTrail((prev) => [
|
|
3859
|
+
setEraserTrail((prev) => [
|
|
3860
|
+
...prev,
|
|
3861
|
+
{ x: worldX, y: worldY, t: Date.now() }
|
|
3862
|
+
]);
|
|
3229
3863
|
const toErase = collectEraserTargetsAtWorldPoint(
|
|
3230
3864
|
itemsRef.current,
|
|
3231
3865
|
worldX,
|
|
@@ -3270,7 +3904,12 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
3270
3904
|
const change = onItemsChangeRef.current;
|
|
3271
3905
|
if (!change) return;
|
|
3272
3906
|
const id = createShapeId();
|
|
3273
|
-
const item = createFreehandStrokeItem(
|
|
3907
|
+
const item = createFreehandStrokeItem(
|
|
3908
|
+
id,
|
|
3909
|
+
st.points,
|
|
3910
|
+
st.tool,
|
|
3911
|
+
strokeStyleRef.current
|
|
3912
|
+
);
|
|
3274
3913
|
if (item) {
|
|
3275
3914
|
change([...itemsRef.current, item]);
|
|
3276
3915
|
}
|
|
@@ -3347,26 +3986,33 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
3347
3986
|
}
|
|
3348
3987
|
}
|
|
3349
3988
|
const id = createShapeId();
|
|
3989
|
+
const style = strokeStyleRef.current;
|
|
3350
3990
|
if (st.tool === "rect") {
|
|
3351
|
-
change([...itemsRef.current, createRectangleItem(id, raw)]);
|
|
3991
|
+
change([...itemsRef.current, createRectangleItem(id, raw, style)]);
|
|
3352
3992
|
onSelectionChangeRef.current?.([id]);
|
|
3353
3993
|
requestSelectToolAfterUse();
|
|
3354
3994
|
return;
|
|
3355
3995
|
}
|
|
3356
3996
|
if (st.tool === "ellipse") {
|
|
3357
|
-
change([...itemsRef.current, createEllipseItem(id, raw)]);
|
|
3997
|
+
change([...itemsRef.current, createEllipseItem(id, raw, style)]);
|
|
3358
3998
|
onSelectionChangeRef.current?.([id]);
|
|
3359
3999
|
requestSelectToolAfterUse();
|
|
3360
4000
|
return;
|
|
3361
4001
|
}
|
|
3362
4002
|
if (st.tool === "architectural-cloud") {
|
|
3363
|
-
change([
|
|
4003
|
+
change([
|
|
4004
|
+
...itemsRef.current,
|
|
4005
|
+
createArchitecturalCloudItem(id, raw, style)
|
|
4006
|
+
]);
|
|
3364
4007
|
onSelectionChangeRef.current?.([id]);
|
|
3365
4008
|
requestSelectToolAfterUse();
|
|
3366
4009
|
return;
|
|
3367
4010
|
}
|
|
3368
4011
|
const line = lineEndpointsToLocal(br, lineStart, lineEnd);
|
|
3369
|
-
change([
|
|
4012
|
+
change([
|
|
4013
|
+
...itemsRef.current,
|
|
4014
|
+
createLineItem(id, br, line, st.tool, style)
|
|
4015
|
+
]);
|
|
3370
4016
|
onSelectionChangeRef.current?.([id]);
|
|
3371
4017
|
requestSelectToolAfterUse();
|
|
3372
4018
|
return;
|
|
@@ -3389,7 +4035,7 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
3389
4035
|
height: 26
|
|
3390
4036
|
},
|
|
3391
4037
|
"Text",
|
|
3392
|
-
|
|
4038
|
+
strokeStyleRef.current,
|
|
3393
4039
|
18
|
|
3394
4040
|
);
|
|
3395
4041
|
change([...itemsRef.current, item]);
|
|
@@ -3425,6 +4071,9 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
3425
4071
|
dragStateRef.current = { kind: "idle" };
|
|
3426
4072
|
setPlacementPreview(null);
|
|
3427
4073
|
setLaserTrail([]);
|
|
4074
|
+
setEraserTrail([]);
|
|
4075
|
+
setEraserPreviewIds([]);
|
|
4076
|
+
eraserPreviewIdSetRef.current.clear();
|
|
3428
4077
|
}
|
|
3429
4078
|
}),
|
|
3430
4079
|
[screenToWorld, requestRender, requestSelectToolAfterUse, interactive]
|
|
@@ -3450,6 +4099,7 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
3450
4099
|
}),
|
|
3451
4100
|
[requestRender, size]
|
|
3452
4101
|
);
|
|
4102
|
+
const activeStyleToolId = toolId === "draw" || toolId === "marker" ? toolId : null;
|
|
3453
4103
|
return /* @__PURE__ */ jsx(
|
|
3454
4104
|
View,
|
|
3455
4105
|
{
|
|
@@ -3479,9 +4129,36 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
3479
4129
|
eraserTrail,
|
|
3480
4130
|
eraserPreviewItems: items.filter(
|
|
3481
4131
|
(it) => eraserPreviewIds.includes(it.id)
|
|
3482
|
-
)
|
|
4132
|
+
),
|
|
4133
|
+
previewStrokeStyle: strokeStyleState
|
|
3483
4134
|
}
|
|
3484
4135
|
),
|
|
4136
|
+
interactive && showStyleInspector && activeStyleToolId ? /* @__PURE__ */ jsx(
|
|
4137
|
+
View,
|
|
4138
|
+
{
|
|
4139
|
+
pointerEvents: "box-none",
|
|
4140
|
+
style: styleInspectorPlacement === "top-left" ? {
|
|
4141
|
+
position: "absolute",
|
|
4142
|
+
left: 16,
|
|
4143
|
+
top: 104,
|
|
4144
|
+
alignItems: "flex-start"
|
|
4145
|
+
} : {
|
|
4146
|
+
position: "absolute",
|
|
4147
|
+
left: 16,
|
|
4148
|
+
right: 16,
|
|
4149
|
+
bottom: 84,
|
|
4150
|
+
alignItems: "center"
|
|
4151
|
+
},
|
|
4152
|
+
children: /* @__PURE__ */ jsx(
|
|
4153
|
+
NativeVectorStyleInspector,
|
|
4154
|
+
{
|
|
4155
|
+
toolId: activeStyleToolId,
|
|
4156
|
+
value: strokeStyleState,
|
|
4157
|
+
onChange: patchCurrentStrokeStyle
|
|
4158
|
+
}
|
|
4159
|
+
)
|
|
4160
|
+
}
|
|
4161
|
+
) : null,
|
|
3485
4162
|
toolbar && /* @__PURE__ */ jsx(
|
|
3486
4163
|
View,
|
|
3487
4164
|
{
|
|
@@ -3503,6 +4180,6 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
3503
4180
|
);
|
|
3504
4181
|
});
|
|
3505
4182
|
|
|
3506
|
-
export { DEFAULT_NATIVE_OVERFLOW_TOOL_IDS, DEFAULT_NATIVE_VECTOR_TOOLS, NativeInteractionOverlay, NativeSceneRenderer, NativeShapeRenderer, NativeVectorToolbar, NativeVectorViewport, createFreehandStrokeItem, createImageItem, createShapeId, parseSvgFragment };
|
|
4183
|
+
export { DEFAULT_NATIVE_OVERFLOW_TOOL_IDS, DEFAULT_NATIVE_VECTOR_TOOLS, NATIVE_STYLE_PALETTE, NativeInteractionOverlay, NativeSceneRenderer, NativeShapeRenderer, NativeVectorStyleInspector, NativeVectorToolbar, NativeVectorViewport, createFreehandStrokeItem, createImageItem, createShapeId, nativeStyleColorWithOpacity, normalizeNativeStyleHex, parseSvgFragment };
|
|
3507
4184
|
//# sourceMappingURL=native.js.map
|
|
3508
4185
|
//# sourceMappingURL=native.js.map
|