@classytic/stage 0.2.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.
Files changed (41) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +5 -1
  3. package/dist/assets/index.mjs +0 -1
  4. package/dist/builder/Palette.mjs +50 -89
  5. package/dist/builder/SceneBuilder.mjs +15 -73
  6. package/dist/core/index.d.mts +2 -1
  7. package/dist/core/index.mjs +2 -1
  8. package/dist/core/math.d.mts +26 -0
  9. package/dist/core/math.mjs +37 -0
  10. package/dist/finance/bizsim.d.mts +93 -0
  11. package/dist/finance/bizsim.mjs +117 -0
  12. package/dist/finance/index.d.mts +118 -0
  13. package/dist/finance/index.mjs +203 -0
  14. package/dist/index.d.mts +4 -3
  15. package/dist/index.mjs +4 -4
  16. package/dist/interaction/MovableDot.mjs +19 -0
  17. package/dist/interaction/useDraggable.mjs +24 -4
  18. package/dist/math/calculus.d.mts +22 -1
  19. package/dist/math/calculus.mjs +156 -2
  20. package/dist/math/index.d.mts +2 -2
  21. package/dist/math/index.mjs +2 -2
  22. package/dist/math/latex.mjs +8 -0
  23. package/dist/primitives/Dot.d.mts +2 -15
  24. package/dist/primitives/Dot.mjs +6 -4
  25. package/dist/primitives/Grid.d.mts +33 -17
  26. package/dist/primitives/Grid.mjs +89 -17
  27. package/dist/primitives/Label.d.mts +1 -14
  28. package/dist/primitives/Label.mjs +3 -2
  29. package/dist/primitives/Lines.d.mts +4 -32
  30. package/dist/primitives/Lines.mjs +10 -8
  31. package/dist/primitives/Shapes.d.mts +5 -43
  32. package/dist/primitives/Shapes.mjs +12 -10
  33. package/dist/primitives/index.d.mts +2 -2
  34. package/dist/primitives/index.mjs +2 -2
  35. package/dist/primitives/props.mjs +31 -0
  36. package/dist/scene/Scene.d.mts +6 -1
  37. package/dist/scene/Scene.mjs +15 -40
  38. package/dist/view/Stage.mjs +4 -11
  39. package/package.json +30 -22
  40. package/styles.css +125 -8
  41. package/dist/assets/kit/index.mjs +0 -4
@@ -2,6 +2,8 @@
2
2
 
3
3
  import { fmt } from "../core/coords.mjs";
4
4
  import { useCoords } from "../core/context.mjs";
5
+ import { geomPropsEqual } from "./props.mjs";
6
+ import { memo } from "react";
5
7
  import { jsx } from "react/jsx-runtime";
6
8
 
7
9
  //#region src/primitives/Lines.tsx
@@ -14,7 +16,7 @@ const extend = (c, a, b, back) => {
14
16
  const big = Math.hypot(c.width, c.height) * 2;
15
17
  return [back ? [a[0] - ux * big, a[1] - uy * big] : a, [a[0] + ux * big, a[1] + uy * big]];
16
18
  };
