canvu-react 0.4.31 → 0.4.33
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{asset-hydration-CWhld14A.d.cts → asset-hydration-BFGZ3igr.d.cts} +1 -1
- package/dist/{asset-hydration-D35mHbUP.d.ts → asset-hydration-D6Q3TJL1.d.ts} +1 -1
- package/dist/chatbot.d.cts +2 -2
- package/dist/chatbot.d.ts +2 -2
- package/dist/index.cjs +173 -102
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +173 -102
- package/dist/index.js.map +1 -1
- package/dist/{link-item-D870_X6P.d.cts → link-item-Dncuz2d_.d.cts} +3 -3
- package/dist/{link-item-Bg5vj0RI.d.ts → link-item-voRU0Up9.d.ts} +3 -3
- package/dist/native.cjs +220 -3
- package/dist/native.cjs.map +1 -1
- package/dist/native.js +220 -3
- package/dist/native.js.map +1 -1
- package/dist/react.cjs +244 -18
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +6 -6
- package/dist/react.d.ts +6 -6
- package/dist/react.js +244 -18
- package/dist/react.js.map +1 -1
- package/dist/realtime.cjs.map +1 -1
- package/dist/realtime.d.cts +3 -3
- package/dist/realtime.d.ts +3 -3
- package/dist/realtime.js.map +1 -1
- package/dist/tldraw.cjs +121 -39
- package/dist/tldraw.cjs.map +1 -1
- package/dist/tldraw.js +121 -39
- package/dist/tldraw.js.map +1 -1
- package/dist/{types-Bw1SdC9v.d.cts → types-BS-YG8Hx.d.cts} +1 -1
- package/dist/{types-DeXFfs7Y.d.ts → types-UZYYwK-v.d.ts} +1 -1
- package/package.json +1 -1
package/dist/react.d.cts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { I as IndexedDbImageStore } from './asset-hydration-
|
|
2
|
-
export { H as HydratedSceneItemsWithAssetsResult, h as hydrateSceneItemsWithAssets } from './asset-hydration-
|
|
1
|
+
import { I as IndexedDbImageStore } from './asset-hydration-BFGZ3igr.cjs';
|
|
2
|
+
export { H as HydratedSceneItemsWithAssetsResult, h as hydrateSceneItemsWithAssets } from './asset-hydration-BFGZ3igr.cjs';
|
|
3
3
|
import { V as VectorSceneItem } from './types-BCCvY6ie.cjs';
|
|
4
|
-
import { V as VectorViewportAssetKind, a as VectorViewportAssetStore } from './link-item-
|
|
5
|
-
export { d as VectorViewportAssetHydrationRequest, e as VectorViewportAssetResolveRequest, f as VectorViewportAssetResolveResult, h as VectorViewportAssetUploadRequest, j as VectorViewportAssetUploadResult } from './link-item-
|
|
6
|
-
import { B as BoardComponentPosition, V as VectorToolDefinition, C as CanvasPlugin, a as VectorSelectionInspector } from './types-
|
|
7
|
-
export { b as CanvasPluginComponentProps, c as CanvasPluginContribution, d as CanvasPluginItemsChangeMiddlewareContext, e as CanvasPluginRenderContext, f as CanvuChromeActiveToolStyle, g as CanvuChromeContext, h as CanvuChromeContextValue, i as CanvuChromeSelectionStyleChange, j as CanvuPluginContext, k as CanvuPluginContextValue, l as CanvuPluginViewportSnapshot, m as CustomShapePlacementOptions, P as PlacementPreview, n as VectorCanvasSpacePosition, o as VectorSelectionInspectorProps, p as VectorViewport, q as VectorViewportHandle, r as VectorViewportProps, W as WorldPointerDownDetail, s as createCanvuPlugin, t as getBoardPositionStyle, u as useCanvuChromeContext, v as useCanvuDocumentContext, w as useCanvuPluginContext, x as useCanvuPluginContribution, y as useCanvuResolvedTools, z as useCanvuViewportContext } from './types-
|
|
4
|
+
import { V as VectorViewportAssetKind, a as VectorViewportAssetStore } from './link-item-Dncuz2d_.cjs';
|
|
5
|
+
export { d as VectorViewportAssetHydrationRequest, e as VectorViewportAssetResolveRequest, f as VectorViewportAssetResolveResult, h as VectorViewportAssetUploadRequest, j as VectorViewportAssetUploadResult } from './link-item-Dncuz2d_.cjs';
|
|
6
|
+
import { B as BoardComponentPosition, V as VectorToolDefinition, C as CanvasPlugin, a as VectorSelectionInspector } from './types-BS-YG8Hx.cjs';
|
|
7
|
+
export { b as CanvasPluginComponentProps, c as CanvasPluginContribution, d as CanvasPluginItemsChangeMiddlewareContext, e as CanvasPluginRenderContext, f as CanvuChromeActiveToolStyle, g as CanvuChromeContext, h as CanvuChromeContextValue, i as CanvuChromeSelectionStyleChange, j as CanvuPluginContext, k as CanvuPluginContextValue, l as CanvuPluginViewportSnapshot, m as CustomShapePlacementOptions, P as PlacementPreview, n as VectorCanvasSpacePosition, o as VectorSelectionInspectorProps, p as VectorViewport, q as VectorViewportHandle, r as VectorViewportProps, W as WorldPointerDownDetail, s as createCanvuPlugin, t as getBoardPositionStyle, u as useCanvuChromeContext, v as useCanvuDocumentContext, w as useCanvuPluginContext, x as useCanvuPluginContribution, y as useCanvuResolvedTools, z as useCanvuViewportContext } from './types-BS-YG8Hx.cjs';
|
|
8
8
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
9
9
|
import * as react from 'react';
|
|
10
10
|
import { CSSProperties, ReactNode, ReactElement, SVGProps } from 'react';
|
package/dist/react.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { I as IndexedDbImageStore } from './asset-hydration-
|
|
2
|
-
export { H as HydratedSceneItemsWithAssetsResult, h as hydrateSceneItemsWithAssets } from './asset-hydration-
|
|
1
|
+
import { I as IndexedDbImageStore } from './asset-hydration-D6Q3TJL1.js';
|
|
2
|
+
export { H as HydratedSceneItemsWithAssetsResult, h as hydrateSceneItemsWithAssets } from './asset-hydration-D6Q3TJL1.js';
|
|
3
3
|
import { V as VectorSceneItem } from './types-BCCvY6ie.js';
|
|
4
|
-
import { V as VectorViewportAssetKind, a as VectorViewportAssetStore } from './link-item-
|
|
5
|
-
export { d as VectorViewportAssetHydrationRequest, e as VectorViewportAssetResolveRequest, f as VectorViewportAssetResolveResult, h as VectorViewportAssetUploadRequest, j as VectorViewportAssetUploadResult } from './link-item-
|
|
6
|
-
import { B as BoardComponentPosition, V as VectorToolDefinition, C as CanvasPlugin, a as VectorSelectionInspector } from './types-
|
|
7
|
-
export { b as CanvasPluginComponentProps, c as CanvasPluginContribution, d as CanvasPluginItemsChangeMiddlewareContext, e as CanvasPluginRenderContext, f as CanvuChromeActiveToolStyle, g as CanvuChromeContext, h as CanvuChromeContextValue, i as CanvuChromeSelectionStyleChange, j as CanvuPluginContext, k as CanvuPluginContextValue, l as CanvuPluginViewportSnapshot, m as CustomShapePlacementOptions, P as PlacementPreview, n as VectorCanvasSpacePosition, o as VectorSelectionInspectorProps, p as VectorViewport, q as VectorViewportHandle, r as VectorViewportProps, W as WorldPointerDownDetail, s as createCanvuPlugin, t as getBoardPositionStyle, u as useCanvuChromeContext, v as useCanvuDocumentContext, w as useCanvuPluginContext, x as useCanvuPluginContribution, y as useCanvuResolvedTools, z as useCanvuViewportContext } from './types-
|
|
4
|
+
import { V as VectorViewportAssetKind, a as VectorViewportAssetStore } from './link-item-voRU0Up9.js';
|
|
5
|
+
export { d as VectorViewportAssetHydrationRequest, e as VectorViewportAssetResolveRequest, f as VectorViewportAssetResolveResult, h as VectorViewportAssetUploadRequest, j as VectorViewportAssetUploadResult } from './link-item-voRU0Up9.js';
|
|
6
|
+
import { B as BoardComponentPosition, V as VectorToolDefinition, C as CanvasPlugin, a as VectorSelectionInspector } from './types-UZYYwK-v.js';
|
|
7
|
+
export { b as CanvasPluginComponentProps, c as CanvasPluginContribution, d as CanvasPluginItemsChangeMiddlewareContext, e as CanvasPluginRenderContext, f as CanvuChromeActiveToolStyle, g as CanvuChromeContext, h as CanvuChromeContextValue, i as CanvuChromeSelectionStyleChange, j as CanvuPluginContext, k as CanvuPluginContextValue, l as CanvuPluginViewportSnapshot, m as CustomShapePlacementOptions, P as PlacementPreview, n as VectorCanvasSpacePosition, o as VectorSelectionInspectorProps, p as VectorViewport, q as VectorViewportHandle, r as VectorViewportProps, W as WorldPointerDownDetail, s as createCanvuPlugin, t as getBoardPositionStyle, u as useCanvuChromeContext, v as useCanvuDocumentContext, w as useCanvuPluginContext, x as useCanvuPluginContribution, y as useCanvuResolvedTools, z as useCanvuViewportContext } from './types-UZYYwK-v.js';
|
|
8
8
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
9
9
|
import * as react from 'react';
|
|
10
10
|
import { CSSProperties, ReactNode, ReactElement, SVGProps } from 'react';
|
package/dist/react.js
CHANGED
|
@@ -49,11 +49,161 @@ var init_custom_shape = __esm({
|
|
|
49
49
|
}
|
|
50
50
|
});
|
|
51
51
|
|
|
52
|
+
// src/scene/link-item.ts
|
|
53
|
+
function buildLinkCardSvg(width, _height, link) {
|
|
54
|
+
const cardWidth = Math.max(1, width);
|
|
55
|
+
const scale = cardWidth / DEFAULT_LINK_CARD_WIDTH;
|
|
56
|
+
const contentWidth = DEFAULT_LINK_CARD_WIDTH;
|
|
57
|
+
const contentHeight = DEFAULT_LINK_CARD_HEIGHT;
|
|
58
|
+
const padding = 14;
|
|
59
|
+
const badgeSize = 42;
|
|
60
|
+
const gap = 13;
|
|
61
|
+
const buttonSize = 34;
|
|
62
|
+
const textX = padding + badgeSize + gap;
|
|
63
|
+
const textWidth = Math.max(1, contentWidth - textX - buttonSize - gap - padding);
|
|
64
|
+
const hostname = getLinkHostname(link.href);
|
|
65
|
+
const title = link.title?.trim() || hostname || "Link";
|
|
66
|
+
const protocol = getLinkProtocol(link.href);
|
|
67
|
+
const subtitle = hostname || link.href;
|
|
68
|
+
const idSuffix = getStableLinkIdSuffix(`${hostname}:${link.href}`);
|
|
69
|
+
const gradientId = `canvu-link-favicon-gradient-${idSuffix}`;
|
|
70
|
+
const buttonX = contentWidth - padding - buttonSize;
|
|
71
|
+
const buttonY = (contentHeight - buttonSize) / 2;
|
|
72
|
+
const isSecure = protocol === "https:";
|
|
73
|
+
const subtitleX = isSecure ? textX + 13 : textX;
|
|
74
|
+
const subtitleWidth = isSecure ? textWidth - 13 : textWidth;
|
|
75
|
+
return `
|
|
76
|
+
<style>
|
|
77
|
+
.canvu-link-card-root .canvu-link-card { transition: transform .18s ease, filter .18s ease, stroke .18s ease; }
|
|
78
|
+
.canvu-link-card-root .canvu-link-open { opacity: 0; transform: translateX(-4px); transition: opacity .18s ease, transform .18s ease; }
|
|
79
|
+
.canvu-link-card-root:hover .canvu-link-card { transform: translateY(-2px); filter: drop-shadow(0 4px 14px oklch(0.4 0.05 265 / .08)) drop-shadow(0 1px 3px oklch(0.4 0.05 265 / .06)); stroke: ${LINK_CARD_BORDER_STRONG}; }
|
|
80
|
+
.canvu-link-card-root:hover .canvu-link-open { opacity: 1; transform: translateX(0); }
|
|
81
|
+
</style>
|
|
82
|
+
<g class="canvu-link-card-root" transform="scale(${formatNumber(scale)})">
|
|
83
|
+
<rect class="canvu-link-card" width="${formatNumber(contentWidth)}" height="${formatNumber(contentHeight)}" rx="16" fill="#ffffff" stroke="${LINK_CARD_BORDER}" stroke-width="1" filter="drop-shadow(0 1px 2px oklch(0.4 0.03 265 / .05)) drop-shadow(0 1px 1px oklch(0.4 0.03 265 / .04))" />
|
|
84
|
+
<defs>
|
|
85
|
+
<linearGradient id="${gradientId}" x1="8" y1="48" x2="48" y2="8" gradientUnits="userSpaceOnUse">
|
|
86
|
+
<stop stop-color="${LINK_CARD_ACCENT}" />
|
|
87
|
+
<stop offset="1" stop-color="${LINK_CARD_ACCENT_DEEP}" />
|
|
88
|
+
</linearGradient>
|
|
89
|
+
</defs>
|
|
90
|
+
<rect x="${formatNumber(padding)}" y="${formatNumber(padding)}" width="${formatNumber(badgeSize)}" height="${formatNumber(badgeSize)}" rx="11" fill="url(#${gradientId})" />
|
|
91
|
+
<text x="${formatNumber(padding + badgeSize / 2)}" y="${formatNumber(padding + badgeSize / 2 + 5)}" text-anchor="middle" font-family="system-ui,sans-serif" font-size="17" font-weight="700" fill="#ffffff">${escapeHtmlText(getLinkInitial(hostname))}</text>
|
|
92
|
+
${buildLinkTextBand({ x: textX, y: 16, width: textWidth, height: 19, text: title, fontSize: 14.5, color: LINK_CARD_TITLE_COLOR, fontWeight: 700 })}
|
|
93
|
+
${isSecure ? `<g transform="translate(${formatNumber(textX)},40)" stroke="${LINK_CARD_TEXT_COLOR}" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round" fill="none"><rect x="1.5" y="4.5" width="7" height="6" rx="1" /><path d="M3 4.5 V3 a2 2 0 0 1 4 0 v1.5" /></g>` : ""}
|
|
94
|
+
${buildLinkTextBand({ x: subtitleX, y: 36, width: subtitleWidth, height: 17, text: subtitle, fontSize: 12.5, color: LINK_CARD_TEXT_COLOR })}
|
|
95
|
+
<g class="canvu-link-open" transform="translate(${formatNumber(buttonX)},${formatNumber(buttonY)})">
|
|
96
|
+
<rect width="${formatNumber(buttonSize)}" height="${formatNumber(buttonSize)}" rx="10" fill="#ffffff" stroke="${LINK_CARD_BORDER}" stroke-width="1" />
|
|
97
|
+
<g transform="translate(10,10)" stroke="${LINK_CARD_TEXT_COLOR}" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" fill="none">
|
|
98
|
+
<path d="M8 2 H14 V8" />
|
|
99
|
+
<path d="M14 2 L7 9" />
|
|
100
|
+
<path d="M12 10 V13 a1 1 0 0 1 -1 1 H3 a1 1 0 0 1 -1 -1 V5 a1 1 0 0 1 1 -1 H6" />
|
|
101
|
+
</g>
|
|
102
|
+
</g>
|
|
103
|
+
</g>
|
|
104
|
+
`;
|
|
105
|
+
}
|
|
106
|
+
function getLinkData(item) {
|
|
107
|
+
const entry = item.pluginData?.[LINK_PLUGIN_KEY];
|
|
108
|
+
return isCanvuLinkData(entry) ? entry : null;
|
|
109
|
+
}
|
|
110
|
+
function rebuildLinkItemSvg(item) {
|
|
111
|
+
const link = getLinkData(item);
|
|
112
|
+
if (!link) return item;
|
|
113
|
+
const scale = clamp(
|
|
114
|
+
item.bounds.width / DEFAULT_LINK_CARD_WIDTH,
|
|
115
|
+
LINK_CARD_MIN_SCALE,
|
|
116
|
+
LINK_CARD_MAX_SCALE
|
|
117
|
+
);
|
|
118
|
+
const width = DEFAULT_LINK_CARD_WIDTH * scale;
|
|
119
|
+
const height = DEFAULT_LINK_CARD_HEIGHT * scale;
|
|
120
|
+
const bounds = {
|
|
121
|
+
...item.bounds,
|
|
122
|
+
width,
|
|
123
|
+
height
|
|
124
|
+
};
|
|
125
|
+
const customInnerSvg = buildLinkCardSvg(
|
|
126
|
+
DEFAULT_LINK_CARD_WIDTH,
|
|
127
|
+
DEFAULT_LINK_CARD_HEIGHT,
|
|
128
|
+
link
|
|
129
|
+
);
|
|
130
|
+
return {
|
|
131
|
+
...item,
|
|
132
|
+
x: bounds.x,
|
|
133
|
+
y: bounds.y,
|
|
134
|
+
bounds,
|
|
135
|
+
customIntrinsicSize: {
|
|
136
|
+
width: DEFAULT_LINK_CARD_WIDTH,
|
|
137
|
+
height: DEFAULT_LINK_CARD_HEIGHT
|
|
138
|
+
},
|
|
139
|
+
customInnerSvg,
|
|
140
|
+
childrenSvg: buildLinkCardSvg(width, height, link)
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
var LINK_PLUGIN_KEY, DEFAULT_LINK_CARD_WIDTH, DEFAULT_LINK_CARD_HEIGHT, LINK_CARD_MIN_SCALE, LINK_CARD_MAX_SCALE, LINK_CARD_ASPECT, LINK_CARD_BORDER, LINK_CARD_BORDER_STRONG, LINK_CARD_ACCENT, LINK_CARD_ACCENT_DEEP, LINK_CARD_TITLE_COLOR, LINK_CARD_TEXT_COLOR, clamp, formatNumber, escapeHtmlText, getLinkHostname, buildLinkTextBand, getLinkProtocol, getLinkInitial, getStableLinkIdSuffix, isCanvuLinkData;
|
|
144
|
+
var init_link_item = __esm({
|
|
145
|
+
"src/scene/link-item.ts"() {
|
|
146
|
+
LINK_PLUGIN_KEY = "canvuLink";
|
|
147
|
+
DEFAULT_LINK_CARD_WIDTH = 320;
|
|
148
|
+
DEFAULT_LINK_CARD_HEIGHT = 70;
|
|
149
|
+
LINK_CARD_MIN_SCALE = 0.6;
|
|
150
|
+
LINK_CARD_MAX_SCALE = 6;
|
|
151
|
+
LINK_CARD_ASPECT = DEFAULT_LINK_CARD_WIDTH / DEFAULT_LINK_CARD_HEIGHT;
|
|
152
|
+
LINK_CARD_BORDER = "oklch(0.918 0.008 255)";
|
|
153
|
+
LINK_CARD_BORDER_STRONG = "oklch(0.86 0.012 255)";
|
|
154
|
+
LINK_CARD_ACCENT = "oklch(0.55 0.19 264)";
|
|
155
|
+
LINK_CARD_ACCENT_DEEP = "oklch(0.46 0.18 264)";
|
|
156
|
+
LINK_CARD_TITLE_COLOR = "oklch(0.26 0.022 265)";
|
|
157
|
+
LINK_CARD_TEXT_COLOR = "oklch(0.55 0.022 265)";
|
|
158
|
+
clamp = (value, min, max) => Math.min(max, Math.max(min, value));
|
|
159
|
+
formatNumber = (value) => {
|
|
160
|
+
const rounded = Math.round(value * 100) / 100;
|
|
161
|
+
return Object.is(rounded, -0) ? "0" : String(rounded);
|
|
162
|
+
};
|
|
163
|
+
escapeHtmlText = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">");
|
|
164
|
+
getLinkHostname = (href) => {
|
|
165
|
+
try {
|
|
166
|
+
return new URL(href).hostname.replace(/^www\./, "");
|
|
167
|
+
} catch {
|
|
168
|
+
return href;
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
buildLinkTextBand = (band) => {
|
|
172
|
+
const lineHeight = band.height;
|
|
173
|
+
const weight = band.fontWeight != null ? `font-weight:${band.fontWeight};` : "";
|
|
174
|
+
return `<foreignObject x="${formatNumber(band.x)}" y="${formatNumber(band.y)}" width="${formatNumber(Math.max(1, band.width))}" height="${formatNumber(Math.max(1, band.height))}"><div xmlns="http://www.w3.org/1999/xhtml" style="box-sizing:border-box;width:100%;height:100%;margin:0;font-family:system-ui,sans-serif;font-size:${formatNumber(band.fontSize)}px;line-height:${formatNumber(lineHeight)}px;letter-spacing:-0.01em;color:${band.color};overflow:hidden;white-space:nowrap;text-overflow:ellipsis;${weight}">${escapeHtmlText(band.text)}</div></foreignObject>`;
|
|
175
|
+
};
|
|
176
|
+
getLinkProtocol = (href) => {
|
|
177
|
+
try {
|
|
178
|
+
return new URL(href).protocol;
|
|
179
|
+
} catch {
|
|
180
|
+
return "";
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
getLinkInitial = (hostname) => {
|
|
184
|
+
const first = hostname.trim().charAt(0).toUpperCase();
|
|
185
|
+
return first || "L";
|
|
186
|
+
};
|
|
187
|
+
getStableLinkIdSuffix = (value) => {
|
|
188
|
+
let hash = 0;
|
|
189
|
+
for (const char of value) {
|
|
190
|
+
hash = hash * 31 + char.charCodeAt(0) >>> 0;
|
|
191
|
+
}
|
|
192
|
+
return hash.toString(36);
|
|
193
|
+
};
|
|
194
|
+
isCanvuLinkData = (value) => {
|
|
195
|
+
if (!value || typeof value !== "object") return false;
|
|
196
|
+
const candidate = value;
|
|
197
|
+
return typeof candidate.href === "string" && candidate.href.length > 0;
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
|
|
52
202
|
// src/scene/text-svg.ts
|
|
53
203
|
function escapeSvgTextContent(s) {
|
|
54
204
|
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
55
205
|
}
|
|
56
|
-
function
|
|
206
|
+
function escapeHtmlText2(s) {
|
|
57
207
|
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
58
208
|
}
|
|
59
209
|
function getSharedMeasureContext() {
|
|
@@ -154,9 +304,9 @@ function buildTextFixedBoundsSvg(content, width, height, fillColor = "#1d1d1d",
|
|
|
154
304
|
const trimmed = content.trim();
|
|
155
305
|
const padTop = EDIT_TOP_PAD_RATIO * fontSize;
|
|
156
306
|
if (trimmed.length === 0) {
|
|
157
|
-
return `<foreignObject width="${w}" height="${h}"><div xmlns="http://www.w3.org/1999/xhtml" style="box-sizing:border-box;width:100%;height:100%;margin:0;padding:${padTop}px 4px 0 4px;font-size:${fontSize}px;line-height:${lh}px;font-family:${TEXT_FONT_FAMILY};white-space:pre-wrap;word-wrap:break-word;overflow:hidden;color:#94a3b8;font-style:italic">${
|
|
307
|
+
return `<foreignObject width="${w}" height="${h}"><div xmlns="http://www.w3.org/1999/xhtml" style="box-sizing:border-box;width:100%;height:100%;margin:0;padding:${padTop}px 4px 0 4px;font-size:${fontSize}px;line-height:${lh}px;font-family:${TEXT_FONT_FAMILY};white-space:pre-wrap;word-wrap:break-word;overflow:hidden;color:#94a3b8;font-style:italic">${escapeHtmlText2(PLACEHOLDER)}</div></foreignObject>`;
|
|
158
308
|
}
|
|
159
|
-
const body =
|
|
309
|
+
const body = escapeHtmlText2(content);
|
|
160
310
|
return `<foreignObject width="${w}" height="${h}"><div xmlns="http://www.w3.org/1999/xhtml" style="box-sizing:border-box;width:100%;height:100%;margin:0;padding:${padTop}px 4px 0 4px;font-size:${fontSize}px;line-height:${lh}px;font-family:${TEXT_FONT_FAMILY};white-space:pre-wrap;word-wrap:break-word;overflow:hidden;color:${fillColor}">${body}</div></foreignObject>`;
|
|
161
311
|
}
|
|
162
312
|
var DEFAULT_TEXT_FONT_SIZE, DEFAULT_TEXT_TOOL_FONT_SIZE, TEXT_FONT_FAMILY, LINE_HEIGHT_RATIO, FIRST_LINE_BASELINE_RATIO, EDIT_TOP_PAD_RATIO, BOTTOM_PAD_RATIO, PLACEHOLDER, MIN_TEXT_BOX_W, MIN_TEXT_BOX_H, TEXT_PAD_X, MAX_TEXT_MEASURE_CACHE_ENTRIES, sharedMeasureContext, textMeasureCache;
|
|
@@ -813,6 +963,9 @@ function rebuildItemSvg(item) {
|
|
|
813
963
|
)
|
|
814
964
|
};
|
|
815
965
|
}
|
|
966
|
+
if (getLinkData(item)) {
|
|
967
|
+
return rebuildLinkItemSvg(item);
|
|
968
|
+
}
|
|
816
969
|
if (k === "custom" && item.customIntrinsicSize && item.customInnerSvg) {
|
|
817
970
|
const b = normalizeRect(item.bounds);
|
|
818
971
|
return {
|
|
@@ -1038,6 +1191,7 @@ var init_shape_builders = __esm({
|
|
|
1038
1191
|
"src/scene/shape-builders.ts"() {
|
|
1039
1192
|
init_rect();
|
|
1040
1193
|
init_custom_shape();
|
|
1194
|
+
init_link_item();
|
|
1041
1195
|
init_text_svg();
|
|
1042
1196
|
DEFAULT_STROKE_STYLE = {
|
|
1043
1197
|
stroke: "#1d1d1d",
|
|
@@ -6355,10 +6509,80 @@ function collectEraserTargetsAtWorldPoint(items, worldX, worldY, options) {
|
|
|
6355
6509
|
|
|
6356
6510
|
// src/interaction/mutations.ts
|
|
6357
6511
|
init_rect();
|
|
6512
|
+
init_link_item();
|
|
6358
6513
|
init_shape_builders();
|
|
6359
6514
|
init_text_svg();
|
|
6515
|
+
var LINK_CORNER_HANDLES = /* @__PURE__ */ new Set(["nw", "ne", "se", "sw"]);
|
|
6516
|
+
var clamp2 = (value, min, max) => Math.min(max, Math.max(min, value));
|
|
6517
|
+
var clampLinkResizeBounds = (startBounds, nextBounds, handle, intrinsicWidth) => {
|
|
6518
|
+
const next = normalizeRect(nextBounds);
|
|
6519
|
+
const scale = clamp2(
|
|
6520
|
+
next.width / Math.max(1e-9, intrinsicWidth),
|
|
6521
|
+
LINK_CARD_MIN_SCALE,
|
|
6522
|
+
LINK_CARD_MAX_SCALE
|
|
6523
|
+
);
|
|
6524
|
+
const width = intrinsicWidth * scale;
|
|
6525
|
+
const height = width / LINK_CARD_ASPECT;
|
|
6526
|
+
const start = normalizeRect(startBounds);
|
|
6527
|
+
const x0 = start.x;
|
|
6528
|
+
const y0 = start.y;
|
|
6529
|
+
const x1 = start.x + start.width;
|
|
6530
|
+
const y1 = start.y + start.height;
|
|
6531
|
+
switch (handle) {
|
|
6532
|
+
case "nw":
|
|
6533
|
+
return { x: x1 - width, y: y1 - height, width, height };
|
|
6534
|
+
case "ne":
|
|
6535
|
+
return { x: x0, y: y1 - height, width, height };
|
|
6536
|
+
case "sw":
|
|
6537
|
+
return { x: x1 - width, y: y0, width, height };
|
|
6538
|
+
default:
|
|
6539
|
+
return { x: x0, y: y0, width, height };
|
|
6540
|
+
}
|
|
6541
|
+
};
|
|
6360
6542
|
function computeNewBoundsForResize(item, sb, handle, currentWorld) {
|
|
6361
6543
|
const rot = getItemRotationRad(item);
|
|
6544
|
+
const link = getLinkData(item);
|
|
6545
|
+
if (link && item.customIntrinsicSize) {
|
|
6546
|
+
if (!LINK_CORNER_HANDLES.has(handle)) return sb;
|
|
6547
|
+
const intrinsicWidth = Math.max(1e-9, item.customIntrinsicSize.width);
|
|
6548
|
+
if (Math.abs(rot) < 1e-12) {
|
|
6549
|
+
const next = computeResizeBoundsFixedAspect(
|
|
6550
|
+
sb,
|
|
6551
|
+
handle,
|
|
6552
|
+
currentWorld,
|
|
6553
|
+
LINK_CARD_ASPECT
|
|
6554
|
+
);
|
|
6555
|
+
return clampLinkResizeBounds(sb, next, handle, intrinsicWidth);
|
|
6556
|
+
}
|
|
6557
|
+
const local2 = worldToItemLocal(
|
|
6558
|
+
currentWorld.x,
|
|
6559
|
+
currentWorld.y,
|
|
6560
|
+
sb.x,
|
|
6561
|
+
sb.y,
|
|
6562
|
+
sb.width,
|
|
6563
|
+
sb.height,
|
|
6564
|
+
rot
|
|
6565
|
+
);
|
|
6566
|
+
const localBounds2 = { x: 0, y: 0, width: sb.width, height: sb.height };
|
|
6567
|
+
const nextLocal = computeResizeBoundsFixedAspect(
|
|
6568
|
+
localBounds2,
|
|
6569
|
+
handle,
|
|
6570
|
+
local2,
|
|
6571
|
+
LINK_CARD_ASPECT
|
|
6572
|
+
);
|
|
6573
|
+
const clamped = clampLinkResizeBounds(
|
|
6574
|
+
localBounds2,
|
|
6575
|
+
nextLocal,
|
|
6576
|
+
handle,
|
|
6577
|
+
intrinsicWidth
|
|
6578
|
+
);
|
|
6579
|
+
return {
|
|
6580
|
+
x: sb.x + clamped.x,
|
|
6581
|
+
y: sb.y + clamped.y,
|
|
6582
|
+
width: clamped.width,
|
|
6583
|
+
height: clamped.height
|
|
6584
|
+
};
|
|
6585
|
+
}
|
|
6362
6586
|
if (Math.abs(rot) < 1e-12) {
|
|
6363
6587
|
if (item.toolKind === "image") {
|
|
6364
6588
|
let aspect;
|
|
@@ -6831,17 +7055,8 @@ var SvgVectorRenderer = class {
|
|
|
6831
7055
|
}
|
|
6832
7056
|
};
|
|
6833
7057
|
|
|
6834
|
-
// src/
|
|
6835
|
-
|
|
6836
|
-
var isCanvuLinkData = (value) => {
|
|
6837
|
-
if (!value || typeof value !== "object") return false;
|
|
6838
|
-
const candidate = value;
|
|
6839
|
-
return typeof candidate.href === "string" && candidate.href.length > 0;
|
|
6840
|
-
};
|
|
6841
|
-
function getLinkData(item) {
|
|
6842
|
-
const entry = item.pluginData?.[LINK_PLUGIN_KEY];
|
|
6843
|
-
return isCanvuLinkData(entry) ? entry : null;
|
|
6844
|
-
}
|
|
7058
|
+
// src/react/VectorViewport.tsx
|
|
7059
|
+
init_link_item();
|
|
6845
7060
|
|
|
6846
7061
|
// src/scene/scene.ts
|
|
6847
7062
|
var VectorScene = class {
|
|
@@ -6935,8 +7150,10 @@ function smoothFreehandPointsToPathD(points) {
|
|
|
6935
7150
|
}
|
|
6936
7151
|
|
|
6937
7152
|
// src/react/InteractionOverlay.tsx
|
|
7153
|
+
init_link_item();
|
|
6938
7154
|
init_shape_builders();
|
|
6939
7155
|
var HANDLE_ORDER = ["nw", "n", "ne", "e", "se", "s", "sw", "w"];
|
|
7156
|
+
var LINK_HANDLE_ORDER = ["nw", "ne", "se", "sw"];
|
|
6940
7157
|
var ERASER_TINT = "#cbd5e1";
|
|
6941
7158
|
var ERASER_TINT_OPACITY = 0.95;
|
|
6942
7159
|
var ERASER_PREVIEW_OPACITY = 0.3;
|
|
@@ -6989,7 +7206,7 @@ function InteractionOverlay({
|
|
|
6989
7206
|
) }, it.id);
|
|
6990
7207
|
}),
|
|
6991
7208
|
showResizeHandles && bSingle && single && rotHandlePos && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
6992
|
-
HANDLE_ORDER.map((hid) => {
|
|
7209
|
+
(getLinkData(single) ? LINK_HANDLE_ORDER : HANDLE_ORDER).map((hid) => {
|
|
6993
7210
|
const p = getHandleWorldPositionRotated(bSingle, hid, rotSingle);
|
|
6994
7211
|
return /* @__PURE__ */ jsx(
|
|
6995
7212
|
"circle",
|
|
@@ -7803,6 +8020,7 @@ function defaultPlacementWorld(tool, center) {
|
|
|
7803
8020
|
lineWorld: [a, b]
|
|
7804
8021
|
};
|
|
7805
8022
|
}
|
|
8023
|
+
var LINK_CORNER_HANDLES2 = /* @__PURE__ */ new Set(["nw", "ne", "se", "sw"]);
|
|
7806
8024
|
function pointInSelectedItemBounds(item, worldX, worldY) {
|
|
7807
8025
|
const bounds = normalizeRect(item.bounds);
|
|
7808
8026
|
const local = worldToItemLocal(
|
|
@@ -8280,7 +8498,11 @@ var VectorViewport = forwardRef(
|
|
|
8280
8498
|
setEffectiveSelectedIdsRef.current = setEffectiveSelectedIds;
|
|
8281
8499
|
toolIdRef.current = toolId;
|
|
8282
8500
|
interactiveRef.current = interactive;
|
|
8283
|
-
|
|
8501
|
+
const normalizedItems = useMemo(
|
|
8502
|
+
() => items.map((item) => getLinkData(item) ? rebuildLinkItemSvg(item) : item),
|
|
8503
|
+
[items]
|
|
8504
|
+
);
|
|
8505
|
+
itemsRef.current = normalizedItems;
|
|
8284
8506
|
onWorldPointerDownRef.current = onWorldPointerDown;
|
|
8285
8507
|
const originalOnItemsChangeRef = useRef(onItemsChange);
|
|
8286
8508
|
originalOnItemsChangeRef.current = onItemsChange;
|
|
@@ -8301,7 +8523,10 @@ var VectorViewport = forwardRef(
|
|
|
8301
8523
|
autoResetToolToRef.current = autoResetToolTo;
|
|
8302
8524
|
const onToolChangeRequestRef = useRef(onToolChangeRequest);
|
|
8303
8525
|
onToolChangeRequestRef.current = onToolChangeRequest;
|
|
8304
|
-
const resolvedItems = useMemo(
|
|
8526
|
+
const resolvedItems = useMemo(
|
|
8527
|
+
() => resolveArrowBindingsInScene(normalizedItems),
|
|
8528
|
+
[normalizedItems]
|
|
8529
|
+
);
|
|
8305
8530
|
const resolvedItemsRef = useRef(resolvedItems);
|
|
8306
8531
|
resolvedItemsRef.current = resolvedItems;
|
|
8307
8532
|
const liveId = useId();
|
|
@@ -9722,7 +9947,8 @@ var VectorViewport = forwardRef(
|
|
|
9722
9947
|
handleRadiusWorld,
|
|
9723
9948
|
rot
|
|
9724
9949
|
);
|
|
9725
|
-
|
|
9950
|
+
const isLinkResizeHandle = hb && getLinkData(selected) ? LINK_CORNER_HANDLES2.has(hb) : Boolean(hb);
|
|
9951
|
+
if (hb && isLinkResizeHandle) {
|
|
9726
9952
|
const snapRs = bakedSnapshot(selected.id);
|
|
9727
9953
|
if (!snapRs) return;
|
|
9728
9954
|
dragStateRef.current = {
|