shapes-ui 0.4.2 → 0.6.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/.github/ISSUE_TEMPLATE/bug_report.yml +47 -0
- package/.github/ISSUE_TEMPLATE/config.yml +1 -0
- package/.github/ISSUE_TEMPLATE/feature_request.yml +31 -0
- package/.github/pull_request_template.md +14 -0
- package/.github/workflows/pr-preview.yml +75 -0
- package/.github/workflows/release.yml +8 -0
- package/CHANGELOG.md +30 -0
- package/CODE_OF_CONDUCT.md +41 -0
- package/CONTRIBUTING.md +52 -0
- package/README.md +18 -0
- package/SECURITY.md +0 -0
- package/content/components/accordion.mdx +13 -0
- package/content/components/alert-dialog.mdx +34 -0
- package/content/components/autocomplete.mdx +62 -0
- package/content/components/avatar.mdx +11 -0
- package/content/components/button.mdx +8 -0
- package/content/components/checkbox.mdx +11 -0
- package/content/components/collapsible.mdx +11 -0
- package/content/components/combobox.mdx +33 -0
- package/content/components/context-menu.mdx +29 -0
- package/content/components/dialog.mdx +33 -0
- package/content/components/drawer.mdx +38 -0
- package/content/components/field.mdx +23 -2
- package/content/components/fieldset.mdx +11 -1
- package/content/components/form.mdx +8 -0
- package/content/components/input.mdx +4 -0
- package/content/components/menu.mdx +27 -0
- package/content/components/menubar.mdx +31 -0
- package/content/components/meter.mdx +14 -0
- package/content/components/navigation-menu.mdx +28 -0
- package/content/components/number-field.mdx +25 -0
- package/content/components/popover.mdx +22 -0
- package/content/components/preview-card.mdx +14 -2
- package/content/components/progress.mdx +15 -1
- package/content/components/radio.mdx +31 -0
- package/content/components/scroll-area.mdx +23 -0
- package/content/components/select.mdx +57 -0
- package/content/components/separator.mdx +29 -0
- package/content/components/slider.mdx +52 -0
- package/content/components/switch.mdx +30 -0
- package/content/components/tabs.mdx +47 -0
- package/content/components/toast.mdx +70 -0
- package/content/components/toggle-group.mdx +37 -0
- package/content/components/toggle.mdx +46 -2
- package/content/components/toolbar.mdx +48 -0
- package/content/components/tooltip.mdx +38 -0
- package/content/docs/installation.mdx +30 -0
- package/content-collections.ts +65 -1
- package/dist/cli.js +947 -101
- package/examples/__index.tsx +320 -66
- package/examples/autocomplete-align.tsx +39 -0
- package/examples/autocomplete-controlled.tsx +44 -0
- package/examples/autocomplete-groups.tsx +65 -0
- package/examples/autocomplete-no-clear.tsx +40 -0
- package/examples/avatar-demo.tsx +3 -3
- package/examples/checkbox-demo.tsx +1 -1
- package/examples/checkbox-form.tsx +3 -3
- package/examples/field-custom-control.tsx +33 -9
- package/examples/form-demo.tsx +5 -10
- package/examples/input-group-with-button.tsx +1 -1
- package/examples/menu-advanced.tsx +1 -3
- package/examples/menu-align.tsx +19 -16
- package/examples/menu-checkbox.tsx +2 -3
- package/examples/menu-demo.tsx +1 -3
- package/examples/menu-group.tsx +1 -3
- package/examples/menu-radio.tsx +1 -3
- package/examples/menu-submenu.tsx +2 -3
- package/examples/meter-demo.tsx +10 -2
- package/examples/meter-flip.tsx +8 -8
- package/examples/meter-no-label.tsx +9 -2
- package/examples/meter-no-value.tsx +7 -8
- package/examples/radio-card.tsx +28 -0
- package/examples/radio-demo.tsx +19 -1
- package/examples/radio-description.tsx +26 -0
- package/examples/radio-orientation.tsx +21 -0
- package/examples/select-alignment.tsx +51 -0
- package/examples/select-demo.tsx +36 -1
- package/examples/select-disabled.tsx +38 -0
- package/examples/select-groups.tsx +54 -0
- package/examples/select-invalid.tsx +41 -0
- package/examples/select-scrollable.tsx +112 -0
- package/examples/separator-demo.tsx +13 -0
- package/examples/separator-horizontal.tsx +18 -0
- package/examples/slider-controlled.tsx +28 -0
- package/examples/slider-demo.tsx +3 -1
- package/examples/slider-disabled.tsx +7 -0
- package/examples/slider-edge.tsx +13 -0
- package/examples/slider-multiple.tsx +7 -0
- package/examples/slider-range.tsx +5 -0
- package/examples/slider-vertical.tsx +10 -0
- package/examples/switch-demo.tsx +19 -1
- package/examples/switch-disabled.tsx +20 -0
- package/examples/switch-sizes.tsx +24 -0
- package/examples/switch-with-label.tsx +16 -0
- package/examples/tabs-demo.tsx +14 -1
- package/examples/tabs-disabled.tsx +21 -0
- package/examples/tabs-line.tsx +18 -0
- package/examples/tabs-vertical.tsx +13 -0
- package/examples/toast-action.tsx +39 -0
- package/examples/toast-anchored.tsx +36 -0
- package/examples/toast-demo.tsx +27 -1
- package/examples/toast-positions.tsx +54 -0
- package/examples/toast-promise.tsx +51 -0
- package/examples/toast-stacked.tsx +30 -0
- package/examples/toast-timeout.tsx +43 -0
- package/examples/toast-update.tsx +38 -0
- package/examples/toast-variants.tsx +54 -0
- package/examples/toggle-controlled.tsx +20 -0
- package/examples/toggle-demo.tsx +7 -51
- package/examples/toggle-group-demo.tsx +19 -0
- package/examples/toggle-group-multiple.tsx +19 -0
- package/examples/toggle-icon-fill.tsx +12 -0
- package/examples/toolbar-demo.tsx +45 -21
- package/examples/toolbar-input-link.tsx +35 -0
- package/examples/toolbar-menu.tsx +53 -0
- package/examples/tooltip-demo.tsx +48 -0
- package/examples/tooltip-positions.tsx +60 -0
- package/package.json +19 -18
- package/public/base-ui.svg +1 -0
- package/public/r/drawer.json +1 -1
- package/public/r/field.json +1 -1
- package/public/r/meter.json +1 -1
- package/public/r/number-field.json +1 -1
- package/public/r/progress.json +1 -1
- package/public/r/radio.json +1 -1
- package/public/r/select.json +1 -1
- package/public/r/slider.json +1 -1
- package/public/r/switch.json +1 -1
- package/public/r/tabs.json +1 -1
- package/public/r/toast.json +2 -1
- package/public/r/toggle.json +1 -1
- package/public/r/toolbar.json +1 -1
- package/public/r/tooltip.json +15 -0
- package/src/assets/base-ui.svg +1 -0
- package/src/commands/add.ts +79 -38
- package/src/commands/cli.ts +50 -3
- package/src/commands/create.ts +262 -0
- package/src/commands/init.ts +45 -12
- package/src/commands/palette.ts +55 -0
- package/src/components/docs/layout/footer.tsx +2 -2
- package/src/components/docs/layout/header.tsx +7 -19
- package/src/components/docs/layout/mobile-menu.tsx +26 -78
- package/src/components/docs/layout/nav-list.tsx +27 -21
- package/src/components/docs/layout/page-header.tsx +52 -7
- package/src/components/docs/layout/split-layout.tsx +11 -9
- package/src/components/docs/layout/table-of-content.tsx +145 -0
- package/src/components/docs/markdown/components.tsx +142 -29
- package/src/components/docs/markdown/copy-button.tsx +41 -0
- package/src/components/docs/markdown/installation-block.tsx +5 -24
- package/src/components/docs/markdown/render-preview.tsx +1 -1
- package/src/components/ui/badge.tsx +1 -1
- package/src/components/ui/button-group.tsx +1 -1
- package/src/components/ui/checkbox.tsx +1 -1
- package/src/components/ui/drawer.tsx +1 -1
- package/src/components/ui/field.tsx +9 -28
- package/src/components/ui/form.tsx +1 -1
- package/src/components/ui/meter.tsx +12 -26
- package/src/components/ui/number-field.tsx +1 -1
- package/src/components/ui/radio.tsx +32 -19
- package/src/components/ui/scroll-area.tsx +11 -2
- package/src/components/ui/select.tsx +6 -6
- package/src/components/ui/slider.tsx +8 -5
- package/src/components/ui/switch.tsx +13 -17
- package/src/components/ui/tabs.tsx +23 -10
- package/src/components/ui/toast.tsx +190 -29
- package/src/components/ui/toggle.tsx +1 -1
- package/src/components/ui/toolbar.tsx +17 -4
- package/src/components/ui/tooltip.tsx +54 -0
- package/src/lib/docs-headings.ts +72 -0
- package/src/routeTree.gen.ts +60 -3
- package/src/routes/__root.tsx +3 -5
- package/src/routes/components.$slug.tsx +20 -4
- package/src/routes/docs.$slug.tsx +78 -0
- package/src/routes/docs.tsx +15 -0
- package/src/styles/styles.css +1 -1
- package/src/utils/cli-utils.ts +8 -8
- package/src/utils/dependency-installer.ts +30 -0
- package/src/utils/package-manager.ts +4 -4
- package/src/utils/palette.ts +666 -0
- package/src/utils/schema.ts +6 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
export type TocHeading = {
|
|
2
|
+
id: string;
|
|
3
|
+
title: string;
|
|
4
|
+
level: number;
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
export function slugifyHeading(value: string) {
|
|
8
|
+
return value
|
|
9
|
+
.trim()
|
|
10
|
+
.toLowerCase()
|
|
11
|
+
.replace(/`/g, "")
|
|
12
|
+
.replace(/\[(.*?)\]\((.*?)\)/g, "$1")
|
|
13
|
+
.replace(/<[^>]+>/g, "")
|
|
14
|
+
.replace(/&[a-z0-9#]+;/gi, "")
|
|
15
|
+
.replace(/[^a-z0-9\s-]/g, "")
|
|
16
|
+
.replace(/\s+/g, "-")
|
|
17
|
+
.replace(/-+/g, "-")
|
|
18
|
+
.replace(/^-|-$/g, "");
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function sanitizeHeadingTitle(value: string) {
|
|
22
|
+
return value
|
|
23
|
+
.replace(/\s+#+\s*$/, "")
|
|
24
|
+
.replace(/`/g, "")
|
|
25
|
+
.replace(/\[(.*?)\]\((.*?)\)/g, "$1")
|
|
26
|
+
.replace(/[*_~]/g, "")
|
|
27
|
+
.replace(/<[^>]+>/g, "")
|
|
28
|
+
.replace(/&[a-z0-9#]+;/gi, "")
|
|
29
|
+
.trim();
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function extractHeadingsFromMarkdown(content: string): TocHeading[] {
|
|
33
|
+
const headings: TocHeading[] = [];
|
|
34
|
+
const lines = content.split("\n");
|
|
35
|
+
let inCodeFence = false;
|
|
36
|
+
|
|
37
|
+
for (const rawLine of lines) {
|
|
38
|
+
const line = rawLine.trim();
|
|
39
|
+
|
|
40
|
+
if (line.startsWith("```")) {
|
|
41
|
+
inCodeFence = !inCodeFence;
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (inCodeFence) {
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const match = line.match(/^(#{1,6})\s+(.+)$/);
|
|
50
|
+
|
|
51
|
+
if (!match) {
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const level = match[1]?.length ?? 0;
|
|
56
|
+
const title = sanitizeHeadingTitle(match[2] ?? "");
|
|
57
|
+
|
|
58
|
+
if (!title) {
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const id = slugifyHeading(title);
|
|
63
|
+
|
|
64
|
+
if (!id) {
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
headings.push({ id, title, level });
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return headings;
|
|
72
|
+
}
|
package/src/routeTree.gen.ts
CHANGED
|
@@ -9,11 +9,18 @@
|
|
|
9
9
|
// Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified.
|
|
10
10
|
|
|
11
11
|
import { Route as rootRouteImport } from './routes/__root'
|
|
12
|
+
import { Route as DocsRouteImport } from './routes/docs'
|
|
12
13
|
import { Route as ComponentsRouteImport } from './routes/components'
|
|
13
14
|
import { Route as IndexRouteImport } from './routes/index'
|
|
14
15
|
import { Route as ComponentsIndexRouteImport } from './routes/components.index'
|
|
16
|
+
import { Route as DocsSlugRouteImport } from './routes/docs.$slug'
|
|
15
17
|
import { Route as ComponentsSlugRouteImport } from './routes/components.$slug'
|
|
16
18
|
|
|
19
|
+
const DocsRoute = DocsRouteImport.update({
|
|
20
|
+
id: '/docs',
|
|
21
|
+
path: '/docs',
|
|
22
|
+
getParentRoute: () => rootRouteImport,
|
|
23
|
+
} as any)
|
|
17
24
|
const ComponentsRoute = ComponentsRouteImport.update({
|
|
18
25
|
id: '/components',
|
|
19
26
|
path: '/components',
|
|
@@ -29,6 +36,11 @@ const ComponentsIndexRoute = ComponentsIndexRouteImport.update({
|
|
|
29
36
|
path: '/',
|
|
30
37
|
getParentRoute: () => ComponentsRoute,
|
|
31
38
|
} as any)
|
|
39
|
+
const DocsSlugRoute = DocsSlugRouteImport.update({
|
|
40
|
+
id: '/$slug',
|
|
41
|
+
path: '/$slug',
|
|
42
|
+
getParentRoute: () => DocsRoute,
|
|
43
|
+
} as any)
|
|
32
44
|
const ComponentsSlugRoute = ComponentsSlugRouteImport.update({
|
|
33
45
|
id: '/$slug',
|
|
34
46
|
path: '/$slug',
|
|
@@ -38,36 +50,63 @@ const ComponentsSlugRoute = ComponentsSlugRouteImport.update({
|
|
|
38
50
|
export interface FileRoutesByFullPath {
|
|
39
51
|
'/': typeof IndexRoute
|
|
40
52
|
'/components': typeof ComponentsRouteWithChildren
|
|
53
|
+
'/docs': typeof DocsRouteWithChildren
|
|
41
54
|
'/components/$slug': typeof ComponentsSlugRoute
|
|
55
|
+
'/docs/$slug': typeof DocsSlugRoute
|
|
42
56
|
'/components/': typeof ComponentsIndexRoute
|
|
43
57
|
}
|
|
44
58
|
export interface FileRoutesByTo {
|
|
45
59
|
'/': typeof IndexRoute
|
|
60
|
+
'/docs': typeof DocsRouteWithChildren
|
|
46
61
|
'/components/$slug': typeof ComponentsSlugRoute
|
|
62
|
+
'/docs/$slug': typeof DocsSlugRoute
|
|
47
63
|
'/components': typeof ComponentsIndexRoute
|
|
48
64
|
}
|
|
49
65
|
export interface FileRoutesById {
|
|
50
66
|
__root__: typeof rootRouteImport
|
|
51
67
|
'/': typeof IndexRoute
|
|
52
68
|
'/components': typeof ComponentsRouteWithChildren
|
|
69
|
+
'/docs': typeof DocsRouteWithChildren
|
|
53
70
|
'/components/$slug': typeof ComponentsSlugRoute
|
|
71
|
+
'/docs/$slug': typeof DocsSlugRoute
|
|
54
72
|
'/components/': typeof ComponentsIndexRoute
|
|
55
73
|
}
|
|
56
74
|
export interface FileRouteTypes {
|
|
57
75
|
fileRoutesByFullPath: FileRoutesByFullPath
|
|
58
|
-
fullPaths:
|
|
76
|
+
fullPaths:
|
|
77
|
+
| '/'
|
|
78
|
+
| '/components'
|
|
79
|
+
| '/docs'
|
|
80
|
+
| '/components/$slug'
|
|
81
|
+
| '/docs/$slug'
|
|
82
|
+
| '/components/'
|
|
59
83
|
fileRoutesByTo: FileRoutesByTo
|
|
60
|
-
to: '/' | '/components/$slug' | '/components'
|
|
61
|
-
id:
|
|
84
|
+
to: '/' | '/docs' | '/components/$slug' | '/docs/$slug' | '/components'
|
|
85
|
+
id:
|
|
86
|
+
| '__root__'
|
|
87
|
+
| '/'
|
|
88
|
+
| '/components'
|
|
89
|
+
| '/docs'
|
|
90
|
+
| '/components/$slug'
|
|
91
|
+
| '/docs/$slug'
|
|
92
|
+
| '/components/'
|
|
62
93
|
fileRoutesById: FileRoutesById
|
|
63
94
|
}
|
|
64
95
|
export interface RootRouteChildren {
|
|
65
96
|
IndexRoute: typeof IndexRoute
|
|
66
97
|
ComponentsRoute: typeof ComponentsRouteWithChildren
|
|
98
|
+
DocsRoute: typeof DocsRouteWithChildren
|
|
67
99
|
}
|
|
68
100
|
|
|
69
101
|
declare module '@tanstack/react-router' {
|
|
70
102
|
interface FileRoutesByPath {
|
|
103
|
+
'/docs': {
|
|
104
|
+
id: '/docs'
|
|
105
|
+
path: '/docs'
|
|
106
|
+
fullPath: '/docs'
|
|
107
|
+
preLoaderRoute: typeof DocsRouteImport
|
|
108
|
+
parentRoute: typeof rootRouteImport
|
|
109
|
+
}
|
|
71
110
|
'/components': {
|
|
72
111
|
id: '/components'
|
|
73
112
|
path: '/components'
|
|
@@ -89,6 +128,13 @@ declare module '@tanstack/react-router' {
|
|
|
89
128
|
preLoaderRoute: typeof ComponentsIndexRouteImport
|
|
90
129
|
parentRoute: typeof ComponentsRoute
|
|
91
130
|
}
|
|
131
|
+
'/docs/$slug': {
|
|
132
|
+
id: '/docs/$slug'
|
|
133
|
+
path: '/$slug'
|
|
134
|
+
fullPath: '/docs/$slug'
|
|
135
|
+
preLoaderRoute: typeof DocsSlugRouteImport
|
|
136
|
+
parentRoute: typeof DocsRoute
|
|
137
|
+
}
|
|
92
138
|
'/components/$slug': {
|
|
93
139
|
id: '/components/$slug'
|
|
94
140
|
path: '/$slug'
|
|
@@ -113,9 +159,20 @@ const ComponentsRouteWithChildren = ComponentsRoute._addFileChildren(
|
|
|
113
159
|
ComponentsRouteChildren,
|
|
114
160
|
)
|
|
115
161
|
|
|
162
|
+
interface DocsRouteChildren {
|
|
163
|
+
DocsSlugRoute: typeof DocsSlugRoute
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const DocsRouteChildren: DocsRouteChildren = {
|
|
167
|
+
DocsSlugRoute: DocsSlugRoute,
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const DocsRouteWithChildren = DocsRoute._addFileChildren(DocsRouteChildren)
|
|
171
|
+
|
|
116
172
|
const rootRouteChildren: RootRouteChildren = {
|
|
117
173
|
IndexRoute: IndexRoute,
|
|
118
174
|
ComponentsRoute: ComponentsRouteWithChildren,
|
|
175
|
+
DocsRoute: DocsRouteWithChildren,
|
|
119
176
|
}
|
|
120
177
|
export const routeTree = rootRouteImport
|
|
121
178
|
._addFileChildren(rootRouteChildren)
|
package/src/routes/__root.tsx
CHANGED
|
@@ -40,17 +40,15 @@ export const Route = createRootRoute({
|
|
|
40
40
|
|
|
41
41
|
function RootDocument({ children }: { children: React.ReactNode }) {
|
|
42
42
|
return (
|
|
43
|
-
<Suspense fallback={<SuspenseFallback className="
|
|
43
|
+
<Suspense fallback={<SuspenseFallback className="" />}>
|
|
44
44
|
<ThemeProvider>
|
|
45
45
|
<html lang="en">
|
|
46
46
|
<head>
|
|
47
47
|
<HeadContent />
|
|
48
48
|
</head>
|
|
49
|
-
<body className="flex h-dvh flex-col">
|
|
49
|
+
<body className="flex h-dvh flex-col overflow-hidden bg-muted">
|
|
50
50
|
<Header />
|
|
51
|
-
<main className=" container mx-auto flex flex-1
|
|
52
|
-
{children}
|
|
53
|
-
</main>
|
|
51
|
+
<main className=" container mx-auto flex min-h-0 xl:bg-card flex-1 px-4 xl:p-0 ">{children}</main>
|
|
54
52
|
<Footer />
|
|
55
53
|
<TanStackDevtools
|
|
56
54
|
config={{
|
|
@@ -7,16 +7,27 @@ import { PageHeader } from "@/components/docs/layout/page-header";
|
|
|
7
7
|
import { mdxComponents } from "@/components/docs/markdown/components";
|
|
8
8
|
import { RenderPreview } from "@/components/docs/markdown/render-preview";
|
|
9
9
|
|
|
10
|
+
const markdownFiles = import.meta.glob("../../content/components/*.mdx", {
|
|
11
|
+
query: "?url",
|
|
12
|
+
import: "default",
|
|
13
|
+
eager: true,
|
|
14
|
+
}) as Record<string, string>;
|
|
15
|
+
|
|
10
16
|
export const Route = createFileRoute("/components/$slug")({
|
|
11
17
|
loader: ({ params }) => {
|
|
12
18
|
const { slug } = params;
|
|
13
|
-
const component =
|
|
19
|
+
const component = allComponents?.find((c) => c.slug === slug);
|
|
14
20
|
|
|
15
21
|
if (!component) {
|
|
16
22
|
throw notFound();
|
|
17
23
|
}
|
|
18
24
|
|
|
19
|
-
|
|
25
|
+
const markdownLink = markdownFiles[`../../content/components/${component.slug}.mdx`];
|
|
26
|
+
|
|
27
|
+
return {
|
|
28
|
+
...component,
|
|
29
|
+
markdownLink,
|
|
30
|
+
};
|
|
20
31
|
},
|
|
21
32
|
head: ({ loaderData }) => ({
|
|
22
33
|
meta: [
|
|
@@ -51,8 +62,13 @@ function RouteComponent() {
|
|
|
51
62
|
|
|
52
63
|
return (
|
|
53
64
|
<div className=" flex flex-col gap-6 ">
|
|
54
|
-
<PageHeader
|
|
55
|
-
|
|
65
|
+
<PageHeader
|
|
66
|
+
title={component?.title}
|
|
67
|
+
subtitle={component?.description}
|
|
68
|
+
baseUILink={component?.referenceLink}
|
|
69
|
+
markdownLink={component?.markdownLink}
|
|
70
|
+
/>
|
|
71
|
+
<div data-docs-content className="container mx-auto max-w-4xl min-w-0 p-6">
|
|
56
72
|
{isMounted ? (
|
|
57
73
|
<MDXContent code={component.mdx} components={{ ...mdxComponents, RenderPreview }} />
|
|
58
74
|
) : null}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { MDXContent } from "@content-collections/mdx/react";
|
|
2
|
+
import { createFileRoute, notFound } from "@tanstack/react-router";
|
|
3
|
+
import { allDocs } from "content-collections";
|
|
4
|
+
import { useEffect, useState } from "react";
|
|
5
|
+
|
|
6
|
+
import { PageHeader } from "@/components/docs/layout/page-header";
|
|
7
|
+
import { mdxComponents } from "@/components/docs/markdown/components";
|
|
8
|
+
import { RenderPreview } from "@/components/docs/markdown/render-preview";
|
|
9
|
+
|
|
10
|
+
const markdownFiles = import.meta.glob("../../content/docs/*.mdx", {
|
|
11
|
+
query: "?url",
|
|
12
|
+
import: "default",
|
|
13
|
+
eager: true,
|
|
14
|
+
}) as Record<string, string>;
|
|
15
|
+
|
|
16
|
+
export const Route = createFileRoute("/docs/$slug")({
|
|
17
|
+
loader: ({ params }) => {
|
|
18
|
+
const { slug } = params;
|
|
19
|
+
const doc = allDocs?.find((d) => d.slug === slug);
|
|
20
|
+
|
|
21
|
+
if (!doc) {
|
|
22
|
+
throw notFound();
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const markdownLink = markdownFiles[`../../content/docs/${doc.slug}.mdx`];
|
|
26
|
+
|
|
27
|
+
return {
|
|
28
|
+
...doc,
|
|
29
|
+
markdownLink,
|
|
30
|
+
};
|
|
31
|
+
},
|
|
32
|
+
head: ({ loaderData }) => ({
|
|
33
|
+
meta: [
|
|
34
|
+
{
|
|
35
|
+
charSet: "utf-8",
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
name: "viewport",
|
|
39
|
+
content: "width=device-width, initial-scale=1",
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
title: `${loaderData?.title} - Shapes UI`,
|
|
43
|
+
},
|
|
44
|
+
],
|
|
45
|
+
links: [
|
|
46
|
+
{
|
|
47
|
+
rel: "icon",
|
|
48
|
+
href: "/favicon.ico",
|
|
49
|
+
},
|
|
50
|
+
],
|
|
51
|
+
}),
|
|
52
|
+
component: RouteComponent,
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
function RouteComponent() {
|
|
56
|
+
const doc = Route.useLoaderData();
|
|
57
|
+
const [isMounted, setIsMounted] = useState(false);
|
|
58
|
+
|
|
59
|
+
useEffect(() => {
|
|
60
|
+
setIsMounted(true);
|
|
61
|
+
}, []);
|
|
62
|
+
|
|
63
|
+
return (
|
|
64
|
+
<div className=" flex flex-col gap-6 ">
|
|
65
|
+
<PageHeader
|
|
66
|
+
title={doc?.title}
|
|
67
|
+
subtitle={doc?.description}
|
|
68
|
+
baseUILink={doc?.referenceLink}
|
|
69
|
+
markdownLink={doc?.markdownLink}
|
|
70
|
+
/>
|
|
71
|
+
<div data-docs-content className="container mx-auto max-w-4xl min-w-0 p-6">
|
|
72
|
+
{isMounted ? (
|
|
73
|
+
<MDXContent code={doc.mdx} components={{ ...mdxComponents, RenderPreview }} />
|
|
74
|
+
) : null}
|
|
75
|
+
</div>
|
|
76
|
+
</div>
|
|
77
|
+
);
|
|
78
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { createFileRoute, Outlet } from "@tanstack/react-router";
|
|
2
|
+
|
|
3
|
+
import { SplitLayout } from "@/components/docs/layout/split-layout";
|
|
4
|
+
|
|
5
|
+
export const Route = createFileRoute("/docs")({
|
|
6
|
+
component: RouteComponent,
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
function RouteComponent() {
|
|
10
|
+
return (
|
|
11
|
+
<SplitLayout>
|
|
12
|
+
<Outlet />
|
|
13
|
+
</SplitLayout>
|
|
14
|
+
);
|
|
15
|
+
}
|
package/src/styles/styles.css
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
--secondary: oklch(0.97 0 0);
|
|
16
16
|
--secondary-foreground: oklch(0.205 0 0);
|
|
17
17
|
--muted: oklch(0.97 0 0);
|
|
18
|
-
--muted-foreground: oklch(
|
|
18
|
+
--muted-foreground: oklch(55.553% 0.00006 271.152);
|
|
19
19
|
--accent: oklch(0.97 0 0);
|
|
20
20
|
--accent-foreground: oklch(0.205 0 0);
|
|
21
21
|
--destructive: oklch(57.7% 0.245 27.325);
|
package/src/utils/cli-utils.ts
CHANGED
|
@@ -13,14 +13,14 @@ export function exitIfCancelled<T>(value: T): Exclude<T, symbol> {
|
|
|
13
13
|
return value as Exclude<T, symbol>;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
export async function getConfig(): Promise<Config | null> {
|
|
17
|
-
const configPath = path.join(
|
|
16
|
+
export async function getConfig(cwd = process.cwd()): Promise<Config | null> {
|
|
17
|
+
const configPath = path.join(cwd, "shapes.json");
|
|
18
18
|
if (!fs.existsSync(configPath)) return null;
|
|
19
19
|
return configSchema.parse(await fs.readJSON(configPath));
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
export async function readPackageJson() {
|
|
23
|
-
const pkgPath = path.join(
|
|
22
|
+
export async function readPackageJson(cwd = process.cwd()) {
|
|
23
|
+
const pkgPath = path.join(cwd, "package.json");
|
|
24
24
|
if (!(await fs.pathExists(pkgPath))) return null;
|
|
25
25
|
return fs.readJSON(pkgPath);
|
|
26
26
|
}
|
|
@@ -45,10 +45,10 @@ export function getMissingDeps(pkg: Record<string, any> | null, deps: string[])
|
|
|
45
45
|
return deps.filter((dep) => !pkg.dependencies?.[dep] && !pkg.devDependencies?.[dep]);
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
export async function isViteProject() {
|
|
49
|
-
const viteConfigTs = path.join(
|
|
50
|
-
const viteConfigJs = path.join(
|
|
51
|
-
const viteConfigMjs = path.join(
|
|
48
|
+
export async function isViteProject(cwd = process.cwd()) {
|
|
49
|
+
const viteConfigTs = path.join(cwd, "vite.config.ts");
|
|
50
|
+
const viteConfigJs = path.join(cwd, "vite.config.js");
|
|
51
|
+
const viteConfigMjs = path.join(cwd, "vite.config.mjs");
|
|
52
52
|
|
|
53
53
|
return (
|
|
54
54
|
(await fs.pathExists(viteConfigTs)) ||
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { spinner } from "@clack/prompts";
|
|
2
|
+
import { execa } from "execa";
|
|
3
|
+
|
|
4
|
+
import { getInstallCommand } from "@/utils/package-manager";
|
|
5
|
+
|
|
6
|
+
type InstallDependenciesOptions = {
|
|
7
|
+
dev?: boolean;
|
|
8
|
+
label?: string;
|
|
9
|
+
successMessage?: string;
|
|
10
|
+
cwd?: string;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export async function installDependencies(
|
|
14
|
+
deps: string[],
|
|
15
|
+
options: InstallDependenciesOptions = {},
|
|
16
|
+
) {
|
|
17
|
+
if (!deps.length) return;
|
|
18
|
+
|
|
19
|
+
const spin = spinner();
|
|
20
|
+
const label =
|
|
21
|
+
options.label ?? (options.dev ? "Installing dev dependencies" : "Installing dependencies");
|
|
22
|
+
|
|
23
|
+
spin.start(label);
|
|
24
|
+
|
|
25
|
+
const cwd = options.cwd ?? process.cwd();
|
|
26
|
+
const [command, ...args] = await getInstallCommand(deps, options.dev ?? false, cwd);
|
|
27
|
+
await execa(command, args, { cwd });
|
|
28
|
+
|
|
29
|
+
spin.stop(options.successMessage ?? "Dependencies installed");
|
|
30
|
+
}
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import { detect } from "detect-package-manager";
|
|
2
2
|
|
|
3
|
-
export async function getPackageManager() {
|
|
3
|
+
export async function getPackageManager(cwd = process.cwd()) {
|
|
4
4
|
try {
|
|
5
|
-
return await detect();
|
|
5
|
+
return await detect({ cwd });
|
|
6
6
|
} catch {
|
|
7
7
|
return "npm";
|
|
8
8
|
}
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
export async function getInstallCommand(deps: string[], dev = false) {
|
|
12
|
-
const pm = await getPackageManager();
|
|
11
|
+
export async function getInstallCommand(deps: string[], dev = false, cwd = process.cwd()) {
|
|
12
|
+
const pm = await getPackageManager(cwd);
|
|
13
13
|
|
|
14
14
|
if (pm === "yarn") {
|
|
15
15
|
return ["yarn", "add", ...(dev ? ["-D"] : []), ...deps];
|