@nghitrum/dsforge 0.1.5-alpha.8 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +21 -0
- package/README.md +0 -1
- package/dist/{chunk-JUMR3N5J.js → chunk-5YT3VNE6.js} +6 -26
- package/dist/chunk-A7VW6SII.js +436 -0
- package/dist/{chunk-QHE35QQQ.js → chunk-ZZRPNO6Z.js} +12 -17
- package/dist/cli/index.js +218 -310
- package/dist/componentDefinitions-5LFCNFQY.js +8 -0
- package/dist/{emitter-KNYIQTS5.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-LQHDCSG4.js → html-4DD6GOHE.js} +223 -130
- package/dist/index.js +86 -110
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1143,31 +1143,6 @@ var rl = readline.createInterface({
|
|
|
1143
1143
|
output: process.stdout
|
|
1144
1144
|
});
|
|
1145
1145
|
|
|
1146
|
-
// src/lib/license.ts
|
|
1147
|
-
import { readFileSync } from "fs";
|
|
1148
|
-
import { join } from "path";
|
|
1149
|
-
function readKeyFromDotEnv() {
|
|
1150
|
-
try {
|
|
1151
|
-
const content = readFileSync(join(process.cwd(), ".env"), "utf8");
|
|
1152
|
-
for (const raw of content.split("\n")) {
|
|
1153
|
-
const line = raw.trim();
|
|
1154
|
-
if (!line || line.startsWith("#")) continue;
|
|
1155
|
-
const eq = line.indexOf("=");
|
|
1156
|
-
if (eq === -1) continue;
|
|
1157
|
-
const key = line.slice(0, eq).trim();
|
|
1158
|
-
if (key !== "DSFORGE_KEY") continue;
|
|
1159
|
-
const val = line.slice(eq + 1).trim().replace(/^["']|["']$/g, "");
|
|
1160
|
-
return val || void 0;
|
|
1161
|
-
}
|
|
1162
|
-
} catch {
|
|
1163
|
-
}
|
|
1164
|
-
return void 0;
|
|
1165
|
-
}
|
|
1166
|
-
function isProUnlocked() {
|
|
1167
|
-
const key = process.env["DSFORGE_KEY"] ?? readKeyFromDotEnv();
|
|
1168
|
-
return typeof key === "string" && key.length > 0;
|
|
1169
|
-
}
|
|
1170
|
-
|
|
1171
1146
|
// src/presets/index.ts
|
|
1172
1147
|
var SPACING_PRESETS = {
|
|
1173
1148
|
compact: {
|
|
@@ -1206,6 +1181,11 @@ var RADIUS_PRESETS = {
|
|
|
1206
1181
|
comfortable: { none: 0, sm: 2, md: 4, lg: 8, xl: 16, full: 9999 },
|
|
1207
1182
|
spacious: { none: 0, sm: 3, md: 6, lg: 12, xl: 20, full: 9999 }
|
|
1208
1183
|
};
|
|
1184
|
+
var CONTROL_SIZE_PRESETS = {
|
|
1185
|
+
compact: { sm: 12, md: 14, lg: 18 },
|
|
1186
|
+
comfortable: { sm: 14, md: 16, lg: 20 },
|
|
1187
|
+
spacious: { sm: 16, md: 18, lg: 24 }
|
|
1188
|
+
};
|
|
1209
1189
|
var PRESET_BASE_UNITS = {
|
|
1210
1190
|
compact: 2,
|
|
1211
1191
|
comfortable: 4,
|
|
@@ -1593,6 +1573,19 @@ function emitBaseCss(config, resolution) {
|
|
|
1593
1573
|
if (typoEntries.length > 0) {
|
|
1594
1574
|
sections.push(emitBlock(":root", typoEntries, "Typography"));
|
|
1595
1575
|
}
|
|
1576
|
+
const currentPreset = config.philosophy?.density ?? "comfortable";
|
|
1577
|
+
const controlSizes = CONTROL_SIZE_PRESETS[currentPreset] ?? CONTROL_SIZE_PRESETS.comfortable;
|
|
1578
|
+
sections.push(
|
|
1579
|
+
emitBlock(
|
|
1580
|
+
":root",
|
|
1581
|
+
[
|
|
1582
|
+
["control-size-sm", `${controlSizes.sm}px`],
|
|
1583
|
+
["control-size-md", `${controlSizes.md}px`],
|
|
1584
|
+
["control-size-lg", `${controlSizes.lg}px`]
|
|
1585
|
+
],
|
|
1586
|
+
"Control sizes"
|
|
1587
|
+
)
|
|
1588
|
+
);
|
|
1596
1589
|
const radiusEntries = Object.entries(
|
|
1597
1590
|
config.radius ?? {}
|
|
1598
1591
|
).filter(([, v]) => v !== void 0).map(([k, v]) => [`radius-${k}`, v === 9999 ? "9999px" : `${v}px`]);
|
|
@@ -2594,62 +2587,7 @@ function generateThemeProvider(config) {
|
|
|
2594
2587
|
const themeNames = Object.keys(config.themes ?? { light: {}, dark: {} });
|
|
2595
2588
|
const defaultTheme = themeNames.includes("light") ? "light" : themeNames[0] ?? "light";
|
|
2596
2589
|
const themeType = themeNames.map((t) => `"${t}"`).join(" | ");
|
|
2597
|
-
const isPro = isProUnlocked();
|
|
2598
2590
|
const defaultDensity = config.meta.preset ?? "comfortable";
|
|
2599
|
-
const densityImport = isPro ? `
|
|
2600
|
-
import "../tokens/density.css";` : "";
|
|
2601
|
-
const densityTypes = isPro ? `
|
|
2602
|
-
export type DensityName = "compact" | "comfortable" | "spacious";
|
|
2603
|
-
` : "";
|
|
2604
|
-
const densityContextTypes = isPro ? `
|
|
2605
|
-
export interface DensityContextValue {
|
|
2606
|
-
density: DensityName;
|
|
2607
|
-
setDensity: (density: DensityName) => void;
|
|
2608
|
-
}
|
|
2609
|
-
` : "";
|
|
2610
|
-
const densityContext = isPro ? `
|
|
2611
|
-
export const DensityContext = React.createContext<DensityContextValue>({
|
|
2612
|
-
density: "${defaultDensity}",
|
|
2613
|
-
setDensity: () => undefined,
|
|
2614
|
-
});
|
|
2615
|
-
|
|
2616
|
-
/**
|
|
2617
|
-
* Hook to read and change the current density.
|
|
2618
|
-
* Must be used inside a <ThemeProvider>.
|
|
2619
|
-
*/
|
|
2620
|
-
export function useDensity(): DensityContextValue {
|
|
2621
|
-
return React.useContext(DensityContext);
|
|
2622
|
-
}
|
|
2623
|
-
` : "";
|
|
2624
|
-
const densityProp = isPro ? `
|
|
2625
|
-
/** Component density. Requires density.css to be imported. Defaults to "${defaultDensity}". */
|
|
2626
|
-
density?: DensityName;` : "";
|
|
2627
|
-
const densityOnChangeProp = isPro ? `
|
|
2628
|
-
/** Called when setDensity is invoked. */
|
|
2629
|
-
onDensityChange?: (density: DensityName) => void;` : "";
|
|
2630
|
-
const densityState = isPro ? `
|
|
2631
|
-
const [density, setDensityState] = React.useState<DensityName>(initialDensity);
|
|
2632
|
-
|
|
2633
|
-
React.useEffect(() => {
|
|
2634
|
-
setDensityState(initialDensity);
|
|
2635
|
-
}, [initialDensity]);
|
|
2636
|
-
|
|
2637
|
-
const setDensity = React.useCallback(
|
|
2638
|
-
(next: DensityName) => {
|
|
2639
|
-
setDensityState(next);
|
|
2640
|
-
onDensityChange?.(next);
|
|
2641
|
-
},
|
|
2642
|
-
[onDensityChange],
|
|
2643
|
-
);
|
|
2644
|
-
` : "";
|
|
2645
|
-
const densityDestructure = isPro ? `,
|
|
2646
|
-
density: initialDensity = "${defaultDensity}",
|
|
2647
|
-
onDensityChange,` : "";
|
|
2648
|
-
const densityProviderOpen = isPro ? `
|
|
2649
|
-
<DensityContext.Provider value={{ density, setDensity }}>` : "";
|
|
2650
|
-
const densityDataAttr = isPro ? ` data-density={density}` : "";
|
|
2651
|
-
const densityProviderClose = isPro ? `
|
|
2652
|
-
</DensityContext.Provider>` : "";
|
|
2653
2591
|
return `/**
|
|
2654
2592
|
* ThemeProvider \u2014 ${config.meta.name}
|
|
2655
2593
|
*
|
|
@@ -2661,27 +2599,39 @@ export function useDensity(): DensityContextValue {
|
|
|
2661
2599
|
* import "@${config.meta.name}/tokens/light.css"; // or dark.css
|
|
2662
2600
|
* import { ThemeProvider } from "@${config.meta.name}";
|
|
2663
2601
|
*
|
|
2664
|
-
* <ThemeProvider theme="light"
|
|
2602
|
+
* <ThemeProvider theme="light" density="${defaultDensity}">
|
|
2665
2603
|
* <App />
|
|
2666
2604
|
* </ThemeProvider>
|
|
2667
2605
|
*/
|
|
2668
2606
|
|
|
2669
|
-
import React from "react"
|
|
2607
|
+
import React from "react";
|
|
2608
|
+
import "../tokens/density.css";
|
|
2670
2609
|
|
|
2671
2610
|
// \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
|
|
2672
2611
|
|
|
2673
2612
|
export type ThemeName = ${themeType};
|
|
2674
|
-
|
|
2613
|
+
|
|
2614
|
+
export type DensityName = "compact" | "comfortable" | "spacious";
|
|
2615
|
+
|
|
2675
2616
|
export interface ThemeContextValue {
|
|
2676
2617
|
theme: ThemeName;
|
|
2677
2618
|
setTheme: (theme: ThemeName) => void;
|
|
2678
2619
|
}
|
|
2679
|
-
|
|
2620
|
+
|
|
2621
|
+
export interface DensityContextValue {
|
|
2622
|
+
density: DensityName;
|
|
2623
|
+
setDensity: (density: DensityName) => void;
|
|
2624
|
+
}
|
|
2625
|
+
|
|
2680
2626
|
export interface ThemeProviderProps {
|
|
2681
2627
|
/** Initial theme. Defaults to "${defaultTheme}". */
|
|
2682
2628
|
theme?: ThemeName;
|
|
2683
2629
|
/** Called when setTheme is invoked \u2014 use to persist theme preference. */
|
|
2684
|
-
onThemeChange?: (theme: ThemeName) => void
|
|
2630
|
+
onThemeChange?: (theme: ThemeName) => void;
|
|
2631
|
+
/** Component density. Requires density.css to be imported. Defaults to "${defaultDensity}". */
|
|
2632
|
+
density?: DensityName;
|
|
2633
|
+
/** Called when setDensity is invoked. */
|
|
2634
|
+
onDensityChange?: (density: DensityName) => void;
|
|
2685
2635
|
children: React.ReactNode;
|
|
2686
2636
|
}
|
|
2687
2637
|
|
|
@@ -2699,12 +2649,27 @@ export const ThemeContext = React.createContext<ThemeContextValue>({
|
|
|
2699
2649
|
export function useTheme(): ThemeContextValue {
|
|
2700
2650
|
return React.useContext(ThemeContext);
|
|
2701
2651
|
}
|
|
2702
|
-
|
|
2652
|
+
|
|
2653
|
+
export const DensityContext = React.createContext<DensityContextValue>({
|
|
2654
|
+
density: "${defaultDensity}",
|
|
2655
|
+
setDensity: () => undefined,
|
|
2656
|
+
});
|
|
2657
|
+
|
|
2658
|
+
/**
|
|
2659
|
+
* Hook to read and change the current density.
|
|
2660
|
+
* Must be used inside a <ThemeProvider>.
|
|
2661
|
+
*/
|
|
2662
|
+
export function useDensity(): DensityContextValue {
|
|
2663
|
+
return React.useContext(DensityContext);
|
|
2664
|
+
}
|
|
2665
|
+
|
|
2703
2666
|
// \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
|
|
2704
2667
|
|
|
2705
2668
|
export function ThemeProvider({
|
|
2706
2669
|
theme: initialTheme = "${defaultTheme}",
|
|
2707
|
-
onThemeChange
|
|
2670
|
+
onThemeChange,
|
|
2671
|
+
density: initialDensity = "${defaultDensity}",
|
|
2672
|
+
onDensityChange,
|
|
2708
2673
|
children,
|
|
2709
2674
|
}: ThemeProviderProps) {
|
|
2710
2675
|
const [theme, setThemeState] = React.useState<ThemeName>(initialTheme);
|
|
@@ -2720,13 +2685,29 @@ export function ThemeProvider({
|
|
|
2720
2685
|
},
|
|
2721
2686
|
[onThemeChange],
|
|
2722
2687
|
);
|
|
2723
|
-
|
|
2724
|
-
|
|
2688
|
+
|
|
2689
|
+
const [density, setDensityState] = React.useState<DensityName>(initialDensity);
|
|
2690
|
+
|
|
2691
|
+
React.useEffect(() => {
|
|
2692
|
+
setDensityState(initialDensity);
|
|
2693
|
+
}, [initialDensity]);
|
|
2694
|
+
|
|
2695
|
+
const setDensity = React.useCallback(
|
|
2696
|
+
(next: DensityName) => {
|
|
2697
|
+
setDensityState(next);
|
|
2698
|
+
onDensityChange?.(next);
|
|
2699
|
+
},
|
|
2700
|
+
[onDensityChange],
|
|
2701
|
+
);
|
|
2702
|
+
|
|
2703
|
+
return (
|
|
2704
|
+
<DensityContext.Provider value={{ density, setDensity }}>
|
|
2725
2705
|
<ThemeContext.Provider value={{ theme, setTheme }}>
|
|
2726
|
-
<div data-theme={theme}
|
|
2706
|
+
<div data-theme={theme} data-density={density} style={{ display: "contents" }}>
|
|
2727
2707
|
{children}
|
|
2728
2708
|
</div>
|
|
2729
|
-
</ThemeContext.Provider
|
|
2709
|
+
</ThemeContext.Provider>
|
|
2710
|
+
</DensityContext.Provider>
|
|
2730
2711
|
);
|
|
2731
2712
|
}
|
|
2732
2713
|
`;
|
|
@@ -2743,9 +2724,9 @@ function generateComponentIndex(config, componentNames) {
|
|
|
2743
2724
|
""
|
|
2744
2725
|
];
|
|
2745
2726
|
for (const name of componentNames) {
|
|
2746
|
-
lines.push(`export * from "
|
|
2727
|
+
lines.push(`export * from "./components/${name}/${name}";`);
|
|
2747
2728
|
}
|
|
2748
|
-
lines.push(`export * from "./ThemeProvider";`);
|
|
2729
|
+
lines.push(`export * from "./components/ThemeProvider/ThemeProvider";`);
|
|
2749
2730
|
lines.push("");
|
|
2750
2731
|
return lines.join("\n");
|
|
2751
2732
|
}
|
|
@@ -3148,12 +3129,14 @@ function generatePackageJson(config, componentNames) {
|
|
|
3148
3129
|
),
|
|
3149
3130
|
"./tokens": "./tokens/tokens.js",
|
|
3150
3131
|
"./tailwind": "./tokens/tailwind.js",
|
|
3151
|
-
"./metadata": "./metadata/index.json",
|
|
3152
3132
|
...Object.fromEntries(
|
|
3153
|
-
componentNames.map((c) =>
|
|
3133
|
+
componentNames.map((c) => {
|
|
3134
|
+
const pascal = c.charAt(0).toUpperCase() + c.slice(1);
|
|
3135
|
+
return [`./components/${pascal}`, `./components/${pascal}/${pascal}.json`];
|
|
3136
|
+
})
|
|
3154
3137
|
)
|
|
3155
3138
|
},
|
|
3156
|
-
files: ["dist", "tokens", "
|
|
3139
|
+
files: ["dist", "tokens", "components", "CHANGELOG.md"],
|
|
3157
3140
|
scripts: {
|
|
3158
3141
|
build: "tsc",
|
|
3159
3142
|
prepublishOnly: "npm run build"
|
|
@@ -3193,7 +3176,7 @@ function generateTsConfig() {
|
|
|
3193
3176
|
moduleResolution: "NodeNext",
|
|
3194
3177
|
lib: ["ES2020", "DOM"],
|
|
3195
3178
|
outDir: "./dist",
|
|
3196
|
-
rootDir: "
|
|
3179
|
+
rootDir: ".",
|
|
3197
3180
|
declaration: true,
|
|
3198
3181
|
declarationMap: true,
|
|
3199
3182
|
sourceMap: true,
|
|
@@ -3202,7 +3185,7 @@ function generateTsConfig() {
|
|
|
3202
3185
|
skipLibCheck: true,
|
|
3203
3186
|
jsx: "react-jsx"
|
|
3204
3187
|
},
|
|
3205
|
-
include: ["
|
|
3188
|
+
include: ["index.ts", "components/**/*"],
|
|
3206
3189
|
exclude: ["node_modules", "dist"]
|
|
3207
3190
|
},
|
|
3208
3191
|
null,
|
|
@@ -3251,7 +3234,10 @@ function App() {
|
|
|
3251
3234
|
## Components
|
|
3252
3235
|
|
|
3253
3236
|
${componentNames.map(
|
|
3254
|
-
(c) =>
|
|
3237
|
+
(c) => {
|
|
3238
|
+
const pascal = c.charAt(0).toUpperCase() + c.slice(1);
|
|
3239
|
+
return `- **${pascal}** \u2014 see \`components/${pascal}/${pascal}.json\` for props and usage`;
|
|
3240
|
+
}
|
|
3255
3241
|
).join("\n")}
|
|
3256
3242
|
|
|
3257
3243
|
## Themes
|
|
@@ -3326,20 +3312,10 @@ every semantic and component token that references it.
|
|
|
3326
3312
|
|
|
3327
3313
|
## AI tool integration
|
|
3328
3314
|
|
|
3329
|
-
|
|
3315
|
+
Each component ships with a machine-readable JSON contract (e.g. \`components/Button/Button.json\`).
|
|
3330
3316
|
AI coding assistants (Copilot, Cursor, Claude Code) can read these to
|
|
3331
3317
|
generate UI that respects your governance rules automatically.
|
|
3332
3318
|
|
|
3333
|
-
\`\`\`json
|
|
3334
|
-
// ${pkgName}/metadata/button.json
|
|
3335
|
-
{
|
|
3336
|
-
"component": "Button",
|
|
3337
|
-
"allowedVariants": ["primary", "secondary", "danger", "ghost"],
|
|
3338
|
-
"requiredProps": ["aria-label"],
|
|
3339
|
-
"accessibilityContract": { "keyboard": true, "focusRing": true }
|
|
3340
|
-
}
|
|
3341
|
-
\`\`\`
|
|
3342
|
-
|
|
3343
3319
|
---
|
|
3344
3320
|
|
|
3345
3321
|
Generated by [dsforge](https://github.com/nghitrum/dsforge) v${config.meta.version}.
|