uniweb 0.2.14 → 0.2.17

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.
Files changed (70) hide show
  1. package/README.md +133 -35
  2. package/package.json +4 -3
  3. package/src/index.js +87 -1022
  4. package/src/templates/processor.js +17 -3
  5. package/src/templates/resolver.js +2 -2
  6. package/templates/_shared/CLAUDE.md.hbs +146 -0
  7. package/templates/_shared/package.json.hbs +23 -0
  8. package/templates/_shared/pnpm-workspace.yaml +5 -0
  9. package/templates/multi/CLAUDE.md.hbs +100 -0
  10. package/templates/multi/README.md.hbs +96 -0
  11. package/templates/multi/foundations/default/package.json.hbs +37 -0
  12. package/templates/multi/foundations/default/src/components/Section/index.jsx +121 -0
  13. package/templates/multi/foundations/default/src/components/Section/meta.js +66 -0
  14. package/templates/multi/foundations/default/src/entry-runtime.js +3 -0
  15. package/templates/multi/foundations/default/src/index.js +32 -0
  16. package/templates/multi/foundations/default/src/meta.js.hbs +6 -0
  17. package/templates/multi/foundations/default/src/styles.css +11 -0
  18. package/templates/multi/foundations/default/vite.config.js +3 -0
  19. package/templates/multi/package.json.hbs +25 -0
  20. package/templates/multi/pnpm-workspace.yaml +5 -0
  21. package/templates/multi/sites/main/index.html.hbs +13 -0
  22. package/templates/multi/sites/main/package.json.hbs +27 -0
  23. package/templates/multi/sites/main/pages/home/1-welcome.md.hbs +14 -0
  24. package/templates/multi/sites/main/pages/home/page.yml +2 -0
  25. package/templates/multi/sites/main/site.yml.hbs +9 -0
  26. package/templates/multi/sites/main/src/main.jsx +1 -0
  27. package/templates/multi/sites/main/vite.config.js +7 -0
  28. package/templates/multi/template.json +4 -0
  29. package/templates/single/README.md.hbs +101 -0
  30. package/templates/single/foundation/package.json.hbs +37 -0
  31. package/templates/single/foundation/src/components/Section/index.jsx +121 -0
  32. package/templates/single/foundation/src/components/Section/meta.js +66 -0
  33. package/templates/single/foundation/src/entry-runtime.js +3 -0
  34. package/templates/single/foundation/src/index.js +35 -0
  35. package/templates/single/foundation/src/meta.js.hbs +6 -0
  36. package/templates/single/foundation/src/styles.css +11 -0
  37. package/templates/single/foundation/vite.config.js +3 -0
  38. package/templates/single/site/index.html.hbs +19 -0
  39. package/templates/single/site/package.json.hbs +27 -0
  40. package/templates/single/site/pages/home/1-welcome.md.hbs +14 -0
  41. package/templates/single/site/pages/home/page.yml +2 -0
  42. package/templates/single/site/site.yml.hbs +7 -0
  43. package/templates/single/site/src/main.jsx +1 -0
  44. package/templates/single/site/vite.config.js +3 -0
  45. package/templates/single/template.json +10 -0
  46. package/templates/template/README.md.hbs +65 -0
  47. package/templates/template/package.json.hbs +33 -0
  48. package/templates/template/template/CLAUDE.md.hbs +70 -0
  49. package/templates/template/template/foundation/package.json.hbs +37 -0
  50. package/templates/template/template/foundation/src/components/Features/index.jsx +75 -0
  51. package/templates/template/template/foundation/src/components/Features/meta.js +41 -0
  52. package/templates/template/template/foundation/src/components/Hero/index.jsx +89 -0
  53. package/templates/template/template/foundation/src/components/Hero/meta.js +47 -0
  54. package/templates/template/template/foundation/src/entry-runtime.js +3 -0
  55. package/templates/template/template/foundation/src/index.js +36 -0
  56. package/templates/template/template/foundation/src/meta.js.hbs +6 -0
  57. package/templates/template/template/foundation/src/styles.css +12 -0
  58. package/templates/template/template/foundation/vite.config.js +3 -0
  59. package/templates/template/template/package.json.hbs +14 -0
  60. package/templates/template/template/pnpm-workspace.yaml +3 -0
  61. package/templates/template/template/site/index.html.hbs +13 -0
  62. package/templates/template/template/site/package.json.hbs +27 -0
  63. package/templates/template/template/site/pages/home/1-hero.md.hbs +16 -0
  64. package/templates/template/template/site/pages/home/2-features.md +21 -0
  65. package/templates/template/template/site/pages/home/page.yml +2 -0
  66. package/templates/template/template/site/site.yml.hbs +8 -0
  67. package/templates/template/template/site/src/main.jsx +1 -0
  68. package/templates/template/template/site/vite.config.js +3 -0
  69. package/templates/template/template/template.json.hbs +7 -0
  70. package/templates/template/template.json +4 -0
