tsquare 0.8.0 → 0.9.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 CHANGED
@@ -1,5 +1,20 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.9.0
4
+
5
+ The language and the renderer haven't changed: every wireframe renders exactly as in 0.8.0, and render URLs give the same images.
6
+
7
+ ### For editors and your own pages
8
+
9
+ - **`tsquare/viewer`:** the playground's zoomable board (zoom, pan, pinch, a chip per screen, dimmed while the text has problems) as a browser module with no dependencies, for showing boards in your own page. Give `createViewer` the elements, then `show()` the SVG from `renderWireframeSvg` with the size and screens from `boardLayout`. It sets the styles its zoom math depends on itself, so a page only gives the stage a size (and can style the `panning`, `animate` and `stale` classes). The playground uses it, and so will the VS Code extension's preview.
10
+ - **`languageData()`** is exported from `tsquare`: every component with its props, option words and description, plus icon names and accents. It's what the playground's highlighting and autocomplete use, now available to editors.
11
+ - **`require("tsquare")` works** in Node versions that can load ES modules from CommonJS (20.19+, 22.12+): every export now has a `default` condition next to `import`. The package is still ESM only.
12
+
13
+ ### Playground
14
+
15
+ - **Fix: pinch zoom and two-finger pan on touch screens.** Touch screens report each finger's movement separately, and each one was handled as a zoom around a different point, so the board drifted out from under the fingers while pinching, and moving two fingers together zoomed out and back in and moved the board the wrong way. Now each move pans by how far the point between the fingers moved, then zooms around it, so the part of the board between your fingers stays there. Trackpad pinch and mouse dragging were already right.
16
+ - **Tests for the playground,** which had none: every endpoint through a real HTTP server (render, PNG, language, prompt, examples, reference, the page), the page's markup against its script and against what tsquare.dev's build expects, and the viewer in jsdom (fitting, zooming to a screen, wheel and buttons, dragging, pinching and two-finger panning).
17
+
3
18
  ## 0.8.0
4
19
 
5
20
  ### Brand logos
package/README.md CHANGED
@@ -123,7 +123,7 @@ const { issues } = compileWireframe(source); // problems by line, empt
123
123
  const png = await renderWireframe(source, { format: "png", scale: 2 });