17
- function Segment({ from, to, color = "var(--stage-fg)", weight = 2, opacity = 1, dashed }) {
19
+ const Segment = memo(function Segment({ from, to, color = "var(--stage-fg)", weight = 2, opacity = 1, dashed }) {
18
20
  const c = useCoords();
19
21
  const a = c.toPx(from.x, from.y);
20
22
  const b = c.toPx(to.x, to.y);
@@ -29,8 +31,8 @@ function Segment({ from, to, color = "var(--stage-fg)", weight = 2, opacity = 1,
29
31
  strokeLinecap: "round",
30
32
  strokeDasharray: dashed ? "6 6" : void 0
31
33
  });
32
- }
33
- function Line({ from, to, color = "var(--stage-axis)", weight = 2, opacity = 1, dashed }) {
34
+ }, geomPropsEqual);
35
+ const Line = memo(function Line({ from, to, color = "var(--stage-axis)", weight = 2, opacity = 1, dashed }) {
34
36
  const c = useCoords();
35
37
  const [p1, p2] = extend(c, c.toPx(from.x, from.y), c.toPx(to.x, to.y), true);
36
38
  return /* @__PURE__ */ jsx("line", {
@@ -43,8 +45,8 @@ function Line({ from, to, color = "var(--stage-axis)", weight = 2, opacity = 1,
43
45
  opacity,
44
46
  strokeDasharray: dashed ? "6 6" : void 0
45
47
  });
46
- }
47
- function Ray({ from, to, color = "var(--stage-axis)", weight = 2, opacity = 1, dashed }) {
48
+ }, geomPropsEqual);
49
+ const Ray = memo(function Ray({ from, to, color = "var(--stage-axis)", weight = 2, opacity = 1, dashed }) {
48
50
  const c = useCoords();
49
51
  const [p1, p2] = extend(c, c.toPx(from.x, from.y), c.toPx(to.x, to.y), false);
50
52
  return /* @__PURE__ */ jsx("line", {
@@ -57,8 +59,8 @@ function Ray({ from, to, color = "var(--stage-axis)", weight = 2, opacity = 1, d
57
59
  opacity,
58
60
  strokeDasharray: dashed ? "6 6" : void 0
59
61
  });
60
- }
61
- function Vector({ tail = {
62
+ }, geomPropsEqual);
63
+ const Vector = memo(function Vector({ tail = {
62
64
  x: 0,
63
65
  y: 0
64
66
  }, tip, color = "var(--stage-accent-2)", weight = 2.5, opacity = 1 }) {
@@ -76,7 +78,7 @@ function Vector({ tail = {
76
78
  strokeLinecap: "round",
77
79
  markerEnd: "url(#stage-arrow)"
78
80
  });
79
- }
81
+ }, geomPropsEqual);
80
82
 
81
83
  //#endregion
82
84
  export { Line, Ray, Segment, Vector };
@@ -1,6 +1,5 @@
1
1
  import { Vec2 } from "../core/vec.mjs";
2
2
  import { StyleProps } from "./props.mjs";
3
- import { ReactNode } from "react";
4
3
 
5
4
  //#region src/primitives/Shapes.d.ts
6
5
  interface CircleProps extends StyleProps {
@@ -9,15 +8,7 @@ interface CircleProps extends StyleProps {
9
8
  fill?: string;
10
9
  fillOpacity?: number;
11
10
  }
12
- declare function Circle({
13
- center,
14
- r,
15
- color,
16
- fill,
17
- fillOpacity,
18
- weight,
19
- opacity
20
- }: CircleProps): ReactNode;
11
+ declare const Circle: import("react").NamedExoticComponent<CircleProps>;
21
12
  interface EllipseProps extends StyleProps {
22
13
  center: Vec2;
23
14
  rx: number;
@@ -25,52 +16,23 @@ interface EllipseProps extends StyleProps {
25
16
  fill?: string;
26
17
  fillOpacity?: number;
27
18
  }
28
- declare function Ellipse({
29
- center,
30
- rx,
31
- ry,
32
- color,
33
- fill,
34
- fillOpacity,
35
- weight,
36
- opacity
37
- }: EllipseProps): ReactNode;
19
+ declare const Ellipse: import("react").NamedExoticComponent<EllipseProps>;
38
20
  interface PolygonProps extends StyleProps {
39
21
  points: Vec2[];
40
22
  fill?: string;
41
23
  fillOpacity?: number;
42
24
  }
43
- declare function Polygon({
44
- points,
45
- color,
46
- fill,
47
- fillOpacity,
48
- weight,
49
- opacity
50
- }: PolygonProps): ReactNode;
25
+ declare const Polygon: import("react").NamedExoticComponent<PolygonProps>;
51
26
  interface PolylineProps extends StyleProps {
52
27
  points: Vec2[];
53
28
  }
54
- declare function Polyline({
55
- points,
56
- color,
57
- weight,
58
- opacity,
59
- dashed
60
- }: PolylineProps): ReactNode;
29
+ declare const Polyline: import("react").NamedExoticComponent<PolylineProps>;
61
30
  /** Low-level pixel-space path (d is already in pixels). */
62
31
  interface PathProps extends StyleProps {
63
32
  d: string;
64
33
  fill?: string;
65
34
  fillOpacity?: number;
66
35
  }
67
- declare function Path({
68
- d,
69
- color,
70
- fill,
71
- fillOpacity,
72
- weight,
73
- opacity
74
- }: PathProps): ReactNode;
36
+ declare const Path: import("react").NamedExoticComponent<PathProps>;
75
37
  //#endregion
76
38
  export { Circle, CircleProps, Ellipse, EllipseProps, Path, PathProps, Polygon, PolygonProps, Polyline, PolylineProps };
@@ -2,6 +2,8 @@
2
2
 
3
3
  import { fmt } from "../core/coords.mjs";
4
4
  import { useCoords } from "../core/context.mjs";
5
+ import { geomPropsEqual } from "./props.mjs";
6
+ import { memo } from "react";
5
7
  import { jsx } from "react/jsx-runtime";
6
8
 
7
9
  //#region src/primitives/Shapes.tsx
@@ -9,7 +11,7 @@ const toPoints = (c, points) => points.map((p) => {
9
11
  const [x, y] = c.toPx(p.x, p.y);
10
12
  return `${fmt(x)},${fmt(y)}`;
11
13
  }).join(" ");
12
- function Circle({ center, r, color = "var(--stage-accent)", fill = "none", fillOpacity = .12, weight = 2, opacity = 1 }) {
14
+ const Circle = memo(function Circle({ center, r, color = "var(--stage-accent)", fill = "none", fillOpacity = .12, weight = 2, opacity = 1 }) {
13
15
  const c = useCoords();
14
16
  const [cx, cy] = c.toPx(center.x, center.y);
15
17
  return /* @__PURE__ */ jsx("ellipse", {
@@ -23,8 +25,8 @@ function Circle({ center, r, color = "var(--stage-accent)", fill = "none", fillO
23
25
  fillOpacity: fill === "none" ? void 0 : fillOpacity,
24
26
  opacity
25
27
  });
26
- }
27
- function Ellipse({ center, rx, ry, color = "var(--stage-accent)", fill = "none", fillOpacity = .12, weight = 2, opacity = 1 }) {
28
+ }, geomPropsEqual);
29
+ const Ellipse = memo(function Ellipse({ center, rx, ry, color = "var(--stage-accent)", fill = "none", fillOpacity = .12, weight = 2, opacity = 1 }) {
28
30
  const c = useCoords();
29
31
  const [cx, cy] = c.toPx(center.x, center.y);
30
32
  return /* @__PURE__ */ jsx("ellipse", {
@@ -38,8 +40,8 @@ function Ellipse({ center, rx, ry, color = "var(--stage-accent)", fill = "none",
38
40
  fillOpacity: fill === "none" ? void 0 : fillOpacity,
39
41
  opacity
40
42
  });
41
- }
42
- function Polygon({ points, color = "var(--stage-accent)", fill = "var(--stage-accent)", fillOpacity = .12, weight = 2, opacity = 1 }) {
43
+ }, geomPropsEqual);
44
+ const Polygon = memo(function Polygon({ points, color = "var(--stage-accent)", fill = "var(--stage-accent)", fillOpacity = .12, weight = 2, opacity = 1 }) {
43
45
  return /* @__PURE__ */ jsx("polygon", {
44
46
  points: toPoints(useCoords(), points),
45
47
  stroke: color,
@@ -49,8 +51,8 @@ function Polygon({ points, color = "var(--stage-accent)", fill = "var(--stage-ac
49
51
  opacity,
50
52
  strokeLinejoin: "round"
51
53
  });
52
- }
53
- function Polyline({ points, color = "var(--stage-fg)", weight = 2, opacity = 1, dashed }) {
54
+ }, geomPropsEqual);
55
+ const Polyline = memo(function Polyline({ points, color = "var(--stage-fg)", weight = 2, opacity = 1, dashed }) {
54
56
  return /* @__PURE__ */ jsx("polyline", {
55
57
  points: toPoints(useCoords(), points),
56
58
  fill: "none",
@@ -61,8 +63,8 @@ function Polyline({ points, color = "var(--stage-fg)", weight = 2, opacity = 1,
61
63
  strokeLinecap: "round",
62
64
  strokeDasharray: dashed ? "6 6" : void 0
63
65
  });
64
- }
65
- function Path({ d, color = "var(--stage-fg)", fill = "none", fillOpacity = 1, weight = 2, opacity = 1 }) {
66
+ }, geomPropsEqual);
67
+ const Path = memo(function Path({ d, color = "var(--stage-fg)", fill = "none", fillOpacity = 1, weight = 2, opacity = 1 }) {
66
68
  return /* @__PURE__ */ jsx("path", {
67
69
  d,
68
70
  stroke: color,
@@ -73,7 +75,7 @@ function Path({ d, color = "var(--stage-fg)", fill = "none", fillOpacity = 1, we
73
75
  strokeLinejoin: "round",
74
76
  strokeLinecap: "round"
75
77
  });
76
- }
78
+ }, geomPropsEqual);
77
79
 
78
80
  //#endregion
79
81
  export { Circle, Ellipse, Path, Polygon, Polyline };
@@ -4,7 +4,7 @@ import { Line, LineProps, Ray, Segment, SegmentProps, Vector, VectorProps } from
4
4
  import { Circle, CircleProps, Ellipse, EllipseProps, Path, PathProps, Polygon, PolygonProps, Polyline, PolylineProps } from "./Shapes.mjs";
5
5
  import { Label, LabelProps } from "./Label.mjs";
6
6
  import { Tex, TexProps } from "./Tex.mjs";
7
- import { Axes, AxesProps, Grid, GridProps, niceStep } from "./Grid.mjs";
7
+ import { Axes, AxesProps, ClearZone, Grid, GridProps, clearOfLabel, niceStep } from "./Grid.mjs";
8
8
  import { OfXProps, OfYProps, ParametricProps, Plot } from "./Plot.mjs";
9
9
  import { CanvasLayer, CanvasLayerProps } from "./CanvasLayer.mjs";
10
- export { type A11yProps, Axes, type AxesProps, CanvasLayer, type CanvasLayerProps, Circle, type CircleProps, Dot, type DotProps, Ellipse, type EllipseProps, Grid, type GridProps, Label, type LabelProps, Line, type LineProps, type OfXProps, type OfYProps, type ParametricProps, Path, type PathProps, Plot, Point, Polygon, type PolygonProps, Polyline, type PolylineProps, Ray, Segment, type SegmentProps, type StyleProps, Tex, type TexProps, Vector, type VectorProps, niceStep };
10
+ export { type A11yProps, Axes, type AxesProps, CanvasLayer, type CanvasLayerProps, Circle, type CircleProps, type ClearZone, Dot, type DotProps, Ellipse, type EllipseProps, Grid, type GridProps, Label, type LabelProps, Line, type LineProps, type OfXProps, type OfYProps, type ParametricProps, Path, type PathProps, Plot, Point, Polygon, type PolygonProps, Polyline, type PolylineProps, Ray, Segment, type SegmentProps, type StyleProps, Tex, type TexProps, Vector, type VectorProps, clearOfLabel, niceStep };
@@ -3,8 +3,8 @@ import { Line, Ray, Segment, Vector } from "./Lines.mjs";
3
3
  import { Circle, Ellipse, Path, Polygon, Polyline } from "./Shapes.mjs";
4
4
  import { Label } from "./Label.mjs";
5
5
  import { Tex } from "./Tex.mjs";
6
- import { Axes, Grid, niceStep } from "./Grid.mjs";
6
+ import { Axes, Grid, clearOfLabel, niceStep } from "./Grid.mjs";
7
7
  import { Plot } from "./Plot.mjs";
8
8
  import { CanvasLayer } from "./CanvasLayer.mjs";
9
9
 
10
- export { Axes, CanvasLayer, Circle, Dot, Ellipse, Grid, Label, Line, Path, Plot, Point, Polygon, Polyline, Ray, Segment, Tex, Vector, niceStep };
10
+ export { Axes, CanvasLayer, Circle, Dot, Ellipse, Grid, Label, Line, Path, Plot, Point, Polygon, Polyline, Ray, Segment, Tex, Vector, clearOfLabel, niceStep };
@@ -0,0 +1,31 @@
1
+ //#region src/primitives/props.ts
2
+ const MAX_DEPTH = 4;
3
+ const valEq = (a, b, depth) => {
4
+ if (Object.is(a, b)) return true;
5
+ if (depth <= 0) return false;
6
+ if (typeof a !== "object" || typeof b !== "object" || a === null || b === null) return false;
7
+ if ("$$typeof" in a || "$$typeof" in b) return false;
8
+ if (Array.isArray(a) || Array.isArray(b)) {
9
+ if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length) return false;
10
+ for (let i = 0; i < a.length; i++) if (!valEq(a[i], b[i], depth - 1)) return false;
11
+ return true;
12
+ }
13
+ const ka = Object.keys(a);
14
+ if (ka.length !== Object.keys(b).length) return false;
15
+ for (const k of ka) {
16
+ if (!(k in b)) return false;
17
+ if (!valEq(a[k], b[k], depth - 1)) return false;
18
+ }
19
+ return true;
20
+ };
21
+ /**
22
+ * Value-based props comparator for `React.memo` on geometry primitives.
23
+ * Labs recreate `Vec2`/`points` objects every render (often 60×/s under a frame
24
+ * tick), so identity-based memo never hits; comparing coordinate VALUES lets
25
+ * static shapes skip reconciliation while anything that actually moved still
26
+ * re-renders. Functions and React elements compare by reference (safe fallback).
27
+ */
28
+ const geomPropsEqual = (prev, next) => valEq(prev, next, MAX_DEPTH);
29
+
30
+ //#endregion
31
+ export { geomPropsEqual };
@@ -15,6 +15,9 @@ interface SceneProps {
15
15
  /** Author opt-in: start a sim running immediately (ambient motion) instead of
16
16
  * the default "press Play". A SceneDoc with no `meta.sims` is always static. */
17
17
  autoPlay?: boolean;
18
+ /** Optional controlled playback for hosts that provide their own transport. */
19
+ playing?: boolean;
20
+ onPlayingChange?: (playing: boolean) => void;
18
21
  }
19
22
  declare function Scene({
20
23
  doc,
@@ -25,7 +28,9 @@ declare function Scene({
25
28
  height,
26
29
  view,
27
30
  ariaLabel,
28
- autoPlay
31
+ autoPlay,
32
+ playing: playingProp,
33
+ onPlayingChange
29
34
  }: SceneProps): ReactNode;
30
35
  //#endregion
31
36
  export { Scene, SceneProps };
@@ -45,7 +45,7 @@ function autoView(resolved) {
45
45
  yMax: Math.max(...ys) + pad
46
46
  };
47
47
  }
48
- function Scene({ doc, onChange, interactive = true, showGrid = true, showAxes = true, height, view, ariaLabel = "Interactive figure", autoPlay = false }) {
48
+ function Scene({ doc, onChange, interactive = true, showGrid = true, showAxes = true, height, view, ariaLabel = "Interactive figure", autoPlay = false, playing: playingProp, onPlayingChange }) {
49
49
  const [overlay, setOverlay] = useState(/* @__PURE__ */ new Map());
50
50
  const prevRef = useRef(void 0);
51
51
  const sims = doc.meta?.sims;
@@ -55,14 +55,22 @@ function Scene({ doc, onChange, interactive = true, showGrid = true, showAxes =
55
55
  const [frame, setFrame] = useState(0);
56
56
  const { ref: rootRef, inView } = useInView();
57
57
  const [done, setDone] = useState(false);
58
- const [playing, setPlaying] = useState(autoPlay);
58
+ const [internalPlaying, setInternalPlaying] = useState(autoPlay);
59
+ const playing = playingProp ?? internalPlaying;
60
+ const setPlaying = (next) => {
61
+ if (playingProp === void 0) setInternalPlaying(next);
62
+ onPlayingChange?.(next);
63
+ };
59
64
  useFrameLoop((f) => {
60
65
  if (!sims?.length || !simStates.current) return;
61
66
  const next = stepSims(sims, simStates.current, Math.min(.05, f.dtMs / 1e3));
62
67
  simStates.current = next.states;
63
68
  simScalars.current = next.scalars;
64
69
  setFrame((n) => (n + 1) % 1e6);
65
- if (next.done) setDone(true);
70
+ if (next.done) {
71
+ setDone(true);
72
+ setPlaying(false);
73
+ }
66
74
  }, { running: !!sims?.length && inView && playing && !done });
67
75
  const merged = useMemo(() => {
68
76
  const scalars = simScalars.current;
@@ -95,7 +103,7 @@ function Scene({ doc, onChange, interactive = true, showGrid = true, showAxes =
95
103
  const hasSims = !!sims?.length;
96
104
  return /* @__PURE__ */ jsxs("div", {
97
105
  ref: rootRef,
98
- style: { position: "relative" },
106
+ className: "stage-scene",
99
107
  children: [
100
108
  /* @__PURE__ */ jsxs(Stage, {
101
109
  view: v,
@@ -114,30 +122,9 @@ function Scene({ doc, onChange, interactive = true, showGrid = true, showAxes =
114
122
  type: "button",
115
123
  onClick: () => setPlaying(true),
116
124
  "aria-label": "Play simulation",
117
- style: {
118
- position: "absolute",
119
- inset: 0,
120
- display: "flex",
121
- alignItems: "center",
122
- justifyContent: "center",
123
- background: "color-mix(in oklab, var(--stage-bg) 38%, transparent)",
124
- border: "none",
125
- borderRadius: 12,
126
- cursor: "pointer"
127
- },
125
+ className: "stage-scene__play-overlay",
128
126
  children: /* @__PURE__ */ jsx("span", {
129
- style: {
130
- display: "inline-flex",
131
- alignItems: "center",
132
- gap: 8,
133
- padding: "11px 26px",
134
- borderRadius: 999,
135
- background: "var(--stage-accent)",
136
- color: "#fff",
137
- fontWeight: 800,
138
- fontSize: 16,
139
- boxShadow: "0 6px 18px rgba(0,0,0,.28)"
140
- },
127
+ className: "stage-scene__play-label",
141
128
  children: "▶ Play"
142
129
  })
143
130
  }),
@@ -145,19 +132,7 @@ function Scene({ doc, onChange, interactive = true, showGrid = true, showAxes =
145
132
  type: "button",
146
133
  onClick: () => setPlaying(false),
147
134
  "aria-label": "Pause simulation",
148
- style: {
149
- position: "absolute",
150
- top: 10,
151
- right: 10,
152
- width: 34,
153
- height: 34,
154
- borderRadius: 999,
155
- border: "1px solid var(--stage-grid)",
156
- background: "color-mix(in oklab, var(--stage-bg) 80%, transparent)",
157
- color: "var(--stage-fg)",
158
- cursor: "pointer",
159
- fontSize: 13
160
- },
135
+ className: "stage-scene__pause",
161
136
  children: "⏸"
162
137
  })
163
138
  ]
@@ -31,7 +31,7 @@ function Stage({ view = DEFAULT_VIEW, width, height, aspectRatio, pad = 12, pres
31
31
  }), [
32
32
  w,
33
33
  h,
34
- view,
34
+ `${view.xMin} ${view.xMax} ${view.yMin} ${view.yMax}`,
35
35
  pad,
36
36
  preserveAspect
37
37
  ]);
@@ -43,8 +43,7 @@ function Stage({ view = DEFAULT_VIEW, width, height, aspectRatio, pad = 12, pres
43
43
  } : void 0;
44
44
  return /* @__PURE__ */ jsx("div", {
45
45
  ref: wrapRef,
46
- className,
47
- style: { width: "100%" },
46
+ className: ["stage-root", className].filter(Boolean).join(" "),
48
47
  children: /* @__PURE__ */ jsxs("svg", {
49
48
  ref: svgRef,
50
49
  width: w,
@@ -53,14 +52,8 @@ function Stage({ view = DEFAULT_VIEW, width, height, aspectRatio, pad = 12, pres
53
52
  role: "group",
54
53
  "aria-label": ariaLabel,
55
54
  onPointerDown: handlePointer,
56
- style: {
57
- display: "block",
58
- background,
59
- borderRadius: 12,
60
- border: "1px solid var(--stage-grid)",
61
- userSelect: "none",
62
- touchAction: "none"
63
- },
55
+ className: "stage-canvas",
56
+ style: { background },
64
57
  children: [/* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsx("marker", {
65
58
  id: "stage-arrow",
66
59
  viewBox: "0 0 10 10",
package/package.json CHANGED
@@ -1,13 +1,12 @@
1
1
  {
2
2
  "name": "@classytic/stage",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Domain-neutral visual primitive engine for the web. Declarative SVG diagram/math primitives, draggable handles, a math↔pixel coordinate system, a motion core + energy effect defs, theming, pure sim cores, and a small kit of neutral glyph primitives. Reactive, web-native, agent-drivable. The render foundation under @classytic/labs (subject-matter glyphs live there); canvas + 3D subpaths later.",
5
5
  "author": "Classytic",
6
6
  "license": "MIT",
7
7
  "type": "module",
8
8
  "sideEffects": [
9
- "**/*.css",
10
- "**/assets/**"
9
+ "**/*.css"
11
10
  ],
12
11
  "engines": {
13
12
  "node": ">=22"
@@ -52,6 +51,10 @@
52
51
  "types": "./dist/math/index.d.mts",
53
52
  "default": "./dist/math/index.mjs"
54
53
  },
54
+ "./logic": {
55
+ "types": "./dist/logic/index.d.mts",
56
+ "default": "./dist/logic/index.mjs"
57
+ },
55
58
  "./sim": {
56
59
  "types": "./dist/sim/index.d.mts",
57
60
  "default": "./dist/sim/index.mjs"
@@ -72,6 +75,10 @@
72
75
  "types": "./dist/chem/index.d.mts",
73
76
  "default": "./dist/chem/index.mjs"
74
77
  },
78
+ "./finance": {
79
+ "types": "./dist/finance/index.d.mts",
80
+ "default": "./dist/finance/index.mjs"
81
+ },
75
82
  "./steps": {
76
83
  "types": "./dist/steps/index.d.mts",
77
84
  "default": "./dist/steps/index.mjs"
@@ -88,21 +95,6 @@
88
95
  "LICENSE",
89
96
  "README.md"
90
97
  ],
91
- "scripts": {
92
- "build": "tsdown",
93
- "dev": "tsdown --watch",
94
- "typecheck": "tsc --noEmit",
95
- "sync": "node scripts/sync-stage.mjs",
96
- "pretest": "npm run build",
97
- "test": "vitest run",
98
- "verify": "npm run typecheck && npm test",
99
- "push": "classytic-push",
100
- "changeset": "changeset",
101
- "version-packages": "changeset version",
102
- "release": "npm run build && changeset publish",
103
- "prepublishOnly": "npm run typecheck && npm run build && npm test",
104
- "clean": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\""
105
- },
106
98
  "peerDependencies": {
107
99
  "katex": ">=0.16",
108
100
  "react": ">=19",
@@ -117,12 +109,11 @@
117
109
  "@changesets/cli": "^2.27.9",
118
110
  "@classytic/dev-tools": "^0.2.0",
119
111
  "@testing-library/react": "^16.3.2",
120
- "@types/katex": "^0.16.7",
121
112
  "@types/node": "^22.0.0",
122
113
  "@types/react": "^19.2.0",
123
114
  "@types/react-dom": "^19.2.0",
124
115
  "happy-dom": "^20.0.0",
125
- "katex": "^0.16.11",
116
+ "katex": "^0.18.7",
126
117
  "react": "^19.2.0",
127
118
  "react-dom": "^19.2.0",
128
119
  "tsdown": "^0.22.0",
@@ -141,5 +132,22 @@
141
132
  "math",
142
133
  "engine",
143
134
  "primitives"
144
- ]
145
- }
135
+ ],
136
+ "scripts": {
137
+ "build": "tsdown",
138
+ "dev": "tsdown --watch",
139
+ "typecheck": "tsc --noEmit",
140
+ "sync": "node scripts/sync-stage.mjs",
141
+ "pretest": "npm run build",
142
+ "test": "vitest run",
143
+ "verify": "npm run typecheck && npm test",
144
+ "package:check": "node scripts/package-check.mjs",
145
+ "package:consumer": "node scripts/packed-consumer-check.mjs",
146
+ "verify:release": "npm run typecheck && npm test && npm run package:check && npm run package:consumer",
147
+ "push": "classytic-push",
148
+ "changeset": "changeset",
149
+ "version-packages": "changeset version",
150
+ "release": "npm run build && changeset publish",
151
+ "clean": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\""
152
+ }
153
+ }