@xom11/whiteboard 0.28.0 → 0.30.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/dist/ai.d.mts +250 -277
- package/dist/ai.d.ts +250 -277
- package/dist/ai.js +6045 -7459
- package/dist/ai.js.map +1 -1
- package/dist/ai.mjs +4806 -5457
- package/dist/ai.mjs.map +1 -1
- package/dist/catalog.json +2 -2
- package/dist/chunk-QK6OVDLC.mjs +103 -0
- package/dist/chunk-QK6OVDLC.mjs.map +1 -0
- package/dist/{chunk-AJAHD35N.mjs → chunk-SF3U7ZF4.mjs} +3 -32
- package/dist/chunk-SF3U7ZF4.mjs.map +1 -0
- package/dist/{chunk-QCZVFEN4.mjs → chunk-XVVLT6B3.mjs} +3 -3
- package/dist/{chunk-QCZVFEN4.mjs.map → chunk-XVVLT6B3.mjs.map} +1 -1
- package/dist/geometry-2d.d.mts +1 -2
- package/dist/geometry-2d.d.ts +1 -2
- package/dist/geometry-2d.js +1457 -3832
- package/dist/geometry-2d.js.map +1 -1
- package/dist/geometry-2d.mjs +1 -1
- package/dist/geometry-3d.d.mts +1 -2
- package/dist/geometry-3d.d.ts +1 -2
- package/dist/graph-2d.d.mts +1 -2
- package/dist/graph-2d.d.ts +1 -2
- package/dist/handleExtractProblem-BrDY9ifM.d.mts +58 -0
- package/dist/handleExtractProblem-BrDY9ifM.d.ts +58 -0
- package/dist/{host-4P766V4J.mjs → host-3UFGFMJ2.mjs} +45 -139
- package/dist/host-3UFGFMJ2.mjs.map +1 -0
- package/dist/index.d.mts +3 -4
- package/dist/index.d.ts +3 -4
- package/dist/index.js +1487 -3862
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +4 -4
- package/dist/latex.d.mts +1 -2
- package/dist/latex.d.ts +1 -2
- package/dist/{types-BHYC2Fiw.d.mts → types-C3FjpoUi.d.mts} +1 -232
- package/dist/{types-BHYC2Fiw.d.ts → types-C3FjpoUi.d.ts} +1 -232
- package/package.json +1 -8
- package/dist/chunk-AJAHD35N.mjs.map +0 -1
- package/dist/chunk-T3SOHYB2.mjs +0 -851
- package/dist/chunk-T3SOHYB2.mjs.map +0 -1
- package/dist/handleExtractProblem-C-U5KluK.d.mts +0 -158
- package/dist/handleExtractProblem-C-U5KluK.d.ts +0 -158
- package/dist/host-4P766V4J.mjs.map +0 -1
package/dist/geometry-2d.mjs
CHANGED
package/dist/geometry-3d.d.mts
CHANGED
package/dist/geometry-3d.d.ts
CHANGED
package/dist/graph-2d.d.mts
CHANGED
package/dist/graph-2d.d.ts
CHANGED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
interface ImagePart {
|
|
2
|
+
/** Whitelist 3 format browser decode native được. */
|
|
3
|
+
mediaType: 'image/png' | 'image/jpeg' | 'image/webp';
|
|
4
|
+
/** Base64 không bao gồm "data:image/...;base64," prefix. */
|
|
5
|
+
base64: string;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
interface ExtractProblemOptions {
|
|
9
|
+
/** Tesseract language. Default 'vie+eng' cho đề toán VN. */
|
|
10
|
+
tesseractLang?: string;
|
|
11
|
+
signal?: AbortSignal;
|
|
12
|
+
}
|
|
13
|
+
interface ExtractProblemSuccess {
|
|
14
|
+
ok: true;
|
|
15
|
+
text: string;
|
|
16
|
+
confidence: 'high' | 'low';
|
|
17
|
+
usage: {
|
|
18
|
+
inputTokens: number;
|
|
19
|
+
outputTokens: number;
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
interface ExtractProblemFailure {
|
|
23
|
+
ok: false;
|
|
24
|
+
reason: 'not-math' | 'unreadable' | 'empty' | 'unsupported';
|
|
25
|
+
message: string;
|
|
26
|
+
}
|
|
27
|
+
type ExtractProblemOutcome = ExtractProblemSuccess | ExtractProblemFailure;
|
|
28
|
+
declare function extractProblemFromImage(image: ImagePart, opts?: ExtractProblemOptions): Promise<ExtractProblemOutcome>;
|
|
29
|
+
|
|
30
|
+
interface HandleExtractProblemOptions extends ExtractProblemOptions {
|
|
31
|
+
}
|
|
32
|
+
type ExtractUiResult = {
|
|
33
|
+
kind: 'success';
|
|
34
|
+
text: string;
|
|
35
|
+
usage: {
|
|
36
|
+
inputTokens: number;
|
|
37
|
+
outputTokens: number;
|
|
38
|
+
};
|
|
39
|
+
} | {
|
|
40
|
+
kind: 'low-confidence';
|
|
41
|
+
text: string;
|
|
42
|
+
warning: string;
|
|
43
|
+
usage: {
|
|
44
|
+
inputTokens: number;
|
|
45
|
+
outputTokens: number;
|
|
46
|
+
};
|
|
47
|
+
} | {
|
|
48
|
+
kind: 'refused';
|
|
49
|
+
reason: 'not-math';
|
|
50
|
+
message: string;
|
|
51
|
+
} | {
|
|
52
|
+
kind: 'error';
|
|
53
|
+
code: 'network' | 'unsupported' | 'unexpected' | 'empty';
|
|
54
|
+
message: string;
|
|
55
|
+
};
|
|
56
|
+
declare function handleExtractProblem(image: ImagePart, opts?: HandleExtractProblemOptions): Promise<ExtractUiResult>;
|
|
57
|
+
|
|
58
|
+
export { type ExtractUiResult as E, type HandleExtractProblemOptions as H, type ImagePart as I, type ExtractProblemOptions as a, type ExtractProblemOutcome as b, extractProblemFromImage as e, handleExtractProblem as h };
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
interface ImagePart {
|
|
2
|
+
/** Whitelist 3 format browser decode native được. */
|
|
3
|
+
mediaType: 'image/png' | 'image/jpeg' | 'image/webp';
|
|
4
|
+
/** Base64 không bao gồm "data:image/...;base64," prefix. */
|
|
5
|
+
base64: string;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
interface ExtractProblemOptions {
|
|
9
|
+
/** Tesseract language. Default 'vie+eng' cho đề toán VN. */
|
|
10
|
+
tesseractLang?: string;
|
|
11
|
+
signal?: AbortSignal;
|
|
12
|
+
}
|
|
13
|
+
interface ExtractProblemSuccess {
|
|
14
|
+
ok: true;
|
|
15
|
+
text: string;
|
|
16
|
+
confidence: 'high' | 'low';
|
|
17
|
+
usage: {
|
|
18
|
+
inputTokens: number;
|
|
19
|
+
outputTokens: number;
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
interface ExtractProblemFailure {
|
|
23
|
+
ok: false;
|
|
24
|
+
reason: 'not-math' | 'unreadable' | 'empty' | 'unsupported';
|
|
25
|
+
message: string;
|
|
26
|
+
}
|
|
27
|
+
type ExtractProblemOutcome = ExtractProblemSuccess | ExtractProblemFailure;
|
|
28
|
+
declare function extractProblemFromImage(image: ImagePart, opts?: ExtractProblemOptions): Promise<ExtractProblemOutcome>;
|
|
29
|
+
|
|
30
|
+
interface HandleExtractProblemOptions extends ExtractProblemOptions {
|
|
31
|
+
}
|
|
32
|
+
type ExtractUiResult = {
|
|
33
|
+
kind: 'success';
|
|
34
|
+
text: string;
|
|
35
|
+
usage: {
|
|
36
|
+
inputTokens: number;
|
|
37
|
+
outputTokens: number;
|
|
38
|
+
};
|
|
39
|
+
} | {
|
|
40
|
+
kind: 'low-confidence';
|
|
41
|
+
text: string;
|
|
42
|
+
warning: string;
|
|
43
|
+
usage: {
|
|
44
|
+
inputTokens: number;
|
|
45
|
+
outputTokens: number;
|
|
46
|
+
};
|
|
47
|
+
} | {
|
|
48
|
+
kind: 'refused';
|
|
49
|
+
reason: 'not-math';
|
|
50
|
+
message: string;
|
|
51
|
+
} | {
|
|
52
|
+
kind: 'error';
|
|
53
|
+
code: 'network' | 'unsupported' | 'unexpected' | 'empty';
|
|
54
|
+
message: string;
|
|
55
|
+
};
|
|
56
|
+
declare function handleExtractProblem(image: ImagePart, opts?: HandleExtractProblemOptions): Promise<ExtractUiResult>;
|
|
57
|
+
|
|
58
|
+
export { type ExtractUiResult as E, type HandleExtractProblemOptions as H, type ImagePart as I, type ExtractProblemOptions as a, type ExtractProblemOutcome as b, extractProblemFromImage as e, handleExtractProblem as h };
|
|
@@ -8,15 +8,15 @@ import { JxgRenderer } from './chunk-SZDAS7LK.mjs';
|
|
|
8
8
|
import './chunk-ICR4CVOE.mjs';
|
|
9
9
|
import { nextLabel, useEditorState, listObjects } from './chunk-ZTQBUKLJ.mjs';
|
|
10
10
|
import './chunk-IHUFOV7L.mjs';
|
|
11
|
-
import { validateFile, fileToImagePart, describeDsl
|
|
12
|
-
import { handleExtractProblem } from './chunk-
|
|
11
|
+
import { validateFile, fileToImagePart, describeDsl } from './chunk-SF3U7ZF4.mjs';
|
|
12
|
+
import { handleExtractProblem } from './chunk-QK6OVDLC.mjs';
|
|
13
13
|
import { DEFAULT_VIEW_2D } from './chunk-73Q7ADVL.mjs';
|
|
14
14
|
import './chunk-B4NJJZFR.mjs';
|
|
15
15
|
import { useIsMobile } from './chunk-P2AOIF7S.mjs';
|
|
16
16
|
import { insertStampImage } from './chunk-QGNU34T7.mjs';
|
|
17
17
|
import './chunk-5UTGXHLJ.mjs';
|
|
18
18
|
import { __export } from './chunk-J5LGTIGS.mjs';
|
|
19
|
-
import { forwardRef, useRef, useId, useState, useEffect, useCallback, useImperativeHandle,
|
|
19
|
+
import { forwardRef, useRef, useId, useState, useEffect, useCallback, useImperativeHandle, useMemo, useLayoutEffect } from 'react';
|
|
20
20
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
21
21
|
import { createPortal } from 'react-dom';
|
|
22
22
|
|
|
@@ -3268,41 +3268,13 @@ var TransformParamPopover = ({ kind, anchor, defaultValue, onConfirm, onCancel,
|
|
|
3268
3268
|
);
|
|
3269
3269
|
return createPortal(node, document.body);
|
|
3270
3270
|
};
|
|
3271
|
-
function useAiFigure(generator
|
|
3272
|
-
const { currentState } = options;
|
|
3271
|
+
function useAiFigure(generator) {
|
|
3273
3272
|
const [prompt, setPrompt] = useState("");
|
|
3274
3273
|
const [isLoading, setIsLoading] = useState(false);
|
|
3275
3274
|
const [error, setError] = useState(null);
|
|
3276
3275
|
const [tokens, setTokens] = useState(0);
|
|
3277
3276
|
const abortRef = useRef(null);
|
|
3278
3277
|
const requestIdRef = useRef(0);
|
|
3279
|
-
const { dsl: currentDsl, unsupported, entityCount, hasContent } = useMemo(() => {
|
|
3280
|
-
if (!currentState || currentState.order.length === 0) {
|
|
3281
|
-
return {
|
|
3282
|
-
dsl: null,
|
|
3283
|
-
unsupported: [],
|
|
3284
|
-
entityCount: { points: 0, shapes: 0 },
|
|
3285
|
-
hasContent: false
|
|
3286
|
-
};
|
|
3287
|
-
}
|
|
3288
|
-
const { dsl, unsupported: unsupported2 } = serializeState(currentState);
|
|
3289
|
-
return {
|
|
3290
|
-
dsl,
|
|
3291
|
-
unsupported: unsupported2,
|
|
3292
|
-
entityCount: { points: dsl.points.length, shapes: dsl.shapes.length },
|
|
3293
|
-
hasContent: true
|
|
3294
|
-
};
|
|
3295
|
-
}, [currentState]);
|
|
3296
|
-
const hasUnsupported = unsupported.length > 0;
|
|
3297
|
-
const initialMode = hasContent && !hasUnsupported ? "refine" : "build";
|
|
3298
|
-
const [mode, setModeInternal] = useState(initialMode);
|
|
3299
|
-
useEffect(() => {
|
|
3300
|
-
if (!hasContent && mode === "refine") setModeInternal("build");
|
|
3301
|
-
if (hasUnsupported && mode === "refine") setModeInternal("build");
|
|
3302
|
-
}, [hasContent, hasUnsupported, mode]);
|
|
3303
|
-
const setMode = useCallback((next) => {
|
|
3304
|
-
setModeInternal(next);
|
|
3305
|
-
}, []);
|
|
3306
3278
|
useEffect(() => () => abortRef.current?.abort(), []);
|
|
3307
3279
|
const submit = useCallback(async () => {
|
|
3308
3280
|
const problem = prompt.trim();
|
|
@@ -3326,8 +3298,7 @@ function useAiFigure(generator, options = {}) {
|
|
|
3326
3298
|
signal: controller.signal,
|
|
3327
3299
|
onProgress: (info) => {
|
|
3328
3300
|
if (requestId === requestIdRef.current) setTokens(info.tokens);
|
|
3329
|
-
}
|
|
3330
|
-
...mode === "refine" && currentDsl ? { currentDsl } : {}
|
|
3301
|
+
}
|
|
3331
3302
|
});
|
|
3332
3303
|
if (controller.signal.aborted || requestId !== requestIdRef.current) return null;
|
|
3333
3304
|
if (!generated.ok) {
|
|
@@ -3351,7 +3322,7 @@ function useAiFigure(generator, options = {}) {
|
|
|
3351
3322
|
setIsLoading(false);
|
|
3352
3323
|
}
|
|
3353
3324
|
}
|
|
3354
|
-
}, [generator, prompt
|
|
3325
|
+
}, [generator, prompt]);
|
|
3355
3326
|
const cancel = useCallback(() => {
|
|
3356
3327
|
abortRef.current?.abort();
|
|
3357
3328
|
}, []);
|
|
@@ -3362,51 +3333,42 @@ function useAiFigure(generator, options = {}) {
|
|
|
3362
3333
|
error,
|
|
3363
3334
|
submit,
|
|
3364
3335
|
cancel,
|
|
3365
|
-
tokens
|
|
3366
|
-
mode,
|
|
3367
|
-
setMode,
|
|
3368
|
-
entityCount,
|
|
3369
|
-
hasUnsupported
|
|
3336
|
+
tokens
|
|
3370
3337
|
};
|
|
3371
3338
|
}
|
|
3372
|
-
var
|
|
3339
|
+
var ArrowUpIcon = (props) => /* @__PURE__ */ jsxs(
|
|
3373
3340
|
"svg",
|
|
3374
3341
|
{
|
|
3375
3342
|
viewBox: "0 0 24 24",
|
|
3376
3343
|
fill: "none",
|
|
3377
3344
|
stroke: "currentColor",
|
|
3378
|
-
strokeWidth:
|
|
3345
|
+
strokeWidth: 2.25,
|
|
3379
3346
|
strokeLinecap: "round",
|
|
3380
3347
|
strokeLinejoin: "round",
|
|
3381
3348
|
"aria-hidden": true,
|
|
3382
3349
|
...props,
|
|
3383
|
-
children:
|
|
3350
|
+
children: [
|
|
3351
|
+
/* @__PURE__ */ jsx("path", { d: "M12 19V5" }),
|
|
3352
|
+
/* @__PURE__ */ jsx("path", { d: "m5 12 7-7 7 7" })
|
|
3353
|
+
]
|
|
3384
3354
|
}
|
|
3385
3355
|
);
|
|
3386
|
-
var
|
|
3356
|
+
var StopIcon = (props) => /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "currentColor", "aria-hidden": true, ...props, children: /* @__PURE__ */ jsx("rect", { x: "6", y: "6", width: "12", height: "12", rx: "2" }) });
|
|
3357
|
+
var PaperclipIcon = (props) => /* @__PURE__ */ jsx(
|
|
3387
3358
|
"svg",
|
|
3388
3359
|
{
|
|
3389
3360
|
viewBox: "0 0 24 24",
|
|
3390
3361
|
fill: "none",
|
|
3391
3362
|
stroke: "currentColor",
|
|
3392
|
-
strokeWidth:
|
|
3363
|
+
strokeWidth: 1.75,
|
|
3393
3364
|
strokeLinecap: "round",
|
|
3394
3365
|
strokeLinejoin: "round",
|
|
3395
3366
|
"aria-hidden": true,
|
|
3396
3367
|
...props,
|
|
3397
|
-
children:
|
|
3398
|
-
/* @__PURE__ */ jsx("path", { d: "M12 19V5" }),
|
|
3399
|
-
/* @__PURE__ */ jsx("path", { d: "m5 12 7-7 7 7" })
|
|
3400
|
-
]
|
|
3368
|
+
children: /* @__PURE__ */ jsx("path", { d: "m21.44 11.05-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48" })
|
|
3401
3369
|
}
|
|
3402
3370
|
);
|
|
3403
|
-
|
|
3404
|
-
function AiFigurePrompt({
|
|
3405
|
-
generator,
|
|
3406
|
-
onGenerated,
|
|
3407
|
-
currentState,
|
|
3408
|
-
extractProblem = handleExtractProblem
|
|
3409
|
-
}) {
|
|
3371
|
+
function AiFigurePrompt({ generator, onGenerated }) {
|
|
3410
3372
|
const {
|
|
3411
3373
|
prompt,
|
|
3412
3374
|
setPrompt,
|
|
@@ -3414,12 +3376,8 @@ function AiFigurePrompt({
|
|
|
3414
3376
|
error,
|
|
3415
3377
|
submit,
|
|
3416
3378
|
cancel,
|
|
3417
|
-
tokens
|
|
3418
|
-
|
|
3419
|
-
setMode,
|
|
3420
|
-
entityCount,
|
|
3421
|
-
hasUnsupported
|
|
3422
|
-
} = useAiFigure(generator, { currentState });
|
|
3379
|
+
tokens
|
|
3380
|
+
} = useAiFigure(generator);
|
|
3423
3381
|
const [elapsed, setElapsed] = useState(0);
|
|
3424
3382
|
useEffect(() => {
|
|
3425
3383
|
if (!isLoading) {
|
|
@@ -3496,7 +3454,7 @@ function AiFigurePrompt({
|
|
|
3496
3454
|
setOcrError(null);
|
|
3497
3455
|
setOcrWarning(null);
|
|
3498
3456
|
try {
|
|
3499
|
-
const r = await
|
|
3457
|
+
const r = await handleExtractProblem(image);
|
|
3500
3458
|
if (r.kind === "success" || r.kind === "low-confidence") {
|
|
3501
3459
|
setPrompt(r.text);
|
|
3502
3460
|
if (r.kind === "low-confidence") setOcrWarning(r.warning);
|
|
@@ -3507,7 +3465,7 @@ function AiFigurePrompt({
|
|
|
3507
3465
|
} finally {
|
|
3508
3466
|
setOcrLoading(false);
|
|
3509
3467
|
}
|
|
3510
|
-
}, [image, setPrompt
|
|
3468
|
+
}, [image, setPrompt]);
|
|
3511
3469
|
const handleSendClick = useCallback(async () => {
|
|
3512
3470
|
if (image && !prompt.trim() && !ocrLoading) {
|
|
3513
3471
|
await runOcr();
|
|
@@ -3516,62 +3474,12 @@ function AiFigurePrompt({
|
|
|
3516
3474
|
const generated = await submit();
|
|
3517
3475
|
if (generated) onGenerated(generated);
|
|
3518
3476
|
}, [image, prompt, ocrLoading, runOcr, submit, onGenerated]);
|
|
3519
|
-
const handleSwitchToBuild = useCallback(() => {
|
|
3520
|
-
if (currentState && currentState.order.length > 0) {
|
|
3521
|
-
const ok = window.confirm(
|
|
3522
|
-
"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?"
|
|
3523
|
-
);
|
|
3524
|
-
if (!ok) return;
|
|
3525
|
-
}
|
|
3526
|
-
setMode("build");
|
|
3527
|
-
}, [currentState, setMode]);
|
|
3528
|
-
const hasContent = currentState != null && currentState.order.length > 0;
|
|
3529
3477
|
const promptEmpty = !prompt.trim();
|
|
3530
3478
|
const willOcr = image != null && promptEmpty;
|
|
3531
3479
|
const sendDisabled = !image && promptEmpty || ocrLoading || isLoading && !willOcr;
|
|
3532
|
-
const
|
|
3533
|
-
const placeholder = willOcr ? "B\u1EA5m g\u1EEDi \u0111\u1EC3 \u0111\u1ECDc \u0111\u1EC1 t\u1EEB \u1EA3nh \u2014 ho\u1EB7c t\u1EF1 g\xF5 \u1EDF \u0111\xE2y\u2026" : mode === "refine" ? "M\xF4 t\u1EA3 ph\u1EA7n c\u1EA7n th\xEAm (vd: trung \u0111i\u1EC3m M c\u1EE7a BC). C\xF3 th\u1EC3 d\xE1n \u1EA3nh \u0111\u1EC1 (Ctrl+V)." : "M\xF4 t\u1EA3 \u0111\u1EC1 b\xE0i c\u1EA7n d\u1EF1ng \u2014 ho\u1EB7c d\xE1n/\u0111\xEDnh \u1EA3nh \u0111\u1EC1 (Ctrl+V).";
|
|
3480
|
+
const placeholder = willOcr ? "B\u1EA5m g\u1EEDi \u0111\u1EC3 \u0111\u1ECDc \u0111\u1EC1 t\u1EEB \u1EA3nh \u2014 ho\u1EB7c t\u1EF1 g\xF5 \u1EDF \u0111\xE2y\u2026" : "M\xF4 t\u1EA3 \u0111\u1EC1 b\xE0i c\u1EA7n d\u1EF1ng \u2014 ho\u1EB7c d\xE1n/\u0111\xEDnh \u1EA3nh \u0111\u1EC1 (Ctrl+V).";
|
|
3534
3481
|
return /* @__PURE__ */ jsxs("div", { className: "border-b border-slate-200 bg-slate-50 px-3 py-3", children: [
|
|
3535
|
-
/* @__PURE__ */
|
|
3536
|
-
/* @__PURE__ */ jsx("span", { className: "text-xs font-medium tracking-wide text-slate-600", children: "D\u1EF1ng h\xECnh b\u1EB1ng AI" }),
|
|
3537
|
-
hasContent && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", role: "tablist", "aria-label": "Ch\u1EBF \u0111\u1ED9 AI", children: [
|
|
3538
|
-
/* @__PURE__ */ jsx(
|
|
3539
|
-
"button",
|
|
3540
|
-
{
|
|
3541
|
-
type: "button",
|
|
3542
|
-
role: "tab",
|
|
3543
|
-
"aria-selected": mode === "refine",
|
|
3544
|
-
"data-testid": "geometry-ai-mode-refine",
|
|
3545
|
-
onClick: () => setMode("refine"),
|
|
3546
|
-
disabled: isLoading || hasUnsupported,
|
|
3547
|
-
title: hasUnsupported ? "H\xECnh c\xF3 \u0111\u1ED1i t\u01B0\u1EE3ng ngo\xE0i DSL \u2014 ch\u1EC9 d\u1EF1ng m\u1EDBi \u0111\u01B0\u1EE3c" : refineChipLabel,
|
|
3548
|
-
className: `rounded-full px-2.5 py-0.5 text-[11px] transition ${mode === "refine" ? "bg-emerald-600 text-white shadow-sm" : "text-slate-500 hover:text-emerald-700"} ${hasUnsupported ? "cursor-not-allowed opacity-40" : ""}`,
|
|
3549
|
-
children: refineChipLabel
|
|
3550
|
-
}
|
|
3551
|
-
),
|
|
3552
|
-
/* @__PURE__ */ jsx(
|
|
3553
|
-
"button",
|
|
3554
|
-
{
|
|
3555
|
-
type: "button",
|
|
3556
|
-
role: "tab",
|
|
3557
|
-
"aria-selected": mode === "build",
|
|
3558
|
-
"data-testid": "geometry-ai-mode-build",
|
|
3559
|
-
onClick: handleSwitchToBuild,
|
|
3560
|
-
disabled: isLoading,
|
|
3561
|
-
className: `rounded-full px-2.5 py-0.5 text-[11px] transition ${mode === "build" ? "bg-emerald-600 text-white shadow-sm" : "text-slate-500 hover:text-emerald-700"}`,
|
|
3562
|
-
children: "D\u1EF1ng m\u1EDBi"
|
|
3563
|
-
}
|
|
3564
|
-
)
|
|
3565
|
-
] })
|
|
3566
|
-
] }),
|
|
3567
|
-
hasUnsupported && /* @__PURE__ */ jsx(
|
|
3568
|
-
"p",
|
|
3569
|
-
{
|
|
3570
|
-
className: "mb-1.5 text-[10px] text-amber-700",
|
|
3571
|
-
"data-testid": "geometry-ai-unsupported-warning",
|
|
3572
|
-
children: "H\xECnh c\xF3 \u0111\u1ED1i t\u01B0\u1EE3ng ngo\xE0i DSL \u2014 ch\u1EC9 d\u1EF1ng m\u1EDBi \u0111\u01B0\u1EE3c"
|
|
3573
|
-
}
|
|
3574
|
-
),
|
|
3482
|
+
/* @__PURE__ */ jsx("div", { className: "mb-2 flex items-center justify-between gap-2", children: /* @__PURE__ */ jsx("span", { className: "text-xs font-medium tracking-wide text-slate-600", children: "D\u1EF1ng h\xECnh b\u1EB1ng AI" }) }),
|
|
3575
3483
|
/* @__PURE__ */ jsxs(
|
|
3576
3484
|
"div",
|
|
3577
3485
|
{
|
|
@@ -3582,8 +3490,6 @@ function AiFigurePrompt({
|
|
|
3582
3490
|
onDragLeave: () => setIsDragOver(false),
|
|
3583
3491
|
onDrop: handleDrop,
|
|
3584
3492
|
onPaste: handlePaste,
|
|
3585
|
-
"aria-label": "Khu v\u1EF1c k\xE9o th\u1EA3 \u1EA3nh",
|
|
3586
|
-
role: "region",
|
|
3587
3493
|
className: "group relative flex flex-col rounded-2xl bg-white shadow-sm transition-all duration-150 ring-1 ring-slate-200 focus-within:ring-2 focus-within:ring-emerald-400/70 focus-within:shadow-md " + (isDragOver ? "ring-2 ring-emerald-500 bg-emerald-50/40" : ""),
|
|
3588
3494
|
children: [
|
|
3589
3495
|
image && imagePreview && /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-2 px-3 pt-2.5", children: /* @__PURE__ */ jsxs("div", { className: "group/chip relative", children: [
|
|
@@ -3687,14 +3593,16 @@ function AiFigurePrompt({
|
|
|
3687
3593
|
]
|
|
3688
3594
|
}
|
|
3689
3595
|
),
|
|
3690
|
-
/* @__PURE__ */
|
|
3691
|
-
"
|
|
3692
|
-
|
|
3693
|
-
|
|
3694
|
-
|
|
3695
|
-
|
|
3596
|
+
ocrWarning && /* @__PURE__ */ jsx(
|
|
3597
|
+
"p",
|
|
3598
|
+
{
|
|
3599
|
+
className: "mt-1 px-1 text-xs text-amber-700",
|
|
3600
|
+
"data-testid": "geometry-ai-ocr-warning",
|
|
3601
|
+
children: ocrWarning
|
|
3602
|
+
}
|
|
3603
|
+
),
|
|
3696
3604
|
ocrError && /* @__PURE__ */ jsx("p", { role: "alert", className: "mt-1 px-1 text-xs text-red-600", children: ocrError }),
|
|
3697
|
-
|
|
3605
|
+
error && /* @__PURE__ */ jsx("p", { role: "alert", className: "mt-1 px-1 text-xs text-red-600", children: error })
|
|
3698
3606
|
] });
|
|
3699
3607
|
}
|
|
3700
3608
|
|
|
@@ -3815,8 +3723,6 @@ var GeometryEditorPanelInner = forwardRef(
|
|
|
3815
3723
|
}, [onGeometryDraft]);
|
|
3816
3724
|
useEditorState({ store, onHistoryChange });
|
|
3817
3725
|
useGeometryDraftEmit({ store, handleRef, api, showAxis, showGrid, onGeometryDraft });
|
|
3818
|
-
const snap = () => store.getState();
|
|
3819
|
-
const currentSceneState = useSyncExternalStore((cb) => store.subscribe(cb), snap, snap);
|
|
3820
3726
|
useEffect(() => {
|
|
3821
3727
|
const sync = () => setHasContent(Object.keys(store.getState().objects).length > 0);
|
|
3822
3728
|
sync();
|
|
@@ -3826,22 +3732,22 @@ var GeometryEditorPanelInner = forwardRef(
|
|
|
3826
3732
|
const h = handleRef.current;
|
|
3827
3733
|
if (!h) return;
|
|
3828
3734
|
setReady(true);
|
|
3829
|
-
h.onSelect((
|
|
3830
|
-
setPropsPopover(
|
|
3735
|
+
h.onSelect((snap) => {
|
|
3736
|
+
setPropsPopover(snap);
|
|
3831
3737
|
setMultiSelection(null);
|
|
3832
|
-
onSelectionChangeRef.current?.(
|
|
3738
|
+
onSelectionChangeRef.current?.(snap.id);
|
|
3833
3739
|
});
|
|
3834
3740
|
h.onTransformParam((info) => setTransformPopover(info));
|
|
3835
|
-
h.onSelectionState((
|
|
3836
|
-
if (!
|
|
3741
|
+
h.onSelectionState((snap) => {
|
|
3742
|
+
if (!snap || snap.ids.length === 0) {
|
|
3837
3743
|
setPropsPopover(null);
|
|
3838
3744
|
setMultiSelection(null);
|
|
3839
3745
|
onSelectionChangeRef.current?.(void 0);
|
|
3840
3746
|
return;
|
|
3841
3747
|
}
|
|
3842
|
-
if (
|
|
3843
|
-
const id =
|
|
3844
|
-
const single = buildObjectSnapshot(store.getState(), id,
|
|
3748
|
+
if (snap.ids.length === 1) {
|
|
3749
|
+
const id = snap.ids[0];
|
|
3750
|
+
const single = buildObjectSnapshot(store.getState(), id, snap.anchor);
|
|
3845
3751
|
if (single) {
|
|
3846
3752
|
setPropsPopover(single);
|
|
3847
3753
|
setMultiSelection(null);
|
|
@@ -3849,7 +3755,7 @@ var GeometryEditorPanelInner = forwardRef(
|
|
|
3849
3755
|
}
|
|
3850
3756
|
return;
|
|
3851
3757
|
}
|
|
3852
|
-
setMultiSelection(
|
|
3758
|
+
setMultiSelection(snap);
|
|
3853
3759
|
setPropsPopover(null);
|
|
3854
3760
|
onSelectionChangeRef.current?.(void 0);
|
|
3855
3761
|
});
|
|
@@ -4008,7 +3914,7 @@ var GeometryEditorPanelInner = forwardRef(
|
|
|
4008
3914
|
/* @__PURE__ */ jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" })
|
|
4009
3915
|
] }) })
|
|
4010
3916
|
] }),
|
|
4011
|
-
generateGeometryFigure && /* @__PURE__ */ jsx(AiFigurePrompt, { generator: generateGeometryFigure, onGenerated: loadAiFigure
|
|
3917
|
+
generateGeometryFigure && /* @__PURE__ */ jsx(AiFigurePrompt, { generator: generateGeometryFigure, onGenerated: loadAiFigure }),
|
|
4012
3918
|
/* @__PURE__ */ jsx("div", { className: "flex min-h-0 flex-1", children: /* @__PURE__ */ jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsx(
|
|
4013
3919
|
MiniBoard2D,
|
|
4014
3920
|
{
|
|
@@ -4293,5 +4199,5 @@ var GeometryStampHost = forwardRef(
|
|
|
4293
4199
|
);
|
|
4294
4200
|
|
|
4295
4201
|
export { GeometryStampHost };
|
|
4296
|
-
//# sourceMappingURL=host-
|
|
4297
|
-
//# sourceMappingURL=host-
|
|
4202
|
+
//# sourceMappingURL=host-3UFGFMJ2.mjs.map
|
|
4203
|
+
//# sourceMappingURL=host-3UFGFMJ2.mjs.map
|