@woven-canvas/core 1.0.0 → 1.0.2
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/build/_tsup-dts-rollup.d.cts +51 -10
- package/build/_tsup-dts-rollup.d.ts +51 -10
- package/build/index.cjs +535 -286
- package/build/index.cjs.map +1 -1
- package/build/index.d.cts +6 -1
- package/build/index.d.ts +6 -1
- package/build/index.js +400 -156
- package/build/index.js.map +1 -1
- package/build/tsconfig.tsbuildinfo +1 -1
- package/package.json +4 -4
package/build/index.js
CHANGED
|
@@ -8,7 +8,7 @@ var __export = (target, all) => {
|
|
|
8
8
|
import {
|
|
9
9
|
CanvasComponentDef as CanvasComponentDef7,
|
|
10
10
|
CanvasSingletonDef as CanvasSingletonDef12,
|
|
11
|
-
defineCanvasComponent as
|
|
11
|
+
defineCanvasComponent as defineCanvasComponent14,
|
|
12
12
|
defineCanvasSingleton as defineCanvasSingleton3,
|
|
13
13
|
Synced as Synced4
|
|
14
14
|
} from "@woven-ecs/canvas-store";
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
defineQuery as defineQuery11,
|
|
20
20
|
defineSystem,
|
|
21
21
|
EventType,
|
|
22
|
-
field as
|
|
22
|
+
field as field29,
|
|
23
23
|
getBackrefs,
|
|
24
24
|
getResources as getResources13,
|
|
25
25
|
hasComponent as hasComponent7,
|
|
@@ -46,6 +46,8 @@ __export(components_exports, {
|
|
|
46
46
|
Color: () => Color,
|
|
47
47
|
Connector: () => Connector,
|
|
48
48
|
Edited: () => Edited,
|
|
49
|
+
Embed: () => Embed,
|
|
50
|
+
EmbedProvider: () => EmbedProvider,
|
|
49
51
|
Held: () => Held,
|
|
50
52
|
HitGeometry: () => HitGeometry,
|
|
51
53
|
Hovered: () => Hovered,
|
|
@@ -164,7 +166,7 @@ var ControlsOptions = z.object({
|
|
|
164
166
|
* Tool activated by right mouse button.
|
|
165
167
|
* @default 'menu'
|
|
166
168
|
*/
|
|
167
|
-
rightMouseTool: z.string().max(32).default("
|
|
169
|
+
rightMouseTool: z.string().max(32).default("hand"),
|
|
168
170
|
/**
|
|
169
171
|
* Tool activated by mouse wheel.
|
|
170
172
|
* @default 'scroll'
|
|
@@ -325,7 +327,7 @@ var BlockDef = z.object({
|
|
|
325
327
|
resizeMode: z.enum([ResizeMode.Scale, ResizeMode.Text, ResizeMode.Free, ResizeMode.GroupOnly]).default(ResizeMode.Scale),
|
|
326
328
|
canRotate: z.boolean().default(true),
|
|
327
329
|
canScale: z.boolean().default(true),
|
|
328
|
-
|
|
330
|
+
interactable: z.boolean().default(true),
|
|
329
331
|
connectors: BlockDefConnectors.default(BlockDefConnectors.parse({}))
|
|
330
332
|
});
|
|
331
333
|
|
|
@@ -722,30 +724,57 @@ var Connector = defineCanvasComponent2(
|
|
|
722
724
|
import { defineCanvasComponent as defineCanvasComponent3 } from "@woven-ecs/canvas-store";
|
|
723
725
|
var Edited = defineCanvasComponent3({ name: "edited" }, {});
|
|
724
726
|
|
|
725
|
-
// src/components/
|
|
727
|
+
// src/components/Embed.ts
|
|
726
728
|
import { defineCanvasComponent as defineCanvasComponent4 } from "@woven-ecs/canvas-store";
|
|
727
729
|
import { field as field6 } from "@woven-ecs/core";
|
|
728
|
-
var
|
|
730
|
+
var EmbedProvider = /* @__PURE__ */ ((EmbedProvider2) => {
|
|
731
|
+
EmbedProvider2["GoogleMaps"] = "google-maps";
|
|
732
|
+
EmbedProvider2["GoogleCalendar"] = "google-calendar";
|
|
733
|
+
EmbedProvider2["GoogleSlides"] = "google-slides";
|
|
734
|
+
EmbedProvider2["Tldraw"] = "tldraw";
|
|
735
|
+
EmbedProvider2["Figma"] = "figma";
|
|
736
|
+
EmbedProvider2["GithubGist"] = "github-gist";
|
|
737
|
+
EmbedProvider2["Youtube"] = "youtube";
|
|
738
|
+
EmbedProvider2["Spotify"] = "spotify";
|
|
739
|
+
EmbedProvider2["Unknown"] = "unknown";
|
|
740
|
+
return EmbedProvider2;
|
|
741
|
+
})(EmbedProvider || {});
|
|
742
|
+
var Embed = defineCanvasComponent4(
|
|
743
|
+
{ name: "embed", sync: "document" },
|
|
744
|
+
{
|
|
745
|
+
/** The original URL provided by the user */
|
|
746
|
+
url: field6.string().max(2048).default(""),
|
|
747
|
+
/** The resolved embed/iframe URL */
|
|
748
|
+
embedUrl: field6.string().max(2048).default(""),
|
|
749
|
+
/** The embed provider (used for provider-specific styling/behavior) */
|
|
750
|
+
provider: field6.enum(EmbedProvider).default("unknown" /* Unknown */)
|
|
751
|
+
}
|
|
752
|
+
);
|
|
753
|
+
|
|
754
|
+
// src/components/Held.ts
|
|
755
|
+
import { defineCanvasComponent as defineCanvasComponent5 } from "@woven-ecs/canvas-store";
|
|
756
|
+
import { field as field7 } from "@woven-ecs/core";
|
|
757
|
+
var Held = defineCanvasComponent5(
|
|
729
758
|
{ name: "held", sync: "ephemeral" },
|
|
730
759
|
{
|
|
731
|
-
sessionId:
|
|
760
|
+
sessionId: field7.string().max(36).default("")
|
|
732
761
|
}
|
|
733
762
|
);
|
|
734
763
|
|
|
735
764
|
// src/components/HitGeometry.ts
|
|
736
765
|
import { Arc, Capsule, Mat2 } from "@woven-canvas/math";
|
|
737
766
|
import { CanvasComponentDef as CanvasComponentDef4 } from "@woven-ecs/canvas-store";
|
|
738
|
-
import { field as
|
|
767
|
+
import { field as field8 } from "@woven-ecs/core";
|
|
739
768
|
var _uvToWorldMatrix = [1, 0, 0, 1, 0, 0];
|
|
740
769
|
var MAX_HIT_CAPSULES = 64;
|
|
741
770
|
var FLOATS_PER_CAPSULE = 5;
|
|
742
771
|
var MAX_HIT_ARCS = 2;
|
|
743
772
|
var FLOATS_PER_ARC = 7;
|
|
744
773
|
var HitGeometrySchema = {
|
|
745
|
-
hitCapsules:
|
|
746
|
-
capsuleCount:
|
|
747
|
-
hitArcs:
|
|
748
|
-
arcCount:
|
|
774
|
+
hitCapsules: field8.buffer(field8.float32()).size(MAX_HIT_CAPSULES * FLOATS_PER_CAPSULE),
|
|
775
|
+
capsuleCount: field8.uint16().default(0),
|
|
776
|
+
hitArcs: field8.buffer(field8.float32()).size(MAX_HIT_ARCS * FLOATS_PER_ARC),
|
|
777
|
+
arcCount: field8.uint16().default(0)
|
|
749
778
|
};
|
|
750
779
|
var HitGeometryDef = class extends CanvasComponentDef4 {
|
|
751
780
|
constructor() {
|
|
@@ -1051,37 +1080,37 @@ var HitGeometryDef = class extends CanvasComponentDef4 {
|
|
|
1051
1080
|
var HitGeometry = new HitGeometryDef();
|
|
1052
1081
|
|
|
1053
1082
|
// src/components/Hovered.ts
|
|
1054
|
-
import { defineCanvasComponent as
|
|
1055
|
-
var Hovered =
|
|
1083
|
+
import { defineCanvasComponent as defineCanvasComponent6 } from "@woven-ecs/canvas-store";
|
|
1084
|
+
var Hovered = defineCanvasComponent6({ name: "hovered" }, {});
|
|
1056
1085
|
|
|
1057
1086
|
// src/components/Image.ts
|
|
1058
|
-
import { defineCanvasComponent as
|
|
1059
|
-
import { field as
|
|
1060
|
-
var Image =
|
|
1087
|
+
import { defineCanvasComponent as defineCanvasComponent7 } from "@woven-ecs/canvas-store";
|
|
1088
|
+
import { field as field9 } from "@woven-ecs/core";
|
|
1089
|
+
var Image = defineCanvasComponent7(
|
|
1061
1090
|
{ name: "image", sync: "document" },
|
|
1062
1091
|
{
|
|
1063
1092
|
/** Image width in pixels */
|
|
1064
|
-
width:
|
|
1093
|
+
width: field9.uint16().default(0),
|
|
1065
1094
|
/** Image height in pixels */
|
|
1066
|
-
height:
|
|
1095
|
+
height: field9.uint16().default(0),
|
|
1067
1096
|
/** Alt text for accessibility */
|
|
1068
|
-
alt:
|
|
1097
|
+
alt: field9.string().max(256).default("")
|
|
1069
1098
|
}
|
|
1070
1099
|
);
|
|
1071
1100
|
|
|
1072
1101
|
// src/components/Opacity.ts
|
|
1073
|
-
import { defineCanvasComponent as
|
|
1074
|
-
import { field as
|
|
1075
|
-
var Opacity =
|
|
1102
|
+
import { defineCanvasComponent as defineCanvasComponent8 } from "@woven-ecs/canvas-store";
|
|
1103
|
+
import { field as field10 } from "@woven-ecs/core";
|
|
1104
|
+
var Opacity = defineCanvasComponent8(
|
|
1076
1105
|
{ name: "opacity" },
|
|
1077
1106
|
{
|
|
1078
|
-
value:
|
|
1107
|
+
value: field10.uint8().default(255)
|
|
1079
1108
|
}
|
|
1080
1109
|
);
|
|
1081
1110
|
|
|
1082
1111
|
// src/components/Pointer.ts
|
|
1083
1112
|
import { CanvasComponentDef as CanvasComponentDef5 } from "@woven-ecs/canvas-store";
|
|
1084
|
-
import { field as
|
|
1113
|
+
import { field as field11 } from "@woven-ecs/core";
|
|
1085
1114
|
var PointerButton = {
|
|
1086
1115
|
None: "none",
|
|
1087
1116
|
Left: "left",
|
|
@@ -1098,30 +1127,30 @@ var PointerType = {
|
|
|
1098
1127
|
var SAMPLE_COUNT = 6;
|
|
1099
1128
|
var PointerSchema = {
|
|
1100
1129
|
/** Unique pointer ID (from PointerEvent.pointerId) */
|
|
1101
|
-
pointerId:
|
|
1130
|
+
pointerId: field11.uint16().default(0),
|
|
1102
1131
|
/** Current position relative to the editor element [x, y] */
|
|
1103
|
-
position:
|
|
1132
|
+
position: field11.tuple(field11.float32(), 2).default([0, 0]),
|
|
1104
1133
|
/** Position where the pointer went down [x, y] */
|
|
1105
|
-
downPosition:
|
|
1134
|
+
downPosition: field11.tuple(field11.float32(), 2).default([0, 0]),
|
|
1106
1135
|
/** Frame number when the pointer went down (for click detection) */
|
|
1107
|
-
downFrame:
|
|
1136
|
+
downFrame: field11.uint32().default(0),
|
|
1108
1137
|
/** Which button is pressed */
|
|
1109
|
-
button:
|
|
1138
|
+
button: field11.enum(PointerButton).default(PointerButton.None),
|
|
1110
1139
|
/** Type of pointer device */
|
|
1111
|
-
pointerType:
|
|
1140
|
+
pointerType: field11.enum(PointerType).default(PointerType.Mouse),
|
|
1112
1141
|
/** Pressure from 0 to 1 (for pen/touch) */
|
|
1113
|
-
pressure:
|
|
1142
|
+
pressure: field11.float32().default(0),
|
|
1114
1143
|
/** Whether the pointer event target was not the editor element */
|
|
1115
|
-
obscured:
|
|
1144
|
+
obscured: field11.boolean().default(false),
|
|
1116
1145
|
// Velocity tracking (ring buffer for position samples)
|
|
1117
1146
|
/** Ring buffer of previous positions [x0, y0, x1, y1, ...] @internal */
|
|
1118
|
-
_prevPositions:
|
|
1147
|
+
_prevPositions: field11.array(field11.float32(), SAMPLE_COUNT * 2),
|
|
1119
1148
|
/** Ring buffer of timestamps for each position sample @internal */
|
|
1120
|
-
_prevTimes:
|
|
1149
|
+
_prevTimes: field11.array(field11.float32(), SAMPLE_COUNT),
|
|
1121
1150
|
/** Total number of samples added (used for ring buffer indexing) @internal */
|
|
1122
|
-
_sampleCount:
|
|
1151
|
+
_sampleCount: field11.int32().default(0),
|
|
1123
1152
|
/** Computed velocity [vx, vy] in pixels per second @internal */
|
|
1124
|
-
_velocity:
|
|
1153
|
+
_velocity: field11.tuple(field11.float32(), 2).default([0, 0])
|
|
1125
1154
|
};
|
|
1126
1155
|
var PointerDef = class extends CanvasComponentDef5 {
|
|
1127
1156
|
constructor() {
|
|
@@ -1232,103 +1261,103 @@ function addPointerSample(pointer, position, time) {
|
|
|
1232
1261
|
}
|
|
1233
1262
|
|
|
1234
1263
|
// src/components/ScaleWithZoom.ts
|
|
1235
|
-
import { defineCanvasComponent as
|
|
1236
|
-
import { field as
|
|
1237
|
-
var ScaleWithZoom =
|
|
1264
|
+
import { defineCanvasComponent as defineCanvasComponent9 } from "@woven-ecs/canvas-store";
|
|
1265
|
+
import { field as field12 } from "@woven-ecs/core";
|
|
1266
|
+
var ScaleWithZoom = defineCanvasComponent9(
|
|
1238
1267
|
{ name: "scaleWithZoom" },
|
|
1239
1268
|
{
|
|
1240
1269
|
/** Pivot point for scaling as [x, y] (0-1, default 0.5,0.5 = center) */
|
|
1241
|
-
anchor:
|
|
1270
|
+
anchor: field12.tuple(field12.float64(), 2).default([0.5, 0.5]),
|
|
1242
1271
|
/** Initial position as [left, top] at zoom=1 */
|
|
1243
|
-
startPosition:
|
|
1272
|
+
startPosition: field12.tuple(field12.float64(), 2).default([0, 0]),
|
|
1244
1273
|
/** Initial size as [width, height] at zoom=1 */
|
|
1245
|
-
startSize:
|
|
1274
|
+
startSize: field12.tuple(field12.float64(), 2).default([0, 0]),
|
|
1246
1275
|
/** Scale multiplier per dimension: [x, y] (0 = no zoom effect, 1 = full zoom effect, 0.5 = half effect) */
|
|
1247
|
-
scaleMultiplier:
|
|
1276
|
+
scaleMultiplier: field12.tuple(field12.float64(), 2).default([1, 1])
|
|
1248
1277
|
}
|
|
1249
1278
|
);
|
|
1250
1279
|
|
|
1251
1280
|
// src/components/Shape.ts
|
|
1252
|
-
import { defineCanvasComponent as
|
|
1253
|
-
import { field as
|
|
1281
|
+
import { defineCanvasComponent as defineCanvasComponent10 } from "@woven-ecs/canvas-store";
|
|
1282
|
+
import { field as field13 } from "@woven-ecs/core";
|
|
1254
1283
|
var StrokeKind = {
|
|
1255
1284
|
Solid: "solid",
|
|
1256
1285
|
Dashed: "dashed",
|
|
1257
1286
|
None: "none"
|
|
1258
1287
|
};
|
|
1259
|
-
var Shape =
|
|
1288
|
+
var Shape = defineCanvasComponent10(
|
|
1260
1289
|
{ name: "shape", sync: "document" },
|
|
1261
1290
|
{
|
|
1262
1291
|
/** The kind of shape to render (e.g. 'rectangle', 'ellipse', or custom shape key) */
|
|
1263
|
-
kind:
|
|
1292
|
+
kind: field13.string().default("rectangle"),
|
|
1264
1293
|
/** Stroke style */
|
|
1265
|
-
strokeKind:
|
|
1294
|
+
strokeKind: field13.enum(StrokeKind).default(StrokeKind.Solid),
|
|
1266
1295
|
/** Stroke width in pixels */
|
|
1267
|
-
strokeWidth:
|
|
1296
|
+
strokeWidth: field13.uint16().default(2),
|
|
1268
1297
|
/** Stroke color - red component (0-255) */
|
|
1269
|
-
strokeRed:
|
|
1298
|
+
strokeRed: field13.uint8().default(0),
|
|
1270
1299
|
/** Stroke color - green component (0-255) */
|
|
1271
|
-
strokeGreen:
|
|
1300
|
+
strokeGreen: field13.uint8().default(0),
|
|
1272
1301
|
/** Stroke color - blue component (0-255) */
|
|
1273
|
-
strokeBlue:
|
|
1302
|
+
strokeBlue: field13.uint8().default(0),
|
|
1274
1303
|
/** Stroke color - alpha component (0-255) */
|
|
1275
|
-
strokeAlpha:
|
|
1304
|
+
strokeAlpha: field13.uint8().default(255),
|
|
1276
1305
|
/** Fill color - red component (0-255) */
|
|
1277
|
-
fillRed:
|
|
1306
|
+
fillRed: field13.uint8().default(255),
|
|
1278
1307
|
/** Fill color - green component (0-255) */
|
|
1279
|
-
fillGreen:
|
|
1308
|
+
fillGreen: field13.uint8().default(255),
|
|
1280
1309
|
/** Fill color - blue component (0-255) */
|
|
1281
|
-
fillBlue:
|
|
1310
|
+
fillBlue: field13.uint8().default(255),
|
|
1282
1311
|
/** Fill color - alpha component (0-255) */
|
|
1283
|
-
fillAlpha:
|
|
1312
|
+
fillAlpha: field13.uint8().default(0)
|
|
1284
1313
|
}
|
|
1285
1314
|
);
|
|
1286
1315
|
|
|
1287
1316
|
// src/components/Text.ts
|
|
1288
|
-
import { defineCanvasComponent as
|
|
1289
|
-
import { field as
|
|
1290
|
-
var Text =
|
|
1317
|
+
import { defineCanvasComponent as defineCanvasComponent11 } from "@woven-ecs/canvas-store";
|
|
1318
|
+
import { field as field14 } from "@woven-ecs/core";
|
|
1319
|
+
var Text = defineCanvasComponent11(
|
|
1291
1320
|
{ name: "text", sync: "document" },
|
|
1292
1321
|
{
|
|
1293
1322
|
/** HTML content (supports rich text formatting) */
|
|
1294
|
-
content:
|
|
1323
|
+
content: field14.string().max(1e4).default(""),
|
|
1295
1324
|
/** Font size in pixels */
|
|
1296
|
-
fontSizePx:
|
|
1325
|
+
fontSizePx: field14.float64().default(24),
|
|
1297
1326
|
/** Font family name */
|
|
1298
|
-
fontFamily:
|
|
1327
|
+
fontFamily: field14.string().max(64).default("Figtree"),
|
|
1299
1328
|
/** Line height multiplier */
|
|
1300
|
-
lineHeight:
|
|
1329
|
+
lineHeight: field14.float64().default(1.2),
|
|
1301
1330
|
/** Letter spacing in em units */
|
|
1302
|
-
letterSpacingEm:
|
|
1331
|
+
letterSpacingEm: field14.float64().default(0),
|
|
1303
1332
|
/** Whether width is constrained (text wraps) */
|
|
1304
|
-
constrainWidth:
|
|
1333
|
+
constrainWidth: field14.boolean().default(true),
|
|
1305
1334
|
/** Default text alignment for new paragraphs */
|
|
1306
|
-
defaultAlignment:
|
|
1335
|
+
defaultAlignment: field14.enum(TextAlignment).default(TextAlignment.Left)
|
|
1307
1336
|
}
|
|
1308
1337
|
);
|
|
1309
1338
|
|
|
1310
1339
|
// src/components/User.ts
|
|
1311
|
-
import { defineCanvasComponent as
|
|
1312
|
-
import { field as
|
|
1313
|
-
var User =
|
|
1340
|
+
import { defineCanvasComponent as defineCanvasComponent12 } from "@woven-ecs/canvas-store";
|
|
1341
|
+
import { field as field15 } from "@woven-ecs/core";
|
|
1342
|
+
var User = defineCanvasComponent12(
|
|
1314
1343
|
{ name: "user", sync: "ephemeral" },
|
|
1315
1344
|
{
|
|
1316
|
-
userId:
|
|
1317
|
-
sessionId:
|
|
1318
|
-
color:
|
|
1319
|
-
name:
|
|
1320
|
-
avatar:
|
|
1321
|
-
position:
|
|
1345
|
+
userId: field15.string().max(36),
|
|
1346
|
+
sessionId: field15.string().max(36),
|
|
1347
|
+
color: field15.string().max(7),
|
|
1348
|
+
name: field15.string().max(100),
|
|
1349
|
+
avatar: field15.string().max(500),
|
|
1350
|
+
position: field15.tuple(field15.float32(), 2).default([0, 0])
|
|
1322
1351
|
}
|
|
1323
1352
|
);
|
|
1324
1353
|
|
|
1325
1354
|
// src/components/VerticalAlign.ts
|
|
1326
|
-
import { defineCanvasComponent as
|
|
1327
|
-
import { field as
|
|
1328
|
-
var VerticalAlign =
|
|
1355
|
+
import { defineCanvasComponent as defineCanvasComponent13 } from "@woven-ecs/canvas-store";
|
|
1356
|
+
import { field as field16 } from "@woven-ecs/core";
|
|
1357
|
+
var VerticalAlign = defineCanvasComponent13(
|
|
1329
1358
|
{ name: "verticalAlign", sync: "document" },
|
|
1330
1359
|
{
|
|
1331
|
-
value:
|
|
1360
|
+
value: field16.enum(VerticalAlignment).default(VerticalAlignment.Top)
|
|
1332
1361
|
}
|
|
1333
1362
|
);
|
|
1334
1363
|
|
|
@@ -1362,20 +1391,20 @@ __export(singletons_exports, {
|
|
|
1362
1391
|
|
|
1363
1392
|
// src/singletons/Camera.ts
|
|
1364
1393
|
import { CanvasSingletonDef as CanvasSingletonDef2 } from "@woven-ecs/canvas-store";
|
|
1365
|
-
import { field as
|
|
1394
|
+
import { field as field18 } from "@woven-ecs/core";
|
|
1366
1395
|
|
|
1367
1396
|
// src/singletons/Screen.ts
|
|
1368
1397
|
import { CanvasSingletonDef } from "@woven-ecs/canvas-store";
|
|
1369
|
-
import { field as
|
|
1398
|
+
import { field as field17 } from "@woven-ecs/core";
|
|
1370
1399
|
var ScreenSchema = {
|
|
1371
1400
|
/** Width of the editor element in pixels */
|
|
1372
|
-
width:
|
|
1401
|
+
width: field17.float64().default(0),
|
|
1373
1402
|
/** Height of the editor element in pixels */
|
|
1374
|
-
height:
|
|
1403
|
+
height: field17.float64().default(0),
|
|
1375
1404
|
/** Left offset of the editor element relative to the viewport */
|
|
1376
|
-
left:
|
|
1405
|
+
left: field17.float64().default(0),
|
|
1377
1406
|
/** Top offset of the editor element relative to the viewport */
|
|
1378
|
-
top:
|
|
1407
|
+
top: field17.float64().default(0)
|
|
1379
1408
|
};
|
|
1380
1409
|
var ScreenDef = class extends CanvasSingletonDef {
|
|
1381
1410
|
constructor() {
|
|
@@ -1402,15 +1431,15 @@ var Screen = new ScreenDef();
|
|
|
1402
1431
|
// src/singletons/Camera.ts
|
|
1403
1432
|
var CameraSchema = {
|
|
1404
1433
|
/** Top position of the camera in world coordinates */
|
|
1405
|
-
top:
|
|
1434
|
+
top: field18.float64().default(0),
|
|
1406
1435
|
/** Left position of the camera in world coordinates */
|
|
1407
|
-
left:
|
|
1436
|
+
left: field18.float64().default(0),
|
|
1408
1437
|
/** Zoom level (1 = 100%, 2 = 200%, 0.5 = 50%) */
|
|
1409
|
-
zoom:
|
|
1438
|
+
zoom: field18.float64().default(1),
|
|
1410
1439
|
/** Whether the camera viewport intersects any blocks */
|
|
1411
|
-
canSeeBlocks:
|
|
1440
|
+
canSeeBlocks: field18.boolean().default(true),
|
|
1412
1441
|
/** Reference to a block that the camera can currently see (for optimization) */
|
|
1413
|
-
lastSeenBlock:
|
|
1442
|
+
lastSeenBlock: field18.ref()
|
|
1414
1443
|
};
|
|
1415
1444
|
var CameraDef = class extends CanvasSingletonDef2 {
|
|
1416
1445
|
constructor() {
|
|
@@ -1486,20 +1515,20 @@ var Camera = new CameraDef();
|
|
|
1486
1515
|
|
|
1487
1516
|
// src/singletons/Controls.ts
|
|
1488
1517
|
import { CanvasSingletonDef as CanvasSingletonDef3 } from "@woven-ecs/canvas-store";
|
|
1489
|
-
import { field as
|
|
1518
|
+
import { field as field19 } from "@woven-ecs/core";
|
|
1490
1519
|
var ControlsSchema = {
|
|
1491
1520
|
/** Tool activated by left mouse button */
|
|
1492
|
-
leftMouseTool:
|
|
1521
|
+
leftMouseTool: field19.string().max(32).default("select"),
|
|
1493
1522
|
/** Tool activated by middle mouse button */
|
|
1494
|
-
middleMouseTool:
|
|
1523
|
+
middleMouseTool: field19.string().max(32).default("hand"),
|
|
1495
1524
|
/** Tool activated by right mouse button */
|
|
1496
|
-
rightMouseTool:
|
|
1525
|
+
rightMouseTool: field19.string().max(32).default("hand"),
|
|
1497
1526
|
/** Tool activated by mouse wheel */
|
|
1498
|
-
wheelTool:
|
|
1527
|
+
wheelTool: field19.string().max(32).default("scroll"),
|
|
1499
1528
|
/** Tool activated by mouse wheel with modifier key held */
|
|
1500
|
-
modWheelTool:
|
|
1529
|
+
modWheelTool: field19.string().max(32).default("zoom"),
|
|
1501
1530
|
/** JSON snapshot of block to place on next click (empty string = no placement active) */
|
|
1502
|
-
heldSnapshot:
|
|
1531
|
+
heldSnapshot: field19.string().max(65536).default("")
|
|
1503
1532
|
};
|
|
1504
1533
|
var ControlsDef = class extends CanvasSingletonDef3 {
|
|
1505
1534
|
constructor() {
|
|
@@ -1541,16 +1570,16 @@ var Controls = new ControlsDef();
|
|
|
1541
1570
|
|
|
1542
1571
|
// src/singletons/Cursor.ts
|
|
1543
1572
|
import { CanvasSingletonDef as CanvasSingletonDef4 } from "@woven-ecs/canvas-store";
|
|
1544
|
-
import { field as
|
|
1573
|
+
import { field as field20 } from "@woven-ecs/core";
|
|
1545
1574
|
var CursorSchema = {
|
|
1546
1575
|
/** Base cursor kind (from current tool) */
|
|
1547
|
-
cursorKind:
|
|
1576
|
+
cursorKind: field20.string().max(64).default("select"),
|
|
1548
1577
|
/** Base cursor rotation in radians */
|
|
1549
|
-
rotation:
|
|
1578
|
+
rotation: field20.float64().default(0),
|
|
1550
1579
|
/** Context-specific cursor kind (overrides cursorKind when set, e.g., during drag/hover) */
|
|
1551
|
-
contextCursorKind:
|
|
1580
|
+
contextCursorKind: field20.string().max(64).default(""),
|
|
1552
1581
|
/** Context cursor rotation in radians */
|
|
1553
|
-
contextRotation:
|
|
1582
|
+
contextRotation: field20.float64().default(0)
|
|
1554
1583
|
};
|
|
1555
1584
|
var CursorDef2 = class extends CanvasSingletonDef4 {
|
|
1556
1585
|
constructor() {
|
|
@@ -1598,37 +1627,37 @@ var Cursor = new CursorDef2();
|
|
|
1598
1627
|
|
|
1599
1628
|
// src/singletons/Frame.ts
|
|
1600
1629
|
import { defineCanvasSingleton } from "@woven-ecs/canvas-store";
|
|
1601
|
-
import { field as
|
|
1630
|
+
import { field as field21 } from "@woven-ecs/core";
|
|
1602
1631
|
var Frame = defineCanvasSingleton(
|
|
1603
1632
|
{ name: "frame" },
|
|
1604
1633
|
{
|
|
1605
1634
|
/** Current frame number (increments each tick) */
|
|
1606
|
-
number:
|
|
1635
|
+
number: field21.uint32().default(0),
|
|
1607
1636
|
/** Time since last frame in seconds */
|
|
1608
|
-
delta:
|
|
1637
|
+
delta: field21.float64().default(0),
|
|
1609
1638
|
/** Timestamp of current frame in milliseconds (from performance.now()) */
|
|
1610
|
-
time:
|
|
1639
|
+
time: field21.float64().default(0),
|
|
1611
1640
|
/** Timestamp of previous frame in milliseconds (0 if first frame) */
|
|
1612
|
-
lastTime:
|
|
1641
|
+
lastTime: field21.float64().default(0)
|
|
1613
1642
|
}
|
|
1614
1643
|
);
|
|
1615
1644
|
|
|
1616
1645
|
// src/singletons/Grid.ts
|
|
1617
1646
|
import { CanvasSingletonDef as CanvasSingletonDef5 } from "@woven-ecs/canvas-store";
|
|
1618
|
-
import { field as
|
|
1647
|
+
import { field as field22 } from "@woven-ecs/core";
|
|
1619
1648
|
var GridSchema = {
|
|
1620
1649
|
/** Whether grid snapping is enabled */
|
|
1621
|
-
enabled:
|
|
1650
|
+
enabled: field22.boolean().default(false),
|
|
1622
1651
|
/** Whether resized/rotated objects must stay aligned to the grid */
|
|
1623
|
-
strict:
|
|
1652
|
+
strict: field22.boolean().default(false),
|
|
1624
1653
|
/** Width of each grid column in world units */
|
|
1625
|
-
colWidth:
|
|
1654
|
+
colWidth: field22.float64().default(20),
|
|
1626
1655
|
/** Height of each grid row in world units */
|
|
1627
|
-
rowHeight:
|
|
1656
|
+
rowHeight: field22.float64().default(20),
|
|
1628
1657
|
/** Angular snap increment in radians when grid is enabled */
|
|
1629
|
-
snapAngleRad:
|
|
1658
|
+
snapAngleRad: field22.float64().default(Math.PI / 36),
|
|
1630
1659
|
/** Angular snap increment in radians when shift key is held */
|
|
1631
|
-
shiftSnapAngleRad:
|
|
1660
|
+
shiftSnapAngleRad: field22.float64().default(Math.PI / 12)
|
|
1632
1661
|
};
|
|
1633
1662
|
var GridDef = class extends CanvasSingletonDef5 {
|
|
1634
1663
|
constructor() {
|
|
@@ -1691,14 +1720,14 @@ var Grid = new GridDef();
|
|
|
1691
1720
|
|
|
1692
1721
|
// src/singletons/Intersect.ts
|
|
1693
1722
|
import { CanvasSingletonDef as CanvasSingletonDef6 } from "@woven-ecs/canvas-store";
|
|
1694
|
-
import { field as
|
|
1723
|
+
import { field as field23 } from "@woven-ecs/core";
|
|
1695
1724
|
var IntersectSchema = {
|
|
1696
1725
|
// Store up to 5 intersected entity IDs
|
|
1697
|
-
entity1:
|
|
1698
|
-
entity2:
|
|
1699
|
-
entity3:
|
|
1700
|
-
entity4:
|
|
1701
|
-
entity5:
|
|
1726
|
+
entity1: field23.ref(),
|
|
1727
|
+
entity2: field23.ref(),
|
|
1728
|
+
entity3: field23.ref(),
|
|
1729
|
+
entity4: field23.ref(),
|
|
1730
|
+
entity5: field23.ref()
|
|
1702
1731
|
};
|
|
1703
1732
|
var IntersectDef = class extends CanvasSingletonDef6 {
|
|
1704
1733
|
constructor() {
|
|
@@ -1750,30 +1779,30 @@ var Intersect = new IntersectDef();
|
|
|
1750
1779
|
|
|
1751
1780
|
// src/singletons/Keyboard.ts
|
|
1752
1781
|
import { CanvasSingletonDef as CanvasSingletonDef7 } from "@woven-ecs/canvas-store";
|
|
1753
|
-
import { field as
|
|
1782
|
+
import { field as field24 } from "@woven-ecs/core";
|
|
1754
1783
|
var KEY_BUFFER_SIZE = 32;
|
|
1755
1784
|
var KeyboardSchema = {
|
|
1756
1785
|
/**
|
|
1757
1786
|
* Buffer where each bit represents whether a key is currently pressed.
|
|
1758
1787
|
* Uses field.buffer for zero-allocation subarray views.
|
|
1759
1788
|
*/
|
|
1760
|
-
keysDown:
|
|
1789
|
+
keysDown: field24.buffer(field24.uint8()).size(KEY_BUFFER_SIZE),
|
|
1761
1790
|
/**
|
|
1762
1791
|
* Buffer for key-down triggers (true for exactly 1 frame when key is pressed).
|
|
1763
1792
|
* Uses field.buffer for zero-allocation subarray views.
|
|
1764
1793
|
*/
|
|
1765
|
-
keysDownTrigger:
|
|
1794
|
+
keysDownTrigger: field24.buffer(field24.uint8()).size(KEY_BUFFER_SIZE),
|
|
1766
1795
|
/**
|
|
1767
1796
|
* Buffer for key-up triggers (true for exactly 1 frame when key is released).
|
|
1768
1797
|
* Uses field.buffer for zero-allocation subarray views.
|
|
1769
1798
|
*/
|
|
1770
|
-
keysUpTrigger:
|
|
1799
|
+
keysUpTrigger: field24.buffer(field24.uint8()).size(KEY_BUFFER_SIZE),
|
|
1771
1800
|
/** Common modifier - Shift key is down */
|
|
1772
|
-
shiftDown:
|
|
1801
|
+
shiftDown: field24.boolean().default(false),
|
|
1773
1802
|
/** Common modifier - Alt/Option key is down */
|
|
1774
|
-
altDown:
|
|
1803
|
+
altDown: field24.boolean().default(false),
|
|
1775
1804
|
/** Common modifier - Ctrl (Windows/Linux) or Cmd (Mac) is down */
|
|
1776
|
-
modDown:
|
|
1805
|
+
modDown: field24.boolean().default(false)
|
|
1777
1806
|
};
|
|
1778
1807
|
function getBit(buffer, bitIndex) {
|
|
1779
1808
|
if (bitIndex < 0 || bitIndex >= buffer.length * 8) return false;
|
|
@@ -2056,24 +2085,24 @@ var Key = {
|
|
|
2056
2085
|
|
|
2057
2086
|
// src/singletons/Mouse.ts
|
|
2058
2087
|
import { CanvasSingletonDef as CanvasSingletonDef8 } from "@woven-ecs/canvas-store";
|
|
2059
|
-
import { field as
|
|
2088
|
+
import { field as field25 } from "@woven-ecs/core";
|
|
2060
2089
|
var MouseSchema = {
|
|
2061
2090
|
/** Current mouse position relative to the editor element [x, y] */
|
|
2062
|
-
position:
|
|
2091
|
+
position: field25.tuple(field25.float32(), 2).default([0, 0]),
|
|
2063
2092
|
/** Horizontal wheel delta (positive = scroll right) */
|
|
2064
|
-
wheelDeltaX:
|
|
2093
|
+
wheelDeltaX: field25.float32().default(0),
|
|
2065
2094
|
/** Vertical wheel delta (positive = scroll down), normalized across browsers */
|
|
2066
|
-
wheelDeltaY:
|
|
2095
|
+
wheelDeltaY: field25.float32().default(0),
|
|
2067
2096
|
/** True for 1 frame when mouse moves */
|
|
2068
|
-
moveTrigger:
|
|
2097
|
+
moveTrigger: field25.boolean().default(false),
|
|
2069
2098
|
/** True for 1 frame when wheel is scrolled */
|
|
2070
|
-
wheelTrigger:
|
|
2099
|
+
wheelTrigger: field25.boolean().default(false),
|
|
2071
2100
|
/** True for 1 frame when mouse enters the editor element */
|
|
2072
|
-
enterTrigger:
|
|
2101
|
+
enterTrigger: field25.boolean().default(false),
|
|
2073
2102
|
/** True for 1 frame when mouse leaves the editor element */
|
|
2074
|
-
leaveTrigger:
|
|
2103
|
+
leaveTrigger: field25.boolean().default(false),
|
|
2075
2104
|
/** Whether the mouse is over a UI element (not the canvas) */
|
|
2076
|
-
obscured:
|
|
2105
|
+
obscured: field25.boolean().default(false)
|
|
2077
2106
|
};
|
|
2078
2107
|
var MouseDef = class extends CanvasSingletonDef8 {
|
|
2079
2108
|
constructor() {
|
|
@@ -2114,11 +2143,11 @@ var Mouse = new MouseDef();
|
|
|
2114
2143
|
|
|
2115
2144
|
// src/singletons/RankBounds.ts
|
|
2116
2145
|
import { CanvasSingletonDef as CanvasSingletonDef9 } from "@woven-ecs/canvas-store";
|
|
2117
|
-
import { field as
|
|
2146
|
+
import { field as field26 } from "@woven-ecs/core";
|
|
2118
2147
|
import { generateJitteredKeyBetween } from "fractional-indexing-jittered";
|
|
2119
2148
|
var RankBoundsSchema = {
|
|
2120
|
-
minRank:
|
|
2121
|
-
maxRank:
|
|
2149
|
+
minRank: field26.string().max(36).default(""),
|
|
2150
|
+
maxRank: field26.string().max(36).default("")
|
|
2122
2151
|
};
|
|
2123
2152
|
var RankBoundsDef = class extends CanvasSingletonDef9 {
|
|
2124
2153
|
constructor() {
|
|
@@ -2177,12 +2206,12 @@ var RankBounds = new RankBoundsDef();
|
|
|
2177
2206
|
|
|
2178
2207
|
// src/singletons/ScaleWithZoomState.ts
|
|
2179
2208
|
import { defineCanvasSingleton as defineCanvasSingleton2 } from "@woven-ecs/canvas-store";
|
|
2180
|
-
import { field as
|
|
2209
|
+
import { field as field27 } from "@woven-ecs/core";
|
|
2181
2210
|
var ScaleWithZoomState = defineCanvasSingleton2(
|
|
2182
2211
|
{ name: "scaleWithZoomState" },
|
|
2183
2212
|
{
|
|
2184
2213
|
/** Last processed zoom level */
|
|
2185
|
-
lastZoom:
|
|
2214
|
+
lastZoom: field27.float64().default(1)
|
|
2186
2215
|
}
|
|
2187
2216
|
);
|
|
2188
2217
|
|
|
@@ -2195,12 +2224,12 @@ import {
|
|
|
2195
2224
|
createEntity,
|
|
2196
2225
|
defineComponent,
|
|
2197
2226
|
defineQuery,
|
|
2198
|
-
field as
|
|
2227
|
+
field as field28,
|
|
2199
2228
|
getResources,
|
|
2200
2229
|
removeEntity
|
|
2201
2230
|
} from "@woven-ecs/core";
|
|
2202
2231
|
var CommandMarker = defineComponent({
|
|
2203
|
-
name:
|
|
2232
|
+
name: field28.string().max(128)
|
|
2204
2233
|
});
|
|
2205
2234
|
var editorPayloads = /* @__PURE__ */ new WeakMap();
|
|
2206
2235
|
function getPayloadMap(ctx) {
|
|
@@ -2339,6 +2368,7 @@ function detachKeyboardListeners(domElement) {
|
|
|
2339
2368
|
}
|
|
2340
2369
|
var keyboardSystem = defineEditorSystem({ phase: "input" }, (ctx) => {
|
|
2341
2370
|
const resources = getResources3(ctx);
|
|
2371
|
+
if (!resources.domElement) return;
|
|
2342
2372
|
const state = instanceState.get(resources.domElement);
|
|
2343
2373
|
if (!state) return;
|
|
2344
2374
|
on(ctx, ResetKeyboard, () => {
|
|
@@ -2440,6 +2470,7 @@ function detachMouseListeners(domElement) {
|
|
|
2440
2470
|
}
|
|
2441
2471
|
var mouseSystem = defineEditorSystem({ phase: "input" }, (ctx) => {
|
|
2442
2472
|
const resources = getResources4(ctx);
|
|
2473
|
+
if (!resources.domElement) return;
|
|
2443
2474
|
const state = instanceState2.get(resources.domElement);
|
|
2444
2475
|
if (!state) return;
|
|
2445
2476
|
const currentMouse = Mouse.read(ctx);
|
|
@@ -2516,9 +2547,12 @@ function attachPointerListeners(domElement) {
|
|
|
2516
2547
|
});
|
|
2517
2548
|
},
|
|
2518
2549
|
onContextMenu: (e) => {
|
|
2550
|
+
if (e.target instanceof HTMLElement && e.target.closest('[contenteditable="true"]')) return;
|
|
2519
2551
|
e.preventDefault();
|
|
2520
|
-
const
|
|
2521
|
-
|
|
2552
|
+
const hasRightButtonEvent = state.eventsBuffer.some(
|
|
2553
|
+
(evt) => evt.button === 2 && (evt.type === "pointerdown" || evt.type === "pointerup")
|
|
2554
|
+
);
|
|
2555
|
+
if (hasRightButtonEvent) return;
|
|
2522
2556
|
state.eventsBuffer.push({
|
|
2523
2557
|
type: "pointerdown",
|
|
2524
2558
|
pointerId: 0,
|
|
@@ -2588,6 +2622,7 @@ function detachPointerListeners(domElement) {
|
|
|
2588
2622
|
var pointerSystem = defineEditorSystem({ phase: "input" }, (ctx) => {
|
|
2589
2623
|
const resources = getResources5(ctx);
|
|
2590
2624
|
const { domElement } = resources;
|
|
2625
|
+
if (!domElement) return;
|
|
2591
2626
|
const state = instanceState3.get(domElement);
|
|
2592
2627
|
if (!state) return;
|
|
2593
2628
|
state.frameCount++;
|
|
@@ -2667,6 +2702,7 @@ function detachScreenObserver(domElement) {
|
|
|
2667
2702
|
var screenSystem = defineEditorSystem({ phase: "input" }, (ctx) => {
|
|
2668
2703
|
const resources = getResources6(ctx);
|
|
2669
2704
|
const { domElement } = resources;
|
|
2705
|
+
if (!domElement) return;
|
|
2670
2706
|
const state = instanceState4.get(domElement);
|
|
2671
2707
|
if (!state) return;
|
|
2672
2708
|
const frame = Frame.read(ctx);
|
|
@@ -2693,6 +2729,7 @@ function getCursorSvg(cursors, kind, rotateZ) {
|
|
|
2693
2729
|
return `url("data:image/svg+xml,${encodeURIComponent(svg.trim())}") ${def.hotspot[0]} ${def.hotspot[1]}, auto`;
|
|
2694
2730
|
}
|
|
2695
2731
|
var cursorSystem = defineEditorSystem({ phase: "render", priority: -100 }, (ctx) => {
|
|
2732
|
+
if (typeof document === "undefined") return;
|
|
2696
2733
|
const changedCursors = cursorQuery.changed(ctx);
|
|
2697
2734
|
const frame = Frame.read(ctx);
|
|
2698
2735
|
if (changedCursors.length === 0 && frame.number !== 1) {
|
|
@@ -2724,8 +2761,8 @@ function getBlockDef(ctx, tag) {
|
|
|
2724
2761
|
function canBlockEdit(ctx, tag) {
|
|
2725
2762
|
return getBlockDef(ctx, tag).editOptions.canEdit;
|
|
2726
2763
|
}
|
|
2727
|
-
function
|
|
2728
|
-
return getBlockDef(ctx, tag).
|
|
2764
|
+
function canBlockInteract(ctx, tag) {
|
|
2765
|
+
return getBlockDef(ctx, tag).interactable;
|
|
2729
2766
|
}
|
|
2730
2767
|
function getBlockResizeMode(ctx, entityId) {
|
|
2731
2768
|
const block = Block.read(ctx, entityId);
|
|
@@ -2749,6 +2786,136 @@ function computeAabb(ctx, entityId, out) {
|
|
|
2749
2786
|
}
|
|
2750
2787
|
}
|
|
2751
2788
|
|
|
2789
|
+
// src/helpers/embed.ts
|
|
2790
|
+
function detectEmbedProvider(url) {
|
|
2791
|
+
try {
|
|
2792
|
+
const parsed = new URL(url);
|
|
2793
|
+
const host = parsed.hostname.replace(/^www\./, "");
|
|
2794
|
+
if (host === "youtube.com" || host === "youtu.be") return "youtube" /* Youtube */;
|
|
2795
|
+
if (host === "open.spotify.com" || host === "spotify.com") return "spotify" /* Spotify */;
|
|
2796
|
+
if (host === "google.com" && parsed.pathname.startsWith("/maps")) return "google-maps" /* GoogleMaps */;
|
|
2797
|
+
if (host === "maps.google.com") return "google-maps" /* GoogleMaps */;
|
|
2798
|
+
if (host === "calendar.google.com") return "google-calendar" /* GoogleCalendar */;
|
|
2799
|
+
if (host === "docs.google.com" && parsed.pathname.includes("/presentation")) return "google-slides" /* GoogleSlides */;
|
|
2800
|
+
if (host === "figma.com" || host.endsWith(".figma.com")) return "figma" /* Figma */;
|
|
2801
|
+
if (host === "gist.github.com") return "github-gist" /* GithubGist */;
|
|
2802
|
+
if (host === "tldraw.com" || host.endsWith(".tldraw.com")) return "tldraw" /* Tldraw */;
|
|
2803
|
+
return "unknown" /* Unknown */;
|
|
2804
|
+
} catch {
|
|
2805
|
+
return "unknown" /* Unknown */;
|
|
2806
|
+
}
|
|
2807
|
+
}
|
|
2808
|
+
function validateEmbedUrl(url, provider) {
|
|
2809
|
+
try {
|
|
2810
|
+
const parsed = new URL(url);
|
|
2811
|
+
const host = parsed.hostname.replace(/^www\./, "");
|
|
2812
|
+
switch (provider) {
|
|
2813
|
+
case "youtube" /* Youtube */: {
|
|
2814
|
+
if (host === "youtu.be") return null;
|
|
2815
|
+
if (host !== "youtube.com") return "URL must be from youtube.com";
|
|
2816
|
+
if (parsed.pathname === "/watch" && parsed.searchParams.has("v")) return null;
|
|
2817
|
+
if (parsed.pathname.startsWith("/embed/")) return null;
|
|
2818
|
+
return "Paste a YouTube video link (e.g. youtube.com/watch?v=...)";
|
|
2819
|
+
}
|
|
2820
|
+
case "spotify" /* Spotify */: {
|
|
2821
|
+
if (host !== "open.spotify.com" && host !== "spotify.com") return "URL must be from open.spotify.com";
|
|
2822
|
+
if (parsed.pathname.length <= 1) return "Paste a Spotify track, album, or playlist link";
|
|
2823
|
+
return null;
|
|
2824
|
+
}
|
|
2825
|
+
case "google-maps" /* GoogleMaps */: {
|
|
2826
|
+
if (host !== "google.com" && host !== "maps.google.com") return "URL must be from google.com/maps";
|
|
2827
|
+
if (!parsed.pathname.startsWith("/maps") && host !== "maps.google.com") return "Paste a Google Maps link";
|
|
2828
|
+
return null;
|
|
2829
|
+
}
|
|
2830
|
+
case "google-calendar" /* GoogleCalendar */: {
|
|
2831
|
+
if (host !== "calendar.google.com") return "URL must be from calendar.google.com";
|
|
2832
|
+
return null;
|
|
2833
|
+
}
|
|
2834
|
+
case "google-slides" /* GoogleSlides */: {
|
|
2835
|
+
if (host !== "docs.google.com") return "URL must be from docs.google.com";
|
|
2836
|
+
if (!parsed.pathname.includes("/presentation/")) return "Paste a Google Slides presentation link";
|
|
2837
|
+
return null;
|
|
2838
|
+
}
|
|
2839
|
+
case "figma" /* Figma */: {
|
|
2840
|
+
if (host !== "figma.com" && !host.endsWith(".figma.com")) return "URL must be from figma.com";
|
|
2841
|
+
return null;
|
|
2842
|
+
}
|
|
2843
|
+
case "github-gist" /* GithubGist */: {
|
|
2844
|
+
if (host !== "gist.github.com") return "URL must be from gist.github.com";
|
|
2845
|
+
return null;
|
|
2846
|
+
}
|
|
2847
|
+
case "tldraw" /* Tldraw */: {
|
|
2848
|
+
if (host !== "tldraw.com" && !host.endsWith(".tldraw.com")) return "URL must be from tldraw.com";
|
|
2849
|
+
return null;
|
|
2850
|
+
}
|
|
2851
|
+
default:
|
|
2852
|
+
return null;
|
|
2853
|
+
}
|
|
2854
|
+
} catch {
|
|
2855
|
+
return "Please enter a valid URL";
|
|
2856
|
+
}
|
|
2857
|
+
}
|
|
2858
|
+
function resolveEmbedUrl(url, provider) {
|
|
2859
|
+
const p = provider ?? detectEmbedProvider(url);
|
|
2860
|
+
try {
|
|
2861
|
+
const parsed = new URL(url);
|
|
2862
|
+
switch (p) {
|
|
2863
|
+
case "youtube" /* Youtube */: {
|
|
2864
|
+
const host = parsed.hostname.replace(/^www\./, "");
|
|
2865
|
+
if (host === "youtu.be") {
|
|
2866
|
+
const videoId2 = parsed.pathname.slice(1);
|
|
2867
|
+
return `https://www.youtube.com/embed/${videoId2}`;
|
|
2868
|
+
}
|
|
2869
|
+
const videoId = parsed.searchParams.get("v");
|
|
2870
|
+
if (videoId && parsed.pathname === "/watch") {
|
|
2871
|
+
return `https://www.youtube.com/embed/${videoId}`;
|
|
2872
|
+
}
|
|
2873
|
+
return url;
|
|
2874
|
+
}
|
|
2875
|
+
case "spotify" /* Spotify */: {
|
|
2876
|
+
if (!parsed.pathname.startsWith("/embed/")) {
|
|
2877
|
+
return `https://open.spotify.com/embed${parsed.pathname}`;
|
|
2878
|
+
}
|
|
2879
|
+
return url;
|
|
2880
|
+
}
|
|
2881
|
+
case "google-maps" /* GoogleMaps */: {
|
|
2882
|
+
if (parsed.pathname.startsWith("/maps/embed")) return url;
|
|
2883
|
+
if (parsed.searchParams.get("output") === "embed") return url;
|
|
2884
|
+
const placeMatch = parsed.pathname.match(/\/maps\/place\/([^/]+)/);
|
|
2885
|
+
if (placeMatch) {
|
|
2886
|
+
return `https://www.google.com/maps?q=${encodeURIComponent(decodeURIComponent(placeMatch[1]))}&output=embed`;
|
|
2887
|
+
}
|
|
2888
|
+
const q = parsed.searchParams.get("q");
|
|
2889
|
+
if (q) {
|
|
2890
|
+
return `https://www.google.com/maps?q=${encodeURIComponent(q)}&output=embed`;
|
|
2891
|
+
}
|
|
2892
|
+
const atMatch = parsed.pathname.match(/\/@(-?[\d.]+),(-?[\d.]+),(\d+\.?\d*)z/);
|
|
2893
|
+
if (atMatch) {
|
|
2894
|
+
const [, lat, lng, zoom] = atMatch;
|
|
2895
|
+
return `https://www.google.com/maps?q=${lat},${lng}&z=${Math.round(parseFloat(zoom))}&output=embed`;
|
|
2896
|
+
}
|
|
2897
|
+
return `https://www.google.com/maps?q=${encodeURIComponent(url)}&output=embed`;
|
|
2898
|
+
}
|
|
2899
|
+
case "google-slides" /* GoogleSlides */: {
|
|
2900
|
+
return url.replace(/\/(edit|pub)(#.*)?(\?.*)?$/, "/embed");
|
|
2901
|
+
}
|
|
2902
|
+
case "figma" /* Figma */: {
|
|
2903
|
+
return `https://www.figma.com/embed?embed_host=share&url=${encodeURIComponent(url)}`;
|
|
2904
|
+
}
|
|
2905
|
+
case "github-gist" /* GithubGist */: {
|
|
2906
|
+
if (!url.endsWith(".pibb")) {
|
|
2907
|
+
return `${url}.pibb`;
|
|
2908
|
+
}
|
|
2909
|
+
return url;
|
|
2910
|
+
}
|
|
2911
|
+
default:
|
|
2912
|
+
return url;
|
|
2913
|
+
}
|
|
2914
|
+
} catch {
|
|
2915
|
+
return url;
|
|
2916
|
+
}
|
|
2917
|
+
}
|
|
2918
|
+
|
|
2752
2919
|
// src/helpers/held.ts
|
|
2753
2920
|
import { getResources as getResources9, hasComponent as hasComponent2 } from "@woven-ecs/core";
|
|
2754
2921
|
function isHeldByRemote(ctx, entityId) {
|
|
@@ -2991,6 +3158,10 @@ var intersectSystem = defineEditorSystem({ phase: "capture", priority: 100 }, (c
|
|
|
2991
3158
|
changed.add(entityId);
|
|
2992
3159
|
}
|
|
2993
3160
|
for (const entityId of added) {
|
|
3161
|
+
if (hasComponent5(ctx, entityId, Block)) {
|
|
3162
|
+
const block = Block.read(ctx, entityId);
|
|
3163
|
+
if (!canBlockInteract(ctx, block.tag)) continue;
|
|
3164
|
+
}
|
|
2994
3165
|
if (!hasComponent5(ctx, entityId, Aabb)) {
|
|
2995
3166
|
addComponent4(ctx, entityId, Aabb, { value: [0, 0, 0, 0] });
|
|
2996
3167
|
}
|
|
@@ -2998,6 +3169,7 @@ var intersectSystem = defineEditorSystem({ phase: "capture", priority: 100 }, (c
|
|
|
2998
3169
|
computeAabb(ctx, entityId, aabb.value);
|
|
2999
3170
|
}
|
|
3000
3171
|
for (const entityId of changed) {
|
|
3172
|
+
if (!hasComponent5(ctx, entityId, Aabb)) continue;
|
|
3001
3173
|
const aabb = Aabb.write(ctx, entityId);
|
|
3002
3174
|
computeAabb(ctx, entityId, aabb.value);
|
|
3003
3175
|
}
|
|
@@ -3018,9 +3190,11 @@ var intersectSystem = defineEditorSystem({ phase: "capture", priority: 100 }, (c
|
|
|
3018
3190
|
}
|
|
3019
3191
|
const resources = getResources11(ctx);
|
|
3020
3192
|
const isObscured = Mouse.isObscured(ctx);
|
|
3021
|
-
const wasObscured = prevObscuredByElement.get(resources.domElement) ?? false;
|
|
3193
|
+
const wasObscured = resources.domElement ? prevObscuredByElement.get(resources.domElement) ?? false : false;
|
|
3022
3194
|
const obscuredChanged = isObscured !== wasObscured;
|
|
3023
|
-
|
|
3195
|
+
if (resources.domElement) {
|
|
3196
|
+
prevObscuredByElement.set(resources.domElement, isObscured);
|
|
3197
|
+
}
|
|
3024
3198
|
if (isObscured) {
|
|
3025
3199
|
clearHovered(ctx);
|
|
3026
3200
|
return;
|
|
@@ -3107,6 +3281,7 @@ import { defineQuery as defineQuery9 } from "@woven-ecs/core";
|
|
|
3107
3281
|
var scaleWithZoomQuery = defineQuery9((q) => q.with(Block).tracking(ScaleWithZoom));
|
|
3108
3282
|
var _scaledSize = [0, 0];
|
|
3109
3283
|
var _anchorOffset = [0, 0];
|
|
3284
|
+
var _anchorAdj = [0, 0];
|
|
3110
3285
|
var scaleWithZoomSystem = defineEditorSystem({ phase: "render", priority: 100 }, (ctx) => {
|
|
3111
3286
|
const camera = Camera.read(ctx);
|
|
3112
3287
|
const state = ScaleWithZoomState.read(ctx);
|
|
@@ -3131,7 +3306,15 @@ function scaleBlock(ctx, entityId, zoom) {
|
|
|
3131
3306
|
_scaledSize[1] = swz.startSize[1] * scaleY;
|
|
3132
3307
|
Vec22.copy(_anchorOffset, swz.startSize);
|
|
3133
3308
|
Vec22.sub(_anchorOffset, _scaledSize);
|
|
3134
|
-
|
|
3309
|
+
if (block.rotateZ !== 0) {
|
|
3310
|
+
_anchorAdj[0] = _anchorOffset[0] * (swz.anchor[0] - 0.5);
|
|
3311
|
+
_anchorAdj[1] = _anchorOffset[1] * (swz.anchor[1] - 0.5);
|
|
3312
|
+
Vec22.rotate(_anchorAdj, block.rotateZ);
|
|
3313
|
+
_anchorOffset[0] = _anchorOffset[0] * 0.5 + _anchorAdj[0];
|
|
3314
|
+
_anchorOffset[1] = _anchorOffset[1] * 0.5 + _anchorAdj[1];
|
|
3315
|
+
} else {
|
|
3316
|
+
Vec22.multiply(_anchorOffset, swz.anchor);
|
|
3317
|
+
}
|
|
3135
3318
|
Vec22.copy(block.position, swz.startPosition);
|
|
3136
3319
|
Vec22.add(block.position, _anchorOffset);
|
|
3137
3320
|
Vec22.copy(block.size, _scaledSize);
|
|
@@ -3171,6 +3354,14 @@ var CorePlugin = {
|
|
|
3171
3354
|
editOptions: {
|
|
3172
3355
|
canEdit: true
|
|
3173
3356
|
}
|
|
3357
|
+
},
|
|
3358
|
+
{
|
|
3359
|
+
tag: "embed",
|
|
3360
|
+
components: [Embed],
|
|
3361
|
+
resizeMode: ResizeMode.Free,
|
|
3362
|
+
editOptions: {
|
|
3363
|
+
canEdit: true
|
|
3364
|
+
}
|
|
3174
3365
|
}
|
|
3175
3366
|
],
|
|
3176
3367
|
systems: [
|
|
@@ -3199,6 +3390,7 @@ var CorePlugin = {
|
|
|
3199
3390
|
],
|
|
3200
3391
|
setup(ctx) {
|
|
3201
3392
|
const { domElement } = getResources12(ctx);
|
|
3393
|
+
if (!domElement) return;
|
|
3202
3394
|
attachKeyboardListeners(domElement);
|
|
3203
3395
|
attachMouseListeners(domElement);
|
|
3204
3396
|
attachScreenObserver(domElement);
|
|
@@ -3206,6 +3398,7 @@ var CorePlugin = {
|
|
|
3206
3398
|
},
|
|
3207
3399
|
teardown(ctx) {
|
|
3208
3400
|
const { domElement } = getResources12(ctx);
|
|
3401
|
+
if (!domElement) return;
|
|
3209
3402
|
detachKeyboardListeners(domElement);
|
|
3210
3403
|
detachMouseListeners(domElement);
|
|
3211
3404
|
detachScreenObserver(domElement);
|
|
@@ -3306,6 +3499,9 @@ var FontLoader = class {
|
|
|
3306
3499
|
*/
|
|
3307
3500
|
loadSingleFont(family) {
|
|
3308
3501
|
this.loadedFonts.add(family.name);
|
|
3502
|
+
if (typeof document === "undefined") {
|
|
3503
|
+
return Promise.resolve();
|
|
3504
|
+
}
|
|
3309
3505
|
return new Promise((resolve, reject) => {
|
|
3310
3506
|
const link = document.createElement("link");
|
|
3311
3507
|
link.rel = "stylesheet";
|
|
@@ -3684,11 +3880,54 @@ var Editor = class {
|
|
|
3684
3880
|
_getContext() {
|
|
3685
3881
|
return this.ctx;
|
|
3686
3882
|
}
|
|
3883
|
+
/**
|
|
3884
|
+
* Attach a DOM element to a headless editor.
|
|
3885
|
+
* Use this after SSR to connect input listeners and enable rendering.
|
|
3886
|
+
*
|
|
3887
|
+
* @param domElement - The DOM element to attach to
|
|
3888
|
+
*
|
|
3889
|
+
* @example
|
|
3890
|
+
* ```typescript
|
|
3891
|
+
* // SSR: create headless editor
|
|
3892
|
+
* const editor = new Editor(null, { plugins: [...] });
|
|
3893
|
+
* await editor.initialize();
|
|
3894
|
+
* editor.tick(); // process initial state
|
|
3895
|
+
*
|
|
3896
|
+
* // Client hydration: attach the DOM
|
|
3897
|
+
* editor.attachDom(document.getElementById('canvas')!);
|
|
3898
|
+
* ```
|
|
3899
|
+
*/
|
|
3900
|
+
attachDom(domElement) {
|
|
3901
|
+
const resources = this.ctx.resources;
|
|
3902
|
+
if (resources.domElement) {
|
|
3903
|
+
throw new Error("Editor already has a DOM element attached. Call detachDom() first.");
|
|
3904
|
+
}
|
|
3905
|
+
resources.domElement = domElement;
|
|
3906
|
+
attachKeyboardListeners(domElement);
|
|
3907
|
+
attachMouseListeners(domElement);
|
|
3908
|
+
attachScreenObserver(domElement);
|
|
3909
|
+
attachPointerListeners(domElement);
|
|
3910
|
+
}
|
|
3911
|
+
/**
|
|
3912
|
+
* Detach the current DOM element.
|
|
3913
|
+
* Removes all input listeners. The editor continues to run headless.
|
|
3914
|
+
*/
|
|
3915
|
+
detachDom() {
|
|
3916
|
+
const resources = this.ctx.resources;
|
|
3917
|
+
const { domElement } = resources;
|
|
3918
|
+
if (!domElement) return;
|
|
3919
|
+
detachKeyboardListeners(domElement);
|
|
3920
|
+
detachMouseListeners(domElement);
|
|
3921
|
+
detachScreenObserver(domElement);
|
|
3922
|
+
detachPointerListeners(domElement);
|
|
3923
|
+
resources.domElement = null;
|
|
3924
|
+
}
|
|
3687
3925
|
/**
|
|
3688
3926
|
* Clean up the editor.
|
|
3689
3927
|
* Call this when done to release resources.
|
|
3690
3928
|
*/
|
|
3691
3929
|
dispose() {
|
|
3930
|
+
this.detachDom();
|
|
3692
3931
|
const plugins = Array.from(this.plugins.values()).reverse();
|
|
3693
3932
|
for (const plugin of plugins) {
|
|
3694
3933
|
if (plugin.teardown) {
|
|
@@ -4005,6 +4244,8 @@ export {
|
|
|
4005
4244
|
Edited,
|
|
4006
4245
|
Editor,
|
|
4007
4246
|
EditorStateDef,
|
|
4247
|
+
Embed,
|
|
4248
|
+
EmbedProvider,
|
|
4008
4249
|
EventType,
|
|
4009
4250
|
FontFamily,
|
|
4010
4251
|
FontLoader,
|
|
@@ -4050,17 +4291,18 @@ export {
|
|
|
4050
4291
|
VerticalAlignment,
|
|
4051
4292
|
addComponent6 as addComponent,
|
|
4052
4293
|
canBlockEdit,
|
|
4053
|
-
|
|
4294
|
+
canBlockInteract,
|
|
4054
4295
|
clearPointerTrackingState,
|
|
4055
4296
|
createEntity5 as createEntity,
|
|
4056
|
-
|
|
4297
|
+
defineCanvasComponent14 as defineCanvasComponent,
|
|
4057
4298
|
defineCanvasSingleton3 as defineCanvasSingleton,
|
|
4058
4299
|
defineCommand,
|
|
4059
4300
|
defineEditorState,
|
|
4060
4301
|
defineEditorSystem,
|
|
4061
4302
|
defineQuery11 as defineQuery,
|
|
4062
4303
|
defineSystem,
|
|
4063
|
-
|
|
4304
|
+
detectEmbedProvider,
|
|
4305
|
+
field29 as field,
|
|
4064
4306
|
getBackrefs,
|
|
4065
4307
|
getBlockDef,
|
|
4066
4308
|
getBlockResizeMode,
|
|
@@ -4081,6 +4323,8 @@ export {
|
|
|
4081
4323
|
parsePlugin,
|
|
4082
4324
|
removeComponent2 as removeComponent,
|
|
4083
4325
|
removeEntity3 as removeEntity,
|
|
4084
|
-
|
|
4326
|
+
resolveEmbedUrl,
|
|
4327
|
+
runMachine,
|
|
4328
|
+
validateEmbedUrl
|
|
4085
4329
|
};
|
|
4086
4330
|
//# sourceMappingURL=index.js.map
|