@weasel-js/modes 1.11.1 → 1.13.0-rc.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/{chunk-TLMWTM4B.js → chunk-LFN3AJIW.js} +3 -24
- package/dist/chunk-LFN3AJIW.js.map +1 -0
- package/dist/{default-CF62V4DX.d.ts → default-D1xUSA5-.d.ts} +3 -6
- package/dist/index.d.ts +19 -16
- package/dist/index.js +4 -3
- package/dist/index.js.map +1 -1
- package/dist/presets/default.d.ts +1 -1
- package/dist/presets/default.js +1 -1
- package/package.json +2 -2
- package/dist/chunk-TLMWTM4B.js.map +0 -1
|
@@ -28,26 +28,6 @@ var PATH_EDIT = {
|
|
|
28
28
|
exit: { shortcut: "Escape" },
|
|
29
29
|
discard: { shortcut: "Meta+Escape" }
|
|
30
30
|
};
|
|
31
|
-
var ISOLATION = {
|
|
32
|
-
id: "isolation",
|
|
33
|
-
label: "Isolation",
|
|
34
|
-
description: "Work inside one group with everything outside it dimmed and locked.",
|
|
35
|
-
kind: "soft",
|
|
36
|
-
allows: [
|
|
37
|
-
"creates-selection",
|
|
38
|
-
"transforms-selection",
|
|
39
|
-
"creates-paths",
|
|
40
|
-
"creates-shapes",
|
|
41
|
-
"creates-text",
|
|
42
|
-
"samples-color",
|
|
43
|
-
"applies-fill"
|
|
44
|
-
],
|
|
45
|
-
scoping: true,
|
|
46
|
-
workspace: { tint: "#8b5cf6", gradient: "bottom-up", intensity: 0.12 },
|
|
47
|
-
entry: { trigger: "double-click-target", targets: ["group"] },
|
|
48
|
-
exit: { shortcut: "Escape" },
|
|
49
|
-
discard: { shortcut: "Meta+Escape" }
|
|
50
|
-
};
|
|
51
31
|
var FREE_TRANSFORM = {
|
|
52
32
|
id: "free-transform",
|
|
53
33
|
label: "Free Transform",
|
|
@@ -87,7 +67,6 @@ var CROP = {
|
|
|
87
67
|
var DEFAULT_MODES = [
|
|
88
68
|
NORMAL,
|
|
89
69
|
PATH_EDIT,
|
|
90
|
-
ISOLATION,
|
|
91
70
|
FREE_TRANSFORM,
|
|
92
71
|
TEXT_EDIT,
|
|
93
72
|
CROP
|
|
@@ -98,6 +77,6 @@ function byId(id) {
|
|
|
98
77
|
return m;
|
|
99
78
|
}
|
|
100
79
|
|
|
101
|
-
export { CROP, DEFAULT_MODES, FREE_TRANSFORM,
|
|
102
|
-
//# sourceMappingURL=chunk-
|
|
103
|
-
//# sourceMappingURL=chunk-
|
|
80
|
+
export { CROP, DEFAULT_MODES, FREE_TRANSFORM, NORMAL, PATH_EDIT, TEXT_EDIT, byId };
|
|
81
|
+
//# sourceMappingURL=chunk-LFN3AJIW.js.map
|
|
82
|
+
//# sourceMappingURL=chunk-LFN3AJIW.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/presets/default.ts"],"names":["m"],"mappings":"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","file":"chunk-LFN3AJIW.js","sourcesContent":["import type { ModeDefinition } from '../modeDefinition';\n\n/** The default mode: everything except anchor and text editing, no scoping,\n * no workspace tint. */\nexport const NORMAL: ModeDefinition = {\n id: 'normal',\n label: 'Normal',\n description: 'Select, draw and arrange anything on the page.',\n kind: 'soft',\n allows: [\n 'creates-selection',\n 'transforms-selection',\n 'creates-paths',\n 'creates-shapes',\n 'creates-text',\n 'samples-color',\n 'applies-fill',\n 'edits-page',\n ],\n scoping: false,\n};\n\n/** Editing the anchors of a path. Scoped to the target, entered by\n * double-clicking a `path` or with Enter, left with Escape. */\nexport const PATH_EDIT: ModeDefinition = {\n id: 'path-edit',\n label: 'Path Edit',\n description: \"Move a path's anchors and handles.\",\n kind: 'soft',\n allows: ['edits-anchors'],\n scoping: true,\n workspace: { tint: '#3b82f6', gradient: 'bottom-up', intensity: 0.12 },\n entry: { trigger: 'double-click-target', targets: ['path'], shortcut: 'Enter' },\n exit: { shortcut: 'Escape' },\n discard: { shortcut: 'Meta+Escape' },\n};\n\n/** A transaction that transforms the selection: the whole session is one undo\n * step, committed with Enter or discarded with Escape. */\nexport const FREE_TRANSFORM: ModeDefinition = {\n id: 'free-transform',\n label: 'Free Transform',\n description: 'Move, scale and rotate the selection as one undoable step.',\n kind: 'strict',\n allows: ['transforms-selection'],\n scoping: false,\n workspace: { tint: '#f59e0b', gradient: 'bottom-up', intensity: 0.12 },\n entry: { shortcut: 'Meta+T' },\n commit: { shortcut: 'Enter' },\n cancel: { shortcut: 'Escape' },\n};\n\n/** Editing the text of one node. Entered by double-clicking it, left with\n * Escape. It names no targets: the text edit opening is what enters it. */\nexport const TEXT_EDIT: ModeDefinition = {\n id: 'text-edit',\n label: 'Text Edit',\n description: \"Edit a text node's content.\",\n kind: 'soft',\n allows: ['edits-text'],\n scoping: false,\n workspace: { tint: '#10b981', gradient: 'bottom-up', intensity: 0.12 },\n entry: { trigger: 'double-click-target' },\n exit: { shortcut: 'Escape' },\n discard: { shortcut: 'Meta+Escape' },\n};\n\n/** A transaction that changes the page extents, committed with Enter or\n * discarded with Escape. */\nexport const CROP: ModeDefinition = {\n id: 'crop',\n label: 'Crop',\n description: 'Change the page extents as one undoable step.',\n kind: 'strict',\n allows: ['edits-page'],\n scoping: false,\n workspace: { tint: '#ef4444', gradient: 'bottom-up', intensity: 0.12 },\n entry: { shortcut: 'C' },\n commit: { shortcut: 'Enter' },\n cancel: { shortcut: 'Escape' },\n};\n\n/** The modes this package ships, ready to hand to `createModeRegistry`. */\nexport const DEFAULT_MODES: readonly ModeDefinition[] = [\n NORMAL,\n PATH_EDIT,\n FREE_TRANSFORM,\n TEXT_EDIT,\n CROP,\n];\n\n/** Look up one of the `DEFAULT_MODES` by id. Throws on an unknown id. For an\n * app's own mode set, use the registry's `byId` instead. */\nexport function byId(id: string): ModeDefinition {\n const m = DEFAULT_MODES.find((m) => m.id === id);\n if (!m) throw new Error(`Unknown mode id: ${id}`);\n return m;\n}\n"]}
|
|
@@ -43,7 +43,7 @@ interface ModeEntry {
|
|
|
43
43
|
* A mode: an app-level editing context that narrows which tools are usable and
|
|
44
44
|
* how the workspace looks. Tools live inside modes; a tool is never "in" one.
|
|
45
45
|
*
|
|
46
|
-
* `kind` picks the lifecycle. A `soft` mode (path-edit,
|
|
46
|
+
* `kind` picks the lifecycle. A `soft` mode (path-edit, text-edit)
|
|
47
47
|
* is a scoped context with no commit ceremony — every edit inside it is
|
|
48
48
|
* independently undoable and `exit` is non-destructive. A `strict` mode
|
|
49
49
|
* (free-transform, crop) is a transaction: the whole session collapses to one
|
|
@@ -93,9 +93,6 @@ declare const NORMAL: ModeDefinition;
|
|
|
93
93
|
/** Editing the anchors of a path. Scoped to the target, entered by
|
|
94
94
|
* double-clicking a `path` or with Enter, left with Escape. */
|
|
95
95
|
declare const PATH_EDIT: ModeDefinition;
|
|
96
|
-
/** Working inside one subtree with everything outside it dimmed and inert,
|
|
97
|
-
* entered by double-clicking a `group`. Allows the same authoring tools as `NORMAL`, minus page edits. */
|
|
98
|
-
declare const ISOLATION: ModeDefinition;
|
|
99
96
|
/** A transaction that transforms the selection: the whole session is one undo
|
|
100
97
|
* step, committed with Enter or discarded with Escape. */
|
|
101
98
|
declare const FREE_TRANSFORM: ModeDefinition;
|
|
@@ -105,10 +102,10 @@ declare const TEXT_EDIT: ModeDefinition;
|
|
|
105
102
|
/** A transaction that changes the page extents, committed with Enter or
|
|
106
103
|
* discarded with Escape. */
|
|
107
104
|
declare const CROP: ModeDefinition;
|
|
108
|
-
/** The
|
|
105
|
+
/** The modes this package ships, ready to hand to `createModeRegistry`. */
|
|
109
106
|
declare const DEFAULT_MODES: readonly ModeDefinition[];
|
|
110
107
|
/** Look up one of the `DEFAULT_MODES` by id. Throws on an unknown id. For an
|
|
111
108
|
* app's own mode set, use the registry's `byId` instead. */
|
|
112
109
|
declare function byId(id: string): ModeDefinition;
|
|
113
110
|
|
|
114
|
-
export { ALL_TAGS as A, type CapabilityTag as C, DEFAULT_MODES as D, FREE_TRANSFORM as F, IMPLICIT_TAGS as I, type ModeDefinition as M, NORMAL as N, PATH_EDIT as P, TEXT_EDIT as T, type WorkspaceVisual as W, CROP as a,
|
|
111
|
+
export { ALL_TAGS as A, type CapabilityTag as C, DEFAULT_MODES as D, FREE_TRANSFORM as F, IMPLICIT_TAGS as I, type ModeDefinition as M, NORMAL as N, PATH_EDIT as P, TEXT_EDIT as T, type WorkspaceVisual as W, CROP as a, type ModeEntry as b, byId as c, capabilitiesAllowed as d, eligibleForMode as e, isCapabilityTag as i, modeLabel as m };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { M as ModeDefinition, C as CapabilityTag } from './default-
|
|
2
|
-
export { A as ALL_TAGS, a as CROP, D as DEFAULT_MODES, F as FREE_TRANSFORM, I as IMPLICIT_TAGS, b as
|
|
1
|
+
import { M as ModeDefinition, C as CapabilityTag } from './default-D1xUSA5-.js';
|
|
2
|
+
export { A as ALL_TAGS, a as CROP, D as DEFAULT_MODES, F as FREE_TRANSFORM, I as IMPLICIT_TAGS, b as ModeEntry, N as NORMAL, P as PATH_EDIT, T as TEXT_EDIT, W as WorkspaceVisual, c as byId, d as capabilitiesAllowed, e as eligibleForMode, i as isCapabilityTag, m as modeLabel } from './default-D1xUSA5-.js';
|
|
3
3
|
import { Reflection } from '@weasel-js/registry';
|
|
4
4
|
|
|
5
5
|
/** Options for `createModeRegistry`: the modes to register and which one is
|
|
@@ -91,32 +91,35 @@ declare function eligibleContribution(reg: ModeRegistry, entry: {
|
|
|
91
91
|
interface CreateScopingDimOptions {
|
|
92
92
|
registry: ModeRegistry;
|
|
93
93
|
/** Returns the set of node ids that are *in* scope for the current mode.
|
|
94
|
-
* The app computes this — typically:
|
|
95
|
-
*
|
|
94
|
+
* The app computes this — typically: the edited path for path-edit,
|
|
95
|
+
* empty for non-scoping modes. */
|
|
96
96
|
getTargetIds: () => ReadonlySet<string>;
|
|
97
|
-
/** Alpha for out-of-scope nodes. Default
|
|
97
|
+
/** Alpha for out-of-scope nodes. Default {@link OUT_OF_SCOPE_ALPHA}. */
|
|
98
98
|
dimAlpha?: number;
|
|
99
99
|
}
|
|
100
|
-
/**
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
* the
|
|
104
|
-
*
|
|
105
|
-
|
|
106
|
-
interface ScopingDim {
|
|
100
|
+
/** The alpha a node outside a scope is drawn at, unless the scope says otherwise. */
|
|
101
|
+
declare const OUT_OF_SCOPE_ALPHA = 0.3;
|
|
102
|
+
/** How a canvas treats each node under a scope: lit or dimmed, reachable or not. Consult it
|
|
103
|
+
* from the renderer and the hit-tester; `subscribe` hears its answers change, so a canvas
|
|
104
|
+
* can repaint on it (`<SceneCanvas redrawOn>`). */
|
|
105
|
+
interface NodeScope {
|
|
107
106
|
/** Multiplier in [0, 1] to apply to a node's render alpha. */
|
|
108
107
|
alphaFor(id: string): number;
|
|
109
108
|
/** Whether the node should respond to pointer hits. */
|
|
110
109
|
isPointerInteractive(id: string): boolean;
|
|
111
|
-
/**
|
|
112
|
-
invalidate(): void;
|
|
113
|
-
/** Monotonic; bumps on a mode switch and on `invalidate`. */
|
|
110
|
+
/** Monotonic; bumps whenever the answers may have changed. */
|
|
114
111
|
getVersion(): number;
|
|
115
112
|
subscribe(listener: () => void): () => void;
|
|
116
113
|
}
|
|
114
|
+
/** A {@link NodeScope} for a mode registry: it computes nothing itself, and its answers change
|
|
115
|
+
* when the mode does, or when the app says the target set moved (`invalidate`). */
|
|
116
|
+
interface ScopingDim extends NodeScope {
|
|
117
|
+
/** Tell subscribers the target set changed without a mode switch. */
|
|
118
|
+
invalidate(): void;
|
|
119
|
+
}
|
|
117
120
|
/** Build the scoping lookup for a mode registry. In a mode with
|
|
118
121
|
* `scoping: false` every node is full-alpha and interactive, so this is safe
|
|
119
122
|
* to consult unconditionally. */
|
|
120
123
|
declare function createScopingDim(opts: CreateScopingDimOptions): ScopingDim;
|
|
121
124
|
|
|
122
|
-
export { type ActiveMode, CapabilityTag, type CreateModeDecorationsOptions, type CreateModeRegistryOptions, type CreateScopingDimOptions, type ModeDecorationPainter, type ModeDecorations, ModeDefinition, type ModeDrawCommand, type ModeRegistry, type ScopingDim, type ToolLike, activeModeOf, createModeDecorations, createModeRegistry, createScopingDim, eligibleContribution, eligibleTool, getActiveModeFor };
|
|
125
|
+
export { type ActiveMode, CapabilityTag, type CreateModeDecorationsOptions, type CreateModeRegistryOptions, type CreateScopingDimOptions, type ModeDecorationPainter, type ModeDecorations, ModeDefinition, type ModeDrawCommand, type ModeRegistry, type NodeScope, OUT_OF_SCOPE_ALPHA, type ScopingDim, type ToolLike, activeModeOf, createModeDecorations, createModeRegistry, createScopingDim, eligibleContribution, eligibleTool, getActiveModeFor };
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { CROP, DEFAULT_MODES, FREE_TRANSFORM,
|
|
1
|
+
export { CROP, DEFAULT_MODES, FREE_TRANSFORM, NORMAL, PATH_EDIT, TEXT_EDIT, byId } from './chunk-LFN3AJIW.js';
|
|
2
2
|
import { createReflectable, createEmitter } from '@weasel-js/registry';
|
|
3
3
|
|
|
4
4
|
// src/capabilities.ts
|
|
@@ -116,9 +116,10 @@ function eligibleTool(reg, tool) {
|
|
|
116
116
|
function eligibleContribution(reg, entry) {
|
|
117
117
|
return eligibleForMode(reg.current(), entry.eligibility?.capabilities ?? []);
|
|
118
118
|
}
|
|
119
|
+
var OUT_OF_SCOPE_ALPHA = 0.3;
|
|
119
120
|
function createScopingDim(opts) {
|
|
120
121
|
const { registry } = opts;
|
|
121
|
-
const dim = opts.dimAlpha ??
|
|
122
|
+
const dim = opts.dimAlpha ?? OUT_OF_SCOPE_ALPHA;
|
|
122
123
|
const listeners = createEmitter();
|
|
123
124
|
let invalidations = 0;
|
|
124
125
|
return {
|
|
@@ -148,6 +149,6 @@ function createScopingDim(opts) {
|
|
|
148
149
|
};
|
|
149
150
|
}
|
|
150
151
|
|
|
151
|
-
export { ALL_TAGS, IMPLICIT_TAGS, activeModeOf, capabilitiesAllowed, createModeDecorations, createModeRegistry, createScopingDim, eligibleContribution, eligibleForMode, eligibleTool, getActiveModeFor, isCapabilityTag, modeLabel };
|
|
152
|
+
export { ALL_TAGS, IMPLICIT_TAGS, OUT_OF_SCOPE_ALPHA, activeModeOf, capabilitiesAllowed, createModeDecorations, createModeRegistry, createScopingDim, eligibleContribution, eligibleForMode, eligibleTool, getActiveModeFor, isCapabilityTag, modeLabel };
|
|
152
153
|
//# sourceMappingURL=index.js.map
|
|
153
154
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/capabilities.ts","../src/modeDefinition.ts","../src/registry.ts","../src/decorations.ts","../src/eligibility.ts","../src/scopingLayer.ts"],"names":["createEmitter"],"mappings":"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","file":"index.js","sourcesContent":["/** The full vocabulary of capability tags shipped in the default preset.\n * Apps and other consumers can add their own tags; this list is what\n * `weasel-modes` itself uses. */\nexport const ALL_TAGS = [\n 'navigation',\n 'creates-selection',\n 'creates-paths',\n 'creates-shapes',\n 'creates-text',\n 'edits-anchors',\n 'edits-text',\n 'transforms-selection',\n 'samples-color',\n 'applies-fill',\n 'edits-page',\n] as const;\n\n/** One capability a tool or contribution declares, and a mode allows. Any\n * string is accepted so apps can add tags of their own; `ALL_TAGS` is the\n * set this package ships. */\nexport type CapabilityTag = (typeof ALL_TAGS)[number] | (string & {});\n\n/** Tags that are implicitly allowed in every mode — never listed per-mode.\n * A tool carrying only these is eligible everywhere. */\nexport const IMPLICIT_TAGS: readonly CapabilityTag[] = ['navigation'];\n\n/**\n * Whether a tool or contribution carrying `tags` may be used while `allowed`\n * is the set of tags the active mode permits. Every tag has to be allowed: a\n * tag names something the entry does, and one refused thing refuses the entry.\n * An entry with no tags asks for nothing and is allowed everywhere.\n */\nexport function capabilitiesAllowed(allowed: ReadonlySet<string>, tags: readonly CapabilityTag[] | undefined): boolean {\n return tags === undefined || tags.every((tag) => allowed.has(tag));\n}\n\n/** Whether a string is one of the shipped `ALL_TAGS`. An app-defined tag is\n * still a valid `CapabilityTag` and will answer `false` here. */\nexport function isCapabilityTag(value: string): value is CapabilityTag {\n return (ALL_TAGS as readonly string[]).includes(value);\n}\n","import { capabilitiesAllowed, IMPLICIT_TAGS, type CapabilityTag } from './capabilities';\n\n/** How a mode tints the workspace — the area around the page — so the user\n * can see at a glance which mode is active. */\nexport interface WorkspaceVisual {\n tint?: string;\n gradient?: 'top-down' | 'bottom-up';\n intensity?: number;\n}\n\n/** How a mode is entered. */\nexport interface ModeEntry {\n shortcut?: string;\n /** `'double-click-target'`: double-clicking a node enters the mode on that node. Which nodes is\n * `targets`; `modeTriggers` in `@weasel-js/core` turns the pair into a canvas binding. */\n trigger?: 'double-click-target';\n /** The routing kinds a double-click enters this mode on — the `Hit.kind` vocabulary a\n * binding's `kind:<k>` target reads, so `'path'` or an app's own `'group'`. A trigger with no\n * targets binds nothing, for a mode whose entry follows something else (text-edit, which the\n * edit opening enters). */\n targets?: readonly string[];\n}\n\n/**\n * A mode: an app-level editing context that narrows which tools are usable and\n * how the workspace looks. Tools live inside modes; a tool is never \"in\" one.\n *\n * `kind` picks the lifecycle. A `soft` mode (path-edit, isolation, text-edit)\n * is a scoped context with no commit ceremony — every edit inside it is\n * independently undoable and `exit` is non-destructive. A `strict` mode\n * (free-transform, crop) is a transaction: the whole session collapses to one\n * undoable step and leaving requires an explicit `commit` or `cancel`.\n *\n * The four shortcut fields are key chords (`'Escape'`, `'Meta+T'`) that\n * `modeShortcuts` in `@weasel-js/routing` turns into dispatcher bindings,\n * each live only while the mode it acts on is (or, for `entry`, is not).\n */\nexport interface ModeDefinition {\n id: string;\n /** Human-readable name for chrome — a breadcrumb, a status bar. Falls back\n * to `id`; read it through {@link modeLabel}. */\n label?: string;\n /** One sentence on what the mode is for, for a tooltip or a hint line. */\n description?: string;\n kind: 'soft' | 'strict';\n /** Capability tags this mode allows beyond IMPLICIT_TAGS. */\n allows: CapabilityTag[];\n /** When true, out-of-target objects dim at the renderer layer. */\n scoping: boolean;\n workspace?: WorkspaceVisual;\n entry?: ModeEntry;\n exit?: { shortcut?: string };\n commit?: { shortcut?: string };\n cancel?: { shortcut?: string };\n /** Leave a soft mode and throw its session away, where `exit` keeps it to\n * resume. */\n discard?: { shortcut?: string };\n}\n\n/** A mode's display name: its `label`, else its `id`. */\nexport function modeLabel(mode: ModeDefinition): string {\n return mode.label ?? mode.id;\n}\n\n/** True iff a tool carrying `toolTags` is eligible for `mode`. */\nexport function eligibleForMode(mode: ModeDefinition, toolTags: readonly CapabilityTag[]): boolean {\n return capabilitiesAllowed(allowedCapabilitiesOf(mode), toolTags);\n}\n\n/** Every tag `mode` permits: its `allows` plus `IMPLICIT_TAGS`. */\nexport function allowedCapabilitiesOf(mode: ModeDefinition): Set<string> {\n return new Set<string>([...mode.allows, ...IMPLICIT_TAGS]);\n}\n","import { createReflectable, type Reflection } from '@weasel-js/registry';\nimport { allowedCapabilitiesOf, type ModeDefinition } from './modeDefinition';\n\n/** Options for `createModeRegistry`: the modes to register and which one is\n * active at startup. */\nexport interface CreateModeRegistryOptions {\n modes: readonly ModeDefinition[];\n initial: string;\n}\n\n/** Holds the set of available modes and which one is active, and notifies\n * subscribers when that changes. `getVersion` is a monotonic counter for\n * render-cache invalidation. Unknown mode ids throw rather than being\n * ignored. */\nexport interface ModeRegistry {\n current(): ModeDefinition;\n /** Every registered mode, in registration order. */\n list(): readonly ModeDefinition[];\n setMode(id: string): void;\n byId(id: string): ModeDefinition;\n getVersion(): number;\n subscribe(listener: () => void): () => void;\n /** The registered modes keyed by id. Shares this registry's version, so it\n * also advances on `setMode`. */\n readonly reflection: Reflection<ModeDefinition>;\n}\n\n/** Build a mode registry. Throws if two of `modes` share an id, or if\n * `initial` does not name one of them. */\nexport function createModeRegistry(opts: CreateModeRegistryOptions): ModeRegistry {\n const modes = createReflectable<ModeDefinition>();\n for (const m of opts.modes) {\n if (modes.get(m.id)) throw new Error(`createModeRegistry: duplicate mode id \"${m.id}\"`);\n modes.set(m.id, m);\n }\n const initial = modes.get(opts.initial);\n if (!initial) throw new Error(`Initial mode \"${opts.initial}\" not in modes list`);\n\n let active: ModeDefinition = initial;\n\n return {\n current: () => active,\n list: () => opts.modes,\n setMode(id: string): void {\n const next = modes.get(id);\n if (!next) throw new Error(`Unknown mode id: ${id}`);\n if (next === active) return;\n active = next;\n modes.bump();\n },\n byId(id: string): ModeDefinition {\n const m = modes.get(id);\n if (!m) throw new Error(`Unknown mode id: ${id}`);\n return m;\n },\n getVersion: modes.getVersion,\n subscribe: modes.subscribe,\n reflection: modes.reflection,\n };\n}\n\n/** The active mode as a canvas gates on it: its id, and every capability tag\n * a tool may carry to be usable in it — the mode's `allows` plus\n * `IMPLICIT_TAGS`. The shape `<SceneCanvas modes>` gates on. */\nexport interface ActiveMode {\n id: string;\n allowedCapabilities: ReadonlySet<string>;\n}\n\n/** A mode definition as a canvas gates on it. */\nexport function activeModeOf(mode: ModeDefinition): ActiveMode {\n return { id: mode.id, allowedCapabilities: allowedCapabilitiesOf(mode) };\n}\n\n/** A reader for the registry's active mode, as `<SceneCanvas modes>` builds\n * one. It returns the same object until the mode changes. */\nexport function getActiveModeFor(registry: ModeRegistry): () => ActiveMode {\n let cached: { version: number; value: ActiveMode } | null = null;\n return () => {\n const version = registry.getVersion();\n if (cached?.version !== version) cached = { version, value: activeModeOf(registry.current()) };\n return cached.value;\n };\n}\n","import { createEmitter } from '@weasel-js/registry';\nimport type { ModeRegistry } from './registry';\n\n/** Loose draw-command type — the kit's `DrawCommand` union shape is over in\n * `src/renderer`. We keep this opaque to avoid a cross-package import in\n * the type surface; consumers cast to the real DrawCommand at use site. */\nexport type ModeDrawCommand = unknown;\n\n/** Produces the draw commands for one mode's persistent decorations. Called\n * once per paint while that mode is active. */\nexport type ModeDecorationPainter = () => ModeDrawCommand[];\n\n/** Options for `createModeDecorations`. */\nexport interface CreateModeDecorationsOptions {\n registry: ModeRegistry;\n}\n\n/** Per-mode decoration painters, keyed by mode id. Mode decorations are drawn\n * for as long as the mode is active and belong to the mode rather than to any\n * tool — path-edit's anchor dots and handle lines are the motivating case. */\nexport interface ModeDecorations {\n /** Register (or replace) the painter for a mode id. Returns a release that\n * removes it, and does nothing once another painter has replaced it. */\n register(modeId: string, painter: ModeDecorationPainter): () => void;\n /** Paint the active mode's decorations. Returns an empty array if no\n * painter is registered for the active mode. */\n paint(): ModeDrawCommand[];\n /** Monotonic version. Bumps on mode change, painter registration, or release. */\n getVersion(): number;\n /** Notified whenever `getVersion` bumps — what a canvas repaints on. */\n subscribe(listener: () => void): () => void;\n}\n\n/** Build a decoration registry bound to a mode registry, so switching modes\n * switches which painter runs. */\nexport function createModeDecorations(opts: CreateModeDecorationsOptions): ModeDecorations {\n const { registry } = opts;\n const painters = new Map<string, ModeDecorationPainter>();\n const listeners = createEmitter();\n let registrations = 0;\n const changed = (): void => {\n registrations++;\n listeners.emit();\n };\n\n return {\n register(modeId: string, painter: ModeDecorationPainter): () => void {\n painters.set(modeId, painter);\n changed();\n return () => {\n if (painters.get(modeId) !== painter) return;\n painters.delete(modeId);\n changed();\n };\n },\n paint(): ModeDrawCommand[] {\n const painter = painters.get(registry.current().id);\n if (!painter) return [];\n return painter();\n },\n getVersion: () => registry.getVersion() + registrations,\n subscribe(listener: () => void): () => void {\n const off = listeners.subscribe(listener);\n const offMode = registry.subscribe(listener);\n return () => {\n off();\n offMode();\n };\n },\n };\n}\n","import type { ModeRegistry } from './registry';\nimport type { CapabilityTag } from './capabilities';\nimport { eligibleForMode } from './modeDefinition';\n\n/** The part of a tool this package needs in order to judge eligibility: its\n * id and the capabilities it claims. Structural, so a real `ToolDef`\n * satisfies it without this package depending on the kit. */\nexport interface ToolLike {\n id: string;\n capabilities?: readonly CapabilityTag[];\n}\n\n/** True iff `tool` is usable in the registry's currently active mode. */\nexport function eligibleTool(reg: ModeRegistry, tool: ToolLike): boolean {\n return eligibleForMode(reg.current(), tool.capabilities ?? []);\n}\n\n/** True iff a contribution is usable in the registry's active mode. */\nexport function eligibleContribution(\n reg: ModeRegistry,\n entry: { id: string; eligibility?: { capabilities?: readonly CapabilityTag[] } },\n): boolean {\n return eligibleForMode(reg.current(), entry.eligibility?.capabilities ?? []);\n}\n","import { createEmitter } from '@weasel-js/registry';\nimport type { ModeRegistry } from './registry';\n\n/** Options for `createScopingDim`. */\nexport interface CreateScopingDimOptions {\n registry: ModeRegistry;\n /** Returns the set of node ids that are *in* scope for the current mode.\n * The app computes this — typically: selection-only for path-edit,\n * isolated subtree for isolation, empty for non-scoping modes. */\n getTargetIds: () => ReadonlySet<string>;\n /** Alpha for out-of-scope nodes. Default 0.3 (spec). */\n dimAlpha?: number;\n}\n\n/** Answers, per node, how a scoping mode should treat it: dimmed or not,\n * hit-testable or not. Consult it from the renderer and the hit-tester —\n * it computes nothing itself. Its answers change when the mode does, or when\n * the app says the target set moved (`invalidate`); both notify\n * subscribers, so a canvas can repaint on `subscribe` (`<SceneCanvas\n * redrawOn>`). */\nexport interface ScopingDim {\n /** Multiplier in [0, 1] to apply to a node's render alpha. */\n alphaFor(id: string): number;\n /** Whether the node should respond to pointer hits. */\n isPointerInteractive(id: string): boolean;\n /** Tell subscribers the target set changed without a mode switch. */\n invalidate(): void;\n /** Monotonic; bumps on a mode switch and on `invalidate`. */\n getVersion(): number;\n subscribe(listener: () => void): () => void;\n}\n\n/** Build the scoping lookup for a mode registry. In a mode with\n * `scoping: false` every node is full-alpha and interactive, so this is safe\n * to consult unconditionally. */\nexport function createScopingDim(opts: CreateScopingDimOptions): ScopingDim {\n const { registry } = opts;\n const dim = opts.dimAlpha ?? 0.3;\n const listeners = createEmitter();\n let invalidations = 0;\n return {\n alphaFor(id) {\n const mode = registry.current();\n if (!mode.scoping) return 1;\n return opts.getTargetIds().has(id) ? 1 : dim;\n },\n isPointerInteractive(id) {\n const mode = registry.current();\n if (!mode.scoping) return true;\n return opts.getTargetIds().has(id);\n },\n invalidate() {\n invalidations++;\n listeners.emit();\n },\n getVersion: () => registry.getVersion() + invalidations,\n subscribe(listener) {\n const off = listeners.subscribe(listener);\n const offMode = registry.subscribe(listener);\n return () => {\n off();\n offMode();\n };\n },\n };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/capabilities.ts","../src/modeDefinition.ts","../src/registry.ts","../src/decorations.ts","../src/eligibility.ts","../src/scopingLayer.ts"],"names":["createEmitter"],"mappings":"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","file":"index.js","sourcesContent":["/** The full vocabulary of capability tags shipped in the default preset.\n * Apps and other consumers can add their own tags; this list is what\n * `weasel-modes` itself uses. */\nexport const ALL_TAGS = [\n 'navigation',\n 'creates-selection',\n 'creates-paths',\n 'creates-shapes',\n 'creates-text',\n 'edits-anchors',\n 'edits-text',\n 'transforms-selection',\n 'samples-color',\n 'applies-fill',\n 'edits-page',\n] as const;\n\n/** One capability a tool or contribution declares, and a mode allows. Any\n * string is accepted so apps can add tags of their own; `ALL_TAGS` is the\n * set this package ships. */\nexport type CapabilityTag = (typeof ALL_TAGS)[number] | (string & {});\n\n/** Tags that are implicitly allowed in every mode — never listed per-mode.\n * A tool carrying only these is eligible everywhere. */\nexport const IMPLICIT_TAGS: readonly CapabilityTag[] = ['navigation'];\n\n/**\n * Whether a tool or contribution carrying `tags` may be used while `allowed`\n * is the set of tags the active mode permits. Every tag has to be allowed: a\n * tag names something the entry does, and one refused thing refuses the entry.\n * An entry with no tags asks for nothing and is allowed everywhere.\n */\nexport function capabilitiesAllowed(allowed: ReadonlySet<string>, tags: readonly CapabilityTag[] | undefined): boolean {\n return tags === undefined || tags.every((tag) => allowed.has(tag));\n}\n\n/** Whether a string is one of the shipped `ALL_TAGS`. An app-defined tag is\n * still a valid `CapabilityTag` and will answer `false` here. */\nexport function isCapabilityTag(value: string): value is CapabilityTag {\n return (ALL_TAGS as readonly string[]).includes(value);\n}\n","import { capabilitiesAllowed, IMPLICIT_TAGS, type CapabilityTag } from './capabilities';\n\n/** How a mode tints the workspace — the area around the page — so the user\n * can see at a glance which mode is active. */\nexport interface WorkspaceVisual {\n tint?: string;\n gradient?: 'top-down' | 'bottom-up';\n intensity?: number;\n}\n\n/** How a mode is entered. */\nexport interface ModeEntry {\n shortcut?: string;\n /** `'double-click-target'`: double-clicking a node enters the mode on that node. Which nodes is\n * `targets`; `modeTriggers` in `@weasel-js/core` turns the pair into a canvas binding. */\n trigger?: 'double-click-target';\n /** The routing kinds a double-click enters this mode on — the `Hit.kind` vocabulary a\n * binding's `kind:<k>` target reads, so `'path'` or an app's own `'group'`. A trigger with no\n * targets binds nothing, for a mode whose entry follows something else (text-edit, which the\n * edit opening enters). */\n targets?: readonly string[];\n}\n\n/**\n * A mode: an app-level editing context that narrows which tools are usable and\n * how the workspace looks. Tools live inside modes; a tool is never \"in\" one.\n *\n * `kind` picks the lifecycle. A `soft` mode (path-edit, text-edit)\n * is a scoped context with no commit ceremony — every edit inside it is\n * independently undoable and `exit` is non-destructive. A `strict` mode\n * (free-transform, crop) is a transaction: the whole session collapses to one\n * undoable step and leaving requires an explicit `commit` or `cancel`.\n *\n * The four shortcut fields are key chords (`'Escape'`, `'Meta+T'`) that\n * `modeShortcuts` in `@weasel-js/routing` turns into dispatcher bindings,\n * each live only while the mode it acts on is (or, for `entry`, is not).\n */\nexport interface ModeDefinition {\n id: string;\n /** Human-readable name for chrome — a breadcrumb, a status bar. Falls back\n * to `id`; read it through {@link modeLabel}. */\n label?: string;\n /** One sentence on what the mode is for, for a tooltip or a hint line. */\n description?: string;\n kind: 'soft' | 'strict';\n /** Capability tags this mode allows beyond IMPLICIT_TAGS. */\n allows: CapabilityTag[];\n /** When true, out-of-target objects dim at the renderer layer. */\n scoping: boolean;\n workspace?: WorkspaceVisual;\n entry?: ModeEntry;\n exit?: { shortcut?: string };\n commit?: { shortcut?: string };\n cancel?: { shortcut?: string };\n /** Leave a soft mode and throw its session away, where `exit` keeps it to\n * resume. */\n discard?: { shortcut?: string };\n}\n\n/** A mode's display name: its `label`, else its `id`. */\nexport function modeLabel(mode: ModeDefinition): string {\n return mode.label ?? mode.id;\n}\n\n/** True iff a tool carrying `toolTags` is eligible for `mode`. */\nexport function eligibleForMode(mode: ModeDefinition, toolTags: readonly CapabilityTag[]): boolean {\n return capabilitiesAllowed(allowedCapabilitiesOf(mode), toolTags);\n}\n\n/** Every tag `mode` permits: its `allows` plus `IMPLICIT_TAGS`. */\nexport function allowedCapabilitiesOf(mode: ModeDefinition): Set<string> {\n return new Set<string>([...mode.allows, ...IMPLICIT_TAGS]);\n}\n","import { createReflectable, type Reflection } from '@weasel-js/registry';\nimport { allowedCapabilitiesOf, type ModeDefinition } from './modeDefinition';\n\n/** Options for `createModeRegistry`: the modes to register and which one is\n * active at startup. */\nexport interface CreateModeRegistryOptions {\n modes: readonly ModeDefinition[];\n initial: string;\n}\n\n/** Holds the set of available modes and which one is active, and notifies\n * subscribers when that changes. `getVersion` is a monotonic counter for\n * render-cache invalidation. Unknown mode ids throw rather than being\n * ignored. */\nexport interface ModeRegistry {\n current(): ModeDefinition;\n /** Every registered mode, in registration order. */\n list(): readonly ModeDefinition[];\n setMode(id: string): void;\n byId(id: string): ModeDefinition;\n getVersion(): number;\n subscribe(listener: () => void): () => void;\n /** The registered modes keyed by id. Shares this registry's version, so it\n * also advances on `setMode`. */\n readonly reflection: Reflection<ModeDefinition>;\n}\n\n/** Build a mode registry. Throws if two of `modes` share an id, or if\n * `initial` does not name one of them. */\nexport function createModeRegistry(opts: CreateModeRegistryOptions): ModeRegistry {\n const modes = createReflectable<ModeDefinition>();\n for (const m of opts.modes) {\n if (modes.get(m.id)) throw new Error(`createModeRegistry: duplicate mode id \"${m.id}\"`);\n modes.set(m.id, m);\n }\n const initial = modes.get(opts.initial);\n if (!initial) throw new Error(`Initial mode \"${opts.initial}\" not in modes list`);\n\n let active: ModeDefinition = initial;\n\n return {\n current: () => active,\n list: () => opts.modes,\n setMode(id: string): void {\n const next = modes.get(id);\n if (!next) throw new Error(`Unknown mode id: ${id}`);\n if (next === active) return;\n active = next;\n modes.bump();\n },\n byId(id: string): ModeDefinition {\n const m = modes.get(id);\n if (!m) throw new Error(`Unknown mode id: ${id}`);\n return m;\n },\n getVersion: modes.getVersion,\n subscribe: modes.subscribe,\n reflection: modes.reflection,\n };\n}\n\n/** The active mode as a canvas gates on it: its id, and every capability tag\n * a tool may carry to be usable in it — the mode's `allows` plus\n * `IMPLICIT_TAGS`. The shape `<SceneCanvas modes>` gates on. */\nexport interface ActiveMode {\n id: string;\n allowedCapabilities: ReadonlySet<string>;\n}\n\n/** A mode definition as a canvas gates on it. */\nexport function activeModeOf(mode: ModeDefinition): ActiveMode {\n return { id: mode.id, allowedCapabilities: allowedCapabilitiesOf(mode) };\n}\n\n/** A reader for the registry's active mode, as `<SceneCanvas modes>` builds\n * one. It returns the same object until the mode changes. */\nexport function getActiveModeFor(registry: ModeRegistry): () => ActiveMode {\n let cached: { version: number; value: ActiveMode } | null = null;\n return () => {\n const version = registry.getVersion();\n if (cached?.version !== version) cached = { version, value: activeModeOf(registry.current()) };\n return cached.value;\n };\n}\n","import { createEmitter } from '@weasel-js/registry';\nimport type { ModeRegistry } from './registry';\n\n/** Loose draw-command type — the kit's `DrawCommand` union shape is over in\n * `src/renderer`. We keep this opaque to avoid a cross-package import in\n * the type surface; consumers cast to the real DrawCommand at use site. */\nexport type ModeDrawCommand = unknown;\n\n/** Produces the draw commands for one mode's persistent decorations. Called\n * once per paint while that mode is active. */\nexport type ModeDecorationPainter = () => ModeDrawCommand[];\n\n/** Options for `createModeDecorations`. */\nexport interface CreateModeDecorationsOptions {\n registry: ModeRegistry;\n}\n\n/** Per-mode decoration painters, keyed by mode id. Mode decorations are drawn\n * for as long as the mode is active and belong to the mode rather than to any\n * tool — path-edit's anchor dots and handle lines are the motivating case. */\nexport interface ModeDecorations {\n /** Register (or replace) the painter for a mode id. Returns a release that\n * removes it, and does nothing once another painter has replaced it. */\n register(modeId: string, painter: ModeDecorationPainter): () => void;\n /** Paint the active mode's decorations. Returns an empty array if no\n * painter is registered for the active mode. */\n paint(): ModeDrawCommand[];\n /** Monotonic version. Bumps on mode change, painter registration, or release. */\n getVersion(): number;\n /** Notified whenever `getVersion` bumps — what a canvas repaints on. */\n subscribe(listener: () => void): () => void;\n}\n\n/** Build a decoration registry bound to a mode registry, so switching modes\n * switches which painter runs. */\nexport function createModeDecorations(opts: CreateModeDecorationsOptions): ModeDecorations {\n const { registry } = opts;\n const painters = new Map<string, ModeDecorationPainter>();\n const listeners = createEmitter();\n let registrations = 0;\n const changed = (): void => {\n registrations++;\n listeners.emit();\n };\n\n return {\n register(modeId: string, painter: ModeDecorationPainter): () => void {\n painters.set(modeId, painter);\n changed();\n return () => {\n if (painters.get(modeId) !== painter) return;\n painters.delete(modeId);\n changed();\n };\n },\n paint(): ModeDrawCommand[] {\n const painter = painters.get(registry.current().id);\n if (!painter) return [];\n return painter();\n },\n getVersion: () => registry.getVersion() + registrations,\n subscribe(listener: () => void): () => void {\n const off = listeners.subscribe(listener);\n const offMode = registry.subscribe(listener);\n return () => {\n off();\n offMode();\n };\n },\n };\n}\n","import type { ModeRegistry } from './registry';\nimport type { CapabilityTag } from './capabilities';\nimport { eligibleForMode } from './modeDefinition';\n\n/** The part of a tool this package needs in order to judge eligibility: its\n * id and the capabilities it claims. Structural, so a real `ToolDef`\n * satisfies it without this package depending on the kit. */\nexport interface ToolLike {\n id: string;\n capabilities?: readonly CapabilityTag[];\n}\n\n/** True iff `tool` is usable in the registry's currently active mode. */\nexport function eligibleTool(reg: ModeRegistry, tool: ToolLike): boolean {\n return eligibleForMode(reg.current(), tool.capabilities ?? []);\n}\n\n/** True iff a contribution is usable in the registry's active mode. */\nexport function eligibleContribution(\n reg: ModeRegistry,\n entry: { id: string; eligibility?: { capabilities?: readonly CapabilityTag[] } },\n): boolean {\n return eligibleForMode(reg.current(), entry.eligibility?.capabilities ?? []);\n}\n","import { createEmitter } from '@weasel-js/registry';\nimport type { ModeRegistry } from './registry';\n\n/** Options for `createScopingDim`. */\nexport interface CreateScopingDimOptions {\n registry: ModeRegistry;\n /** Returns the set of node ids that are *in* scope for the current mode.\n * The app computes this — typically: the edited path for path-edit,\n * empty for non-scoping modes. */\n getTargetIds: () => ReadonlySet<string>;\n /** Alpha for out-of-scope nodes. Default {@link OUT_OF_SCOPE_ALPHA}. */\n dimAlpha?: number;\n}\n\n/** The alpha a node outside a scope is drawn at, unless the scope says otherwise. */\nexport const OUT_OF_SCOPE_ALPHA = 0.3;\n\n/** How a canvas treats each node under a scope: lit or dimmed, reachable or not. Consult it\n * from the renderer and the hit-tester; `subscribe` hears its answers change, so a canvas\n * can repaint on it (`<SceneCanvas redrawOn>`). */\nexport interface NodeScope {\n /** Multiplier in [0, 1] to apply to a node's render alpha. */\n alphaFor(id: string): number;\n /** Whether the node should respond to pointer hits. */\n isPointerInteractive(id: string): boolean;\n /** Monotonic; bumps whenever the answers may have changed. */\n getVersion(): number;\n subscribe(listener: () => void): () => void;\n}\n\n/** A {@link NodeScope} for a mode registry: it computes nothing itself, and its answers change\n * when the mode does, or when the app says the target set moved (`invalidate`). */\nexport interface ScopingDim extends NodeScope {\n /** Tell subscribers the target set changed without a mode switch. */\n invalidate(): void;\n}\n\n/** Build the scoping lookup for a mode registry. In a mode with\n * `scoping: false` every node is full-alpha and interactive, so this is safe\n * to consult unconditionally. */\nexport function createScopingDim(opts: CreateScopingDimOptions): ScopingDim {\n const { registry } = opts;\n const dim = opts.dimAlpha ?? OUT_OF_SCOPE_ALPHA;\n const listeners = createEmitter();\n let invalidations = 0;\n return {\n alphaFor(id) {\n const mode = registry.current();\n if (!mode.scoping) return 1;\n return opts.getTargetIds().has(id) ? 1 : dim;\n },\n isPointerInteractive(id) {\n const mode = registry.current();\n if (!mode.scoping) return true;\n return opts.getTargetIds().has(id);\n },\n invalidate() {\n invalidations++;\n listeners.emit();\n },\n getVersion: () => registry.getVersion() + invalidations,\n subscribe(listener) {\n const off = listeners.subscribe(listener);\n const offMode = registry.subscribe(listener);\n return () => {\n off();\n offMode();\n };\n },\n };\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { a as CROP, D as DEFAULT_MODES, F as FREE_TRANSFORM,
|
|
1
|
+
export { a as CROP, D as DEFAULT_MODES, F as FREE_TRANSFORM, N as NORMAL, P as PATH_EDIT, T as TEXT_EDIT, c as byId } from '../default-D1xUSA5-.js';
|
package/dist/presets/default.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { CROP, DEFAULT_MODES, FREE_TRANSFORM,
|
|
1
|
+
export { CROP, DEFAULT_MODES, FREE_TRANSFORM, NORMAL, PATH_EDIT, TEXT_EDIT, byId } from '../chunk-LFN3AJIW.js';
|
|
2
2
|
//# sourceMappingURL=default.js.map
|
|
3
3
|
//# sourceMappingURL=default.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@weasel-js/modes",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.13.0-rc.0",
|
|
4
4
|
"description": "App-level modality primitives: capability tags, mode definitions, mode registry, and decoration layer.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"node": ">=22"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@weasel-js/registry": "1.
|
|
36
|
+
"@weasel-js/registry": "1.13.0-rc.0"
|
|
37
37
|
},
|
|
38
38
|
"files": [
|
|
39
39
|
"dist",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/presets/default.ts"],"names":["m"],"mappings":"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","file":"chunk-TLMWTM4B.js","sourcesContent":["import type { ModeDefinition } from '../modeDefinition';\n\n/** The default mode: everything except anchor and text editing, no scoping,\n * no workspace tint. */\nexport const NORMAL: ModeDefinition = {\n id: 'normal',\n label: 'Normal',\n description: 'Select, draw and arrange anything on the page.',\n kind: 'soft',\n allows: [\n 'creates-selection',\n 'transforms-selection',\n 'creates-paths',\n 'creates-shapes',\n 'creates-text',\n 'samples-color',\n 'applies-fill',\n 'edits-page',\n ],\n scoping: false,\n};\n\n/** Editing the anchors of a path. Scoped to the target, entered by\n * double-clicking a `path` or with Enter, left with Escape. */\nexport const PATH_EDIT: ModeDefinition = {\n id: 'path-edit',\n label: 'Path Edit',\n description: \"Move a path's anchors and handles.\",\n kind: 'soft',\n allows: ['edits-anchors'],\n scoping: true,\n workspace: { tint: '#3b82f6', gradient: 'bottom-up', intensity: 0.12 },\n entry: { trigger: 'double-click-target', targets: ['path'], shortcut: 'Enter' },\n exit: { shortcut: 'Escape' },\n discard: { shortcut: 'Meta+Escape' },\n};\n\n/** Working inside one subtree with everything outside it dimmed and inert,\n * entered by double-clicking a `group`. Allows the same authoring tools as `NORMAL`, minus page edits. */\nexport const ISOLATION: ModeDefinition = {\n id: 'isolation',\n label: 'Isolation',\n description: 'Work inside one group with everything outside it dimmed and locked.',\n kind: 'soft',\n allows: [\n 'creates-selection',\n 'transforms-selection',\n 'creates-paths',\n 'creates-shapes',\n 'creates-text',\n 'samples-color',\n 'applies-fill',\n ],\n scoping: true,\n workspace: { tint: '#8b5cf6', gradient: 'bottom-up', intensity: 0.12 },\n entry: { trigger: 'double-click-target', targets: ['group'] },\n exit: { shortcut: 'Escape' },\n discard: { shortcut: 'Meta+Escape' },\n};\n\n/** A transaction that transforms the selection: the whole session is one undo\n * step, committed with Enter or discarded with Escape. */\nexport const FREE_TRANSFORM: ModeDefinition = {\n id: 'free-transform',\n label: 'Free Transform',\n description: 'Move, scale and rotate the selection as one undoable step.',\n kind: 'strict',\n allows: ['transforms-selection'],\n scoping: false,\n workspace: { tint: '#f59e0b', gradient: 'bottom-up', intensity: 0.12 },\n entry: { shortcut: 'Meta+T' },\n commit: { shortcut: 'Enter' },\n cancel: { shortcut: 'Escape' },\n};\n\n/** Editing the text of one node. Entered by double-clicking it, left with\n * Escape. It names no targets: the text edit opening is what enters it. */\nexport const TEXT_EDIT: ModeDefinition = {\n id: 'text-edit',\n label: 'Text Edit',\n description: \"Edit a text node's content.\",\n kind: 'soft',\n allows: ['edits-text'],\n scoping: false,\n workspace: { tint: '#10b981', gradient: 'bottom-up', intensity: 0.12 },\n entry: { trigger: 'double-click-target' },\n exit: { shortcut: 'Escape' },\n discard: { shortcut: 'Meta+Escape' },\n};\n\n/** A transaction that changes the page extents, committed with Enter or\n * discarded with Escape. */\nexport const CROP: ModeDefinition = {\n id: 'crop',\n label: 'Crop',\n description: 'Change the page extents as one undoable step.',\n kind: 'strict',\n allows: ['edits-page'],\n scoping: false,\n workspace: { tint: '#ef4444', gradient: 'bottom-up', intensity: 0.12 },\n entry: { shortcut: 'C' },\n commit: { shortcut: 'Enter' },\n cancel: { shortcut: 'Escape' },\n};\n\n/** The six modes this package ships, ready to hand to `createModeRegistry`. */\nexport const DEFAULT_MODES: readonly ModeDefinition[] = [\n NORMAL,\n PATH_EDIT,\n ISOLATION,\n FREE_TRANSFORM,\n TEXT_EDIT,\n CROP,\n];\n\n/** Look up one of the `DEFAULT_MODES` by id. Throws on an unknown id. For an\n * app's own mode set, use the registry's `byId` instead. */\nexport function byId(id: string): ModeDefinition {\n const m = DEFAULT_MODES.find((m) => m.id === id);\n if (!m) throw new Error(`Unknown mode id: ${id}`);\n return m;\n}\n"]}
|