@nghitrum/dsforge 0.1.5-alpha.1 → 0.1.5-alpha.10
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 +22 -29
- package/dist/chunk-A7VW6SII.js +436 -0
- package/dist/chunk-YUPXTQZ5.js +118 -0
- package/dist/{chunk-RI3XDGKU.js → chunk-ZZRPNO6Z.js} +12 -17
- package/dist/cli/index.js +292 -310
- package/dist/componentDefinitions-5LFCNFQY.js +8 -0
- package/dist/{emitter-ZNRPJ4D6.js → emitter-IC77G4QF.js} +1 -1
- package/dist/generateAiFolder-3OOFWBH7.js +70 -0
- package/dist/generateComponentJson-XBEUWCW6.js +16 -0
- package/dist/generateComponentMetadata-2L5VNERD.js +13 -0
- package/dist/generateRegistry-3MEZDJAJ.js +19 -0
- package/dist/{html-6SIG34W5.js → html-XGJ22SXB.js} +385 -123
- package/dist/index.d.ts +12 -0
- package/dist/index.js +150 -46
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -3,7 +3,17 @@ import {
|
|
|
3
3
|
generateChangelog,
|
|
4
4
|
generatePackageJson,
|
|
5
5
|
generateTsConfig
|
|
6
|
-
} from "../chunk-
|
|
6
|
+
} from "../chunk-ZZRPNO6Z.js";
|
|
7
|
+
import {
|
|
8
|
+
CONTROL_SIZE_PRESETS,
|
|
9
|
+
PRESETS,
|
|
10
|
+
PRESET_BASE_UNITS,
|
|
11
|
+
RADIUS_PRESETS,
|
|
12
|
+
SPACING_PRESETS,
|
|
13
|
+
applyPreset,
|
|
14
|
+
buildSemanticSpacing,
|
|
15
|
+
isProUnlocked
|
|
16
|
+
} from "../chunk-YUPXTQZ5.js";
|
|
7
17
|
|
|
8
18
|
// src/cli/index.ts
|
|
9
19
|
import { program } from "commander";
|
|
@@ -399,43 +409,6 @@ async function confirm(question) {
|
|
|
399
409
|
}
|
|
400
410
|
|
|
401
411
|
// src/cli/commands/init.ts
|
|
402
|
-
var SPACING_PRESETS = {
|
|
403
|
-
compact: {
|
|
404
|
-
"1": 2,
|
|
405
|
-
"2": 4,
|
|
406
|
-
"3": 8,
|
|
407
|
-
"4": 12,
|
|
408
|
-
"5": 16,
|
|
409
|
-
"6": 24,
|
|
410
|
-
"7": 32,
|
|
411
|
-
"8": 48
|
|
412
|
-
},
|
|
413
|
-
comfortable: {
|
|
414
|
-
"1": 4,
|
|
415
|
-
"2": 8,
|
|
416
|
-
"3": 12,
|
|
417
|
-
"4": 16,
|
|
418
|
-
"5": 24,
|
|
419
|
-
"6": 32,
|
|
420
|
-
"7": 48,
|
|
421
|
-
"8": 64
|
|
422
|
-
},
|
|
423
|
-
spacious: {
|
|
424
|
-
"1": 6,
|
|
425
|
-
"2": 12,
|
|
426
|
-
"3": 18,
|
|
427
|
-
"4": 24,
|
|
428
|
-
"5": 36,
|
|
429
|
-
"6": 48,
|
|
430
|
-
"7": 72,
|
|
431
|
-
"8": 96
|
|
432
|
-
}
|
|
433
|
-
};
|
|
434
|
-
var RADIUS_PRESETS = {
|
|
435
|
-
compact: { none: 0, sm: 2, md: 3, lg: 6, xl: 10, full: 9999 },
|
|
436
|
-
comfortable: { none: 0, sm: 2, md: 4, lg: 8, xl: 16, full: 9999 },
|
|
437
|
-
spacious: { none: 0, sm: 3, md: 6, lg: 12, xl: 20, full: 9999 }
|
|
438
|
-
};
|
|
439
412
|
function buildInitialConfig(name, preset = "comfortable") {
|
|
440
413
|
const spacing = SPACING_PRESETS[preset];
|
|
441
414
|
const radius = RADIUS_PRESETS[preset];
|
|
@@ -626,19 +599,9 @@ function buildInitialConfig(name, preset = "comfortable") {
|
|
|
626
599
|
}
|
|
627
600
|
},
|
|
628
601
|
spacing: {
|
|
629
|
-
baseUnit: preset
|
|
602
|
+
baseUnit: PRESET_BASE_UNITS[preset],
|
|
630
603
|
scale: spacing,
|
|
631
|
-
semantic:
|
|
632
|
-
"component-padding-xs": `${spacing[1]}`,
|
|
633
|
-
"component-padding-sm": `${spacing[2]}`,
|
|
634
|
-
"component-padding-md": `${spacing[4]}`,
|
|
635
|
-
"component-padding-lg": `${spacing[5]}`,
|
|
636
|
-
"layout-gap-xs": `${spacing[2]}`,
|
|
637
|
-
"layout-gap-sm": `${spacing[3]}`,
|
|
638
|
-
"layout-gap-md": `${spacing[5]}`,
|
|
639
|
-
"layout-gap-lg": `${spacing[6]}`,
|
|
640
|
-
"layout-section": `${spacing[7]}`
|
|
641
|
-
}
|
|
604
|
+
semantic: buildSemanticSpacing(spacing)
|
|
642
605
|
},
|
|
643
606
|
radius,
|
|
644
607
|
elevation: {
|
|
@@ -775,7 +738,15 @@ async function runInit(cwd, options) {
|
|
|
775
738
|
}
|
|
776
739
|
const name = rawName.replace(/\s+/g, "-").toLowerCase();
|
|
777
740
|
let preset;
|
|
778
|
-
if (
|
|
741
|
+
if (!isProUnlocked()) {
|
|
742
|
+
if (options.preset && options.preset !== "comfortable") {
|
|
743
|
+
logger.hint(
|
|
744
|
+
`Preset "${options.preset}" requires dsforge Pro`,
|
|
745
|
+
`Set DSFORGE_KEY to unlock compact and spacious. Using comfortable.`
|
|
746
|
+
);
|
|
747
|
+
}
|
|
748
|
+
preset = "comfortable";
|
|
749
|
+
} else if (options.preset && VALID_PRESETS.includes(options.preset)) {
|
|
779
750
|
preset = options.preset;
|
|
780
751
|
} else {
|
|
781
752
|
const answer = await ask(
|
|
@@ -1803,6 +1774,19 @@ function emitBaseCss(config, resolution) {
|
|
|
1803
1774
|
if (typoEntries.length > 0) {
|
|
1804
1775
|
sections.push(emitBlock(":root", typoEntries, "Typography"));
|
|
1805
1776
|
}
|
|
1777
|
+
const currentPreset = config.philosophy?.density ?? "comfortable";
|
|
1778
|
+
const controlSizes = CONTROL_SIZE_PRESETS[currentPreset] ?? CONTROL_SIZE_PRESETS.comfortable;
|
|
1779
|
+
sections.push(
|
|
1780
|
+
emitBlock(
|
|
1781
|
+
":root",
|
|
1782
|
+
[
|
|
1783
|
+
["control-size-sm", `${controlSizes.sm}px`],
|
|
1784
|
+
["control-size-md", `${controlSizes.md}px`],
|
|
1785
|
+
["control-size-lg", `${controlSizes.lg}px`]
|
|
1786
|
+
],
|
|
1787
|
+
"Control sizes"
|
|
1788
|
+
)
|
|
1789
|
+
);
|
|
1806
1790
|
const radiusEntries = Object.entries(
|
|
1807
1791
|
config.radius ?? {}
|
|
1808
1792
|
).filter(([, v]) => v !== void 0).map(([k, v]) => [`radius-${k}`, v === 9999 ? "9999px" : `${v}px`]);
|
|
@@ -1861,6 +1845,38 @@ function emitThemeCss(themeName, themeOverrides, config) {
|
|
|
1861
1845
|
lines.push(emitBlock(`:root[data-theme="${themeName}"]`, entries));
|
|
1862
1846
|
return lines.join("\n") + "\n";
|
|
1863
1847
|
}
|
|
1848
|
+
function emitDensityCss(config) {
|
|
1849
|
+
const lines = [
|
|
1850
|
+
`/* \u2500\u2500\u2500 ${config.meta.name} \u2014 density presets \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */`,
|
|
1851
|
+
`/* Generated by dsforge. Do not edit manually. */`,
|
|
1852
|
+
`/* Pro feature: import this file to enable runtime density switching. */`,
|
|
1853
|
+
`/* Usage: <html data-density="compact | comfortable | spacious"> */`,
|
|
1854
|
+
`/* or wrap with <DensityProvider density="compact"> */`,
|
|
1855
|
+
""
|
|
1856
|
+
];
|
|
1857
|
+
for (const preset of PRESETS) {
|
|
1858
|
+
const scale = SPACING_PRESETS[preset];
|
|
1859
|
+
const radius = RADIUS_PRESETS[preset];
|
|
1860
|
+
const semantic = buildSemanticSpacing(scale);
|
|
1861
|
+
const entries = [];
|
|
1862
|
+
for (const [key, value] of Object.entries(scale)) {
|
|
1863
|
+
entries.push([`spacing-${key}`, `${value}px`]);
|
|
1864
|
+
}
|
|
1865
|
+
for (const [key, value] of Object.entries(semantic)) {
|
|
1866
|
+
entries.push([key, `${value}px`]);
|
|
1867
|
+
}
|
|
1868
|
+
for (const [key, value] of Object.entries(radius)) {
|
|
1869
|
+
entries.push([`radius-${key}`, value === 9999 ? "9999px" : `${value}px`]);
|
|
1870
|
+
}
|
|
1871
|
+
const controlSizes = CONTROL_SIZE_PRESETS[preset];
|
|
1872
|
+
entries.push(["control-size-sm", `${controlSizes.sm}px`]);
|
|
1873
|
+
entries.push(["control-size-md", `${controlSizes.md}px`]);
|
|
1874
|
+
entries.push(["control-size-lg", `${controlSizes.lg}px`]);
|
|
1875
|
+
lines.push(emitBlock(`[data-density="${preset}"]`, entries, `Preset: ${preset}`));
|
|
1876
|
+
lines.push("");
|
|
1877
|
+
}
|
|
1878
|
+
return lines.join("\n");
|
|
1879
|
+
}
|
|
1864
1880
|
function generateCssFiles(config, resolution) {
|
|
1865
1881
|
const files = [];
|
|
1866
1882
|
files.push({
|
|
@@ -1891,192 +1907,6 @@ function generateCssFiles(config, resolution) {
|
|
|
1891
1907
|
return files;
|
|
1892
1908
|
}
|
|
1893
1909
|
|
|
1894
|
-
// src/generators/metadata/generator.ts
|
|
1895
|
-
var COMPONENT_DEFAULTS = {
|
|
1896
|
-
button: {
|
|
1897
|
-
description: "Triggers an action or navigation. The primary interactive element.",
|
|
1898
|
-
role: "action-trigger",
|
|
1899
|
-
hierarchyLevel: "primary",
|
|
1900
|
-
interactionModel: "synchronous",
|
|
1901
|
-
layoutImpact: "inline",
|
|
1902
|
-
destructive: false,
|
|
1903
|
-
sizes: ["sm", "md", "lg"]
|
|
1904
|
-
},
|
|
1905
|
-
input: {
|
|
1906
|
-
description: "Accepts user text input. Use with a label for accessibility.",
|
|
1907
|
-
role: "data-entry",
|
|
1908
|
-
hierarchyLevel: "primary",
|
|
1909
|
-
interactionModel: "synchronous",
|
|
1910
|
-
layoutImpact: "block",
|
|
1911
|
-
destructive: false,
|
|
1912
|
-
sizes: ["sm", "md", "lg"]
|
|
1913
|
-
},
|
|
1914
|
-
card: {
|
|
1915
|
-
description: "Groups related content with optional header, body, and footer slots.",
|
|
1916
|
-
role: "content-container",
|
|
1917
|
-
hierarchyLevel: "utility",
|
|
1918
|
-
interactionModel: "none",
|
|
1919
|
-
layoutImpact: "block",
|
|
1920
|
-
destructive: false
|
|
1921
|
-
},
|
|
1922
|
-
badge: {
|
|
1923
|
-
description: "Compact label for status, categories, or counts. Display-only \u2014 not interactive.",
|
|
1924
|
-
role: "status-indicator",
|
|
1925
|
-
hierarchyLevel: "utility",
|
|
1926
|
-
interactionModel: "none",
|
|
1927
|
-
layoutImpact: "inline",
|
|
1928
|
-
destructive: false,
|
|
1929
|
-
sizes: ["sm", "md", "lg"]
|
|
1930
|
-
},
|
|
1931
|
-
checkbox: {
|
|
1932
|
-
description: "Binary toggle for boolean values. Supports indeterminate state for partial selections.",
|
|
1933
|
-
role: "data-entry",
|
|
1934
|
-
hierarchyLevel: "primary",
|
|
1935
|
-
interactionModel: "synchronous",
|
|
1936
|
-
layoutImpact: "inline",
|
|
1937
|
-
destructive: false,
|
|
1938
|
-
sizes: ["sm", "md", "lg"]
|
|
1939
|
-
},
|
|
1940
|
-
radio: {
|
|
1941
|
-
description: "Single selection within a mutually exclusive group. Always use inside RadioGroup.",
|
|
1942
|
-
role: "data-entry",
|
|
1943
|
-
hierarchyLevel: "primary",
|
|
1944
|
-
interactionModel: "synchronous",
|
|
1945
|
-
layoutImpact: "inline",
|
|
1946
|
-
destructive: false,
|
|
1947
|
-
sizes: ["sm", "md", "lg"]
|
|
1948
|
-
},
|
|
1949
|
-
select: {
|
|
1950
|
-
description: "Dropdown picker for selecting from a list of options. Wraps native <select> for accessibility.",
|
|
1951
|
-
role: "data-entry",
|
|
1952
|
-
hierarchyLevel: "primary",
|
|
1953
|
-
interactionModel: "synchronous",
|
|
1954
|
-
layoutImpact: "block",
|
|
1955
|
-
destructive: false,
|
|
1956
|
-
sizes: ["sm", "md", "lg"]
|
|
1957
|
-
},
|
|
1958
|
-
toast: {
|
|
1959
|
-
description: "Feedback messages for user actions. Alert is inline; Toast is an overlay with auto-dismiss.",
|
|
1960
|
-
role: "feedback",
|
|
1961
|
-
hierarchyLevel: "utility",
|
|
1962
|
-
interactionModel: "asynchronous",
|
|
1963
|
-
layoutImpact: "overlay",
|
|
1964
|
-
destructive: false
|
|
1965
|
-
},
|
|
1966
|
-
spinner: {
|
|
1967
|
-
description: "Loading indicator for async operations. Use with an accessible label for screen readers.",
|
|
1968
|
-
role: "loading-indicator",
|
|
1969
|
-
hierarchyLevel: "utility",
|
|
1970
|
-
interactionModel: "asynchronous",
|
|
1971
|
-
layoutImpact: "inline",
|
|
1972
|
-
destructive: false,
|
|
1973
|
-
sizes: ["xs", "sm", "md", "lg", "xl"]
|
|
1974
|
-
}
|
|
1975
|
-
};
|
|
1976
|
-
function buildComponentMetadata(componentName, rule, config) {
|
|
1977
|
-
const defaults = COMPONENT_DEFAULTS[componentName.toLowerCase()] ?? {};
|
|
1978
|
-
const variants = rule.allowedVariants ?? ["default"];
|
|
1979
|
-
const requiredProps = rule.requiredProps ?? [];
|
|
1980
|
-
const tokens = {};
|
|
1981
|
-
for (const [tokenName] of Object.entries(rule.tokens ?? {})) {
|
|
1982
|
-
tokens[tokenName] = `--${tokenName}`;
|
|
1983
|
-
}
|
|
1984
|
-
const meta = {
|
|
1985
|
-
component: pascalCase(componentName),
|
|
1986
|
-
version: config.meta.version,
|
|
1987
|
-
description: defaults.description ?? `A ${componentName} component.`,
|
|
1988
|
-
role: defaults.role ?? "ui-element",
|
|
1989
|
-
hierarchyLevel: defaults.hierarchyLevel ?? "utility",
|
|
1990
|
-
interactionModel: defaults.interactionModel ?? "none",
|
|
1991
|
-
layoutImpact: defaults.layoutImpact ?? "inline",
|
|
1992
|
-
destructive: componentName.toLowerCase().includes("delete") || variants.includes("danger"),
|
|
1993
|
-
allowedVariants: variants,
|
|
1994
|
-
defaultVariant: variants[0] ?? "default",
|
|
1995
|
-
requiredProps,
|
|
1996
|
-
optionalProps: buildOptionalProps(componentName, defaults),
|
|
1997
|
-
tokens,
|
|
1998
|
-
accessibilityContract: {
|
|
1999
|
-
keyboard: rule.a11y?.keyboard ?? true,
|
|
2000
|
-
focusRing: rule.a11y?.focusRing ?? true,
|
|
2001
|
-
ariaLabel: rule.a11y?.ariaLabel ?? "optional",
|
|
2002
|
-
...rule.a11y?.role ? { role: rule.a11y.role } : {}
|
|
2003
|
-
},
|
|
2004
|
-
governanceRules: {
|
|
2005
|
-
...rule.maxWidth ? { maxWidth: rule.maxWidth } : {},
|
|
2006
|
-
...rule.allowedRadius ? { allowedRadius: rule.allowedRadius } : {},
|
|
2007
|
-
...rule.allowedShadows ? { allowedShadows: rule.allowedShadows } : {},
|
|
2008
|
-
...rule.colorPalette ? { colorPalette: rule.colorPalette } : {}
|
|
2009
|
-
}
|
|
2010
|
-
};
|
|
2011
|
-
if (defaults.sizes) {
|
|
2012
|
-
meta.sizes = defaults.sizes;
|
|
2013
|
-
}
|
|
2014
|
-
return meta;
|
|
2015
|
-
}
|
|
2016
|
-
function buildOptionalProps(componentName, _defaults) {
|
|
2017
|
-
const common = ["className", "style", "id", "data-testid"];
|
|
2018
|
-
const byComponent = {
|
|
2019
|
-
button: [
|
|
2020
|
-
"size",
|
|
2021
|
-
"loading",
|
|
2022
|
-
"disabled",
|
|
2023
|
-
"fullWidth",
|
|
2024
|
-
"iconLeft",
|
|
2025
|
-
"iconRight",
|
|
2026
|
-
"onClick"
|
|
2027
|
-
],
|
|
2028
|
-
input: [
|
|
2029
|
-
"size",
|
|
2030
|
-
"disabled",
|
|
2031
|
-
"label",
|
|
2032
|
-
"helperText",
|
|
2033
|
-
"errorMessage",
|
|
2034
|
-
"placeholder",
|
|
2035
|
-
"startAdornment",
|
|
2036
|
-
"endAdornment",
|
|
2037
|
-
"onChange"
|
|
2038
|
-
],
|
|
2039
|
-
card: ["maxWidth", "noPadding", "onClick"],
|
|
2040
|
-
badge: ["size", "dot"],
|
|
2041
|
-
checkbox: ["size", "disabled", "label", "helperText", "indeterminate", "checked", "onChange"],
|
|
2042
|
-
radio: ["size", "disabled", "label", "value", "onChange"],
|
|
2043
|
-
select: ["size", "disabled", "label", "helperText", "errorMessage", "placeholder", "options", "fullWidth", "onChange"],
|
|
2044
|
-
toast: ["variant", "title", "dismissible", "duration", "onDismiss"],
|
|
2045
|
-
spinner: ["size", "variant", "label"]
|
|
2046
|
-
};
|
|
2047
|
-
return [...byComponent[componentName.toLowerCase()] ?? [], ...common];
|
|
2048
|
-
}
|
|
2049
|
-
function pascalCase(str) {
|
|
2050
|
-
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
2051
|
-
}
|
|
2052
|
-
function buildIndexMetadata(config, componentNames, tokenCount) {
|
|
2053
|
-
return {
|
|
2054
|
-
name: config.meta.name,
|
|
2055
|
-
version: config.meta.version,
|
|
2056
|
-
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2057
|
-
components: componentNames.map(pascalCase),
|
|
2058
|
-
tokenCount,
|
|
2059
|
-
themes: Object.keys(config.themes ?? {})
|
|
2060
|
-
};
|
|
2061
|
-
}
|
|
2062
|
-
function generateMetadata(config, rules, tokenCount) {
|
|
2063
|
-
const files = [];
|
|
2064
|
-
const componentNames = Object.keys(rules);
|
|
2065
|
-
for (const [componentName, rule] of Object.entries(rules)) {
|
|
2066
|
-
const metadata = buildComponentMetadata(componentName, rule, config);
|
|
2067
|
-
files.push({
|
|
2068
|
-
filename: `${componentName}.json`,
|
|
2069
|
-
content: JSON.stringify(metadata, null, 2)
|
|
2070
|
-
});
|
|
2071
|
-
}
|
|
2072
|
-
const index = buildIndexMetadata(config, componentNames, tokenCount);
|
|
2073
|
-
files.push({
|
|
2074
|
-
filename: "index.json",
|
|
2075
|
-
content: JSON.stringify(index, null, 2)
|
|
2076
|
-
});
|
|
2077
|
-
return files;
|
|
2078
|
-
}
|
|
2079
|
-
|
|
2080
1910
|
// src/adapters/react/components/button.ts
|
|
2081
1911
|
function generateButton(config, rule) {
|
|
2082
1912
|
const variants = rule?.allowedVariants ?? [
|
|
@@ -2866,9 +2696,17 @@ export interface CheckboxProps
|
|
|
2866
2696
|
// \u2500\u2500\u2500 Size map \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
2867
2697
|
|
|
2868
2698
|
const SIZE_BOX: Record<"sm" | "md" | "lg", string> = {
|
|
2869
|
-
sm: "14px",
|
|
2870
|
-
md: "16px",
|
|
2871
|
-
lg: "20px",
|
|
2699
|
+
sm: "var(--control-size-sm, 14px)",
|
|
2700
|
+
md: "var(--control-size-md, 16px)",
|
|
2701
|
+
lg: "var(--control-size-lg, 20px)",
|
|
2702
|
+
};
|
|
2703
|
+
|
|
2704
|
+
// SVG check/dash icon fits inside the box with a 6px inset, via calc() so it
|
|
2705
|
+
// tracks the CSS var when density changes at runtime.
|
|
2706
|
+
const SVG_SIZE: Record<"sm" | "md" | "lg", string> = {
|
|
2707
|
+
sm: "calc(var(--control-size-sm, 14px) - 6px)",
|
|
2708
|
+
md: "calc(var(--control-size-md, 16px) - 6px)",
|
|
2709
|
+
lg: "calc(var(--control-size-lg, 20px) - 6px)",
|
|
2872
2710
|
};
|
|
2873
2711
|
|
|
2874
2712
|
const SIZE_FONT: Record<"sm" | "md" | "lg", string> = {
|
|
@@ -3012,8 +2850,7 @@ export const Checkbox = React.forwardRef<HTMLInputElement, CheckboxProps>(
|
|
|
3012
2850
|
<span style={boxStyle} aria-hidden="true">
|
|
3013
2851
|
{isActive && (
|
|
3014
2852
|
<svg
|
|
3015
|
-
|
|
3016
|
-
height={parseInt(boxSize) - 6}
|
|
2853
|
+
style={{ width: SVG_SIZE[size], height: SVG_SIZE[size] }}
|
|
3017
2854
|
viewBox="0 0 10 10"
|
|
3018
2855
|
fill="none"
|
|
3019
2856
|
stroke="#fff"
|
|
@@ -3115,9 +2952,9 @@ export interface RadioGroupProps {
|
|
|
3115
2952
|
// \u2500\u2500\u2500 Size map \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
3116
2953
|
|
|
3117
2954
|
const SIZE_BOX: Record<"sm" | "md" | "lg", string> = {
|
|
3118
|
-
sm: "14px",
|
|
3119
|
-
md: "16px",
|
|
3120
|
-
lg: "20px",
|
|
2955
|
+
sm: "var(--control-size-sm, 14px)",
|
|
2956
|
+
md: "var(--control-size-md, 16px)",
|
|
2957
|
+
lg: "var(--control-size-lg, 20px)",
|
|
3121
2958
|
};
|
|
3122
2959
|
|
|
3123
2960
|
const SIZE_FONT: Record<"sm" | "md" | "lg", string> = {
|
|
@@ -4088,6 +3925,62 @@ function generateThemeProvider(config) {
|
|
|
4088
3925
|
const themeNames = Object.keys(config.themes ?? { light: {}, dark: {} });
|
|
4089
3926
|
const defaultTheme = themeNames.includes("light") ? "light" : themeNames[0] ?? "light";
|
|
4090
3927
|
const themeType = themeNames.map((t) => `"${t}"`).join(" | ");
|
|
3928
|
+
const isPro = isProUnlocked();
|
|
3929
|
+
const defaultDensity = config.meta.preset ?? "comfortable";
|
|
3930
|
+
const densityImport = isPro ? `
|
|
3931
|
+
import "../tokens/density.css";` : "";
|
|
3932
|
+
const densityTypes = isPro ? `
|
|
3933
|
+
export type DensityName = "compact" | "comfortable" | "spacious";
|
|
3934
|
+
` : "";
|
|
3935
|
+
const densityContextTypes = isPro ? `
|
|
3936
|
+
export interface DensityContextValue {
|
|
3937
|
+
density: DensityName;
|
|
3938
|
+
setDensity: (density: DensityName) => void;
|
|
3939
|
+
}
|
|
3940
|
+
` : "";
|
|
3941
|
+
const densityContext = isPro ? `
|
|
3942
|
+
export const DensityContext = React.createContext<DensityContextValue>({
|
|
3943
|
+
density: "${defaultDensity}",
|
|
3944
|
+
setDensity: () => undefined,
|
|
3945
|
+
});
|
|
3946
|
+
|
|
3947
|
+
/**
|
|
3948
|
+
* Hook to read and change the current density.
|
|
3949
|
+
* Must be used inside a <ThemeProvider>.
|
|
3950
|
+
*/
|
|
3951
|
+
export function useDensity(): DensityContextValue {
|
|
3952
|
+
return React.useContext(DensityContext);
|
|
3953
|
+
}
|
|
3954
|
+
` : "";
|
|
3955
|
+
const densityProp = isPro ? `
|
|
3956
|
+
/** Component density. Requires density.css to be imported. Defaults to "${defaultDensity}". */
|
|
3957
|
+
density?: DensityName;` : "";
|
|
3958
|
+
const densityOnChangeProp = isPro ? `
|
|
3959
|
+
/** Called when setDensity is invoked. */
|
|
3960
|
+
onDensityChange?: (density: DensityName) => void;` : "";
|
|
3961
|
+
const densityState = isPro ? `
|
|
3962
|
+
const [density, setDensityState] = React.useState<DensityName>(initialDensity);
|
|
3963
|
+
|
|
3964
|
+
React.useEffect(() => {
|
|
3965
|
+
setDensityState(initialDensity);
|
|
3966
|
+
}, [initialDensity]);
|
|
3967
|
+
|
|
3968
|
+
const setDensity = React.useCallback(
|
|
3969
|
+
(next: DensityName) => {
|
|
3970
|
+
setDensityState(next);
|
|
3971
|
+
onDensityChange?.(next);
|
|
3972
|
+
},
|
|
3973
|
+
[onDensityChange],
|
|
3974
|
+
);
|
|
3975
|
+
` : "";
|
|
3976
|
+
const densityDestructure = isPro ? `,
|
|
3977
|
+
density: initialDensity = "${defaultDensity}",
|
|
3978
|
+
onDensityChange,` : "";
|
|
3979
|
+
const densityProviderOpen = isPro ? `
|
|
3980
|
+
<DensityContext.Provider value={{ density, setDensity }}>` : "";
|
|
3981
|
+
const densityDataAttr = isPro ? ` data-density={density}` : "";
|
|
3982
|
+
const densityProviderClose = isPro ? `
|
|
3983
|
+
</DensityContext.Provider>` : "";
|
|
4091
3984
|
return `/**
|
|
4092
3985
|
* ThemeProvider \u2014 ${config.meta.name}
|
|
4093
3986
|
*
|
|
@@ -4099,27 +3992,27 @@ function generateThemeProvider(config) {
|
|
|
4099
3992
|
* import "@${config.meta.name}/tokens/light.css"; // or dark.css
|
|
4100
3993
|
* import { ThemeProvider } from "@${config.meta.name}";
|
|
4101
3994
|
*
|
|
4102
|
-
* <ThemeProvider theme="light">
|
|
3995
|
+
* <ThemeProvider theme="light"${isPro ? ` density="${defaultDensity}"` : ""}>
|
|
4103
3996
|
* <App />
|
|
4104
3997
|
* </ThemeProvider>
|
|
4105
3998
|
*/
|
|
4106
3999
|
|
|
4107
|
-
import React from "react"
|
|
4000
|
+
import React from "react";${densityImport}
|
|
4108
4001
|
|
|
4109
4002
|
// \u2500\u2500\u2500 Types \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
4110
4003
|
|
|
4111
4004
|
export type ThemeName = ${themeType};
|
|
4112
|
-
|
|
4005
|
+
${densityTypes}
|
|
4113
4006
|
export interface ThemeContextValue {
|
|
4114
4007
|
theme: ThemeName;
|
|
4115
4008
|
setTheme: (theme: ThemeName) => void;
|
|
4116
4009
|
}
|
|
4117
|
-
|
|
4010
|
+
${densityContextTypes}
|
|
4118
4011
|
export interface ThemeProviderProps {
|
|
4119
4012
|
/** Initial theme. Defaults to "${defaultTheme}". */
|
|
4120
4013
|
theme?: ThemeName;
|
|
4121
4014
|
/** Called when setTheme is invoked \u2014 use to persist theme preference. */
|
|
4122
|
-
onThemeChange?: (theme: ThemeName) => void
|
|
4015
|
+
onThemeChange?: (theme: ThemeName) => void;${densityProp}${densityOnChangeProp}
|
|
4123
4016
|
children: React.ReactNode;
|
|
4124
4017
|
}
|
|
4125
4018
|
|
|
@@ -4137,12 +4030,12 @@ export const ThemeContext = React.createContext<ThemeContextValue>({
|
|
|
4137
4030
|
export function useTheme(): ThemeContextValue {
|
|
4138
4031
|
return React.useContext(ThemeContext);
|
|
4139
4032
|
}
|
|
4140
|
-
|
|
4033
|
+
${densityContext}
|
|
4141
4034
|
// \u2500\u2500\u2500 Provider \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
4142
4035
|
|
|
4143
4036
|
export function ThemeProvider({
|
|
4144
4037
|
theme: initialTheme = "${defaultTheme}",
|
|
4145
|
-
onThemeChange
|
|
4038
|
+
onThemeChange,${densityDestructure}
|
|
4146
4039
|
children,
|
|
4147
4040
|
}: ThemeProviderProps) {
|
|
4148
4041
|
const [theme, setThemeState] = React.useState<ThemeName>(initialTheme);
|
|
@@ -4158,13 +4051,13 @@ export function ThemeProvider({
|
|
|
4158
4051
|
},
|
|
4159
4052
|
[onThemeChange],
|
|
4160
4053
|
);
|
|
4161
|
-
|
|
4162
|
-
return (
|
|
4163
|
-
|
|
4164
|
-
|
|
4165
|
-
|
|
4166
|
-
|
|
4167
|
-
|
|
4054
|
+
${densityState}
|
|
4055
|
+
return (${densityProviderOpen}
|
|
4056
|
+
<ThemeContext.Provider value={{ theme, setTheme }}>
|
|
4057
|
+
<div data-theme={theme}${densityDataAttr} style={{ display: "contents" }}>
|
|
4058
|
+
{children}
|
|
4059
|
+
</div>
|
|
4060
|
+
</ThemeContext.Provider>${densityProviderClose}
|
|
4168
4061
|
);
|
|
4169
4062
|
}
|
|
4170
4063
|
`;
|
|
@@ -4181,9 +4074,9 @@ function generateComponentIndex(config, componentNames) {
|
|
|
4181
4074
|
""
|
|
4182
4075
|
];
|
|
4183
4076
|
for (const name of componentNames) {
|
|
4184
|
-
lines.push(`export * from "
|
|
4077
|
+
lines.push(`export * from "./components/${name}/${name}";`);
|
|
4185
4078
|
}
|
|
4186
|
-
lines.push(`export * from "./ThemeProvider";`);
|
|
4079
|
+
lines.push(`export * from "./components/ThemeProvider/ThemeProvider";`);
|
|
4187
4080
|
lines.push("");
|
|
4188
4081
|
return lines.join("\n");
|
|
4189
4082
|
}
|
|
@@ -4761,6 +4654,13 @@ async function runGenerate(cwd, options) {
|
|
|
4761
4654
|
options.debug ?? false
|
|
4762
4655
|
);
|
|
4763
4656
|
}
|
|
4657
|
+
const presetValue = config.meta.preset;
|
|
4658
|
+
if (presetValue === "compact" || presetValue === "comfortable" || presetValue === "spacious") {
|
|
4659
|
+
applyPreset(config, presetValue);
|
|
4660
|
+
}
|
|
4661
|
+
const fullRules = Object.fromEntries(
|
|
4662
|
+
REACT_COMPONENTS.map((name) => [name, rules[name] ?? {}])
|
|
4663
|
+
);
|
|
4764
4664
|
logger.step("Running pre-flight validation...");
|
|
4765
4665
|
const validation = validateConfig(config, rules);
|
|
4766
4666
|
const errors = validation.issues.filter((i) => i.severity === "error");
|
|
@@ -4814,6 +4714,13 @@ async function runGenerate(cwd, options) {
|
|
|
4814
4714
|
await writeFile(path3.join(tokensDir, filename), content);
|
|
4815
4715
|
logger.dim(` \u2192 tokens/${filename}`);
|
|
4816
4716
|
}
|
|
4717
|
+
if (isProUnlocked()) {
|
|
4718
|
+
await writeFile(
|
|
4719
|
+
path3.join(tokensDir, "density.css"),
|
|
4720
|
+
emitDensityCss(config)
|
|
4721
|
+
);
|
|
4722
|
+
logger.dim(` \u2192 tokens/density.css`);
|
|
4723
|
+
}
|
|
4817
4724
|
const tokenFiles = reactAdapter.generateTokenFiles(config, resolution);
|
|
4818
4725
|
for (const { filename, content } of tokenFiles) {
|
|
4819
4726
|
await writeFile(path3.join(tokensDir, filename), content);
|
|
@@ -4823,21 +4730,55 @@ async function runGenerate(cwd, options) {
|
|
|
4823
4730
|
}
|
|
4824
4731
|
if (!only || only === "components") {
|
|
4825
4732
|
logger.step("Generating React components...");
|
|
4826
|
-
const
|
|
4827
|
-
await ensureDir(
|
|
4733
|
+
const componentsDir = path3.join(outRoot, "components");
|
|
4734
|
+
await ensureDir(componentsDir);
|
|
4828
4735
|
const generatedNames = [];
|
|
4736
|
+
const generatedComponentJsons = [];
|
|
4737
|
+
const flatTokens = {};
|
|
4738
|
+
for (const [k, v] of Object.entries(resolution.tokens)) {
|
|
4739
|
+
flatTokens[`--${k.replace(/^(global|semantic|component)\./, "")}`] = v;
|
|
4740
|
+
}
|
|
4741
|
+
const lightOverrides = config.themes?.["light"] ?? {};
|
|
4742
|
+
const darkOverrides = config.themes?.["dark"] ?? {};
|
|
4743
|
+
const lightCssVars = {
|
|
4744
|
+
...flatTokens,
|
|
4745
|
+
...Object.fromEntries(Object.entries(lightOverrides).map(([k, v]) => [`--${k}`, String(v)]))
|
|
4746
|
+
};
|
|
4747
|
+
const darkCssVars = {
|
|
4748
|
+
...flatTokens,
|
|
4749
|
+
...Object.fromEntries(Object.entries(darkOverrides).map(([k, v]) => [`--${k}`, String(v)]))
|
|
4750
|
+
};
|
|
4751
|
+
const resolvedCssVars = { light: lightCssVars, dark: darkCssVars };
|
|
4752
|
+
const { generateComponentJson } = await import("../generateComponentJson-XBEUWCW6.js");
|
|
4753
|
+
const { generateComponentMetadata } = await import("../generateComponentMetadata-2L5VNERD.js");
|
|
4829
4754
|
for (const componentName of REACT_COMPONENTS) {
|
|
4755
|
+
const pascalName = componentName.charAt(0).toUpperCase() + componentName.slice(1);
|
|
4830
4756
|
try {
|
|
4831
4757
|
const { filename, content } = reactAdapter.generateComponent(
|
|
4832
4758
|
componentName,
|
|
4833
4759
|
config,
|
|
4834
4760
|
rules[componentName]
|
|
4835
4761
|
);
|
|
4836
|
-
|
|
4837
|
-
|
|
4838
|
-
|
|
4839
|
-
|
|
4762
|
+
const componentSubDir = path3.join(componentsDir, pascalName);
|
|
4763
|
+
await ensureDir(componentSubDir);
|
|
4764
|
+
await writeFile(path3.join(componentSubDir, filename), content);
|
|
4765
|
+
logger.dim(` \u2192 components/${pascalName}/${filename}`);
|
|
4766
|
+
generatedNames.push(pascalName);
|
|
4767
|
+
const componentJson = generateComponentJson(pascalName, resolvedCssVars);
|
|
4768
|
+
generatedComponentJsons.push(componentJson);
|
|
4769
|
+
await writeFile(
|
|
4770
|
+
path3.join(componentSubDir, `${pascalName}.json`),
|
|
4771
|
+
JSON.stringify(componentJson, null, 2)
|
|
4840
4772
|
);
|
|
4773
|
+
logger.dim(` \u2192 components/${pascalName}/${pascalName}.json`);
|
|
4774
|
+
if (isProUnlocked()) {
|
|
4775
|
+
const metadata = generateComponentMetadata(pascalName);
|
|
4776
|
+
await writeFile(
|
|
4777
|
+
path3.join(componentSubDir, `${pascalName}.metadata.json`),
|
|
4778
|
+
JSON.stringify(metadata, null, 2)
|
|
4779
|
+
);
|
|
4780
|
+
logger.dim(` \u2192 components/${pascalName}/${pascalName}.metadata.json`);
|
|
4781
|
+
}
|
|
4841
4782
|
} catch (err) {
|
|
4842
4783
|
logger.warn(
|
|
4843
4784
|
`[dsforge] Could not generate ${componentName} \u2014 ${err.message}`
|
|
@@ -4845,76 +4786,117 @@ async function runGenerate(cwd, options) {
|
|
|
4845
4786
|
}
|
|
4846
4787
|
}
|
|
4847
4788
|
const { filename: tpFile, content: tpContent } = reactAdapter.generateThemeProvider(config);
|
|
4848
|
-
|
|
4849
|
-
|
|
4850
|
-
|
|
4851
|
-
|
|
4852
|
-
|
|
4853
|
-
|
|
4854
|
-
|
|
4855
|
-
|
|
4856
|
-
|
|
4857
|
-
|
|
4858
|
-
|
|
4859
|
-
|
|
4860
|
-
|
|
4861
|
-
|
|
4862
|
-
|
|
4863
|
-
|
|
4864
|
-
|
|
4865
|
-
}
|
|
4866
|
-
if (!only || only === "docs") {
|
|
4867
|
-
logger.step("Generating docs...");
|
|
4868
|
-
const docsDir = path3.join(outRoot, "docs");
|
|
4869
|
-
await ensureDir(docsDir);
|
|
4870
|
-
const metadataFiles = generateMetadata(config, rules, tokenCount);
|
|
4871
|
-
const metadataMap = {};
|
|
4872
|
-
for (const { filename, content } of metadataFiles) {
|
|
4873
|
-
const name = filename.replace(".json", "");
|
|
4874
|
-
if (name !== "index") {
|
|
4875
|
-
metadataMap[name] = JSON.parse(
|
|
4876
|
-
content
|
|
4789
|
+
const tpDir = path3.join(componentsDir, "ThemeProvider");
|
|
4790
|
+
await ensureDir(tpDir);
|
|
4791
|
+
await writeFile(path3.join(tpDir, tpFile), tpContent);
|
|
4792
|
+
logger.dim(` \u2192 components/ThemeProvider/${tpFile}`);
|
|
4793
|
+
try {
|
|
4794
|
+
const tpJson = generateComponentJson("ThemeProvider", resolvedCssVars);
|
|
4795
|
+
generatedComponentJsons.push(tpJson);
|
|
4796
|
+
await writeFile(
|
|
4797
|
+
path3.join(tpDir, "ThemeProvider.json"),
|
|
4798
|
+
JSON.stringify(tpJson, null, 2)
|
|
4799
|
+
);
|
|
4800
|
+
logger.dim(` \u2192 components/ThemeProvider/ThemeProvider.json`);
|
|
4801
|
+
if (isProUnlocked()) {
|
|
4802
|
+
const tpMeta = generateComponentMetadata("ThemeProvider");
|
|
4803
|
+
await writeFile(
|
|
4804
|
+
path3.join(tpDir, "ThemeProvider.metadata.json"),
|
|
4805
|
+
JSON.stringify(tpMeta, null, 2)
|
|
4877
4806
|
);
|
|
4807
|
+
logger.dim(` \u2192 components/ThemeProvider/ThemeProvider.metadata.json`);
|
|
4878
4808
|
}
|
|
4809
|
+
} catch {
|
|
4879
4810
|
}
|
|
4880
|
-
const
|
|
4881
|
-
|
|
4882
|
-
|
|
4883
|
-
|
|
4884
|
-
|
|
4885
|
-
logger.success(`Docs written (${docFiles.length} files)`);
|
|
4811
|
+
const { filename: idxFile, content: idxContent } = reactAdapter.generateComponentIndex(config, generatedNames);
|
|
4812
|
+
await writeFile(path3.join(outRoot, idxFile), idxContent);
|
|
4813
|
+
logger.dim(` \u2192 ${idxFile}`);
|
|
4814
|
+
logger.success(`${generatedNames.length} components generated`);
|
|
4815
|
+
globalThis["__dsforgGeneratedJsons"] = generatedComponentJsons;
|
|
4886
4816
|
}
|
|
4887
4817
|
if (!only) {
|
|
4888
4818
|
logger.step("Writing package files...");
|
|
4889
|
-
const componentNames = Object.keys(
|
|
4819
|
+
const componentNames = Object.keys(fullRules);
|
|
4890
4820
|
const { filename: pkgFile, content: pkgContent } = reactAdapter.generatePackageManifest(config, componentNames);
|
|
4891
4821
|
await writeFile(path3.join(outRoot, pkgFile), pkgContent);
|
|
4892
4822
|
logger.dim(` \u2192 ${pkgFile}`);
|
|
4893
4823
|
const tsConfig = generateTsConfig();
|
|
4894
4824
|
await writeFile(path3.join(outRoot, "tsconfig.json"), tsConfig);
|
|
4895
4825
|
logger.dim(` \u2192 tsconfig.json`);
|
|
4896
|
-
const { generateReadme } = await import("../emitter-
|
|
4826
|
+
const { generateReadme } = await import("../emitter-IC77G4QF.js");
|
|
4897
4827
|
await writeFile(
|
|
4898
4828
|
path3.join(outRoot, "README.md"),
|
|
4899
4829
|
generateReadme(config, componentNames)
|
|
4900
4830
|
);
|
|
4901
4831
|
logger.dim(` \u2192 README.md`);
|
|
4902
4832
|
const changelogPath = path3.join(outRoot, "CHANGELOG.md");
|
|
4903
|
-
const
|
|
4904
|
-
const fsE2 =
|
|
4833
|
+
const fsExtra = await import("fs-extra");
|
|
4834
|
+
const fsE2 = fsExtra.default ?? fsExtra;
|
|
4905
4835
|
if (!await fsE2.pathExists(changelogPath)) {
|
|
4906
4836
|
await writeFile(changelogPath, generateChangelog(config));
|
|
4907
4837
|
logger.dim(` \u2192 CHANGELOG.md (seeded)`);
|
|
4908
4838
|
}
|
|
4909
4839
|
logger.success(`Package files written`);
|
|
4910
4840
|
}
|
|
4841
|
+
if (isProUnlocked() && (!only || only === "components")) {
|
|
4842
|
+
logger.step("Writing Pro outputs...");
|
|
4843
|
+
const generatedJsons = globalThis["__dsforgGeneratedJsons"] ?? [];
|
|
4844
|
+
const { generateRegistry } = await import("../generateRegistry-3MEZDJAJ.js");
|
|
4845
|
+
const {
|
|
4846
|
+
generateSystemPrompt,
|
|
4847
|
+
generateComponentsJson,
|
|
4848
|
+
generateCursorContext,
|
|
4849
|
+
generateCopilotInstructions
|
|
4850
|
+
} = await import("../generateAiFolder-3OOFWBH7.js");
|
|
4851
|
+
const systemName = config.meta.name;
|
|
4852
|
+
const version = config.meta.version;
|
|
4853
|
+
const registry = generateRegistry(systemName, version, generatedJsons);
|
|
4854
|
+
await writeFile(path3.join(outRoot, "registry.json"), JSON.stringify(registry, null, 2));
|
|
4855
|
+
logger.dim(` \u2192 registry.json`);
|
|
4856
|
+
const { COMPONENT_METADATA_DEFINITIONS } = await import("../componentDefinitions-5LFCNFQY.js");
|
|
4857
|
+
const metadataList = generatedJsons.map((c) => COMPONENT_METADATA_DEFINITIONS[c.name]).filter((m) => Boolean(m));
|
|
4858
|
+
const flatTokensForAi = {};
|
|
4859
|
+
for (const [k, v] of Object.entries(resolution.tokens)) {
|
|
4860
|
+
const cssVar2 = `--${k.replace(/^(global|semantic|component)\./, "")}`;
|
|
4861
|
+
flatTokensForAi[cssVar2] = {
|
|
4862
|
+
light: config.themes?.["light"]?.[cssVar2.slice(2)] ?? v,
|
|
4863
|
+
dark: config.themes?.["dark"]?.[cssVar2.slice(2)] ?? v
|
|
4864
|
+
};
|
|
4865
|
+
}
|
|
4866
|
+
const aiDir = path3.join(outRoot, "ai");
|
|
4867
|
+
await ensureDir(aiDir);
|
|
4868
|
+
const cursorDir = path3.join(aiDir, ".cursor");
|
|
4869
|
+
await ensureDir(cursorDir);
|
|
4870
|
+
const componentNames = generatedJsons.map((c) => c.name);
|
|
4871
|
+
await writeFile(
|
|
4872
|
+
path3.join(aiDir, "system-prompt.md"),
|
|
4873
|
+
generateSystemPrompt(systemName, flatTokensForAi, componentNames)
|
|
4874
|
+
);
|
|
4875
|
+
logger.dim(` \u2192 ai/system-prompt.md`);
|
|
4876
|
+
await writeFile(
|
|
4877
|
+
path3.join(aiDir, "components.json"),
|
|
4878
|
+
generateComponentsJson(systemName, generatedJsons, metadataList)
|
|
4879
|
+
);
|
|
4880
|
+
logger.dim(` \u2192 ai/components.json`);
|
|
4881
|
+
await writeFile(
|
|
4882
|
+
path3.join(cursorDir, "context.md"),
|
|
4883
|
+
generateCursorContext(systemName)
|
|
4884
|
+
);
|
|
4885
|
+
logger.dim(` \u2192 ai/.cursor/context.md`);
|
|
4886
|
+
await writeFile(
|
|
4887
|
+
path3.join(outRoot, "copilot-instructions.md"),
|
|
4888
|
+
generateCopilotInstructions(systemName)
|
|
4889
|
+
);
|
|
4890
|
+
logger.dim(` \u2192 copilot-instructions.md`);
|
|
4891
|
+
logger.success(`Pro outputs written`);
|
|
4892
|
+
}
|
|
4911
4893
|
logger.step("Generating showcase...");
|
|
4912
|
-
const { generateShowcase } = await import("../html-
|
|
4894
|
+
const { generateShowcase } = await import("../html-XGJ22SXB.js");
|
|
4913
4895
|
const showcaseHtml = generateShowcase(config, resolution);
|
|
4914
4896
|
await writeFile(path3.join(outRoot, "showcase.html"), showcaseHtml);
|
|
4915
4897
|
logger.dim(` \u2192 showcase.html`);
|
|
4916
|
-
const
|
|
4917
|
-
const fsE =
|
|
4898
|
+
const fsExtraShowcase = await import("fs-extra");
|
|
4899
|
+
const fsE = fsExtraShowcase.default ?? fsExtraShowcase;
|
|
4918
4900
|
const faviconSrc = path3.join(cwd, "assets", "favicon.svg");
|
|
4919
4901
|
const faviconDest = path3.join(outRoot, "assets", "favicon.svg");
|
|
4920
4902
|
if (await fsE.pathExists(faviconSrc)) {
|
|
@@ -5296,7 +5278,7 @@ async function runMenu() {
|
|
|
5296
5278
|
// package.json
|
|
5297
5279
|
var package_default = {
|
|
5298
5280
|
name: "@nghitrum/dsforge",
|
|
5299
|
-
version: "0.1.5-alpha.
|
|
5281
|
+
version: "0.1.5-alpha.10",
|
|
5300
5282
|
description: "AI-native design system generator \u2014 tokens \u2192 components \u2192 docs \u2192 npm",
|
|
5301
5283
|
keywords: [
|
|
5302
5284
|
"design-system",
|