@tamagui/cli 3.0.0-beta.1187.1 → 3.0.0-beta.1202.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/dist/cli.cjs +1 -7
- package/dist/generate-prompt.cjs +3 -474
- package/package.json +9 -9
- package/src/cli.ts +1 -12
- package/src/generate-prompt.ts +2 -609
- package/types/generate-prompt.d.ts +0 -4
- package/types/generate-prompt.d.ts.map +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -95,13 +95,7 @@ const COMMAND_MAP = {
|
|
|
95
95
|
await loadTamagui({
|
|
96
96
|
...options.tamaguiOptions,
|
|
97
97
|
platform: "web"
|
|
98
|
-
});
|
|
99
|
-
const { generatePrompt } = require("./generate-prompt.cjs");
|
|
100
|
-
const { join } = require("node:path");
|
|
101
|
-
await generatePrompt({
|
|
102
|
-
...options,
|
|
103
|
-
output: join(options.paths.dotDir, "prompt.md")
|
|
104
|
-
});
|
|
98
|
+
}, true);
|
|
105
99
|
}
|
|
106
100
|
},
|
|
107
101
|
"generate-css": {
|
package/dist/generate-prompt.cjs
CHANGED
|
@@ -25,11 +25,9 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
25
25
|
}) : target, mod));
|
|
26
26
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
27
27
|
var generate_prompt_exports = {};
|
|
28
|
-
__export(generate_prompt_exports, {
|
|
29
|
-
generateMarkdown: () => generateMarkdown,
|
|
30
|
-
generatePrompt: () => generatePrompt
|
|
31
|
-
});
|
|
28
|
+
__export(generate_prompt_exports, { generatePrompt: () => generatePrompt });
|
|
32
29
|
module.exports = __toCommonJS(generate_prompt_exports);
|
|
30
|
+
var import_static = require("@tamagui/static");
|
|
33
31
|
var import_node_path = require("node:path");
|
|
34
32
|
var FS = __toESM(require("fs-extra"));
|
|
35
33
|
async function generatePrompt(options) {
|
|
@@ -49,479 +47,10 @@ async function generatePrompt(options) {
|
|
|
49
47
|
const explicitChoice = options.styleValueSyntax || process.env.TAMAGUI_STYLE_VALUE_SYNTAX || configSetting;
|
|
50
48
|
const { resolveStyleValueSyntax } = require("./setup-prompt.cjs");
|
|
51
49
|
const resolvedSyntax = await resolveStyleValueSyntax(explicitChoice);
|
|
52
|
-
const markdown =
|
|
50
|
+
const markdown = (0, import_static.generateConfigMarkdown)(config, { styleValueSyntax: resolvedSyntax });
|
|
53
51
|
const outputPath = output || (0, import_node_path.join)(process.cwd(), "tamagui-prompt.md");
|
|
54
52
|
await FS.writeFile(outputPath, markdown, "utf-8");
|
|
55
53
|
console.info(`
|
|
56
54
|
\u2713 Generated prompt file at ${outputPath}
|
|
57
55
|
`);
|
|
58
56
|
}
|
|
59
|
-
function generateMarkdown(config, options) {
|
|
60
|
-
const sections = [];
|
|
61
|
-
sections.push("# Tamagui Configuration\n\n");
|
|
62
|
-
sections.push("This document provides an overview of the Tamagui configuration for this project.\n\n");
|
|
63
|
-
const shorthands = config.tamaguiConfig?.shorthands || {};
|
|
64
|
-
const reverseShorthands = {};
|
|
65
|
-
for (const [short, full] of Object.entries(shorthands)) {
|
|
66
|
-
reverseShorthands[full] = short;
|
|
67
|
-
}
|
|
68
|
-
const getPropName = (fullProp) => {
|
|
69
|
-
const settings2 = config.tamaguiConfig?.settings || {};
|
|
70
|
-
if (settings2.onlyAllowShorthands) {
|
|
71
|
-
if (reverseShorthands[fullProp]) return reverseShorthands[fullProp];
|
|
72
|
-
if (fullProp === "backgroundColor" && reverseShorthands["background"]) {
|
|
73
|
-
return reverseShorthands["background"];
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
return fullProp;
|
|
77
|
-
};
|
|
78
|
-
const settings = config.tamaguiConfig?.settings || {};
|
|
79
|
-
const syntaxChoice = options?.styleValueSyntax || settings.styleValueSyntax || "both";
|
|
80
|
-
sections.push("## Configuration Settings\n\n");
|
|
81
|
-
sections.push("**IMPORTANT:** These settings affect how you write Tamagui code in this project.\n\n");
|
|
82
|
-
if (settings.defaultFont) {
|
|
83
|
-
sections.push(`### Default Font: \`${settings.defaultFont}\`
|
|
84
|
-
|
|
85
|
-
`);
|
|
86
|
-
sections.push(`All text components will use the "${settings.defaultFont}" font family by default.
|
|
87
|
-
|
|
88
|
-
`);
|
|
89
|
-
}
|
|
90
|
-
if (settings.onlyAllowShorthands !== void 0) {
|
|
91
|
-
sections.push(`### Only Allow Shorthands: \`${settings.onlyAllowShorthands}\`
|
|
92
|
-
|
|
93
|
-
`);
|
|
94
|
-
if (settings.onlyAllowShorthands) {
|
|
95
|
-
sections.push("**You MUST use shorthand properties in this project.**\n\n");
|
|
96
|
-
sections.push("Full property names are not allowed. For example:\n");
|
|
97
|
-
sections.push("- ✅ `<View w=\"10\" />` (correct)\n");
|
|
98
|
-
sections.push("- ❌ `<View width=\"10\" />` (will error)\n\n");
|
|
99
|
-
sections.push("See the Shorthand Properties section below for all available shorthands.\n\n");
|
|
100
|
-
} else {
|
|
101
|
-
sections.push("You can use either shorthand or full property names.\n\n");
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
if (syntaxChoice === "string") {
|
|
105
|
-
sections.push("### Style value syntax: `string`\n\n");
|
|
106
|
-
sections.push("Only the string form is allowed in this project (e.g. `bg=\"red hover:blue\"`).\n\n");
|
|
107
|
-
} else if (syntaxChoice === "object") {
|
|
108
|
-
sections.push("### Style value syntax: `object`\n\n");
|
|
109
|
-
sections.push("Only the object form is allowed in this project (e.g. `bg={{ default: 'red', hover: 'blue' }}`).\n\n");
|
|
110
|
-
} else {
|
|
111
|
-
sections.push("### Style value syntax\n\n");
|
|
112
|
-
sections.push("Both string and object style value syntax are allowed.\n\n");
|
|
113
|
-
}
|
|
114
|
-
if (settings.addThemeClassName !== void 0) {
|
|
115
|
-
sections.push(`### Theme Class Name: \`${settings.addThemeClassName}\`
|
|
116
|
-
|
|
117
|
-
`);
|
|
118
|
-
if (settings.addThemeClassName === "html") {
|
|
119
|
-
sections.push("Theme classes are applied to the root HTML element.\n\n");
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
if (settings.allowedStyleValues) {
|
|
123
|
-
sections.push("### Allowed Style Values\n\n");
|
|
124
|
-
sections.push(`Type validation: \`${JSON.stringify(settings.allowedStyleValues)}\`.
|
|
125
|
-
|
|
126
|
-
`);
|
|
127
|
-
sections.push("Single-token values are type-checked. Run `tamagui check --strict` to also validate conditional payloads.\n\n");
|
|
128
|
-
}
|
|
129
|
-
sections.push("## Flat Value Grammar\n\n");
|
|
130
|
-
sections.push("Conditional style values follow this grammar:\n\n");
|
|
131
|
-
sections.push("```txt\n");
|
|
132
|
-
sections.push("value := base? clause*\n");
|
|
133
|
-
sections.push("clause := modifier(:modifier)*:payload\n");
|
|
134
|
-
sections.push("```\n\n");
|
|
135
|
-
sections.push("- No `$` sigils: bare token names (`bg=\"background\"`, not `bg=\"$background\"`).\n");
|
|
136
|
-
sections.push("- Kebab-case theme names: `background-hover`, `border-color`, `shadow-color`.\n");
|
|
137
|
-
sections.push("- Numbers are px: `p={4}` is 4px, while `p=\"4\"` is space token 4.\n");
|
|
138
|
-
sections.push("- Specificity precedence: platform (`ios:` > `native:` > bare) > condition count > category (media < container < theme < group < state).\n\n");
|
|
139
|
-
const bgProp = getPropName("background");
|
|
140
|
-
const pProp = getPropName("padding");
|
|
141
|
-
if (syntaxChoice === "string") {
|
|
142
|
-
sections.push("**String form:**\n\n");
|
|
143
|
-
sections.push("```tsx\n");
|
|
144
|
-
sections.push(`<View ${bgProp}="background hover:background-hover dark:blue-500" ${pProp}="4 sm:6 max-sm:2" />
|
|
145
|
-
`);
|
|
146
|
-
sections.push("```\n\n");
|
|
147
|
-
} else if (syntaxChoice === "object") {
|
|
148
|
-
sections.push("**Object form:**\n\n");
|
|
149
|
-
sections.push("```tsx\n");
|
|
150
|
-
sections.push(`<View ${bgProp}={{ default: 'background', hover: 'background-hover', dark: 'blue-500' }} ${pProp}={{ default: '4', sm: '6', 'max-sm': '2' }} />
|
|
151
|
-
`);
|
|
152
|
-
sections.push("```\n\n");
|
|
153
|
-
} else {
|
|
154
|
-
sections.push("Both forms are allowed:\n\n");
|
|
155
|
-
sections.push("```tsx\n");
|
|
156
|
-
sections.push("// string form\n");
|
|
157
|
-
sections.push(`<View ${bgProp}="background hover:background-hover dark:blue-500" ${pProp}="4 sm:6 max-sm:2" />
|
|
158
|
-
|
|
159
|
-
`);
|
|
160
|
-
sections.push("// object form\n");
|
|
161
|
-
sections.push(`<View ${bgProp}={{ default: 'background', hover: 'background-hover', dark: 'blue-500' }} ${pProp}={{ default: '4', sm: '6', 'max-sm': '2' }} />
|
|
162
|
-
`);
|
|
163
|
-
sections.push("```\n\n");
|
|
164
|
-
}
|
|
165
|
-
sections.push("## Shorthand Properties\n\n");
|
|
166
|
-
sections.push("These shorthand properties are available for styling:\n\n");
|
|
167
|
-
const shorthandEntries = Object.entries(shorthands).sort(([a], [b]) => a.localeCompare(b));
|
|
168
|
-
sections.push(shorthandEntries.map(([short, full]) => `- \`${short}\` \u2192 \`${full}\``).join("\n"));
|
|
169
|
-
sections.push("\n\n");
|
|
170
|
-
const sizes = config.tamaguiConfig?.sizes;
|
|
171
|
-
if (sizes && typeof sizes === "object") {
|
|
172
|
-
sections.push("## Named Control Sizes\n\n");
|
|
173
|
-
sections.push(`Control components (Button, Input, etc.) use the configured names below. Default is \`${sizes.default ?? "md"}\`.
|
|
174
|
-
|
|
175
|
-
`);
|
|
176
|
-
sections.push("| Size | Configuration |\n");
|
|
177
|
-
sections.push("|---|---|\n");
|
|
178
|
-
for (const [sizeKey, val] of Object.entries(sizes)) {
|
|
179
|
-
if (sizeKey === "default") continue;
|
|
180
|
-
const valStr = typeof val === "object" && val !== null ? JSON.stringify(val) : String(val);
|
|
181
|
-
const isDefault = sizes.default === sizeKey ? " (default)" : "";
|
|
182
|
-
sections.push(`| \`${sizeKey}\`${isDefault} | ${valStr} |
|
|
183
|
-
`);
|
|
184
|
-
}
|
|
185
|
-
sections.push("\n");
|
|
186
|
-
}
|
|
187
|
-
sections.push("## Themes\n\n");
|
|
188
|
-
const themes = config.tamaguiConfig?.themes || {};
|
|
189
|
-
const themeNames = Object.keys(themes).sort();
|
|
190
|
-
sections.push(themeNames.map((name) => `- \`${name}\``).join("\n"));
|
|
191
|
-
sections.push("\n\nTheme names above are exact configured names. Nested themes resolve relative to their parent. Use an explicit theme boundary in a component skin.\n\n");
|
|
192
|
-
if (themeNames.length) {
|
|
193
|
-
sections.push("### Theme Usage\n\n");
|
|
194
|
-
sections.push(`\`\`\`tsx
|
|
195
|
-
<Theme name=${JSON.stringify(themeNames[0])}>
|
|
196
|
-
<Button>Uses this theme</Button>
|
|
197
|
-
</Theme>
|
|
198
|
-
\`\`\`
|
|
199
|
-
|
|
200
|
-
`);
|
|
201
|
-
}
|
|
202
|
-
sections.push("**Accessing theme values:**\n\n");
|
|
203
|
-
sections.push("Components access theme values by their bare names:\n\n");
|
|
204
|
-
const colorProp = getPropName("color");
|
|
205
|
-
if (syntaxChoice === "string") {
|
|
206
|
-
sections.push("```tsx\n");
|
|
207
|
-
sections.push(`<View ${bgProp}="background hover:background-hover" ${colorProp}="color" />
|
|
208
|
-
`);
|
|
209
|
-
sections.push("```\n\n");
|
|
210
|
-
} else if (syntaxChoice === "object") {
|
|
211
|
-
sections.push("```tsx\n");
|
|
212
|
-
sections.push(`<View ${bgProp}={{ default: 'background', hover: 'background-hover' }} ${colorProp}={{ default: 'color' }} />
|
|
213
|
-
`);
|
|
214
|
-
sections.push("```\n\n");
|
|
215
|
-
} else {
|
|
216
|
-
sections.push("```tsx\n");
|
|
217
|
-
sections.push("// string form\n");
|
|
218
|
-
sections.push(`<View ${bgProp}="background hover:background-hover" ${colorProp}="color" />
|
|
219
|
-
|
|
220
|
-
`);
|
|
221
|
-
sections.push("// object form\n");
|
|
222
|
-
sections.push(`<View ${bgProp}={{ default: 'background', hover: 'background-hover' }} ${colorProp}={{ default: 'color' }} />
|
|
223
|
-
`);
|
|
224
|
-
sections.push("```\n\n");
|
|
225
|
-
}
|
|
226
|
-
sections.push("**Special props:**\n\n");
|
|
227
|
-
sections.push("- `theme=\"inverse\"`: Uses the opposite light or dark sub-theme\n");
|
|
228
|
-
sections.push("## Tokens\n\n");
|
|
229
|
-
sections.push("Tokens are design system values referenced by their bare names.\n\n");
|
|
230
|
-
const tokens = config.tamaguiConfig?.tokens || {};
|
|
231
|
-
if (tokens.space && Object.keys(tokens.space).length > 0) {
|
|
232
|
-
sections.push("### Space Tokens\n\n");
|
|
233
|
-
const spaceTokens = Object.entries(tokens.space).sort(([a], [b]) => {
|
|
234
|
-
const numA = parseFloat(a);
|
|
235
|
-
const numB = parseFloat(b);
|
|
236
|
-
if (!isNaN(numA) && !isNaN(numB)) {
|
|
237
|
-
return numA - numB;
|
|
238
|
-
}
|
|
239
|
-
return a.localeCompare(b);
|
|
240
|
-
});
|
|
241
|
-
sections.push(spaceTokens.map(([key, value]) => `- \`${key}\`: ${formatTokenValue(value)}`).join("\n"));
|
|
242
|
-
sections.push("\n\n");
|
|
243
|
-
}
|
|
244
|
-
if (tokens.size && Object.keys(tokens.size).length > 0) {
|
|
245
|
-
sections.push("### Size Tokens\n\n");
|
|
246
|
-
const sizeTokens = Object.entries(tokens.size).sort(([a], [b]) => {
|
|
247
|
-
const numA = parseFloat(a);
|
|
248
|
-
const numB = parseFloat(b);
|
|
249
|
-
if (!isNaN(numA) && !isNaN(numB)) {
|
|
250
|
-
return numA - numB;
|
|
251
|
-
}
|
|
252
|
-
return a.localeCompare(b);
|
|
253
|
-
});
|
|
254
|
-
sections.push(sizeTokens.map(([key, value]) => `- \`${key}\`: ${formatTokenValue(value)}`).join("\n"));
|
|
255
|
-
sections.push("\n\n");
|
|
256
|
-
}
|
|
257
|
-
if (tokens.radius && Object.keys(tokens.radius).length > 0) {
|
|
258
|
-
sections.push("### Radius Tokens\n\n");
|
|
259
|
-
const radiusTokens = Object.entries(tokens.radius).sort(([a], [b]) => {
|
|
260
|
-
const numA = parseFloat(a);
|
|
261
|
-
const numB = parseFloat(b);
|
|
262
|
-
if (!isNaN(numA) && !isNaN(numB)) {
|
|
263
|
-
return numA - numB;
|
|
264
|
-
}
|
|
265
|
-
return a.localeCompare(b);
|
|
266
|
-
});
|
|
267
|
-
sections.push(radiusTokens.map(([key, value]) => `- \`${key}\`: ${formatTokenValue(value)}`).join("\n"));
|
|
268
|
-
sections.push("\n\n");
|
|
269
|
-
}
|
|
270
|
-
if (tokens.zIndex && Object.keys(tokens.zIndex).length > 0) {
|
|
271
|
-
sections.push("### Z-Index Tokens\n\n");
|
|
272
|
-
const zIndexTokens = Object.entries(tokens.zIndex).sort(([a], [b]) => {
|
|
273
|
-
const numA = parseFloat(a);
|
|
274
|
-
const numB = parseFloat(b);
|
|
275
|
-
if (!isNaN(numA) && !isNaN(numB)) {
|
|
276
|
-
return numA - numB;
|
|
277
|
-
}
|
|
278
|
-
return a.localeCompare(b);
|
|
279
|
-
});
|
|
280
|
-
sections.push(zIndexTokens.map(([key, value]) => `- \`${key}\`: ${formatTokenValue(value)}`).join("\n"));
|
|
281
|
-
sections.push("\n\n");
|
|
282
|
-
}
|
|
283
|
-
let sampleColorBg = "blue-500";
|
|
284
|
-
let sampleColorText = "color";
|
|
285
|
-
if (tokens.color && Object.keys(tokens.color).length > 0) {
|
|
286
|
-
sections.push("### Color Tokens\n\n");
|
|
287
|
-
const colorKeys = Object.keys(tokens.color).sort();
|
|
288
|
-
const paletteMap = /* @__PURE__ */ new Map();
|
|
289
|
-
const standaloneColors = [];
|
|
290
|
-
for (const key of colorKeys) {
|
|
291
|
-
const match = key.match(/^([a-z]+)-(\d+)$/);
|
|
292
|
-
if (match) {
|
|
293
|
-
const [, palette, step] = match;
|
|
294
|
-
if (!paletteMap.has(palette)) {
|
|
295
|
-
paletteMap.set(palette, /* @__PURE__ */ new Set());
|
|
296
|
-
}
|
|
297
|
-
paletteMap.get(palette).add(step);
|
|
298
|
-
} else {
|
|
299
|
-
standaloneColors.push([key, tokens.color[key]]);
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
if (paletteMap.size >= 4) {
|
|
303
|
-
const palettes = Array.from(paletteMap.keys()).sort().join(", ");
|
|
304
|
-
sections.push(`**Tailwind Palettes (\`<name>-<50..950>\`):** ${palettes}
|
|
305
|
-
|
|
306
|
-
`);
|
|
307
|
-
if (standaloneColors.length > 0) {
|
|
308
|
-
sections.push("**Named Colors:**\n\n");
|
|
309
|
-
sections.push(standaloneColors.map(([k, v]) => `- \`${k}\`: ${formatTokenValue(v)}`).join("\n"));
|
|
310
|
-
sections.push("\n\n");
|
|
311
|
-
}
|
|
312
|
-
sampleColorBg = colorKeys.find((k) => k.startsWith("blue-")) || colorKeys[0];
|
|
313
|
-
sampleColorText = colorKeys.find((k) => k.startsWith("gray-") || k.startsWith("zinc-")) || colorKeys[1] || "color";
|
|
314
|
-
} else {
|
|
315
|
-
sections.push(colorKeys.map((key) => `- \`${key}\`: ${formatTokenValue(tokens.color[key])}`).join("\n"));
|
|
316
|
-
sections.push("\n\n");
|
|
317
|
-
sampleColorBg = colorKeys[0] || "background";
|
|
318
|
-
sampleColorText = colorKeys[1] || "color";
|
|
319
|
-
}
|
|
320
|
-
} else {
|
|
321
|
-
sampleColorBg = "background";
|
|
322
|
-
sampleColorText = "color";
|
|
323
|
-
}
|
|
324
|
-
sections.push("### Token Usage\n\n");
|
|
325
|
-
sections.push("Tokens can be used in component props by their bare names:\n\n");
|
|
326
|
-
const paddingProp = getPropName("padding");
|
|
327
|
-
const gapProp = getPropName("gap");
|
|
328
|
-
const marginProp = getPropName("margin");
|
|
329
|
-
const widthProp = getPropName("width");
|
|
330
|
-
const heightProp = getPropName("height");
|
|
331
|
-
const radiusProp = getPropName("borderRadius");
|
|
332
|
-
const sampleRadius = tokens.radius?.md ? "md" : Object.keys(tokens.radius || {})[0] || "0px";
|
|
333
|
-
if (syntaxChoice === "string") {
|
|
334
|
-
sections.push("```tsx\n");
|
|
335
|
-
sections.push(`// Space tokens - for margin, padding, gap
|
|
336
|
-
<View ${paddingProp}="4 sm:6" ${gapProp}="2" ${marginProp}="3" />
|
|
337
|
-
|
|
338
|
-
`);
|
|
339
|
-
sections.push(`// Size tokens - for width, height, dimensions
|
|
340
|
-
<View ${widthProp}="10 sm:12" ${heightProp}="6" />
|
|
341
|
-
|
|
342
|
-
`);
|
|
343
|
-
sections.push(`// Color tokens - for colors and backgrounds
|
|
344
|
-
<View ${bgProp}="${sampleColorBg} hover:${sampleColorBg}" ${colorProp}="${sampleColorText}" />
|
|
345
|
-
|
|
346
|
-
`);
|
|
347
|
-
sections.push(`// Radius tokens - for border-radius
|
|
348
|
-
<View ${radiusProp}="${sampleRadius}" />
|
|
349
|
-
`);
|
|
350
|
-
sections.push("```\n\n");
|
|
351
|
-
} else if (syntaxChoice === "object") {
|
|
352
|
-
sections.push("```tsx\n");
|
|
353
|
-
sections.push(`// Space tokens - for margin, padding, gap
|
|
354
|
-
<View ${paddingProp}={{ default: '4', sm: '6' }} ${gapProp}="2" ${marginProp}="3" />
|
|
355
|
-
|
|
356
|
-
`);
|
|
357
|
-
sections.push(`// Size tokens - for width, height, dimensions
|
|
358
|
-
<View ${widthProp}={{ default: '10', sm: '12' }} ${heightProp}="6" />
|
|
359
|
-
|
|
360
|
-
`);
|
|
361
|
-
sections.push(`// Color tokens - for colors and backgrounds
|
|
362
|
-
<View ${bgProp}={{ default: '${sampleColorBg}', hover: '${sampleColorBg}' }} ${colorProp}={{ default: '${sampleColorText}' }} />
|
|
363
|
-
|
|
364
|
-
`);
|
|
365
|
-
sections.push(`// Radius tokens - for border-radius
|
|
366
|
-
<View ${radiusProp}="${sampleRadius}" />
|
|
367
|
-
`);
|
|
368
|
-
sections.push("```\n\n");
|
|
369
|
-
} else {
|
|
370
|
-
sections.push("```tsx\n");
|
|
371
|
-
sections.push("// String form\n");
|
|
372
|
-
sections.push(`<View ${paddingProp}="4 sm:6" ${widthProp}="10 sm:12" ${bgProp}="${sampleColorBg}" />
|
|
373
|
-
|
|
374
|
-
`);
|
|
375
|
-
sections.push("// Object form\n");
|
|
376
|
-
sections.push(`<View ${paddingProp}={{ default: '4', sm: '6' }} ${widthProp}={{ default: '10', sm: '12' }} ${bgProp}={{ default: '${sampleColorBg}' }} />
|
|
377
|
-
|
|
378
|
-
`);
|
|
379
|
-
sections.push(`// Space and radius tokens
|
|
380
|
-
<View ${gapProp}="2" ${marginProp}="3" ${heightProp}="6" ${radiusProp}="${sampleRadius}" />
|
|
381
|
-
`);
|
|
382
|
-
sections.push("```\n\n");
|
|
383
|
-
}
|
|
384
|
-
if (config.tamaguiConfig?.media) {
|
|
385
|
-
sections.push("## Media Queries\n\n");
|
|
386
|
-
sections.push("Available responsive breakpoints:\n\n");
|
|
387
|
-
const media = config.tamaguiConfig.media;
|
|
388
|
-
const mediaEntries = Object.entries(media).sort(([a], [b]) => a.localeCompare(b));
|
|
389
|
-
for (const [name, query] of mediaEntries) {
|
|
390
|
-
sections.push(`- **${name}**: ${formatMediaQuery(query)}
|
|
391
|
-
`);
|
|
392
|
-
}
|
|
393
|
-
sections.push("\n");
|
|
394
|
-
sections.push("### Media Query Usage\n\n");
|
|
395
|
-
sections.push("Media queries can be used as style props or with the `useMedia` hook:\n\n");
|
|
396
|
-
const representative = mediaEntries.find(([n]) => n === "sm" || n === "md")?.[0] || mediaEntries.find(([n]) => !n.includes("-"))?.[0] || mediaEntries[0]?.[0];
|
|
397
|
-
if (representative) {
|
|
398
|
-
const isIdentifier = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(representative);
|
|
399
|
-
const mediaAccess = isIdentifier ? `media.${representative}` : `media['${representative}']`;
|
|
400
|
-
sections.push("```tsx\n");
|
|
401
|
-
if (syntaxChoice === "string") {
|
|
402
|
-
sections.push("// As a clause in the same style value\n");
|
|
403
|
-
sections.push(`<View ${widthProp}="100% ${representative}:50%" />
|
|
404
|
-
|
|
405
|
-
`);
|
|
406
|
-
} else if (syntaxChoice === "object") {
|
|
407
|
-
sections.push("// Using the object form\n");
|
|
408
|
-
sections.push(`<View ${widthProp}={{ default: '100%', '${representative}': '50%' }} />
|
|
409
|
-
|
|
410
|
-
`);
|
|
411
|
-
} else {
|
|
412
|
-
sections.push("// String form and object form\n");
|
|
413
|
-
sections.push(`<View ${widthProp}="100% ${representative}:50%" />
|
|
414
|
-
`);
|
|
415
|
-
sections.push(`<View ${widthProp}={{ default: '100%', '${representative}': '50%' }} />
|
|
416
|
-
|
|
417
|
-
`);
|
|
418
|
-
}
|
|
419
|
-
sections.push("// Using the useMedia hook\n");
|
|
420
|
-
sections.push("const media = useMedia()\n");
|
|
421
|
-
sections.push(`if (${mediaAccess}) {
|
|
422
|
-
`);
|
|
423
|
-
sections.push(" // Render for this breakpoint\n");
|
|
424
|
-
sections.push("}\n");
|
|
425
|
-
sections.push("```\n\n");
|
|
426
|
-
}
|
|
427
|
-
}
|
|
428
|
-
if (config.tamaguiConfig?.fonts) {
|
|
429
|
-
sections.push("## Fonts\n\n");
|
|
430
|
-
sections.push("Available font families:\n\n");
|
|
431
|
-
const fonts = config.tamaguiConfig.fonts;
|
|
432
|
-
const fontNames = Object.keys(fonts).sort();
|
|
433
|
-
sections.push(fontNames.map((name) => `- ${name}`).join("\n"));
|
|
434
|
-
sections.push("\n\n");
|
|
435
|
-
}
|
|
436
|
-
if (config.tamaguiConfig?.animations) {
|
|
437
|
-
sections.push("## Animations\n\n");
|
|
438
|
-
sections.push("Available animation presets:\n\n");
|
|
439
|
-
const animations = config.tamaguiConfig.animations;
|
|
440
|
-
if (animations.animations) {
|
|
441
|
-
const animationNames = Object.keys(animations.animations).sort();
|
|
442
|
-
sections.push(animationNames.map((name) => `- ${name}`).join("\n"));
|
|
443
|
-
sections.push("\n\n");
|
|
444
|
-
}
|
|
445
|
-
}
|
|
446
|
-
const componentsSection = [];
|
|
447
|
-
const componentSet = /* @__PURE__ */ new Set();
|
|
448
|
-
let barrelExported = false;
|
|
449
|
-
const candidateModules = ["tamagui", ...(config.components || []).map((c) => c.moduleName)];
|
|
450
|
-
for (const modName of candidateModules) {
|
|
451
|
-
if (!modName) continue;
|
|
452
|
-
try {
|
|
453
|
-
const mod = require(modName);
|
|
454
|
-
for (const [key, val] of Object.entries(mod)) {
|
|
455
|
-
if (/^[A-Z]/.test(key) && (typeof val === "function" || typeof val === "object" && val !== null)) {
|
|
456
|
-
if (!key.endsWith("Context") && !key.endsWith("Provider") && key !== "Fragment") {
|
|
457
|
-
componentSet.add(key);
|
|
458
|
-
barrelExported = true;
|
|
459
|
-
}
|
|
460
|
-
}
|
|
461
|
-
}
|
|
462
|
-
if (barrelExported) break;
|
|
463
|
-
} catch {}
|
|
464
|
-
}
|
|
465
|
-
if (!barrelExported && config.components) {
|
|
466
|
-
for (const componentModule of config.components) {
|
|
467
|
-
for (const name of Object.keys(componentModule.nameToInfo || {})) {
|
|
468
|
-
componentSet.add(name);
|
|
469
|
-
}
|
|
470
|
-
}
|
|
471
|
-
}
|
|
472
|
-
const allComponents = Array.from(componentSet).filter((name) => {
|
|
473
|
-
if (name.endsWith("Frame")) {
|
|
474
|
-
const base = name.replace(/Frame$/, "");
|
|
475
|
-
if (componentSet.has(base) || name.startsWith("Popper") || name.startsWith("DialogPortal") || name.startsWith("SelectScrollButton")) {
|
|
476
|
-
return false;
|
|
477
|
-
}
|
|
478
|
-
}
|
|
479
|
-
return true;
|
|
480
|
-
});
|
|
481
|
-
componentsSection.push("## Components\n\n");
|
|
482
|
-
componentsSection.push("Available named exports (import these names directly):\n\n");
|
|
483
|
-
for (const name of allComponents.sort()) {
|
|
484
|
-
componentsSection.push(`- ${name}
|
|
485
|
-
`);
|
|
486
|
-
}
|
|
487
|
-
componentsSection.push("\n");
|
|
488
|
-
sections.push(...componentsSection);
|
|
489
|
-
return sections.join("");
|
|
490
|
-
}
|
|
491
|
-
function formatTokenValue(value) {
|
|
492
|
-
if (typeof value === "object" && value !== null && "val" in value) {
|
|
493
|
-
return String(value.val);
|
|
494
|
-
}
|
|
495
|
-
return String(value);
|
|
496
|
-
}
|
|
497
|
-
function formatMediaQuery(query) {
|
|
498
|
-
if (typeof query !== "object" || query === null) {
|
|
499
|
-
return String(query);
|
|
500
|
-
}
|
|
501
|
-
const parts = [];
|
|
502
|
-
if (query.minWidth !== void 0) {
|
|
503
|
-
parts.push(`min-width: ${query.minWidth}px (screens >= ${query.minWidth}px wide)`);
|
|
504
|
-
}
|
|
505
|
-
if (query.maxWidth !== void 0) {
|
|
506
|
-
parts.push(`max-width: ${query.maxWidth}px (screens <= ${query.maxWidth}px wide)`);
|
|
507
|
-
}
|
|
508
|
-
if (query.minHeight !== void 0) {
|
|
509
|
-
parts.push(`min-height: ${query.minHeight}px (screens >= ${query.minHeight}px tall)`);
|
|
510
|
-
}
|
|
511
|
-
if (query.maxHeight !== void 0) {
|
|
512
|
-
parts.push(`max-height: ${query.maxHeight}px (screens <= ${query.maxHeight}px tall)`);
|
|
513
|
-
}
|
|
514
|
-
if (query.hover !== void 0) {
|
|
515
|
-
parts.push(`pointer: hover (${query.hover})`);
|
|
516
|
-
}
|
|
517
|
-
if (query.pointer !== void 0) {
|
|
518
|
-
parts.push(`pointer: ${query.pointer}`);
|
|
519
|
-
}
|
|
520
|
-
if (query.prefersReducedMotion !== void 0) {
|
|
521
|
-
parts.push(`prefers-reduced-motion: ${query.prefersReducedMotion}`);
|
|
522
|
-
}
|
|
523
|
-
if (parts.length === 0) {
|
|
524
|
-
return JSON.stringify(query);
|
|
525
|
-
}
|
|
526
|
-
return parts.join(", ");
|
|
527
|
-
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tamagui/cli",
|
|
3
|
-
"version": "3.0.0-beta.
|
|
3
|
+
"version": "3.0.0-beta.1202.1",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"bin": {
|
|
6
6
|
"tama": "dist/index.cjs",
|
|
@@ -52,12 +52,12 @@
|
|
|
52
52
|
"test:web": "bun run test"
|
|
53
53
|
},
|
|
54
54
|
"dependencies": {
|
|
55
|
-
"@tamagui/generate-themes": "3.0.0-beta.
|
|
56
|
-
"@tamagui/metro-plugin": "3.0.0-beta.
|
|
57
|
-
"@tamagui/static": "3.0.0-beta.
|
|
58
|
-
"@tamagui/to-tailwind": "3.0.0-beta.
|
|
59
|
-
"@tamagui/types": "3.0.0-beta.
|
|
60
|
-
"@tamagui/vite-plugin": "3.0.0-beta.
|
|
55
|
+
"@tamagui/generate-themes": "3.0.0-beta.1202.1",
|
|
56
|
+
"@tamagui/metro-plugin": "3.0.0-beta.1202.1",
|
|
57
|
+
"@tamagui/static": "3.0.0-beta.1202.1",
|
|
58
|
+
"@tamagui/to-tailwind": "3.0.0-beta.1202.1",
|
|
59
|
+
"@tamagui/types": "3.0.0-beta.1202.1",
|
|
60
|
+
"@tamagui/vite-plugin": "3.0.0-beta.1202.1",
|
|
61
61
|
"arg": "^5.0.2",
|
|
62
62
|
"chalk": "^4.1.2",
|
|
63
63
|
"change-case": "^4.1.2",
|
|
@@ -76,10 +76,10 @@
|
|
|
76
76
|
"ts-morph": "^28.0.0",
|
|
77
77
|
"typescript": "~6.0.3",
|
|
78
78
|
"url": "^0.11.0",
|
|
79
|
-
"@tamagui/language-service": "3.0.0-beta.
|
|
79
|
+
"@tamagui/language-service": "3.0.0-beta.1202.1"
|
|
80
80
|
},
|
|
81
81
|
"devDependencies": {
|
|
82
|
-
"@tamagui/build": "3.0.0-beta.
|
|
82
|
+
"@tamagui/build": "3.0.0-beta.1202.1",
|
|
83
83
|
"@types/chokidar": "^2.1.3",
|
|
84
84
|
"@types/marked": "^5.0.0",
|
|
85
85
|
"vitest": "4.1.0"
|
package/src/cli.ts
CHANGED
|
@@ -78,18 +78,7 @@ const COMMAND_MAP = {
|
|
|
78
78
|
})
|
|
79
79
|
const { loadTamagui } = require('@tamagui/static/loadTamagui')
|
|
80
80
|
process.env.TAMAGUI_KEEP_THEMES = '1'
|
|
81
|
-
await loadTamagui({
|
|
82
|
-
...options.tamaguiOptions,
|
|
83
|
-
platform: 'web',
|
|
84
|
-
})
|
|
85
|
-
|
|
86
|
-
// also generate prompt to .tamagui/prompt.md
|
|
87
|
-
const { generatePrompt } = require('./generate-prompt')
|
|
88
|
-
const { join } = require('node:path')
|
|
89
|
-
await generatePrompt({
|
|
90
|
-
...options,
|
|
91
|
-
output: join(options.paths.dotDir, 'prompt.md'),
|
|
92
|
-
})
|
|
81
|
+
await loadTamagui({ ...options.tamaguiOptions, platform: 'web' }, true)
|
|
93
82
|
},
|
|
94
83
|
},
|
|
95
84
|
|
package/src/generate-prompt.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { generateConfigMarkdown } from '@tamagui/static'
|
|
1
2
|
import { join } from 'node:path'
|
|
2
3
|
import * as FS from 'fs-extra'
|
|
3
4
|
import type { CLIResolvedOptions } from '@tamagui/types'
|
|
@@ -36,7 +37,7 @@ export async function generatePrompt(options: GeneratePromptOptions) {
|
|
|
36
37
|
const resolvedSyntax = await resolveStyleValueSyntax(explicitChoice)
|
|
37
38
|
|
|
38
39
|
// generate markdown
|
|
39
|
-
const markdown =
|
|
40
|
+
const markdown = generateConfigMarkdown(config, { styleValueSyntax: resolvedSyntax })
|
|
40
41
|
|
|
41
42
|
// write to file
|
|
42
43
|
const outputPath = output || join(process.cwd(), 'tamagui-prompt.md')
|
|
@@ -44,611 +45,3 @@ export async function generatePrompt(options: GeneratePromptOptions) {
|
|
|
44
45
|
|
|
45
46
|
console.info(`\n ✓ Generated prompt file at ${outputPath}\n`)
|
|
46
47
|
}
|
|
47
|
-
|
|
48
|
-
export interface GenerateMarkdownOptions {
|
|
49
|
-
styleValueSyntax?: 'string' | 'object' | 'both'
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
export function generateMarkdown(config: any, options?: GenerateMarkdownOptions): string {
|
|
53
|
-
const sections: string[] = []
|
|
54
|
-
|
|
55
|
-
// header
|
|
56
|
-
sections.push('# Tamagui Configuration\n\n')
|
|
57
|
-
sections.push(
|
|
58
|
-
'This document provides an overview of the Tamagui configuration for this project.\n\n'
|
|
59
|
-
)
|
|
60
|
-
|
|
61
|
-
// get shorthands for use throughout the document
|
|
62
|
-
const shorthands = config.tamaguiConfig?.shorthands || {}
|
|
63
|
-
const reverseShorthands: Record<string, string> = {}
|
|
64
|
-
for (const [short, full] of Object.entries(shorthands)) {
|
|
65
|
-
reverseShorthands[full as string] = short
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// helper function to get the correct property name based on settings
|
|
69
|
-
const getPropName = (fullProp: string): string => {
|
|
70
|
-
const settings = config.tamaguiConfig?.settings || {}
|
|
71
|
-
if (settings.onlyAllowShorthands) {
|
|
72
|
-
if (reverseShorthands[fullProp]) return reverseShorthands[fullProp]
|
|
73
|
-
if (fullProp === 'backgroundColor' && reverseShorthands['background']) {
|
|
74
|
-
return reverseShorthands['background']
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
return fullProp
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
const settings = config.tamaguiConfig?.settings || {}
|
|
81
|
-
const syntaxChoice = options?.styleValueSyntax || settings.styleValueSyntax || 'both'
|
|
82
|
-
|
|
83
|
-
// configuration settings
|
|
84
|
-
sections.push('## Configuration Settings\n\n')
|
|
85
|
-
sections.push(
|
|
86
|
-
'**IMPORTANT:** These settings affect how you write Tamagui code in this project.\n\n'
|
|
87
|
-
)
|
|
88
|
-
|
|
89
|
-
if (settings.defaultFont) {
|
|
90
|
-
sections.push(`### Default Font: \`${settings.defaultFont}\`\n\n`)
|
|
91
|
-
sections.push(
|
|
92
|
-
`All text components will use the "${settings.defaultFont}" font family by default.\n\n`
|
|
93
|
-
)
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
if (settings.onlyAllowShorthands !== undefined) {
|
|
97
|
-
sections.push(`### Only Allow Shorthands: \`${settings.onlyAllowShorthands}\`\n\n`)
|
|
98
|
-
if (settings.onlyAllowShorthands) {
|
|
99
|
-
sections.push('**You MUST use shorthand properties in this project.**\n\n')
|
|
100
|
-
sections.push('Full property names are not allowed. For example:\n')
|
|
101
|
-
sections.push('- ✅ `<View w="10" />` (correct)\n')
|
|
102
|
-
sections.push('- ❌ `<View width="10" />` (will error)\n\n')
|
|
103
|
-
sections.push(
|
|
104
|
-
'See the Shorthand Properties section below for all available shorthands.\n\n'
|
|
105
|
-
)
|
|
106
|
-
} else {
|
|
107
|
-
sections.push('You can use either shorthand or full property names.\n\n')
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
// style value syntax section
|
|
112
|
-
if (syntaxChoice === 'string') {
|
|
113
|
-
sections.push('### Style value syntax: `string`\n\n')
|
|
114
|
-
sections.push(
|
|
115
|
-
'Only the string form is allowed in this project (e.g. `bg="red hover:blue"`).\n\n'
|
|
116
|
-
)
|
|
117
|
-
} else if (syntaxChoice === 'object') {
|
|
118
|
-
sections.push('### Style value syntax: `object`\n\n')
|
|
119
|
-
sections.push(
|
|
120
|
-
"Only the object form is allowed in this project (e.g. `bg={{ default: 'red', hover: 'blue' }}`).\n\n"
|
|
121
|
-
)
|
|
122
|
-
} else {
|
|
123
|
-
sections.push('### Style value syntax\n\n')
|
|
124
|
-
sections.push('Both string and object style value syntax are allowed.\n\n')
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
if (settings.addThemeClassName !== undefined) {
|
|
128
|
-
sections.push(`### Theme Class Name: \`${settings.addThemeClassName}\`\n\n`)
|
|
129
|
-
if (settings.addThemeClassName === 'html') {
|
|
130
|
-
sections.push('Theme classes are applied to the root HTML element.\n\n')
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
if (settings.allowedStyleValues) {
|
|
135
|
-
sections.push('### Allowed Style Values\n\n')
|
|
136
|
-
sections.push(
|
|
137
|
-
`Type validation: \`${JSON.stringify(settings.allowedStyleValues)}\`.\n\n`
|
|
138
|
-
)
|
|
139
|
-
sections.push(
|
|
140
|
-
'Single-token values are type-checked. Run `tamagui check --strict` to also validate conditional payloads.\n\n'
|
|
141
|
-
)
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
// flat value grammar section
|
|
145
|
-
sections.push('## Flat Value Grammar\n\n')
|
|
146
|
-
sections.push('Conditional style values follow this grammar:\n\n')
|
|
147
|
-
sections.push('```txt\n')
|
|
148
|
-
sections.push('value := base? clause*\n')
|
|
149
|
-
sections.push('clause := modifier(:modifier)*:payload\n')
|
|
150
|
-
sections.push('```\n\n')
|
|
151
|
-
sections.push(
|
|
152
|
-
'- No `$` sigils: bare token names (`bg="background"`, not `bg="$background"`).\n'
|
|
153
|
-
)
|
|
154
|
-
sections.push(
|
|
155
|
-
'- Kebab-case theme names: `background-hover`, `border-color`, `shadow-color`.\n'
|
|
156
|
-
)
|
|
157
|
-
sections.push('- Numbers are px: `p={4}` is 4px, while `p="4"` is space token 4.\n')
|
|
158
|
-
sections.push(
|
|
159
|
-
'- Specificity precedence: platform (`ios:` > `native:` > bare) > condition count > category (media < container < theme < group < state).\n\n'
|
|
160
|
-
)
|
|
161
|
-
|
|
162
|
-
const bgProp = getPropName('background')
|
|
163
|
-
const pProp = getPropName('padding')
|
|
164
|
-
|
|
165
|
-
if (syntaxChoice === 'string') {
|
|
166
|
-
sections.push('**String form:**\n\n')
|
|
167
|
-
sections.push('```tsx\n')
|
|
168
|
-
sections.push(
|
|
169
|
-
`<View ${bgProp}="background hover:background-hover dark:blue-500" ${pProp}="4 sm:6 max-sm:2" />\n`
|
|
170
|
-
)
|
|
171
|
-
sections.push('```\n\n')
|
|
172
|
-
} else if (syntaxChoice === 'object') {
|
|
173
|
-
sections.push('**Object form:**\n\n')
|
|
174
|
-
sections.push('```tsx\n')
|
|
175
|
-
sections.push(
|
|
176
|
-
`<View ${bgProp}={{ default: 'background', hover: 'background-hover', dark: 'blue-500' }} ${pProp}={{ default: '4', sm: '6', 'max-sm': '2' }} />\n`
|
|
177
|
-
)
|
|
178
|
-
sections.push('```\n\n')
|
|
179
|
-
} else {
|
|
180
|
-
sections.push('Both forms are allowed:\n\n')
|
|
181
|
-
sections.push('```tsx\n')
|
|
182
|
-
sections.push('// string form\n')
|
|
183
|
-
sections.push(
|
|
184
|
-
`<View ${bgProp}="background hover:background-hover dark:blue-500" ${pProp}="4 sm:6 max-sm:2" />\n\n`
|
|
185
|
-
)
|
|
186
|
-
sections.push('// object form\n')
|
|
187
|
-
sections.push(
|
|
188
|
-
`<View ${bgProp}={{ default: 'background', hover: 'background-hover', dark: 'blue-500' }} ${pProp}={{ default: '4', sm: '6', 'max-sm': '2' }} />\n`
|
|
189
|
-
)
|
|
190
|
-
sections.push('```\n\n')
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
// shorthands
|
|
194
|
-
sections.push('## Shorthand Properties\n\n')
|
|
195
|
-
sections.push('These shorthand properties are available for styling:\n\n')
|
|
196
|
-
const shorthandEntries = Object.entries(shorthands).sort(([a], [b]) =>
|
|
197
|
-
a.localeCompare(b)
|
|
198
|
-
)
|
|
199
|
-
sections.push(
|
|
200
|
-
shorthandEntries.map(([short, full]) => `- \`${short}\` → \`${full}\``).join('\n')
|
|
201
|
-
)
|
|
202
|
-
sections.push('\n\n')
|
|
203
|
-
|
|
204
|
-
// named control sizes table
|
|
205
|
-
const sizes = config.tamaguiConfig?.sizes
|
|
206
|
-
if (sizes && typeof sizes === 'object') {
|
|
207
|
-
sections.push('## Named Control Sizes\n\n')
|
|
208
|
-
sections.push(
|
|
209
|
-
`Control components (Button, Input, etc.) use the configured names below. Default is \`${sizes.default ?? 'md'}\`.\n\n`
|
|
210
|
-
)
|
|
211
|
-
sections.push('| Size | Configuration |\n')
|
|
212
|
-
sections.push('|---|---|\n')
|
|
213
|
-
for (const [sizeKey, val] of Object.entries(sizes)) {
|
|
214
|
-
if (sizeKey === 'default') continue
|
|
215
|
-
const valStr =
|
|
216
|
-
typeof val === 'object' && val !== null ? JSON.stringify(val) : String(val)
|
|
217
|
-
const isDefault = sizes.default === sizeKey ? ' (default)' : ''
|
|
218
|
-
sections.push(`| \`${sizeKey}\`${isDefault} | ${valStr} |\n`)
|
|
219
|
-
}
|
|
220
|
-
sections.push('\n')
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
// themes
|
|
224
|
-
sections.push('## Themes\n\n')
|
|
225
|
-
const themes = config.tamaguiConfig?.themes || {}
|
|
226
|
-
const themeNames = Object.keys(themes).sort()
|
|
227
|
-
|
|
228
|
-
sections.push(themeNames.map((name) => `- \`${name}\``).join('\n'))
|
|
229
|
-
sections.push(
|
|
230
|
-
'\n\nTheme names above are exact configured names. Nested themes resolve relative to their parent. Use an explicit theme boundary in a component skin.\n\n'
|
|
231
|
-
)
|
|
232
|
-
if (themeNames.length) {
|
|
233
|
-
sections.push('### Theme Usage\n\n')
|
|
234
|
-
sections.push(
|
|
235
|
-
`\`\`\`tsx\n<Theme name=${JSON.stringify(themeNames[0])}>\n <Button>Uses this theme</Button>\n</Theme>\n\`\`\`\n\n`
|
|
236
|
-
)
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
sections.push('**Accessing theme values:**\n\n')
|
|
240
|
-
sections.push('Components access theme values by their bare names:\n\n')
|
|
241
|
-
const colorProp = getPropName('color')
|
|
242
|
-
if (syntaxChoice === 'string') {
|
|
243
|
-
sections.push('```tsx\n')
|
|
244
|
-
sections.push(
|
|
245
|
-
`<View ${bgProp}="background hover:background-hover" ${colorProp}="color" />\n`
|
|
246
|
-
)
|
|
247
|
-
sections.push('```\n\n')
|
|
248
|
-
} else if (syntaxChoice === 'object') {
|
|
249
|
-
sections.push('```tsx\n')
|
|
250
|
-
sections.push(
|
|
251
|
-
`<View ${bgProp}={{ default: 'background', hover: 'background-hover' }} ${colorProp}={{ default: 'color' }} />\n`
|
|
252
|
-
)
|
|
253
|
-
sections.push('```\n\n')
|
|
254
|
-
} else {
|
|
255
|
-
sections.push('```tsx\n')
|
|
256
|
-
sections.push('// string form\n')
|
|
257
|
-
sections.push(
|
|
258
|
-
`<View ${bgProp}="background hover:background-hover" ${colorProp}="color" />\n\n`
|
|
259
|
-
)
|
|
260
|
-
sections.push('// object form\n')
|
|
261
|
-
sections.push(
|
|
262
|
-
`<View ${bgProp}={{ default: 'background', hover: 'background-hover' }} ${colorProp}={{ default: 'color' }} />\n`
|
|
263
|
-
)
|
|
264
|
-
sections.push('```\n\n')
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
sections.push('**Special props:**\n\n')
|
|
268
|
-
sections.push('- `theme="inverse"`: Uses the opposite light or dark sub-theme\n')
|
|
269
|
-
|
|
270
|
-
// tokens
|
|
271
|
-
sections.push('## Tokens\n\n')
|
|
272
|
-
sections.push('Tokens are design system values referenced by their bare names.\n\n')
|
|
273
|
-
|
|
274
|
-
const tokens = config.tamaguiConfig?.tokens || {}
|
|
275
|
-
|
|
276
|
-
// space tokens (only if present and non-empty)
|
|
277
|
-
if (tokens.space && Object.keys(tokens.space).length > 0) {
|
|
278
|
-
sections.push('### Space Tokens\n\n')
|
|
279
|
-
const spaceTokens = Object.entries(tokens.space).sort(([a], [b]) => {
|
|
280
|
-
const numA = parseFloat(a)
|
|
281
|
-
const numB = parseFloat(b)
|
|
282
|
-
if (!isNaN(numA) && !isNaN(numB)) {
|
|
283
|
-
return numA - numB
|
|
284
|
-
}
|
|
285
|
-
return a.localeCompare(b)
|
|
286
|
-
})
|
|
287
|
-
sections.push(
|
|
288
|
-
spaceTokens
|
|
289
|
-
.map(([key, value]) => `- \`${key}\`: ${formatTokenValue(value)}`)
|
|
290
|
-
.join('\n')
|
|
291
|
-
)
|
|
292
|
-
sections.push('\n\n')
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
// size tokens (only if present and non-empty)
|
|
296
|
-
if (tokens.size && Object.keys(tokens.size).length > 0) {
|
|
297
|
-
sections.push('### Size Tokens\n\n')
|
|
298
|
-
const sizeTokens = Object.entries(tokens.size).sort(([a], [b]) => {
|
|
299
|
-
const numA = parseFloat(a)
|
|
300
|
-
const numB = parseFloat(b)
|
|
301
|
-
if (!isNaN(numA) && !isNaN(numB)) {
|
|
302
|
-
return numA - numB
|
|
303
|
-
}
|
|
304
|
-
return a.localeCompare(b)
|
|
305
|
-
})
|
|
306
|
-
sections.push(
|
|
307
|
-
sizeTokens
|
|
308
|
-
.map(([key, value]) => `- \`${key}\`: ${formatTokenValue(value)}`)
|
|
309
|
-
.join('\n')
|
|
310
|
-
)
|
|
311
|
-
sections.push('\n\n')
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
// radius tokens (only if present and non-empty)
|
|
315
|
-
if (tokens.radius && Object.keys(tokens.radius).length > 0) {
|
|
316
|
-
sections.push('### Radius Tokens\n\n')
|
|
317
|
-
const radiusTokens = Object.entries(tokens.radius).sort(([a], [b]) => {
|
|
318
|
-
const numA = parseFloat(a)
|
|
319
|
-
const numB = parseFloat(b)
|
|
320
|
-
if (!isNaN(numA) && !isNaN(numB)) {
|
|
321
|
-
return numA - numB
|
|
322
|
-
}
|
|
323
|
-
return a.localeCompare(b)
|
|
324
|
-
})
|
|
325
|
-
sections.push(
|
|
326
|
-
radiusTokens
|
|
327
|
-
.map(([key, value]) => `- \`${key}\`: ${formatTokenValue(value)}`)
|
|
328
|
-
.join('\n')
|
|
329
|
-
)
|
|
330
|
-
sections.push('\n\n')
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
// zIndex tokens (only if present and non-empty)
|
|
334
|
-
if (tokens.zIndex && Object.keys(tokens.zIndex).length > 0) {
|
|
335
|
-
sections.push('### Z-Index Tokens\n\n')
|
|
336
|
-
const zIndexTokens = Object.entries(tokens.zIndex).sort(([a], [b]) => {
|
|
337
|
-
const numA = parseFloat(a)
|
|
338
|
-
const numB = parseFloat(b)
|
|
339
|
-
if (!isNaN(numA) && !isNaN(numB)) {
|
|
340
|
-
return numA - numB
|
|
341
|
-
}
|
|
342
|
-
return a.localeCompare(b)
|
|
343
|
-
})
|
|
344
|
-
sections.push(
|
|
345
|
-
zIndexTokens
|
|
346
|
-
.map(([key, value]) => `- \`${key}\`: ${formatTokenValue(value)}`)
|
|
347
|
-
.join('\n')
|
|
348
|
-
)
|
|
349
|
-
sections.push('\n\n')
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
// color tokens (only if present and non-empty; summarized if large palette set)
|
|
353
|
-
let sampleColorBg = 'blue-500'
|
|
354
|
-
let sampleColorText = 'color'
|
|
355
|
-
if (tokens.color && Object.keys(tokens.color).length > 0) {
|
|
356
|
-
sections.push('### Color Tokens\n\n')
|
|
357
|
-
const colorKeys = Object.keys(tokens.color).sort()
|
|
358
|
-
|
|
359
|
-
// detect tailwind style palette keys: <palette>-<step>
|
|
360
|
-
const paletteMap = new Map<string, Set<string>>()
|
|
361
|
-
const standaloneColors: Array<[string, any]> = []
|
|
362
|
-
|
|
363
|
-
for (const key of colorKeys) {
|
|
364
|
-
const match = key.match(/^([a-z]+)-(\d+)$/)
|
|
365
|
-
if (match) {
|
|
366
|
-
const [, palette, step] = match
|
|
367
|
-
if (!paletteMap.has(palette)) {
|
|
368
|
-
paletteMap.set(palette, new Set())
|
|
369
|
-
}
|
|
370
|
-
paletteMap.get(palette)!.add(step)
|
|
371
|
-
} else {
|
|
372
|
-
standaloneColors.push([key, tokens.color[key]])
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
if (paletteMap.size >= 4) {
|
|
377
|
-
// summarize palettes compactly instead of 300+ line dump
|
|
378
|
-
const palettes = Array.from(paletteMap.keys()).sort().join(', ')
|
|
379
|
-
sections.push(`**Tailwind Palettes (\`<name>-<50..950>\`):** ${palettes}\n\n`)
|
|
380
|
-
if (standaloneColors.length > 0) {
|
|
381
|
-
sections.push('**Named Colors:**\n\n')
|
|
382
|
-
sections.push(
|
|
383
|
-
standaloneColors
|
|
384
|
-
.map(([k, v]) => `- \`${k}\`: ${formatTokenValue(v)}`)
|
|
385
|
-
.join('\n')
|
|
386
|
-
)
|
|
387
|
-
sections.push('\n\n')
|
|
388
|
-
}
|
|
389
|
-
sampleColorBg = colorKeys.find((k) => k.startsWith('blue-')) || colorKeys[0]
|
|
390
|
-
sampleColorText =
|
|
391
|
-
colorKeys.find((k) => k.startsWith('gray-') || k.startsWith('zinc-')) ||
|
|
392
|
-
colorKeys[1] ||
|
|
393
|
-
'color'
|
|
394
|
-
} else {
|
|
395
|
-
sections.push(
|
|
396
|
-
colorKeys
|
|
397
|
-
.map((key) => `- \`${key}\`: ${formatTokenValue(tokens.color[key])}`)
|
|
398
|
-
.join('\n')
|
|
399
|
-
)
|
|
400
|
-
sections.push('\n\n')
|
|
401
|
-
sampleColorBg = colorKeys[0] || 'background'
|
|
402
|
-
sampleColorText = colorKeys[1] || 'color'
|
|
403
|
-
}
|
|
404
|
-
} else {
|
|
405
|
-
sampleColorBg = 'background'
|
|
406
|
-
sampleColorText = 'color'
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
// token usage examples
|
|
410
|
-
sections.push('### Token Usage\n\n')
|
|
411
|
-
sections.push('Tokens can be used in component props by their bare names:\n\n')
|
|
412
|
-
|
|
413
|
-
const paddingProp = getPropName('padding')
|
|
414
|
-
const gapProp = getPropName('gap')
|
|
415
|
-
const marginProp = getPropName('margin')
|
|
416
|
-
const widthProp = getPropName('width')
|
|
417
|
-
const heightProp = getPropName('height')
|
|
418
|
-
const radiusProp = getPropName('borderRadius')
|
|
419
|
-
const sampleRadius = tokens.radius?.md
|
|
420
|
-
? 'md'
|
|
421
|
-
: Object.keys(tokens.radius || {})[0] || '0px'
|
|
422
|
-
|
|
423
|
-
if (syntaxChoice === 'string') {
|
|
424
|
-
sections.push('```tsx\n')
|
|
425
|
-
sections.push(
|
|
426
|
-
`// Space tokens - for margin, padding, gap\n<View ${paddingProp}="4 sm:6" ${gapProp}="2" ${marginProp}="3" />\n\n`
|
|
427
|
-
)
|
|
428
|
-
sections.push(
|
|
429
|
-
`// Size tokens - for width, height, dimensions\n<View ${widthProp}="10 sm:12" ${heightProp}="6" />\n\n`
|
|
430
|
-
)
|
|
431
|
-
sections.push(
|
|
432
|
-
`// Color tokens - for colors and backgrounds\n<View ${bgProp}="${sampleColorBg} hover:${sampleColorBg}" ${colorProp}="${sampleColorText}" />\n\n`
|
|
433
|
-
)
|
|
434
|
-
sections.push(
|
|
435
|
-
`// Radius tokens - for border-radius\n<View ${radiusProp}="${sampleRadius}" />\n`
|
|
436
|
-
)
|
|
437
|
-
sections.push('```\n\n')
|
|
438
|
-
} else if (syntaxChoice === 'object') {
|
|
439
|
-
sections.push('```tsx\n')
|
|
440
|
-
sections.push(
|
|
441
|
-
`// Space tokens - for margin, padding, gap\n<View ${paddingProp}={{ default: '4', sm: '6' }} ${gapProp}="2" ${marginProp}="3" />\n\n`
|
|
442
|
-
)
|
|
443
|
-
sections.push(
|
|
444
|
-
`// Size tokens - for width, height, dimensions\n<View ${widthProp}={{ default: '10', sm: '12' }} ${heightProp}="6" />\n\n`
|
|
445
|
-
)
|
|
446
|
-
sections.push(
|
|
447
|
-
`// Color tokens - for colors and backgrounds\n<View ${bgProp}={{ default: '${sampleColorBg}', hover: '${sampleColorBg}' }} ${colorProp}={{ default: '${sampleColorText}' }} />\n\n`
|
|
448
|
-
)
|
|
449
|
-
sections.push(
|
|
450
|
-
`// Radius tokens - for border-radius\n<View ${radiusProp}="${sampleRadius}" />\n`
|
|
451
|
-
)
|
|
452
|
-
sections.push('```\n\n')
|
|
453
|
-
} else {
|
|
454
|
-
sections.push('```tsx\n')
|
|
455
|
-
sections.push('// String form\n')
|
|
456
|
-
sections.push(
|
|
457
|
-
`<View ${paddingProp}="4 sm:6" ${widthProp}="10 sm:12" ${bgProp}="${sampleColorBg}" />\n\n`
|
|
458
|
-
)
|
|
459
|
-
sections.push('// Object form\n')
|
|
460
|
-
sections.push(
|
|
461
|
-
`<View ${paddingProp}={{ default: '4', sm: '6' }} ${widthProp}={{ default: '10', sm: '12' }} ${bgProp}={{ default: '${sampleColorBg}' }} />\n\n`
|
|
462
|
-
)
|
|
463
|
-
sections.push(
|
|
464
|
-
`// Space and radius tokens\n<View ${gapProp}="2" ${marginProp}="3" ${heightProp}="6" ${radiusProp}="${sampleRadius}" />\n`
|
|
465
|
-
)
|
|
466
|
-
sections.push('```\n\n')
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
// media queries
|
|
470
|
-
if (config.tamaguiConfig?.media) {
|
|
471
|
-
sections.push('## Media Queries\n\n')
|
|
472
|
-
sections.push('Available responsive breakpoints:\n\n')
|
|
473
|
-
|
|
474
|
-
const media = config.tamaguiConfig.media
|
|
475
|
-
const mediaEntries = Object.entries(media).sort(([a], [b]) => a.localeCompare(b))
|
|
476
|
-
|
|
477
|
-
for (const [name, query] of mediaEntries) {
|
|
478
|
-
sections.push(`- **${name}**: ${formatMediaQuery(query)}\n`)
|
|
479
|
-
}
|
|
480
|
-
sections.push('\n')
|
|
481
|
-
|
|
482
|
-
sections.push('### Media Query Usage\n\n')
|
|
483
|
-
sections.push(
|
|
484
|
-
'Media queries can be used as style props or with the `useMedia` hook:\n\n'
|
|
485
|
-
)
|
|
486
|
-
|
|
487
|
-
// pick a representative media query (prefer sm or md over height-*)
|
|
488
|
-
const representative =
|
|
489
|
-
mediaEntries.find(([n]) => n === 'sm' || n === 'md')?.[0] ||
|
|
490
|
-
mediaEntries.find(([n]) => !n.includes('-'))?.[0] ||
|
|
491
|
-
mediaEntries[0]?.[0]
|
|
492
|
-
|
|
493
|
-
if (representative) {
|
|
494
|
-
const isIdentifier = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(representative)
|
|
495
|
-
const mediaAccess = isIdentifier
|
|
496
|
-
? `media.${representative}`
|
|
497
|
-
: `media['${representative}']`
|
|
498
|
-
|
|
499
|
-
sections.push('```tsx\n')
|
|
500
|
-
if (syntaxChoice === 'string') {
|
|
501
|
-
sections.push('// As a clause in the same style value\n')
|
|
502
|
-
sections.push(`<View ${widthProp}="100% ${representative}:50%" />\n\n`)
|
|
503
|
-
} else if (syntaxChoice === 'object') {
|
|
504
|
-
sections.push('// Using the object form\n')
|
|
505
|
-
sections.push(
|
|
506
|
-
`<View ${widthProp}={{ default: '100%', '${representative}': '50%' }} />\n\n`
|
|
507
|
-
)
|
|
508
|
-
} else {
|
|
509
|
-
sections.push('// String form and object form\n')
|
|
510
|
-
sections.push(`<View ${widthProp}="100% ${representative}:50%" />\n`)
|
|
511
|
-
sections.push(
|
|
512
|
-
`<View ${widthProp}={{ default: '100%', '${representative}': '50%' }} />\n\n`
|
|
513
|
-
)
|
|
514
|
-
}
|
|
515
|
-
|
|
516
|
-
sections.push('// Using the useMedia hook\n')
|
|
517
|
-
sections.push('const media = useMedia()\n')
|
|
518
|
-
sections.push(`if (${mediaAccess}) {\n`)
|
|
519
|
-
sections.push(' // Render for this breakpoint\n')
|
|
520
|
-
sections.push('}\n')
|
|
521
|
-
sections.push('```\n\n')
|
|
522
|
-
}
|
|
523
|
-
}
|
|
524
|
-
|
|
525
|
-
// fonts
|
|
526
|
-
if (config.tamaguiConfig?.fonts) {
|
|
527
|
-
sections.push('## Fonts\n\n')
|
|
528
|
-
sections.push('Available font families:\n\n')
|
|
529
|
-
const fonts = config.tamaguiConfig.fonts
|
|
530
|
-
const fontNames = Object.keys(fonts).sort()
|
|
531
|
-
sections.push(fontNames.map((name) => `- ${name}`).join('\n'))
|
|
532
|
-
sections.push('\n\n')
|
|
533
|
-
}
|
|
534
|
-
|
|
535
|
-
// animations
|
|
536
|
-
if (config.tamaguiConfig?.animations) {
|
|
537
|
-
sections.push('## Animations\n\n')
|
|
538
|
-
sections.push('Available animation presets:\n\n')
|
|
539
|
-
const animations = config.tamaguiConfig.animations
|
|
540
|
-
if (animations.animations) {
|
|
541
|
-
const animationNames = Object.keys(animations.animations).sort()
|
|
542
|
-
sections.push(animationNames.map((name) => `- ${name}`).join('\n'))
|
|
543
|
-
sections.push('\n\n')
|
|
544
|
-
}
|
|
545
|
-
}
|
|
546
|
-
|
|
547
|
-
// components section: emit barrel's public import surface
|
|
548
|
-
const componentsSection: string[] = []
|
|
549
|
-
const componentSet = new Set<string>()
|
|
550
|
-
|
|
551
|
-
// try loading public exports from tamagui or candidate modules
|
|
552
|
-
let barrelExported = false
|
|
553
|
-
const candidateModules = [
|
|
554
|
-
'tamagui',
|
|
555
|
-
...(config.components || []).map((c: any) => c.moduleName),
|
|
556
|
-
]
|
|
557
|
-
for (const modName of candidateModules) {
|
|
558
|
-
if (!modName) continue
|
|
559
|
-
try {
|
|
560
|
-
const mod = require(modName)
|
|
561
|
-
for (const [key, val] of Object.entries(mod)) {
|
|
562
|
-
if (
|
|
563
|
-
/^[A-Z]/.test(key) &&
|
|
564
|
-
(typeof val === 'function' || (typeof val === 'object' && val !== null))
|
|
565
|
-
) {
|
|
566
|
-
if (
|
|
567
|
-
!key.endsWith('Context') &&
|
|
568
|
-
!key.endsWith('Provider') &&
|
|
569
|
-
key !== 'Fragment'
|
|
570
|
-
) {
|
|
571
|
-
componentSet.add(key)
|
|
572
|
-
barrelExported = true
|
|
573
|
-
}
|
|
574
|
-
}
|
|
575
|
-
}
|
|
576
|
-
if (barrelExported) break
|
|
577
|
-
} catch {
|
|
578
|
-
// fallback to config.components below
|
|
579
|
-
}
|
|
580
|
-
}
|
|
581
|
-
|
|
582
|
-
if (!barrelExported && config.components) {
|
|
583
|
-
for (const componentModule of config.components) {
|
|
584
|
-
for (const name of Object.keys(componentModule.nameToInfo || {})) {
|
|
585
|
-
componentSet.add(name)
|
|
586
|
-
}
|
|
587
|
-
}
|
|
588
|
-
}
|
|
589
|
-
|
|
590
|
-
// filter internal frames ending with Frame when parent or part exists
|
|
591
|
-
const allComponents = Array.from(componentSet).filter((name) => {
|
|
592
|
-
if (name.endsWith('Frame')) {
|
|
593
|
-
const base = name.replace(/Frame$/, '')
|
|
594
|
-
if (
|
|
595
|
-
componentSet.has(base) ||
|
|
596
|
-
name.startsWith('Popper') ||
|
|
597
|
-
name.startsWith('DialogPortal') ||
|
|
598
|
-
name.startsWith('SelectScrollButton')
|
|
599
|
-
) {
|
|
600
|
-
return false
|
|
601
|
-
}
|
|
602
|
-
}
|
|
603
|
-
return true
|
|
604
|
-
})
|
|
605
|
-
|
|
606
|
-
componentsSection.push('## Components\n\n')
|
|
607
|
-
componentsSection.push('Available named exports (import these names directly):\n\n')
|
|
608
|
-
for (const name of allComponents.sort()) {
|
|
609
|
-
componentsSection.push(`- ${name}\n`)
|
|
610
|
-
}
|
|
611
|
-
componentsSection.push('\n')
|
|
612
|
-
|
|
613
|
-
sections.push(...componentsSection)
|
|
614
|
-
return sections.join('')
|
|
615
|
-
}
|
|
616
|
-
|
|
617
|
-
function formatTokenValue(value: any): string {
|
|
618
|
-
if (typeof value === 'object' && value !== null && 'val' in value) {
|
|
619
|
-
return String(value.val)
|
|
620
|
-
}
|
|
621
|
-
return String(value)
|
|
622
|
-
}
|
|
623
|
-
|
|
624
|
-
function formatMediaQuery(query: any): string {
|
|
625
|
-
if (typeof query !== 'object' || query === null) {
|
|
626
|
-
return String(query)
|
|
627
|
-
}
|
|
628
|
-
const parts: string[] = []
|
|
629
|
-
if (query.minWidth !== undefined) {
|
|
630
|
-
parts.push(`min-width: ${query.minWidth}px (screens >= ${query.minWidth}px wide)`)
|
|
631
|
-
}
|
|
632
|
-
if (query.maxWidth !== undefined) {
|
|
633
|
-
parts.push(`max-width: ${query.maxWidth}px (screens <= ${query.maxWidth}px wide)`)
|
|
634
|
-
}
|
|
635
|
-
if (query.minHeight !== undefined) {
|
|
636
|
-
parts.push(`min-height: ${query.minHeight}px (screens >= ${query.minHeight}px tall)`)
|
|
637
|
-
}
|
|
638
|
-
if (query.maxHeight !== undefined) {
|
|
639
|
-
parts.push(`max-height: ${query.maxHeight}px (screens <= ${query.maxHeight}px tall)`)
|
|
640
|
-
}
|
|
641
|
-
if (query.hover !== undefined) {
|
|
642
|
-
parts.push(`pointer: hover (${query.hover})`)
|
|
643
|
-
}
|
|
644
|
-
if (query.pointer !== undefined) {
|
|
645
|
-
parts.push(`pointer: ${query.pointer}`)
|
|
646
|
-
}
|
|
647
|
-
if (query.prefersReducedMotion !== undefined) {
|
|
648
|
-
parts.push(`prefers-reduced-motion: ${query.prefersReducedMotion}`)
|
|
649
|
-
}
|
|
650
|
-
if (parts.length === 0) {
|
|
651
|
-
return JSON.stringify(query)
|
|
652
|
-
}
|
|
653
|
-
return parts.join(', ')
|
|
654
|
-
}
|
|
@@ -4,8 +4,4 @@ export interface GeneratePromptOptions extends CLIResolvedOptions {
|
|
|
4
4
|
styleValueSyntax?: 'string' | 'object' | 'both';
|
|
5
5
|
}
|
|
6
6
|
export declare function generatePrompt(options: GeneratePromptOptions): Promise<void>;
|
|
7
|
-
export interface GenerateMarkdownOptions {
|
|
8
|
-
styleValueSyntax?: 'string' | 'object' | 'both';
|
|
9
|
-
}
|
|
10
|
-
export declare function generateMarkdown(config: any, options?: GenerateMarkdownOptions): string;
|
|
11
7
|
//# sourceMappingURL=generate-prompt.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate-prompt.d.ts","sourceRoot":"","sources":["../src/generate-prompt.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"generate-prompt.d.ts","sourceRoot":"","sources":["../src/generate-prompt.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAA;AAExD,MAAM,WAAW,qBAAsB,SAAQ,kBAAkB;IAC/D,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,gBAAgB,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAAA;CAChD;AAED,wBAAsB,cAAc,CAAC,OAAO,EAAE,qBAAqB,iBAoClE"}
|