canvu-react 0.4.14 → 0.4.16
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 +1090 -158
- package/dist/native.cjs.map +1 -1
- package/dist/native.d.cts +51 -13
- package/dist/native.d.ts +51 -13
- package/dist/native.js +1089 -161
- package/dist/native.js.map +1 -1
- package/package.json +1 -1
package/dist/native.cjs
CHANGED
|
@@ -1822,13 +1822,224 @@ function NativeShapeRenderer({ item }) {
|
|
|
1822
1822
|
}
|
|
1823
1823
|
return null;
|
|
1824
1824
|
}
|
|
1825
|
+
var CURSOR_STROKE = "#18181b";
|
|
1826
|
+
var CURSOR_STROKE_WIDTH = 2;
|
|
1827
|
+
var CROSSHAIR_STROKE_WIDTH = 1.5;
|
|
1828
|
+
function NativeDrawCursor() {
|
|
1829
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1830
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1831
|
+
reactNativeSkia.Path,
|
|
1832
|
+
{
|
|
1833
|
+
path: "M13 21h8",
|
|
1834
|
+
color: CURSOR_STROKE,
|
|
1835
|
+
style: "stroke",
|
|
1836
|
+
strokeWidth: CURSOR_STROKE_WIDTH,
|
|
1837
|
+
strokeCap: "round",
|
|
1838
|
+
strokeJoin: "round",
|
|
1839
|
+
antiAlias: true
|
|
1840
|
+
}
|
|
1841
|
+
),
|
|
1842
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1843
|
+
reactNativeSkia.Path,
|
|
1844
|
+
{
|
|
1845
|
+
path: "M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z",
|
|
1846
|
+
color: CURSOR_STROKE,
|
|
1847
|
+
style: "stroke",
|
|
1848
|
+
strokeWidth: CURSOR_STROKE_WIDTH,
|
|
1849
|
+
strokeCap: "round",
|
|
1850
|
+
strokeJoin: "round",
|
|
1851
|
+
antiAlias: true
|
|
1852
|
+
}
|
|
1853
|
+
)
|
|
1854
|
+
] });
|
|
1855
|
+
}
|
|
1856
|
+
function NativeMarkerCursor() {
|
|
1857
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1858
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1859
|
+
reactNativeSkia.Path,
|
|
1860
|
+
{
|
|
1861
|
+
path: "m9 11-6 6v3h9l3-3",
|
|
1862
|
+
color: CURSOR_STROKE,
|
|
1863
|
+
style: "stroke",
|
|
1864
|
+
strokeWidth: CURSOR_STROKE_WIDTH,
|
|
1865
|
+
strokeCap: "round",
|
|
1866
|
+
strokeJoin: "round",
|
|
1867
|
+
antiAlias: true
|
|
1868
|
+
}
|
|
1869
|
+
),
|
|
1870
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1871
|
+
reactNativeSkia.Path,
|
|
1872
|
+
{
|
|
1873
|
+
path: "m22 12-4.6 4.6a2 2 0 0 1-2.8 0l-5.2-5.2a2 2 0 0 1 0-2.8L14 4",
|
|
1874
|
+
color: CURSOR_STROKE,
|
|
1875
|
+
style: "stroke",
|
|
1876
|
+
strokeWidth: CURSOR_STROKE_WIDTH,
|
|
1877
|
+
strokeCap: "round",
|
|
1878
|
+
strokeJoin: "round",
|
|
1879
|
+
antiAlias: true
|
|
1880
|
+
}
|
|
1881
|
+
)
|
|
1882
|
+
] });
|
|
1883
|
+
}
|
|
1884
|
+
function NativeEraserCursor() {
|
|
1885
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1886
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1887
|
+
reactNativeSkia.Path,
|
|
1888
|
+
{
|
|
1889
|
+
path: "M21 21H8a2 2 0 0 1-1.42-.587l-3.994-3.999a2 2 0 0 1 0-2.828l10-10a2 2 0 0 1 2.829 0l5.999 6a2 2 0 0 1 0 2.828L12.834 21",
|
|
1890
|
+
color: CURSOR_STROKE,
|
|
1891
|
+
style: "stroke",
|
|
1892
|
+
strokeWidth: CURSOR_STROKE_WIDTH,
|
|
1893
|
+
strokeCap: "round",
|
|
1894
|
+
strokeJoin: "round",
|
|
1895
|
+
antiAlias: true
|
|
1896
|
+
}
|
|
1897
|
+
),
|
|
1898
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1899
|
+
reactNativeSkia.Path,
|
|
1900
|
+
{
|
|
1901
|
+
path: "m5.082 11.09 8.828 8.828",
|
|
1902
|
+
color: CURSOR_STROKE,
|
|
1903
|
+
style: "stroke",
|
|
1904
|
+
strokeWidth: CURSOR_STROKE_WIDTH,
|
|
1905
|
+
strokeCap: "round",
|
|
1906
|
+
strokeJoin: "round",
|
|
1907
|
+
antiAlias: true
|
|
1908
|
+
}
|
|
1909
|
+
)
|
|
1910
|
+
] });
|
|
1911
|
+
}
|
|
1912
|
+
function NativeCrosshairCursor() {
|
|
1913
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1914
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1915
|
+
reactNativeSkia.Line,
|
|
1916
|
+
{
|
|
1917
|
+
p1: reactNativeSkia.vec(12, 3),
|
|
1918
|
+
p2: reactNativeSkia.vec(12, 21),
|
|
1919
|
+
color: CURSOR_STROKE,
|
|
1920
|
+
style: "stroke",
|
|
1921
|
+
strokeWidth: CROSSHAIR_STROKE_WIDTH,
|
|
1922
|
+
strokeCap: "round",
|
|
1923
|
+
antiAlias: true
|
|
1924
|
+
}
|
|
1925
|
+
),
|
|
1926
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1927
|
+
reactNativeSkia.Line,
|
|
1928
|
+
{
|
|
1929
|
+
p1: reactNativeSkia.vec(3, 12),
|
|
1930
|
+
p2: reactNativeSkia.vec(21, 12),
|
|
1931
|
+
color: CURSOR_STROKE,
|
|
1932
|
+
style: "stroke",
|
|
1933
|
+
strokeWidth: CROSSHAIR_STROKE_WIDTH,
|
|
1934
|
+
strokeCap: "round",
|
|
1935
|
+
antiAlias: true
|
|
1936
|
+
}
|
|
1937
|
+
)
|
|
1938
|
+
] });
|
|
1939
|
+
}
|
|
1940
|
+
function NativeTextCursor() {
|
|
1941
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1942
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1943
|
+
reactNativeSkia.Line,
|
|
1944
|
+
{
|
|
1945
|
+
p1: reactNativeSkia.vec(12, 4),
|
|
1946
|
+
p2: reactNativeSkia.vec(12, 20),
|
|
1947
|
+
color: CURSOR_STROKE,
|
|
1948
|
+
style: "stroke",
|
|
1949
|
+
strokeWidth: CURSOR_STROKE_WIDTH,
|
|
1950
|
+
strokeCap: "round",
|
|
1951
|
+
antiAlias: true
|
|
1952
|
+
}
|
|
1953
|
+
),
|
|
1954
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1955
|
+
reactNativeSkia.Line,
|
|
1956
|
+
{
|
|
1957
|
+
p1: reactNativeSkia.vec(8, 4),
|
|
1958
|
+
p2: reactNativeSkia.vec(16, 4),
|
|
1959
|
+
color: CURSOR_STROKE,
|
|
1960
|
+
style: "stroke",
|
|
1961
|
+
strokeWidth: CURSOR_STROKE_WIDTH,
|
|
1962
|
+
strokeCap: "round",
|
|
1963
|
+
antiAlias: true
|
|
1964
|
+
}
|
|
1965
|
+
),
|
|
1966
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1967
|
+
reactNativeSkia.Line,
|
|
1968
|
+
{
|
|
1969
|
+
p1: reactNativeSkia.vec(8, 20),
|
|
1970
|
+
p2: reactNativeSkia.vec(16, 20),
|
|
1971
|
+
color: CURSOR_STROKE,
|
|
1972
|
+
style: "stroke",
|
|
1973
|
+
strokeWidth: CURSOR_STROKE_WIDTH,
|
|
1974
|
+
strokeCap: "round",
|
|
1975
|
+
antiAlias: true
|
|
1976
|
+
}
|
|
1977
|
+
)
|
|
1978
|
+
] });
|
|
1979
|
+
}
|
|
1980
|
+
function NativeToolCursorGlyph({
|
|
1981
|
+
cursor
|
|
1982
|
+
}) {
|
|
1983
|
+
if (cursor.kind === "draw") return /* @__PURE__ */ jsxRuntime.jsx(NativeDrawCursor, {});
|
|
1984
|
+
if (cursor.kind === "marker") return /* @__PURE__ */ jsxRuntime.jsx(NativeMarkerCursor, {});
|
|
1985
|
+
if (cursor.kind === "eraser") return /* @__PURE__ */ jsxRuntime.jsx(NativeEraserCursor, {});
|
|
1986
|
+
if (cursor.kind === "text") return /* @__PURE__ */ jsxRuntime.jsx(NativeTextCursor, {});
|
|
1987
|
+
return /* @__PURE__ */ jsxRuntime.jsx(NativeCrosshairCursor, {});
|
|
1988
|
+
}
|
|
1989
|
+
function NativeToolCursorRenderer({
|
|
1990
|
+
cursor,
|
|
1991
|
+
point
|
|
1992
|
+
}) {
|
|
1993
|
+
const x = point.x - cursor.hotspot.x;
|
|
1994
|
+
const y = point.y - cursor.hotspot.y;
|
|
1995
|
+
return /* @__PURE__ */ jsxRuntime.jsx(reactNativeSkia.Group, { transform: [{ translateX: x }, { translateY: y }], children: /* @__PURE__ */ jsxRuntime.jsx(NativeToolCursorGlyph, { cursor }) });
|
|
1996
|
+
}
|
|
1997
|
+
|
|
1998
|
+
// src/native/native-overlay-style.ts
|
|
1999
|
+
var ERASER_TINT = "#cbd5e1";
|
|
2000
|
+
var ERASER_TINT_OPACITY = 0.95;
|
|
2001
|
+
var LASER_TINT = "#f43f5e";
|
|
2002
|
+
var LASER_TINT_OPACITY = 0.9;
|
|
2003
|
+
var ERASER_TRAIL_MAX_AGE_MS = 150;
|
|
2004
|
+
var LASER_TRAIL_MAX_AGE_MS = 650;
|
|
2005
|
+
function colorWithOpacity(hex, alpha) {
|
|
2006
|
+
if (alpha == null || alpha >= 1) return hex;
|
|
2007
|
+
const r = parseInt(hex.slice(1, 3), 16);
|
|
2008
|
+
const g = parseInt(hex.slice(3, 5), 16);
|
|
2009
|
+
const b = parseInt(hex.slice(5, 7), 16);
|
|
2010
|
+
if (Number.isNaN(r) || Number.isNaN(g) || Number.isNaN(b)) return hex;
|
|
2011
|
+
return `rgba(${r},${g},${b},${alpha})`;
|
|
2012
|
+
}
|
|
2013
|
+
function freshTimedTrailPoints(points, now, maxAgeMs) {
|
|
2014
|
+
return points.filter((point) => now - point.t <= maxAgeMs);
|
|
2015
|
+
}
|
|
2016
|
+
function timedTrailHeadOpacity(point, now, maxAgeMs) {
|
|
2017
|
+
if (!point) return 0;
|
|
2018
|
+
return Math.max(0, 1 - (now - point.t) / maxAgeMs);
|
|
2019
|
+
}
|
|
2020
|
+
function resolveNativeStrokePreviewStyle(tool, previewStrokeStyle) {
|
|
2021
|
+
const isLaser = tool === "laser";
|
|
2022
|
+
return {
|
|
2023
|
+
stroke: isLaser ? LASER_TINT : previewStrokeStyle?.stroke ?? "#64748b",
|
|
2024
|
+
strokeWidth: isLaser ? 4 : previewStrokeStyle?.strokeWidth ?? (tool === "marker" ? 16 : 3),
|
|
2025
|
+
...previewStrokeStyle?.strokeOpacity != null && !isLaser ? { strokeOpacity: previewStrokeStyle.strokeOpacity } : {},
|
|
2026
|
+
...previewStrokeStyle?.strokeDash != null && !isLaser ? { strokeDash: previewStrokeStyle.strokeDash } : {}
|
|
2027
|
+
};
|
|
2028
|
+
}
|
|
1825
2029
|
var HANDLE_ORDER = ["nw", "n", "ne", "e", "se", "s", "sw", "w"];
|
|
1826
2030
|
var ERASER_PREVIEW_OPACITY = 0.3;
|
|
2031
|
+
var OVERLAY_STROKE_PX = 1.25;
|
|
2032
|
+
var MARQUEE_DASH_PX = 4;
|
|
1827
2033
|
function pointsToSmoothPathD(points) {
|
|
1828
2034
|
if (points.length < 2) return null;
|
|
1829
2035
|
const d = smoothFreehandPointsToPathD(points);
|
|
1830
2036
|
return d || null;
|
|
1831
2037
|
}
|
|
2038
|
+
function dashIntervalsFromStrokeDasharray(strokeDasharray) {
|
|
2039
|
+
if (!strokeDasharray) return null;
|
|
2040
|
+
const intervals = strokeDasharray.split(/\s+/).map((part) => Number(part)).filter((part) => Number.isFinite(part) && part > 0);
|
|
2041
|
+
return intervals.length > 0 ? intervals : null;
|
|
2042
|
+
}
|
|
1832
2043
|
function NativeInteractionOverlay({
|
|
1833
2044
|
camera,
|
|
1834
2045
|
width,
|
|
@@ -1838,13 +2049,19 @@ function NativeInteractionOverlay({
|
|
|
1838
2049
|
placementPreview,
|
|
1839
2050
|
eraserTrail,
|
|
1840
2051
|
laserTrail,
|
|
1841
|
-
eraserPreviewItems = []
|
|
2052
|
+
eraserPreviewItems = [],
|
|
2053
|
+
previewStrokeStyle,
|
|
2054
|
+
toolCursor
|
|
1842
2055
|
}) {
|
|
1843
2056
|
const z = camera.zoom;
|
|
1844
2057
|
const camTransform = skiaCameraTransform(z, camera.x, camera.y);
|
|
1845
2058
|
const handleR = 5 / z;
|
|
1846
|
-
const
|
|
2059
|
+
const overlayStrokeWorld = OVERLAY_STROKE_PX / z;
|
|
2060
|
+
const marqueeDashWorld = MARQUEE_DASH_PX / z;
|
|
1847
2061
|
const rotateOffsetWorld = 24 / z;
|
|
2062
|
+
const rotateIconWorld = 16 / z;
|
|
2063
|
+
const rotateIconScale = rotateIconWorld / 24;
|
|
2064
|
+
const rotateIconStroke = OVERLAY_STROKE_PX / (z * rotateIconScale);
|
|
1848
2065
|
const selectionElements = react.useMemo(() => {
|
|
1849
2066
|
if (selectedItems.length === 0) return null;
|
|
1850
2067
|
const single = selectedItems.length === 1 ? selectedItems[0] : void 0;
|
|
@@ -1866,7 +2083,7 @@ function NativeInteractionOverlay({
|
|
|
1866
2083
|
height: b.height,
|
|
1867
2084
|
color: "#3b82f6",
|
|
1868
2085
|
style: "stroke",
|
|
1869
|
-
strokeWidth:
|
|
2086
|
+
strokeWidth: overlayStrokeWorld,
|
|
1870
2087
|
antiAlias: true
|
|
1871
2088
|
}
|
|
1872
2089
|
) }, it.id);
|
|
@@ -1874,83 +2091,167 @@ function NativeInteractionOverlay({
|
|
|
1874
2091
|
showResizeHandles && bSingle && single && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1875
2092
|
HANDLE_ORDER.map((hid) => {
|
|
1876
2093
|
const p = getHandleWorldPositionRotated(bSingle, hid, rotSingle);
|
|
1877
|
-
return /* @__PURE__ */ jsxRuntime.
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
2094
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(reactNativeSkia.Group, { children: [
|
|
2095
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2096
|
+
reactNativeSkia.Circle,
|
|
2097
|
+
{
|
|
2098
|
+
cx: p.x,
|
|
2099
|
+
cy: p.y,
|
|
2100
|
+
r: handleR,
|
|
2101
|
+
color: "#ffffff",
|
|
2102
|
+
style: "fill",
|
|
2103
|
+
antiAlias: true
|
|
2104
|
+
}
|
|
2105
|
+
),
|
|
2106
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2107
|
+
reactNativeSkia.Circle,
|
|
2108
|
+
{
|
|
2109
|
+
cx: p.x,
|
|
2110
|
+
cy: p.y,
|
|
2111
|
+
r: handleR,
|
|
2112
|
+
color: "#3b82f6",
|
|
2113
|
+
style: "stroke",
|
|
2114
|
+
strokeWidth: overlayStrokeWorld,
|
|
2115
|
+
antiAlias: true
|
|
2116
|
+
}
|
|
2117
|
+
)
|
|
2118
|
+
] }, hid);
|
|
1889
2119
|
}),
|
|
1890
|
-
rotHandlePos && /* @__PURE__ */ jsxRuntime.
|
|
1891
|
-
reactNativeSkia.
|
|
2120
|
+
rotHandlePos && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2121
|
+
reactNativeSkia.Group,
|
|
1892
2122
|
{
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
2123
|
+
transform: [
|
|
2124
|
+
{ translateX: rotHandlePos.x },
|
|
2125
|
+
{ translateY: rotHandlePos.y },
|
|
2126
|
+
{ rotate: rotSingle },
|
|
2127
|
+
{ translateX: -rotateIconWorld / 2 },
|
|
2128
|
+
{ translateY: -rotateIconWorld / 2 },
|
|
2129
|
+
{ scale: rotateIconScale }
|
|
2130
|
+
],
|
|
2131
|
+
children: [
|
|
2132
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2133
|
+
reactNativeSkia.Path,
|
|
2134
|
+
{
|
|
2135
|
+
path: "M21 12a9 9 0 1 1-9-9c2.52 0 4.93 1 6.74 2.74L21 8",
|
|
2136
|
+
color: "#3b82f6",
|
|
2137
|
+
style: "stroke",
|
|
2138
|
+
strokeWidth: rotateIconStroke,
|
|
2139
|
+
strokeCap: "round",
|
|
2140
|
+
strokeJoin: "round",
|
|
2141
|
+
antiAlias: true
|
|
2142
|
+
}
|
|
2143
|
+
),
|
|
2144
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2145
|
+
reactNativeSkia.Path,
|
|
2146
|
+
{
|
|
2147
|
+
path: "M21 3v5h-5",
|
|
2148
|
+
color: "#3b82f6",
|
|
2149
|
+
style: "stroke",
|
|
2150
|
+
strokeWidth: rotateIconStroke,
|
|
2151
|
+
strokeCap: "round",
|
|
2152
|
+
strokeJoin: "round",
|
|
2153
|
+
antiAlias: true
|
|
2154
|
+
}
|
|
2155
|
+
)
|
|
2156
|
+
]
|
|
1900
2157
|
}
|
|
1901
2158
|
)
|
|
1902
2159
|
] })
|
|
1903
2160
|
] });
|
|
1904
|
-
}, [
|
|
2161
|
+
}, [
|
|
2162
|
+
selectedItems,
|
|
2163
|
+
showResizeHandles,
|
|
2164
|
+
rotateOffsetWorld,
|
|
2165
|
+
handleR,
|
|
2166
|
+
overlayStrokeWorld,
|
|
2167
|
+
rotateIconWorld,
|
|
2168
|
+
rotateIconScale,
|
|
2169
|
+
rotateIconStroke
|
|
2170
|
+
]);
|
|
1905
2171
|
const previewElements = react.useMemo(() => {
|
|
1906
2172
|
if (!placementPreview) return null;
|
|
1907
2173
|
const p = placementPreview;
|
|
2174
|
+
const shapeStroke = previewStrokeStyle?.stroke ?? "#1d1d1d";
|
|
2175
|
+
const shapeWidth = previewStrokeStyle?.strokeWidth ?? 2;
|
|
2176
|
+
const shapeColor = colorWithOpacity(
|
|
2177
|
+
shapeStroke,
|
|
2178
|
+
previewStrokeStyle?.strokeOpacity
|
|
2179
|
+
);
|
|
1908
2180
|
if (p.kind === "rect" || p.kind === "ellipse" || p.kind === "architectural-cloud") {
|
|
1909
2181
|
const r = normalizeRect(p.rect);
|
|
1910
|
-
return p.kind === "rect"
|
|
1911
|
-
reactNativeSkia.
|
|
2182
|
+
return p.kind === "rect" ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2183
|
+
reactNativeSkia.RoundedRect,
|
|
1912
2184
|
{
|
|
1913
2185
|
x: r.x,
|
|
1914
2186
|
y: r.y,
|
|
1915
2187
|
width: r.width,
|
|
1916
2188
|
height: r.height,
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
strokeWidth: overlayStrokePx,
|
|
1920
|
-
antiAlias: true
|
|
1921
|
-
}
|
|
1922
|
-
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
1923
|
-
reactNativeSkia.Circle,
|
|
1924
|
-
{
|
|
1925
|
-
cx: r.x + r.width / 2,
|
|
1926
|
-
cy: r.y + r.height / 2,
|
|
1927
|
-
r: Math.max(0, r.width / 2),
|
|
1928
|
-
color: "#64748b",
|
|
2189
|
+
r: 4,
|
|
2190
|
+
color: shapeColor,
|
|
1929
2191
|
style: "stroke",
|
|
1930
|
-
strokeWidth:
|
|
2192
|
+
strokeWidth: shapeWidth,
|
|
1931
2193
|
antiAlias: true
|
|
1932
2194
|
}
|
|
1933
|
-
)
|
|
1934
|
-
|
|
1935
|
-
if (p.kind === "marquee") {
|
|
1936
|
-
const r = normalizeRect(p.rect);
|
|
1937
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1938
|
-
reactNativeSkia.Rect,
|
|
2195
|
+
) : p.kind === "ellipse" ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2196
|
+
reactNativeSkia.Oval,
|
|
1939
2197
|
{
|
|
1940
2198
|
x: r.x,
|
|
1941
2199
|
y: r.y,
|
|
1942
2200
|
width: r.width,
|
|
1943
2201
|
height: r.height,
|
|
1944
|
-
color:
|
|
1945
|
-
style: "
|
|
2202
|
+
color: shapeColor,
|
|
2203
|
+
style: "stroke",
|
|
2204
|
+
strokeWidth: shapeWidth,
|
|
1946
2205
|
antiAlias: true
|
|
1947
2206
|
}
|
|
1948
|
-
)
|
|
2207
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(reactNativeSkia.Group, { transform: [{ translateX: r.x }, { translateY: r.y }], children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2208
|
+
reactNativeSkia.Path,
|
|
2209
|
+
{
|
|
2210
|
+
path: buildArchitecturalCloudPathD(r.width, r.height, shapeWidth),
|
|
2211
|
+
color: shapeColor,
|
|
2212
|
+
style: "stroke",
|
|
2213
|
+
strokeWidth: shapeWidth,
|
|
2214
|
+
strokeCap: "round",
|
|
2215
|
+
strokeJoin: "round",
|
|
2216
|
+
antiAlias: true
|
|
2217
|
+
}
|
|
2218
|
+
) });
|
|
2219
|
+
}
|
|
2220
|
+
if (p.kind === "marquee") {
|
|
2221
|
+
const r = normalizeRect(p.rect);
|
|
2222
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2223
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2224
|
+
reactNativeSkia.Rect,
|
|
2225
|
+
{
|
|
2226
|
+
x: r.x,
|
|
2227
|
+
y: r.y,
|
|
2228
|
+
width: r.width,
|
|
2229
|
+
height: r.height,
|
|
2230
|
+
color: "rgba(59, 130, 246, 0.12)",
|
|
2231
|
+
style: "fill",
|
|
2232
|
+
antiAlias: true
|
|
2233
|
+
}
|
|
2234
|
+
),
|
|
2235
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2236
|
+
reactNativeSkia.Rect,
|
|
2237
|
+
{
|
|
2238
|
+
x: r.x,
|
|
2239
|
+
y: r.y,
|
|
2240
|
+
width: r.width,
|
|
2241
|
+
height: r.height,
|
|
2242
|
+
color: "#3b82f6",
|
|
2243
|
+
style: "stroke",
|
|
2244
|
+
strokeWidth: overlayStrokeWorld,
|
|
2245
|
+
antiAlias: true,
|
|
2246
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(reactNativeSkia.DashPathEffect, { intervals: [marqueeDashWorld, marqueeDashWorld] })
|
|
2247
|
+
}
|
|
2248
|
+
)
|
|
2249
|
+
] });
|
|
1949
2250
|
}
|
|
1950
2251
|
if (p.kind === "line" || p.kind === "arrow") {
|
|
1951
2252
|
const geometry = p.kind === "arrow" ? computeStraightArrowGeometry(
|
|
1952
2253
|
{ x1: p.start.x, y1: p.start.y, x2: p.end.x, y2: p.end.y },
|
|
1953
|
-
|
|
2254
|
+
shapeWidth
|
|
1954
2255
|
) : null;
|
|
1955
2256
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1956
2257
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -1958,9 +2259,9 @@ function NativeInteractionOverlay({
|
|
|
1958
2259
|
{
|
|
1959
2260
|
p1: reactNativeSkia.vec(p.start.x, p.start.y),
|
|
1960
2261
|
p2: reactNativeSkia.vec(geometry?.shaftEndX ?? p.end.x, geometry?.shaftEndY ?? p.end.y),
|
|
1961
|
-
color:
|
|
2262
|
+
color: shapeColor,
|
|
1962
2263
|
style: "stroke",
|
|
1963
|
-
strokeWidth:
|
|
2264
|
+
strokeWidth: shapeWidth,
|
|
1964
2265
|
strokeCap: "round",
|
|
1965
2266
|
antiAlias: true
|
|
1966
2267
|
}
|
|
@@ -1969,9 +2270,9 @@ function NativeInteractionOverlay({
|
|
|
1969
2270
|
reactNativeSkia.Path,
|
|
1970
2271
|
{
|
|
1971
2272
|
path: `M ${geometry.headLeftX} ${geometry.headLeftY} L ${geometry.headTipX} ${geometry.headTipY} L ${geometry.headRightX} ${geometry.headRightY}`,
|
|
1972
|
-
color:
|
|
2273
|
+
color: shapeColor,
|
|
1973
2274
|
style: "stroke",
|
|
1974
|
-
strokeWidth:
|
|
2275
|
+
strokeWidth: shapeWidth,
|
|
1975
2276
|
strokeCap: "round",
|
|
1976
2277
|
strokeJoin: "round",
|
|
1977
2278
|
antiAlias: true
|
|
@@ -1980,10 +2281,15 @@ function NativeInteractionOverlay({
|
|
|
1980
2281
|
] });
|
|
1981
2282
|
}
|
|
1982
2283
|
if (p.kind === "stroke" && p.points.length >= 1) {
|
|
2284
|
+
const isLaser = p.tool === "laser";
|
|
2285
|
+
const style = resolveNativeStrokePreviewStyle(
|
|
2286
|
+
p.tool,
|
|
2287
|
+
p.style ?? previewStrokeStyle
|
|
2288
|
+
);
|
|
1983
2289
|
const payload = computeFreehandSvgPayload(
|
|
1984
2290
|
p.points,
|
|
1985
|
-
|
|
1986
|
-
"draw",
|
|
2291
|
+
style,
|
|
2292
|
+
isLaser ? "draw" : p.tool,
|
|
1987
2293
|
p.points.length === 2
|
|
1988
2294
|
);
|
|
1989
2295
|
if (!payload) return null;
|
|
@@ -1994,33 +2300,47 @@ function NativeInteractionOverlay({
|
|
|
1994
2300
|
cx: payload.cx,
|
|
1995
2301
|
cy: payload.cy,
|
|
1996
2302
|
r: payload.r,
|
|
1997
|
-
color: payload.fill,
|
|
2303
|
+
color: colorWithOpacity(payload.fill, payload.fillOpacity),
|
|
1998
2304
|
style: "fill",
|
|
1999
2305
|
antiAlias: true
|
|
2000
2306
|
}
|
|
2001
2307
|
);
|
|
2002
2308
|
}
|
|
2003
2309
|
if (payload.kind === "fillPath") {
|
|
2004
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2310
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2311
|
+
reactNativeSkia.Path,
|
|
2312
|
+
{
|
|
2313
|
+
path: payload.d,
|
|
2314
|
+
color: colorWithOpacity(payload.fill, payload.fillOpacity),
|
|
2315
|
+
style: "fill",
|
|
2316
|
+
fillType: "winding",
|
|
2317
|
+
antiAlias: true
|
|
2318
|
+
}
|
|
2319
|
+
);
|
|
2005
2320
|
}
|
|
2006
2321
|
if (payload.kind === "strokePath") {
|
|
2322
|
+
const intervals = dashIntervalsFromStrokeDasharray(payload.strokeDasharray);
|
|
2007
2323
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2008
2324
|
reactNativeSkia.Path,
|
|
2009
2325
|
{
|
|
2010
2326
|
path: payload.d,
|
|
2011
|
-
color:
|
|
2327
|
+
color: colorWithOpacity(
|
|
2328
|
+
payload.stroke,
|
|
2329
|
+
isLaser ? 0.85 : payload.strokeOpacity
|
|
2330
|
+
),
|
|
2012
2331
|
style: "stroke",
|
|
2013
|
-
strokeWidth:
|
|
2332
|
+
strokeWidth: payload.strokeWidth,
|
|
2014
2333
|
strokeCap: "round",
|
|
2015
2334
|
strokeJoin: "round",
|
|
2016
|
-
antiAlias: true
|
|
2335
|
+
antiAlias: true,
|
|
2336
|
+
children: intervals ? /* @__PURE__ */ jsxRuntime.jsx(reactNativeSkia.DashPathEffect, { intervals }) : null
|
|
2017
2337
|
}
|
|
2018
2338
|
);
|
|
2019
2339
|
}
|
|
2020
2340
|
return null;
|
|
2021
2341
|
}
|
|
2022
2342
|
return null;
|
|
2023
|
-
}, [placementPreview]);
|
|
2343
|
+
}, [placementPreview, previewStrokeStyle, overlayStrokeWorld, marqueeDashWorld]);
|
|
2024
2344
|
const eraserPreviewElements = react.useMemo(() => {
|
|
2025
2345
|
if (eraserPreviewItems.length === 0) return null;
|
|
2026
2346
|
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: eraserPreviewItems.map((it) => {
|
|
@@ -2041,62 +2361,74 @@ function NativeInteractionOverlay({
|
|
|
2041
2361
|
}, [eraserPreviewItems]);
|
|
2042
2362
|
const eraserTrailElements = react.useMemo(() => {
|
|
2043
2363
|
if (!eraserTrail || eraserTrail.length < 1) return null;
|
|
2044
|
-
const
|
|
2045
|
-
|
|
2046
|
-
|
|
2364
|
+
const now = Date.now();
|
|
2365
|
+
const alive = freshTimedTrailPoints(eraserTrail, now, ERASER_TRAIL_MAX_AGE_MS);
|
|
2366
|
+
if (alive.length === 0) return null;
|
|
2367
|
+
const d = pointsToSmoothPathD(alive);
|
|
2368
|
+
const newest = alive[alive.length - 1];
|
|
2369
|
+
const headOpacity = timedTrailHeadOpacity(newest, now, ERASER_TRAIL_MAX_AGE_MS);
|
|
2370
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2371
|
+
alive.length >= 2 && d ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2372
|
+
reactNativeSkia.Path,
|
|
2373
|
+
{
|
|
2374
|
+
path: d,
|
|
2375
|
+
color: colorWithOpacity(ERASER_TINT, ERASER_TINT_OPACITY),
|
|
2376
|
+
style: "stroke",
|
|
2377
|
+
strokeWidth: Math.max(3.5, OVERLAY_STROKE_PX) / z,
|
|
2378
|
+
strokeCap: "round",
|
|
2379
|
+
strokeJoin: "round",
|
|
2380
|
+
antiAlias: true
|
|
2381
|
+
}
|
|
2382
|
+
) : null,
|
|
2383
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2047
2384
|
reactNativeSkia.Circle,
|
|
2048
2385
|
{
|
|
2049
|
-
cx:
|
|
2050
|
-
cy:
|
|
2386
|
+
cx: newest?.x ?? alive[0]?.x ?? 0,
|
|
2387
|
+
cy: newest?.y ?? alive[0]?.y ?? 0,
|
|
2051
2388
|
r: Math.max(5 / z, 3),
|
|
2052
|
-
color:
|
|
2389
|
+
color: colorWithOpacity(ERASER_TINT, headOpacity),
|
|
2053
2390
|
style: "fill",
|
|
2054
2391
|
antiAlias: true
|
|
2055
2392
|
}
|
|
2056
|
-
)
|
|
2057
|
-
|
|
2058
|
-
reactNativeSkia.Path,
|
|
2059
|
-
{
|
|
2060
|
-
path: d,
|
|
2061
|
-
color: "#cbd5e1",
|
|
2062
|
-
style: "stroke",
|
|
2063
|
-
strokeWidth: Math.max(3.5 / z, overlayStrokePx),
|
|
2064
|
-
strokeCap: "round",
|
|
2065
|
-
strokeJoin: "round",
|
|
2066
|
-
antiAlias: true
|
|
2067
|
-
}
|
|
2068
|
-
);
|
|
2393
|
+
)
|
|
2394
|
+
] });
|
|
2069
2395
|
}, [eraserTrail, z]);
|
|
2070
2396
|
const laserTrailElements = react.useMemo(() => {
|
|
2071
2397
|
if (!laserTrail || laserTrail.length < 1) return null;
|
|
2072
|
-
const
|
|
2073
|
-
|
|
2074
|
-
|
|
2398
|
+
const now = Date.now();
|
|
2399
|
+
const alive = freshTimedTrailPoints(laserTrail, now, LASER_TRAIL_MAX_AGE_MS);
|
|
2400
|
+
if (alive.length === 0) return null;
|
|
2401
|
+
const d = pointsToSmoothPathD(alive);
|
|
2402
|
+
const newest = alive[alive.length - 1];
|
|
2403
|
+
const headOpacity = timedTrailHeadOpacity(newest, now, LASER_TRAIL_MAX_AGE_MS);
|
|
2404
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2405
|
+
alive.length >= 2 && d ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2406
|
+
reactNativeSkia.Path,
|
|
2407
|
+
{
|
|
2408
|
+
path: d,
|
|
2409
|
+
color: colorWithOpacity(LASER_TINT, LASER_TINT_OPACITY),
|
|
2410
|
+
style: "stroke",
|
|
2411
|
+
strokeWidth: Math.max(4, OVERLAY_STROKE_PX) / z,
|
|
2412
|
+
strokeCap: "round",
|
|
2413
|
+
strokeJoin: "round",
|
|
2414
|
+
antiAlias: true
|
|
2415
|
+
}
|
|
2416
|
+
) : null,
|
|
2417
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2075
2418
|
reactNativeSkia.Circle,
|
|
2076
2419
|
{
|
|
2077
|
-
cx:
|
|
2078
|
-
cy:
|
|
2420
|
+
cx: newest?.x ?? alive[0]?.x ?? 0,
|
|
2421
|
+
cy: newest?.y ?? alive[0]?.y ?? 0,
|
|
2079
2422
|
r: Math.max(5 / z, 3),
|
|
2080
|
-
color:
|
|
2423
|
+
color: colorWithOpacity(LASER_TINT, headOpacity),
|
|
2081
2424
|
style: "fill",
|
|
2082
2425
|
antiAlias: true
|
|
2083
2426
|
}
|
|
2084
|
-
)
|
|
2085
|
-
|
|
2086
|
-
reactNativeSkia.Path,
|
|
2087
|
-
{
|
|
2088
|
-
path: d,
|
|
2089
|
-
color: "#f43f5e",
|
|
2090
|
-
style: "stroke",
|
|
2091
|
-
strokeWidth: Math.max(4 / z, overlayStrokePx),
|
|
2092
|
-
strokeCap: "round",
|
|
2093
|
-
strokeJoin: "round",
|
|
2094
|
-
antiAlias: true
|
|
2095
|
-
}
|
|
2096
|
-
);
|
|
2427
|
+
)
|
|
2428
|
+
] });
|
|
2097
2429
|
}, [laserTrail, z]);
|
|
2098
2430
|
if (width <= 0 || height <= 0) return null;
|
|
2099
|
-
return /* @__PURE__ */ jsxRuntime.
|
|
2431
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2100
2432
|
reactNativeSkia.Canvas,
|
|
2101
2433
|
{
|
|
2102
2434
|
style: {
|
|
@@ -2107,13 +2439,22 @@ function NativeInteractionOverlay({
|
|
|
2107
2439
|
height
|
|
2108
2440
|
},
|
|
2109
2441
|
pointerEvents: "none",
|
|
2110
|
-
children:
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2442
|
+
children: [
|
|
2443
|
+
/* @__PURE__ */ jsxRuntime.jsxs(reactNativeSkia.Group, { transform: camTransform, children: [
|
|
2444
|
+
previewElements,
|
|
2445
|
+
laserTrailElements,
|
|
2446
|
+
eraserTrailElements,
|
|
2447
|
+
eraserPreviewElements,
|
|
2448
|
+
selectionElements
|
|
2449
|
+
] }),
|
|
2450
|
+
toolCursor ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2451
|
+
NativeToolCursorRenderer,
|
|
2452
|
+
{
|
|
2453
|
+
cursor: toolCursor.cursor,
|
|
2454
|
+
point: toolCursor.point
|
|
2455
|
+
}
|
|
2456
|
+
) : null
|
|
2457
|
+
]
|
|
2117
2458
|
}
|
|
2118
2459
|
);
|
|
2119
2460
|
}
|
|
@@ -2239,6 +2580,383 @@ function NativeSceneRenderer({
|
|
|
2239
2580
|
if (width <= 0 || height <= 0) return null;
|
|
2240
2581
|
return /* @__PURE__ */ jsxRuntime.jsx(reactNativeSkia.Canvas, { style: { width, height }, children: /* @__PURE__ */ jsxRuntime.jsx(reactNativeSkia.Group, { transform: cameraTransform, children: visible.map((item) => /* @__PURE__ */ jsxRuntime.jsx(MemoShape, { item }, item.id)) }) });
|
|
2241
2582
|
}
|
|
2583
|
+
|
|
2584
|
+
// src/native/native-style-inspector-values.ts
|
|
2585
|
+
var NATIVE_STYLE_PALETTE = [
|
|
2586
|
+
{ name: "black", hex: "#1d1d1d" },
|
|
2587
|
+
{ name: "grey", hex: "#9fa8b2" },
|
|
2588
|
+
{ name: "light-violet", hex: "#e085f4" },
|
|
2589
|
+
{ name: "violet", hex: "#ae3ec9" },
|
|
2590
|
+
{ name: "blue", hex: "#4263eb" },
|
|
2591
|
+
{ name: "light-blue", hex: "#4dabf7" },
|
|
2592
|
+
{ name: "yellow", hex: "#ffc078" },
|
|
2593
|
+
{ name: "orange", hex: "#f76707" },
|
|
2594
|
+
{ name: "green", hex: "#099268" },
|
|
2595
|
+
{ name: "light-green", hex: "#40c057" },
|
|
2596
|
+
{ name: "light-red", hex: "#ff8787" },
|
|
2597
|
+
{ name: "red", hex: "#e03131" }
|
|
2598
|
+
];
|
|
2599
|
+
function normalizeNativeStyleHex(stroke) {
|
|
2600
|
+
if (stroke && /^#[0-9A-Fa-f]{6}$/.test(stroke)) return stroke;
|
|
2601
|
+
return "#1d1d1d";
|
|
2602
|
+
}
|
|
2603
|
+
function nativeStyleColorWithOpacity(hex, opacity) {
|
|
2604
|
+
const alpha = opacity ?? 1;
|
|
2605
|
+
if (alpha >= 1) return hex;
|
|
2606
|
+
const r = Number.parseInt(hex.slice(1, 3), 16);
|
|
2607
|
+
const g = Number.parseInt(hex.slice(3, 5), 16);
|
|
2608
|
+
const b = Number.parseInt(hex.slice(5, 7), 16);
|
|
2609
|
+
return `rgba(${r},${g},${b},${alpha})`;
|
|
2610
|
+
}
|
|
2611
|
+
function hexesEqual(a, b) {
|
|
2612
|
+
return a.toLowerCase() === b.toLowerCase();
|
|
2613
|
+
}
|
|
2614
|
+
function DashPreview({
|
|
2615
|
+
color,
|
|
2616
|
+
width,
|
|
2617
|
+
dashed = false
|
|
2618
|
+
}) {
|
|
2619
|
+
const strokeHeight = Math.max(3, Math.min(6, width));
|
|
2620
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles.dashPreviewTrack, children: [
|
|
2621
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2622
|
+
reactNative.View,
|
|
2623
|
+
{
|
|
2624
|
+
style: [
|
|
2625
|
+
styles.dashPreviewStroke,
|
|
2626
|
+
{
|
|
2627
|
+
width: dashed ? 11 : 26,
|
|
2628
|
+
height: strokeHeight,
|
|
2629
|
+
borderRadius: strokeHeight / 2,
|
|
2630
|
+
backgroundColor: color
|
|
2631
|
+
}
|
|
2632
|
+
]
|
|
2633
|
+
}
|
|
2634
|
+
),
|
|
2635
|
+
dashed ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2636
|
+
reactNative.View,
|
|
2637
|
+
{
|
|
2638
|
+
style: [
|
|
2639
|
+
styles.dashPreviewStroke,
|
|
2640
|
+
{
|
|
2641
|
+
width: 11,
|
|
2642
|
+
height: strokeHeight,
|
|
2643
|
+
borderRadius: strokeHeight / 2,
|
|
2644
|
+
backgroundColor: color
|
|
2645
|
+
}
|
|
2646
|
+
]
|
|
2647
|
+
}
|
|
2648
|
+
) : null
|
|
2649
|
+
] });
|
|
2650
|
+
}
|
|
2651
|
+
function clampValue(value, min, max) {
|
|
2652
|
+
return Math.min(max, Math.max(min, value));
|
|
2653
|
+
}
|
|
2654
|
+
function RangeControl({
|
|
2655
|
+
value,
|
|
2656
|
+
min,
|
|
2657
|
+
max,
|
|
2658
|
+
onChange,
|
|
2659
|
+
valueLabel
|
|
2660
|
+
}) {
|
|
2661
|
+
const [trackWidth, setTrackWidth] = react.useState(1);
|
|
2662
|
+
const normalized = (clampValue(value, min, max) - min) / (max - min);
|
|
2663
|
+
const updateFromX = react.useCallback(
|
|
2664
|
+
(x) => {
|
|
2665
|
+
const next = min + clampValue(x / trackWidth, 0, 1) * (max - min);
|
|
2666
|
+
onChange(Math.round(next));
|
|
2667
|
+
},
|
|
2668
|
+
[max, min, onChange, trackWidth]
|
|
2669
|
+
);
|
|
2670
|
+
const panResponder = react.useMemo(
|
|
2671
|
+
() => reactNative.PanResponder.create({
|
|
2672
|
+
onMoveShouldSetPanResponder: () => true,
|
|
2673
|
+
onStartShouldSetPanResponder: () => true,
|
|
2674
|
+
onPanResponderGrant: (event) => {
|
|
2675
|
+
updateFromX(event.nativeEvent.locationX);
|
|
2676
|
+
},
|
|
2677
|
+
onPanResponderMove: (event) => {
|
|
2678
|
+
updateFromX(event.nativeEvent.locationX);
|
|
2679
|
+
}
|
|
2680
|
+
}),
|
|
2681
|
+
[updateFromX]
|
|
2682
|
+
);
|
|
2683
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles.rangeRow, children: [
|
|
2684
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2685
|
+
reactNative.View,
|
|
2686
|
+
{
|
|
2687
|
+
style: styles.rangeTrack,
|
|
2688
|
+
onLayout: (event) => setTrackWidth(event.nativeEvent.layout.width),
|
|
2689
|
+
...panResponder.panHandlers,
|
|
2690
|
+
children: [
|
|
2691
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles.rangeBase }),
|
|
2692
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [styles.rangeFill, { width: `${normalized * 100}%` }] }),
|
|
2693
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [styles.rangeThumb, { left: `${normalized * 100}%` }] })
|
|
2694
|
+
]
|
|
2695
|
+
}
|
|
2696
|
+
),
|
|
2697
|
+
valueLabel ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.rangeValue, children: valueLabel }) : null
|
|
2698
|
+
] });
|
|
2699
|
+
}
|
|
2700
|
+
function InspectorSection({
|
|
2701
|
+
label,
|
|
2702
|
+
children
|
|
2703
|
+
}) {
|
|
2704
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles.section, children: [
|
|
2705
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.sectionLabel, children: label }),
|
|
2706
|
+
children
|
|
2707
|
+
] });
|
|
2708
|
+
}
|
|
2709
|
+
function SegmentControl({
|
|
2710
|
+
segments,
|
|
2711
|
+
value,
|
|
2712
|
+
onChange
|
|
2713
|
+
}) {
|
|
2714
|
+
return /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles.segmentGroup, children: segments.map((segment) => {
|
|
2715
|
+
const selected = segment.value === value;
|
|
2716
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2717
|
+
reactNative.Pressable,
|
|
2718
|
+
{
|
|
2719
|
+
accessibilityRole: "button",
|
|
2720
|
+
accessibilityState: { selected },
|
|
2721
|
+
accessibilityLabel: segment.label,
|
|
2722
|
+
onPress: () => onChange(segment.value),
|
|
2723
|
+
style: [styles.segment, selected ? styles.segmentSelected : null],
|
|
2724
|
+
children: [
|
|
2725
|
+
segment.preview,
|
|
2726
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2727
|
+
reactNative.Text,
|
|
2728
|
+
{
|
|
2729
|
+
style: [
|
|
2730
|
+
styles.segmentLabel,
|
|
2731
|
+
selected ? styles.segmentLabelSelected : null
|
|
2732
|
+
],
|
|
2733
|
+
children: segment.label
|
|
2734
|
+
}
|
|
2735
|
+
)
|
|
2736
|
+
]
|
|
2737
|
+
},
|
|
2738
|
+
String(segment.value)
|
|
2739
|
+
);
|
|
2740
|
+
}) });
|
|
2741
|
+
}
|
|
2742
|
+
function NativeVectorStyleInspector({
|
|
2743
|
+
toolId,
|
|
2744
|
+
value,
|
|
2745
|
+
onChange,
|
|
2746
|
+
style
|
|
2747
|
+
}) {
|
|
2748
|
+
const hex = normalizeNativeStyleHex(value.stroke);
|
|
2749
|
+
const opacity = toolId === "marker" ? value.strokeOpacity ?? 0.5 : void 0;
|
|
2750
|
+
const dashSegments = [
|
|
2751
|
+
{
|
|
2752
|
+
value: "solid",
|
|
2753
|
+
label: "Cont\xEDnuo",
|
|
2754
|
+
preview: /* @__PURE__ */ jsxRuntime.jsx(DashPreview, { color: "#18181b", width: 4 })
|
|
2755
|
+
},
|
|
2756
|
+
{
|
|
2757
|
+
value: "dashed",
|
|
2758
|
+
label: "Tracejado",
|
|
2759
|
+
preview: /* @__PURE__ */ jsxRuntime.jsx(DashPreview, { color: "#18181b", width: 4, dashed: true })
|
|
2760
|
+
}
|
|
2761
|
+
];
|
|
2762
|
+
const opacityPercent = Math.round((opacity ?? 1) * 100);
|
|
2763
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2764
|
+
reactNative.View,
|
|
2765
|
+
{
|
|
2766
|
+
pointerEvents: "auto",
|
|
2767
|
+
style: [styles.shell, style],
|
|
2768
|
+
accessibilityRole: "summary",
|
|
2769
|
+
accessibilityLabel: toolId === "marker" ? "Configura\xE7\xF5es do marcador" : "Configura\xE7\xF5es da caneta",
|
|
2770
|
+
children: [
|
|
2771
|
+
/* @__PURE__ */ jsxRuntime.jsx(InspectorSection, { label: "Cor", children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles.palette, children: NATIVE_STYLE_PALETTE.map((color) => {
|
|
2772
|
+
const selected = hexesEqual(color.hex, hex);
|
|
2773
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2774
|
+
reactNative.Pressable,
|
|
2775
|
+
{
|
|
2776
|
+
accessibilityRole: "button",
|
|
2777
|
+
accessibilityState: { selected },
|
|
2778
|
+
accessibilityLabel: color.name,
|
|
2779
|
+
onPress: () => onChange({ stroke: color.hex }),
|
|
2780
|
+
style: [
|
|
2781
|
+
styles.swatch,
|
|
2782
|
+
{
|
|
2783
|
+
backgroundColor: color.hex,
|
|
2784
|
+
borderWidth: selected ? 2 : 1,
|
|
2785
|
+
transform: [{ scale: selected ? 1.08 : 1 }],
|
|
2786
|
+
shadowOpacity: selected ? 0.08 : 0
|
|
2787
|
+
}
|
|
2788
|
+
]
|
|
2789
|
+
},
|
|
2790
|
+
color.name
|
|
2791
|
+
);
|
|
2792
|
+
}) }) }),
|
|
2793
|
+
/* @__PURE__ */ jsxRuntime.jsx(InspectorSection, { label: "Grossura", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2794
|
+
RangeControl,
|
|
2795
|
+
{
|
|
2796
|
+
value: value.strokeWidth,
|
|
2797
|
+
min: 1,
|
|
2798
|
+
max: 48,
|
|
2799
|
+
onChange: (strokeWidth) => onChange({ strokeWidth })
|
|
2800
|
+
}
|
|
2801
|
+
) }),
|
|
2802
|
+
toolId === "draw" ? /* @__PURE__ */ jsxRuntime.jsx(InspectorSection, { label: "Tra\xE7o", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2803
|
+
SegmentControl,
|
|
2804
|
+
{
|
|
2805
|
+
segments: dashSegments,
|
|
2806
|
+
value: value.strokeDash === "dashed" ? "dashed" : "solid",
|
|
2807
|
+
onChange: (strokeDash) => onChange({ strokeDash })
|
|
2808
|
+
}
|
|
2809
|
+
) }) : /* @__PURE__ */ jsxRuntime.jsx(InspectorSection, { label: "Opacidade", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2810
|
+
RangeControl,
|
|
2811
|
+
{
|
|
2812
|
+
value: opacityPercent,
|
|
2813
|
+
min: 10,
|
|
2814
|
+
max: 100,
|
|
2815
|
+
valueLabel: `${opacityPercent}%`,
|
|
2816
|
+
onChange: (nextOpacity) => onChange({ strokeOpacity: nextOpacity / 100 })
|
|
2817
|
+
}
|
|
2818
|
+
) })
|
|
2819
|
+
]
|
|
2820
|
+
}
|
|
2821
|
+
);
|
|
2822
|
+
}
|
|
2823
|
+
var styles = reactNative.StyleSheet.create({
|
|
2824
|
+
shell: {
|
|
2825
|
+
minWidth: 240,
|
|
2826
|
+
paddingHorizontal: 14,
|
|
2827
|
+
paddingVertical: 12,
|
|
2828
|
+
borderRadius: 10,
|
|
2829
|
+
borderWidth: 1,
|
|
2830
|
+
borderColor: "rgba(0,0,0,0.1)",
|
|
2831
|
+
backgroundColor: "rgba(255,255,255,0.97)",
|
|
2832
|
+
shadowColor: "#000000",
|
|
2833
|
+
shadowOpacity: 0.06,
|
|
2834
|
+
shadowRadius: 16,
|
|
2835
|
+
shadowOffset: { width: 0, height: 4 },
|
|
2836
|
+
gap: 10
|
|
2837
|
+
},
|
|
2838
|
+
section: {
|
|
2839
|
+
gap: 6
|
|
2840
|
+
},
|
|
2841
|
+
sectionLabel: {
|
|
2842
|
+
fontSize: 11,
|
|
2843
|
+
fontWeight: "600",
|
|
2844
|
+
color: "#52525b",
|
|
2845
|
+
textTransform: "uppercase",
|
|
2846
|
+
letterSpacing: 0.22
|
|
2847
|
+
},
|
|
2848
|
+
palette: {
|
|
2849
|
+
flexDirection: "row",
|
|
2850
|
+
flexWrap: "wrap",
|
|
2851
|
+
columnGap: 6,
|
|
2852
|
+
rowGap: 6,
|
|
2853
|
+
maxWidth: 174
|
|
2854
|
+
},
|
|
2855
|
+
swatch: {
|
|
2856
|
+
width: 24,
|
|
2857
|
+
height: 24,
|
|
2858
|
+
borderRadius: 12,
|
|
2859
|
+
borderColor: "rgba(0,0,0,0.12)",
|
|
2860
|
+
shadowColor: "#000000",
|
|
2861
|
+
shadowRadius: 2,
|
|
2862
|
+
shadowOffset: { width: 0, height: 1 }
|
|
2863
|
+
},
|
|
2864
|
+
rangeRow: {
|
|
2865
|
+
minHeight: 28,
|
|
2866
|
+
flexDirection: "row",
|
|
2867
|
+
alignItems: "center",
|
|
2868
|
+
gap: 8
|
|
2869
|
+
},
|
|
2870
|
+
rangeTrack: {
|
|
2871
|
+
position: "relative",
|
|
2872
|
+
flex: 1,
|
|
2873
|
+
height: 28,
|
|
2874
|
+
justifyContent: "center"
|
|
2875
|
+
},
|
|
2876
|
+
rangeBase: {
|
|
2877
|
+
position: "absolute",
|
|
2878
|
+
left: 0,
|
|
2879
|
+
right: 0,
|
|
2880
|
+
height: 3,
|
|
2881
|
+
borderRadius: 2,
|
|
2882
|
+
backgroundColor: "rgba(24,24,27,0.12)"
|
|
2883
|
+
},
|
|
2884
|
+
rangeFill: {
|
|
2885
|
+
position: "absolute",
|
|
2886
|
+
left: 0,
|
|
2887
|
+
height: 3,
|
|
2888
|
+
borderRadius: 2,
|
|
2889
|
+
backgroundColor: "#18181b"
|
|
2890
|
+
},
|
|
2891
|
+
rangeThumb: {
|
|
2892
|
+
position: "absolute",
|
|
2893
|
+
width: 18,
|
|
2894
|
+
height: 18,
|
|
2895
|
+
marginLeft: -9,
|
|
2896
|
+
borderRadius: 9,
|
|
2897
|
+
borderWidth: 2,
|
|
2898
|
+
borderColor: "#18181b",
|
|
2899
|
+
backgroundColor: "#ffffff",
|
|
2900
|
+
shadowColor: "#000000",
|
|
2901
|
+
shadowOpacity: 0.12,
|
|
2902
|
+
shadowRadius: 3,
|
|
2903
|
+
shadowOffset: { width: 0, height: 1 }
|
|
2904
|
+
},
|
|
2905
|
+
rangeValue: {
|
|
2906
|
+
minWidth: 34,
|
|
2907
|
+
textAlign: "right",
|
|
2908
|
+
fontSize: 11,
|
|
2909
|
+
fontWeight: "500",
|
|
2910
|
+
color: "#71717a"
|
|
2911
|
+
},
|
|
2912
|
+
segmentGroup: {
|
|
2913
|
+
flexDirection: "row",
|
|
2914
|
+
alignItems: "center",
|
|
2915
|
+
gap: 3,
|
|
2916
|
+
padding: 3,
|
|
2917
|
+
borderRadius: 8,
|
|
2918
|
+
backgroundColor: "rgba(24,24,27,0.06)"
|
|
2919
|
+
},
|
|
2920
|
+
segment: {
|
|
2921
|
+
flex: 1,
|
|
2922
|
+
minWidth: 96,
|
|
2923
|
+
minHeight: 32,
|
|
2924
|
+
flexDirection: "row",
|
|
2925
|
+
alignItems: "center",
|
|
2926
|
+
justifyContent: "center",
|
|
2927
|
+
gap: 6,
|
|
2928
|
+
paddingHorizontal: 8,
|
|
2929
|
+
paddingVertical: 5,
|
|
2930
|
+
borderRadius: 6
|
|
2931
|
+
},
|
|
2932
|
+
segmentSelected: {
|
|
2933
|
+
backgroundColor: "#ffffff",
|
|
2934
|
+
shadowColor: "#000000",
|
|
2935
|
+
shadowOpacity: 0.1,
|
|
2936
|
+
shadowRadius: 2,
|
|
2937
|
+
shadowOffset: { width: 0, height: 1 }
|
|
2938
|
+
},
|
|
2939
|
+
segmentLabel: {
|
|
2940
|
+
fontSize: 11,
|
|
2941
|
+
fontWeight: "600",
|
|
2942
|
+
color: "#71717a",
|
|
2943
|
+
flexShrink: 0
|
|
2944
|
+
},
|
|
2945
|
+
segmentLabelSelected: {
|
|
2946
|
+
color: "#18181b"
|
|
2947
|
+
},
|
|
2948
|
+
dashPreviewTrack: {
|
|
2949
|
+
width: 26,
|
|
2950
|
+
height: 6,
|
|
2951
|
+
flexDirection: "row",
|
|
2952
|
+
alignItems: "center",
|
|
2953
|
+
justifyContent: "center",
|
|
2954
|
+
gap: 3
|
|
2955
|
+
},
|
|
2956
|
+
dashPreviewStroke: {
|
|
2957
|
+
flexShrink: 0
|
|
2958
|
+
}
|
|
2959
|
+
});
|
|
2242
2960
|
var DEFAULT_NATIVE_OVERFLOW_TOOL_IDS = [
|
|
2243
2961
|
"rect",
|
|
2244
2962
|
"ellipse",
|
|
@@ -2370,7 +3088,7 @@ function NativeVectorToolbar({
|
|
|
2370
3088
|
reactNative.View,
|
|
2371
3089
|
{
|
|
2372
3090
|
accessibilityLabel,
|
|
2373
|
-
style: [
|
|
3091
|
+
style: [styles2.shell, style],
|
|
2374
3092
|
pointerEvents: "box-none",
|
|
2375
3093
|
children: [
|
|
2376
3094
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -2379,8 +3097,8 @@ function NativeVectorToolbar({
|
|
|
2379
3097
|
horizontal: true,
|
|
2380
3098
|
showsHorizontalScrollIndicator: false,
|
|
2381
3099
|
contentContainerStyle: [
|
|
2382
|
-
|
|
2383
|
-
density === "comfortable" ?
|
|
3100
|
+
styles2.content,
|
|
3101
|
+
density === "comfortable" ? styles2.comfortableContent : void 0,
|
|
2384
3102
|
contentContainerStyle
|
|
2385
3103
|
],
|
|
2386
3104
|
children: [
|
|
@@ -2397,21 +3115,21 @@ function NativeVectorToolbar({
|
|
|
2397
3115
|
disabled: toolLockDisabled,
|
|
2398
3116
|
onPress: toggleToolLock,
|
|
2399
3117
|
style: ({ pressed }) => [
|
|
2400
|
-
|
|
2401
|
-
density === "comfortable" ?
|
|
2402
|
-
toolLocked ?
|
|
2403
|
-
pressed && !toolLockDisabled ?
|
|
2404
|
-
toolLockDisabled ?
|
|
3118
|
+
styles2.toolButton,
|
|
3119
|
+
density === "comfortable" ? styles2.comfortableToolButton : void 0,
|
|
3120
|
+
toolLocked ? styles2.activeToolButton : void 0,
|
|
3121
|
+
pressed && !toolLockDisabled ? styles2.pressedToolButton : void 0,
|
|
3122
|
+
toolLockDisabled ? styles2.disabledToolButton : void 0
|
|
2405
3123
|
],
|
|
2406
3124
|
children: renderToolLockIcon?.({
|
|
2407
3125
|
locked: toolLocked,
|
|
2408
3126
|
disabled: toolLockDisabled,
|
|
2409
3127
|
foregroundColor: "#18181b",
|
|
2410
3128
|
onToggle: toggleToolLock
|
|
2411
|
-
}) ?? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style:
|
|
3129
|
+
}) ?? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles2.lockGlyph, children: toolLocked ? "L" : "U" })
|
|
2412
3130
|
}
|
|
2413
3131
|
),
|
|
2414
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style:
|
|
3132
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles2.toolLockDivider })
|
|
2415
3133
|
] }) : null,
|
|
2416
3134
|
toolbarTools.map(
|
|
2417
3135
|
(tool) => renderNativeToolButton({
|
|
@@ -2429,7 +3147,7 @@ function NativeVectorToolbar({
|
|
|
2429
3147
|
renderToolButton
|
|
2430
3148
|
})
|
|
2431
3149
|
),
|
|
2432
|
-
showOverflowMenu ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style:
|
|
3150
|
+
showOverflowMenu ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles2.overflowSpacer }) : null,
|
|
2433
3151
|
showOverflowMenu ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2434
3152
|
reactNative.Pressable,
|
|
2435
3153
|
{
|
|
@@ -2443,27 +3161,27 @@ function NativeVectorToolbar({
|
|
|
2443
3161
|
disabled,
|
|
2444
3162
|
onPress: toggleOverflow,
|
|
2445
3163
|
style: ({ pressed }) => [
|
|
2446
|
-
|
|
2447
|
-
overflowOpen || activeOverflowTool ?
|
|
2448
|
-
pressed && !disabled ?
|
|
2449
|
-
disabled ?
|
|
3164
|
+
styles2.overflowTrigger,
|
|
3165
|
+
overflowOpen || activeOverflowTool ? styles2.activeToolButton : void 0,
|
|
3166
|
+
pressed && !disabled ? styles2.pressedToolButton : void 0,
|
|
3167
|
+
disabled ? styles2.disabledToolButton : void 0
|
|
2450
3168
|
],
|
|
2451
3169
|
children: [
|
|
2452
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style:
|
|
3170
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles2.iconSlot, children: activeOverflowTool ? renderToolIcon?.({
|
|
2453
3171
|
tool: activeOverflowTool,
|
|
2454
3172
|
selected: true,
|
|
2455
3173
|
disabled,
|
|
2456
3174
|
foregroundColor: "#18181b",
|
|
2457
3175
|
onSelect: () => onChange(activeOverflowTool.id)
|
|
2458
|
-
}) ?? renderNativeToolFallback(activeOverflowTool, "#18181b") : renderOverflowIcon?.(overflowRenderInput) ?? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style:
|
|
2459
|
-
renderOverflowChevronIcon?.(overflowRenderInput) ?? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style:
|
|
3176
|
+
}) ?? renderNativeToolFallback(activeOverflowTool, "#18181b") : renderOverflowIcon?.(overflowRenderInput) ?? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles2.shapesGlyph, children: "S" }) }),
|
|
3177
|
+
renderOverflowChevronIcon?.(overflowRenderInput) ?? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles2.chevronGlyph, children: overflowOpen ? "^" : "v" })
|
|
2460
3178
|
]
|
|
2461
3179
|
}
|
|
2462
3180
|
) : null
|
|
2463
3181
|
]
|
|
2464
3182
|
}
|
|
2465
3183
|
),
|
|
2466
|
-
overflowOpen && showOverflowMenu ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [
|
|
3184
|
+
overflowOpen && showOverflowMenu ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [styles2.overflowPanel, overflowPanelStyle], children: remainingOverflowTools.map(
|
|
2467
3185
|
(tool) => renderNativeToolButton({
|
|
2468
3186
|
tool,
|
|
2469
3187
|
value,
|
|
@@ -2474,7 +3192,7 @@ function NativeVectorToolbar({
|
|
|
2474
3192
|
disabled,
|
|
2475
3193
|
disabledIds,
|
|
2476
3194
|
density: "compact",
|
|
2477
|
-
toolButtonStyle:
|
|
3195
|
+
toolButtonStyle: styles2.overflowToolButton,
|
|
2478
3196
|
activeToolButtonStyle,
|
|
2479
3197
|
toolLabelStyle,
|
|
2480
3198
|
activeToolLabelStyle,
|
|
@@ -2515,22 +3233,22 @@ function renderNativeToolButton(input) {
|
|
|
2515
3233
|
disabled: toolDisabled,
|
|
2516
3234
|
onPress: onSelect,
|
|
2517
3235
|
style: ({ pressed }) => [
|
|
2518
|
-
|
|
2519
|
-
input.density === "comfortable" ?
|
|
3236
|
+
styles2.toolButton,
|
|
3237
|
+
input.density === "comfortable" ? styles2.comfortableToolButton : void 0,
|
|
2520
3238
|
input.toolButtonStyle,
|
|
2521
|
-
selected ?
|
|
3239
|
+
selected ? styles2.activeToolButton : void 0,
|
|
2522
3240
|
selected ? input.activeToolButtonStyle : void 0,
|
|
2523
|
-
pressed && !toolDisabled ?
|
|
2524
|
-
toolDisabled ?
|
|
3241
|
+
pressed && !toolDisabled ? styles2.pressedToolButton : void 0,
|
|
3242
|
+
toolDisabled ? styles2.disabledToolButton : void 0
|
|
2525
3243
|
],
|
|
2526
3244
|
children: [
|
|
2527
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style:
|
|
3245
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles2.iconSlot, children: icon }),
|
|
2528
3246
|
input.density === "comfortable" ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2529
3247
|
reactNative.Text,
|
|
2530
3248
|
{
|
|
2531
3249
|
numberOfLines: 1,
|
|
2532
3250
|
style: [
|
|
2533
|
-
|
|
3251
|
+
styles2.toolLabel,
|
|
2534
3252
|
{ color: foregroundColor },
|
|
2535
3253
|
input.toolLabelStyle,
|
|
2536
3254
|
selected ? input.activeToolLabelStyle : void 0
|
|
@@ -2544,9 +3262,9 @@ function renderNativeToolButton(input) {
|
|
|
2544
3262
|
);
|
|
2545
3263
|
}
|
|
2546
3264
|
function renderNativeToolFallback(tool, foregroundColor, toolLabelStyle) {
|
|
2547
|
-
return /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [
|
|
3265
|
+
return /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles2.shortLabel, { color: foregroundColor }, toolLabelStyle], children: tool.shortLabel ?? tool.label.slice(0, 1).toUpperCase() });
|
|
2548
3266
|
}
|
|
2549
|
-
var
|
|
3267
|
+
var styles2 = reactNative.StyleSheet.create({
|
|
2550
3268
|
shell: {
|
|
2551
3269
|
borderRadius: 8,
|
|
2552
3270
|
borderWidth: reactNative.StyleSheet.hairlineWidth,
|
|
@@ -2868,12 +3586,56 @@ function collectEraserTargetsAtWorldPoint(items, worldX, worldY, options) {
|
|
|
2868
3586
|
}
|
|
2869
3587
|
return ids;
|
|
2870
3588
|
}
|
|
3589
|
+
|
|
3590
|
+
// src/native/native-tool-cursors.ts
|
|
3591
|
+
var ICON_SIZE = 24;
|
|
3592
|
+
var CENTER_HOTSPOT = { x: 12, y: 12 };
|
|
3593
|
+
function nativeCursorForVectorToolId(toolId) {
|
|
3594
|
+
switch (toolId) {
|
|
3595
|
+
case "rect":
|
|
3596
|
+
case "ellipse":
|
|
3597
|
+
case "architectural-cloud":
|
|
3598
|
+
case "line":
|
|
3599
|
+
case "arrow":
|
|
3600
|
+
case "laser":
|
|
3601
|
+
case "image":
|
|
3602
|
+
return { kind: "crosshair", size: ICON_SIZE, hotspot: CENTER_HOTSPOT };
|
|
3603
|
+
case "draw":
|
|
3604
|
+
return { kind: "draw", size: ICON_SIZE, hotspot: { x: 4, y: 18 } };
|
|
3605
|
+
case "marker":
|
|
3606
|
+
return { kind: "marker", size: ICON_SIZE, hotspot: { x: 11, y: 14 } };
|
|
3607
|
+
case "eraser":
|
|
3608
|
+
return { kind: "eraser", size: ICON_SIZE, hotspot: { x: 12, y: 14 } };
|
|
3609
|
+
case "text":
|
|
3610
|
+
return { kind: "text", size: ICON_SIZE, hotspot: CENTER_HOTSPOT };
|
|
3611
|
+
default:
|
|
3612
|
+
return null;
|
|
3613
|
+
}
|
|
3614
|
+
}
|
|
2871
3615
|
var MIN_PLACE_SIZE = 8;
|
|
2872
3616
|
var MIN_ARROW_DRAG_PX = 8;
|
|
2873
3617
|
var TAP_PX = 20;
|
|
3618
|
+
var MARKER_TOOL_STYLE = {
|
|
3619
|
+
stroke: "#fde047",
|
|
3620
|
+
strokeWidth: 16,
|
|
3621
|
+
strokeOpacity: 0.5
|
|
3622
|
+
};
|
|
2874
3623
|
function isPlacementTool(toolId) {
|
|
2875
3624
|
return toolId === "rect" || toolId === "ellipse" || toolId === "architectural-cloud" || toolId === "line" || toolId === "arrow";
|
|
2876
3625
|
}
|
|
3626
|
+
function isDefaultMarkerToolStyle(style) {
|
|
3627
|
+
return style.stroke === MARKER_TOOL_STYLE.stroke && style.strokeWidth === MARKER_TOOL_STYLE.strokeWidth && style.strokeOpacity === MARKER_TOOL_STYLE.strokeOpacity;
|
|
3628
|
+
}
|
|
3629
|
+
function supportsNativeResizeHandles(item) {
|
|
3630
|
+
const k = item?.toolKind;
|
|
3631
|
+
if (k === "rect" || k === "ellipse" || k === "architectural-cloud" || k === "line" || k === "arrow" || k === "image" || k === "text") {
|
|
3632
|
+
return true;
|
|
3633
|
+
}
|
|
3634
|
+
if ((k === "draw" || k === "pencil" || k === "brush" || k === "marker") && item?.pathPointsLocal && item.pathPointsLocal.length > 0) {
|
|
3635
|
+
return true;
|
|
3636
|
+
}
|
|
3637
|
+
return k === "custom" && !!item?.customIntrinsicSize && !!item?.customInnerSvg;
|
|
3638
|
+
}
|
|
2877
3639
|
function placementPreviewForTool(toolId, start, end) {
|
|
2878
3640
|
if (toolId === "rect" || toolId === "ellipse" || toolId === "architectural-cloud") {
|
|
2879
3641
|
return { kind: toolId, rect: rectFromCorners(start, end) };
|
|
@@ -2910,6 +3672,12 @@ function collectIdsInRect(items, marquee) {
|
|
|
2910
3672
|
}
|
|
2911
3673
|
return out;
|
|
2912
3674
|
}
|
|
3675
|
+
function screenPointFromPointerEvent(event) {
|
|
3676
|
+
const nativeEvent = event.nativeEvent;
|
|
3677
|
+
const x = Number.isFinite(nativeEvent.offsetX) ? nativeEvent.offsetX : nativeEvent.x;
|
|
3678
|
+
const y = Number.isFinite(nativeEvent.offsetY) ? nativeEvent.offsetY : nativeEvent.y;
|
|
3679
|
+
return { x, y };
|
|
3680
|
+
}
|
|
2913
3681
|
function fitCameraToWorldRect(camera, viewportW, viewportH, worldRect, padding) {
|
|
2914
3682
|
const r = normalizeRect(worldRect);
|
|
2915
3683
|
if (r.width <= 0 || r.height <= 0 || viewportW <= 0 || viewportH <= 0) return;
|
|
@@ -2936,7 +3704,9 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
|
|
|
2936
3704
|
onItemsChange,
|
|
2937
3705
|
onToolChangeRequest,
|
|
2938
3706
|
onCameraChange,
|
|
2939
|
-
toolbar
|
|
3707
|
+
toolbar,
|
|
3708
|
+
showStyleInspector = false,
|
|
3709
|
+
styleInspectorPlacement = "bottom"
|
|
2940
3710
|
}, ref) {
|
|
2941
3711
|
const [size, setSize] = react.useState({ width: 0, height: 0 });
|
|
2942
3712
|
const cameraRef = react.useRef(null);
|
|
@@ -2962,7 +3732,15 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
|
|
|
2962
3732
|
);
|
|
2963
3733
|
const [eraserTrail, setEraserTrail] = react.useState([]);
|
|
2964
3734
|
const [laserTrail, setLaserTrail] = react.useState([]);
|
|
3735
|
+
const [toolCursorPoint, setToolCursorPoint] = react.useState(null);
|
|
2965
3736
|
const laserClearTimerRef = react.useRef(null);
|
|
3737
|
+
const strokeStyleRef = react.useRef({ ...DEFAULT_STROKE_STYLE });
|
|
3738
|
+
const markerStrokeStyleRef = react.useRef({ ...MARKER_TOOL_STYLE });
|
|
3739
|
+
const styleBeforeMarkerRef = react.useRef({ ...DEFAULT_STROKE_STYLE });
|
|
3740
|
+
const lastToolIdRef = react.useRef(toolId);
|
|
3741
|
+
const [strokeStyleState, setStrokeStyleState] = react.useState({
|
|
3742
|
+
...DEFAULT_STROKE_STYLE
|
|
3743
|
+
});
|
|
2966
3744
|
react.useEffect(
|
|
2967
3745
|
() => () => {
|
|
2968
3746
|
if (laserClearTimerRef.current) {
|
|
@@ -2971,6 +3749,60 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
|
|
|
2971
3749
|
},
|
|
2972
3750
|
[]
|
|
2973
3751
|
);
|
|
3752
|
+
react.useEffect(() => {
|
|
3753
|
+
if (eraserTrail.length === 0 && laserTrail.length === 0) return;
|
|
3754
|
+
const timer = setInterval(() => {
|
|
3755
|
+
const now = Date.now();
|
|
3756
|
+
setEraserTrail(
|
|
3757
|
+
(prev) => freshTimedTrailPoints(prev, now, ERASER_TRAIL_MAX_AGE_MS)
|
|
3758
|
+
);
|
|
3759
|
+
setLaserTrail(
|
|
3760
|
+
(prev) => freshTimedTrailPoints(prev, now, LASER_TRAIL_MAX_AGE_MS)
|
|
3761
|
+
);
|
|
3762
|
+
}, 50);
|
|
3763
|
+
return () => clearInterval(timer);
|
|
3764
|
+
}, [eraserTrail.length, laserTrail.length]);
|
|
3765
|
+
react.useEffect(() => {
|
|
3766
|
+
const previousToolId = lastToolIdRef.current;
|
|
3767
|
+
const current = strokeStyleRef.current;
|
|
3768
|
+
let next = current;
|
|
3769
|
+
if (toolId === "marker") {
|
|
3770
|
+
if (previousToolId !== "marker") {
|
|
3771
|
+
styleBeforeMarkerRef.current = current;
|
|
3772
|
+
}
|
|
3773
|
+
next = markerStrokeStyleRef.current;
|
|
3774
|
+
} else if (previousToolId === "marker") {
|
|
3775
|
+
markerStrokeStyleRef.current = current;
|
|
3776
|
+
const restored = styleBeforeMarkerRef.current;
|
|
3777
|
+
next = {
|
|
3778
|
+
stroke: restored.stroke,
|
|
3779
|
+
strokeWidth: toolId === "draw" && restored.strokeWidth === DEFAULT_STROKE_STYLE.strokeWidth ? 10 : restored.strokeWidth,
|
|
3780
|
+
...restored.strokeDash != null ? { strokeDash: restored.strokeDash } : {}
|
|
3781
|
+
};
|
|
3782
|
+
} else if (toolId === "draw") {
|
|
3783
|
+
next = {
|
|
3784
|
+
...current,
|
|
3785
|
+
strokeWidth: current.strokeWidth === DEFAULT_STROKE_STYLE.strokeWidth ? 10 : current.strokeWidth
|
|
3786
|
+
};
|
|
3787
|
+
} else if (isDefaultMarkerToolStyle(current)) {
|
|
3788
|
+
next = {
|
|
3789
|
+
stroke: DEFAULT_STROKE_STYLE.stroke,
|
|
3790
|
+
strokeWidth: DEFAULT_STROKE_STYLE.strokeWidth,
|
|
3791
|
+
...current.strokeDash != null ? { strokeDash: current.strokeDash } : {}
|
|
3792
|
+
};
|
|
3793
|
+
}
|
|
3794
|
+
strokeStyleRef.current = next;
|
|
3795
|
+
setStrokeStyleState(next);
|
|
3796
|
+
lastToolIdRef.current = toolId;
|
|
3797
|
+
}, [toolId]);
|
|
3798
|
+
const patchCurrentStrokeStyle = react.useCallback((patch) => {
|
|
3799
|
+
const next = { ...strokeStyleRef.current, ...patch };
|
|
3800
|
+
strokeStyleRef.current = next;
|
|
3801
|
+
if (toolIdRef.current === "marker") {
|
|
3802
|
+
markerStrokeStyleRef.current = next;
|
|
3803
|
+
}
|
|
3804
|
+
setStrokeStyleState(next);
|
|
3805
|
+
}, []);
|
|
2974
3806
|
const [eraserPreviewIds, setEraserPreviewIds] = react.useState([]);
|
|
2975
3807
|
const eraserPreviewIdSetRef = react.useRef(/* @__PURE__ */ new Set());
|
|
2976
3808
|
const requestSelectToolAfterUse = react.useCallback(() => {
|
|
@@ -2999,6 +3831,23 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
|
|
|
2999
3831
|
const { width, height } = e.nativeEvent.layout;
|
|
3000
3832
|
setSize({ width, height });
|
|
3001
3833
|
}, []);
|
|
3834
|
+
const updateToolCursorPoint = react.useCallback(
|
|
3835
|
+
(point) => {
|
|
3836
|
+
if (!interactive) return;
|
|
3837
|
+
if (!nativeCursorForVectorToolId(toolIdRef.current)) return;
|
|
3838
|
+
setToolCursorPoint(point);
|
|
3839
|
+
},
|
|
3840
|
+
[interactive]
|
|
3841
|
+
);
|
|
3842
|
+
const hideToolCursor = react.useCallback(() => {
|
|
3843
|
+
setToolCursorPoint(null);
|
|
3844
|
+
}, []);
|
|
3845
|
+
const handlePointerMove = react.useCallback(
|
|
3846
|
+
(event) => {
|
|
3847
|
+
updateToolCursorPoint(screenPointFromPointerEvent(event));
|
|
3848
|
+
},
|
|
3849
|
+
[updateToolCursorPoint]
|
|
3850
|
+
);
|
|
3002
3851
|
const selectedItems = react.useMemo(
|
|
3003
3852
|
() => items.filter((it) => selectedIds.includes(it.id)),
|
|
3004
3853
|
[items, selectedIds]
|
|
@@ -3008,7 +3857,7 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
|
|
|
3008
3857
|
const hidden = new Set(eraserPreviewIds);
|
|
3009
3858
|
return items.filter((it) => !hidden.has(it.id));
|
|
3010
3859
|
}, [items, eraserPreviewIds]);
|
|
3011
|
-
const showResizeHandles = interactive && selectedItems.length === 1 && !selectedItems[0]?.locked;
|
|
3860
|
+
const showResizeHandles = interactive && selectedItems.length === 1 && !selectedItems[0]?.locked && supportsNativeResizeHandles(selectedItems[0]);
|
|
3012
3861
|
const lastPinchDist = react.useRef(null);
|
|
3013
3862
|
const lastPanPoint = react.useRef(null);
|
|
3014
3863
|
const panResponder = react.useMemo(
|
|
@@ -3022,9 +3871,11 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
|
|
|
3022
3871
|
const sx = evt.nativeEvent.locationX;
|
|
3023
3872
|
const sy = evt.nativeEvent.locationY;
|
|
3024
3873
|
if (touches && touches.length >= 2) {
|
|
3874
|
+
hideToolCursor();
|
|
3025
3875
|
dragStateRef.current = { kind: "pan" };
|
|
3026
3876
|
return;
|
|
3027
3877
|
}
|
|
3878
|
+
updateToolCursorPoint({ x: sx, y: sy });
|
|
3028
3879
|
if (!interactive) {
|
|
3029
3880
|
dragStateRef.current = { kind: "pan" };
|
|
3030
3881
|
return;
|
|
@@ -3083,7 +3934,14 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
|
|
|
3083
3934
|
clearTimeout(laserClearTimerRef.current);
|
|
3084
3935
|
laserClearTimerRef.current = null;
|
|
3085
3936
|
}
|
|
3086
|
-
setLaserTrail([{ x: worldX, y: worldY }]);
|
|
3937
|
+
setLaserTrail([{ x: worldX, y: worldY, t: Date.now() }]);
|
|
3938
|
+
} else {
|
|
3939
|
+
setPlacementPreview({
|
|
3940
|
+
kind: "stroke",
|
|
3941
|
+
tool,
|
|
3942
|
+
points: [{ x: worldX, y: worldY }],
|
|
3943
|
+
style: { ...strokeStyleRef.current }
|
|
3944
|
+
});
|
|
3087
3945
|
}
|
|
3088
3946
|
return;
|
|
3089
3947
|
}
|
|
@@ -3091,7 +3949,7 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
|
|
|
3091
3949
|
dragStateRef.current = { kind: "erase" };
|
|
3092
3950
|
eraserPreviewIdSetRef.current = /* @__PURE__ */ new Set();
|
|
3093
3951
|
setEraserPreviewIds([]);
|
|
3094
|
-
setEraserTrail([{ x: worldX, y: worldY }]);
|
|
3952
|
+
setEraserTrail([{ x: worldX, y: worldY, t: Date.now() }]);
|
|
3095
3953
|
const toErase = collectEraserTargetsAtWorldPoint(
|
|
3096
3954
|
itemsRef.current,
|
|
3097
3955
|
worldX,
|
|
@@ -3143,6 +4001,7 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
|
|
|
3143
4001
|
const pageX = evt.nativeEvent.pageX;
|
|
3144
4002
|
const pageY = evt.nativeEvent.pageY;
|
|
3145
4003
|
if (touches && touches.length >= 2) {
|
|
4004
|
+
hideToolCursor();
|
|
3146
4005
|
const t0 = touches[0];
|
|
3147
4006
|
const t1 = touches[1];
|
|
3148
4007
|
if (t0 && t1) {
|
|
@@ -3162,6 +4021,7 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
|
|
|
3162
4021
|
return;
|
|
3163
4022
|
}
|
|
3164
4023
|
lastPinchDist.current = null;
|
|
4024
|
+
updateToolCursorPoint({ x: sx, y: sy });
|
|
3165
4025
|
const { worldX, worldY } = screenToWorld(sx, sy);
|
|
3166
4026
|
const st = dragStateRef.current;
|
|
3167
4027
|
if (st.kind === "pan") {
|
|
@@ -3182,18 +4042,25 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
|
|
|
3182
4042
|
const last = pts[pts.length - 1];
|
|
3183
4043
|
const dx = worldX - (last?.x ?? worldX);
|
|
3184
4044
|
const dy = worldY - (last?.y ?? worldY);
|
|
3185
|
-
|
|
4045
|
+
const shouldAppendPoint = Math.hypot(dx, dy) > 0.5 / cam.zoom;
|
|
4046
|
+
if (shouldAppendPoint) {
|
|
3186
4047
|
pts.push({ x: worldX, y: worldY });
|
|
3187
4048
|
}
|
|
3188
4049
|
if (st.tool === "laser") {
|
|
3189
|
-
|
|
3190
|
-
|
|
3191
|
-
|
|
3192
|
-
|
|
3193
|
-
|
|
3194
|
-
|
|
3195
|
-
|
|
4050
|
+
if (shouldAppendPoint) {
|
|
4051
|
+
setLaserTrail((prev) => [
|
|
4052
|
+
...prev,
|
|
4053
|
+
{ x: worldX, y: worldY, t: Date.now() }
|
|
4054
|
+
]);
|
|
4055
|
+
}
|
|
4056
|
+
return;
|
|
3196
4057
|
}
|
|
4058
|
+
setPlacementPreview({
|
|
4059
|
+
kind: "stroke",
|
|
4060
|
+
tool: st.tool,
|
|
4061
|
+
points: [...pts],
|
|
4062
|
+
style: { ...strokeStyleRef.current }
|
|
4063
|
+
});
|
|
3197
4064
|
return;
|
|
3198
4065
|
}
|
|
3199
4066
|
if (st.kind === "move") {
|
|
@@ -3231,7 +4098,10 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
|
|
|
3231
4098
|
return;
|
|
3232
4099
|
}
|
|
3233
4100
|
if (st.kind === "erase") {
|
|
3234
|
-
setEraserTrail((prev) => [
|
|
4101
|
+
setEraserTrail((prev) => [
|
|
4102
|
+
...prev,
|
|
4103
|
+
{ x: worldX, y: worldY, t: Date.now() }
|
|
4104
|
+
]);
|
|
3235
4105
|
const toErase = collectEraserTargetsAtWorldPoint(
|
|
3236
4106
|
itemsRef.current,
|
|
3237
4107
|
worldX,
|
|
@@ -3257,6 +4127,7 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
|
|
|
3257
4127
|
onPanResponderRelease: (evt) => {
|
|
3258
4128
|
lastPinchDist.current = null;
|
|
3259
4129
|
lastPanPoint.current = null;
|
|
4130
|
+
hideToolCursor();
|
|
3260
4131
|
const st = dragStateRef.current;
|
|
3261
4132
|
if (st.kind === "draw") {
|
|
3262
4133
|
dragStateRef.current = { kind: "idle" };
|
|
@@ -3276,7 +4147,12 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
|
|
|
3276
4147
|
const change = onItemsChangeRef.current;
|
|
3277
4148
|
if (!change) return;
|
|
3278
4149
|
const id = createShapeId();
|
|
3279
|
-
const item = createFreehandStrokeItem(
|
|
4150
|
+
const item = createFreehandStrokeItem(
|
|
4151
|
+
id,
|
|
4152
|
+
st.points,
|
|
4153
|
+
st.tool,
|
|
4154
|
+
strokeStyleRef.current
|
|
4155
|
+
);
|
|
3280
4156
|
if (item) {
|
|
3281
4157
|
change([...itemsRef.current, item]);
|
|
3282
4158
|
}
|
|
@@ -3353,26 +4229,33 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
|
|
|
3353
4229
|
}
|
|
3354
4230
|
}
|
|
3355
4231
|
const id = createShapeId();
|
|
4232
|
+
const style = strokeStyleRef.current;
|
|
3356
4233
|
if (st.tool === "rect") {
|
|
3357
|
-
change([...itemsRef.current, createRectangleItem(id, raw)]);
|
|
4234
|
+
change([...itemsRef.current, createRectangleItem(id, raw, style)]);
|
|
3358
4235
|
onSelectionChangeRef.current?.([id]);
|
|
3359
4236
|
requestSelectToolAfterUse();
|
|
3360
4237
|
return;
|
|
3361
4238
|
}
|
|
3362
4239
|
if (st.tool === "ellipse") {
|
|
3363
|
-
change([...itemsRef.current, createEllipseItem(id, raw)]);
|
|
4240
|
+
change([...itemsRef.current, createEllipseItem(id, raw, style)]);
|
|
3364
4241
|
onSelectionChangeRef.current?.([id]);
|
|
3365
4242
|
requestSelectToolAfterUse();
|
|
3366
4243
|
return;
|
|
3367
4244
|
}
|
|
3368
4245
|
if (st.tool === "architectural-cloud") {
|
|
3369
|
-
change([
|
|
4246
|
+
change([
|
|
4247
|
+
...itemsRef.current,
|
|
4248
|
+
createArchitecturalCloudItem(id, raw, style)
|
|
4249
|
+
]);
|
|
3370
4250
|
onSelectionChangeRef.current?.([id]);
|
|
3371
4251
|
requestSelectToolAfterUse();
|
|
3372
4252
|
return;
|
|
3373
4253
|
}
|
|
3374
4254
|
const line = lineEndpointsToLocal(br, lineStart, lineEnd);
|
|
3375
|
-
change([
|
|
4255
|
+
change([
|
|
4256
|
+
...itemsRef.current,
|
|
4257
|
+
createLineItem(id, br, line, st.tool, style)
|
|
4258
|
+
]);
|
|
3376
4259
|
onSelectionChangeRef.current?.([id]);
|
|
3377
4260
|
requestSelectToolAfterUse();
|
|
3378
4261
|
return;
|
|
@@ -3395,7 +4278,7 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
|
|
|
3395
4278
|
height: 26
|
|
3396
4279
|
},
|
|
3397
4280
|
"Text",
|
|
3398
|
-
|
|
4281
|
+
strokeStyleRef.current,
|
|
3399
4282
|
18
|
|
3400
4283
|
);
|
|
3401
4284
|
change([...itemsRef.current, item]);
|
|
@@ -3428,12 +4311,23 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
|
|
|
3428
4311
|
onPanResponderTerminate: () => {
|
|
3429
4312
|
lastPinchDist.current = null;
|
|
3430
4313
|
lastPanPoint.current = null;
|
|
4314
|
+
hideToolCursor();
|
|
3431
4315
|
dragStateRef.current = { kind: "idle" };
|
|
3432
4316
|
setPlacementPreview(null);
|
|
3433
4317
|
setLaserTrail([]);
|
|
4318
|
+
setEraserTrail([]);
|
|
4319
|
+
setEraserPreviewIds([]);
|
|
4320
|
+
eraserPreviewIdSetRef.current.clear();
|
|
3434
4321
|
}
|
|
3435
4322
|
}),
|
|
3436
|
-
[
|
|
4323
|
+
[
|
|
4324
|
+
screenToWorld,
|
|
4325
|
+
requestRender,
|
|
4326
|
+
requestSelectToolAfterUse,
|
|
4327
|
+
interactive,
|
|
4328
|
+
updateToolCursorPoint,
|
|
4329
|
+
hideToolCursor
|
|
4330
|
+
]
|
|
3437
4331
|
);
|
|
3438
4332
|
react.useImperativeHandle(
|
|
3439
4333
|
ref,
|
|
@@ -3456,11 +4350,17 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
|
|
|
3456
4350
|
}),
|
|
3457
4351
|
[requestRender, size]
|
|
3458
4352
|
);
|
|
4353
|
+
const activeStyleToolId = toolId === "draw" || toolId === "marker" ? toolId : null;
|
|
4354
|
+
const activeToolCursor = nativeCursorForVectorToolId(toolId);
|
|
4355
|
+
const toolCursor = activeToolCursor && toolCursorPoint ? { cursor: activeToolCursor, point: toolCursorPoint } : null;
|
|
3459
4356
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3460
4357
|
reactNative.View,
|
|
3461
4358
|
{
|
|
3462
4359
|
style: { flex: 1, overflow: "hidden" },
|
|
3463
4360
|
onLayout,
|
|
4361
|
+
onPointerMove: handlePointerMove,
|
|
4362
|
+
onPointerEnter: handlePointerMove,
|
|
4363
|
+
onPointerLeave: hideToolCursor,
|
|
3464
4364
|
...panResponder.panHandlers,
|
|
3465
4365
|
children: size.width > 0 && size.height > 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3466
4366
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -3485,9 +4385,37 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
|
|
|
3485
4385
|
eraserTrail,
|
|
3486
4386
|
eraserPreviewItems: items.filter(
|
|
3487
4387
|
(it) => eraserPreviewIds.includes(it.id)
|
|
3488
|
-
)
|
|
4388
|
+
),
|
|
4389
|
+
previewStrokeStyle: strokeStyleState,
|
|
4390
|
+
toolCursor
|
|
3489
4391
|
}
|
|
3490
4392
|
),
|
|
4393
|
+
interactive && showStyleInspector && activeStyleToolId ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
4394
|
+
reactNative.View,
|
|
4395
|
+
{
|
|
4396
|
+
pointerEvents: "box-none",
|
|
4397
|
+
style: styleInspectorPlacement === "top-left" ? {
|
|
4398
|
+
position: "absolute",
|
|
4399
|
+
left: 16,
|
|
4400
|
+
top: 104,
|
|
4401
|
+
alignItems: "flex-start"
|
|
4402
|
+
} : {
|
|
4403
|
+
position: "absolute",
|
|
4404
|
+
left: 16,
|
|
4405
|
+
right: 16,
|
|
4406
|
+
bottom: 84,
|
|
4407
|
+
alignItems: "center"
|
|
4408
|
+
},
|
|
4409
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4410
|
+
NativeVectorStyleInspector,
|
|
4411
|
+
{
|
|
4412
|
+
toolId: activeStyleToolId,
|
|
4413
|
+
value: strokeStyleState,
|
|
4414
|
+
onChange: patchCurrentStrokeStyle
|
|
4415
|
+
}
|
|
4416
|
+
)
|
|
4417
|
+
}
|
|
4418
|
+
) : null,
|
|
3491
4419
|
toolbar && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3492
4420
|
reactNative.View,
|
|
3493
4421
|
{
|
|
@@ -3511,14 +4439,18 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
|
|
|
3511
4439
|
|
|
3512
4440
|
exports.DEFAULT_NATIVE_OVERFLOW_TOOL_IDS = DEFAULT_NATIVE_OVERFLOW_TOOL_IDS;
|
|
3513
4441
|
exports.DEFAULT_NATIVE_VECTOR_TOOLS = DEFAULT_NATIVE_VECTOR_TOOLS;
|
|
4442
|
+
exports.NATIVE_STYLE_PALETTE = NATIVE_STYLE_PALETTE;
|
|
3514
4443
|
exports.NativeInteractionOverlay = NativeInteractionOverlay;
|
|
3515
4444
|
exports.NativeSceneRenderer = NativeSceneRenderer;
|
|
3516
4445
|
exports.NativeShapeRenderer = NativeShapeRenderer;
|
|
4446
|
+
exports.NativeVectorStyleInspector = NativeVectorStyleInspector;
|
|
3517
4447
|
exports.NativeVectorToolbar = NativeVectorToolbar;
|
|
3518
4448
|
exports.NativeVectorViewport = NativeVectorViewport;
|
|
3519
4449
|
exports.createFreehandStrokeItem = createFreehandStrokeItem;
|
|
3520
4450
|
exports.createImageItem = createImageItem;
|
|
3521
4451
|
exports.createShapeId = createShapeId;
|
|
4452
|
+
exports.nativeStyleColorWithOpacity = nativeStyleColorWithOpacity;
|
|
4453
|
+
exports.normalizeNativeStyleHex = normalizeNativeStyleHex;
|
|
3522
4454
|
exports.parseSvgFragment = parseSvgFragment;
|
|
3523
4455
|
//# sourceMappingURL=native.cjs.map
|
|
3524
4456
|
//# sourceMappingURL=native.cjs.map
|