@weasel-js/core 0.5.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 +381 -0
- package/LICENSE +21 -0
- package/README.md +144 -0
- package/dist/DrawCommand-Dl0bXNfS.d.ts +500 -0
- package/dist/chunk-775XXAHR.js +216 -0
- package/dist/chunk-775XXAHR.js.map +1 -0
- package/dist/chunk-7V6JEOXE.js +27754 -0
- package/dist/chunk-7V6JEOXE.js.map +1 -0
- package/dist/chunk-AM6ARSPN.js +517 -0
- package/dist/chunk-AM6ARSPN.js.map +1 -0
- package/dist/chunk-BGGZ4CVF.js +248 -0
- package/dist/chunk-BGGZ4CVF.js.map +1 -0
- package/dist/chunk-BHVYVFGV.js +29 -0
- package/dist/chunk-BHVYVFGV.js.map +1 -0
- package/dist/chunk-CQNKCG34.js +831 -0
- package/dist/chunk-CQNKCG34.js.map +1 -0
- package/dist/chunk-GVCNT7UH.js +47 -0
- package/dist/chunk-GVCNT7UH.js.map +1 -0
- package/dist/chunk-PZ5AY32C.js +9 -0
- package/dist/chunk-PZ5AY32C.js.map +1 -0
- package/dist/chunk-UGFFCMQP.js +28 -0
- package/dist/chunk-UGFFCMQP.js.map +1 -0
- package/dist/chunk-VOVKONXA.js +103 -0
- package/dist/chunk-VOVKONXA.js.map +1 -0
- package/dist/chunk-Y52N27PF.js +39 -0
- package/dist/chunk-Y52N27PF.js.map +1 -0
- package/dist/clipboard.d.ts +91 -0
- package/dist/clipboard.js +6 -0
- package/dist/clipboard.js.map +1 -0
- package/dist/clone.d.ts +8 -0
- package/dist/clone.js +6 -0
- package/dist/clone.js.map +1 -0
- package/dist/fitViewToBounds-evGsnR8Q.d.ts +62 -0
- package/dist/grid-Cf87knjU.d.ts +153 -0
- package/dist/index-DZBYMsHI.d.ts +1555 -0
- package/dist/index.css +121 -0
- package/dist/index.css.map +1 -0
- package/dist/index.d.ts +10200 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/insert.d.ts +33 -0
- package/dist/insert.js +81 -0
- package/dist/insert.js.map +1 -0
- package/dist/move.d.ts +69 -0
- package/dist/move.js +145 -0
- package/dist/move.js.map +1 -0
- package/dist/options-BPPBWMa7.d.ts +64 -0
- package/dist/patterns-builtin.d.ts +55 -0
- package/dist/patterns-builtin.js +100 -0
- package/dist/patterns-builtin.js.map +1 -0
- package/dist/pointSnapToGrid-D7s7QmOF.d.ts +185 -0
- package/dist/registerFont-CP-wCsrz.d.ts +109 -0
- package/dist/registerTexture-BzHTLhD9.d.ts +25 -0
- package/dist/renderer.css +121 -0
- package/dist/renderer.css.map +1 -0
- package/dist/renderer.d.ts +376 -0
- package/dist/renderer.js +13 -0
- package/dist/renderer.js.map +1 -0
- package/dist/resize.d.ts +78 -0
- package/dist/resize.js +5 -0
- package/dist/resize.js.map +1 -0
- package/dist/routing.css +35 -0
- package/dist/routing.css.map +1 -0
- package/dist/routing.d.ts +14 -0
- package/dist/routing.js +4 -0
- package/dist/routing.js.map +1 -0
- package/dist/types-B6MMiodD.d.ts +59 -0
- package/dist/types-BJ8_cyT7.d.ts +130 -0
- package/dist/types-B_-khFM0.d.ts +331 -0
- package/dist/types-BjUi2vA-.d.ts +355 -0
- package/dist/types-Cpb4hii1.d.ts +445 -0
- package/dist/types-D2tTKEU0.d.ts +18 -0
- package/dist/view-DSQgxBJB.d.ts +63 -0
- package/package.json +96 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export { ALWAYS, ActionDisabledReason, ActionsProvider, ActionsProviderIfRoot, ActiveToolContextProvider, ActiveToolContextProviderIfRoot, BUNDLE_TOOLS, CURVE_REPS, ColorOverrideRegistry, CropIcon, CursorCoordsHud, DEFAULT_ALPHA_DECAY, DEFAULT_ALPHA_MIN, DEFAULT_DEBUG_THEME, DEFAULT_FILL_COLOR, DEFAULT_HANDLE_SIZE, DEFAULT_PALETTE, DEFAULT_ROTATION_HANDLE_DISTANCE, DEFAULT_STROKE_COLOR, DEFAULT_TEXT_STYLE, DEFAULT_VELOCITY_DECAY, DepRegistryProvider, DepRegistryProviderIfRoot, DivideIcon, EASINGS, EllipseIcon, ExcludeIcon, EyedropperIcon, FALLBACK_FIT_VIEW, GHOST_STROKE, HandIcon, IDENTITY_POSE_COMPOSITION, IntersectIcon, KIT_SHAPE_KINDS, LassoIcon, LineIcon, MOVE_ANCHORS, MinimapCanvas, NEVER, PenIcon, PencilIcon, PickHud, PointerProviderIfRoot, PolygonIcon, RECT_ALIGN_PROJECTION, RectIcon, SPRING_PRESETS, SceneCanvas, SceneViewCanvas, SelectIcon, SelectionContextProvider, SelectionContextProviderIfRoot, StarIcon, SubtractIcon, TextIcon, UnionIcon, UnknownIcon, WeaselProvider, aabbCenter, actionIs, alignDeltaFor, alignInsertBehavior, alignMoveBehavior, alignResizeBehavior, alignedStrokeRect, always, and, animateLifecycle, animateOnSetPose, applyBooleanOp, applyHitExistingGate, areaSelectAction, arrayAdapter, asNodeId, bezierCubic, bezierQuadratic, buildChromeCtx, buildRuleCtx, buildSceneViewCommands, canBringForward, canSendBackward, capabilityAll, capabilityIn, capabilityIs, capabilityNot, caretIndexAt, cellAt, charOffsetToDomPosition, clampView, clearSelectionAction, clientToCanvas, cloneAction, composeAffordanceLayer, composePath, composeRectPose, composeSelectionPose, composeWorldPose, computeFitView, computeIndicatorCommand, computeWheelAction, cond, constrainTo45, containedThenNearest, countPathAnchors, createAnchorEditOverlayLayer, createCellHighlightLayer, createChildrenLayer, createCornerResizeAffordance, createDebugOverlayLayer, createDebugSink, createDispatcher, createGridLayer, createGuidesLayer, createHistory, createMarkdownRenderer, createMoveToIndexOp, createNodeProperties, createNodeRouting, createParallaxLayer, createPathEditingOverlayLayer, createPathLayer, createPenPreviewLayer, createReorderOp, createRotationAffordance, createScene, createSelectionHandlesLayer, createSelectionOutlineLayer, createSelectionOverlayLayer, createSetDataOp, createSetLayerOp, createSetPathOp, createSetTextOp, createTextLayer, createToolsDispatcher, createViewportLayer, cycleVertexColors, decomposePath, decomposeRectPose, defaultCommitAdapter, defaultDrawOne, defaultLabelTextRenderer, defaultNodeProperties, defaultNodeRouting, defaultVisibilityRules, defineTool, deriveAlignmentGuides, deriveParallaxView, domPositionToCharOffset, domToRuns, drawLayers, 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, enterTextEditAction, enumerateAnchors, evaluate, evaluateEnabled, findNodeShape, findShapeSilhouette, fitTextPose, fitToBounds, fitViewToBounds, fitZoom, focused, fontString, forEachCoalesced, freeform, gateLayer, gesturing, getAlpha01, getImageBitmap, getNodeShapes, getStylusData, hexToRgba, hitAnchor, hitRotationHandle, hovering, hoveringSelected, imageStatus, inferredNodeProperties, inferredNodeRouting, insertAction, isCanvasFont, isEditableTarget, lassoSelectAction, layoutMarkdown, lerpColorArray, lerpOklab, lerpOklch, linear, makeViewportZoomAction, markdownToRuns, matchAlignment, matchesKeyBinding, measureText, measureTextBounds, mergeAlphaFromPrev, modeIn, modeIs, modeNot, modifierHeld, momentum, moveAction, multiActive, nearest, nearestWithin, nestedHitTester, never, 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, pathSubtract, pathToAnchors, pathUnion, pickTopMostHit, pinchZoomAction, planPixelRender, pointInRotatedRect, pointInTextPose, poseRotationOf, pressureToWidth, rainbowVertexColors, rebaseLocalPose, rectCorners, registerCanvasFont, registerContentHandler, registerFont, registerNodeShape, renderLabel, renderSceneToCanvas, renderSceneToPixels, resizeAction, resolveColor, resolveRuns, resolveTextStyle, resolveVisibility, rgbaToHex, rotateAction, rotateAroundAABBCenter, rotatePathAround, rotatePoint, rotatedRectCorners, rotationDegreesUnit, rotationHandle, roundToCell, runsToDom, runsToMarkdown, runsToPlainText, sceneFromJSON, sceneNodeClientRect, sceneToAdapter, screenToWorld, selectFromLasso, selectFromMarquee, selectionAtLeast, selectionEmpty, selectionIs, sliceAction, snapPoint, solidVertexColors, spiro, splitPathByLine, splitSubpaths, springPose, springVertexColors, srgbU8ToOklab, staggerVertexColors, startThresholdDrag, subscribeGlyphReady, subscribeImageReady, textCommand, tileGrid, toHex8, toRuns, translatePoseViaDescriptor, translateRectPose, tweenPose, tweenVertexColors, unionBounds, unionBoundsPath, unregisterCanvasFont, useAction, useActionsRegistry, useActiveToolContext, useAlign, useAnimator, useArrayAdapter, useAutoCenter, useBooleans, useBooleansAdapter, useCanvasFocus, useCanvasSize, useDecayLoop, useDepRegistry, useDepSource, useDistribute, useDragGesture, useDragHandle, useDragRadial, useDragRect, useDropZone, useEllipseTool, useEyedropperTool, useGestureDispatcher, useGridCellHover, useGuides, useHandTool, useHandleDrag, useHoverTracking, useImageTool, useInsertTool, useKeybindings, useLassoTool, useLineTool, useNestedSelectTool, useOptionalActiveToolContext, useOptionalDepRegistry, usePenTool, usePencilTool, usePinchGesture, usePinchZoomTool, usePointerGestures, usePointerStylus, usePolygonTool, usePublishSelection, useRectTool, useResizePolicy, useRotateTool, useScene, useSceneAdapter, useSceneTextEdit, useSelectTool, useSelection, useSelectionContext, useSimulation, useSliceDep, useStandardActions, useStarTool, useTextEdit, useTextTool, useTools, useVelocityTracker, useViewAnimation, useViewTween, useZoom, verticalAlignOffset, viewToMat3, viewToTransform, viewportDragPanAction, viewportZoomAction, when, withAlpha01, withCoord, worldEditToStorage, worldPoseLookup, worldToScreen, zoomAt, zoomAtLeast } from './chunk-7V6JEOXE.js';
|
|
2
|
+
export { routing_exports as routing } from './chunk-AM6ARSPN.js';
|
|
3
|
+
export { createReparentOp, createTransformOp, deleteScratch, getScratch, scratchKey, setScratch, snap } from './chunk-VOVKONXA.js';
|
|
4
|
+
export { CORNER_ANCHORS, cornerPoint, cornerResizeHandles, hitCornerHandle, pointSnapToGrid } from './chunk-BGGZ4CVF.js';
|
|
5
|
+
export { DEFAULT_FLATTEN_TOLERANCE, DEFAULT_GUIDE_TOLERANCE_PX, IMPERIAL_INCHES, METRIC_MM, PATH_C, PATH_CMD_LENGTHS, PATH_L, PATH_M, PATH_Q, PATH_Z, PIXELS, PathBuilder, RECT_ORIGIN_PROJECTION, RECT_POSE_DESCRIPTOR, ROTATED_POSE_DESCRIPTOR, boundsOfPath, ellipsePath, flattenCubic, flattenCubicWithArcLen, flattenQuadratic, flattenQuadraticWithArcLen, formatUnit, gridSnapStrategy, guideSnapStrategy, linePath, meanScale, pathPoseDescriptor, pointInPath, pointToGridCell, polygonFromPoints, rectPath, regularPolygonPath, resolveUnit, scalePathToBounds, starPath, transformPath, translatePath, translatePolygonInPlace } from './chunk-CQNKCG34.js';
|
|
6
|
+
export { PointerContextProvider, WEASEL_CLIPBOARD_MIME, WEASEL_CLIPBOARD_MIME_WEB, applyOpsTo, buildWeaselClipboardText, dispatchApplyBatch, dlog, dwarn, embedWeaselMetadataInSvg, extractWeaselClipboardFromSvg, isDebugEnabled, parseWeaselClipboardText, sniffWeaselClipboardText, useClipboardOps, usePointerContext } from './chunk-775XXAHR.js';
|
|
7
|
+
export { cloneByAltDrag } from './chunk-UGFFCMQP.js';
|
|
8
|
+
export { createSetSelectionOp } from './chunk-BHVYVFGV.js';
|
|
9
|
+
export { createDeleteOp, createInsertOp, rebuildOp, registerOpFactory } from './chunk-GVCNT7UH.js';
|
|
10
|
+
export { createTilePattern } from './chunk-Y52N27PF.js';
|
|
11
|
+
import './chunk-PZ5AY32C.js';
|
|
12
|
+
//# sourceMappingURL=index.js.map
|
|
13
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
|
package/dist/insert.d.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export { U as UseInsertOptions } from './options-BPPBWMa7.js';
|
|
2
|
+
import { M as ModifierState, I as InsertBehavior } from './types-BjUi2vA-.js';
|
|
3
|
+
import { G as Guide } from './types-D2tTKEU0.js';
|
|
4
|
+
import { V as View } from './view-DSQgxBJB.js';
|
|
5
|
+
import '@weasel-js/history';
|
|
6
|
+
import './types-B_-khFM0.js';
|
|
7
|
+
|
|
8
|
+
type ModKey$1 = keyof ModifierState;
|
|
9
|
+
declare function snapToGrid<TPose>(args: {
|
|
10
|
+
spacing: number;
|
|
11
|
+
bypassKey?: ModKey$1;
|
|
12
|
+
}): InsertBehavior<TPose>;
|
|
13
|
+
|
|
14
|
+
type ModKey = keyof ModifierState;
|
|
15
|
+
/** Options for the insert-flavored `snapToGuides`. */
|
|
16
|
+
interface SnapToGuidesInsertArgs {
|
|
17
|
+
/** Stable getter into the live guide list (typically from `useGuides`). */
|
|
18
|
+
getGuides: () => readonly Guide[];
|
|
19
|
+
/** Snap tolerance (screen px when `getView` is set, world units otherwise). */
|
|
20
|
+
tolerance?: number;
|
|
21
|
+
/** Read the active view; required for screen-pixel tolerance. */
|
|
22
|
+
getView?: () => View;
|
|
23
|
+
/** Modifier key that bypasses snapping while held. */
|
|
24
|
+
bypassKey?: ModKey;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Insert behavior that snaps the start anchor (on gesture start) and the
|
|
28
|
+
* live current point (during drag) to the nearest guide on each axis when
|
|
29
|
+
* within `tolerance`. Pair with `useGuides` and `createGuidesLayer`.
|
|
30
|
+
*/
|
|
31
|
+
declare function snapToGuides<TPose>(args: SnapToGuidesInsertArgs): InsertBehavior<TPose>;
|
|
32
|
+
|
|
33
|
+
export { snapToGrid, snapToGuides };
|
package/dist/insert.js
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { DEFAULT_GUIDE_TOLERANCE_PX, meanScale } from './chunk-CQNKCG34.js';
|
|
2
|
+
import './chunk-PZ5AY32C.js';
|
|
3
|
+
|
|
4
|
+
// src/interactions/actions/insert/behaviors/snapToGrid.ts
|
|
5
|
+
function snapToGrid(args) {
|
|
6
|
+
const { spacing, bypassKey } = args;
|
|
7
|
+
const round = (v) => Math.round(v / spacing) * spacing;
|
|
8
|
+
return {
|
|
9
|
+
onStart(ctx) {
|
|
10
|
+
if (bypassKey && ctx.modifiers[bypassKey]) return;
|
|
11
|
+
const id = ctx.draggedIds[0];
|
|
12
|
+
const o = ctx.origin.get(id);
|
|
13
|
+
if (!o) return;
|
|
14
|
+
ctx.origin.set(id, { x: round(o.x), y: round(o.y) });
|
|
15
|
+
},
|
|
16
|
+
onMove(ctx, { current }) {
|
|
17
|
+
if (bypassKey && ctx.modifiers[bypassKey]) return;
|
|
18
|
+
return { current: { x: round(current.x), y: round(current.y) } };
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// src/interactions/actions/insert/behaviors/snapToGuides.ts
|
|
24
|
+
function snapPoint(p, guides, worldTolerance) {
|
|
25
|
+
let bestDx = 0;
|
|
26
|
+
let bestAbsDx = Infinity;
|
|
27
|
+
let bestDy = 0;
|
|
28
|
+
let bestAbsDy = Infinity;
|
|
29
|
+
for (const g of guides) {
|
|
30
|
+
if (g.axis === "x") {
|
|
31
|
+
const d = g.offset - p.x;
|
|
32
|
+
const ad = Math.abs(d);
|
|
33
|
+
if (ad <= worldTolerance && ad < bestAbsDx) {
|
|
34
|
+
bestAbsDx = ad;
|
|
35
|
+
bestDx = d;
|
|
36
|
+
}
|
|
37
|
+
} else {
|
|
38
|
+
const d = g.offset - p.y;
|
|
39
|
+
const ad = Math.abs(d);
|
|
40
|
+
if (ad <= worldTolerance && ad < bestAbsDy) {
|
|
41
|
+
bestAbsDy = ad;
|
|
42
|
+
bestDy = d;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
if (bestAbsDx === Infinity && bestAbsDy === Infinity) return null;
|
|
47
|
+
const dx = bestAbsDx === Infinity ? 0 : bestDx;
|
|
48
|
+
const dy = bestAbsDy === Infinity ? 0 : bestDy;
|
|
49
|
+
if (dx === 0 && dy === 0) return null;
|
|
50
|
+
return { x: p.x + dx, y: p.y + dy };
|
|
51
|
+
}
|
|
52
|
+
function snapToGuides(args) {
|
|
53
|
+
const tolerance = args.tolerance ?? DEFAULT_GUIDE_TOLERANCE_PX;
|
|
54
|
+
const getView = args.getView;
|
|
55
|
+
const bypassKey = args.bypassKey;
|
|
56
|
+
const computeWorldTol = () => getView ? tolerance / Math.max(1e-9, meanScale(getView().scale)) : tolerance;
|
|
57
|
+
return {
|
|
58
|
+
onStart(ctx) {
|
|
59
|
+
if (bypassKey && ctx.modifiers[bypassKey]) return;
|
|
60
|
+
const guides = args.getGuides();
|
|
61
|
+
if (guides.length === 0) return;
|
|
62
|
+
const id = ctx.draggedIds[0];
|
|
63
|
+
const o = ctx.origin.get(id);
|
|
64
|
+
if (!o) return;
|
|
65
|
+
const snapped = snapPoint(o, guides, computeWorldTol());
|
|
66
|
+
if (snapped) ctx.origin.set(id, snapped);
|
|
67
|
+
},
|
|
68
|
+
onMove(ctx, { current }) {
|
|
69
|
+
if (bypassKey && ctx.modifiers[bypassKey]) return;
|
|
70
|
+
const guides = args.getGuides();
|
|
71
|
+
if (guides.length === 0) return;
|
|
72
|
+
const snapped = snapPoint(current, guides, computeWorldTol());
|
|
73
|
+
if (!snapped) return;
|
|
74
|
+
return { current: snapped };
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export { snapToGrid, snapToGuides };
|
|
80
|
+
//# sourceMappingURL=insert.js.map
|
|
81
|
+
//# sourceMappingURL=insert.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/interactions/actions/insert/behaviors/snapToGrid.ts","../src/interactions/actions/insert/behaviors/snapToGuides.ts"],"names":[],"mappings":"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","file":"insert.js","sourcesContent":["import type {\n InsertBehavior,\n InsertPoint,\n ModifierState,\n} from '../../../gestures/types';\n\ntype ModKey = keyof ModifierState;\n\nexport function snapToGrid<TPose>(args: {\n spacing: number;\n bypassKey?: ModKey;\n}): InsertBehavior<TPose> {\n const { spacing, bypassKey } = args;\n const round = (v: number) => Math.round(v / spacing) * spacing;\n return {\n onStart(ctx) {\n if (bypassKey && ctx.modifiers[bypassKey]) return;\n const id = ctx.draggedIds[0];\n const o = ctx.origin.get(id) as unknown as InsertPoint | undefined;\n if (!o) return;\n ctx.origin.set(id, { x: round(o.x), y: round(o.y) } as unknown as TPose);\n },\n onMove(ctx, { current }) {\n if (bypassKey && ctx.modifiers[bypassKey]) return;\n return { current: { x: round(current.x), y: round(current.y) } };\n },\n };\n}\n","import type {\n InsertBehavior,\n InsertPoint,\n ModifierState,\n} from '../../../gestures/types';\nimport type { Guide } from 'features/guides/types';\nimport type { View } from 'core/viewport/view';\nimport { meanScale } from 'core/viewport/meanScale';\nimport { DEFAULT_GUIDE_TOLERANCE_PX } from '../../../gestures/shared/strategies/guides';\n\ntype ModKey = keyof ModifierState;\n\n/** Options for the insert-flavored `snapToGuides`. */\nexport interface SnapToGuidesInsertArgs {\n /** Stable getter into the live guide list (typically from `useGuides`). */\n getGuides: () => readonly Guide[];\n /** Snap tolerance (screen px when `getView` is set, world units otherwise). */\n tolerance?: number;\n /** Read the active view; required for screen-pixel tolerance. */\n getView?: () => View;\n /** Modifier key that bypasses snapping while held. */\n bypassKey?: ModKey;\n}\n\nfunction snapPoint(\n p: InsertPoint,\n guides: readonly Guide[],\n worldTolerance: number,\n): InsertPoint | null {\n let bestDx = 0;\n let bestAbsDx = Infinity;\n let bestDy = 0;\n let bestAbsDy = Infinity;\n for (const g of guides) {\n if (g.axis === 'x') {\n const d = g.offset - p.x;\n const ad = Math.abs(d);\n if (ad <= worldTolerance && ad < bestAbsDx) {\n bestAbsDx = ad;\n bestDx = d;\n }\n } else {\n const d = g.offset - p.y;\n const ad = Math.abs(d);\n if (ad <= worldTolerance && ad < bestAbsDy) {\n bestAbsDy = ad;\n bestDy = d;\n }\n }\n }\n if (bestAbsDx === Infinity && bestAbsDy === Infinity) return null;\n const dx = bestAbsDx === Infinity ? 0 : bestDx;\n const dy = bestAbsDy === Infinity ? 0 : bestDy;\n if (dx === 0 && dy === 0) return null;\n return { x: p.x + dx, y: p.y + dy };\n}\n\n/**\n * Insert behavior that snaps the start anchor (on gesture start) and the\n * live current point (during drag) to the nearest guide on each axis when\n * within `tolerance`. Pair with `useGuides` and `createGuidesLayer`.\n */\nexport function snapToGuides<TPose>(\n args: SnapToGuidesInsertArgs,\n): InsertBehavior<TPose> {\n const tolerance = args.tolerance ?? DEFAULT_GUIDE_TOLERANCE_PX;\n const getView = args.getView;\n const bypassKey = args.bypassKey;\n\n const computeWorldTol = (): number =>\n getView ? tolerance / Math.max(1e-9, meanScale(getView().scale)) : tolerance;\n\n return {\n onStart(ctx) {\n if (bypassKey && ctx.modifiers[bypassKey]) return;\n const guides = args.getGuides();\n if (guides.length === 0) return;\n const id = ctx.draggedIds[0];\n const o = ctx.origin.get(id) as unknown as InsertPoint | undefined;\n if (!o) return;\n const snapped = snapPoint(o, guides, computeWorldTol());\n if (snapped) ctx.origin.set(id, snapped as unknown as TPose);\n },\n onMove(ctx, { current }) {\n if (bypassKey && ctx.modifiers[bypassKey]) return;\n const guides = args.getGuides();\n if (guides.length === 0) return;\n const snapped = snapPoint(current, guides, computeWorldTol());\n if (!snapped) return;\n return { current: snapped };\n },\n };\n}\n"]}
|
package/dist/move.d.ts
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { O as OriginProjection } from './grid-Cf87knjU.js';
|
|
2
|
+
export { U as UseMoveOptions } from './grid-Cf87knjU.js';
|
|
3
|
+
import { M as ModifierState, a as MoveBehavior } from './types-BjUi2vA-.js';
|
|
4
|
+
import { S as SnapTarget } from './types-B_-khFM0.js';
|
|
5
|
+
import { G as Guide } from './types-D2tTKEU0.js';
|
|
6
|
+
import { V as View } from './view-DSQgxBJB.js';
|
|
7
|
+
import './types-BJ8_cyT7.js';
|
|
8
|
+
import '@weasel-js/history';
|
|
9
|
+
|
|
10
|
+
type ModKey$1 = keyof ModifierState;
|
|
11
|
+
declare function snapToGrid<TPose extends {
|
|
12
|
+
x: number;
|
|
13
|
+
y: number;
|
|
14
|
+
}>(args: {
|
|
15
|
+
spacing: number;
|
|
16
|
+
bypassKey?: ModKey$1;
|
|
17
|
+
}): MoveBehavior<TPose>;
|
|
18
|
+
|
|
19
|
+
declare function snapToContainer<TPose>(args: {
|
|
20
|
+
dwellMs: number;
|
|
21
|
+
findTarget: (draggedId: string, worldX: number, worldY: number) => SnapTarget<TPose> | null;
|
|
22
|
+
isInstant?: (target: SnapTarget<TPose>) => boolean;
|
|
23
|
+
moveLabel?: string;
|
|
24
|
+
reparentLabel?: string;
|
|
25
|
+
}): MoveBehavior<TPose>;
|
|
26
|
+
|
|
27
|
+
declare function snapBackOrDelete<TPose extends {
|
|
28
|
+
x: number;
|
|
29
|
+
y: number;
|
|
30
|
+
}>(args: {
|
|
31
|
+
radius: number;
|
|
32
|
+
onFreeRelease: 'snap-back' | 'delete';
|
|
33
|
+
deleteLabel?: string;
|
|
34
|
+
}): MoveBehavior<TPose>;
|
|
35
|
+
declare function snapBackOrDelete<TPose>(args: {
|
|
36
|
+
radius: number;
|
|
37
|
+
onFreeRelease: 'snap-back' | 'delete';
|
|
38
|
+
deleteLabel?: string;
|
|
39
|
+
origin: OriginProjection<TPose>;
|
|
40
|
+
}): MoveBehavior<TPose>;
|
|
41
|
+
|
|
42
|
+
type ModKey = keyof ModifierState;
|
|
43
|
+
/** Options for the move-flavored `snapToGuides`. */
|
|
44
|
+
interface SnapToGuidesMoveArgs<TPose> {
|
|
45
|
+
/** Stable getter into the live guide list (typically from `useGuides`). */
|
|
46
|
+
getGuides: () => readonly Guide[];
|
|
47
|
+
/** Snap tolerance (screen px when `getView` is set, world units otherwise). */
|
|
48
|
+
tolerance?: number;
|
|
49
|
+
/** Read the active view; required for screen-pixel tolerance. */
|
|
50
|
+
getView?: () => View;
|
|
51
|
+
/** Modifier key that bypasses snapping while held. */
|
|
52
|
+
bypassKey?: ModKey;
|
|
53
|
+
/** Origin projection for non-rect TPose (e.g. Path). */
|
|
54
|
+
origin?: OriginProjection<TPose>;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Move behavior that snaps the dragged pose's origin to the nearest world-space
|
|
58
|
+
* guide line within `tolerance`. Closest-guide-per-axis wins; the two axes are
|
|
59
|
+
* considered independently. Pair with `useGuides` and `createGuidesLayer`.
|
|
60
|
+
*/
|
|
61
|
+
declare function snapToGuides<TPose extends {
|
|
62
|
+
x: number;
|
|
63
|
+
y: number;
|
|
64
|
+
}>(args: Omit<SnapToGuidesMoveArgs<TPose>, 'origin'>): MoveBehavior<TPose>;
|
|
65
|
+
declare function snapToGuides<TPose>(args: SnapToGuidesMoveArgs<TPose> & {
|
|
66
|
+
origin: OriginProjection<TPose>;
|
|
67
|
+
}): MoveBehavior<TPose>;
|
|
68
|
+
|
|
69
|
+
export { snapBackOrDelete, snapToContainer, snapToGrid, snapToGuides };
|
package/dist/move.js
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { scratchKey, snap, createTransformOp, createReparentOp, getScratch, setScratch } from './chunk-VOVKONXA.js';
|
|
2
|
+
import { gridSnapStrategy, RECT_ORIGIN_PROJECTION, guideSnapStrategy } from './chunk-CQNKCG34.js';
|
|
3
|
+
import { createDeleteOp } from './chunk-GVCNT7UH.js';
|
|
4
|
+
import './chunk-PZ5AY32C.js';
|
|
5
|
+
|
|
6
|
+
// src/interactions/actions/move/behaviors/snapToGrid.ts
|
|
7
|
+
function snapToGrid(args) {
|
|
8
|
+
return snap(gridSnapStrategy(args.spacing), { bypassKey: args.bypassKey });
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// src/interactions/actions/move/behaviors/snapToContainer.ts
|
|
12
|
+
var STATE = scratchKey("snapToContainer");
|
|
13
|
+
function getState(ctx) {
|
|
14
|
+
let s = getScratch(ctx.scratch, STATE);
|
|
15
|
+
if (!s) {
|
|
16
|
+
s = { pendingTargetId: null, pendingTimer: null, committedSnap: null };
|
|
17
|
+
setScratch(ctx.scratch, STATE, s);
|
|
18
|
+
}
|
|
19
|
+
return s;
|
|
20
|
+
}
|
|
21
|
+
function clearTimer(s) {
|
|
22
|
+
if (s.pendingTimer !== null) {
|
|
23
|
+
clearTimeout(s.pendingTimer);
|
|
24
|
+
s.pendingTimer = null;
|
|
25
|
+
}
|
|
26
|
+
s.pendingTargetId = null;
|
|
27
|
+
}
|
|
28
|
+
function snapToContainer(args) {
|
|
29
|
+
const { dwellMs, findTarget, isInstant, moveLabel = "Move", reparentLabel = "Move and reparent" } = args;
|
|
30
|
+
return {
|
|
31
|
+
onMove(ctx, _proposed) {
|
|
32
|
+
const s = getState(ctx);
|
|
33
|
+
const target = findTarget(ctx.draggedIds[0], ctx.pointer.worldX, ctx.pointer.worldY);
|
|
34
|
+
if (s.committedSnap) {
|
|
35
|
+
if (target && target.parentId === s.committedSnap.parentId) {
|
|
36
|
+
return { pose: s.committedSnap.slotPose, snap: s.committedSnap };
|
|
37
|
+
}
|
|
38
|
+
s.committedSnap = null;
|
|
39
|
+
}
|
|
40
|
+
if (!target) {
|
|
41
|
+
clearTimer(s);
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
if (isInstant?.(target)) {
|
|
45
|
+
clearTimer(s);
|
|
46
|
+
s.committedSnap = target;
|
|
47
|
+
return { pose: target.slotPose, snap: target };
|
|
48
|
+
}
|
|
49
|
+
if (s.pendingTargetId === target.parentId) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
clearTimer(s);
|
|
53
|
+
s.pendingTargetId = target.parentId;
|
|
54
|
+
s.pendingTimer = setTimeout(() => {
|
|
55
|
+
s.committedSnap = target;
|
|
56
|
+
s.pendingTimer = null;
|
|
57
|
+
}, dwellMs);
|
|
58
|
+
return;
|
|
59
|
+
},
|
|
60
|
+
onEnd(ctx) {
|
|
61
|
+
const s = getState(ctx);
|
|
62
|
+
clearTimer(s);
|
|
63
|
+
const snap2 = s.committedSnap ?? ctx.snap;
|
|
64
|
+
if (!snap2) return;
|
|
65
|
+
const draggedId = ctx.draggedIds[0];
|
|
66
|
+
const oldParent = ctx.adapter.getParent?.(draggedId) ?? null;
|
|
67
|
+
const fromPose = ctx.origin.get(draggedId);
|
|
68
|
+
const ops = [
|
|
69
|
+
createTransformOp({
|
|
70
|
+
id: draggedId,
|
|
71
|
+
from: fromPose,
|
|
72
|
+
to: snap2.slotPose,
|
|
73
|
+
label: moveLabel
|
|
74
|
+
})
|
|
75
|
+
];
|
|
76
|
+
if (oldParent !== snap2.parentId) {
|
|
77
|
+
ops.push(createReparentOp({
|
|
78
|
+
id: draggedId,
|
|
79
|
+
fromParentId: oldParent,
|
|
80
|
+
toParentId: snap2.parentId,
|
|
81
|
+
label: reparentLabel
|
|
82
|
+
}));
|
|
83
|
+
}
|
|
84
|
+
return ops;
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// src/interactions/actions/move/behaviors/snapBackOrDelete.ts
|
|
90
|
+
var SNAPSHOTS = scratchKey("snapBackOrDelete.snapshots");
|
|
91
|
+
var INDEXES = scratchKey("snapBackOrDelete.indexes");
|
|
92
|
+
function snapBackOrDelete(args) {
|
|
93
|
+
const { radius, onFreeRelease, deleteLabel = "Delete" } = args;
|
|
94
|
+
const proj = args.origin ?? RECT_ORIGIN_PROJECTION;
|
|
95
|
+
const r2 = radius * radius;
|
|
96
|
+
return {
|
|
97
|
+
onStart(ctx) {
|
|
98
|
+
const snapshots = /* @__PURE__ */ new Map();
|
|
99
|
+
const indexes = /* @__PURE__ */ new Map();
|
|
100
|
+
const nodes = ctx.adapter.getNodes();
|
|
101
|
+
for (const id of ctx.draggedIds) {
|
|
102
|
+
const obj = ctx.adapter.getNode(id) ?? { id };
|
|
103
|
+
snapshots.set(id, obj);
|
|
104
|
+
indexes.set(id, nodes.findIndex((n) => n.id === id));
|
|
105
|
+
}
|
|
106
|
+
setScratch(ctx.scratch, SNAPSHOTS, snapshots);
|
|
107
|
+
setScratch(ctx.scratch, INDEXES, indexes);
|
|
108
|
+
},
|
|
109
|
+
onEnd(ctx) {
|
|
110
|
+
if (ctx.snap) return;
|
|
111
|
+
const id = ctx.draggedIds[0];
|
|
112
|
+
const o0 = proj.getOrigin(ctx.origin.get(id));
|
|
113
|
+
const o1 = proj.getOrigin(ctx.current.get(id));
|
|
114
|
+
const dx = o1.x - o0.x;
|
|
115
|
+
const dy = o1.y - o0.y;
|
|
116
|
+
const within = dx * dx + dy * dy <= r2;
|
|
117
|
+
if (within) {
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
if (onFreeRelease === "delete") {
|
|
121
|
+
const snapshots = getScratch(ctx.scratch, SNAPSHOTS);
|
|
122
|
+
const indexes = getScratch(ctx.scratch, INDEXES);
|
|
123
|
+
const obj = snapshots?.get(id) ?? { id };
|
|
124
|
+
const index = indexes?.get(id) ?? -1;
|
|
125
|
+
const ops = [createDeleteOp({ node: obj, label: deleteLabel, index })];
|
|
126
|
+
return ops;
|
|
127
|
+
}
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// src/interactions/actions/move/behaviors/snapToGuides.ts
|
|
134
|
+
function snapToGuides(args) {
|
|
135
|
+
const strategy = guideSnapStrategy(args.getGuides, {
|
|
136
|
+
tolerance: args.tolerance,
|
|
137
|
+
getView: args.getView,
|
|
138
|
+
origin: args.origin
|
|
139
|
+
});
|
|
140
|
+
return snap(strategy, { bypassKey: args.bypassKey });
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
export { snapBackOrDelete, snapToContainer, snapToGrid, snapToGuides };
|
|
144
|
+
//# sourceMappingURL=move.js.map
|
|
145
|
+
//# sourceMappingURL=move.js.map
|
package/dist/move.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/interactions/actions/move/behaviors/snapToGrid.ts","../src/interactions/actions/move/behaviors/snapToContainer.ts","../src/interactions/actions/move/behaviors/snapBackOrDelete.ts","../src/interactions/actions/move/behaviors/snapToGuides.ts"],"names":["snap"],"mappings":"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","file":"move.js","sourcesContent":["import type { ModifierState, MoveBehavior } from '../../../gestures/types';\nimport { snap } from '../../../gestures/shared/snap';\nimport { gridSnapStrategy } from '../../../gestures/shared/strategies/grid';\n\ntype ModKey = keyof ModifierState;\n\nexport function snapToGrid<TPose extends { x: number; y: number }>(args: {\n spacing: number;\n bypassKey?: ModKey;\n}): MoveBehavior<TPose> {\n return snap(gridSnapStrategy<TPose>(args.spacing), { bypassKey: args.bypassKey });\n}\n","import { createTransformOp } from 'core/ops/transform';\nimport { createReparentOp } from 'core/ops/reparent';\nimport type { Op } from 'core/ops/types';\nimport type { SnapTarget } from 'core/adapters/types';\nimport type { MoveBehavior, GestureContext } from '../../../gestures/types';\nimport { scratchKey, getScratch, setScratch } from '../../../scratchKey';\n\ninterface SnapState<TPose> {\n pendingTargetId: string | null;\n pendingTimer: ReturnType<typeof setTimeout> | null;\n committedSnap: SnapTarget<TPose> | null;\n}\n\n// The slot is generic over TPose; we keep the unknown-pose key at module\n// scope and project it through `as` at the read site (each consumer call\n// of `snapToContainer<TPose>` is the only writer of its own SnapState\n// instance, so the cast is safe at runtime).\nconst STATE = scratchKey<SnapState<unknown>>('snapToContainer');\n\nfunction getState<TPose>(ctx: GestureContext<TPose>): SnapState<TPose> {\n let s = getScratch(ctx.scratch, STATE) as SnapState<TPose> | undefined;\n if (!s) {\n s = { pendingTargetId: null, pendingTimer: null, committedSnap: null };\n setScratch(ctx.scratch, STATE, s as SnapState<unknown>);\n }\n return s;\n}\n\nfunction clearTimer<TPose>(s: SnapState<TPose>) {\n if (s.pendingTimer !== null) {\n clearTimeout(s.pendingTimer);\n s.pendingTimer = null;\n }\n s.pendingTargetId = null;\n}\n\nexport function snapToContainer<TPose>(args: {\n dwellMs: number;\n findTarget: (\n draggedId: string,\n worldX: number,\n worldY: number,\n ) => SnapTarget<TPose> | null;\n isInstant?: (target: SnapTarget<TPose>) => boolean;\n moveLabel?: string;\n reparentLabel?: string;\n}): MoveBehavior<TPose> {\n const { dwellMs, findTarget, isInstant, moveLabel = 'Move', reparentLabel = 'Move and reparent' } = args;\n\n return {\n onMove(ctx, _proposed) {\n const s = getState<TPose>(ctx);\n const target = findTarget(ctx.draggedIds[0], ctx.pointer.worldX, ctx.pointer.worldY);\n\n if (s.committedSnap) {\n if (target && target.parentId === s.committedSnap.parentId) {\n return { pose: s.committedSnap.slotPose, snap: s.committedSnap };\n }\n s.committedSnap = null;\n }\n\n if (!target) {\n clearTimer(s);\n return;\n }\n\n if (isInstant?.(target)) {\n clearTimer(s);\n s.committedSnap = target;\n return { pose: target.slotPose, snap: target };\n }\n\n if (s.pendingTargetId === target.parentId) {\n return;\n }\n clearTimer(s);\n s.pendingTargetId = target.parentId;\n s.pendingTimer = setTimeout(() => {\n s.committedSnap = target;\n s.pendingTimer = null;\n }, dwellMs);\n return;\n },\n\n onEnd(ctx) {\n const s = getState<TPose>(ctx);\n clearTimer(s);\n const snap = s.committedSnap ?? ctx.snap;\n if (!snap) return;\n const draggedId = ctx.draggedIds[0];\n const oldParent = ctx.adapter.getParent?.(draggedId) ?? null;\n const fromPose = ctx.origin.get(draggedId)!;\n const ops: Op[] = [\n createTransformOp<TPose>({\n id: draggedId,\n from: fromPose,\n to: snap.slotPose,\n label: moveLabel,\n }),\n ];\n if (oldParent !== snap.parentId) {\n ops.push(createReparentOp({\n id: draggedId,\n fromParentId: oldParent,\n toParentId: snap.parentId,\n label: reparentLabel,\n }));\n }\n return ops;\n },\n };\n}\n","import { createDeleteOp } from 'core/ops/delete';\nimport type { Op } from 'core/ops/types';\nimport type { MoveBehavior } from '../../../gestures/types';\nimport {\n RECT_ORIGIN_PROJECTION,\n type OriginProjection,\n} from '../../../gestures/shared/strategies';\nimport { scratchKey, getScratch, setScratch } from '../../../scratchKey';\n\nconst SNAPSHOTS = scratchKey<Map<string, { id: string }>>('snapBackOrDelete.snapshots');\nconst INDEXES = scratchKey<Map<string, number>>('snapBackOrDelete.indexes');\n\nexport function snapBackOrDelete<TPose extends { x: number; y: number }>(args: {\n radius: number;\n onFreeRelease: 'snap-back' | 'delete';\n deleteLabel?: string;\n}): MoveBehavior<TPose>;\nexport function snapBackOrDelete<TPose>(args: {\n radius: number;\n onFreeRelease: 'snap-back' | 'delete';\n deleteLabel?: string;\n origin: OriginProjection<TPose>;\n}): MoveBehavior<TPose>;\nexport function snapBackOrDelete<TPose>(args: {\n radius: number;\n onFreeRelease: 'snap-back' | 'delete';\n deleteLabel?: string;\n origin?: OriginProjection<TPose>;\n}): MoveBehavior<TPose> {\n const { radius, onFreeRelease, deleteLabel = 'Delete' } = args;\n const proj: OriginProjection<TPose> =\n args.origin ?? (RECT_ORIGIN_PROJECTION as unknown as OriginProjection<TPose>);\n const r2 = radius * radius;\n\n return {\n onStart(ctx) {\n // Snapshot the dragged objects + their z-indexes at gesture start so\n // delete can undo with paint order intact.\n const snapshots = new Map<string, { id: string }>();\n const indexes = new Map<string, number>();\n const nodes = ctx.adapter.getNodes();\n for (const id of ctx.draggedIds) {\n const obj = ctx.adapter.getNode(id) ?? { id };\n snapshots.set(id, obj);\n indexes.set(id, nodes.findIndex((n) => n.id === id));\n }\n setScratch(ctx.scratch, SNAPSHOTS, snapshots);\n setScratch(ctx.scratch, INDEXES, indexes);\n },\n\n onEnd(ctx) {\n if (ctx.snap) return;\n const id = ctx.draggedIds[0];\n const o0 = proj.getOrigin(ctx.origin.get(id)!);\n const o1 = proj.getOrigin(ctx.current.get(id)!);\n const dx = o1.x - o0.x;\n const dy = o1.y - o0.y;\n const within = dx * dx + dy * dy <= r2;\n if (within) {\n return null;\n }\n if (onFreeRelease === 'delete') {\n const snapshots = getScratch(ctx.scratch, SNAPSHOTS);\n const indexes = getScratch(ctx.scratch, INDEXES);\n const obj = snapshots?.get(id) ?? { id };\n const index = indexes?.get(id) ?? -1;\n const ops: Op[] = [createDeleteOp({ node: obj, label: deleteLabel, index })];\n return ops;\n }\n return;\n },\n };\n}\n","import type { ModifierState, MoveBehavior } from '../../../gestures/types';\nimport type { Guide } from 'features/guides/types';\nimport type { View } from 'core/viewport/view';\nimport type { OriginProjection } from '../../../gestures/shared/strategies/grid';\nimport { snap } from '../../../gestures/shared/snap';\nimport { guideSnapStrategy } from '../../../gestures/shared/strategies/guides';\n\ntype ModKey = keyof ModifierState;\n\n/** Options for the move-flavored `snapToGuides`. */\nexport interface SnapToGuidesMoveArgs<TPose> {\n /** Stable getter into the live guide list (typically from `useGuides`). */\n getGuides: () => readonly Guide[];\n /** Snap tolerance (screen px when `getView` is set, world units otherwise). */\n tolerance?: number;\n /** Read the active view; required for screen-pixel tolerance. */\n getView?: () => View;\n /** Modifier key that bypasses snapping while held. */\n bypassKey?: ModKey;\n /** Origin projection for non-rect TPose (e.g. Path). */\n origin?: OriginProjection<TPose>;\n}\n\n/**\n * Move behavior that snaps the dragged pose's origin to the nearest world-space\n * guide line within `tolerance`. Closest-guide-per-axis wins; the two axes are\n * considered independently. Pair with `useGuides` and `createGuidesLayer`.\n */\nexport function snapToGuides<TPose extends { x: number; y: number }>(\n args: Omit<SnapToGuidesMoveArgs<TPose>, 'origin'>,\n): MoveBehavior<TPose>;\nexport function snapToGuides<TPose>(\n args: SnapToGuidesMoveArgs<TPose> & { origin: OriginProjection<TPose> },\n): MoveBehavior<TPose>;\nexport function snapToGuides<TPose>(\n args: SnapToGuidesMoveArgs<TPose>,\n): MoveBehavior<TPose> {\n const strategy = guideSnapStrategy<TPose>(args.getGuides, {\n tolerance: args.tolerance,\n getView: args.getView,\n origin: args.origin as OriginProjection<TPose>,\n });\n return snap(strategy, { bypassKey: args.bypassKey });\n}\n"]}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { Op } from '@weasel-js/history';
|
|
2
|
+
import { I as InsertBehavior, R as ResizePose } from './types-BjUi2vA-.js';
|
|
3
|
+
|
|
4
|
+
/** Option surface for the `insert` action.
|
|
5
|
+
*
|
|
6
|
+
* Lives in a sibling file (not `insert.ts`) so the type contract stays stable
|
|
7
|
+
* even after the legacy `useInsert` hook is gone.
|
|
8
|
+
* Consumers should import from here directly; `insert.ts` re-exports the
|
|
9
|
+
* same symbol for back-compat. */
|
|
10
|
+
|
|
11
|
+
interface UseInsertOptions<TPose, TNode extends {
|
|
12
|
+
id: string;
|
|
13
|
+
} = {
|
|
14
|
+
id: string;
|
|
15
|
+
}> {
|
|
16
|
+
behaviors?: InsertBehavior<TPose>[];
|
|
17
|
+
insertLabel?: string;
|
|
18
|
+
/** Reserved; insert is never transient in practice. Ignored. */
|
|
19
|
+
transient?: boolean;
|
|
20
|
+
/** Strictly-greater-than thresholds; bounds with width <= or height <= abort. Default { width: 0, height: 0 }. */
|
|
21
|
+
minBounds?: {
|
|
22
|
+
width: number;
|
|
23
|
+
height: number;
|
|
24
|
+
};
|
|
25
|
+
/** Construct the in-flight pose from the drag bounds. Defaults to the
|
|
26
|
+
* identity cast (treat bounds as TPose). Override for non-rect TPose
|
|
27
|
+
* (e.g. `(b) => rectPath(b)` or a polygon factory). */
|
|
28
|
+
posefromBounds?: (bounds: ResizePose) => TPose;
|
|
29
|
+
/** Click / sub-threshold-drag fallback. When provided, a release whose
|
|
30
|
+
* bounds fall <= minBounds calls `pointInsert(start)` instead of aborting.
|
|
31
|
+
* Returning null aborts. The created object is dispatched as an InsertOp
|
|
32
|
+
* under the same `insertLabel`. */
|
|
33
|
+
pointInsert?: (point: {
|
|
34
|
+
x: number;
|
|
35
|
+
y: number;
|
|
36
|
+
}) => TNode | null;
|
|
37
|
+
/** Drag-disabled mode. When true, every release routes to pointInsert(start)
|
|
38
|
+
* regardless of bounds — commitInsert is never called. Used by tool hooks
|
|
39
|
+
* that wire only pointer.onClick (no marquee). */
|
|
40
|
+
clickOnly?: boolean;
|
|
41
|
+
/** Override for op dispatch on commit. When set, this is called instead of
|
|
42
|
+
* `dispatchApplyBatch(adapter, ...)`. Tool hooks that synthesize an adapter
|
|
43
|
+
* but want commits to route through the active tool ctx's `applyOps`
|
|
44
|
+
* (for history integration) supply a function that reads from a ref
|
|
45
|
+
* captured on handler entry. Read fresh on every commit, so a ref-reader
|
|
46
|
+
* works without retriggering memos. */
|
|
47
|
+
applyOps?: (ops: Op[], label: string) => void;
|
|
48
|
+
onGestureStart?: () => void;
|
|
49
|
+
onGestureEnd?: (committed: boolean) => void;
|
|
50
|
+
/** Optional: snap world-space points to the active grid (or any other
|
|
51
|
+
* snap target). Applied to every coord the gesture ingests, so both the
|
|
52
|
+
* live marquee overlay and the committed bounds track the snapped
|
|
53
|
+
* values. When omitted, behavior is identical to today (identity
|
|
54
|
+
* passthrough). */
|
|
55
|
+
snapPoint?: (p: {
|
|
56
|
+
x: number;
|
|
57
|
+
y: number;
|
|
58
|
+
}) => {
|
|
59
|
+
x: number;
|
|
60
|
+
y: number;
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export type { UseInsertOptions as U };
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { T as TextureHandle } from './registerTexture-BzHTLhD9.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Built-in pattern factories — generic line/dot/scatter textures. Each
|
|
5
|
+
* returns a `TextureHandle` you can wrap in a `FillStyle` of
|
|
6
|
+
* `{ fill: 'pattern', pattern }` and pass to anything that accepts a `FillStyle`
|
|
7
|
+
* (`FillStyle`-aware layers, path fills, etc.).
|
|
8
|
+
* Imported from a subpath so consumers that ship their own catalog can
|
|
9
|
+
* avoid the bundle cost.
|
|
10
|
+
*
|
|
11
|
+
* All factories require an explicit `color` (and `bg` for `chunks`). No
|
|
12
|
+
* defaults are baked in — the caller's design system is the source of truth
|
|
13
|
+
* for palette decisions.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
/** Diagonal hatch (forward slash). */
|
|
17
|
+
interface HatchParams {
|
|
18
|
+
color: string;
|
|
19
|
+
size?: number;
|
|
20
|
+
lineWidth?: number;
|
|
21
|
+
}
|
|
22
|
+
declare function hatch(params: HatchParams): TextureHandle | null;
|
|
23
|
+
/** Diagonal hatch in both directions. */
|
|
24
|
+
interface CrosshatchParams {
|
|
25
|
+
color: string;
|
|
26
|
+
size?: number;
|
|
27
|
+
lineWidth?: number;
|
|
28
|
+
}
|
|
29
|
+
declare function crosshatch(params: CrosshatchParams): TextureHandle | null;
|
|
30
|
+
/** Regular grid of filled dots. */
|
|
31
|
+
interface DotsParams {
|
|
32
|
+
color: string;
|
|
33
|
+
size?: number;
|
|
34
|
+
radius?: number;
|
|
35
|
+
}
|
|
36
|
+
declare function dots(params: DotsParams): TextureHandle | null;
|
|
37
|
+
/**
|
|
38
|
+
* Random scatter of small ellipses on top of a solid background. Driven by a
|
|
39
|
+
* seeded PRNG so the same `seed` produces a deterministic tile.
|
|
40
|
+
*
|
|
41
|
+
* Note: the `bg` field is optional — omit it for a transparent background
|
|
42
|
+
* (the scatter shapes draw directly onto whatever sits beneath the overlay).
|
|
43
|
+
*/
|
|
44
|
+
interface ChunksParams {
|
|
45
|
+
color: string;
|
|
46
|
+
bg?: string;
|
|
47
|
+
size?: number;
|
|
48
|
+
/** Coverage: `chunks * chunkSize²` per `size²` tile. Range ~[0, 1]. */
|
|
49
|
+
density?: number;
|
|
50
|
+
chunkSize?: number;
|
|
51
|
+
seed?: number;
|
|
52
|
+
}
|
|
53
|
+
declare function chunks(params: ChunksParams): TextureHandle | null;
|
|
54
|
+
|
|
55
|
+
export { type ChunksParams, type CrosshatchParams, type DotsParams, type HatchParams, chunks, crosshatch, dots, hatch };
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { createTilePattern } from './chunk-Y52N27PF.js';
|
|
2
|
+
import './chunk-PZ5AY32C.js';
|
|
3
|
+
|
|
4
|
+
// src/features/patterns/patterns-builtin.ts
|
|
5
|
+
function hatch(params) {
|
|
6
|
+
const { color, size = 5, lineWidth = 1 } = params;
|
|
7
|
+
return createTilePattern({
|
|
8
|
+
size,
|
|
9
|
+
draw: (oc, s) => {
|
|
10
|
+
oc.strokeStyle = color;
|
|
11
|
+
oc.lineWidth = lineWidth;
|
|
12
|
+
oc.beginPath();
|
|
13
|
+
oc.moveTo(-1, s + 1);
|
|
14
|
+
oc.lineTo(s + 1, -1);
|
|
15
|
+
oc.moveTo(-1, 1);
|
|
16
|
+
oc.lineTo(1, -1);
|
|
17
|
+
oc.moveTo(s - 1, s + 1);
|
|
18
|
+
oc.lineTo(s + 1, s - 1);
|
|
19
|
+
oc.stroke();
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
function crosshatch(params) {
|
|
24
|
+
const { color, size = 6, lineWidth = 0.8 } = params;
|
|
25
|
+
return createTilePattern({
|
|
26
|
+
size,
|
|
27
|
+
draw: (oc, s) => {
|
|
28
|
+
oc.strokeStyle = color;
|
|
29
|
+
oc.lineWidth = lineWidth;
|
|
30
|
+
oc.beginPath();
|
|
31
|
+
oc.moveTo(-1, s + 1);
|
|
32
|
+
oc.lineTo(s + 1, -1);
|
|
33
|
+
oc.moveTo(-1, 1);
|
|
34
|
+
oc.lineTo(1, -1);
|
|
35
|
+
oc.moveTo(s - 1, s + 1);
|
|
36
|
+
oc.lineTo(s + 1, s - 1);
|
|
37
|
+
oc.moveTo(-1, -1);
|
|
38
|
+
oc.lineTo(s + 1, s + 1);
|
|
39
|
+
oc.moveTo(s - 1, -1);
|
|
40
|
+
oc.lineTo(s + 1, 1);
|
|
41
|
+
oc.moveTo(-1, s - 1);
|
|
42
|
+
oc.lineTo(1, s + 1);
|
|
43
|
+
oc.stroke();
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
function dots(params) {
|
|
48
|
+
const { color, size = 6, radius = 1 } = params;
|
|
49
|
+
return createTilePattern({
|
|
50
|
+
size,
|
|
51
|
+
draw: (oc, s) => {
|
|
52
|
+
oc.fillStyle = color;
|
|
53
|
+
oc.beginPath();
|
|
54
|
+
oc.arc(s / 2, s / 2, radius, 0, Math.PI * 2);
|
|
55
|
+
oc.fill();
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
function mulberry32(seed) {
|
|
60
|
+
let s = seed | 0;
|
|
61
|
+
return () => {
|
|
62
|
+
s = s + 1831565813 | 0;
|
|
63
|
+
let t = Math.imul(s ^ s >>> 15, 1 | s);
|
|
64
|
+
t = t + Math.imul(t ^ t >>> 7, 61 | t) ^ t;
|
|
65
|
+
return ((t ^ t >>> 14) >>> 0) / 4294967296;
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
function chunks(params) {
|
|
69
|
+
const { color, bg, size = 48, density = 0.35, chunkSize = 3, seed = 42 } = params;
|
|
70
|
+
return createTilePattern({
|
|
71
|
+
size,
|
|
72
|
+
draw: (oc, s) => {
|
|
73
|
+
if (bg !== void 0) {
|
|
74
|
+
oc.fillStyle = bg;
|
|
75
|
+
oc.fillRect(0, 0, s, s);
|
|
76
|
+
}
|
|
77
|
+
const rand = mulberry32(seed);
|
|
78
|
+
const count = Math.round(s * s * density / (chunkSize * chunkSize));
|
|
79
|
+
oc.fillStyle = color;
|
|
80
|
+
for (let i = 0; i < count; i++) {
|
|
81
|
+
const cx = rand() * s;
|
|
82
|
+
const cy = rand() * s;
|
|
83
|
+
const w = chunkSize * (0.5 + rand());
|
|
84
|
+
const h = chunkSize * (0.5 + rand());
|
|
85
|
+
const angle = rand() * Math.PI;
|
|
86
|
+
oc.save();
|
|
87
|
+
oc.translate(cx, cy);
|
|
88
|
+
oc.rotate(angle);
|
|
89
|
+
oc.beginPath();
|
|
90
|
+
oc.ellipse(0, 0, w / 2, h / 2, 0, 0, Math.PI * 2);
|
|
91
|
+
oc.fill();
|
|
92
|
+
oc.restore();
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export { chunks, crosshatch, dots, hatch };
|
|
99
|
+
//# sourceMappingURL=patterns-builtin.js.map
|
|
100
|
+
//# sourceMappingURL=patterns-builtin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/features/patterns/patterns-builtin.ts"],"names":[],"mappings":";;;;AAuBO,SAAS,MAAM,MAAA,EAA2C;AAC/D,EAAA,MAAM,EAAE,KAAA,EAAO,IAAA,GAAO,CAAA,EAAG,SAAA,GAAY,GAAE,GAAI,MAAA;AAC3C,EAAA,OAAO,iBAAA,CAAkB;AAAA,IACvB,IAAA;AAAA,IACA,IAAA,EAAM,CAAC,EAAA,EAAI,CAAA,KAAM;AACf,MAAA,EAAA,CAAG,WAAA,GAAc,KAAA;AACjB,MAAA,EAAA,CAAG,SAAA,GAAY,SAAA;AACf,MAAA,EAAA,CAAG,SAAA,EAAU;AACb,MAAA,EAAA,CAAG,MAAA,CAAO,EAAA,EAAI,CAAA,GAAI,CAAC,CAAA;AACnB,MAAA,EAAA,CAAG,MAAA,CAAO,CAAA,GAAI,CAAA,EAAG,EAAE,CAAA;AACnB,MAAA,EAAA,CAAG,MAAA,CAAO,IAAI,CAAC,CAAA;AACf,MAAA,EAAA,CAAG,MAAA,CAAO,GAAG,EAAE,CAAA;AACf,MAAA,EAAA,CAAG,MAAA,CAAO,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,CAAC,CAAA;AACtB,MAAA,EAAA,CAAG,MAAA,CAAO,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,CAAC,CAAA;AACtB,MAAA,EAAA,CAAG,MAAA,EAAO;AAAA,IACZ;AAAA,GACD,CAAA;AACH;AASO,SAAS,WAAW,MAAA,EAAgD;AACzE,EAAA,MAAM,EAAE,KAAA,EAAO,IAAA,GAAO,CAAA,EAAG,SAAA,GAAY,KAAI,GAAI,MAAA;AAC7C,EAAA,OAAO,iBAAA,CAAkB;AAAA,IACvB,IAAA;AAAA,IACA,IAAA,EAAM,CAAC,EAAA,EAAI,CAAA,KAAM;AACf,MAAA,EAAA,CAAG,WAAA,GAAc,KAAA;AACjB,MAAA,EAAA,CAAG,SAAA,GAAY,SAAA;AACf,MAAA,EAAA,CAAG,SAAA,EAAU;AAEb,MAAA,EAAA,CAAG,MAAA,CAAO,EAAA,EAAI,CAAA,GAAI,CAAC,CAAA;AACnB,MAAA,EAAA,CAAG,MAAA,CAAO,CAAA,GAAI,CAAA,EAAG,EAAE,CAAA;AACnB,MAAA,EAAA,CAAG,MAAA,CAAO,IAAI,CAAC,CAAA;AACf,MAAA,EAAA,CAAG,MAAA,CAAO,GAAG,EAAE,CAAA;AACf,MAAA,EAAA,CAAG,MAAA,CAAO,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,CAAC,CAAA;AACtB,MAAA,EAAA,CAAG,MAAA,CAAO,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,CAAC,CAAA;AAEtB,MAAA,EAAA,CAAG,MAAA,CAAO,IAAI,EAAE,CAAA;AAChB,MAAA,EAAA,CAAG,MAAA,CAAO,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,CAAC,CAAA;AACtB,MAAA,EAAA,CAAG,MAAA,CAAO,CAAA,GAAI,CAAA,EAAG,EAAE,CAAA;AACnB,MAAA,EAAA,CAAG,MAAA,CAAO,CAAA,GAAI,CAAA,EAAG,CAAC,CAAA;AAClB,MAAA,EAAA,CAAG,MAAA,CAAO,EAAA,EAAI,CAAA,GAAI,CAAC,CAAA;AACnB,MAAA,EAAA,CAAG,MAAA,CAAO,CAAA,EAAG,CAAA,GAAI,CAAC,CAAA;AAClB,MAAA,EAAA,CAAG,MAAA,EAAO;AAAA,IACZ;AAAA,GACD,CAAA;AACH;AASO,SAAS,KAAK,MAAA,EAA0C;AAC7D,EAAA,MAAM,EAAE,KAAA,EAAO,IAAA,GAAO,CAAA,EAAG,MAAA,GAAS,GAAE,GAAI,MAAA;AACxC,EAAA,OAAO,iBAAA,CAAkB;AAAA,IACvB,IAAA;AAAA,IACA,IAAA,EAAM,CAAC,EAAA,EAAI,CAAA,KAAM;AACf,MAAA,EAAA,CAAG,SAAA,GAAY,KAAA;AACf,MAAA,EAAA,CAAG,SAAA,EAAU;AACb,MAAA,EAAA,CAAG,GAAA,CAAI,IAAI,CAAA,EAAG,CAAA,GAAI,GAAG,MAAA,EAAQ,CAAA,EAAG,IAAA,CAAK,EAAA,GAAK,CAAC,CAAA;AAC3C,MAAA,EAAA,CAAG,IAAA,EAAK;AAAA,IACV;AAAA,GACD,CAAA;AACH;AAoBA,SAAS,WAAW,IAAA,EAA4B;AAC9C,EAAA,IAAI,IAAI,IAAA,GAAO,CAAA;AACf,EAAA,OAAO,MAAM;AACX,IAAA,CAAA,GAAK,IAAI,UAAA,GAAc,CAAA;AACvB,IAAA,IAAI,IAAI,IAAA,CAAK,IAAA,CAAK,IAAK,CAAA,KAAM,EAAA,EAAK,IAAI,CAAC,CAAA;AACvC,IAAA,CAAA,GAAK,CAAA,GAAI,KAAK,IAAA,CAAK,CAAA,GAAK,MAAM,CAAA,EAAI,EAAA,GAAK,CAAC,CAAA,GAAK,CAAA;AAC7C,IAAA,OAAA,CAAA,CAAS,CAAA,GAAK,CAAA,KAAM,EAAA,MAAS,CAAA,IAAK,UAAA;AAAA,EACpC,CAAA;AACF;AAEO,SAAS,OAAO,MAAA,EAA4C;AACjE,EAAA,MAAM,EAAE,KAAA,EAAO,EAAA,EAAI,IAAA,GAAO,EAAA,EAAI,OAAA,GAAU,IAAA,EAAM,SAAA,GAAY,CAAA,EAAG,IAAA,GAAO,EAAA,EAAG,GAAI,MAAA;AAC3E,EAAA,OAAO,iBAAA,CAAkB;AAAA,IACvB,IAAA;AAAA,IACA,IAAA,EAAM,CAAC,EAAA,EAAI,CAAA,KAAM;AACf,MAAA,IAAI,OAAO,MAAA,EAAW;AACpB,QAAA,EAAA,CAAG,SAAA,GAAY,EAAA;AACf,QAAA,EAAA,CAAG,QAAA,CAAS,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,CAAC,CAAA;AAAA,MACxB;AACA,MAAA,MAAM,IAAA,GAAO,WAAW,IAAI,CAAA;AAC5B,MAAA,MAAM,QAAQ,IAAA,CAAK,KAAA,CAAO,IAAI,CAAA,GAAI,OAAA,IAAY,YAAY,SAAA,CAAU,CAAA;AACpE,MAAA,EAAA,CAAG,SAAA,GAAY,KAAA;AACf,MAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,KAAA,EAAO,CAAA,EAAA,EAAK;AAC9B,QAAA,MAAM,EAAA,GAAK,MAAK,GAAI,CAAA;AACpB,QAAA,MAAM,EAAA,GAAK,MAAK,GAAI,CAAA;AACpB,QAAA,MAAM,CAAA,GAAI,SAAA,IAAa,GAAA,GAAM,IAAA,EAAK,CAAA;AAClC,QAAA,MAAM,CAAA,GAAI,SAAA,IAAa,GAAA,GAAM,IAAA,EAAK,CAAA;AAClC,QAAA,MAAM,KAAA,GAAQ,IAAA,EAAK,GAAI,IAAA,CAAK,EAAA;AAC5B,QAAA,EAAA,CAAG,IAAA,EAAK;AACR,QAAA,EAAA,CAAG,SAAA,CAAU,IAAI,EAAE,CAAA;AACnB,QAAA,EAAA,CAAG,OAAO,KAAK,CAAA;AACf,QAAA,EAAA,CAAG,SAAA,EAAU;AACb,QAAA,EAAA,CAAG,OAAA,CAAQ,CAAA,EAAG,CAAA,EAAG,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,IAAA,CAAK,EAAA,GAAK,CAAC,CAAA;AAChD,QAAA,EAAA,CAAG,IAAA,EAAK;AACR,QAAA,EAAA,CAAG,OAAA,EAAQ;AAAA,MACb;AAAA,IACF;AAAA,GACD,CAAA;AACH","file":"patterns-builtin.js","sourcesContent":["/**\n * Built-in pattern factories — generic line/dot/scatter textures. Each\n * returns a `TextureHandle` you can wrap in a `FillStyle` of\n * `{ fill: 'pattern', pattern }` and pass to anything that accepts a `FillStyle`\n * (`FillStyle`-aware layers, path fills, etc.).\n * Imported from a subpath so consumers that ship their own catalog can\n * avoid the bundle cost.\n *\n * All factories require an explicit `color` (and `bg` for `chunks`). No\n * defaults are baked in — the caller's design system is the source of truth\n * for palette decisions.\n */\n\nimport { createTilePattern } from '.';\nimport type { TextureHandle } from '../../renderer/textures/registerTexture';\n\n/** Diagonal hatch (forward slash). */\nexport interface HatchParams {\n color: string;\n size?: number;\n lineWidth?: number;\n}\n\nexport function hatch(params: HatchParams): TextureHandle | null {\n const { color, size = 5, lineWidth = 1 } = params;\n return createTilePattern({\n size,\n draw: (oc, s) => {\n oc.strokeStyle = color;\n oc.lineWidth = lineWidth;\n oc.beginPath();\n oc.moveTo(-1, s + 1);\n oc.lineTo(s + 1, -1);\n oc.moveTo(-1, 1);\n oc.lineTo(1, -1);\n oc.moveTo(s - 1, s + 1);\n oc.lineTo(s + 1, s - 1);\n oc.stroke();\n },\n });\n}\n\n/** Diagonal hatch in both directions. */\nexport interface CrosshatchParams {\n color: string;\n size?: number;\n lineWidth?: number;\n}\n\nexport function crosshatch(params: CrosshatchParams): TextureHandle | null {\n const { color, size = 6, lineWidth = 0.8 } = params;\n return createTilePattern({\n size,\n draw: (oc, s) => {\n oc.strokeStyle = color;\n oc.lineWidth = lineWidth;\n oc.beginPath();\n // Forward diagonal (with seamless tiling).\n oc.moveTo(-1, s + 1);\n oc.lineTo(s + 1, -1);\n oc.moveTo(-1, 1);\n oc.lineTo(1, -1);\n oc.moveTo(s - 1, s + 1);\n oc.lineTo(s + 1, s - 1);\n // Backward diagonal.\n oc.moveTo(-1, -1);\n oc.lineTo(s + 1, s + 1);\n oc.moveTo(s - 1, -1);\n oc.lineTo(s + 1, 1);\n oc.moveTo(-1, s - 1);\n oc.lineTo(1, s + 1);\n oc.stroke();\n },\n });\n}\n\n/** Regular grid of filled dots. */\nexport interface DotsParams {\n color: string;\n size?: number;\n radius?: number;\n}\n\nexport function dots(params: DotsParams): TextureHandle | null {\n const { color, size = 6, radius = 1 } = params;\n return createTilePattern({\n size,\n draw: (oc, s) => {\n oc.fillStyle = color;\n oc.beginPath();\n oc.arc(s / 2, s / 2, radius, 0, Math.PI * 2);\n oc.fill();\n },\n });\n}\n\n/**\n * Random scatter of small ellipses on top of a solid background. Driven by a\n * seeded PRNG so the same `seed` produces a deterministic tile.\n *\n * Note: the `bg` field is optional — omit it for a transparent background\n * (the scatter shapes draw directly onto whatever sits beneath the overlay).\n */\nexport interface ChunksParams {\n color: string;\n bg?: string;\n size?: number;\n /** Coverage: `chunks * chunkSize²` per `size²` tile. Range ~[0, 1]. */\n density?: number;\n chunkSize?: number;\n seed?: number;\n}\n\n/** Simple seeded PRNG (mulberry32) for deterministic chunk placement. */\nfunction mulberry32(seed: number): () => number {\n let s = seed | 0;\n return () => {\n s = (s + 0x6D2B79F5) | 0;\n let t = Math.imul(s ^ (s >>> 15), 1 | s);\n t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296;\n };\n}\n\nexport function chunks(params: ChunksParams): TextureHandle | null {\n const { color, bg, size = 48, density = 0.35, chunkSize = 3, seed = 42 } = params;\n return createTilePattern({\n size,\n draw: (oc, s) => {\n if (bg !== undefined) {\n oc.fillStyle = bg;\n oc.fillRect(0, 0, s, s);\n }\n const rand = mulberry32(seed);\n const count = Math.round((s * s * density) / (chunkSize * chunkSize));\n oc.fillStyle = color;\n for (let i = 0; i < count; i++) {\n const cx = rand() * s;\n const cy = rand() * s;\n const w = chunkSize * (0.5 + rand());\n const h = chunkSize * (0.5 + rand());\n const angle = rand() * Math.PI;\n oc.save();\n oc.translate(cx, cy);\n oc.rotate(angle);\n oc.beginPath();\n oc.ellipse(0, 0, w / 2, h / 2, 0, 0, Math.PI * 2);\n oc.fill();\n oc.restore();\n }\n },\n });\n}\n"]}
|