@weasel-js/core 1.14.2 → 1.15.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/CHANGELOG.md +167 -0
- package/dist/affordances/pathAnchors.js +0 -1
- package/dist/affordances/pathAnchors.js.map +1 -1
- package/dist/barrel/paths.js +1 -1
- package/dist/barrel/renderer.js +2 -2
- package/dist/barrel/routing.js +6 -4
- package/dist/barrel/text.js +5 -3
- package/dist/canvas/Canvas.js +5 -1
- package/dist/canvas/Canvas.js.map +1 -1
- package/dist/canvas/DrawCanvas.js +5 -1
- package/dist/canvas/DrawCanvas.js.map +1 -1
- package/dist/canvas/SceneCanvas/SceneCanvasInput.js +4 -0
- package/dist/canvas/SceneCanvas/SceneCanvasInput.js.map +1 -1
- package/dist/canvas/SceneCanvas/builtinToolSets.js +6 -3
- package/dist/canvas/SceneCanvas/builtinToolSets.js.map +1 -1
- package/dist/canvas/SceneCanvas/defaultNodeProperties.js +1 -1
- package/dist/canvas/SceneCanvas/presets/paths.js +6 -6
- package/dist/canvas/SceneCanvas/presets/paths.js.map +1 -1
- package/dist/canvas/SceneCanvas/shapeGeneratorProperties.js +1 -1
- package/dist/canvas/SceneCanvas/shapeGeneratorProperties.js.map +1 -1
- package/dist/canvas/SceneCanvas/useBuiltinTools.js +2 -0
- package/dist/canvas/SceneCanvas/useBuiltinTools.js.map +1 -1
- package/dist/canvas/SceneCanvas/useContributionRoles.js +2 -0
- package/dist/canvas/SceneCanvas/useContributionRoles.js.map +1 -1
- package/dist/canvas/SceneCanvas/useSceneChrome.js +17 -5
- package/dist/canvas/SceneCanvas/useSceneChrome.js.map +1 -1
- package/dist/canvas/SceneCanvas/useSceneStandardActions.js +3 -0
- package/dist/canvas/SceneCanvas/useSceneStandardActions.js.map +1 -1
- package/dist/canvas/SceneCanvas.js +5 -4
- package/dist/canvas/SceneCanvas.js.map +1 -1
- package/dist/canvas/SceneViewCanvas.js +5 -1
- package/dist/canvas/SceneViewCanvas.js.map +1 -1
- package/dist/canvas/affordanceAt.js +0 -1
- package/dist/canvas/affordanceAt.js.map +1 -1
- package/dist/canvas/deps/chromeRules.js +37 -0
- package/dist/canvas/deps/chromeRules.js.map +1 -0
- package/dist/canvas/deps/editAnchors.js +0 -6
- package/dist/canvas/deps/editAnchors.js.map +1 -1
- package/dist/canvas/deps/hitTestArea.js +3 -1
- package/dist/canvas/deps/hitTestArea.js.map +1 -1
- package/dist/canvas/deps/modeDefaultTool.js +23 -0
- package/dist/canvas/deps/modeDefaultTool.js.map +1 -0
- package/dist/canvas/deps/pathEditCommits.js +1 -1
- package/dist/canvas/deps/selectionSnapshot.js +23 -0
- package/dist/canvas/deps/selectionSnapshot.js.map +1 -0
- package/dist/canvas/deps/snap.js +1 -0
- package/dist/canvas/deps/snap.js.map +1 -1
- package/dist/canvas/pickReach.js +12 -8
- package/dist/canvas/pickReach.js.map +1 -1
- package/dist/canvas/pickWalk.js +7 -5
- package/dist/canvas/pickWalk.js.map +1 -1
- package/dist/canvas/scenePickSource.js +2 -2
- package/dist/canvas/scenePickSource.js.map +1 -1
- package/dist/canvas/useCanvasSurface.js +21 -3
- package/dist/canvas/useCanvasSurface.js.map +1 -1
- package/dist/canvas/useFrameLoop.js +6 -7
- package/dist/canvas/useFrameLoop.js.map +1 -1
- package/dist/canvas/useSurfaceSize.js +4 -3
- package/dist/canvas/useSurfaceSize.js.map +1 -1
- package/dist/core/geometry/regionHit.js +35 -16
- package/dist/core/geometry/regionHit.js.map +1 -1
- package/dist/core/scene/editMode.js +4 -1
- package/dist/core/scene/editMode.js.map +1 -1
- package/dist/core/scene/historyFacade.js +7 -50
- package/dist/core/scene/historyFacade.js.map +1 -1
- package/dist/core/scene/nodeGates.js +2 -2
- package/dist/core/scene/nodeGates.js.map +1 -1
- package/dist/core/scene/opTable.js +8 -8
- package/dist/core/scene/opTable.js.map +1 -1
- package/dist/core/scene/outerOps.js +2 -2
- package/dist/core/scene/outerOps.js.map +1 -1
- package/dist/core/scene/poseWrites.js +16 -15
- package/dist/core/scene/poseWrites.js.map +1 -1
- package/dist/core/scene/sceneJournals.js +78 -0
- package/dist/core/scene/sceneJournals.js.map +1 -0
- package/dist/core/scene/sceneRecording.js +3 -2
- package/dist/core/scene/sceneRecording.js.map +1 -1
- package/dist/core/viewport/useCanvasSize.js +47 -26
- package/dist/core/viewport/useCanvasSize.js.map +1 -1
- package/dist/{depSchema-DD9H89gX.d.ts → depSchema-ChQPzEkW.d.ts} +40 -13
- package/dist/domains/chrome-caps/resolve.js +1 -0
- package/dist/domains/chrome-caps/resolve.js.map +1 -1
- package/dist/domains/chrome-caps/useChromeCaps.js +4 -2
- package/dist/domains/chrome-caps/useChromeCaps.js.map +1 -1
- package/dist/domains/paths/pathEditState.js +0 -24
- package/dist/domains/paths/pathEditState.js.map +1 -1
- package/dist/domains/snap/probes2d.js +5 -0
- package/dist/domains/snap/probes2d.js.map +1 -1
- package/dist/domains/snap/sceneReads.js +11 -1
- package/dist/domains/snap/sceneReads.js.map +1 -1
- package/dist/domains/snap/sceneSession2d.js +4 -2
- package/dist/domains/snap/sceneSession2d.js.map +1 -1
- package/dist/domains/text/index.js +2 -2
- package/dist/icons.table.js +1 -1
- package/dist/icons.table.js.map +1 -1
- package/dist/icons.table.json +5 -0
- package/dist/index.d.ts +112 -60
- package/dist/index.js +12 -8
- package/dist/interactions/actions/booleans/action.js +4 -2
- package/dist/interactions/actions/booleans/action.js.map +1 -1
- package/dist/interactions/actions/defaults/anchorEditing.js +3 -6
- package/dist/interactions/actions/defaults/anchorEditing.js.map +1 -1
- package/dist/interactions/actions/defaults/bendSegment.js +1 -2
- package/dist/interactions/actions/defaults/bendSegment.js.map +1 -1
- package/dist/interactions/actions/defaults/exitPathEdit.js +17 -1
- package/dist/interactions/actions/defaults/exitPathEdit.js.map +1 -1
- package/dist/interactions/actions/edit-anchors/action.js +3 -4
- package/dist/interactions/actions/edit-anchors/action.js.map +1 -1
- package/dist/interactions/actions/insert/action.js +21 -2
- package/dist/interactions/actions/insert/action.js.map +1 -1
- package/dist/interactions/actions/insert/params.js +43 -0
- package/dist/interactions/actions/insert/params.js.map +1 -0
- package/dist/interactions/actions/notices.js +17 -0
- package/dist/interactions/actions/notices.js.map +1 -0
- package/dist/interactions/actions/outlines/createOutlines.js +8 -6
- package/dist/interactions/actions/outlines/createOutlines.js.map +1 -1
- package/dist/interactions/actions/outlines/createOutlinesAction.js +13 -8
- package/dist/interactions/actions/outlines/createOutlinesAction.js.map +1 -1
- package/dist/interactions/actions/outlines/outlineStrokeAction.js +3 -2
- package/dist/interactions/actions/outlines/outlineStrokeAction.js.map +1 -1
- package/dist/interactions/actions/pathCommands/pathNodes.js +1 -1
- package/dist/interactions/actions/testUtils.js +0 -7
- package/dist/interactions/actions/testUtils.js.map +1 -1
- package/dist/interactions/actions/useNotices.js +13 -0
- package/dist/interactions/actions/useNotices.js.map +1 -0
- package/dist/test-seams.d.ts +5 -12
- package/dist/tools/builtin/anchors/anchorsTool.js +31 -0
- package/dist/tools/builtin/anchors/anchorsTool.js.map +1 -0
- package/dist/tools/builtin/polygon/usePolygonTool.js +1 -1
- package/dist/tools/builtin/star/useStarTool.js +1 -1
- package/dist/tools/index.js +4 -2
- package/dist/tools/toolOptions.js +47 -0
- package/dist/tools/toolOptions.js.map +1 -0
- package/dist/version.js +1 -1
- package/package.json +25 -25
- package/dist/interactions/actions/defaults/pathEditTools.js +0 -60
- package/dist/interactions/actions/defaults/pathEditTools.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createOutlinesAction.js","names":[],"sources":["../../../../src/interactions/actions/outlines/createOutlinesAction.tsx"],"sourcesContent":["import type { Action, ImmediateInvoker } from '@weasel-js/routing';\nimport { ActionDisabledReason } from '@weasel-js/routing';\nimport type { NodeId } from 'core/scene/types';\nimport { loadTextOutlines, type TextNodeSource, type TextOutlinesError } from '@weasel-js/text';\nimport {\n applyCreateOutlines, type CreateOutlinesAdapter, type CreateOutlinesResult,\n} from './createOutlines';\nimport { icon } from '../../../icons.gen';\n\n/** What an outline conversion answers when a text face had no outlines. */\ntype OutlinesFailure = { kind: 'failed'; error: TextOutlinesError };\n\n/**\n * Run `apply`, an outline conversion of `adapter`'s selection, waiting first\n * for any face whose outlines are registered but not yet loaded — a face is\n * parsed on first use, so the first conversion in a session would otherwise\n * fail. Warns under `tag` with the reason when the selection still cannot be\n * converted.\n */\nexport async function withTextOutlines<R extends { kind: string } | OutlinesFailure>(\n adapter: CreateOutlinesAdapter,\n apply: () => R,\n tag: string,\n): Promise<R> {\n const failure = (r: R): TextOutlinesError | null => (r.kind === 'failed' ? (r as OutlinesFailure).error : null);\n let result = apply();\n if (failure(result)?.reason === 'outlines-loading') {\n const texts = [...adapter.getSelection()]\n .map((id) => adapter.getTextSource(id as NodeId))\n .filter((t): t is TextNodeSource => t !== undefined);\n await Promise.all(texts.map((t) => loadTextOutlines(t.data)));\n result = apply();\n }\n const error = failure(result);\n if (error) console.warn(`[${tag}] ${error.message}`);\n return result;\n}\n\n/** {@link applyCreateOutlines} through {@link withTextOutlines}. */\nexport function runCreateOutlines(adapter: CreateOutlinesAdapter): Promise<CreateOutlinesResult> {\n return withTextOutlines(adapter, () => applyCreateOutlines(adapter), 'createOutlines');\n}\n\n/**\n * Static descriptor for Create Outlines: replace the selected\n * text nodes with path nodes carrying their glyph outlines. Reads the\n * `createOutlinesAdapter` dep, published with `useCreateOutlinesAdapter`.\n */\nexport const createOutlinesAction: Action = {\n id: 'createOutlines',\n label: 'Create Outlines',\n icon: icon('createOutlines'),\n group: 'text',\n // Affinity's Convert to Curves; Illustrator's Mod+Shift+O is Chrome's bookmark manager.\n defaultBinding: [{ spec: { kind: 'key', key: 'Enter', mods: { mod: true } }, opts: { id: 'createOutlines.key' } }],\n eligible: { capability: 'creates-shapes' },\n requires: ['selection', 'createOutlinesAdapter'],\n invoker: {\n timing: 'immediate',\n run: (deps) => {\n const adapter = deps.createOutlinesAdapter;\n if (adapter) void runCreateOutlines(adapter);\n },\n } satisfies ImmediateInvoker,\n enabled: (deps) => {\n const ids = deps?.selection?.get() ?? [];\n if (ids.length === 0) return ActionDisabledReason.SelectionRequired;\n const adapter = deps?.createOutlinesAdapter;\n return adapter && ids.some((id) => adapter.getTextSource(id) !== undefined)\n ? true\n : ActionDisabledReason.NotApplicable;\n },\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"createOutlinesAction.js","names":[],"sources":["../../../../src/interactions/actions/outlines/createOutlinesAction.tsx"],"sourcesContent":["import type { Action, ImmediateInvoker } from '@weasel-js/routing';\nimport { ActionDisabledReason } from '@weasel-js/routing';\nimport type { NodeId } from 'core/scene/types';\nimport { loadTextOutlines, type TextNodeSource, type TextOutlinesError } from '@weasel-js/text';\nimport {\n applyCreateOutlines, type CreateOutlinesAdapter, type CreateOutlinesResult,\n} from './createOutlines';\nimport { icon } from '../../../icons.gen';\nimport { warnTextOutlines, type NoticesDep } from '../notices';\n\n/** What an outline conversion answers when a text face had no outlines. */\ntype OutlinesFailure = { kind: 'failed'; error: TextOutlinesError };\n\n/**\n * Run `apply`, an outline conversion of `adapter`'s selection, waiting first\n * for any face whose outlines are registered but not yet loaded — a face is\n * parsed on first use, so the first conversion in a session would otherwise\n * fail. Warns the user through `notices` (under `tag` on the console without\n * it) when the selection still cannot be converted.\n */\nexport async function withTextOutlines<R extends { kind: string } | OutlinesFailure>(\n adapter: CreateOutlinesAdapter,\n apply: () => R,\n tag: string,\n notices?: NoticesDep,\n): Promise<R> {\n const failure = (r: R): TextOutlinesError | null => (r.kind === 'failed' ? (r as OutlinesFailure).error : null);\n let result = apply();\n if (failure(result)?.reason === 'outlines-loading') {\n const texts = [...adapter.getSelection()]\n .map((id) => adapter.getTextSource(id as NodeId))\n .filter((t): t is TextNodeSource => t !== undefined);\n await Promise.all(texts.map((t) => loadTextOutlines(t.data)));\n result = apply();\n }\n const error = failure(result);\n if (error) warnTextOutlines(notices, tag, error);\n return result;\n}\n\n/** {@link applyCreateOutlines} through {@link withTextOutlines}. */\nexport function runCreateOutlines(adapter: CreateOutlinesAdapter, notices?: NoticesDep): Promise<CreateOutlinesResult> {\n return withTextOutlines(adapter, () => applyCreateOutlines(adapter), 'createOutlines', notices);\n}\n\n/**\n * Static descriptor for Create Outlines: replace the selected\n * text nodes with path nodes carrying their glyph outlines. Reads the\n * `createOutlinesAdapter` dep, published with `useCreateOutlinesAdapter`.\n */\nexport const createOutlinesAction: Action = {\n id: 'createOutlines',\n label: 'Create Outlines',\n icon: icon('createOutlines'),\n group: 'text',\n // Affinity's Convert to Curves; Illustrator's Mod+Shift+O is Chrome's bookmark manager.\n defaultBinding: [{ spec: { kind: 'key', key: 'Enter', mods: { mod: true } }, opts: { id: 'createOutlines.key' } }],\n eligible: { capability: 'creates-shapes' },\n requires: ['selection', 'createOutlinesAdapter', 'notices'],\n invoker: {\n timing: 'immediate',\n run: (deps) => {\n const adapter = deps.createOutlinesAdapter;\n if (adapter) void runCreateOutlines(adapter, deps.notices);\n },\n } satisfies ImmediateInvoker,\n enabled: (deps) => {\n const ids = deps?.selection?.get() ?? [];\n if (ids.length === 0) return ActionDisabledReason.SelectionRequired;\n const adapter = deps?.createOutlinesAdapter;\n return adapter && ids.some((id) => adapter.getTextSource(id) !== undefined)\n ? true\n : ActionDisabledReason.NotApplicable;\n },\n};\n"],"mappings":"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"}
|
|
@@ -18,7 +18,8 @@ var outlineStrokeAction = {
|
|
|
18
18
|
requires: [
|
|
19
19
|
"selection",
|
|
20
20
|
"createOutlinesAdapter",
|
|
21
|
-
"view"
|
|
21
|
+
"view",
|
|
22
|
+
"notices"
|
|
22
23
|
],
|
|
23
24
|
invoker: {
|
|
24
25
|
timing: "immediate",
|
|
@@ -26,7 +27,7 @@ var outlineStrokeAction = {
|
|
|
26
27
|
const adapter = deps.createOutlinesAdapter;
|
|
27
28
|
if (!adapter) return;
|
|
28
29
|
const scale = deps.view?.get().scale;
|
|
29
|
-
withTextOutlines(adapter, () => applyOutlineStroke(adapter, scale ? { scale } : {}), "outlineStroke");
|
|
30
|
+
withTextOutlines(adapter, () => applyOutlineStroke(adapter, scale ? { scale } : {}), "outlineStroke", deps.notices);
|
|
30
31
|
}
|
|
31
32
|
},
|
|
32
33
|
enabled: (deps) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"outlineStrokeAction.js","names":[],"sources":["../../../../src/interactions/actions/outlines/outlineStrokeAction.tsx"],"sourcesContent":["import type { Action, ImmediateInvoker } from '@weasel-js/routing';\nimport { ActionDisabledReason } from '@weasel-js/routing';\nimport { applyOutlineStroke, textIsStroked } from './outlineStroke';\nimport { withTextOutlines } from './createOutlinesAction';\nimport { icon } from '../../../icons.gen';\n\n/**\n * Static descriptor for Outline Stroke: replace each selected\n * stroked path, or stroked text, with the region its stroke covers, filled in\n * the stroke's paint. Reads the `createOutlinesAdapter` dep, published with\n * `useCreateOutlinesAdapter`, and needs its `getWorldPath` and `getPaint` for paths.\n */\nexport const outlineStrokeAction: Action = {\n id: 'outlineStroke',\n label: 'Outline Stroke',\n icon: icon('outlineStroke'),\n group: 'pathfinder',\n eligible: { capability: 'creates-shapes' },\n requires: ['selection', 'createOutlinesAdapter', 'view'],\n invoker: {\n timing: 'immediate',\n run: (deps) => {\n const adapter = deps.createOutlinesAdapter;\n if (!adapter) return;\n const scale = deps.view?.get().scale;\n void withTextOutlines(adapter, () => applyOutlineStroke(adapter, scale ? { scale } : {}), 'outlineStroke');\n },\n } satisfies ImmediateInvoker,\n enabled: (deps) => {\n const ids = deps?.selection?.get() ?? [];\n if (ids.length === 0) return ActionDisabledReason.SelectionRequired;\n const adapter = deps?.createOutlinesAdapter;\n return adapter && ids.some((id) => adapter.getPaint?.(id)?.stroke !== undefined || textIsStroked(adapter.getTextSource(id)))\n ? true\n : ActionDisabledReason.NotApplicable;\n },\n};\n"],"mappings":";;;;;;;;;;;AAYA,CAAA,CAAA,CAAA,CAAa,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAA8B;AACzC,CAAA,CAAA,CAAA,CAAA,CAAI,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA;AACJ,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAO,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA;AACP,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,aAAM,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA;AACN,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAO,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA;AACP,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAU,CAAA,CAAE,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAY,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAiB,CAAA;AACzC,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAU;AAAC,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA;AAAa,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA;AAAyB,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA;
|
|
1
|
+
{"version":3,"file":"outlineStrokeAction.js","names":[],"sources":["../../../../src/interactions/actions/outlines/outlineStrokeAction.tsx"],"sourcesContent":["import type { Action, ImmediateInvoker } from '@weasel-js/routing';\nimport { ActionDisabledReason } from '@weasel-js/routing';\nimport { applyOutlineStroke, textIsStroked } from './outlineStroke';\nimport { withTextOutlines } from './createOutlinesAction';\nimport { icon } from '../../../icons.gen';\n\n/**\n * Static descriptor for Outline Stroke: replace each selected\n * stroked path, or stroked text, with the region its stroke covers, filled in\n * the stroke's paint. Reads the `createOutlinesAdapter` dep, published with\n * `useCreateOutlinesAdapter`, and needs its `getWorldPath` and `getPaint` for paths.\n */\nexport const outlineStrokeAction: Action = {\n id: 'outlineStroke',\n label: 'Outline Stroke',\n icon: icon('outlineStroke'),\n group: 'pathfinder',\n eligible: { capability: 'creates-shapes' },\n requires: ['selection', 'createOutlinesAdapter', 'view', 'notices'],\n invoker: {\n timing: 'immediate',\n run: (deps) => {\n const adapter = deps.createOutlinesAdapter;\n if (!adapter) return;\n const scale = deps.view?.get().scale;\n void withTextOutlines(adapter, () => applyOutlineStroke(adapter, scale ? { scale } : {}), 'outlineStroke', deps.notices);\n },\n } satisfies ImmediateInvoker,\n enabled: (deps) => {\n const ids = deps?.selection?.get() ?? [];\n if (ids.length === 0) return ActionDisabledReason.SelectionRequired;\n const adapter = deps?.createOutlinesAdapter;\n return adapter && ids.some((id) => adapter.getPaint?.(id)?.stroke !== undefined || textIsStroked(adapter.getTextSource(id)))\n ? true\n : ActionDisabledReason.NotApplicable;\n },\n};\n"],"mappings":"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"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { createTransformOp } from "../../../core/ops/transform.js";
|
|
2
2
|
import { createSetDataOp } from "../../../core/ops/setData.js";
|
|
3
|
+
import { withoutShapeGenerator } from "../../../domains/paths/shapeGenerator.js";
|
|
3
4
|
import { createDeleteOp } from "../../../core/ops/delete.js";
|
|
4
5
|
import { createInsertOp } from "../../../core/ops/create.js";
|
|
5
6
|
import { resolveEditablePathOf, storeEditablePath } from "../../../domains/paths/editablePath.js";
|
|
6
|
-
import { withoutShapeGenerator } from "../../../domains/paths/shapeGenerator.js";
|
|
7
7
|
import { withoutGeometryBoundData } from "../../../domains/paths/pathEditExtension.js";
|
|
8
8
|
|
|
9
9
|
//#region src/interactions/actions/pathCommands/pathNodes.ts
|
|
@@ -13,7 +13,6 @@ function makeEditAnchorsDep(over = {}) {
|
|
|
13
13
|
let selected = /* @__PURE__ */ new Set();
|
|
14
14
|
let marquee = null;
|
|
15
15
|
let handleLocks;
|
|
16
|
-
let tool = null;
|
|
17
16
|
return Object.defineProperties({
|
|
18
17
|
get handleLocks() {
|
|
19
18
|
return handleLocks;
|
|
@@ -38,12 +37,6 @@ function makeEditAnchorsDep(over = {}) {
|
|
|
38
37
|
},
|
|
39
38
|
setMarquee(rect) {
|
|
40
39
|
marquee = rect;
|
|
41
|
-
},
|
|
42
|
-
get tool() {
|
|
43
|
-
return tool;
|
|
44
|
-
},
|
|
45
|
-
setTool(id) {
|
|
46
|
-
tool = id;
|
|
47
40
|
}
|
|
48
41
|
}, Object.getOwnPropertyDescriptors(over));
|
|
49
42
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"testUtils.js","names":[],"sources":["../../../src/interactions/actions/testUtils.ts"],"sourcesContent":["import type { NodeId, PoseOverrides } from 'core/scene/types';\nimport type { ActionDeps } from '@weasel-js/routing';\nimport type { MoveEnd } from '../gestures/types';\nimport type { EditAnchorsDep } from './depSchema';\n\n/**\n * Deps for an action unit test, stubbing only the slice the action reads.\n * Such stubs fall short of the full `DepSchema` types an action's deps carry,\n * and this is where they are let through.\n */\nexport function stubDeps(deps: Record<string, unknown>): ActionDeps {\n return deps as ActionDeps;\n}\n\n/**\n * What a move behavior's `onEnd` is told, for a test calling it directly:\n * unanswered and released at the world origin, with a `translateOps` that\n * emits nothing unless one is given.\n */\nexport function moveEnd(translateOps: MoveEnd['translateOps'] = () => []): MoveEnd {\n return { answered: false, translateOps, pointer: { x: 0, y: 0 } };\n}\n\n/**\n * Build an inert {@link EditAnchorsDep} for action unit tests. Every\n * member has a harmless default; override just the ones a test cares\n * about.\n *\n * Anchor selection and the marquee default to a **live** in-memory store\n * rather than a no-op, because most anchor-editing actions read back what\n * they wrote (select-then-nudge, marquee-then-delete). A test that wants\n * to assert the write instead of the round trip can pass its own spies.\n */\nexport function makeEditAnchorsDep(over: Partial<EditAnchorsDep> = {}): EditAnchorsDep {\n let selected: ReadonlySet<number> = new Set();\n let marquee: EditAnchorsDep['marquee'] = null;\n let handleLocks: EditAnchorsDep['handleLocks'];\n
|
|
1
|
+
{"version":3,"file":"testUtils.js","names":[],"sources":["../../../src/interactions/actions/testUtils.ts"],"sourcesContent":["import type { NodeId, PoseOverrides } from 'core/scene/types';\nimport type { ActionDeps } from '@weasel-js/routing';\nimport type { MoveEnd } from '../gestures/types';\nimport type { EditAnchorsDep } from './depSchema';\n\n/**\n * Deps for an action unit test, stubbing only the slice the action reads.\n * Such stubs fall short of the full `DepSchema` types an action's deps carry,\n * and this is where they are let through.\n */\nexport function stubDeps(deps: Record<string, unknown>): ActionDeps {\n return deps as ActionDeps;\n}\n\n/**\n * What a move behavior's `onEnd` is told, for a test calling it directly:\n * unanswered and released at the world origin, with a `translateOps` that\n * emits nothing unless one is given.\n */\nexport function moveEnd(translateOps: MoveEnd['translateOps'] = () => []): MoveEnd {\n return { answered: false, translateOps, pointer: { x: 0, y: 0 } };\n}\n\n/**\n * Build an inert {@link EditAnchorsDep} for action unit tests. Every\n * member has a harmless default; override just the ones a test cares\n * about.\n *\n * Anchor selection and the marquee default to a **live** in-memory store\n * rather than a no-op, because most anchor-editing actions read back what\n * they wrote (select-then-nudge, marquee-then-delete). A test that wants\n * to assert the write instead of the round trip can pass its own spies.\n */\nexport function makeEditAnchorsDep(over: Partial<EditAnchorsDep> = {}): EditAnchorsDep {\n let selected: ReadonlySet<number> = new Set();\n let marquee: EditAnchorsDep['marquee'] = null;\n let handleLocks: EditAnchorsDep['handleLocks'];\n const base: EditAnchorsDep = {\n get handleLocks() {\n return handleLocks;\n },\n setHandleLocks(next) {\n handleLocks = next;\n },\n editingId: 'node-a',\n setEditingId: () => {},\n getStorageKind: () => 'pose',\n getNodeShape: () => null,\n getEditablePath: () => null,\n applyEdit: () => {},\n get selectedAnchors() {\n return selected;\n },\n setSelectedAnchors(next: Iterable<number>) {\n selected = new Set(next);\n },\n get marquee() {\n return marquee;\n },\n setMarquee(rect) {\n marquee = rect;\n },\n };\n // Spread order matters: an explicit `selectedAnchors` / `marquee`\n // override must win over the accessor pair above, so copy descriptors\n // rather than plain-assigning (a getter would otherwise be clobbered by\n // an undefined value or survive a legitimate override).\n return Object.defineProperties(\n base,\n Object.getOwnPropertyDescriptors(over),\n ) as EditAnchorsDep;\n}\n\n/** The pose a transform drag publishes for `id` to the scene's overrides, or\n * null: where the drag shows it, since its handle carries no pose. */\nexport function heldPose(scene: unknown, id: string): unknown {\n return (scene as { overrides: PoseOverrides<unknown> }).overrides.read(id as NodeId)?.pose ?? null;\n}\n"],"mappings":";;;;;;;;;;;AAiCA,SAAgB,mBAAmB,OAAgC,CAAC,GAAmB;CACrF,IAAI,2BAAgC,IAAI,IAAI;CAC5C,IAAI,UAAqC;CACzC,IAAI;CA+BJ,OAAO,OAAO,iBACZ;EA9BA,IAAI,cAAc;GAChB,OAAO;EACT;EACA,eAAe,MAAM;GACnB,cAAc;EAChB;EACA,WAAW;EACX,oBAAoB,CAAC;EACrB,sBAAsB;EACtB,oBAAoB;EACpB,uBAAuB;EACvB,iBAAiB,CAAC;EAClB,IAAI,kBAAkB;GACpB,OAAO;EACT;EACA,mBAAmB,MAAwB;GACzC,WAAW,IAAI,IAAI,IAAI;EACzB;EACA,IAAI,UAAU;GACZ,OAAO;EACT;EACA,WAAW,MAAM;GACf,UAAU;EACZ;CAOA,GACA,OAAO,0BAA0B,IAAI,CACvC;AACF"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { useDepSource } from "@weasel-js/routing/react";
|
|
2
|
+
|
|
3
|
+
//#region src/interactions/actions/useNotices.ts
|
|
4
|
+
/** Publish the host's notice surface as the `notices` dep, where actions tell
|
|
5
|
+
* the user something went wrong. Silently does nothing outside a
|
|
6
|
+
* `<DepRegistryProvider>`. */
|
|
7
|
+
function useNotices(notices) {
|
|
8
|
+
useDepSource("notices", () => notices);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
//#endregion
|
|
12
|
+
export { useNotices };
|
|
13
|
+
//# sourceMappingURL=useNotices.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useNotices.js","names":[],"sources":["../../../src/interactions/actions/useNotices.ts"],"sourcesContent":["import { useDepSource } from '@weasel-js/routing/react';\nimport type { NoticesDep } from './notices';\n\n/** Publish the host's notice surface as the `notices` dep, where actions tell\n * the user something went wrong. Silently does nothing outside a\n * `<DepRegistryProvider>`. */\nexport function useNotices(notices: NoticesDep): void {\n useDepSource('notices', () => notices);\n}\n"],"mappings":";;;;;;AAMA,SAAgB,WAAW,SAA2B;CACpD,aAAa,iBAAiB,OAAO;AACvC"}
|
package/dist/test-seams.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { E as EditAnchorsDep, P as PathEditMark, a as PathEditExtension, H as HandleLocks, S as SnapSource, b as SnapGesture, c as SnapConstrain, d as SnapResizeBox, e as SnapGeometry, f as SnapOutcomeStore, g as SnapSession } from './depSchema-
|
|
2
|
-
export { _ as _resetPaintKindsForTests } from './depSchema-
|
|
1
|
+
import { E as EditAnchorsDep, P as PathEditMark, a as PathEditExtension, H as HandleLocks, S as SnapSource, b as SnapGesture, c as SnapConstrain, d as SnapResizeBox, e as SnapGeometry, f as SnapOutcomeStore, g as SnapAnchors, h as SnapSession } from './depSchema-ChQPzEkW.js';
|
|
2
|
+
export { _ as _resetPaintKindsForTests } from './depSchema-ChQPzEkW.js';
|
|
3
3
|
export { _resetMarkersForTests } from '@weasel-js/stroke/test-seams';
|
|
4
4
|
import { S as Scene } from './types-DW14eu9B.js';
|
|
5
5
|
import { SelectionApi, ActionTunings, WorldPoint, ResizeAnchor } from '@weasel-js/routing';
|
|
@@ -72,16 +72,6 @@ interface PathEditState {
|
|
|
72
72
|
* pressed. Not tied to the edited path, so they outlast a change of it. */
|
|
73
73
|
getHandleLocks(): HandleLocks | null;
|
|
74
74
|
setHandleLocks(next: HandleLocks): void;
|
|
75
|
-
/**
|
|
76
|
-
* The path-edit tool in use, or null for plain anchor editing. Path edit has
|
|
77
|
-
* a set of named tools, one active at a time, each changing what a plain
|
|
78
|
-
* drag does: `'simplifyBrush'` brushes the path simpler. A tool belongs to
|
|
79
|
-
* the open path; with none open, or a different one, there is none.
|
|
80
|
-
*/
|
|
81
|
-
getTool(): string | null;
|
|
82
|
-
/** Switch tool, or pass null to go back to plain anchor editing. Ignored
|
|
83
|
-
* with no path open. */
|
|
84
|
-
setTool(id: string | null): void;
|
|
85
75
|
/** Notified when a write changes what the anchor overlay paints. A host
|
|
86
76
|
* that owns the id announces its own changes. */
|
|
87
77
|
subscribe(listener: () => void): () => void;
|
|
@@ -154,6 +144,9 @@ interface SnapSession2dOptions {
|
|
|
154
144
|
/** How a pose's origin, the point a grid or a guide snaps, is read.
|
|
155
145
|
* Default `AUTO_ORIGIN_PROJECTION`: a rect's `{x, y}`, a path's bounds. */
|
|
156
146
|
originProjection?: OriginProjection<unknown>;
|
|
147
|
+
/** Points of each node a move snaps, in its own box frame, as
|
|
148
|
+
* `SceneCanvasSnap.anchors`. */
|
|
149
|
+
anchors?: SnapAnchors;
|
|
157
150
|
/** How `view`'s world maps into the parallax plane the gesture's points
|
|
158
151
|
* are in. Default: they are in `view`'s own world. */
|
|
159
152
|
plane?: PlaneMap | null;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { defineTool } from "../../overlayBinding.js";
|
|
2
|
+
|
|
3
|
+
//#region src/tools/builtin/anchors/anchorsTool.ts
|
|
4
|
+
/** The id of {@link anchorsTool}, which `PATH_EDIT` names as its `defaultTool`. The `pathEdit`
|
|
5
|
+
* preset mounts it. */
|
|
6
|
+
var ANCHORS_TOOL_ID = "anchors";
|
|
7
|
+
/**
|
|
8
|
+
* Path edit's anchor editing, as a tool: what a drag in path edit does with no
|
|
9
|
+
* other path-edit tool on. It binds nothing. Anchor editing's bindings —
|
|
10
|
+
* `editAnchors`, the marquee, the segment bend and the rest the `pathEdit`
|
|
11
|
+
* preset registers — are ambient, so they take a gesture under any tool that
|
|
12
|
+
* leaves it unclaimed; a path-edit tool such as the Simplify brush claims the
|
|
13
|
+
* drag at the active tier, which outranks them. Holding the active slot is
|
|
14
|
+
* what this tool is for: it is the tool path edit starts on and Escape
|
|
15
|
+
* returns to.
|
|
16
|
+
*/
|
|
17
|
+
var anchorsTool = defineTool({
|
|
18
|
+
id: ANCHORS_TOOL_ID,
|
|
19
|
+
keybinding: { key: "A" },
|
|
20
|
+
capabilities: ["edits-anchors"],
|
|
21
|
+
hookName: "anchorsTool",
|
|
22
|
+
presentation: {
|
|
23
|
+
label: "Anchors",
|
|
24
|
+
icon: /* @icon */ "core:anchors",
|
|
25
|
+
group: "path-edit"
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
//#endregion
|
|
30
|
+
export { ANCHORS_TOOL_ID, anchorsTool };
|
|
31
|
+
//# sourceMappingURL=anchorsTool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"anchorsTool.js","names":[],"sources":["../../../../src/tools/builtin/anchors/anchorsTool.ts"],"sourcesContent":["import { defineTool, type Tool } from '../../overlayBinding';\nimport { icon } from '../../../icons.gen';\n\n/** The id of {@link anchorsTool}, which `PATH_EDIT` names as its `defaultTool`. The `pathEdit`\n * preset mounts it. */\nexport const ANCHORS_TOOL_ID = 'anchors';\n\n/**\n * Path edit's anchor editing, as a tool: what a drag in path edit does with no\n * other path-edit tool on. It binds nothing. Anchor editing's bindings —\n * `editAnchors`, the marquee, the segment bend and the rest the `pathEdit`\n * preset registers — are ambient, so they take a gesture under any tool that\n * leaves it unclaimed; a path-edit tool such as the Simplify brush claims the\n * drag at the active tier, which outranks them. Holding the active slot is\n * what this tool is for: it is the tool path edit starts on and Escape\n * returns to.\n */\nexport const anchorsTool: Tool = defineTool({\n id: ANCHORS_TOOL_ID,\n keybinding: { key: 'A' },\n capabilities: ['edits-anchors'],\n hookName: 'anchorsTool',\n presentation: { label: 'Anchors', icon: icon('anchors'), group: 'path-edit' },\n});\n"],"mappings":";;;;;AAKA,CAAA,CAAA,CAAA,CAAa,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAkB,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA;;;;;;;;;;;AAY/B,CAAA,CAAA,CAAA,CAAa,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAoB,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAW;AAC1C,CAAA,CAAA,CAAA,CAAA,CAAI,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA;AACJ,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAY,CAAA,CAAE,CAAA,CAAA,CAAA,CAAA,CAAK,CAAA,CAAA,CAAA,CAAI,CAAA;AACvB,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAc,CAAC,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAe,CAAA;AAC9B,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAU,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA;AACV,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAc;AAAE,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAO,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA;AAAW,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,aAAM,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA;AAAiB,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAO,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA;AAAY,CAAA;AAC9E,CAAC,CAAA"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { INSERT_REPOSITION_BINDING } from "../../../interactions/actions/insert/repositionAction.js";
|
|
2
1
|
import { SHAPE_COUNT_RANGE } from "../../../domains/paths/shapeGenerator.js";
|
|
2
|
+
import { INSERT_REPOSITION_BINDING } from "../../../interactions/actions/insert/repositionAction.js";
|
|
3
3
|
import { defineTool } from "../../overlayBinding.js";
|
|
4
4
|
import { insertBindingBehaviors } from "../shared/insertToolOptions.js";
|
|
5
5
|
import { useCallback, useMemo, useRef, useState } from "react";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { INSERT_REPOSITION_BINDING } from "../../../interactions/actions/insert/repositionAction.js";
|
|
2
1
|
import { SHAPE_COUNT_RANGE } from "../../../domains/paths/shapeGenerator.js";
|
|
2
|
+
import { INSERT_REPOSITION_BINDING } from "../../../interactions/actions/insert/repositionAction.js";
|
|
3
3
|
import { defineTool } from "../../overlayBinding.js";
|
|
4
4
|
import { insertBindingBehaviors } from "../shared/insertToolOptions.js";
|
|
5
5
|
import { useCallback, useMemo, useRef, useState } from "react";
|
package/dist/tools/index.js
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { AREA_SELECT_ID, SELECTION_MOVE_ID, SELECTION_RESIZE_ID, SELECTION_ROTATE_ID, SELECTION_TRANSFORM_ID, areaSelectContribution, onEmptyCanvas, selectionMoveBindings, selectionMoveContribution, selectionResizeBindings, selectionResizeContribution, selectionRotateBindings, selectionRotateContribution, selectionTransformBindings, selectionTransformContribution } from "./builtin/select/selectionContributions.js";
|
|
2
2
|
import { defineTool, useTools } from "./overlayBinding.js";
|
|
3
|
+
import { useToolOptionTunings, useToolOptionValues } from "./toolOptions.js";
|
|
3
4
|
import { useKeybindings } from "./useKeybindings.js";
|
|
4
5
|
import { pickTopMostHit } from "./builtin/pickTopMostHit.js";
|
|
5
6
|
import { GROUP_ENTRY_ID, createGroupEntryContribution, useGroupEntryContribution } from "./builtin/select/groupEntry.js";
|
|
6
7
|
import { useSelectTool } from "./builtin/select/useSelectTool.js";
|
|
7
8
|
import { useHandTool } from "./builtin/hand/useHandTool.js";
|
|
8
9
|
import { DRAG_PAN_ID, dragPanContribution } from "./builtin/hand/dragPanContribution.js";
|
|
10
|
+
import { ANCHORS_TOOL_ID, anchorsTool } from "./builtin/anchors/anchorsTool.js";
|
|
9
11
|
import { useTextTool } from "./builtin/text/useTextTool.js";
|
|
10
12
|
import { STICKY_DEFAULTS, stickyData, stickyNodeFactory } from "./builtin/sticky/stickyNode.js";
|
|
11
13
|
import { useStickyTool } from "./builtin/sticky/useStickyTool.js";
|
|
@@ -22,6 +24,6 @@ import { useStarTool } from "./builtin/star/useStarTool.js";
|
|
|
22
24
|
import { usePencilTool } from "./builtin/pencil/usePencilTool.js";
|
|
23
25
|
import { useSliceTool } from "./builtin/slice/useSliceTool.js";
|
|
24
26
|
import { useMeasureTool } from "./builtin/measure/useMeasureTool.js";
|
|
25
|
-
import { isToolSet, toolIdsOf as toolIdsOf$1, toolSet as toolSet$1, toolSetHas, withoutTools } from "@weasel-js/routing";
|
|
27
|
+
import { createToolOptionValues, isToolSet, steppedOption, toolIdsOf as toolIdsOf$1, toolOptionParams, toolOptionSteps, toolSet as toolSet$1, toolSetHas, withoutTools } from "@weasel-js/routing";
|
|
26
28
|
|
|
27
|
-
export { AREA_SELECT_ID, DRAG_PAN_ID, GROUP_ENTRY_ID, SELECTION_MOVE_ID, SELECTION_RESIZE_ID, SELECTION_ROTATE_ID, SELECTION_TRANSFORM_ID, STICKY_DEFAULTS, areaSelectContribution, createGroupEntryContribution, createPointerFollower, defineTool, dragPanContribution, isToolSet, onEmptyCanvas, pickTopMostHit, selectionMoveBindings, selectionMoveContribution, selectionResizeBindings, selectionResizeContribution, selectionRotateBindings, selectionRotateContribution, selectionTransformBindings, selectionTransformContribution, stickyData, stickyNodeFactory, toolIdsOf$1 as toolIdsOf, toolSet$1 as toolSet, toolSetHas, useEllipseTool, useEyedropperTool, useGroupEntryContribution, useHandTool, useImageTool, useKeybindings, useLassoTool, useLineTool, useMeasureTool, usePenTool, usePencilTool, usePolygonTool, useRectTool, useSelectTool, useSliceTool, useStarTool, useStickyTool, useTextTool, useTools, withoutTools };
|
|
29
|
+
export { ANCHORS_TOOL_ID, AREA_SELECT_ID, DRAG_PAN_ID, GROUP_ENTRY_ID, SELECTION_MOVE_ID, SELECTION_RESIZE_ID, SELECTION_ROTATE_ID, SELECTION_TRANSFORM_ID, STICKY_DEFAULTS, anchorsTool, areaSelectContribution, createGroupEntryContribution, createPointerFollower, createToolOptionValues, defineTool, dragPanContribution, isToolSet, onEmptyCanvas, pickTopMostHit, selectionMoveBindings, selectionMoveContribution, selectionResizeBindings, selectionResizeContribution, selectionRotateBindings, selectionRotateContribution, selectionTransformBindings, selectionTransformContribution, steppedOption, stickyData, stickyNodeFactory, toolIdsOf$1 as toolIdsOf, toolOptionParams, toolOptionSteps, toolSet$1 as toolSet, toolSetHas, useEllipseTool, useEyedropperTool, useGroupEntryContribution, useHandTool, useImageTool, useKeybindings, useLassoTool, useLineTool, useMeasureTool, usePenTool, usePencilTool, usePolygonTool, useRectTool, useSelectTool, useSliceTool, useStarTool, useStickyTool, useTextTool, useToolOptionTunings, useToolOptionValues, useTools, withoutTools };
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { useEffect } from "react";
|
|
2
|
+
import { useDepSource, useOptionalDepRegistry } from "@weasel-js/routing/react";
|
|
3
|
+
|
|
4
|
+
//#region src/tools/toolOptions.ts
|
|
5
|
+
/**
|
|
6
|
+
* The canvas side of tool options (`ToolDef.options`): publishing where their
|
|
7
|
+
* values live, and tuning each tool's action from them.
|
|
8
|
+
*/
|
|
9
|
+
/** Publish where the host keeps its tools' option values, as the `toolOptionValues`
|
|
10
|
+
* dep. Silently does nothing outside a `<DepRegistryProvider>`. */
|
|
11
|
+
function useToolOptionValues(values) {
|
|
12
|
+
useDepSource("toolOptionValues", () => values);
|
|
13
|
+
}
|
|
14
|
+
function heldOptions(toolId, options, values) {
|
|
15
|
+
const held = values?.get(toolId) ?? {};
|
|
16
|
+
const out = {};
|
|
17
|
+
for (const key of Object.keys(options.prefs.children)) if (typeof held[key] === "number") out[key] = held[key];
|
|
18
|
+
return out;
|
|
19
|
+
}
|
|
20
|
+
/** Tune each tool's options action with the values the `toolOptionValues` dep
|
|
21
|
+
* holds, read on every invocation: only those it holds, so an option it does
|
|
22
|
+
* not leaves the action's own default, or another tuning's value, in place.
|
|
23
|
+
* Returns a release. */
|
|
24
|
+
function tuneToolOptions(registry, deps, tools) {
|
|
25
|
+
const releases = [];
|
|
26
|
+
for (const tool of tools) {
|
|
27
|
+
const options = tool.options;
|
|
28
|
+
if (!options) continue;
|
|
29
|
+
releases.push(registry.tune(options.actionId, { params: () => heldOptions(tool.id, options, deps?.get("toolOptionValues")) }));
|
|
30
|
+
}
|
|
31
|
+
return () => {
|
|
32
|
+
for (const r of releases) r();
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/** {@link tuneToolOptions} for as long as the component is mounted. */
|
|
36
|
+
function useToolOptionTunings(registry, tools) {
|
|
37
|
+
const deps = useOptionalDepRegistry();
|
|
38
|
+
useEffect(() => registry ? tuneToolOptions(registry, deps, Object.values(tools)) : void 0, [
|
|
39
|
+
registry,
|
|
40
|
+
deps,
|
|
41
|
+
tools
|
|
42
|
+
]);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
//#endregion
|
|
46
|
+
export { tuneToolOptions, useToolOptionTunings, useToolOptionValues };
|
|
47
|
+
//# sourceMappingURL=toolOptions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toolOptions.js","names":[],"sources":["../../src/tools/toolOptions.ts"],"sourcesContent":["/**\n * The canvas side of tool options (`ToolDef.options`): publishing where their\n * values live, and tuning each tool's action from them.\n */\nimport { useEffect } from 'react';\nimport type { ToolOptions, ToolOptionValues } from '@weasel-js/routing';\nimport { useDepSource, useOptionalDepRegistry, type DepRegistry } from '@weasel-js/routing/react';\nimport type { ActionsRegistry } from '@weasel-js/routing';\nimport type { Tool } from './overlayBinding';\n\n/** Publish where the host keeps its tools' option values, as the `toolOptionValues`\n * dep. Silently does nothing outside a `<DepRegistryProvider>`. */\nexport function useToolOptionValues(values: ToolOptionValues): void {\n useDepSource('toolOptionValues', () => values);\n}\n\nfunction heldOptions(toolId: string, options: ToolOptions, values: ToolOptionValues | undefined): Record<string, number> {\n const held = values?.get(toolId) ?? {};\n const out: Record<string, number> = {};\n for (const key of Object.keys(options.prefs.children)) if (typeof held[key] === 'number') out[key] = held[key];\n return out;\n}\n\n/** Tune each tool's options action with the values the `toolOptionValues` dep\n * holds, read on every invocation: only those it holds, so an option it does\n * not leaves the action's own default, or another tuning's value, in place.\n * Returns a release. */\nexport function tuneToolOptions(\n registry: Pick<ActionsRegistry, 'tune'>,\n deps: Pick<DepRegistry, 'get'> | null,\n tools: Iterable<Tool>,\n): () => void {\n const releases: Array<() => void> = [];\n for (const tool of tools) {\n const options = tool.options;\n if (!options) continue;\n releases.push(registry.tune(options.actionId, {\n params: () => heldOptions(tool.id, options, deps?.get('toolOptionValues')),\n }));\n }\n return () => { for (const r of releases) r(); };\n}\n\n/** {@link tuneToolOptions} for as long as the component is mounted. */\nexport function useToolOptionTunings(registry: Pick<ActionsRegistry, 'tune'> | null, tools: Readonly<Record<string, Tool>>): void {\n const deps = useOptionalDepRegistry();\n useEffect(() => (registry ? tuneToolOptions(registry, deps, Object.values(tools)) : undefined), [registry, deps, tools]);\n}\n"],"mappings":";;;;;;;;;;AAYA,SAAgB,oBAAoB,QAAgC;CAClE,aAAa,0BAA0B,MAAM;AAC/C;AAEA,SAAS,YAAY,QAAgB,SAAsB,QAA8D;CACvH,MAAM,OAAO,QAAQ,IAAI,MAAM,KAAK,CAAC;CACrC,MAAM,MAA8B,CAAC;CACrC,KAAK,MAAM,OAAO,OAAO,KAAK,QAAQ,MAAM,QAAQ,GAAG,IAAI,OAAO,KAAK,SAAS,UAAU,IAAI,OAAO,KAAK;CAC1G,OAAO;AACT;;;;;AAMA,SAAgB,gBACd,UACA,MACA,OACY;CACZ,MAAM,WAA8B,CAAC;CACrC,KAAK,MAAM,QAAQ,OAAO;EACxB,MAAM,UAAU,KAAK;EACrB,IAAI,CAAC,SAAS;EACd,SAAS,KAAK,SAAS,KAAK,QAAQ,UAAU,EAC5C,cAAc,YAAY,KAAK,IAAI,SAAS,MAAM,IAAI,kBAAkB,CAAC,EAC3E,CAAC,CAAC;CACJ;CACA,aAAa;EAAE,KAAK,MAAM,KAAK,UAAU,EAAE;CAAG;AAChD;;AAGA,SAAgB,qBAAqB,UAAgD,OAA6C;CAChI,MAAM,OAAO,uBAAuB;CACpC,gBAAiB,WAAW,gBAAgB,UAAU,MAAM,OAAO,OAAO,KAAK,CAAC,IAAI,QAAY;EAAC;EAAU;EAAM;CAAK,CAAC;AACzH"}
|
package/dist/version.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@weasel-js/core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.15.0",
|
|
4
4
|
"description": "A 2D scene-graph engine for React, rendered on WebGL2: the scene tree, viewport math, pointer and keyboard input, layered rendering, and op-based undo.",
|
|
5
5
|
"weasel": {
|
|
6
6
|
"needs": ["webgl2"]
|
|
@@ -110,31 +110,31 @@
|
|
|
110
110
|
"typecheck": "tsc --noEmit -p tsconfig.json"
|
|
111
111
|
},
|
|
112
112
|
"peerDependencies": {
|
|
113
|
-
"@weasel-js/font": "1.
|
|
113
|
+
"@weasel-js/font": "1.15.0",
|
|
114
114
|
"react": ">=18"
|
|
115
115
|
},
|
|
116
116
|
"dependencies": {
|
|
117
117
|
"@msb235/blits": "0.12.0",
|
|
118
|
-
"@weasel-js/animator": "1.
|
|
119
|
-
"@weasel-js/cursor": "1.
|
|
120
|
-
"@weasel-js/geom": "1.
|
|
121
|
-
"@weasel-js/gestures": "1.
|
|
122
|
-
"@weasel-js/headless": "1.
|
|
123
|
-
"@weasel-js/history": "1.
|
|
124
|
-
"@weasel-js/icons": "1.
|
|
125
|
-
"@weasel-js/modes": "1.
|
|
126
|
-
"@weasel-js/paint": "1.
|
|
127
|
-
"@weasel-js/prefs": "1.
|
|
128
|
-
"@weasel-js/quantity": "1.
|
|
129
|
-
"@weasel-js/react": "1.
|
|
130
|
-
"@weasel-js/registry": "1.
|
|
131
|
-
"@weasel-js/renderer": "1.
|
|
132
|
-
"@weasel-js/routing": "1.
|
|
133
|
-
"@weasel-js/select": "1.
|
|
134
|
-
"@weasel-js/simulation": "1.
|
|
135
|
-
"@weasel-js/stroke": "1.
|
|
136
|
-
"@weasel-js/text": "1.
|
|
137
|
-
"@weasel-js/text-dom": "1.
|
|
118
|
+
"@weasel-js/animator": "1.15.0",
|
|
119
|
+
"@weasel-js/cursor": "1.15.0",
|
|
120
|
+
"@weasel-js/geom": "1.15.0",
|
|
121
|
+
"@weasel-js/gestures": "1.15.0",
|
|
122
|
+
"@weasel-js/headless": "1.15.0",
|
|
123
|
+
"@weasel-js/history": "1.15.0",
|
|
124
|
+
"@weasel-js/icons": "1.15.0",
|
|
125
|
+
"@weasel-js/modes": "1.15.0",
|
|
126
|
+
"@weasel-js/paint": "1.15.0",
|
|
127
|
+
"@weasel-js/prefs": "1.15.0",
|
|
128
|
+
"@weasel-js/quantity": "1.15.0",
|
|
129
|
+
"@weasel-js/react": "1.15.0",
|
|
130
|
+
"@weasel-js/registry": "1.15.0",
|
|
131
|
+
"@weasel-js/renderer": "1.15.0",
|
|
132
|
+
"@weasel-js/routing": "1.15.0",
|
|
133
|
+
"@weasel-js/select": "1.15.0",
|
|
134
|
+
"@weasel-js/simulation": "1.15.0",
|
|
135
|
+
"@weasel-js/stroke": "1.15.0",
|
|
136
|
+
"@weasel-js/text": "1.15.0",
|
|
137
|
+
"@weasel-js/text-dom": "1.15.0",
|
|
138
138
|
"earcut": "3.2.3",
|
|
139
139
|
"polygon-clipping": "^0.15.7"
|
|
140
140
|
},
|
|
@@ -152,8 +152,8 @@
|
|
|
152
152
|
"2d"
|
|
153
153
|
],
|
|
154
154
|
"devDependencies": {
|
|
155
|
-
"@weasel-js/icons-plugin": "1.
|
|
156
|
-
"@weasel-js/modes": "1.
|
|
157
|
-
"@weasel-js/theme": "1.
|
|
155
|
+
"@weasel-js/icons-plugin": "1.15.0",
|
|
156
|
+
"@weasel-js/modes": "1.15.0",
|
|
157
|
+
"@weasel-js/theme": "1.15.0"
|
|
158
158
|
}
|
|
159
159
|
}
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import { ActionDisabledReason } from "@weasel-js/routing";
|
|
2
|
-
|
|
3
|
-
//#region src/interactions/actions/defaults/pathEditTools.ts
|
|
4
|
-
var depOf = (deps) => deps?.editAnchors?.editingId ? deps.editAnchors : null;
|
|
5
|
-
/** Whether a path-edit tool is active, so plain anchor editing should yield. */
|
|
6
|
-
function pathEditToolActive(deps) {
|
|
7
|
-
return (depOf(deps)?.tool ?? null) !== null;
|
|
8
|
-
}
|
|
9
|
-
/** A toolbar toggle for path-edit tool `tool`: on, a plain drag is that
|
|
10
|
-
* tool's; pressed again, anchor editing comes back. Its id is
|
|
11
|
-
* `pathEditTool.<tool>`. */
|
|
12
|
-
function pathEditToolAction(tool, label, icon) {
|
|
13
|
-
return {
|
|
14
|
-
id: `pathEditTool.${tool}`,
|
|
15
|
-
label,
|
|
16
|
-
...icon ? { icon } : {},
|
|
17
|
-
group: "anchors",
|
|
18
|
-
eligible: { capability: "edits-anchors" },
|
|
19
|
-
requires: ["editAnchors"],
|
|
20
|
-
invoker: {
|
|
21
|
-
timing: "immediate",
|
|
22
|
-
run: (deps) => {
|
|
23
|
-
const dep = depOf(deps);
|
|
24
|
-
if (dep) dep.setTool(dep.tool === tool ? null : tool);
|
|
25
|
-
}
|
|
26
|
-
},
|
|
27
|
-
active: (deps) => depOf(deps)?.tool === tool,
|
|
28
|
-
enabled: (deps) => depOf(deps) ? true : ActionDisabledReason.SelectionRequired
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
/** Escape with a path-edit tool on puts it down; a second Escape then leaves
|
|
32
|
-
* path edit. The phase makes it outrank `exitPathEdit`'s bare Escape, and it
|
|
33
|
-
* is disabled with no tool on, so it takes the first press only; mid-drag,
|
|
34
|
-
* Escape is `cancelGesture`'s. */
|
|
35
|
-
var exitPathEditToolAction = {
|
|
36
|
-
id: "pathEditTool.exit",
|
|
37
|
-
label: "Put down path-edit tool",
|
|
38
|
-
defaultBinding: [{
|
|
39
|
-
spec: {
|
|
40
|
-
kind: "key",
|
|
41
|
-
key: "Escape",
|
|
42
|
-
phase: [{
|
|
43
|
-
channel: "*",
|
|
44
|
-
phase: "initial"
|
|
45
|
-
}]
|
|
46
|
-
},
|
|
47
|
-
opts: { id: "pathEditTool.exit.key" }
|
|
48
|
-
}],
|
|
49
|
-
eligible: { capability: "edits-anchors" },
|
|
50
|
-
requires: ["editAnchors"],
|
|
51
|
-
invoker: {
|
|
52
|
-
timing: "immediate",
|
|
53
|
-
run: (deps) => depOf(deps)?.setTool(null)
|
|
54
|
-
},
|
|
55
|
-
enabled: (deps) => pathEditToolActive(deps) ? true : ActionDisabledReason.NotApplicable
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
//#endregion
|
|
59
|
-
export { exitPathEditToolAction, pathEditToolAction, pathEditToolActive };
|
|
60
|
-
//# sourceMappingURL=pathEditTools.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"pathEditTools.js","names":[],"sources":["../../../../src/interactions/actions/defaults/pathEditTools.ts"],"sourcesContent":["/**\n * Path edit's tools: a set of named tools, one active at a time, each\n * changing what a plain drag in path edit does (the `editAnchors` dep's `tool`).\n * With none active a drag edits anchors as usual. These actions switch them:\n * one toggle per tool for a bar, and Escape to go back to anchor editing.\n */\n\nimport type { Action, ActionDeps, ImmediateInvoker } from '@weasel-js/routing';\nimport { ActionDisabledReason } from '@weasel-js/routing';\nimport type { EditAnchorsDep } from '../depSchema';\n\nconst depOf = (deps: ActionDeps | undefined): EditAnchorsDep | null =>\n (deps?.editAnchors?.editingId ? deps.editAnchors : null);\n\n/** Whether a path-edit tool is active, so plain anchor editing should yield. */\nexport function pathEditToolActive(deps: ActionDeps | undefined): boolean {\n return (depOf(deps)?.tool ?? null) !== null;\n}\n\n/** A toolbar toggle for path-edit tool `tool`: on, a plain drag is that\n * tool's; pressed again, anchor editing comes back. Its id is\n * `pathEditTool.<tool>`. */\nexport function pathEditToolAction(\n tool: string,\n label: string,\n icon?: Action['icon'],\n): Action & { requires: string[] } {\n return {\n id: `pathEditTool.${tool}`,\n label,\n ...(icon ? { icon } : {}),\n group: 'anchors',\n eligible: { capability: 'edits-anchors' },\n requires: ['editAnchors'],\n invoker: {\n timing: 'immediate',\n run: (deps) => {\n const dep = depOf(deps);\n if (dep) dep.setTool(dep.tool === tool ? null : tool);\n },\n } as ImmediateInvoker,\n active: (deps) => depOf(deps)?.tool === tool,\n enabled: (deps) => (depOf(deps) ? true : ActionDisabledReason.SelectionRequired),\n };\n}\n\n/** Escape with a path-edit tool on puts it down; a second Escape then leaves\n * path edit. The phase makes it outrank `exitPathEdit`'s bare Escape, and it\n * is disabled with no tool on, so it takes the first press only; mid-drag,\n * Escape is `cancelGesture`'s. */\nexport const exitPathEditToolAction: Action & { requires: string[] } = {\n id: 'pathEditTool.exit',\n label: 'Put down path-edit tool',\n defaultBinding: [{ spec: { kind: 'key', key: 'Escape', phase: [{ channel: '*', phase: 'initial' }] }, opts: { id: 'pathEditTool.exit.key' } }],\n eligible: { capability: 'edits-anchors' },\n requires: ['editAnchors'],\n invoker: {\n timing: 'immediate',\n run: (deps) => depOf(deps)?.setTool(null),\n } as ImmediateInvoker,\n enabled: (deps) => (pathEditToolActive(deps) ? true : ActionDisabledReason.NotApplicable),\n};\n"],"mappings":";;;AAWA,IAAM,SAAS,SACZ,MAAM,aAAa,YAAY,KAAK,cAAc;;AAGrD,SAAgB,mBAAmB,MAAuC;CACxE,QAAQ,MAAM,IAAI,CAAC,EAAE,QAAQ,UAAU;AACzC;;;;AAKA,SAAgB,mBACd,MACA,OACA,MACiC;CACjC,OAAO;EACL,IAAI,gBAAgB;EACpB;EACA,GAAI,OAAO,EAAE,KAAK,IAAI,CAAC;EACvB,OAAO;EACP,UAAU,EAAE,YAAY,gBAAgB;EACxC,UAAU,CAAC,aAAa;EACxB,SAAS;GACP,QAAQ;GACR,MAAM,SAAS;IACb,MAAM,MAAM,MAAM,IAAI;IACtB,IAAI,KAAK,IAAI,QAAQ,IAAI,SAAS,OAAO,OAAO,IAAI;GACtD;EACF;EACA,SAAS,SAAS,MAAM,IAAI,CAAC,EAAE,SAAS;EACxC,UAAU,SAAU,MAAM,IAAI,IAAI,OAAO,qBAAqB;CAChE;AACF;;;;;AAMA,IAAa,yBAA0D;CACrE,IAAI;CACJ,OAAO;CACP,gBAAgB,CAAC;EAAE,MAAM;GAAE,MAAM;GAAO,KAAK;GAAU,OAAO,CAAC;IAAE,SAAS;IAAK,OAAO;GAAU,CAAC;EAAE;EAAG,MAAM,EAAE,IAAI,wBAAwB;CAAE,CAAC;CAC7I,UAAU,EAAE,YAAY,gBAAgB;CACxC,UAAU,CAAC,aAAa;CACxB,SAAS;EACP,QAAQ;EACR,MAAM,SAAS,MAAM,IAAI,CAAC,EAAE,QAAQ,IAAI;CAC1C;CACA,UAAU,SAAU,mBAAmB,IAAI,IAAI,OAAO,qBAAqB;AAC7E"}
|