tsquare 0.3.1 → 0.3.2
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 +91 -0
- package/README.md +1 -1
- package/dist/catalog.d.ts +2 -0
- package/dist/chunks/{chunk-YCIRLKKD.js → chunk-X46EDSCQ.js} +2 -1
- package/dist/cli.js +1 -1
- package/dist/index.js +1 -1
- package/dist/playground/index.js +13 -5
- package/package.json +5 -3
- package/skill/tsquare/reference.md +1 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.3.2
|
|
4
|
+
|
|
5
|
+
- **`grow` on Select**, like Input: `select "State" grow` fills the rest of a row. Sonnet wrote it in 5 of 9 eval runs, its only remaining mistake; with it, every stored Sonnet text output is valid.
|
|
6
|
+
- **Docs:** a new [Embedding](docs/embedding.md) page for Notion, GitHub and your own site, and the Radio page shows radios side by side (`stack row` + `radio`).
|
|
7
|
+
- **Tests and CI:** a test suite (`npm test`), run on Node 20, 22 and 24 for every pull request, plus a check that eval scores, docs and the skill match what's committed.
|
|
8
|
+
- `CHANGELOG.md` is now included in the npm package.
|
|
9
|
+
|
|
10
|
+
## 0.3.1
|
|
11
|
+
|
|
12
|
+
### Older wireframes are upgraded in one step
|
|
13
|
+
|
|
14
|
+
- All support for older syntax now lives in one module (`upgradeWireframe`, `upgradeSpec`), run before parsing. The parser, catalog and renderer only know the current language.
|
|
15
|
+
- **Links made before 0.3.0 render again** when a comment follows an element on the same line (`screen phone "Home" # main`): the comment moves onto its own line. Text you write or paste still gets the error, so new comments go on their own line.
|
|
16
|
+
- `decodeWireframe` returns the upgraded text, so a decoded link always means what it did when it was made.
|
|
17
|
+
|
|
18
|
+
### Better suggestions for unknown icons
|
|
19
|
+
|
|
20
|
+
- Common guesses that aren't Lucide names now suggest what was meant: `compose` → `square-pen`, `call` → `phone`, `person` → `user`, `bag` → `shopping-bag`, `notification` → `bell`, `close` → `x`.
|
|
21
|
+
- Among equally close matches, the usual directions come first: `chevron` suggests `chevron-right, chevron-left, chevron-down, chevron-up`.
|
|
22
|
+
- On a list item, `trailingIcon=chevron` (or `toggle`, `avatar`…) says to write `trailing=chevron`, since that's a kind, not an icon.
|
|
23
|
+
|
|
24
|
+
## 0.3.0
|
|
25
|
+
|
|
26
|
+
### Renamed: `icon` is now `leadingIcon` on Button and ListItem
|
|
27
|
+
|
|
28
|
+
Buttons and list items take an icon on either side, so the prop names now say which side:
|
|
29
|
+
|
|
30
|
+
| Before | Now |
|
|
31
|
+
|---|---|
|
|
32
|
+
| `button "Download" icon=download` | `button "Download" leadingIcon=download` |
|
|
33
|
+
| (not possible) | `button "Next" trailingIcon=chevron-right` |
|
|
34
|
+
| `listitem "Inbox" leading=icon icon=inbox` | `listitem "Inbox" leadingIcon=inbox` |
|
|
35
|
+
| `listitem "Delete" trailing=icon trailingIcon=trash-2` | `listitem "Delete" trailingIcon=trash-2` |
|
|
36
|
+
|
|
37
|
+
- **Nothing breaks.** The old `icon=` spelling still works on both components, so existing files and shared render links render the same. `tsquare fmt` rewrites it to `leadingIcon=`. The prompt, the skill and the docs only teach the new names.
|
|
38
|
+
- **Buttons can have a trailing icon**, for Next, external links or dropdowns. Both sides work together.
|
|
39
|
+
- `leading` and `trailing` on ListItem stay as before. They pick what fills each side (`avatar`, `image`, `checkbox`, `chevron`, `badge`, `toggle`, …). An icon or text value implies its kind, so `leading=icon` and `trailing=icon` are optional.
|
|
40
|
+
- `icon` stays as it is on TabBar items (`{label=Home icon=house}`) and on the Icon component.
|
|
41
|
+
|
|
42
|
+
### Changed: comments go on their own line
|
|
43
|
+
|
|
44
|
+
A line that starts with `#` is a comment. Anywhere else, `#` is ordinary text, so order numbers, tags and hex colors need no quotes:
|
|
45
|
+
|
|
46
|
+
```tsquare
|
|
47
|
+
# the orders page
|
|
48
|
+
screen desktop "Orders"
|
|
49
|
+
table columns=[Order, Customer] data=[[#1001, Ana Torres], [#1002, Ben Lee]]
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
- **Why:** comments used to start at any `#` after a space. That cut off `[#1001, Ana Torres]` and broke the table, which happened to Sonnet in 3 of 4 eval runs. Across 160 eval outputs, models never wrote a comment.
|
|
53
|
+
- **Upgrading:** a comment after an element on the same line (`screen phone "Home" # main`) is now an error that tells you to move it to its own line. Nothing is dropped silently.
|
|
54
|
+
|
|
55
|
+
### Clearer errors for props on the wrong component
|
|
56
|
+
|
|
57
|
+
When a word or prop belongs to a different component, the error now says which one:
|
|
58
|
+
|
|
59
|
+
```
|
|
60
|
+
Input: fullWidth is a Button prop, not an Input one; an Input already fills its width (width=… sets a fixed one), so remove it
|
|
61
|
+
Card has no prop "border": border is a Stack prop, not a Card one
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
A prop or list wrapped onto its own line says where it belongs, instead of "unknown component":
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
trailing=…: props go on the same line as their component; move it to the end of line 15
|
|
68
|
+
a list must stay on one line; join this to line 6
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Playground
|
|
72
|
+
|
|
73
|
+
- A CodeMirror editor: highlighting, autocomplete for components, options, props, Lucide icons and accent colors, and problems underlined on their line.
|
|
74
|
+
- Light and dark themes.
|
|
75
|
+
- Zoom and pan, zoom to a single screen, full screen and a resizable split.
|
|
76
|
+
- Copy link: share link, SVG/PNG image links, Markdown and HTML snippets.
|
|
77
|
+
- An examples gallery with thumbnails.
|
|
78
|
+
|
|
79
|
+
### Library
|
|
80
|
+
|
|
81
|
+
- `encodeWireframe` / `decodeWireframe` for share and render links.
|
|
82
|
+
- `boardLayout()` returns the board size and each screen's position.
|
|
83
|
+
|
|
84
|
+
### List items: a value implies its kind
|
|
85
|
+
|
|
86
|
+
- `trailingIcon=trash-2` without `trailing=icon` used to render nothing, silently. Now the value implies the kind.
|
|
87
|
+
- A value that contradicts an explicit kind is an error that names the fix, for example: `leadingIcon only shows with leading=icon (this item has leading=avatar); remove one of them`.
|
|
88
|
+
|
|
89
|
+
### Examples
|
|
90
|
+
|
|
91
|
+
- New: `sign-in`, `dashboard`, `checkout` and `states`.
|
package/README.md
CHANGED
|
@@ -50,7 +50,7 @@ A wireframe can be embedded anywhere an image works (Notion, GitHub, docs sites)
|
|
|
50
50
|

|
|
51
51
|
```
|
|
52
52
|
|
|
53
|
-
The playground's **Copy link** menu makes these. The text is compressed into the URL, not encrypted, so anyone with the link can read it; see [privacy](https://tsquare.dev/privacy). `encodeWireframe` and `decodeWireframe` in the library produce and read the same links.
|
|
53
|
+
The playground's **Copy link** menu makes these; [Embedding](docs/embedding.md) has the steps for Notion, GitHub and your own site. The text is compressed into the URL, not encrypted, so anyone with the link can read it; see [privacy](https://tsquare.dev/privacy). `encodeWireframe` and `decodeWireframe` in the library produce and read the same links.
|
|
54
54
|
|
|
55
55
|
## The language
|
|
56
56
|
|
package/dist/catalog.d.ts
CHANGED
|
@@ -341,6 +341,7 @@ export declare const componentDefinitions: {
|
|
|
341
341
|
label: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
342
342
|
value: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
343
343
|
placeholder: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
344
|
+
grow: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
|
|
344
345
|
width: z.ZodOptional<z.ZodNullable<z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>>>;
|
|
345
346
|
}, z.core.$strip>;
|
|
346
347
|
slots: never[];
|
|
@@ -864,6 +865,7 @@ export declare const catalog: import("@json-render/core").Catalog<{
|
|
|
864
865
|
label: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
865
866
|
value: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
866
867
|
placeholder: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
868
|
+
grow: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
|
|
867
869
|
width: z.ZodOptional<z.ZodNullable<z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>>>;
|
|
868
870
|
}, z.core.$strip>;
|
|
869
871
|
slots: never[];
|
|
@@ -433,6 +433,7 @@ var componentDefinitions = {
|
|
|
433
433
|
label: o(z.string()),
|
|
434
434
|
value: o(z.string()),
|
|
435
435
|
placeholder: o(z.string()),
|
|
436
|
+
grow: o(z.boolean()).describe("Fill the remaining space in a row"),
|
|
436
437
|
width: o(z.union([z.number(), z.string()])).describe("Fixed width, e.g. 320. Default fills the space.")
|
|
437
438
|
}),
|
|
438
439
|
slots: [],
|
|
@@ -1053,7 +1054,7 @@ function Input({ element, dir }) {
|
|
|
1053
1054
|
}
|
|
1054
1055
|
function Select({ element, dir }) {
|
|
1055
1056
|
const p = element.props;
|
|
1056
|
-
return /* @__PURE__ */ jsxs(Box, { style: { flexDirection: "column", gap: 6, ...fieldWidth(p.width, dir) }, children: [
|
|
1057
|
+
return /* @__PURE__ */ jsxs(Box, { style: { flexDirection: "column", gap: 6, ...fieldWidth(p.width, dir), ...p.grow ? { flexGrow: 1 } : {} }, children: [
|
|
1057
1058
|
/* @__PURE__ */ jsx(FieldLabel, { text: p.label }),
|
|
1058
1059
|
/* @__PURE__ */ jsxs(Field, { children: [
|
|
1059
1060
|
/* @__PURE__ */ jsx(Box, { style: { flexGrow: 1, color: p.value ? theme.ink : theme.muted }, children: p.value ?? p.placeholder ?? "Select\u2026" }),
|
package/dist/cli.js
CHANGED
package/dist/index.js
CHANGED
package/dist/playground/index.js
CHANGED
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
renderWireframePng,
|
|
12
12
|
renderWireframeSvg,
|
|
13
13
|
wireframePrompt
|
|
14
|
-
} from "../chunks/chunk-
|
|
14
|
+
} from "../chunks/chunk-X46EDSCQ.js";
|
|
15
15
|
|
|
16
16
|
// src/playground/index.ts
|
|
17
17
|
import { createServer } from "node:http";
|
|
@@ -242,18 +242,26 @@ var EXAMPLES = {
|
|
|
242
242
|
checkbox "Checked" checked
|
|
243
243
|
checkbox "Unchecked"`,
|
|
244
244
|
Radio: `board
|
|
245
|
-
screen custom width=
|
|
245
|
+
screen custom width=380 height=230
|
|
246
246
|
radio "Selected" checked
|
|
247
247
|
radio "Not selected"
|
|
248
|
-
radio "Not selected"
|
|
248
|
+
radio "Not selected"
|
|
249
|
+
text "Side by side: put them in a row" sm muted
|
|
250
|
+
stack row gap=20
|
|
251
|
+
radio "Standard" checked
|
|
252
|
+
radio "Express"
|
|
253
|
+
radio "Pickup"`,
|
|
249
254
|
Toggle: `board
|
|
250
255
|
screen custom width=300 height=100
|
|
251
256
|
toggle "On" on
|
|
252
257
|
toggle "Off" off`,
|
|
253
258
|
Select: `board
|
|
254
|
-
screen custom width=
|
|
259
|
+
screen custom width=380 height=260
|
|
255
260
|
select "Country" value="Mexico"
|
|
256
|
-
select "Size" placeholder="Choose one" width=160
|
|
261
|
+
select "Size" placeholder="Choose one" width=160
|
|
262
|
+
stack row gap=12
|
|
263
|
+
input "City" placeholder="Monterrey" grow
|
|
264
|
+
select "State" value="Nuevo Le\xF3n" grow`,
|
|
257
265
|
NavBar: `board
|
|
258
266
|
screen custom width=380 height=240 padding=0 gap=0
|
|
259
267
|
navbar "leading=menu" leading=menu actions=[search, bell]
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tsquare",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.2",
|
|
4
4
|
"description": "Wireframes in plain text: easy for LLMs to write, fast to render as SVG or PNG.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"wireframe",
|
|
@@ -44,7 +44,8 @@
|
|
|
44
44
|
"examples/*.tsq",
|
|
45
45
|
"assets/mark.png",
|
|
46
46
|
"LICENSE",
|
|
47
|
-
"README.md"
|
|
47
|
+
"README.md",
|
|
48
|
+
"CHANGELOG.md"
|
|
48
49
|
],
|
|
49
50
|
"engines": {
|
|
50
51
|
"node": ">=20"
|
|
@@ -62,7 +63,8 @@
|
|
|
62
63
|
"eval:prompts": "tsx eval/prompts.ts",
|
|
63
64
|
"eval:score": "tsx eval/score.ts",
|
|
64
65
|
"build": "tsx scripts/build.ts",
|
|
65
|
-
"prepare": "npm run build"
|
|
66
|
+
"prepare": "npm run build",
|
|
67
|
+
"test": "tsx --test test/*.test.ts"
|
|
66
68
|
},
|
|
67
69
|
"dependencies": {
|
|
68
70
|
"@fontsource/inter": "5.3.0",
|
|
@@ -142,6 +142,7 @@ Dropdown field (closed state).
|
|
|
142
142
|
- label: string (main text)
|
|
143
143
|
- value: string
|
|
144
144
|
- placeholder: string
|
|
145
|
+
- grow: boolean — Fill the remaining space in a row
|
|
145
146
|
- width: number | string — Fixed width, e.g. 320. Default fills the space.
|
|
146
147
|
|
|
147
148
|
### NavBar
|