@@ -153,11 +153,17 @@ async function processFile(sourcePath, targetPath, data, options = {}) {
153
153
  * @param {Object} data - Template variables
154
154
  * @param {Object} options - Processing options
155
155
  * @param {string|null} options.variant - Template variant to use
156
+ * @param {string|null} options.basePath - Base template to merge with (files copied first)
156
157
  * @param {Function} options.onWarning - Warning callback
157
158
  * @param {Function} options.onProgress - Progress callback
158
159
  */
159
160
  export async function copyTemplateDirectory(sourcePath, targetPath, data, options = {}) {
160
- const { variant = null, onWarning, onProgress } = options
161
+ const { variant = null, basePath = null, onWarning, onProgress } = options
162
+
163
+ // If a base template is specified, copy it first (without the basePath option to avoid recursion)
164
+ if (basePath && existsSync(basePath)) {
165
+ await copyTemplateDirectory(basePath, targetPath, data, { variant, onWarning, onProgress })
166
+ }
161
167
 
162
168
  await fs.mkdir(targetPath, { recursive: true })
163
169
  const entries = await fs.readdir(sourcePath, { withFileTypes: true })
@@ -173,6 +179,9 @@ export async function copyTemplateDirectory(sourcePath, targetPath, data, option
173
179
  }
174
180
  }
175
181
 
182
+ // Options for recursive calls (without basePath to avoid re-copying base at each level)
183
+ const recursionOptions = { variant, onWarning, onProgress }
184
+
176
185
  for (const entry of entries) {
177
186
  const sourceName = entry.name
178
187
 
@@ -199,7 +208,7 @@ export async function copyTemplateDirectory(sourcePath, targetPath, data, option
199
208
  const sourceFullPath = path.join(sourcePath, sourceName)
200
209
  const targetFullPath = path.join(targetPath, baseName)
201
210
 
202
- await copyTemplateDirectory(sourceFullPath, targetFullPath, data, options)
211
+ await copyTemplateDirectory(sourceFullPath, targetFullPath, data, recursionOptions)
203
212
  } else {
204
213
  // Regular directory - skip if a variant override exists and we're using that variant
205
214
  if (variant && variantBases.has(sourceName)) {
@@ -210,10 +219,15 @@ export async function copyTemplateDirectory(sourcePath, targetPath, data, option
210
219
  const sourceFullPath = path.join(sourcePath, sourceName)
211
220
  const targetFullPath = path.join(targetPath, sourceName)
212
221
 
213
- await copyTemplateDirectory(sourceFullPath, targetFullPath, data, options)
222
+ await copyTemplateDirectory(sourceFullPath, targetFullPath, data, recursionOptions)
214
223
  }
215
224
  } else {
216
225
  // File processing
226
+ // Skip template.json as it's metadata for the template, not for the output
227
+ if (sourceName === 'template.json') {
228
+ continue
229
+ }
230
+
217
231
  // Remove .hbs extension for target filename
218
232
  const targetName = sourceName.endsWith('.hbs')
219
233
  ? sourceName.slice(0, -4)
@@ -2,8 +2,8 @@
2
2
  * Template resolver - parses template identifiers and determines source type
3
3
  */
4
4
 
5
- // Built-in templates that are generated programmatically
6
- export const BUILTIN_TEMPLATES = ['single', 'multi']
5
+ // Built-in templates (file-based in cli/templates/)
6
+ export const BUILTIN_TEMPLATES = ['single', 'multi', 'template']
7
7
 
8
8
  // Official templates from @uniweb/templates package
9
9
  export const OFFICIAL_TEMPLATES = ['marketing', 'docs', 'learning']
@@ -0,0 +1,146 @@
1
+ # CLAUDE.md - AI Assistant Instructions
2
+
3
+ This file provides guidance for AI assistants working with this Uniweb project.
4
+
5
+ ## Project Overview
6
+
7
+ This is a **Uniweb** project - a component web platform that separates content from code.
8
+
9
+ ```
10
+ {{projectName}}/
11
+ ├── foundation/ # React component library (code)
12
+ ├── site/ # Content and pages (markdown)
13
+ ├── package.json # Root workspace config
14
+ └── pnpm-workspace.yaml
15
+ ```
16
+
17
+ ## Quick Commands
18
+
19
+ ```bash
20
+ # Install dependencies
21
+ pnpm install
22
+
23
+ # Start development server (site with foundation)
24
+ pnpm dev
25
+
26
+ # Build foundation (generates dist/foundation.js and schema.json)
27
+ cd foundation && pnpm build
28
+
29
+ # Build site for production (outputs to site/dist/)
30
+ cd site && pnpm build
31
+ ```
32
+
33
+ ## Key Files
34
+
35
+ **Site:**
36
+ - `site/vite.config.js` - 3-line config using `defineSiteConfig()` from `@uniweb/build/site`
37
+ - `site/src/main.jsx` - 1-line entry: `import 'virtual:uniweb-site-entry'`
38
+ - `site/site.yml` - Site configuration (foundation path, title, i18n)
39
+ - `site/pages/` - Content pages (file-based routing)
40
+
41
+ **Foundation:**
42
+ - `foundation/vite.config.js` - 3-line config using `defineFoundationConfig()` from `@uniweb/build`
43
+ - `foundation/src/entry-runtime.js` - Runtime entry point (imports styles + components)
44
+ - `foundation/src/index.js` - Component exports
45
+ - `foundation/src/styles.css` - Tailwind CSS v4 theme
46
+ - `foundation/src/components/*/meta.js` - Component metadata and schema
47
+
48
+ ## Architecture
49
+
50
+ ### Foundation Package (`/foundation`)
51
+
52
+ The **foundation** is a React component library. Each component:
53
+
54
+ 1. Receives structured content parsed from markdown
55
+ 2. Has configurable parameters (theme, layout, etc.)
56
+ 3. Renders the content according to its design
57
+
58
+ **Key directories:**
59
+ - `src/components/*/` - Component implementations
60
+ - `src/components/*/meta.js` - Component metadata and schema
61
+ - `src/styles.css` - Global Tailwind styles
62
+
63
+ ### Site Package (`/site`)
64
+
65
+ The **site** contains content written in markdown. The runtime loads the foundation and renders content based on component selections.
66
+
67
+ **Key directories:**
68
+ - `pages/` - Content pages organized in folders
69
+ - `pages/[page-name]/page.yml` - Page metadata
70
+ - `pages/[page-name]/*.md` - Content sections
71
+
72
+ ## Content Authoring
73
+
74
+ ### Section File Format
75
+
76
+ ```markdown
77
+ ---
78
+ type: ComponentName
79
+ theme: dark
80
+ layout: center
81
+ ---
82
+
83
+ # Main Headline
84
+
85
+ Description paragraph.
86
+
87
+ [Call to Action](#link)
88
+ ```
89
+
90
+ ### Content Structure
91
+
92
+ The semantic parser extracts content into:
93
+
94
+ - **`content.main.header`**: title, pretitle, subtitle
95
+ - **`content.main.body`**: paragraphs, links, imgs, lists
96
+ - **`content.items`**: Content groups from H3 headings
97
+
98
+ ## Component Development
99
+
100
+ ### Component Interface
101
+
102
+ ```jsx
103
+ function MyComponent({ content, params, block, website }) {
104
+ const { title } = content.main?.header || {}
105
+ const { paragraphs = [] } = content.main?.body || {}
106
+ // ...
107
+ }
108
+ ```
109
+
110
+ ### Using @uniweb/kit
111
+
112
+ ```jsx
113
+ import { H1, P, Link, cn } from '@uniweb/kit'
114
+ ```
115
+
116
+ ### Component Metadata (`meta.js`)
117
+
118
+ ```javascript
119
+ export default {
120
+ title: 'Component Name',
121
+ description: 'What the component does',
122
+ category: 'Content',
123
+ elements: { /* content elements */ },
124
+ properties: { /* configurable params */ },
125
+ }
126
+ ```
127
+
128
+ ## Tailwind CSS v4
129
+
130
+ This project uses Tailwind CSS v4 with the Vite plugin.
131
+
132
+ **Theme customization** (`foundation/src/styles.css`):
133
+
134
+ ```css
135
+ @import "tailwindcss";
136
+ @source "./components/**/*.{js,jsx}";
137
+ @theme {
138
+ --color-primary: #3b82f6;
139
+ }
140
+ ```
141
+
142
+ ## Resources
143
+
144
+ - [Uniweb Documentation](https://github.com/uniweb/uniweb)
145
+ - [@uniweb/kit Documentation](https://www.npmjs.com/package/@uniweb/kit)
146
+ - [Tailwind CSS v4](https://tailwindcss.com/docs)
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "{{projectName}}",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "pnpm --filter site dev",
8
+ "build": "pnpm --filter foundation build && pnpm --filter site build",
9
+ "preview": "pnpm --filter site preview"
10
+ },
11
+ "devDependencies": {
12
+ "@types/node": "^22.0.0"
13
+ },
14
+ "workspaces": [
15
+ "site",
16
+ "foundation",
17
+ "sites/*",
18
+ "foundations/*"
19
+ ],
20
+ "pnpm": {
21
+ "onlyBuiltDependencies": ["esbuild", "sharp"]
22
+ }
23
+ }
@@ -0,0 +1,5 @@
1
+ packages:
2
+ - foundation
3
+ - site
4
+ - foundations/*
5
+ - sites/*
@@ -0,0 +1,100 @@
1
+ # CLAUDE.md - AI Assistant Instructions
2
+
3
+ This file provides guidance for AI assistants working with this Uniweb multi-site workspace.
4
+
5
+ ## Project Overview
6
+
7
+ This is a **Uniweb multi-site workspace** - supporting multiple sites and foundations.
8
+
9
+ ```
10
+ {{projectName}}/
11
+ ├── foundations/ # Shared component libraries
12
+ │ └── default/ # Default foundation
13
+ ├── sites/ # Content sites
14
+ │ └── main/ # Main site
15
+ ├── package.json # Root workspace config
16
+ └── pnpm-workspace.yaml
17
+ ```
18
+
19
+ ## Quick Commands
20
+
21
+ ```bash
22
+ # Install dependencies
23
+ pnpm install
24
+
25
+ # Start main site development
26
+ pnpm dev
27
+
28
+ # Start all sites in parallel
29
+ pnpm dev:all
30
+
31
+ # Build main site
32
+ pnpm build
33
+
34
+ # Build all sites
35
+ pnpm build:all
36
+ ```
37
+
38
+ ## Adding New Sites
39
+
40
+ 1. Copy an existing site directory:
41
+ ```bash
42
+ cp -r sites/main sites/newsite
43
+ ```
44
+
45
+ 2. Update `sites/newsite/package.json` with a unique name
46
+
47
+ 3. Update `sites/newsite/site.yml` with site configuration
48
+
49
+ 4. Run `pnpm install` to link the new site
50
+
51
+ ## Adding New Foundations
52
+
53
+ 1. Copy an existing foundation:
54
+ ```bash
55
+ cp -r foundations/default foundations/newfoundation
56
+ ```
57
+
58
+ 2. Update `foundations/newfoundation/package.json` with a unique name
59
+
60
+ 3. In your site's `site.yml`, reference the foundation:
61
+ ```yaml
62
+ foundation: newfoundation
63
+ ```
64
+
65
+ 4. In your site's `package.json`, add the dependency:
66
+ ```json
67
+ "dependencies": {
68
+ "newfoundation": "file:../../foundations/newfoundation"
69
+ }
70
+ ```
71
+
72
+ ## Key Files
73
+
74
+ **Sites:**
75
+ - `sites/*/vite.config.js` - 3-line config using `defineSiteConfig()` from `@uniweb/build/site`
76
+ - `sites/*/src/main.jsx` - 1-line entry: `import 'virtual:uniweb-site-entry'`
77
+ - `sites/*/site.yml` - Site configuration (foundation reference, title, i18n)
78
+ - `sites/*/pages/` - Content pages (file-based routing)
79
+
80
+ **Foundations:**
81
+ - `foundations/*/vite.config.js` - 3-line config using `defineFoundationConfig()` from `@uniweb/build`
82
+ - `foundations/*/src/entry-runtime.js` - Runtime entry point
83
+ - `foundations/*/src/styles.css` - Tailwind CSS v4 theme
84
+ - `foundations/*/src/components/*/meta.js` - Component metadata
85
+
86
+ ## Architecture
87
+
88
+ ### Foundations (`/foundations/*`)
89
+
90
+ Each foundation is a React component library. Sites can share foundations or have their own.
91
+
92
+ ### Sites (`/sites/*`)
93
+
94
+ Each site contains content in markdown. A site references one foundation for its components.
95
+
96
+ ## Resources
97
+
98
+ - [Uniweb Documentation](https://github.com/uniweb/uniweb)
99
+ - [@uniweb/kit Documentation](https://www.npmjs.com/package/@uniweb/kit)
100
+ - [Tailwind CSS v4](https://tailwindcss.com/docs)
@@ -0,0 +1,96 @@
1
+ # {{projectName}}
2
+
3
+ A multi-site workspace built with [Uniweb](https://github.com/uniweb/uniweb) — a component web platform that separates content from code.
4
+
5
+ ## Quick Start
6
+
7
+ ```bash
8
+ pnpm install # Install dependencies
9
+ pnpm dev # Start main site development
10
+ ```
11
+
12
+ Visit `http://localhost:5173` to see your site.
13
+
14
+ ## Project Structure
15
+
16
+ ```
17
+ {{projectName}}/
18
+ ├── foundations/ # Shared component libraries
19
+ │ └── default/ # Default foundation
20
+ │ ├── src/
21
+ │ │ ├── components/
22
+ │ │ └── styles.css
23
+ │ └── vite.config.js
24
+
25
+ ├── sites/ # Content sites
26
+ │ └── main/ # Main site
27
+ │ ├── pages/
28
+ │ ├── site.yml
29
+ │ ├── src/main.jsx
30
+ │ └── vite.config.js
31
+
32
+ ├── CLAUDE.md # AI assistant instructions
33
+ └── README.md # This file
34
+ ```
35
+
36
+ ## Commands
37
+
38
+ ```bash
39
+ pnpm dev # Start main site
40
+ pnpm dev:all # Start all sites in parallel
41
+ pnpm build # Build main site
42
+ pnpm build:all # Build all sites
43
+ ```
44
+
45
+ ## Adding a New Site
46
+
47
+ 1. Copy an existing site:
48
+ ```bash
49
+ cp -r sites/main sites/newsite
50
+ ```
51
+
52
+ 2. Update `sites/newsite/package.json` with a unique name
53
+
54
+ 3. Update `sites/newsite/site.yml` with site configuration
55
+
56
+ 4. Run `pnpm install` to link the new site
57
+
58
+ ## Adding a New Foundation
59
+
60
+ 1. Copy an existing foundation:
61
+ ```bash
62
+ cp -r foundations/default foundations/newfoundation
63
+ ```
64
+
65
+ 2. Update the package.json with a unique name
66
+
67
+ 3. In your site's `site.yml`, reference the foundation:
68
+ ```yaml
69
+ foundation: newfoundation
70
+ ```
71
+
72
+ 4. In your site's `package.json`, add the dependency:
73
+ ```json
74
+ "dependencies": {
75
+ "newfoundation": "file:../../foundations/newfoundation"
76
+ }
77
+ ```
78
+
79
+ ## Sharing Foundations
80
+
81
+ Multiple sites can use the same foundation. Each site references the foundation in its `site.yml` and `package.json`.
82
+
83
+ This allows:
84
+ - Consistent components across sites
85
+ - Single source of truth for design
86
+ - Foundation updates propagate to all sites
87
+
88
+ ## AI Assistance
89
+
90
+ See [CLAUDE.md](./CLAUDE.md) for detailed instructions that AI assistants can use.
91
+
92
+ ## Learn More
93
+
94
+ - [Uniweb Documentation](https://github.com/uniweb/uniweb)
95
+ - [@uniweb/kit Components](https://www.npmjs.com/package/@uniweb/kit)
96
+ - [Tailwind CSS v4](https://tailwindcss.com)
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "default",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "main": "./src/index.js",
6
+ "exports": {
7
+ ".": "./src/index.js",
8
+ "./styles": "./src/styles.css",
9
+ "./dist": "./dist/foundation.js",
10
+ "./dist/styles": "./dist/assets/style.css"
11
+ },
12
+ "files": ["dist", "src"],
13
+ "scripts": {
14
+ "dev": "vite",
15
+ "build": "uniweb build",
16
+ "build:vite": "vite build",
17
+ "preview": "vite preview"
18
+ },
19
+ "peerDependencies": {
20
+ "react": "^18.0.0 || ^19.0.0",
21
+ "react-dom": "^18.0.0 || ^19.0.0"
22
+ },
23
+ "dependencies": {
24
+ "@uniweb/core": "{{version "@uniweb/core"}}",
25
+ "@uniweb/kit": "{{version "@uniweb/kit"}}"
26
+ },
27
+ "devDependencies": {
28
+ "@tailwindcss/vite": "^4.0.0",
29
+ "@vitejs/plugin-react": "^5.0.0",
30
+ "react": "^18.2.0",
31
+ "react-dom": "^18.2.0",
32
+ "tailwindcss": "^4.0.0",
33
+ "uniweb": "{{version "uniweb"}}",
34
+ "vite": "^7.0.0",
35
+ "vite-plugin-svgr": "^4.2.0"
36
+ }
37
+ }
@@ -0,0 +1,121 @@
1
+ import React from 'react'
2
+ import { H1, H2, P, Link, cn } from '@uniweb/kit'
3
+
4
+ /**
5
+ * Section Component
6
+ *
7
+ * A versatile content section that handles headings, text, and links.
8
+ * This is the default component for rendering markdown content.
9
+ */
10
+ export function Section({ content, params }) {
11
+ const { title, pretitle, subtitle } = content.main?.header || {}
12
+ const { paragraphs = [], links = [], imgs = [] } = content.main?.body || {}
13
+
14
+ const {
15
+ theme = 'light',
16
+ align = 'center',
17
+ width = 'default',
18
+ } = params || {}
19
+
20
+ // Theme styles
21
+ const themes = {
22
+ light: 'bg-white text-gray-900',
23
+ dark: 'bg-gray-900 text-white',
24
+ primary: 'bg-primary text-white',
25
+ }
26
+
27
+ // Alignment styles
28
+ const alignments = {
29
+ left: 'text-left',
30
+ center: 'text-center',
31
+ right: 'text-right',
32
+ }
33
+
34
+ // Width styles
35
+ const widths = {
36
+ narrow: 'max-w-2xl',
37
+ default: 'max-w-4xl',
38
+ wide: 'max-w-6xl',
39
+ full: 'max-w-none',
40
+ }
41
+
42
+ return (
43
+ <section className={cn('py-16 px-6', themes[theme])}>
44
+ <div className={cn('mx-auto', widths[width], alignments[align])}>
45
+ {/* Pretitle / Eyebrow */}
46
+ {pretitle && (
47
+ <p className="text-sm font-medium text-primary mb-4 uppercase tracking-wide">
48
+ {pretitle}
49
+ </p>
50
+ )}
51
+
52
+ {/* Title */}
53
+ {title && (
54
+ <H1
55
+ text={title}
56
+ className="text-3xl sm:text-4xl font-bold mb-4"
57
+ />
58
+ )}
59
+
60
+ {/* Subtitle */}
61
+ {subtitle && (
62
+ <H2
63
+ text={subtitle}
64
+ className={cn(
65
+ 'text-xl mb-6',
66
+ theme === 'light' ? 'text-gray-600' : 'text-gray-300'
67
+ )}
68
+ />
69
+ )}
70
+
71
+ {/* Paragraphs */}
72
+ {paragraphs.map((para, index) => (
73
+ <P
74
+ key={index}
75
+ text={para}
76
+ className={cn(
77
+ 'text-lg mb-4 leading-relaxed',
78
+ theme === 'light' ? 'text-gray-700' : 'text-gray-300'
79
+ )}
80
+ />
81
+ ))}
82
+
83
+ {/* Links */}
84
+ {links.length > 0 && (
85
+ <div className={cn('mt-8 flex gap-4 flex-wrap', alignments[align] === 'text-center' && 'justify-center')}>
86
+ {links.map((link, index) => (
87
+ <Link
88
+ key={index}
89
+ href={link.href}
90
+ className={cn(
91
+ 'inline-flex items-center px-6 py-3 font-medium rounded-lg transition-colors',
92
+ index === 0
93
+ ? 'bg-primary text-white hover:bg-primary-dark'
94
+ : 'border border-current hover:bg-gray-100'
95
+ )}
96
+ >
97
+ {link.label}
98
+ </Link>
99
+ ))}
100
+ </div>
101
+ )}
102
+
103
+ {/* Images */}
104
+ {imgs.length > 0 && (
105
+ <div className="mt-8">
106
+ {imgs.map((img, index) => (
107
+ <img
108
+ key={index}
109
+ src={img.url || img.src}
110
+ alt={img.alt || ''}
111
+ className="rounded-lg shadow-lg mx-auto"
112
+ />
113
+ ))}
114
+ </div>
115
+ )}
116
+ </div>
117
+ </section>
118
+ )
119
+ }
120
+
121
+ export default Section
@@ -0,0 +1,66 @@
1
+ export default {
2
+ title: 'Section',
3
+ description: 'A versatile content section for headings, text, and links',
4
+ category: 'Content',
5
+
6
+ elements: {
7
+ pretitle: {
8
+ label: 'Eyebrow',
9
+ description: 'Small text above the title (H3 before H1)',
10
+ },
11
+ title: {
12
+ label: 'Title',
13
+ description: 'Main heading (H1)',
14
+ },
15
+ subtitle: {
16
+ label: 'Subtitle',
17
+ description: 'Secondary heading (H2 after H1)',
18
+ },
19
+ paragraphs: {
20
+ label: 'Content',
21
+ description: 'Body text paragraphs',
22
+ },
23
+ links: {
24
+ label: 'Links',
25
+ description: 'Call-to-action buttons',
26
+ },
27
+ imgs: {
28
+ label: 'Images',
29
+ description: 'Section images',
30
+ },
31
+ },
32
+
33
+ properties: {
34
+ theme: {
35
+ type: 'select',
36
+ label: 'Theme',
37
+ options: [
38
+ { value: 'light', label: 'Light' },
39
+ { value: 'dark', label: 'Dark' },
40
+ { value: 'primary', label: 'Primary' },
41
+ ],
42
+ default: 'light',
43
+ },
44
+ align: {
45
+ type: 'select',
46
+ label: 'Alignment',
47
+ options: [
48
+ { value: 'left', label: 'Left' },
49
+ { value: 'center', label: 'Center' },
50
+ { value: 'right', label: 'Right' },
51
+ ],
52
+ default: 'center',
53
+ },
54
+ width: {
55
+ type: 'select',
56
+ label: 'Width',
57
+ options: [
58
+ { value: 'narrow', label: 'Narrow' },
59
+ { value: 'default', label: 'Default' },
60
+ { value: 'wide', label: 'Wide' },
61
+ { value: 'full', label: 'Full Width' },
62
+ ],
63
+ default: 'default',
64
+ },
65
+ },
66
+ }
@@ -0,0 +1,3 @@
1
+ import './styles.css'
2
+ export * from './index.js'
3
+ export { default } from './index.js'