@react-scad/core 0.1.19 → 0.1.21

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/README.md CHANGED
@@ -12,7 +12,7 @@ Render JSX to **SCAD** models using the [React reconciler](https://github.com/fa
12
12
 
13
13
  ![Example](./assets/example.gif)
14
14
 
15
- *Rocket example with animated rotation.*
15
+ *Rocket example with animated translation.*
16
16
 
17
17
  ---
18
18
 
@@ -220,7 +220,7 @@ All listed SCAD primitives and operations are implemented. Prop names follow SCA
220
220
  3. **Build and test** before committing:
221
221
  ```bash
222
222
  pnpm run build
223
- pnpm run dev
223
+ pnpm run sandbox:dev
224
224
  ```
225
225
 
226
226
  4. **Format and lint** your code:
package/dist/log.d.ts CHANGED
@@ -11,5 +11,6 @@ export declare const log: {
11
11
  progress(msg: string): void;
12
12
  complete(ms: number): void;
13
13
  outputPath(path: string): void;
14
+ fileSize(bytes: number): void;
14
15
  stop(): void;
15
16
  };
package/dist/log.js CHANGED
@@ -16,6 +16,11 @@ const PAD = " ";
16
16
  function line(msg) {
17
17
  console.log(msg);
18
18
  }
19
+ function formatSize(bytes) {
20
+ if (bytes >= 1024)
21
+ return `${(bytes / 1024).toFixed(2)} kB`;
22
+ return `${bytes} B`;
23
+ }
19
24
  export const log = {
20
25
  banner() {
21
26
  line(`${PAD}${c.cyan("◆")} ${c.bold(TOOL_NAME)} ${c.dim(VERSION)} ${c.dim("-")} ${c.dim("Ctrl+C to exit")}`);
@@ -24,11 +29,15 @@ export const log = {
24
29
  line(`${PAD}${c.dim("○")} ${c.dim(msg)}`);
25
30
  },
26
31
  complete(ms) {
27
- line(`${PAD}${c.green("✓")} ${c.dim("Built")} ${c.dim(`in ${ms}ms`)}`);
32
+ const sec = (ms / 1000).toFixed(2);
33
+ line(`${PAD}${c.green("✓")} ${c.green("Done")} ${c.dim(`in ${sec}s`)}`);
28
34
  },
29
35
  outputPath(path) {
30
36
  line(`${PAD}${c.dim("→")} ${c.cyan(path)}`);
31
37
  },
38
+ fileSize(bytes) {
39
+ line(`${PAD}${c.dim("+")} ${c.dim(formatSize(bytes))}`);
40
+ },
32
41
  stop() {
33
42
  line(`${PAD}${c.dim("Stopped.")}`);
34
43
  },
@@ -1,11 +1,12 @@
1
1
  import * as React from "react";
2
+ import { formatScadExpr } from "../utils.js";
2
3
  import { Primitive } from "./primitive.js";
3
4
  export const Circle = (props) => React.createElement(Primitive, { ...props, type: "circle" });
4
5
  Circle.displayName = "Circle";
5
6
  export function serialize(node, _indent, _ctx) {
6
7
  const rVal = node.r ?? 1;
7
8
  const dVal = node.d;
8
- let args = dVal != null ? `d = ${String(dVal)}` : `r = ${String(rVal)}`;
9
+ let args = dVal != null ? `d = ${formatScadExpr(dVal)}` : `r = ${formatScadExpr(rVal)}`;
9
10
  if (node.$fn != null)
10
11
  args += `, $fn = ${node.$fn}`;
11
12
  return `circle(${args});`;
@@ -1,11 +1,11 @@
1
1
  import * as React from "react";
2
- import { formatVec3 } from "../utils.js";
2
+ import { formatScadExpr, formatVec3 } from "../utils.js";
3
3
  import { Primitive } from "./primitive.js";
4
4
  export const Cube = (props) => React.createElement(Primitive, { ...props, type: "cube" });
5
5
  Cube.displayName = "Cube";
6
6
  export function serialize(node, _indent, _ctx) {
7
7
  const s = typeof node.size === "number"
8
- ? String(node.size)
8
+ ? formatScadExpr(node.size)
9
9
  : typeof node.size === "string"
10
10
  ? node.size
11
11
  : formatVec3(node.size);
@@ -1,9 +1,10 @@
1
1
  import * as React from "react";
2
+ import { formatScadExpr } from "../utils.js";
2
3
  import { Primitive } from "./primitive.js";
3
4
  export const Cylinder = (props) => React.createElement(Primitive, { ...props, type: "cylinder" });
4
5
  Cylinder.displayName = "Cylinder";
5
6
  export function serialize(node, _indent, _ctx) {
6
- let args = `h = ${String(node.h)}, r1 = ${String(node.r1)}, r2 = ${String(node.r2)}`;
7
+ let args = `h = ${formatScadExpr(node.h)}, r1 = ${formatScadExpr(node.r1)}, r2 = ${formatScadExpr(node.r2)}`;
7
8
  if (node.$fn != null)
8
9
  args += `, $fn = ${node.$fn}`;
9
10
  return `cylinder(${args});`;
@@ -1,5 +1,5 @@
1
1
  import * as React from "react";
2
- import { formatVec2 } from "../utils.js";
2
+ import { formatScadExpr, formatVec2 } from "../utils.js";
3
3
  import { Primitive } from "./primitive.js";
4
4
  export const LinearExtrude = (props) => React.createElement(Primitive, { ...props, type: "linear_extrude" });
5
5
  LinearExtrude.displayName = "LinearExtrude";
@@ -7,15 +7,15 @@ function formatScale(scale) {
7
7
  if (scale == null)
8
8
  return undefined;
9
9
  if (typeof scale === "number" || typeof scale === "string")
10
- return String(scale);
10
+ return formatScadExpr(scale);
11
11
  return formatVec2(scale);
12
12
  }
13
13
  export function serialize(node, indent, ctx) {
14
- const parts = [`height = ${String(node.height)}`];
14
+ const parts = [`height = ${formatScadExpr(node.height)}`];
15
15
  if (node.center === true)
16
16
  parts.push("center = true");
17
17
  if (node.twist != null)
18
- parts.push(`twist = ${String(node.twist)}`);
18
+ parts.push(`twist = ${formatScadExpr(node.twist)}`);
19
19
  const scaleStr = formatScale(node.scale);
20
20
  if (scaleStr != null)
21
21
  parts.push(`scale = ${scaleStr}`);
@@ -1,11 +1,12 @@
1
1
  import * as React from "react";
2
+ import { formatScadExpr } from "../utils.js";
2
3
  import { Primitive } from "./primitive.js";
3
4
  export const RotateExtrude = (props) => React.createElement(Primitive, { ...props, type: "rotate_extrude" });
4
5
  RotateExtrude.displayName = "RotateExtrude";
5
6
  export function serialize(node, indent, ctx) {
6
7
  const parts = [];
7
8
  if (node.angle != null)
8
- parts.push(`angle = ${String(node.angle)}`);
9
+ parts.push(`angle = ${formatScadExpr(node.angle)}`);
9
10
  if (node.convexity != null)
10
11
  parts.push(`convexity = ${node.convexity}`);
11
12
  if (node.$fn != null)
@@ -1,11 +1,12 @@
1
1
  import * as React from "react";
2
+ import { formatScadExpr } from "../utils.js";
2
3
  import { Primitive } from "./primitive.js";
3
4
  export const Sphere = (props) => React.createElement(Primitive, { ...props, type: "sphere" });
4
5
  Sphere.displayName = "Sphere";
5
6
  export function serialize(node, _indent, _ctx) {
6
7
  const rVal = node.r ?? 1;
7
8
  const dVal = node.d;
8
- let args = dVal != null ? `d = ${String(dVal)}` : `r = ${String(rVal)}`;
9
+ let args = dVal != null ? `d = ${formatScadExpr(dVal)}` : `r = ${formatScadExpr(rVal)}`;
9
10
  if (node.$fn != null)
10
11
  args += `, $fn = ${node.$fn}`;
11
12
  return `sphere(${args});`;
@@ -1,11 +1,11 @@
1
1
  import * as React from "react";
2
- import { formatVec2 } from "../utils.js";
2
+ import { formatScadExpr, formatVec2 } from "../utils.js";
3
3
  import { Primitive } from "./primitive.js";
4
4
  export const Square = (props) => React.createElement(Primitive, { ...props, type: "square" });
5
5
  Square.displayName = "Square";
6
6
  export function serialize(node, _indent, _ctx) {
7
7
  const s = typeof node.size === "number"
8
- ? String(node.size)
8
+ ? formatScadExpr(node.size)
9
9
  : typeof node.size === "string"
10
10
  ? node.size
11
11
  : formatVec2(node.size);
@@ -27,6 +27,7 @@ export function createRoot(path) {
27
27
  log.complete(Date.now() - start);
28
28
  if (path) {
29
29
  log.outputPath(resolve(path));
30
+ log.fileSize(Buffer.byteLength(toScad(container), "utf8"));
30
31
  }
31
32
  },
32
33
  toScad() {
@@ -76,6 +76,8 @@ export function toScad(container) {
76
76
  const ctx = {
77
77
  serializeNode: (n, i) => serializeNode(n, i, ctx),
78
78
  };
79
- const body = container.children.map((n) => serializeNode(n, "", ctx)).join("\n\n");
79
+ const body = container.children
80
+ .map((n) => serializeNode(n, "", ctx))
81
+ .join("\n\n");
80
82
  return body ? `${CREDIT}\n\n${body}` : CREDIT;
81
83
  }
package/dist/utils.d.ts CHANGED
@@ -1,4 +1,6 @@
1
- import type { Vec2, Vec3 } from "./types.js";
1
+ import type { ScadExpr, Vec2, Vec3 } from "./types.js";
2
+ export declare function formatNumber(n: number): string;
3
+ export declare function formatScadExpr(x: ScadExpr): string;
2
4
  export declare function formatVec2(v: Vec2): string;
3
5
  export declare function formatVec3(v: Vec3): string;
4
6
  export declare function formatPoints2D(points: [number, number][]): string;
package/dist/utils.js CHANGED
@@ -1,19 +1,28 @@
1
+ export function formatNumber(n) {
2
+ if (Number.isInteger(n))
3
+ return String(n);
4
+ const s = n.toFixed(6);
5
+ return s.replace(/\.?0+$/, "");
6
+ }
7
+ export function formatScadExpr(x) {
8
+ return typeof x === "number" ? formatNumber(x) : x;
9
+ }
1
10
  export function formatVec2(v) {
2
11
  if (typeof v === "number" || typeof v === "string")
3
- return String(v);
4
- return `[${String(v[0])}, ${String(v[1])}]`;
12
+ return formatScadExpr(v);
13
+ return `[${formatScadExpr(v[0])}, ${formatScadExpr(v[1])}]`;
5
14
  }
6
15
  export function formatVec3(v) {
7
16
  if (typeof v === "number" || typeof v === "string")
8
- return String(v);
9
- return `[${String(v[0])}, ${String(v[1])}, ${String(v[2])}]`;
17
+ return formatScadExpr(v);
18
+ return `[${formatScadExpr(v[0])}, ${formatScadExpr(v[1])}, ${formatScadExpr(v[2])}]`;
10
19
  }
11
20
  export function formatPoints2D(points) {
12
- return `[${points.map((p) => `[${p[0]}, ${p[1]}]`).join(", ")}]`;
21
+ return `[${points.map((p) => `[${formatNumber(p[0])}, ${formatNumber(p[1])}]`).join(", ")}]`;
13
22
  }
14
23
  export function formatPoints3D(points) {
15
- return `[${points.map((p) => `[${p[0]}, ${p[1]}, ${p[2]}]`).join(", ")}]`;
24
+ return `[${points.map((p) => `[${formatNumber(p[0])}, ${formatNumber(p[1])}, ${formatNumber(p[2])}]`).join(", ")}]`;
16
25
  }
17
26
  export function formatFaces(faces) {
18
- return `[${faces.map((f) => `[${f.join(", ")}]`).join(", ")}]`;
27
+ return `[${faces.map((f) => `[${f.map(formatNumber).join(", ")}]`).join(", ")}]`;
19
28
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@react-scad/core",
3
- "version": "0.1.19",
3
+ "version": "0.1.21",
4
4
  "description": "Render JSX to OpenSCAD models using the React reconciler",
5
5
  "keywords": [
6
6
  "react",