@weasel-js/routing 1.14.2 → 1.15.1

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/index.d.ts CHANGED
@@ -1,11 +1,12 @@
1
- export { t as ALWAYS, A as Action, c as ActionDeps, e as ActionDisabledReason, e as ActionDisabledReasonValue, v as ActionDispatch, w as ActionEnabledResult, x as ActionEntry, y as ActionItem, z as ActionParamSchema, E as ActionParams, F as ActionPresentation, G as ActionSettings, H as ActionSettingsState, I as ActionShortcut, J as ActionSource, P as ActionTuning, Q as ActionTunings, U as ActionUnavailable, f as ActionVariant, V as ActionsProp, d as ActionsRegistry, q as AffordanceHit, X as AnyTool, Y as AssemblyInputs, Z as BROWSER_RESERVED_CHORDS, _ as BindingOpts, $ as BindingOverrides, a0 as BindingScope, a1 as BindingSource, a2 as BodyPredicate, B as BoundGesture, a3 as Bounds, a4 as BuildRuleCtxArgs, a5 as COARSE_TARGET_SCALE, a6 as CaptureGestureOptions, a7 as CaptureKeyOptions, a8 as CaptureKind, a9 as CapturedSpec, aa as Carried, ab as Carry, ac as CarryCallbacks, ad as CarryPayload, ae as CarryPointer, af as CarryStage, ag as Condition, ah as Conflict, C as Contribution, ai as ContributionChrome, aj as ContributionDeps, ak as ContributionRouting, al as DEFAULT_ALLOWED_CAPABILITIES, am as DEFAULT_DEVICE_PROFILE, an as DebugSink, ao as DepListing, a as DepName, D as DepRegistry, s as DepSchema, b as DepSource, ap as DetectedDeviceFacts, aq as DeviceProfile, ar as DispatchRecord, as as DispatchRecordInput, r as DispatchTrace, p as Dispatcher, at as DispatcherContext, au as DragSample, av as DroppedCandidate, aw as Eligibility, ax as EligibilityState, ay as GestureBinding, az as GestureKitSettings, aA as HandleKind, aB as HitShape, aC as HotkeyTrigger, aD as INGEST_STRING_MIMES, aE as ImmediateInvoker, aF as ImmediateParams, aG as InvocationCtx, aH as Invoker, aI as KEYMAP_HOLD, i as KernelOverlay, aJ as KeyBinding, aK as KeyReach, aL as KeymapDef, K as KeymapDescription, aM as KeymapRow, aN as KeymapStack, aO as KeymapUnbound, aP as KeymapVerdict, L as LongPressOptions, aQ as LongPressState, aR as LongPressStore, aS as MatchOutcome, aT as MatchResult, aU as MenuAccess, aV as MenuCustomAt, g as MenuDef, aW as MenuHit, M as MenuHost, aX as MenuOpenRequest, aY as MenuSources, aZ as MenuWhen, a_ as ModeShortcutHandlers, a$ as ModeSwitchLogEntry, b0 as ModifierRole, b1 as ModifierRoles, b2 as ModifierState, b3 as NEVER, N as NodeId, b4 as OngoingHandle, b5 as OngoingInvoker, b6 as OngoingOverlay, b7 as OpenKeymap, b8 as OpenMenu, O as OverlayPosition, b9 as OverlayRole, ba as OverlaySchema, bb as OwnedMenuDef, bc as PREDICATE_TARGET, bd as PendingIngestItem, be as PendingLongPress, bf as PlacedBy, bg as Point2, bh as PointerSession, bi as PointerSessionCallbacks, bj as PointerSessionCancelReason, bk as PointerSessionOptions, bl as RankedCandidate, bm as RecordCandidate, bn as RegistryEntry, bo as ReservedChord, bp as ResizeAnchor, bq as ResolveAllOptions, br as ResolveOnlyResult, bs as ResolvedBindingOverrides, bt as ResolvedCandidate, bu as RoleKeys, bv as RoleRebinds, bw as Rule, R as RuleCtx, bx as ScopedBinding, by as ScratchKey, bz as ScratchStore, bA as SelectionApi, bB as Selector, bC as SpecificityPart, bD as TOOL_OFFHAND_ID, j as Tool, bE as ToolDef, bF as ToolEntry, bG as ToolKeybinding, bH as ToolModifiers, bI as ToolOffhandBindingSpec, bJ as ToolPresentation, bK as ToolScopes, bL as ToolSet, bM as ToolSlot, bN as TraceLogEntry, bO as TraceRing, bP as TunedBinding, bQ as UiOngoingControl, bR as ViewportGestureKind, bS as WalkStep, W as WorldPoint, bT as actionBindings, bU as actionCursor, bV as actionItemTitle, bW as actionItems, bX as actionSettingsParams, bY as actionShortcuts, bZ as actionsTagged, b_ as admitIngestMime, b$ as assembleEntries, c0 as bindingId, c1 as browserReservedChord, c2 as buildDepsFromRequires, c3 as buildRouteRegistry, c4 as buildRuleCtx, c5 as buildToolOffhandBindings, c6 as captureGesture, c7 as captureKey, c8 as clientToCanvas, c9 as clientToCanvasRect, ca as createDepRegistry, cb as createDispatchTrace, cc as createDispatcher, cd as createKeymapStack, ce as createLongPressStore, cf as createMenuHost, cg as createTraceRing, ch as defineTool, ci as deleteScratch, cj as describeKeymap, ck as describeRule, cl as dlog, cm as dwarn, cn as evaluate, co as evaluateActive, cp as evaluateEnabled, cq as findConflicts, cr as getScratch, cs as heldKeySpec, ct as historyKey, cu as holdPreview, cv as holdPreviewId, cw as isAnchor, cx as isAnchorOrControl, cy as isBalanceGrip, cz as isBody, cA as isControlHandle, cB as isCornerWidget, cC as isDebugEnabled, cD as isEmpty, cE as isPathEditPart, cF as isResizeHandle, cG as isRotateHandle, cH as isSegment, cI as isSelectedBody, cJ as isTool, cK as isToolSet, cL as isUnselectedBody, cM as itemTypesFromDataTransfer, cN as itemsFromClipboardData, cO as itemsFromDataTransfer, cP as itemsFromFiles, cQ as keySpecShortcut, cR as keymapContribution, cS as keymapLeaderBindingId, cT as keymapLeaderId, cU as keymapShortcuts, cV as keysHeld, cW as liveScope, cX as makeToolOffhandAction, cY as matchActionItem, cZ as matchBest, c_ as matchSorted, c$ as matchSortedWithBarred, d0 as matchesKeyBinding, d1 as mergeContributions, d2 as mergeMenuDefs, d3 as modeShortcutSpec, d4 as modeShortcuts, d5 as modifierStateOf, d6 as multiTouchGestureId, d7 as offhandKeyFor, d8 as openPointerSession, d9 as overlaysOf, da as overriddenBindings, db as pendingKindOf, dc as pickMenu, dd as pointerGestureId, de as readActionSettings, df as reportRouteConflicts, dg as resolveBindingOverrides, dh as resolveDeviceProfile, di as resolveMenu, dj as resolveParams, dk as resolveSchemaMenu, dl as roleReader, dm as routesForSpec, dn as ruleCanHoldIn, dp as rulesExclusive, dq as scopeBindings, dr as scratchKey, ds as setScratch, dt as startCarry, du as taggedActionItems, dv as targetConsultsAffordance, dw as toolIdsOf, dx as toolSet, dy as toolSetHas, dz as tuneAction, dA as validateActionDefaultBinding, dB as validateActionId, dC as withoutTools } from './index-DJ7SxEKS.js';
1
+ export { x as ALWAYS, A as Action, c as ActionDeps, e as ActionDisabledReason, e as ActionDisabledReasonValue, y as ActionDispatch, z as ActionEnabledResult, E as ActionEntry, F as ActionItem, G as ActionParamSchema, H as ActionParams, I as ActionPresentation, J as ActionSettings, P as ActionSettingsState, Q as ActionShortcut, U as ActionSource, V as ActionTuning, X as ActionTunings, Y as ActionUnavailable, f as ActionVariant, Z as ActionsProp, d as ActionsRegistry, s as AffordanceHit, _ as AnyTool, $ as AssemblyInputs, a0 as BROWSER_RESERVED_CHORDS, a1 as BindingOpts, a2 as BindingOverrides, a3 as BindingScope, a4 as BindingSource, a5 as BodyPredicate, B as BoundGesture, a6 as Bounds, a7 as BuildRuleCtxArgs, a8 as COARSE_TARGET_SCALE, a9 as CaptureGestureOptions, aa as CaptureKeyOptions, ab as CaptureKind, ac as CapturedSpec, ad as Carried, ae as Carry, af as CarryCallbacks, ag as CarryPayload, ah as CarryPointer, ai as CarryStage, aj as Condition, ak as Conflict, C as Contribution, al as ContributionChrome, am as ContributionDeps, an as ContributionRouting, ao as DEFAULT_ALLOWED_CAPABILITIES, ap as DEFAULT_DEVICE_PROFILE, aq as DebugSink, ar as DepListing, a as DepName, D as DepRegistry, w as DepSchema, b as DepSource, as as DetectedDeviceFacts, at as DeviceProfile, au as DispatchRecord, av as DispatchRecordInput, t as DispatchTrace, r as Dispatcher, aw as DispatcherContext, ax as DragSample, ay as DroppedCandidate, az as Eligibility, aA as EligibilityState, aB as GestureBinding, aC as GestureKitSettings, aD as HandleKind, aE as HitShape, aF as HotkeyTrigger, aG as INGEST_STRING_MIMES, aH as ImmediateInvoker, aI as ImmediateParams, aJ as InvocationCtx, aK as Invoker, aL as KEYMAP_HOLD, k as KernelOverlay, aM as KeyBinding, aN as KeyReach, aO as KeymapDef, K as KeymapDescription, aP as KeymapRow, aQ as KeymapStack, aR as KeymapUnbound, aS as KeymapVerdict, h as LastOperation, g as LastOperationStore, v as LongPressOptions, aT as LongPressState, aU as LongPressStore, aV as MatchOutcome, aW as MatchResult, aX as MenuAccess, aY as MenuCustomAt, i as MenuDef, aZ as MenuHit, M as MenuHost, a_ as MenuOpenRequest, a$ as MenuSources, b0 as MenuWhen, b1 as ModeShortcutHandlers, b2 as ModeSwitchLogEntry, b3 as ModifierRole, b4 as ModifierRoles, b5 as ModifierState, b6 as NEVER, N as NodeId, b7 as OngoingHandle, b8 as OngoingInvoker, b9 as OngoingOverlay, ba as OpenKeymap, bb as OpenMenu, O as OverlayPosition, bc as OverlayRole, bd as OverlaySchema, be as OwnedMenuDef, bf as PREDICATE_TARGET, bg as PendingIngestItem, bh as PendingLongPress, bi as PlacedBy, bj as Point2, bk as PointerSession, bl as PointerSessionCallbacks, bm as PointerSessionCancelReason, bn as PointerSessionOptions, bo as RankedCandidate, bp as RecordCandidate, bq as RegistryEntry, br as ReservedChord, bs as ResizeAnchor, bt as ResolveAllOptions, bu as ResolveOnlyResult, bv as ResolvedBindingOverrides, bw as ResolvedCandidate, bx as RoleKeys, by as RoleRebinds, bz as Rule, R as RuleCtx, bA as ScopedBinding, bB as ScratchKey, bC as ScratchStore, bD as SelectionApi, bE as SelectionSnapshotDep, bF as Selector, bG as SpecificityPart, bH as TOOL_OFFHAND_ID, l as Tool, bI as ToolDef, bJ as ToolEntry, bK as ToolKeybinding, bL as ToolModifiers, bM as ToolOffhandBindingSpec, bN as ToolOptionStep, bO as ToolOptionValues, bP as ToolOptions, bQ as ToolPresentation, bR as ToolScopes, bS as ToolSet, bT as ToolSlot, bU as TraceLogEntry, bV as TraceRing, bW as TunedBinding, bX as UiOngoingControl, bY as ViewportGestureKind, bZ as WalkStep, W as WorldPoint, b_ as actionBindings, b$ as actionCursor, c0 as actionItemTitle, c1 as actionItems, c2 as actionSettingsParams, c3 as actionShortcuts, c4 as actionsTagged, c5 as admitIngestMime, c6 as assembleEntries, c7 as bindingId, c8 as browserReservedChord, c9 as buildDepsFromRequires, ca as buildRouteRegistry, cb as buildRuleCtx, cc as buildToolOffhandBindings, cd as captureGesture, ce as captureKey, cf as clientToCanvas, cg as clientToCanvasRect, ch as createDepRegistry, ci as createDispatchTrace, cj as createDispatcher, ck as createKeymapStack, cl as createLongPressStore, cm as createMenuHost, cn as createToolOptionValues, co as createTraceRing, cp as defineTool, cq as deleteScratch, cr as describeKeymap, cs as describeRule, ct as dlog, cu as dwarn, cv as evaluate, cw as evaluateActive, cx as evaluateEnabled, cy as findConflicts, cz as getScratch, cA as heldKeySpec, cB as historyKey, cC as holdPreview, cD as holdPreviewId, cE as isAnchor, cF as isAnchorOrControl, cG as isBalanceGrip, cH as isBody, cI as isControlHandle, cJ as isCornerWidget, cK as isDebugEnabled, cL as isEmpty, cM as isPathEditPart, cN as isResizeHandle, cO as isRotateHandle, cP as isSegment, cQ as isSelectedBody, cR as isTool, cS as isToolSet, cT as isUnselectedBody, cU as itemTypesFromDataTransfer, cV as itemsFromClipboardData, cW as itemsFromDataTransfer, cX as itemsFromFiles, cY as keySpecShortcut, cZ as keymapContribution, c_ as keymapLeaderBindingId, c$ as keymapLeaderId, d0 as keymapShortcuts, d1 as keysHeld, d2 as liveScope, d3 as makeToolOffhandAction, d4 as matchActionItem, d5 as matchBest, d6 as matchSorted, d7 as matchSortedWithBarred, d8 as matchesKeyBinding, d9 as mergeContributions, da as mergeMenuDefs, db as modeShortcutSpec, dc as modeShortcuts, dd as modifierStateOf, de as multiTouchGestureId, df as offhandKeyFor, dg as openPointerSession, dh as overlaysOf, di as overriddenBindings, dj as pendingKindOf, dk as pickMenu, dl as pointerGestureId, dm as readActionSettings, dn as reportRouteConflicts, dp as resolveBindingOverrides, dq as resolveDeviceProfile, dr as resolveMenu, ds as resolveParams, dt as resolveSchemaMenu, du as returnToModeDefault, dv as roleReader, dw as routesForSpec, dx as ruleCanHoldIn, dy as rulesExclusive, dz as scopeBindings, dA as scratchKey, dB as setScratch, dC as startCarry, dD as steppedOption, dE as taggedActionItems, dF as targetConsultsAffordance, dG as toolIdsOf, dH as toolOptionParams, dI as toolOptionSteps, dJ as toolSet, dK as toolSetHas, dL as tuneAction, dM as validateActionDefaultBinding, dN as validateActionId, dO as withoutTools } from './index-D-XFwx8D.js';
2
2
  export { CONTROL_SELECTOR, ChannelRef, DRAG_THRESHOLD_PX, DescribeRouteOptions, GESTURE_DESCRIPTORS, GestureArgSpec, GestureDescriptor, GestureName, IngestItem, InputEvent, LONG_PRESS_MS, ModRequirement, ModifierKey, ParsedModifiers, ParsedRoute, PhaseAtom, PhaseContext, RESERVED_ID_NAMES, RESERVED_ID_PREFIXES, ROUTE_FIELD_DEFINITIONS, ROUTE_TERMS, RouteDescriptionPart, RouteFieldName, RouteTermLabel, activatesFocusedControl, canonicalModifiers, collapseShiftPairs, describeRoute, describeRouteParts, focusedControlOwnsKey, formatPhaseAtom, formatRoute, getGestureDescriptor, isEditableTarget, isInControlWithin, isKnownGestureName, matchKey, matchModifiers, matchPhase, matchSpec, matchTarget, parseRoute, pastDragThreshold, routeGestureForSpecKind, specKindForRouteGesture, specificity } from '@weasel-js/gestures';
3
3
  export { SelectionExtendKey, SelectionMode } from '@weasel-js/select';
4
4
  export { View } from '@weasel-js/geom';
5
- import '@weasel-js/cursor';
6
- import '@weasel-js/menu';
5
+ import '@weasel-js/history';
7
6
  import '@weasel-js/prefs';
8
7
  import '@weasel-js/modes';
9
8
  import '@weasel-js/icons';
9
+ import '@weasel-js/cursor';
10
+ import '@weasel-js/menu';
10
11
  import 'react';
11
12
  import '@weasel-js/registry';
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
- export { ALWAYS, COARSE_TARGET_SCALE, DEFAULT_ALLOWED_CAPABILITIES, DEFAULT_DEVICE_PROFILE, GESTURE_DESCRIPTORS, INGEST_STRING_MIMES, KEYMAP_HOLD, LONG_PRESS_MS, NEVER, PREDICATE_TARGET, TOOL_OFFHAND_ID, activatesFocusedControl, admitIngestMime, assembleEntries, buildRouteRegistry, buildRuleCtx, buildToolOffhandBindings, clientToCanvas, clientToCanvasRect, createDispatchTrace, createDispatcher, createKeymapStack, createLongPressStore, createTraceRing, describeKeymap, describeRule, dlog, dwarn, evaluate, findConflicts, focusedControlOwnsKey, getGestureDescriptor, heldKeySpec, historyKey, isDebugEnabled, isEditableTarget, isKnownGestureName, isTool, itemTypesFromDataTransfer, itemsFromClipboardData, itemsFromDataTransfer, itemsFromFiles, keymapContribution, keymapLeaderBindingId, keymapLeaderId, keymapShortcuts, liveScope, makeToolOffhandAction, matchBest, matchKey, matchModifiers, matchPhase, matchSorted, matchSortedWithBarred, matchSpec, matchTarget, matchesKeyBinding, modifierStateOf, multiTouchGestureId, offhandKeyFor, openPointerSession, pendingKindOf, pointerGestureId, reportRouteConflicts, resolveDeviceProfile, routeGestureForSpecKind, routesForSpec, ruleCanHoldIn, rulesExclusive, scopeBindings, specKindForRouteGesture, specificity, startCarry, targetConsultsAffordance } from './chunk-HR5F4LBX.js';
2
- import { actionItems, actionItemTitle, resolveParams, ActionDisabledReason } from './chunk-EUCNVGJV.js';
3
- export { ActionDisabledReason, RESERVED_ID_NAMES, RESERVED_ID_PREFIXES, ROUTE_FIELD_DEFINITIONS, ROUTE_TERMS, actionBindings, actionCursor, actionItemTitle, actionItems, actionSettingsParams, actionShortcuts, bindingId, buildDepsFromRequires, canonicalModifiers, collapseShiftPairs, createDepRegistry, createMenuHost, describeRoute, describeRouteParts, evaluateActive, evaluateEnabled, formatPhaseAtom, formatRoute, keySpecShortcut, keysHeld, mergeMenuDefs, overriddenBindings, parseRoute, pickMenu, readActionSettings, resolveBindingOverrides, resolveMenu, resolveParams, resolveSchemaMenu, roleReader, tuneAction, validateActionDefaultBinding, validateActionId } from './chunk-EUCNVGJV.js';
1
+ export { ALWAYS, COARSE_TARGET_SCALE, DEFAULT_ALLOWED_CAPABILITIES, DEFAULT_DEVICE_PROFILE, GESTURE_DESCRIPTORS, INGEST_STRING_MIMES, KEYMAP_HOLD, LONG_PRESS_MS, NEVER, PREDICATE_TARGET, TOOL_OFFHAND_ID, activatesFocusedControl, admitIngestMime, assembleEntries, buildRouteRegistry, buildRuleCtx, buildToolOffhandBindings, clientToCanvas, clientToCanvasRect, createDispatchTrace, createDispatcher, createKeymapStack, createLongPressStore, createTraceRing, describeKeymap, describeRule, dlog, dwarn, evaluate, findConflicts, focusedControlOwnsKey, getGestureDescriptor, heldKeySpec, historyKey, isDebugEnabled, isEditableTarget, isKnownGestureName, isTool, itemTypesFromDataTransfer, itemsFromClipboardData, itemsFromDataTransfer, itemsFromFiles, keymapContribution, keymapLeaderBindingId, keymapLeaderId, keymapShortcuts, liveScope, makeToolOffhandAction, matchBest, matchKey, matchModifiers, matchPhase, matchSorted, matchSortedWithBarred, matchSpec, matchTarget, matchesKeyBinding, modifierStateOf, multiTouchGestureId, offhandKeyFor, openPointerSession, pendingKindOf, pointerGestureId, reportRouteConflicts, resolveDeviceProfile, routeGestureForSpecKind, routesForSpec, ruleCanHoldIn, rulesExclusive, scopeBindings, specKindForRouteGesture, specificity, startCarry, targetConsultsAffordance } from './chunk-ZUAFANMN.js';
2
+ import { actionItems, actionItemTitle, resolveParams, ActionDisabledReason } from './chunk-Z2BZBJ7W.js';
3
+ export { ActionDisabledReason, RESERVED_ID_NAMES, RESERVED_ID_PREFIXES, ROUTE_FIELD_DEFINITIONS, ROUTE_TERMS, actionBindings, actionCursor, actionItemTitle, actionItems, actionSettingsParams, actionShortcuts, bindingId, buildDepsFromRequires, canonicalModifiers, collapseShiftPairs, createDepRegistry, createMenuHost, describeRoute, describeRouteParts, evaluateActive, evaluateEnabled, formatPhaseAtom, formatRoute, keySpecShortcut, keysHeld, mergeMenuDefs, overriddenBindings, parseRoute, pickMenu, readActionSettings, resolveBindingOverrides, resolveMenu, resolveParams, resolveSchemaMenu, roleReader, tuneAction, validateActionDefaultBinding, validateActionId } from './chunk-Z2BZBJ7W.js';
4
4
  import { hasTag, matchQuery } from '@weasel-js/registry';