124
124
  ```
125
125
 
126
- `tsquare/playground` exports the playground's request handler, for hosting it inside your own Node server. See [Using it with AI](docs/ai.md) for the prompt and the repair loop.
126
+ `tsquare/playground` exports the playground's request handler, for hosting it inside your own Node server. `tsquare/viewer` is the playground's zoomable board (zoom, pan, pinch, a chip per screen) for your own page: pass it the elements, then `show()` the SVG from `renderWireframeSvg` with the size and screens from `boardLayout`. It sets the styles its zoom math needs itself; give the stage a size, and optionally style the classes it toggles on the stage: `panning` (while dragging), `animate` (while fitting or zooming to a screen, e.g. `.animate > * { transition: transform .25s }`) and `stale` (from `setStale`, e.g. `.stale img { opacity: .35 }`). `languageData()` lists every component, prop, option word, icon and accent, for editor highlighting and autocomplete. See [Using it with AI](docs/ai.md) for the prompt and the repair loop.
127
127
 
128
128
  ## Using it with Claude (skill)
129
129
 
@@ -0,0 +1,65 @@
1
+ import {
2
+ ACCENTS,
3
+ PRIMARY_PROP,
4
+ UNIVERSAL_PROPS,
5
+ bareWords,
6
+ componentDefinitions,
7
+ iconNames,
8
+ takesUniversalProps
9
+ } from "./chunk-W3OU5IS6.js";
10
+
11
+ // src/playground/language-data.ts
12
+ function unwrap(t) {
13
+ let cur = t;
14
+ while (cur && ["optional", "nullable", "default"].includes(cur.def?.type)) cur = cur.def.innerType;
15
+ return cur;
16
+ }
17
+ function describe(name, schema) {
18
+ const s = unwrap(schema);
19
+ const description = schema.description ?? s?.description;
20
+ const iconish = /Lucide icon|Icon names/i.test(description ?? "");
21
+ switch (s?.def?.type) {
22
+ case "enum":
23
+ return { name, kind: "enum", values: s.options, description };
24
+ case "boolean":
25
+ return { name, kind: "boolean", values: ["true", "false"], description };
26
+ case "number":
27
+ return { name, kind: "number", description };
28
+ case "array": {
29
+ const el = unwrap(s.def.element);
30
+ const objects = el?.def?.type === "union" ? el.def.options.map(unwrap) : [el];
31
+ const hasIcon = objects.some((x) => x?.def?.type === "object" && "icon" in x.shape);
32
+ return { name, kind: "list", icon: iconish || hasIcon, description };
33
+ }
34
+ case "object":
35
+ return { name, kind: "object", description };
36
+ default:
37
+ return { name, kind: "string", icon: iconish || void 0, accent: name === "accent" || void 0, description };
38
+ }
39
+ }
40
+ var cache = null;
41
+ function languageData() {
42
+ if (cache) return cache;
43
+ const components = Object.entries(componentDefinitions).map(([type, def]) => {
44
+ const shape = def.props.shape;
45
+ const props = Object.entries(shape).map(([name, schema]) => describe(name, schema));
46
+ if (takesUniversalProps(type)) for (const [name, schema] of Object.entries(UNIVERSAL_PROPS)) props.push(describe(name, schema));
47
+ if (type === "Icon") props.find((p) => p.name === "name").icon = true;
48
+ const words = bareWords(type);
49
+ const off = words.booleans.flatMap((b) => b === "on" ? ["off"] : b === "checked" ? ["unchecked"] : [`no-${b}`]);
50
+ return {
51
+ name: type.toLowerCase(),
52
+ description: def.description,
53
+ main: PRIMARY_PROP[type],
54
+ children: def.slots.length > 0,
55
+ props,
56
+ words: [...words.options.map((o) => o.value), ...words.booleans, ...off]
57
+ };
58
+ });
59
+ cache = { components, icons: [...new Set(iconNames)].sort(), accents: Object.keys(ACCENTS) };
60
+ return cache;
61
+ }
62
+
63
+ export {
64
+ languageData
65
+ };
package/dist/index.d.ts CHANGED
@@ -10,3 +10,4 @@ export { parseWireframeText, type TextIssue, type ParseResult } from "./text.js"
10
10
  export { catalog, componentDefinitions } from "./catalog.js";
11
11
  export { registry } from "./components.js";
12
12
  export { theme, DEVICES } from "./layout.js";
13
+ export { languageData, type LanguageData, type ComponentInfo, type PropInfo } from "./playground/language-data.js";
package/dist/index.js CHANGED
@@ -1,3 +1,6 @@
1
+ import {
2
+ languageData
3
+ } from "./chunks/chunk-GTWUMF6W.js";
1
4
  import {
2
5
  DEVICES,
3
6
  RENAMED_PROPS,
@@ -180,6 +183,7 @@ export {
180
183
  encodeWireframe,
181
184
  formatIssues,
182
185
  printWireframeText as formatWireframe,
186
+ languageData,
183
187
  mcpTools,
184
188
  parseWireframeText,
185
189
  registry,
@@ -1,17 +1,13 @@
1
1
  import {
2
- ACCENTS,
3
- PRIMARY_PROP,
4
- UNIVERSAL_PROPS,
5
- bareWords,
2
+ languageData
3
+ } from "../chunks/chunk-GTWUMF6W.js";
4
+ import {
6
5
  boardLayout,
7
6
  compileWireframe,
8
- componentDefinitions,
9
7
  componentDocs,
10
8
  formatIssues,
11
- iconNames,
12
9
  renderWireframePng,
13
10
  renderWireframeSvg,
14
- takesUniversalProps,
15
11
  wireframePrompt
16
12
  } from "../chunks/chunk-W3OU5IS6.js";
17
13
 
@@ -21,58 +17,6 @@ import { readFile, readdir } from "node:fs/promises";
21
17
  import path from "node:path";
22
18
  import { fileURLToPath } from "node:url";
23
19
 
24
- // src/playground/language-data.ts
25
- function unwrap(t) {
26
- let cur = t;
27
- while (cur && ["optional", "nullable", "default"].includes(cur.def?.type)) cur = cur.def.innerType;
28
- return cur;
29
- }
30
- function describe(name, schema) {
31
- const s = unwrap(schema);
32
- const description = schema.description ?? s?.description;
33
- const iconish = /Lucide icon|Icon names/i.test(description ?? "");
34
- switch (s?.def?.type) {
35
- case "enum":
36
- return { name, kind: "enum", values: s.options, description };
37
- case "boolean":
38
- return { name, kind: "boolean", values: ["true", "false"], description };
39
- case "number":
40
- return { name, kind: "number", description };
41
- case "array": {
42
- const el = unwrap(s.def.element);
43
- const objects = el?.def?.type === "union" ? el.def.options.map(unwrap) : [el];
44
- const hasIcon = objects.some((x) => x?.def?.type === "object" && "icon" in x.shape);
45
- return { name, kind: "list", icon: iconish || hasIcon, description };
46
- }
47
- case "object":
48
- return { name, kind: "object", description };
49
- default:
50
- return { name, kind: "string", icon: iconish || void 0, accent: name === "accent" || void 0, description };
51
- }
52
- }
53
- var cache = null;
54
- function languageData() {
55
- if (cache) return cache;
56
- const components = Object.entries(componentDefinitions).map(([type, def]) => {
57
- const shape = def.props.shape;
58
- const props = Object.entries(shape).map(([name, schema]) => describe(name, schema));
59
- if (takesUniversalProps(type)) for (const [name, schema] of Object.entries(UNIVERSAL_PROPS)) props.push(describe(name, schema));
60
- if (type === "Icon") props.find((p) => p.name === "name").icon = true;
61
- const words = bareWords(type);
62
- const off = words.booleans.flatMap((b) => b === "on" ? ["off"] : b === "checked" ? ["unchecked"] : [`no-${b}`]);
63
- return {
64
- name: type.toLowerCase(),
65
- description: def.description,
66
- main: PRIMARY_PROP[type],
67
- children: def.slots.length > 0,
68
- props,
69
- words: [...words.options.map((o) => o.value), ...words.booleans, ...off]
70
- };
71
- });
72
- cache = { components, icons: [...new Set(iconNames)].sort(), accents: Object.keys(ACCENTS) };
73
- return cache;
74
- }
75
-
76
20
  // src/playground/reference.ts
77
21
  var GROUPS = [
78
22
  { name: "Canvas", components: ["Board", "Screen", "Note", "Flow"] },