@classytic/stage 0.1.0 → 0.3.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/LICENSE +1 -1
- package/README.md +7 -3
- package/dist/assets/index.mjs +0 -1
- package/dist/assets/kit/glyphs.d.mts +5 -5
- package/dist/assets/kit/glyphs.mjs +4 -4
- package/dist/builder/Palette.mjs +50 -89
- package/dist/builder/SceneBuilder.mjs +18 -76
- package/dist/builder/editor.d.mts +2 -1
- package/dist/builder/editor.mjs +14 -4
- package/dist/builder/tools.d.mts +1 -1
- package/dist/builder/tools.mjs +1 -1
- package/dist/chem/index.d.mts +5 -5
- package/dist/chem/index.mjs +4 -4
- package/dist/circuit/index.d.mts +92 -0
- package/dist/circuit/index.mjs +333 -0
- package/dist/core/clock.d.mts +1 -1
- package/dist/core/clock.mjs +3 -3
- package/dist/core/control.d.mts +1 -1
- package/dist/core/control.mjs +2 -2
- package/dist/core/coords.d.mts +4 -4
- package/dist/core/coords.mjs +1 -1
- package/dist/core/index.d.mts +2 -1
- package/dist/core/index.mjs +2 -1
- package/dist/core/learner.d.mts +1 -1
- package/dist/core/learner.mjs +1 -1
- package/dist/core/math.d.mts +26 -0
- package/dist/core/math.mjs +37 -0
- package/dist/core/motion.d.mts +6 -6
- package/dist/core/motion.mjs +6 -6
- package/dist/core/richText.d.mts +2 -2
- package/dist/core/vec.d.mts +1 -1
- package/dist/field/index.d.mts +11 -3
- package/dist/field/index.mjs +20 -3
- package/dist/finance/bizsim.d.mts +93 -0
- package/dist/finance/bizsim.mjs +117 -0
- package/dist/finance/index.d.mts +118 -0
- package/dist/finance/index.mjs +203 -0
- package/dist/index.d.mts +6 -3
- package/dist/index.mjs +6 -4
- package/dist/interaction/MovableDot.d.mts +17 -1
- package/dist/interaction/MovableDot.mjs +160 -43
- package/dist/interaction/index.d.mts +2 -1
- package/dist/interaction/index.mjs +2 -1
- package/dist/interaction/useDraggable.d.mts +1 -1
- package/dist/interaction/useDraggable.mjs +55 -5
- package/dist/interaction/usePressSpring.d.mts +24 -0
- package/dist/interaction/usePressSpring.mjs +67 -0
- package/dist/logic/ast.d.mts +1 -1
- package/dist/logic/index.mjs +8 -3
- package/dist/logic/minimize.d.mts +2 -2
- package/dist/logic/minimize.mjs +56 -18
- package/dist/logic/table.mjs +1 -1
- package/dist/math/ast.d.mts +1 -1
- package/dist/math/ast.mjs +1 -1
- package/dist/math/calculus.d.mts +22 -1
- package/dist/math/calculus.mjs +224 -11
- package/dist/math/compile.d.mts +8 -0
- package/dist/math/compile.mjs +40 -0
- package/dist/math/defs.mjs +1 -1
- package/dist/math/index.d.mts +5 -4
- package/dist/math/index.mjs +5 -4
- package/dist/math/latex.mjs +8 -0
- package/dist/math/parse.mjs +2 -2
- package/dist/math/tokenize.mjs +1 -1
- package/dist/primitives/CanvasLayer.mjs +3 -3
- package/dist/primitives/Dot.d.mts +2 -15
- package/dist/primitives/Dot.mjs +6 -4
- package/dist/primitives/Grid.d.mts +41 -14
- package/dist/primitives/Grid.mjs +100 -22
- package/dist/primitives/Label.d.mts +2 -15
- package/dist/primitives/Label.mjs +4 -3
- package/dist/primitives/Lines.d.mts +4 -32
- package/dist/primitives/Lines.mjs +10 -8
- package/dist/primitives/Shapes.d.mts +5 -43
- package/dist/primitives/Shapes.mjs +12 -10
- package/dist/primitives/Tex.mjs +2 -2
- package/dist/primitives/index.d.mts +2 -2
- package/dist/primitives/index.mjs +2 -2
- package/dist/primitives/props.mjs +31 -0
- package/dist/scene/Scene.d.mts +6 -1
- package/dist/scene/Scene.mjs +16 -41
- package/dist/scene/assets.d.mts +2 -2
- package/dist/scene/assets.mjs +2 -2
- package/dist/scene/commands.d.mts +10 -1
- package/dist/scene/commands.mjs +42 -2
- package/dist/scene/evaluators.mjs +2 -2
- package/dist/scene/index.d.mts +2 -2
- package/dist/scene/index.mjs +2 -2
- package/dist/scene/migrate.mjs +1 -1
- package/dist/scene/sims.mjs +1 -1
- package/dist/scene/types.d.mts +4 -4
- package/dist/sim/particles.d.mts +2 -2
- package/dist/sim/rate.d.mts +4 -4
- package/dist/sim/rate.mjs +1 -1
- package/dist/sim/registry.d.mts +1 -1
- package/dist/sim/sampler.d.mts +5 -5
- package/dist/sim/thermal.d.mts +3 -3
- package/dist/sim/thermal.mjs +2 -2
- package/dist/sim/types.d.mts +2 -2
- package/dist/sim/wave.d.mts +2 -2
- package/dist/sim/wave.mjs +2 -2
- package/dist/steps/index.d.mts +1 -1
- package/dist/steps/index.mjs +3 -3
- package/dist/thermo/index.d.mts +1 -1
- package/dist/thermo/index.mjs +1 -1
- package/dist/view/Stage.mjs +6 -13
- package/dist/view/useInView.mjs +1 -1
- package/package.json +37 -25
- package/styles.css +141 -1
- package/dist/assets/kit/index.mjs +0 -4
package/dist/index.d.mts
CHANGED
|
@@ -15,6 +15,7 @@ import { Palette, PaletteProps } from "./builder/Palette.mjs";
|
|
|
15
15
|
import { CoordsContext, DragOverlayContext, StageRefContext, useCoords, useDragOverlay, useStageRef } from "./core/context.mjs";
|
|
16
16
|
import { ClockProvider, ClockProviderProps, FrameDriver, FrameInfo, useFrameLoop } from "./core/clock.mjs";
|
|
17
17
|
import { Learner, LearnerProvider, LearnerResult, PriorAttempts, useLearner } from "./core/learner.mjs";
|
|
18
|
+
import { approxEq, clamp, clamp01, gcd, remap, round, snapTo, toDeg, toRad } from "./core/math.mjs";
|
|
18
19
|
import { RichSpan, Script, parseRichText } from "./core/richText.mjs";
|
|
19
20
|
import { StepProgress, StepProgressProvider, StepScope, StepSpec, StepState, useStepProgress } from "./steps/index.mjs";
|
|
20
21
|
import { Stage, StageProps } from "./view/Stage.mjs";
|
|
@@ -26,12 +27,13 @@ import { Line, LineProps, Ray, Segment, SegmentProps, Vector, VectorProps } from
|
|
|
26
27
|
import { Circle, CircleProps, Ellipse, EllipseProps, Path, PathProps, Polygon, PolygonProps, Polyline, PolylineProps } from "./primitives/Shapes.mjs";
|
|
27
28
|
import { Label, LabelProps } from "./primitives/Label.mjs";
|
|
28
29
|
import { Tex, TexProps } from "./primitives/Tex.mjs";
|
|
29
|
-
import { Axes, AxesProps, Grid, GridProps, niceStep } from "./primitives/Grid.mjs";
|
|
30
|
+
import { Axes, AxesProps, ClearZone, Grid, GridProps, clearOfLabel, niceStep } from "./primitives/Grid.mjs";
|
|
30
31
|
import { OfXProps, OfYProps, ParametricProps, Plot } from "./primitives/Plot.mjs";
|
|
31
32
|
import { CanvasLayer, CanvasLayerProps } from "./primitives/CanvasLayer.mjs";
|
|
32
33
|
import { useScreenToMath } from "./interaction/useScreenToMath.mjs";
|
|
33
34
|
import { AriaSliderProps, Constrain, DraggableHandlers, UseDraggable, UseDraggableArgs, useDraggable } from "./interaction/useDraggable.mjs";
|
|
34
35
|
import { MovableDot, MovableDotProps } from "./interaction/MovableDot.mjs";
|
|
36
|
+
import { PressSpringOpts, useImpulse, usePressSpring } from "./interaction/usePressSpring.mjs";
|
|
35
37
|
import { HitCandidate, hitTest } from "./interaction/hitTest.mjs";
|
|
36
38
|
import { OP_REFS, isRef, parentIds } from "./scene/schema.mjs";
|
|
37
39
|
import { EVALUATORS, EvalCtx } from "./scene/evaluators.mjs";
|
|
@@ -41,7 +43,8 @@ import { Scene, SceneProps } from "./scene/Scene.mjs";
|
|
|
41
43
|
import { RenderOpts, renderElements } from "./scene/render.mjs";
|
|
42
44
|
import { BinOp, Node, compileNode, evaluate, freeVars } from "./math/ast.mjs";
|
|
43
45
|
import { parse as parse$1 } from "./math/parse.mjs";
|
|
44
|
-
import { differentiate, simplify } from "./math/calculus.mjs";
|
|
46
|
+
import { definiteIntegral, differentiate, integrate, simplify } from "./math/calculus.mjs";
|
|
47
|
+
import { CompiledFn, compile } from "./math/compile.mjs";
|
|
45
48
|
import { toLatex as toLatex$1 } from "./math/latex.mjs";
|
|
46
49
|
import { CompiledExpr, ExprError, ExprResult, compileExpr } from "./math/index.mjs";
|
|
47
50
|
import { BinOp as BinOp$1, LNode, evalBool, freeVars as freeVars$1 } from "./logic/ast.mjs";
|
|
@@ -51,4 +54,4 @@ import { toLatex } from "./logic/latex.mjs";
|
|
|
51
54
|
import { Cube, Minimization, cubeCovers, cubeOfSelection, cubeTerm, minimalCover, minimize, primeImplicants } from "./logic/minimize.mjs";
|
|
52
55
|
import { CompiledLogic, LogicResult, compileLogic } from "./logic/index.mjs";
|
|
53
56
|
import { AssetResolveArgs, AssetSpec, assetMeta, getAsset, listAssets, registerAsset } from "./scene/assets.mjs";
|
|
54
|
-
export { type A11yProps, AUTHORING_TOOLS, type AriaSliderProps, type AssetGeometry, type AssetResolveArgs, type AssetSpec, Axes, type AxesProps, type BinOp, type Binding, BucketGlyph, CIRCLE, CURRENT_SCHEMA_VERSION, CanvasLayer, type CanvasLayerProps, Circle, type CircleProps, type CircleVal, type Classification, ClockProvider, type ClockProviderProps, type Command, type CommandResult, type CompiledExpr, type CompiledLogic, type Constrain, type ControlMap, type ControlPick, type ControlSpec, type ControlSurface, type CoordinateSystem, CoordsContext, type CoordsOptions, type Cube, DELETE, type DerivedDef, type DerivedElement, type DerivedKind, type DispatchOpts, Dot, type DotProps, DragOverlayContext, type DraggableHandlers, EVALUATORS, Editor, type ElementBase, type ElementStyle, Ellipse, type EllipseProps, type EvalCtx, type ExprError, type ExprResult, type FrameDriver, type FrameInfo, type FreeElement, type FreeNote, type FreePoint, type FreeScalar, GEOMETRY_TOOLS, type GlyphBox, Grid, type GridProps, HangerHook, type HangerHookProps, type HitCandidate, INTERSECT, type IconName, type Id, type InstanceState, LINE, type LNode, type LabMeta, Label, type LabelProps, type Learner, LearnerProvider, type LearnerResult, Line, type LineProps, type BinOp$1 as LogicBinOp, type LogicResult, MEASURE, MIDPOINT, type Matrix, type Minimization, MovableDot, type MovableDotProps, type MutatePatch, NOTE, type Node, type NumOrRef, OP_REFS, type OfXProps, type OfYProps, type Op, POINT, Palette, type PaletteProps, type ParametricProps, Path, type PathProps, Plot, Point, Polygon, type PolygonProps, Polyline, type PolylineProps, type PriorAttempts, Ray, type Ref, type RenderOpts, type Resolved, type RichSpan, SCALAR, SEGMENT, SELECT, Scene, SceneBuilder, type SceneBuilderProps, type SceneDoc, type SceneElement, type SceneMeta, type SceneProps, SceneStore, type Vec2 as SceneVec2, type Script, Segment, type SegmentProps, type ShapeLineVal, type Size, Stage, StageAssetDefs, type StageProps, StageRefContext, type StepProgress, StepProgressProvider, StepScope, type StepSpec, type StepState, type StyleProps, Tex, type TexProps, type Tool, type ToolCtx, ToolIcon, type TruthRow, type TruthTable, type UseDraggable, type UseDraggableArgs, type Val, type Vec2, Vector, type VectorProps, type ViewBox, WeightGlyph, XBlockGlyph, applyCommand, assetMeta, classify, collectRemoved, compileExpr, compileLogic, compileNode, controlsFromScene, createCoords, cubeCovers, cubeOfSelection, cubeTerm, differentiate, emptyDoc, equivalent, evalBool, evaluate, fmt, freeVars, getAsset, getControlSurface, hitTest, inverse, isAssetGeom, isCircleVal, isDerived, isFree, isLineVal, isRef, isVec2, listAssets, listControlSurfaces, freeVars$1 as logicFreeVars, toLatex as logicToLatex, mat, migrate, minimalCover, minimize, niceStep, numOf, onControlChange, parentIds, parse, parse$1 as parseExpr, parseLogic, parseRichText, primeImplicants, registerAsset, renderElements, resolve, serialize, simplify, toCNF, toDNF, toLatex$1 as toLatex, truthTable, useControlSurface, useCoords, useDragOverlay, useDraggable, useEditor, useElementSize, useFrameLoop, useInView, useLearner, useScreenToMath, useStageRef, useStepProgress, vec };
|
|
57
|
+
export { type A11yProps, AUTHORING_TOOLS, type AriaSliderProps, type AssetGeometry, type AssetResolveArgs, type AssetSpec, Axes, type AxesProps, type BinOp, type Binding, BucketGlyph, CIRCLE, CURRENT_SCHEMA_VERSION, CanvasLayer, type CanvasLayerProps, Circle, type CircleProps, type CircleVal, type Classification, type ClearZone, ClockProvider, type ClockProviderProps, type Command, type CommandResult, type CompiledExpr, type CompiledFn, type CompiledLogic, type Constrain, type ControlMap, type ControlPick, type ControlSpec, type ControlSurface, type CoordinateSystem, CoordsContext, type CoordsOptions, type Cube, DELETE, type DerivedDef, type DerivedElement, type DerivedKind, type DispatchOpts, Dot, type DotProps, DragOverlayContext, type DraggableHandlers, EVALUATORS, Editor, type ElementBase, type ElementStyle, Ellipse, type EllipseProps, type EvalCtx, type ExprError, type ExprResult, type FrameDriver, type FrameInfo, type FreeElement, type FreeNote, type FreePoint, type FreeScalar, GEOMETRY_TOOLS, type GlyphBox, Grid, type GridProps, HangerHook, type HangerHookProps, type HitCandidate, INTERSECT, type IconName, type Id, type InstanceState, LINE, type LNode, type LabMeta, Label, type LabelProps, type Learner, LearnerProvider, type LearnerResult, Line, type LineProps, type BinOp$1 as LogicBinOp, type LogicResult, MEASURE, MIDPOINT, type Matrix, type Minimization, MovableDot, type MovableDotProps, type MutatePatch, NOTE, type Node, type NumOrRef, OP_REFS, type OfXProps, type OfYProps, type Op, POINT, Palette, type PaletteProps, type ParametricProps, Path, type PathProps, Plot, Point, Polygon, type PolygonProps, Polyline, type PolylineProps, type PressSpringOpts, type PriorAttempts, Ray, type Ref, type RenderOpts, type Resolved, type RichSpan, SCALAR, SEGMENT, SELECT, Scene, SceneBuilder, type SceneBuilderProps, type SceneDoc, type SceneElement, type SceneMeta, type SceneProps, SceneStore, type Vec2 as SceneVec2, type Script, Segment, type SegmentProps, type ShapeLineVal, type Size, Stage, StageAssetDefs, type StageProps, StageRefContext, type StepProgress, StepProgressProvider, StepScope, type StepSpec, type StepState, type StyleProps, Tex, type TexProps, type Tool, type ToolCtx, ToolIcon, type TruthRow, type TruthTable, type UseDraggable, type UseDraggableArgs, type Val, type Vec2, Vector, type VectorProps, type ViewBox, WeightGlyph, XBlockGlyph, applyCommand, approxEq, assetMeta, clamp, clamp01, classify, clearOfLabel, collectRemoved, compile, compileExpr, compileLogic, compileNode, controlsFromScene, createCoords, cubeCovers, cubeOfSelection, cubeTerm, definiteIntegral, differentiate, emptyDoc, equivalent, evalBool, evaluate, fmt, freeVars, gcd, getAsset, getControlSurface, hitTest, integrate, inverse, isAssetGeom, isCircleVal, isDerived, isFree, isLineVal, isRef, isVec2, listAssets, listControlSurfaces, freeVars$1 as logicFreeVars, toLatex as logicToLatex, mat, migrate, minimalCover, minimize, niceStep, numOf, onControlChange, parentIds, parse, parse$1 as parseExpr, parseLogic, parseRichText, primeImplicants, registerAsset, remap, renderElements, resolve, round, serialize, simplify, snapTo, toCNF, toDNF, toDeg, toLatex$1 as toLatex, toRad, truthTable, useControlSurface, useCoords, useDragOverlay, useDraggable, useEditor, useElementSize, useFrameLoop, useImpulse, useInView, useLearner, usePressSpring, useScreenToMath, useStageRef, useStepProgress, vec };
|
package/dist/index.mjs
CHANGED
|
@@ -5,6 +5,7 @@ import { CoordsContext, DragOverlayContext, StageRefContext, useCoords, useDragO
|
|
|
5
5
|
import { ClockProvider, useFrameLoop } from "./core/clock.mjs";
|
|
6
6
|
import { getControlSurface, listControlSurfaces, onControlChange, useControlSurface } from "./core/control.mjs";
|
|
7
7
|
import { LearnerProvider, useLearner } from "./core/learner.mjs";
|
|
8
|
+
import { approxEq, clamp, clamp01, gcd, remap, round, snapTo, toDeg, toRad } from "./core/math.mjs";
|
|
8
9
|
import { StepProgressProvider, StepScope, useStepProgress } from "./steps/index.mjs";
|
|
9
10
|
import { useElementSize } from "./view/useElementSize.mjs";
|
|
10
11
|
import { Stage } from "./view/Stage.mjs";
|
|
@@ -14,11 +15,12 @@ import { Line, Ray, Segment, Vector } from "./primitives/Lines.mjs";
|
|
|
14
15
|
import { Circle, Ellipse, Path, Polygon, Polyline } from "./primitives/Shapes.mjs";
|
|
15
16
|
import { Label } from "./primitives/Label.mjs";
|
|
16
17
|
import { Tex } from "./primitives/Tex.mjs";
|
|
17
|
-
import { Axes, Grid, niceStep } from "./primitives/Grid.mjs";
|
|
18
|
+
import { Axes, Grid, clearOfLabel, niceStep } from "./primitives/Grid.mjs";
|
|
18
19
|
import { Plot } from "./primitives/Plot.mjs";
|
|
19
20
|
import { CanvasLayer } from "./primitives/CanvasLayer.mjs";
|
|
20
21
|
import { useScreenToMath } from "./interaction/useScreenToMath.mjs";
|
|
21
22
|
import { useDraggable } from "./interaction/useDraggable.mjs";
|
|
23
|
+
import { useImpulse, usePressSpring } from "./interaction/usePressSpring.mjs";
|
|
22
24
|
import { MovableDot } from "./interaction/MovableDot.mjs";
|
|
23
25
|
import { hitTest } from "./interaction/hitTest.mjs";
|
|
24
26
|
import { isAssetGeom, isCircleVal, isDerived, isFree, isLineVal, isVec2, numOf } from "./scene/types.mjs";
|
|
@@ -26,7 +28,8 @@ import { OP_REFS, isRef, parentIds } from "./scene/schema.mjs";
|
|
|
26
28
|
import { assetMeta, getAsset, listAssets, registerAsset } from "./scene/assets.mjs";
|
|
27
29
|
import { compileNode, evaluate, freeVars } from "./math/ast.mjs";
|
|
28
30
|
import { parse as parse$1 } from "./math/parse.mjs";
|
|
29
|
-
import { differentiate, simplify } from "./math/calculus.mjs";
|
|
31
|
+
import { definiteIntegral, differentiate, integrate, simplify } from "./math/calculus.mjs";
|
|
32
|
+
import { compile } from "./math/compile.mjs";
|
|
30
33
|
import { toLatex as toLatex$1 } from "./math/latex.mjs";
|
|
31
34
|
import { compileExpr } from "./math/index.mjs";
|
|
32
35
|
import { EVALUATORS } from "./scene/evaluators.mjs";
|
|
@@ -44,7 +47,6 @@ import { AUTHORING_TOOLS, CIRCLE, DELETE, GEOMETRY_TOOLS, INTERSECT, LINE, MEASU
|
|
|
44
47
|
import { SceneBuilder } from "./builder/SceneBuilder.mjs";
|
|
45
48
|
import { StageAssetDefs } from "./assets/kit/svg-defs.mjs";
|
|
46
49
|
import { BucketGlyph, HangerHook, WeightGlyph, XBlockGlyph } from "./assets/kit/glyphs.mjs";
|
|
47
|
-
import "./assets/kit/index.mjs";
|
|
48
50
|
import { evalBool, freeVars as freeVars$1 } from "./logic/ast.mjs";
|
|
49
51
|
import { parseLogic } from "./logic/parse.mjs";
|
|
50
52
|
import { classify, equivalent, toCNF, toDNF, truthTable } from "./logic/table.mjs";
|
|
@@ -52,4 +54,4 @@ import { toLatex } from "./logic/latex.mjs";
|
|
|
52
54
|
import { cubeCovers, cubeOfSelection, cubeTerm, minimalCover, minimize, primeImplicants } from "./logic/minimize.mjs";
|
|
53
55
|
import { compileLogic } from "./logic/index.mjs";
|
|
54
56
|
|
|
55
|
-
export { AUTHORING_TOOLS, Axes, BucketGlyph, CIRCLE, CURRENT_SCHEMA_VERSION, CanvasLayer, Circle, ClockProvider, CoordsContext, DELETE, Dot, DragOverlayContext, EVALUATORS, Editor, Ellipse, GEOMETRY_TOOLS, Grid, HangerHook, INTERSECT, LINE, Label, LearnerProvider, Line, MEASURE, MIDPOINT, MovableDot, NOTE, OP_REFS, POINT, Palette, Path, Plot, Point, Polygon, Polyline, Ray, SCALAR, SEGMENT, SELECT, Scene, SceneBuilder, SceneStore, Segment, Stage, StageAssetDefs, StageRefContext, StepProgressProvider, StepScope, Tex, ToolIcon, Vector, WeightGlyph, XBlockGlyph, applyCommand, assetMeta, classify, collectRemoved, compileExpr, compileLogic, compileNode, controlsFromScene, createCoords, cubeCovers, cubeOfSelection, cubeTerm, differentiate, emptyDoc, equivalent, evalBool, evaluate, fmt, freeVars, getAsset, getControlSurface, hitTest, inverse, isAssetGeom, isCircleVal, isDerived, isFree, isLineVal, isRef, isVec2, listAssets, listControlSurfaces, freeVars$1 as logicFreeVars, toLatex as logicToLatex, mat, migrate, minimalCover, minimize, niceStep, numOf, onControlChange, parentIds, parse, parse$1 as parseExpr, parseLogic, parseRichText, primeImplicants, registerAsset, renderElements, resolve, serialize, simplify, toCNF, toDNF, toLatex$1 as toLatex, truthTable, useControlSurface, useCoords, useDragOverlay, useDraggable, useEditor, useElementSize, useFrameLoop, useInView, useLearner, useScreenToMath, useStageRef, useStepProgress, vec };
|
|
57
|
+
export { AUTHORING_TOOLS, Axes, BucketGlyph, CIRCLE, CURRENT_SCHEMA_VERSION, CanvasLayer, Circle, ClockProvider, CoordsContext, DELETE, Dot, DragOverlayContext, EVALUATORS, Editor, Ellipse, GEOMETRY_TOOLS, Grid, HangerHook, INTERSECT, LINE, Label, LearnerProvider, Line, MEASURE, MIDPOINT, MovableDot, NOTE, OP_REFS, POINT, Palette, Path, Plot, Point, Polygon, Polyline, Ray, SCALAR, SEGMENT, SELECT, Scene, SceneBuilder, SceneStore, Segment, Stage, StageAssetDefs, StageRefContext, StepProgressProvider, StepScope, Tex, ToolIcon, Vector, WeightGlyph, XBlockGlyph, applyCommand, approxEq, assetMeta, clamp, clamp01, classify, clearOfLabel, collectRemoved, compile, compileExpr, compileLogic, compileNode, controlsFromScene, createCoords, cubeCovers, cubeOfSelection, cubeTerm, definiteIntegral, differentiate, emptyDoc, equivalent, evalBool, evaluate, fmt, freeVars, gcd, getAsset, getControlSurface, hitTest, integrate, inverse, isAssetGeom, isCircleVal, isDerived, isFree, isLineVal, isRef, isVec2, listAssets, listControlSurfaces, freeVars$1 as logicFreeVars, toLatex as logicToLatex, mat, migrate, minimalCover, minimize, niceStep, numOf, onControlChange, parentIds, parse, parse$1 as parseExpr, parseLogic, parseRichText, primeImplicants, registerAsset, remap, renderElements, resolve, round, serialize, simplify, snapTo, toCNF, toDNF, toDeg, toLatex$1 as toLatex, toRad, truthTable, useControlSurface, useCoords, useDragOverlay, useDraggable, useEditor, useElementSize, useFrameLoop, useImpulse, useInView, useLearner, usePressSpring, useScreenToMath, useStageRef, useStepProgress, vec };
|
|
@@ -18,6 +18,18 @@ interface MovableDotProps {
|
|
|
18
18
|
/** Keyboard arrow-key nudge in math units. Match the lab's snap grid so a
|
|
19
19
|
* single arrow press actually moves (e.g. 1 for an integer number line). */
|
|
20
20
|
step?: number;
|
|
21
|
+
/** Math-unit snap grid. Tells the handle the lattice so it can preview the
|
|
22
|
+
* candidate landing spots (ghosts) and a snap-tick — purely visual; the lab
|
|
23
|
+
* still owns the actual snapping in its onMove. 0/undefined = no preview. */
|
|
24
|
+
snap?: number;
|
|
25
|
+
/** Faint candidate snap-stops shown while dragging (default: on when `snap`
|
|
26
|
+
* is set). Pass explicit points to drive non-grid lattices (e.g. stops along
|
|
27
|
+
* a ray); otherwise they're derived from `snap` + the view + `constrain`. */
|
|
28
|
+
ghosts?: boolean;
|
|
29
|
+
ghostPoints?: Vec2[];
|
|
30
|
+
/** Live value pill near the handle while dragging. true = default formatter,
|
|
31
|
+
* a fn for custom text, false to hide. Default true. */
|
|
32
|
+
readout?: boolean | ((v: Vec2) => string);
|
|
21
33
|
}
|
|
22
34
|
declare function MovableDot({
|
|
23
35
|
value,
|
|
@@ -27,7 +39,11 @@ declare function MovableDot({
|
|
|
27
39
|
r,
|
|
28
40
|
ariaLabel,
|
|
29
41
|
range,
|
|
30
|
-
step
|
|
42
|
+
step,
|
|
43
|
+
snap,
|
|
44
|
+
ghosts,
|
|
45
|
+
ghostPoints,
|
|
46
|
+
readout
|
|
31
47
|
}: MovableDotProps): ReactNode;
|
|
32
48
|
//#endregion
|
|
33
49
|
export { MovableDot, MovableDotProps };
|
|
@@ -2,12 +2,52 @@
|
|
|
2
2
|
|
|
3
3
|
import { useCoords } from "../core/context.mjs";
|
|
4
4
|
import { useDraggable } from "./useDraggable.mjs";
|
|
5
|
+
import { useImpulse, usePressSpring } from "./usePressSpring.mjs";
|
|
5
6
|
import { useState } from "react";
|
|
6
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
7
8
|
|
|
8
9
|
//#region src/interaction/MovableDot.tsx
|
|
9
|
-
|
|
10
|
-
|
|
10
|
+
const ACCENT = "var(--stage-accent)";
|
|
11
|
+
function fnum(n) {
|
|
12
|
+
const r = Math.round(n * 100) / 100;
|
|
13
|
+
return Object.is(r, -0) ? "0" : String(r);
|
|
14
|
+
}
|
|
15
|
+
/** Candidate snap-stops within a small window around `value`, derived from the
|
|
16
|
+
* grid + which axes are free. Kept LOCAL (±3 steps) so the guide reads as
|
|
17
|
+
* "here are your nearby choices", not a wall of dots. */
|
|
18
|
+
function autoGhosts(value, snap, constrain, view, range) {
|
|
19
|
+
if (!(snap > 0)) return [];
|
|
20
|
+
const W = 3;
|
|
21
|
+
const stops = [];
|
|
22
|
+
const along = (axis) => {
|
|
23
|
+
const base = axis === "x" ? value.x : value.y;
|
|
24
|
+
const lo = axis === "x" ? range?.min ?? view.xMin : range?.min ?? view.yMin;
|
|
25
|
+
const hi = axis === "x" ? range?.max ?? view.xMax : range?.max ?? view.yMax;
|
|
26
|
+
for (let k = -3; k <= W; k++) {
|
|
27
|
+
if (k === 0) continue;
|
|
28
|
+
const v = Math.round(base / snap) * snap + k * snap;
|
|
29
|
+
if (v < lo - 1e-9 || v > hi + 1e-9) continue;
|
|
30
|
+
stops.push(axis === "x" ? {
|
|
31
|
+
x: v,
|
|
32
|
+
y: value.y
|
|
33
|
+
} : {
|
|
34
|
+
x: value.x,
|
|
35
|
+
y: v
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
const oneD = constrain === "horizontal" || constrain === "vertical";
|
|
40
|
+
if (constrain === "horizontal") along("x");
|
|
41
|
+
else if (constrain === "vertical") along("y");
|
|
42
|
+
else if (!oneD && typeof constrain !== "function") {
|
|
43
|
+
along("x");
|
|
44
|
+
along("y");
|
|
45
|
+
}
|
|
46
|
+
return stops;
|
|
47
|
+
}
|
|
48
|
+
function MovableDot({ value, onMove, constrain, color = ACCENT, r = 7, ariaLabel = "draggable point", range, step, snap, ghosts, ghostPoints, readout = true }) {
|
|
49
|
+
const c = useCoords();
|
|
50
|
+
const [px, py] = c.toPx(value.x, value.y);
|
|
11
51
|
const { dragging, handlers, ariaProps } = useDraggable({
|
|
12
52
|
value,
|
|
13
53
|
onMove,
|
|
@@ -16,50 +56,127 @@ function MovableDot({ value, onMove, constrain, color = "var(--stage-accent)", r
|
|
|
16
56
|
...step !== void 0 ? { step } : {}
|
|
17
57
|
});
|
|
18
58
|
const [hovered, setHovered] = useState(false);
|
|
19
|
-
const
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
59
|
+
const [interacted, setInteracted] = useState(false);
|
|
60
|
+
const press = usePressSpring(dragging, {
|
|
61
|
+
to: 1,
|
|
62
|
+
stiffness: 360,
|
|
63
|
+
damping: 24
|
|
64
|
+
});
|
|
65
|
+
const dotR = r + (hovered && !dragging ? 1.5 : 0) + press * 3;
|
|
66
|
+
const tickRaw = useImpulse(`${Math.round(value.x * 1e4)}:${Math.round(value.y * 1e4)}`, 280);
|
|
67
|
+
const tick = dragging ? tickRaw : 0;
|
|
68
|
+
const stops = !(dragging && (ghosts ?? (snap != null && snap > 0))) ? [] : ghostPoints ?? autoGhosts(value, snap ?? 0, constrain, c.view, range);
|
|
69
|
+
const label = readout === false ? null : typeof readout === "function" ? readout(value) : constrain === "horizontal" || constrain === "vertical" ? fnum(constrain === "vertical" ? value.y : value.x) : `(${fnum(value.x)}, ${fnum(value.y)})`;
|
|
70
|
+
const pillW = label ? Math.max(30, label.length * 7.5 + 14) : 0;
|
|
71
|
+
const pillY = py - dotR - 30;
|
|
72
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
73
|
+
stops.length > 0 && /* @__PURE__ */ jsx("g", {
|
|
74
|
+
style: { pointerEvents: "none" },
|
|
75
|
+
children: stops.map((s, i) => {
|
|
76
|
+
const [gx, gy] = c.toPx(s.x, s.y);
|
|
77
|
+
const d = Math.hypot(gx - px, gy - py);
|
|
78
|
+
return /* @__PURE__ */ jsx("circle", {
|
|
79
|
+
cx: gx,
|
|
80
|
+
cy: gy,
|
|
81
|
+
r: 3,
|
|
82
|
+
fill: color,
|
|
83
|
+
opacity: Math.max(.12, .5 - d / 360)
|
|
84
|
+
}, i);
|
|
85
|
+
})
|
|
86
|
+
}),
|
|
87
|
+
/* @__PURE__ */ jsxs("g", {
|
|
88
|
+
...handlers,
|
|
89
|
+
...ariaProps,
|
|
90
|
+
"aria-label": ariaLabel,
|
|
91
|
+
onPointerDown: (e) => {
|
|
92
|
+
setInteracted(true);
|
|
93
|
+
handlers.onPointerDown(e);
|
|
94
|
+
},
|
|
95
|
+
onKeyDown: (e) => {
|
|
96
|
+
setInteracted(true);
|
|
97
|
+
handlers.onKeyDown(e);
|
|
98
|
+
},
|
|
99
|
+
onPointerEnter: () => setHovered(true),
|
|
100
|
+
onPointerLeave: () => setHovered(false),
|
|
101
|
+
style: {
|
|
102
|
+
cursor: dragging ? "grabbing" : "grab",
|
|
103
|
+
outline: "none"
|
|
104
|
+
},
|
|
105
|
+
children: [
|
|
106
|
+
/* @__PURE__ */ jsx("circle", {
|
|
107
|
+
cx: px,
|
|
108
|
+
cy: py,
|
|
109
|
+
r: Math.max(r + 14, 12),
|
|
110
|
+
fill: "transparent"
|
|
111
|
+
}),
|
|
112
|
+
!interacted && !dragging && /* @__PURE__ */ jsx("circle", {
|
|
113
|
+
className: "stage-nudge",
|
|
114
|
+
cx: px,
|
|
115
|
+
cy: py,
|
|
116
|
+
r: r + 5,
|
|
117
|
+
fill: "none",
|
|
118
|
+
stroke: color,
|
|
119
|
+
strokeWidth: 1.5,
|
|
120
|
+
style: { pointerEvents: "none" }
|
|
121
|
+
}),
|
|
122
|
+
dragging ? /* @__PURE__ */ jsx("circle", {
|
|
123
|
+
cx: px,
|
|
124
|
+
cy: py,
|
|
125
|
+
r: r + 6 + press * 4,
|
|
126
|
+
fill: color,
|
|
127
|
+
opacity: .18
|
|
128
|
+
}) : /* @__PURE__ */ jsx("circle", {
|
|
129
|
+
cx: px,
|
|
130
|
+
cy: py,
|
|
131
|
+
r: r + 5,
|
|
132
|
+
fill: "none",
|
|
133
|
+
stroke: color,
|
|
134
|
+
strokeWidth: 1.5,
|
|
135
|
+
opacity: hovered ? .55 : .28
|
|
136
|
+
}),
|
|
137
|
+
/* @__PURE__ */ jsx("circle", {
|
|
138
|
+
cx: px,
|
|
139
|
+
cy: py,
|
|
140
|
+
r: dotR,
|
|
141
|
+
fill: color,
|
|
142
|
+
stroke: "var(--stage-bg)",
|
|
143
|
+
strokeWidth: 2
|
|
144
|
+
})
|
|
145
|
+
]
|
|
146
|
+
}),
|
|
147
|
+
/* @__PURE__ */ jsxs("g", {
|
|
148
|
+
style: { pointerEvents: "none" },
|
|
149
|
+
children: [tick > 0 && /* @__PURE__ */ jsx("circle", {
|
|
45
150
|
cx: px,
|
|
46
151
|
cy: py,
|
|
47
|
-
r:
|
|
152
|
+
r: dotR + (1 - tick) * 12,
|
|
48
153
|
fill: "none",
|
|
49
154
|
stroke: color,
|
|
50
|
-
strokeWidth:
|
|
51
|
-
opacity:
|
|
52
|
-
}),
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
155
|
+
strokeWidth: 2,
|
|
156
|
+
opacity: tick * .6
|
|
157
|
+
}), dragging && label && /* @__PURE__ */ jsxs("g", { children: [/* @__PURE__ */ jsx("rect", {
|
|
158
|
+
x: px - pillW / 2,
|
|
159
|
+
y: pillY,
|
|
160
|
+
width: pillW,
|
|
161
|
+
height: 22,
|
|
162
|
+
rx: 7,
|
|
163
|
+
fill: "var(--stage-bg)",
|
|
164
|
+
stroke: "var(--stage-grid)",
|
|
165
|
+
strokeWidth: 1,
|
|
166
|
+
opacity: .96
|
|
167
|
+
}), /* @__PURE__ */ jsx("text", {
|
|
168
|
+
x: px,
|
|
169
|
+
y: pillY + 11,
|
|
170
|
+
textAnchor: "middle",
|
|
171
|
+
dominantBaseline: "central",
|
|
172
|
+
fontSize: 12,
|
|
173
|
+
fontWeight: 700,
|
|
174
|
+
fill: "var(--stage-fg)",
|
|
175
|
+
style: { fontVariantNumeric: "tabular-nums" },
|
|
176
|
+
children: label
|
|
177
|
+
})] })]
|
|
178
|
+
})
|
|
179
|
+
] });
|
|
63
180
|
}
|
|
64
181
|
|
|
65
182
|
//#endregion
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { useScreenToMath } from "./useScreenToMath.mjs";
|
|
2
2
|
import { AriaSliderProps, Constrain, DraggableHandlers, UseDraggable, UseDraggableArgs, useDraggable } from "./useDraggable.mjs";
|
|
3
3
|
import { MovableDot, MovableDotProps } from "./MovableDot.mjs";
|
|
4
|
+
import { PressSpringOpts, useImpulse, usePressSpring } from "./usePressSpring.mjs";
|
|
4
5
|
import { HitCandidate, hitTest } from "./hitTest.mjs";
|
|
5
|
-
export { type AriaSliderProps, type Constrain, type DraggableHandlers, type HitCandidate, MovableDot, type MovableDotProps, type UseDraggable, type UseDraggableArgs, hitTest, useDraggable, useScreenToMath };
|
|
6
|
+
export { type AriaSliderProps, type Constrain, type DraggableHandlers, type HitCandidate, MovableDot, type MovableDotProps, type PressSpringOpts, type UseDraggable, type UseDraggableArgs, hitTest, useDraggable, useImpulse, usePressSpring, useScreenToMath };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { useScreenToMath } from "./useScreenToMath.mjs";
|
|
2
2
|
import { useDraggable } from "./useDraggable.mjs";
|
|
3
|
+
import { useImpulse, usePressSpring } from "./usePressSpring.mjs";
|
|
3
4
|
import { MovableDot } from "./MovableDot.mjs";
|
|
4
5
|
import { hitTest } from "./hitTest.mjs";
|
|
5
6
|
|
|
6
|
-
export { MovableDot, hitTest, useDraggable, useScreenToMath };
|
|
7
|
+
export { MovableDot, hitTest, useDraggable, useImpulse, usePressSpring, useScreenToMath };
|
|
@@ -10,7 +10,7 @@ interface UseDraggableArgs {
|
|
|
10
10
|
constrain?: Constrain;
|
|
11
11
|
/** Keyboard nudge step in math units. */
|
|
12
12
|
step?: number;
|
|
13
|
-
/** Bounds on the active axis
|
|
13
|
+
/** Bounds on the active axis, drives aria-valuemin/max for a proper slider
|
|
14
14
|
* (WAI-ARIA APG). Omit for an unbounded 2D point (valuetext still describes it). */
|
|
15
15
|
range?: {
|
|
16
16
|
min: number;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import { useScreenToMath } from "./useScreenToMath.mjs";
|
|
4
|
-
import { useCallback, useRef, useState } from "react";
|
|
4
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
5
5
|
|
|
6
6
|
//#region src/interaction/useDraggable.ts
|
|
7
7
|
function constrained(p, start, constrain) {
|
|
@@ -20,6 +20,20 @@ function useDraggable({ value, onMove, constrain, step = .5, range }) {
|
|
|
20
20
|
const toMath = useScreenToMath();
|
|
21
21
|
const [dragging, setDragging] = useState(false);
|
|
22
22
|
const startRef = useRef(value);
|
|
23
|
+
const onMoveRef = useRef(onMove);
|
|
24
|
+
onMoveRef.current = onMove;
|
|
25
|
+
const pendingRef = useRef(null);
|
|
26
|
+
const rafRef = useRef(0);
|
|
27
|
+
const flushMove = useCallback(() => {
|
|
28
|
+
rafRef.current = 0;
|
|
29
|
+
const p = pendingRef.current;
|
|
30
|
+
if (!p) return;
|
|
31
|
+
pendingRef.current = null;
|
|
32
|
+
onMoveRef.current(p, "move");
|
|
33
|
+
}, []);
|
|
34
|
+
useEffect(() => () => {
|
|
35
|
+
if (rafRef.current) cancelAnimationFrame(rafRef.current);
|
|
36
|
+
}, []);
|
|
23
37
|
const onPointerDown = useCallback((e) => {
|
|
24
38
|
e.currentTarget.setPointerCapture(e.pointerId);
|
|
25
39
|
startRef.current = value;
|
|
@@ -30,19 +44,25 @@ function useDraggable({ value, onMove, constrain, step = .5, range }) {
|
|
|
30
44
|
if (!dragging) return;
|
|
31
45
|
const m = toMath(e);
|
|
32
46
|
if (!m) return;
|
|
33
|
-
|
|
47
|
+
pendingRef.current = constrained({
|
|
34
48
|
x: m[0],
|
|
35
49
|
y: m[1]
|
|
36
|
-
}, startRef.current, constrain)
|
|
50
|
+
}, startRef.current, constrain);
|
|
51
|
+
if (!rafRef.current) rafRef.current = requestAnimationFrame(flushMove);
|
|
37
52
|
}, [
|
|
38
53
|
dragging,
|
|
39
54
|
toMath,
|
|
40
55
|
constrain,
|
|
41
|
-
|
|
56
|
+
flushMove
|
|
42
57
|
]);
|
|
43
58
|
const onPointerUp = useCallback((e) => {
|
|
44
59
|
if (!dragging) return;
|
|
45
60
|
setDragging(false);
|
|
61
|
+
if (rafRef.current) {
|
|
62
|
+
cancelAnimationFrame(rafRef.current);
|
|
63
|
+
rafRef.current = 0;
|
|
64
|
+
}
|
|
65
|
+
pendingRef.current = null;
|
|
46
66
|
const m = toMath(e);
|
|
47
67
|
onMove(m ? constrained({
|
|
48
68
|
x: m[0],
|
|
@@ -57,6 +77,7 @@ function useDraggable({ value, onMove, constrain, step = .5, range }) {
|
|
|
57
77
|
]);
|
|
58
78
|
const onKeyDown = useCallback((e) => {
|
|
59
79
|
const d = step * (e.shiftKey ? 5 : 1) * (e.altKey ? .25 : 1);
|
|
80
|
+
const vertical = constrain === "vertical";
|
|
60
81
|
let np = null;
|
|
61
82
|
if (e.key === "ArrowLeft") np = {
|
|
62
83
|
x: value.x - d,
|
|
@@ -74,6 +95,34 @@ function useDraggable({ value, onMove, constrain, step = .5, range }) {
|
|
|
74
95
|
x: value.x,
|
|
75
96
|
y: value.y - d
|
|
76
97
|
};
|
|
98
|
+
else if (e.key === "PageUp") np = vertical ? {
|
|
99
|
+
x: value.x,
|
|
100
|
+
y: value.y + 5 * step
|
|
101
|
+
} : {
|
|
102
|
+
x: value.x + 5 * step,
|
|
103
|
+
y: value.y
|
|
104
|
+
};
|
|
105
|
+
else if (e.key === "PageDown") np = vertical ? {
|
|
106
|
+
x: value.x,
|
|
107
|
+
y: value.y - 5 * step
|
|
108
|
+
} : {
|
|
109
|
+
x: value.x - 5 * step,
|
|
110
|
+
y: value.y
|
|
111
|
+
};
|
|
112
|
+
else if (e.key === "Home" && range) np = vertical ? {
|
|
113
|
+
x: value.x,
|
|
114
|
+
y: range.min
|
|
115
|
+
} : {
|
|
116
|
+
x: range.min,
|
|
117
|
+
y: value.y
|
|
118
|
+
};
|
|
119
|
+
else if (e.key === "End" && range) np = vertical ? {
|
|
120
|
+
x: value.x,
|
|
121
|
+
y: range.max
|
|
122
|
+
} : {
|
|
123
|
+
x: range.max,
|
|
124
|
+
y: value.y
|
|
125
|
+
};
|
|
77
126
|
if (np) {
|
|
78
127
|
e.preventDefault();
|
|
79
128
|
const p = constrained(np, value, constrain);
|
|
@@ -84,7 +133,8 @@ function useDraggable({ value, onMove, constrain, step = .5, range }) {
|
|
|
84
133
|
value,
|
|
85
134
|
step,
|
|
86
135
|
constrain,
|
|
87
|
-
onMove
|
|
136
|
+
onMove,
|
|
137
|
+
range
|
|
88
138
|
]);
|
|
89
139
|
const oneD = constrain === "horizontal" || constrain === "vertical";
|
|
90
140
|
const vertical = constrain === "vertical";
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
//#region src/interaction/usePressSpring.d.ts
|
|
2
|
+
interface PressSpringOpts {
|
|
3
|
+
/** Resting value when inactive. Default 0. */
|
|
4
|
+
from?: number;
|
|
5
|
+
/** Target value when active. Default 1. */
|
|
6
|
+
to?: number;
|
|
7
|
+
stiffness?: number;
|
|
8
|
+
damping?: number;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* A scalar that springs toward `to` while `active`, back to `from` on release,
|
|
12
|
+
* e.g. a 0→1 "press" amount you map to a radius bump or halo grow. The RAF loop
|
|
13
|
+
* is gated on "still moving" so a page full of idle handles costs nothing.
|
|
14
|
+
* Under reduced-motion it returns the target immediately (no animation).
|
|
15
|
+
*/
|
|
16
|
+
declare function usePressSpring(active: boolean, opts?: PressSpringOpts): number;
|
|
17
|
+
/**
|
|
18
|
+
* A one-shot impulse: jumps to 1 whenever `key` changes, then decays to 0 over
|
|
19
|
+
* `ms`. Map it to an expanding ring / flash to make a discrete event (a snap, a
|
|
20
|
+
* correct landing) FEEL like it clicked. Returns 0 under reduced-motion.
|
|
21
|
+
*/
|
|
22
|
+
declare function useImpulse(key: number | string, ms?: number): number;
|
|
23
|
+
//#endregion
|
|
24
|
+
export { PressSpringOpts, useImpulse, usePressSpring };
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useFrameLoop } from "../core/clock.mjs";
|
|
4
|
+
import { prefersReducedMotion, spring } from "../core/motion.mjs";
|
|
5
|
+
import { useRef, useState } from "react";
|
|
6
|
+
|
|
7
|
+
//#region src/interaction/usePressSpring.ts
|
|
8
|
+
/**
|
|
9
|
+
* Interaction "feel" hooks, the juice layer for draggable handles. Both are thin
|
|
10
|
+
* wrappers over the pure `spring` / decay maths in core/motion.ts; they own a
|
|
11
|
+
* frame loop that runs ONLY while the value is unsettled (no idle RAF), and they
|
|
12
|
+
* honor prefers-reduced-motion by snapping to the end state. SSR-safe.
|
|
13
|
+
*/
|
|
14
|
+
const EPS = 8e-4;
|
|
15
|
+
/**
|
|
16
|
+
* A scalar that springs toward `to` while `active`, back to `from` on release,
|
|
17
|
+
* e.g. a 0→1 "press" amount you map to a radius bump or halo grow. The RAF loop
|
|
18
|
+
* is gated on "still moving" so a page full of idle handles costs nothing.
|
|
19
|
+
* Under reduced-motion it returns the target immediately (no animation).
|
|
20
|
+
*/
|
|
21
|
+
function usePressSpring(active, opts = {}) {
|
|
22
|
+
const { from = 0, to = 1, stiffness = 320, damping = 26 } = opts;
|
|
23
|
+
const target = active ? to : from;
|
|
24
|
+
const reduce = prefersReducedMotion();
|
|
25
|
+
const [val, setVal] = useState(from);
|
|
26
|
+
const valRef = useRef(from);
|
|
27
|
+
const vel = useRef(0);
|
|
28
|
+
const settled = Math.abs(valRef.current - target) < EPS && Math.abs(vel.current) < EPS;
|
|
29
|
+
useFrameLoop((f) => {
|
|
30
|
+
const next = spring(valRef.current, target, vel, f.dtMs / 1e3, {
|
|
31
|
+
stiffness,
|
|
32
|
+
damping
|
|
33
|
+
});
|
|
34
|
+
if (Math.abs(next - target) < EPS && Math.abs(vel.current) < EPS) {
|
|
35
|
+
valRef.current = target;
|
|
36
|
+
vel.current = 0;
|
|
37
|
+
setVal(target);
|
|
38
|
+
} else {
|
|
39
|
+
valRef.current = next;
|
|
40
|
+
setVal(next);
|
|
41
|
+
}
|
|
42
|
+
}, { running: !reduce && !settled });
|
|
43
|
+
return reduce ? target : val;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* A one-shot impulse: jumps to 1 whenever `key` changes, then decays to 0 over
|
|
47
|
+
* `ms`. Map it to an expanding ring / flash to make a discrete event (a snap, a
|
|
48
|
+
* correct landing) FEEL like it clicked. Returns 0 under reduced-motion.
|
|
49
|
+
*/
|
|
50
|
+
function useImpulse(key, ms = 260) {
|
|
51
|
+
const [v, setV] = useState(0);
|
|
52
|
+
const amp = useRef(0);
|
|
53
|
+
const prevKey = useRef(key);
|
|
54
|
+
const reduce = prefersReducedMotion();
|
|
55
|
+
if (prevKey.current !== key) {
|
|
56
|
+
prevKey.current = key;
|
|
57
|
+
if (!reduce) amp.current = 1;
|
|
58
|
+
}
|
|
59
|
+
useFrameLoop((f) => {
|
|
60
|
+
amp.current = Math.max(0, amp.current - f.dtMs / ms);
|
|
61
|
+
setV(amp.current);
|
|
62
|
+
}, { running: !reduce && amp.current > 0 });
|
|
63
|
+
return reduce ? 0 : v;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
//#endregion
|
|
67
|
+
export { useImpulse, usePressSpring };
|
package/dist/logic/ast.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
//#region src/logic/ast.d.ts
|
|
2
2
|
/**
|
|
3
|
-
* Propositional-logic AST
|
|
3
|
+
* Propositional-logic AST, the boolean-domain sibling of the `expr` engine's
|
|
4
4
|
* numeric AST. A formula is variables joined by ¬ ∧ ∨ ⊕ → ↔. Pure + zero-dep;
|
|
5
5
|
* `evalBool` is the single evaluator every consumer (truth tables, equivalence,
|
|
6
6
|
* boolean circuits) runs.
|
package/dist/logic/index.mjs
CHANGED
|
@@ -6,7 +6,7 @@ import { cubeCovers, cubeOfSelection, cubeTerm, minimalCover, minimize, primeImp
|
|
|
6
6
|
|
|
7
7
|
//#region src/logic/index.ts
|
|
8
8
|
/**
|
|
9
|
-
* @classytic/stage logic kernel
|
|
9
|
+
* @classytic/stage logic kernel, a pure, dependency-free propositional-logic
|
|
10
10
|
* engine, the boolean-domain sibling of the `expr` (numeric) engine. Parses
|
|
11
11
|
* ¬ ∧ ∨ ⊕ → ↔ (unicode or ASCII), evaluates, builds truth tables, classifies
|
|
12
12
|
* tautology/contradiction/contingency, checks equivalence, and emits DNF/CNF +
|
|
@@ -18,11 +18,16 @@ import { cubeCovers, cubeOfSelection, cubeTerm, minimalCover, minimize, primeImp
|
|
|
18
18
|
function compileLogic(src) {
|
|
19
19
|
try {
|
|
20
20
|
const ast = parseLogic(src);
|
|
21
|
+
const vars = freeVars(ast);
|
|
21
22
|
return {
|
|
22
23
|
ok: true,
|
|
23
24
|
ast,
|
|
24
|
-
vars
|
|
25
|
-
eval: (env) =>
|
|
25
|
+
vars,
|
|
26
|
+
eval: (env) => {
|
|
27
|
+
const missing = vars.filter((v) => !(v in env));
|
|
28
|
+
if (missing.length) throw new Error(`logic: assignment is missing variable${missing.length > 1 ? "s" : ""} ${missing.join(", ")}`);
|
|
29
|
+
return evalBool(ast, env);
|
|
30
|
+
}
|
|
26
31
|
};
|
|
27
32
|
} catch (e) {
|
|
28
33
|
return {
|
|
@@ -17,11 +17,11 @@ interface Minimization {
|
|
|
17
17
|
}
|
|
18
18
|
/** All minterms a cube covers, within an n-variable space. */
|
|
19
19
|
declare function cubeCovers(c: Cube, n: number): number[];
|
|
20
|
-
/** The product term for a cube
|
|
20
|
+
/** The product term for a cube, a literal per FIXED bit (MSB = first var). */
|
|
21
21
|
declare function cubeTerm(c: Cube, vars: string[], neg?: string, join?: string): string;
|
|
22
22
|
/** Quine–McCluskey prime implicants of a set of minterms (+ optional don't-cares). */
|
|
23
23
|
declare function primeImplicants(minterms: number[], n: number, dontCares?: number[]): Cube[];
|
|
24
|
-
/** A
|
|
24
|
+
/** A minimum SOP cover: essential prime implicants + Petrick's exact cover of the rest. */
|
|
25
25
|
declare function minimalCover(minterms: number[], n: number, dontCares?: number[]): Cube[];
|
|
26
26
|
/** Full minimisation of a formula (or explicit minterms) → cover + SOP string. */
|
|
27
27
|
declare function minimize(input: LNode | {
|