5
5
  import { bodyPredicate, hitPredicate, key, isApplePlatform, createPointerRecognizer, RESERVED_ID_PREFIXES, RESERVED_ID_NAMES, DOUBLE_CLICK_MAX_MS } from '@weasel-js/gestures';
6
6
  export { CONTROL_SELECTOR, DRAG_THRESHOLD_PX, isInControlWithin, pastDragThreshold } from '@weasel-js/gestures';
@@ -113,6 +113,17 @@ function mergeContributions(...bundles) {
113
113
  }
114
114
  return out;
115
115
  }
116
+
117
+ // src/tools/returnToModeDefault.ts
118
+ function returnToModeDefault(deps) {
119
+ const target = deps?.modeDefaultTool?.() ?? null;
120
+ const tools = deps?.activeTool;
121
+ if (target === null || !tools || tools.active === target) return false;
122
+ tools.setActive(target);
123
+ return true;
124
+ }
125
+
126
+ // src/contributions/modeShortcuts.ts
116
127
  var LEAVING = ["exit", "discard", "commit", "cancel"];
117
128
  var VERB = {
118
129
  entry: "Enter",
@@ -144,13 +155,16 @@ function modeShortcuts(registry, handlers) {
144
155
  const shortcut = mode[role]?.shortcut;
145
156
  const run = handlers[role];
146
157
  if (!shortcut || !run) continue;
158
+ const backsOut = role === "exit" || role === "cancel";
147
159
  actions.push(shortcutAction(
148
160
  mode,
149
161
  role,
150
162
  shortcut,
151
163
  { mode: mode.id },
152
164
  () => registry.current().id === mode.id,
153
- run,
165
+ backsOut ? (deps) => {
166
+ if (!returnToModeDefault(deps)) run();
167
+ } : run,
154
168
  true
155
169
  ));
156
170
  }
@@ -167,11 +181,12 @@ function shortcutAction(mode, role, shortcut, eligible, live, run, yields) {
167
181
  opts: { id: `mode.${mode.id}.${role}.key`, yields }
168
182
  }],
169
183
  eligible,
184
+ requires: ["activeTool", "modeDefaultTool"],
170
185
  // `eligible` is the gate the dispatcher and palettes read, but a canvas
171
186
  // with no `modes` evaluates none; without this the key is
172
187
  // swallowed in every mode.
173
188
  enabled: () => live() ? true : ActionDisabledReason.NotApplicable,
174
- invoker: { timing: "immediate", run: () => run() }
189
+ invoker: { timing: "immediate", run: (deps) => run(deps) }
175
190
  };
176
191
  }
177
192
 
@@ -360,6 +375,93 @@ function captureKey(target, opts = {}) {
360
375
  ...opts.apple !== void 0 ? { apple: opts.apple } : {}
361
376
  });
362
377
  }
