@matteoaliano/forest-ui 1.0.0 โ 1.1.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/bin/sync.mjs +37 -72
- package/dist/index.d.mts +74 -2
- package/dist/index.d.ts +74 -2
- package/dist/index.js +250 -40
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +257 -49
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
- package/skills/forest-alkemy-plus/SKILL.md +25 -131
- package/skills/forest-alkemy-plus/references/components.md +2 -0
- package/skills/forest-alkemy-plus/references/patterns.md +65 -121
- package/skills/forest-alkemy-plus/references/upgrading.md +6 -25
package/bin/sync.mjs
CHANGED
|
@@ -3,94 +3,59 @@
|
|
|
3
3
|
/**
|
|
4
4
|
* forest-ui sync
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
6
|
+
* DEPRECATED for consumers โ documentation + enforcement now ship as a Claude
|
|
7
|
+
* Code plugin. Copying loose skill files is no longer supported because stale
|
|
8
|
+
* copies drift from the plugin's hook.
|
|
9
|
+
*
|
|
10
|
+
* `--internal` (used by the monorepo's `npm run sync`) still propagates the
|
|
11
|
+
* skill source to the dogfood `.claude/skills/` copy and the plugin bundle.
|
|
8
12
|
*/
|
|
9
13
|
|
|
10
|
-
import {
|
|
14
|
+
import { mkdirSync, readdirSync, cpSync } from "node:fs";
|
|
11
15
|
import { resolve, dirname } from "node:path";
|
|
12
16
|
import { fileURLToPath } from "node:url";
|
|
13
17
|
|
|
14
18
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
15
19
|
const skillsDir = resolve(__dirname, "..", "skills");
|
|
16
20
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
while (dir !== dirname(dir)) {
|
|
21
|
-
if (existsSync(resolve(dir, "package.json"))) {
|
|
22
|
-
try {
|
|
23
|
-
const pkg = JSON.parse(readFileSync(resolve(dir, "package.json"), "utf-8"));
|
|
24
|
-
if (pkg.name !== "@matteoaliano/forest-ui") return dir;
|
|
25
|
-
} catch {
|
|
26
|
-
return dir;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
dir = dirname(dir);
|
|
30
|
-
}
|
|
31
|
-
return process.cwd();
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
const projectRoot = findProjectRoot(process.cwd());
|
|
21
|
+
if (!process.argv.includes("--internal")) {
|
|
22
|
+
console.log(`
|
|
23
|
+
๐ฒ Forest UI โ \`sync\` is deprecated
|
|
35
24
|
|
|
36
|
-
|
|
37
|
-
|
|
25
|
+
Skills are now delivered through the Forest Design System Claude Code
|
|
26
|
+
plugin, which also ships design-system enforcement hooks. Install it:
|
|
38
27
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
resolve(projectRoot, ".claude", "forest-ui.md"),
|
|
42
|
-
resolve(projectRoot, ".cursor", "rules", "forest-ui.mdc"),
|
|
43
|
-
resolve(projectRoot, ".gemini", "forest-ui.md"),
|
|
44
|
-
resolve(projectRoot, ".antigravity", "rules.md"),
|
|
45
|
-
];
|
|
28
|
+
/plugin marketplace add Witailer/wtl-design-system-forest
|
|
29
|
+
/plugin install forest-ui@forest-design-system
|
|
46
30
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
rmSync(legacyPath);
|
|
52
|
-
const rel = legacyPath.replace(projectRoot + "/", "");
|
|
53
|
-
console.log(` ๐งน Removed legacy ${rel}`);
|
|
54
|
-
cleaned++;
|
|
55
|
-
} catch (err) {
|
|
56
|
-
const rel = legacyPath.replace(projectRoot + "/", "");
|
|
57
|
-
console.log(` โ ๏ธ Could not remove ${rel} (${err.message})`);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
31
|
+
No files were copied. If you previously synced, you can delete
|
|
32
|
+
.claude/skills/forest-alkemy-plus/ โ the plugin replaces it.
|
|
33
|
+
`);
|
|
34
|
+
process.exit(0);
|
|
60
35
|
}
|
|
61
|
-
if (cleaned > 0) console.log();
|
|
62
36
|
|
|
63
|
-
|
|
64
|
-
|
|
37
|
+
// โโ Internal monorepo sync: skills/ โ dogfood + plugin bundle โโ
|
|
38
|
+
const repoRoot = resolve(__dirname, "..", "..", "..");
|
|
39
|
+
const targets = [
|
|
40
|
+
resolve(repoRoot, ".claude", "skills"),
|
|
41
|
+
resolve(repoRoot, "plugins", "forest-ui", "skills"),
|
|
42
|
+
];
|
|
65
43
|
|
|
66
|
-
|
|
67
|
-
console.log(` โ ๏ธ No skills directory found, nothing to sync.\n`);
|
|
68
|
-
process.exit(0);
|
|
69
|
-
}
|
|
44
|
+
console.log(`\n๐ฒ Forest UI โ Syncing skills (internal)\n`);
|
|
70
45
|
|
|
71
46
|
const skillFolders = readdirSync(skillsDir, { withFileTypes: true })
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
if (skillFolders.length === 0) {
|
|
76
|
-
console.log(` โ ๏ธ No skill folders found, nothing to sync.\n`);
|
|
77
|
-
process.exit(0);
|
|
78
|
-
}
|
|
47
|
+
.filter((d) => d.isDirectory())
|
|
48
|
+
.map((d) => d.name);
|
|
79
49
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
for (const folder of skillFolders) {
|
|
83
|
-
const
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
console.log(` โ
.claude/skills/${folder}/`);
|
|
90
|
-
synced++;
|
|
91
|
-
} catch (err) {
|
|
92
|
-
console.log(` โ ๏ธ .claude/skills/${folder}/ skipped (${err.message})`);
|
|
93
|
-
}
|
|
50
|
+
let synced = 0;
|
|
51
|
+
for (const target of targets) {
|
|
52
|
+
for (const folder of skillFolders) {
|
|
53
|
+
const dest = resolve(target, folder);
|
|
54
|
+
mkdirSync(dest, { recursive: true });
|
|
55
|
+
cpSync(resolve(skillsDir, folder), dest, { recursive: true });
|
|
56
|
+
console.log(` โ
${dest.replace(repoRoot + "/", "")}/`);
|
|
57
|
+
synced++;
|
|
58
|
+
}
|
|
94
59
|
}
|
|
95
60
|
|
|
96
|
-
console.log(`\n Synced ${
|
|
61
|
+
console.log(`\n Synced ${skillFolders.length} skill(s) to ${targets.length} target(s) (${synced} copies).\n`);
|
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
-
import { Theme } from '@mui/material/styles';
|
|
2
|
+
import { Theme, SxProps } from '@mui/material/styles';
|
|
3
3
|
export { useColorScheme } from '@mui/material/styles';
|
|
4
4
|
import * as _mui_material from '@mui/material';
|
|
5
5
|
import { BoxProps } from '@mui/material';
|
|
@@ -369,6 +369,78 @@ interface SidebarItemProps extends ListItemButtonProps {
|
|
|
369
369
|
}
|
|
370
370
|
declare function SidebarItem({ icon, label, endAdornment, sx, ...rest }: SidebarItemProps): react_jsx_runtime.JSX.Element;
|
|
371
371
|
|
|
372
|
+
interface AppShellNavItem {
|
|
373
|
+
label: string;
|
|
374
|
+
icon: React__default.ReactNode;
|
|
375
|
+
active?: boolean;
|
|
376
|
+
href?: string;
|
|
377
|
+
onClick?: () => void;
|
|
378
|
+
/** Router escape โ e.g. Next.js Link or React Router Link. */
|
|
379
|
+
component?: React__default.ElementType;
|
|
380
|
+
/** Rendered after the label when expanded (e.g. a count Chip). */
|
|
381
|
+
endAdornment?: React__default.ReactNode;
|
|
382
|
+
}
|
|
383
|
+
interface AppShellProps {
|
|
384
|
+
/** Data-driven sidebar nav. */
|
|
385
|
+
navItems?: AppShellNavItem[];
|
|
386
|
+
/** Escape hatch: full control over sidebar content. Overrides navItems. */
|
|
387
|
+
nav?: React__default.ReactNode;
|
|
388
|
+
/** Product brand passed to <Logo>. Default "studio". */
|
|
389
|
+
product?: LogoProduct;
|
|
390
|
+
/** Logomark (default) or the full wordmark logo. */
|
|
391
|
+
logoVariant?: "logomark" | "full";
|
|
392
|
+
/** Escape hatch: fully custom brand node (overrides product/logoVariant). */
|
|
393
|
+
brand?: React__default.ReactNode;
|
|
394
|
+
/** Center search: true โ default <Search>; node โ custom; omit โ none. */
|
|
395
|
+
search?: React__default.ReactNode | boolean;
|
|
396
|
+
/** Right-side AppBar actions. The mandatory color-mode toggle is rendered
|
|
397
|
+
* by AppShell itself, before these. */
|
|
398
|
+
actions?: React__default.ReactNode;
|
|
399
|
+
sidebarBehavior?: "permanent" | "hover";
|
|
400
|
+
defaultSidebarOpen?: boolean;
|
|
401
|
+
/** The page content โ expected to be a <Page>. */
|
|
402
|
+
children: React__default.ReactNode;
|
|
403
|
+
}
|
|
404
|
+
/**
|
|
405
|
+
* The mandatory top-level layout for authenticated Forest UI surfaces: a
|
|
406
|
+
* sticky AppBar (brand / search / actions + the color-mode toggle) over a
|
|
407
|
+
* SidebarNav and a main content area. Render a <Page> as children.
|
|
408
|
+
*
|
|
409
|
+
* Below the "sm" breakpoint the sidebar becomes a temporary overlay drawer
|
|
410
|
+
* opened by a hamburger button in the AppBar.
|
|
411
|
+
*/
|
|
412
|
+
declare function AppShell({ navItems, nav, product, logoVariant, brand, search, actions, sidebarBehavior, defaultSidebarOpen, children, }: AppShellProps): react_jsx_runtime.JSX.Element;
|
|
413
|
+
|
|
414
|
+
interface PageBreadcrumb {
|
|
415
|
+
label: string;
|
|
416
|
+
href?: string;
|
|
417
|
+
onClick?: () => void;
|
|
418
|
+
/** Router escape โ e.g. Next.js Link or React Router Link. */
|
|
419
|
+
component?: React__default.ElementType;
|
|
420
|
+
}
|
|
421
|
+
interface PageProps {
|
|
422
|
+
/** Page title. Rendered as Typography variant="h5". */
|
|
423
|
+
title: string;
|
|
424
|
+
/** Breadcrumb trail rendered above the title. Omit for pages without one. */
|
|
425
|
+
breadcrumbs?: PageBreadcrumb[];
|
|
426
|
+
/** Right-aligned header actions (e.g. a primary Button). */
|
|
427
|
+
actions?: React__default.ReactNode;
|
|
428
|
+
/** Drop the default 24px gutters for full-bleed pages. */
|
|
429
|
+
disableGutters?: boolean;
|
|
430
|
+
/** Constrain and center the content column. Default: full width. */
|
|
431
|
+
maxWidth?: number | string;
|
|
432
|
+
sx?: SxProps<Theme>;
|
|
433
|
+
children?: React__default.ReactNode;
|
|
434
|
+
}
|
|
435
|
+
/**
|
|
436
|
+
* The mandatory page-content scaffold rendered inside the App Shell's main
|
|
437
|
+
* slot. Owns the flat `background.paper` surface and the standard gutters, and
|
|
438
|
+
* renders the page header (breadcrumbs โ title + actions). Everything below
|
|
439
|
+
* the header goes in `children` โ widgets, charts, and tables belong inside
|
|
440
|
+
* `<Card>`s there.
|
|
441
|
+
*/
|
|
442
|
+
declare function Page({ title, breadcrumbs, actions, disableGutters, maxWidth, sx, children, }: PageProps): react_jsx_runtime.JSX.Element;
|
|
443
|
+
|
|
372
444
|
declare const Box: _mui_types.OverridableComponent<_mui_system.BoxTypeMap<{}, "div", _mui_material.Theme>>;
|
|
373
445
|
|
|
374
446
|
declare const Stack: _mui_material_OverridableComponent.OverridableComponent<_mui_material.StackTypeMap<{}, "div">>;
|
|
@@ -408,4 +480,4 @@ declare function ScatterChart({ series, colors, ...props }: ScatterChartProps):
|
|
|
408
480
|
type GaugeProps = GaugeProps$1;
|
|
409
481
|
declare function Gauge(props: GaugeProps): react_jsx_runtime.JSX.Element;
|
|
410
482
|
|
|
411
|
-
export { AppBarNavItem, type AppBarNavItemProps, BarChart, type BarChartProps, Box, Button, ButtonGroup, type ButtonProps, Card, type CardProps, Chip, Container, DatePicker, type DatePickerProps, Drawer, Fab, type ForestCardColor, type ForestChipColor, type ForestChipProps, ForestProvider, type ForestProviderProps, Gauge, Grid, IconButton, type IconButtonProps, type IconButtonVariant, LineChart, type LineChartProps, Logo, type LogoProps, MultiSelect, type MultiSelectOption, type MultiSelectProps, Paper, PieChart, type PieChartProps, Popover, Portal, ScatterChart, Search, type SearchProps, Select, SidebarItem, type SidebarItemProps, SidebarNav, type SidebarNavProps, Stack, Switch, Tooltip, useChartColors, useSidebar };
|
|
483
|
+
export { AppBarNavItem, type AppBarNavItemProps, AppShell, type AppShellNavItem, type AppShellProps, BarChart, type BarChartProps, Box, Button, ButtonGroup, type ButtonProps, Card, type CardProps, Chip, Container, DatePicker, type DatePickerProps, Drawer, Fab, type ForestCardColor, type ForestChipColor, type ForestChipProps, ForestProvider, type ForestProviderProps, Gauge, Grid, IconButton, type IconButtonProps, type IconButtonVariant, LineChart, type LineChartProps, Logo, type LogoProps, MultiSelect, type MultiSelectOption, type MultiSelectProps, Page, type PageBreadcrumb, type PageProps, Paper, PieChart, type PieChartProps, Popover, Portal, ScatterChart, Search, type SearchProps, Select, SidebarItem, type SidebarItemProps, SidebarNav, type SidebarNavProps, Stack, Switch, Tooltip, useChartColors, useSidebar };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
-
import { Theme } from '@mui/material/styles';
|
|
2
|
+
import { Theme, SxProps } from '@mui/material/styles';
|
|
3
3
|
export { useColorScheme } from '@mui/material/styles';
|
|
4
4
|
import * as _mui_material from '@mui/material';
|
|
5
5
|
import { BoxProps } from '@mui/material';
|
|
@@ -369,6 +369,78 @@ interface SidebarItemProps extends ListItemButtonProps {
|
|
|
369
369
|
}
|
|
370
370
|
declare function SidebarItem({ icon, label, endAdornment, sx, ...rest }: SidebarItemProps): react_jsx_runtime.JSX.Element;
|
|
371
371
|
|
|
372
|
+
interface AppShellNavItem {
|
|
373
|
+
label: string;
|
|
374
|
+
icon: React__default.ReactNode;
|
|
375
|
+
active?: boolean;
|
|
376
|
+
href?: string;
|
|
377
|
+
onClick?: () => void;
|
|
378
|
+
/** Router escape โ e.g. Next.js Link or React Router Link. */
|
|
379
|
+
component?: React__default.ElementType;
|
|
380
|
+
/** Rendered after the label when expanded (e.g. a count Chip). */
|
|
381
|
+
endAdornment?: React__default.ReactNode;
|
|
382
|
+
}
|
|
383
|
+
interface AppShellProps {
|
|
384
|
+
/** Data-driven sidebar nav. */
|
|
385
|
+
navItems?: AppShellNavItem[];
|
|
386
|
+
/** Escape hatch: full control over sidebar content. Overrides navItems. */
|
|
387
|
+
nav?: React__default.ReactNode;
|
|
388
|
+
/** Product brand passed to <Logo>. Default "studio". */
|
|
389
|
+
product?: LogoProduct;
|
|
390
|
+
/** Logomark (default) or the full wordmark logo. */
|
|
391
|
+
logoVariant?: "logomark" | "full";
|
|
392
|
+
/** Escape hatch: fully custom brand node (overrides product/logoVariant). */
|
|
393
|
+
brand?: React__default.ReactNode;
|
|
394
|
+
/** Center search: true โ default <Search>; node โ custom; omit โ none. */
|
|
395
|
+
search?: React__default.ReactNode | boolean;
|
|
396
|
+
/** Right-side AppBar actions. The mandatory color-mode toggle is rendered
|
|
397
|
+
* by AppShell itself, before these. */
|
|
398
|
+
actions?: React__default.ReactNode;
|
|
399
|
+
sidebarBehavior?: "permanent" | "hover";
|
|
400
|
+
defaultSidebarOpen?: boolean;
|
|
401
|
+
/** The page content โ expected to be a <Page>. */
|
|
402
|
+
children: React__default.ReactNode;
|
|
403
|
+
}
|
|
404
|
+
/**
|
|
405
|
+
* The mandatory top-level layout for authenticated Forest UI surfaces: a
|
|
406
|
+
* sticky AppBar (brand / search / actions + the color-mode toggle) over a
|
|
407
|
+
* SidebarNav and a main content area. Render a <Page> as children.
|
|
408
|
+
*
|
|
409
|
+
* Below the "sm" breakpoint the sidebar becomes a temporary overlay drawer
|
|
410
|
+
* opened by a hamburger button in the AppBar.
|
|
411
|
+
*/
|
|
412
|
+
declare function AppShell({ navItems, nav, product, logoVariant, brand, search, actions, sidebarBehavior, defaultSidebarOpen, children, }: AppShellProps): react_jsx_runtime.JSX.Element;
|
|
413
|
+
|
|
414
|
+
interface PageBreadcrumb {
|
|
415
|
+
label: string;
|
|
416
|
+
href?: string;
|
|
417
|
+
onClick?: () => void;
|
|
418
|
+
/** Router escape โ e.g. Next.js Link or React Router Link. */
|
|
419
|
+
component?: React__default.ElementType;
|
|
420
|
+
}
|
|
421
|
+
interface PageProps {
|
|
422
|
+
/** Page title. Rendered as Typography variant="h5". */
|
|
423
|
+
title: string;
|
|
424
|
+
/** Breadcrumb trail rendered above the title. Omit for pages without one. */
|
|
425
|
+
breadcrumbs?: PageBreadcrumb[];
|
|
426
|
+
/** Right-aligned header actions (e.g. a primary Button). */
|
|
427
|
+
actions?: React__default.ReactNode;
|
|
428
|
+
/** Drop the default 24px gutters for full-bleed pages. */
|
|
429
|
+
disableGutters?: boolean;
|
|
430
|
+
/** Constrain and center the content column. Default: full width. */
|
|
431
|
+
maxWidth?: number | string;
|
|
432
|
+
sx?: SxProps<Theme>;
|
|
433
|
+
children?: React__default.ReactNode;
|
|
434
|
+
}
|
|
435
|
+
/**
|
|
436
|
+
* The mandatory page-content scaffold rendered inside the App Shell's main
|
|
437
|
+
* slot. Owns the flat `background.paper` surface and the standard gutters, and
|
|
438
|
+
* renders the page header (breadcrumbs โ title + actions). Everything below
|
|
439
|
+
* the header goes in `children` โ widgets, charts, and tables belong inside
|
|
440
|
+
* `<Card>`s there.
|
|
441
|
+
*/
|
|
442
|
+
declare function Page({ title, breadcrumbs, actions, disableGutters, maxWidth, sx, children, }: PageProps): react_jsx_runtime.JSX.Element;
|
|
443
|
+
|
|
372
444
|
declare const Box: _mui_types.OverridableComponent<_mui_system.BoxTypeMap<{}, "div", _mui_material.Theme>>;
|
|
373
445
|
|
|
374
446
|
declare const Stack: _mui_material_OverridableComponent.OverridableComponent<_mui_material.StackTypeMap<{}, "div">>;
|
|
@@ -408,4 +480,4 @@ declare function ScatterChart({ series, colors, ...props }: ScatterChartProps):
|
|
|
408
480
|
type GaugeProps = GaugeProps$1;
|
|
409
481
|
declare function Gauge(props: GaugeProps): react_jsx_runtime.JSX.Element;
|
|
410
482
|
|
|
411
|
-
export { AppBarNavItem, type AppBarNavItemProps, BarChart, type BarChartProps, Box, Button, ButtonGroup, type ButtonProps, Card, type CardProps, Chip, Container, DatePicker, type DatePickerProps, Drawer, Fab, type ForestCardColor, type ForestChipColor, type ForestChipProps, ForestProvider, type ForestProviderProps, Gauge, Grid, IconButton, type IconButtonProps, type IconButtonVariant, LineChart, type LineChartProps, Logo, type LogoProps, MultiSelect, type MultiSelectOption, type MultiSelectProps, Paper, PieChart, type PieChartProps, Popover, Portal, ScatterChart, Search, type SearchProps, Select, SidebarItem, type SidebarItemProps, SidebarNav, type SidebarNavProps, Stack, Switch, Tooltip, useChartColors, useSidebar };
|
|
483
|
+
export { AppBarNavItem, type AppBarNavItemProps, AppShell, type AppShellNavItem, type AppShellProps, BarChart, type BarChartProps, Box, Button, ButtonGroup, type ButtonProps, Card, type CardProps, Chip, Container, DatePicker, type DatePickerProps, Drawer, Fab, type ForestCardColor, type ForestChipColor, type ForestChipProps, ForestProvider, type ForestProviderProps, Gauge, Grid, IconButton, type IconButtonProps, type IconButtonVariant, LineChart, type LineChartProps, Logo, type LogoProps, MultiSelect, type MultiSelectOption, type MultiSelectProps, Page, type PageBreadcrumb, type PageProps, Paper, PieChart, type PieChartProps, Popover, Portal, ScatterChart, Search, type SearchProps, Select, SidebarItem, type SidebarItemProps, SidebarNav, type SidebarNavProps, Stack, Switch, Tooltip, useChartColors, useSidebar };
|