tsquare 0.2.0 → 0.3.1
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 +20 -6
- package/dist/catalog.d.ts +24 -8
- package/dist/chunks/{chunk-L6GTIZQH.js → chunk-YCIRLKKD.js} +389 -161
- package/dist/cli.js +1 -1
- package/dist/icons.d.ts +2 -3
- package/dist/index.d.ts +3 -1
- package/dist/index.js +24 -1
- package/dist/playground/index.d.ts +12 -1
- package/dist/playground/index.html +180 -356
- package/dist/playground/index.js +100 -10
- package/dist/playground/language-data.d.ts +28 -0
- package/dist/playground/playground.js +50 -0
- package/dist/prompt.d.ts +1 -1
- package/dist/render.d.ts +21 -1
- package/dist/share.d.ts +8 -0
- package/dist/text.d.ts +6 -1
- package/dist/upgrade.d.ts +41 -0
- package/examples/checkout.tsq +15 -0
- package/examples/dashboard.tsq +27 -0
- package/examples/notes-mobile.tsq +9 -9
- package/examples/notes-web.tsq +6 -6
- package/examples/sign-in.tsq +14 -0
- package/examples/states.tsq +16 -0
- package/package.json +9 -1
- package/skill/tsquare/SKILL.md +3 -2
- package/skill/tsquare/reference.md +5 -4
package/dist/playground/index.js
CHANGED
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
import {
|
|
2
|
+
ACCENTS,
|
|
3
|
+
PRIMARY_PROP,
|
|
4
|
+
bareWords,
|
|
5
|
+
boardLayout,
|
|
2
6
|
compileWireframe,
|
|
7
|
+
componentDefinitions,
|
|
3
8
|
componentDocs,
|
|
4
9
|
formatIssues,
|
|
10
|
+
iconNames,
|
|
5
11
|
renderWireframePng,
|
|
6
12
|
renderWireframeSvg,
|
|
7
13
|
wireframePrompt
|
|
8
|
-
} from "../chunks/chunk-
|
|
14
|
+
} from "../chunks/chunk-YCIRLKKD.js";
|
|
9
15
|
|
|
10
16
|
// src/playground/index.ts
|
|
11
17
|
import { createServer } from "node:http";
|
|
@@ -13,6 +19,56 @@ import { readFile, readdir } from "node:fs/promises";
|
|
|
13
19
|
import path from "node:path";
|
|
14
20
|
import { fileURLToPath } from "node:url";
|
|
15
21
|
|
|
22
|
+
// src/playground/language-data.ts
|
|
23
|
+
function unwrap(t) {
|
|
24
|
+
let cur = t;
|
|
25
|
+
while (cur && ["optional", "nullable", "default"].includes(cur.def?.type)) cur = cur.def.innerType;
|
|
26
|
+
return cur;
|
|
27
|
+
}
|
|
28
|
+
function describe(name, schema) {
|
|
29
|
+
const s = unwrap(schema);
|
|
30
|
+
const description = schema.description ?? s?.description;
|
|
31
|
+
const iconish = /Lucide icon|Icon names/i.test(description ?? "");
|
|
32
|
+
switch (s?.def?.type) {
|
|
33
|
+
case "enum":
|
|
34
|
+
return { name, kind: "enum", values: s.options, description };
|
|
35
|
+
case "boolean":
|
|
36
|
+
return { name, kind: "boolean", values: ["true", "false"], description };
|
|
37
|
+
case "number":
|
|
38
|
+
return { name, kind: "number", description };
|
|
39
|
+
case "array": {
|
|
40
|
+
const el = unwrap(s.def.element);
|
|
41
|
+
const hasIcon = el?.def?.type === "object" && "icon" in el.shape;
|
|
42
|
+
return { name, kind: "list", icon: iconish || hasIcon, description };
|
|
43
|
+
}
|
|
44
|
+
case "object":
|
|
45
|
+
return { name, kind: "object", description };
|
|
46
|
+
default:
|
|
47
|
+
return { name, kind: "string", icon: iconish || void 0, accent: name === "accent" || void 0, description };
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
var cache = null;
|
|
51
|
+
function languageData() {
|
|
52
|
+
if (cache) return cache;
|
|
53
|
+
const components = Object.entries(componentDefinitions).map(([type, def]) => {
|
|
54
|
+
const shape = def.props.shape;
|
|
55
|
+
const props = Object.entries(shape).map(([name, schema]) => describe(name, schema));
|
|
56
|
+
if (type === "Icon") props.find((p) => p.name === "name").icon = true;
|
|
57
|
+
const words = bareWords(type);
|
|
58
|
+
const off = words.booleans.flatMap((b) => b === "on" ? ["off"] : b === "checked" ? ["unchecked"] : [`no-${b}`]);
|
|
59
|
+
return {
|
|
60
|
+
name: type.toLowerCase(),
|
|
61
|
+
description: def.description,
|
|
62
|
+
main: PRIMARY_PROP[type],
|
|
63
|
+
children: def.slots.length > 0,
|
|
64
|
+
props,
|
|
65
|
+
words: [...words.options.map((o) => o.value), ...words.booleans, ...off]
|
|
66
|
+
};
|
|
67
|
+
});
|
|
68
|
+
cache = { components, icons: [...new Set(iconNames)].sort(), accents: Object.keys(ACCENTS) };
|
|
69
|
+
return cache;
|
|
70
|
+
}
|
|
71
|
+
|
|
16
72
|
// src/playground/reference.ts
|
|
17
73
|
var GROUPS = [
|
|
18
74
|
{ name: "Canvas", components: ["Board", "Screen", "Note"] },
|
|
@@ -166,7 +222,9 @@ var EXAMPLES = {
|
|
|
166
222
|
button primary sm "Small"
|
|
167
223
|
button primary "Medium"
|
|
168
224
|
button primary lg "Large"
|
|
169
|
-
|
|
225
|
+
stack row gap=8 align=center
|
|
226
|
+
button secondary "Back" leadingIcon=chevron-left
|
|
227
|
+
button primary "Next" trailingIcon=chevron-right
|
|
170
228
|
button primary "Full width" fullWidth
|
|
171
229
|
text "With a board accent, primary buttons fill with it and ghost buttons use it for text." sm muted`,
|
|
172
230
|
Input: `board
|
|
@@ -225,11 +283,11 @@ var EXAMPLES = {
|
|
|
225
283
|
ListItem: `board
|
|
226
284
|
screen custom width=400 height=440
|
|
227
285
|
list
|
|
228
|
-
listitem "
|
|
286
|
+
listitem "leadingIcon=settings" subtitle="trailing=chevron" leadingIcon=settings trailing=chevron
|
|
229
287
|
listitem "leading=avatar" subtitle="trailing=text" leading=avatar trailing=text trailingText="9:41"
|
|
230
288
|
listitem "leading=image" subtitle="trailing=badge" leading=image trailing=badge trailingText="3"
|
|
231
289
|
listitem "leading=checkbox" leading=checkbox trailing=toggle
|
|
232
|
-
listitem "
|
|
290
|
+
listitem "trailingIcon=trash-2" trailingIcon=trash-2
|
|
233
291
|
listitem leading=image trailing=chevron`,
|
|
234
292
|
Table: `board
|
|
235
293
|
screen custom width=520 height=400
|
|
@@ -252,15 +310,15 @@ var EXAMPLES = {
|
|
|
252
310
|
drawer left size=260
|
|
253
311
|
heading "Menu" level=3
|
|
254
312
|
list dividers=false
|
|
255
|
-
listitem "Inbox"
|
|
256
|
-
listitem "Sent"
|
|
313
|
+
listitem "Inbox" leadingIcon=inbox
|
|
314
|
+
listitem "Sent" leadingIcon=send
|
|
257
315
|
screen phone "side=bottom"
|
|
258
316
|
navbar "Photo" leading=back
|
|
259
317
|
image height=300
|
|
260
318
|
drawer bottom "Share" size=280
|
|
261
319
|
list dividers=false
|
|
262
|
-
listitem "Copy link"
|
|
263
|
-
listitem "Message"
|
|
320
|
+
listitem "Copy link" leadingIcon=link
|
|
321
|
+
listitem "Message" leadingIcon=message-circle`
|
|
264
322
|
};
|
|
265
323
|
|
|
266
324
|
// src/playground/index.ts
|
|
@@ -280,6 +338,28 @@ ${formatIssues(issues)}`);
|
|
|
280
338
|
}
|
|
281
339
|
return problems;
|
|
282
340
|
}
|
|
341
|
+
var scriptCache = null;
|
|
342
|
+
function playgroundScript() {
|
|
343
|
+
scriptCache ??= (async () => {
|
|
344
|
+
const built = path.join(here, "playground.js");
|
|
345
|
+
try {
|
|
346
|
+
return await readFile(built, "utf8");
|
|
347
|
+
} catch {
|
|
348
|
+
const { build } = await import("esbuild");
|
|
349
|
+
const out = await build({ ...PLAYGROUND_BUNDLE, entryPoints: [path.join(here, "app.ts")], write: false });
|
|
350
|
+
return out.outputFiles[0].text;
|
|
351
|
+
}
|
|
352
|
+
})();
|
|
353
|
+
return scriptCache;
|
|
354
|
+
}
|
|
355
|
+
var PLAYGROUND_BUNDLE = {
|
|
356
|
+
bundle: true,
|
|
357
|
+
format: "esm",
|
|
358
|
+
platform: "browser",
|
|
359
|
+
target: "es2022",
|
|
360
|
+
minify: true,
|
|
361
|
+
legalComments: "eof"
|
|
362
|
+
};
|
|
283
363
|
var referenceCache = null;
|
|
284
364
|
function reference() {
|
|
285
365
|
referenceCache ??= Promise.all(
|
|
@@ -290,9 +370,11 @@ function reference() {
|
|
|
290
370
|
).then((components) => ({ groups: GROUPS, components }));
|
|
291
371
|
return referenceCache;
|
|
292
372
|
}
|
|
373
|
+
var EXAMPLE_ORDER = ["sign-in", "dashboard", "checkout", "states", "notes-mobile", "notes-web"];
|
|
374
|
+
var rank = (name) => EXAMPLE_ORDER.indexOf(name) + 1 || EXAMPLE_ORDER.length + 1;
|
|
293
375
|
async function examples() {
|
|
294
376
|
const dir = path.join(packageRoot, "examples");
|
|
295
|
-
const files = (await readdir(dir)).filter((f) => f.endsWith(".tsq")).sort();
|
|
377
|
+
const files = (await readdir(dir)).filter((f) => f.endsWith(".tsq")).sort((a, b) => rank(a.slice(0, -4)) - rank(b.slice(0, -4)) || a.localeCompare(b));
|
|
296
378
|
return Promise.all(files.map(async (f) => ({ name: f.replace(/\.tsq$/, ""), source: await readFile(path.join(dir, f), "utf8") })));
|
|
297
379
|
}
|
|
298
380
|
function readBody(req) {
|
|
@@ -321,6 +403,12 @@ function createPlaygroundHandler() {
|
|
|
321
403
|
res.end(await readFile(path.join(here, "index.html")));
|
|
322
404
|
return true;
|
|
323
405
|
}
|
|
406
|
+
if (req.method === "GET" && url.pathname === "/playground.js") {
|
|
407
|
+
res.writeHead(200, { "content-type": "text/javascript; charset=utf-8" });
|
|
408
|
+
res.end(await playgroundScript());
|
|
409
|
+
return true;
|
|
410
|
+
}
|
|
411
|
+
if (req.method === "GET" && url.pathname === "/api/language") return json(res, 200, languageData());
|
|
324
412
|
if (req.method === "GET" && url.pathname === "/mark.png") {
|
|
325
413
|
res.writeHead(200, { "content-type": "image/png", "cache-control": "max-age=3600" });
|
|
326
414
|
res.end(await readFile(path.join(packageRoot, "assets", "mark.png")));
|
|
@@ -337,7 +425,8 @@ function createPlaygroundHandler() {
|
|
|
337
425
|
const { spec, issues } = compileWireframe(await readBody(req));
|
|
338
426
|
if (url.pathname === "/api/render") {
|
|
339
427
|
if (!spec || issues.length) return json(res, 200, { issues });
|
|
340
|
-
|
|
428
|
+
const { width, height, items } = boardLayout(spec);
|
|
429
|
+
return json(res, 200, { issues, svg: await renderWireframeSvg(spec, { skipValidation: true }), width, height, items });
|
|
341
430
|
}
|
|
342
431
|
if (!spec || issues.length) return json(res, 400, { issues });
|
|
343
432
|
const scale = Math.min(4, Math.max(1, Number(url.searchParams.get("scale") ?? 2)));
|
|
@@ -370,6 +459,7 @@ ${problems.join("\n")}`);
|
|
|
370
459
|
return server;
|
|
371
460
|
}
|
|
372
461
|
export {
|
|
462
|
+
PLAYGROUND_BUNDLE,
|
|
373
463
|
checkReferenceExamples,
|
|
374
464
|
createPlaygroundHandler,
|
|
375
465
|
startPlayground
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export interface PropInfo {
|
|
2
|
+
name: string;
|
|
3
|
+
kind: "string" | "number" | "boolean" | "enum" | "list" | "object";
|
|
4
|
+
/** Allowed values for enums (and booleans: true/false). */
|
|
5
|
+
values?: string[];
|
|
6
|
+
/** The value is a Lucide icon name (or a list of them). */
|
|
7
|
+
icon?: boolean;
|
|
8
|
+
/** The value is an accent color. */
|
|
9
|
+
accent?: boolean;
|
|
10
|
+
description?: string;
|
|
11
|
+
}
|
|
12
|
+
export interface ComponentInfo {
|
|
13
|
+
/** Lowercase, as written: "listitem". */
|
|
14
|
+
name: string;
|
|
15
|
+
description: string;
|
|
16
|
+
/** The prop a quoted string fills, if any. */
|
|
17
|
+
main?: string;
|
|
18
|
+
children: boolean;
|
|
19
|
+
props: PropInfo[];
|
|
20
|
+
/** Bare words this component accepts: option values, switch names and their off forms. */
|
|
21
|
+
words: string[];
|
|
22
|
+
}
|
|
23
|
+
export interface LanguageData {
|
|
24
|
+
components: ComponentInfo[];
|
|
25
|
+
icons: string[];
|
|
26
|
+
accents: string[];
|
|
27
|
+
}
|
|
28
|
+
export declare function languageData(): LanguageData;
|