@xom11/whiteboard 0.24.1 → 0.25.0
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/README.md +85 -12
- package/dist/ai.d.mts +472 -0
- package/dist/ai.d.ts +472 -0
- package/dist/ai.js +2156 -0
- package/dist/ai.js.map +1 -0
- package/dist/ai.mjs +1495 -0
- package/dist/ai.mjs.map +1 -0
- package/dist/catalog.json +4 -4
- package/dist/chunk-73Q7ADVL.mjs +35 -0
- package/dist/chunk-73Q7ADVL.mjs.map +1 -0
- package/dist/{chunk-BKSXPNPQ.mjs → chunk-AYSFWUPK.mjs} +4 -3
- package/dist/chunk-AYSFWUPK.mjs.map +1 -0
- package/dist/chunk-B4NJJZFR.mjs +18 -0
- package/dist/chunk-B4NJJZFR.mjs.map +1 -0
- package/dist/{chunk-LVNCYP4J.mjs → chunk-CJBLJUWG.mjs} +5 -5
- package/dist/{chunk-LVNCYP4J.mjs.map → chunk-CJBLJUWG.mjs.map} +1 -1
- package/dist/{chunk-YIPI3WUL.mjs → chunk-ESVPQWHX.mjs} +5 -5
- package/dist/{chunk-YIPI3WUL.mjs.map → chunk-ESVPQWHX.mjs.map} +1 -1
- package/dist/{chunk-IBTRMWD6.mjs → chunk-I24QOHPU.mjs} +3 -3
- package/dist/{chunk-IBTRMWD6.mjs.map → chunk-I24QOHPU.mjs.map} +1 -1
- package/dist/{chunk-ZBJBQKJ2.mjs → chunk-IHUFOV7L.mjs} +4 -19
- package/dist/chunk-IHUFOV7L.mjs.map +1 -0
- package/dist/{chunk-AZIARTGX.mjs → chunk-M42TGYT6.mjs} +3 -3
- package/dist/{chunk-AZIARTGX.mjs.map → chunk-M42TGYT6.mjs.map} +1 -1
- package/dist/{chunk-WWMQ2VHZ.mjs → chunk-NDEZJKNY.mjs} +4 -4
- package/dist/{chunk-WWMQ2VHZ.mjs.map → chunk-NDEZJKNY.mjs.map} +1 -1
- package/dist/{chunk-CSCF3YFZ.mjs → chunk-ONBCUWVI.mjs} +6 -4
- package/dist/chunk-ONBCUWVI.mjs.map +1 -0
- package/dist/{chunk-6V4SH4JJ.mjs → chunk-REIJZDVZ.mjs} +6 -35
- package/dist/chunk-REIJZDVZ.mjs.map +1 -0
- package/dist/{chunk-4D5CSIJO.mjs → chunk-TB4CL25L.mjs} +10 -8
- package/dist/chunk-TB4CL25L.mjs.map +1 -0
- package/dist/chunk-VNCCIV6O.mjs +938 -0
- package/dist/chunk-VNCCIV6O.mjs.map +1 -0
- package/dist/{chunk-MFOGFFIL.mjs → chunk-VRHWDZ66.mjs} +6 -5
- package/dist/chunk-VRHWDZ66.mjs.map +1 -0
- package/dist/{chunk-CRAPWQKJ.mjs → chunk-YSJOVBCD.mjs} +4 -4
- package/dist/{chunk-CRAPWQKJ.mjs.map → chunk-YSJOVBCD.mjs.map} +1 -1
- package/dist/geometry-2d.d.mts +2 -1
- package/dist/geometry-2d.d.ts +2 -1
- package/dist/geometry-2d.js +1383 -23
- package/dist/geometry-2d.js.map +1 -1
- package/dist/geometry-2d.mjs +7 -5
- package/dist/geometry-3d.d.mts +2 -1
- package/dist/geometry-3d.d.ts +2 -1
- package/dist/geometry-3d.js +2 -2
- package/dist/geometry-3d.js.map +1 -1
- package/dist/geometry-3d.mjs +6 -4
- package/dist/graph-2d.d.mts +2 -1
- package/dist/graph-2d.d.ts +2 -1
- package/dist/graph-2d.js +2 -2
- package/dist/graph-2d.js.map +1 -1
- package/dist/graph-2d.mjs +9 -7
- package/dist/{host-TLIXN4CF.mjs → host-A64ITWVX.mjs} +8 -6
- package/dist/host-A64ITWVX.mjs.map +1 -0
- package/dist/{host-DOAYVL35.mjs → host-L7FMFZUW.mjs} +228 -30
- package/dist/host-L7FMFZUW.mjs.map +1 -0
- package/dist/{host-GKNQBBUE.mjs → host-QK53UYMD.mjs} +12 -10
- package/dist/host-QK53UYMD.mjs.map +1 -0
- package/dist/index.d.mts +4 -616
- package/dist/index.d.ts +4 -616
- package/dist/index.js +8889 -8529
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +21 -1012
- package/dist/index.mjs.map +1 -1
- package/dist/latex.d.mts +2 -1
- package/dist/latex.d.ts +2 -1
- package/dist/render-3WTY7NZB.mjs +9 -0
- package/dist/{render-SA4JTOW3.mjs.map → render-3WTY7NZB.mjs.map} +1 -1
- package/dist/serialize-SRJVKYUG.mjs +8 -0
- package/dist/{serialize-3NZS6A6Q.mjs.map → serialize-SRJVKYUG.mjs.map} +1 -1
- package/dist/{types-rA4slL08.d.ts → types-DWRyCa2m.d.mts} +139 -1
- package/dist/{types-rA4slL08.d.mts → types-DWRyCa2m.d.ts} +139 -1
- package/package.json +6 -1
- package/dist/chunk-4D5CSIJO.mjs.map +0 -1
- package/dist/chunk-6V4SH4JJ.mjs.map +0 -1
- package/dist/chunk-BKSXPNPQ.mjs.map +0 -1
- package/dist/chunk-CSCF3YFZ.mjs.map +0 -1
- package/dist/chunk-MFOGFFIL.mjs.map +0 -1
- package/dist/chunk-ZBJBQKJ2.mjs.map +0 -1
- package/dist/host-DOAYVL35.mjs.map +0 -1
- package/dist/host-GKNQBBUE.mjs.map +0 -1
- package/dist/host-TLIXN4CF.mjs.map +0 -1
- package/dist/render-SA4JTOW3.mjs +0 -8
- package/dist/serialize-3NZS6A6Q.mjs +0 -6
package/dist/geometry-2d.js
CHANGED
|
@@ -5,6 +5,7 @@ var immer = require('immer');
|
|
|
5
5
|
var React = require('react');
|
|
6
6
|
var jsxRuntime = require('react/jsx-runtime');
|
|
7
7
|
var reactDom = require('react-dom');
|
|
8
|
+
var zod = require('zod');
|
|
8
9
|
|
|
9
10
|
function _interopNamespace(e) {
|
|
10
11
|
if (e && e.__esModule) return e;
|
|
@@ -3266,11 +3267,11 @@ function formatMeasure(items) {
|
|
|
3266
3267
|
return items.map((it) => `${it.label} = ${it.value.toFixed(2)}`).join(", ");
|
|
3267
3268
|
}
|
|
3268
3269
|
function ObjectRow(props) {
|
|
3269
|
-
const { obj, state, selected, onSelect, onToggleVisible, onToggleLocked, onRename, onChangeColor, onDelete } = props;
|
|
3270
|
+
const { obj, state, selected, onSelect, onToggleVisible, onToggleLocked, onRename, onChangeColor, onDelete, describe } = props;
|
|
3270
3271
|
const meta = getKindUiMeta(obj.kind);
|
|
3271
3272
|
let title = "";
|
|
3272
3273
|
try {
|
|
3273
|
-
title = getKind(obj.kind).describe(obj, state);
|
|
3274
|
+
title = describe ? describe(obj, state) : getKind(obj.kind).describe(obj, state);
|
|
3274
3275
|
} catch {
|
|
3275
3276
|
title = `${meta.displayName} ${obj.label}`;
|
|
3276
3277
|
}
|
|
@@ -7207,12 +7208,1122 @@ var init_Toast2 = __esm({
|
|
|
7207
7208
|
init_useToast();
|
|
7208
7209
|
}
|
|
7209
7210
|
});
|
|
7210
|
-
|
|
7211
|
+
var NameZ;
|
|
7212
|
+
var init_names = __esm({
|
|
7213
|
+
"src/stamps/geometry-2d/dsl/names.ts"() {
|
|
7214
|
+
NameZ = zod.z.string().regex(/^[A-Za-z][A-Za-z0-9_'₀-₉]{0,11}$/);
|
|
7215
|
+
}
|
|
7216
|
+
});
|
|
7217
|
+
|
|
7218
|
+
// src/stamps/geometry-2d/dsl/kinds/_types.ts
|
|
7219
|
+
function defineModule(m) {
|
|
7220
|
+
return m;
|
|
7221
|
+
}
|
|
7222
|
+
var init_types4 = __esm({
|
|
7223
|
+
"src/stamps/geometry-2d/dsl/kinds/_types.ts"() {
|
|
7224
|
+
}
|
|
7225
|
+
});
|
|
7226
|
+
|
|
7227
|
+
// src/stamps/geometry-2d/dsl/kinds/_shared.ts
|
|
7228
|
+
function emitPointObject(id, name, constraint) {
|
|
7229
|
+
return {
|
|
7230
|
+
id,
|
|
7231
|
+
kind: "point",
|
|
7232
|
+
label: name,
|
|
7233
|
+
...POINT_BASE_FIELDS,
|
|
7234
|
+
attrs: { constraint }
|
|
7235
|
+
};
|
|
7236
|
+
}
|
|
7237
|
+
function resolveTriangleVertices(ctx, vertices) {
|
|
7238
|
+
return [ctx.resolveId(vertices[0]), ctx.resolveId(vertices[1]), ctx.resolveId(vertices[2])];
|
|
7239
|
+
}
|
|
7240
|
+
var POINT_BASE_FIELDS, SHAPE_BASE_FIELDS;
|
|
7241
|
+
var init_shared = __esm({
|
|
7242
|
+
"src/stamps/geometry-2d/dsl/kinds/_shared.ts"() {
|
|
7243
|
+
POINT_BASE_FIELDS = {
|
|
7244
|
+
visible: true,
|
|
7245
|
+
locked: false,
|
|
7246
|
+
layer: "default",
|
|
7247
|
+
schemaVersion: 1
|
|
7248
|
+
};
|
|
7249
|
+
SHAPE_BASE_FIELDS = {
|
|
7250
|
+
visible: true,
|
|
7251
|
+
locked: false,
|
|
7252
|
+
layer: "default",
|
|
7253
|
+
schemaVersion: 1
|
|
7254
|
+
};
|
|
7255
|
+
}
|
|
7256
|
+
});
|
|
7257
|
+
var freeModule;
|
|
7258
|
+
var init_free = __esm({
|
|
7259
|
+
"src/stamps/geometry-2d/dsl/kinds/points/free.ts"() {
|
|
7260
|
+
init_names();
|
|
7261
|
+
init_types4();
|
|
7262
|
+
init_shared();
|
|
7263
|
+
freeModule = defineModule({
|
|
7264
|
+
kind: "free",
|
|
7265
|
+
role: "point",
|
|
7266
|
+
category: "points",
|
|
7267
|
+
prefix: "p",
|
|
7268
|
+
schema: zod.z.object({
|
|
7269
|
+
name: NameZ,
|
|
7270
|
+
kind: zod.z.literal("free"),
|
|
7271
|
+
x: zod.z.number().finite(),
|
|
7272
|
+
y: zod.z.number().finite()
|
|
7273
|
+
}),
|
|
7274
|
+
collectRefs: () => [],
|
|
7275
|
+
emit: (e, ctx) => [{
|
|
7276
|
+
role: "primary",
|
|
7277
|
+
object: emitPointObject(ctx.resolveId(e.name), e.name, { kind: "free", x: e.x, y: e.y })
|
|
7278
|
+
}]
|
|
7279
|
+
});
|
|
7280
|
+
}
|
|
7281
|
+
});
|
|
7282
|
+
var midpointModule;
|
|
7283
|
+
var init_midpoint = __esm({
|
|
7284
|
+
"src/stamps/geometry-2d/dsl/kinds/points/midpoint.ts"() {
|
|
7285
|
+
init_names();
|
|
7286
|
+
init_types4();
|
|
7287
|
+
init_shared();
|
|
7288
|
+
midpointModule = defineModule({
|
|
7289
|
+
kind: "midpoint",
|
|
7290
|
+
role: "point",
|
|
7291
|
+
category: "points",
|
|
7292
|
+
prefix: "p",
|
|
7293
|
+
schema: zod.z.object({
|
|
7294
|
+
name: NameZ,
|
|
7295
|
+
kind: zod.z.literal("midpoint"),
|
|
7296
|
+
p1: NameZ,
|
|
7297
|
+
p2: NameZ
|
|
7298
|
+
}),
|
|
7299
|
+
collectRefs: (e) => [e.p1, e.p2],
|
|
7300
|
+
emit: (e, ctx) => [{
|
|
7301
|
+
role: "primary",
|
|
7302
|
+
object: emitPointObject(
|
|
7303
|
+
ctx.resolveId(e.name),
|
|
7304
|
+
e.name,
|
|
7305
|
+
{ kind: "midpoint", p1: ctx.resolveId(e.p1), p2: ctx.resolveId(e.p2) }
|
|
7306
|
+
)
|
|
7307
|
+
}]
|
|
7308
|
+
});
|
|
7309
|
+
}
|
|
7310
|
+
});
|
|
7311
|
+
var onSegmentModule;
|
|
7312
|
+
var init_onSegment = __esm({
|
|
7313
|
+
"src/stamps/geometry-2d/dsl/kinds/points/onSegment.ts"() {
|
|
7314
|
+
init_names();
|
|
7315
|
+
init_types4();
|
|
7316
|
+
init_shared();
|
|
7317
|
+
onSegmentModule = defineModule({
|
|
7318
|
+
kind: "onSegment",
|
|
7319
|
+
role: "point",
|
|
7320
|
+
category: "points",
|
|
7321
|
+
prefix: "p",
|
|
7322
|
+
schema: zod.z.object({
|
|
7323
|
+
name: NameZ,
|
|
7324
|
+
kind: zod.z.literal("onSegment"),
|
|
7325
|
+
segmentId: NameZ,
|
|
7326
|
+
t: zod.z.number().min(0).max(1)
|
|
7327
|
+
}),
|
|
7328
|
+
collectRefs: (e) => [e.segmentId],
|
|
7329
|
+
emit: (e, ctx) => [{
|
|
7330
|
+
role: "primary",
|
|
7331
|
+
object: emitPointObject(
|
|
7332
|
+
ctx.resolveId(e.name),
|
|
7333
|
+
e.name,
|
|
7334
|
+
{ kind: "onSegment", segmentId: ctx.resolveId(e.segmentId), t: e.t }
|
|
7335
|
+
)
|
|
7336
|
+
}]
|
|
7337
|
+
});
|
|
7338
|
+
}
|
|
7339
|
+
});
|
|
7340
|
+
var onLineModule;
|
|
7341
|
+
var init_onLine = __esm({
|
|
7342
|
+
"src/stamps/geometry-2d/dsl/kinds/points/onLine.ts"() {
|
|
7343
|
+
init_names();
|
|
7344
|
+
init_types4();
|
|
7345
|
+
init_shared();
|
|
7346
|
+
onLineModule = defineModule({
|
|
7347
|
+
kind: "onLine",
|
|
7348
|
+
role: "point",
|
|
7349
|
+
category: "points",
|
|
7350
|
+
prefix: "p",
|
|
7351
|
+
schema: zod.z.object({
|
|
7352
|
+
name: NameZ,
|
|
7353
|
+
kind: zod.z.literal("onLine"),
|
|
7354
|
+
lineId: NameZ,
|
|
7355
|
+
t: zod.z.number().finite()
|
|
7356
|
+
}),
|
|
7357
|
+
collectRefs: (e) => [e.lineId],
|
|
7358
|
+
emit: (e, ctx) => [{
|
|
7359
|
+
role: "primary",
|
|
7360
|
+
object: emitPointObject(
|
|
7361
|
+
ctx.resolveId(e.name),
|
|
7362
|
+
e.name,
|
|
7363
|
+
{ kind: "onLine", lineId: ctx.resolveId(e.lineId), t: e.t }
|
|
7364
|
+
)
|
|
7365
|
+
}]
|
|
7366
|
+
});
|
|
7367
|
+
}
|
|
7368
|
+
});
|
|
7369
|
+
var onCircleModule;
|
|
7370
|
+
var init_onCircle = __esm({
|
|
7371
|
+
"src/stamps/geometry-2d/dsl/kinds/points/onCircle.ts"() {
|
|
7372
|
+
init_names();
|
|
7373
|
+
init_types4();
|
|
7374
|
+
init_shared();
|
|
7375
|
+
onCircleModule = defineModule({
|
|
7376
|
+
kind: "onCircle",
|
|
7377
|
+
role: "point",
|
|
7378
|
+
category: "points",
|
|
7379
|
+
prefix: "p",
|
|
7380
|
+
schema: zod.z.object({
|
|
7381
|
+
name: NameZ,
|
|
7382
|
+
kind: zod.z.literal("onCircle"),
|
|
7383
|
+
circleId: NameZ,
|
|
7384
|
+
theta: zod.z.number().finite()
|
|
7385
|
+
}),
|
|
7386
|
+
collectRefs: (e) => [e.circleId],
|
|
7387
|
+
emit: (e, ctx) => [{
|
|
7388
|
+
role: "primary",
|
|
7389
|
+
object: emitPointObject(
|
|
7390
|
+
ctx.resolveId(e.name),
|
|
7391
|
+
e.name,
|
|
7392
|
+
{ kind: "onCircle", circleId: ctx.resolveId(e.circleId), theta: e.theta }
|
|
7393
|
+
)
|
|
7394
|
+
}]
|
|
7395
|
+
});
|
|
7396
|
+
}
|
|
7397
|
+
});
|
|
7398
|
+
var perpFootModule;
|
|
7399
|
+
var init_perpFoot = __esm({
|
|
7400
|
+
"src/stamps/geometry-2d/dsl/kinds/points/perpFoot.ts"() {
|
|
7401
|
+
init_names();
|
|
7402
|
+
init_types4();
|
|
7403
|
+
init_shared();
|
|
7404
|
+
perpFootModule = defineModule({
|
|
7405
|
+
kind: "perpFoot",
|
|
7406
|
+
role: "point",
|
|
7407
|
+
category: "points",
|
|
7408
|
+
prefix: "p",
|
|
7409
|
+
schema: zod.z.object({
|
|
7410
|
+
name: NameZ,
|
|
7411
|
+
kind: zod.z.literal("perpFoot"),
|
|
7412
|
+
from: NameZ,
|
|
7413
|
+
onLine: NameZ
|
|
7414
|
+
}),
|
|
7415
|
+
collectRefs: (e) => [e.from, e.onLine],
|
|
7416
|
+
emit: (e, ctx) => [{
|
|
7417
|
+
role: "primary",
|
|
7418
|
+
object: emitPointObject(
|
|
7419
|
+
ctx.resolveId(e.name),
|
|
7420
|
+
e.name,
|
|
7421
|
+
{ kind: "perpFoot", from: ctx.resolveId(e.from), onLine: ctx.resolveId(e.onLine) }
|
|
7422
|
+
)
|
|
7423
|
+
}]
|
|
7424
|
+
});
|
|
7425
|
+
}
|
|
7426
|
+
});
|
|
7427
|
+
var circumcenterModule;
|
|
7428
|
+
var init_circumcenter = __esm({
|
|
7429
|
+
"src/stamps/geometry-2d/dsl/kinds/points/circumcenter.ts"() {
|
|
7430
|
+
init_names();
|
|
7431
|
+
init_types4();
|
|
7432
|
+
init_shared();
|
|
7433
|
+
circumcenterModule = defineModule({
|
|
7434
|
+
kind: "circumcenter",
|
|
7435
|
+
role: "point",
|
|
7436
|
+
category: "points",
|
|
7437
|
+
prefix: "p",
|
|
7438
|
+
schema: zod.z.object({
|
|
7439
|
+
name: NameZ,
|
|
7440
|
+
kind: zod.z.literal("circumcenter"),
|
|
7441
|
+
vertices: zod.z.tuple([NameZ, NameZ, NameZ])
|
|
7442
|
+
}),
|
|
7443
|
+
collectRefs: (e) => [...e.vertices],
|
|
7444
|
+
emit: (e, ctx) => [{
|
|
7445
|
+
role: "primary",
|
|
7446
|
+
object: emitPointObject(
|
|
7447
|
+
ctx.resolveId(e.name),
|
|
7448
|
+
e.name,
|
|
7449
|
+
{ kind: "circumcenter", vertices: resolveTriangleVertices(ctx, e.vertices) }
|
|
7450
|
+
)
|
|
7451
|
+
}]
|
|
7452
|
+
});
|
|
7453
|
+
}
|
|
7454
|
+
});
|
|
7455
|
+
var incenterModule;
|
|
7456
|
+
var init_incenter = __esm({
|
|
7457
|
+
"src/stamps/geometry-2d/dsl/kinds/points/incenter.ts"() {
|
|
7458
|
+
init_names();
|
|
7459
|
+
init_types4();
|
|
7460
|
+
init_shared();
|
|
7461
|
+
incenterModule = defineModule({
|
|
7462
|
+
kind: "incenter",
|
|
7463
|
+
role: "point",
|
|
7464
|
+
category: "points",
|
|
7465
|
+
prefix: "p",
|
|
7466
|
+
schema: zod.z.object({
|
|
7467
|
+
name: NameZ,
|
|
7468
|
+
kind: zod.z.literal("incenter"),
|
|
7469
|
+
vertices: zod.z.tuple([NameZ, NameZ, NameZ])
|
|
7470
|
+
}),
|
|
7471
|
+
collectRefs: (e) => [...e.vertices],
|
|
7472
|
+
emit: (e, ctx) => [{
|
|
7473
|
+
role: "primary",
|
|
7474
|
+
object: emitPointObject(
|
|
7475
|
+
ctx.resolveId(e.name),
|
|
7476
|
+
e.name,
|
|
7477
|
+
{ kind: "incenter", vertices: resolveTriangleVertices(ctx, e.vertices) }
|
|
7478
|
+
)
|
|
7479
|
+
}]
|
|
7480
|
+
});
|
|
7481
|
+
}
|
|
7482
|
+
});
|
|
7483
|
+
var centroidModule;
|
|
7484
|
+
var init_centroid = __esm({
|
|
7485
|
+
"src/stamps/geometry-2d/dsl/kinds/points/centroid.ts"() {
|
|
7486
|
+
init_names();
|
|
7487
|
+
init_types4();
|
|
7488
|
+
init_shared();
|
|
7489
|
+
centroidModule = defineModule({
|
|
7490
|
+
kind: "centroid",
|
|
7491
|
+
role: "point",
|
|
7492
|
+
category: "points",
|
|
7493
|
+
prefix: "p",
|
|
7494
|
+
schema: zod.z.object({
|
|
7495
|
+
name: NameZ,
|
|
7496
|
+
kind: zod.z.literal("centroid"),
|
|
7497
|
+
vertices: zod.z.tuple([NameZ, NameZ, NameZ])
|
|
7498
|
+
}),
|
|
7499
|
+
collectRefs: (e) => [...e.vertices],
|
|
7500
|
+
emit: (e, ctx) => [{
|
|
7501
|
+
role: "primary",
|
|
7502
|
+
object: emitPointObject(
|
|
7503
|
+
ctx.resolveId(e.name),
|
|
7504
|
+
e.name,
|
|
7505
|
+
{ kind: "centroid", vertices: resolveTriangleVertices(ctx, e.vertices) }
|
|
7506
|
+
)
|
|
7507
|
+
}]
|
|
7508
|
+
});
|
|
7509
|
+
}
|
|
7510
|
+
});
|
|
7511
|
+
var orthocenterModule;
|
|
7512
|
+
var init_orthocenter = __esm({
|
|
7513
|
+
"src/stamps/geometry-2d/dsl/kinds/points/orthocenter.ts"() {
|
|
7514
|
+
init_names();
|
|
7515
|
+
init_types4();
|
|
7516
|
+
init_shared();
|
|
7517
|
+
orthocenterModule = defineModule({
|
|
7518
|
+
kind: "orthocenter",
|
|
7519
|
+
role: "point",
|
|
7520
|
+
category: "points",
|
|
7521
|
+
prefix: "p",
|
|
7522
|
+
schema: zod.z.object({
|
|
7523
|
+
name: NameZ,
|
|
7524
|
+
kind: zod.z.literal("orthocenter"),
|
|
7525
|
+
vertices: zod.z.tuple([NameZ, NameZ, NameZ])
|
|
7526
|
+
}),
|
|
7527
|
+
collectRefs: (e) => [...e.vertices],
|
|
7528
|
+
emit: (e, ctx) => [{
|
|
7529
|
+
role: "primary",
|
|
7530
|
+
object: emitPointObject(
|
|
7531
|
+
ctx.resolveId(e.name),
|
|
7532
|
+
e.name,
|
|
7533
|
+
{ kind: "orthocenter", vertices: resolveTriangleVertices(ctx, e.vertices) }
|
|
7534
|
+
)
|
|
7535
|
+
}]
|
|
7536
|
+
});
|
|
7537
|
+
}
|
|
7538
|
+
});
|
|
7539
|
+
var intersectionModule;
|
|
7540
|
+
var init_intersection2 = __esm({
|
|
7541
|
+
"src/stamps/geometry-2d/dsl/kinds/points/intersection.ts"() {
|
|
7542
|
+
init_names();
|
|
7543
|
+
init_types4();
|
|
7544
|
+
init_shared();
|
|
7545
|
+
intersectionModule = defineModule({
|
|
7546
|
+
kind: "intersection",
|
|
7547
|
+
role: "point",
|
|
7548
|
+
category: "points",
|
|
7549
|
+
prefix: "i",
|
|
7550
|
+
schema: zod.z.object({
|
|
7551
|
+
name: NameZ,
|
|
7552
|
+
kind: zod.z.literal("intersection"),
|
|
7553
|
+
ref1: NameZ,
|
|
7554
|
+
ref2: NameZ,
|
|
7555
|
+
branch: zod.z.union([zod.z.literal(0), zod.z.literal(1)]).optional()
|
|
7556
|
+
}),
|
|
7557
|
+
collectRefs: (e) => [e.ref1, e.ref2],
|
|
7558
|
+
emit: (e, ctx) => {
|
|
7559
|
+
const r1IsCircle = ctx.hintOf(e.ref1) === "circle";
|
|
7560
|
+
const r2IsCircle = ctx.hintOf(e.ref2) === "circle";
|
|
7561
|
+
let intersectKind;
|
|
7562
|
+
if (r1IsCircle && r2IsCircle) intersectKind = "circleCircle";
|
|
7563
|
+
else if (r1IsCircle || r2IsCircle) intersectKind = "lineCircle";
|
|
7564
|
+
else intersectKind = "lineLine";
|
|
7565
|
+
const attrs = {
|
|
7566
|
+
kind: intersectKind,
|
|
7567
|
+
ref1: ctx.resolveId(e.ref1),
|
|
7568
|
+
ref2: ctx.resolveId(e.ref2)
|
|
7569
|
+
};
|
|
7570
|
+
if (intersectKind !== "lineLine") {
|
|
7571
|
+
attrs.branch = e.branch ?? 0;
|
|
7572
|
+
}
|
|
7573
|
+
return [{
|
|
7574
|
+
role: "primary",
|
|
7575
|
+
object: {
|
|
7576
|
+
id: ctx.resolveId(e.name),
|
|
7577
|
+
kind: "intersection",
|
|
7578
|
+
label: e.name,
|
|
7579
|
+
...POINT_BASE_FIELDS,
|
|
7580
|
+
attrs
|
|
7581
|
+
}
|
|
7582
|
+
}];
|
|
7583
|
+
}
|
|
7584
|
+
});
|
|
7585
|
+
}
|
|
7586
|
+
});
|
|
7587
|
+
var segmentModule;
|
|
7588
|
+
var init_segment2 = __esm({
|
|
7589
|
+
"src/stamps/geometry-2d/dsl/kinds/lines/segment.ts"() {
|
|
7590
|
+
init_names();
|
|
7591
|
+
init_types4();
|
|
7592
|
+
init_shared();
|
|
7593
|
+
segmentModule = defineModule({
|
|
7594
|
+
kind: "segment",
|
|
7595
|
+
role: "segment",
|
|
7596
|
+
category: "lines",
|
|
7597
|
+
prefix: "s",
|
|
7598
|
+
schema: zod.z.object({
|
|
7599
|
+
name: NameZ,
|
|
7600
|
+
kind: zod.z.literal("segment"),
|
|
7601
|
+
p1: NameZ,
|
|
7602
|
+
p2: NameZ
|
|
7603
|
+
}),
|
|
7604
|
+
collectRefs: (e) => [e.p1, e.p2],
|
|
7605
|
+
emit: (e, ctx) => [{
|
|
7606
|
+
role: "primary",
|
|
7607
|
+
object: {
|
|
7608
|
+
id: ctx.resolveId(e.name),
|
|
7609
|
+
kind: "segment",
|
|
7610
|
+
label: e.name,
|
|
7611
|
+
...SHAPE_BASE_FIELDS,
|
|
7612
|
+
attrs: { p1: ctx.resolveId(e.p1), p2: ctx.resolveId(e.p2) }
|
|
7613
|
+
}
|
|
7614
|
+
}]
|
|
7615
|
+
});
|
|
7616
|
+
}
|
|
7617
|
+
});
|
|
7618
|
+
var lineModule;
|
|
7619
|
+
var init_line2 = __esm({
|
|
7620
|
+
"src/stamps/geometry-2d/dsl/kinds/lines/line.ts"() {
|
|
7621
|
+
init_names();
|
|
7622
|
+
init_types4();
|
|
7623
|
+
init_shared();
|
|
7624
|
+
lineModule = defineModule({
|
|
7625
|
+
kind: "line",
|
|
7626
|
+
role: "line",
|
|
7627
|
+
category: "lines",
|
|
7628
|
+
prefix: "l",
|
|
7629
|
+
schema: zod.z.object({
|
|
7630
|
+
name: NameZ,
|
|
7631
|
+
kind: zod.z.literal("line"),
|
|
7632
|
+
p1: NameZ,
|
|
7633
|
+
p2: NameZ
|
|
7634
|
+
}),
|
|
7635
|
+
collectRefs: (e) => [e.p1, e.p2],
|
|
7636
|
+
emit: (e, ctx) => [{
|
|
7637
|
+
role: "primary",
|
|
7638
|
+
object: {
|
|
7639
|
+
id: ctx.resolveId(e.name),
|
|
7640
|
+
kind: "line",
|
|
7641
|
+
label: e.name,
|
|
7642
|
+
...SHAPE_BASE_FIELDS,
|
|
7643
|
+
attrs: { p1: ctx.resolveId(e.p1), p2: ctx.resolveId(e.p2) }
|
|
7644
|
+
}
|
|
7645
|
+
}]
|
|
7646
|
+
});
|
|
7647
|
+
}
|
|
7648
|
+
});
|
|
7649
|
+
var rayModule;
|
|
7650
|
+
var init_ray2 = __esm({
|
|
7651
|
+
"src/stamps/geometry-2d/dsl/kinds/lines/ray.ts"() {
|
|
7652
|
+
init_names();
|
|
7653
|
+
init_types4();
|
|
7654
|
+
init_shared();
|
|
7655
|
+
rayModule = defineModule({
|
|
7656
|
+
kind: "ray",
|
|
7657
|
+
role: "ray",
|
|
7658
|
+
category: "lines",
|
|
7659
|
+
prefix: "r",
|
|
7660
|
+
schema: zod.z.object({
|
|
7661
|
+
name: NameZ,
|
|
7662
|
+
kind: zod.z.literal("ray"),
|
|
7663
|
+
origin: NameZ,
|
|
7664
|
+
through: NameZ
|
|
7665
|
+
}),
|
|
7666
|
+
collectRefs: (e) => [e.origin, e.through],
|
|
7667
|
+
emit: (e, ctx) => [{
|
|
7668
|
+
role: "primary",
|
|
7669
|
+
object: {
|
|
7670
|
+
id: ctx.resolveId(e.name),
|
|
7671
|
+
kind: "ray",
|
|
7672
|
+
label: e.name,
|
|
7673
|
+
...SHAPE_BASE_FIELDS,
|
|
7674
|
+
attrs: { origin: ctx.resolveId(e.origin), through: ctx.resolveId(e.through) }
|
|
7675
|
+
}
|
|
7676
|
+
}]
|
|
7677
|
+
});
|
|
7678
|
+
}
|
|
7679
|
+
});
|
|
7680
|
+
var perpendicularModule;
|
|
7681
|
+
var init_perpendicular = __esm({
|
|
7682
|
+
"src/stamps/geometry-2d/dsl/kinds/lines/perpendicular.ts"() {
|
|
7683
|
+
init_names();
|
|
7684
|
+
init_types4();
|
|
7685
|
+
init_shared();
|
|
7686
|
+
perpendicularModule = defineModule({
|
|
7687
|
+
kind: "perpendicular",
|
|
7688
|
+
role: "lineConstruction",
|
|
7689
|
+
category: "lines",
|
|
7690
|
+
prefix: "l",
|
|
7691
|
+
schema: zod.z.object({
|
|
7692
|
+
name: NameZ,
|
|
7693
|
+
kind: zod.z.literal("perpendicular"),
|
|
7694
|
+
throughPoint: NameZ,
|
|
7695
|
+
toLine: NameZ
|
|
7696
|
+
}),
|
|
7697
|
+
collectRefs: (e) => [e.throughPoint, e.toLine],
|
|
7698
|
+
emit: (e, ctx) => [{
|
|
7699
|
+
role: "primary",
|
|
7700
|
+
object: {
|
|
7701
|
+
id: ctx.resolveId(e.name),
|
|
7702
|
+
kind: "line",
|
|
7703
|
+
label: e.name,
|
|
7704
|
+
...SHAPE_BASE_FIELDS,
|
|
7705
|
+
attrs: {
|
|
7706
|
+
construction: {
|
|
7707
|
+
kind: "perpendicular",
|
|
7708
|
+
throughPoint: ctx.resolveId(e.throughPoint),
|
|
7709
|
+
toLine: ctx.resolveId(e.toLine)
|
|
7710
|
+
}
|
|
7711
|
+
}
|
|
7712
|
+
}
|
|
7713
|
+
}]
|
|
7714
|
+
});
|
|
7715
|
+
}
|
|
7716
|
+
});
|
|
7717
|
+
var parallelModule;
|
|
7718
|
+
var init_parallel = __esm({
|
|
7719
|
+
"src/stamps/geometry-2d/dsl/kinds/lines/parallel.ts"() {
|
|
7720
|
+
init_names();
|
|
7721
|
+
init_types4();
|
|
7722
|
+
init_shared();
|
|
7723
|
+
parallelModule = defineModule({
|
|
7724
|
+
kind: "parallel",
|
|
7725
|
+
role: "lineConstruction",
|
|
7726
|
+
category: "lines",
|
|
7727
|
+
prefix: "l",
|
|
7728
|
+
schema: zod.z.object({
|
|
7729
|
+
name: NameZ,
|
|
7730
|
+
kind: zod.z.literal("parallel"),
|
|
7731
|
+
throughPoint: NameZ,
|
|
7732
|
+
toLine: NameZ
|
|
7733
|
+
}),
|
|
7734
|
+
collectRefs: (e) => [e.throughPoint, e.toLine],
|
|
7735
|
+
emit: (e, ctx) => [{
|
|
7736
|
+
role: "primary",
|
|
7737
|
+
object: {
|
|
7738
|
+
id: ctx.resolveId(e.name),
|
|
7739
|
+
kind: "line",
|
|
7740
|
+
label: e.name,
|
|
7741
|
+
...SHAPE_BASE_FIELDS,
|
|
7742
|
+
attrs: {
|
|
7743
|
+
construction: {
|
|
7744
|
+
kind: "parallel",
|
|
7745
|
+
throughPoint: ctx.resolveId(e.throughPoint),
|
|
7746
|
+
toLine: ctx.resolveId(e.toLine)
|
|
7747
|
+
}
|
|
7748
|
+
}
|
|
7749
|
+
}
|
|
7750
|
+
}]
|
|
7751
|
+
});
|
|
7752
|
+
}
|
|
7753
|
+
});
|
|
7754
|
+
var perpBisectorModule;
|
|
7755
|
+
var init_perpBisector = __esm({
|
|
7756
|
+
"src/stamps/geometry-2d/dsl/kinds/lines/perpBisector.ts"() {
|
|
7757
|
+
init_names();
|
|
7758
|
+
init_types4();
|
|
7759
|
+
init_shared();
|
|
7760
|
+
perpBisectorModule = defineModule({
|
|
7761
|
+
kind: "perpBisector",
|
|
7762
|
+
role: "lineConstruction",
|
|
7763
|
+
category: "lines",
|
|
7764
|
+
prefix: "l",
|
|
7765
|
+
schema: zod.z.object({
|
|
7766
|
+
name: NameZ,
|
|
7767
|
+
kind: zod.z.literal("perpBisector"),
|
|
7768
|
+
p1: NameZ,
|
|
7769
|
+
p2: NameZ
|
|
7770
|
+
}),
|
|
7771
|
+
collectRefs: (e) => [e.p1, e.p2],
|
|
7772
|
+
emit: (e, ctx) => [{
|
|
7773
|
+
role: "primary",
|
|
7774
|
+
object: {
|
|
7775
|
+
id: ctx.resolveId(e.name),
|
|
7776
|
+
kind: "line",
|
|
7777
|
+
label: e.name,
|
|
7778
|
+
...SHAPE_BASE_FIELDS,
|
|
7779
|
+
attrs: {
|
|
7780
|
+
construction: {
|
|
7781
|
+
kind: "perpBisector",
|
|
7782
|
+
p1: ctx.resolveId(e.p1),
|
|
7783
|
+
p2: ctx.resolveId(e.p2)
|
|
7784
|
+
}
|
|
7785
|
+
}
|
|
7786
|
+
}
|
|
7787
|
+
}]
|
|
7788
|
+
});
|
|
7789
|
+
}
|
|
7790
|
+
});
|
|
7791
|
+
var angleBisectorModule;
|
|
7792
|
+
var init_angleBisector = __esm({
|
|
7793
|
+
"src/stamps/geometry-2d/dsl/kinds/lines/angleBisector.ts"() {
|
|
7794
|
+
init_names();
|
|
7795
|
+
init_types4();
|
|
7796
|
+
init_shared();
|
|
7797
|
+
angleBisectorModule = defineModule({
|
|
7798
|
+
kind: "angleBisector",
|
|
7799
|
+
role: "lineConstruction",
|
|
7800
|
+
category: "lines",
|
|
7801
|
+
prefix: "l",
|
|
7802
|
+
schema: zod.z.object({
|
|
7803
|
+
name: NameZ,
|
|
7804
|
+
kind: zod.z.literal("angleBisector"),
|
|
7805
|
+
p1: NameZ,
|
|
7806
|
+
vertex: NameZ,
|
|
7807
|
+
p2: NameZ
|
|
7808
|
+
}),
|
|
7809
|
+
collectRefs: (e) => [e.p1, e.vertex, e.p2],
|
|
7810
|
+
emit: (e, ctx) => [{
|
|
7811
|
+
role: "primary",
|
|
7812
|
+
object: {
|
|
7813
|
+
id: ctx.resolveId(e.name),
|
|
7814
|
+
kind: "line",
|
|
7815
|
+
label: e.name,
|
|
7816
|
+
...SHAPE_BASE_FIELDS,
|
|
7817
|
+
attrs: {
|
|
7818
|
+
construction: {
|
|
7819
|
+
kind: "angleBisector",
|
|
7820
|
+
p1: ctx.resolveId(e.p1),
|
|
7821
|
+
vertex: ctx.resolveId(e.vertex),
|
|
7822
|
+
p2: ctx.resolveId(e.p2)
|
|
7823
|
+
}
|
|
7824
|
+
}
|
|
7825
|
+
}
|
|
7826
|
+
}]
|
|
7827
|
+
});
|
|
7828
|
+
}
|
|
7829
|
+
});
|
|
7830
|
+
var tangentModule;
|
|
7831
|
+
var init_tangent = __esm({
|
|
7832
|
+
"src/stamps/geometry-2d/dsl/kinds/lines/tangent.ts"() {
|
|
7833
|
+
init_names();
|
|
7834
|
+
init_types4();
|
|
7835
|
+
init_shared();
|
|
7836
|
+
tangentModule = defineModule({
|
|
7837
|
+
kind: "tangent",
|
|
7838
|
+
role: "lineConstruction",
|
|
7839
|
+
category: "lines",
|
|
7840
|
+
prefix: "l",
|
|
7841
|
+
schema: zod.z.object({
|
|
7842
|
+
name: NameZ,
|
|
7843
|
+
kind: zod.z.literal("tangent"),
|
|
7844
|
+
throughPoint: NameZ,
|
|
7845
|
+
toCircle: NameZ,
|
|
7846
|
+
branch: zod.z.union([zod.z.literal(0), zod.z.literal(1), zod.z.literal("on")]).optional()
|
|
7847
|
+
}),
|
|
7848
|
+
collectRefs: (e) => [e.throughPoint, e.toCircle],
|
|
7849
|
+
emit: (e, ctx) => {
|
|
7850
|
+
const construction = {
|
|
7851
|
+
kind: "tangent",
|
|
7852
|
+
throughPoint: ctx.resolveId(e.throughPoint),
|
|
7853
|
+
toCircle: ctx.resolveId(e.toCircle)
|
|
7854
|
+
};
|
|
7855
|
+
if (e.branch !== void 0) construction.branch = e.branch;
|
|
7856
|
+
return [{
|
|
7857
|
+
role: "primary",
|
|
7858
|
+
object: {
|
|
7859
|
+
id: ctx.resolveId(e.name),
|
|
7860
|
+
kind: "line",
|
|
7861
|
+
label: e.name,
|
|
7862
|
+
...SHAPE_BASE_FIELDS,
|
|
7863
|
+
attrs: { construction }
|
|
7864
|
+
}
|
|
7865
|
+
}];
|
|
7866
|
+
}
|
|
7867
|
+
});
|
|
7868
|
+
}
|
|
7869
|
+
});
|
|
7870
|
+
var polygonModule;
|
|
7871
|
+
var init_polygon3 = __esm({
|
|
7872
|
+
"src/stamps/geometry-2d/dsl/kinds/polygons/polygon.ts"() {
|
|
7873
|
+
init_names();
|
|
7874
|
+
init_types4();
|
|
7875
|
+
init_shared();
|
|
7876
|
+
polygonModule = defineModule({
|
|
7877
|
+
kind: "polygon",
|
|
7878
|
+
role: "polygon",
|
|
7879
|
+
category: "polygons",
|
|
7880
|
+
prefix: "poly",
|
|
7881
|
+
schema: zod.z.object({
|
|
7882
|
+
name: NameZ,
|
|
7883
|
+
kind: zod.z.literal("polygon"),
|
|
7884
|
+
vertices: zod.z.array(NameZ).min(3)
|
|
7885
|
+
}),
|
|
7886
|
+
collectRefs: (e) => [...e.vertices],
|
|
7887
|
+
emit: (e, ctx) => [{
|
|
7888
|
+
role: "primary",
|
|
7889
|
+
object: {
|
|
7890
|
+
id: ctx.resolveId(e.name),
|
|
7891
|
+
kind: "polygon",
|
|
7892
|
+
label: e.name,
|
|
7893
|
+
...SHAPE_BASE_FIELDS,
|
|
7894
|
+
attrs: { vertices: e.vertices.map((v) => ctx.resolveId(v)) }
|
|
7895
|
+
}
|
|
7896
|
+
}]
|
|
7897
|
+
});
|
|
7898
|
+
}
|
|
7899
|
+
});
|
|
7900
|
+
var circleCPModule;
|
|
7901
|
+
var init_circleCP = __esm({
|
|
7902
|
+
"src/stamps/geometry-2d/dsl/kinds/circles/circleCP.ts"() {
|
|
7903
|
+
init_names();
|
|
7904
|
+
init_types4();
|
|
7905
|
+
init_shared();
|
|
7906
|
+
circleCPModule = defineModule({
|
|
7907
|
+
kind: "circleCP",
|
|
7908
|
+
role: "circle",
|
|
7909
|
+
category: "circles",
|
|
7910
|
+
prefix: "c",
|
|
7911
|
+
schema: zod.z.object({
|
|
7912
|
+
name: NameZ,
|
|
7913
|
+
kind: zod.z.literal("circleCP"),
|
|
7914
|
+
center: NameZ,
|
|
7915
|
+
surfacePoint: NameZ
|
|
7916
|
+
}),
|
|
7917
|
+
collectRefs: (e) => [e.center, e.surfacePoint],
|
|
7918
|
+
emit: (e, ctx) => [{
|
|
7919
|
+
role: "primary",
|
|
7920
|
+
object: {
|
|
7921
|
+
id: ctx.resolveId(e.name),
|
|
7922
|
+
kind: "circle",
|
|
7923
|
+
label: e.name,
|
|
7924
|
+
...SHAPE_BASE_FIELDS,
|
|
7925
|
+
attrs: { center: ctx.resolveId(e.center), surfacePoint: ctx.resolveId(e.surfacePoint) }
|
|
7926
|
+
}
|
|
7927
|
+
}]
|
|
7928
|
+
});
|
|
7929
|
+
}
|
|
7930
|
+
});
|
|
7931
|
+
var circle3Module;
|
|
7932
|
+
var init_circle3 = __esm({
|
|
7933
|
+
"src/stamps/geometry-2d/dsl/kinds/circles/circle3.ts"() {
|
|
7934
|
+
init_names();
|
|
7935
|
+
init_types4();
|
|
7936
|
+
init_shared();
|
|
7937
|
+
circle3Module = defineModule({
|
|
7938
|
+
kind: "circle3",
|
|
7939
|
+
role: "circle",
|
|
7940
|
+
category: "circles",
|
|
7941
|
+
prefix: "c",
|
|
7942
|
+
schema: zod.z.object({
|
|
7943
|
+
name: NameZ,
|
|
7944
|
+
kind: zod.z.literal("circle3"),
|
|
7945
|
+
p1: NameZ,
|
|
7946
|
+
p2: NameZ,
|
|
7947
|
+
p3: NameZ
|
|
7948
|
+
}),
|
|
7949
|
+
collectRefs: (e) => [e.p1, e.p2, e.p3],
|
|
7950
|
+
emit: (e, ctx) => [{
|
|
7951
|
+
role: "primary",
|
|
7952
|
+
object: {
|
|
7953
|
+
id: ctx.resolveId(e.name),
|
|
7954
|
+
kind: "circle",
|
|
7955
|
+
label: e.name,
|
|
7956
|
+
...SHAPE_BASE_FIELDS,
|
|
7957
|
+
attrs: {
|
|
7958
|
+
construction: {
|
|
7959
|
+
kind: "circumscribed",
|
|
7960
|
+
p1: ctx.resolveId(e.p1),
|
|
7961
|
+
p2: ctx.resolveId(e.p2),
|
|
7962
|
+
p3: ctx.resolveId(e.p3)
|
|
7963
|
+
}
|
|
7964
|
+
}
|
|
7965
|
+
}
|
|
7966
|
+
}]
|
|
7967
|
+
});
|
|
7968
|
+
}
|
|
7969
|
+
});
|
|
7970
|
+
var ALL_MODULES, POINT_KINDS;
|
|
7971
|
+
var init_registry2 = __esm({
|
|
7972
|
+
"src/stamps/geometry-2d/dsl/registry.ts"() {
|
|
7973
|
+
init_free();
|
|
7974
|
+
init_midpoint();
|
|
7975
|
+
init_onSegment();
|
|
7976
|
+
init_onLine();
|
|
7977
|
+
init_onCircle();
|
|
7978
|
+
init_perpFoot();
|
|
7979
|
+
init_circumcenter();
|
|
7980
|
+
init_incenter();
|
|
7981
|
+
init_centroid();
|
|
7982
|
+
init_orthocenter();
|
|
7983
|
+
init_intersection2();
|
|
7984
|
+
init_segment2();
|
|
7985
|
+
init_line2();
|
|
7986
|
+
init_ray2();
|
|
7987
|
+
init_perpendicular();
|
|
7988
|
+
init_parallel();
|
|
7989
|
+
init_perpBisector();
|
|
7990
|
+
init_angleBisector();
|
|
7991
|
+
init_tangent();
|
|
7992
|
+
init_polygon3();
|
|
7993
|
+
init_circleCP();
|
|
7994
|
+
init_circle3();
|
|
7995
|
+
ALL_MODULES = [
|
|
7996
|
+
freeModule,
|
|
7997
|
+
midpointModule,
|
|
7998
|
+
onSegmentModule,
|
|
7999
|
+
onLineModule,
|
|
8000
|
+
onCircleModule,
|
|
8001
|
+
perpFootModule,
|
|
8002
|
+
circumcenterModule,
|
|
8003
|
+
incenterModule,
|
|
8004
|
+
centroidModule,
|
|
8005
|
+
orthocenterModule,
|
|
8006
|
+
intersectionModule,
|
|
8007
|
+
segmentModule,
|
|
8008
|
+
lineModule,
|
|
8009
|
+
rayModule,
|
|
8010
|
+
perpendicularModule,
|
|
8011
|
+
parallelModule,
|
|
8012
|
+
perpBisectorModule,
|
|
8013
|
+
angleBisectorModule,
|
|
8014
|
+
tangentModule,
|
|
8015
|
+
polygonModule,
|
|
8016
|
+
circleCPModule,
|
|
8017
|
+
circle3Module
|
|
8018
|
+
];
|
|
8019
|
+
new Map(ALL_MODULES.map((m) => [m.kind, m]));
|
|
8020
|
+
POINT_KINDS = new Set(
|
|
8021
|
+
ALL_MODULES.filter((m) => m.role === "point").map((m) => m.kind)
|
|
8022
|
+
);
|
|
8023
|
+
new Set(
|
|
8024
|
+
ALL_MODULES.filter(
|
|
8025
|
+
(m) => m.role === "segment" || m.role === "line" || m.role === "ray" || m.role === "lineConstruction"
|
|
8026
|
+
).map((m) => m.kind)
|
|
8027
|
+
);
|
|
8028
|
+
new Set(
|
|
8029
|
+
ALL_MODULES.filter((m) => m.role === "circle").map((m) => m.kind)
|
|
8030
|
+
);
|
|
8031
|
+
zod.z.discriminatedUnion(
|
|
8032
|
+
"kind",
|
|
8033
|
+
ALL_MODULES.map((m) => m.schema)
|
|
8034
|
+
);
|
|
8035
|
+
}
|
|
8036
|
+
});
|
|
8037
|
+
|
|
8038
|
+
// src/stamps/geometry-2d/dsl/serialize.ts
|
|
8039
|
+
function isValidName(s) {
|
|
8040
|
+
return NAME_REGEX.test(s);
|
|
8041
|
+
}
|
|
8042
|
+
function labelOf2(id, state) {
|
|
8043
|
+
const obj = state.objects[id];
|
|
8044
|
+
return obj ? obj.label : null;
|
|
8045
|
+
}
|
|
8046
|
+
function resolveRefs(ids, state) {
|
|
8047
|
+
const out = [];
|
|
8048
|
+
for (const id of ids) {
|
|
8049
|
+
const lab = labelOf2(id, state);
|
|
8050
|
+
if (lab == null || !isValidName(lab)) return null;
|
|
8051
|
+
out.push(lab);
|
|
8052
|
+
}
|
|
8053
|
+
return out;
|
|
8054
|
+
}
|
|
8055
|
+
function fail(reason, detail) {
|
|
8056
|
+
return { ok: false, reason, detail };
|
|
8057
|
+
}
|
|
8058
|
+
function serializePoint(obj, state) {
|
|
8059
|
+
const c = obj.attrs?.constraint;
|
|
8060
|
+
if (!c) return fail("unsupported-constraint", "missing");
|
|
8061
|
+
switch (c.kind) {
|
|
8062
|
+
case "free":
|
|
8063
|
+
return { ok: true, entity: { name: obj.label, kind: "free", x: c.x, y: c.y } };
|
|
8064
|
+
case "midpoint": {
|
|
8065
|
+
const refs = resolveRefs([c.p1, c.p2], state);
|
|
8066
|
+
if (!refs) return fail("unresolved-ref", `${c.p1},${c.p2}`);
|
|
8067
|
+
return { ok: true, entity: { name: obj.label, kind: "midpoint", p1: refs[0], p2: refs[1] } };
|
|
8068
|
+
}
|
|
8069
|
+
case "onSegment": {
|
|
8070
|
+
const refs = resolveRefs([c.segmentId], state);
|
|
8071
|
+
if (!refs) return fail("unresolved-ref", c.segmentId);
|
|
8072
|
+
return { ok: true, entity: { name: obj.label, kind: "onSegment", segmentId: refs[0], t: c.t } };
|
|
8073
|
+
}
|
|
8074
|
+
case "onLine": {
|
|
8075
|
+
const refs = resolveRefs([c.lineId], state);
|
|
8076
|
+
if (!refs) return fail("unresolved-ref", c.lineId);
|
|
8077
|
+
return { ok: true, entity: { name: obj.label, kind: "onLine", lineId: refs[0], t: c.t } };
|
|
8078
|
+
}
|
|
8079
|
+
case "onCircle": {
|
|
8080
|
+
const refs = resolveRefs([c.circleId], state);
|
|
8081
|
+
if (!refs) return fail("unresolved-ref", c.circleId);
|
|
8082
|
+
return { ok: true, entity: { name: obj.label, kind: "onCircle", circleId: refs[0], theta: c.theta } };
|
|
8083
|
+
}
|
|
8084
|
+
case "perpFoot": {
|
|
8085
|
+
const refs = resolveRefs([c.from, c.onLine], state);
|
|
8086
|
+
if (!refs) return fail("unresolved-ref", `${c.from},${c.onLine}`);
|
|
8087
|
+
return { ok: true, entity: { name: obj.label, kind: "perpFoot", from: refs[0], onLine: refs[1] } };
|
|
8088
|
+
}
|
|
8089
|
+
case "circumcenter":
|
|
8090
|
+
case "incenter":
|
|
8091
|
+
case "centroid":
|
|
8092
|
+
case "orthocenter": {
|
|
8093
|
+
const refs = resolveRefs(c.vertices, state);
|
|
8094
|
+
if (!refs || refs.length !== 3) return fail("unresolved-ref", c.vertices.join(","));
|
|
8095
|
+
return {
|
|
8096
|
+
ok: true,
|
|
8097
|
+
entity: {
|
|
8098
|
+
name: obj.label,
|
|
8099
|
+
kind: c.kind,
|
|
8100
|
+
vertices: [refs[0], refs[1], refs[2]]
|
|
8101
|
+
}
|
|
8102
|
+
};
|
|
8103
|
+
}
|
|
8104
|
+
// Out of DSL v1:
|
|
8105
|
+
case "onAxis":
|
|
8106
|
+
case "onPolygon":
|
|
8107
|
+
case "transformed":
|
|
8108
|
+
return fail("unsupported-constraint", c.kind);
|
|
8109
|
+
default: {
|
|
8110
|
+
return fail("unsupported-constraint");
|
|
8111
|
+
}
|
|
8112
|
+
}
|
|
8113
|
+
}
|
|
8114
|
+
function serializeIntersection(obj, state) {
|
|
8115
|
+
const a = obj.attrs;
|
|
8116
|
+
const refs = resolveRefs([a.ref1, a.ref2], state);
|
|
8117
|
+
if (!refs) return fail("unresolved-ref", `${a.ref1},${a.ref2}`);
|
|
8118
|
+
if (a.kind === "lineLine") {
|
|
8119
|
+
return { ok: true, entity: { name: obj.label, kind: "intersection", ref1: refs[0], ref2: refs[1] } };
|
|
8120
|
+
}
|
|
8121
|
+
return {
|
|
8122
|
+
ok: true,
|
|
8123
|
+
entity: {
|
|
8124
|
+
name: obj.label,
|
|
8125
|
+
kind: "intersection",
|
|
8126
|
+
ref1: refs[0],
|
|
8127
|
+
ref2: refs[1],
|
|
8128
|
+
branch: a.branch
|
|
8129
|
+
}
|
|
8130
|
+
};
|
|
8131
|
+
}
|
|
8132
|
+
function serializeSegment(obj, state) {
|
|
8133
|
+
const refs = resolveRefs([obj.attrs.p1, obj.attrs.p2], state);
|
|
8134
|
+
if (!refs) return fail("unresolved-ref", `${obj.attrs.p1},${obj.attrs.p2}`);
|
|
8135
|
+
return { ok: true, entity: { name: obj.label, kind: "segment", p1: refs[0], p2: refs[1] } };
|
|
8136
|
+
}
|
|
8137
|
+
function serializeRay(obj, state) {
|
|
8138
|
+
const refs = resolveRefs([obj.attrs.origin, obj.attrs.through], state);
|
|
8139
|
+
if (!refs) return fail("unresolved-ref", `${obj.attrs.origin},${obj.attrs.through}`);
|
|
8140
|
+
return { ok: true, entity: { name: obj.label, kind: "ray", origin: refs[0], through: refs[1] } };
|
|
8141
|
+
}
|
|
8142
|
+
function serializeLine(obj, state) {
|
|
8143
|
+
const a = obj.attrs;
|
|
8144
|
+
const c = a.construction;
|
|
8145
|
+
if (!c) {
|
|
8146
|
+
if (!a.p1 || !a.p2) return fail("unsupported-construction", "missing p1/p2");
|
|
8147
|
+
const refs = resolveRefs([a.p1, a.p2], state);
|
|
8148
|
+
if (!refs) return fail("unresolved-ref", `${a.p1},${a.p2}`);
|
|
8149
|
+
return { ok: true, entity: { name: obj.label, kind: "line", p1: refs[0], p2: refs[1] } };
|
|
8150
|
+
}
|
|
8151
|
+
switch (c.kind) {
|
|
8152
|
+
case "perpendicular":
|
|
8153
|
+
case "parallel": {
|
|
8154
|
+
const refs = resolveRefs([c.throughPoint, c.toLine], state);
|
|
8155
|
+
if (!refs) return fail("unresolved-ref", `${c.throughPoint},${c.toLine}`);
|
|
8156
|
+
return {
|
|
8157
|
+
ok: true,
|
|
8158
|
+
entity: { name: obj.label, kind: c.kind, throughPoint: refs[0], toLine: refs[1] }
|
|
8159
|
+
};
|
|
8160
|
+
}
|
|
8161
|
+
case "perpBisector": {
|
|
8162
|
+
const refs = resolveRefs([c.p1, c.p2], state);
|
|
8163
|
+
if (!refs) return fail("unresolved-ref", `${c.p1},${c.p2}`);
|
|
8164
|
+
return { ok: true, entity: { name: obj.label, kind: "perpBisector", p1: refs[0], p2: refs[1] } };
|
|
8165
|
+
}
|
|
8166
|
+
case "angleBisector": {
|
|
8167
|
+
const refs = resolveRefs([c.p1, c.vertex, c.p2], state);
|
|
8168
|
+
if (!refs) return fail("unresolved-ref", `${c.p1},${c.vertex},${c.p2}`);
|
|
8169
|
+
return {
|
|
8170
|
+
ok: true,
|
|
8171
|
+
entity: {
|
|
8172
|
+
name: obj.label,
|
|
8173
|
+
kind: "angleBisector",
|
|
8174
|
+
p1: refs[0],
|
|
8175
|
+
vertex: refs[1],
|
|
8176
|
+
p2: refs[2]
|
|
8177
|
+
}
|
|
8178
|
+
};
|
|
8179
|
+
}
|
|
8180
|
+
case "tangent": {
|
|
8181
|
+
const refs = resolveRefs([c.throughPoint, c.toCircle], state);
|
|
8182
|
+
if (!refs) return fail("unresolved-ref", `${c.throughPoint},${c.toCircle}`);
|
|
8183
|
+
const entity = c.branch !== void 0 ? {
|
|
8184
|
+
name: obj.label,
|
|
8185
|
+
kind: "tangent",
|
|
8186
|
+
throughPoint: refs[0],
|
|
8187
|
+
toCircle: refs[1],
|
|
8188
|
+
branch: c.branch
|
|
8189
|
+
} : { name: obj.label, kind: "tangent", throughPoint: refs[0], toCircle: refs[1] };
|
|
8190
|
+
return { ok: true, entity };
|
|
8191
|
+
}
|
|
8192
|
+
case "angleBisectorLines":
|
|
8193
|
+
return fail("unsupported-construction", "angleBisectorLines");
|
|
8194
|
+
default: {
|
|
8195
|
+
return fail("unsupported-construction");
|
|
8196
|
+
}
|
|
8197
|
+
}
|
|
8198
|
+
}
|
|
8199
|
+
function serializePolygon(obj, state) {
|
|
8200
|
+
const a = obj.attrs;
|
|
8201
|
+
if (a.construction) return fail("unsupported-construction", a.construction.kind);
|
|
8202
|
+
if (!Array.isArray(a.vertices) || a.vertices.length < 3) {
|
|
8203
|
+
return fail("unsupported-construction", "missing vertices");
|
|
8204
|
+
}
|
|
8205
|
+
const refs = resolveRefs(a.vertices, state);
|
|
8206
|
+
if (!refs) return fail("unresolved-ref", a.vertices.join(","));
|
|
8207
|
+
return { ok: true, entity: { name: obj.label, kind: "polygon", vertices: refs } };
|
|
8208
|
+
}
|
|
8209
|
+
function serializeCircle(obj, state) {
|
|
8210
|
+
const a = obj.attrs;
|
|
8211
|
+
const c = a.construction;
|
|
8212
|
+
if (!c) {
|
|
8213
|
+
if (!a.center || !a.surfacePoint) {
|
|
8214
|
+
return fail("unsupported-construction", "missing center/surfacePoint");
|
|
8215
|
+
}
|
|
8216
|
+
const refs = resolveRefs([a.center, a.surfacePoint], state);
|
|
8217
|
+
if (!refs) return fail("unresolved-ref", `${a.center},${a.surfacePoint}`);
|
|
8218
|
+
return {
|
|
8219
|
+
ok: true,
|
|
8220
|
+
entity: { name: obj.label, kind: "circleCP", center: refs[0], surfacePoint: refs[1] }
|
|
8221
|
+
};
|
|
8222
|
+
}
|
|
8223
|
+
if (c.kind === "circumscribed") {
|
|
8224
|
+
const refs = resolveRefs([c.p1, c.p2, c.p3], state);
|
|
8225
|
+
if (!refs) return fail("unresolved-ref", `${c.p1},${c.p2},${c.p3}`);
|
|
8226
|
+
return {
|
|
8227
|
+
ok: true,
|
|
8228
|
+
entity: { name: obj.label, kind: "circle3", p1: refs[0], p2: refs[1], p3: refs[2] }
|
|
8229
|
+
};
|
|
8230
|
+
}
|
|
8231
|
+
return fail("unsupported-construction");
|
|
8232
|
+
}
|
|
8233
|
+
function serializeObject(obj, state) {
|
|
8234
|
+
if (!isValidName(obj.label)) {
|
|
8235
|
+
return fail("invalid-label", obj.label);
|
|
8236
|
+
}
|
|
8237
|
+
switch (obj.kind) {
|
|
8238
|
+
case "point":
|
|
8239
|
+
return serializePoint(obj, state);
|
|
8240
|
+
case "segment":
|
|
8241
|
+
return serializeSegment(obj, state);
|
|
8242
|
+
case "ray":
|
|
8243
|
+
return serializeRay(obj, state);
|
|
8244
|
+
case "line":
|
|
8245
|
+
return serializeLine(obj, state);
|
|
8246
|
+
case "polygon":
|
|
8247
|
+
return serializePolygon(obj, state);
|
|
8248
|
+
case "circle":
|
|
8249
|
+
return serializeCircle(obj, state);
|
|
8250
|
+
case "intersection":
|
|
8251
|
+
return serializeIntersection(obj, state);
|
|
8252
|
+
default:
|
|
8253
|
+
return fail("unsupported-kind", obj.kind);
|
|
8254
|
+
}
|
|
8255
|
+
}
|
|
8256
|
+
function serializeState(state) {
|
|
8257
|
+
const points = [];
|
|
8258
|
+
const shapes = [];
|
|
8259
|
+
const unsupported = [];
|
|
8260
|
+
for (const id of state.order) {
|
|
8261
|
+
const obj = state.objects[id];
|
|
8262
|
+
if (!obj) continue;
|
|
8263
|
+
const r = serializeObject(obj, state);
|
|
8264
|
+
if (!r.ok) {
|
|
8265
|
+
unsupported.push({
|
|
8266
|
+
id: obj.id,
|
|
8267
|
+
label: obj.label,
|
|
8268
|
+
kind: obj.kind,
|
|
8269
|
+
reason: r.reason,
|
|
8270
|
+
detail: r.detail
|
|
8271
|
+
});
|
|
8272
|
+
continue;
|
|
8273
|
+
}
|
|
8274
|
+
if (POINT_KINDS.has(r.entity.kind)) {
|
|
8275
|
+
points.push(r.entity);
|
|
8276
|
+
} else {
|
|
8277
|
+
shapes.push(r.entity);
|
|
8278
|
+
}
|
|
8279
|
+
}
|
|
8280
|
+
return {
|
|
8281
|
+
dsl: { version: 1, points, shapes },
|
|
8282
|
+
unsupported
|
|
8283
|
+
};
|
|
8284
|
+
}
|
|
8285
|
+
var NAME_REGEX;
|
|
8286
|
+
var init_serialize2 = __esm({
|
|
8287
|
+
"src/stamps/geometry-2d/dsl/serialize.ts"() {
|
|
8288
|
+
init_registry2();
|
|
8289
|
+
NAME_REGEX = /^[A-Za-z][A-Za-z0-9_'₀-₉]{0,11}$/;
|
|
8290
|
+
}
|
|
8291
|
+
});
|
|
8292
|
+
function useAiFigure(generator, options = {}) {
|
|
8293
|
+
const { currentState } = options;
|
|
7211
8294
|
const [prompt, setPrompt] = React.useState("");
|
|
7212
8295
|
const [isLoading, setIsLoading] = React.useState(false);
|
|
7213
8296
|
const [error, setError] = React.useState(null);
|
|
8297
|
+
const [tokens, setTokens] = React.useState(0);
|
|
7214
8298
|
const abortRef = React.useRef(null);
|
|
7215
8299
|
const requestIdRef = React.useRef(0);
|
|
8300
|
+
const { dsl: currentDsl, unsupported, entityCount, hasContent } = React.useMemo(() => {
|
|
8301
|
+
if (!currentState || currentState.order.length === 0) {
|
|
8302
|
+
return {
|
|
8303
|
+
dsl: null,
|
|
8304
|
+
unsupported: [],
|
|
8305
|
+
entityCount: { points: 0, shapes: 0 },
|
|
8306
|
+
hasContent: false
|
|
8307
|
+
};
|
|
8308
|
+
}
|
|
8309
|
+
const { dsl, unsupported: unsupported2 } = serializeState(currentState);
|
|
8310
|
+
return {
|
|
8311
|
+
dsl,
|
|
8312
|
+
unsupported: unsupported2,
|
|
8313
|
+
entityCount: { points: dsl.points.length, shapes: dsl.shapes.length },
|
|
8314
|
+
hasContent: true
|
|
8315
|
+
};
|
|
8316
|
+
}, [currentState]);
|
|
8317
|
+
const hasUnsupported = unsupported.length > 0;
|
|
8318
|
+
const initialMode = hasContent && !hasUnsupported ? "refine" : "build";
|
|
8319
|
+
const [mode, setModeInternal] = React.useState(initialMode);
|
|
8320
|
+
React.useEffect(() => {
|
|
8321
|
+
if (!hasContent && mode === "refine") setModeInternal("build");
|
|
8322
|
+
if (hasUnsupported && mode === "refine") setModeInternal("build");
|
|
8323
|
+
}, [hasContent, hasUnsupported, mode]);
|
|
8324
|
+
const setMode = React.useCallback((next) => {
|
|
8325
|
+
setModeInternal(next);
|
|
8326
|
+
}, []);
|
|
7216
8327
|
React.useEffect(() => () => abortRef.current?.abort(), []);
|
|
7217
8328
|
const submit = React.useCallback(async () => {
|
|
7218
8329
|
const problem = prompt.trim();
|
|
@@ -7230,8 +8341,15 @@ function useAiFigure(generator) {
|
|
|
7230
8341
|
abortRef.current = controller;
|
|
7231
8342
|
setIsLoading(true);
|
|
7232
8343
|
setError(null);
|
|
8344
|
+
setTokens(0);
|
|
7233
8345
|
try {
|
|
7234
|
-
const generated = await generator(problem, {
|
|
8346
|
+
const generated = await generator(problem, {
|
|
8347
|
+
signal: controller.signal,
|
|
8348
|
+
onProgress: (info) => {
|
|
8349
|
+
if (requestId === requestIdRef.current) setTokens(info.tokens);
|
|
8350
|
+
},
|
|
8351
|
+
...mode === "refine" && currentDsl ? { currentDsl } : {}
|
|
8352
|
+
});
|
|
7235
8353
|
if (controller.signal.aborted || requestId !== requestIdRef.current) return null;
|
|
7236
8354
|
if (!generated.ok) {
|
|
7237
8355
|
setError(generated.message);
|
|
@@ -7243,7 +8361,9 @@ function useAiFigure(generator) {
|
|
|
7243
8361
|
return null;
|
|
7244
8362
|
}
|
|
7245
8363
|
if (requestId === requestIdRef.current) {
|
|
7246
|
-
setError(
|
|
8364
|
+
setError(
|
|
8365
|
+
caught instanceof Error && caught.message ? caught.message : "Kh\xF4ng th\u1EC3 d\u1EF1ng h\xECnh b\u1EB1ng AI."
|
|
8366
|
+
);
|
|
7247
8367
|
}
|
|
7248
8368
|
return null;
|
|
7249
8369
|
} finally {
|
|
@@ -7252,27 +8372,75 @@ function useAiFigure(generator) {
|
|
|
7252
8372
|
setIsLoading(false);
|
|
7253
8373
|
}
|
|
7254
8374
|
}
|
|
7255
|
-
}, [generator, prompt]);
|
|
7256
|
-
|
|
8375
|
+
}, [generator, prompt, mode, currentDsl]);
|
|
8376
|
+
const cancel = React.useCallback(() => {
|
|
8377
|
+
abortRef.current?.abort();
|
|
8378
|
+
}, []);
|
|
8379
|
+
return {
|
|
8380
|
+
prompt,
|
|
8381
|
+
setPrompt,
|
|
8382
|
+
isLoading,
|
|
8383
|
+
error,
|
|
8384
|
+
submit,
|
|
8385
|
+
cancel,
|
|
8386
|
+
tokens,
|
|
8387
|
+
mode,
|
|
8388
|
+
setMode,
|
|
8389
|
+
entityCount,
|
|
8390
|
+
hasUnsupported
|
|
8391
|
+
};
|
|
7257
8392
|
}
|
|
7258
8393
|
var init_useAiFigure = __esm({
|
|
7259
8394
|
"src/stamps/geometry-2d/editor/useAiFigure.ts"() {
|
|
7260
8395
|
"use client";
|
|
8396
|
+
init_serialize2();
|
|
7261
8397
|
}
|
|
7262
8398
|
});
|
|
7263
|
-
function AiFigurePrompt({ generator, onGenerated }) {
|
|
8399
|
+
function AiFigurePrompt({ generator, onGenerated, currentState }) {
|
|
7264
8400
|
const {
|
|
7265
8401
|
prompt,
|
|
7266
8402
|
setPrompt,
|
|
7267
8403
|
isLoading,
|
|
7268
8404
|
error,
|
|
7269
|
-
submit
|
|
7270
|
-
|
|
7271
|
-
|
|
7272
|
-
|
|
7273
|
-
|
|
7274
|
-
|
|
7275
|
-
|
|
8405
|
+
submit,
|
|
8406
|
+
cancel,
|
|
8407
|
+
tokens,
|
|
8408
|
+
mode,
|
|
8409
|
+
setMode,
|
|
8410
|
+
entityCount,
|
|
8411
|
+
hasUnsupported
|
|
8412
|
+
} = useAiFigure(generator, { currentState });
|
|
8413
|
+
const [elapsed, setElapsed] = React.useState(0);
|
|
8414
|
+
React.useEffect(() => {
|
|
8415
|
+
if (!isLoading) {
|
|
8416
|
+
setElapsed(0);
|
|
8417
|
+
return;
|
|
8418
|
+
}
|
|
8419
|
+
setElapsed(0);
|
|
8420
|
+
const id = setInterval(() => setElapsed((s) => s + 1), 1e3);
|
|
8421
|
+
return () => clearInterval(id);
|
|
8422
|
+
}, [isLoading]);
|
|
8423
|
+
const handleSubmit = React.useCallback(
|
|
8424
|
+
async (event) => {
|
|
8425
|
+
event.preventDefault();
|
|
8426
|
+
const generated = await submit();
|
|
8427
|
+
if (generated) onGenerated(generated);
|
|
8428
|
+
},
|
|
8429
|
+
[onGenerated, submit]
|
|
8430
|
+
);
|
|
8431
|
+
const handleSwitchToBuild = React.useCallback(() => {
|
|
8432
|
+
if (currentState && currentState.order.length > 0) {
|
|
8433
|
+
const ok = window.confirm(
|
|
8434
|
+
"D\u1EF1ng m\u1EDBi s\u1EBD thay to\xE0n b\u1ED9 h\xECnh hi\u1EC7n t\u1EA1i b\u1EB1ng h\xECnh m\u1EDBi t\u1EEB AI. Ti\u1EBFp t\u1EE5c?"
|
|
8435
|
+
);
|
|
8436
|
+
if (!ok) return;
|
|
8437
|
+
}
|
|
8438
|
+
setMode("build");
|
|
8439
|
+
}, [currentState, setMode]);
|
|
8440
|
+
const primaryLabel = isLoading ? tokens > 0 ? `\u0110ang d\u1EF1ng ${tokens}tok / ${elapsed}s \u2014 Hu\u1EF7` : `\u0110ang d\u1EF1ng... ${elapsed}s \u2014 Hu\u1EF7` : "D\u1EF1ng b\u1EB1ng AI";
|
|
8441
|
+
const hasContent = currentState != null && currentState.order.length > 0;
|
|
8442
|
+
const examples = mode === "refine" ? REFINE_EXAMPLES : BUILD_EXAMPLES;
|
|
8443
|
+
const refineChipLabel = entityCount.points + entityCount.shapes > 0 ? `Th\xEAm v\xE0o \xB7 ${entityCount.points}\u0111, ${entityCount.shapes}\u0111o\u1EA1n` : "Th\xEAm v\xE0o";
|
|
7276
8444
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
7277
8445
|
"form",
|
|
7278
8446
|
{
|
|
@@ -7282,7 +8450,47 @@ function AiFigurePrompt({ generator, onGenerated }) {
|
|
|
7282
8450
|
},
|
|
7283
8451
|
className: "border-b border-slate-200 bg-slate-50 px-3 py-2",
|
|
7284
8452
|
children: [
|
|
7285
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8453
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8454
|
+
"label",
|
|
8455
|
+
{
|
|
8456
|
+
htmlFor: "geometry-ai-prompt",
|
|
8457
|
+
className: "mb-1 block text-xs font-medium text-slate-600",
|
|
8458
|
+
children: "D\u1EF1ng h\xECnh b\u1EB1ng AI"
|
|
8459
|
+
}
|
|
8460
|
+
),
|
|
8461
|
+
hasContent && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-2 flex items-center gap-2", children: [
|
|
8462
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8463
|
+
"button",
|
|
8464
|
+
{
|
|
8465
|
+
type: "button",
|
|
8466
|
+
"data-testid": "geometry-ai-mode-refine",
|
|
8467
|
+
onClick: () => setMode("refine"),
|
|
8468
|
+
disabled: isLoading || hasUnsupported,
|
|
8469
|
+
className: `rounded-full border px-2 py-0.5 text-[11px] transition ${mode === "refine" ? "border-emerald-600 bg-emerald-100 text-emerald-800" : "border-slate-300 bg-white text-slate-600 hover:border-emerald-400"} ${hasUnsupported ? "cursor-not-allowed opacity-50" : ""}`,
|
|
8470
|
+
title: hasUnsupported ? "H\xECnh hi\u1EC7n t\u1EA1i c\xF3 \u0111\u1ED1i t\u01B0\u1EE3ng ngo\xE0i DSL \u2014 ch\u1EC9 d\u1EF1ng m\u1EDBi \u0111\u01B0\u1EE3c" : refineChipLabel,
|
|
8471
|
+
children: refineChipLabel
|
|
8472
|
+
}
|
|
8473
|
+
),
|
|
8474
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8475
|
+
"button",
|
|
8476
|
+
{
|
|
8477
|
+
type: "button",
|
|
8478
|
+
"data-testid": "geometry-ai-mode-build",
|
|
8479
|
+
onClick: handleSwitchToBuild,
|
|
8480
|
+
disabled: isLoading,
|
|
8481
|
+
className: `rounded-full border px-2 py-0.5 text-[11px] transition ${mode === "build" ? "border-emerald-600 bg-emerald-100 text-emerald-800" : "border-slate-300 bg-white text-slate-600 hover:border-emerald-400"}`,
|
|
8482
|
+
children: "D\u1EF1ng m\u1EDBi"
|
|
8483
|
+
}
|
|
8484
|
+
),
|
|
8485
|
+
hasUnsupported && /* @__PURE__ */ jsxRuntime.jsx(
|
|
8486
|
+
"span",
|
|
8487
|
+
{
|
|
8488
|
+
className: "text-[10px] text-amber-700",
|
|
8489
|
+
"data-testid": "geometry-ai-unsupported-warning",
|
|
8490
|
+
children: "H\xECnh c\xF3 \u0111\u1ED1i t\u01B0\u1EE3ng ngo\xE0i DSL"
|
|
8491
|
+
}
|
|
8492
|
+
)
|
|
8493
|
+
] }),
|
|
7286
8494
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-2", children: [
|
|
7287
8495
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7288
8496
|
"textarea",
|
|
@@ -7293,29 +8501,63 @@ function AiFigurePrompt({ generator, onGenerated }) {
|
|
|
7293
8501
|
onChange: (event) => setPrompt(event.target.value),
|
|
7294
8502
|
disabled: isLoading,
|
|
7295
8503
|
rows: 2,
|
|
7296
|
-
placeholder: "V\xED d\u1EE5: Cho tam gi\xE1c ABC, d\u1EF1ng \u0111\u01B0\u1EDDng cao AH.",
|
|
8504
|
+
placeholder: mode === "refine" ? "V\xED d\u1EE5: th\xEAm trung \u0111i\u1EC3m M c\u1EE7a BC" : "V\xED d\u1EE5: Cho tam gi\xE1c ABC, d\u1EF1ng \u0111\u01B0\u1EDDng cao AH.",
|
|
7297
8505
|
className: "min-h-12 flex-1 resize-none rounded border border-slate-300 bg-white px-2 py-1.5 text-xs text-slate-800 outline-none focus:border-emerald-500 disabled:opacity-60"
|
|
7298
8506
|
}
|
|
7299
8507
|
),
|
|
7300
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8508
|
+
isLoading ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
8509
|
+
"button",
|
|
8510
|
+
{
|
|
8511
|
+
type: "button",
|
|
8512
|
+
onClick: cancel,
|
|
8513
|
+
className: "rounded bg-amber-600 px-3 py-2 text-xs font-medium text-white transition hover:bg-amber-700",
|
|
8514
|
+
children: primaryLabel
|
|
8515
|
+
}
|
|
8516
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
7301
8517
|
"button",
|
|
7302
8518
|
{
|
|
7303
8519
|
type: "submit",
|
|
7304
|
-
disabled:
|
|
8520
|
+
disabled: !prompt.trim(),
|
|
7305
8521
|
className: "rounded bg-emerald-600 px-3 py-2 text-xs font-medium text-white transition hover:bg-emerald-700 disabled:opacity-50",
|
|
7306
|
-
children:
|
|
8522
|
+
children: primaryLabel
|
|
7307
8523
|
}
|
|
7308
8524
|
)
|
|
7309
8525
|
] }),
|
|
7310
|
-
error && /* @__PURE__ */ jsxRuntime.jsx("p", { role: "alert", className: "mt-1 text-xs text-red-600", children: error })
|
|
8526
|
+
error && /* @__PURE__ */ jsxRuntime.jsx("p", { role: "alert", className: "mt-1 text-xs text-red-600", children: error }),
|
|
8527
|
+
!isLoading && !prompt.trim() && !error && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-1.5 flex flex-wrap items-center gap-1", children: [
|
|
8528
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-slate-500", children: "G\u1EE3i \xFD:" }),
|
|
8529
|
+
examples.map((ex) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
8530
|
+
"button",
|
|
8531
|
+
{
|
|
8532
|
+
type: "button",
|
|
8533
|
+
onClick: () => setPrompt(ex),
|
|
8534
|
+
className: "rounded-full border border-slate-300 bg-white px-2 py-0.5 text-[10px] text-slate-600 transition hover:border-emerald-400 hover:bg-emerald-50 hover:text-emerald-700",
|
|
8535
|
+
children: ex
|
|
8536
|
+
},
|
|
8537
|
+
ex
|
|
8538
|
+
))
|
|
8539
|
+
] })
|
|
7311
8540
|
]
|
|
7312
8541
|
}
|
|
7313
8542
|
);
|
|
7314
8543
|
}
|
|
8544
|
+
var BUILD_EXAMPLES, REFINE_EXAMPLES;
|
|
7315
8545
|
var init_AiFigurePrompt = __esm({
|
|
7316
8546
|
"src/stamps/geometry-2d/editor/AiFigurePrompt.tsx"() {
|
|
7317
8547
|
"use client";
|
|
7318
8548
|
init_useAiFigure();
|
|
8549
|
+
BUILD_EXAMPLES = [
|
|
8550
|
+
"Tam gi\xE1c ABC, d\u1EF1ng trung \u0111i\u1EC3m M c\u1EE7a BC",
|
|
8551
|
+
"Tam gi\xE1c ABC vu\xF4ng t\u1EA1i A, AH l\xE0 \u0111\u01B0\u1EDDng cao xu\u1ED1ng BC",
|
|
8552
|
+
"H\xECnh thoi ABCD, hai \u0111\u01B0\u1EDDng ch\xE9o c\u1EAFt nhau t\u1EA1i O",
|
|
8553
|
+
"T\u1EEB \u0111i\u1EC3m M ngo\xE0i \u0111\u01B0\u1EDDng tr\xF2n (O), k\u1EBB hai ti\u1EBFp tuy\u1EBFn"
|
|
8554
|
+
];
|
|
8555
|
+
REFINE_EXAMPLES = [
|
|
8556
|
+
"Th\xEAm trung \u0111i\u1EC3m M c\u1EE7a BC",
|
|
8557
|
+
"D\u1EF1ng \u0111\u01B0\u1EDDng cao AH xu\u1ED1ng BC",
|
|
8558
|
+
"V\u1EBD \u0111\u01B0\u1EDDng tr\xF2n ngo\u1EA1i ti\u1EBFp",
|
|
8559
|
+
"Th\xEAm ti\u1EBFp tuy\u1EBFn t\u1EA1i A"
|
|
8560
|
+
];
|
|
7319
8561
|
}
|
|
7320
8562
|
});
|
|
7321
8563
|
var GeometryEditorPanelInner, GeometryEditorPanel;
|
|
@@ -7366,6 +8608,11 @@ var init_EditorPanel = __esm({
|
|
|
7366
8608
|
onSelectionChangeRef.current = onSelectionChange;
|
|
7367
8609
|
}, [onSelectionChange]);
|
|
7368
8610
|
useEditorState({ store, onHistoryChange });
|
|
8611
|
+
const currentSceneState = React.useSyncExternalStore(
|
|
8612
|
+
(cb) => store.subscribe(cb),
|
|
8613
|
+
() => store.getState(),
|
|
8614
|
+
() => store.getState()
|
|
8615
|
+
);
|
|
7369
8616
|
React.useEffect(() => {
|
|
7370
8617
|
const sync = () => setHasContent(Object.keys(store.getState().objects).length > 0);
|
|
7371
8618
|
sync();
|
|
@@ -7559,7 +8806,7 @@ var init_EditorPanel = __esm({
|
|
|
7559
8806
|
/* @__PURE__ */ jsxRuntime.jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" })
|
|
7560
8807
|
] }) })
|
|
7561
8808
|
] }),
|
|
7562
|
-
generateGeometryFigure && /* @__PURE__ */ jsxRuntime.jsx(AiFigurePrompt, { generator: generateGeometryFigure, onGenerated: loadAiFigure }),
|
|
8809
|
+
generateGeometryFigure && /* @__PURE__ */ jsxRuntime.jsx(AiFigurePrompt, { generator: generateGeometryFigure, onGenerated: loadAiFigure, currentState: currentSceneState }),
|
|
7563
8810
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex min-h-0 flex-1", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
7564
8811
|
MiniBoard2D,
|
|
7565
8812
|
{
|
|
@@ -7850,6 +9097,116 @@ var init_useStampStore = __esm({
|
|
|
7850
9097
|
}
|
|
7851
9098
|
});
|
|
7852
9099
|
|
|
9100
|
+
// src/stamps/geometry-2d/dsl/describeDsl.ts
|
|
9101
|
+
function describeEntity(e) {
|
|
9102
|
+
switch (e.kind) {
|
|
9103
|
+
case "free":
|
|
9104
|
+
return `${e.name} = (${e.x}, ${e.y})`;
|
|
9105
|
+
case "midpoint":
|
|
9106
|
+
return `${e.name} = trung \u0111i\u1EC3m ${e.p1}${e.p2}`;
|
|
9107
|
+
case "onSegment":
|
|
9108
|
+
return `${e.name} \u2208 \u0111o\u1EA1n ${e.segmentId} (t = ${e.t})`;
|
|
9109
|
+
case "onLine":
|
|
9110
|
+
return `${e.name} \u2208 \u0111\u01B0\u1EDDng ${e.lineId} (t = ${e.t})`;
|
|
9111
|
+
case "onCircle":
|
|
9112
|
+
return `${e.name} \u2208 \u0111\u01B0\u1EDDng tr\xF2n ${e.circleId} (\u03B8 = ${e.theta})`;
|
|
9113
|
+
case "perpFoot":
|
|
9114
|
+
return `${e.name} = ch\xE2n vu\xF4ng g\xF3c t\u1EEB ${e.from} xu\u1ED1ng ${e.onLine}`;
|
|
9115
|
+
case "circumcenter":
|
|
9116
|
+
return `${e.name} = t\xE2m ngo\u1EA1i ti\u1EBFp ${e.vertices.join("")}`;
|
|
9117
|
+
case "incenter":
|
|
9118
|
+
return `${e.name} = t\xE2m n\u1ED9i ti\u1EBFp ${e.vertices.join("")}`;
|
|
9119
|
+
case "centroid":
|
|
9120
|
+
return `${e.name} = tr\u1ECDng t\xE2m ${e.vertices.join("")}`;
|
|
9121
|
+
case "orthocenter":
|
|
9122
|
+
return `${e.name} = tr\u1EF1c t\xE2m ${e.vertices.join("")}`;
|
|
9123
|
+
case "intersection": {
|
|
9124
|
+
const branch = "branch" in e && e.branch !== void 0 ? ` (nh\xE1nh ${e.branch})` : "";
|
|
9125
|
+
return `${e.name} = ${e.ref1} \u2229 ${e.ref2}${branch}`;
|
|
9126
|
+
}
|
|
9127
|
+
case "segment":
|
|
9128
|
+
return `${e.name} = \u0111o\u1EA1n ${e.p1}${e.p2}`;
|
|
9129
|
+
case "line":
|
|
9130
|
+
return `${e.name} = \u0111\u01B0\u1EDDng th\u1EB3ng ${e.p1}${e.p2}`;
|
|
9131
|
+
case "ray":
|
|
9132
|
+
return `${e.name} = tia ${e.origin}${e.through}`;
|
|
9133
|
+
case "polygon":
|
|
9134
|
+
return `${e.name} = \u0111a gi\xE1c ${e.vertices.join("")}`;
|
|
9135
|
+
case "perpendicular":
|
|
9136
|
+
return `${e.name} \u27C2 ${e.toLine} qua ${e.throughPoint}`;
|
|
9137
|
+
case "parallel":
|
|
9138
|
+
return `${e.name} \u2225 ${e.toLine} qua ${e.throughPoint}`;
|
|
9139
|
+
case "perpBisector":
|
|
9140
|
+
return `${e.name} = trung tr\u1EF1c ${e.p1}${e.p2}`;
|
|
9141
|
+
case "angleBisector":
|
|
9142
|
+
return `${e.name} = ph\xE2n gi\xE1c \u2220${e.p1}${e.vertex}${e.p2}`;
|
|
9143
|
+
case "tangent": {
|
|
9144
|
+
const branch = "branch" in e && e.branch !== void 0 ? ` (nh\xE1nh ${e.branch})` : "";
|
|
9145
|
+
return `${e.name} = ti\u1EBFp tuy\u1EBFn ${e.toCircle} qua ${e.throughPoint}${branch}`;
|
|
9146
|
+
}
|
|
9147
|
+
case "circleCP":
|
|
9148
|
+
return `${e.name} = (${e.center}; ${e.center}${e.surfacePoint})`;
|
|
9149
|
+
case "circle3":
|
|
9150
|
+
return `${e.name} = \u0111\u01B0\u1EDDng tr\xF2n qua ${e.p1}${e.p2}${e.p3}`;
|
|
9151
|
+
default: {
|
|
9152
|
+
return "";
|
|
9153
|
+
}
|
|
9154
|
+
}
|
|
9155
|
+
}
|
|
9156
|
+
function describeDsl(obj, state) {
|
|
9157
|
+
const r = serializeObject(obj, state);
|
|
9158
|
+
if (r.ok) return describeEntity(r.entity);
|
|
9159
|
+
let base;
|
|
9160
|
+
try {
|
|
9161
|
+
base = getKind(obj.kind).describe(obj, state);
|
|
9162
|
+
} catch {
|
|
9163
|
+
base = `${obj.kind} ${obj.label}`;
|
|
9164
|
+
}
|
|
9165
|
+
return `${base} (kh\xF4ng h\u1ED7 tr\u1EE3 DSL)`;
|
|
9166
|
+
}
|
|
9167
|
+
var init_describeDsl = __esm({
|
|
9168
|
+
"src/stamps/geometry-2d/dsl/describeDsl.ts"() {
|
|
9169
|
+
init_registry();
|
|
9170
|
+
init_serialize2();
|
|
9171
|
+
}
|
|
9172
|
+
});
|
|
9173
|
+
function makeDslRenderRow(store) {
|
|
9174
|
+
return function renderDslRow(obj, defaults) {
|
|
9175
|
+
const state = store.getState();
|
|
9176
|
+
const noop = () => {
|
|
9177
|
+
};
|
|
9178
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
9179
|
+
ObjectRow,
|
|
9180
|
+
{
|
|
9181
|
+
obj,
|
|
9182
|
+
state,
|
|
9183
|
+
selected: defaults.selected,
|
|
9184
|
+
onSelect: defaults.onClick,
|
|
9185
|
+
onToggleVisible: (id) => {
|
|
9186
|
+
const o = state.objects[id];
|
|
9187
|
+
if (!o) return;
|
|
9188
|
+
store.dispatch({ type: "UPDATE", payload: { id, patch: { visible: !o.visible } } });
|
|
9189
|
+
},
|
|
9190
|
+
onToggleLocked: (id) => {
|
|
9191
|
+
const o = state.objects[id];
|
|
9192
|
+
if (!o) return;
|
|
9193
|
+
store.dispatch({ type: "UPDATE", payload: { id, patch: { locked: !o.locked } } });
|
|
9194
|
+
},
|
|
9195
|
+
onRename: noop,
|
|
9196
|
+
onChangeColor: noop,
|
|
9197
|
+
onDelete: (id) => store.dispatch({ type: "DELETE", payload: { id } }),
|
|
9198
|
+
describe: describeDsl
|
|
9199
|
+
}
|
|
9200
|
+
);
|
|
9201
|
+
};
|
|
9202
|
+
}
|
|
9203
|
+
var init_dslRenderRow = __esm({
|
|
9204
|
+
"src/stamps/geometry-2d/editor/dslRenderRow.tsx"() {
|
|
9205
|
+
init_ObjectRow();
|
|
9206
|
+
init_describeDsl();
|
|
9207
|
+
}
|
|
9208
|
+
});
|
|
9209
|
+
|
|
7853
9210
|
// src/stamps/geometry-2d/host.tsx
|
|
7854
9211
|
var host_exports = {};
|
|
7855
9212
|
__export(host_exports, {
|
|
@@ -7874,6 +9231,7 @@ var init_host = __esm({
|
|
|
7874
9231
|
init_scene();
|
|
7875
9232
|
init_useIsMobile();
|
|
7876
9233
|
init_useStampStore();
|
|
9234
|
+
init_dslRenderRow();
|
|
7877
9235
|
GeometryStampHost = React.forwardRef(
|
|
7878
9236
|
function GeometryStampHost2({ api, editingElement, onClose, isDark, generateGeometryFigure }, ref) {
|
|
7879
9237
|
const panelRef = React.useRef(null);
|
|
@@ -7900,6 +9258,7 @@ var init_host = __esm({
|
|
|
7900
9258
|
onSelect: (key) => setSelectedTool(key),
|
|
7901
9259
|
enabled: !isMobile
|
|
7902
9260
|
});
|
|
9261
|
+
const renderRow = React.useMemo(() => makeDslRenderRow(sceneStore), [sceneStore]);
|
|
7903
9262
|
const handleInsert = React.useCallback(
|
|
7904
9263
|
async (jsonState, svgString) => {
|
|
7905
9264
|
if (!api) return;
|
|
@@ -7961,7 +9320,8 @@ var init_host = __esm({
|
|
|
7961
9320
|
onObjectSelect: (id) => {
|
|
7962
9321
|
setSelectedObjectId(id ?? void 0);
|
|
7963
9322
|
panelRef.current?.selectObject(id);
|
|
7964
|
-
}
|
|
9323
|
+
},
|
|
9324
|
+
renderRow
|
|
7965
9325
|
},
|
|
7966
9326
|
isMobile,
|
|
7967
9327
|
drawerOpen,
|