@frontfriend/tailwind 4.0.0 → 4.0.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.js +36 -52
- package/dist/lib/core/default-config-data.js +1 -1
- package/dist/lib/core/default-config-data.js.map +2 -2
- package/dist/lib/core/default-config.js +1 -1
- package/dist/lib/core/default-config.js.map +2 -2
- package/dist/next.js +1 -1
- package/dist/next.js.map +2 -2
- package/dist/vite.js +11 -6
- package/dist/vite.js.map +3 -3
- package/dist/vite.mjs +6 -1
- package/dist/vite.mjs.map +3 -3
- package/package.json +1 -1
- package/scripts/master-components-config.json +953 -0
- package/scripts/update-default-config-data.js +105 -4
- package/src/theme.css +6 -10
|
@@ -4,7 +4,11 @@ const path = require('path');
|
|
|
4
4
|
|
|
5
5
|
const packageRoot = path.join(__dirname, '..');
|
|
6
6
|
const repoRoot = path.join(packageRoot, '..', '..');
|
|
7
|
-
|
|
7
|
+
// Vendored snapshot of the Master Design System componentsConfig. Lives inside
|
|
8
|
+
// the package so the bundled fallback can be regenerated without depending on
|
|
9
|
+
// apps/saas (which no longer ships the code-editor setup config). Refresh it
|
|
10
|
+
// from the canonical source with `--from-master-db`.
|
|
11
|
+
const sourcePath = path.join(packageRoot, 'scripts', 'master-components-config.json');
|
|
8
12
|
const outputPath = path.join(packageRoot, 'lib', 'core', 'default-config-data.js');
|
|
9
13
|
const SYSTEM_WORKSPACE_SLUG = 'system-templates';
|
|
10
14
|
const MASTER_DS_NAME = 'Master Design System';
|
|
@@ -256,6 +260,78 @@ const MINIMAL_V4_FALLBACKS = {
|
|
|
256
260
|
},
|
|
257
261
|
};
|
|
258
262
|
|
|
263
|
+
// Class values re-authored from the shadcn/ui new-york-v4 sources
|
|
264
|
+
// (clone: apps/v4/registry/new-york-v4/ui/{button,badge,input}.tsx). These are
|
|
265
|
+
// deep-merged on top of the neutralized Master DS so the out-of-the-box fallback
|
|
266
|
+
// renders like a stock shadcn install: token-driven radius (rounded-md), the
|
|
267
|
+
// shadcn size scale (default h-9 / sm h-8 / lg h-10 / icon size-9), and shadcn
|
|
268
|
+
// variant treatments. shadcn's cva variant/size buckets are mapped into the
|
|
269
|
+
// FrontFriend component envelope keys (e.g. shadcn `default` -> FF `main`,
|
|
270
|
+
// shadcn `outline` -> FF `tertiary`). FrontFriend-only buckets (ghostmain,
|
|
271
|
+
// linkdestructive, badge success/warning/subtle, ...) are left to the
|
|
272
|
+
// neutralized Master DS values and survive the merge untouched.
|
|
273
|
+
const SHADCN_DEFAULTS = {
|
|
274
|
+
button: {
|
|
275
|
+
root:
|
|
276
|
+
'font-primary group inline-flex shrink-0 items-center justify-center gap-2 rounded-md text-sm font-medium whitespace-nowrap transition-all outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20',
|
|
277
|
+
variant: {
|
|
278
|
+
main: 'bg-primary text-primary-foreground hover:bg-primary/90',
|
|
279
|
+
destructive:
|
|
280
|
+
'bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20',
|
|
281
|
+
tertiary:
|
|
282
|
+
'border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground',
|
|
283
|
+
secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80',
|
|
284
|
+
ghost: 'hover:bg-accent hover:text-accent-foreground',
|
|
285
|
+
ghostmain: 'text-primary hover:bg-accent hover:text-primary/90',
|
|
286
|
+
link: 'text-primary underline-offset-4 hover:underline',
|
|
287
|
+
linkdestructive: 'text-destructive underline-offset-4 hover:underline',
|
|
288
|
+
},
|
|
289
|
+
size: {
|
|
290
|
+
xs: 'h-6 gap-1 px-2 text-xs',
|
|
291
|
+
sm: 'h-8 gap-1.5 px-3',
|
|
292
|
+
default: 'h-9 px-4 py-2',
|
|
293
|
+
lg: 'h-10 px-6',
|
|
294
|
+
icon: 'size-9',
|
|
295
|
+
},
|
|
296
|
+
icon: {
|
|
297
|
+
size: { sm: '4', default: '4', lg: '4' },
|
|
298
|
+
color: {
|
|
299
|
+
main: 'text-primary-foreground',
|
|
300
|
+
secondary: 'text-secondary-foreground',
|
|
301
|
+
tertiary: 'text-foreground group-hover:text-accent-foreground',
|
|
302
|
+
destructive: 'text-white',
|
|
303
|
+
ghost: 'text-foreground group-hover:text-accent-foreground',
|
|
304
|
+
ghostmain: 'text-primary',
|
|
305
|
+
link: 'text-primary',
|
|
306
|
+
linkdestructive: 'text-destructive',
|
|
307
|
+
},
|
|
308
|
+
},
|
|
309
|
+
iconPosition: {
|
|
310
|
+
default: {
|
|
311
|
+
small: 'w-8 px-0',
|
|
312
|
+
default: 'w-9 px-0',
|
|
313
|
+
large: 'w-10 px-0',
|
|
314
|
+
},
|
|
315
|
+
},
|
|
316
|
+
},
|
|
317
|
+
badge: {
|
|
318
|
+
root:
|
|
319
|
+
'font-primary inline-flex w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-full border border-transparent px-2 py-0.5 text-xs font-medium whitespace-nowrap transition-[color,box-shadow] focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 aria-invalid:border-destructive [&>svg]:pointer-events-none [&>svg]:size-3',
|
|
320
|
+
variant: {
|
|
321
|
+
main: 'bg-primary border-transparent text-primary-foreground [&>svg]:text-primary-foreground',
|
|
322
|
+
secondary:
|
|
323
|
+
'bg-secondary border-transparent text-secondary-foreground [&>svg]:text-secondary-foreground',
|
|
324
|
+
destructive:
|
|
325
|
+
'bg-destructive border-transparent text-white [&>svg]:text-white',
|
|
326
|
+
tertiary: 'bg-transparent border-border text-foreground [&>svg]:text-foreground',
|
|
327
|
+
},
|
|
328
|
+
},
|
|
329
|
+
input: {
|
|
330
|
+
root:
|
|
331
|
+
'font-primary flex h-9 w-full min-w-0 rounded-md border border-input bg-transparent px-3 py-1 text-base md:text-sm shadow-xs transition-[color,box-shadow] outline-none text-foreground placeholder:text-muted-foreground file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 aria-invalid:border-destructive disabled:cursor-not-allowed disabled:opacity-50',
|
|
332
|
+
},
|
|
333
|
+
};
|
|
334
|
+
|
|
259
335
|
const DIRECT_CLASS_MAP = {
|
|
260
336
|
'border-transperent': 'border-transparent',
|
|
261
337
|
'hover:interactive-brand-mid-hover': 'hover:text-primary/90',
|
|
@@ -315,6 +391,8 @@ const FORBIDDEN_DEFAULT_CLASS_PATTERNS = [
|
|
|
315
391
|
/(?:^|:)fill-disabled$/,
|
|
316
392
|
/(?:^|:)border-disabled$/,
|
|
317
393
|
/transperent/,
|
|
394
|
+
// Fixed radius that ignores --radius; must use the rounded-md/lg/xl scale.
|
|
395
|
+
/(?:^|:)rounded(?:-(?:t|b|l|r|tl|tr|bl|br|ss|se|es|ee|s|e))?$/,
|
|
318
396
|
];
|
|
319
397
|
|
|
320
398
|
function clone(value) {
|
|
@@ -415,6 +493,16 @@ function mapTextClass(base, prefix) {
|
|
|
415
493
|
return important + withVariantTone(prefix, mapped);
|
|
416
494
|
}
|
|
417
495
|
|
|
496
|
+
// Tailwind v4 / shadcn theme ties rounded-{sm,md,lg,xl} to the --radius token.
|
|
497
|
+
// Bare `rounded` (and bare directional variants) are fixed 0.25rem and ignore
|
|
498
|
+
// --radius, so map them onto the token-driven `rounded-md` scale.
|
|
499
|
+
function mapRadiusClass(base) {
|
|
500
|
+
if (base === 'rounded') return 'rounded-md';
|
|
501
|
+
const match = base.match(/^rounded-(t|b|l|r|tl|tr|bl|br|ss|se|es|ee|s|e)$/);
|
|
502
|
+
if (match) return `rounded-${match[1]}-md`;
|
|
503
|
+
return null;
|
|
504
|
+
}
|
|
505
|
+
|
|
418
506
|
function mapBorderClass(base, prefix) {
|
|
419
507
|
const match = base.match(/^!?border-([a-z]+)(?:-[a-z]+)*(?:-(hover|active|selected|disabled))?$/);
|
|
420
508
|
if (!match) return null;
|
|
@@ -438,6 +526,7 @@ function neutralizeClassToken(token) {
|
|
|
438
526
|
|| mapBgClass(base, prefix)
|
|
439
527
|
|| mapTextClass(base, prefix)
|
|
440
528
|
|| mapBorderClass(base, prefix)
|
|
529
|
+
|| mapRadiusClass(base)
|
|
441
530
|
|| base;
|
|
442
531
|
|
|
443
532
|
return `${prefix}${mappedBase}`;
|
|
@@ -506,6 +595,12 @@ function buildDefaultConfigData(rawMasterConfig) {
|
|
|
506
595
|
generated[key] = key in generated ? deepMerge(generated[key], config) : clone(config);
|
|
507
596
|
}
|
|
508
597
|
|
|
598
|
+
// Re-author shadcn-covered components from the shadcn sources. Deep-merge so
|
|
599
|
+
// shadcn leaves win (root/variant/size) while FrontFriend-only buckets persist.
|
|
600
|
+
for (const [key, override] of Object.entries(SHADCN_DEFAULTS)) {
|
|
601
|
+
generated[key] = key in generated ? deepMerge(generated[key], override) : clone(override);
|
|
602
|
+
}
|
|
603
|
+
|
|
509
604
|
const forbidden = findForbiddenDefaultClasses(generated);
|
|
510
605
|
if (forbidden.length > 0) {
|
|
511
606
|
throw new Error(`Default config still contains FrontFriend-only classes: ${forbidden.join(', ')}`);
|
|
@@ -520,9 +615,13 @@ function generateDefaultConfigData() {
|
|
|
520
615
|
}
|
|
521
616
|
|
|
522
617
|
function formatModule(config) {
|
|
523
|
-
return `//
|
|
524
|
-
`//
|
|
525
|
-
`//
|
|
618
|
+
return `// Neutral bundled Master Design System fallback for Tailwind v4 registry components.\n` +
|
|
619
|
+
`// Structure + FrontFriend-only components are derived from\n` +
|
|
620
|
+
`// packages/frontfriend-tailwind/scripts/master-components-config.json (colors neutralized).\n` +
|
|
621
|
+
`// shadcn-covered components (button, badge, input) have their root/variant/size classes\n` +
|
|
622
|
+
`// re-authored from the shadcn new-york-v4 sources so the out-of-the-box fallback renders\n` +
|
|
623
|
+
`// like a stock shadcn install (token-driven --radius, shadcn size scale + treatments).\n` +
|
|
624
|
+
`// Run \`node packages/frontfriend-tailwind/scripts/update-default-config-data.js\` to regenerate.\n` +
|
|
526
625
|
`// Do not edit this file by hand.\n\n` +
|
|
527
626
|
`module.exports = ${JSON.stringify(config, null, 2)};\n`;
|
|
528
627
|
}
|
|
@@ -557,6 +656,8 @@ async function readMasterComponentsConfigFromDb() {
|
|
|
557
656
|
|
|
558
657
|
async function writeDefaultConfigDataFromMasterDb() {
|
|
559
658
|
const masterConfig = await readMasterComponentsConfigFromDb();
|
|
659
|
+
// Keep the vendored snapshot in sync so the file-based generator stays reproducible.
|
|
660
|
+
fs.writeFileSync(sourcePath, `${JSON.stringify(masterConfig, null, 2)}\n`);
|
|
560
661
|
const config = buildDefaultConfigData(masterConfig);
|
|
561
662
|
fs.writeFileSync(outputPath, formatModule(config));
|
|
562
663
|
return config;
|
package/src/theme.css
CHANGED
|
@@ -1,13 +1,9 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* Frontfriend Tailwind v4
|
|
2
|
+
* Frontfriend Tailwind v4 bundled source.
|
|
3
3
|
*
|
|
4
|
-
* `frontfriend init`
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* to the generated cache file so apps can import a stable path:
|
|
9
|
-
* @import "@frontfriend/tailwind/theme.css";
|
|
10
|
-
*
|
|
11
|
-
* If this placeholder appears in your compiled CSS, run `npx frontfriend init`
|
|
12
|
-
* and make sure the Frontfriend Next.js/Vite integration is enabled.
|
|
4
|
+
* `frontfriend init` aliases this package entrypoint to the generated cache
|
|
5
|
+
* theme at node_modules/.cache/frontfriend/theme.css when available. Until
|
|
6
|
+
* then, this file still points Tailwind v4 at the bundled component config so
|
|
7
|
+
* config-driven component utilities are generated out-of-the-box.
|
|
13
8
|
*/
|
|
9
|
+
@source "../dist/lib/core/default-config-data.js";
|