@sudajs/cli 0.11.0 → 0.12.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/dist/index.d.ts +712 -0
- package/dist/index.js +157 -2
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
- package/templates/theme/AGENTS.md +9 -6
- package/templates/theme/package.json +2 -2
- package/templates/theme/src/layout.tsx +26 -8
- package/templates/theme/src/locales/en.json +2 -1
- package/templates/theme/src/manifest.ts +49 -1
- package/templates/theme/src/sections.tsx +4 -1
- package/templates/theme/src/styles.css +20 -20
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sudajs/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"suda": "./bin/suda.js"
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
28
|
-
"@puckeditor/core": "^0.
|
|
28
|
+
"@puckeditor/core": "^0.22.0",
|
|
29
29
|
"commander": "^12.1.0",
|
|
30
30
|
"esbuild": "^0.25.12",
|
|
31
31
|
"lucide-react": "^1.17.0",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"react": "^19.2.7",
|
|
35
35
|
"react-dom": "^19.2.7",
|
|
36
36
|
"zod": "^3.24.1",
|
|
37
|
-
"@sudajs/theme-engine": "
|
|
37
|
+
"@sudajs/theme-engine": "4.0.0"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@tailwindcss/postcss": "^4.3.0",
|
|
@@ -49,8 +49,8 @@
|
|
|
49
49
|
"typescript": "^5.7.2",
|
|
50
50
|
"vite": "^7.3.3",
|
|
51
51
|
"vitest": "^3.2.4",
|
|
52
|
-
"@suda/eslint-config": "0.0.0",
|
|
53
52
|
"@suda/build-config": "0.0.0",
|
|
53
|
+
"@suda/eslint-config": "0.0.0",
|
|
54
54
|
"@suda/tsconfig": "0.0.0"
|
|
55
55
|
},
|
|
56
56
|
"scripts": {
|
|
@@ -308,8 +308,8 @@ example `FeaturedPosts`, `LatestPosts`, or `TopicPosts`. Use it for homepage
|
|
|
308
308
|
insights, featured articles, case studies, news teasers, or tag-filtered post
|
|
309
309
|
groups on ordinary pages.
|
|
310
310
|
|
|
311
|
-
Define that section with
|
|
312
|
-
default query on
|
|
311
|
+
Define that section with one or more top-level `type: "posts"` fields and a
|
|
312
|
+
default query on each matching prop:
|
|
313
313
|
|
|
314
314
|
```tsx
|
|
315
315
|
fields: {
|
|
@@ -320,10 +320,13 @@ defaultProps: {
|
|
|
320
320
|
},
|
|
321
321
|
```
|
|
322
322
|
|
|
323
|
-
Supported strategies are `latest`, `featured`, `by_tag`, and `manual`.
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
323
|
+
Supported strategies are `latest`, `featured`, `by_tag`, and `manual`. Manual
|
|
324
|
+
queries store only `items` and must not include `limit`. Runtime post resources
|
|
325
|
+
are keyed as `${props.id}.${fieldKey}` with both parts URL-encoded by the
|
|
326
|
+
platform. In the section render function, call
|
|
327
|
+
`getPostResource(puck?.metadata, { componentId: props.id, fieldKey: "postList" })`
|
|
328
|
+
with the exact posts field key. Never import Prisma, call platform APIs, or
|
|
329
|
+
query the database from theme code.
|
|
327
330
|
|
|
328
331
|
Starter pages must include one home/index page with `isHome: true`. Recommended
|
|
329
332
|
starter pages include `index`, `about-us`, `contact-us`, `services`, and `team`.
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"devDependencies": {
|
|
20
20
|
"@eslint/js": "^9.39.4",
|
|
21
21
|
"@tailwindcss/postcss": "^4.3.0",
|
|
22
|
-
"@puckeditor/core": "^0.
|
|
22
|
+
"@puckeditor/core": "^0.22.0",
|
|
23
23
|
"@sudajs/cli": "*",
|
|
24
24
|
"@sudajs/theme-engine": "*",
|
|
25
25
|
"@types/node": "^24.13.2",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"vite": "^8.1.0"
|
|
43
43
|
},
|
|
44
44
|
"peerDependencies": {
|
|
45
|
-
"@puckeditor/core": "^0.
|
|
45
|
+
"@puckeditor/core": "^0.22.0",
|
|
46
46
|
"@sudajs/theme-engine": "*",
|
|
47
47
|
"lucide-react": "^1.17.0",
|
|
48
48
|
"react": "^19.2.7",
|
|
@@ -1,11 +1,21 @@
|
|
|
1
1
|
import type { SudaComponentConfig, SudaRootConfig } from "@sudajs/theme-engine";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
createThemeDesignCssVariables,
|
|
4
|
+
createThemeDesignDefault,
|
|
5
|
+
designSystemField,
|
|
6
|
+
getIcpRecord,
|
|
7
|
+
getPageSlot,
|
|
8
|
+
getWhiteLabel,
|
|
9
|
+
resolveThemeDesignTokens,
|
|
10
|
+
type ThemeDesignValue,
|
|
11
|
+
} from "@sudajs/theme-engine/runtime";
|
|
3
12
|
import type { ReactElement, ReactNode } from "react";
|
|
4
13
|
|
|
5
14
|
import { t } from "./i18n.js";
|
|
15
|
+
import { sourceManifest } from "./manifest.js";
|
|
6
16
|
|
|
7
17
|
type PuckExtras = { puck?: { metadata?: Record<string, unknown> } };
|
|
8
|
-
type RootProps = { children?: ReactNode; title?: string };
|
|
18
|
+
type RootProps = { children?: ReactNode; title?: string; designSystem?: ThemeDesignValue };
|
|
9
19
|
type HeaderProps = { siteName?: string };
|
|
10
20
|
type PageOutletProps = PuckExtras;
|
|
11
21
|
type FooterProps = { text?: string } & PuckExtras;
|
|
@@ -13,13 +23,21 @@ type FooterProps = { text?: string } & PuckExtras;
|
|
|
13
23
|
export const rootConfig: SudaRootConfig<RootProps> = {
|
|
14
24
|
fields: {
|
|
15
25
|
title: { type: "text", label: t("layout.root.fields.title") },
|
|
26
|
+
designSystem: designSystemField(t("layout.root.fields.designSystem"), sourceManifest.designSystem),
|
|
27
|
+
},
|
|
28
|
+
defaultProps: {
|
|
29
|
+
title: "__SUDA_THEME_KEY__",
|
|
30
|
+
designSystem: createThemeDesignDefault(sourceManifest.designSystem),
|
|
31
|
+
},
|
|
32
|
+
render: ({ children, designSystem, title }) => {
|
|
33
|
+
const tokens = resolveThemeDesignTokens(sourceManifest.designSystem, designSystem);
|
|
34
|
+
const style = createThemeDesignCssVariables(tokens);
|
|
35
|
+
return (
|
|
36
|
+
<div className="__SUDA_THEME_KEY__-root" data-site-name={title} style={style}>
|
|
37
|
+
{children}
|
|
38
|
+
</div>
|
|
39
|
+
);
|
|
16
40
|
},
|
|
17
|
-
defaultProps: { title: "__SUDA_THEME_KEY__" },
|
|
18
|
-
render: ({ children, title }) => (
|
|
19
|
-
<div className="__SUDA_THEME_KEY__-root" data-site-name={title}>
|
|
20
|
-
{children}
|
|
21
|
-
</div>
|
|
22
|
-
),
|
|
23
41
|
};
|
|
24
42
|
|
|
25
43
|
export const Header: SudaComponentConfig<HeaderProps> = {
|
|
@@ -8,7 +8,55 @@ export const sourceManifest: ThemeSourceManifest = {
|
|
|
8
8
|
key: "__SUDA_THEME_KEY__",
|
|
9
9
|
name: "__SUDA_THEME_KEY__",
|
|
10
10
|
categories: ["other"],
|
|
11
|
-
minEngineVersion: "
|
|
11
|
+
minEngineVersion: "4.0.0",
|
|
12
|
+
designSystem: {
|
|
13
|
+
version: 1,
|
|
14
|
+
defaultPresetId: "default",
|
|
15
|
+
presets: [
|
|
16
|
+
{
|
|
17
|
+
id: "default",
|
|
18
|
+
label: "Default",
|
|
19
|
+
tokens: {
|
|
20
|
+
colors: {
|
|
21
|
+
background: "#ffffff",
|
|
22
|
+
foreground: "#111827",
|
|
23
|
+
primary: "#111827",
|
|
24
|
+
primaryForeground: "#ffffff",
|
|
25
|
+
accent: "#f8fafc",
|
|
26
|
+
accentForeground: "#111827",
|
|
27
|
+
muted: "#f4f5f7",
|
|
28
|
+
mutedForeground: "#4b5563",
|
|
29
|
+
},
|
|
30
|
+
radius: {
|
|
31
|
+
card: "8px",
|
|
32
|
+
button: "8px",
|
|
33
|
+
input: "8px",
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
id: "ocean",
|
|
39
|
+
label: "Ocean",
|
|
40
|
+
tokens: {
|
|
41
|
+
colors: {
|
|
42
|
+
background: "#f8fbff",
|
|
43
|
+
foreground: "#0e1b36",
|
|
44
|
+
primary: "#2563eb",
|
|
45
|
+
primaryForeground: "#ffffff",
|
|
46
|
+
accent: "#dbeafe",
|
|
47
|
+
accentForeground: "#0e1b36",
|
|
48
|
+
muted: "#eff6ff",
|
|
49
|
+
mutedForeground: "#42526e",
|
|
50
|
+
},
|
|
51
|
+
radius: {
|
|
52
|
+
card: "14px",
|
|
53
|
+
button: "9999px",
|
|
54
|
+
input: "10px",
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
],
|
|
59
|
+
},
|
|
12
60
|
entry: "index.js",
|
|
13
61
|
clientEntry: "runtime.client.js",
|
|
14
62
|
// Required. SudaCloud currently hosts SSR themes only; CSR/Hybrid postures
|
|
@@ -240,7 +240,10 @@ export const FeaturedPosts: SudaComponentConfig<FeaturedPostsProps> = {
|
|
|
240
240
|
postList: { strategy: "featured", limit: 3 },
|
|
241
241
|
},
|
|
242
242
|
render: ({ id, title, description, puck }) => {
|
|
243
|
-
const resource = getPostResource(puck?.metadata,
|
|
243
|
+
const resource = getPostResource(puck?.metadata, {
|
|
244
|
+
componentId: id,
|
|
245
|
+
fieldKey: "postList",
|
|
246
|
+
});
|
|
244
247
|
const posts = resource.posts;
|
|
245
248
|
return (
|
|
246
249
|
<section className="__SUDA_THEME_KEY__-section">
|
|
@@ -3,22 +3,22 @@
|
|
|
3
3
|
|
|
4
4
|
.__SUDA_THEME_KEY__-root {
|
|
5
5
|
font-family: Inter, ui-sans-serif, system-ui, sans-serif;
|
|
6
|
-
color: #111827;
|
|
7
|
-
background: #ffffff;
|
|
6
|
+
color: var(--suda-color-foreground, #111827);
|
|
7
|
+
background: var(--suda-color-background, #ffffff);
|
|
8
8
|
}
|
|
9
9
|
.__SUDA_THEME_KEY__-header,
|
|
10
10
|
.__SUDA_THEME_KEY__-footer {
|
|
11
11
|
padding: 20px clamp(20px, 5vw, 64px);
|
|
12
|
-
border-bottom: 1px solid #e5e7eb;
|
|
12
|
+
border-bottom: 1px solid var(--suda-color-muted, #e5e7eb);
|
|
13
13
|
}
|
|
14
14
|
.__SUDA_THEME_KEY__-footer {
|
|
15
15
|
display: flex;
|
|
16
16
|
flex-wrap: wrap;
|
|
17
17
|
align-items: center;
|
|
18
18
|
gap: 12px 20px;
|
|
19
|
-
border-top: 1px solid #e5e7eb;
|
|
19
|
+
border-top: 1px solid var(--suda-color-muted, #e5e7eb);
|
|
20
20
|
border-bottom: 0;
|
|
21
|
-
color: #6b7280;
|
|
21
|
+
color: var(--suda-color-muted-foreground, #6b7280);
|
|
22
22
|
}
|
|
23
23
|
.__SUDA_THEME_KEY__-footer a {
|
|
24
24
|
display: inline-flex;
|
|
@@ -35,19 +35,19 @@
|
|
|
35
35
|
padding: 64px clamp(20px, 5vw, 64px);
|
|
36
36
|
}
|
|
37
37
|
.__SUDA_THEME_KEY__-hero {
|
|
38
|
-
background: #f8fafc;
|
|
38
|
+
background: var(--suda-color-accent, #f8fafc);
|
|
39
39
|
}
|
|
40
40
|
.__SUDA_THEME_KEY__-hero-logo {
|
|
41
41
|
width: 64px;
|
|
42
42
|
height: 64px;
|
|
43
|
-
border-radius: 14px;
|
|
43
|
+
border-radius: var(--suda-radius-card, 14px);
|
|
44
44
|
margin-bottom: 24px;
|
|
45
45
|
}
|
|
46
46
|
.__SUDA_THEME_KEY__-eyebrow {
|
|
47
47
|
text-transform: uppercase;
|
|
48
48
|
letter-spacing: 0.08em;
|
|
49
49
|
font-size: 12px;
|
|
50
|
-
color: #2563eb;
|
|
50
|
+
color: var(--suda-color-primary, #2563eb);
|
|
51
51
|
font-weight: 700;
|
|
52
52
|
}
|
|
53
53
|
.__SUDA_THEME_KEY__-section h1 {
|
|
@@ -65,16 +65,16 @@
|
|
|
65
65
|
.__SUDA_THEME_KEY__-section p {
|
|
66
66
|
max-width: 680px;
|
|
67
67
|
line-height: 1.7;
|
|
68
|
-
color: #4b5563;
|
|
68
|
+
color: var(--suda-color-muted-foreground, #4b5563);
|
|
69
69
|
}
|
|
70
70
|
.__SUDA_THEME_KEY__-button {
|
|
71
71
|
display: inline-flex;
|
|
72
72
|
align-items: center;
|
|
73
73
|
min-height: 42px;
|
|
74
74
|
padding: 0 18px;
|
|
75
|
-
border-radius: 8px;
|
|
76
|
-
background: #111827;
|
|
77
|
-
color: #ffffff;
|
|
75
|
+
border-radius: var(--suda-radius-button, 8px);
|
|
76
|
+
background: var(--suda-color-primary, #111827);
|
|
77
|
+
color: var(--suda-color-primary-foreground, #ffffff);
|
|
78
78
|
text-decoration: none;
|
|
79
79
|
font-weight: 700;
|
|
80
80
|
}
|
|
@@ -85,14 +85,14 @@
|
|
|
85
85
|
margin-top: 28px;
|
|
86
86
|
}
|
|
87
87
|
.__SUDA_THEME_KEY__-card {
|
|
88
|
-
border: 1px solid #e5e7eb;
|
|
89
|
-
border-radius: 8px;
|
|
88
|
+
border: 1px solid var(--suda-color-muted, #e5e7eb);
|
|
89
|
+
border-radius: var(--suda-radius-card, 8px);
|
|
90
90
|
padding: 20px;
|
|
91
91
|
}
|
|
92
92
|
.__SUDA_THEME_KEY__-card-icon {
|
|
93
93
|
width: 24px;
|
|
94
94
|
height: 24px;
|
|
95
|
-
color: #2563eb;
|
|
95
|
+
color: var(--suda-color-primary, #2563eb);
|
|
96
96
|
}
|
|
97
97
|
.__SUDA_THEME_KEY__-quote blockquote {
|
|
98
98
|
max-width: 780px;
|
|
@@ -101,15 +101,15 @@
|
|
|
101
101
|
margin: 0 0 16px;
|
|
102
102
|
}
|
|
103
103
|
.__SUDA_THEME_KEY__-cta {
|
|
104
|
-
background: #111827;
|
|
105
|
-
color: #ffffff;
|
|
104
|
+
background: var(--suda-color-foreground, #111827);
|
|
105
|
+
color: var(--suda-color-background, #ffffff);
|
|
106
106
|
}
|
|
107
107
|
.__SUDA_THEME_KEY__-cta p {
|
|
108
|
-
color: #d1d5db;
|
|
108
|
+
color: var(--suda-color-muted, #d1d5db);
|
|
109
109
|
}
|
|
110
110
|
.__SUDA_THEME_KEY__-cta .__SUDA_THEME_KEY__-button {
|
|
111
|
-
background: #ffffff;
|
|
112
|
-
color: #111827;
|
|
111
|
+
background: var(--suda-color-background, #ffffff);
|
|
112
|
+
color: var(--suda-color-foreground, #111827);
|
|
113
113
|
}
|
|
114
114
|
@media (max-width: 760px) {
|
|
115
115
|
.__SUDA_THEME_KEY__-grid {
|