@weasel-js/core 1.1.0 → 1.3.0-pre.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1988 -0
- package/dist/{DrawCommand-BbPrSTra.d.ts → DrawCommand-BnZyQaDc.d.ts} +29 -189
- package/dist/chunk-2KKYDDDD.js +121 -0
- package/dist/chunk-2KKYDDDD.js.map +1 -0
- package/dist/{chunk-J7LUY47N.js → chunk-3FB44DBC.js} +3 -3
- package/dist/{chunk-J7LUY47N.js.map → chunk-3FB44DBC.js.map} +1 -1
- package/dist/{chunk-J3YC3GVF.js → chunk-3ZV53ZW2.js} +51 -14
- package/dist/chunk-3ZV53ZW2.js.map +1 -0
- package/dist/{chunk-JOSUVS6C.js → chunk-67KE7SDP.js} +4 -4
- package/dist/chunk-67KE7SDP.js.map +1 -0
- package/dist/{chunk-CSMF654J.js → chunk-AQS4JGRA.js} +50 -7
- package/dist/chunk-AQS4JGRA.js.map +1 -0
- package/dist/{chunk-HGF5X6MZ.js → chunk-BJN5ZRIJ.js} +2 -2
- package/dist/chunk-BJN5ZRIJ.js.map +1 -0
- package/dist/{chunk-4Z6J4IVH.js → chunk-F74NVEHT.js} +14 -46
- package/dist/chunk-F74NVEHT.js.map +1 -0
- package/dist/{chunk-3B4QEB2G.js → chunk-IFOVTYAK.js} +26291 -24809
- package/dist/chunk-IFOVTYAK.js.map +1 -0
- package/dist/{chunk-UGFFCMQP.js → chunk-MXFSHJOM.js} +4 -4
- package/dist/{chunk-UGFFCMQP.js.map → chunk-MXFSHJOM.js.map} +1 -1
- package/dist/{chunk-BHVYVFGV.js → chunk-ZB7UYJVG.js} +3 -3
- package/dist/{chunk-BHVYVFGV.js.map → chunk-ZB7UYJVG.js.map} +1 -1
- package/dist/clipboard.d.ts +3 -3
- package/dist/clipboard.js +3 -3
- package/dist/clone.d.ts +2 -2
- package/dist/clone.js +3 -3
- package/dist/{geometry-C56YbnfD.d.ts → geometry-Dtt_k6Dq.d.ts} +1 -1
- package/dist/{grid-DqOi0Vgi.d.ts → grid-nnXU4VjN.d.ts} +1 -1
- package/dist/index.d.ts +1929 -1342
- package/dist/index.js +10 -10
- package/dist/insert.d.ts +3 -3
- package/dist/insert.js +1 -1
- package/dist/move.d.ts +4 -4
- package/dist/move.js +3 -3
- package/dist/{options-C6HYCKP7.d.ts → options-CdFl510T.d.ts} +1 -1
- package/dist/{path-B6MMiodD.d.ts → path-JEV2c5If.d.ts} +2 -13
- package/dist/patterns-builtin.d.ts +1 -1
- package/dist/patterns-builtin.js +1 -1
- package/dist/{pointSnapToGrid-BBtn5bus.d.ts → pointSnapToGrid-Dmthv94u.d.ts} +2 -2
- package/dist/{registry-DGBrjGbB.d.ts → registry-BU1_3L_C.d.ts} +691 -38
- package/dist/renderer.d.ts +38 -83
- package/dist/renderer.js +10 -10
- package/dist/resize.d.ts +4 -4
- package/dist/resize.js +2 -2
- package/dist/routing.d.ts +35 -9
- package/dist/routing.js +1 -1
- package/dist/stroke-5pBwOm9s.d.ts +190 -0
- package/dist/{types-vqxpCFVp.d.ts → types-DIQAisSG.d.ts} +107 -5
- package/dist/{types-DbysOO-2.d.ts → types-XBcDEp3Y.d.ts} +14 -9
- package/dist/{types-BhrifbZ1.d.ts → types-miXHGrZM.d.ts} +1 -1
- package/package.json +8 -6
- package/dist/chunk-3B4QEB2G.js.map +0 -1
- package/dist/chunk-4Z6J4IVH.js.map +0 -1
- package/dist/chunk-CSMF654J.js.map +0 -1
- package/dist/chunk-GVCNT7UH.js +0 -47
- package/dist/chunk-GVCNT7UH.js.map +0 -1
- package/dist/chunk-HGF5X6MZ.js.map +0 -1
- package/dist/chunk-J3YC3GVF.js.map +0 -1
- package/dist/chunk-JOSUVS6C.js.map +0 -1
- package/dist/paint-types-CnLIzqq1.d.ts +0 -261
- package/dist/viewToMat3-CQW_YqDw.d.ts +0 -67
package/dist/index.d.ts
CHANGED
|
@@ -1,41 +1,44 @@
|
|
|
1
1
|
import * as React$1 from 'react';
|
|
2
|
-
import React__default, { RefObject, ReactNode, Ref, MouseEvent as MouseEvent$1, MutableRefObject } from 'react';
|
|
2
|
+
import React__default, { RefObject, ReactNode, Ref, MouseEvent as MouseEvent$1, ComponentType, MutableRefObject } from 'react';
|
|
3
3
|
import { a as ViewTransform, V as View, Z as ZoomBound, b as ZoomFactor } from './view-DSQgxBJB.js';
|
|
4
4
|
export { s as screenToWorld, v as viewToTransform, w as worldToScreen } from './view-DSQgxBJB.js';
|
|
5
|
-
import { a as UnitValue, b as UnitSystem, U as UseMoveOptions, O as OriginProjection } from './grid-
|
|
6
|
-
export { I as IMPERIAL_INCHES, M as METRIC_MM, P as PIXELS, R as RECT_ORIGIN_PROJECTION, c as Unit, f as formatUnit, g as gridSnapStrategy, p as pointToGridCell, r as resolveUnit } from './grid-
|
|
7
|
-
import { R as RenderLayer, D as Dims, a as DeviceProfile, b as DetectedDeviceFacts, C as Condition, c as Rule, d as RuleCtx, V as VisibilityRules, e as ChromeCtx, f as ChromeId, A as Action, g as DepSchema, S as SliceDep,
|
|
8
|
-
export {
|
|
9
|
-
import {
|
|
10
|
-
export {
|
|
11
|
-
import {
|
|
12
|
-
export {
|
|
13
|
-
import {
|
|
14
|
-
export {
|
|
15
|
-
import {
|
|
16
|
-
export { A as ActionBehavior, f as AreaSelectOverlay, g as BehaviorMoveResult, h as BehaviorResult, C as CloneBehavior, i as CloneLayer, j as ClonePose, G as GestureContext, k as GroupTransform, l as InsertMoveResult, m as InsertOverlay, n as InsertPoint, o as InsertProposed, p as LassoSelectMoveResult, q as LassoSelectOverlay, r as LassoSelectPose, s as LassoSelectProposed, t as PointSnapContext, d as PointSnapFrame, u as PointSnapResult, v as PointerState, w as ResizeMoveResult, x as ResizeOverlay, y as ResizeProposed, z as RotateMoveResult, D as RotateOverlay, E as RotateProposed } from './types-BhrifbZ1.js';
|
|
17
|
-
import { U as UseResizeOptions } from './pointSnapToGrid-BBtn5bus.js';
|
|
18
|
-
export { C as CORNER_ANCHORS, a as CornerAnchor, e as CornerEdge, b as CornerHandle, c as cornerPoint, d as cornerResizeHandles, h as hitCornerHandle, p as pointSnapToGrid } from './pointSnapToGrid-BBtn5bus.js';
|
|
19
|
-
import { BodyClassification, IngestItem } from '@weasel-js/gestures';
|
|
5
|
+
import { a as UnitValue, b as UnitSystem, U as UseMoveOptions, O as OriginProjection } from './grid-nnXU4VjN.js';
|
|
6
|
+
export { I as IMPERIAL_INCHES, M as METRIC_MM, P as PIXELS, R as RECT_ORIGIN_PROJECTION, c as Unit, f as formatUnit, g as gridSnapStrategy, p as pointToGridCell, r as resolveUnit } from './grid-nnXU4VjN.js';
|
|
7
|
+
import { R as RenderLayer, D as Dims, a as DeviceProfile, b as DetectedDeviceFacts, C as Condition, c as Rule, d as RuleCtx, V as VisibilityRules, e as ChromeCtx, f as ChromeId, A as Action, g as ViewAnimationOptions, h as DepSchema, S as SliceDep, i as ActionsRegistry, T as Tool, j as AffordanceHit, k as Dispatcher, l as ToolDef, m as ViewportToolDef, n as AnyTool, O as OverlayPosition, o as ToolKeybinding, H as HotkeyTrigger, L as LayerHit, p as OngoingOverlay, q as ChromeState, r as SelectionApi, U as UseSelectionOptions, I as InsertExtras, B as BuiltinShapeToolId, G as GeometryProjection, s as ContentHandlerEntry, t as SvgIngestOptions, u as ActionsProp, v as Animator, w as Affordance, x as AffordanceRegion, y as AffordanceBinding, z as CommonAffordanceScratch, E as ColorOverrideRegistry, F as BooleansAdapter, J as EasingFn, K as SpringPresetName, M as SpringPreset, N as UseAnimatorOptions, P as AnimationHandle, Q as VertexColorChannel, W as SampledTrack, X as Eligibility, Y as BindingScope, Z as Contribution, _ as ScopedBinding } from './registry-BU1_3L_C.js';
|
|
8
|
+
export { $ as ALWAYS, a0 as ActionDeps, a1 as ActionDisabledReason, a2 as ActionEnabledResult, a3 as ActionEntry, a4 as ActionsProvider, a5 as ActiveToolContextProvider, a6 as ActiveToolContextProviderIfRoot, a7 as ActiveToolContextProviderProps, a8 as ActiveToolContextValue, a9 as AnimateToBoundsOptions, aa as AreaSelectDep, ab as BindingOpts, ac as BooleanOp, ad as BooleanOpResult, ae as BoundGesture, af as BuildRuleCtxArgs, ag as ClaimableGesture, ah as ClipboardDep, ai as ClipboardIngestCtx, aj as ColorOverride, ak as ColorOverrideFn, al as CustomPaintContext, am as DecayOptions, an as DepName, ao as DepRegistry, ap as DepRegistryProvider, aq as DispatcherContext, ar as DragSample, as as EditAnchorsDep, at as EventTrack, au as GestureBinding, av as IDENTITY_POSE_COMPOSITION, aw as ImmediateInvoker, ax as IngestCtx, ay as IngestionDep, az as InsertDep, aA as Interpolate, aB as InterpolatorFactory, aC as InvocationCtx, aD as Invoker, aE as KIT_SHAPE_KINDS, aF as Keyframe, aG as LassoSelectDep, aH as LayerCommandCache, aI as LayoutDep, aJ as LoopFactory, aK as LoopOptions, aL as MatchResult, aM as NEVER, aN as NestedTimeline, aO as NodeAtPointDep, aP as OngoingHandle, aQ as OngoingInvoker, aR as PhysicsHandle, aS as PhysicsOptions, aT as Point2, aU as PointerContextProvider, aV as PointerContextValue, aW as PointerWorldPos, aX as PoseAdapter, aY as PoseComposition, aZ as ResizePolicy, a_ as ResolveAllOptions, a$ as ResolveOnlyResult, b0 as ResolvedCandidate, b1 as SelectionExtendKey, b2 as SelectionMode, b3 as Selector, b4 as SnapDep, b5 as SpringOptions, b6 as StaggerBuilder, b7 as StaggerDelay, b8 as StaggerFactory, b9 as StaggerOptions, ba as StaggerPerItem, bb as StaggerSpringPoseOptions, bc as StaggerTweenOptions, bd as SvgUnpacker, be as TextEditDep, bf as TimelineHandle, bg as TimelineOptions, bh as TimelineTrack, bi as ToolCtx, bj as ToolModifiers, bk as ToolPresentation, bl as ToolSlot, bm as Track, bn as TweenLoopOptions, bo as TweenOptions, bp as UiOngoingControl, bq as VIEW_ANIMATION_KEY, br as ViewAnimationApi, bs as ViewApi, bt as ViewChannel, bu as actionBindings, bv as applyBooleanOp, bw as buildRuleCtx, bx as clipboardCopyAction, by as clipboardCutAction, bz as composeRectPose, bA as composeWorldPose, bB as createDispatcher, bC as decomposeRectPose, bD as describeRule, bE as drawLayers, bF as drawOneLayer, bG as enterTextEditAction, bH as evaluate, bI as evaluateEnabled, bJ as isLayerPainted, bK as isLayerVisible, bL as rebaseLocalPose, bM as registerContentHandler, bN as resolveParams, bO as sliceAction, bP as specificity, bQ as translateRectPose, bR as useAction, bS as useActionsRegistry, bT as useActiveToolContext, bU as useDepRegistry, bV as useDepSource, bW as useOptionalActiveToolContext, bX as useOptionalDepRegistry, bY as usePointerContext, bZ as useSelection, b_ as useViewAnimation, b$ as worldPoseLookup } from './registry-BU1_3L_C.js';
|
|
9
|
+
import { Stroke, FillStyle, TextureHandle, TilePatternSpec, GradientKind, GradStop, GradientFill, GradientUnits, MarkerKey, MarkerRef } from '@weasel-js/paint';
|
|
10
|
+
export { FillStyle, GradStop, GradientFill, GradientKind, GradientUnits, KitMarkerKey, MarkerKey, MarkerRef, Region, STROKE_DASH_RATIOS, Stroke, StrokeAlign, StrokeDashStyle, TextureHandle, TilePatternSpec, alignedStrokeRect, dashForStrokeStyle, strokeDashStyleOf } from '@weasel-js/paint';
|
|
11
|
+
import { R as RectPose, S as Scene, N as NodeId, a as Node$1, b as SerializedScene, U as UseSceneOptions, c as SceneRegistry, d as RegisteredOp } from './types-DIQAisSG.js';
|
|
12
|
+
export { A as AddLayerSpec, e as AddNodeSpec, C as ContainerNode, L as LayerRecord, f as LeafNode, P as PoseOverride, g as PoseOverrides, h as SerializedNode, i as SystemLayerRecord, j as SystemLayerSpec, k as UserLayerRecord, l as asNodeId } from './types-DIQAisSG.js';
|
|
13
|
+
import { B as Bounds, P as PoseProjection, V as ViewportDims } from './geometry-Dtt_k6Dq.js';
|
|
14
|
+
export { F as FitViewToBoundsOptions, R as RECT_POSE_DESCRIPTOR, a as ROTATED_POSE_DESCRIPTOR, f as fitViewToBounds } from './geometry-Dtt_k6Dq.js';
|
|
15
|
+
import { GestureSpec, BodyClassification, IngestItem } from '@weasel-js/gestures';
|
|
20
16
|
export { ClickSpec, DragSpec, DropSpec, GestureSpec, IngestItem, InputEvent, KeyHeldSpec, KeySpec, ModSpec, MultiTouchSpec, PasteSpec, TargetSpec, WheelSpec } from '@weasel-js/gestures';
|
|
21
|
-
import { M as
|
|
22
|
-
export {
|
|
17
|
+
import { M as ModifierState, R as ResizePose, B as BoundsConstraint, P as PointSnapBehavior, L as LassoSelectBehavior, a as RotatedPose, e as RotateBehavior, S as SnapStrategy, c as ResizeAnchor, b as MoveBehavior, I as InsertBehavior } from './types-miXHGrZM.js';
|
|
18
|
+
export { A as ActionBehavior, f as AreaSelectOverlay, g as BehaviorMoveResult, h as BehaviorResult, C as CloneBehavior, i as CloneLayer, j as ClonePose, G as GestureContext, k as GroupTransform, l as InsertMoveResult, m as InsertOverlay, n as InsertPoint, o as InsertProposed, p as LassoSelectMoveResult, q as LassoSelectOverlay, r as LassoSelectPose, s as LassoSelectProposed, t as PointSnapContext, d as PointSnapFrame, u as PointSnapResult, v as PointerState, w as ResizeMoveResult, x as ResizeOverlay, y as ResizeProposed, z as RotateMoveResult, D as RotateOverlay, E as RotateProposed } from './types-miXHGrZM.js';
|
|
19
|
+
import { U as UseResizeOptions } from './pointSnapToGrid-Dmthv94u.js';
|
|
20
|
+
export { C as CORNER_ANCHORS, a as CornerAnchor, e as CornerEdge, b as CornerHandle, c as cornerPoint, d as cornerResizeHandles, h as hitCornerHandle, p as pointSnapToGrid } from './pointSnapToGrid-Dmthv94u.js';
|
|
21
|
+
import { M as MoveAdapter, A as AreaSelectAdapter, R as RotateAdapter, b as LassoHitMode, c as LassoSelectAdapter, d as ResizeAdapter, L as LayoutStrategy, e as LayerEnumerableAdapter, I as InsertAdapter, C as ClipboardSnapshot, O as OrderedAdapter, a as SceneAdapter, f as LayoutSnap } from './types-XBcDEp3Y.js';
|
|
22
|
+
export { g as ContainerBounds, D as DropTarget, h as LayoutChild, i as LayoutContainer, j as LayoutDragged, S as SnapTarget } from './types-XBcDEp3Y.js';
|
|
23
23
|
import { D as DebugSink, a as DebugConfig, b as DebugSnapshot, c as DebugStrokes, d as DebugTheme } from './types-BHK2dkMu.js';
|
|
24
24
|
export { e as DebugFeature, f as DebugStroke, H as HandleKind, g as HitShape, R as RecordedBounds, h as RecordedHandle, i as RecordedHitbox, j as RecordedLayer, k as RecordedOrigin, l as RecordedSnap } from './types-BHK2dkMu.js';
|
|
25
|
-
import { a as PolygonPath, P as Path, b as PathFillRule, R as RectPath } from './path-
|
|
26
|
-
export { c as PATH_C, d as PATH_CMD_LENGTHS, e as PATH_L, f as PATH_M, g as PATH_Q, h as PATH_Z } from './path-B6MMiodD.js';
|
|
25
|
+
import { a as PolygonPath, P as Path, b as PathFillRule, R as RectPath } from './path-JEV2c5If.js';
|
|
27
26
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
28
|
-
import { D as DrawCommand, S as ShaderProgramHandle, P as PathDrawCommand,
|
|
29
|
-
export {
|
|
30
|
-
import { Op, CreateHistoryOptions, History } from '@weasel-js/history';
|
|
27
|
+
import { D as DrawCommand, S as ShaderProgramHandle, P as PathDrawCommand, M as Mat3$1 } from './DrawCommand-BnZyQaDc.js';
|
|
28
|
+
export { G as GroupDrawCommand, I as ImageDrawCommand, a as ShaderDrawCommand, b as ShaderUniform, T as TextDrawCommand, m as mat3 } from './DrawCommand-BnZyQaDc.js';
|
|
29
|
+
import { Op, HistorySelection, CreateHistoryOptions, History } from '@weasel-js/history';
|
|
31
30
|
export * from '@weasel-js/history';
|
|
32
31
|
export { Op } from '@weasel-js/history';
|
|
33
|
-
import {
|
|
32
|
+
import { TextRenderer, TextPose, StyledRun, TextStyle, TextPaint, TextVerticalAlign } from '@weasel-js/text';
|
|
33
|
+
export { DEFAULT_TEXT_STYLE, LaidOutDecoration, LaidOutGroup, LaidOutLineBox, LaidOutOutlineGlyph, LaidOutQuad, LaidOutRuns, LayoutLine, LayoutResult, LayoutRunsOpts, MARKDOWN_RUN_GRAMMAR, MarkdownFontOptions, MeasureFn, MeasureTextBoundsOpts, MeasuredText, PositionedRun, ResolvedRun, ResolvedTextStyle, RunFlag, RunGrammar, RunMarker, SCRIPT_METRICS, StyledRun, TextAlign, TextDirection, TextLineBoxesOpts, TextPaint, TextPose, TextRenderer, TextStyle, TextVerticalAlign, cachedLayoutRuns, createMarkdownRenderer, fontString, layoutMarkdown, layoutRuns, markdownToRuns, measureText, measureTextBounds, measuredWidth, resolveAlign, resolveRuns, resolveTextStyle, runsToMarkdown, runsToPlainText, textLineBoxes, toRuns, verticalAlignOffset } from '@weasel-js/text';
|
|
34
|
+
import { S as ShaderProgram } from './stroke-5pBwOm9s.js';
|
|
35
|
+
export { I as ImageMinification, b as SpriteSheet, f as frameRect, r as resolveStrokeWidth, v as viewToMat3 } from './stroke-5pBwOm9s.js';
|
|
36
|
+
import { Rect, Mat3 } from '@weasel-js/geom';
|
|
37
|
+
export { PATH_C, PATH_CMD_LENGTHS, PATH_L, PATH_M, PATH_Q, PATH_Z, Rect, pathCommandCoordCount } from '@weasel-js/geom';
|
|
34
38
|
import { G as Guide } from './types-D2tTKEU0.js';
|
|
35
|
-
export { U as UseInsertOptions } from './options-
|
|
39
|
+
export { U as UseInsertOptions } from './options-CdFl510T.js';
|
|
36
40
|
export { UseClipboardOpsOptions, UseClipboardOpsReturn, WEASEL_CLIPBOARD_MIME, WEASEL_CLIPBOARD_MIME_WEB, buildWeaselClipboardText, embedWeaselMetadataInSvg, extractWeaselClipboardFromSvg, parseWeaselClipboardText, sniffWeaselClipboardText, useClipboardOps } from './clipboard.js';
|
|
37
41
|
export { cloneByAltDrag } from './clone.js';
|
|
38
|
-
export { I as ImageMinification, v as viewToMat3 } from './viewToMat3-CQW_YqDw.js';
|
|
39
42
|
export { FontVariant, LocalFontOutlinesResult, OutlineFontStyle, OutlineSource, OutlineStatus, OutlineVariant, canQueryLocalFonts, enableLocalFontOutlines, hasFontOutlines, isCanvasFont, listFontOutlines, outlineStatus, registerCanvasFont, registerFont, registerFontOutlines, subscribeGlyphReady, unregisterCanvasFont, unregisterFontOutlines } from '@weasel-js/font';
|
|
40
43
|
import { CapabilityTag } from '@weasel-js/modes';
|
|
41
44
|
|
|
@@ -189,6 +192,79 @@ interface CellHighlightLayerOpts {
|
|
|
189
192
|
/** Build a `RenderLayer` that fills a single grid cell — typically a snap-target preview. */
|
|
190
193
|
declare function createCellHighlightLayer(opts: CellHighlightLayerOpts): RenderLayer<unknown>;
|
|
191
194
|
|
|
195
|
+
/**
|
|
196
|
+
* @experimental
|
|
197
|
+
*
|
|
198
|
+
* A view the resolver can route input to: a camera and the rect it paints
|
|
199
|
+
* into, in canvas CSS-pixel space. A viewport node supplies one of these per
|
|
200
|
+
* frame; so could any other per-view surface.
|
|
201
|
+
*/
|
|
202
|
+
interface ResolvableView {
|
|
203
|
+
id: string;
|
|
204
|
+
view: View;
|
|
205
|
+
rect: {
|
|
206
|
+
x: number;
|
|
207
|
+
y: number;
|
|
208
|
+
w: number;
|
|
209
|
+
h: number;
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* @experimental
|
|
214
|
+
*
|
|
215
|
+
* The view an input event belongs to. `id` is `null` for the root view —
|
|
216
|
+
* the whole canvas, when no viewport contains the point.
|
|
217
|
+
*
|
|
218
|
+
* `origin` is the client-space origin of that view's surface, ready to hand
|
|
219
|
+
* to `clientToWorld` — which is the whole reason this type carries it rather
|
|
220
|
+
* than leaving callers to add the canvas rect and the view rect themselves.
|
|
221
|
+
*/
|
|
222
|
+
interface ViewTarget {
|
|
223
|
+
id: string | null;
|
|
224
|
+
view: View;
|
|
225
|
+
origin: {
|
|
226
|
+
left: number;
|
|
227
|
+
top: number;
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* @experimental
|
|
232
|
+
*
|
|
233
|
+
* Routes client points to views, and holds a captured pointer on the view its
|
|
234
|
+
* gesture started in.
|
|
235
|
+
*
|
|
236
|
+
* Stickiness is the point. A drag that leaves its view's rect — over a
|
|
237
|
+
* neighbouring view, or off the canvas — must keep reporting coordinates in
|
|
238
|
+
* the space it began in, or a marquee crossing a panel edge silently starts
|
|
239
|
+
* measuring against the wrong camera.
|
|
240
|
+
*/
|
|
241
|
+
interface ViewResolver {
|
|
242
|
+
/** Resolve and pin `pointerId`. Call on pointerdown. */
|
|
243
|
+
begin(pointerId: number, clientX: number, clientY: number): ViewTarget;
|
|
244
|
+
/**
|
|
245
|
+
* The view for a point. A pinned `pointerId` gets its pinned view, looked
|
|
246
|
+
* up fresh so a rect that moved mid-gesture is honored. Pass `null` for
|
|
247
|
+
* input with no pointer to capture — wheel, hover, keys.
|
|
248
|
+
*/
|
|
249
|
+
at(pointerId: number | null, clientX: number, clientY: number): ViewTarget;
|
|
250
|
+
/** Release `pointerId`. Call on pointerup and pointercancel. */
|
|
251
|
+
end(pointerId: number): void;
|
|
252
|
+
/** Release every pin. */
|
|
253
|
+
clear(): void;
|
|
254
|
+
}
|
|
255
|
+
interface CreateViewResolverOpts {
|
|
256
|
+
/** Candidate views in paint order — the last one containing a point wins. */
|
|
257
|
+
views: () => readonly ResolvableView[];
|
|
258
|
+
/** The camera for points no view claims. */
|
|
259
|
+
root: () => View;
|
|
260
|
+
/** Client-space origin of the canvas element. */
|
|
261
|
+
canvasOrigin: () => {
|
|
262
|
+
left: number;
|
|
263
|
+
top: number;
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
declare function createViewResolver(opts: CreateViewResolverOpts): ViewResolver;
|
|
267
|
+
|
|
192
268
|
/**
|
|
193
269
|
* @experimental
|
|
194
270
|
*
|
|
@@ -202,33 +278,50 @@ declare function createCellHighlightLayer(opts: CellHighlightLayerOpts): RenderL
|
|
|
202
278
|
* lenses on the source.
|
|
203
279
|
*
|
|
204
280
|
* **Inner view semantics.** The source layers draw as if the inner view
|
|
205
|
-
* filled the screen at world-origin
|
|
206
|
-
*
|
|
207
|
-
* view's origin lands at `bounds.x,
|
|
208
|
-
* bounds.
|
|
209
|
-
* of source-world is shown.
|
|
281
|
+
* filled the screen at world-origin — each is wrapped in `viewToMat3(view)`
|
|
282
|
+
* by the same `drawOneLayer` the outer canvas uses. The viewport then
|
|
283
|
+
* translates the result so that the inner view's origin lands at `bounds.x,
|
|
284
|
+
* bounds.y` and clips to `(bounds.w, bounds.h)`. Caller chooses
|
|
285
|
+
* `innerView.{x,y,scale}` to control which slice of source-world is shown.
|
|
210
286
|
*
|
|
211
287
|
* **Input is re-projected on request, not automatically.** `reproject` maps a
|
|
212
288
|
* screen point into the inner view's world; a consumer that wants a click
|
|
213
|
-
* inside a viewport to mean something calls it from its own handler
|
|
214
|
-
*
|
|
215
|
-
*
|
|
216
|
-
*
|
|
289
|
+
* inside a viewport to mean something calls it from its own handler, or feeds
|
|
290
|
+
* `resolvable` to `createViewResolver` to route a whole pointer stream.
|
|
291
|
+
* `<CanvasView>` is that wiring done for you; build on this directly for a
|
|
292
|
+
* viewport that takes no input, or to route it yourself.
|
|
217
293
|
*
|
|
218
294
|
* **Screen-space source layers** (e.g., debug overlays, selection chrome)
|
|
219
|
-
*
|
|
220
|
-
*
|
|
295
|
+
* draw in the viewport's own CSS-pixel space: their coords are relative to
|
|
296
|
+
* the rect's top-left, and they clip to it, rather than to the outer canvas.
|
|
221
297
|
*/
|
|
222
|
-
interface CreateViewportLayerOpts<TData> {
|
|
298
|
+
interface CreateViewportLayerOpts<TData, TSource = TData> {
|
|
223
299
|
id: string;
|
|
224
300
|
label: string;
|
|
225
301
|
/** Layers re-rendered through `view`. Each receives `(data, view, dims)`
|
|
226
|
-
* exactly as the outer Canvas would call it.
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
* `
|
|
230
|
-
|
|
231
|
-
|
|
302
|
+
* exactly as the outer Canvas would call it.
|
|
303
|
+
*
|
|
304
|
+
* Pass a thunk for a stack that is assembled elsewhere — it is read fresh
|
|
305
|
+
* on every `draw`, the same way a thunked `view` is. */
|
|
306
|
+
source: readonly RenderLayer<TSource>[] | (() => readonly RenderLayer<TSource>[]);
|
|
307
|
+
/**
|
|
308
|
+
* The `data` the source layers receive, derived from what the outer canvas
|
|
309
|
+
* passed down. Omit and they get the outer canvas's own.
|
|
310
|
+
*
|
|
311
|
+
* A viewport showing the same scene through a second camera wants its own
|
|
312
|
+
* per-view helpers here — selection, chrome state and gesture previews that
|
|
313
|
+
* belong to *this* view rather than the one hosting it.
|
|
314
|
+
*/
|
|
315
|
+
data?: (outer: TData) => TSource;
|
|
316
|
+
/**
|
|
317
|
+
* The inner view. Pass a thunk for a camera that moves — it is read fresh
|
|
318
|
+
* on every `draw`, `reproject` and `resolvable`, so those three cannot
|
|
319
|
+
* disagree about where the viewport is looking mid-gesture.
|
|
320
|
+
*
|
|
321
|
+
* The thunk receives the outer view and dims, so a derived camera
|
|
322
|
+
* (parallax, node-anchored scroll) is a function of the one hosting it.
|
|
323
|
+
*/
|
|
324
|
+
view: View | ((outer: View, dims: Dims) => View);
|
|
232
325
|
/** Where on the outer canvas this viewport is painted, in screen-space
|
|
233
326
|
* CSS pixels. Recomputed every frame so the rect can track an outer
|
|
234
327
|
* pose, follow a corner, etc. */
|
|
@@ -260,9 +353,9 @@ interface ViewportLayer<TData> extends RenderLayer<TData> {
|
|
|
260
353
|
* `bounds` is a pure function of those, so this reproduces the exact rect
|
|
261
354
|
* that was painted rather than a remembered one.
|
|
262
355
|
*
|
|
263
|
-
* This does not touch the dispatcher:
|
|
264
|
-
*
|
|
265
|
-
*
|
|
356
|
+
* This does not touch the dispatcher: a consumer that wants a click inside
|
|
357
|
+
* a viewport to mean something calls this from its own handler, or declares
|
|
358
|
+
* the viewport as a `<CanvasView>` and lets the canvas route to it.
|
|
266
359
|
*/
|
|
267
360
|
reproject(outer: View, dims: Dims, screen: {
|
|
268
361
|
x: number;
|
|
@@ -271,12 +364,20 @@ interface ViewportLayer<TData> extends RenderLayer<TData> {
|
|
|
271
364
|
x: number;
|
|
272
365
|
y: number;
|
|
273
366
|
} | null;
|
|
367
|
+
/**
|
|
368
|
+
* This viewport as a routing candidate for {@link createViewResolver} —
|
|
369
|
+
* its inner view and the rect it paints into for the given outer frame.
|
|
370
|
+
*
|
|
371
|
+
* Pass the `outer` view and `dims` the frame was drawn with, for the same
|
|
372
|
+
* reason `reproject` wants them: `bounds` is recomputed, not remembered.
|
|
373
|
+
*/
|
|
374
|
+
resolvable(outer: View, dims: Dims): ResolvableView;
|
|
274
375
|
}
|
|
275
376
|
/** Build a layer that renders other layers through a second view, inside a
|
|
276
377
|
* sub-region of the canvas — a minimap, an inset, a magnifier. Its
|
|
277
378
|
* `reproject` maps screen points back through the inner view so the region
|
|
278
379
|
* can be interacted with. */
|
|
279
|
-
declare function createViewportLayer<TData>(opts: CreateViewportLayerOpts<TData>): ViewportLayer<TData>;
|
|
380
|
+
declare function createViewportLayer<TData, TSource = TData>(opts: CreateViewportLayerOpts<TData, TSource>): ViewportLayer<TData>;
|
|
280
381
|
/**
|
|
281
382
|
* @experimental
|
|
282
383
|
*
|
|
@@ -454,6 +555,71 @@ declare const DEFAULT_VELOCITY_DECAY = 0.4;
|
|
|
454
555
|
*/
|
|
455
556
|
declare function useSimulation<TNode extends SimulationNode>(opts: UseSimulationOptions<TNode>): Simulation<TNode>;
|
|
456
557
|
|
|
558
|
+
/**
|
|
559
|
+
* `useNodeOverlayFrame` — the coordinate frame a DOM overlay pinned to one
|
|
560
|
+
* scene node needs: the node's world box, the projection from that box's
|
|
561
|
+
* frame into overlay pixels, and the overlay's measured size.
|
|
562
|
+
*
|
|
563
|
+
* This is the frame half of `subscribeView`'s "DOM pinned to world
|
|
564
|
+
* coordinates" case. Consumers positioning chrome over a node — gradient
|
|
565
|
+
* handles, a badge, a caret — otherwise re-derive it, and the
|
|
566
|
+
* translate-and-scale inverse that derivation usually reaches for drops
|
|
567
|
+
* `pose.rotation`, so the chrome sits where the node would be unrotated.
|
|
568
|
+
*
|
|
569
|
+
* `toScreen` maps the node's **unrotated world box** frame, which is the
|
|
570
|
+
* frame `fillInPoseFrame` resolves a `units: 'bounds'` paint into and the
|
|
571
|
+
* one `pathInPoseFrame` projects geometry into. Rotation lives in this hook,
|
|
572
|
+
* not in those: a node's stored geometry is pre-rotation by definition.
|
|
573
|
+
*/
|
|
574
|
+
|
|
575
|
+
/** Structural point, matching every other `{ x, y }` the kit passes across a
|
|
576
|
+
* boundary. */
|
|
577
|
+
interface OverlayPoint {
|
|
578
|
+
x: number;
|
|
579
|
+
y: number;
|
|
580
|
+
}
|
|
581
|
+
/** The overlay frame for one node. `null` from the hook means there is no
|
|
582
|
+
* frame yet — no node, or nothing measured to draw it on. */
|
|
583
|
+
interface NodeOverlayFrame {
|
|
584
|
+
/** The node's composed world box, **unrotated**: the frame `toScreen` maps
|
|
585
|
+
* from, and the box to hand `fillInPoseFrame` / `fillToBoundsFrame`. */
|
|
586
|
+
box: {
|
|
587
|
+
x: number;
|
|
588
|
+
y: number;
|
|
589
|
+
width: number;
|
|
590
|
+
height: number;
|
|
591
|
+
};
|
|
592
|
+
/** Node box frame → overlay pixels, rotation and view included. */
|
|
593
|
+
toScreen: (p: OverlayPoint) => OverlayPoint;
|
|
594
|
+
/** Overlay pixels → node box frame. Inverts `toScreen`. */
|
|
595
|
+
toLocal: (p: OverlayPoint) => OverlayPoint;
|
|
596
|
+
/** The container's size in CSS pixels — the overlay's own box. */
|
|
597
|
+
width: number;
|
|
598
|
+
height: number;
|
|
599
|
+
}
|
|
600
|
+
interface UseNodeOverlayFrameOptions<TPose> {
|
|
601
|
+
/**
|
|
602
|
+
* Current viewport. A thunk is re-read on every projection, which is what
|
|
603
|
+
* an uncontrolled `SceneCanvas` needs — its camera lives in a ref and moves
|
|
604
|
+
* without a render, so pass the handle's `getView`. A plain `View` is the
|
|
605
|
+
* value from the render that supplied it, correct for a controlled
|
|
606
|
+
* consumer. Omit it and world units are handed through as screen pixels.
|
|
607
|
+
*/
|
|
608
|
+
view?: View | (() => View);
|
|
609
|
+
/** Fold a child pose into its parent's frame. Default `composeRectPose`. */
|
|
610
|
+
compose?: (parent: TPose, child: TPose) => TPose;
|
|
611
|
+
}
|
|
612
|
+
/**
|
|
613
|
+
* Resolve the overlay frame for `nodeId` against `containerRef` — the element
|
|
614
|
+
* the overlay is positioned in, which must be the canvas's own box for the
|
|
615
|
+
* projection to land.
|
|
616
|
+
*
|
|
617
|
+
* Returns `null` when there is no node under `nodeId`, when the container has
|
|
618
|
+
* not been measured, or when the view collapses an axis to zero — the three
|
|
619
|
+
* states in which an overlay has nothing to draw.
|
|
620
|
+
*/
|
|
621
|
+
declare function useNodeOverlayFrame<TData, TLayer extends string, TPose extends RectPose>(scene: Scene<TData, TLayer, TPose>, containerRef: RefObject<HTMLElement | null>, nodeId: string | null | undefined, options?: UseNodeOverlayFrameOptions<TPose>): NodeOverlayFrame | null;
|
|
622
|
+
|
|
457
623
|
/**
|
|
458
624
|
* Stylus / Pencil pointer-event helpers.
|
|
459
625
|
*
|
|
@@ -790,7 +956,7 @@ interface CanvasSizeSnapshot extends CanvasSize {
|
|
|
790
956
|
* so dragging a window to a different-density display without resizing it
|
|
791
957
|
* left the snapshot stale. The profile watches a re-armed resolution media
|
|
792
958
|
* query instead. */
|
|
793
|
-
declare function useCanvasSize(containerRef: RefObject<
|
|
959
|
+
declare function useCanvasSize(containerRef: RefObject<HTMLElement | null>): CanvasSizeSnapshot;
|
|
794
960
|
|
|
795
961
|
/**
|
|
796
962
|
* Handle/hit multiplier applied on a coarse pointer.
|
|
@@ -820,25 +986,23 @@ declare function resolveDeviceProfile(detected: DetectedDeviceFacts, overrides?:
|
|
|
820
986
|
declare const DEFAULT_DEVICE_PROFILE: DeviceProfile;
|
|
821
987
|
|
|
822
988
|
/**
|
|
823
|
-
* Base sizes for grabbable chrome, in CSS pixels at `targetScale = 1
|
|
824
|
-
*
|
|
825
|
-
* These were six separate literal `8`s and one `24` scattered across
|
|
826
|
-
* `SceneCanvas`, `features/selection/overlay`, `affordances/cornerResize`,
|
|
827
|
-
* `canvas/affordanceAt`, and `interactions/actions/rotate/handle`. They are
|
|
828
|
-
* consolidated here because paint and hit-test MUST scale together: chrome
|
|
829
|
-
* you can see but cannot grab is the exact failure `chrome-caps` exists to
|
|
830
|
-
* make impossible, and duplicated literals in five files is how that failure
|
|
831
|
-
* gets reintroduced.
|
|
989
|
+
* Base sizes for grabbable chrome, in CSS pixels at `targetScale = 1`, and the
|
|
990
|
+
* one accessor that resolves them for a live pointer type.
|
|
832
991
|
*
|
|
833
|
-
*
|
|
834
|
-
* is
|
|
992
|
+
* Paint and hit-test MUST scale together: chrome you can see but cannot grab
|
|
993
|
+
* is the exact failure `chrome-caps` exists to make impossible, and a literal
|
|
994
|
+
* `8` copied into a fifth file is how that failure gets reintroduced. So every
|
|
995
|
+
* kit-internal use site goes through {@link targetSizesPx} — the selection
|
|
996
|
+
* overlay's handle size, `buildAffordanceAt`'s hit radii, and the slops debug
|
|
997
|
+
* overlay all read the same object. The bare constants below stay exported for
|
|
998
|
+
* consumers, who get the unscaled numbers they always got.
|
|
835
999
|
*/
|
|
836
1000
|
/** Selection corner-handle visual size and hit radius. */
|
|
837
|
-
declare const HANDLE_BASE_PX
|
|
1001
|
+
declare const HANDLE_BASE_PX: 8;
|
|
838
1002
|
/** Path anchor / control-point hit radius. */
|
|
839
|
-
declare const ANCHOR_HIT_BASE_PX
|
|
1003
|
+
declare const ANCHOR_HIT_BASE_PX: 8;
|
|
840
1004
|
/** Distance from a selection's top edge to the rotation handle's center. */
|
|
841
|
-
declare const ROTATION_HANDLE_BASE_PX
|
|
1005
|
+
declare const ROTATION_HANDLE_BASE_PX: 24;
|
|
842
1006
|
|
|
843
1007
|
/**
|
|
844
1008
|
* Read the ambient device profile.
|
|
@@ -1007,7 +1171,17 @@ interface UseZoomReturn {
|
|
|
1007
1171
|
declare function useZoom(opts: UseZoomOptions): UseZoomReturn;
|
|
1008
1172
|
|
|
1009
1173
|
/**
|
|
1010
|
-
*
|
|
1174
|
+
* Compute zoom and pan that fit `contentW x contentH` (in content units)
|
|
1175
|
+
* inside `viewportW x viewportH` (in pixels). `padRatio` is the fraction of
|
|
1176
|
+
* each axis to fill (default 0.85 — leaves a uniform 15% margin).
|
|
1177
|
+
*/
|
|
1178
|
+
declare function computeFitViewport(viewportW: number, viewportH: number, contentW: number, contentH: number, padRatio?: number): {
|
|
1179
|
+
zoom: number;
|
|
1180
|
+
panX: number;
|
|
1181
|
+
panY: number;
|
|
1182
|
+
};
|
|
1183
|
+
/**
|
|
1184
|
+
* Run `computeFitViewport` once when the viewport first has non-zero size, and
|
|
1011
1185
|
* apply the result via the supplied setters. Subsequent size changes are
|
|
1012
1186
|
* ignored — this hook centers exactly once.
|
|
1013
1187
|
*/
|
|
@@ -1219,10 +1393,9 @@ declare function buildChromeCtx(args: BuildChromeCtxArgs): ChromeCtx;
|
|
|
1219
1393
|
/**
|
|
1220
1394
|
* useHoverTracking — last-hovered NodeId for chrome-caps rules.
|
|
1221
1395
|
*
|
|
1222
|
-
* Attaches a `pointermove` listener to the supplied canvas; on each
|
|
1223
|
-
*
|
|
1224
|
-
* `
|
|
1225
|
-
* `pointerleave` (pointer left the canvas → nothing is hovered).
|
|
1396
|
+
* Attaches a `pointermove` listener to the supplied canvas; on each move it
|
|
1397
|
+
* runs the supplied `nodeAtClientPoint` and caches the resulting id on a ref.
|
|
1398
|
+
* Cleared on `pointerleave` (pointer left the canvas → nothing is hovered).
|
|
1226
1399
|
*
|
|
1227
1400
|
* Returns a stable getter — call once per frame from `buildChromeCtx`.
|
|
1228
1401
|
*
|
|
@@ -1234,13 +1407,11 @@ declare function buildChromeCtx(args: BuildChromeCtxArgs): ChromeCtx;
|
|
|
1234
1407
|
/** Options for `useHoverTracking`. */
|
|
1235
1408
|
interface UseHoverTrackingArgs {
|
|
1236
1409
|
canvasRef: RefObject<HTMLCanvasElement | null>;
|
|
1237
|
-
/**
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
/** Topmost-id resolver. Returns null when the world point hits nothing. */
|
|
1243
|
-
getNodeAtPoint: (worldX: number, worldY: number) => {
|
|
1410
|
+
/** Topmost id under a client point, or null. One lookup rather than a
|
|
1411
|
+
* client→world thunk beside a world-space picker: a screen-pixel pick
|
|
1412
|
+
* tolerance converts against the camera the point resolved to, and two
|
|
1413
|
+
* thunks are two chances to disagree about which view that is. */
|
|
1414
|
+
nodeAtClientPoint: (clientX: number, clientY: number) => {
|
|
1244
1415
|
id: NodeId;
|
|
1245
1416
|
} | null;
|
|
1246
1417
|
enabled?: boolean;
|
|
@@ -1250,28 +1421,75 @@ interface UseHoverTrackingArgs {
|
|
|
1250
1421
|
* the component on every pointer move. */
|
|
1251
1422
|
declare function useHoverTracking(args: UseHoverTrackingArgs): () => NodeId | null;
|
|
1252
1423
|
|
|
1424
|
+
/**
|
|
1425
|
+
* Project an action's keyboard bindings into the shape a shortcut chip
|
|
1426
|
+
* renders from (`formatShortcut` / `formatShortcutParts` in
|
|
1427
|
+
* `@weasel-js/ui`). Palette and menu surfaces show what an action answers
|
|
1428
|
+
* to; the dispatcher reads the specs themselves.
|
|
1429
|
+
*/
|
|
1430
|
+
|
|
1431
|
+
/** One keyboard shortcut, flattened for display. Structurally the
|
|
1432
|
+
* `ShortcutInput` weasel-ui formats — kept local so core doesn't depend on
|
|
1433
|
+
* the UI package. */
|
|
1434
|
+
interface ActionShortcut {
|
|
1435
|
+
key: string;
|
|
1436
|
+
mod: boolean;
|
|
1437
|
+
alt: boolean;
|
|
1438
|
+
shift: boolean;
|
|
1439
|
+
}
|
|
1440
|
+
/**
|
|
1441
|
+
* The chip form of a single gesture spec, or `undefined` when the spec has
|
|
1442
|
+
* none.
|
|
1443
|
+
*
|
|
1444
|
+
* Two kinds of collapsing, both because a binding list is written for a
|
|
1445
|
+
* matcher rather than for a reader:
|
|
1446
|
+
*
|
|
1447
|
+
* - A spec's `key` may list spellings of one keycap (`['[', '{']` — the
|
|
1448
|
+
* shifted bracket reports as `'{'`). The first is the shortcut's name.
|
|
1449
|
+
* - A modifier declared `'optional'` matches held or unheld, so it isn't
|
|
1450
|
+
* part of what the user has to press.
|
|
1451
|
+
*
|
|
1452
|
+
* Non-keyboard specs (drag, wheel, click) have no chip form. Neither does a
|
|
1453
|
+
* *required* `ctrl` or `meta` — nothing in the kit declares one, and the
|
|
1454
|
+
* display shape carries only `mod`.
|
|
1455
|
+
*/
|
|
1456
|
+
declare function keySpecShortcut(spec: GestureSpec): ActionShortcut | undefined;
|
|
1457
|
+
/**
|
|
1458
|
+
* Every keyboard shortcut an action answers to, in declaration order.
|
|
1459
|
+
* Specs `keySpecShortcut` has no chip for are skipped, and bindings it leaves
|
|
1460
|
+
* identical are emitted once; an action bound only to those returns empty.
|
|
1461
|
+
*/
|
|
1462
|
+
declare function actionShortcuts(action: Action): readonly ActionShortcut[];
|
|
1463
|
+
|
|
1253
1464
|
/**
|
|
1254
1465
|
* `moveAction` — first `ongoing`-timing Action descriptor.
|
|
1255
1466
|
*
|
|
1256
1467
|
* Mirrors the per-frame translate semantics of the `useMove` hook:
|
|
1257
1468
|
* - `start`: capture origin poses for all selected nodes; record the
|
|
1258
1469
|
* current drag delta in scratch each frame.
|
|
1259
|
-
* - `onMove`: update the in-scratch `currentDelta
|
|
1260
|
-
*
|
|
1470
|
+
* - `onMove`: update the in-scratch `currentDelta`, and publish the frame's
|
|
1471
|
+
* poses as ephemeral overrides. No *document* writes, so the undo stack
|
|
1472
|
+
* still sees one entry for the whole drag.
|
|
1261
1473
|
* - `onEnd('commit')`: emit the final delta as transform ops and route
|
|
1262
1474
|
* them through the consumer `applyOps` hook when present, else
|
|
1263
1475
|
* `scene.applyBatch(ops, 'Move', adapter)` — either way a single batch
|
|
1264
1476
|
* → exactly one undo entry for the whole drag.
|
|
1265
|
-
* - `onEnd('cancel')`:
|
|
1266
|
-
* the
|
|
1477
|
+
* - `onEnd('cancel')`: drop the overrides — the document was never mutated,
|
|
1478
|
+
* so the committed poses are the restoration.
|
|
1267
1479
|
*
|
|
1268
|
-
* ## Why no per-frame
|
|
1480
|
+
* ## Why no per-frame document writes
|
|
1269
1481
|
*
|
|
1270
1482
|
* `Scene.setPose` calls `executeAndLog`, which immediately records an undo
|
|
1271
|
-
* entry on the scene's history engine. Per-frame writes during drag would
|
|
1272
|
-
* O(frames) history entries
|
|
1273
|
-
*
|
|
1274
|
-
*
|
|
1483
|
+
* entry on the scene's history engine. Per-frame writes during drag would
|
|
1484
|
+
* create O(frames) history entries, so the drag commits one
|
|
1485
|
+
* `createTransformOp` batch at the end.
|
|
1486
|
+
*
|
|
1487
|
+
* The per-frame poses still go *somewhere* the scene can see: the ephemeral
|
|
1488
|
+
* override table, which bypasses history entirely. That is what lets a node
|
|
1489
|
+
* deriving its geometry from a dragged one follow the drag — `scenePoseLookup`
|
|
1490
|
+
* and the pick source both read overrides, and neither can see this action's
|
|
1491
|
+
* scratch. Keeping the frame in scratch alone is why the edge used to stay
|
|
1492
|
+
* anchored to the old endpoint and jump on drop.
|
|
1275
1493
|
*
|
|
1276
1494
|
* The behavior pipeline (snap-to-grid, snap-back-or-delete, snap-to-container,
|
|
1277
1495
|
* etc.) via `opts.behaviors` from `BindingOpts` IS wired: `start` builds a
|
|
@@ -1680,7 +1898,10 @@ declare const viewportDragPanAction: Action & {
|
|
|
1680
1898
|
*
|
|
1681
1899
|
* ## Bindings (parametric — each passes `params.kind`)
|
|
1682
1900
|
* - `{ kind: 'wheel', mods: { mod: true } }` → Cmd+wheel, params: `{ kind: 'wheel' }`
|
|
1683
|
-
*
|
|
1901
|
+
* - `{ kind: 'wheel', mods: { ctrl: true } }` → trackpad pinch, params: `{ kind: 'wheel' }`.
|
|
1902
|
+
* Browsers synthesize a trackpad pinch as ctrl+wheel. On a Mac that is a
|
|
1903
|
+
* *different* event from the `mod` binding above (`mod` is metaKey there), so
|
|
1904
|
+
* pinch needs its own binding or nothing claims it and the page zooms instead.
|
|
1684
1905
|
* - `{ kind: 'key', key: '=' }` → zoom in, params: `{ kind: 'in' }`
|
|
1685
1906
|
* - `{ kind: 'key', key: '-' }` → zoom out, params: `{ kind: 'out' }`
|
|
1686
1907
|
* - `{ kind: 'key', key: '0' }` → reset zoom, params: `{ kind: 'reset' }`
|
|
@@ -1694,13 +1915,27 @@ declare const viewportDragPanAction: Action & {
|
|
|
1694
1915
|
* - `'in'`/`'out'`: step zoom by ×1.25 / ×0.8, anchored at the host center
|
|
1695
1916
|
* when the `view` dep wires `hostSize()` (SceneCanvas does), falling back
|
|
1696
1917
|
* to the canvas top-left origin for consumers that don't.
|
|
1697
|
-
* - `'reset'`: resets scale to 1, translation to 0
|
|
1918
|
+
* - `'reset'`: resets scale to 1, translation to 0, or calls the `view` dep's
|
|
1919
|
+
* `recenter()`.
|
|
1920
|
+
*
|
|
1921
|
+
* The three discrete branches glide instead of jumping when the `animate`
|
|
1922
|
+
* option is configured and the `view` dep implements `animate` — they hand the
|
|
1923
|
+
* action a target and nothing in between, which is the whole condition for
|
|
1924
|
+
* tweening. `'wheel'` always jumps per sample.
|
|
1698
1925
|
*
|
|
1699
1926
|
* ## Key binding modifier notes
|
|
1700
1927
|
* The key bindings (`=`, `-`, `0`) require `mod: true` (Cmd on Mac, Ctrl elsewhere).
|
|
1701
1928
|
* This matches the behaviour of the dissolved `useKeyboardZoomTool`.
|
|
1702
1929
|
*/
|
|
1703
1930
|
|
|
1931
|
+
/**
|
|
1932
|
+
* @experimental
|
|
1933
|
+
* Tuning for the animated form of the discrete zoom steps.
|
|
1934
|
+
*/
|
|
1935
|
+
interface ViewportZoomAnimateOptions extends ViewAnimationOptions {
|
|
1936
|
+
/** Duration for the Cmd+0 reset branch. Defaults to `ms`. */
|
|
1937
|
+
resetMs?: number;
|
|
1938
|
+
}
|
|
1704
1939
|
/**
|
|
1705
1940
|
* @experimental
|
|
1706
1941
|
* Tuning for {@link makeViewportZoomAction}.
|
|
@@ -1709,7 +1944,8 @@ interface ViewportZoomOptions {
|
|
|
1709
1944
|
/**
|
|
1710
1945
|
* Which wheel gesture triggers zoom.
|
|
1711
1946
|
* - `'mod'` (default): Cmd/Ctrl+wheel — coexists with plain-wheel pan
|
|
1712
|
-
* (`viewport.wheelPan`)
|
|
1947
|
+
* (`viewport.wheelPan`). A Mac trackpad pinch arrives as ctrl+wheel, which
|
|
1948
|
+
* `mod: true` forbids on Mac; nothing here handles it.
|
|
1713
1949
|
* - `'plain'`: bare wheel, no modifier. Pair with `viewport.pan: false`,
|
|
1714
1950
|
* since plain wheel otherwise drives pan and the two would compete.
|
|
1715
1951
|
*/
|
|
@@ -1718,6 +1954,13 @@ interface ViewportZoomOptions {
|
|
|
1718
1954
|
min?: number;
|
|
1719
1955
|
/** Upper clamp on the resulting view scale, forwarded to `zoomAt`. Default 8. */
|
|
1720
1956
|
max?: number;
|
|
1957
|
+
/**
|
|
1958
|
+
* Glide the discrete steps (Cmd+=, Cmd+-, Cmd+0) instead of jumping.
|
|
1959
|
+
* `true` uses the kit defaults; an object tunes them. Wheel and pinch never
|
|
1960
|
+
* animate — their input already samples every frame. Requires a `view` dep
|
|
1961
|
+
* that implements `animate`; without one this is ignored.
|
|
1962
|
+
*/
|
|
1963
|
+
animate?: boolean | ViewportZoomAnimateOptions;
|
|
1721
1964
|
}
|
|
1722
1965
|
/**
|
|
1723
1966
|
* @experimental
|
|
@@ -1865,12 +2108,31 @@ declare const lassoSelectAction: Action & {
|
|
|
1865
2108
|
|
|
1866
2109
|
/**
|
|
1867
2110
|
* @experimental
|
|
1868
|
-
*
|
|
2111
|
+
* Tuning for {@link makePinchZoomAction}.
|
|
2112
|
+
*/
|
|
2113
|
+
interface PinchZoomOptions {
|
|
2114
|
+
/** Lower clamp on the resulting view scale, forwarded to `zoomAt`. Default 0.1. */
|
|
2115
|
+
min?: number;
|
|
2116
|
+
/** Upper clamp on the resulting view scale, forwarded to `zoomAt`. Default 8. */
|
|
2117
|
+
max?: number;
|
|
2118
|
+
}
|
|
2119
|
+
/**
|
|
2120
|
+
* @experimental
|
|
2121
|
+
* Build a `viewport.pinchZoom` Action descriptor with a configurable scale
|
|
2122
|
+
* clamp. The binding (two-finger multitouch) is fixed; only the clamp varies.
|
|
1869
2123
|
*
|
|
1870
2124
|
* Requires dep-schema entries: `view`.
|
|
1871
2125
|
*
|
|
1872
2126
|
* The invoker is `ongoing`. Zoom is applied per-frame via `view.set(zoomAt(...))`.
|
|
1873
2127
|
*/
|
|
2128
|
+
declare function makePinchZoomAction(opts?: PinchZoomOptions): Action & {
|
|
2129
|
+
requires: string[];
|
|
2130
|
+
};
|
|
2131
|
+
/**
|
|
2132
|
+
* @experimental
|
|
2133
|
+
* Default `viewport.pinchZoom` descriptor: two-finger pinch with the kit's
|
|
2134
|
+
* default 0.1–8 scale clamp. Equivalent to `makePinchZoomAction()`.
|
|
2135
|
+
*/
|
|
1874
2136
|
declare const pinchZoomAction: Action & {
|
|
1875
2137
|
requires: string[];
|
|
1876
2138
|
};
|
|
@@ -1916,10 +2178,9 @@ declare function useStandardActions(opts: UseStandardActionsOptions): void;
|
|
|
1916
2178
|
* this adapter. It carries the scene-backed op-apply methods (`setPose` /
|
|
1917
2179
|
* `setParent` / `setData` / `setLayer` / `removeNode` / `insertNode` /
|
|
1918
2180
|
* `setChildOrder`) plus the read-side queries (`getNode` / `getNodes` /
|
|
1919
|
-
* `getPose` / `getParent` / `getChildren`
|
|
1920
|
-
*
|
|
1921
|
-
*
|
|
1922
|
-
* ops must replay), `setPath`, and `setText`.
|
|
2181
|
+
* `getPose` / `getParent` / `getChildren` / `getSelection`) and
|
|
2182
|
+
* `setSelection`. Known exclusions from the op factory roster — surfaces the
|
|
2183
|
+
* scene doesn't own: `setPath` and `setText`.
|
|
1923
2184
|
*
|
|
1924
2185
|
* Lives in `interactions/actions/` (not `canvas/sceneAdapter.ts`) so default
|
|
1925
2186
|
* actions never import from `canvas/` — that back-edge would create an
|
|
@@ -1929,12 +2190,14 @@ declare function useStandardActions(opts: UseStandardActionsOptions): void;
|
|
|
1929
2190
|
|
|
1930
2191
|
/** Build the adapter the default actions commit through when the consumer
|
|
1931
2192
|
* supplies no `applyOps` hook of its own — it applies ops straight to the
|
|
1932
|
-
* scene.
|
|
1933
|
-
*
|
|
2193
|
+
* scene. Path and text ops are not covered; those surfaces belong to their
|
|
2194
|
+
* own owners. */
|
|
1934
2195
|
declare function defaultCommitAdapter<TPose>(scene: Scene<unknown, string, TPose>): {
|
|
1935
2196
|
getNode: (id: string) => Node$1<unknown, string, TPose> | undefined;
|
|
1936
2197
|
getNodes: () => Node$1<unknown, string, TPose>[];
|
|
1937
2198
|
getPose: (id: string) => TPose;
|
|
2199
|
+
getSelection: () => string[];
|
|
2200
|
+
setSelection: (ids: string[]) => void;
|
|
1938
2201
|
getParent: (id: string) => string | null;
|
|
1939
2202
|
getChildren: (parentId: string | null) => string[];
|
|
1940
2203
|
setChildOrder: (parentId: string | null, orderedIds: string[]) => void;
|
|
@@ -1962,6 +2225,63 @@ declare function useResizePolicy<TPose>(options: UseResizePolicyOptions<TPose>):
|
|
|
1962
2225
|
* run against the consumer's geometry. */
|
|
1963
2226
|
declare function useSliceDep(dep: SliceDep): void;
|
|
1964
2227
|
|
|
2228
|
+
/**
|
|
2229
|
+
* Everything about handling an input event that depends on *which view* it
|
|
2230
|
+
* landed in: the dispatcher that runs it, and the three lookups that resolve
|
|
2231
|
+
* a client point against that view's camera.
|
|
2232
|
+
*
|
|
2233
|
+
* @internal One per view. The hook builds the `id: null` one from its flat
|
|
2234
|
+
* options; `views` supplies the rest, and the hook chooses between them per
|
|
2235
|
+
* event, so that it — and its listener set — still mounts exactly once.
|
|
2236
|
+
*/
|
|
2237
|
+
interface DispatcherViewTarget {
|
|
2238
|
+
/** `null` is the root view — the whole canvas. Matches `ViewTarget.id`. */
|
|
2239
|
+
id: string | null;
|
|
2240
|
+
dispatcher: Dispatcher;
|
|
2241
|
+
affordanceAt: UseGestureDispatcherOptions['affordanceAt'];
|
|
2242
|
+
classifyTarget: UseGestureDispatcherOptions['classifyTarget'];
|
|
2243
|
+
clientToWorld: UseGestureDispatcherOptions['clientToWorld'];
|
|
2244
|
+
/**
|
|
2245
|
+
* The deps this view answers for itself — its camera, its selection, and
|
|
2246
|
+
* whatever else is per-view rather than per-canvas. Read per event; every
|
|
2247
|
+
* name it does not carry still resolves through the canvas registry.
|
|
2248
|
+
*
|
|
2249
|
+
* This is why a view does not get a `DepRegistryProvider` of its own. The
|
|
2250
|
+
* registry is where a consumer registers *sources*, and one per view would
|
|
2251
|
+
* fragment that: a consumer overriding `insert` would have to know how many
|
|
2252
|
+
* views exist and override each. An overlay keeps one place to register and
|
|
2253
|
+
* one authority per dep, with the view claiming only what is genuinely its.
|
|
2254
|
+
*
|
|
2255
|
+
* Without this a gesture inside a panel pans the whole canvas and selects
|
|
2256
|
+
* into the canvas's selection — correct coordinates alone do not make
|
|
2257
|
+
* routing correct.
|
|
2258
|
+
*/
|
|
2259
|
+
deps?: () => Partial<DepSchema>;
|
|
2260
|
+
/**
|
|
2261
|
+
* This view's chrome-caps rule context, for the eligibility filter. The rule
|
|
2262
|
+
* table is the surface's, but a rule keyed on selection or the in-flight
|
|
2263
|
+
* action answers per view — so an action hidden in one panel must not
|
|
2264
|
+
* decline a gesture in another. `undefined` means "nothing gates here", the
|
|
2265
|
+
* same answer a surface with no mode registry gives.
|
|
2266
|
+
*/
|
|
2267
|
+
getRuleCtx?: () => RuleCtx | undefined;
|
|
2268
|
+
}
|
|
2269
|
+
/**
|
|
2270
|
+
* The part of `features/viewports`' `ViewResolver` the dispatcher needs: which
|
|
2271
|
+
* view a client point belongs to, pinned to the view a gesture began in.
|
|
2272
|
+
*
|
|
2273
|
+
* @internal Structural on purpose — a `ViewResolver` satisfies it, and the
|
|
2274
|
+
* dispatcher stays free of the viewport module.
|
|
2275
|
+
*/
|
|
2276
|
+
interface ViewIdResolver {
|
|
2277
|
+
begin(pointerId: number, clientX: number, clientY: number): {
|
|
2278
|
+
id: string | null;
|
|
2279
|
+
};
|
|
2280
|
+
at(pointerId: number | null, clientX: number, clientY: number): {
|
|
2281
|
+
id: string | null;
|
|
2282
|
+
};
|
|
2283
|
+
end(pointerId: number): void;
|
|
2284
|
+
}
|
|
1965
2285
|
/** Options for `useGestureDispatcher`: the element to listen on, the actions
|
|
1966
2286
|
* and tools in play, and the hooks that turn raw DOM events into the world
|
|
1967
2287
|
* coordinates and hit targets bindings match against. */
|
|
@@ -2088,7 +2408,25 @@ interface UseGestureDispatcherOptions {
|
|
|
2088
2408
|
* `Action.eligible` rule (omitted => always eligible). `<SceneCanvas>`
|
|
2089
2409
|
* wires this; tests / harnesses without chrome-caps state can omit it.
|
|
2090
2410
|
*/
|
|
2091
|
-
getRuleCtx?: () => RuleCtx;
|
|
2411
|
+
getRuleCtx?: () => RuleCtx | undefined;
|
|
2412
|
+
/**
|
|
2413
|
+
* Routing for a canvas hosting more than one view: the non-root dispatch
|
|
2414
|
+
* records to choose between, read fresh per event, and the resolver that
|
|
2415
|
+
* chooses. Omit for a single view — then every event runs on the record the
|
|
2416
|
+
* flat options above describe, which is what they are: view zero.
|
|
2417
|
+
*
|
|
2418
|
+
* A resolved id with no live record falls back to the root, so a view that
|
|
2419
|
+
* unmounts mid-gesture degrades instead of dropping the event.
|
|
2420
|
+
*
|
|
2421
|
+
* Keyboard and paste have no coordinates to resolve; they run on the view
|
|
2422
|
+
* the last coordinate-bearing event resolved to.
|
|
2423
|
+
*
|
|
2424
|
+
* @internal
|
|
2425
|
+
*/
|
|
2426
|
+
views?: {
|
|
2427
|
+
targets: () => readonly DispatcherViewTarget[];
|
|
2428
|
+
resolver: ViewIdResolver;
|
|
2429
|
+
};
|
|
2092
2430
|
}
|
|
2093
2431
|
/**
|
|
2094
2432
|
* Attach the input pipeline to a canvas: DOM pointer, wheel, keyboard and
|
|
@@ -2101,6 +2439,56 @@ interface UseGestureDispatcherOptions {
|
|
|
2101
2439
|
*/
|
|
2102
2440
|
declare function useGestureDispatcher(opts: UseGestureDispatcherOptions): void;
|
|
2103
2441
|
|
|
2442
|
+
/**
|
|
2443
|
+
* The one place weasel decides whether a frame may run, so that "a loop does no
|
|
2444
|
+
* work nobody can see" holds by construction rather than by every loop author
|
|
2445
|
+
* remembering. Nothing runs while the document is hidden; a loop that names an
|
|
2446
|
+
* element also stops while that element is outside the viewport.
|
|
2447
|
+
*
|
|
2448
|
+
* A request made while suspended is held, not dropped, and re-armed when the
|
|
2449
|
+
* surface comes back — so a loop never needs to poll visibility itself.
|
|
2450
|
+
*/
|
|
2451
|
+
|
|
2452
|
+
/** What a loop names as its element, resolved every time the gate is consulted
|
|
2453
|
+
* so a ref filled in after mount still starts the observer. */
|
|
2454
|
+
type VisibleRafTarget = RefObject<Element | null> | (() => Element | null);
|
|
2455
|
+
interface VisibleRafOptions {
|
|
2456
|
+
/** Also gate on this element's intersection with the viewport. Omit it and
|
|
2457
|
+
* the loop is gated on document visibility alone. */
|
|
2458
|
+
target?: VisibleRafTarget;
|
|
2459
|
+
/**
|
|
2460
|
+
* Run frames regardless of visibility. The escape hatch for a loop that is
|
|
2461
|
+
* not painting for a viewer — an offscreen recording, an export driving its
|
|
2462
|
+
* own frames. It is the wrong fix for a loop that stalls after a tab switch:
|
|
2463
|
+
* that is a missing `request()`, and setting this hides it.
|
|
2464
|
+
*/
|
|
2465
|
+
dangerouslyRunWhenHidden?: boolean;
|
|
2466
|
+
/** Frame clock. Read live, so a test may inject one after mount. */
|
|
2467
|
+
requestFrame?: (cb: FrameRequestCallback) => number;
|
|
2468
|
+
cancelFrame?: (handle: number) => void;
|
|
2469
|
+
/**
|
|
2470
|
+
* Runs once when the loop leaves suspension, before the frame that follows
|
|
2471
|
+
* it. Where a loop that measures elapsed time drops the interval it spent
|
|
2472
|
+
* suspended — without it, an hour hidden arrives as one hour-long frame.
|
|
2473
|
+
*/
|
|
2474
|
+
onResume?: () => void;
|
|
2475
|
+
}
|
|
2476
|
+
interface VisibleRaf {
|
|
2477
|
+
/** Ask for a frame. Idempotent while one is outstanding, and held rather than
|
|
2478
|
+
* dropped while suspended. Identity is stable for the component's lifetime. */
|
|
2479
|
+
request(): void;
|
|
2480
|
+
/** Drop the outstanding request, held or scheduled. */
|
|
2481
|
+
cancel(): void;
|
|
2482
|
+
/** Whether a frame would run right now. */
|
|
2483
|
+
isVisible(): boolean;
|
|
2484
|
+
}
|
|
2485
|
+
/**
|
|
2486
|
+
* @param frame Runs on the frame, with the timestamp the clock supplied.
|
|
2487
|
+
* A continuous loop calls `request()` again from inside it; a one-shot loop
|
|
2488
|
+
* does not.
|
|
2489
|
+
*/
|
|
2490
|
+
declare function useVisibleRaf(frame: (time: number) => void, options?: VisibleRafOptions): VisibleRaf;
|
|
2491
|
+
|
|
2104
2492
|
/**
|
|
2105
2493
|
* Pure wheel-event reducer. Stateless sibling of `useZoom`'s
|
|
2106
2494
|
* `onWheel` handler — useful in tests, in non-React reducers, or anywhere
|
|
@@ -2194,17 +2582,6 @@ declare function useDecayLoop(): {
|
|
|
2194
2582
|
cancel: () => void;
|
|
2195
2583
|
};
|
|
2196
2584
|
|
|
2197
|
-
/** Animate the view from where it is to a target view — zoom-to-fit,
|
|
2198
|
-
* zoom-to-selection, and anything else that should glide rather than jump. */
|
|
2199
|
-
declare function useViewTween(setView: (v: View) => void): {
|
|
2200
|
-
animateTo: (from: View, to: View, opts?: {
|
|
2201
|
-
duration?: number;
|
|
2202
|
-
easing?: (t: number) => number;
|
|
2203
|
-
}) => void;
|
|
2204
|
-
cancel: () => void;
|
|
2205
|
-
isAnimating: React$1.RefObject<boolean>;
|
|
2206
|
-
};
|
|
2207
|
-
|
|
2208
2585
|
/**
|
|
2209
2586
|
* Detects two-finger pinch on a canvas element.
|
|
2210
2587
|
*
|
|
@@ -2218,31 +2595,11 @@ declare function usePinchGesture(canvasRef: React.RefObject<HTMLCanvasElement |
|
|
|
2218
2595
|
y: number;
|
|
2219
2596
|
}, scaleFactor: number) => void, enabled?: boolean): void;
|
|
2220
2597
|
|
|
2221
|
-
/** Options accepted by {@link useViewAnimation}'s `animateToBounds`. */
|
|
2222
|
-
interface AnimateToBoundsOptions extends FitViewToBoundsOptions {
|
|
2223
|
-
/** Tween duration in ms (forwarded to `animateTo`). */
|
|
2224
|
-
duration?: number;
|
|
2225
|
-
/** Tween easing (forwarded to `animateTo`). */
|
|
2226
|
-
easing?: (t: number) => number;
|
|
2227
|
-
}
|
|
2228
2598
|
/**
|
|
2229
|
-
*
|
|
2230
|
-
*
|
|
2231
|
-
* `fitViewToBounds` with the existing tween so consumers can say "zoom to this
|
|
2232
|
-
* bounds with animation" in one call.
|
|
2233
|
-
*
|
|
2234
|
-
* `animateToBounds` needs the current `View` and the current viewport
|
|
2235
|
-
* dimensions to compute the target — both are passed as arguments so this
|
|
2236
|
-
* hook stays a leaf (no canvas-size subscription, no `View` storage).
|
|
2599
|
+
* `InterpolatorFactory<View>` for camera animation — built once per animation,
|
|
2600
|
+
* called with eased `t` each frame. Pass to `Animator.tween`'s `interpolator`.
|
|
2237
2601
|
*/
|
|
2238
|
-
declare function
|
|
2239
|
-
animateTo: (from: View, to: View, opts?: {
|
|
2240
|
-
duration?: number;
|
|
2241
|
-
easing?: (t: number) => number;
|
|
2242
|
-
}) => void;
|
|
2243
|
-
animateToBounds: (bounds: Bounds, currentView: View, viewportDims: ViewportDims, opts?: AnimateToBoundsOptions) => void;
|
|
2244
|
-
cancel: () => void;
|
|
2245
|
-
};
|
|
2602
|
+
declare function interpolateView(from: View, to: View): (t: number) => View;
|
|
2246
2603
|
|
|
2247
2604
|
/**
|
|
2248
2605
|
* Build a `Tool<TScratch>` from a declarative `ToolDef<TScratch>`.
|
|
@@ -2358,7 +2715,7 @@ interface UseKeybindingsOptions {
|
|
|
2358
2715
|
declare function useKeybindings(tools: ToolsApi, options?: UseKeybindingsOptions): void;
|
|
2359
2716
|
|
|
2360
2717
|
/** The value types a built-in pref leaf can hold. */
|
|
2361
|
-
type ToolPrefKind = 'number' | 'boolean' | 'string' | 'enum' | 'color' | 'paint';
|
|
2718
|
+
type ToolPrefKind = 'number' | 'boolean' | 'string' | 'enum' | 'color' | 'paint' | 'object';
|
|
2362
2719
|
interface ToolPrefBase<K extends string, Value> {
|
|
2363
2720
|
kind: K;
|
|
2364
2721
|
/** Human-readable label. */
|
|
@@ -2373,6 +2730,12 @@ interface ToolPrefBase<K extends string, Value> {
|
|
|
2373
2730
|
* (weasel-ui `PrefsForm` honors this for leaves whose control brings
|
|
2374
2731
|
* its own chrome). */
|
|
2375
2732
|
block?: boolean;
|
|
2733
|
+
/** Glyph naming this leaf in a host UI's icon set (weasel-ui resolves it
|
|
2734
|
+
* against `ICON_PATHS`). A plain string because core ships no icon set and
|
|
2735
|
+
* cannot depend on one. Read where a leaf's `name` has nowhere to go — a
|
|
2736
|
+
* `pair`ed row is labeled by the pair, so its fields have only the glyph
|
|
2737
|
+
* to tell them apart. */
|
|
2738
|
+
icon?: string;
|
|
2376
2739
|
/** Row-pairing hint for compact property UIs (weasel-ui
|
|
2377
2740
|
* `SelectionPanel`): leaves sharing a `pair` id render side-by-side
|
|
2378
2741
|
* on one row labeled with the `pair` string (e.g. `'Position'` for
|
|
@@ -2386,7 +2749,7 @@ type ToolPrefBooleanControl = 'checkbox' | 'switch';
|
|
|
2386
2749
|
/** How a schema-driven UI should present a string pref. */
|
|
2387
2750
|
type ToolPrefStringControl = 'input' | 'textarea';
|
|
2388
2751
|
/** How a schema-driven UI should present an enum pref. */
|
|
2389
|
-
type ToolPrefEnumControl = 'select' | 'radio';
|
|
2752
|
+
type ToolPrefEnumControl = 'select' | 'radio' | 'toggle';
|
|
2390
2753
|
/** Display-unit conversion for number leaves whose stored value uses a
|
|
2391
2754
|
* canonical unit the user shouldn't see (e.g. radians stored, degrees
|
|
2392
2755
|
* shown). The stored value stays canonical; UIs convert at the edge. */
|
|
@@ -2413,13 +2776,51 @@ interface ToolPrefBoolean extends ToolPrefBase<'boolean', boolean> {
|
|
|
2413
2776
|
interface ToolPrefString extends ToolPrefBase<'string', string> {
|
|
2414
2777
|
control?: ToolPrefStringControl;
|
|
2415
2778
|
}
|
|
2779
|
+
/**
|
|
2780
|
+
* Stored-value bridge for an enum leaf whose value is not the option string —
|
|
2781
|
+
* the counterpart of {@link ToolPrefNumberUnit}, which does the same for a
|
|
2782
|
+
* number stored in a canonical unit.
|
|
2783
|
+
*
|
|
2784
|
+
* A dash array is the case that needs it: `Stroke.dash` stores lengths, and
|
|
2785
|
+
* the thing a person chooses is a style. The presets scale by the stroke's
|
|
2786
|
+
* width, so both directions are given the object's other fields — a style is
|
|
2787
|
+
* meaningless without the width it is a multiple of.
|
|
2788
|
+
*/
|
|
2789
|
+
interface ToolPrefEnumEncoding<T extends string = string> {
|
|
2790
|
+
/**
|
|
2791
|
+
* The option `stored` reads as, or `undefined` for none — which a UI shows
|
|
2792
|
+
* the way it shows a mixed selection, by selecting nothing.
|
|
2793
|
+
*
|
|
2794
|
+
* `siblings` is the object the leaf is a field of, or `undefined` when the
|
|
2795
|
+
* node does not hold that object (and for a top-level leaf, which has none).
|
|
2796
|
+
*/
|
|
2797
|
+
read: (stored: unknown, siblings: Record<string, unknown> | undefined) => T | undefined;
|
|
2798
|
+
/** What to store for `option`. `undefined` removes the field. */
|
|
2799
|
+
write: (option: T, siblings: Record<string, unknown> | undefined) => unknown;
|
|
2800
|
+
}
|
|
2416
2801
|
/** A pref with a fixed set of labeled choices. */
|
|
2417
2802
|
interface ToolPrefEnum<T extends string = string> extends ToolPrefBase<'enum', T> {
|
|
2803
|
+
/** `short` is the label a segmented control uses when a full one would not
|
|
2804
|
+
* fit — a capital or two. `icon` names a glyph in the host UI's set
|
|
2805
|
+
* (weasel-ui resolves it against `ICON_PATHS`) and outranks `short` where
|
|
2806
|
+
* it resolves. It is a plain string because core ships no icon set and
|
|
2807
|
+
* cannot depend on one. The full `label` stays the accessible name, so
|
|
2808
|
+
* neither the abbreviation nor the glyph becomes the only thing naming
|
|
2809
|
+
* the option.
|
|
2810
|
+
*
|
|
2811
|
+
* `disabled` marks an option a control reports but cannot author — the
|
|
2812
|
+
* value a stored form reads as when it matches nothing offered. Dropping it
|
|
2813
|
+
* from the list instead would leave the control selecting nothing and
|
|
2814
|
+
* claiming the field is unset. */
|
|
2418
2815
|
options: readonly {
|
|
2419
2816
|
value: T;
|
|
2420
2817
|
label: string;
|
|
2818
|
+
short?: string;
|
|
2819
|
+
icon?: string;
|
|
2820
|
+
disabled?: boolean;
|
|
2421
2821
|
}[];
|
|
2422
2822
|
control?: ToolPrefEnumControl;
|
|
2823
|
+
encoding?: ToolPrefEnumEncoding<T>;
|
|
2423
2824
|
}
|
|
2424
2825
|
/** A single color, stored as a hex string. For a value that may also be a
|
|
2425
2826
|
* gradient or a pattern, use {@link ToolPrefPaint} instead. */
|
|
@@ -2434,8 +2835,7 @@ interface ToolPrefColor extends ToolPrefBase<'color', string> {
|
|
|
2434
2835
|
* app-supplied renderer. Deliberately NOT index-signatured so concrete
|
|
2435
2836
|
* app interfaces stay assignable. Mirrors weasel-ui's `PrefCustom`.
|
|
2436
2837
|
*/
|
|
2437
|
-
|
|
2438
|
-
}
|
|
2838
|
+
type ToolPrefCustom = ToolPrefBase<string, unknown>;
|
|
2439
2839
|
/**
|
|
2440
2840
|
* A whole `FillStyle`, not a color inside one. Use it wherever the value is
|
|
2441
2841
|
* the tagged paint union — a solid color, a pattern, a gradient — rather
|
|
@@ -2451,13 +2851,60 @@ interface ToolPrefPaint extends ToolPrefBase<'paint', unknown> {
|
|
|
2451
2851
|
/** Offer an opacity control alongside the color. */
|
|
2452
2852
|
alpha?: boolean;
|
|
2453
2853
|
}
|
|
2854
|
+
/**
|
|
2855
|
+
* A leaf whose value is one object, with its own fields hanging off it.
|
|
2856
|
+
*
|
|
2857
|
+
* A compound value — a stroke, a shadow, a pattern spec — could be described
|
|
2858
|
+
* as several sibling leaves addressing into it (`data.stroke.width`,
|
|
2859
|
+
* `data.stroke.cap`). It shouldn't be: each control would then write one field
|
|
2860
|
+
* of a value it can only half see, and writing into something that is not an
|
|
2861
|
+
* object yet corrupts it. Here the fields are `children` of one leaf, and
|
|
2862
|
+
* every edit commits the parent object whole.
|
|
2863
|
+
*
|
|
2864
|
+
* `children` paths are relative to the object. They are ordinary leaves, so a
|
|
2865
|
+
* field that is itself a union (a stroke's `paint`) declares the kind that
|
|
2866
|
+
* edits that union. A child may also be a {@link ToolPrefGroup}, which
|
|
2867
|
+
* organises the fields under a heading without contributing to the path —
|
|
2868
|
+
* the same rule group keys follow at the top level. A `TextStyle` needs it:
|
|
2869
|
+
* its character and paragraph fields belong to one value but read as two
|
|
2870
|
+
* lists.
|
|
2871
|
+
*/
|
|
2872
|
+
interface ToolPrefObject extends ToolPrefBase<'object', unknown> {
|
|
2873
|
+
children: Record<string, ToolPrefLeaf | ToolPrefGroup>;
|
|
2874
|
+
/**
|
|
2875
|
+
* Lift a non-object value into the object form, for a consumer field that
|
|
2876
|
+
* may also be held as a scalar. Called before a child edit is applied;
|
|
2877
|
+
* without it a scalar-valued leaf shows its children empty and refuses the
|
|
2878
|
+
* edit.
|
|
2879
|
+
*/
|
|
2880
|
+
fromScalar?: (value: unknown) => Record<string, unknown>;
|
|
2881
|
+
}
|
|
2454
2882
|
/** One built-in pref leaf. `ToolPrefLeaf` widens this to include
|
|
2455
2883
|
* app-defined kinds. */
|
|
2456
|
-
type ToolPref = ToolPrefNumber | ToolPrefBoolean | ToolPrefString | ToolPrefEnum | ToolPrefColor | ToolPrefPaint;
|
|
2884
|
+
type ToolPref = ToolPrefNumber | ToolPrefBoolean | ToolPrefString | ToolPrefEnum | ToolPrefColor | ToolPrefPaint | ToolPrefObject;
|
|
2885
|
+
/**
|
|
2886
|
+
* The built-in kinds, as a table. A kind added to {@link ToolPrefKind} is a
|
|
2887
|
+
* compile error here, and from here it is one in every renderer's `never`
|
|
2888
|
+
* guard — the only thing standing between a new kind and rendering as
|
|
2889
|
+
* nothing in four places at once.
|
|
2890
|
+
*/
|
|
2891
|
+
declare const TOOL_PREF_KINDS: Record<ToolPrefKind, true>;
|
|
2892
|
+
/**
|
|
2893
|
+
* Narrows a leaf to the built-in union, so a renderer's switch discriminates
|
|
2894
|
+
* on {@link ToolPrefKind} instead of the open `string` that
|
|
2895
|
+
* {@link ToolPrefCustom} widens `kind` to. An app-defined kind answers false
|
|
2896
|
+
* and belongs to the renderer's custom-renderer path.
|
|
2897
|
+
*/
|
|
2898
|
+
declare function isBuiltinToolPref(leaf: ToolPrefLeaf): leaf is ToolPref;
|
|
2457
2899
|
/** Built-in or app-defined leaf. */
|
|
2458
2900
|
type ToolPrefLeaf = ToolPref | ToolPrefCustom;
|
|
2459
2901
|
/** Nestable group: branch nodes a tool can use to organize its prefs. */
|
|
2460
2902
|
interface ToolPrefGroup {
|
|
2903
|
+
/** Heading for the group's rows. **Empty means no heading** — for a group
|
|
2904
|
+
* that exists to organise, not to name: one whose children are themselves
|
|
2905
|
+
* groups carrying the labels a reader needs. Give it a name whenever the
|
|
2906
|
+
* name is the referent (a `Border` group over `Top` / `Right` / `Bottom`
|
|
2907
|
+
* reads as nothing without it). */
|
|
2461
2908
|
name: string;
|
|
2462
2909
|
description?: string;
|
|
2463
2910
|
children: Record<string, ToolPrefLeaf | ToolPrefGroup>;
|
|
@@ -2558,8 +3005,8 @@ declare function useSelectTool<TNode extends {
|
|
|
2558
3005
|
id: string;
|
|
2559
3006
|
}, TPose>(adapter: SelectAdapter<TNode, TPose>, options: UseSelectToolOptions<TPose>): Tool<null>;
|
|
2560
3007
|
|
|
2561
|
-
/** Options for `useRotateTool` — mostly the placement
|
|
2562
|
-
*
|
|
3008
|
+
/** Options for `useRotateTool` — mostly the placement of the rotation
|
|
3009
|
+
* handle's hover band. */
|
|
2563
3010
|
interface UseRotateToolOptions<TNode extends {
|
|
2564
3011
|
id: string;
|
|
2565
3012
|
}, _TPose> {
|
|
@@ -2569,10 +3016,10 @@ interface UseRotateToolOptions<TNode extends {
|
|
|
2569
3016
|
* backwards-compat with consumers (notably `SceneCanvas`'s
|
|
2570
3017
|
* `rotateOptions`) that still pass a value. */
|
|
2571
3018
|
rotate?: unknown;
|
|
2572
|
-
/**
|
|
3019
|
+
/** Minimum thickness of the rotate band outside the selection AABB, in
|
|
3020
|
+
* screen px. Defaults to {@link ROTATION_HANDLE_BASE_PX}; `<SceneCanvas>`
|
|
3021
|
+
* passes the device-scaled value. */
|
|
2573
3022
|
rotationHandleDistance?: number;
|
|
2574
|
-
/** Square hit-radius for the rotation handle. Default: 8. */
|
|
2575
|
-
handleHitRadius?: number;
|
|
2576
3023
|
/** World-space bounds lookup. Required for the rotation affordance hit-test
|
|
2577
3024
|
* in consumers that wire a `boundsOf` source separately from the
|
|
2578
3025
|
* ChromeState-driven affordance pipeline. Retained for parity with
|
|
@@ -2706,12 +3153,29 @@ declare function useHandTool(opts?: UseHandToolOptions): Tool<HandScratch | null
|
|
|
2706
3153
|
* factories and hit gating belong on those deps, not on the tool. */
|
|
2707
3154
|
declare function useTextTool(): Tool<undefined>;
|
|
2708
3155
|
|
|
3156
|
+
/** The camera a pinch acts on, and the origin its anchor is measured from. */
|
|
3157
|
+
interface PinchZoomTarget {
|
|
3158
|
+
view: View;
|
|
3159
|
+
setView: (v: View) => void;
|
|
3160
|
+
/** Client-space origin of the surface this camera paints into. */
|
|
3161
|
+
origin: {
|
|
3162
|
+
left: number;
|
|
3163
|
+
top: number;
|
|
3164
|
+
};
|
|
3165
|
+
}
|
|
2709
3166
|
/** Options for `usePinchZoomTool`: the zoom limits, and whether it is wired
|
|
2710
3167
|
* at all. */
|
|
2711
3168
|
interface PinchZoomToolOpts {
|
|
2712
3169
|
min?: number;
|
|
2713
3170
|
max?: number;
|
|
2714
3171
|
enabled?: boolean;
|
|
3172
|
+
/**
|
|
3173
|
+
* Which camera the anchor point belongs to. Return `null` — or omit this —
|
|
3174
|
+
* for the canvas's own. A canvas hosting several views resolves the point
|
|
3175
|
+
* here, so a pinch inside a panel zooms the panel rather than the canvas
|
|
3176
|
+
* underneath it.
|
|
3177
|
+
*/
|
|
3178
|
+
resolveTarget?: (clientX: number, clientY: number) => PinchZoomTarget | null;
|
|
2715
3179
|
}
|
|
2716
3180
|
/**
|
|
2717
3181
|
* Two-finger pinch zoom on the canvas. Standalone hook (not a Tool record)
|
|
@@ -2719,8 +3183,12 @@ interface PinchZoomToolOpts {
|
|
|
2719
3183
|
*
|
|
2720
3184
|
* The anchor point under the gesture midpoint stays fixed on screen as the
|
|
2721
3185
|
* view scales.
|
|
3186
|
+
*
|
|
3187
|
+
* @param getView Read at gesture time, not at render time: each pinch move
|
|
3188
|
+
* applies a per-frame delta to the view the previous move produced, and the
|
|
3189
|
+
* canvas does not re-render between them.
|
|
2722
3190
|
*/
|
|
2723
|
-
declare function usePinchZoomTool(canvasRef: React.RefObject<HTMLCanvasElement | null>,
|
|
3191
|
+
declare function usePinchZoomTool(canvasRef: React.RefObject<HTMLCanvasElement | null>, getView: () => View, setView: (v: View) => void, opts?: PinchZoomToolOpts): void;
|
|
2724
3192
|
|
|
2725
3193
|
/**
|
|
2726
3194
|
* In-progress pen anchor. `outHandle` is set when the anchor was placed via
|
|
@@ -3132,6 +3600,35 @@ interface CanvasExtensionApi {
|
|
|
3132
3600
|
* (Replaces the pre-A2 pattern where `ref.current` directly *was* the element.) */
|
|
3133
3601
|
readonly element: HTMLCanvasElement | null;
|
|
3134
3602
|
requestRedraw(): void;
|
|
3603
|
+
/**
|
|
3604
|
+
* Run `fn` after every paint, on the frame that painted — for chrome that
|
|
3605
|
+
* must observe landed pixels (a loupe readback, a frame counter). Returns
|
|
3606
|
+
* an unsubscribe.
|
|
3607
|
+
*/
|
|
3608
|
+
subscribeFrame(fn: () => void): () => void;
|
|
3609
|
+
/** The current view. Readable mid-frame — this is the value the next paint
|
|
3610
|
+
* will use, not a value from the last React commit. */
|
|
3611
|
+
getView(): View;
|
|
3612
|
+
/**
|
|
3613
|
+
* Set the view without a React render: the ref updates now and the next
|
|
3614
|
+
* frame paints with it.
|
|
3615
|
+
*
|
|
3616
|
+
* Not applied locally when the canvas is controlled by a `view` prop — there
|
|
3617
|
+
* the prop is the authority and a local write would only desynchronize
|
|
3618
|
+
* pixels from props. The value still goes out through `onViewChange`, so a
|
|
3619
|
+
* controlled owner can honor it; without an `onViewChange` it is dropped.
|
|
3620
|
+
* Either way the canvas warns once per mount.
|
|
3621
|
+
*/
|
|
3622
|
+
setView(next: View | ((current: View) => View)): void;
|
|
3623
|
+
/** Called after each view change, for chrome that mirrors the camera — a
|
|
3624
|
+
* zoom readout, a minimap, DOM pinned to world coordinates. Returns an
|
|
3625
|
+
* unsubscribe. */
|
|
3626
|
+
subscribeView(fn: (view: View) => void): () => void;
|
|
3627
|
+
/** The `contentVersion` the current pixels were painted from — on
|
|
3628
|
+
* `<SceneCanvas>`, the scene version. Chrome in lockstep with canvas
|
|
3629
|
+
* content compares this against the version it is about to render and
|
|
3630
|
+
* defers a frame when they differ. `0` until the first paint lands. */
|
|
3631
|
+
getPaintedVersion(): number;
|
|
3135
3632
|
/** Register an externally-owned RenderLayer. The layer participates in the
|
|
3136
3633
|
* draw stack and, if it implements `hitTest`, in {@link hitTestExtras}. */
|
|
3137
3634
|
registerLayer(layer: RenderLayer<unknown>): () => void;
|
|
@@ -3148,8 +3645,17 @@ interface CanvasExtensionApi {
|
|
|
3148
3645
|
* `strength` carry through from the hit when the layer sets them.
|
|
3149
3646
|
* A layer's owner binds a `kindOf` predicate on that kind to claim the
|
|
3150
3647
|
* gesture; see `@weasel-js/hud` for the worked example.
|
|
3648
|
+
*
|
|
3649
|
+
* `frame` names the camera and surface size the point is expressed against.
|
|
3650
|
+
* Omit it for the canvas's own view — the only case until a caller routes
|
|
3651
|
+
* input to a viewport node, where the point is in that node's inner world
|
|
3652
|
+
* and a layer resolving screen-pixel tolerances needs its view and rect
|
|
3653
|
+
* size rather than the canvas's.
|
|
3151
3654
|
*/
|
|
3152
|
-
hitTestExtras(worldX: number, worldY: number
|
|
3655
|
+
hitTestExtras(worldX: number, worldY: number, frame?: {
|
|
3656
|
+
view: View;
|
|
3657
|
+
dims: Dims;
|
|
3658
|
+
}): {
|
|
3153
3659
|
layerId: string;
|
|
3154
3660
|
hit: LayerHit;
|
|
3155
3661
|
} | null;
|
|
@@ -3180,21 +3686,50 @@ interface SceneCanvasApi extends CanvasExtensionApi {
|
|
|
3180
3686
|
x: number;
|
|
3181
3687
|
y: number;
|
|
3182
3688
|
}): void;
|
|
3689
|
+
/**
|
|
3690
|
+
* Glide the camera to `to` rather than jumping there — a fit-to-selection, a
|
|
3691
|
+
* recenter, a scripted tour. A thunk receives the pending target when an
|
|
3692
|
+
* animation is already in flight, so steps compound. Any other view write
|
|
3693
|
+
* cancels it.
|
|
3694
|
+
*/
|
|
3695
|
+
animateView(to: View | ((base: View) => View), opts?: ViewAnimationOptions): void;
|
|
3696
|
+
/** Cancel a camera animation. The view stays where it is. */
|
|
3697
|
+
stopViewAnimation(): void;
|
|
3698
|
+
isViewAnimating(): boolean;
|
|
3183
3699
|
}
|
|
3184
3700
|
|
|
3185
3701
|
/**
|
|
3186
|
-
*
|
|
3702
|
+
* The seam `<Canvas>` reads in-flight gesture state through.
|
|
3187
3703
|
*
|
|
3188
3704
|
* `getGestureBounds` answers "where is the thing the user is dragging right
|
|
3189
3705
|
* now, in total?" — a question every other lookup on `CanvasHelpers` can't
|
|
3190
3706
|
* answer because they're keyed by node id, and a drag-to-insert has no node
|
|
3191
|
-
* yet. Canvas collects the parts
|
|
3192
|
-
*
|
|
3707
|
+
* yet. `<Canvas>` collects the parts named here and folds them with
|
|
3708
|
+
* `unionAABB` (`core/geometry/unionBounds`).
|
|
3193
3709
|
*
|
|
3194
|
-
* Kept free of
|
|
3195
|
-
*
|
|
3710
|
+
* Kept free of the dispatcher itself so `<Canvas>` stays dispatcher-agnostic:
|
|
3711
|
+
* it owns the `CanvasHelpers` contract, and the live gesture state lives in
|
|
3712
|
+
* the dispatcher. The overlay and preview shapes an action publishes are data,
|
|
3713
|
+
* and travel through here as such.
|
|
3196
3714
|
*/
|
|
3197
3715
|
|
|
3716
|
+
/**
|
|
3717
|
+
* A source of in-flight preview state — a tool from the tools registry, or an
|
|
3718
|
+
* `OngoingHandle` from the dispatcher's in-flight map. Readers merge several
|
|
3719
|
+
* with first-non-null semantics.
|
|
3720
|
+
*
|
|
3721
|
+
* @public
|
|
3722
|
+
*/
|
|
3723
|
+
interface GesturePreviewSource {
|
|
3724
|
+
previewIds?(): Iterable<string> | null;
|
|
3725
|
+
previewPose?(id: string): unknown;
|
|
3726
|
+
/** Companion to `previewPose` for actions that mutate node data (anchor
|
|
3727
|
+
* edits on `data.path` nodes). Absent/null falls back to committed data. */
|
|
3728
|
+
previewData?(id: string): unknown;
|
|
3729
|
+
/** Subset of `previewIds` painted at full opacity rather than as a ghost —
|
|
3730
|
+
* a layout sibling reflowing to its destination is not in flight. */
|
|
3731
|
+
previewOpaqueIds?(): Iterable<string> | null;
|
|
3732
|
+
}
|
|
3198
3733
|
/**
|
|
3199
3734
|
* Everything `<Canvas>` needs to know about in-flight gestures that it can't
|
|
3200
3735
|
* see for itself.
|
|
@@ -3226,58 +3761,391 @@ interface GestureSource {
|
|
|
3226
3761
|
subscribe(fn: () => void): () => void;
|
|
3227
3762
|
/** Monotonic counter bumped on the same events `subscribe` fires on. */
|
|
3228
3763
|
getVersion(): number;
|
|
3764
|
+
/** The in-flight handles' preview surfaces, in dispatch order. What a ghost
|
|
3765
|
+
* layer paints from — read off the draw envelope so a layer drawn for one
|
|
3766
|
+
* view cannot report another's gesture. */
|
|
3767
|
+
previewSources(): readonly GesturePreviewSource[];
|
|
3768
|
+
/** The overlay shapes the in-flight handles publish — marquee, lasso, insert
|
|
3769
|
+
* preview, raw commands. */
|
|
3770
|
+
overlays(): readonly OngoingOverlay[];
|
|
3229
3771
|
}
|
|
3230
3772
|
|
|
3231
3773
|
/**
|
|
3232
|
-
*
|
|
3233
|
-
*
|
|
3234
|
-
*
|
|
3235
|
-
* Three pieces:
|
|
3236
|
-
* - `composeSelectionPose` resolves the live pose for a selected id by
|
|
3237
|
-
* consulting the move overlay first, then the resize overlay, then the
|
|
3238
|
-
* stored pose. When `getChildren`/`isContainer` are supplied and the id
|
|
3239
|
-
* resolves to a container, the returned pose is the union AABB of all
|
|
3240
|
-
* transitive leaf poses (with the same precedence rules applied per leaf).
|
|
3241
|
-
* - `createSelectionOutlineLayer` draws the outline rect for each selected
|
|
3242
|
-
* id (container ids resolve to a union AABB via `getChildren`/`isContainer`).
|
|
3243
|
-
* - `createSelectionHandlesLayer` draws resize-handle rects (default 4
|
|
3244
|
-
* corners) for each selected id, with the same container-resolution rules.
|
|
3245
|
-
*
|
|
3246
|
-
* `createSelectionOverlayLayer` is a thin convenience that returns a single
|
|
3247
|
-
* `RenderLayer` whose draw runs the outline pass then the handles pass.
|
|
3248
|
-
*
|
|
3249
|
-
* **Pose shape:** TPose is generic; callers must supply `getBounds(pose)`
|
|
3250
|
-
* to project any pose into the AABB the renderer needs. For rect-shaped
|
|
3251
|
-
* poses (`{x, y, width, height}`) pass the identity. For `Path` poses pass
|
|
3252
|
-
* `boundsOfPath`. Container ids reduce via `unionBounds` over the projected
|
|
3253
|
-
* AABBs.
|
|
3774
|
+
* The half of {@link CanvasHelpers} that belongs to one view — everything
|
|
3775
|
+
* answered by a camera's own tools, gestures and selection. A canvas hosting
|
|
3776
|
+
* several viewports needs one of these per view; the surface half is shared.
|
|
3254
3777
|
*/
|
|
3255
|
-
|
|
3256
|
-
/**
|
|
3257
|
-
|
|
3258
|
-
|
|
3259
|
-
|
|
3260
|
-
|
|
3261
|
-
|
|
3262
|
-
/**
|
|
3263
|
-
* Resize overlay; consulted only when move overlay does not own the id.
|
|
3264
|
-
* For container resize, `leafPoses` (when present) maps each leaf id under
|
|
3265
|
-
* the container to its overlay pose. If absent the container falls back to
|
|
3266
|
-
* stored leaf poses (defensive — container-resize integration is in flight).
|
|
3267
|
-
*/
|
|
3268
|
-
resizeOverlay?: {
|
|
3269
|
-
id: string;
|
|
3270
|
-
currentPose: TPose;
|
|
3271
|
-
leafPoses?: Map<string, TPose>;
|
|
3272
|
-
} | null;
|
|
3273
|
-
/** Fallback pose lookup (typically the stored/committed pose). */
|
|
3274
|
-
getStoredPose: (id: string) => TPose;
|
|
3778
|
+
interface CanvasViewHelpers<TPose> {
|
|
3779
|
+
/** Pose currently displayed for `id` — drag/resize/rotate overlay if active,
|
|
3780
|
+
* otherwise the committed pose from the adapter. Returns `null` if the id
|
|
3781
|
+
* isn't known. */
|
|
3782
|
+
getEffectivePose(id: string): TPose | null;
|
|
3783
|
+
/** Overlay-aware bounds for `id`. */
|
|
3784
|
+
getEffectiveBounds(id: string): Bounds | null;
|
|
3275
3785
|
/**
|
|
3276
|
-
*
|
|
3277
|
-
*
|
|
3278
|
-
*
|
|
3279
|
-
*
|
|
3280
|
-
|
|
3786
|
+
* World-space AABB of everything the in-flight gesture proposes — the
|
|
3787
|
+
* displaced poses of nodes being moved / resized / rotated / cloned, plus
|
|
3788
|
+
* any nascent insert that has no scene node yet. `null` when no gesture is
|
|
3789
|
+
* in flight.
|
|
3790
|
+
*
|
|
3791
|
+
* This reports the *gesture*, not the document: committed content the
|
|
3792
|
+
* gesture isn't touching is excluded, so a consumer that wants the union
|
|
3793
|
+
* with the rest of the scene still walks its own ids through
|
|
3794
|
+
* `getEffectiveBounds`. It exists because every other lookup here is keyed
|
|
3795
|
+
* by node id, which can't answer "where is the shape the user is drawing
|
|
3796
|
+
* right now" — a drag-to-insert has no id until pointer-up.
|
|
3797
|
+
*
|
|
3798
|
+
* Select-only gestures are deliberately excluded: a marquee or lasso has
|
|
3799
|
+
* geometry but proposes no content, and a consumer sizing itself to the
|
|
3800
|
+
* gesture must not grow because the user swept a selection rectangle.
|
|
3801
|
+
*
|
|
3802
|
+
* The result is a plain AABB — never rotated. Rotated parts are folded in
|
|
3803
|
+
* by their rotated extent (a union of several oriented boxes has no single
|
|
3804
|
+
* orientation to report).
|
|
3805
|
+
*/
|
|
3806
|
+
getGestureBounds(): Bounds | null;
|
|
3807
|
+
/**
|
|
3808
|
+
* Subscribe to the gesture layer's change signal — the other half of the
|
|
3809
|
+
* `useSyncExternalStore` contract for everything on this object that moves
|
|
3810
|
+
* during a drag (`getEffectivePose`, `getEffectiveBounds`,
|
|
3811
|
+
* `getGestureBounds`). Returns an unsubscribe.
|
|
3812
|
+
*
|
|
3813
|
+
* Fires once per dispatcher pump: gesture start, every pointermove that
|
|
3814
|
+
* reaches an in-flight handle, end, and cancel — plus UI-driven ongoing
|
|
3815
|
+
* actions (a slider bound to an ongoing action pumps the same way). It
|
|
3816
|
+
* fires on the pump, not on a diff: a pump that changed nothing observable
|
|
3817
|
+
* still notifies, so don't hang expensive work directly off the callback.
|
|
3818
|
+
*
|
|
3819
|
+
* It does **not** cover committed scene edits (subscribe to the scene for
|
|
3820
|
+
* those) or previews a consumer's own tool publishes from React state
|
|
3821
|
+
* (that tool re-renders on its own).
|
|
3822
|
+
*
|
|
3823
|
+
* Without a gesture source wired — a bare `<Canvas>` — this is a no-op
|
|
3824
|
+
* subscription that never fires.
|
|
3825
|
+
*/
|
|
3826
|
+
subscribeGestures(fn: () => void): () => void;
|
|
3827
|
+
/**
|
|
3828
|
+
* Monotonic counter bumped on exactly the events `subscribeGestures` fires
|
|
3829
|
+
* on. Pair the two for `useSyncExternalStore`:
|
|
3830
|
+
*
|
|
3831
|
+
* ```ts
|
|
3832
|
+
* const gestureVersion = useSyncExternalStore(
|
|
3833
|
+
* useCallback((cb) => helpersRef.current?.subscribeGestures(cb) ?? (() => {}), []),
|
|
3834
|
+
* () => helpersRef.current?.getGestureVersion() ?? 0,
|
|
3835
|
+
* );
|
|
3836
|
+
* ```
|
|
3837
|
+
*
|
|
3838
|
+
* Starts at 0 and only increases. `0` is also what a bare `<Canvas>` with
|
|
3839
|
+
* no gesture source reports, forever.
|
|
3840
|
+
*/
|
|
3841
|
+
getGestureVersion(): number;
|
|
3842
|
+
/** Returns the live ChromeState built once per render. Affordances and
|
|
3843
|
+
* custom layers that need overlay-aware selection state (selection ids,
|
|
3844
|
+
* bounds, multi-union AABB, modifier flags) read from this. */
|
|
3845
|
+
getChromeState(): ChromeState;
|
|
3846
|
+
/**
|
|
3847
|
+
* Everything publishing an in-flight preview for this view, in resolution
|
|
3848
|
+
* order: tool-side first (hotkey → active → registry → ambient), then the
|
|
3849
|
+
* handles in flight on this view's dispatcher. Readers take the first
|
|
3850
|
+
* non-null answer per id.
|
|
3851
|
+
*
|
|
3852
|
+
* A ghost layer must read this off its draw envelope rather than close over
|
|
3853
|
+
* a dispatcher: one layer array paints every view, so a closure ghosts view
|
|
3854
|
+
* zero's drag into every panel.
|
|
3855
|
+
*/
|
|
3856
|
+
getPreviewSources(): readonly GesturePreviewSource[];
|
|
3857
|
+
/** Overlay shapes this view's in-flight handles publish — marquee, lasso,
|
|
3858
|
+
* insert preview, raw commands. Same envelope rule as
|
|
3859
|
+
* {@link CanvasViewHelpers.getPreviewSources}. */
|
|
3860
|
+
getGestureOverlays(): readonly OngoingOverlay[];
|
|
3861
|
+
/**
|
|
3862
|
+
* Chrome-caps visibility predicate, keyed by chrome id. Overlay layers and
|
|
3863
|
+
* affordances call it per element to decide whether to draw / hit-test.
|
|
3864
|
+
*
|
|
3865
|
+
* The rule table is the surface's; the context it resolves against is this
|
|
3866
|
+
* view's selection, camera and in-flight action — so the predicate belongs
|
|
3867
|
+
* here rather than on {@link CanvasSurfaceHelpers}. Unwired, it is the
|
|
3868
|
+
* universal `() => true`.
|
|
3869
|
+
*/
|
|
3870
|
+
getIsVisible(): (id: string) => boolean;
|
|
3871
|
+
}
|
|
3872
|
+
/**
|
|
3873
|
+
* The half of {@link CanvasHelpers} that belongs to the surface — one GL
|
|
3874
|
+
* context, one debug sink, however many views are drawn on it.
|
|
3875
|
+
*/
|
|
3876
|
+
interface CanvasSurfaceHelpers {
|
|
3877
|
+
/** Active debug sink, when `<Canvas debug=...>` is enabled. Layers that
|
|
3878
|
+
* want to participate in `hitboxes`/`bounds`/etc. visualization can
|
|
3879
|
+
* call into this from their `draw` callback. Returns `null` when
|
|
3880
|
+
* debug is off — no-op for production renders. */
|
|
3881
|
+
getDebug(): DebugSink | null;
|
|
3882
|
+
}
|
|
3883
|
+
/** Live overlay-aware lookups exposed to custom layers via `helpersRef`.
|
|
3884
|
+
* What a layer receives as its `data` argument, unchanged: the two halves
|
|
3885
|
+
* are split so a per-view set can be built independently of the surface's,
|
|
3886
|
+
* not to make layers ask for one. */
|
|
3887
|
+
interface CanvasHelpers<TPose> extends CanvasViewHelpers<TPose>, CanvasSurfaceHelpers {
|
|
3888
|
+
}
|
|
3889
|
+
|
|
3890
|
+
/**
|
|
3891
|
+
* NodeShape — the **shape trait's** registry. Each trait of a node
|
|
3892
|
+
* (shape, routing, label, icon, affordances, …) is its own registry;
|
|
3893
|
+
* this one holds the per-kind `paint` + `silhouette` (and future
|
|
3894
|
+
* fields) used by `defaultDrawOne`, clipping, non-rect hit-testing,
|
|
3895
|
+
* and lasso/area-select.
|
|
3896
|
+
*
|
|
3897
|
+
* Teaching the kit about a new kind of shape goes through this registry
|
|
3898
|
+
* rather than by overriding `drawOne`. Overrides are still possible but
|
|
3899
|
+
* shouldn't be the default seam: most consumers want the same dispatch
|
|
3900
|
+
* logic, just extended with their own shape kinds (images, custom paths,
|
|
3901
|
+
* SVG fragments, etc.).
|
|
3902
|
+
*
|
|
3903
|
+
* Built-in entries (`kit:text`, `kit:path`, `kit:rect-fallback`) are
|
|
3904
|
+
* registered at module load. Consumer entries added via
|
|
3905
|
+
* `registerNodeShape` join the chain; the first entry whose
|
|
3906
|
+
* `matches` predicate returns true paints the node.
|
|
3907
|
+
*
|
|
3908
|
+
* Two priority tiers:
|
|
3909
|
+
* - `'high'` — checked before all `'normal'` entries. Use this to
|
|
3910
|
+
* override a kit built-in for a specific data shape (e.g. a custom
|
|
3911
|
+
* text renderer that wins over `kit:text`).
|
|
3912
|
+
* - `'normal'` (default) — appended after the built-ins.
|
|
3913
|
+
*
|
|
3914
|
+
* Within a tier, entries run in registration order. Each
|
|
3915
|
+
* `registerNodeShape` call returns a disposer that removes the
|
|
3916
|
+
* entry — useful for tests, for plugin lifecycles, and for swapping
|
|
3917
|
+
* implementations at runtime.
|
|
3918
|
+
*
|
|
3919
|
+
* See `docs/superpowers/specs/2026-05-24-node-traits-reframe-design.md`
|
|
3920
|
+
* for the trait taxonomy.
|
|
3921
|
+
*/
|
|
3922
|
+
|
|
3923
|
+
/** Optional per-call paint context, threaded through `defaultDrawOne`'s third
|
|
3924
|
+
* argument. Lets a rendering entry point override ambient environment reads
|
|
3925
|
+
* — the headless `renderSceneToPixels` path supplies its own bitmap resolver
|
|
3926
|
+
* here so consumers reuse their own decode caches. Custom painters may
|
|
3927
|
+
* ignore it entirely. */
|
|
3928
|
+
interface NodePaintCtx {
|
|
3929
|
+
/** Override bitmap resolution for image nodes. When set it is authoritative:
|
|
3930
|
+
* the global `imageCache` is not consulted, and an `undefined` result
|
|
3931
|
+
* paints the deterministic grey placeholder outline (never the ambient
|
|
3932
|
+
* load-status error variant). */
|
|
3933
|
+
resolveImage?: (node: Node$1<unknown, string, unknown>) => ImageBitmap | undefined;
|
|
3934
|
+
/** The node's derived path, resolved by the scene-aware `drawOne` wrapper
|
|
3935
|
+
* before painting: `paint` has no scene handle, and deriving needs the
|
|
3936
|
+
* dependencies' poses. **Absent** for a node that derives from nothing —
|
|
3937
|
+
* the wrapper hands such a node the caller's own ctx untouched. `null`
|
|
3938
|
+
* means the node derives but has nothing to draw. */
|
|
3939
|
+
derivedPath?: Path | null;
|
|
3940
|
+
}
|
|
3941
|
+
/**
|
|
3942
|
+
* Per-node draw function — the scene-slot `drawOne` signature shared by
|
|
3943
|
+
* `<SceneCanvas>`, `renderSceneToCanvas` and `renderSceneToPixels`, so a
|
|
3944
|
+
* consumer can reuse one callback across a main canvas and a detached view.
|
|
3945
|
+
*
|
|
3946
|
+
* Called once per node in the walk. Returned commands are world-space; the
|
|
3947
|
+
* caller applies the view transform at the group level. `ctx` is supplied by
|
|
3948
|
+
* the scene-aware wrappers — see {@link NodePaintCtx}.
|
|
3949
|
+
*/
|
|
3950
|
+
type SceneViewDrawOne<TData, TLayer extends string, TPose> = (node: Node$1<TData, TLayer, TPose>, pose: TPose, view: View, ctx?: NodePaintCtx) => DrawCommand[];
|
|
3951
|
+
/** A painter for one kind of node: which nodes it claims, and the draw
|
|
3952
|
+
* commands it emits for them. Registering one is how a consumer teaches the
|
|
3953
|
+
* default renderer to draw its own node kinds. */
|
|
3954
|
+
interface NodeShapeEntry<TData = unknown, TPose = unknown> {
|
|
3955
|
+
/** Stable identifier — used for unregistration and debugging. Pick
|
|
3956
|
+
* something descriptive: `'kit:text'`, `'app:image'`, etc. */
|
|
3957
|
+
id: string;
|
|
3958
|
+
/** Returns true when this painter renders the node. The first matching
|
|
3959
|
+
* painter (`'high'` tier first, then `'normal'`) wins. */
|
|
3960
|
+
matches(node: Node$1<TData, string, TPose>): boolean;
|
|
3961
|
+
/** Emits the draw commands for the node's primary visual. `ctx` is an
|
|
3962
|
+
* optional per-call paint context (see `NodePaintCtx`); painters that
|
|
3963
|
+
* don't need it can keep a two-argument signature.
|
|
3964
|
+
*
|
|
3965
|
+
* **The returned array belongs to the painter.** Callers must treat it as
|
|
3966
|
+
* immutable and copy before appending — a painter is free to memoize its
|
|
3967
|
+
* command list (`kit:shape` and `kit:path` do), and an in-place `push`
|
|
3968
|
+
* would grow that list on every frame. `defaultDrawOne` copies before
|
|
3969
|
+
* adding its label overlay for exactly this reason. */
|
|
3970
|
+
paint(node: Node$1<TData, string, TPose>, pose: TPose, ctx?: NodePaintCtx): DrawCommand[];
|
|
3971
|
+
/** Optional: derive the node's silhouette path from its pose.
|
|
3972
|
+
* Used by clipping (when the container has no explicit
|
|
3973
|
+
* `clipFromPose`), by non-rect hit-testing, and by lasso/area-select.
|
|
3974
|
+
* Painters whose visual has no meaningful closed silhouette (e.g. text)
|
|
3975
|
+
* leave this undefined. */
|
|
3976
|
+
silhouette?(node: Node$1<TData, string, TPose>, pose: TPose, ctx?: NodeSilhouetteCtx): Path | null;
|
|
3977
|
+
/** Optional: how the silhouette is inked — whether the interior is filled,
|
|
3978
|
+
* and how wide the outline is. Read by picking, so that an unfilled shape
|
|
3979
|
+
* is grabbable by its outline rather than by its empty middle.
|
|
3980
|
+
*
|
|
3981
|
+
* This is declared separately from `paint` rather than read back off the
|
|
3982
|
+
* emitted draw commands because picking runs on every pointer move, and
|
|
3983
|
+
* `paint` is allowed to be expensive (`kit:text` lays out glyphs). Keep it
|
|
3984
|
+
* to cheap field reads.
|
|
3985
|
+
*
|
|
3986
|
+
* Painters that leave it undefined are treated as {@link DEFAULT_INK} —
|
|
3987
|
+
* the pre-`ink` behavior, where the whole silhouette interior is grabbable
|
|
3988
|
+
* and the outline adds nothing.
|
|
3989
|
+
*
|
|
3990
|
+
* `ctx.scale` carries the view scale so a `{ px }` stroke width resolves to
|
|
3991
|
+
* world units; without it a screen-pixel width is read as world units. */
|
|
3992
|
+
ink?(node: Node$1<TData, string, TPose>, pose: TPose, ctx?: NodeInkCtx): NodeInk | null;
|
|
3993
|
+
}
|
|
3994
|
+
/** How a painter inks its silhouette. See {@link NodeShapeEntry.ink}.
|
|
3995
|
+
*
|
|
3996
|
+
* Reach is per-side because `align` decides which side the ribbon lands on:
|
|
3997
|
+
* a centered stroke straddles the outline, `'inner'` puts nothing outside it,
|
|
3998
|
+
* `'outer'` nothing inside. */
|
|
3999
|
+
interface NodeInk {
|
|
4000
|
+
/** True when the silhouette's interior is painted, and so grabbable. */
|
|
4001
|
+
filled: boolean;
|
|
4002
|
+
/** How far the ink reaches outside the outline, world units. */
|
|
4003
|
+
outset: number;
|
|
4004
|
+
/** How far it reaches inside. */
|
|
4005
|
+
inset: number;
|
|
4006
|
+
}
|
|
4007
|
+
/** Per-call context for {@link NodeShapeEntry.silhouette}. */
|
|
4008
|
+
interface NodeSilhouetteCtx {
|
|
4009
|
+
/** The node's derived path, resolved by the caller — a painter has no scene
|
|
4010
|
+
* handle and deriving needs the dependencies' poses. Same convention as
|
|
4011
|
+
* {@link NodePaintCtx.derivedPath}: absent for a node that derives from
|
|
4012
|
+
* nothing, `null` when it derives but has nothing to draw. */
|
|
4013
|
+
derivedPath?: Path | null;
|
|
4014
|
+
}
|
|
4015
|
+
/** Per-call context for {@link NodeShapeEntry.ink}. */
|
|
4016
|
+
interface NodeInkCtx {
|
|
4017
|
+
/** View scale, for resolving `{ px }` stroke widths to world units. */
|
|
4018
|
+
scale?: number;
|
|
4019
|
+
}
|
|
4020
|
+
/** Options for `registerNodeShape`. */
|
|
4021
|
+
interface RegisterNodeShapeOptions {
|
|
4022
|
+
/** `'high'` puts the painter ahead of all normally-registered ones (so
|
|
4023
|
+
* it can win over a kit built-in). `'normal'` appends at the end. */
|
|
4024
|
+
priority?: 'high' | 'normal';
|
|
4025
|
+
}
|
|
4026
|
+
/** Register a shape painter. Returns a disposer that removes it. */
|
|
4027
|
+
declare function registerNodeShape<TData, TPose>(painter: NodeShapeEntry<TData, TPose>, opts?: RegisterNodeShapeOptions): () => void;
|
|
4028
|
+
/** Find the painter that will render `node` — first match in priority
|
|
4029
|
+
* order. Returns undefined if no painter (including the built-in
|
|
4030
|
+
* fallback) accepts the node. */
|
|
4031
|
+
declare function findNodeShape<TData, TPose>(node: Node$1<TData, string, TPose>): NodeShapeEntry<TData, TPose> | undefined;
|
|
4032
|
+
/** Find the painter for `node` and ask it for the node's silhouette path,
|
|
4033
|
+
* in **world** coords. Returns null if no painter matches, or the matching
|
|
4034
|
+
* painter has no `silhouette` method, or the method returns null. Used by
|
|
4035
|
+
* clipping, generic non-rect hit-testing and lasso/area-select — anywhere
|
|
4036
|
+
* the kit needs the "closed boundary" of whatever this kind of node draws as.
|
|
4037
|
+
*
|
|
4038
|
+
* Painters return their silhouette in the pose's local (unrotated) frame;
|
|
4039
|
+
* this bakes `pose.rotation` on top via the shared rotation convention, so
|
|
4040
|
+
* clips/area-select of a rotated node use the rotated boundary the renderer
|
|
4041
|
+
* draws. (`paint()` is unaffected — it applies rotation via the render wrap,
|
|
4042
|
+
* not the silhouette, so there is no double-rotation.) */
|
|
4043
|
+
declare function findShapeSilhouette<TData, TPose>(node: Node$1<TData, string, TPose>, pose: TPose, ctx?: NodeSilhouetteCtx): Path | null;
|
|
4044
|
+
/** Find the painter for `node` and ask how it inks its silhouette. Returns
|
|
4045
|
+
* the painter's declared {@link NodeInk}, or `null` when no painter matches
|
|
4046
|
+
* or it declares none — callers substitute {@link DEFAULT_INK}. */
|
|
4047
|
+
declare function findShapeInk<TData, TPose>(node: Node$1<TData, string, TPose>, pose: TPose, ctx?: NodeInkCtx): NodeInk | null;
|
|
4048
|
+
/** Options for {@link shapeCoversPoint}. */
|
|
4049
|
+
interface ShapeCoversPointOptions {
|
|
4050
|
+
/** Extra grab distance around the outline, in **world** units. Callers
|
|
4051
|
+
* derive it from a screen-pixel slop and the view scale, the same way
|
|
4052
|
+
* affordance hit radii work.
|
|
4053
|
+
*
|
|
4054
|
+
* Without slop a hairline is a mathematically zero-width target: the
|
|
4055
|
+
* stroke of a 1px outline is half a world unit wide at scale 1, which no
|
|
4056
|
+
* one can hit. Defaults to `0` so a caller that hasn't thought about the
|
|
4057
|
+
* view still gets exact geometry rather than a wrong guess. */
|
|
4058
|
+
tolerance?: number;
|
|
4059
|
+
/** View scale, passed to the painter's `ink` so a `{ px }` stroke width
|
|
4060
|
+
* resolves to world units. Defaults to 1. */
|
|
4061
|
+
scale?: number;
|
|
4062
|
+
/** The node's derived path — see {@link NodeSilhouetteCtx.derivedPath}.
|
|
4063
|
+
* Without it a derived node reports no silhouette and this answers `true`
|
|
4064
|
+
* everywhere, which degrades picking to the caller's AABB: for an edge,
|
|
4065
|
+
* a zero-sized pose. */
|
|
4066
|
+
derivedPath?: Path | null;
|
|
4067
|
+
}
|
|
4068
|
+
/**
|
|
4069
|
+
* Does the shape `node` actually paints cover the world point?
|
|
4070
|
+
*
|
|
4071
|
+
* The pose rect says a node covers its whole bounding box. That is wrong for
|
|
4072
|
+
* everything that is not a rectangle: the concave notch of a star, the corner
|
|
4073
|
+
* outside an ellipse, the blank right half of a text box. This asks the
|
|
4074
|
+
* painter's silhouette instead, which is the same boundary used for clipping
|
|
4075
|
+
* and area-select, so "what you can click" and "what is drawn" answer
|
|
4076
|
+
* together.
|
|
4077
|
+
*
|
|
4078
|
+
* "What is drawn" includes the *ink*, not just the boundary. A shape whose
|
|
4079
|
+
* interior isn't filled — an outlined rect, a pencil stroke, a bare line — is
|
|
4080
|
+
* grabbable along its outline and not through its empty middle, which is the
|
|
4081
|
+
* opposite of what a fill test alone answers. The outline's grab width is the
|
|
4082
|
+
* stroke's half-width plus `tolerance`.
|
|
4083
|
+
*
|
|
4084
|
+
* A painter with no `silhouette`, or one that returns `null` for this node
|
|
4085
|
+
* (`kit:text` does, for a node with no non-blank lines), reports `true` —
|
|
4086
|
+
* "no opinion", leaving the caller's own AABB test as the answer. Callers
|
|
4087
|
+
* should keep that AABB test as a cheap pre-filter; this is the refinement,
|
|
4088
|
+
* not a replacement.
|
|
4089
|
+
*
|
|
4090
|
+
* Rotation is already baked by `findShapeSilhouette`, so the point is in
|
|
4091
|
+
* plain world coordinates.
|
|
4092
|
+
*/
|
|
4093
|
+
declare function shapeCoversPoint<TData, TPose>(node: Node$1<TData, string, TPose>, pose: TPose, x: number, y: number, opts?: ShapeCoversPointOptions): boolean;
|
|
4094
|
+
/** Snapshot of the current painters in evaluation order — `'high'` tier
|
|
4095
|
+
* first, then `'normal'`. Useful for debugging which painter handles a
|
|
4096
|
+
* given node. */
|
|
4097
|
+
declare function getNodeShapes(): readonly NodeShapeEntry[];
|
|
4098
|
+
|
|
4099
|
+
/**
|
|
4100
|
+
* Selection overlay primitives — render layers for drawing selection
|
|
4101
|
+
* outlines and corner resize handles in world space.
|
|
4102
|
+
*
|
|
4103
|
+
* Three pieces:
|
|
4104
|
+
* - `composeSelectionPose` resolves the live pose for a selected id by
|
|
4105
|
+
* consulting the move overlay first, then the resize overlay, then the
|
|
4106
|
+
* stored pose. When `getChildren`/`isContainer` are supplied and the id
|
|
4107
|
+
* resolves to a container, the returned pose is the union AABB of all
|
|
4108
|
+
* transitive leaf poses (with the same precedence rules applied per leaf).
|
|
4109
|
+
* - `createSelectionOutlineLayer` draws the outline rect for each selected
|
|
4110
|
+
* id (container ids resolve to a union AABB via `getChildren`/`isContainer`).
|
|
4111
|
+
* - `createSelectionHandlesLayer` draws resize-handle rects (default 4
|
|
4112
|
+
* corners) for each selected id, with the same container-resolution rules.
|
|
4113
|
+
*
|
|
4114
|
+
* `createSelectionOverlayLayer` is a thin convenience that returns a single
|
|
4115
|
+
* `RenderLayer` whose draw runs the outline pass then the handles pass.
|
|
4116
|
+
*
|
|
4117
|
+
* **Pose shape:** TPose is generic; callers must supply `getBounds(pose)`
|
|
4118
|
+
* to project any pose into the AABB the renderer needs. For rect-shaped
|
|
4119
|
+
* poses (`{x, y, width, height}`) pass the identity. For `Path` poses pass
|
|
4120
|
+
* `boundsOfPath`. Container ids reduce via `unionAABB` over the projected
|
|
4121
|
+
* AABBs.
|
|
4122
|
+
*/
|
|
4123
|
+
|
|
4124
|
+
/** Options for `composeSelectionPose`. */
|
|
4125
|
+
interface ComposeSelectionPoseOpts<TPose> {
|
|
4126
|
+
/** Move overlay; when present its `poses` map wins over everything else. */
|
|
4127
|
+
moveOverlay?: {
|
|
4128
|
+
poses: Map<string, TPose>;
|
|
4129
|
+
} | null;
|
|
4130
|
+
/**
|
|
4131
|
+
* Resize overlay; consulted only when move overlay does not own the id.
|
|
4132
|
+
* For container resize, `leafPoses` (when present) maps each leaf id under
|
|
4133
|
+
* the container to its overlay pose. If absent the container falls back to
|
|
4134
|
+
* stored leaf poses (defensive — container-resize integration is in flight).
|
|
4135
|
+
*/
|
|
4136
|
+
resizeOverlay?: {
|
|
4137
|
+
id: string;
|
|
4138
|
+
currentPose: TPose;
|
|
4139
|
+
leafPoses?: Map<string, TPose>;
|
|
4140
|
+
} | null;
|
|
4141
|
+
/** Fallback pose lookup (typically the stored/committed pose). */
|
|
4142
|
+
getStoredPose: (id: string) => TPose;
|
|
4143
|
+
/**
|
|
4144
|
+
* Project a pose into its AABB. Used when reducing a group of leaf poses
|
|
4145
|
+
* into a single union AABB. Defaults to the identity — rect-shaped poses
|
|
4146
|
+
* (`{x, y, width, height}`) need no override. For `Path` poses pass
|
|
4147
|
+
* `boundsOfPath`.
|
|
4148
|
+
*/
|
|
3281
4149
|
getBounds?: (pose: TPose) => Bounds;
|
|
3282
4150
|
/**
|
|
3283
4151
|
* Wrap an AABB back into a TPose. Called only when the resolver collapses
|
|
@@ -3300,15 +4168,10 @@ interface ComposeSelectionPoseOpts<TPose> {
|
|
|
3300
4168
|
* precedence rules). Containers with no leaves resolve to `null`.
|
|
3301
4169
|
*/
|
|
3302
4170
|
declare function composeSelectionPose<TPose>(opts: ComposeSelectionPoseOpts<TPose>): (id: string) => TPose | null;
|
|
3303
|
-
/**
|
|
4171
|
+
/** Options every selection layer shares. `getSelection` and `getPose` are
|
|
4172
|
+
* declared on {@link SelectionOverlayLayerOpts}, which makes both optional —
|
|
4173
|
+
* omitted, they come off the draw envelope. */
|
|
3304
4174
|
interface SelectionLayerCommon<TPose> {
|
|
3305
|
-
getSelection: () => readonly NodeId[];
|
|
3306
|
-
/** Return null to skip rendering for an id (e.g. resolved pose unavailable).
|
|
3307
|
-
* Takes `string` rather than `NodeId` because the container-aware bounds
|
|
3308
|
-
* resolver internally walks expanded leaf ids via `getChildren`, which is
|
|
3309
|
-
* generic over arbitrary string ids. NodeIds flow in fine — a NodeId is a
|
|
3310
|
-
* string. */
|
|
3311
|
-
getPose: (id: string) => TPose | null;
|
|
3312
4175
|
/**
|
|
3313
4176
|
* Project a pose into its AABB. Defaults to the identity — rect-shaped
|
|
3314
4177
|
* poses (`{x, y, width, height}`) need no override. For `Path` poses pass
|
|
@@ -3322,46 +4185,38 @@ interface SelectionLayerCommon<TPose> {
|
|
|
3322
4185
|
/** True when `id` is a structural container. */
|
|
3323
4186
|
isContainer?: (id: string) => boolean;
|
|
3324
4187
|
}
|
|
3325
|
-
/** Options for `createSelectionOutlineLayer`.
|
|
3326
|
-
|
|
3327
|
-
|
|
3328
|
-
|
|
3329
|
-
|
|
3330
|
-
|
|
3331
|
-
}
|
|
3332
|
-
/** Options for `createSelectionHandlesLayer`. */
|
|
3333
|
-
interface SelectionHandlesLayerOpts<TPose> extends SelectionLayerCommon<TPose> {
|
|
3334
|
-
/** Handle visuals. Omit for defaults. */
|
|
3335
|
-
handles?: {
|
|
3336
|
-
size?: number;
|
|
3337
|
-
fill?: FillStyle;
|
|
3338
|
-
outline?: Stroke;
|
|
3339
|
-
};
|
|
3340
|
-
/** Override handle placement. Default: 4 corners of the AABB. */
|
|
3341
|
-
handlesOf?: (bounds: Bounds) => {
|
|
3342
|
-
x: number;
|
|
3343
|
-
y: number;
|
|
3344
|
-
}[];
|
|
3345
|
-
/** Render a rotation handle above the (rotated) top-center of the AABB.
|
|
3346
|
-
* When `true`, uses default visuals + distance. When an object, override
|
|
3347
|
-
* the world-space distance from the top edge. Defaults to `false` —
|
|
3348
|
-
* consumers opt in only when wiring `useRotate`. */
|
|
3349
|
-
rotationHandle?: boolean | {
|
|
3350
|
-
/** World-pixel distance from the top edge to the handle center. */
|
|
3351
|
-
distance?: number;
|
|
3352
|
-
};
|
|
3353
|
-
}
|
|
4188
|
+
/** Options for `createSelectionOutlineLayer`. The overlay layer's options
|
|
4189
|
+
* minus the handle visuals — the two run the same body. */
|
|
4190
|
+
type SelectionOutlineLayerOpts<TPose> = Omit<SelectionOverlayLayerOpts<TPose>, 'handles' | 'handlesOf' | 'rotationHandle'>;
|
|
4191
|
+
/** Options for `createSelectionHandlesLayer`. The overlay layer's options
|
|
4192
|
+
* minus the outline stroke — the two run the same body. */
|
|
4193
|
+
type SelectionHandlesLayerOpts<TPose> = Omit<SelectionOverlayLayerOpts<TPose>, 'outline'>;
|
|
3354
4194
|
/** Options for `createSelectionOverlayLayer`. */
|
|
3355
4195
|
interface SelectionOverlayLayerOpts<TPose> extends SelectionLayerCommon<TPose> {
|
|
4196
|
+
/**
|
|
4197
|
+
* Which ids to draw chrome for. Omit to take them from the `ChromeState` on
|
|
4198
|
+
* the draw envelope, which is what makes one canvas's several views each
|
|
4199
|
+
* outline their own selection — the layer is shared, the envelope is not.
|
|
4200
|
+
*
|
|
4201
|
+
* A multi-selection resolves to the synthetic union id, with the real
|
|
4202
|
+
* members going to the outline pass, exactly as the explicit form does.
|
|
4203
|
+
*/
|
|
4204
|
+
getSelection?: () => readonly NodeId[];
|
|
4205
|
+
/**
|
|
4206
|
+
* Resolve an id to the pose to draw chrome around. Return null to skip an
|
|
4207
|
+
* id. Omit to take bounds from the same envelope `getSelection` omitted
|
|
4208
|
+
* takes ids from — one cascade, the one the chrome state was built with,
|
|
4209
|
+
* rather than a second one here that has to agree with it.
|
|
4210
|
+
*
|
|
4211
|
+
* Takes `string` rather than `NodeId` because the container-aware resolver
|
|
4212
|
+
* walks expanded leaf ids via `getChildren`, which is generic over strings.
|
|
4213
|
+
*/
|
|
4214
|
+
getPose?: (id: string) => TPose | null;
|
|
3356
4215
|
outline?: Stroke & {
|
|
3357
4216
|
pad?: number;
|
|
3358
4217
|
};
|
|
3359
4218
|
/** Pass `false` to render outlines only. */
|
|
3360
|
-
handles?:
|
|
3361
|
-
size?: number;
|
|
3362
|
-
fill?: FillStyle;
|
|
3363
|
-
outline?: Stroke;
|
|
3364
|
-
} | false;
|
|
4219
|
+
handles?: SelectionHandleStyle | false;
|
|
3365
4220
|
handlesOf?: (bounds: Bounds) => {
|
|
3366
4221
|
x: number;
|
|
3367
4222
|
y: number;
|
|
@@ -3382,10 +4237,16 @@ interface SelectionOverlayLayerOpts<TPose> extends SelectionLayerCommon<TPose> {
|
|
|
3382
4237
|
* per-anchor chrome takes over. */
|
|
3383
4238
|
getSuppressedIds?: () => ReadonlySet<string>;
|
|
3384
4239
|
}
|
|
4240
|
+
/** Handle visuals, as a consumer supplies them. */
|
|
4241
|
+
interface SelectionHandleStyle {
|
|
4242
|
+
size?: number;
|
|
4243
|
+
fill?: FillStyle;
|
|
4244
|
+
outline?: Stroke;
|
|
4245
|
+
}
|
|
3385
4246
|
/**
|
|
3386
4247
|
* `RenderLayer` that draws selection outlines only. Stack alongside
|
|
3387
|
-
* `createSelectionHandlesLayer` (or
|
|
3388
|
-
*
|
|
4248
|
+
* `createSelectionHandlesLayer` (or use `createSelectionOverlayLayer`, which
|
|
4249
|
+
* runs both passes in one layer) when both are wanted.
|
|
3389
4250
|
*/
|
|
3390
4251
|
declare function createSelectionOutlineLayer<TPose>(opts: SelectionOutlineLayerOpts<TPose>): RenderLayer<unknown>;
|
|
3391
4252
|
/**
|
|
@@ -3394,10 +4255,9 @@ declare function createSelectionOutlineLayer<TPose>(opts: SelectionOutlineLayerO
|
|
|
3394
4255
|
*/
|
|
3395
4256
|
declare function createSelectionHandlesLayer<TPose>(opts: SelectionHandlesLayerOpts<TPose>): RenderLayer<unknown>;
|
|
3396
4257
|
/**
|
|
3397
|
-
*
|
|
3398
|
-
*
|
|
3399
|
-
*
|
|
3400
|
-
* render outlines only.
|
|
4258
|
+
* Draws outlines then handles in a single layer. Exactly equivalent to
|
|
4259
|
+
* stacking `createSelectionOutlineLayer` and `createSelectionHandlesLayer` —
|
|
4260
|
+
* all three run the same body. Pass `handles: false` to render outlines only.
|
|
3401
4261
|
*/
|
|
3402
4262
|
declare function createSelectionOverlayLayer<TPose>(opts: SelectionOverlayLayerOpts<TPose>): RenderLayer<unknown>;
|
|
3403
4263
|
|
|
@@ -3475,8 +4335,15 @@ interface SceneSlotConfig<TNode extends {
|
|
|
3475
4335
|
objects?: TNode[];
|
|
3476
4336
|
/** Project an object to its committed pose. Defaults to `adapter.getPose(obj.id)`. */
|
|
3477
4337
|
toPose?: (obj: TNode) => TPose;
|
|
3478
|
-
/** Draw a single object as a `DrawCommand` tree.
|
|
3479
|
-
|
|
4338
|
+
/** Draw a single object as a `DrawCommand` tree. `ctx` carries what only a
|
|
4339
|
+
* scene-aware caller can supply (a node's derived path); `<SceneCanvas>`
|
|
4340
|
+
* fills it in, bare `<Canvas>` never does. */
|
|
4341
|
+
drawOne: (obj: TNode, pose: TPose, view: View, ctx?: NodePaintCtx) => DrawCommand[];
|
|
4342
|
+
/** The path a container derives from its dependencies' poses, for the clip
|
|
4343
|
+
* it imposes on its subtree. The other half of what only a scene-aware
|
|
4344
|
+
* caller can supply — `drawOne`'s `ctx` carries the derived path a node
|
|
4345
|
+
* *paints*, this one the clip it *imposes*. */
|
|
4346
|
+
derivedPathOf?: (obj: TNode, pose: TPose) => Path | null;
|
|
3480
4347
|
/** Default ghost alpha for the move-overlay slot. Default 0.85. */
|
|
3481
4348
|
ghostAlpha?: number;
|
|
3482
4349
|
/**
|
|
@@ -3575,6 +4442,20 @@ interface CanvasProps<TNode extends {
|
|
|
3575
4442
|
* same contract the headless `renderSceneToPixels` path follows (that
|
|
3576
4443
|
* path never reads ambient density at all). */
|
|
3577
4444
|
dpr?: number;
|
|
4445
|
+
/** The version of whatever content this canvas draws, sampled at paint time
|
|
4446
|
+
* and reported by {@link CanvasExtensionApi.getPaintedVersion}.
|
|
4447
|
+
* `<SceneCanvas>` wires this to `scene.getVersion`. Chrome that must not
|
|
4448
|
+
* show DOM ahead of pixels compares the two and defers a frame. */
|
|
4449
|
+
contentVersion?: () => number;
|
|
4450
|
+
/** Paint inside the React commit rather than on the next animation frame.
|
|
4451
|
+
* Costs a synchronous paint per commit and per redraw request; buys
|
|
4452
|
+
* single-commit consistency between React-rendered DOM and canvas pixels.
|
|
4453
|
+
* For consumers with DOM chrome pinned to canvas content that cannot
|
|
4454
|
+
* tolerate a frame of skew. Live: toggling it switches modes from the next
|
|
4455
|
+
* redraw on. A redraw requested from inside a layer's `draw`, or from a
|
|
4456
|
+
* `subscribeFrame` callback, still waits for a frame — painting it in place
|
|
4457
|
+
* would recurse. */
|
|
4458
|
+
syncPaint?: boolean;
|
|
3578
4459
|
/**
|
|
3579
4460
|
* Combined adapter for scene-slot rendering, bounds computation, and
|
|
3580
4461
|
* move/resize/rotate gesture math. Optional — bare-Canvas consumers that
|
|
@@ -3638,6 +4519,12 @@ interface CanvasProps<TNode extends {
|
|
|
3638
4519
|
className?: string;
|
|
3639
4520
|
style?: React__default.CSSProperties;
|
|
3640
4521
|
tabIndex?: number;
|
|
4522
|
+
/** Fired when the canvas element gains focus. The canvas is focusable by
|
|
4523
|
+
* default (`tabIndex` 0), so consumers driving focus-dependent chrome —
|
|
4524
|
+
* a focus ring, a "keyboard shortcuts active" hint — need to observe it. */
|
|
4525
|
+
onFocus?: React__default.FocusEventHandler<HTMLCanvasElement>;
|
|
4526
|
+
/** Fired when the canvas element loses focus. */
|
|
4527
|
+
onBlur?: React__default.FocusEventHandler<HTMLCanvasElement>;
|
|
3641
4528
|
/**
|
|
3642
4529
|
* When `true` (default), the canvas element receives focus on `pointerdown`
|
|
3643
4530
|
* so keyboard events (tool hotkeys, undo/redo) are captured without a
|
|
@@ -3746,7 +4633,9 @@ interface CanvasProps<TNode extends {
|
|
|
3746
4633
|
* Hand tool registration, wheel pan/zoom action descriptors, and keyboard
|
|
3747
4634
|
* zoom shortcuts are SceneCanvas-level concerns and are NOT owned by Canvas.
|
|
3748
4635
|
* Those belong with the tool registry and gesture dispatcher that live in
|
|
3749
|
-
* SceneCanvas
|
|
4636
|
+
* SceneCanvas — which is also why SceneCanvas does not pass this prop: it
|
|
4637
|
+
* drives pinch through the `viewport.pinchZoom` action instead, and both
|
|
4638
|
+
* paths at once would apply one gesture's zoom factor twice.
|
|
3750
4639
|
*
|
|
3751
4640
|
* When omitted, no pinch-zoom listener is attached.
|
|
3752
4641
|
*/
|
|
@@ -3819,528 +4708,26 @@ interface CanvasProps<TNode extends {
|
|
|
3819
4708
|
* every chrome element visible (pre-chrome-caps behavior).
|
|
3820
4709
|
*/
|
|
3821
4710
|
getIsVisible?: () => (id: string) => boolean;
|
|
3822
|
-
}
|
|
3823
|
-
/** Live overlay-aware lookups exposed to custom layers via `helpersRef`. */
|
|
3824
|
-
interface CanvasHelpers<TPose> {
|
|
3825
|
-
/** Pose currently displayed for `id` — drag/resize/rotate overlay if active,
|
|
3826
|
-
* otherwise the committed pose from the adapter. Returns `null` if the id
|
|
3827
|
-
* isn't known. */
|
|
3828
|
-
getEffectivePose(id: string): TPose | null;
|
|
3829
|
-
/** Overlay-aware bounds for `id`. */
|
|
3830
|
-
getEffectiveBounds(id: string): Bounds | null;
|
|
3831
|
-
/**
|
|
3832
|
-
* World-space AABB of everything the in-flight gesture proposes — the
|
|
3833
|
-
* displaced poses of nodes being moved / resized / rotated / cloned, plus
|
|
3834
|
-
* any nascent insert that has no scene node yet. `null` when no gesture is
|
|
3835
|
-
* in flight.
|
|
3836
|
-
*
|
|
3837
|
-
* This reports the *gesture*, not the document: committed content the
|
|
3838
|
-
* gesture isn't touching is excluded, so a consumer that wants the union
|
|
3839
|
-
* with the rest of the scene still walks its own ids through
|
|
3840
|
-
* `getEffectiveBounds`. It exists because every other lookup here is keyed
|
|
3841
|
-
* by node id, which can't answer "where is the shape the user is drawing
|
|
3842
|
-
* right now" — a drag-to-insert has no id until pointer-up.
|
|
3843
|
-
*
|
|
3844
|
-
* Select-only gestures are deliberately excluded: a marquee or lasso has
|
|
3845
|
-
* geometry but proposes no content, and a consumer sizing itself to the
|
|
3846
|
-
* gesture must not grow because the user swept a selection rectangle.
|
|
3847
|
-
*
|
|
3848
|
-
* The result is a plain AABB — never rotated. Rotated parts are folded in
|
|
3849
|
-
* by their rotated extent (a union of several oriented boxes has no single
|
|
3850
|
-
* orientation to report).
|
|
3851
|
-
*/
|
|
3852
|
-
getGestureBounds(): Bounds | null;
|
|
3853
4711
|
/**
|
|
3854
|
-
*
|
|
3855
|
-
*
|
|
3856
|
-
*
|
|
3857
|
-
* `getGestureBounds`). Returns an unsubscribe.
|
|
4712
|
+
* Show or hide whole render layers by id. An id absent from the map falls
|
|
4713
|
+
* back to the layer's own `defaultVisible`, and a layer marked `alwaysOn`
|
|
4714
|
+
* ignores the map entirely.
|
|
3858
4715
|
*
|
|
3859
|
-
*
|
|
3860
|
-
*
|
|
3861
|
-
* actions (a slider bound to an ongoing action pumps the same way). It
|
|
3862
|
-
* fires on the pump, not on a diff: a pump that changed nothing observable
|
|
3863
|
-
* still notifies, so don't hang expensive work directly off the callback.
|
|
4716
|
+
* Hiding a layer also stops it claiming pointer events through
|
|
4717
|
+
* `hitTestExtras` — a layer nobody can see must not swallow a click.
|
|
3864
4718
|
*
|
|
3865
|
-
*
|
|
3866
|
-
*
|
|
3867
|
-
* (that tool re-renders on its own).
|
|
3868
|
-
*
|
|
3869
|
-
* Without a gesture source wired — a bare `<Canvas>` — this is a no-op
|
|
3870
|
-
* subscription that never fires.
|
|
4719
|
+
* This is `getIsVisible`'s coarser sibling: that one gates individual
|
|
4720
|
+
* chrome elements *within* a layer, this one gates the layer.
|
|
3871
4721
|
*/
|
|
3872
|
-
|
|
4722
|
+
layerVisibility?: Record<string, boolean>;
|
|
3873
4723
|
/**
|
|
3874
|
-
*
|
|
3875
|
-
*
|
|
3876
|
-
*
|
|
3877
|
-
* ```ts
|
|
3878
|
-
* const gestureVersion = useSyncExternalStore(
|
|
3879
|
-
* useCallback((cb) => helpersRef.current?.subscribeGestures(cb) ?? (() => {}), []),
|
|
3880
|
-
* () => helpersRef.current?.getGestureVersion() ?? 0,
|
|
3881
|
-
* );
|
|
3882
|
-
* ```
|
|
4724
|
+
* Draw order, by layer id, bottom first. Omit for the order the layers
|
|
4725
|
+
* arrive in.
|
|
3883
4726
|
*
|
|
3884
|
-
*
|
|
3885
|
-
*
|
|
4727
|
+
* **A listed order is the whole list:** any layer whose id is missing from
|
|
4728
|
+
* it is not drawn. Reordering two layers means naming all of them.
|
|
3886
4729
|
*/
|
|
3887
|
-
|
|
3888
|
-
/** Returns the live ChromeState built once per render. Affordances and
|
|
3889
|
-
* custom layers that need overlay-aware selection state (selection ids,
|
|
3890
|
-
* bounds, multi-union AABB, modifier flags) read from this. */
|
|
3891
|
-
getChromeState(): ChromeState;
|
|
3892
|
-
/** Active debug sink, when `<Canvas debug=...>` is enabled. Layers that
|
|
3893
|
-
* want to participate in `hitboxes`/`bounds`/etc. visualization can
|
|
3894
|
-
* call into this from their `draw` callback. Returns `null` when
|
|
3895
|
-
* debug is off — no-op for production renders. */
|
|
3896
|
-
getDebug(): DebugSink | null;
|
|
3897
|
-
/** Chrome-caps visibility predicate, keyed by chrome id. Returns a
|
|
3898
|
-
* function that affordance/overlay layers can call per-element to
|
|
3899
|
-
* decide whether to draw / hit-test. When the parent didn't supply
|
|
3900
|
-
* a resolver, this returns the universal `() => true`. */
|
|
3901
|
-
getIsVisible(): (id: string) => boolean;
|
|
3902
|
-
}
|
|
3903
|
-
|
|
3904
|
-
/** Which of a node's two per-anchor color arrays an override applies to. */
|
|
3905
|
-
type VertexColorChannel = 'fill' | 'stroke';
|
|
3906
|
-
/** Function-form override: receives the consumer-supplied base color
|
|
3907
|
-
* array and the current animation timestamp (ms, from the animator's
|
|
3908
|
-
* clock). Returns a flat RGBA float array (values in 0..1, matching
|
|
3909
|
-
* the renderer's `stroke.vertexColors` / `PathDrawCommand.vertexColors`
|
|
3910
|
-
* color space) of the same length as `base`. */
|
|
3911
|
-
type ColorOverrideFn = (base: readonly number[], tMs: number) => number[];
|
|
3912
|
-
/** Either a static per-anchor RGBA float array (0..1) or a function-form
|
|
3913
|
-
* override (see {@link ColorOverrideFn}). */
|
|
3914
|
-
type ColorOverride = readonly number[] | ColorOverrideFn;
|
|
3915
|
-
/** Per-node, per-channel store of color overrides consulted by `createPathLayer`
|
|
3916
|
-
* before falling back to the consumer's `getVertexColors` / `getStrokeVertexColors`
|
|
3917
|
-
* accessor. Attached to `useAnimator` as `animator.colorOverrides`. */
|
|
3918
|
-
declare class ColorOverrideRegistry {
|
|
3919
|
-
private readonly map;
|
|
3920
|
-
private _version;
|
|
3921
|
-
set(id: string, channel: VertexColorChannel, override: ColorOverride): void;
|
|
3922
|
-
clear(id: string, channel: VertexColorChannel): void;
|
|
3923
|
-
clearAll(): void;
|
|
3924
|
-
get(id: string, channel: VertexColorChannel): ColorOverride | undefined;
|
|
3925
|
-
version(): number;
|
|
3926
|
-
}
|
|
3927
|
-
|
|
3928
|
-
/** One keyframe. `easing` shapes the approach INTO this key from the previous
|
|
3929
|
-
* one, so the first key's easing is never consulted. */
|
|
3930
|
-
interface Keyframe<T> {
|
|
3931
|
-
/** Time within the track's timeline, in ms. */
|
|
3932
|
-
t: number;
|
|
3933
|
-
value: T;
|
|
3934
|
-
easing?: EasingFn;
|
|
3935
|
-
}
|
|
3936
|
-
/** A track sampled as a pure function of the playhead. Scrubbing one is free
|
|
3937
|
-
* and order-independent. */
|
|
3938
|
-
interface SampledTrack<T> {
|
|
3939
|
-
kind: 'sampled';
|
|
3940
|
-
label?: string;
|
|
3941
|
-
/** Sorted ascending by `t`. `sampleTrack` assumes this and does not sort. */
|
|
3942
|
-
keys: Keyframe<T>[];
|
|
3943
|
-
/** Required when T is not `number`; defaults to numeric lerp otherwise. */
|
|
3944
|
-
interpolate?: Interpolate<T>;
|
|
3945
|
-
/** Built once per segment and cached. Takes precedence over `interpolate`. */
|
|
3946
|
-
interpolator?: InterpolatorFactory<T>;
|
|
3947
|
-
onTick: (value: T) => void;
|
|
3948
|
-
}
|
|
3949
|
-
/** A track of edge crossings. Fires only when the playhead advances forward
|
|
3950
|
-
* under playback — never on `seek`. */
|
|
3951
|
-
interface EventTrack {
|
|
3952
|
-
kind: 'event';
|
|
3953
|
-
label?: string;
|
|
3954
|
-
/** Sorted ascending by `t`. */
|
|
3955
|
-
events: {
|
|
3956
|
-
t: number;
|
|
3957
|
-
fire: () => void;
|
|
3958
|
-
}[];
|
|
3959
|
-
}
|
|
3960
|
-
/** A nested timeline, evaluated at `playhead - at`. Children are NOT registered
|
|
3961
|
-
* with the animator separately; the parent evaluates them. */
|
|
3962
|
-
interface TimelineTrack {
|
|
3963
|
-
kind: 'timeline';
|
|
3964
|
-
label?: string;
|
|
3965
|
-
at: number;
|
|
3966
|
-
timeline: NestedTimeline;
|
|
3967
|
-
}
|
|
3968
|
-
type Track = SampledTrack<any> | EventTrack | TimelineTrack;
|
|
3969
|
-
/** What a child timeline may declare. The parent owns playback, so `loop`,
|
|
3970
|
-
* `autoplay`, `onDone` and `cancelKey` have no meaning below the root. */
|
|
3971
|
-
interface NestedTimeline {
|
|
3972
|
-
tracks: Track[];
|
|
3973
|
-
/** Defaults to the largest end time across `tracks`. */
|
|
3974
|
-
duration?: number;
|
|
3975
|
-
}
|
|
3976
|
-
interface TimelineOptions extends NestedTimeline {
|
|
3977
|
-
/** `true` loops forever, `n` loops n additional times. Default false. */
|
|
3978
|
-
loop?: boolean | number;
|
|
3979
|
-
/** Default true. When false the timeline registers but holds at t=0 until resumed. */
|
|
3980
|
-
autoplay?: boolean;
|
|
3981
|
-
onDone?: () => void;
|
|
3982
|
-
cancelKey?: string;
|
|
3983
|
-
}
|
|
3984
|
-
interface TimelineHandle extends AnimationHandle {
|
|
3985
|
-
/** Move the playhead. Never fires event tracks, at any depth. */
|
|
3986
|
-
seek(t: number): void;
|
|
3987
|
-
/** Current playhead in ms. */
|
|
3988
|
-
time(): number;
|
|
3989
|
-
duration(): number;
|
|
3990
|
-
tracks(): readonly Track[];
|
|
3991
|
-
/** Run `fn`, then recompute duration, drop cached interpolators, and notify.
|
|
3992
|
-
* Every mutation must go through this — an edited keyframe otherwise keeps
|
|
3993
|
-
* interpolating toward its old value with no visible error. */
|
|
3994
|
-
edit(fn: () => void): void;
|
|
3995
|
-
/** Notified after each `edit`. Returns an unsubscribe. */
|
|
3996
|
-
subscribe(cb: () => void): () => void;
|
|
3997
|
-
}
|
|
3998
|
-
|
|
3999
|
-
/** An easing curve: maps normalized progress `t ∈ [0, 1]` to eased progress.
|
|
4000
|
-
* Curves may leave the 0–1 range in the middle (back, elastic) but should
|
|
4001
|
-
* pass through 0 at 0 and 1 at 1. */
|
|
4002
|
-
type EasingFn = (t: number) => number;
|
|
4003
|
-
/** Blends two `T` values at eased progress `t`. Called once per frame; see
|
|
4004
|
-
* {@link InterpolatorFactory} when the blend has setup worth hoisting. */
|
|
4005
|
-
type Interpolate<T> = (from: T, to: T, t: number) => T;
|
|
4006
|
-
/** Factory interpolator: built ONCE at tween start with (from, to), the returned
|
|
4007
|
-
* function is called with `t ∈ [0, 1]` each frame. Use for interpolators with
|
|
4008
|
-
* expensive setup (color-space conversion, path-string parsing) — d3-interpolate's
|
|
4009
|
-
* shape exactly. For cheap interpolations the per-tick `Interpolate<T>` form is
|
|
4010
|
-
* fine; this is the escape hatch when setup-per-tick is wasteful. */
|
|
4011
|
-
type InterpolatorFactory<T> = (from: T, to: T) => (t: number) => T;
|
|
4012
|
-
/** A spring's physical parameters. Higher stiffness settles faster, higher
|
|
4013
|
-
* damping overshoots less, higher mass makes both sluggish. */
|
|
4014
|
-
interface SpringPreset {
|
|
4015
|
-
stiffness: number;
|
|
4016
|
-
damping: number;
|
|
4017
|
-
mass: number;
|
|
4018
|
-
}
|
|
4019
|
-
/** One of the tunings in `SPRING_PRESETS`. */
|
|
4020
|
-
type SpringPresetName = 'gentle' | 'wobbly' | 'stiff' | 'slow';
|
|
4021
|
-
/** A running animation. Cancel it, or bend its time — pausing and time-scaling
|
|
4022
|
-
* act on this animation's own virtual clock, independent of the animator's. */
|
|
4023
|
-
interface AnimationHandle {
|
|
4024
|
-
/** Monotonic id assigned by the animator. */
|
|
4025
|
-
id: number;
|
|
4026
|
-
/** Cancel this animation. Idempotent — no-op once already finished/canceled. */
|
|
4027
|
-
cancel(): void;
|
|
4028
|
-
/** Freeze this animation's virtual clock. Idempotent. */
|
|
4029
|
-
pause(): void;
|
|
4030
|
-
/** Resume this animation's virtual clock. Idempotent. */
|
|
4031
|
-
resume(): void;
|
|
4032
|
-
/** Multiply this animation's virtual-clock rate by `scale`. 1 = normal. */
|
|
4033
|
-
setTimeScale(scale: number): void;
|
|
4034
|
-
/** True iff this handle is currently paused. */
|
|
4035
|
-
isPaused(): boolean;
|
|
4036
|
-
}
|
|
4037
|
-
/** A duration-based animation from `from` to `to` over `ms`, shaped by an
|
|
4038
|
-
* easing curve. Reach for a spring instead when the motion should respond to
|
|
4039
|
-
* where the value already is rather than restart from a fixed duration. */
|
|
4040
|
-
interface TweenOptions<T> {
|
|
4041
|
-
from: T;
|
|
4042
|
-
to: T;
|
|
4043
|
-
ms: number;
|
|
4044
|
-
easing?: EasingFn;
|
|
4045
|
-
/** Required when T is not `number`. For T = number, defaults to linear numeric lerp.
|
|
4046
|
-
* Called per-tick with `(from, to, t)`. For interpolators with expensive setup,
|
|
4047
|
-
* prefer `interpolator` which is built once at tween start. */
|
|
4048
|
-
interpolate?: Interpolate<T>;
|
|
4049
|
-
/** Factory interpolator built once at tween start. Takes precedence over
|
|
4050
|
-
* `interpolate` when both are provided. Use this for d3-interpolate or any
|
|
4051
|
-
* `(from, to) => (t) => v` shape. */
|
|
4052
|
-
interpolator?: InterpolatorFactory<T>;
|
|
4053
|
-
onTick: (value: T) => void;
|
|
4054
|
-
onDone?: () => void;
|
|
4055
|
-
/** Any new animation passed the same cancelKey cancels the prior one in flight. */
|
|
4056
|
-
cancelKey?: string;
|
|
4057
|
-
}
|
|
4058
|
-
/** A spring animation: runs until the value settles on `to` rather than for a
|
|
4059
|
-
* set duration, so it absorbs an initial velocity naturally. Non-numeric `T`
|
|
4060
|
-
* needs the four vector helpers. */
|
|
4061
|
-
interface SpringOptions<T> {
|
|
4062
|
-
from: T;
|
|
4063
|
-
to: T;
|
|
4064
|
-
/** Initial velocity in T-units per second. Default: zero (T-shape-aware). */
|
|
4065
|
-
velocity?: T;
|
|
4066
|
-
preset?: SpringPresetName;
|
|
4067
|
-
stiffness?: number;
|
|
4068
|
-
damping?: number;
|
|
4069
|
-
mass?: number;
|
|
4070
|
-
interpolate?: Interpolate<T>;
|
|
4071
|
-
/** Vector helpers — required for non-numeric T. */
|
|
4072
|
-
add?: (a: T, b: T) => T;
|
|
4073
|
-
subtract?: (a: T, b: T) => T;
|
|
4074
|
-
scale?: (v: T, k: number) => T;
|
|
4075
|
-
magnitude?: (v: T) => number;
|
|
4076
|
-
/** Velocity magnitude below which the spring is considered settled. Default 0.01. */
|
|
4077
|
-
restThreshold?: number;
|
|
4078
|
-
onTick: (value: T) => void;
|
|
4079
|
-
onDone?: () => void;
|
|
4080
|
-
cancelKey?: string;
|
|
4081
|
-
}
|
|
4082
|
-
/** Spring and decay as one animation. With a `to`, a spring pulls toward it;
|
|
4083
|
-
* with `to: null`, the value coasts on its velocity. Either can become the
|
|
4084
|
-
* other mid-flight through the handle. */
|
|
4085
|
-
interface PhysicsOptions<T> {
|
|
4086
|
-
from: T;
|
|
4087
|
-
/** Target. `null` ⇒ no spring force (decay-mode). */
|
|
4088
|
-
to?: T | null;
|
|
4089
|
-
/** Initial velocity in T-units per second. */
|
|
4090
|
-
velocity?: T;
|
|
4091
|
-
preset?: SpringPresetName;
|
|
4092
|
-
stiffness?: number;
|
|
4093
|
-
damping?: number;
|
|
4094
|
-
mass?: number;
|
|
4095
|
-
restThreshold?: number;
|
|
4096
|
-
/** Vector helpers — required for non-numeric T. */
|
|
4097
|
-
add?: (a: T, b: T) => T;
|
|
4098
|
-
subtract?: (a: T, b: T) => T;
|
|
4099
|
-
scale?: (v: T, k: number) => T;
|
|
4100
|
-
magnitude?: (v: T) => number;
|
|
4101
|
-
onTick: (value: T) => void;
|
|
4102
|
-
onDone?: () => void;
|
|
4103
|
-
cancelKey?: string;
|
|
4104
|
-
}
|
|
4105
|
-
/** An `AnimationHandle` that can also be steered while it runs — the point of
|
|
4106
|
-
* the physics primitive. */
|
|
4107
|
-
interface PhysicsHandle<T = unknown> extends AnimationHandle {
|
|
4108
|
-
/** Retarget mid-flight. `null` ⇒ switch to decay-mode (no spring force). */
|
|
4109
|
-
setTarget(to: T | null): void;
|
|
4110
|
-
/** Replace the current velocity in T-units per second. */
|
|
4111
|
-
setVelocity(v: T): void;
|
|
4112
|
-
}
|
|
4113
|
-
/** Momentum: coast from `from` at `velocity`, slowing by `friction` each
|
|
4114
|
-
* second until below `threshold`. What a flick-to-pan leaves behind. */
|
|
4115
|
-
interface DecayOptions<T> {
|
|
4116
|
-
from: T;
|
|
4117
|
-
velocity: T;
|
|
4118
|
-
/** Per-second velocity multiplier in (0, 1). Default 0.95. */
|
|
4119
|
-
friction?: number;
|
|
4120
|
-
/** Velocity magnitude below which decay stops. Default 0.5. */
|
|
4121
|
-
threshold?: number;
|
|
4122
|
-
add: (a: T, b: T) => T;
|
|
4123
|
-
scale: (v: T, k: number) => T;
|
|
4124
|
-
magnitude: (v: T) => number;
|
|
4125
|
-
onTick: (value: T) => void;
|
|
4126
|
-
onDone?: () => void;
|
|
4127
|
-
cancelKey?: string;
|
|
4128
|
-
}
|
|
4129
|
-
/** Options for `useAnimator`. Everything here is an injection seam for tests;
|
|
4130
|
-
* the defaults are the real clock, rAF, and `setTimeout`. */
|
|
4131
|
-
interface UseAnimatorOptions {
|
|
4132
|
-
/** Optional clock injection for tests. Returns ms since some epoch. */
|
|
4133
|
-
now?: () => number;
|
|
4134
|
-
/** Optional rAF / cAF injection for tests. Defaults to window.requestAnimationFrame. */
|
|
4135
|
-
requestFrame?: (cb: (t: number) => void) => number;
|
|
4136
|
-
cancelFrame?: (handle: number) => void;
|
|
4137
|
-
/** Optional `setTimeout` injection used by `stagger` for per-item delays.
|
|
4138
|
-
* Defaults to the global `setTimeout`. Tests inject a virtual scheduler. */
|
|
4139
|
-
setTimer?: (cb: () => void, ms: number) => unknown;
|
|
4140
|
-
/** Companion to `setTimer`. Defaults to global `clearTimeout`. */
|
|
4141
|
-
clearTimer?: (handle: unknown) => void;
|
|
4142
|
-
}
|
|
4143
|
-
/**
|
|
4144
|
-
* Owns every running animation on a canvas and drives them from one rAF loop.
|
|
4145
|
-
* Beyond the primitives (`tween`, `spring`, `decay`, `physics`) it offers
|
|
4146
|
-
* composition — `loop`, `stagger` — and bulk control by handle, by cancel-key,
|
|
4147
|
-
* or over everything at once.
|
|
4148
|
-
*
|
|
4149
|
-
* An animator does not know about the scene: animations report values through
|
|
4150
|
-
* `onTick` and the caller decides what to do with them.
|
|
4151
|
-
*/
|
|
4152
|
-
interface Animator {
|
|
4153
|
-
tween<T>(opts: TweenOptions<T>): AnimationHandle;
|
|
4154
|
-
spring<T>(opts: SpringOptions<T>): AnimationHandle;
|
|
4155
|
-
decay<T>(opts: DecayOptions<T>): AnimationHandle;
|
|
4156
|
-
/** Unified spring/decay primitive. With `to` set, behaves as a spring;
|
|
4157
|
-
* with `to: null`, behaves as a velocity-driven decay. Supports
|
|
4158
|
-
* mid-flight retargeting via the returned handle's `setTarget`. */
|
|
4159
|
-
physics<T>(opts: PhysicsOptions<T>): PhysicsHandle<T>;
|
|
4160
|
-
/** Cancel a specific animation by handle. Pose stays at current value (no jump). */
|
|
4161
|
-
cancel(handle: AnimationHandle): void;
|
|
4162
|
-
/** Cancel every animation currently active under `key`. */
|
|
4163
|
-
cancelKey(key: string): void;
|
|
4164
|
-
/** Cancel everything. Useful from a destructor or "reset scene" path. */
|
|
4165
|
-
cancelAll(): void;
|
|
4166
|
-
/** True iff at least one animation is active. With `key`, scoped to that cancelKey. */
|
|
4167
|
-
isActive(key?: string): boolean;
|
|
4168
|
-
/**
|
|
4169
|
-
* True while the animator is currently executing an animation tick. Useful
|
|
4170
|
-
* for adapter wrappers (e.g. `animateOnSetPose`) that need to detect
|
|
4171
|
-
* "this `setPose` was called from inside another animation's onTick"
|
|
4172
|
-
* (momentum decay, in-flight tween, spring) and avoid recursively
|
|
4173
|
-
* scheduling a new wrap-animation that would fight the caller.
|
|
4174
|
-
*/
|
|
4175
|
-
isTicking(): boolean;
|
|
4176
|
-
/** Freeze every animation managed by this animator. */
|
|
4177
|
-
pause(): void;
|
|
4178
|
-
/** Resume every animation managed by this animator. */
|
|
4179
|
-
resume(): void;
|
|
4180
|
-
/** True iff the animator is currently globally paused. */
|
|
4181
|
-
isPaused(): boolean;
|
|
4182
|
-
/** Multiply every animation's virtual-clock rate by `scale`. 1 = normal. */
|
|
4183
|
-
setTimeScale(scale: number): void;
|
|
4184
|
-
/** Freeze every animation whose `cancelKey` matches. */
|
|
4185
|
-
pauseKey(key: string): void;
|
|
4186
|
-
/** Resume every animation whose `cancelKey` matches. */
|
|
4187
|
-
resumeKey(key: string): void;
|
|
4188
|
-
/** Set per-animation timeScale for every animation whose `cancelKey` matches. */
|
|
4189
|
-
setTimeScaleByKey(key: string, scale: number): void;
|
|
4190
|
-
/**
|
|
4191
|
-
* Loop primitive: repeatedly invoke `factory` to produce a child animation.
|
|
4192
|
-
* The factory must wire its returned handle's `onDone` to call `next` so
|
|
4193
|
-
* the loop advances. Returns a handle whose pause/resume/setTimeScale/cancel
|
|
4194
|
-
* delegate to the current in-flight child (and prevent future iterations
|
|
4195
|
-
* on cancel).
|
|
4196
|
-
*
|
|
4197
|
-
* The loop is registered with the animator under a supervisor entry so
|
|
4198
|
-
* `animator.cancel(handle)`, `animator.cancelKey(opts.cancelKey)`, and
|
|
4199
|
-
* `animator.isActive(opts.cancelKey)` all work for it.
|
|
4200
|
-
*/
|
|
4201
|
-
loop(factory: LoopFactory, opts?: LoopOptions): AnimationHandle;
|
|
4202
|
-
/** Sugar over `loop` for the common case of looping a tween between two
|
|
4203
|
-
* values with optional direction handling (`restart` | `reverse` |
|
|
4204
|
-
* `alternate`). Registered with the animator like `loop`. */
|
|
4205
|
-
tweenLoop<T>(opts: TweenLoopOptions<T>): AnimationHandle;
|
|
4206
|
-
/**
|
|
4207
|
-
* Stagger primitive: schedule a per-item animation, offset by `delay` ms
|
|
4208
|
-
* per index (or a custom function of the index). Two forms:
|
|
4209
|
-
* - Factory form: pass `factory` directly, returns a composite
|
|
4210
|
-
* `AnimationHandle`.
|
|
4211
|
-
* - Builder form: omit `factory`, get a `StaggerBuilder` for fluent
|
|
4212
|
-
* `.each` / `.tween` / `.springPose` calls.
|
|
4213
|
-
*
|
|
4214
|
-
* The composite handle's `cancel` cancels pending timers AND in-flight
|
|
4215
|
-
* children. `pause` / `resume` / `setTimeScale` propagate to in-flight
|
|
4216
|
-
* children; `pause`/`resume` also freeze and thaw pending per-item timers
|
|
4217
|
-
* (the remaining time before each pending fire is preserved across the
|
|
4218
|
-
* pause).
|
|
4219
|
-
*
|
|
4220
|
-
* The stagger is registered with the animator under a supervisor entry so
|
|
4221
|
-
* `animator.cancel(handle)`, `animator.cancelKey(opts.cancelKey)`, and
|
|
4222
|
-
* `animator.isActive(opts.cancelKey)` all work for it.
|
|
4223
|
-
*/
|
|
4224
|
-
stagger<TItem>(items: readonly TItem[], delay: StaggerDelay): StaggerBuilder<TItem>;
|
|
4225
|
-
stagger<TItem>(items: readonly TItem[], delay: StaggerDelay, factory: StaggerFactory<TItem>, opts?: StaggerOptions): AnimationHandle;
|
|
4226
|
-
/**
|
|
4227
|
-
* Keyframe timeline. Registered like any other animation, so its playhead
|
|
4228
|
-
* responds to `pause`, `setTimeScale` and `cancelKey`. Sampled tracks are a
|
|
4229
|
-
* pure function of the playhead; event tracks fire only on forward playback.
|
|
4230
|
-
*/
|
|
4231
|
-
timeline(opts: TimelineOptions): TimelineHandle;
|
|
4232
|
-
/** Per-node, per-channel color override registry consulted by the renderer's
|
|
4233
|
-
* path layer before reading consumer accessors. Used by `tweenVertexColors`,
|
|
4234
|
-
* `springVertexColors`, `cycleVertexColors`, `staggerVertexColors`. Cleared
|
|
4235
|
-
* automatically on animator unmount. */
|
|
4236
|
-
colorOverrides: ColorOverrideRegistry;
|
|
4237
|
-
/**
|
|
4238
|
-
* Subscribe to a callback fired once per RAF frame while any animation is
|
|
4239
|
-
* active. Returns an unsubscribe function. Used by consumers (typically
|
|
4240
|
-
* `<SceneCanvas>`) that need to repaint when an animation's side-effect
|
|
4241
|
-
* is read from a non-scene channel (e.g. `colorOverrides` consulted from
|
|
4242
|
-
* a custom `drawOne`) — scene mutations naturally trigger a repaint, but
|
|
4243
|
-
* `colorOverrides` writes do not.
|
|
4244
|
-
*
|
|
4245
|
-
* The callback fires AFTER the per-frame tick of each registered
|
|
4246
|
-
* animation, so by the time it runs `colorOverrides.get(...)` returns
|
|
4247
|
-
* the latest values. If no animations are active, no tick fires.
|
|
4248
|
-
*/
|
|
4249
|
-
onTick(cb: () => void): () => void;
|
|
4250
|
-
/**
|
|
4251
|
-
* Keep the animator's RAF loop running until the returned cancel
|
|
4252
|
-
* function is called. Use for animations whose effect is read on every
|
|
4253
|
-
* frame but which don't have a natural progress state (e.g.
|
|
4254
|
-
* `cycleVertexColors`, which expresses its current value as a function
|
|
4255
|
-
* of `performance.now()` rather than as a tween from `from` to `to`).
|
|
4256
|
-
* Without a keep-alive entry the loop would idle and `onTick` would
|
|
4257
|
-
* stop firing even though the override is still installed.
|
|
4258
|
-
*/
|
|
4259
|
-
keepAlive(): () => void;
|
|
4260
|
-
}
|
|
4261
|
-
/** Options for `Animator.loop`. */
|
|
4262
|
-
interface LoopOptions {
|
|
4263
|
-
/** Maximum number of iterations. Default Infinity. */
|
|
4264
|
-
count?: number;
|
|
4265
|
-
/** Invoked when the loop reaches `count` iterations naturally (not on cancel). */
|
|
4266
|
-
onDone?: () => void;
|
|
4267
|
-
/** Any new animation passed the same cancelKey cancels the prior one in flight.
|
|
4268
|
-
* Also enables `animator.cancelKey` / `animator.isActive(key)` for this loop. */
|
|
4269
|
-
cancelKey?: string;
|
|
4270
|
-
}
|
|
4271
|
-
/** Options for the top-level `Animator.stagger` factory form (third overload). */
|
|
4272
|
-
interface StaggerOptions {
|
|
4273
|
-
/** Cancel-key for the supervising registration. `animator.cancelKey(key)`
|
|
4274
|
-
* cancels the whole stagger; `animator.isActive(key)` returns true while
|
|
4275
|
-
* any timer or child is alive. */
|
|
4276
|
-
cancelKey?: string;
|
|
4277
|
-
}
|
|
4278
|
-
/** Produces one iteration of a loop. Must arrange for `next` to be called when
|
|
4279
|
-
* the animation it returns finishes, or the loop stalls after one pass. */
|
|
4280
|
-
type LoopFactory = (iteration: number, next: () => void) => AnimationHandle;
|
|
4281
|
-
/** Per-index delay schedule. Number ⇒ `index * delay` ms. Function ⇒ caller
|
|
4282
|
-
* decides the absolute delay for each index (e.g. `i => i * i * 30`). */
|
|
4283
|
-
type StaggerDelay = number | ((index: number) => number);
|
|
4284
|
-
/** Produces the animation for one staggered item. */
|
|
4285
|
-
type StaggerFactory<TItem> = (item: TItem, index: number) => AnimationHandle;
|
|
4286
|
-
/** A `T` value or a function that derives one from the per-item context. Used
|
|
4287
|
-
* by the fluent builder methods (`.tween`, `.springPose`) so each item can
|
|
4288
|
-
* vary an option (e.g. `to: (_item, i) => (i + 1) * 10`). */
|
|
4289
|
-
type StaggerPerItem<T, TItem> = T | ((item: TItem, index: number) => T);
|
|
4290
|
-
/** Options for the stagger builder's `.tween`: a tween per item, where
|
|
4291
|
-
* `from`, `to` and `ms` may each vary by item. */
|
|
4292
|
-
interface StaggerTweenOptions<T, TItem> {
|
|
4293
|
-
from: StaggerPerItem<T, TItem>;
|
|
4294
|
-
to: StaggerPerItem<T, TItem>;
|
|
4295
|
-
ms: StaggerPerItem<number, TItem>;
|
|
4296
|
-
easing?: EasingFn;
|
|
4297
|
-
interpolate?: Interpolate<T>;
|
|
4298
|
-
onTick: (value: T, item: TItem, index: number) => void;
|
|
4299
|
-
onDone?: (item: TItem, index: number) => void;
|
|
4300
|
-
}
|
|
4301
|
-
/** Options for the stagger builder's `.springPose`: the spring tuning, and
|
|
4302
|
-
* whether each item's settle is recorded as an undoable op. */
|
|
4303
|
-
interface StaggerSpringPoseOptions<TPose> {
|
|
4304
|
-
preset?: SpringPresetName;
|
|
4305
|
-
stiffness?: number;
|
|
4306
|
-
damping?: number;
|
|
4307
|
-
mass?: number;
|
|
4308
|
-
geometry?: PoseProjection<TPose>;
|
|
4309
|
-
recordOp?: boolean;
|
|
4310
|
-
opLabel?: string;
|
|
4311
|
-
}
|
|
4312
|
-
/** Fluent form of `Animator.stagger`: pick what to run per item after the
|
|
4313
|
-
* items and the delay schedule are already fixed. */
|
|
4314
|
-
interface StaggerBuilder<TItem> {
|
|
4315
|
-
/** Run an arbitrary per-item factory. */
|
|
4316
|
-
each(factory: StaggerFactory<TItem>): AnimationHandle;
|
|
4317
|
-
/** Sugar: per-item `animator.tween` with per-item-varying options. */
|
|
4318
|
-
tween<T>(opts: StaggerTweenOptions<T, TItem>): AnimationHandle;
|
|
4319
|
-
/** Sugar: per-item `springPose` against an adapter. `poseFn` returns the
|
|
4320
|
-
* target pose for each item. Each item must either be a primitive
|
|
4321
|
-
* (string/number) or expose a string `id` field — otherwise pose ids
|
|
4322
|
-
* would collide on `"[object Object]"` and successive tweens would
|
|
4323
|
-
* cancel each other. Throws on items that satisfy neither. */
|
|
4324
|
-
springPose<TPose>(adapter: SceneAdapter<{
|
|
4325
|
-
id: string;
|
|
4326
|
-
}, TPose>, poseFn: (item: TItem, index: number) => TPose, opts?: StaggerSpringPoseOptions<TPose>): AnimationHandle;
|
|
4327
|
-
}
|
|
4328
|
-
/** Options for `Animator.tweenLoop` — a tween's options plus how each
|
|
4329
|
-
* iteration relates to the last. */
|
|
4330
|
-
interface TweenLoopOptions<T> {
|
|
4331
|
-
from: T;
|
|
4332
|
-
to: T;
|
|
4333
|
-
ms: number;
|
|
4334
|
-
easing?: EasingFn;
|
|
4335
|
-
/** `restart` (default): from→to every iteration.
|
|
4336
|
-
* `reverse`: to→from every iteration.
|
|
4337
|
-
* `alternate`: even iterations from→to, odd iterations to→from. */
|
|
4338
|
-
direction?: 'restart' | 'reverse' | 'alternate';
|
|
4339
|
-
count?: number;
|
|
4340
|
-
interpolate?: Interpolate<T>;
|
|
4341
|
-
onTick: (value: T) => void;
|
|
4342
|
-
onDone?: () => void;
|
|
4343
|
-
cancelKey?: string;
|
|
4730
|
+
layerOrder?: string[];
|
|
4344
4731
|
}
|
|
4345
4732
|
|
|
4346
4733
|
/** Minimal selection contract `sceneToAdapter` needs to wire `getSelection` /
|
|
@@ -4487,21 +4874,61 @@ interface UseRotateOptions<TPose> {
|
|
|
4487
4874
|
* Has no effect on single-id gestures. */
|
|
4488
4875
|
pivot?: 'each' | 'union';
|
|
4489
4876
|
}
|
|
4490
|
-
|
|
4877
|
+
|
|
4878
|
+
/** A rect on the surface, in CSS pixels from the canvas top-left. */
|
|
4879
|
+
interface ViewRect {
|
|
4880
|
+
x: number;
|
|
4881
|
+
y: number;
|
|
4882
|
+
w: number;
|
|
4883
|
+
h: number;
|
|
4884
|
+
}
|
|
4885
|
+
/** Props for `<CanvasView>`. @experimental */
|
|
4886
|
+
interface CanvasViewProps {
|
|
4887
|
+
/** Identifies the view to the surface and to input routing. Must be unique
|
|
4888
|
+
* among the views on one canvas. */
|
|
4889
|
+
id: string;
|
|
4890
|
+
/** Where this view paints, recomputed every frame so the rect can track the
|
|
4891
|
+
* outer camera. A plain rect is accepted for a fixed panel. */
|
|
4892
|
+
bounds: ViewRect | ((outer: View, dims: Dims) => ViewRect);
|
|
4893
|
+
/** Camera. Supply this to control it; otherwise the view keeps its own,
|
|
4894
|
+
* seeded from `defaultView`. `onViewChange` fires either way. */
|
|
4895
|
+
view?: View;
|
|
4896
|
+
defaultView?: View;
|
|
4897
|
+
onViewChange?: (v: View) => void;
|
|
4898
|
+
/** Pan limits, applied to every camera change the same way `<Canvas>`
|
|
4899
|
+
* applies its own. */
|
|
4900
|
+
viewBounds?: Bounds;
|
|
4901
|
+
/** Which of the surface's layers this view paints. Defaults to all of them —
|
|
4902
|
+
* the same content through a second camera. */
|
|
4903
|
+
layers?: (surface: readonly RenderLayer<unknown>[]) => readonly RenderLayer<unknown>[];
|
|
4904
|
+
/** Opaque ground painted before the source layers, so the surface does not
|
|
4905
|
+
* show through where the inner camera sees nothing. */
|
|
4906
|
+
background?: string;
|
|
4907
|
+
/** Paint and hit order. Defaults to `Infinity` — after every view the
|
|
4908
|
+
* surface declared as a prop. */
|
|
4909
|
+
order?: number;
|
|
4910
|
+
/** Label for debug overlays. Defaults to the id. */
|
|
4911
|
+
label?: string;
|
|
4912
|
+
/** A selection of this view's own, which actions dispatched inside it read
|
|
4913
|
+
* and write instead of the surface's. Omit both this and
|
|
4914
|
+
* `selectionOptions` and the view shares the surface's selection — the
|
|
4915
|
+
* default, so undo restores one selection rather than N. */
|
|
4916
|
+
selection?: SelectionApi;
|
|
4917
|
+
/** Opts this view into owning a selection, configured thus. Ignored when
|
|
4918
|
+
* `selection` is supplied. */
|
|
4919
|
+
selectionOptions?: UseSelectionOptions;
|
|
4920
|
+
}
|
|
4491
4921
|
/**
|
|
4492
|
-
*
|
|
4493
|
-
* kit tool hook + a default `create` that produces a leaf node compatible
|
|
4494
|
-
* with `PATH_PAINTER`.
|
|
4922
|
+
* @experimental
|
|
4495
4923
|
*
|
|
4496
|
-
*
|
|
4497
|
-
*
|
|
4498
|
-
*
|
|
4924
|
+
* One view on a shared canvas. Owns a camera, contributes the viewport node
|
|
4925
|
+
* that paints it, and registers the dispatch record that sends gestures inside
|
|
4926
|
+
* its rect to that camera rather than to the canvas's.
|
|
4927
|
+
*
|
|
4928
|
+
* Renders nothing itself — it is a declaration, and the surface does the
|
|
4929
|
+
* drawing. Outside a surface that mounts a view registry it is inert.
|
|
4499
4930
|
*/
|
|
4500
|
-
|
|
4501
|
-
/** Runtime, iterable list of the shape-tool ids in `BuiltinShapeToolId`.
|
|
4502
|
-
* Surfaced so consumers (e.g. the Bundle Inspector) can enumerate the
|
|
4503
|
-
* builtin shape kinds without re-encoding the union. */
|
|
4504
|
-
declare const KIT_SHAPE_KINDS: readonly ["rect", "ellipse", "line", "polygon", "star", "pen", "pencil", "lasso", "text"];
|
|
4931
|
+
declare function CanvasView(props: CanvasViewProps): null;
|
|
4505
4932
|
|
|
4506
4933
|
/** Per-tool option overrides for the built-in shape/lasso tools.
|
|
4507
4934
|
* Each entry is a narrow subset of the underlying hook's options surface
|
|
@@ -4640,182 +5067,6 @@ declare function createNodeRouting(): NodeRouting;
|
|
|
4640
5067
|
* matches `poseRotationOf` (the shared rotation convention). */
|
|
4641
5068
|
declare function rotateAroundAABBCenter(x: number, y: number, width: number, height: number, rotation: number): Float32Array;
|
|
4642
5069
|
|
|
4643
|
-
/**
|
|
4644
|
-
* NodeShape — the **shape trait's** registry. Each trait of a node
|
|
4645
|
-
* (shape, routing, label, icon, affordances, …) is its own registry;
|
|
4646
|
-
* this one holds the per-kind `paint` + `silhouette` (and future
|
|
4647
|
-
* fields) used by `defaultDrawOne`, clipping, non-rect hit-testing,
|
|
4648
|
-
* lasso/area-select, and SVG export.
|
|
4649
|
-
*
|
|
4650
|
-
* Teaching the kit about a new kind of shape goes through this registry
|
|
4651
|
-
* rather than by overriding `drawOne`. Overrides are still possible but
|
|
4652
|
-
* shouldn't be the default seam: most consumers want the same dispatch
|
|
4653
|
-
* logic, just extended with their own shape kinds (images, custom paths,
|
|
4654
|
-
* SVG fragments, etc.).
|
|
4655
|
-
*
|
|
4656
|
-
* Built-in entries (`kit:text`, `kit:path`, `kit:rect-fallback`) are
|
|
4657
|
-
* registered at module load. Consumer entries added via
|
|
4658
|
-
* `registerNodeShape` join the chain; the first entry whose
|
|
4659
|
-
* `matches` predicate returns true paints the node.
|
|
4660
|
-
*
|
|
4661
|
-
* Two priority tiers:
|
|
4662
|
-
* - `'high'` — checked before all `'normal'` entries. Use this to
|
|
4663
|
-
* override a kit built-in for a specific data shape (e.g. a custom
|
|
4664
|
-
* text renderer that wins over `kit:text`).
|
|
4665
|
-
* - `'normal'` (default) — appended after the built-ins.
|
|
4666
|
-
*
|
|
4667
|
-
* Within a tier, entries run in registration order. Each
|
|
4668
|
-
* `registerNodeShape` call returns a disposer that removes the
|
|
4669
|
-
* entry — useful for tests, for plugin lifecycles, and for swapping
|
|
4670
|
-
* implementations at runtime.
|
|
4671
|
-
*
|
|
4672
|
-
* See `docs/superpowers/specs/2026-05-24-node-traits-reframe-design.md`
|
|
4673
|
-
* for the trait taxonomy.
|
|
4674
|
-
*/
|
|
4675
|
-
|
|
4676
|
-
/** Optional per-call paint context, threaded through `defaultDrawOne`'s third
|
|
4677
|
-
* argument. Lets a rendering entry point override ambient environment reads
|
|
4678
|
-
* — the headless `renderSceneToPixels` path supplies its own bitmap resolver
|
|
4679
|
-
* here so consumers reuse their own decode caches. Custom painters may
|
|
4680
|
-
* ignore it entirely. */
|
|
4681
|
-
interface NodePaintCtx {
|
|
4682
|
-
/** Override bitmap resolution for image nodes. When set it is authoritative:
|
|
4683
|
-
* the global `imageCache` is not consulted, and an `undefined` result
|
|
4684
|
-
* paints the deterministic grey placeholder outline (never the ambient
|
|
4685
|
-
* load-status error variant). */
|
|
4686
|
-
resolveImage?: (node: Node$1<unknown, string, unknown>) => ImageBitmap | undefined;
|
|
4687
|
-
}
|
|
4688
|
-
/** A painter for one kind of node: which nodes it claims, and the draw
|
|
4689
|
-
* commands it emits for them. Registering one is how a consumer teaches the
|
|
4690
|
-
* default renderer to draw its own node kinds. */
|
|
4691
|
-
interface NodeShapeEntry<TData = unknown, TPose = unknown> {
|
|
4692
|
-
/** Stable identifier — used for unregistration and debugging. Pick
|
|
4693
|
-
* something descriptive: `'kit:text'`, `'app:image'`, etc. */
|
|
4694
|
-
id: string;
|
|
4695
|
-
/** Returns true when this painter renders the node. The first matching
|
|
4696
|
-
* painter (`'high'` tier first, then `'normal'`) wins. */
|
|
4697
|
-
matches(node: Node$1<TData, string, TPose>): boolean;
|
|
4698
|
-
/** Emits the draw commands for the node's primary visual. `ctx` is an
|
|
4699
|
-
* optional per-call paint context (see `NodePaintCtx`); painters that
|
|
4700
|
-
* don't need it can keep a two-argument signature.
|
|
4701
|
-
*
|
|
4702
|
-
* **The returned array belongs to the painter.** Callers must treat it as
|
|
4703
|
-
* immutable and copy before appending — a painter is free to memoize its
|
|
4704
|
-
* command list (`kit:shape` and `kit:path` do), and an in-place `push`
|
|
4705
|
-
* would grow that list on every frame. `defaultDrawOne` copies before
|
|
4706
|
-
* adding its label overlay for exactly this reason. */
|
|
4707
|
-
paint(node: Node$1<TData, string, TPose>, pose: TPose, ctx?: NodePaintCtx): DrawCommand[];
|
|
4708
|
-
/** Optional: derive the node's silhouette path from its pose.
|
|
4709
|
-
* Used by clipping (when the container has no explicit
|
|
4710
|
-
* `clipFromPose`), by non-rect hit-testing, by lasso/area-select,
|
|
4711
|
-
* and by SVG export. Painters whose visual has no meaningful closed
|
|
4712
|
-
* silhouette (e.g. text) leave this undefined. */
|
|
4713
|
-
silhouette?(node: Node$1<TData, string, TPose>, pose: TPose): Path | null;
|
|
4714
|
-
/** Optional: how the silhouette is inked — whether the interior is filled,
|
|
4715
|
-
* and how wide the outline is. Read by picking, so that an unfilled shape
|
|
4716
|
-
* is grabbable by its outline rather than by its empty middle.
|
|
4717
|
-
*
|
|
4718
|
-
* This is declared separately from `paint` rather than read back off the
|
|
4719
|
-
* emitted draw commands because picking runs on every pointer move, and
|
|
4720
|
-
* `paint` is allowed to be expensive (`kit:text` lays out glyphs). Keep it
|
|
4721
|
-
* to cheap field reads.
|
|
4722
|
-
*
|
|
4723
|
-
* Painters that leave it undefined are treated as `{ filled: true,
|
|
4724
|
-
* strokeWidth: 0 }` — the pre-`ink` behavior, where the whole silhouette
|
|
4725
|
-
* interior is grabbable and the outline adds nothing. */
|
|
4726
|
-
ink?(node: Node$1<TData, string, TPose>, pose: TPose): NodeInk | null;
|
|
4727
|
-
}
|
|
4728
|
-
/** How a painter inks its silhouette. See {@link NodeShapeEntry.ink}. */
|
|
4729
|
-
interface NodeInk {
|
|
4730
|
-
/** True when the silhouette's interior is painted, and so grabbable. */
|
|
4731
|
-
filled: boolean;
|
|
4732
|
-
/** Stroke width in world units. `0` for no stroke. */
|
|
4733
|
-
strokeWidth: number;
|
|
4734
|
-
}
|
|
4735
|
-
/** Options for `registerNodeShape`. */
|
|
4736
|
-
interface RegisterNodeShapeOptions {
|
|
4737
|
-
/** `'high'` puts the painter ahead of all normally-registered ones (so
|
|
4738
|
-
* it can win over a kit built-in). `'normal'` appends at the end. */
|
|
4739
|
-
priority?: 'high' | 'normal';
|
|
4740
|
-
}
|
|
4741
|
-
/** Register a shape painter. Returns a disposer that removes it. */
|
|
4742
|
-
declare function registerNodeShape<TData, TPose>(painter: NodeShapeEntry<TData, TPose>, opts?: RegisterNodeShapeOptions): () => void;
|
|
4743
|
-
/** Find the painter that will render `node` — first match in priority
|
|
4744
|
-
* order. Returns undefined if no painter (including the built-in
|
|
4745
|
-
* fallback) accepts the node. */
|
|
4746
|
-
declare function findNodeShape<TData, TPose>(node: Node$1<TData, string, TPose>): NodeShapeEntry<TData, TPose> | undefined;
|
|
4747
|
-
/** Find the painter for `node` and ask it for the node's silhouette path,
|
|
4748
|
-
* in **world** coords. Returns null if no painter matches, or the matching
|
|
4749
|
-
* painter has no `silhouette` method, or the method returns null. Used by
|
|
4750
|
-
* clipping, generic non-rect hit-testing, lasso, and SVG export — anywhere
|
|
4751
|
-
* the kit needs the "closed boundary" of whatever this kind of node draws as.
|
|
4752
|
-
*
|
|
4753
|
-
* Painters return their silhouette in the pose's local (unrotated) frame;
|
|
4754
|
-
* this bakes `pose.rotation` on top via the shared rotation convention, so
|
|
4755
|
-
* clips/area-select of a rotated node use the rotated boundary the renderer
|
|
4756
|
-
* draws. (`paint()` is unaffected — it applies rotation via the render wrap,
|
|
4757
|
-
* not the silhouette, so there is no double-rotation.) */
|
|
4758
|
-
declare function findShapeSilhouette<TData, TPose>(node: Node$1<TData, string, TPose>, pose: TPose): Path | null;
|
|
4759
|
-
/** Find the painter for `node` and ask how it inks its silhouette. Returns
|
|
4760
|
-
* the painter's declared {@link NodeInk}, or `null` when no painter matches
|
|
4761
|
-
* or it declares none — callers substitute {@link DEFAULT_INK}. */
|
|
4762
|
-
declare function findShapeInk<TData, TPose>(node: Node$1<TData, string, TPose>, pose: TPose): NodeInk | null;
|
|
4763
|
-
/** Options for {@link shapeCoversPoint}. */
|
|
4764
|
-
interface ShapeCoversPointOptions {
|
|
4765
|
-
/** Extra grab distance around the outline, in **world** units. Callers
|
|
4766
|
-
* derive it from a screen-pixel slop and the view scale, the same way
|
|
4767
|
-
* affordance hit radii work.
|
|
4768
|
-
*
|
|
4769
|
-
* Without slop a hairline is a mathematically zero-width target: the
|
|
4770
|
-
* stroke of a 1px outline is half a world unit wide at scale 1, which no
|
|
4771
|
-
* one can hit. Defaults to `0` so a caller that hasn't thought about the
|
|
4772
|
-
* view still gets exact geometry rather than a wrong guess. */
|
|
4773
|
-
tolerance?: number;
|
|
4774
|
-
}
|
|
4775
|
-
/**
|
|
4776
|
-
* Does the shape `node` actually paints cover the world point?
|
|
4777
|
-
*
|
|
4778
|
-
* The pose rect says a node covers its whole bounding box. That is wrong for
|
|
4779
|
-
* everything that is not a rectangle: the concave notch of a star, the corner
|
|
4780
|
-
* outside an ellipse, the blank right half of a text box. This asks the
|
|
4781
|
-
* painter's silhouette instead, which is the same boundary used for clipping
|
|
4782
|
-
* and SVG export, so "what you can click" and "what is drawn" answer together.
|
|
4783
|
-
*
|
|
4784
|
-
* "What is drawn" includes the *ink*, not just the boundary. A shape whose
|
|
4785
|
-
* interior isn't filled — an outlined rect, a pencil stroke, a bare line — is
|
|
4786
|
-
* grabbable along its outline and not through its empty middle, which is the
|
|
4787
|
-
* opposite of what a fill test alone answers. The outline's grab width is the
|
|
4788
|
-
* stroke's half-width plus `tolerance`.
|
|
4789
|
-
*
|
|
4790
|
-
* A painter with no `silhouette`, or one that returns `null` for this node
|
|
4791
|
-
* (`kit:text` does, for a node with no non-blank lines), reports `true` —
|
|
4792
|
-
* "no opinion", leaving the caller's own AABB test as the answer. Callers
|
|
4793
|
-
* should keep that AABB test as a cheap pre-filter; this is the refinement,
|
|
4794
|
-
* not a replacement.
|
|
4795
|
-
*
|
|
4796
|
-
* Rotation is already baked by `findShapeSilhouette`, so the point is in
|
|
4797
|
-
* plain world coordinates.
|
|
4798
|
-
*/
|
|
4799
|
-
declare function shapeCoversPoint<TData, TPose>(node: Node$1<TData, string, TPose>, pose: TPose, x: number, y: number, opts?: ShapeCoversPointOptions): boolean;
|
|
4800
|
-
/** Snapshot of the current painters in evaluation order — `'high'` tier
|
|
4801
|
-
* first, then `'normal'`. Useful for debugging which painter handles a
|
|
4802
|
-
* given node. */
|
|
4803
|
-
declare function getNodeShapes(): readonly NodeShapeEntry[];
|
|
4804
|
-
/**
|
|
4805
|
-
* What a node's `data.fill` means to the built-in painters.
|
|
4806
|
-
*
|
|
4807
|
-
* A string is a color, `'none'` skips the fill, and an object is a
|
|
4808
|
-
* {@link FillStyle} used as-is — which is how a gradient or a pattern reaches
|
|
4809
|
-
* the renderer without a consumer registering a painter of its own. The
|
|
4810
|
-
* renderer has taken every `FillStyle` variant since the paint model landed;
|
|
4811
|
-
* only these two painters were narrower than it.
|
|
4812
|
-
*
|
|
4813
|
-
* `undefined` falls back to `data.color`, then to a default fill — but only
|
|
4814
|
-
* when there is no stroke, since a stroke-only path (pencil) should not
|
|
4815
|
-
* acquire one.
|
|
4816
|
-
*/
|
|
4817
|
-
type NodeFill = string | FillStyle;
|
|
4818
|
-
|
|
4819
5070
|
/**
|
|
4820
5071
|
* `defaultDrawOne` — the kit's default per-node draw function.
|
|
4821
5072
|
*
|
|
@@ -4845,7 +5096,7 @@ type NodeFill = string | FillStyle;
|
|
|
4845
5096
|
/** Paint one node the way the kit does by default: dispatch to the first
|
|
4846
5097
|
* registered node-shape painter that matches, then draw its `data.label` on
|
|
4847
5098
|
* top when it has one. Consumers replace or wrap this via `drawOne`. */
|
|
4848
|
-
declare function defaultDrawOne<TData, TLayer extends string, TPose>(node: Node$1<TData, TLayer, TPose>, pose: TPose, ctx?: NodePaintCtx): DrawCommand[];
|
|
5099
|
+
declare function defaultDrawOne<TData, TLayer extends string, TPose>(node: Node$1<TData, TLayer, TPose>, pose: TPose, _view?: View, ctx?: NodePaintCtx): DrawCommand[];
|
|
4849
5100
|
|
|
4850
5101
|
/** Default size in CSS pixels for selection corner-handles AND their
|
|
4851
5102
|
* hit-test radius, at `targetScale = 1`. Used by the SceneCanvas defaults;
|
|
@@ -4855,10 +5106,13 @@ declare function defaultDrawOne<TData, TLayer extends string, TPose>(node: Node$
|
|
|
4855
5106
|
* Deliberately unscaled: consumers reading this constant keep getting the
|
|
4856
5107
|
* number they always got. Kit-internal use sites multiply by
|
|
4857
5108
|
* `DeviceProfile.targetScale`. */
|
|
4858
|
-
declare const DEFAULT_HANDLE_SIZE
|
|
5109
|
+
declare const DEFAULT_HANDLE_SIZE: 8;
|
|
5110
|
+
/** Built-in tool ids that aren't shape tools — the ones with no entry in
|
|
5111
|
+
* the `core/shapeKinds` table. */
|
|
5112
|
+
declare const NON_SHAPE_BUILTIN_TOOLS: readonly ["select", "rotate", "hand"];
|
|
4859
5113
|
/** Built-in tool ids SceneCanvas knows how to mount when no `tools` prop
|
|
4860
5114
|
* is supplied. Pass a subset via `defaultTools` to slim the registered set. */
|
|
4861
|
-
type BuiltinToolId =
|
|
5115
|
+
type BuiltinToolId = (typeof NON_SHAPE_BUILTIN_TOOLS)[number] | BuiltinShapeToolId;
|
|
4862
5116
|
/** Named preset tool collections for the `toolBundle` prop. Maps to a
|
|
4863
5117
|
* `BuiltinToolId[]` consumed by SceneCanvas's internal `useTools`. */
|
|
4864
5118
|
type ToolBundle = 'minimal' | 'standard' | 'exhaustive';
|
|
@@ -4877,7 +5131,7 @@ interface SceneCanvasHit {
|
|
|
4877
5131
|
/** Props for `<SceneCanvas>`. Most are optional: a scene is the only thing it
|
|
4878
5132
|
* truly needs, and everything else — tools, layers, selection handling,
|
|
4879
5133
|
* layouts, animation — layers onto sensible defaults. */
|
|
4880
|
-
type SceneCanvasProps<TData, TLayer extends string, TPose> = Omit<CanvasProps<Node$1<TData, TLayer, TPose>, TPose>, 'adapter' | 'moveOptions' | 'resizeOptions' | 'rotateOptions' | 'snap' | 'pickEvery' | 'boundsOf' | 'handleHitRadius' | 'selection' | 'selectionOptions' | 'tools' | 'geometry' | 'layers' | 'onBackgroundClick' | 'getIsVisible'> & {
|
|
5134
|
+
type SceneCanvasProps<TData, TLayer extends string, TPose> = Omit<CanvasProps<Node$1<TData, TLayer, TPose>, TPose>, 'adapter' | 'moveOptions' | 'resizeOptions' | 'rotateOptions' | 'snap' | 'pickEvery' | 'boundsOf' | 'handleHitRadius' | 'selection' | 'selectionOptions' | 'tools' | 'geometry' | 'layers' | 'onBackgroundClick' | 'getIsVisible' | 'contentVersion'> & {
|
|
4881
5135
|
/** A `Scene` (typically from `useScene`) — or a `SerializedScene`
|
|
4882
5136
|
* JSON object, which SceneCanvas bakes into a Scene internally on
|
|
4883
5137
|
* first render. The serialized form is read once; subsequent
|
|
@@ -5133,17 +5387,19 @@ type SceneCanvasProps<TData, TLayer extends string, TPose> = Omit<CanvasProps<No
|
|
|
5133
5387
|
ambient?: AnyTool[];
|
|
5134
5388
|
/** Viewport feature wiring.
|
|
5135
5389
|
*
|
|
5136
|
-
* - `inertia
|
|
5137
|
-
*
|
|
5138
|
-
* - `pan` (wheel pan)
|
|
5139
|
-
* on by default; pass `false` to
|
|
5140
|
-
* the kit's `viewport
|
|
5141
|
-
* the actions registry — disabling via the
|
|
5142
|
-
* (`actions: { 'viewport.wheelPan': null }`) also works
|
|
5390
|
+
* - `inertia` and `animatedZoom` are opt-in: pass `true` for defaults or
|
|
5391
|
+
* an object to tune. Omitted means off.
|
|
5392
|
+
* - `pan` (wheel pan), `zoom` (Cmd+wheel + Cmd+=/-/0) and `pinchZoom`
|
|
5393
|
+
* (two-finger pinch) are opt-OUT: on by default; pass `false` to
|
|
5394
|
+
* disable. All three are wired by registering the kit's `viewport.*`
|
|
5395
|
+
* action descriptors with the actions registry — disabling via the
|
|
5396
|
+
* `actions` prop (`actions: { 'viewport.wheelPan': null }`) also works
|
|
5397
|
+
* and runs after this.
|
|
5143
5398
|
*
|
|
5144
|
-
* When omitted entirely, no hand
|
|
5145
|
-
*
|
|
5146
|
-
* default). Pass `{ pan: false, zoom: false }` to opt
|
|
5399
|
+
* When omitted entirely, no hand tool is registered but the default wheel
|
|
5400
|
+
* pan, Cmd+wheel/key zoom and pinch zoom remain wired (canvas-first
|
|
5401
|
+
* default). Pass `{ pan: false, zoom: false, pinchZoom: false }` to opt
|
|
5402
|
+
* out entirely. */
|
|
5147
5403
|
viewport?: {
|
|
5148
5404
|
inertia?: boolean | {
|
|
5149
5405
|
friction?: number;
|
|
@@ -5151,15 +5407,14 @@ type SceneCanvasProps<TData, TLayer extends string, TPose> = Omit<CanvasProps<No
|
|
|
5151
5407
|
boundary?: 'stop' | 'bounce' | 'spring';
|
|
5152
5408
|
bounds?: PanBounds;
|
|
5153
5409
|
};
|
|
5154
|
-
|
|
5155
|
-
|
|
5156
|
-
|
|
5157
|
-
|
|
5158
|
-
|
|
5159
|
-
|
|
5160
|
-
|
|
5161
|
-
|
|
5162
|
-
};
|
|
5410
|
+
/** Two-finger pinch zoom. `true`/omitted = on with the kit's 0.1–8
|
|
5411
|
+
* clamp; `false` disables. An object sets the scale clamp. */
|
|
5412
|
+
pinchZoom?: boolean | PinchZoomOptions;
|
|
5413
|
+
/** Glide Cmd+=/-/0 instead of jumping. `true` uses the kit defaults
|
|
5414
|
+
* (250 ms, ease-out-cubic); a {@link ViewportZoomAnimateOptions} tunes
|
|
5415
|
+
* duration, easing, interpolator and the reset-branch duration. Wheel
|
|
5416
|
+
* and pinch are unaffected — their input already samples every frame. */
|
|
5417
|
+
animatedZoom?: boolean | ViewportZoomAnimateOptions;
|
|
5163
5418
|
pan?: boolean;
|
|
5164
5419
|
/** Wheel/keyboard zoom. `true`/omitted = default Cmd+wheel zoom with the
|
|
5165
5420
|
* kit's 0.1–8 clamp; `false` disables. Pass a {@link ViewportZoomOptions}
|
|
@@ -5168,10 +5423,11 @@ type SceneCanvasProps<TData, TLayer extends string, TPose> = Omit<CanvasProps<No
|
|
|
5168
5423
|
zoom?: boolean | ViewportZoomOptions;
|
|
5169
5424
|
/** Callback invoked by Cmd-0 (`viewport.zoom` action's `reset` branch).
|
|
5170
5425
|
* When supplied, replaces the default reset-to-identity behavior —
|
|
5171
|
-
* consumers typically refit the document page into the workspace
|
|
5172
|
-
*
|
|
5173
|
-
*
|
|
5174
|
-
|
|
5426
|
+
* consumers typically refit the document page into the workspace via
|
|
5427
|
+
* `fitViewToBounds`. Return the target `View` to let the kit animate
|
|
5428
|
+
* there when `animatedZoom` is on; return nothing to dispatch it
|
|
5429
|
+
* yourself, which is what a controlled canvas does. */
|
|
5430
|
+
recenter?: () => View | void;
|
|
5175
5431
|
};
|
|
5176
5432
|
/**
|
|
5177
5433
|
* @experimental
|
|
@@ -5231,6 +5487,17 @@ type SceneCanvasProps<TData, TLayer extends string, TPose> = Omit<CanvasProps<No
|
|
|
5231
5487
|
* subscriber list stays quiet).
|
|
5232
5488
|
*/
|
|
5233
5489
|
animator?: Animator;
|
|
5490
|
+
/**
|
|
5491
|
+
* Extra views on this canvas: each is a camera over a rect of the same
|
|
5492
|
+
* surface, drawn through one GL context, with input routed to it. The flat
|
|
5493
|
+
* `view` / `onViewChange` props above stay the canvas's own camera — view
|
|
5494
|
+
* zero — and are unaffected by anything declared here.
|
|
5495
|
+
*
|
|
5496
|
+
* Order is paint and hit order, low to high. Each entry is a
|
|
5497
|
+
* `<CanvasView>`; mounting one as a child is the same declaration, and
|
|
5498
|
+
* children land after every entry here.
|
|
5499
|
+
*/
|
|
5500
|
+
views?: readonly CanvasViewProps[];
|
|
5234
5501
|
/**
|
|
5235
5502
|
* Children rendered alongside the canvas. Useful for siblings that need
|
|
5236
5503
|
* the same `<ActionsProvider>` scope (e.g. shortcuts overlays, probes).
|
|
@@ -5572,17 +5839,6 @@ declare const inferredNodeProperties: readonly NodePropertiesEntry[];
|
|
|
5572
5839
|
* in sync by hand where it matters (DPR handling, viewToMat3 wrap).
|
|
5573
5840
|
*/
|
|
5574
5841
|
|
|
5575
|
-
/**
|
|
5576
|
-
* Per-node draw function. Mirrors the scene-slot `drawOne` signature on
|
|
5577
|
-
* `<SceneCanvas>` (`SceneSlotConfig.drawOne`) so consumers can reuse the
|
|
5578
|
-
* same callback (or a simplified variant) between a main canvas and a
|
|
5579
|
-
* detached scene-view canvas.
|
|
5580
|
-
*
|
|
5581
|
-
* The function is called once per node in `scene.renderOrder()`. Returned
|
|
5582
|
-
* commands are in world coords; the caller's `view` is applied at the
|
|
5583
|
-
* group level (see `renderSceneToCanvas`'s implementation).
|
|
5584
|
-
*/
|
|
5585
|
-
type SceneViewDrawOne<TData, TLayer extends string, TPose> = (node: Node$1<TData, TLayer, TPose>, pose: TPose, view: View) => DrawCommand[];
|
|
5586
5842
|
/** What to draw into an existing canvas: the scene, the view, and the same
|
|
5587
5843
|
* painting hooks `<SceneCanvas>` takes. */
|
|
5588
5844
|
interface RenderSceneToCanvasArgs<TData, TLayer extends string, TPose> {
|
|
@@ -5706,6 +5962,14 @@ declare const SceneViewCanvas: typeof SceneViewCanvasInner;
|
|
|
5706
5962
|
* this in tests, in headless rendering, or wherever a scene must outlive a
|
|
5707
5963
|
* component. Throws if no system layers are declared. */
|
|
5708
5964
|
declare function createScene<TData, TLayer extends string, TPose = RectPose>(options: UseSceneOptions<TData, TLayer, TPose>): Scene<TData, TLayer, TPose>;
|
|
5965
|
+
/** The scene's selection in the shape `createHistory` wants, for a consumer
|
|
5966
|
+
* building a second History over the same scene (a modality machine, a
|
|
5967
|
+
* journal owner) that should restore selection the way the scene's own
|
|
5968
|
+
* history does. */
|
|
5969
|
+
declare function sceneSelectionStore(scene: {
|
|
5970
|
+
getSelection(): readonly NodeId[];
|
|
5971
|
+
setSelection(ids: readonly NodeId[]): void;
|
|
5972
|
+
}): HistorySelection;
|
|
5709
5973
|
/** Reconstruct a Scene from a JSON snapshot produced by `scene.toJSON()`.
|
|
5710
5974
|
* Function fields (e.g., `clipFromPose`) are resolved by string key via the
|
|
5711
5975
|
* registry passed in `options`. Throws on unknown version, unknown registry
|
|
@@ -5732,12 +5996,16 @@ interface UseSceneTrivialOptions<TItem extends {
|
|
|
5732
5996
|
items: readonly TItem[];
|
|
5733
5997
|
historyLimit?: number;
|
|
5734
5998
|
generateId?: () => NodeId;
|
|
5999
|
+
/** Re-render the host on every scene mutation. Default `true`. See
|
|
6000
|
+
* {@link UseSceneOptions.subscribe}. */
|
|
6001
|
+
subscribe?: boolean;
|
|
5735
6002
|
}
|
|
5736
6003
|
declare const DEFAULT_LAYER: "default";
|
|
5737
6004
|
type DefaultLayer = typeof DEFAULT_LAYER;
|
|
5738
6005
|
/** React hook returning a kit-owned `Scene`. The Scene is constructed once
|
|
5739
6006
|
* per host component and tracked via `useSyncExternalStore`, so React re-
|
|
5740
|
-
* renders on every Scene mutation (including undo/redo)
|
|
6007
|
+
* renders on every Scene mutation (including undo/redo) unless
|
|
6008
|
+
* `subscribe: false` opts out.
|
|
5741
6009
|
*
|
|
5742
6010
|
* Two call shapes:
|
|
5743
6011
|
* - **Trivial**: `useScene({ items })` — one auto-registered system layer
|
|
@@ -5855,7 +6123,12 @@ interface MinimapCanvasProps<TData, TLayer extends string, TPose> {
|
|
|
5855
6123
|
* can reuse it (typically simplified — just colored AABBs). */
|
|
5856
6124
|
drawOne: SceneViewDrawOne<TData, TLayer, TPose>;
|
|
5857
6125
|
/** Fit policy. Defaults to `"scene"` (AABB union of leaf poses). See
|
|
5858
|
-
* `MinimapFit` for the full shape.
|
|
6126
|
+
* `MinimapFit` for the full shape.
|
|
6127
|
+
*
|
|
6128
|
+
* Framing is derived from **document** poses, not `scene.overrides` — a
|
|
6129
|
+
* node moved by an override paints where the override puts it, outside the
|
|
6130
|
+
* frame if it goes there, rather than making the whole minimap rescale on
|
|
6131
|
+
* every frame of a drag or a settle. */
|
|
5859
6132
|
fit?: MinimapFit<TData, TLayer, TPose>;
|
|
5860
6133
|
/** Pose → AABB. Defaults to identity (`pose as Bounds`), matching
|
|
5861
6134
|
* `sceneAdapter` / `useSelectTool`. */
|
|
@@ -5914,9 +6187,10 @@ interface RenderSceneToPixelsArgs<TData, TLayer extends string, TPose> {
|
|
|
5914
6187
|
y: number;
|
|
5915
6188
|
};
|
|
5916
6189
|
/** Per-node draw callback. Default: `defaultDrawOne` with `resolveImage`
|
|
5917
|
-
*
|
|
5918
|
-
* want resolver injection should call
|
|
5919
|
-
* themselves
|
|
6190
|
+
* merged into the `NodePaintCtx` the scene walk supplies. Custom `drawOne`
|
|
6191
|
+
* callers that still want resolver injection should call
|
|
6192
|
+
* `defaultDrawOne(node, pose, view, { ...ctx, resolveImage })` themselves —
|
|
6193
|
+
* dropping the walk's `ctx` drops derived geometry with it. */
|
|
5920
6194
|
drawOne?: SceneViewDrawOne<TData, TLayer, TPose>;
|
|
5921
6195
|
/** Bitmap resolver for image nodes — lets consumers reuse their own decode
|
|
5922
6196
|
* caches. `undefined` results paint the deterministic grey placeholder
|
|
@@ -6397,8 +6671,6 @@ declare const PATH_ANCHOR_CHROME_ID = "path-edit.anchors";
|
|
|
6397
6671
|
*/
|
|
6398
6672
|
declare function createPathAnchorAffordances(getAnchorState: () => AnchorState | null, opts?: PathAnchorAffordanceOptions): Affordance[];
|
|
6399
6673
|
|
|
6400
|
-
/** Pluggable text-painting strategy. The default fills white at `(x, y)`; markdown renderers replace this. */
|
|
6401
|
-
type TextRenderer = (ctx: CanvasRenderingContext2D, text: string, x: number, y: number) => void;
|
|
6402
6674
|
/** Visual options for `renderLabel`. */
|
|
6403
6675
|
interface LabelOptions {
|
|
6404
6676
|
align?: 'center' | 'left';
|
|
@@ -6420,112 +6692,6 @@ declare function renderLabel(ctx: CanvasRenderingContext2D, text: string, x: num
|
|
|
6420
6692
|
/** Default `TextRenderer` used by `renderLabel`: white fill, no styling. */
|
|
6421
6693
|
declare const defaultLabelTextRenderer: TextRenderer;
|
|
6422
6694
|
|
|
6423
|
-
/** Width-measurement strategy for `layoutMarkdown`; canvas-backed default supplied by `createMarkdownRenderer`. */
|
|
6424
|
-
type MeasureFn = (text: string, fontSize: number, bold: boolean, italic: boolean) => number;
|
|
6425
|
-
/** A `StyledRun` with its computed x-offset relative to the start of its line. */
|
|
6426
|
-
interface PositionedRun extends StyledRun {
|
|
6427
|
-
x: number;
|
|
6428
|
-
}
|
|
6429
|
-
/** A single laid-out line of text: its positioned runs, total width, and computed line height. */
|
|
6430
|
-
interface LayoutLine {
|
|
6431
|
-
runs: PositionedRun[];
|
|
6432
|
-
width: number;
|
|
6433
|
-
height: number;
|
|
6434
|
-
}
|
|
6435
|
-
/** Output of `layoutMarkdown`: per-line breakdown plus overall block dimensions. */
|
|
6436
|
-
interface LayoutResult {
|
|
6437
|
-
lines: LayoutLine[];
|
|
6438
|
-
width: number;
|
|
6439
|
-
height: number;
|
|
6440
|
-
}
|
|
6441
|
-
/** Word-wrap parsed runs into lines bounded by `maxWidth`; pass `Infinity` for single-line layout. */
|
|
6442
|
-
declare function layoutMarkdown(runs: StyledRun[], maxWidth: number, fontSize: number, measure: MeasureFn, lineHeightFactor?: number): LayoutResult;
|
|
6443
|
-
|
|
6444
|
-
/** Font styling options threaded through `createMarkdownRenderer`. */
|
|
6445
|
-
interface MarkdownFontOptions {
|
|
6446
|
-
/** Font-family spec (e.g. `'"Iowan Old Style", Georgia, serif'`). Defaults to `sans-serif`. */
|
|
6447
|
-
family?: string;
|
|
6448
|
-
/** Numeric weight applied to non-bold runs. Bold runs always use `bold`. Default `normal`. */
|
|
6449
|
-
weight?: string | number;
|
|
6450
|
-
/** Override fill color. When set, used for all runs (italic and bold). */
|
|
6451
|
-
color?: string;
|
|
6452
|
-
/** Multiplier applied to font size for line height. Default 1.3. */
|
|
6453
|
-
lineHeight?: number;
|
|
6454
|
-
}
|
|
6455
|
-
/** Build a fill+stroke `TextRenderer` pair for a markdown string at the given size; pre-computes layout once. */
|
|
6456
|
-
declare function createMarkdownRenderer(ctx: CanvasRenderingContext2D, text: string, fontSize: number, maxWidth?: number, fontOpts?: MarkdownFontOptions): {
|
|
6457
|
-
renderer: TextRenderer;
|
|
6458
|
-
strokeRenderer: TextRenderer;
|
|
6459
|
-
width: number;
|
|
6460
|
-
height: number;
|
|
6461
|
-
};
|
|
6462
|
-
|
|
6463
|
-
/**
|
|
6464
|
-
* Wrap-aware text measurement. Greedy word-wrap against `maxWidth` using
|
|
6465
|
-
* `ctx.measureText`. Lines explicitly broken by `\n` are preserved; long
|
|
6466
|
-
* single words that exceed `maxWidth` are emitted on their own line without
|
|
6467
|
-
* mid-word breaking (caller can decide to clip).
|
|
6468
|
-
*
|
|
6469
|
-
* Returns the laid-out lines, the total block height in world units
|
|
6470
|
-
* (`lines.length * fontSize * lineHeight`), and per-line `lineStarts` —
|
|
6471
|
-
* the offset of each line's first character in the original `text`. The
|
|
6472
|
-
* starts are used by `caretIndexAt` to map a clicked (x, y) back to a
|
|
6473
|
-
* character offset in the source string. Trailing whitespace consumed by
|
|
6474
|
-
* the wrap is not included in `lines[i]` but is implicit in the gap
|
|
6475
|
-
* between `lineStarts[i] + lines[i].length` and `lineStarts[i + 1]`.
|
|
6476
|
-
*
|
|
6477
|
-
* The caller owns the `ctx.font` setup — pass a context whose `font`
|
|
6478
|
-
* already matches `style` (use `fontString(style)`).
|
|
6479
|
-
*/
|
|
6480
|
-
|
|
6481
|
-
/**
|
|
6482
|
-
* Advance width of `text` in world units, tracking included.
|
|
6483
|
-
*
|
|
6484
|
-
* `letter-spacing` is not part of the CSS `font` shorthand, so a context
|
|
6485
|
-
* whose `font` was set from `fontString(style)` measures glyphs only. The
|
|
6486
|
-
* GL path (`layoutRuns`) adds `letterSpacing` after **every** code point
|
|
6487
|
-
* including the last, matching CSS, so this does too — and every 2D-side
|
|
6488
|
-
* width has to go through here or the two paths disagree about where a line
|
|
6489
|
-
* breaks.
|
|
6490
|
-
*/
|
|
6491
|
-
declare function measuredWidth(ctx: CanvasRenderingContext2D, text: string, style: ResolvedTextStyle): number;
|
|
6492
|
-
/** Result of `measureText`: wrapped lines, per-line source offsets, and total block height. */
|
|
6493
|
-
interface MeasuredText {
|
|
6494
|
-
lines: string[];
|
|
6495
|
-
lineStarts: number[];
|
|
6496
|
-
height: number;
|
|
6497
|
-
}
|
|
6498
|
-
/** Greedy word-wrap text measurement against `maxWidth`; preserves explicit `\n` breaks. */
|
|
6499
|
-
declare function measureText(ctx: CanvasRenderingContext2D, text: string, maxWidth: number, style: ResolvedTextStyle): MeasuredText;
|
|
6500
|
-
|
|
6501
|
-
/** Options for `measureTextBounds`. */
|
|
6502
|
-
interface MeasureTextBoundsOpts {
|
|
6503
|
-
/** Wrap width; words exceeding it start a new line. Default `Infinity` (no wrap). */
|
|
6504
|
-
maxWidth?: number;
|
|
6505
|
-
/** Overrides `style`'s `lineHeight` multiplier for this measurement. */
|
|
6506
|
-
lineHeight?: number;
|
|
6507
|
-
}
|
|
6508
|
-
/**
|
|
6509
|
-
* Measure how the GL/MSDF renderer will lay out a single plain-text string,
|
|
6510
|
-
* using the registered font atlas metrics. Mirrors {@link textCommand} exactly
|
|
6511
|
-
* (`resolveTextStyle` → `resolveRuns` → `layoutRuns`), so the returned bounds
|
|
6512
|
-
* match what actually gets drawn — use it to size backgrounds/pills, place
|
|
6513
|
-
* labels, or test overlap without guessing widths.
|
|
6514
|
-
*
|
|
6515
|
-
* Pass `opts.maxWidth` to measure word-wrapped height (e.g. for a fixed-width
|
|
6516
|
-
* text box); omitting it measures the unwrapped single-line width. `opts.lineHeight`
|
|
6517
|
-
* overrides the style's multiplier without changing `style` itself.
|
|
6518
|
-
*
|
|
6519
|
-
* Returns `{ width, height }` in the same units as `style.fontSize`. The font
|
|
6520
|
-
* must already be registered via `registerFont`; an unregistered family falls
|
|
6521
|
-
* back to the atlas fallback glyph (and warns), so register fonts at app boot
|
|
6522
|
-
* before measuring.
|
|
6523
|
-
*/
|
|
6524
|
-
declare function measureTextBounds(text: string, style?: TextStyle, opts?: MeasureTextBoundsOpts): {
|
|
6525
|
-
width: number;
|
|
6526
|
-
height: number;
|
|
6527
|
-
};
|
|
6528
|
-
|
|
6529
6695
|
/**
|
|
6530
6696
|
* Text RenderLayer. Emits one TextDrawCommand per text node carrying the
|
|
6531
6697
|
* node's resolved runs and bounding rect. Word wrap and multi-line layout
|
|
@@ -6538,135 +6704,70 @@ declare function measureTextBounds(text: string, style?: TextStyle, opts?: Measu
|
|
|
6538
6704
|
* `TextDrawCommand`'s contract).
|
|
6539
6705
|
*/
|
|
6540
6706
|
|
|
6541
|
-
/** Pose for a text node: bounding rect plus the text and optional style. */
|
|
6542
|
-
interface TextPose {
|
|
6543
|
-
x: number;
|
|
6544
|
-
y: number;
|
|
6545
|
-
width: number;
|
|
6546
|
-
height: number;
|
|
6547
|
-
text: string;
|
|
6548
|
-
/** Rich-text runs. When present, `runsToPlainText(runs)` must equal `text`. */
|
|
6549
|
-
runs?: StyledRun[];
|
|
6550
|
-
style?: TextStyle;
|
|
6551
|
-
/** Box vertical alignment within `[y, y+height]`. Default 'top'. */
|
|
6552
|
-
verticalAlign?: TextVerticalAlign;
|
|
6553
|
-
}
|
|
6554
6707
|
/** Options for `createTextLayer`. */
|
|
6555
6708
|
interface CreateTextLayerOpts<T> {
|
|
6556
6709
|
id?: string;
|
|
6557
6710
|
label?: string;
|
|
6558
|
-
getTexts: () => readonly T[];
|
|
6559
|
-
getPose: (node: T) => TextPose;
|
|
6560
|
-
/** Optional per-node hide hook (e.g., suppress while editing). */
|
|
6561
|
-
isHidden?: (node: T) => boolean;
|
|
6562
|
-
/** When `true`, each text command is wrapped in a clipped group so any
|
|
6563
|
-
* overflow beyond the pose's `(width × height)` is hidden. Default
|
|
6564
|
-
* `false` (legacy: text can spill outside the declared bounds). Opt-in
|
|
6565
|
-
* so existing consumers who rely on overflow keep working. */
|
|
6566
|
-
clipToBounds?: boolean;
|
|
6567
|
-
}
|
|
6568
|
-
/** Build a `RenderLayer` that emits one `TextDrawCommand` per text node. */
|
|
6569
|
-
declare function createTextLayer<T>(opts: CreateTextLayerOpts<T>): RenderLayer<unknown>;
|
|
6570
|
-
|
|
6571
|
-
/**
|
|
6572
|
-
* Hit-testing for text nodes.
|
|
6573
|
-
*
|
|
6574
|
-
* `pointInTextPose` does a coarse pose-rect test — suitable for click-to-edit
|
|
6575
|
-
* where the pose rect is the authoritative bounding box (selection outline,
|
|
6576
|
-
* drag target).
|
|
6577
|
-
*
|
|
6578
|
-
* `caretIndexAt` does the finer test: given a world-space (x, y) inside the
|
|
6579
|
-
* pose, returns the corresponding character offset in `pose.text` so the
|
|
6580
|
-
* consumer can place the caret on click. Re-runs the wrap to map the click
|
|
6581
|
-
* back through `lineStarts`; respects `style.align` for line anchoring.
|
|
6582
|
-
*/
|
|
6583
|
-
|
|
6584
|
-
/** Options for `pointInTextPose`. */
|
|
6585
|
-
interface PointInTextPoseOpts {
|
|
6586
|
-
/** Extra padding (world units) added to the rect on all sides. Default 0. */
|
|
6587
|
-
padding?: number;
|
|
6588
|
-
}
|
|
6589
|
-
/** Coarse pose-rect hit-test for a text node — suitable for click-to-edit dispatch. */
|
|
6590
|
-
declare function pointInTextPose(x: number, y: number, pose: TextPose, opts?: PointInTextPoseOpts): boolean;
|
|
6591
|
-
/**
|
|
6592
|
-
* Map a world-space point inside `pose` to a character offset into
|
|
6593
|
-
* `pose.text` (0..text.length). Clicks above the first line clamp to 0;
|
|
6594
|
-
* clicks below the last line clamp to `text.length`. Within a line, the
|
|
6595
|
-
* caret lands between two glyphs at whichever side of the glyph midpoint
|
|
6596
|
-
* `x` falls on — the standard "snap caret to nearest character boundary"
|
|
6597
|
-
* rule.
|
|
6598
|
-
*
|
|
6599
|
-
* The `ctx` is used only for `measureText`; its `font` is set internally
|
|
6600
|
-
* to match the resolved text style. Pass any 2D context (the same one used
|
|
6601
|
-
* to render is fine).
|
|
6602
|
-
*/
|
|
6603
|
-
declare function caretIndexAt(ctx: CanvasRenderingContext2D, x: number, y: number, pose: TextPose): number;
|
|
6604
|
-
|
|
6605
|
-
/**
|
|
6606
|
-
* Polygon-vs-axis-aligned-rect tests. Pure functions; no React/kit deps.
|
|
6607
|
-
*
|
|
6608
|
-
* `polygon` is a closed polyline given as an ordered vertex array; the
|
|
6609
|
-
* closing edge from `polygon[N-1]` to `polygon[0]` is implicit. Even-odd
|
|
6610
|
-
* fill rule (matches `pointInPath`).
|
|
6611
|
-
*/
|
|
6612
|
-
/** A 2D point or vector. */
|
|
6613
|
-
interface Vec2 {
|
|
6614
|
-
x: number;
|
|
6615
|
-
y: number;
|
|
6616
|
-
}
|
|
6617
|
-
/** An axis-aligned rectangle. */
|
|
6618
|
-
interface Rect {
|
|
6619
|
-
x: number;
|
|
6620
|
-
y: number;
|
|
6621
|
-
width: number;
|
|
6622
|
-
height: number;
|
|
6711
|
+
getTexts: () => readonly T[];
|
|
6712
|
+
getPose: (node: T) => TextPose;
|
|
6713
|
+
/** Optional per-node hide hook (e.g., suppress while editing). */
|
|
6714
|
+
isHidden?: (node: T) => boolean;
|
|
6715
|
+
/** When `true`, each text command is wrapped in a clipped group so any
|
|
6716
|
+
* overflow beyond the pose's `(width × height)` is hidden. Default
|
|
6717
|
+
* `false` (legacy: text can spill outside the declared bounds). Opt-in
|
|
6718
|
+
* so existing consumers who rely on overflow keep working. */
|
|
6719
|
+
clipToBounds?: boolean;
|
|
6623
6720
|
}
|
|
6721
|
+
/** Build a `RenderLayer` that emits one `TextDrawCommand` per text node. */
|
|
6722
|
+
declare function createTextLayer<T>(opts: CreateTextLayerOpts<T>): RenderLayer<unknown>;
|
|
6624
6723
|
|
|
6625
6724
|
/**
|
|
6626
|
-
*
|
|
6627
|
-
*
|
|
6628
|
-
* A text pose is a *wrap box*, not a bounding box: `"Away"` in a 309-unit-wide
|
|
6629
|
-
* box leaves most of the box empty, and anything that treats the pose as the
|
|
6630
|
-
* node's extent — picking, lasso, clipping, SVG export — claims that empty
|
|
6631
|
-
* space. `textLineBoxes` returns the per-line rectangles instead.
|
|
6725
|
+
* Hit-testing for text nodes.
|
|
6632
6726
|
*
|
|
6633
|
-
*
|
|
6634
|
-
*
|
|
6635
|
-
*
|
|
6636
|
-
* particular they honor `align` (a centered line reports its own span, not the
|
|
6637
|
-
* wrap width) and `verticalAlign` (the block shifts inside `[y, y + height]`
|
|
6638
|
-
* exactly as `drawText` shifts the quads).
|
|
6727
|
+
* `pointInTextPose` does a coarse pose-rect test — suitable for click-to-edit
|
|
6728
|
+
* where the pose rect is the authoritative bounding box (selection outline,
|
|
6729
|
+
* drag target).
|
|
6639
6730
|
*
|
|
6640
|
-
*
|
|
6641
|
-
*
|
|
6642
|
-
*
|
|
6643
|
-
*
|
|
6644
|
-
*
|
|
6731
|
+
* `caretIndexAt` does the finer test: given a world-space (x, y) inside the
|
|
6732
|
+
* pose, returns the corresponding character offset so the consumer can place
|
|
6733
|
+
* the caret on click. It reads the caret stops off the same
|
|
6734
|
+
* `cachedLayoutRuns` result the renderer paints and `textLineBoxes` picks
|
|
6735
|
+
* against, so the caret cannot land on a different line — or between
|
|
6736
|
+
* different glyphs — than the one under the pointer.
|
|
6645
6737
|
*/
|
|
6646
6738
|
|
|
6647
|
-
/** Options for
|
|
6648
|
-
interface
|
|
6649
|
-
/**
|
|
6650
|
-
* Picking wants a little slack so a single hairline row of text is still
|
|
6651
|
-
* grabbable; clipping and export want none. */
|
|
6739
|
+
/** Options for `pointInTextPose`. */
|
|
6740
|
+
interface PointInTextPoseOpts {
|
|
6741
|
+
/** Extra padding (world units) added to the rect on all sides. Default 0. */
|
|
6652
6742
|
padding?: number;
|
|
6653
|
-
|
|
6654
|
-
|
|
6655
|
-
|
|
6656
|
-
|
|
6743
|
+
}
|
|
6744
|
+
/** Coarse pose-rect hit-test for a text node — suitable for click-to-edit dispatch. */
|
|
6745
|
+
declare function pointInTextPose(x: number, y: number, pose: TextPose, opts?: PointInTextPoseOpts): boolean;
|
|
6746
|
+
/** Options for `caretIndexAt`. */
|
|
6747
|
+
interface CaretIndexAtOpts {
|
|
6657
6748
|
/**
|
|
6658
6749
|
* Wrap width. Default `pose.width`, which is what `createTextLayer` passes
|
|
6659
6750
|
* and what `TextPose` means by its box.
|
|
6660
6751
|
*
|
|
6661
6752
|
* Pass `Infinity` for a node painted by the built-in `kit:text` painter:
|
|
6662
|
-
* that painter deliberately does
|
|
6663
|
-
*
|
|
6664
|
-
*
|
|
6753
|
+
* that painter deliberately does not forward `maxWidth`, so its text does
|
|
6754
|
+
* not wrap, and a caret mapped through a finite width would answer for a
|
|
6755
|
+
* line break the paint never made. Mirrors `textLineBoxes`.
|
|
6665
6756
|
*/
|
|
6666
6757
|
maxWidth?: number;
|
|
6667
6758
|
}
|
|
6668
|
-
/**
|
|
6669
|
-
|
|
6759
|
+
/**
|
|
6760
|
+
* Map a world-space point inside `pose` to a character offset into the pose's
|
|
6761
|
+
* text (0..length). Clicks above the first line clamp to 0; clicks below the
|
|
6762
|
+
* last line clamp to the end. Within a line, the caret lands between two
|
|
6763
|
+
* glyphs at whichever side of the advance cell's midpoint `x` falls on — the
|
|
6764
|
+
* standard "snap caret to nearest character boundary" rule.
|
|
6765
|
+
*
|
|
6766
|
+
* Honors `pose.runs` (a mixed-size line snaps on the cells each run actually
|
|
6767
|
+
* produced) and `pose.verticalAlign`. The offset is into the runs'
|
|
6768
|
+
* concatenated text, which `TextPose` requires to equal `pose.text`.
|
|
6769
|
+
*/
|
|
6770
|
+
declare function caretIndexAt(x: number, y: number, pose: TextPose, opts?: CaretIndexAtOpts): number;
|
|
6670
6771
|
|
|
6671
6772
|
/**
|
|
6672
6773
|
* Resize a text node's pose to fit its content. Pure helper — does not own
|
|
@@ -6700,7 +6801,60 @@ interface FitTextPoseOptions {
|
|
|
6700
6801
|
};
|
|
6701
6802
|
}
|
|
6702
6803
|
/** Recompute a `TextPose`'s `width`/`height` to fit its content; pure helper, doesn't mutate scene state. */
|
|
6703
|
-
declare function fitTextPose(
|
|
6804
|
+
declare function fitTextPose(pose: TextPose, opts?: FitTextPoseOptions): TextPose;
|
|
6805
|
+
|
|
6806
|
+
/**
|
|
6807
|
+
* Turning a run-level flag **off** inside a node that sets it.
|
|
6808
|
+
*
|
|
6809
|
+
* Run flags are additive over the node's `TextStyle` — a run turns `bold` /
|
|
6810
|
+
* `italic` / `underline` / `strikethrough` on, never off (see the contract at
|
|
6811
|
+
* the top of `rangeStyle.ts`). So "select a word inside an underlined node and
|
|
6812
|
+
* hit U" is unrepresentable by the stored shape, and the character bar can
|
|
6813
|
+
* only refuse.
|
|
6814
|
+
*
|
|
6815
|
+
* This resolves it by rewriting rather than by widening the model: clear the
|
|
6816
|
+
* flag on the node, and set it on every run *outside* the range. The rendered
|
|
6817
|
+
* result is identical and the edit becomes expressible, with `StyledRun`
|
|
6818
|
+
* unchanged — so nothing a document can already contain changes meaning, which
|
|
6819
|
+
* matters while the flags are heading for a persisted format.
|
|
6820
|
+
*
|
|
6821
|
+
* The alternative was a tri-state run flag (`true` / `false` / inherit). It
|
|
6822
|
+
* cannot cover `bold` or `italic`: those are booleans on a run but
|
|
6823
|
+
* `fontWeight` and `fontStyle` on the node, so a run's `false` has no node-level
|
|
6824
|
+
* boolean to override. Tri-state fixes two of the five flags; this fixes all
|
|
6825
|
+
* five.
|
|
6826
|
+
*/
|
|
6827
|
+
|
|
6828
|
+
/** The additive run flags. */
|
|
6829
|
+
type FlagKey = 'bold' | 'italic' | 'underline' | 'strikethrough' | 'overline';
|
|
6830
|
+
/** The result of toggling a style flag over a text range: the rewritten runs
|
|
6831
|
+
* and node style, and whether the change could be made at all. */
|
|
6832
|
+
interface SetFlagResult {
|
|
6833
|
+
runs: StyledRun[];
|
|
6834
|
+
style: TextStyle;
|
|
6835
|
+
/**
|
|
6836
|
+
* False when the node flag could not be lowered without changing what is
|
|
6837
|
+
* drawn, and nothing was written. The only case is a `fontWeight` the run
|
|
6838
|
+
* boolean cannot express: `run.bold` resolves to exactly 700 everywhere, so
|
|
6839
|
+
* a node at 900 cannot have its weight pushed onto its runs. Callers should
|
|
6840
|
+
* disable the control rather than apply a silent downgrade.
|
|
6841
|
+
*/
|
|
6842
|
+
applied: boolean;
|
|
6843
|
+
}
|
|
6844
|
+
/** Does the node style carry this flag? */
|
|
6845
|
+
declare function nodeHasFlag(style: TextStyle, key: FlagKey): boolean;
|
|
6846
|
+
/**
|
|
6847
|
+
* Set `key` to `value` over `[start, end)`.
|
|
6848
|
+
*
|
|
6849
|
+
* Turning a flag **on**, or off in a node that doesn't set it, is the ordinary
|
|
6850
|
+
* additive write and leaves `style` alone. Turning it off in a node that *does*
|
|
6851
|
+
* set it takes the rewrite: the node flag is cleared and the flag is written
|
|
6852
|
+
* onto the complement of the range.
|
|
6853
|
+
*
|
|
6854
|
+
* `runs` is normalized on every path, so the complement collapses back to one
|
|
6855
|
+
* run when the range is empty and the whole array coalesces as usual.
|
|
6856
|
+
*/
|
|
6857
|
+
declare function setFlagOverRange(runs: readonly StyledRun[], style: TextStyle, start: number, end: number, key: FlagKey, value: boolean): SetFlagResult;
|
|
6704
6858
|
|
|
6705
6859
|
/**
|
|
6706
6860
|
* The kit-wide "these values disagree" sentinel. Used wherever a value is
|
|
@@ -6791,6 +6945,13 @@ declare function applyStyleToRange(runs: readonly StyledRun[], start: number, en
|
|
|
6791
6945
|
* (`isHidden: (n) => n.id === editingId`) so the overlay isn't drawn twice.
|
|
6792
6946
|
*/
|
|
6793
6947
|
|
|
6948
|
+
type StyleFlag = FlagKey;
|
|
6949
|
+
/**
|
|
6950
|
+
* A styling a shortcut or a control toggles. The additive booleans, plus the
|
|
6951
|
+
* two `script` values — which are exclusive rather than additive, so they
|
|
6952
|
+
* toggle against one enum rather than each owning a boolean.
|
|
6953
|
+
*/
|
|
6954
|
+
type StyleToggle = StyleFlag | 'super' | 'sub';
|
|
6794
6955
|
/**
|
|
6795
6956
|
* The caret's character range within the text being edited. Half-open
|
|
6796
6957
|
* `[start, end)` over the concatenated run text, normalized so `start <= end`
|
|
@@ -6845,6 +7006,13 @@ interface UseTextEditOptions {
|
|
|
6845
7006
|
getText: (id: string) => string;
|
|
6846
7007
|
/** Read style for `id` (used for font setup on the overlay). */
|
|
6847
7008
|
getStyle: (id: string) => TextStyle | undefined;
|
|
7009
|
+
/**
|
|
7010
|
+
* Read the node's paint for `id` — its `data.fill` / `data.stroke`. The
|
|
7011
|
+
* overlay paints its text and caret from the fill, so omitting this
|
|
7012
|
+
* renders every node's editor in the default black however the node
|
|
7013
|
+
* itself is painted.
|
|
7014
|
+
*/
|
|
7015
|
+
getPaint?: (id: string) => TextPaint | undefined;
|
|
6848
7016
|
/**
|
|
6849
7017
|
* Write style back for `id`. Optional; needed only to turn a flag **off**
|
|
6850
7018
|
* inside a node whose own `TextStyle` sets it. Run flags are additive, so
|
|
@@ -6909,8 +7077,8 @@ interface UseTextEditReturn {
|
|
|
6909
7077
|
/**
|
|
6910
7078
|
* The caret's character range, or `null` when nothing is being edited. A
|
|
6911
7079
|
* collapsed caret reports `{ start: n, end: n }`, so `null` and "caret at
|
|
6912
|
-
* n" stay distinguishable — a
|
|
6913
|
-
*
|
|
7080
|
+
* n" stay distinguishable — a styling written at a collapsed caret arms
|
|
7081
|
+
* {@link UseTextEditReturn.pendingStyle} instead of restyling a range.
|
|
6914
7082
|
*
|
|
6915
7083
|
* Follows the DOM selection, which browsers (and jsdom) report from a task
|
|
6916
7084
|
* rather than synchronously; anything this hook writes itself updates it
|
|
@@ -6924,33 +7092,82 @@ interface UseTextEditReturn {
|
|
|
6924
7092
|
/**
|
|
6925
7093
|
* The styling shared by every run in `selection` — a concrete value where
|
|
6926
7094
|
* the range agrees, `MIXED` where it doesn't. `null` exactly when
|
|
6927
|
-
* `selection` is `null`. A collapsed caret reports
|
|
6928
|
-
*
|
|
6929
|
-
* what
|
|
7095
|
+
* `selection` is `null`. A collapsed caret reports the styling *at* the
|
|
7096
|
+
* caret (the run to its left, or the run to its right at offset 0), which
|
|
7097
|
+
* is what the next typed character inherits.
|
|
7098
|
+
*
|
|
7099
|
+
* This does not include {@link UseTextEditReturn.pendingStyle}. A control
|
|
7100
|
+
* showing what the next character will look like wants both, merged in
|
|
7101
|
+
* that order; one showing what is already written wants only this.
|
|
6930
7102
|
*/
|
|
6931
7103
|
rangeStyle: RangeStyle | null;
|
|
6932
7104
|
/**
|
|
6933
|
-
*
|
|
6934
|
-
*
|
|
6935
|
-
* `
|
|
6936
|
-
*
|
|
6937
|
-
*
|
|
7105
|
+
* Styling armed at a collapsed caret, applied to the next character typed
|
|
7106
|
+
* and then dropped. `{}` when nothing is armed — which is always the case
|
|
7107
|
+
* while `selection` covers a real range, since a range is styled directly.
|
|
7108
|
+
*
|
|
7109
|
+
* Moving the caret abandons it, as in any other editor.
|
|
7110
|
+
*/
|
|
7111
|
+
pendingStyle: RunStylePatch;
|
|
7112
|
+
/**
|
|
7113
|
+
* Write `patch` over `selection`. A no-op with no active edit or an empty
|
|
7114
|
+
* patch. Over a real range this restyles the runs under it; at a collapsed
|
|
7115
|
+
* caret it merges into `pendingStyle` instead, so the styling lands on
|
|
7116
|
+
* what gets typed next rather than on text the user didn't select.
|
|
7117
|
+
*
|
|
7118
|
+
* Lowering a flag the *node* sets is neither of those — a run cannot say
|
|
7119
|
+
* "not bold" — so it rewrites instead: the node flag is cleared and raised
|
|
7120
|
+
* on every run outside the range. That path can decline (a node at
|
|
7121
|
+
* `fontWeight: 900` has no run boolean to move it to), in which case
|
|
7122
|
+
* nothing is written.
|
|
7123
|
+
*
|
|
7124
|
+
* The caret survives, so a second style can be applied without
|
|
7125
|
+
* re-selecting, and `rangeStyle` reflects the write before this returns.
|
|
6938
7126
|
*/
|
|
6939
7127
|
applyStyleToSelection: (patch: RunStylePatch) => void;
|
|
7128
|
+
/**
|
|
7129
|
+
* Toggle one styling over `selection` — set it if the range doesn't
|
|
7130
|
+
* uniformly carry it, clear it if it does. The shape a B / I / x² control
|
|
7131
|
+
* or a keyboard shortcut wants, and what this hook's own shortcuts call.
|
|
7132
|
+
*/
|
|
7133
|
+
toggleStyle: (toggle: StyleToggle) => void;
|
|
6940
7134
|
}
|
|
6941
7135
|
/** In-place text editing via a contenteditable overlay positioned over the text node's screen-space pose. */
|
|
6942
7136
|
declare function useTextEdit(opts: UseTextEditOptions): UseTextEditReturn;
|
|
6943
7137
|
|
|
6944
7138
|
/**
|
|
6945
|
-
*
|
|
7139
|
+
* Union math over rect-shaped poses.
|
|
6946
7140
|
*
|
|
6947
|
-
*
|
|
6948
|
-
*
|
|
6949
|
-
*
|
|
7141
|
+
* Two answers, deliberately distinct. `unionBounds` folds the *unrotated*
|
|
7142
|
+
* boxes and is what commit-time actions want, because they go on to write
|
|
7143
|
+
* poses back in that same frame. `unionAABB` expands each rotated member to
|
|
7144
|
+
* the extent of its ink first, and is what anything a user looks at or clicks
|
|
7145
|
+
* wants — selection chrome, gesture bounds, an export viewBox. Folding the
|
|
7146
|
+
* unrotated box there under-reports the extent of a rotated member exactly
|
|
7147
|
+
* when the consumer is watching it move.
|
|
6950
7148
|
*/
|
|
6951
7149
|
|
|
6952
|
-
/** Compute the AABB envelope of a set of rect-shaped poses
|
|
7150
|
+
/** Compute the AABB envelope of a set of rect-shaped poses, ignoring any
|
|
7151
|
+
* rotation they carry. See the module docstring before reaching for this
|
|
7152
|
+
* over {@link unionAABB}. */
|
|
6953
7153
|
declare function unionBounds<TPose extends RectPose>(poses: Iterable<TPose>): RectPose | null;
|
|
7154
|
+
/**
|
|
7155
|
+
* Axis-align a pose that carries a `rotation`: returns the AABB of the
|
|
7156
|
+
* rotated rectangle, with `rotation` dropped. Follows the kit's rotation
|
|
7157
|
+
* convention (`poseRotationOf`): rotate about the unrotated AABB center.
|
|
7158
|
+
*
|
|
7159
|
+
* Unrotated input is returned as-is.
|
|
7160
|
+
*/
|
|
7161
|
+
declare function axisAlignedBounds<TPose extends RectPose>(b: TPose): RectPose;
|
|
7162
|
+
/**
|
|
7163
|
+
* Fold every part into one world-space AABB, skipping `null` / `undefined`
|
|
7164
|
+
* entries. Rotated parts are expanded via {@link axisAlignedBounds} first;
|
|
7165
|
+
* the result never carries a `rotation` (a union of several oriented boxes
|
|
7166
|
+
* has no single orientation to report).
|
|
7167
|
+
*
|
|
7168
|
+
* Returns `null` when nothing was contributed.
|
|
7169
|
+
*/
|
|
7170
|
+
declare function unionAABB<TPose extends RectPose>(parts: Iterable<TPose | null | undefined>): RectPose | null;
|
|
6954
7171
|
|
|
6955
7172
|
/**
|
|
6956
7173
|
* `useSceneTextEdit` — scene-aware wrapper around `useTextEdit`.
|
|
@@ -6983,6 +7200,8 @@ interface DefaultTextData {
|
|
|
6983
7200
|
text?: string;
|
|
6984
7201
|
style?: TextStyle;
|
|
6985
7202
|
runs?: readonly StyledRun[];
|
|
7203
|
+
fill?: FillStyle | null;
|
|
7204
|
+
stroke?: Stroke | null;
|
|
6986
7205
|
}
|
|
6987
7206
|
/** All-optional projections + fontSize fallback. */
|
|
6988
7207
|
interface UseSceneTextEditOptions<TData> {
|
|
@@ -6990,6 +7209,8 @@ interface UseSceneTextEditOptions<TData> {
|
|
|
6990
7209
|
getText?: (data: TData) => string;
|
|
6991
7210
|
/** Read style from `data`. Default: `data.style`. */
|
|
6992
7211
|
getStyle?: (data: TData) => TextStyle | undefined;
|
|
7212
|
+
/** Read the node's paint from `data`. Default: `data.fill` / `data.stroke`. */
|
|
7213
|
+
getPaint?: (data: TData) => TextPaint | undefined;
|
|
6993
7214
|
/** Read rich-text runs from `data`. Default: `data.runs`. */
|
|
6994
7215
|
getRuns?: (data: TData) => readonly StyledRun[] | undefined;
|
|
6995
7216
|
/** Produce updated data with new text. Default: `{ ...data, text }`. */
|
|
@@ -7017,8 +7238,13 @@ interface UseSceneTextEditOptions<TData> {
|
|
|
7017
7238
|
* The overlay takes a single scale factor, so a non-uniform view scale is
|
|
7018
7239
|
* represented by its `scale.x`; text under `scale.x !== scale.y` will not
|
|
7019
7240
|
* match the canvas.
|
|
7241
|
+
*
|
|
7242
|
+
* A thunk is re-read on every projection, which is what an uncontrolled
|
|
7243
|
+
* `SceneCanvas` needs — its camera lives in a ref and moves without a
|
|
7244
|
+
* render, so pass the handle's `getView`. A plain `View` is the value from
|
|
7245
|
+
* the render that supplied it, which is correct for a controlled consumer.
|
|
7020
7246
|
*/
|
|
7021
|
-
view?: View;
|
|
7247
|
+
view?: View | (() => View);
|
|
7022
7248
|
/**
|
|
7023
7249
|
* Forwarded to `useTextEdit`: is `el` part of the editor's own chrome?
|
|
7024
7250
|
* Focus moving into it does not end the edit. Wire it to whatever renders
|
|
@@ -7041,59 +7267,6 @@ interface UseSceneTextEditReturn extends UseTextEditReturn {
|
|
|
7041
7267
|
* over the node being edited and writes the result back as an undoable op. */
|
|
7042
7268
|
declare function useSceneTextEdit<TData extends DefaultTextData, TLayer extends string, TPose extends RectPose = RectPose>(scene: Scene<TData, TLayer, TPose>, container: HTMLElement | null, options?: UseSceneTextEditOptions<TData>): UseSceneTextEditReturn;
|
|
7043
7269
|
|
|
7044
|
-
/**
|
|
7045
|
-
* Turning a run-level flag **off** inside a node that sets it.
|
|
7046
|
-
*
|
|
7047
|
-
* Run flags are additive over the node's `TextStyle` — a run turns `bold` /
|
|
7048
|
-
* `italic` / `underline` / `strikethrough` on, never off (see the contract at
|
|
7049
|
-
* the top of `rangeStyle.ts`). So "select a word inside an underlined node and
|
|
7050
|
-
* hit U" is unrepresentable by the stored shape, and the character bar can
|
|
7051
|
-
* only refuse.
|
|
7052
|
-
*
|
|
7053
|
-
* This resolves it by rewriting rather than by widening the model: clear the
|
|
7054
|
-
* flag on the node, and set it on every run *outside* the range. The rendered
|
|
7055
|
-
* result is identical and the edit becomes expressible, with `StyledRun`
|
|
7056
|
-
* unchanged — so nothing a document can already contain changes meaning, which
|
|
7057
|
-
* matters while the flags are heading for a persisted format.
|
|
7058
|
-
*
|
|
7059
|
-
* The alternative was a tri-state run flag (`true` / `false` / inherit). It
|
|
7060
|
-
* cannot cover `bold` or `italic`: those are booleans on a run but
|
|
7061
|
-
* `fontWeight` and `fontStyle` on the node, so a run's `false` has no node-level
|
|
7062
|
-
* boolean to override. Tri-state fixes two of the four flags; this fixes all
|
|
7063
|
-
* four.
|
|
7064
|
-
*/
|
|
7065
|
-
|
|
7066
|
-
/** The additive run flags. */
|
|
7067
|
-
type FlagKey = 'bold' | 'italic' | 'underline' | 'strikethrough';
|
|
7068
|
-
/** The result of toggling a style flag over a text range: the rewritten runs
|
|
7069
|
-
* and node style, and whether the change could be made at all. */
|
|
7070
|
-
interface SetFlagResult {
|
|
7071
|
-
runs: StyledRun[];
|
|
7072
|
-
style: TextStyle;
|
|
7073
|
-
/**
|
|
7074
|
-
* False when the node flag could not be lowered without changing what is
|
|
7075
|
-
* drawn, and nothing was written. The only case is a `fontWeight` the run
|
|
7076
|
-
* boolean cannot express: `run.bold` resolves to exactly 700 everywhere, so
|
|
7077
|
-
* a node at 900 cannot have its weight pushed onto its runs. Callers should
|
|
7078
|
-
* disable the control rather than apply a silent downgrade.
|
|
7079
|
-
*/
|
|
7080
|
-
applied: boolean;
|
|
7081
|
-
}
|
|
7082
|
-
/** Does the node style carry this flag? */
|
|
7083
|
-
declare function nodeHasFlag(style: TextStyle, key: FlagKey): boolean;
|
|
7084
|
-
/**
|
|
7085
|
-
* Set `key` to `value` over `[start, end)`.
|
|
7086
|
-
*
|
|
7087
|
-
* Turning a flag **on**, or off in a node that doesn't set it, is the ordinary
|
|
7088
|
-
* additive write and leaves `style` alone. Turning it off in a node that *does*
|
|
7089
|
-
* set it takes the rewrite: the node flag is cleared and the flag is written
|
|
7090
|
-
* onto the complement of the range.
|
|
7091
|
-
*
|
|
7092
|
-
* `runs` is normalized on every path, so the complement collapses back to one
|
|
7093
|
-
* run when the range is empty and the whole array coalesces as usual.
|
|
7094
|
-
*/
|
|
7095
|
-
declare function setFlagOverRange(runs: readonly StyledRun[], style: TextStyle, start: number, end: number, key: FlagKey, value: boolean): SetFlagResult;
|
|
7096
|
-
|
|
7097
7270
|
/**
|
|
7098
7271
|
* Build a `TextDrawCommand`. `textCommand` takes a plain string and wraps it
|
|
7099
7272
|
* in one run; `textCommandFromRuns` takes the styled runs directly. Both
|
|
@@ -7101,12 +7274,16 @@ declare function setFlagOverRange(runs: readonly StyledRun[], style: TextStyle,
|
|
|
7101
7274
|
* text command derives `align` and per-run resolution the same way — a
|
|
7102
7275
|
* caller that assembles the command by hand is one field away from a
|
|
7103
7276
|
* silently different result.
|
|
7277
|
+
*
|
|
7278
|
+
* `paint` is the node's `data.fill` / `data.stroke`. A caller with no node —
|
|
7279
|
+
* a HUD widget, a debug overlay — states its color on the run instead.
|
|
7104
7280
|
*/
|
|
7105
7281
|
|
|
7282
|
+
declare function textCommandFromRuns(x: number, y: number, runs: readonly StyledRun[], style?: TextStyle, maxWidth?: number, height?: number, verticalAlign?: TextVerticalAlign, paint?: TextPaint): DrawCommand;
|
|
7106
7283
|
/** Build a draw command for a single unstyled string. Text is laid out with
|
|
7107
7284
|
* the registered font's metrics, wrapped at `maxWidth` and aligned within
|
|
7108
7285
|
* `height` when both are given. */
|
|
7109
|
-
declare function textCommand(x: number, y: number, text: string, style?: TextStyle, maxWidth?: number, height?: number, verticalAlign?: TextVerticalAlign): DrawCommand;
|
|
7286
|
+
declare function textCommand(x: number, y: number, text: string, style?: TextStyle, maxWidth?: number, height?: number, verticalAlign?: TextVerticalAlign, paint?: TextPaint): DrawCommand;
|
|
7110
7287
|
|
|
7111
7288
|
/**
|
|
7112
7289
|
* Pure DOM ↔ `StyledRun[]` serializers for the contenteditable overlay
|
|
@@ -7148,7 +7325,7 @@ declare function domPositionToCharOffset(parent: HTMLElement, node: Node, offset
|
|
|
7148
7325
|
/**
|
|
7149
7326
|
* Tile-pattern primitive — a small helper for building repeating texture
|
|
7150
7327
|
* tiles from a draw callback. The result plugs into a `FillStyle` of
|
|
7151
|
-
* `{ fill: 'pattern', pattern }` (see
|
|
7328
|
+
* `{ fill: 'pattern', pattern }` (see `@weasel-js/paint`).
|
|
7152
7329
|
*
|
|
7153
7330
|
* GL-backed: the tile is rendered to an `OffscreenCanvas` (with a 2D fallback
|
|
7154
7331
|
* to a regular `<canvas>` for environments without `OffscreenCanvas`),
|
|
@@ -7210,13 +7387,16 @@ declare function resolveFillPattern(fill: FillStyle): FillStyle | null;
|
|
|
7210
7387
|
* `withGradientKind` exists to translate.
|
|
7211
7388
|
*/
|
|
7212
7389
|
|
|
7390
|
+
/** Narrow a paint to the gradient members of `FillStyle`. The three
|
|
7391
|
+
* discriminants are the union's own definition of `GradientFill`, so every
|
|
7392
|
+
* consumer that reaches for gradient geometry starts here. */
|
|
7393
|
+
declare function isGradientFill(fill: FillStyle | null | undefined): fill is GradientFill;
|
|
7213
7394
|
/**
|
|
7214
|
-
* Color at position `t` (0..1) along a stop list,
|
|
7215
|
-
*
|
|
7216
|
-
*
|
|
7395
|
+
* Color at position `t` (0..1) along a stop list, as a hex string — the same
|
|
7396
|
+
* sampling the GL ramp texture bakes, so an editor track and the painted
|
|
7397
|
+
* gradient cannot disagree.
|
|
7217
7398
|
*
|
|
7218
|
-
* Returns transparent black for an empty list.
|
|
7219
|
-
* a stop list fading to `transparent` samples correctly.
|
|
7399
|
+
* Returns transparent black for an empty list.
|
|
7220
7400
|
*/
|
|
7221
7401
|
declare function sampleGradientStops(stops: readonly GradStop[], t: number): string;
|
|
7222
7402
|
/**
|
|
@@ -7253,9 +7433,10 @@ declare function gradientGeometry(fill: GradientFill): {
|
|
|
7253
7433
|
angle: number;
|
|
7254
7434
|
};
|
|
7255
7435
|
/**
|
|
7256
|
-
* A gradient spanning a box
|
|
7257
|
-
* (radial / conic) — the sensible starting
|
|
7258
|
-
* solid fill into a gradient and has only
|
|
7436
|
+
* A gradient spanning a box left edge to right edge through its vertical
|
|
7437
|
+
* center (linear) or filling it (radial / conic) — the sensible starting
|
|
7438
|
+
* geometry when a consumer turns a solid fill into a gradient and has only
|
|
7439
|
+
* the shape's bounds to go on.
|
|
7259
7440
|
*/
|
|
7260
7441
|
declare function gradientForBounds(kind: GradientKind, bounds: {
|
|
7261
7442
|
x: number;
|
|
@@ -7341,16 +7522,40 @@ interface TransformArgs<TPose> {
|
|
|
7341
7522
|
* coalesce window. Pass an explicit key (or a unique one) to opt out. */
|
|
7342
7523
|
declare function createTransformOp<TPose>(args: TransformArgs<TPose>): Op;
|
|
7343
7524
|
|
|
7525
|
+
interface Slot {
|
|
7526
|
+
/** Ordinal among the siblings. `-1` means "nowhere in particular". */
|
|
7527
|
+
index: number;
|
|
7528
|
+
/** Id of the sibling that followed at capture time; `null` when the node
|
|
7529
|
+
* was last. Absent when nothing observed it — `null` survives JSON and
|
|
7530
|
+
* `undefined` does not, so the two stay distinguishable across a
|
|
7531
|
+
* serialize/restore round trip. */
|
|
7532
|
+
before?: string | null;
|
|
7533
|
+
}
|
|
7534
|
+
|
|
7344
7535
|
/** @internal */
|
|
7345
7536
|
interface ReparentArgs {
|
|
7346
7537
|
id: string;
|
|
7347
7538
|
fromParentId: string | null;
|
|
7348
7539
|
toParentId: string | null;
|
|
7540
|
+
/** Sibling ordinal under the old parent. Sugar for `fromSlot: { index }`,
|
|
7541
|
+
* and only a seed: `apply` re-observes the node's full slot through the
|
|
7542
|
+
* adapter and that observation supersedes this. */
|
|
7543
|
+
fromIndex?: number;
|
|
7544
|
+
/** Sibling ordinal under the new parent. Sugar for `toSlot: { index }`.
|
|
7545
|
+
* Omit to append. */
|
|
7546
|
+
toIndex?: number;
|
|
7547
|
+
/** Slot under the old parent, anchor included. `invert()` forwards it as
|
|
7548
|
+
* the destination slot; without it undo re-parents with no position and
|
|
7549
|
+
* the node lands last, quietly changing paint order. */
|
|
7550
|
+
fromSlot?: Slot;
|
|
7551
|
+
/** Slot under the new parent, anchor included. Omit to append. */
|
|
7552
|
+
toSlot?: Slot;
|
|
7349
7553
|
label?: string;
|
|
7350
7554
|
coalesceKey?: string;
|
|
7351
7555
|
}
|
|
7352
7556
|
/**
|
|
7353
|
-
* Op: change `id`'s parent, inverting back to the prior
|
|
7557
|
+
* Op: change `id`'s parent and sibling slot, inverting back to the prior
|
|
7558
|
+
* parent and slot.
|
|
7354
7559
|
*
|
|
7355
7560
|
* `coalesceKey` defaults to `reparent:${id}` so successive reparents of the
|
|
7356
7561
|
* same id batch-merge cleanly.
|
|
@@ -7366,32 +7571,46 @@ interface InsertArgs<TNode extends {
|
|
|
7366
7571
|
}> {
|
|
7367
7572
|
node: TNode;
|
|
7368
7573
|
label?: string;
|
|
7369
|
-
/**
|
|
7370
|
-
*
|
|
7371
|
-
* batch restores paint order instead of reversing it. Optional — adapters
|
|
7372
|
-
* that don't honor it still work. */
|
|
7574
|
+
/** Sibling ordinal to insert at. Sugar for `slot: { index }` — the weaker
|
|
7575
|
+
* of the two forms, and all a fresh-insert callsite can know. */
|
|
7373
7576
|
index?: number;
|
|
7577
|
+
/** Full slot, anchor included. Produced only by `captureSlot` (via a
|
|
7578
|
+
* delete op's `invert`), and supersedes `index` when present. */
|
|
7579
|
+
slot?: Slot;
|
|
7374
7580
|
}
|
|
7375
7581
|
/** Op: insert `node` into the scene; inverts to a delete of the same id. */
|
|
7376
7582
|
declare function createInsertOp<TNode extends {
|
|
7377
7583
|
id: string;
|
|
7378
7584
|
}>(args: InsertArgs<TNode>): InsertOp;
|
|
7379
7585
|
|
|
7586
|
+
/** A captured node plus its slot in its own parent's child list. */
|
|
7587
|
+
interface Placed<TNode> {
|
|
7588
|
+
node: TNode;
|
|
7589
|
+
index: number;
|
|
7590
|
+
}
|
|
7380
7591
|
/** @internal */
|
|
7381
7592
|
interface DeleteArgs<TNode extends {
|
|
7382
7593
|
id: string;
|
|
7383
7594
|
}> {
|
|
7384
7595
|
node: TNode;
|
|
7385
7596
|
label?: string;
|
|
7386
|
-
/**
|
|
7387
|
-
*
|
|
7388
|
-
*
|
|
7389
|
-
* the
|
|
7390
|
-
*
|
|
7391
|
-
|
|
7392
|
-
index
|
|
7393
|
-
|
|
7394
|
-
/**
|
|
7597
|
+
/** Sibling ordinal the node occupies at the moment of delete. Sugar for
|
|
7598
|
+
* `slot: { index }`, and only a seed: `apply` re-observes the node's full
|
|
7599
|
+
* slot through the adapter and that observation supersedes this. Kept
|
|
7600
|
+
* because it is the whole story for a flat adapter with no `getChildren`,
|
|
7601
|
+
* where nothing can be observed. */
|
|
7602
|
+
index?: number;
|
|
7603
|
+
/** Full slot, anchor included. Written by `apply`; supersedes `index`. */
|
|
7604
|
+
slot?: Slot;
|
|
7605
|
+
/** Descendants of `node`, preorder (parents before children). `removeNode`
|
|
7606
|
+
* cascades the whole subtree, so an inverse that re-inserts `node` alone
|
|
7607
|
+
* brings the container back empty and drops every child on the floor.
|
|
7608
|
+
* Captured on apply; mirrored into the serialized args so a rebuilt op
|
|
7609
|
+
* can invert without having run. */
|
|
7610
|
+
descendants?: Placed<TNode>[];
|
|
7611
|
+
}
|
|
7612
|
+
/** Op: remove `node` and its subtree from the scene; inverts to a re-insert
|
|
7613
|
+
* of the whole subtree at its captured slots. */
|
|
7395
7614
|
declare function createDeleteOp<TNode extends {
|
|
7396
7615
|
id: string;
|
|
7397
7616
|
}>(args: DeleteArgs<TNode>): Op;
|
|
@@ -7534,6 +7753,10 @@ declare function registerOpFactory<A>(name: string, build: (args: A) => Op): voi
|
|
|
7534
7753
|
* `name` isn't registered — callers handle this (typically by substituting
|
|
7535
7754
|
* a no-op placeholder so stack ordering survives across kit version skew). */
|
|
7536
7755
|
declare function rebuildOp(name: string, args: unknown): Op | null;
|
|
7756
|
+
/** Every op name currently registered, in registration order. The kit's
|
|
7757
|
+
* built-ins self-register at module init, so importing the barrel is enough
|
|
7758
|
+
* to see all of them; consumer factories appear once their module has run. */
|
|
7759
|
+
declare function registeredOpNames(): readonly string[];
|
|
7537
7760
|
|
|
7538
7761
|
/** @internal */
|
|
7539
7762
|
interface HitAdapter<TNode extends {
|
|
@@ -7752,6 +7975,20 @@ interface PointInPathOptions {
|
|
|
7752
7975
|
/** Filled-region hit-test for a `Path`. Rect short-circuits to AABB; polygons run ray-cast / winding per `fillRule`. */
|
|
7753
7976
|
declare function pointInPath(path: Path, x: number, y: number, opts?: PointInPathOptions): boolean;
|
|
7754
7977
|
|
|
7978
|
+
/**
|
|
7979
|
+
* Polygon-vs-axis-aligned-rect tests. Pure functions; no React/kit deps.
|
|
7980
|
+
*
|
|
7981
|
+
* `polygon` is a closed polyline given as an ordered vertex array; the
|
|
7982
|
+
* closing edge from `polygon[N-1]` to `polygon[0]` is implicit. Even-odd
|
|
7983
|
+
* fill rule (matches `pointInPath`).
|
|
7984
|
+
*/
|
|
7985
|
+
|
|
7986
|
+
/** A 2D point or vector. */
|
|
7987
|
+
interface Vec2 {
|
|
7988
|
+
x: number;
|
|
7989
|
+
y: number;
|
|
7990
|
+
}
|
|
7991
|
+
|
|
7755
7992
|
/**
|
|
7756
7993
|
* Path-vs-geometry hit-test helpers. Five pure functions covering all
|
|
7757
7994
|
* combinations of path-vs-point, path-vs-rect, and path-vs-polygon.
|
|
@@ -7903,22 +8140,6 @@ declare function worldEditToStorage<P extends PathInWorldPose>(pose: P, worldPat
|
|
|
7903
8140
|
path: PolygonPath;
|
|
7904
8141
|
};
|
|
7905
8142
|
|
|
7906
|
-
/**
|
|
7907
|
-
* The kit's single encoding of the pose-rotation convention: "rotate about the
|
|
7908
|
-
* pose's unrotated AABB center by `pose.rotation` (radians)."
|
|
7909
|
-
*
|
|
7910
|
-
* Every consumer that needs to apply rotation — the render-tree wrap
|
|
7911
|
-
* (`canvas/poseRotation.ts`), the world coordinate bake (`pathInWorld`), the
|
|
7912
|
-
* silhouette/clip bake (`findShapeSilhouette`), the hit-test inverse
|
|
7913
|
-
* (`poseContainsRotated`), and selection chrome — derives its pivot + angle
|
|
7914
|
-
* from `poseRotationOf` rather than re-inlining the `if (rotation && x != null
|
|
7915
|
-
* …)` gate. If the convention ever changes (different pivot, a transform
|
|
7916
|
-
* field, etc.), it changes here.
|
|
7917
|
-
*
|
|
7918
|
-
* Lives in `features/paths` (the low layer) so both `features` and `canvas`
|
|
7919
|
-
* can share it without `features` importing `canvas`.
|
|
7920
|
-
*/
|
|
7921
|
-
|
|
7922
8143
|
/** Pivot (`cx`, `cy`) and angle resolved from a pose's rotation convention. */
|
|
7923
8144
|
interface PoseRotation {
|
|
7924
8145
|
cx: number;
|
|
@@ -8199,8 +8420,9 @@ declare function createPenPreviewLayer(opts: CreatePenPreviewLayerOptions): Rend
|
|
|
8199
8420
|
* but a human user needs to see what's hittable.
|
|
8200
8421
|
*
|
|
8201
8422
|
* The layer reads the live edit target each frame via the supplied
|
|
8202
|
-
* `getEditingId()` + `getPose(
|
|
8203
|
-
*
|
|
8423
|
+
* `getEditingId()` + `getPose(...)` thunks, resolving the path against the
|
|
8424
|
+
* drawing view's own previews. Returns `[]` when no editing target is set or
|
|
8425
|
+
* the target isn't a polygon — the layer never throws.
|
|
8204
8426
|
*
|
|
8205
8427
|
* Anchors render as small white-filled stroked squares — filled solid
|
|
8206
8428
|
* when selected; control points as small filled circles connected to
|
|
@@ -8220,9 +8442,15 @@ interface CreatePathEditingOverlayLayerOptions {
|
|
|
8220
8442
|
* when no node is being edited. Read each frame so live selection /
|
|
8221
8443
|
* edit-target changes show up without re-creating the layer. */
|
|
8222
8444
|
getEditingId(): string | null;
|
|
8223
|
-
/**
|
|
8224
|
-
*
|
|
8225
|
-
|
|
8445
|
+
/**
|
|
8446
|
+
* Returns the pose for an id, or null if the node has been deleted.
|
|
8447
|
+
* Non-polygon poses are tolerated (the layer no-ops on them).
|
|
8448
|
+
*
|
|
8449
|
+
* `previews` are the drawing view's in-flight preview surfaces, so an
|
|
8450
|
+
* anchor dragged in one panel does not move in the others. Resolve against
|
|
8451
|
+
* them before falling back to the committed pose.
|
|
8452
|
+
*/
|
|
8453
|
+
getPose(id: string, previews: readonly GesturePreviewSource[]): Path | null;
|
|
8226
8454
|
/** Flat indices of the selected anchors. Selected anchors render
|
|
8227
8455
|
* filled; unselected ones hollow — the standard vector-editor cue for
|
|
8228
8456
|
* "these are what the arrow keys and Delete will act on". Omit when
|
|
@@ -8236,12 +8464,6 @@ interface CreatePathEditingOverlayLayerOptions {
|
|
|
8236
8464
|
width: number;
|
|
8237
8465
|
height: number;
|
|
8238
8466
|
} | null;
|
|
8239
|
-
/** Chrome-caps predicate. The layer asks `'path-edit.anchors'` before
|
|
8240
|
-
* drawing anything, so paint and the anchor hit-test in
|
|
8241
|
-
* `affordanceAt` consult the same rule — otherwise a consumer that
|
|
8242
|
-
* hides the chrome still gets grabbable invisible anchors, or vice
|
|
8243
|
-
* versa. Omit to always draw when an edit target is set. */
|
|
8244
|
-
isVisible?(chromeId: string): boolean;
|
|
8245
8467
|
/** Optional styling overrides. */
|
|
8246
8468
|
style?: PathEditingOverlayStyle;
|
|
8247
8469
|
}
|
|
@@ -8422,6 +8644,301 @@ declare function withAlpha01(color: string, alpha01: number): string;
|
|
|
8422
8644
|
* strips the alpha channel and returns a bare 6-char hex. */
|
|
8423
8645
|
declare function mergeAlphaFromPrev(picked: string, prev: string): string;
|
|
8424
8646
|
|
|
8647
|
+
/**
|
|
8648
|
+
* The paint-kind registry — what makes `FillStyle` open.
|
|
8649
|
+
*
|
|
8650
|
+
* A consumer registers a sixth kind and it renders, converts between the
|
|
8651
|
+
* bounds and pose frames, and serializes, with no kit edits. The five built-in
|
|
8652
|
+
* kinds are registered here at module load so an editor's kind bar can
|
|
8653
|
+
* enumerate every kind through one list.
|
|
8654
|
+
*
|
|
8655
|
+
* Each kit layer consults this registry for a kind it does not recognize and
|
|
8656
|
+
* otherwise runs its own built-in branch. That split is not laziness: a built-in
|
|
8657
|
+
* kind's render slot lives in the GL renderer, its serialize slot lives in
|
|
8658
|
+
* `@weasel-js/svg`, and neither can be imported from here without inverting a
|
|
8659
|
+
* package dependency.
|
|
8660
|
+
*/
|
|
8661
|
+
|
|
8662
|
+
/** A compiled GL program. A paint kind gets one from
|
|
8663
|
+
* {@link PaintBindContext.program} and hands it back from `bind`. */
|
|
8664
|
+
type PaintProgram = ShaderProgram;
|
|
8665
|
+
/**
|
|
8666
|
+
* `FillStyle`'s discriminant, open on the string the way `ChromeId` is: the
|
|
8667
|
+
* five kinds the kit ships, plus whatever a consumer registers.
|
|
8668
|
+
*/
|
|
8669
|
+
type PaintKind = 'solid' | 'linear-gradient' | 'radial-gradient' | 'conic-gradient' | 'pattern' | (string & {});
|
|
8670
|
+
/** What a registered kind's editor renders. `PaintInput` in `@weasel-js/ui`
|
|
8671
|
+
* is the control that mounts it. */
|
|
8672
|
+
interface PaintKindEditorProps {
|
|
8673
|
+
value: FillStyle;
|
|
8674
|
+
onInput?(next: FillStyle): void;
|
|
8675
|
+
onChange(next: FillStyle): void;
|
|
8676
|
+
}
|
|
8677
|
+
/**
|
|
8678
|
+
* The renderer surface a paint kind binds against, narrowed to what a paint
|
|
8679
|
+
* needs. The full `DrawContext` is not consumer surface.
|
|
8680
|
+
*/
|
|
8681
|
+
interface PaintBindContext {
|
|
8682
|
+
readonly gl: WebGL2RenderingContext;
|
|
8683
|
+
/** The group alpha this draw inherits — multiply it into the paint's own. */
|
|
8684
|
+
readonly alpha: number;
|
|
8685
|
+
/**
|
|
8686
|
+
* The compiled program for a `registerProgram` id, compiled against this
|
|
8687
|
+
* renderer on first use. `null` when no source is registered under `id` or
|
|
8688
|
+
* compilation failed.
|
|
8689
|
+
*/
|
|
8690
|
+
program(id: string): PaintProgram | null;
|
|
8691
|
+
/** Send `u_proj` and `u_model`, which every kit vertex shader takes. */
|
|
8692
|
+
setProjAndModel(program: PaintProgram): void;
|
|
8693
|
+
/**
|
|
8694
|
+
* `u_worldInv` for a paint declaring `units` — the inverse of the transform
|
|
8695
|
+
* from the paint's space to the frame the geometry arrives in. Paired with
|
|
8696
|
+
* the vertex shader's `v_world` varying this is *the* paint-space
|
|
8697
|
+
* convention; it is not gradient-specific.
|
|
8698
|
+
*/
|
|
8699
|
+
spaceInverse(units: GradientUnits | undefined): Mat3$1;
|
|
8700
|
+
/** Upload a stop ramp and bind it to a texture unit. */
|
|
8701
|
+
bindRamp(stops: GradStop[], unit: number): void;
|
|
8702
|
+
}
|
|
8703
|
+
/**
|
|
8704
|
+
* One paint kind.
|
|
8705
|
+
*
|
|
8706
|
+
* `seed`, `label` and `colorOf` are the editor's slots and every kind has
|
|
8707
|
+
* them. The rest are optional because a kind may not need them — but
|
|
8708
|
+
* `inPoseFrame` and `toBoundsFrame` come as a pair or not at all: a kind that
|
|
8709
|
+
* converts one direction and not the other paints correctly once and then
|
|
8710
|
+
* drifts on the next resize.
|
|
8711
|
+
*/
|
|
8712
|
+
interface PaintKindEntry {
|
|
8713
|
+
id: string;
|
|
8714
|
+
label: string;
|
|
8715
|
+
/** Glyph naming this kind in an editor's kind bar, as an icon name the UI
|
|
8716
|
+
* layer resolves — the same indirection `ToolPrefBase.icon` uses. A kind
|
|
8717
|
+
* without one is named by its `label`. */
|
|
8718
|
+
icon?: string;
|
|
8719
|
+
/** A paint of this kind seeded from a color — what an editor writes when a
|
|
8720
|
+
* consumer switches a solid to this kind. */
|
|
8721
|
+
seed(fromColor: string): FillStyle;
|
|
8722
|
+
/** The single color this paint shows, or `undefined` when it has none. */
|
|
8723
|
+
colorOf(paint: FillStyle): string | undefined;
|
|
8724
|
+
/** Editor slot. */
|
|
8725
|
+
Editor?: ComponentType<PaintKindEditorProps>;
|
|
8726
|
+
/**
|
|
8727
|
+
* Render slot: bind program, uniforms and textures for `fill` and return the
|
|
8728
|
+
* bound program; `null` declines the paint.
|
|
8729
|
+
*
|
|
8730
|
+
* Binding is split from drawing on purpose — a caller owning its own stencil
|
|
8731
|
+
* state (an inner/outer-aligned stroke, an even-odd fill) must issue its own
|
|
8732
|
+
* draw call, and the kit's draw wrapper would clobber that state. Shader
|
|
8733
|
+
* output must be premultiplied: `outColor = vec4(rgb * a, a)`.
|
|
8734
|
+
*/
|
|
8735
|
+
bind?(ctx: PaintBindContext, fill: FillStyle): PaintProgram | null;
|
|
8736
|
+
/** Bounds frame → the frame the node is painted in. */
|
|
8737
|
+
inPoseFrame?(fill: FillStyle, box: FillPoseBox): FillStyle;
|
|
8738
|
+
/** The inverse. Required whenever `inPoseFrame` is supplied. */
|
|
8739
|
+
toBoundsFrame?(fill: FillStyle, box: FillPoseBox): FillStyle;
|
|
8740
|
+
/** The `<defs>` entry backing a `url(#id)` reference. */
|
|
8741
|
+
toSvg?(id: string, fill: FillStyle): string;
|
|
8742
|
+
}
|
|
8743
|
+
/**
|
|
8744
|
+
* A consumer's own paint, typed as a `FillStyle`.
|
|
8745
|
+
*
|
|
8746
|
+
* `FillStyle` stays a closed union: opening its discriminant would widen every
|
|
8747
|
+
* built-in member and break the narrowing the kit's own branches depend on.
|
|
8748
|
+
* A registered kind declares its own interface instead and passes it through
|
|
8749
|
+
* here — the kit reads only `fill` and hands the whole object back to that
|
|
8750
|
+
* kind's slots.
|
|
8751
|
+
*/
|
|
8752
|
+
declare function asPaint<T extends {
|
|
8753
|
+
fill: string;
|
|
8754
|
+
}>(paint: T): FillStyle;
|
|
8755
|
+
/** Register a paint kind. Returns a disposer that removes it. */
|
|
8756
|
+
declare function registerPaintKind(entry: PaintKindEntry): () => void;
|
|
8757
|
+
/** The entry for `kind`, or `undefined`. */
|
|
8758
|
+
declare function getPaintKind(kind: string | undefined): PaintKindEntry | undefined;
|
|
8759
|
+
/** Every registered kind, built-ins first, in registration order. */
|
|
8760
|
+
declare function listPaintKinds(): readonly PaintKindEntry[];
|
|
8761
|
+
/** The registry entry for a paint, or `undefined` when its kind is unknown. */
|
|
8762
|
+
declare function paintKindOf(fill: FillStyle): PaintKindEntry | undefined;
|
|
8763
|
+
/** @internal Test helper — do not call from product code. */
|
|
8764
|
+
declare function _resetPaintKindsForTests(): void;
|
|
8765
|
+
|
|
8766
|
+
/**
|
|
8767
|
+
* The stroke-marker registry — arrowheads and other line terminators.
|
|
8768
|
+
*
|
|
8769
|
+
* Keyed by string, because a key is what sits in `stroke.markerEnd`. That is
|
|
8770
|
+
* the difference from `registerNodeShape`, which resolves by first-matching
|
|
8771
|
+
* predicate and whose `id` is only a label.
|
|
8772
|
+
*
|
|
8773
|
+
* A built-in's SVG slot lives in `@weasel-js/svg` and cannot be imported here
|
|
8774
|
+
* without inverting a package dependency, so an entry carries `toSvg` for that
|
|
8775
|
+
* package to consume — the same split `PaintKindEntry` uses.
|
|
8776
|
+
*/
|
|
8777
|
+
|
|
8778
|
+
/** What an entry's `path` is given. Entries that ignore it may return a
|
|
8779
|
+
* constant path. */
|
|
8780
|
+
interface MarkerCtx {
|
|
8781
|
+
/** One geometry unit, in the same world units the ribbon is tessellated in.
|
|
8782
|
+
* Defaults to the resolved stroke width. */
|
|
8783
|
+
readonly size: number;
|
|
8784
|
+
/** The stroke this marker belongs to, already width-resolved. */
|
|
8785
|
+
readonly stroke: Stroke;
|
|
8786
|
+
}
|
|
8787
|
+
/** `'line'` means the stroke's own paint — SVG 2's `context-stroke`, as the
|
|
8788
|
+
* default rather than an opt-in. */
|
|
8789
|
+
type MarkerPaint = FillStyle | 'line' | 'none';
|
|
8790
|
+
interface MarkerEntry {
|
|
8791
|
+
/** `'kit:'`-free for built-ins so the key matches the SVG attribute value;
|
|
8792
|
+
* consumers should prefix (`'app-my-head'`). A key becomes the `id` of the
|
|
8793
|
+
* emitted `<marker>` def, so it must be a valid XML name — no colons. */
|
|
8794
|
+
id: MarkerKey;
|
|
8795
|
+
/** Geometry with its anchor at the origin, pointing +X, in units of
|
|
8796
|
+
* `ctx.size`. An arbitrary anchor is expressed by where the geometry is
|
|
8797
|
+
* drawn, which is why there is no `refX`/`refY`. */
|
|
8798
|
+
path(ctx: MarkerCtx): Path;
|
|
8799
|
+
/** Default `'line'`. */
|
|
8800
|
+
fill?: MarkerPaint;
|
|
8801
|
+
/** Outline width is in the same units as `path`. `false` (the default)
|
|
8802
|
+
* means no outline. */
|
|
8803
|
+
outline?: {
|
|
8804
|
+
width: number;
|
|
8805
|
+
paint?: MarkerPaint;
|
|
8806
|
+
} | false;
|
|
8807
|
+
/** How far back along the line the stroke stops, in units of `ctx.size`.
|
|
8808
|
+
* Default 0. A property of the shape, not a setting on the stroke: an open
|
|
8809
|
+
* V needs 0 or its arms stop meeting the line. */
|
|
8810
|
+
inset?: number;
|
|
8811
|
+
/** `'auto'` (default) follows the line; a number is a fixed angle in
|
|
8812
|
+
* radians, ignoring the line — SVG's `orient="<angle>"`. */
|
|
8813
|
+
orient?: 'auto' | number;
|
|
8814
|
+
/** Emits the `<marker>` def. Consumed by `@weasel-js/svg`. */
|
|
8815
|
+
toSvg?(id: string, entry: MarkerEntry): string;
|
|
8816
|
+
}
|
|
8817
|
+
/** Register a marker. Returns a disposer. Re-registering a built-in id is an
|
|
8818
|
+
* override; disposing it restores the built-in rather than deleting the key. */
|
|
8819
|
+
declare function registerMarker(entry: MarkerEntry): () => void;
|
|
8820
|
+
/** The entry for `key`, or `undefined`. */
|
|
8821
|
+
declare function getMarker(key: string | undefined): MarkerEntry | undefined;
|
|
8822
|
+
/** Every registered marker, built-ins first, in registration order. */
|
|
8823
|
+
declare function listMarkers(): readonly MarkerEntry[];
|
|
8824
|
+
/** Test helper. Do not call from product code. */
|
|
8825
|
+
declare function _resetMarkersForTests(): void;
|
|
8826
|
+
|
|
8827
|
+
/**
|
|
8828
|
+
* Resolving a `MarkerRef` to the distance the ribbon must stop short.
|
|
8829
|
+
*
|
|
8830
|
+
* The tessellation layer takes these as plain numbers and knows nothing about
|
|
8831
|
+
* the registry — keeping that layer free of upward dependencies is deliberate.
|
|
8832
|
+
* The ribbon cache, the SVG serializer and `inkReach` all resolve through here,
|
|
8833
|
+
* so the ribbon, the export and the hit region cannot disagree about where the
|
|
8834
|
+
* line ends.
|
|
8835
|
+
*/
|
|
8836
|
+
|
|
8837
|
+
/** The size of one marker unit, in the same world units as `strokeWidth`. */
|
|
8838
|
+
declare function resolveMarkerSize(ref: MarkerRef, strokeWidth: number): number;
|
|
8839
|
+
declare function markerKeyOf(ref: MarkerRef): string;
|
|
8840
|
+
/**
|
|
8841
|
+
* How far back the ribbon stops for `ref`, in world units. Zero for an absent
|
|
8842
|
+
* marker, an unregistered key, or an open head — never throws, because an
|
|
8843
|
+
* unknown key is a data problem and dropping the head is the graceful answer.
|
|
8844
|
+
*/
|
|
8845
|
+
declare function markerInset(ref: MarkerRef | undefined, strokeWidth: number): number;
|
|
8846
|
+
/** The start and end insets a stroke asks for. `markerMid` never insets —
|
|
8847
|
+
* trimming at an interior vertex would cut the line in two. */
|
|
8848
|
+
declare function strokeInsets(stroke: Stroke, strokeWidth: number): {
|
|
8849
|
+
start: number;
|
|
8850
|
+
end: number;
|
|
8851
|
+
};
|
|
8852
|
+
|
|
8853
|
+
interface Polyline {
|
|
8854
|
+
/** Interleaved x,y vertices (length = 2 × point count). */
|
|
8855
|
+
points: number[];
|
|
8856
|
+
/** Whether the contour was closed (ends with Z, or is a RectPath). */
|
|
8857
|
+
closed: boolean;
|
|
8858
|
+
/** For each point, the previous anchor index. Anchor-aligned points set A === B. */
|
|
8859
|
+
anchorA?: Uint32Array;
|
|
8860
|
+
/** For each point, the next anchor index. */
|
|
8861
|
+
anchorB?: Uint32Array;
|
|
8862
|
+
/** For each point, the arc-length fraction along (A, B). 0 at anchor A; for anchor-aligned, set to 0. */
|
|
8863
|
+
anchorT?: Float32Array;
|
|
8864
|
+
/** Per-point stroke width, populated by the tessellator when the Stroke
|
|
8865
|
+
* carries `vertexWidths`. Undefined means uniform `Stroke.width`. */
|
|
8866
|
+
widths?: Float32Array;
|
|
8867
|
+
}
|
|
8868
|
+
|
|
8869
|
+
/**
|
|
8870
|
+
* Where a stroke's markers sit and which way they point.
|
|
8871
|
+
*
|
|
8872
|
+
* Computed from the *untrimmed* polyline: trimming moves the endpoint, and a
|
|
8873
|
+
* marker anchors to where the line was authored to end, not to where the
|
|
8874
|
+
* ribbon was cut.
|
|
8875
|
+
*/
|
|
8876
|
+
|
|
8877
|
+
interface MarkerSite {
|
|
8878
|
+
x: number;
|
|
8879
|
+
y: number;
|
|
8880
|
+
/** Radians. The direction the marker's +X axis should point — outward at a
|
|
8881
|
+
* start or end, along the bisector at an interior vertex. */
|
|
8882
|
+
angle: number;
|
|
8883
|
+
role: 'start' | 'mid' | 'end';
|
|
8884
|
+
}
|
|
8885
|
+
interface MarkerSiteRequest {
|
|
8886
|
+
start: boolean;
|
|
8887
|
+
mid: boolean;
|
|
8888
|
+
end: boolean;
|
|
8889
|
+
}
|
|
8890
|
+
declare function markerSites(pl: Polyline, want: MarkerSiteRequest): MarkerSite[];
|
|
8891
|
+
|
|
8892
|
+
/**
|
|
8893
|
+
* Turning a stroke's markers into draw commands.
|
|
8894
|
+
*
|
|
8895
|
+
* Separate `PathDrawCommand`s rather than triangles appended to the stroke
|
|
8896
|
+
* ribbon: an entry may carry a fill and an outline at once, or a paint that
|
|
8897
|
+
* differs from the line's, neither of which one mesh can express — and folding
|
|
8898
|
+
* them in would drag the whole marker vocabulary into the ribbon cache key.
|
|
8899
|
+
*/
|
|
8900
|
+
|
|
8901
|
+
/**
|
|
8902
|
+
* Every marker command for `path` under `stroke`. `strokeWidth` is the already
|
|
8903
|
+
* width-resolved stroke width; `flattenTolerance` matches what the ribbon used,
|
|
8904
|
+
* so markers land on the same flattened vertices the stroke did.
|
|
8905
|
+
*/
|
|
8906
|
+
declare function markerDrawCommands(path: Path, stroke: Stroke, strokeWidth: number, flattenTolerance: number | undefined): PathDrawCommand[];
|
|
8907
|
+
|
|
8908
|
+
/**
|
|
8909
|
+
* The kit's built-in stroke-marker vocabulary.
|
|
8910
|
+
*
|
|
8911
|
+
* Every entry is authored with its anchor at the origin and pointing +X, so
|
|
8912
|
+
* the line arrives from -X and no geometry sits at positive X. Coordinates are
|
|
8913
|
+
* in units of `MarkerCtx.size`, which defaults to the resolved stroke width —
|
|
8914
|
+
* one definition is therefore correct at any line weight.
|
|
8915
|
+
*
|
|
8916
|
+
* Not to be confused with `features/paths/markers.ts`, which builds
|
|
8917
|
+
* decorative chrome shapes and is unrelated.
|
|
8918
|
+
*/
|
|
8919
|
+
|
|
8920
|
+
declare const BUILTIN_MARKERS: readonly MarkerEntry[];
|
|
8921
|
+
|
|
8922
|
+
/**
|
|
8923
|
+
* Shortening a flattened subpath so a filled marker is not speared by its own
|
|
8924
|
+
* line. SVG has no equivalent — it paints the marker over a full-length
|
|
8925
|
+
* stroke — so this is the one place our rendering deliberately differs.
|
|
8926
|
+
*
|
|
8927
|
+
* Runs before dash splitting, so a dash pattern fits the visible line rather
|
|
8928
|
+
* than running off under the head. The anchor-param interpolation matches
|
|
8929
|
+
* `splitForDash`'s rule for a boundary landing mid-segment.
|
|
8930
|
+
*/
|
|
8931
|
+
|
|
8932
|
+
/**
|
|
8933
|
+
* Shorten `pl` by `startInset` from its first point and `endInset` from its
|
|
8934
|
+
* last, both in the same world units as the points.
|
|
8935
|
+
*
|
|
8936
|
+
* Returns `pl` itself when there is nothing to do (both insets zero, or the
|
|
8937
|
+
* subpath is closed and so has no free ends), and `null` when the insets
|
|
8938
|
+
* consume the whole run — a caller should then draw no ribbon at all.
|
|
8939
|
+
*/
|
|
8940
|
+
declare function trimPolyline(pl: Polyline, startInset: number, endInset: number): Polyline | null;
|
|
8941
|
+
|
|
8425
8942
|
/** Kit-shipped default paint constants.
|
|
8426
8943
|
*
|
|
8427
8944
|
* Single source of truth for the colors the built-in tools and the default
|
|
@@ -8432,6 +8949,7 @@ declare function mergeAlphaFromPrev(picked: string, prev: string): string;
|
|
|
8432
8949
|
* All values are `#rrggbbaa` so they round-trip through the kit's hex8 alpha
|
|
8433
8950
|
* helpers (`util/color`) without ambiguity.
|
|
8434
8951
|
*/
|
|
8952
|
+
|
|
8435
8953
|
/** Default fill paint for shapes and the fill action — opaque white. */
|
|
8436
8954
|
declare const DEFAULT_FILL_COLOR = "#ffffffff";
|
|
8437
8955
|
/** Default stroke paint for shapes and the stroke action — opaque black. */
|
|
@@ -8443,6 +8961,41 @@ declare const DEFAULT_PALETTE: readonly string[];
|
|
|
8443
8961
|
* selected-anchor highlight. Derived from the first palette entry so the
|
|
8444
8962
|
* preview chrome matches the default insert color. */
|
|
8445
8963
|
declare const GHOST_STROKE: string;
|
|
8964
|
+
/**
|
|
8965
|
+
* A solid paint from a color string — the authoring shorthand for the one
|
|
8966
|
+
* shape a node's `data.fill` (and a `Stroke.paint`) may take.
|
|
8967
|
+
*
|
|
8968
|
+
* An alpha channel in `color` moves to `opacity`, because that is where every
|
|
8969
|
+
* paint kind carries its alpha; leaving it in the hex too would multiply the
|
|
8970
|
+
* two in the renderer.
|
|
8971
|
+
*/
|
|
8972
|
+
declare function solid(color: string): FillStyle;
|
|
8973
|
+
/** A solid stroke of `color` at `width` world units. Authoring shorthand for
|
|
8974
|
+
* `{ paint: solid(color), width }`. */
|
|
8975
|
+
declare function strokeOf(color: string, width?: number): Stroke;
|
|
8976
|
+
/** A stroke painted with `paint` at `width` world units — `strokeOf`'s sibling
|
|
8977
|
+
* for a gradient or pattern, which has no color to pass. */
|
|
8978
|
+
declare function strokeWith(paint: FillStyle, width?: number): Stroke;
|
|
8979
|
+
/** The kit's default node paint — what a shape with no declared fill paints. */
|
|
8980
|
+
declare const DEFAULT_SHAPE_FILL: FillStyle;
|
|
8981
|
+
/**
|
|
8982
|
+
* The 0..1 alpha a paint paints at.
|
|
8983
|
+
*
|
|
8984
|
+
* Every paint kind carries its alpha in `opacity` — that is the one slot a
|
|
8985
|
+
* gradient or a pattern has, so it is the slot all of them use.
|
|
8986
|
+
*/
|
|
8987
|
+
declare function paintAlpha(paint: FillStyle | undefined): number;
|
|
8988
|
+
/** `paint` painting at `alpha01` (clamped to 0..1). */
|
|
8989
|
+
declare function paintWithAlpha(paint: FillStyle, alpha01: number): FillStyle;
|
|
8990
|
+
/**
|
|
8991
|
+
* `paint` recolored to `color`, keeping everything else about it.
|
|
8992
|
+
*
|
|
8993
|
+
* A solid paint takes the new color; a gradient or a pattern has no single
|
|
8994
|
+
* color to replace, so it is superseded by a solid one — picking a color off
|
|
8995
|
+
* a swatch means "paint this color". An alpha channel in `color` wins;
|
|
8996
|
+
* without one, the paint's existing opacity carries over.
|
|
8997
|
+
*/
|
|
8998
|
+
declare function paintWithColor(paint: FillStyle | undefined, color: string): FillStyle;
|
|
8446
8999
|
|
|
8447
9000
|
/**
|
|
8448
9001
|
* Build an op-batched undo/redo `History`, defaulting restore-time op
|
|
@@ -8476,7 +9029,9 @@ interface ArrayAdapterConfig<TNode extends {
|
|
|
8476
9029
|
getParent?: (id: string) => string | null;
|
|
8477
9030
|
/** Optional reparent mutator. Default is a noop. */
|
|
8478
9031
|
setParent?: (id: string, parentId: string | null) => void;
|
|
8479
|
-
/** Optional children lookup.
|
|
9032
|
+
/** Optional children lookup for a node id. The adapter answers the root
|
|
9033
|
+
* itself, from `ref` and `getParent` in array order, so this is never
|
|
9034
|
+
* called with `null`. Default omits the method entirely. */
|
|
8480
9035
|
getChildren?: (id: string) => string[] | undefined;
|
|
8481
9036
|
/** Live ref to the current selection. Default: empty array. */
|
|
8482
9037
|
selectionRef?: MutableRefObject<string[]>;
|
|
@@ -8672,7 +9227,8 @@ interface GuidesLayerOpts {
|
|
|
8672
9227
|
* screen space, projected from world offsets via the active view. */
|
|
8673
9228
|
declare function createGuidesLayer(opts: GuidesLayerOpts): RenderLayer<unknown>;
|
|
8674
9229
|
|
|
8675
|
-
/** Axis-aligned bounding box.
|
|
9230
|
+
/** Axis-aligned bounding box. Alignment matches AABBs throughout; a rotated
|
|
9231
|
+
* pose enters as the AABB of its ink (see `AlignBoundsProjection.boundsOf`). */
|
|
8676
9232
|
interface AlignBounds {
|
|
8677
9233
|
x: number;
|
|
8678
9234
|
y: number;
|
|
@@ -8695,18 +9251,27 @@ interface AlignMatchResult {
|
|
|
8695
9251
|
* and translates a pose. The rect default handles `{x,y,width,height}` poses;
|
|
8696
9252
|
* non-rect poses (Path, polygon) supply their own. */
|
|
8697
9253
|
interface AlignBoundsProjection<TPose> {
|
|
9254
|
+
/** The pose's *visual* AABB — a rotated pose reports the extent of its ink,
|
|
9255
|
+
* not the box it was posed in. Guides and matching both read this, so an
|
|
9256
|
+
* implementation that returns the stored box makes a rotated shape snap to
|
|
9257
|
+
* lines nothing is drawn at. */
|
|
8698
9258
|
boundsOf(pose: TPose): AlignBounds;
|
|
9259
|
+
/** Move the pose, preserving every other field it carries — nothing
|
|
9260
|
+
* downstream re-derives rotation or style from anywhere else. */
|
|
8699
9261
|
translate(pose: TPose, dx: number, dy: number): TPose;
|
|
8700
9262
|
}
|
|
8701
|
-
/** Which candidate lines to derive from a set of
|
|
9263
|
+
/** Which candidate lines to derive from a set of poses — edges, centers, or
|
|
8702
9264
|
* both, and whether the page box contributes its own. */
|
|
8703
|
-
interface DeriveAlignmentGuidesOptions {
|
|
9265
|
+
interface DeriveAlignmentGuidesOptions<TPose = AlignBounds> {
|
|
8704
9266
|
/** Include the document/page box's edges + center as candidates. */
|
|
8705
9267
|
page?: AlignBounds;
|
|
8706
9268
|
/** Emit left/right (x) and top/bottom (y) edge guides. Default true. */
|
|
8707
9269
|
edges?: boolean;
|
|
8708
9270
|
/** Emit centerX (x) and centerY (y) guides. Default true. */
|
|
8709
9271
|
centers?: boolean;
|
|
9272
|
+
/** Reads each target's AABB. Defaults to `RECT_ALIGN_PROJECTION`. Pass the
|
|
9273
|
+
* same projection `alignMoveBehavior` gets, or the two sides disagree. */
|
|
9274
|
+
projection?: AlignBoundsProjection<TPose>;
|
|
8710
9275
|
}
|
|
8711
9276
|
/** Common options shared by the three alignment behavior factories. */
|
|
8712
9277
|
interface AlignmentBehaviorBase {
|
|
@@ -8723,18 +9288,23 @@ interface AlignmentBehaviorBase {
|
|
|
8723
9288
|
bypassKey?: keyof ModifierState;
|
|
8724
9289
|
}
|
|
8725
9290
|
|
|
8726
|
-
/** Derive candidate alignment lines from a set of
|
|
9291
|
+
/** Derive candidate alignment lines from a set of sibling poses plus an
|
|
8727
9292
|
* optional page box. Each box contributes up to 3 guides per axis: the two
|
|
8728
|
-
* edges and the center. Overlapping offsets collapse to one candidate.
|
|
8729
|
-
|
|
9293
|
+
* edges and the center. Overlapping offsets collapse to one candidate.
|
|
9294
|
+
* Poses go through the same projection `alignMoveBehavior` matches with, so
|
|
9295
|
+
* a rotated sibling advertises its ink edges rather than its stored box. */
|
|
9296
|
+
declare function deriveAlignmentGuides<TPose = AlignBounds>(targets: readonly TPose[], opts?: DeriveAlignmentGuidesOptions<TPose>): Guide[];
|
|
8730
9297
|
|
|
8731
9298
|
/** Move/insert test all three features per axis. */
|
|
8732
9299
|
declare const MOVE_ANCHORS: {
|
|
8733
9300
|
x: readonly AlignAnchor[];
|
|
8734
9301
|
y: readonly AlignAnchor[];
|
|
8735
9302
|
};
|
|
8736
|
-
/** Default projection for rect-shaped poses (`{x,y,width,height}`).
|
|
8737
|
-
|
|
9303
|
+
/** Default projection for rect-shaped poses (`{x,y,width,height,rotation?}`).
|
|
9304
|
+
* A rotated pose reports the AABB of its ink, so guides derived from a
|
|
9305
|
+
* stationary sibling and the box a dragged selection matches with are the
|
|
9306
|
+
* same measurement. */
|
|
9307
|
+
declare const RECT_ALIGN_PROJECTION: AlignBoundsProjection<RectPose>;
|
|
8738
9308
|
/**
|
|
8739
9309
|
* Match a moving box's selected edge/center features against candidate guide
|
|
8740
9310
|
* lines. Returns the per-axis snap delta and the matched candidate line(s).
|
|
@@ -8801,7 +9371,7 @@ declare function pointInRotatedRect(pose: RotatedPose, worldX: number, worldY: n
|
|
|
8801
9371
|
* handle's center. Matches the demo's visual default; consumers can
|
|
8802
9372
|
* override per-call. Unscaled — kit-internal use sites multiply by
|
|
8803
9373
|
* `DeviceProfile.targetScale`. */
|
|
8804
|
-
declare const DEFAULT_ROTATION_HANDLE_DISTANCE
|
|
9374
|
+
declare const DEFAULT_ROTATION_HANDLE_DISTANCE: 24;
|
|
8805
9375
|
/** Rotation handle position in world coords. */
|
|
8806
9376
|
interface RotationHandle {
|
|
8807
9377
|
/** Handle center in world coords. */
|
|
@@ -9137,7 +9707,8 @@ interface SelectFromLassoOptions {
|
|
|
9137
9707
|
* preserve, with shift). */
|
|
9138
9708
|
declare function selectFromLasso(opts?: SelectFromLassoOptions): LassoSelectBehavior;
|
|
9139
9709
|
|
|
9140
|
-
/** Edge or center the selection should align to within the selection's
|
|
9710
|
+
/** Edge or center the selection should align to within the selection's visual
|
|
9711
|
+
* union AABB (rotated members contribute their ink extent). */
|
|
9141
9712
|
type AlignEdge = 'left' | 'right' | 'top' | 'bottom' | 'center-x' | 'center-y';
|
|
9142
9713
|
/** Adapter for `useAlign`. */
|
|
9143
9714
|
interface AlignAdapter<TPose> {
|
|
@@ -9159,6 +9730,17 @@ interface UseAlignReturn {
|
|
|
9159
9730
|
/** Imperative trigger. No-op when fewer than 2 items selected. */
|
|
9160
9731
|
align(edge: AlignEdge): void;
|
|
9161
9732
|
}
|
|
9733
|
+
/**
|
|
9734
|
+
* The pose's *visual* bounds: its descriptor bounds expanded to cover the
|
|
9735
|
+
* rotated rectangle, so a turned shape reports the extent of its ink rather
|
|
9736
|
+
* than the box it was posed in. Align, distribute and flip all fold these.
|
|
9737
|
+
*
|
|
9738
|
+
* Both ends of an align must use it — a visual union measured against
|
|
9739
|
+
* unrotated member boxes misplaces every rotated member. The expanded box
|
|
9740
|
+
* shares its centre with the stored one, so the delta stays a translation of
|
|
9741
|
+
* the stored pose and no re-posing is needed.
|
|
9742
|
+
*/
|
|
9743
|
+
declare function visualBoundsViaDescriptor<TPose>(pose: TPose, geometry: PoseProjection<TPose>): ResizePose;
|
|
9162
9744
|
/** Compute the (dx, dy) translation that moves AABB `b` so that the requested
|
|
9163
9745
|
* `edge`/center matches the corresponding feature of the union AABB `u`. */
|
|
9164
9746
|
declare function alignDeltaFor(b: ResizePose, u: ResizePose, edge: AlignEdge): {
|
|
@@ -9175,8 +9757,9 @@ declare function useAlign<TPose>(adapter: AlignAdapter<TPose>, options?: UseAlig
|
|
|
9175
9757
|
|
|
9176
9758
|
/** Axis along which selection is distributed. `'x'` spreads horizontally. */
|
|
9177
9759
|
type DistributeAxis = 'x' | 'y';
|
|
9178
|
-
/** `'centers'` spaces
|
|
9179
|
-
* consecutive
|
|
9760
|
+
/** `'centers'` spaces centers equally; `'gaps'` makes the gap between
|
|
9761
|
+
* consecutive items equal. Both measure a rotated item by its ink extent.
|
|
9762
|
+
* Endpoints stay put in both modes. */
|
|
9180
9763
|
type DistributeMode = 'centers' | 'gaps';
|
|
9181
9764
|
/** Adapter for `useDistribute`. */
|
|
9182
9765
|
interface DistributeAdapter<TPose> {
|
|
@@ -9976,6 +10559,10 @@ declare function RectIcon({ className, size }: IconProps): react_jsx_runtime.JSX
|
|
|
9976
10559
|
/** Outlined ellipse. Used for the ellipse insertion tool. */
|
|
9977
10560
|
declare function EllipseIcon({ className, size }: IconProps): react_jsx_runtime.JSX.Element;
|
|
9978
10561
|
|
|
10562
|
+
/** Framed picture with a sun and mountain — the conventional "image" glyph.
|
|
10563
|
+
* Used for the image insertion tool (`useImageTool`). */
|
|
10564
|
+
declare function ImageIcon({ className, size }: IconProps): react_jsx_runtime.JSX.Element;
|
|
10565
|
+
|
|
9979
10566
|
/** Eyedropper — diagonal stem running from upper-right (bulb) to
|
|
9980
10567
|
* lower-left (tip), with a small squared bulb cap at the top. Used
|
|
9981
10568
|
* for the eyedropper / color-picker tool. */
|
|
@@ -10069,4 +10656,4 @@ interface InsertOverlayStyle {
|
|
|
10069
10656
|
lineWidth?: number;
|
|
10070
10657
|
}
|
|
10071
10658
|
|
|
10072
|
-
export { ANCHOR_HIT_BASE_PX, Action, ActionsProp, ActionsProviderIfRoot, ActionsRegistry, Affordance, AffordanceBinding, AffordanceHit, AffordanceRegion, type AffordanceRegionHit, type AlignAdapter, type AlignAnchor, type AlignBounds, type AlignBoundsProjection, type AlignEdge, type AlignMatchResult, type AlignMoveArgs, type AlignmentBehaviorBase, type AnchorHit, type AnchorScratch, type AnchorState, type AnimateOnSetPoseOptions, type AnimateToBoundsOptions, type AnimationHandle, type Animator, AnyTool, AreaSelectAdapter, type ArrayAdapter, type ArrayAdapterConfig, BUNDLE_TOOLS, BindingScope, BooleansAdapter, Bounds, BoundsConstraint, type BuildChromeCtxArgs, type BuiltinShapeToolId, type BuiltinToolId, type BuiltinToolOptions, COARSE_TARGET_SCALE, CURVE_REPS, type CanvasExtensionApi, type CanvasFocusReturn, type CanvasHelpers, type CanvasProps, type CanvasSelectionMode, type CanvasSize, type CanvasSizeSnapshot, type CellHighlightLayerOpts, ChromeCtx, ChromeId, ChromeState, type ClampBounds, ClipboardSnapshot, type CoalescedCtx, type ColorInterpolate, type ColorOverride, type ColorOverrideFn, ColorOverrideRegistry, type ColorSpace, CommonAffordanceScratch, type ComposeSelectionPoseOpts, type ComputeFitViewOptions, Condition, ContentHandlerEntry, Contribution, type CornerResizeAffordanceOptions, type CornerResizeScratch, type CreateChildrenLayerOpts, type CreateParallaxLayerOpts, type CreatePathEditingOverlayLayerOptions, type CreatePathLayerOpts, type CreatePenPreviewLayerOptions, type CreateTextLayerOpts, type CreateViewportLayerOpts, CropIcon, CursorCoordsHud, type CursorCoordsHudProps, type CurveRepKind, type CurveRepresentation, type CustomLayerEntry, type CycleHandle, type CycleVertexColorsOptions, DEFAULT_ALPHA_DECAY, DEFAULT_ALPHA_MIN, DEFAULT_DEBUG_STROKES, DEFAULT_DEBUG_THEME, DEFAULT_DEVICE_PROFILE, DEFAULT_FILL_COLOR, DEFAULT_FLATTEN_TOLERANCE, DEFAULT_GUIDE_TOLERANCE_PX, DEFAULT_HANDLE_SIZE, DEFAULT_PALETTE, DEFAULT_ROTATION_HANDLE_DISTANCE, DEFAULT_STROKE_COLOR, DEFAULT_VELOCITY_DECAY, DebugConfig, DebugSink, DebugSnapshot, DebugStrokes, DebugTheme, type DecayLoopConfig, type DecayOptions, type DefaultTextData, DepRegistryProviderIfRoot, DepSchema, type DeriveAlignmentGuidesOptions, DetectedDeviceFacts, DeviceProfile, DeviceProfileProvider, type DeviceProfileProviderProps, Dims, type Discriminator, Dispatcher, type DistributeAdapter, type DistributeAxis, type DistributeMode, DivideIcon, type DragGestureController, type DragGestureCtx, type DragGestureEndCtx, type DragGesturePhase, type DragGesturePoint, type DragHandleOptions, type DragPayload, type DragRadialController, type DragRadialCtx, type DragRadialEndCtx, type DragRadialPoint, type DragRadialState, type DragRectBounds, type DragRectController, type DragRectCtx, type DragRectEndCtx, type DragRectPoint, DrawCommand, type DropZoneOptions, EASINGS, type EasingFn, type EasingName, Eligibility, type EligibilityState, EllipseIcon, type EventTrack, ExcludeIcon, EyedropperIcon, FALLBACK_FIT_VIEW, type FillPoseBox, FillStyle, type FitTextPoseOptions, FitViewToBoundsOptions, type FlagKey, type FreeformOptions, GHOST_STROKE, type GateLayerOptions, GeometryProjection, type GestureSource, GradStop, GradientFill, GradientKind, type GridLayerOpts, type GridSlotConfig, Guide, type GuideSnapOptions, type GuidesLayerOpts, HANDLE_BASE_PX, HandIcon, type InertiaConfig as HandToolInertiaConfig, type HandleDragPoint, type HeadlessCanvasLike, HotkeyTrigger, IDENTITY_JOINT, type IconProps, type ImageNodeData, type ImageStatus, type IndicatorStyle, InsertAdapter, InsertBehavior, InsertExtras, type InsertNodeFactory, type InsertOp, type InsertOverlayStyle, type Interpolate, type InterpolatorFactory, IntersectIcon, type Joint, type JointTransform, KIT_SHAPE_KINDS, type Keyframe, type LabelOptions, LassoHitMode, LassoIcon, LassoSelectAdapter, LassoSelectBehavior, LayerEnumerableAdapter, LayerHit, type LayerSlotValue, type LayersMap, type LayoutLine, type LayoutResult, LayoutSnap, LayoutStrategy, type LifecycleAnimation, LineIcon, type LinePoint, type LoopFactory, type LoopOptions, MIXED, MOVE_ANCHORS, type MarkdownFontOptions, Mat3$1 as Mat3, type MeasureFn, type MeasureTextBoundsOpts, type MeasuredText, MinimapCanvas, type MinimapCanvasProps, type MinimapFit, type Mixed, ModifierState, type MomentumOptions, MoveAdapter, MoveBehavior, type NestedHitOpts, type NestedHitTester, type NestedTimeline, type NodeClientRect, type NodeFill, NodeId, type NodeInk, type NodePaintCtx, type NodeProperties, type NodePropertiesEntry, type NodeRouting, type NodeRoutingEntry, type NodeShapeEntry, type OpenFilePickerOptions, OrderedAdapter, OriginProjection, OverlayPosition, PATH_ANCHOR_CHROME_ID, type PanBounds, type ParallaxOpts, Path, type PathAnchor, type PathAnchorAffordanceOptions, PathBuilder, PathDrawCommand, type PathEditingOverlayStyle, PathFillRule, type PathInWorldPose, type PenAnchor, PenIcon, type PenPreviewStyle, type PenScratch, type PenSubpath, PencilIcon, type PencilPoint, type PhysicsHandle, type PhysicsOptions, PickHud, type PickHudProps, type PickTopMostHitAdapter, type PinchZoomToolOpts, type PixelRenderPlan, type PointInPathOptions, type PointInTextPoseOpts, PointSnapBehavior, PointerProviderIfRoot, type PointerSample, type PointerStylusState, PolygonIcon, PolygonPath, type PolygonPoint, type Pose, PoseProjection, type PoseRotation, type PositionedRun, type PressureToWidthOptions, type Pt, RECT_ALIGN_PROJECTION, ROTATION_HANDLE_BASE_PX, type RangeStyle, type RasterImage, type Rect, RectIcon, RectPath, RectPose, type RegisterNodeShapeOptions, RegisteredOp, RenderLayer, type RenderSceneToCanvasArgs, type RenderSceneToPixelsArgs, type ReorderDirection, ResizeAdapter, ResizeAnchor, ResizePose, ResolvedTextStyle, RotateAdapter, RotateBehavior, type RotateGeometry, RotatedPose, type RotationAffordanceOptions, type RotationHandle, type RotationScratch, Rule, RuleCtx, type RunStylePatch, SPRING_PRESETS, type SampledTrack, type ScalarOrXY, Scene, SceneAdapter, type SceneAdapterSelection, SceneCanvas, type SceneCanvasAdapter, type SceneCanvasApi, type SceneCanvasHit, type SceneCanvasProps, Node$1 as SceneNode, type SceneNodeClientRectOpts, SceneRegistry, type SceneSlotConfig, type SceneToAdapterOptions, SceneViewCanvas, type SceneViewCanvasProps, type SceneViewDrawOne, ScopedBinding, type ScratchKey, type ScratchStore, type SelectAdapter, type SelectFromLassoOptions, SelectIcon, SelectionApi, SelectionContextProvider, SelectionContextProviderIfRoot, type SelectionContextValue, type SelectionHandlesLayerOpts, type SelectionOutlineLayerOpts, type SelectionOverlayLayerOpts, type SelectionOverlaySlotConfig, SerializedScene, type SetFlagResult, type SetPathFields, ShaderProgramHandle, type ShapeCoversPointOptions, type SharedAnchor, type Simulation, type SimulationForce, type SimulationNode, type Skeleton, SliceDep, type SnapPattern, type SnapPointOptions, SnapStrategy, type SplitByLineOptions, type SpringOptions, type SpringPoseOptions, type SpringPreset, type SpringPresetName, type SpringVertexColorsOptions, type StaggerBuilder, type StaggerDelay, type StaggerFactory, type StaggerOptions, type StaggerPerItem, type StaggerSpringPoseOptions, type StaggerTweenOptions, type StaggerVertexColorsOptions, type StandardSlotConfig, type StandardSlotName, StarIcon, type StarPoint, type StartEditOptions, Stroke, type StyleKey, StyledRun, type StylusData, SubtractIcon, SvgIngestOptions, type TextEditScreenPose, type TextEditSelection, TextIcon, type TextLineBoxesOpts, type TextPose, type TextRenderer, TextStyle, TextVerticalAlign, TextureHandle, type ThresholdDragHandle, type ThresholdDragOptions, type TileGridOptions, type TilePatternOpts, TilePatternSpec, type TimelineHandle, type TimelineOptions, type TimelineTrack, Tool, type ToolBundle, ToolDef, ToolKeybinding, type ToolPref, type ToolPrefBoolean, type ToolPrefBooleanControl, type ToolPrefColor, type ToolPrefCustom, type ToolPrefEnum, type ToolPrefEnumControl, type ToolPrefGroup, type ToolPrefKind, type ToolPrefLeaf, type ToolPrefNumber, type ToolPrefNumberControl, type ToolPrefNumberUnit, type ToolPrefPaint, type ToolPrefString, type ToolPrefStringControl, type ToolsApi, type Track, type TweenLoopOptions, type TweenOptions, type TweenPoseOptions, type TweenVertexColorsOptions, UnionIcon, UnitSystem, UnitValue, UnknownIcon, type UseAlignOptions, type UseAlignReturn, type UseAnimatorOptions, type UseArrayAdapterOptions, type UseBooleansOptions, type UseBooleansReturn, type UseCanvasFocusOptions, type UseDistributeOptions, type UseDistributeReturn, type UseDragGestureOptions, type UseDragRadialOptions, type UseDragRectOptions, type UseEyedropperToolOptions, type UseGestureDispatcherOptions, type UseGridCellHoverOptions, type UseGridCellHoverReturn, type UseGuidesReturn, type UseHandToolOptions, type UseHandleDragOptions, type UseHandleDragReturn, type UseHoverTrackingArgs, type UseImageToolOptions, type UseKeybindingsOptions, type UseLassoSelectOptions, type UseLassoToolOptions, UseMoveOptions, type UsePenToolOptions, type UsePointerStylusOptions, type UsePolygonToolOptions, UseResizeOptions, type UseResizePolicyOptions, type UseRotateOptions, type UseRotateToolOptions, UseSceneOptions, type UseSceneTextEditOptions, type UseSceneTextEditReturn, type UseSceneTrivialOptions, type UseSelectToolOptions, UseSelectionOptions, type UseSimulationOptions, type UseStandardActionsOptions, type UseStarToolOptions, type UseTextEditOptions, type UseTextEditReturn, type UseToolsOptions, type UseZoomOptions, type UseZoomReturn, VERSION, type Vec2, type VertexColorChannel, View, ViewTransform, type ViewportConfig, ViewportDims, type ViewportLayer, ViewportToolDef, type ViewportZoomOptions, VisibilityRules, WeaselProvider, type WheelInput, type WheelState, ZoomBound, type ZoomBounds, type ZoomClampOpts, ZoomFactor, aabbCenter, actionIs, alignDeltaFor, alignInsertBehavior, alignMoveBehavior, alignResizeBehavior, always, and, animateLifecycle, animateOnSetPose, annulusSemiAxes, applyOpsTo, applyStyleToRange, areaSelectAction, arrayAdapter, bezierCubic, bezierQuadratic, blendPoses, boundsOfPath, buildChromeCtx, buildSceneViewCommands, canBringForward, canHover, canSendBackward, capabilityAll, capabilityIn, capabilityIs, capabilityNot, caretIndexAt, cellAt, charOffsetToDomPosition, clampView, clearSelectionAction, clientToCanvas, cloneAction, coarsePointer, composeAffordanceLayer, composePath, composeSelectionPose, computeFitView, computeIndicatorCommand, computeWheelAction, cond, constrainTo45, containedThenNearest, countPathAnchors, createCellHighlightLayer, createChildrenLayer, createCornerResizeAffordance, createDebugOverlayLayer, createDebugSink, createDeleteOp, createGridLayer, createGuidesLayer, createHistory, createInsertOp, createMarkdownRenderer, createMoveToIndexOp, createNodeProperties, createNodeRouting, createParallaxLayer, createPathAnchorAffordances, createPathEditingOverlayLayer, createPathLayer, createPenPreviewLayer, createReorderOp, createReparentOp, createRotationAffordance, createScene, createSelectionHandlesLayer, createSelectionOutlineLayer, createSelectionOverlayLayer, createSetDataOp, createSetLayerOp, createSetPathOp, createSetSelectionOp, createSetTextOp, createTextLayer, createTilePattern, createTransformOp, createViewportLayer, cycleVertexColors, decomposePath, defaultCommitAdapter, defaultDrawOne, defaultLabelTextRenderer, defaultNodeProperties, defaultNodeRouting, defaultVisibilityRules, defineTool, defineViewportTool, deleteScratch, deriveAlignmentGuides, deriveParallaxView, dispatchApplyBatch, dlog, domPositionToCharOffset, domToRuns, dwarn, easeIn, easeInBack, easeInBounce, easeInCirc, easeInCubic, easeInElastic, easeInExpo, easeInOut, easeInOutBack, easeInOutBounce, easeInOutCirc, easeInOutCubic, easeInOutElastic, easeInOutExpo, easeInOutQuad, easeInOutQuart, easeInOutQuint, easeInOutSine, easeInQuad, easeInQuart, easeInQuint, easeInSine, easeOut, easeOutBack, easeOutBounce, easeOutCirc, easeOutCubic, easeOutElastic, easeOutExpo, easeOutQuad, easeOutQuart, easeOutQuint, easeOutSine, editAnchorsAction, ellipsePath, enumerateAnchors, fillInPoseFrame, fillToBoundsFrame, findNodeShape, findShapeInk, findShapeSilhouette, fitTextPose, fitToBounds, fitZoom, flattenCubic, flattenCubicWithArcLen, flattenQuadratic, flattenQuadraticWithArcLen, focused, forEachCoalesced, freeform, gateLayer, gesturing, getAlpha01, getImageBitmap, getNodeShapes, getScratch, getStylusData, gradientForBounds, gradientGeometry, guideSnapStrategy, hexToRgba, hitAffordanceRegions, hitAnchor, hitRotationHandle, hovering, hoveringSelected, imageStatus, inferredNodeProperties, inferredNodeRouting, insertAction, isDebugEnabled, isEditableTarget, isPatternSpec, lassoSelectAction, layoutMarkdown, lerpColorArray, lerpOklab, lerpOklch, linePath, linear, liveScope, makeViewportZoomAction, matchAlignment, matchesKeyBinding, meanScale, measureText, measureTextBounds, measuredWidth, mergeAlphaFromPrev, mergeContributions, modeIn, modeIs, modeNot, modifierHeld, momentum, moveAction, multiActive, nearest, nearestWithin, nestedHitTester, never, nodeHasFlag, none, normalizeHex, not, nurbs, oklabToOklch, oklabToSrgbU8, oklchToOklab, openFilePicker, or, parseColor, parseColorToRgba255, parseDebugFlags, pathContainsPoint, pathContainsPolygon, pathContainsRect, pathDistanceToPoint, pathDivide, pathExclude, pathFromD, pathInPoseFrame, pathInWorld, pathIntersect, pathIntersectsPolygon, pathIntersectsRect, pathOriginProjection, pathPoseDescriptor, pathSubtract, pathToAnchors, pathUnion, pickTopMostHit, pinchZoomAction, planPixelRender, pointInPath, pointInRotatedRect, pointInTextPose, polygonFromPoints, poseRotationOf, pressureToWidth, pxExtent, rainbowVertexColors, rebuildOp, rectCorners, rectPath, registerNodeShape, registerOpFactory, regularPolygonPath, renderLabel, renderSceneToCanvas, renderSceneToPixels, resizeAction, resolveColor, resolveDeviceProfile, resolveFillPattern, resolvePatternSpec, resolveSkeleton, resolveVisibility, rgbaToHex, rotateAction, rotateAroundAABBCenter, rotatePathAround, rotatePoint, rotatedRectCorners, rotationDegreesUnit, rotationHandle, roundToCell, runsToDom, sampleGradientStops, sampleTrack, scaleDelta, scalePathToBounds, sceneFromJSON, sceneNodeClientRect, sceneToAdapter, scopeBindings, scratchKey, selectFromLasso, selectionAtLeast, selectionEmpty, selectionIs, setFlagOverRange, setScratch, shapeCoversPoint, snap, snapPoint, solidVertexColors, spiro, splitPathByLine, splitSubpaths, springPose, springVertexColors, srgbU8ToOklab, staggerVertexColors, starPath, startThresholdDrag, styleAtRange, subscribeImageReady, textCommand, textLineBoxes, tileGrid, toHex8, transformPath, translatePath, translatePolygonInPlace, translatePoseViaDescriptor, tweenPose, tweenVertexColors, unionBounds, unionBoundsPath, useAlign, useAnimator, useArrayAdapter, useAutoCenter, useBooleans, useBooleansAdapter, useCanvasFocus, useCanvasSize, useDecayLoop, useDeviceProfile, useDistribute, useDragGesture, useDragHandle, useDragRadial, useDragRect, useDropZone, useEllipseTool, useEyedropperTool, useGestureDispatcher, useGridCellHover, useGuides, useHandTool, useHandleDrag, useHoverTracking, useImageTool, useKeybindings, useLassoTool, useLineTool, usePenTool, usePencilTool, usePinchGesture, usePinchZoomTool, usePointerStylus, usePolygonTool, usePublishSelection, useRectTool, useResizePolicy, useRotateTool, useScene, useSceneAdapter, useSceneTextEdit, useSelectTool, useSelectionContext, useSimulation, useSliceDep, useStandardActions, useStarTool, useTextEdit, useTextTool, useTools, useVelocityTracker, useViewAnimation, useViewTween, useZoom, viewportDragPanAction, viewportZoomAction, viewportsAt, when, withAlpha01, withCoord, withGradientKind, withinPxBox, withinPxRadius, worldEditToStorage, zoomAt, zoomAtLeast };
|
|
10659
|
+
export { ANCHOR_HIT_BASE_PX, Action, type ActionShortcut, ActionsProp, ActionsProviderIfRoot, ActionsRegistry, Affordance, AffordanceBinding, AffordanceHit, AffordanceRegion, type AffordanceRegionHit, type AlignAdapter, type AlignAnchor, type AlignBounds, type AlignBoundsProjection, type AlignEdge, type AlignMatchResult, type AlignMoveArgs, type AlignmentBehaviorBase, type AnchorHit, type AnchorScratch, type AnchorState, type AnimateOnSetPoseOptions, AnimationHandle, Animator, AnyTool, AreaSelectAdapter, type ArrayAdapter, type ArrayAdapterConfig, BUILTIN_MARKERS, BUNDLE_TOOLS, BindingScope, BooleansAdapter, Bounds, BoundsConstraint, type BuildChromeCtxArgs, BuiltinShapeToolId, type BuiltinToolId, type BuiltinToolOptions, COARSE_TARGET_SCALE, CURVE_REPS, type CanvasExtensionApi, type CanvasFocusReturn, type CanvasHelpers, type CanvasProps, type CanvasSelectionMode, type CanvasSize, type CanvasSizeSnapshot, type CanvasSurfaceHelpers, CanvasView, type CanvasViewHelpers, type CanvasViewProps, type CaretIndexAtOpts, type CellHighlightLayerOpts, ChromeCtx, ChromeId, ChromeState, type ClampBounds, ClipboardSnapshot, type CoalescedCtx, type ColorInterpolate, ColorOverrideRegistry, type ColorSpace, CommonAffordanceScratch, type ComposeSelectionPoseOpts, type ComputeFitViewOptions, Condition, ContentHandlerEntry, Contribution, type CornerResizeAffordanceOptions, type CornerResizeScratch, type CreateChildrenLayerOpts, type CreateParallaxLayerOpts, type CreatePathEditingOverlayLayerOptions, type CreatePathLayerOpts, type CreatePenPreviewLayerOptions, type CreateTextLayerOpts, type CreateViewResolverOpts, type CreateViewportLayerOpts, CropIcon, CursorCoordsHud, type CursorCoordsHudProps, type CurveRepKind, type CurveRepresentation, type CustomLayerEntry, type CycleHandle, type CycleVertexColorsOptions, DEFAULT_ALPHA_DECAY, DEFAULT_ALPHA_MIN, DEFAULT_DEBUG_STROKES, DEFAULT_DEBUG_THEME, DEFAULT_DEVICE_PROFILE, DEFAULT_FILL_COLOR, DEFAULT_FLATTEN_TOLERANCE, DEFAULT_GUIDE_TOLERANCE_PX, DEFAULT_HANDLE_SIZE, DEFAULT_PALETTE, DEFAULT_ROTATION_HANDLE_DISTANCE, DEFAULT_SHAPE_FILL, DEFAULT_STROKE_COLOR, DEFAULT_VELOCITY_DECAY, DebugConfig, DebugSink, DebugSnapshot, DebugStrokes, DebugTheme, type DecayLoopConfig, type DefaultTextData, DepRegistryProviderIfRoot, DepSchema, type DeriveAlignmentGuidesOptions, DetectedDeviceFacts, DeviceProfile, DeviceProfileProvider, type DeviceProfileProviderProps, Dims, type Discriminator, Dispatcher, type DistributeAdapter, type DistributeAxis, type DistributeMode, DivideIcon, type DragGestureController, type DragGestureCtx, type DragGestureEndCtx, type DragGesturePhase, type DragGesturePoint, type DragHandleOptions, type DragPayload, type DragRadialController, type DragRadialCtx, type DragRadialEndCtx, type DragRadialPoint, type DragRadialState, type DragRectBounds, type DragRectController, type DragRectCtx, type DragRectEndCtx, type DragRectPoint, DrawCommand, type DropZoneOptions, EASINGS, EasingFn, type EasingName, Eligibility, type EligibilityState, EllipseIcon, ExcludeIcon, EyedropperIcon, FALLBACK_FIT_VIEW, type FillPoseBox, type FitTextPoseOptions, type FlagKey, type FreeformOptions, GHOST_STROKE, type GateLayerOptions, GeometryProjection, type GesturePreviewSource, type GestureSource, type GridLayerOpts, type GridSlotConfig, Guide, type GuideSnapOptions, type GuidesLayerOpts, HANDLE_BASE_PX, HandIcon, type InertiaConfig as HandToolInertiaConfig, type HandleDragPoint, type HeadlessCanvasLike, HotkeyTrigger, IDENTITY_JOINT, type IconProps, ImageIcon, type ImageNodeData, type ImageStatus, type IndicatorStyle, InsertAdapter, InsertBehavior, InsertExtras, type InsertNodeFactory, type InsertOp, type InsertOverlayStyle, IntersectIcon, type Joint, type JointTransform, type LabelOptions, LassoHitMode, LassoIcon, LassoSelectAdapter, LassoSelectBehavior, LayerEnumerableAdapter, LayerHit, type LayerSlotValue, type LayersMap, LayoutSnap, LayoutStrategy, type LifecycleAnimation, LineIcon, type LinePoint, MIXED, MOVE_ANCHORS, type MarkerCtx, type MarkerEntry, type MarkerPaint, type MarkerSite, type MarkerSiteRequest, Mat3$1 as Mat3, MinimapCanvas, type MinimapCanvasProps, type MinimapFit, type Mixed, ModifierState, type MomentumOptions, MoveAdapter, MoveBehavior, type NestedHitOpts, type NestedHitTester, type NodeClientRect, NodeId, type NodeInk, type NodeInkCtx, type NodeOverlayFrame, type NodePaintCtx, type NodeProperties, type NodePropertiesEntry, type NodeRouting, type NodeRoutingEntry, type NodeShapeEntry, type NodeSilhouetteCtx, OngoingOverlay, type OpenFilePickerOptions, OrderedAdapter, OriginProjection, type OverlayPoint, OverlayPosition, PATH_ANCHOR_CHROME_ID, type PaintBindContext, type PaintKind, type PaintKindEditorProps, type PaintKindEntry, type PaintProgram, type PanBounds, type ParallaxOpts, Path, type PathAnchor, type PathAnchorAffordanceOptions, PathBuilder, PathDrawCommand, type PathEditingOverlayStyle, PathFillRule, type PathInWorldPose, type PenAnchor, PenIcon, type PenPreviewStyle, type PenScratch, type PenSubpath, PencilIcon, type PencilPoint, PickHud, type PickHudProps, type PickTopMostHitAdapter, type PinchZoomOptions, type PinchZoomToolOpts, type PixelRenderPlan, type PointInPathOptions, type PointInTextPoseOpts, PointSnapBehavior, PointerProviderIfRoot, type PointerSample, type PointerStylusState, PolygonIcon, PolygonPath, type PolygonPoint, type Pose, PoseProjection, type PoseRotation, type PressureToWidthOptions, type Pt, RECT_ALIGN_PROJECTION, ROTATION_HANDLE_BASE_PX, type RangeStyle, type RasterImage, RectIcon, RectPath, RectPose, type RegisterNodeShapeOptions, RegisteredOp, RenderLayer, type RenderSceneToCanvasArgs, type RenderSceneToPixelsArgs, type ReorderDirection, ResizeAdapter, ResizeAnchor, ResizePose, type ResolvableView, RotateAdapter, RotateBehavior, type RotateGeometry, RotatedPose, type RotationAffordanceOptions, type RotationHandle, type RotationScratch, Rule, RuleCtx, type RunStylePatch, SPRING_PRESETS, SampledTrack, type ScalarOrXY, Scene, SceneAdapter, type SceneAdapterSelection, SceneCanvas, type SceneCanvasAdapter, type SceneCanvasApi, type SceneCanvasHit, type SceneCanvasProps, Node$1 as SceneNode, type SceneNodeClientRectOpts, SceneRegistry, type SceneSlotConfig, type SceneToAdapterOptions, SceneViewCanvas, type SceneViewCanvasProps, type SceneViewDrawOne, ScopedBinding, type ScratchKey, type ScratchStore, type SelectAdapter, type SelectFromLassoOptions, SelectIcon, SelectionApi, SelectionContextProvider, SelectionContextProviderIfRoot, type SelectionContextValue, type SelectionHandleStyle, type SelectionHandlesLayerOpts, type SelectionOutlineLayerOpts, type SelectionOverlayLayerOpts, type SelectionOverlaySlotConfig, SerializedScene, type SetFlagResult, type SetPathFields, ShaderProgramHandle, type ShapeCoversPointOptions, type SharedAnchor, type Simulation, type SimulationForce, type SimulationNode, type Skeleton, SliceDep, type SnapPattern, type SnapPointOptions, SnapStrategy, type SplitByLineOptions, type SpringPoseOptions, SpringPreset, SpringPresetName, type SpringVertexColorsOptions, type StaggerVertexColorsOptions, type StandardSlotConfig, type StandardSlotName, StarIcon, type StarPoint, type StartEditOptions, type StyleKey, type StylusData, SubtractIcon, SvgIngestOptions, TOOL_PREF_KINDS, type TextEditScreenPose, type TextEditSelection, TextIcon, type ThresholdDragHandle, type ThresholdDragOptions, type TileGridOptions, type TilePatternOpts, Tool, type ToolBundle, ToolDef, ToolKeybinding, type ToolPref, type ToolPrefBoolean, type ToolPrefBooleanControl, type ToolPrefColor, type ToolPrefCustom, type ToolPrefEnum, type ToolPrefEnumControl, type ToolPrefEnumEncoding, type ToolPrefGroup, type ToolPrefKind, type ToolPrefLeaf, type ToolPrefNumber, type ToolPrefNumberControl, type ToolPrefNumberUnit, type ToolPrefObject, type ToolPrefPaint, type ToolPrefString, type ToolPrefStringControl, type ToolsApi, type TweenPoseOptions, type TweenVertexColorsOptions, UnionIcon, UnitSystem, UnitValue, UnknownIcon, type UseAlignOptions, type UseAlignReturn, UseAnimatorOptions, type UseArrayAdapterOptions, type UseBooleansOptions, type UseBooleansReturn, type UseCanvasFocusOptions, type UseDistributeOptions, type UseDistributeReturn, type UseDragGestureOptions, type UseDragRadialOptions, type UseDragRectOptions, type UseEyedropperToolOptions, type UseGestureDispatcherOptions, type UseGridCellHoverOptions, type UseGridCellHoverReturn, type UseGuidesReturn, type UseHandToolOptions, type UseHandleDragOptions, type UseHandleDragReturn, type UseHoverTrackingArgs, type UseImageToolOptions, type UseKeybindingsOptions, type UseLassoSelectOptions, type UseLassoToolOptions, UseMoveOptions, type UseNodeOverlayFrameOptions, type UsePenToolOptions, type UsePointerStylusOptions, type UsePolygonToolOptions, UseResizeOptions, type UseResizePolicyOptions, type UseRotateOptions, type UseRotateToolOptions, UseSceneOptions, type UseSceneTextEditOptions, type UseSceneTextEditReturn, type UseSceneTrivialOptions, type UseSelectToolOptions, UseSelectionOptions, type UseSimulationOptions, type UseStandardActionsOptions, type UseStarToolOptions, type UseTextEditOptions, type UseTextEditReturn, type UseToolsOptions, type UseZoomOptions, type UseZoomReturn, VERSION, type Vec2, VertexColorChannel, View, ViewAnimationOptions, type ViewRect, type ViewResolver, type ViewTarget, ViewTransform, type ViewportConfig, ViewportDims, type ViewportLayer, ViewportToolDef, type ViewportZoomAnimateOptions, type ViewportZoomOptions, VisibilityRules, type VisibleRaf, type VisibleRafOptions, type VisibleRafTarget, WeaselProvider, type WheelInput, type WheelState, ZoomBound, type ZoomBounds, type ZoomClampOpts, ZoomFactor, _resetMarkersForTests, _resetPaintKindsForTests, aabbCenter, actionIs, actionShortcuts, alignDeltaFor, alignInsertBehavior, alignMoveBehavior, alignResizeBehavior, always, and, animateLifecycle, animateOnSetPose, annulusSemiAxes, applyOpsTo, applyStyleToRange, areaSelectAction, arrayAdapter, asPaint, axisAlignedBounds, bezierCubic, bezierQuadratic, blendPoses, boundsOfPath, buildChromeCtx, buildSceneViewCommands, canBringForward, canHover, canSendBackward, capabilityAll, capabilityIn, capabilityIs, capabilityNot, caretIndexAt, cellAt, charOffsetToDomPosition, clampView, clearSelectionAction, clientToCanvas, cloneAction, coarsePointer, composeAffordanceLayer, composePath, composeSelectionPose, computeFitView, computeFitViewport, computeIndicatorCommand, computeWheelAction, cond, constrainTo45, containedThenNearest, countPathAnchors, createCellHighlightLayer, createChildrenLayer, createCornerResizeAffordance, createDebugOverlayLayer, createDebugSink, createDeleteOp, createGridLayer, createGuidesLayer, createHistory, createInsertOp, createMoveToIndexOp, createNodeProperties, createNodeRouting, createParallaxLayer, createPathAnchorAffordances, createPathEditingOverlayLayer, createPathLayer, createPenPreviewLayer, createReorderOp, createReparentOp, createRotationAffordance, createScene, createSelectionHandlesLayer, createSelectionOutlineLayer, createSelectionOverlayLayer, createSetDataOp, createSetLayerOp, createSetPathOp, createSetSelectionOp, createSetTextOp, createTextLayer, createTilePattern, createTransformOp, createViewResolver, createViewportLayer, cycleVertexColors, decomposePath, defaultCommitAdapter, defaultDrawOne, defaultLabelTextRenderer, defaultNodeProperties, defaultNodeRouting, defaultVisibilityRules, defineTool, defineViewportTool, deleteScratch, deriveAlignmentGuides, deriveParallaxView, dispatchApplyBatch, dlog, domPositionToCharOffset, domToRuns, dwarn, easeIn, easeInBack, easeInBounce, easeInCirc, easeInCubic, easeInElastic, easeInExpo, easeInOut, easeInOutBack, easeInOutBounce, easeInOutCirc, easeInOutCubic, easeInOutElastic, easeInOutExpo, easeInOutQuad, easeInOutQuart, easeInOutQuint, easeInOutSine, easeInQuad, easeInQuart, easeInQuint, easeInSine, easeOut, easeOutBack, easeOutBounce, easeOutCirc, easeOutCubic, easeOutElastic, easeOutExpo, easeOutQuad, easeOutQuart, easeOutQuint, easeOutSine, editAnchorsAction, ellipsePath, enumerateAnchors, fillInPoseFrame, fillToBoundsFrame, findNodeShape, findShapeInk, findShapeSilhouette, fitTextPose, fitToBounds, fitZoom, flattenCubic, flattenCubicWithArcLen, flattenQuadratic, flattenQuadraticWithArcLen, focused, forEachCoalesced, freeform, gateLayer, gesturing, getAlpha01, getImageBitmap, getMarker, getNodeShapes, getPaintKind, getScratch, getStylusData, gradientForBounds, gradientGeometry, guideSnapStrategy, hexToRgba, hitAffordanceRegions, hitAnchor, hitRotationHandle, hovering, hoveringSelected, imageStatus, inferredNodeProperties, inferredNodeRouting, insertAction, interpolateView, isBuiltinToolPref, isDebugEnabled, isEditableTarget, isGradientFill, isPatternSpec, keySpecShortcut, lassoSelectAction, lerpColorArray, lerpOklab, lerpOklch, linePath, linear, listMarkers, listPaintKinds, liveScope, makePinchZoomAction, makeViewportZoomAction, markerDrawCommands, markerInset, markerKeyOf, markerSites, matchAlignment, matchesKeyBinding, meanScale, mergeAlphaFromPrev, mergeContributions, modeIn, modeIs, modeNot, modifierHeld, momentum, moveAction, multiActive, nearest, nearestWithin, nestedHitTester, never, nodeHasFlag, none, normalizeHex, not, nurbs, oklabToOklch, oklabToSrgbU8, oklchToOklab, openFilePicker, or, paintAlpha, paintKindOf, paintWithAlpha, paintWithColor, parseColor, parseColorToRgba255, parseDebugFlags, pathContainsPoint, pathContainsPolygon, pathContainsRect, pathDistanceToPoint, pathDivide, pathExclude, pathFromD, pathInPoseFrame, pathInWorld, pathIntersect, pathIntersectsPolygon, pathIntersectsRect, pathOriginProjection, pathPoseDescriptor, pathSubtract, pathToAnchors, pathUnion, pickTopMostHit, pinchZoomAction, planPixelRender, pointInPath, pointInRotatedRect, pointInTextPose, polygonFromPoints, poseRotationOf, pressureToWidth, pxExtent, rainbowVertexColors, rebuildOp, rectCorners, rectPath, registerMarker, registerNodeShape, registerOpFactory, registerPaintKind, registeredOpNames, regularPolygonPath, renderLabel, renderSceneToCanvas, renderSceneToPixels, resizeAction, resolveColor, resolveDeviceProfile, resolveFillPattern, resolveMarkerSize, resolvePatternSpec, resolveSkeleton, resolveVisibility, rgbaToHex, rotateAction, rotateAroundAABBCenter, rotatePathAround, rotatePoint, rotatedRectCorners, rotationDegreesUnit, rotationHandle, roundToCell, runsToDom, sampleGradientStops, sampleTrack, scaleDelta, scalePathToBounds, sceneFromJSON, sceneNodeClientRect, sceneSelectionStore, sceneToAdapter, scopeBindings, scratchKey, selectFromLasso, selectionAtLeast, selectionEmpty, selectionIs, setFlagOverRange, setScratch, shapeCoversPoint, snap, snapPoint, solid, solidVertexColors, spiro, splitPathByLine, splitSubpaths, springPose, springVertexColors, srgbU8ToOklab, staggerVertexColors, starPath, startThresholdDrag, strokeInsets, strokeOf, strokeWith, styleAtRange, subscribeImageReady, textCommand, textCommandFromRuns, tileGrid, toHex8, transformPath, translatePath, translatePolygonInPlace, translatePoseViaDescriptor, trimPolyline, tweenPose, tweenVertexColors, unionAABB, unionBounds, unionBoundsPath, useAlign, useAnimator, useArrayAdapter, useAutoCenter, useBooleans, useBooleansAdapter, useCanvasFocus, useCanvasSize, useDecayLoop, useDeviceProfile, useDistribute, useDragGesture, useDragHandle, useDragRadial, useDragRect, useDropZone, useEllipseTool, useEyedropperTool, useGestureDispatcher, useGridCellHover, useGuides, useHandTool, useHandleDrag, useHoverTracking, useImageTool, useKeybindings, useLassoTool, useLineTool, useNodeOverlayFrame, usePenTool, usePencilTool, usePinchGesture, usePinchZoomTool, usePointerStylus, usePolygonTool, usePublishSelection, useRectTool, useResizePolicy, useRotateTool, useScene, useSceneAdapter, useSceneTextEdit, useSelectTool, useSelectionContext, useSimulation, useSliceDep, useStandardActions, useStarTool, useTextEdit, useTextTool, useTools, useVelocityTracker, useVisibleRaf, useZoom, viewportDragPanAction, viewportZoomAction, viewportsAt, visualBoundsViaDescriptor, when, withAlpha01, withCoord, withGradientKind, withinPxBox, withinPxRadius, worldEditToStorage, zoomAt, zoomAtLeast };
|