378
+
379
+ // src/tools/toolOptions.ts
380
+ var NONE = Object.freeze({});
381
+ function createToolOptionValues() {
382
+ const values = /* @__PURE__ */ new Map();
383
+ const listeners = /* @__PURE__ */ new Set();
384
+ return {
385
+ get: (toolId) => values.get(toolId) ?? NONE,
386
+ set(toolId, option, value) {
387
+ values.set(toolId, { ...values.get(toolId), [option]: value });
388
+ for (const l of [...listeners]) l();
389
+ },
390
+ subscribe(listener) {
391
+ listeners.add(listener);
392
+ return () => {
393
+ listeners.delete(listener);
394
+ };
395
+ }
396
+ };
397
+ }
398
+ function leafOf(options, option) {
399
+ const leaf = options.prefs.children[option];
400
+ return leaf?.kind === "number" ? leaf : void 0;
401
+ }
402
+ function toolOptionParams(toolId, options, values) {
403
+ const held = values?.get(toolId) ?? {};
404
+ const out = {};
405
+ for (const key2 of Object.keys(options.prefs.children)) {
406
+ const leaf = leafOf(options, key2);
407
+ const v = held[key2] ?? leaf?.default;
408
+ if (typeof v === "number") out[key2] = v;
409
+ }
410
+ return out;
411
+ }
412
+ function steppedOption(leaf, value, step, dir) {
413
+ const moved = step.times !== void 0 ? value * step.times ** dir : value + dir * (step.plus ?? leaf.step ?? 1);
414
+ const snapped = leaf.step ? Math.round(moved / leaf.step) * leaf.step : moved;
415
+ const next = snapped === value && leaf.step ? value + dir * leaf.step : snapped;
416
+ const clamped = Math.min(leaf.max ?? Infinity, Math.max(leaf.min ?? -Infinity, next));
417
+ return Number(clamped.toFixed(6));
418
+ }
419
+ var STEP_KEYS = {
420
+ grow: { kind: "key", key: "]", code: "BracketRight" },
421
+ shrink: { kind: "key", key: "[", code: "BracketLeft" },
422
+ raise: { kind: "key", key: ["]", "}"], code: "BracketRight", mods: { shift: true } },
423
+ lower: { kind: "key", key: ["[", "{"], code: "BracketLeft", mods: { shift: true } }
424
+ };
425
+ var STEPS = [
426
+ { name: "grow", which: "size", dir: 1, label: (t) => `Grow ${t}` },
427
+ { name: "shrink", which: "size", dir: -1, label: (t) => `Shrink ${t}` },
428
+ { name: "raise", which: "strength", dir: 1, label: (t, o) => `Raise ${t} ${o}` },
429
+ { name: "lower", which: "strength", dir: -1, label: (t, o) => `Lower ${t} ${o}` }
430
+ ];
431
+ function stepAction(toolId, toolLabel, options, spec) {
432
+ const step = options[spec.which];
433
+ const leaf = step ? leafOf(options, step.option) : void 0;
434
+ if (!step || !leaf) return null;
435
+ return {
436
+ id: `${toolId}.${spec.name}`,
437
+ label: spec.label(toolLabel, leaf.name.toLowerCase()),
438
+ group: "tool",
439
+ requires: ["activeTool", "toolOptionValues"],
440
+ invoker: {
441
+ timing: "immediate",
442
+ run: (deps) => {
443
+ const values = deps.toolOptionValues;
444
+ if (!values) return;
445
+ const current = toolOptionParams(toolId, options, values)[step.option] ?? leaf.default ?? 0;
446
+ values.set(toolId, step.option, steppedOption(leaf, current, step, spec.dir));
447
+ }
448
+ },
449
+ enabled: (deps) => deps?.activeTool?.active === toolId && deps.toolOptionValues ? true : ActionDisabledReason.NotApplicable
450
+ };
451
+ }
452
+ function toolOptionSteps(toolId, toolLabel, options) {
453
+ const actions = [];
454
+ const bindings = [];
455
+ for (const spec of STEPS) {
456
+ const action = stepAction(toolId, toolLabel, options, spec);
457
+ if (!action) continue;
458
+ actions.push(action);
459
+ bindings.push({ spec: STEP_KEYS[spec.name], actionId: action.id, opts: { id: `${action.id}.key` } });
460
+ }
461
+ return { actions, bindings };
462
+ }
463
+
464
+ // src/tools/defineTool.ts
363
465
  function validateId(id, kind) {
364
466
  if (id.length === 0) {
365
467
  throw new Error(`weasel: ${kind} id may not be empty`);
@@ -381,6 +483,9 @@ function defineTool(def) {
381
483
  if (def.cursor == null) return "";
382
484
  return typeof def.cursor === "function" ? def.cursor() : def.cursor;
383
485
  };
486
+ const steps = def.options ? toolOptionSteps(def.id, def.presentation?.label ?? def.id, def.options) : { actions: [], bindings: [] };
487
+ const actions = steps.actions.length > 0 ? [...def.actions ?? [], ...steps.actions] : def.actions;
488
+ const bindings = steps.bindings.length > 0 ? [...def.bindings ?? [], ...steps.bindings] : def.bindings;
384
489
  return {
385
490
  id: def.id,
386
491
  eligibility: {
@@ -388,7 +493,9 @@ function defineTool(def) {
388
493
  capabilities: def.capabilities,
389
494
  ...def.hotkey ? { offhand: def.hotkey } : {}
390
495
  },
391
- actions: def.actions,
496
+ actions,
497
+ ...def.options ? { options: def.options } : {},
498
+ ...def.hides ? { hides: def.hides } : {},
392
499
  menus: def.menus,
393
500
  def,
394
501
  presentation: def.presentation,
@@ -396,7 +503,7 @@ function defineTool(def) {
396
503
  onActivate: def.onActivate,
397
504
  onDeactivate: def.onDeactivate,
398
505
  cursor: resolveCursor,
399
- bindings: def.bindings,
506
+ bindings,
400
507
  overlay: def.overlay,
401
508
  overlayPosition: def.overlayPosition
402
509
  };
@@ -473,6 +580,6 @@ function deleteScratch(store, key2) {
473
580
  return false;
474
581
  }
475
582
 
476
- export { BROWSER_RESERVED_CHORDS, actionsTagged, browserReservedChord, captureGesture, captureKey, defineTool, deleteScratch, getScratch, holdPreview, holdPreviewId, isAnchor, isAnchorOrControl, isBalanceGrip, isBody, isControlHandle, isCornerWidget, isEmpty, isPathEditPart, isResizeHandle, isRotateHandle, isSegment, isSelectedBody, isToolSet, isUnselectedBody, matchActionItem, mergeContributions, modeShortcutSpec, modeShortcuts, overlaysOf, scratchKey, setScratch, taggedActionItems, toolIdsOf, toolSet, toolSetHas, withoutTools };
583
+ export { BROWSER_RESERVED_CHORDS, actionsTagged, browserReservedChord, captureGesture, captureKey, createToolOptionValues, defineTool, deleteScratch, getScratch, holdPreview, holdPreviewId, isAnchor, isAnchorOrControl, isBalanceGrip, isBody, isControlHandle, isCornerWidget, isEmpty, isPathEditPart, isResizeHandle, isRotateHandle, isSegment, isSelectedBody, isToolSet, isUnselectedBody, matchActionItem, mergeContributions, modeShortcutSpec, modeShortcuts, overlaysOf, returnToModeDefault, scratchKey, setScratch, steppedOption, taggedActionItems, toolIdsOf, toolOptionParams, toolOptionSteps, toolSet, toolSetHas, withoutTools };
477
584
  //# sourceMappingURL=index.js.map
478
585
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/interactions/actions/actionTags.ts","../src/interactions/actions/holdPreview.ts","../src/interactions/actions/overlay.ts","../src/interactions/dispatcher/predicates.ts","../src/contributions/merge.ts","../src/contributions/modeShortcuts.ts","../src/keymaps/captureSpec.ts","../src/keymaps/capturePointer.ts","../src/keymaps/captureGesture.ts","../src/keymaps/captureKey.ts","../src/tools/defineTool.ts","../src/tools/toolSet.ts","../src/interactions/browserReservedKeys.ts","../src/interactions/scratchKey.ts"],"names":["RESERVED_ID_PREFIXES","RESERVED_ID_NAMES","key"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Finding actions by tag: gathering the ones that carry it, and a person's\n * search matching it as it matches a label.\n */\nimport { hasTag, matchQuery, type QueryMatch } from '@weasel-js/registry';\nimport type { Action } from './action';\nimport { actionItems, actionItemTitle, type ActionItem } from './actionItems';\n\n/** The actions carrying `tag`, themselves or on any variant, in\n * the order given. Drags included, which have no entries to show. */\nexport function actionsTagged(actions: readonly Action[], tag: string): Action[] {\n return actions.filter((a) => hasTag(a.tags, tag) || (a.variants?.some((v) => hasTag(v.tags, tag)) ?? false));\n}\n\n/** The entries carrying `tag`: what a bar or a menu built from\n * a tag shows. A variant that does not carry it is left out. */\nexport function taggedActionItems(actions: readonly Action[], tag: string): ActionItem[] {\n return actionsTagged(actions, tag).flatMap(actionItems).filter((i) => hasTag(i.tags, tag));\n}\n\n/** Whether `item` answers a search for `query`, by its palette title or\n * by a tag, and which. */\nexport function matchActionItem(item: ActionItem, query: string): QueryMatch | null {\n return matchQuery(query, { text: [actionItemTitle(item)], tags: item.tags });\n}\n","/**\n * An action as a hold: bound to a held key, the press shows what it would do\n * through its `preview`, the release runs it, and a cancel — Escape, through\n * the kit's cancel-gesture action — takes the preview down and runs nothing.\n */\nimport type { Action } from './action';\nimport { resolveParams, type OngoingHandle } from './invoker';\n\n/** The id {@link holdPreview} gives the hold of action `id`. */\nexport const holdPreviewId = (id: string): string => `${id}.hold`;\n\n/**\n * `action` as a hold, under {@link holdPreviewId}. Bind it to a `held(…)` key,\n * in a keymap or anywhere else; the binding's params reach both the preview\n * and the run. It is enabled, eligible and requires what `action` does, so it\n * is skipped wherever `action` would be. An action with no `preview` shows\n * nothing and still runs on release; one whose invoker is not immediate is\n * not run.\n */\nexport function holdPreview(action: Action): Action {\n const { invoker } = action;\n return {\n id: holdPreviewId(action.id),\n label: action.label,\n ...(action.requires ? { requires: action.requires } : {}),\n ...(action.enabled ? { enabled: action.enabled } : {}),\n ...(action.eligible ? { eligible: action.eligible } : {}),\n invoker: {\n timing: 'ongoing',\n start: (ctx, opts): OngoingHandle => {\n const params = resolveParams(opts?.params);\n const hide = action.preview?.(ctx.deps, params);\n return {\n // An end's ctx carries no deps, so the run takes the press's.\n onEnd: (_end, reason) => {\n hide?.();\n if (reason === 'commit' && invoker?.timing === 'immediate') invoker.run(ctx.deps, params);\n },\n };\n },\n },\n };\n}\n","/** The chrome an in-flight gesture paints beside the scene. */\nimport type { OngoingHandle } from './invoker';\n\n/**\n * What a `polyline` overlay is, in a word — the narrowest thing an action can\n * say about how its run should look without naming a paint.\n *\n * The named roles are the kit's; a painter maps each to a style and falls back\n * to plain chrome for one it does not know, so a package outside core can coin\n * its own and still be drawn.\n */\nexport type OverlayRole =\n /** Generic in-flight chrome — the marquee/lasso paint. */\n | 'chrome'\n /** A cut the gesture would make. */\n | 'cut'\n /** An edge the gesture would author between two points. */\n | 'connector'\n /** The stretch of a path a soft-selection drag reaches. */\n | 'falloff'\n /** What a lock holds a dragged point to — a line, a circle. */\n | 'lock'\n /** What a dragged item would be dropped on: the box it would go into. */\n | 'target'\n /** Where a dragged item would land: a reorder's insertion bar. */\n | 'insert'\n /** Where a dragged item is over and cannot land. */\n | 'refused'\n | (string & {});\n\n/**\n * What an in-flight gesture proposes to paint *beside* the scene, returned by\n * `OngoingHandle.overlay()` — a marquee rect, a lasso trail, the outline of a\n * shape being dragged out, the line a slice would cut along.\n *\n * Every variant is world geometry and nothing else — no `DrawCommand`, no\n * color, no coordinate space to choose — so a surface rendering the same\n * gesture some other way can still read it. The painter owns every style\n * decision.\n */\nexport type OngoingOverlay =\n | {\n kind: 'marquee';\n start: { x: number; y: number };\n current: { x: number; y: number };\n shiftHeld: boolean;\n }\n | {\n kind: 'lasso';\n vertices: ReadonlyArray<{ x: number; y: number }>;\n current: { x: number; y: number };\n shiftHeld: boolean;\n }\n | {\n /**\n * An open run of world points the gesture is proposing — a cut line, a\n * routed connector. `role` is the whole of what an action says about\n * appearance.\n */\n kind: 'polyline';\n /** At least two points. Anything shorter is dropped in resolution. */\n points: ReadonlyArray<{ x: number; y: number }>;\n /** What the run means. Omitted reads as {@link OverlayRole} `'chrome'`. */\n role?: OverlayRole;\n }\n | {\n /**\n * A round brush dragged through world points: the area it has swept so\n * far, and its footprint at the last point. The radius is in screen\n * pixels, so the footprint keeps its size at every zoom.\n */\n kind: 'brush';\n /** The brush's path so far, at least one point; the last is where it is now. */\n points: ReadonlyArray<{ x: number; y: number }>;\n radiusPx: number;\n }\n | {\n /**\n * Live insert-drag preview. Pre-commit there is no scene node to ghost\n * via `previewIds()`/`previewPose()`, so insert paints its preview\n * through the overlay instead.\n *\n * `bounds` is the AABB of the current drag (start/current normalized).\n * `extras` is the per-kind extras the action already collected; the\n * overlay renderer narrows on `shape` and casts the field shape it\n * expects.\n */\n kind: 'insertPreview';\n /** Which preview the dispatcher's overlay draws. The kit's own shape\n * kinds are the ones it knows how to render; a consumer-defined kind\n * is legal and simply gets no live preview. */\n shape: string;\n bounds: { x: number; y: number; width: number; height: number };\n extras: unknown;\n /** World-space point to paint a small \"anchor\" dot at, marking the\n * click point — for radial shapes (polygon/star), where no vertex\n * sits on it, and for any shape in center mode. */\n anchorPoint?: { x: number; y: number };\n /** World affines the shape will also be drawn under once it lands, by\n * the container it is drawn into: the preview is painted under each. */\n copies?: readonly (readonly [number, number, number, number, number, number])[];\n }\n | {\n /**\n * Why the gesture cannot land where it is, in words for the user: a\n * refusal's reason. A surface shows `text` beside the pointer, which\n * `at` is, in world coordinates.\n */\n kind: 'reason';\n at: { x: number; y: number };\n text: string;\n };\n\n/** A handle's overlays as a list: empty when it has none. */\nexport function overlaysOf(handle: OngoingHandle): readonly OngoingOverlay[] {\n const ov = handle.overlay?.();\n if (!ov) return [];\n return isOverlayList(ov) ? ov : [ov];\n}\n\nfunction isOverlayList(ov: OngoingOverlay | readonly OngoingOverlay[]): ov is readonly OngoingOverlay[] {\n return Array.isArray(ov);\n}\n","/**\n * Named predicates for `defaultBinding.target.kindOf`. Each matches the\n * `TargetPredicate` shape, declaring whether it reads the hit,\n * so they drop into action descriptors without a wrapper:\n *\n * target: { kindOf: isAnchor }\n *\n * Single source of truth for \"what does this affordance kind mean\" — adding\n * a new predicate here is what enables every action that needs the same\n * shape to read it. Drift prevention.\n */\nimport { bodyPredicate, hitPredicate, type TargetPredicate } from '@weasel-js/gestures';\n\n// ─── Body-class predicates (read the second arg) ───────────────────────\n\n/** A predicate that resolves from `bodyTarget` alone. */\nexport type BodyPredicate = TargetPredicate & { readsAffordance: false };\n\n/** Matches any body hit — selected or unselected node body. */\nexport const isBody: BodyPredicate = bodyPredicate((bodyTarget) =>\n bodyTarget === 'selected-body' || bodyTarget === 'unselected-body');\n\n/** Body hit specifically already in the selection. */\nexport const isSelectedBody: BodyPredicate = bodyPredicate((bodyTarget) =>\n bodyTarget === 'selected-body');\n\n/** Body hit specifically NOT in the selection. */\nexport const isUnselectedBody: BodyPredicate = bodyPredicate((bodyTarget) =>\n bodyTarget === 'unselected-body');\n\n/** Empty-canvas hit — no node beneath cursor. */\nexport const isEmpty: BodyPredicate = bodyPredicate((bodyTarget) =>\n bodyTarget === 'empty');\n\n// ─── Affordance-kind predicates (read the first arg) ───────────────────\n\nfunction kindOf(target: unknown): string | undefined {\n if (typeof target !== 'object' || target === null) return undefined;\n const k = (target as { kind?: unknown }).kind;\n return typeof k === 'string' ? k : undefined;\n}\n\n/** Any resize handle: a corner (`handle:top-left`, …) or an edge (`handle:top`, …). */\nexport const isResizeHandle = hitPredicate((target) => {\n const k = kindOf(target);\n return k !== undefined && k.startsWith('handle:');\n});\n\n/** The rotate-around-center handle above the bounding box. */\nexport const isRotateHandle = hitPredicate((target) =>\n kindOf(target) === 'rotate-handle');\n\n/** Any path anchor (the on-curve dot). */\nexport const isAnchor = hitPredicate((target) => {\n const k = kindOf(target);\n return k !== undefined && /^anchor:\\d+$/.test(k);\n});\n\n/** Either control handle (controlIn or controlOut). */\nexport const isControlHandle = hitPredicate((target) => {\n const k = kindOf(target);\n return k !== undefined && /^(controlIn|controlOut):\\d+$/.test(k);\n});\n\n/** A corner-shape widget, set inside a corner anchor of the edited path. */\nexport const isCornerWidget = hitPredicate((target) => {\n const k = kindOf(target);\n return k !== undefined && /^corner:\\d+$/.test(k);\n});\n\n/** Any of the three anchor-editing affordances (anchor + both controls). */\nexport const isAnchorOrControl = hitPredicate((target) =>\n isAnchor(target) || isControlHandle(target));\n\n/** The outline of the path being edited, between its anchors. */\nexport const isSegment = hitPredicate((target) => kindOf(target) === 'segment');\n\n/** The grip midway along a curved segment's balance line, `balance:N`, where\n * N is the flat index of the anchor the segment starts at. */\nexport const isBalanceGrip = hitPredicate((target) => {\n const k = kindOf(target);\n return k !== undefined && /^balance:\\d+$/.test(k);\n});\n\n/** Anything path edit puts on the path: an anchor, a control, a segment, a\n * segment's balance grip, or a corner widget. */\nexport const isPathEditPart = hitPredicate((target) =>\n isAnchorOrControl(target) || isSegment(target) || isBalanceGrip(target) || isCornerWidget(target));\n","import type { Contribution } from './types';\n\n/**\n * Concatenate contribution bundles into one registry, preserving order —\n * entry order decides which of two same-specificity bindings in one scope\n * tier wins, so it is part of the result, not an accident of it.\n *\n * Throws on a duplicate id or dep name rather than dropping one: a feature\n * silently losing its bindings, or reading another feature's dep, is the\n * failure this registry exists to make loud.\n */\nexport function mergeContributions<T extends Contribution<unknown>>(\n ...bundles: readonly (readonly T[])[]\n): T[] {\n const out: T[] = [];\n const seen = new Set<string>();\n const depOwner = new Map<string, string>();\n for (const bundle of bundles) {\n for (const entry of bundle) {\n if (seen.has(entry.id)) {\n throw new Error(\n `mergeContributions: duplicate contribution id \"${entry.id}\". `\n + `Two bundles registered the same id; rename one or merge them by hand.`,\n );\n }\n seen.add(entry.id);\n for (const dep of Object.keys(entry.deps ?? {})) {\n const owner = depOwner.get(dep);\n if (owner !== undefined) {\n throw new Error(\n `mergeContributions: dep \"${dep}\" is provided by both \"${owner}\" and \"${entry.id}\". `\n + `One registry answers each dep name; drop one source.`,\n );\n }\n depOwner.set(dep, entry.id);\n }\n out.push(entry);\n }\n }\n return out;\n}\n","import { modeLabel, type ModeDefinition, type ModeRegistry } from '@weasel-js/modes';\nimport { key, type KeySpec } from '@weasel-js/gestures';\nimport { ActionDisabledReason, type Action } from '../interactions/actions/action';\nimport type { Rule } from '../eligibility';\nimport type { Contribution } from './types';\n\n/**\n * What each mode shortcut does. A role left out binds nothing, so its key\n * falls through to whatever else the dispatcher has on it.\n */\nexport interface ModeShortcutHandlers {\n /** Enter mode `id` — the `entry` shortcut. */\n enter?: (id: string) => void;\n /** Whether mode `id` can be entered now. A mode that needs a target it\n * doesn't have answers no, and its entry key falls through. Default yes. */\n canEnter?: (id: string) => boolean;\n /** Leave the active soft mode, keeping its session to resume. */\n exit?: () => void;\n /** Leave the active soft mode and throw its session away. */\n discard?: () => void;\n /** Commit the active strict mode's transaction. */\n commit?: () => void;\n /** Abandon the active strict mode's transaction. */\n cancel?: () => void;\n}\n\ntype Role = 'exit' | 'discard' | 'commit' | 'cancel';\nconst LEAVING: readonly Role[] = ['exit', 'discard', 'commit', 'cancel'];\nconst VERB: Record<Role | 'entry', string> = {\n entry: 'Enter', exit: 'Exit', discard: 'Discard', commit: 'Commit', cancel: 'Cancel',\n};\n\n/**\n * A `ModeDefinition` shortcut chord — `'Escape'`, `'Meta+T'` — as a key spec.\n * Modifier names are case-insensitive; the last segment is the key.\n */\nexport function modeShortcutSpec(shortcut: string): KeySpec {\n return key(shortcut);\n}\n\n/**\n * The registry's declared mode shortcuts as an always-on contribution: one\n * action per shortcut, bound to its chord and gated on the mode it acts on —\n * `exit` / `discard` / `commit` / `cancel` while that mode is active, `entry`\n * while it is not. Install it with `<SceneCanvas ambient>`.\n *\n * An entry key one mode shares with another mode's leaving key is reported as\n * a route conflict unless `canEnter` is given: that is what keeps the entry\n * key from firing inside the other mode.\n *\n * The bindings ride the hotkey tier, so leaving a mode outranks what the same\n * key does otherwise (Escape clearing the selection), and they yield while a\n * gesture is in flight, so Escape mid-drag still cancels the drag first. Keys\n * typed into an editable element never reach them.\n */\nexport function modeShortcuts(\n registry: ModeRegistry,\n handlers: ModeShortcutHandlers,\n): Contribution<never> {\n const actions: Action[] = [];\n for (const mode of registry.list()) {\n const entry = mode.entry?.shortcut;\n const enter = handlers.enter;\n if (entry && enter) {\n // Without `canEnter` an entry key is live in every other mode, so it does not yield there.\n actions.push(shortcutAction(mode, 'entry', entry, { mode: { not: mode.id } },\n () => registry.current().id !== mode.id && (handlers.canEnter?.(mode.id) ?? true),\n () => enter(mode.id), handlers.canEnter !== undefined));\n }\n for (const role of LEAVING) {\n const shortcut = mode[role]?.shortcut;\n const run = handlers[role];\n if (!shortcut || !run) continue;\n actions.push(shortcutAction(mode, role, shortcut, { mode: mode.id },\n () => registry.current().id === mode.id,\n run, true));\n }\n }\n return { id: 'modes.shortcuts', eligibility: { always: true }, actions };\n}\n\nfunction shortcutAction(\n mode: ModeDefinition,\n role: Role | 'entry',\n shortcut: string,\n eligible: Rule,\n live: () => boolean,\n run: () => void,\n yields: boolean,\n): Action {\n return {\n id: `mode.${mode.id}.${role}`,\n label: `${VERB[role]} ${modeLabel(mode)}`,\n scope: 'hotkey',\n defaultBinding: [{\n spec: { ...modeShortcutSpec(shortcut), phase: [{ channel: '*', phase: 'initial' }] },\n opts: { id: `mode.${mode.id}.${role}.key`, yields },\n }],\n eligible,\n // `eligible` is the gate the dispatcher and palettes read, but a canvas\n // with no `modes` evaluates none; without this the key is\n // swallowed in every mode.\n enabled: () => (live() ? true : ActionDisabledReason.NotApplicable),\n invoker: { timing: 'immediate', run: () => run() },\n };\n}\n","import type {\n ClickSpec, ContextMenuSpec, DoubleClickSpec, DragSpec, EventModifiers, KeyHeldSpec, KeySpec, ModSpec,\n} from '@weasel-js/gestures';\n\n/** A spec kind a binding editor can capture. */\nexport type CaptureKind = 'key' | 'key-held' | 'click' | 'doubleClick' | 'drag' | 'contextMenu';\n\n/** What `captureGesture` resolves to. */\nexport type CapturedSpec = KeySpec | KeyHeldSpec | ClickSpec | DoubleClickSpec | DragSpec | ContextMenuSpec;\n\n/** An event's modifiers as a spec's, with the platform's primary one as `mod`. */\nfunction modSpecOf(e: EventModifiers, apple: boolean): ModSpec | undefined {\n const mods: ModSpec = {};\n if (apple ? e.metaKey : e.ctrlKey) mods.mod = true;\n if (e.shiftKey) mods.shift = true;\n if (e.altKey) mods.alt = true;\n if (apple ? e.ctrlKey : e.metaKey) mods[apple ? 'ctrl' : 'meta'] = true;\n return Object.keys(mods).length > 0 ? mods : undefined;\n}\n\nexport function specOf<K extends CapturedSpec['kind']>(kind: K, e: EventModifiers, apple: boolean): { kind: K; mods?: ModSpec } {\n const mods = modSpecOf(e, apple);\n return mods ? { kind, mods } : { kind };\n}\n\n/** Keep an event from the page. */\nexport const take = (e: Event): void => { e.preventDefault(); e.stopPropagation(); };\n","import {\n createPointerRecognizer, DOUBLE_CLICK_MAX_MS,\n type EventModifiers, type InputEvent, type PointerSample, type RecognizerClock,\n} from '@weasel-js/gestures';\nimport { specOf, take, type CaptureKind, type CapturedSpec } from './captureSpec';\n\n/** The click-and-drag thresholds a capture reads, each defaulting to its constant. */\nexport interface CaptureThresholds {\n dragPx?: number;\n doubleClickMs?: number;\n doubleClickPx?: number;\n}\n\n/** What a browser follows a press with; taken too, or the page acts on a gesture already captured. */\nexport const TRAILING = ['click', 'auxclick', 'dblclick', 'contextmenu'] as const;\n\nconst sampleOf = (e: PointerEvent): PointerSample => ({\n pointerId: e.pointerId, clientX: e.clientX, clientY: e.clientY, target: e.target, timeStamp: e.timeStamp,\n altKey: e.altKey, ctrlKey: e.ctrlKey, metaKey: e.metaKey, shiftKey: e.shiftKey,\n});\n\nconst browserClock: RecognizerClock = {\n now: () => performance.now(),\n setTimer: (fn, ms) => setTimeout(fn, ms),\n clearTimer: (t) => { clearTimeout(t as ReturnType<typeof setTimeout>); },\n};\n\n/**\n * Listen, through `listen`, for the next pointer gesture of `kinds` and hand\n * its spec to `done`. Returns what stops it. A press goes through the\n * dispatcher's recognizer, so a click and a drag part where they do on a canvas.\n */\nexport function capturePointer(\n target: EventTarget,\n kinds: ReadonlySet<CaptureKind>,\n apple: boolean,\n thresholds: CaptureThresholds,\n listen: (type: string, fn: (e: Event) => void) => void,\n done: (spec: CapturedSpec) => void,\n): () => void {\n let pendingClick: ReturnType<typeof setTimeout> | null = null;\n let dragMods: EventModifiers | null = null;\n\n const recognized = (ev: InputEvent): 'handled' | 'unhandled' => {\n switch (ev.kind) {\n case 'pointerdown':\n // Without `stage` it is the press held back until it crossed the drag threshold.\n if (!('stage' in ev && ev.stage === 'press')) dragMods = ev;\n return 'unhandled';\n case 'click': {\n if (!kinds.has('click')) return 'unhandled';\n const spec = specOf('click', ev, apple);\n if (!kinds.has('doubleClick')) { done(spec); return 'handled'; }\n if (pendingClick) clearTimeout(pendingClick);\n pendingClick = setTimeout(() => { done(spec); }, thresholds.doubleClickMs ?? DOUBLE_CLICK_MAX_MS);\n return 'handled';\n }\n case 'doubleclick':\n case 'contextmenu': {\n const kind = ev.kind === 'doubleclick' ? 'doubleClick' : 'contextMenu';\n if (!kinds.has(kind)) return 'unhandled';\n done(specOf(kind, ev, apple));\n return 'handled';\n }\n default:\n return 'unhandled';\n }\n };\n\n const recognizer = createPointerRecognizer({\n clock: browserClock,\n dragPx: () => thresholds.dragPx,\n doubleClickMs: () => thresholds.doubleClickMs,\n doubleClickPx: () => thresholds.doubleClickPx,\n sink: { dispatch: recognized, multiTouchInFlight: () => false },\n });\n\n /** A pointer event for a press this capture holds, taken from the page; otherwise `null`. */\n const held = (e: Event): PointerEvent | null => {\n const p = e as PointerEvent;\n if (recognizer.positionOf(p.pointerId) === undefined) return null;\n take(p);\n return p;\n };\n\n listen('pointerdown', (e) => {\n const p = e as PointerEvent;\n take(p);\n // Only the primary button presses as the dispatcher sees it; a secondary\n // one reaches a binding as its `contextmenu`.\n if ((p.button ?? 0) !== 0) return;\n // An element hears a held pointer's moves and release only while it captures them.\n if (target instanceof Element) {\n try { target.setPointerCapture(p.pointerId); } catch { /* the pointer is already gone */ }\n }\n recognizer.press({ ...sampleOf(p), x: p.clientX, y: p.clientY, pointerType: p.pointerType });\n });\n listen('pointermove', (e) => {\n const p = held(e);\n if (p) recognizer.move(sampleOf(p));\n });\n listen('pointerup', (e) => {\n const p = held(e);\n if (!p) return;\n const drag = dragMods;\n dragMods = null;\n recognizer.release(sampleOf(p));\n if (drag && kinds.has('drag')) done(specOf('drag', drag, apple));\n });\n listen('pointercancel', (e) => {\n const p = held(e);\n if (!p) return;\n dragMods = null;\n recognizer.cancel(p.pointerId);\n });\n for (const type of TRAILING) {\n listen(type, (e) => {\n take(e);\n if (type === 'contextmenu' && kinds.has('contextMenu')) done(specOf('contextMenu', e as MouseEvent, apple));\n });\n }\n\n return () => {\n if (pendingClick) clearTimeout(pendingClick);\n recognizer.reset();\n };\n}\n","import { isApplePlatform } from '@weasel-js/gestures';\nimport { capturePointer, TRAILING, type CaptureThresholds } from './capturePointer';\nimport { specOf, take, type CaptureKind, type CapturedSpec } from './captureSpec';\n\nexport type { CaptureKind, CapturedSpec } from './captureSpec';\n\n/** Options for {@link captureGesture}. */\nexport interface CaptureGestureOptions extends CaptureThresholds {\n /** The kinds to take; input of any other kind is waited past. A keystroke\n * is taken as `key` when both `key` and `key-held` are listed. Defaults to\n * `key`, `click`, `doubleClick`, `drag` and `contextMenu`. */\n kinds?: readonly CaptureKind[];\n /** Stop listening and resolve `null`. */\n signal?: AbortSignal;\n /** Whether Cmd is Mod. Defaults to the detected platform. */\n apple?: boolean;\n /** Travel that makes a press a drag, in CSS px: pass the `gestures.dragPx`\n * kit setting. Defaults to `DRAG_THRESHOLD_PX`. */\n dragPx?: number;\n /** The `gestures.doubleClickMs` kit setting. Defaults to `DOUBLE_CLICK_MAX_MS`. */\n doubleClickMs?: number;\n /** The `gestures.doubleClickPx` kit setting. Defaults to `DOUBLE_CLICK_MAX_PX`. */\n doubleClickPx?: number;\n}\n\nconst DEFAULT_KINDS: readonly CaptureKind[] = ['key', 'click', 'doubleClick', 'drag', 'contextMenu'];\nconst POINTER_KINDS: readonly CaptureKind[] = ['click', 'doubleClick', 'drag', 'contextMenu'];\nconst MODIFIER_KEYS: ReadonlySet<string> = new Set(['Shift', 'Control', 'Alt', 'Meta', 'AltGraph', 'CapsLock']);\n\n/**\n * The next input on `target` of one of `opts.kinds`, as a gesture spec, for a\n * binding editor: its modifiers with the platform's primary one as `mod`. A\n * press is told a click or a drag by the dispatcher's own recognizer, at its\n * drag threshold; a click is held back for a double click only when both are\n * asked for. A bare modifier key is waited past. Escape, or an abort, resolves\n * `null`. What it takes is `preventDefault`ed and stopped, the click a browser\n * follows a press with included, so nothing else acts on it. The pointer is\n * left alone when no pointer kind is asked for, and keys other than Escape\n * when no key kind is.\n */\nexport function captureGesture(target: EventTarget, opts: CaptureGestureOptions = {}): Promise<CapturedSpec | null> {\n const apple = opts.apple ?? isApplePlatform();\n const kinds = new Set(opts.kinds ?? DEFAULT_KINDS);\n const keyKind = kinds.has('key') ? 'key' : kinds.has('key-held') ? 'key-held' : null;\n const pointer = POINTER_KINDS.some((k) => kinds.has(k));\n\n return new Promise((resolve) => {\n if (opts.signal?.aborted) { resolve(null); return; }\n let settled = false;\n let stopPointer = (): void => {};\n const listeners: [string, (e: Event) => void][] = [];\n const listen = (type: string, fn: (e: Event) => void): void => {\n listeners.push([type, fn]);\n target.addEventListener(type, fn, true);\n };\n\n const done = (spec: CapturedSpec | null): void => {\n if (settled) return;\n settled = true;\n stopPointer();\n opts.signal?.removeEventListener('abort', onAbort);\n for (const [type, fn] of listeners) target.removeEventListener(type, fn, true);\n // The click and dblclick a release goes on to fire arrive in the same task.\n if (pointer) {\n for (const type of TRAILING) target.addEventListener(type, take, true);\n setTimeout(() => { for (const type of TRAILING) target.removeEventListener(type, take, true); }, 0);\n }\n resolve(spec);\n };\n const onAbort = (): void => { done(null); };\n\n opts.signal?.addEventListener('abort', onAbort);\n listen('keydown', (e) => {\n const k = e as KeyboardEvent;\n if (MODIFIER_KEYS.has(k.key)) return;\n const escape = k.key === 'Escape' && !k.metaKey && !k.ctrlKey && !k.altKey && !k.shiftKey;\n if (!escape && !keyKind) return;\n take(k);\n done(escape || !keyKind ? null : { ...specOf(keyKind, k, apple), key: k.key });\n });\n if (pointer) stopPointer = capturePointer(target, kinds, apple, opts, listen, done);\n });\n}\n","import type { KeyHeldSpec, KeySpec } from '@weasel-js/gestures';\nimport { captureGesture } from './captureGesture';\n\n/** Options for {@link captureKey}. */\nexport interface CaptureKeyOptions {\n /** Capture the held form, `key-held`, rather than the keystroke. */\n held?: boolean;\n /** Stop listening and resolve `null`. */\n signal?: AbortSignal;\n /** Whether Cmd is Mod. Defaults to the detected platform. */\n apple?: boolean;\n}\n\n/**\n * The next keystroke on `target` as a key spec: {@link captureGesture} taking\n * a keystroke alone, and leaving the pointer to the page. A bare modifier is\n * waited past. Write the result with `keySpecRoute` to persist it as a binding\n * override.\n */\nexport function captureKey(target: EventTarget, opts: CaptureKeyOptions = {}): Promise<KeySpec | KeyHeldSpec | null> {\n return captureGesture(target, {\n kinds: [opts.held ? 'key-held' : 'key'],\n ...(opts.signal ? { signal: opts.signal } : {}),\n ...(opts.apple !== undefined ? { apple: opts.apple } : {}),\n }) as Promise<KeySpec | KeyHeldSpec | null>;\n}\n","// src/tools/defineTool.ts\nimport type { Tool } from './types';\nimport type { ToolDef } from './routeTypes';\nimport { RESERVED_ID_NAMES, RESERVED_ID_PREFIXES } from '@weasel-js/gestures';\nimport type { CursorSpec } from '@weasel-js/cursor';\nimport type { KernelOverlay } from '../index';\n\n/** Validate that `id` is usable as a tool / channel id in the route\n * grammar. Rejects ids that start with a reserved sigil (would shadow\n * future grammar extensions) and ids that collide with phase keywords\n * (would parse as the bare-phase shorthand). */\nfunction validateId(id: string, kind: 'tool' | 'action'): void {\n if (id.length === 0) {\n throw new Error(`weasel: ${kind} id may not be empty`);\n }\n if (RESERVED_ID_PREFIXES.has(id[0]!)) {\n throw new Error(\n `weasel: ${kind} id \"${id}\" starts with reserved sigil \"${id[0]}\" ` +\n `(reserved set: ${[...RESERVED_ID_PREFIXES].join(' ')})`,\n );\n }\n if (RESERVED_ID_NAMES.has(id)) {\n throw new Error(\n `weasel: ${kind} id \"${id}\" collides with a reserved phase keyword ` +\n `(reserved: ${[...RESERVED_ID_NAMES].join(', ')})`,\n );\n }\n}\n\n/**\n * Build a `Tool` from a declarative `ToolDef`: validates the id, applies the\n * `cursor` default, and keeps the authored form on `Tool.def` for reflection.\n */\nexport function defineTool<TOverlay = KernelOverlay>(\n def: ToolDef<TOverlay>,\n): Tool<TOverlay> {\n validateId(def.id, 'tool');\n\n const resolveCursor = (): CursorSpec => {\n if (def.cursor == null) return '';\n return typeof def.cursor === 'function' ? def.cursor() : def.cursor;\n };\n\n return {\n id: def.id,\n eligibility: {\n focus: true,\n capabilities: def.capabilities,\n ...(def.hotkey ? { offhand: def.hotkey } : {}),\n },\n actions: def.actions,\n menus: def.menus,\n def,\n presentation: def.presentation,\n keybinding: def.keybinding,\n onActivate: def.onActivate,\n onDeactivate: def.onDeactivate,\n cursor: resolveCursor,\n bindings: def.bindings,\n overlay: def.overlay,\n overlayPosition: def.overlayPosition,\n };\n}\n","/**\n * Tool sets: a named group of tool ids, the unit a consumer opts into whole.\n * A set names ids, never tools, because a tool is built by a hook that holds\n * its state; whatever mounts the set supplies the tool for each id.\n */\n\n/** A named group of tool ids. A member is an id or another set, whose ids it takes in order. */\nexport interface ToolSet<TId extends string = string> {\n readonly id: string;\n readonly members: readonly (TId | ToolSet<TId>)[];\n}\n\n/** One entry of a list of tools to mount: an id, or a set of them. */\nexport type ToolEntry<TId extends string = string> = TId | ToolSet<TId>;\n\n/** A set named `id` of `members`, in palette order. */\nexport function toolSet<TId extends string>(id: string, members: readonly ToolEntry<TId>[]): ToolSet<TId> {\n return { id, members };\n}\n\n/** Whether `entry` is a set rather than a single id. */\nexport function isToolSet<TId extends string>(entry: ToolEntry<TId>): entry is ToolSet<TId> {\n return typeof entry !== 'string';\n}\n\n/** Every id `entries` name, sets opened in place, each id once at its first place. */\nexport function toolIdsOf<TId extends string>(entries: readonly ToolEntry<TId>[]): TId[] {\n const out: TId[] = [];\n const seen = new Set<string>();\n const walk = (list: readonly ToolEntry<TId>[]): void => {\n for (const entry of list) {\n if (isToolSet(entry)) walk(entry.members);\n else if (!seen.has(entry)) {\n seen.add(entry);\n out.push(entry);\n }\n }\n };\n walk(entries);\n return out;\n}\n\n/** `set` less every id `omit` names, sets opened. Keeps `set`'s id with a `-without` suffix. */\nexport function withoutTools<TId extends string>(set: ToolSet<TId>, ...omit: readonly ToolEntry<TId>[]): ToolSet<TId> {\n const gone = new Set<string>(toolIdsOf(omit));\n return { id: `${set.id}-without`, members: toolIdsOf([set]).filter((id) => !gone.has(id)) };\n}\n\n/** Whether `set` names `id`, directly or through a set inside it. */\nexport function toolSetHas<TId extends string>(set: ToolSet<TId>, id: string): boolean {\n return (toolIdsOf([set]) as string[]).includes(id);\n}\n","/**\n * Key chords a major browser or the desktop under it takes before a page can:\n * reload, devtools, tab and window commands, menu accelerators. A binding on\n * one never fires for some users, so kit defaults steer clear of them.\n *\n * `mod` is Cmd on macOS and Ctrl elsewhere, as in a `KeySpec`. The list is\n * the union across Chrome, Safari, Firefox and Edge on macOS, Windows and\n * Linux, and errs toward listing a chord.\n */\nimport type { KeySpec } from '@weasel-js/gestures';\n\n/** One reserved chord, and what takes it. */\nexport interface ReservedChord {\n key: string;\n mod?: boolean;\n alt?: boolean;\n shift?: boolean;\n /** Who takes it, for a message. */\n use: string;\n}\n\nconst chord = (keys: string, mods: Omit<ReservedChord, 'key' | 'use'>, use: string): ReservedChord[] =>\n [...keys].map((key) => ({ key, ...mods, use }));\n\n/** Every chord the module's header describes, one entry per key. */\nexport const BROWSER_RESERVED_CHORDS: readonly ReservedChord[] = [\n ...chord('nqtwlrpmh', { mod: true }, 'new window, quit, new or close tab, address bar, reload, print, minimize, hide'),\n ...chord('ntwrbo', { mod: true, shift: true }, 'private window, reopen or close tab, hard reload, bookmarks, bookmark manager'),\n ...chord('ijck', { mod: true, shift: true }, 'devtools, console and inspector on Windows and Linux; Firefox Browser and Web Console'),\n ...chord('ijcukbrlemhdwfn', { mod: true, alt: true }, 'devtools, console, inspector, view source, bookmarks, reload from origin, downloads, empty caches, minimize all, hide others, Dock, close all, search field'),\n ...chord('fevsbthd', { alt: true }, 'menu accelerators and address bar on Windows and Linux'),\n ...chord('ita', { alt: true, shift: true }, 'feedback, toolbar focus and accessibility commands'),\n];\n\nconst lower = (k: string | readonly string[]): string[] => (typeof k === 'string' ? [k] : [...k]).map((x) => x.toLowerCase());\n\n/** Whether a modifier policy can be satisfied with the modifier held (`true`)\n * or released (`false`). */\nconst allows = (policy: boolean | 'optional' | undefined, held: boolean): boolean =>\n policy === 'optional' || (policy === true) === held;\n\n/** The first reserved chord `spec` can fire on, or `null` when none. */\nexport function browserReservedChord(spec: KeySpec): ReservedChord | null {\n const keys = lower(spec.key);\n const m = spec.mods ?? {};\n const mod = m.mod ?? (m.meta === true || m.ctrl === true ? true : m.meta ?? m.ctrl);\n for (const c of BROWSER_RESERVED_CHORDS) {\n if (!keys.includes(c.key)) continue;\n if (allows(mod, c.mod === true) && allows(m.alt, c.alt === true) && allows(m.shift, c.shift === true)) return c;\n }\n return null;\n}\n","/**\n * Typed keys for the gesture/behavior scratch store, `ctx.scratch`.\n * `ScratchKey<T>` carries its payload type at the typing layer; at runtime\n * the key is just its underlying string and the store remains a plain `Record`.\n *\n * @example\n * ```ts\n * // Module-level constant, shared by writer + reader:\n * const LASSO_VERTICES = scratchKey<readonly { x: number; y: number }[]>('lasso.vertices');\n * setScratch(ctx.scratch, LASSO_VERTICES, vertices);\n * const vertices = getScratch(ctx.scratch, LASSO_VERTICES) ?? [];\n * ```\n */\n\n/** Phantom-typed key for a scratch slot. The `__scratchKeyPayload` phantom\n * field carries the value type without occupying any runtime memory. */\nexport interface ScratchKey<T> {\n readonly name: string;\n /** Phantom — never read at runtime. Only present so TypeScript can\n * recover `T` at use sites. */\n readonly __scratchKeyPayload?: (_: T) => T;\n}\n\n/** Compatible scratch store shape. The kit's gesture context's `scratch`\n * field already satisfies this; consumers don't need to construct one. */\nexport type ScratchStore = Record<string, unknown>;\n\n/**\n * Make a typed scratch key. Two keys with the same `name` refer to the same\n * slot at runtime — the type parameter is a compile-time contract, not a\n * uniqueness guarantee — so namespace the name (`'behavior.field'`).\n */\nexport function scratchKey<T>(name: string): ScratchKey<T> {\n return { name };\n}\n\n/** Read a typed slot from the scratch store. Returns `undefined` if\n * nothing has been written under the key. */\nexport function getScratch<T>(\n store: ScratchStore,\n key: ScratchKey<T>,\n): T | undefined {\n return store[key.name] as T | undefined;\n}\n\n/** Write a value to a typed slot. Overwrites whatever was there. */\nexport function setScratch<T>(\n store: ScratchStore,\n key: ScratchKey<T>,\n value: T,\n): void {\n store[key.name] = value;\n}\n\n/** Remove a slot from the scratch store. Returns `true` if it was set,\n * `false` if it wasn't. */\nexport function deleteScratch<T>(\n store: ScratchStore,\n key: ScratchKey<T>,\n): boolean {\n if (Object.prototype.hasOwnProperty.call(store, key.name)) {\n delete store[key.name];\n return true;\n }\n return false;\n}\n"]}
1
+ {"version":3,"sources":["../src/interactions/actions/actionTags.ts","../src/interactions/actions/holdPreview.ts","../src/interactions/actions/overlay.ts","../src/interactions/dispatcher/predicates.ts","../src/contributions/merge.ts","../src/tools/returnToModeDefault.ts","../src/contributions/modeShortcuts.ts","../src/keymaps/captureSpec.ts","../src/keymaps/capturePointer.ts","../src/keymaps/captureGesture.ts","../src/keymaps/captureKey.ts","../src/tools/toolOptions.ts","../src/tools/defineTool.ts","../src/tools/toolSet.ts","../src/interactions/browserReservedKeys.ts","../src/interactions/scratchKey.ts"],"names":["key","RESERVED_ID_PREFIXES","RESERVED_ID_NAMES"],"mappings":";;;;;;;;AAUO,SAAS,aAAA,CAAc,SAA4B,GAAA,EAAuB;AAC/E,EAAA,OAAO,OAAA,CAAQ,OAAO,CAAC,CAAA,KAAM,OAAO,CAAA,CAAE,IAAA,EAAM,GAAG,CAAA,KAAM,CAAA,CAAE,UAAU,IAAA,CAAK,CAAC,MAAM,MAAA,CAAO,CAAA,CAAE,MAAM,GAAG,CAAC,KAAK,KAAA,CAAM,CAAA;AAC7G;AAIO,SAAS,iBAAA,CAAkB,SAA4B,GAAA,EAA2B;AACvF,EAAA,OAAO,aAAA,CAAc,OAAA,EAAS,GAAG,CAAA,CAAE,QAAQ,WAAW,CAAA,CAAE,MAAA,CAAO,CAAC,CAAA,KAAM,MAAA,CAAO,CAAA,CAAE,IAAA,EAAM,GAAG,CAAC,CAAA;AAC3F;AAIO,SAAS,eAAA,CAAgB,MAAkB,KAAA,EAAkC;AAClF,EAAA,OAAO,UAAA,CAAW,KAAA,EAAO,EAAE,IAAA,EAAM,CAAC,eAAA,CAAgB,IAAI,CAAC,CAAA,EAAG,IAAA,EAAM,IAAA,CAAK,IAAA,EAAM,CAAA;AAC7E;;;ACfO,IAAM,aAAA,GAAgB,CAAC,EAAA,KAAuB,CAAA,EAAG,EAAE,CAAA,KAAA;AAUnD,SAAS,YAAY,MAAA,EAAwB;AAClD,EAAA,MAAM,EAAE,SAAQ,GAAI,MAAA;AACpB,EAAA,OAAO;AAAA,IACL,EAAA,EAAI,aAAA,CAAc,MAAA,CAAO,EAAE,CAAA;AAAA,IAC3B,OAAO,MAAA,CAAO,KAAA;AAAA,IACd,GAAI,OAAO,QAAA,GAAW,EAAE,UAAU,MAAA,CAAO,QAAA,KAAa,EAAC;AAAA,IACvD,GAAI,OAAO,OAAA,GAAU,EAAE,SAAS,MAAA,CAAO,OAAA,KAAY,EAAC;AAAA,IACpD,GAAI,OAAO,QAAA,GAAW,EAAE,UAAU,MAAA,CAAO,QAAA,KAAa,EAAC;AAAA,IACvD,OAAA,EAAS;AAAA,MACP,MAAA,EAAQ,SAAA;AAAA,MACR,KAAA,EAAO,CAAC,GAAA,EAAK,IAAA,KAAwB;AACnC,QAAA,MAAM,MAAA,GAAS,aAAA,CAAc,IAAA,EAAM,MAAM,CAAA;AACzC,QAAA,MAAM,IAAA,GAAO,MAAA,CAAO,OAAA,GAAU,GAAA,CAAI,MAAM,MAAM,CAAA;AAC9C,QAAA,OAAO;AAAA;AAAA,UAEL,KAAA,EAAO,CAAC,IAAA,EAAM,MAAA,KAAW;AACvB,YAAA,IAAA,IAAO;AACP,YAAA,IAAI,MAAA,KAAW,YAAY,OAAA,EAAS,MAAA,KAAW,aAAa,OAAA,CAAQ,GAAA,CAAI,GAAA,CAAI,IAAA,EAAM,MAAM,CAAA;AAAA,UAC1F;AAAA,SACF;AAAA,MACF;AAAA;AACF,GACF;AACF;;;ACwEO,SAAS,WAAW,MAAA,EAAkD;AAC3E,EAAA,MAAM,EAAA,GAAK,OAAO,OAAA,IAAU;AAC5B,EAAA,IAAI,CAAC,EAAA,EAAI,OAAO,EAAC;AACjB,EAAA,OAAO,aAAA,CAAc,EAAE,CAAA,GAAI,EAAA,GAAK,CAAC,EAAE,CAAA;AACrC;AAEA,SAAS,cAAc,EAAA,EAAiF;AACtG,EAAA,OAAO,KAAA,CAAM,QAAQ,EAAE,CAAA;AACzB;ACvGO,IAAM,SAAwB,aAAA,CAAc,CAAC,eAClD,UAAA,KAAe,eAAA,IAAmB,eAAe,iBAAiB;AAG7D,IAAM,cAAA,GAAgC,aAAA,CAAc,CAAC,UAAA,KAC1D,eAAe,eAAe;AAGzB,IAAM,gBAAA,GAAkC,aAAA,CAAc,CAAC,UAAA,KAC5D,eAAe,iBAAiB;AAG3B,IAAM,OAAA,GAAyB,aAAA,CAAc,CAAC,UAAA,KACnD,eAAe,OAAO;AAIxB,SAAS,OAAO,MAAA,EAAqC;AACnD,EAAA,IAAI,OAAO,MAAA,KAAW,QAAA,IAAY,MAAA,KAAW,MAAM,OAAO,MAAA;AAC1D,EAAA,MAAM,IAAK,MAAA,CAA8B,IAAA;AACzC,EAAA,OAAO,OAAO,CAAA,KAAM,QAAA,GAAW,CAAA,GAAI,MAAA;AACrC;AAGO,IAAM,cAAA,GAAiB,YAAA,CAAa,CAAC,MAAA,KAAW;AACrD,EAAA,MAAM,CAAA,GAAI,OAAO,MAAM,CAAA;AACvB,EAAA,OAAO,CAAA,KAAM,MAAA,IAAa,CAAA,CAAE,UAAA,CAAW,SAAS,CAAA;AAClD,CAAC;AAGM,IAAM,iBAAiB,YAAA,CAAa,CAAC,WAC1C,MAAA,CAAO,MAAM,MAAM,eAAe;AAG7B,IAAM,QAAA,GAAW,YAAA,CAAa,CAAC,MAAA,KAAW;AAC/C,EAAA,MAAM,CAAA,GAAI,OAAO,MAAM,CAAA;AACvB,EAAA,OAAO,CAAA,KAAM,MAAA,IAAa,cAAA,CAAe,IAAA,CAAK,CAAC,CAAA;AACjD,CAAC;AAGM,IAAM,eAAA,GAAkB,YAAA,CAAa,CAAC,MAAA,KAAW;AACtD,EAAA,MAAM,CAAA,GAAI,OAAO,MAAM,CAAA;AACvB,EAAA,OAAO,CAAA,KAAM,MAAA,IAAa,8BAAA,CAA+B,IAAA,CAAK,CAAC,CAAA;AACjE,CAAC;AAGM,IAAM,cAAA,GAAiB,YAAA,CAAa,CAAC,MAAA,KAAW;AACrD,EAAA,MAAM,CAAA,GAAI,OAAO,MAAM,CAAA;AACvB,EAAA,OAAO,CAAA,KAAM,MAAA,IAAa,cAAA,CAAe,IAAA,CAAK,CAAC,CAAA;AACjD,CAAC;AAGM,IAAM,iBAAA,GAAoB,aAAa,CAAC,MAAA,KAC7C,SAAS,MAAM,CAAA,IAAK,eAAA,CAAgB,MAAM,CAAC;AAGtC,IAAM,YAAY,YAAA,CAAa,CAAC,WAAW,MAAA,CAAO,MAAM,MAAM,SAAS;AAIvE,IAAM,aAAA,GAAgB,YAAA,CAAa,CAAC,MAAA,KAAW;AACpD,EAAA,MAAM,CAAA,GAAI,OAAO,MAAM,CAAA;AACvB,EAAA,OAAO,CAAA,KAAM,MAAA,IAAa,eAAA,CAAgB,IAAA,CAAK,CAAC,CAAA;AAClD,CAAC;AAIM,IAAM,cAAA,GAAiB,YAAA,CAAa,CAAC,MAAA,KAC1C,kBAAkB,MAAM,CAAA,IAAK,SAAA,CAAU,MAAM,KAAK,aAAA,CAAc,MAAM,CAAA,IAAK,cAAA,CAAe,MAAM,CAAC;;;AC5E5F,SAAS,sBACX,OAAA,EACE;AACL,EAAA,MAAM,MAAW,EAAC;AAClB,EAAA,MAAM,IAAA,uBAAW,GAAA,EAAY;AAC7B,EAAA,MAAM,QAAA,uBAAe,GAAA,EAAoB;AACzC,EAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC5B,IAAA,KAAA,MAAW,SAAS,MAAA,EAAQ;AAC1B,MAAA,IAAI,IAAA,CAAK,GAAA,CAAI,KAAA,CAAM,EAAE,CAAA,EAAG;AACtB,QAAA,MAAM,IAAI,KAAA;AAAA,UACR,CAAA,+CAAA,EAAkD,MAAM,EAAE,CAAA,wEAAA;AAAA,SAE5D;AAAA,MACF;AACA,MAAA,IAAA,CAAK,GAAA,CAAI,MAAM,EAAE,CAAA;AACjB,MAAA,KAAA,MAAW,OAAO,MAAA,CAAO,IAAA,CAAK,MAAM,IAAA,IAAQ,EAAE,CAAA,EAAG;AAC/C,QAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,GAAA,CAAI,GAAG,CAAA;AAC9B,QAAA,IAAI,UAAU,MAAA,EAAW;AACvB,UAAA,MAAM,IAAI,KAAA;AAAA,YACR,4BAA4B,GAAG,CAAA,uBAAA,EAA0B,KAAK,CAAA,OAAA,EAAU,MAAM,EAAE,CAAA,uDAAA;AAAA,WAElF;AAAA,QACF;AACA,QAAA,QAAA,CAAS,GAAA,CAAI,GAAA,EAAK,KAAA,CAAM,EAAE,CAAA;AAAA,MAC5B;AACA,MAAA,GAAA,CAAI,KAAK,KAAK,CAAA;AAAA,IAChB;AAAA,EACF;AACA,EAAA,OAAO,GAAA;AACT;;;AC/BO,SAAS,oBAAoB,IAAA,EAAuC;AACzE,EAAA,MAAM,MAAA,GAAS,IAAA,EAAM,eAAA,IAAkB,IAAK,IAAA;AAC5C,EAAA,MAAM,QAAQ,IAAA,EAAM,UAAA;AACpB,EAAA,IAAI,WAAW,IAAA,IAAQ,CAAC,SAAS,KAAA,CAAM,MAAA,KAAW,QAAQ,OAAO,KAAA;AACjE,EAAA,KAAA,CAAM,UAAU,MAAM,CAAA;AACtB,EAAA,OAAO,IAAA;AACT;;;ACcA,IAAM,OAAA,GAA2B,CAAC,MAAA,EAAQ,SAAA,EAAW,UAAU,QAAQ,CAAA;AACvE,IAAM,IAAA,GAAuC;AAAA,EAC3C,KAAA,EAAO,OAAA;AAAA,EAAS,IAAA,EAAM,MAAA;AAAA,EAAQ,OAAA,EAAS,SAAA;AAAA,EAAW,MAAA,EAAQ,QAAA;AAAA,EAAU,MAAA,EAAQ;AAC9E,CAAA;AAMO,SAAS,iBAAiB,QAAA,EAA2B;AAC1D,EAAA,OAAO,IAAI,QAAQ,CAAA;AACrB;AAmBO,SAAS,aAAA,CACd,UACA,QAAA,EACqB;AACrB,EAAA,MAAM,UAAoB,EAAC;AAC3B,EAAA,KAAA,MAAW,IAAA,IAAQ,QAAA,CAAS,IAAA,EAAK,EAAG;AAClC,IAAA,MAAM,KAAA,GAAQ,KAAK,KAAA,EAAO,QAAA;AAC1B,IAAA,MAAM,QAAQ,QAAA,CAAS,KAAA;AACvB,IAAA,IAAI,SAAS,KAAA,EAAO;AAElB,MAAA,OAAA,CAAQ,IAAA,CAAK,cAAA;AAAA,QAAe,IAAA;AAAA,QAAM,OAAA;AAAA,QAAS,KAAA;AAAA,QAAO,EAAE,IAAA,EAAM,EAAE,GAAA,EAAK,IAAA,CAAK,IAAG,EAAE;AAAA,QACzE,MAAM,QAAA,CAAS,OAAA,EAAQ,CAAE,EAAA,KAAO,IAAA,CAAK,EAAA,KAAO,QAAA,CAAS,QAAA,GAAW,IAAA,CAAK,EAAE,CAAA,IAAK,IAAA,CAAA;AAAA,QAC5E,MAAM,KAAA,CAAM,IAAA,CAAK,EAAE,CAAA;AAAA,QAAG,SAAS,QAAA,KAAa;AAAA,OAAU,CAAA;AAAA,IAC1D;AACA,IAAA,KAAA,MAAW,QAAQ,OAAA,EAAS;AAC1B,MAAA,MAAM,QAAA,GAAW,IAAA,CAAK,IAAI,CAAA,EAAG,QAAA;AAC7B,MAAA,MAAM,GAAA,GAAM,SAAS,IAAI,CAAA;AACzB,MAAA,IAAI,CAAC,QAAA,IAAY,CAAC,GAAA,EAAK;AACvB,MAAA,MAAM,QAAA,GAAW,IAAA,KAAS,MAAA,IAAU,IAAA,KAAS,QAAA;AAC7C,MAAA,OAAA,CAAQ,IAAA,CAAK,cAAA;AAAA,QAAe,IAAA;AAAA,QAAM,IAAA;AAAA,QAAM,QAAA;AAAA,QAAU,EAAE,IAAA,EAAM,IAAA,CAAK,EAAA,EAAG;AAAA,QAChE,MAAM,QAAA,CAAS,OAAA,EAAQ,CAAE,OAAO,IAAA,CAAK,EAAA;AAAA,QACrC,QAAA,GAAW,CAAC,IAAA,KAAS;AAAE,UAAA,IAAI,CAAC,mBAAA,CAAoB,IAAI,CAAA,EAAG,GAAA,EAAI;AAAA,QAAG,CAAA,GAAI,GAAA;AAAA,QAAK;AAAA,OAAK,CAAA;AAAA,IAChF;AAAA,EACF;AACA,EAAA,OAAO,EAAE,IAAI,iBAAA,EAAmB,WAAA,EAAa,EAAE,MAAA,EAAQ,IAAA,IAAQ,OAAA,EAAQ;AACzE;AAEA,SAAS,eACP,IAAA,EACA,IAAA,EACA,UACA,QAAA,EACA,IAAA,EACA,KACA,MAAA,EACQ;AACR,EAAA,OAAO;AAAA,IACL,EAAA,EAAI,CAAA,KAAA,EAAQ,IAAA,CAAK,EAAE,IAAI,IAAI,CAAA,CAAA;AAAA,IAC3B,KAAA,EAAO,GAAG,IAAA,CAAK,IAAI,CAAC,CAAA,CAAA,EAAI,SAAA,CAAU,IAAI,CAAC,CAAA,CAAA;AAAA,IACvC,KAAA,EAAO,QAAA;AAAA,IACP,gBAAgB,CAAC;AAAA,MACf,IAAA,EAAM,EAAE,GAAG,gBAAA,CAAiB,QAAQ,CAAA,EAAG,KAAA,EAAO,CAAC,EAAE,OAAA,EAAS,GAAA,EAAK,KAAA,EAAO,SAAA,EAAW,CAAA,EAAE;AAAA,MACnF,IAAA,EAAM,EAAE,EAAA,EAAI,CAAA,KAAA,EAAQ,KAAK,EAAE,CAAA,CAAA,EAAI,IAAI,CAAA,IAAA,CAAA,EAAQ,MAAA;AAAO,KACnD,CAAA;AAAA,IACD,QAAA;AAAA,IACA,QAAA,EAAU,CAAC,YAAA,EAAc,iBAAiB,CAAA;AAAA;AAAA;AAAA;AAAA,IAI1C,OAAA,EAAS,MAAO,IAAA,EAAK,GAAI,OAAO,oBAAA,CAAqB,aAAA;AAAA,IACrD,OAAA,EAAS,EAAE,MAAA,EAAQ,WAAA,EAAa,KAAK,CAAC,IAAA,KAAS,GAAA,CAAI,IAAI,CAAA;AAAE,GAC3D;AACF;;;ACpGA,SAAS,SAAA,CAAU,GAAmB,KAAA,EAAqC;AACzE,EAAA,MAAM,OAAgB,EAAC;AACvB,EAAA,IAAI,QAAQ,CAAA,CAAE,OAAA,GAAU,CAAA,CAAE,OAAA,OAAc,GAAA,GAAM,IAAA;AAC9C,EAAA,IAAI,CAAA,CAAE,QAAA,EAAU,IAAA,CAAK,KAAA,GAAQ,IAAA;AAC7B,EAAA,IAAI,CAAA,CAAE,MAAA,EAAQ,IAAA,CAAK,GAAA,GAAM,IAAA;AACzB,EAAA,IAAI,KAAA,GAAQ,EAAE,OAAA,GAAU,CAAA,CAAE,SAAS,IAAA,CAAK,KAAA,GAAQ,MAAA,GAAS,MAAM,CAAA,GAAI,IAAA;AACnE,EAAA,OAAO,OAAO,IAAA,CAAK,IAAI,CAAA,CAAE,MAAA,GAAS,IAAI,IAAA,GAAO,MAAA;AAC/C;AAEO,SAAS,MAAA,CAAuC,IAAA,EAAS,CAAA,EAAmB,KAAA,EAA6C;AAC9H,EAAA,MAAM,IAAA,GAAO,SAAA,CAAU,CAAA,EAAG,KAAK,CAAA;AAC/B,EAAA,OAAO,OAAO,EAAE,IAAA,EAAM,IAAA,EAAK,GAAI,EAAE,IAAA,EAAK;AACxC;AAGO,IAAM,IAAA,GAAO,CAAC,CAAA,KAAmB;AAAE,EAAA,CAAA,CAAE,cAAA,EAAe;AAAG,EAAA,CAAA,CAAE,eAAA,EAAgB;AAAG,CAAA;;;ACZ5E,IAAM,QAAA,GAAW,CAAC,OAAA,EAAS,UAAA,EAAY,YAAY,aAAa,CAAA;AAEvE,IAAM,QAAA,GAAW,CAAC,CAAA,MAAoC;AAAA,EACpD,WAAW,CAAA,CAAE,SAAA;AAAA,EAAW,SAAS,CAAA,CAAE,OAAA;AAAA,EAAS,SAAS,CAAA,CAAE,OAAA;AAAA,EAAS,QAAQ,CAAA,CAAE,MAAA;AAAA,EAAQ,WAAW,CAAA,CAAE,SAAA;AAAA,EAC/F,QAAQ,CAAA,CAAE,MAAA;AAAA,EAAQ,SAAS,CAAA,CAAE,OAAA;AAAA,EAAS,SAAS,CAAA,CAAE,OAAA;AAAA,EAAS,UAAU,CAAA,CAAE;AACxE,CAAA,CAAA;AAEA,IAAM,YAAA,GAAgC;AAAA,EACpC,GAAA,EAAK,MAAM,WAAA,CAAY,GAAA,EAAI;AAAA,EAC3B,UAAU,CAAC,EAAA,EAAI,EAAA,KAAO,UAAA,CAAW,IAAI,EAAE,CAAA;AAAA,EACvC,UAAA,EAAY,CAAC,CAAA,KAAM;AAAE,IAAA,YAAA,CAAa,CAAkC,CAAA;AAAA,EAAG;AACzE,CAAA;AAOO,SAAS,eACd,MAAA,EACA,KAAA,EACA,KAAA,EACA,UAAA,EACA,QACA,IAAA,EACY;AACZ,EAAA,IAAI,YAAA,GAAqD,IAAA;AACzD,EAAA,IAAI,QAAA,GAAkC,IAAA;AAEtC,EAAA,MAAM,UAAA,GAAa,CAAC,EAAA,KAA4C;AAC9D,IAAA,QAAQ,GAAG,IAAA;AAAM,MACf,KAAK,aAAA;AAEH,QAAA,IAAI,EAAE,OAAA,IAAW,EAAA,IAAM,EAAA,CAAG,KAAA,KAAU,UAAU,QAAA,GAAW,EAAA;AACzD,QAAA,OAAO,WAAA;AAAA,MACT,KAAK,OAAA,EAAS;AACZ,QAAA,IAAI,CAAC,KAAA,CAAM,GAAA,CAAI,OAAO,GAAG,OAAO,WAAA;AAChC,QAAA,MAAM,IAAA,GAAO,MAAA,CAAO,OAAA,EAAS,EAAA,EAAI,KAAK,CAAA;AACtC,QAAA,IAAI,CAAC,KAAA,CAAM,GAAA,CAAI,aAAa,CAAA,EAAG;AAAE,UAAA,IAAA,CAAK,IAAI,CAAA;AAAG,UAAA,OAAO,SAAA;AAAA,QAAW;AAC/D,QAAA,IAAI,YAAA,eAA2B,YAAY,CAAA;AAC3C,QAAA,YAAA,GAAe,WAAW,MAAM;AAAE,UAAA,IAAA,CAAK,IAAI,CAAA;AAAA,QAAG,CAAA,EAAG,UAAA,CAAW,aAAA,IAAiB,mBAAmB,CAAA;AAChG,QAAA,OAAO,SAAA;AAAA,MACT;AAAA,MACA,KAAK,aAAA;AAAA,MACL,KAAK,aAAA,EAAe;AAClB,QAAA,MAAM,IAAA,GAAO,EAAA,CAAG,IAAA,KAAS,aAAA,GAAgB,aAAA,GAAgB,aAAA;AACzD,QAAA,IAAI,CAAC,KAAA,CAAM,GAAA,CAAI,IAAI,GAAG,OAAO,WAAA;AAC7B,QAAA,IAAA,CAAK,MAAA,CAAO,IAAA,EAAM,EAAA,EAAI,KAAK,CAAC,CAAA;AAC5B,QAAA,OAAO,SAAA;AAAA,MACT;AAAA,MACA;AACE,QAAA,OAAO,WAAA;AAAA;AACX,EACF,CAAA;AAEA,EAAA,MAAM,aAAa,uBAAA,CAAwB;AAAA,IACzC,KAAA,EAAO,YAAA;AAAA,IACP,MAAA,EAAQ,MAAM,UAAA,CAAW,MAAA;AAAA,IACzB,aAAA,EAAe,MAAM,UAAA,CAAW,aAAA;AAAA,IAChC,aAAA,EAAe,MAAM,UAAA,CAAW,aAAA;AAAA,IAChC,MAAM,EAAE,QAAA,EAAU,UAAA,EAAY,kBAAA,EAAoB,MAAM,KAAA;AAAM,GAC/D,CAAA;AAGD,EAAA,MAAM,IAAA,GAAO,CAAC,CAAA,KAAkC;AAC9C,IAAA,MAAM,CAAA,GAAI,CAAA;AACV,IAAA,IAAI,WAAW,UAAA,CAAW,CAAA,CAAE,SAAS,CAAA,KAAM,QAAW,OAAO,IAAA;AAC7D,IAAA,IAAA,CAAK,CAAC,CAAA;AACN,IAAA,OAAO,CAAA;AAAA,EACT,CAAA;AAEA,EAAA,MAAA,CAAO,aAAA,EAAe,CAAC,CAAA,KAAM;AAC3B,IAAA,MAAM,CAAA,GAAI,CAAA;AACV,IAAA,IAAA,CAAK,CAAC,CAAA;AAGN,IAAA,IAAA,CAAK,CAAA,CAAE,MAAA,IAAU,CAAA,MAAO,CAAA,EAAG;AAE3B,IAAA,IAAI,kBAAkB,OAAA,EAAS;AAC7B,MAAA,IAAI;AAAE,QAAA,MAAA,CAAO,iBAAA,CAAkB,EAAE,SAAS,CAAA;AAAA,MAAG,CAAA,CAAA,MAAQ;AAAA,MAAoC;AAAA,IAC3F;AACA,IAAA,UAAA,CAAW,KAAA,CAAM,EAAE,GAAG,QAAA,CAAS,CAAC,CAAA,EAAG,CAAA,EAAG,CAAA,CAAE,OAAA,EAAS,GAAG,CAAA,CAAE,OAAA,EAAS,WAAA,EAAa,CAAA,CAAE,aAAa,CAAA;AAAA,EAC7F,CAAC,CAAA;AACD,EAAA,MAAA,CAAO,aAAA,EAAe,CAAC,CAAA,KAAM;AAC3B,IAAA,MAAM,CAAA,GAAI,KAAK,CAAC,CAAA;AAChB,IAAA,IAAI,CAAA,EAAG,UAAA,CAAW,IAAA,CAAK,QAAA,CAAS,CAAC,CAAC,CAAA;AAAA,EACpC,CAAC,CAAA;AACD,EAAA,MAAA,CAAO,WAAA,EAAa,CAAC,CAAA,KAAM;AACzB,IAAA,MAAM,CAAA,GAAI,KAAK,CAAC,CAAA;AAChB,IAAA,IAAI,CAAC,CAAA,EAAG;AACR,IAAA,MAAM,IAAA,GAAO,QAAA;AACb,IAAA,QAAA,GAAW,IAAA;AACX,IAAA,UAAA,CAAW,OAAA,CAAQ,QAAA,CAAS,CAAC,CAAC,CAAA;AAC9B,IAAA,IAAI,IAAA,IAAQ,KAAA,CAAM,GAAA,CAAI,MAAM,CAAA,OAAQ,MAAA,CAAO,MAAA,EAAQ,IAAA,EAAM,KAAK,CAAC,CAAA;AAAA,EACjE,CAAC,CAAA;AACD,EAAA,MAAA,CAAO,eAAA,EAAiB,CAAC,CAAA,KAAM;AAC7B,IAAA,MAAM,CAAA,GAAI,KAAK,CAAC,CAAA;AAChB,IAAA,IAAI,CAAC,CAAA,EAAG;AACR,IAAA,QAAA,GAAW,IAAA;AACX,IAAA,UAAA,CAAW,MAAA,CAAO,EAAE,SAAS,CAAA;AAAA,EAC/B,CAAC,CAAA;AACD,EAAA,KAAA,MAAW,QAAQ,QAAA,EAAU;AAC3B,IAAA,MAAA,CAAO,IAAA,EAAM,CAAC,CAAA,KAAM;AAClB,MAAA,IAAA,CAAK,CAAC,CAAA;AACN,MAAA,IAAI,IAAA,KAAS,aAAA,IAAiB,KAAA,CAAM,GAAA,CAAI,aAAa,CAAA,EAAG,IAAA,CAAK,MAAA,CAAO,aAAA,EAAe,CAAA,EAAiB,KAAK,CAAC,CAAA;AAAA,IAC5G,CAAC,CAAA;AAAA,EACH;AAEA,EAAA,OAAO,MAAM;AACX,IAAA,IAAI,YAAA,eAA2B,YAAY,CAAA;AAC3C,IAAA,UAAA,CAAW,KAAA,EAAM;AAAA,EACnB,CAAA;AACF;;;ACrGA,IAAM,gBAAwC,CAAC,KAAA,EAAO,OAAA,EAAS,aAAA,EAAe,QAAQ,aAAa,CAAA;AACnG,IAAM,aAAA,GAAwC,CAAC,OAAA,EAAS,aAAA,EAAe,QAAQ,aAAa,CAAA;AAC5F,IAAM,aAAA,mBAAqC,IAAI,GAAA,CAAI,CAAC,OAAA,EAAS,WAAW,KAAA,EAAO,MAAA,EAAQ,UAAA,EAAY,UAAU,CAAC,CAAA;AAavG,SAAS,cAAA,CAAe,MAAA,EAAqB,IAAA,GAA8B,EAAC,EAAiC;AAClH,EAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,KAAA,IAAS,eAAA,EAAgB;AAC5C,EAAA,MAAM,KAAA,GAAQ,IAAI,GAAA,CAAI,IAAA,CAAK,SAAS,aAAa,CAAA;AACjD,EAAA,MAAM,OAAA,GAAU,KAAA,CAAM,GAAA,CAAI,KAAK,CAAA,GAAI,QAAQ,KAAA,CAAM,GAAA,CAAI,UAAU,CAAA,GAAI,UAAA,GAAa,IAAA;AAChF,EAAA,MAAM,OAAA,GAAU,cAAc,IAAA,CAAK,CAAC,MAAM,KAAA,CAAM,GAAA,CAAI,CAAC,CAAC,CAAA;AAEtD,EAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,OAAA,KAAY;AAC9B,IAAA,IAAI,IAAA,CAAK,QAAQ,OAAA,EAAS;AAAE,MAAA,OAAA,CAAQ,IAAI,CAAA;AAAG,MAAA;AAAA,IAAQ;AACnD,IAAA,IAAI,OAAA,GAAU,KAAA;AACd,IAAA,IAAI,cAAc,MAAY;AAAA,IAAC,CAAA;AAC/B,IAAA,MAAM,YAA4C,EAAC;AACnD,IAAA,MAAM,MAAA,GAAS,CAAC,IAAA,EAAc,EAAA,KAAiC;AAC7D,MAAA,SAAA,CAAU,IAAA,CAAK,CAAC,IAAA,EAAM,EAAE,CAAC,CAAA;AACzB,MAAA,MAAA,CAAO,gBAAA,CAAiB,IAAA,EAAM,EAAA,EAAI,IAAI,CAAA;AAAA,IACxC,CAAA;AAEA,IAAA,MAAM,IAAA,GAAO,CAAC,IAAA,KAAoC;AAChD,MAAA,IAAI,OAAA,EAAS;AACb,MAAA,OAAA,GAAU,IAAA;AACV,MAAA,WAAA,EAAY;AACZ,MAAA,IAAA,CAAK,MAAA,EAAQ,mBAAA,CAAoB,OAAA,EAAS,OAAO,CAAA;AACjD,MAAA,KAAA,MAAW,CAAC,MAAM,EAAE,CAAA,IAAK,WAAW,MAAA,CAAO,mBAAA,CAAoB,IAAA,EAAM,EAAA,EAAI,IAAI,CAAA;AAE7E,MAAA,IAAI,OAAA,EAAS;AACX,QAAA,KAAA,MAAW,QAAQ,QAAA,EAAU,MAAA,CAAO,gBAAA,CAAiB,IAAA,EAAM,MAAM,IAAI,CAAA;AACrE,QAAA,UAAA,CAAW,MAAM;AAAE,UAAA,KAAA,MAAW,QAAQ,QAAA,EAAU,MAAA,CAAO,mBAAA,CAAoB,IAAA,EAAM,MAAM,IAAI,CAAA;AAAA,QAAG,GAAG,CAAC,CAAA;AAAA,MACpG;AACA,MAAA,OAAA,CAAQ,IAAI,CAAA;AAAA,IACd,CAAA;AACA,IAAA,MAAM,UAAU,MAAY;AAAE,MAAA,IAAA,CAAK,IAAI,CAAA;AAAA,IAAG,CAAA;AAE1C,IAAA,IAAA,CAAK,MAAA,EAAQ,gBAAA,CAAiB,OAAA,EAAS,OAAO,CAAA;AAC9C,IAAA,MAAA,CAAO,SAAA,EAAW,CAAC,CAAA,KAAM;AACvB,MAAA,MAAM,CAAA,GAAI,CAAA;AACV,MAAA,IAAI,aAAA,CAAc,GAAA,CAAI,CAAA,CAAE,GAAG,CAAA,EAAG;AAC9B,MAAA,MAAM,MAAA,GAAS,CAAA,CAAE,GAAA,KAAQ,QAAA,IAAY,CAAC,CAAA,CAAE,OAAA,IAAW,CAAC,CAAA,CAAE,OAAA,IAAW,CAAC,CAAA,CAAE,MAAA,IAAU,CAAC,CAAA,CAAE,QAAA;AACjF,MAAA,IAAI,CAAC,MAAA,IAAU,CAAC,OAAA,EAAS;AACzB,MAAA,IAAA,CAAK,CAAC,CAAA;AACN,MAAA,IAAA,CAAK,MAAA,IAAU,CAAC,OAAA,GAAU,IAAA,GAAO,EAAE,GAAG,MAAA,CAAO,OAAA,EAAS,CAAA,EAAG,KAAK,CAAA,EAAG,GAAA,EAAK,CAAA,CAAE,KAAK,CAAA;AAAA,IAC/E,CAAC,CAAA;AACD,IAAA,IAAI,OAAA,gBAAuB,cAAA,CAAe,MAAA,EAAQ,OAAO,KAAA,EAAO,IAAA,EAAM,QAAQ,IAAI,CAAA;AAAA,EACpF,CAAC,CAAA;AACH;;;AC/DO,SAAS,UAAA,CAAW,MAAA,EAAqB,IAAA,GAA0B,EAAC,EAA0C;AACnH,EAAA,OAAO,eAAe,MAAA,EAAQ;AAAA,IAC5B,KAAA,EAAO,CAAC,IAAA,CAAK,IAAA,GAAO,aAAa,KAAK,CAAA;AAAA,IACtC,GAAI,KAAK,MAAA,GAAS,EAAE,QAAQ,IAAA,CAAK,MAAA,KAAW,EAAC;AAAA,IAC7C,GAAI,KAAK,KAAA,KAAU,MAAA,GAAY,EAAE,KAAA,EAAO,IAAA,CAAK,KAAA,EAAM,GAAI;AAAC,GACzD,CAAA;AACH;;;ACuBA,IAAM,IAAA,GAAyC,MAAA,CAAO,MAAA,CAAO,EAAE,CAAA;AAGxD,SAAS,sBAAA,GAA2C;AACzD,EAAA,MAAM,MAAA,uBAAa,GAAA,EAAoC;AACvD,EAAA,MAAM,SAAA,uBAAgB,GAAA,EAAgB;AACtC,EAAA,OAAO;AAAA,IACL,KAAK,CAAC,MAAA,KAAW,MAAA,CAAO,GAAA,CAAI,MAAM,CAAA,IAAK,IAAA;AAAA,IACvC,GAAA,CAAI,MAAA,EAAQ,MAAA,EAAQ,KAAA,EAAO;AACzB,MAAA,MAAA,CAAO,GAAA,CAAI,MAAA,EAAQ,EAAE,GAAG,MAAA,CAAO,GAAA,CAAI,MAAM,CAAA,EAAG,CAAC,MAAM,GAAG,KAAA,EAAO,CAAA;AAC7D,MAAA,KAAA,MAAW,CAAA,IAAK,CAAC,GAAG,SAAS,GAAG,CAAA,EAAE;AAAA,IACpC,CAAA;AAAA,IACA,UAAU,QAAA,EAAU;AAClB,MAAA,SAAA,CAAU,IAAI,QAAQ,CAAA;AACtB,MAAA,OAAO,MAAM;AAAE,QAAA,SAAA,CAAU,OAAO,QAAQ,CAAA;AAAA,MAAG,CAAA;AAAA,IAC7C;AAAA,GACF;AACF;AAEA,SAAS,MAAA,CAAO,SAAsB,MAAA,EAAwC;AAC5E,EAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,KAAA,CAAM,QAAA,CAAS,MAAM,CAAA;AAC1C,EAAA,OAAO,IAAA,EAAM,IAAA,KAAS,QAAA,GAAY,IAAA,GAAsB,MAAA;AAC1D;AAGO,SAAS,gBAAA,CACd,MAAA,EAAgB,OAAA,EAAsB,MAAA,EACd;AACxB,EAAA,MAAM,IAAA,GAAO,MAAA,EAAQ,GAAA,CAAI,MAAM,KAAK,EAAC;AACrC,EAAA,MAAM,MAA8B,EAAC;AACrC,EAAA,KAAA,MAAWA,QAAO,MAAA,CAAO,IAAA,CAAK,OAAA,CAAQ,KAAA,CAAM,QAAQ,CAAA,EAAG;AACrD,IAAA,MAAM,IAAA,GAAO,MAAA,CAAO,OAAA,EAASA,IAAG,CAAA;AAChC,IAAA,MAAM,CAAA,GAAI,IAAA,CAAKA,IAAG,CAAA,IAAK,IAAA,EAAM,OAAA;AAC7B,IAAA,IAAI,OAAO,CAAA,KAAM,QAAA,EAAU,GAAA,CAAIA,IAAG,CAAA,GAAI,CAAA;AAAA,EACxC;AACA,EAAA,OAAO,GAAA;AACT;AAIO,SAAS,aAAA,CAAc,IAAA,EAAkB,KAAA,EAAe,IAAA,EAAsB,GAAA,EAAqB;AACxG,EAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,KAAA,KAAU,MAAA,GAAY,KAAA,GAAQ,IAAA,CAAK,KAAA,IAAS,GAAA,GAAM,KAAA,GAAQ,GAAA,IAAO,IAAA,CAAK,IAAA,IAAQ,KAAK,IAAA,IAAQ,CAAA,CAAA;AAC9G,EAAA,MAAM,OAAA,GAAU,IAAA,CAAK,IAAA,GAAO,IAAA,CAAK,KAAA,CAAM,QAAQ,IAAA,CAAK,IAAI,CAAA,GAAI,IAAA,CAAK,IAAA,GAAO,KAAA;AAExE,EAAA,MAAM,IAAA,GAAO,YAAY,KAAA,IAAS,IAAA,CAAK,OAAO,KAAA,GAAQ,GAAA,GAAM,KAAK,IAAA,GAAO,OAAA;AACxE,EAAA,MAAM,OAAA,GAAU,IAAA,CAAK,GAAA,CAAI,IAAA,CAAK,GAAA,IAAO,QAAA,EAAU,IAAA,CAAK,GAAA,CAAI,IAAA,CAAK,GAAA,IAAO,CAAA,QAAA,EAAW,IAAI,CAAC,CAAA;AACpF,EAAA,OAAO,MAAA,CAAO,OAAA,CAAQ,OAAA,CAAQ,CAAC,CAAC,CAAA;AAClC;AAIA,IAAM,SAAA,GAAuC;AAAA,EAC3C,MAAM,EAAE,IAAA,EAAM,OAAO,GAAA,EAAK,GAAA,EAAK,MAAM,cAAA,EAAe;AAAA,EACpD,QAAQ,EAAE,IAAA,EAAM,OAAO,GAAA,EAAK,GAAA,EAAK,MAAM,aAAA,EAAc;AAAA,EACrD,KAAA,EAAO,EAAE,IAAA,EAAM,KAAA,EAAO,KAAK,CAAC,GAAA,EAAK,GAAG,CAAA,EAAG,MAAM,cAAA,EAAgB,IAAA,EAAM,EAAE,KAAA,EAAO,MAAK,EAAE;AAAA,EACnF,KAAA,EAAO,EAAE,IAAA,EAAM,KAAA,EAAO,KAAK,CAAC,GAAA,EAAK,GAAG,CAAA,EAAG,MAAM,aAAA,EAAe,IAAA,EAAM,EAAE,KAAA,EAAO,MAAK;AAClF,CAAA;AAIA,IAAM,KAAA,GAA6B;AAAA,EACjC,EAAE,IAAA,EAAM,MAAA,EAAQ,KAAA,EAAO,MAAA,EAAQ,GAAA,EAAK,CAAA,EAAG,KAAA,EAAO,CAAC,CAAA,KAAM,CAAA,KAAA,EAAQ,CAAC,CAAA,CAAA,EAAG;AAAA,EACjE,EAAE,IAAA,EAAM,QAAA,EAAU,KAAA,EAAO,MAAA,EAAQ,GAAA,EAAK,EAAA,EAAI,KAAA,EAAO,CAAC,CAAA,KAAM,CAAA,OAAA,EAAU,CAAC,CAAA,CAAA,EAAG;AAAA,EACtE,EAAE,IAAA,EAAM,OAAA,EAAS,KAAA,EAAO,YAAY,GAAA,EAAK,CAAA,EAAG,KAAA,EAAO,CAAC,GAAG,CAAA,KAAM,CAAA,MAAA,EAAS,CAAC,CAAA,CAAA,EAAI,CAAC,CAAA,CAAA,EAAG;AAAA,EAC/E,EAAE,IAAA,EAAM,OAAA,EAAS,KAAA,EAAO,YAAY,GAAA,EAAK,EAAA,EAAI,KAAA,EAAO,CAAC,GAAG,CAAA,KAAM,CAAA,MAAA,EAAS,CAAC,CAAA,CAAA,EAAI,CAAC,CAAA,CAAA;AAC/E,CAAA;AAEA,SAAS,UAAA,CAAW,MAAA,EAAgB,SAAA,EAAmB,OAAA,EAAsB,IAAA,EAA+B;AAC1G,EAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,IAAA,CAAK,KAAK,CAAA;AAC/B,EAAA,MAAM,OAAO,IAAA,GAAO,MAAA,CAAO,OAAA,EAAS,IAAA,CAAK,MAAM,CAAA,GAAI,MAAA;AACnD,EAAA,IAAI,CAAC,IAAA,IAAQ,CAAC,IAAA,EAAM,OAAO,IAAA;AAC3B,EAAA,OAAO;AAAA,IACL,EAAA,EAAI,CAAA,EAAG,MAAM,CAAA,CAAA,EAAI,KAAK,IAAI,CAAA,CAAA;AAAA,IAC1B,OAAO,IAAA,CAAK,KAAA,CAAM,WAAW,IAAA,CAAK,IAAA,CAAK,aAAa,CAAA;AAAA,IACpD,KAAA,EAAO,MAAA;AAAA,IACP,QAAA,EAAU,CAAC,YAAA,EAAc,kBAAkB,CAAA;AAAA,IAC3C,OAAA,EAAS;AAAA,MACP,MAAA,EAAQ,WAAA;AAAA,MACR,GAAA,EAAK,CAAC,IAAA,KAAS;AACb,QAAA,MAAM,SAAS,IAAA,CAAK,gBAAA;AACpB,QAAA,IAAI,CAAC,MAAA,EAAQ;AACb,QAAA,MAAM,OAAA,GAAU,gBAAA,CAAiB,MAAA,EAAQ,OAAA,EAAS,MAAM,EAAE,IAAA,CAAK,MAAM,CAAA,IAAK,IAAA,CAAK,OAAA,IAAW,CAAA;AAC1F,QAAA,MAAA,CAAO,GAAA,CAAI,MAAA,EAAQ,IAAA,CAAK,MAAA,EAAQ,aAAA,CAAc,MAAM,OAAA,EAAS,IAAA,EAAM,IAAA,CAAK,GAAG,CAAC,CAAA;AAAA,MAC9E;AAAA,KACF;AAAA,IACA,OAAA,EAAS,CAAC,IAAA,KACR,IAAA,EAAM,UAAA,EAAY,WAAW,MAAA,IAAU,IAAA,CAAK,gBAAA,GAAmB,IAAA,GAAO,oBAAA,CAAqB;AAAA,GAC/F;AACF;AAIO,SAAS,eAAA,CACd,MAAA,EAAgB,SAAA,EAAmB,OAAA,EACgB;AACnD,EAAA,MAAM,UAAoB,EAAC;AAC3B,EAAA,MAAM,WAA6B,EAAC;AACpC,EAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,IAAA,MAAM,MAAA,GAAS,UAAA,CAAW,MAAA,EAAQ,SAAA,EAAW,SAAS,IAAI,CAAA;AAC1D,IAAA,IAAI,CAAC,MAAA,EAAQ;AACb,IAAA,OAAA,CAAQ,KAAK,MAAM,CAAA;AACnB,IAAA,QAAA,CAAS,KAAK,EAAE,IAAA,EAAM,UAAU,IAAA,CAAK,IAAI,GAAG,QAAA,EAAU,MAAA,CAAO,EAAA,EAAI,IAAA,EAAM,EAAE,EAAA,EAAI,CAAA,EAAG,OAAO,EAAE,CAAA,IAAA,CAAA,IAAU,CAAA;AAAA,EACrG;AACA,EAAA,OAAO,EAAE,SAAS,QAAA,EAAS;AAC7B;;;AC5IA,SAAS,UAAA,CAAW,IAAY,IAAA,EAA+B;AAC7D,EAAA,IAAI,EAAA,CAAG,WAAW,CAAA,EAAG;AACnB,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,QAAA,EAAW,IAAI,CAAA,oBAAA,CAAsB,CAAA;AAAA,EACvD;AACA,EAAA,IAAIC,oBAAAA,CAAqB,GAAA,CAAI,EAAA,CAAG,CAAC,CAAE,CAAA,EAAG;AACpC,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,QAAA,EAAW,IAAI,CAAA,KAAA,EAAQ,EAAE,iCAAiC,EAAA,CAAG,CAAC,CAAC,CAAA,iBAAA,EAC7C,CAAC,GAAGA,oBAAoB,CAAA,CAAE,IAAA,CAAK,GAAG,CAAC,CAAA,CAAA;AAAA,KACvD;AAAA,EACF;AACA,EAAA,IAAIC,iBAAAA,CAAkB,GAAA,CAAI,EAAE,CAAA,EAAG;AAC7B,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,QAAA,EAAW,IAAI,CAAA,KAAA,EAAQ,EAAE,CAAA,oDAAA,EACX,CAAC,GAAGA,iBAAiB,CAAA,CAAE,IAAA,CAAK,IAAI,CAAC,CAAA,CAAA;AAAA,KACjD;AAAA,EACF;AACF;AAMO,SAAS,WACd,GAAA,EACgB;AAChB,EAAA,UAAA,CAAW,GAAA,CAAI,IAAI,MAAM,CAAA;AAEzB,EAAA,MAAM,gBAAgB,MAAkB;AACtC,IAAA,IAAI,GAAA,CAAI,MAAA,IAAU,IAAA,EAAM,OAAO,EAAA;AAC/B,IAAA,OAAO,OAAO,GAAA,CAAI,MAAA,KAAW,aAAa,GAAA,CAAI,MAAA,KAAW,GAAA,CAAI,MAAA;AAAA,EAC/D,CAAA;AAEA,EAAA,MAAM,KAAA,GAAQ,IAAI,OAAA,GACd,eAAA,CAAgB,IAAI,EAAA,EAAI,GAAA,CAAI,cAAc,KAAA,IAAS,GAAA,CAAI,IAAI,GAAA,CAAI,OAAO,IACtE,EAAE,OAAA,EAAS,EAAC,EAAG,QAAA,EAAU,EAAC,EAAE;AAChC,EAAA,MAAM,OAAA,GAAU,KAAA,CAAM,OAAA,CAAQ,MAAA,GAAS,IAAI,CAAC,GAAI,GAAA,CAAI,OAAA,IAAW,EAAC,EAAI,GAAG,KAAA,CAAM,OAAO,IAAI,GAAA,CAAI,OAAA;AAC5F,EAAA,MAAM,QAAA,GAAW,KAAA,CAAM,QAAA,CAAS,MAAA,GAAS,IAAI,CAAC,GAAI,GAAA,CAAI,QAAA,IAAY,EAAC,EAAI,GAAG,KAAA,CAAM,QAAQ,IAAI,GAAA,CAAI,QAAA;AAEhG,EAAA,OAAO;AAAA,IACL,IAAI,GAAA,CAAI,EAAA;AAAA,IACR,WAAA,EAAa;AAAA,MACX,KAAA,EAAO,IAAA;AAAA,MACP,cAAc,GAAA,CAAI,YAAA;AAAA,MAClB,GAAI,IAAI,MAAA,GAAS,EAAE,SAAS,GAAA,CAAI,MAAA,KAAW;AAAC,KAC9C;AAAA,IACA,OAAA;AAAA,IACA,GAAI,IAAI,OAAA,GAAU,EAAE,SAAS,GAAA,CAAI,OAAA,KAAY,EAAC;AAAA,IAC9C,GAAI,IAAI,KAAA,GAAQ,EAAE,OAAO,GAAA,CAAI,KAAA,KAAU,EAAC;AAAA,IACxC,OAAO,GAAA,CAAI,KAAA;AAAA,IACX,GAAA;AAAA,IACA,cAAc,GAAA,CAAI,YAAA;AAAA,IAClB,YAAY,GAAA,CAAI,UAAA;AAAA,IAChB,YAAY,GAAA,CAAI,UAAA;AAAA,IAChB,cAAc,GAAA,CAAI,YAAA;AAAA,IAClB,MAAA,EAAQ,aAAA;AAAA,IACR,QAAA;AAAA,IACA,SAAS,GAAA,CAAI,OAAA;AAAA,IACb,iBAAiB,GAAA,CAAI;AAAA,GACvB;AACF;;;ACvDO,SAAS,OAAA,CAA4B,IAAY,OAAA,EAAkD;AACxG,EAAA,OAAO,EAAE,IAAI,OAAA,EAAQ;AACvB;AAGO,SAAS,UAA8B,KAAA,EAA8C;AAC1F,EAAA,OAAO,OAAO,KAAA,KAAU,QAAA;AAC1B;AAGO,SAAS,UAA8B,OAAA,EAA2C;AACvF,EAAA,MAAM,MAAa,EAAC;AACpB,EAAA,MAAM,IAAA,uBAAW,GAAA,EAAY;AAC7B,EAAA,MAAM,IAAA,GAAO,CAAC,IAAA,KAA0C;AACtD,IAAA,KAAA,MAAW,SAAS,IAAA,EAAM;AACxB,MAAA,IAAI,SAAA,CAAU,KAAK,CAAA,EAAG,IAAA,CAAK,MAAM,OAAO,CAAA;AAAA,WAAA,IAC/B,CAAC,IAAA,CAAK,GAAA,CAAI,KAAK,CAAA,EAAG;AACzB,QAAA,IAAA,CAAK,IAAI,KAAK,CAAA;AACd,QAAA,GAAA,CAAI,KAAK,KAAK,CAAA;AAAA,MAChB;AAAA,IACF;AAAA,EACF,CAAA;AACA,EAAA,IAAA,CAAK,OAAO,CAAA;AACZ,EAAA,OAAO,GAAA;AACT;AAGO,SAAS,YAAA,CAAiC,QAAsB,IAAA,EAA+C;AACpH,EAAA,MAAM,IAAA,GAAO,IAAI,GAAA,CAAY,SAAA,CAAU,IAAI,CAAC,CAAA;AAC5C,EAAA,OAAO,EAAE,IAAI,CAAA,EAAG,GAAA,CAAI,EAAE,CAAA,QAAA,CAAA,EAAY,OAAA,EAAS,UAAU,CAAC,GAAG,CAAC,CAAA,CAAE,MAAA,CAAO,CAAC,EAAA,KAAO,CAAC,KAAK,GAAA,CAAI,EAAE,CAAC,CAAA,EAAE;AAC5F;AAGO,SAAS,UAAA,CAA+B,KAAmB,EAAA,EAAqB;AACrF,EAAA,OAAQ,UAAU,CAAC,GAAG,CAAC,CAAA,CAAe,SAAS,EAAE,CAAA;AACnD;;;AC9BA,IAAM,QAAQ,CAAC,IAAA,EAAc,MAA0C,GAAA,KACrE,CAAC,GAAG,IAAI,CAAA,CAAE,GAAA,CAAI,CAACF,UAAS,EAAE,GAAA,EAAAA,MAAK,GAAG,IAAA,EAAM,KAAI,CAAE,CAAA;AAGzC,IAAM,uBAAA,GAAoD;AAAA,EAC/D,GAAG,KAAA,CAAM,WAAA,EAAa,EAAE,GAAA,EAAK,IAAA,IAAQ,gFAAgF,CAAA;AAAA,EACrH,GAAG,MAAM,QAAA,EAAU,EAAE,KAAK,IAAA,EAAM,KAAA,EAAO,IAAA,EAAK,EAAG,+EAA+E,CAAA;AAAA,EAC9H,GAAG,MAAM,MAAA,EAAQ,EAAE,KAAK,IAAA,EAAM,KAAA,EAAO,IAAA,EAAK,EAAG,uFAAuF,CAAA;AAAA,EACpI,GAAG,MAAM,iBAAA,EAAmB,EAAE,KAAK,IAAA,EAAM,GAAA,EAAK,IAAA,EAAK,EAAG,6JAA6J,CAAA;AAAA,EACnN,GAAG,KAAA,CAAM,UAAA,EAAY,EAAE,GAAA,EAAK,IAAA,IAAQ,wDAAwD,CAAA;AAAA,EAC5F,GAAG,MAAM,KAAA,EAAO,EAAE,KAAK,IAAA,EAAM,KAAA,EAAO,IAAA,EAAK,EAAG,oDAAoD;AAClG;AAEA,IAAM,QAAQ,CAAC,CAAA,KAAA,CAA6C,OAAO,CAAA,KAAM,QAAA,GAAW,CAAC,CAAC,CAAA,GAAI,CAAC,GAAG,CAAC,CAAA,EAAG,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,aAAa,CAAA;AAI5H,IAAM,SAAS,CAAC,MAAA,EAA0C,SACxD,MAAA,KAAW,UAAA,IAAe,WAAW,IAAA,KAAU,IAAA;AAG1C,SAAS,qBAAqB,IAAA,EAAqC;AACxE,EAAA,MAAM,IAAA,GAAO,KAAA,CAAM,IAAA,CAAK,GAAG,CAAA;AAC3B,EAAA,MAAM,CAAA,GAAI,IAAA,CAAK,IAAA,IAAQ,EAAC;AACxB,EAAA,MAAM,GAAA,GAAM,CAAA,CAAE,GAAA,KAAQ,CAAA,CAAE,IAAA,KAAS,IAAA,IAAQ,CAAA,CAAE,IAAA,KAAS,IAAA,GAAO,IAAA,GAAO,CAAA,CAAE,IAAA,IAAQ,CAAA,CAAE,IAAA,CAAA;AAC9E,EAAA,KAAA,MAAW,KAAK,uBAAA,EAAyB;AACvC,IAAA,IAAI,CAAC,IAAA,CAAK,QAAA,CAAS,CAAA,CAAE,GAAG,CAAA,EAAG;AAC3B,IAAA,IAAI,MAAA,CAAO,KAAK,CAAA,CAAE,GAAA,KAAQ,IAAI,CAAA,IAAK,MAAA,CAAO,EAAE,GAAA,EAAK,CAAA,CAAE,QAAQ,IAAI,CAAA,IAAK,OAAO,CAAA,CAAE,KAAA,EAAO,EAAE,KAAA,KAAU,IAAI,GAAG,OAAO,CAAA;AAAA,EAChH;AACA,EAAA,OAAO,IAAA;AACT;;;ACnBO,SAAS,WAAc,IAAA,EAA6B;AACzD,EAAA,OAAO,EAAE,IAAA,EAAK;AAChB;AAIO,SAAS,UAAA,CACd,OACAA,IAAAA,EACe;AACf,EAAA,OAAO,KAAA,CAAMA,KAAI,IAAI,CAAA;AACvB;AAGO,SAAS,UAAA,CACd,KAAA,EACAA,IAAAA,EACA,KAAA,EACM;AACN,EAAA,KAAA,CAAMA,IAAAA,CAAI,IAAI,CAAA,GAAI,KAAA;AACpB;AAIO,SAAS,aAAA,CACd,OACAA,IAAAA,EACS;AACT,EAAA,IAAI,OAAO,SAAA,CAAU,cAAA,CAAe,KAAK,KAAA,EAAOA,IAAAA,CAAI,IAAI,CAAA,EAAG;AACzD,IAAA,OAAO,KAAA,CAAMA,KAAI,IAAI,CAAA;AACrB,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,OAAO,KAAA;AACT","file":"index.js","sourcesContent":["/**\n * Finding actions by tag: gathering the ones that carry it, and a person's\n * search matching it as it matches a label.\n */\nimport { hasTag, matchQuery, type QueryMatch } from '@weasel-js/registry';\nimport type { Action } from './action';\nimport { actionItems, actionItemTitle, type ActionItem } from './actionItems';\n\n/** The actions carrying `tag`, themselves or on any variant, in\n * the order given. Drags included, which have no entries to show. */\nexport function actionsTagged(actions: readonly Action[], tag: string): Action[] {\n return actions.filter((a) => hasTag(a.tags, tag) || (a.variants?.some((v) => hasTag(v.tags, tag)) ?? false));\n}\n\n/** The entries carrying `tag`: what a bar or a menu built from\n * a tag shows. A variant that does not carry it is left out. */\nexport function taggedActionItems(actions: readonly Action[], tag: string): ActionItem[] {\n return actionsTagged(actions, tag).flatMap(actionItems).filter((i) => hasTag(i.tags, tag));\n}\n\n/** Whether `item` answers a search for `query`, by its palette title or\n * by a tag, and which. */\nexport function matchActionItem(item: ActionItem, query: string): QueryMatch | null {\n return matchQuery(query, { text: [actionItemTitle(item)], tags: item.tags });\n}\n","/**\n * An action as a hold: bound to a held key, the press shows what it would do\n * through its `preview`, the release runs it, and a cancel — Escape, through\n * the kit's cancel-gesture action — takes the preview down and runs nothing.\n */\nimport type { Action } from './action';\nimport { resolveParams, type OngoingHandle } from './invoker';\n\n/** The id {@link holdPreview} gives the hold of action `id`. */\nexport const holdPreviewId = (id: string): string => `${id}.hold`;\n\n/**\n * `action` as a hold, under {@link holdPreviewId}. Bind it to a `held(…)` key,\n * in a keymap or anywhere else; the binding's params reach both the preview\n * and the run. It is enabled, eligible and requires what `action` does, so it\n * is skipped wherever `action` would be. An action with no `preview` shows\n * nothing and still runs on release; one whose invoker is not immediate is\n * not run.\n */\nexport function holdPreview(action: Action): Action {\n const { invoker } = action;\n return {\n id: holdPreviewId(action.id),\n label: action.label,\n ...(action.requires ? { requires: action.requires } : {}),\n ...(action.enabled ? { enabled: action.enabled } : {}),\n ...(action.eligible ? { eligible: action.eligible } : {}),\n invoker: {\n timing: 'ongoing',\n start: (ctx, opts): OngoingHandle => {\n const params = resolveParams(opts?.params);\n const hide = action.preview?.(ctx.deps, params);\n return {\n // An end's ctx carries no deps, so the run takes the press's.\n onEnd: (_end, reason) => {\n hide?.();\n if (reason === 'commit' && invoker?.timing === 'immediate') invoker.run(ctx.deps, params);\n },\n };\n },\n },\n };\n}\n","/** The chrome an in-flight gesture paints beside the scene. */\nimport type { OngoingHandle } from './invoker';\n\n/**\n * What a `polyline` overlay is, in a word — the narrowest thing an action can\n * say about how its run should look without naming a paint.\n *\n * The named roles are the kit's; a painter maps each to a style and falls back\n * to plain chrome for one it does not know, so a package outside core can coin\n * its own and still be drawn.\n */\nexport type OverlayRole =\n /** Generic in-flight chrome — the marquee/lasso paint. */\n | 'chrome'\n /** A cut the gesture would make. */\n | 'cut'\n /** An edge the gesture would author between two points. */\n | 'connector'\n /** The stretch of a path a soft-selection drag reaches. */\n | 'falloff'\n /** What a lock holds a dragged point to — a line, a circle. */\n | 'lock'\n /** What a dragged item would be dropped on: the box it would go into. */\n | 'target'\n /** Where a dragged item would land: a reorder's insertion bar. */\n | 'insert'\n /** Where a dragged item is over and cannot land. */\n | 'refused'\n | (string & {});\n\n/**\n * What an in-flight gesture proposes to paint *beside* the scene, returned by\n * `OngoingHandle.overlay()` — a marquee rect, a lasso trail, the outline of a\n * shape being dragged out, the line a slice would cut along.\n *\n * Every variant is world geometry and nothing else — no `DrawCommand`, no\n * color, no coordinate space to choose — so a surface rendering the same\n * gesture some other way can still read it. The painter owns every style\n * decision.\n */\nexport type OngoingOverlay =\n | {\n kind: 'marquee';\n start: { x: number; y: number };\n current: { x: number; y: number };\n shiftHeld: boolean;\n }\n | {\n kind: 'lasso';\n vertices: ReadonlyArray<{ x: number; y: number }>;\n current: { x: number; y: number };\n shiftHeld: boolean;\n }\n | {\n /**\n * An open run of world points the gesture is proposing — a cut line, a\n * routed connector. `role` is the whole of what an action says about\n * appearance.\n */\n kind: 'polyline';\n /** At least two points. Anything shorter is dropped in resolution. */\n points: ReadonlyArray<{ x: number; y: number }>;\n /** What the run means. Omitted reads as {@link OverlayRole} `'chrome'`. */\n role?: OverlayRole;\n }\n | {\n /**\n * A round brush dragged through world points: the area it has swept so\n * far, and its footprint at the last point. The radius is in screen\n * pixels, so the footprint keeps its size at every zoom.\n */\n kind: 'brush';\n /** The brush's path so far, at least one point; the last is where it is now. */\n points: ReadonlyArray<{ x: number; y: number }>;\n radiusPx: number;\n }\n | {\n /**\n * Live insert-drag preview. Pre-commit there is no scene node to ghost\n * via `previewIds()`/`previewPose()`, so insert paints its preview\n * through the overlay instead.\n *\n * `bounds` is the AABB of the current drag (start/current normalized).\n * `extras` is the per-kind extras the action already collected; the\n * overlay renderer narrows on `shape` and casts the field shape it\n * expects.\n */\n kind: 'insertPreview';\n /** Which preview the dispatcher's overlay draws. The kit's own shape\n * kinds are the ones it knows how to render; a consumer-defined kind\n * is legal and simply gets no live preview. */\n shape: string;\n bounds: { x: number; y: number; width: number; height: number };\n extras: unknown;\n /** World-space point to paint a small \"anchor\" dot at, marking the\n * click point — for radial shapes (polygon/star), where no vertex\n * sits on it, and for any shape in center mode. */\n anchorPoint?: { x: number; y: number };\n /** World affines the shape will also be drawn under once it lands, by\n * the container it is drawn into: the preview is painted under each. */\n copies?: readonly (readonly [number, number, number, number, number, number])[];\n }\n | {\n /**\n * Why the gesture cannot land where it is, in words for the user: a\n * refusal's reason. A surface shows `text` beside the pointer, which\n * `at` is, in world coordinates.\n */\n kind: 'reason';\n at: { x: number; y: number };\n text: string;\n };\n\n/** A handle's overlays as a list: empty when it has none. */\nexport function overlaysOf(handle: OngoingHandle): readonly OngoingOverlay[] {\n const ov = handle.overlay?.();\n if (!ov) return [];\n return isOverlayList(ov) ? ov : [ov];\n}\n\nfunction isOverlayList(ov: OngoingOverlay | readonly OngoingOverlay[]): ov is readonly OngoingOverlay[] {\n return Array.isArray(ov);\n}\n","/**\n * Named predicates for `defaultBinding.target.kindOf`. Each matches the\n * `TargetPredicate` shape, declaring whether it reads the hit,\n * so they drop into action descriptors without a wrapper:\n *\n * target: { kindOf: isAnchor }\n *\n * Single source of truth for \"what does this affordance kind mean\" — adding\n * a new predicate here is what enables every action that needs the same\n * shape to read it. Drift prevention.\n */\nimport { bodyPredicate, hitPredicate, type TargetPredicate } from '@weasel-js/gestures';\n\n// ─── Body-class predicates (read the second arg) ───────────────────────\n\n/** A predicate that resolves from `bodyTarget` alone. */\nexport type BodyPredicate = TargetPredicate & { readsAffordance: false };\n\n/** Matches any body hit — selected or unselected node body. */\nexport const isBody: BodyPredicate = bodyPredicate((bodyTarget) =>\n bodyTarget === 'selected-body' || bodyTarget === 'unselected-body');\n\n/** Body hit specifically already in the selection. */\nexport const isSelectedBody: BodyPredicate = bodyPredicate((bodyTarget) =>\n bodyTarget === 'selected-body');\n\n/** Body hit specifically NOT in the selection. */\nexport const isUnselectedBody: BodyPredicate = bodyPredicate((bodyTarget) =>\n bodyTarget === 'unselected-body');\n\n/** Empty-canvas hit — no node beneath cursor. */\nexport const isEmpty: BodyPredicate = bodyPredicate((bodyTarget) =>\n bodyTarget === 'empty');\n\n// ─── Affordance-kind predicates (read the first arg) ───────────────────\n\nfunction kindOf(target: unknown): string | undefined {\n if (typeof target !== 'object' || target === null) return undefined;\n const k = (target as { kind?: unknown }).kind;\n return typeof k === 'string' ? k : undefined;\n}\n\n/** Any resize handle: a corner (`handle:top-left`, …) or an edge (`handle:top`, …). */\nexport const isResizeHandle = hitPredicate((target) => {\n const k = kindOf(target);\n return k !== undefined && k.startsWith('handle:');\n});\n\n/** The rotate-around-center handle above the bounding box. */\nexport const isRotateHandle = hitPredicate((target) =>\n kindOf(target) === 'rotate-handle');\n\n/** Any path anchor (the on-curve dot). */\nexport const isAnchor = hitPredicate((target) => {\n const k = kindOf(target);\n return k !== undefined && /^anchor:\\d+$/.test(k);\n});\n\n/** Either control handle (controlIn or controlOut). */\nexport const isControlHandle = hitPredicate((target) => {\n const k = kindOf(target);\n return k !== undefined && /^(controlIn|controlOut):\\d+$/.test(k);\n});\n\n/** A corner-shape widget, set inside a corner anchor of the edited path. */\nexport const isCornerWidget = hitPredicate((target) => {\n const k = kindOf(target);\n return k !== undefined && /^corner:\\d+$/.test(k);\n});\n\n/** Any of the three anchor-editing affordances (anchor + both controls). */\nexport const isAnchorOrControl = hitPredicate((target) =>\n isAnchor(target) || isControlHandle(target));\n\n/** The outline of the path being edited, between its anchors. */\nexport const isSegment = hitPredicate((target) => kindOf(target) === 'segment');\n\n/** The grip midway along a curved segment's balance line, `balance:N`, where\n * N is the flat index of the anchor the segment starts at. */\nexport const isBalanceGrip = hitPredicate((target) => {\n const k = kindOf(target);\n return k !== undefined && /^balance:\\d+$/.test(k);\n});\n\n/** Anything path edit puts on the path: an anchor, a control, a segment, a\n * segment's balance grip, or a corner widget. */\nexport const isPathEditPart = hitPredicate((target) =>\n isAnchorOrControl(target) || isSegment(target) || isBalanceGrip(target) || isCornerWidget(target));\n","import type { Contribution } from './types';\n\n/**\n * Concatenate contribution bundles into one registry, preserving order —\n * entry order decides which of two same-specificity bindings in one scope\n * tier wins, so it is part of the result, not an accident of it.\n *\n * Throws on a duplicate id or dep name rather than dropping one: a feature\n * silently losing its bindings, or reading another feature's dep, is the\n * failure this registry exists to make loud.\n */\nexport function mergeContributions<T extends Contribution<unknown>>(\n ...bundles: readonly (readonly T[])[]\n): T[] {\n const out: T[] = [];\n const seen = new Set<string>();\n const depOwner = new Map<string, string>();\n for (const bundle of bundles) {\n for (const entry of bundle) {\n if (seen.has(entry.id)) {\n throw new Error(\n `mergeContributions: duplicate contribution id \"${entry.id}\". `\n + `Two bundles registered the same id; rename one or merge them by hand.`,\n );\n }\n seen.add(entry.id);\n for (const dep of Object.keys(entry.deps ?? {})) {\n const owner = depOwner.get(dep);\n if (owner !== undefined) {\n throw new Error(\n `mergeContributions: dep \"${dep}\" is provided by both \"${owner}\" and \"${entry.id}\". `\n + `One registry answers each dep name; drop one source.`,\n );\n }\n depOwner.set(dep, entry.id);\n }\n out.push(entry);\n }\n }\n return out;\n}\n","import type { ActionDeps } from '../interactions/actions/invoker';\n\n/**\n * Make the active mode's default tool active when another tool holds the\n * slot, and say whether it did. A key that leaves a mode calls this first, so\n * one press returns to the mode's tool and the next leaves: the mode shortcuts'\n * `exit` and `cancel`, and core's `exitPathEdit`. Reads the `activeTool` and\n * `modeDefaultTool` deps, which the caller must require.\n */\nexport function returnToModeDefault(deps: ActionDeps | undefined): boolean {\n const target = deps?.modeDefaultTool?.() ?? null;\n const tools = deps?.activeTool;\n if (target === null || !tools || tools.active === target) return false;\n tools.setActive(target);\n return true;\n}\n","import { modeLabel, type ModeDefinition, type ModeRegistry } from '@weasel-js/modes';\nimport { key, type KeySpec } from '@weasel-js/gestures';\nimport { ActionDisabledReason, type Action } from '../interactions/actions/action';\nimport type { ActionDeps } from '../interactions/actions/invoker';\nimport { returnToModeDefault } from '../tools/returnToModeDefault';\nimport type { Rule } from '../eligibility';\nimport type { Contribution } from './types';\n\n/**\n * What each mode shortcut does. A role left out binds nothing, so its key\n * falls through to whatever else the dispatcher has on it.\n */\nexport interface ModeShortcutHandlers {\n /** Enter mode `id` — the `entry` shortcut. */\n enter?: (id: string) => void;\n /** Whether mode `id` can be entered now. A mode that needs a target it\n * doesn't have answers no, and its entry key falls through. Default yes. */\n canEnter?: (id: string) => boolean;\n /** Leave the active soft mode, keeping its session to resume. */\n exit?: () => void;\n /** Leave the active soft mode and throw its session away. */\n discard?: () => void;\n /** Commit the active strict mode's transaction. */\n commit?: () => void;\n /** Abandon the active strict mode's transaction. */\n cancel?: () => void;\n}\n\ntype Role = 'exit' | 'discard' | 'commit' | 'cancel';\nconst LEAVING: readonly Role[] = ['exit', 'discard', 'commit', 'cancel'];\nconst VERB: Record<Role | 'entry', string> = {\n entry: 'Enter', exit: 'Exit', discard: 'Discard', commit: 'Commit', cancel: 'Cancel',\n};\n\n/**\n * A `ModeDefinition` shortcut chord — `'Escape'`, `'Meta+T'` — as a key spec.\n * Modifier names are case-insensitive; the last segment is the key.\n */\nexport function modeShortcutSpec(shortcut: string): KeySpec {\n return key(shortcut);\n}\n\n/**\n * The registry's declared mode shortcuts as an always-on contribution: one\n * action per shortcut, bound to its chord and gated on the mode it acts on —\n * `exit` / `discard` / `commit` / `cancel` while that mode is active, `entry`\n * while it is not. Install it with `<SceneCanvas ambient>`.\n *\n * An entry key one mode shares with another mode's leaving key is reported as\n * a route conflict unless `canEnter` is given: that is what keeps the entry\n * key from firing inside the other mode.\n *\n * The bindings ride the hotkey tier, so leaving a mode outranks what the same\n * key does otherwise (Escape clearing the selection), and they yield while a\n * gesture is in flight, so Escape mid-drag still cancels the drag first. Keys\n * typed into an editable element never reach them. A mode's `exit` and\n * `cancel`, pressed while a tool other than its `defaultTool` is active,\n * return to that tool instead (`returnToModeDefault`), so the next press leaves.\n */\nexport function modeShortcuts(\n registry: ModeRegistry,\n handlers: ModeShortcutHandlers,\n): Contribution<never> {\n const actions: Action[] = [];\n for (const mode of registry.list()) {\n const entry = mode.entry?.shortcut;\n const enter = handlers.enter;\n if (entry && enter) {\n // Without `canEnter` an entry key is live in every other mode, so it does not yield there.\n actions.push(shortcutAction(mode, 'entry', entry, { mode: { not: mode.id } },\n () => registry.current().id !== mode.id && (handlers.canEnter?.(mode.id) ?? true),\n () => enter(mode.id), handlers.canEnter !== undefined));\n }\n for (const role of LEAVING) {\n const shortcut = mode[role]?.shortcut;\n const run = handlers[role];\n if (!shortcut || !run) continue;\n const backsOut = role === 'exit' || role === 'cancel';\n actions.push(shortcutAction(mode, role, shortcut, { mode: mode.id },\n () => registry.current().id === mode.id,\n backsOut ? (deps) => { if (!returnToModeDefault(deps)) run(); } : run, true));\n }\n }\n return { id: 'modes.shortcuts', eligibility: { always: true }, actions };\n}\n\nfunction shortcutAction(\n mode: ModeDefinition,\n role: Role | 'entry',\n shortcut: string,\n eligible: Rule,\n live: () => boolean,\n run: (deps: ActionDeps) => void,\n yields: boolean,\n): Action {\n return {\n id: `mode.${mode.id}.${role}`,\n label: `${VERB[role]} ${modeLabel(mode)}`,\n scope: 'hotkey',\n defaultBinding: [{\n spec: { ...modeShortcutSpec(shortcut), phase: [{ channel: '*', phase: 'initial' }] },\n opts: { id: `mode.${mode.id}.${role}.key`, yields },\n }],\n eligible,\n requires: ['activeTool', 'modeDefaultTool'],\n // `eligible` is the gate the dispatcher and palettes read, but a canvas\n // with no `modes` evaluates none; without this the key is\n // swallowed in every mode.\n enabled: () => (live() ? true : ActionDisabledReason.NotApplicable),\n invoker: { timing: 'immediate', run: (deps) => run(deps) },\n };\n}\n","import type {\n ClickSpec, ContextMenuSpec, DoubleClickSpec, DragSpec, EventModifiers, KeyHeldSpec, KeySpec, ModSpec,\n} from '@weasel-js/gestures';\n\n/** A spec kind a binding editor can capture. */\nexport type CaptureKind = 'key' | 'key-held' | 'click' | 'doubleClick' | 'drag' | 'contextMenu';\n\n/** What `captureGesture` resolves to. */\nexport type CapturedSpec = KeySpec | KeyHeldSpec | ClickSpec | DoubleClickSpec | DragSpec | ContextMenuSpec;\n\n/** An event's modifiers as a spec's, with the platform's primary one as `mod`. */\nfunction modSpecOf(e: EventModifiers, apple: boolean): ModSpec | undefined {\n const mods: ModSpec = {};\n if (apple ? e.metaKey : e.ctrlKey) mods.mod = true;\n if (e.shiftKey) mods.shift = true;\n if (e.altKey) mods.alt = true;\n if (apple ? e.ctrlKey : e.metaKey) mods[apple ? 'ctrl' : 'meta'] = true;\n return Object.keys(mods).length > 0 ? mods : undefined;\n}\n\nexport function specOf<K extends CapturedSpec['kind']>(kind: K, e: EventModifiers, apple: boolean): { kind: K; mods?: ModSpec } {\n const mods = modSpecOf(e, apple);\n return mods ? { kind, mods } : { kind };\n}\n\n/** Keep an event from the page. */\nexport const take = (e: Event): void => { e.preventDefault(); e.stopPropagation(); };\n","import {\n createPointerRecognizer, DOUBLE_CLICK_MAX_MS,\n type EventModifiers, type InputEvent, type PointerSample, type RecognizerClock,\n} from '@weasel-js/gestures';\nimport { specOf, take, type CaptureKind, type CapturedSpec } from './captureSpec';\n\n/** The click-and-drag thresholds a capture reads, each defaulting to its constant. */\nexport interface CaptureThresholds {\n dragPx?: number;\n doubleClickMs?: number;\n doubleClickPx?: number;\n}\n\n/** What a browser follows a press with; taken too, or the page acts on a gesture already captured. */\nexport const TRAILING = ['click', 'auxclick', 'dblclick', 'contextmenu'] as const;\n\nconst sampleOf = (e: PointerEvent): PointerSample => ({\n pointerId: e.pointerId, clientX: e.clientX, clientY: e.clientY, target: e.target, timeStamp: e.timeStamp,\n altKey: e.altKey, ctrlKey: e.ctrlKey, metaKey: e.metaKey, shiftKey: e.shiftKey,\n});\n\nconst browserClock: RecognizerClock = {\n now: () => performance.now(),\n setTimer: (fn, ms) => setTimeout(fn, ms),\n clearTimer: (t) => { clearTimeout(t as ReturnType<typeof setTimeout>); },\n};\n\n/**\n * Listen, through `listen`, for the next pointer gesture of `kinds` and hand\n * its spec to `done`. Returns what stops it. A press goes through the\n * dispatcher's recognizer, so a click and a drag part where they do on a canvas.\n */\nexport function capturePointer(\n target: EventTarget,\n kinds: ReadonlySet<CaptureKind>,\n apple: boolean,\n thresholds: CaptureThresholds,\n listen: (type: string, fn: (e: Event) => void) => void,\n done: (spec: CapturedSpec) => void,\n): () => void {\n let pendingClick: ReturnType<typeof setTimeout> | null = null;\n let dragMods: EventModifiers | null = null;\n\n const recognized = (ev: InputEvent): 'handled' | 'unhandled' => {\n switch (ev.kind) {\n case 'pointerdown':\n // Without `stage` it is the press held back until it crossed the drag threshold.\n if (!('stage' in ev && ev.stage === 'press')) dragMods = ev;\n return 'unhandled';\n case 'click': {\n if (!kinds.has('click')) return 'unhandled';\n const spec = specOf('click', ev, apple);\n if (!kinds.has('doubleClick')) { done(spec); return 'handled'; }\n if (pendingClick) clearTimeout(pendingClick);\n pendingClick = setTimeout(() => { done(spec); }, thresholds.doubleClickMs ?? DOUBLE_CLICK_MAX_MS);\n return 'handled';\n }\n case 'doubleclick':\n case 'contextmenu': {\n const kind = ev.kind === 'doubleclick' ? 'doubleClick' : 'contextMenu';\n if (!kinds.has(kind)) return 'unhandled';\n done(specOf(kind, ev, apple));\n return 'handled';\n }\n default:\n return 'unhandled';\n }\n };\n\n const recognizer = createPointerRecognizer({\n clock: browserClock,\n dragPx: () => thresholds.dragPx,\n doubleClickMs: () => thresholds.doubleClickMs,\n doubleClickPx: () => thresholds.doubleClickPx,\n sink: { dispatch: recognized, multiTouchInFlight: () => false },\n });\n\n /** A pointer event for a press this capture holds, taken from the page; otherwise `null`. */\n const held = (e: Event): PointerEvent | null => {\n const p = e as PointerEvent;\n if (recognizer.positionOf(p.pointerId) === undefined) return null;\n take(p);\n return p;\n };\n\n listen('pointerdown', (e) => {\n const p = e as PointerEvent;\n take(p);\n // Only the primary button presses as the dispatcher sees it; a secondary\n // one reaches a binding as its `contextmenu`.\n if ((p.button ?? 0) !== 0) return;\n // An element hears a held pointer's moves and release only while it captures them.\n if (target instanceof Element) {\n try { target.setPointerCapture(p.pointerId); } catch { /* the pointer is already gone */ }\n }\n recognizer.press({ ...sampleOf(p), x: p.clientX, y: p.clientY, pointerType: p.pointerType });\n });\n listen('pointermove', (e) => {\n const p = held(e);\n if (p) recognizer.move(sampleOf(p));\n });\n listen('pointerup', (e) => {\n const p = held(e);\n if (!p) return;\n const drag = dragMods;\n dragMods = null;\n recognizer.release(sampleOf(p));\n if (drag && kinds.has('drag')) done(specOf('drag', drag, apple));\n });\n listen('pointercancel', (e) => {\n const p = held(e);\n if (!p) return;\n dragMods = null;\n recognizer.cancel(p.pointerId);\n });\n for (const type of TRAILING) {\n listen(type, (e) => {\n take(e);\n if (type === 'contextmenu' && kinds.has('contextMenu')) done(specOf('contextMenu', e as MouseEvent, apple));\n });\n }\n\n return () => {\n if (pendingClick) clearTimeout(pendingClick);\n recognizer.reset();\n };\n}\n","import { isApplePlatform } from '@weasel-js/gestures';\nimport { capturePointer, TRAILING, type CaptureThresholds } from './capturePointer';\nimport { specOf, take, type CaptureKind, type CapturedSpec } from './captureSpec';\n\nexport type { CaptureKind, CapturedSpec } from './captureSpec';\n\n/** Options for {@link captureGesture}. */\nexport interface CaptureGestureOptions extends CaptureThresholds {\n /** The kinds to take; input of any other kind is waited past. A keystroke\n * is taken as `key` when both `key` and `key-held` are listed. Defaults to\n * `key`, `click`, `doubleClick`, `drag` and `contextMenu`. */\n kinds?: readonly CaptureKind[];\n /** Stop listening and resolve `null`. */\n signal?: AbortSignal;\n /** Whether Cmd is Mod. Defaults to the detected platform. */\n apple?: boolean;\n /** Travel that makes a press a drag, in CSS px: pass the `gestures.dragPx`\n * kit setting. Defaults to `DRAG_THRESHOLD_PX`. */\n dragPx?: number;\n /** The `gestures.doubleClickMs` kit setting. Defaults to `DOUBLE_CLICK_MAX_MS`. */\n doubleClickMs?: number;\n /** The `gestures.doubleClickPx` kit setting. Defaults to `DOUBLE_CLICK_MAX_PX`. */\n doubleClickPx?: number;\n}\n\nconst DEFAULT_KINDS: readonly CaptureKind[] = ['key', 'click', 'doubleClick', 'drag', 'contextMenu'];\nconst POINTER_KINDS: readonly CaptureKind[] = ['click', 'doubleClick', 'drag', 'contextMenu'];\nconst MODIFIER_KEYS: ReadonlySet<string> = new Set(['Shift', 'Control', 'Alt', 'Meta', 'AltGraph', 'CapsLock']);\n\n/**\n * The next input on `target` of one of `opts.kinds`, as a gesture spec, for a\n * binding editor: its modifiers with the platform's primary one as `mod`. A\n * press is told a click or a drag by the dispatcher's own recognizer, at its\n * drag threshold; a click is held back for a double click only when both are\n * asked for. A bare modifier key is waited past. Escape, or an abort, resolves\n * `null`. What it takes is `preventDefault`ed and stopped, the click a browser\n * follows a press with included, so nothing else acts on it. The pointer is\n * left alone when no pointer kind is asked for, and keys other than Escape\n * when no key kind is.\n */\nexport function captureGesture(target: EventTarget, opts: CaptureGestureOptions = {}): Promise<CapturedSpec | null> {\n const apple = opts.apple ?? isApplePlatform();\n const kinds = new Set(opts.kinds ?? DEFAULT_KINDS);\n const keyKind = kinds.has('key') ? 'key' : kinds.has('key-held') ? 'key-held' : null;\n const pointer = POINTER_KINDS.some((k) => kinds.has(k));\n\n return new Promise((resolve) => {\n if (opts.signal?.aborted) { resolve(null); return; }\n let settled = false;\n let stopPointer = (): void => {};\n const listeners: [string, (e: Event) => void][] = [];\n const listen = (type: string, fn: (e: Event) => void): void => {\n listeners.push([type, fn]);\n target.addEventListener(type, fn, true);\n };\n\n const done = (spec: CapturedSpec | null): void => {\n if (settled) return;\n settled = true;\n stopPointer();\n opts.signal?.removeEventListener('abort', onAbort);\n for (const [type, fn] of listeners) target.removeEventListener(type, fn, true);\n // The click and dblclick a release goes on to fire arrive in the same task.\n if (pointer) {\n for (const type of TRAILING) target.addEventListener(type, take, true);\n setTimeout(() => { for (const type of TRAILING) target.removeEventListener(type, take, true); }, 0);\n }\n resolve(spec);\n };\n const onAbort = (): void => { done(null); };\n\n opts.signal?.addEventListener('abort', onAbort);\n listen('keydown', (e) => {\n const k = e as KeyboardEvent;\n if (MODIFIER_KEYS.has(k.key)) return;\n const escape = k.key === 'Escape' && !k.metaKey && !k.ctrlKey && !k.altKey && !k.shiftKey;\n if (!escape && !keyKind) return;\n take(k);\n done(escape || !keyKind ? null : { ...specOf(keyKind, k, apple), key: k.key });\n });\n if (pointer) stopPointer = capturePointer(target, kinds, apple, opts, listen, done);\n });\n}\n","import type { KeyHeldSpec, KeySpec } from '@weasel-js/gestures';\nimport { captureGesture } from './captureGesture';\n\n/** Options for {@link captureKey}. */\nexport interface CaptureKeyOptions {\n /** Capture the held form, `key-held`, rather than the keystroke. */\n held?: boolean;\n /** Stop listening and resolve `null`. */\n signal?: AbortSignal;\n /** Whether Cmd is Mod. Defaults to the detected platform. */\n apple?: boolean;\n}\n\n/**\n * The next keystroke on `target` as a key spec: {@link captureGesture} taking\n * a keystroke alone, and leaving the pointer to the page. A bare modifier is\n * waited past. Write the result with `keySpecRoute` to persist it as a binding\n * override.\n */\nexport function captureKey(target: EventTarget, opts: CaptureKeyOptions = {}): Promise<KeySpec | KeyHeldSpec | null> {\n return captureGesture(target, {\n kinds: [opts.held ? 'key-held' : 'key'],\n ...(opts.signal ? { signal: opts.signal } : {}),\n ...(opts.apple !== undefined ? { apple: opts.apple } : {}),\n }) as Promise<KeySpec | KeyHeldSpec | null>;\n}\n","/**\n * Tool options: the settings a tool's user adjusts while it is active, such as\n * a brush's size and strength. A tool declares them as a prefs group whose\n * number leaves are params of the action it binds; the host holds their values\n * (`toolOptionValues` dep) and `<SceneCanvas>` tunes the action from them. A tool\n * whose options name a size or a strength also gets step actions for them,\n * bound to `[` `]` and `Shift+[` `Shift+]` while it is the active tool.\n */\nimport type { PrefGroup, PrefNumber } from '@weasel-js/prefs';\nimport type { KeySpec } from '@weasel-js/gestures';\nimport { ActionDisabledReason, type Action } from '../interactions/actions/action';\nimport type { ActionDeps, ImmediateInvoker } from '../interactions/actions/invoker';\nimport type { GestureBinding } from '../interactions/actions/binding';\n\n/** How a step action moves one option: by a factor, or by an amount. */\nexport interface ToolOptionStep {\n /** The option's key in `prefs`. */\n option: string;\n /** Each step multiplies (or divides) the value by this. */\n times?: number;\n /** Each step adds (or takes away) this. Used when `times` is absent. */\n plus?: number;\n}\n\n/** What a tool declares about its options. See {@link ToolDef.options}. */\nexport interface ToolOptions {\n /** The action the options are params of: each leaf of `prefs` is the param\n * of the same key. */\n actionId: string;\n /** The options, as number leaves keyed by param, with their bounds and\n * defaults. A host draws them from this (a group drawn `as: 'bar'` makes an\n * options row) and keeps their values in its prefs. */\n prefs: PrefGroup;\n /** The option `[` and `]` step: how large the tool acts. */\n size?: ToolOptionStep;\n /** The option `Shift+[` and `Shift+]` step: how hard it acts. */\n strength?: ToolOptionStep;\n}\n\n/** Where a host keeps tool options' values: the `toolOptionValues` dep. */\nexport interface ToolOptionValues {\n /** `toolId`'s values, sparse: an option missing from it reads its default.\n * The same object until one of them changes. */\n get(toolId: string): Readonly<Record<string, number>>;\n set(toolId: string, option: string, value: number): void;\n subscribe(listener: () => void): () => void;\n}\n\nconst NONE: Readonly<Record<string, number>> = Object.freeze({});\n\n/** A {@link ToolOptionValues} held in memory, for a host that keeps no prefs. */\nexport function createToolOptionValues(): ToolOptionValues {\n const values = new Map<string, Record<string, number>>();\n const listeners = new Set<() => void>();\n return {\n get: (toolId) => values.get(toolId) ?? NONE,\n set(toolId, option, value) {\n values.set(toolId, { ...values.get(toolId), [option]: value });\n for (const l of [...listeners]) l();\n },\n subscribe(listener) {\n listeners.add(listener);\n return () => { listeners.delete(listener); };\n },\n };\n}\n\nfunction leafOf(options: ToolOptions, option: string): PrefNumber | undefined {\n const leaf = options.prefs.children[option] as { kind?: string } | undefined;\n return leaf?.kind === 'number' ? (leaf as PrefNumber) : undefined;\n}\n\n/** Every option's value for `toolId`: what `values` holds, else its default. */\nexport function toolOptionParams(\n toolId: string, options: ToolOptions, values: ToolOptionValues | undefined,\n): 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)) {\n const leaf = leafOf(options, key);\n const v = held[key] ?? leaf?.default;\n if (typeof v === 'number') out[key] = v;\n }\n return out;\n}\n\n/** `value` moved one step up (`dir` 1) or down (-1), within the leaf's bounds\n * and rounded to its `step`. */\nexport function steppedOption(leaf: PrefNumber, value: number, step: ToolOptionStep, dir: 1 | -1): number {\n const moved = step.times !== undefined ? value * step.times ** dir : value + dir * (step.plus ?? leaf.step ?? 1);\n const snapped = leaf.step ? Math.round(moved / leaf.step) * leaf.step : moved;\n // A step that rounds back to where it began still moves one `step`.\n const next = snapped === value && leaf.step ? value + dir * leaf.step : snapped;\n const clamped = Math.min(leaf.max ?? Infinity, Math.max(leaf.min ?? -Infinity, next));\n return Number(clamped.toFixed(6));\n}\n\n/** The keys each step action is bound to while its tool is active. */\ntype StepName = 'grow' | 'shrink' | 'raise' | 'lower';\nconst STEP_KEYS: Record<StepName, KeySpec> = {\n grow: { kind: 'key', key: ']', code: 'BracketRight' },\n shrink: { kind: 'key', key: '[', code: 'BracketLeft' },\n raise: { kind: 'key', key: [']', '}'], code: 'BracketRight', mods: { shift: true } },\n lower: { kind: 'key', key: ['[', '{'], code: 'BracketLeft', mods: { shift: true } },\n};\n\ninterface StepSpec { name: StepName; which: 'size' | 'strength'; dir: 1 | -1; label: (tool: string, option: string) => string }\n\nconst STEPS: readonly StepSpec[] = [\n { name: 'grow', which: 'size', dir: 1, label: (t) => `Grow ${t}` },\n { name: 'shrink', which: 'size', dir: -1, label: (t) => `Shrink ${t}` },\n { name: 'raise', which: 'strength', dir: 1, label: (t, o) => `Raise ${t} ${o}` },\n { name: 'lower', which: 'strength', dir: -1, label: (t, o) => `Lower ${t} ${o}` },\n];\n\nfunction stepAction(toolId: string, toolLabel: string, options: ToolOptions, spec: StepSpec): Action | null {\n const step = options[spec.which];\n const leaf = step ? leafOf(options, step.option) : undefined;\n if (!step || !leaf) return null;\n return {\n id: `${toolId}.${spec.name}`,\n label: spec.label(toolLabel, leaf.name.toLowerCase()),\n group: 'tool',\n requires: ['activeTool', 'toolOptionValues'],\n invoker: {\n timing: 'immediate',\n run: (deps) => {\n const values = deps.toolOptionValues;\n if (!values) return;\n const current = toolOptionParams(toolId, options, values)[step.option] ?? leaf.default ?? 0;\n values.set(toolId, step.option, steppedOption(leaf, current, step, spec.dir));\n },\n } satisfies ImmediateInvoker,\n enabled: (deps?: ActionDeps) =>\n deps?.activeTool?.active === toolId && deps.toolOptionValues ? true : ActionDisabledReason.NotApplicable,\n };\n}\n\n/** The step actions for `toolId`'s size and strength options, and the key\n * bindings that reach them. */\nexport function toolOptionSteps(\n toolId: string, toolLabel: string, options: ToolOptions,\n): { actions: Action[]; bindings: GestureBinding[] } {\n const actions: Action[] = [];\n const bindings: GestureBinding[] = [];\n for (const spec of STEPS) {\n const action = stepAction(toolId, toolLabel, options, spec);\n if (!action) continue;\n actions.push(action);\n bindings.push({ spec: STEP_KEYS[spec.name], actionId: action.id, opts: { id: `${action.id}.key` } });\n }\n return { actions, bindings };\n}\n","// src/tools/defineTool.ts\nimport type { Tool } from './types';\nimport type { ToolDef } from './routeTypes';\nimport { RESERVED_ID_NAMES, RESERVED_ID_PREFIXES } from '@weasel-js/gestures';\nimport type { CursorSpec } from '@weasel-js/cursor';\nimport type { KernelOverlay } from '../index';\nimport { toolOptionSteps } from './toolOptions';\n\n/** Validate that `id` is usable as a tool / channel id in the route\n * grammar. Rejects ids that start with a reserved sigil (would shadow\n * future grammar extensions) and ids that collide with phase keywords\n * (would parse as the bare-phase shorthand). */\nfunction validateId(id: string, kind: 'tool' | 'action'): void {\n if (id.length === 0) {\n throw new Error(`weasel: ${kind} id may not be empty`);\n }\n if (RESERVED_ID_PREFIXES.has(id[0]!)) {\n throw new Error(\n `weasel: ${kind} id \"${id}\" starts with reserved sigil \"${id[0]}\" ` +\n `(reserved set: ${[...RESERVED_ID_PREFIXES].join(' ')})`,\n );\n }\n if (RESERVED_ID_NAMES.has(id)) {\n throw new Error(\n `weasel: ${kind} id \"${id}\" collides with a reserved phase keyword ` +\n `(reserved: ${[...RESERVED_ID_NAMES].join(', ')})`,\n );\n }\n}\n\n/**\n * Build a `Tool` from a declarative `ToolDef`: validates the id, applies the\n * `cursor` default, and keeps the authored form on `Tool.def` for reflection.\n */\nexport function defineTool<TOverlay = KernelOverlay>(\n def: ToolDef<TOverlay>,\n): Tool<TOverlay> {\n validateId(def.id, 'tool');\n\n const resolveCursor = (): CursorSpec => {\n if (def.cursor == null) return '';\n return typeof def.cursor === 'function' ? def.cursor() : def.cursor;\n };\n\n const steps = def.options\n ? toolOptionSteps(def.id, def.presentation?.label ?? def.id, def.options)\n : { actions: [], bindings: [] };\n const actions = steps.actions.length > 0 ? [...(def.actions ?? []), ...steps.actions] : def.actions;\n const bindings = steps.bindings.length > 0 ? [...(def.bindings ?? []), ...steps.bindings] : def.bindings;\n\n return {\n id: def.id,\n eligibility: {\n focus: true,\n capabilities: def.capabilities,\n ...(def.hotkey ? { offhand: def.hotkey } : {}),\n },\n actions,\n ...(def.options ? { options: def.options } : {}),\n ...(def.hides ? { hides: def.hides } : {}),\n menus: def.menus,\n def,\n presentation: def.presentation,\n keybinding: def.keybinding,\n onActivate: def.onActivate,\n onDeactivate: def.onDeactivate,\n cursor: resolveCursor,\n bindings,\n overlay: def.overlay,\n overlayPosition: def.overlayPosition,\n };\n}\n","/**\n * Tool sets: a named group of tool ids, the unit a consumer opts into whole.\n * A set names ids, never tools, because a tool is built by a hook that holds\n * its state; whatever mounts the set supplies the tool for each id.\n */\n\n/** A named group of tool ids. A member is an id or another set, whose ids it takes in order. */\nexport interface ToolSet<TId extends string = string> {\n readonly id: string;\n readonly members: readonly (TId | ToolSet<TId>)[];\n}\n\n/** One entry of a list of tools to mount: an id, or a set of them. */\nexport type ToolEntry<TId extends string = string> = TId | ToolSet<TId>;\n\n/** A set named `id` of `members`, in palette order. */\nexport function toolSet<TId extends string>(id: string, members: readonly ToolEntry<TId>[]): ToolSet<TId> {\n return { id, members };\n}\n\n/** Whether `entry` is a set rather than a single id. */\nexport function isToolSet<TId extends string>(entry: ToolEntry<TId>): entry is ToolSet<TId> {\n return typeof entry !== 'string';\n}\n\n/** Every id `entries` name, sets opened in place, each id once at its first place. */\nexport function toolIdsOf<TId extends string>(entries: readonly ToolEntry<TId>[]): TId[] {\n const out: TId[] = [];\n const seen = new Set<string>();\n const walk = (list: readonly ToolEntry<TId>[]): void => {\n for (const entry of list) {\n if (isToolSet(entry)) walk(entry.members);\n else if (!seen.has(entry)) {\n seen.add(entry);\n out.push(entry);\n }\n }\n };\n walk(entries);\n return out;\n}\n\n/** `set` less every id `omit` names, sets opened. Keeps `set`'s id with a `-without` suffix. */\nexport function withoutTools<TId extends string>(set: ToolSet<TId>, ...omit: readonly ToolEntry<TId>[]): ToolSet<TId> {\n const gone = new Set<string>(toolIdsOf(omit));\n return { id: `${set.id}-without`, members: toolIdsOf([set]).filter((id) => !gone.has(id)) };\n}\n\n/** Whether `set` names `id`, directly or through a set inside it. */\nexport function toolSetHas<TId extends string>(set: ToolSet<TId>, id: string): boolean {\n return (toolIdsOf([set]) as string[]).includes(id);\n}\n","/**\n * Key chords a major browser or the desktop under it takes before a page can:\n * reload, devtools, tab and window commands, menu accelerators. A binding on\n * one never fires for some users, so kit defaults steer clear of them.\n *\n * `mod` is Cmd on macOS and Ctrl elsewhere, as in a `KeySpec`. The list is\n * the union across Chrome, Safari, Firefox and Edge on macOS, Windows and\n * Linux, and errs toward listing a chord.\n */\nimport type { KeySpec } from '@weasel-js/gestures';\n\n/** One reserved chord, and what takes it. */\nexport interface ReservedChord {\n key: string;\n mod?: boolean;\n alt?: boolean;\n shift?: boolean;\n /** Who takes it, for a message. */\n use: string;\n}\n\nconst chord = (keys: string, mods: Omit<ReservedChord, 'key' | 'use'>, use: string): ReservedChord[] =>\n [...keys].map((key) => ({ key, ...mods, use }));\n\n/** Every chord the module's header describes, one entry per key. */\nexport const BROWSER_RESERVED_CHORDS: readonly ReservedChord[] = [\n ...chord('nqtwlrpmh', { mod: true }, 'new window, quit, new or close tab, address bar, reload, print, minimize, hide'),\n ...chord('ntwrbo', { mod: true, shift: true }, 'private window, reopen or close tab, hard reload, bookmarks, bookmark manager'),\n ...chord('ijck', { mod: true, shift: true }, 'devtools, console and inspector on Windows and Linux; Firefox Browser and Web Console'),\n ...chord('ijcukbrlemhdwfn', { mod: true, alt: true }, 'devtools, console, inspector, view source, bookmarks, reload from origin, downloads, empty caches, minimize all, hide others, Dock, close all, search field'),\n ...chord('fevsbthd', { alt: true }, 'menu accelerators and address bar on Windows and Linux'),\n ...chord('ita', { alt: true, shift: true }, 'feedback, toolbar focus and accessibility commands'),\n];\n\nconst lower = (k: string | readonly string[]): string[] => (typeof k === 'string' ? [k] : [...k]).map((x) => x.toLowerCase());\n\n/** Whether a modifier policy can be satisfied with the modifier held (`true`)\n * or released (`false`). */\nconst allows = (policy: boolean | 'optional' | undefined, held: boolean): boolean =>\n policy === 'optional' || (policy === true) === held;\n\n/** The first reserved chord `spec` can fire on, or `null` when none. */\nexport function browserReservedChord(spec: KeySpec): ReservedChord | null {\n const keys = lower(spec.key);\n const m = spec.mods ?? {};\n const mod = m.mod ?? (m.meta === true || m.ctrl === true ? true : m.meta ?? m.ctrl);\n for (const c of BROWSER_RESERVED_CHORDS) {\n if (!keys.includes(c.key)) continue;\n if (allows(mod, c.mod === true) && allows(m.alt, c.alt === true) && allows(m.shift, c.shift === true)) return c;\n }\n return null;\n}\n","/**\n * Typed keys for the gesture/behavior scratch store, `ctx.scratch`.\n * `ScratchKey<T>` carries its payload type at the typing layer; at runtime\n * the key is just its underlying string and the store remains a plain `Record`.\n *\n * @example\n * ```ts\n * // Module-level constant, shared by writer + reader:\n * const LASSO_VERTICES = scratchKey<readonly { x: number; y: number }[]>('lasso.vertices');\n * setScratch(ctx.scratch, LASSO_VERTICES, vertices);\n * const vertices = getScratch(ctx.scratch, LASSO_VERTICES) ?? [];\n * ```\n */\n\n/** Phantom-typed key for a scratch slot. The `__scratchKeyPayload` phantom\n * field carries the value type without occupying any runtime memory. */\nexport interface ScratchKey<T> {\n readonly name: string;\n /** Phantom — never read at runtime. Only present so TypeScript can\n * recover `T` at use sites. */\n readonly __scratchKeyPayload?: (_: T) => T;\n}\n\n/** Compatible scratch store shape. The kit's gesture context's `scratch`\n * field already satisfies this; consumers don't need to construct one. */\nexport type ScratchStore = Record<string, unknown>;\n\n/**\n * Make a typed scratch key. Two keys with the same `name` refer to the same\n * slot at runtime — the type parameter is a compile-time contract, not a\n * uniqueness guarantee — so namespace the name (`'behavior.field'`).\n */\nexport function scratchKey<T>(name: string): ScratchKey<T> {\n return { name };\n}\n\n/** Read a typed slot from the scratch store. Returns `undefined` if\n * nothing has been written under the key. */\nexport function getScratch<T>(\n store: ScratchStore,\n key: ScratchKey<T>,\n): T | undefined {\n return store[key.name] as T | undefined;\n}\n\n/** Write a value to a typed slot. Overwrites whatever was there. */\nexport function setScratch<T>(\n store: ScratchStore,\n key: ScratchKey<T>,\n value: T,\n): void {\n store[key.name] = value;\n}\n\n/** Remove a slot from the scratch store. Returns `true` if it was set,\n * `false` if it wasn't. */\nexport function deleteScratch<T>(\n store: ScratchStore,\n key: ScratchKey<T>,\n): boolean {\n if (Object.prototype.hasOwnProperty.call(store, key.name)) {\n delete store[key.name];\n return true;\n }\n return false;\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { p as Dispatcher, d as ActionsRegistry, C as Contribution, W as WorldPoint, q as AffordanceHit, r as DispatchTrace, L as LongPressOptions, R as RuleCtx, s as DepSchema } from './index-DJ7SxEKS.js';
1
+ import { r as Dispatcher, d as ActionsRegistry, C as Contribution, W as WorldPoint, s as AffordanceHit, t as DispatchTrace, v as LongPressOptions, R as RuleCtx, w as DepSchema } from './index-D-XFwx8D.js';
2
2
  import { RefObject } from 'react';
3
3
  import { BodyClassification } from '@weasel-js/gestures';
4
4
  import { PaintedCursorState, CursorSink } from '@weasel-js/cursor';
@@ -102,6 +102,13 @@ interface UseGestureDispatcherOptions {
102
102
  * nest under.
103
103
  */
104
104
  hears?: 'scope' | 'own';
105
+ /**
106
+ * With no canvas: hear no key while a canvas dispatching on `actions`
107
+ * itself holds the keys. That canvas hears everything this one does, and
108
+ * runs it with its own views and deps. For an app-wide dispatcher whose
109
+ * canvases share its registry. Default `false`.
110
+ */
111
+ yieldKeys?: boolean;
105
112
  /** Every entry in play, keyed by id: tools and any other contribution
106
113
  * whose bindings this dispatcher routes. */
107
114
  entriesById: ReadonlyMap<string, Contribution<unknown>>;
@@ -1,12 +1,13 @@
1
- export { a as DispatcherViewTarget, V as ViewIdResolver } from './internal-CaJ4viHc.js';
2
- import './index-DJ7SxEKS.js';
3
- import '@weasel-js/gestures';
4
- import '@weasel-js/geom';
5
- import '@weasel-js/cursor';
6
- import '@weasel-js/menu';
1
+ export { a as DispatcherViewTarget, V as ViewIdResolver } from './internal-nqfC0td8.js';
2
+ import './index-D-XFwx8D.js';
3
+ import '@weasel-js/history';
7
4
  import '@weasel-js/prefs';
5
+ import '@weasel-js/geom';
8
6
  import '@weasel-js/modes';
7
+ import '@weasel-js/gestures';
9
8
  import '@weasel-js/icons';
9
+ import '@weasel-js/cursor';
10
+ import '@weasel-js/menu';
10
11
  import 'react';
11
12
  import '@weasel-js/registry';
12
13
  import '@weasel-js/select';