@booga/vblocks 0.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/CHANGELOG.md +18 -0
- package/LICENSE +21 -0
- package/README.md +83 -0
- package/dist/blog/index.cjs +148 -0
- package/dist/blog/index.cjs.map +1 -0
- package/dist/blog/index.d.cts +140 -0
- package/dist/blog/index.d.ts +140 -0
- package/dist/blog/index.js +141 -0
- package/dist/blog/index.js.map +1 -0
- package/dist/business/index.cjs +121 -0
- package/dist/business/index.cjs.map +1 -0
- package/dist/business/index.d.cts +102 -0
- package/dist/business/index.d.ts +102 -0
- package/dist/business/index.js +114 -0
- package/dist/business/index.js.map +1 -0
- package/dist/cta/index.cjs +99 -0
- package/dist/cta/index.cjs.map +1 -0
- package/dist/cta/index.d.cts +110 -0
- package/dist/cta/index.d.ts +110 -0
- package/dist/cta/index.js +92 -0
- package/dist/cta/index.js.map +1 -0
- package/dist/faq/index.cjs +93 -0
- package/dist/faq/index.cjs.map +1 -0
- package/dist/faq/index.d.cts +71 -0
- package/dist/faq/index.d.ts +71 -0
- package/dist/faq/index.js +86 -0
- package/dist/faq/index.js.map +1 -0
- package/dist/features/index.cjs +104 -0
- package/dist/features/index.cjs.map +1 -0
- package/dist/features/index.d.cts +81 -0
- package/dist/features/index.d.ts +81 -0
- package/dist/features/index.js +97 -0
- package/dist/features/index.js.map +1 -0
- package/dist/footer/index.cjs +117 -0
- package/dist/footer/index.cjs.map +1 -0
- package/dist/footer/index.d.cts +107 -0
- package/dist/footer/index.d.ts +107 -0
- package/dist/footer/index.js +110 -0
- package/dist/footer/index.js.map +1 -0
- package/dist/gallery/index.cjs +106 -0
- package/dist/gallery/index.cjs.map +1 -0
- package/dist/gallery/index.d.cts +78 -0
- package/dist/gallery/index.d.ts +78 -0
- package/dist/gallery/index.js +99 -0
- package/dist/gallery/index.js.map +1 -0
- package/dist/hero/index.cjs +108 -0
- package/dist/hero/index.cjs.map +1 -0
- package/dist/hero/index.d.cts +134 -0
- package/dist/hero/index.d.ts +134 -0
- package/dist/hero/index.js +101 -0
- package/dist/hero/index.js.map +1 -0
- package/dist/index.cjs +1079 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +22 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.js +1005 -0
- package/dist/index.js.map +1 -0
- package/dist/portfolio/index.cjs +122 -0
- package/dist/portfolio/index.cjs.map +1 -0
- package/dist/portfolio/index.d.cts +120 -0
- package/dist/portfolio/index.d.ts +120 -0
- package/dist/portfolio/index.js +115 -0
- package/dist/portfolio/index.js.map +1 -0
- package/dist/post/index.cjs +116 -0
- package/dist/post/index.cjs.map +1 -0
- package/dist/post/index.d.cts +74 -0
- package/dist/post/index.d.ts +74 -0
- package/dist/post/index.js +109 -0
- package/dist/post/index.js.map +1 -0
- package/dist/team/index.cjs +120 -0
- package/dist/team/index.cjs.map +1 -0
- package/dist/team/index.d.cts +128 -0
- package/dist/team/index.d.ts +128 -0
- package/dist/team/index.js +113 -0
- package/dist/team/index.js.map +1 -0
- package/dist/testimonial/index.cjs +130 -0
- package/dist/testimonial/index.cjs.map +1 -0
- package/dist/testimonial/index.d.cts +113 -0
- package/dist/testimonial/index.d.ts +113 -0
- package/dist/testimonial/index.js +123 -0
- package/dist/testimonial/index.js.map +1 -0
- package/dist/types-n6w6cZmP.d.cts +16 -0
- package/dist/types-n6w6cZmP.d.ts +16 -0
- package/package.json +126 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [0.1.0] - 2026-05-12
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- 24 blocks across 12 categories: hero, CTA, FAQ, footer, gallery, portfolio, post, team, testimonial, blog, business, features
|
|
13
|
+
- Per-block Zod content schemas with strict validation and exported TypeScript types
|
|
14
|
+
- Per-block default content using neutral placeholder copy
|
|
15
|
+
- Flat registry (`src/registry.ts`) mapping block IDs to `{ schema, default, component }`
|
|
16
|
+
- Per-category tree-shakable entry points (`@booga/vblocks/hero`, etc.)
|
|
17
|
+
- `ThemeOverride` prop wired to CSS custom properties per block
|
|
18
|
+
- Full accessibility: semantic HTML, ARIA landmarks, proper heading hierarchy
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 bvasilenko
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# vBlocks
|
|
2
|
+
|
|
3
|
+
Composed section blocks: hero, CTA, FAQ, footer, gallery, portfolio, post, team, testimonial, blog, business, features. Schema-validated content, vUi primitives, DSL-styled. Drop into a page — no manual wiring.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
npm install @booga/vblocks
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```tsx
|
|
14
|
+
import { HeroSplit, HeroSplitDefaultContent } from "@booga/vblocks/hero";
|
|
15
|
+
|
|
16
|
+
<HeroSplit content={HeroSplitDefaultContent} />
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Or with typed content:
|
|
20
|
+
|
|
21
|
+
```tsx
|
|
22
|
+
import { HeroSplit, type HeroSplitContent } from "@booga/vblocks/hero";
|
|
23
|
+
|
|
24
|
+
const content: HeroSplitContent = {
|
|
25
|
+
heading: "Ship faster.",
|
|
26
|
+
description: "Composable blocks with schema-validated content.",
|
|
27
|
+
primaryCta: { label: "Get started", href: "/start" },
|
|
28
|
+
image: { src: "/hero.png", alt: "Product screenshot" },
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
<HeroSplit content={content} />
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Blocks
|
|
35
|
+
|
|
36
|
+
| Category | Variants |
|
|
37
|
+
|---|---|
|
|
38
|
+
| `hero` | `HeroSplit`, `HeroCentered` |
|
|
39
|
+
| `cta` | `CtaSplit`, `CtaCentered` |
|
|
40
|
+
| `faq` | `FaqSplit`, `FaqGrid` |
|
|
41
|
+
| `footer` | `FooterSplit`, `FooterGrid` |
|
|
42
|
+
| `gallery` | `GallerySplit`, `GalleryGrid` |
|
|
43
|
+
| `portfolio` | `PortfolioSplit`, `PortfolioGrid` |
|
|
44
|
+
| `post` | `PostSplit`, `PostCentered` |
|
|
45
|
+
| `team` | `TeamSplit`, `TeamGrid` |
|
|
46
|
+
| `testimonial` | `TestimonialSplit`, `TestimonialGrid` |
|
|
47
|
+
| `blog` | `BlogSplit`, `BlogGrid` |
|
|
48
|
+
| `business` | `BusinessSplit`, `BusinessGrid` |
|
|
49
|
+
| `features` | `FeaturesSplit`, `FeaturesGrid` |
|
|
50
|
+
|
|
51
|
+
Each block exports:
|
|
52
|
+
|
|
53
|
+
- `<Variant>` — component
|
|
54
|
+
- `<Variant>ContentSchema` — Zod schema
|
|
55
|
+
- `<Variant>Content` — TypeScript type
|
|
56
|
+
- `<Variant>DefaultContent` — sample content for previews
|
|
57
|
+
|
|
58
|
+
## Theme overrides
|
|
59
|
+
|
|
60
|
+
Pass a `ThemeOverride` to remap CSS custom properties per block:
|
|
61
|
+
|
|
62
|
+
```tsx
|
|
63
|
+
<HeroSplit content={content} theme={{ "color-accent": "#6366f1" }} />
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Keys are mapped to `--v-<key>` on the block's root element.
|
|
67
|
+
|
|
68
|
+
## Registry
|
|
69
|
+
|
|
70
|
+
A flat registry for `vRegistry` consumption:
|
|
71
|
+
|
|
72
|
+
```ts
|
|
73
|
+
import { registry } from "@booga/vblocks";
|
|
74
|
+
// registry["hero/split"] → { schema, default, component }
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Code of conduct
|
|
78
|
+
|
|
79
|
+
[Contributor Covenant 2.1](https://www.contributor-covenant.org/version/2/1/code_of_conduct/)
|
|
80
|
+
|
|
81
|
+
## License
|
|
82
|
+
|
|
83
|
+
MIT © 2026 bvasilenko
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var vui = require('@booga/vui');
|
|
4
|
+
var vdsl = require('@booga/vdsl');
|
|
5
|
+
var zod = require('zod');
|
|
6
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
7
|
+
|
|
8
|
+
// src/blog/BlogSplit/index.tsx
|
|
9
|
+
var DBox = vdsl.dsl(vui.Box);
|
|
10
|
+
var DStack = vdsl.dsl(vui.Stack);
|
|
11
|
+
var DGrid = vdsl.dsl(vui.Grid);
|
|
12
|
+
vdsl.dsl(vui.Inline);
|
|
13
|
+
|
|
14
|
+
// src/theme.ts
|
|
15
|
+
function themeStyle(theme) {
|
|
16
|
+
if (!theme) return void 0;
|
|
17
|
+
return Object.fromEntries(
|
|
18
|
+
Object.entries(theme).map(([k, v]) => [`--v-${k}`, v])
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
zod.z.object({
|
|
22
|
+
label: zod.z.string(),
|
|
23
|
+
href: zod.z.string()
|
|
24
|
+
}).strict();
|
|
25
|
+
var ImageSchema = zod.z.object({
|
|
26
|
+
src: zod.z.string(),
|
|
27
|
+
alt: zod.z.string()
|
|
28
|
+
}).strict();
|
|
29
|
+
|
|
30
|
+
// src/blog/BlogSplit/schema.ts
|
|
31
|
+
var BlogPostSchema = zod.z.object({
|
|
32
|
+
title: zod.z.string(),
|
|
33
|
+
excerpt: zod.z.string(),
|
|
34
|
+
date: zod.z.string(),
|
|
35
|
+
category: zod.z.string().optional(),
|
|
36
|
+
image: ImageSchema
|
|
37
|
+
}).strict();
|
|
38
|
+
var BlogSplitContentSchema = zod.z.object({
|
|
39
|
+
heading: zod.z.string(),
|
|
40
|
+
posts: zod.z.array(BlogPostSchema).min(1)
|
|
41
|
+
}).strict();
|
|
42
|
+
function BlogSplit({ content, theme }) {
|
|
43
|
+
BlogSplitContentSchema.parse(content);
|
|
44
|
+
const { heading, posts } = content;
|
|
45
|
+
const [featured, ...rest] = posts;
|
|
46
|
+
return /* @__PURE__ */ jsxRuntime.jsx(DBox, { as: "section", "aria-label": heading, style: themeStyle(theme), children: /* @__PURE__ */ jsxRuntime.jsxs(DStack, { px: 6, py: 16, className: vui.cn("max-w-6xl mx-auto gap-10"), children: [
|
|
47
|
+
/* @__PURE__ */ jsxRuntime.jsx(DBox, { as: "h2", className: vui.cn("text-3xl font-bold tracking-tight"), children: heading }),
|
|
48
|
+
/* @__PURE__ */ jsxRuntime.jsxs(DGrid, { columns: 2, gap: 8, align: "start", children: [
|
|
49
|
+
featured && /* @__PURE__ */ jsxRuntime.jsx(DBox, { as: "article", children: /* @__PURE__ */ jsxRuntime.jsxs(DStack, { gap: 4, children: [
|
|
50
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
51
|
+
DBox,
|
|
52
|
+
{
|
|
53
|
+
as: "img",
|
|
54
|
+
src: featured.image.src,
|
|
55
|
+
alt: featured.image.alt,
|
|
56
|
+
className: vui.cn("w-full rounded-lg object-cover aspect-video")
|
|
57
|
+
}
|
|
58
|
+
),
|
|
59
|
+
/* @__PURE__ */ jsxRuntime.jsxs(DStack, { gap: 2, children: [
|
|
60
|
+
featured.category && /* @__PURE__ */ jsxRuntime.jsx(vui.Badge, { variant: "secondary", children: featured.category }),
|
|
61
|
+
/* @__PURE__ */ jsxRuntime.jsx(DBox, { as: "h3", className: vui.cn("text-xl font-semibold"), children: featured.title }),
|
|
62
|
+
/* @__PURE__ */ jsxRuntime.jsx(DBox, { as: "p", color: "muted", children: featured.excerpt }),
|
|
63
|
+
/* @__PURE__ */ jsxRuntime.jsx(DBox, { as: "time", dateTime: featured.date, color: "muted", className: vui.cn("text-xs"), children: featured.date })
|
|
64
|
+
] })
|
|
65
|
+
] }) }),
|
|
66
|
+
/* @__PURE__ */ jsxRuntime.jsx(DBox, { as: "ul", m: 0, p: 0, gap: 6, display: "flex", className: vui.cn("list-none flex-col"), children: rest.map((post, i) => /* @__PURE__ */ jsxRuntime.jsx(DBox, { as: "li", children: /* @__PURE__ */ jsxRuntime.jsx(DBox, { as: "article", children: /* @__PURE__ */ jsxRuntime.jsxs(DGrid, { columns: 2, gap: 4, align: "start", children: [
|
|
67
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
68
|
+
DBox,
|
|
69
|
+
{
|
|
70
|
+
as: "img",
|
|
71
|
+
src: post.image.src,
|
|
72
|
+
alt: post.image.alt,
|
|
73
|
+
className: vui.cn("w-full rounded-md object-cover aspect-video")
|
|
74
|
+
}
|
|
75
|
+
),
|
|
76
|
+
/* @__PURE__ */ jsxRuntime.jsxs(DStack, { gap: 1, children: [
|
|
77
|
+
post.category && /* @__PURE__ */ jsxRuntime.jsx(vui.Badge, { variant: "secondary", children: post.category }),
|
|
78
|
+
/* @__PURE__ */ jsxRuntime.jsx(DBox, { as: "h3", className: vui.cn("font-semibold leading-snug"), children: post.title }),
|
|
79
|
+
/* @__PURE__ */ jsxRuntime.jsx(DBox, { as: "time", dateTime: post.date, color: "muted", className: vui.cn("text-xs"), children: post.date })
|
|
80
|
+
] })
|
|
81
|
+
] }) }) }, i)) })
|
|
82
|
+
] })
|
|
83
|
+
] }) });
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// src/blog/BlogSplit/default.ts
|
|
87
|
+
var BlogSplitDefaultContent = {
|
|
88
|
+
heading: "Latest posts",
|
|
89
|
+
posts: [
|
|
90
|
+
{ title: "Designing for composability", excerpt: "How modular thinking unlocks maintainable systems at scale.", date: "2026-05-01", category: "Design", image: { src: "https://placehold.co/600x400", alt: "Design systems post" } },
|
|
91
|
+
{ title: "Type-safe content at runtime", excerpt: "Zod schemas as the single source of truth for block content.", date: "2026-04-18", image: { src: "https://placehold.co/400x280", alt: "Type safety post" } },
|
|
92
|
+
{ title: "Tree-shaking section blocks", excerpt: "Per-category entry points and how they keep bundles lean.", date: "2026-04-05", category: "Engineering", image: { src: "https://placehold.co/400x280", alt: "Tree-shaking post" } }
|
|
93
|
+
]
|
|
94
|
+
};
|
|
95
|
+
var BlogPostSchema2 = zod.z.object({
|
|
96
|
+
title: zod.z.string(),
|
|
97
|
+
excerpt: zod.z.string(),
|
|
98
|
+
date: zod.z.string(),
|
|
99
|
+
category: zod.z.string().optional(),
|
|
100
|
+
image: ImageSchema
|
|
101
|
+
}).strict();
|
|
102
|
+
var BlogGridContentSchema = zod.z.object({
|
|
103
|
+
heading: zod.z.string(),
|
|
104
|
+
posts: zod.z.array(BlogPostSchema2).min(1)
|
|
105
|
+
}).strict();
|
|
106
|
+
function BlogGrid({ content, theme }) {
|
|
107
|
+
BlogGridContentSchema.parse(content);
|
|
108
|
+
const { heading, posts } = content;
|
|
109
|
+
return /* @__PURE__ */ jsxRuntime.jsx(DBox, { as: "section", "aria-label": heading, style: themeStyle(theme), children: /* @__PURE__ */ jsxRuntime.jsxs(DStack, { px: 6, py: 16, className: vui.cn("max-w-6xl mx-auto gap-10"), children: [
|
|
110
|
+
/* @__PURE__ */ jsxRuntime.jsx(DBox, { as: "h2", className: vui.cn("text-3xl font-bold tracking-tight"), children: heading }),
|
|
111
|
+
/* @__PURE__ */ jsxRuntime.jsx(DGrid, { columns: 3, gap: 6, children: posts.map((post, i) => /* @__PURE__ */ jsxRuntime.jsx(vui.Card, { children: /* @__PURE__ */ jsxRuntime.jsxs(DBox, { as: "article", children: [
|
|
112
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
113
|
+
DBox,
|
|
114
|
+
{
|
|
115
|
+
as: "img",
|
|
116
|
+
src: post.image.src,
|
|
117
|
+
alt: post.image.alt,
|
|
118
|
+
className: vui.cn("w-full rounded-t-lg object-cover aspect-video")
|
|
119
|
+
}
|
|
120
|
+
),
|
|
121
|
+
/* @__PURE__ */ jsxRuntime.jsx(vui.CardContent, { children: /* @__PURE__ */ jsxRuntime.jsxs(DStack, { gap: 2, pt: 2, children: [
|
|
122
|
+
post.category && /* @__PURE__ */ jsxRuntime.jsx(vui.Badge, { variant: "secondary", children: post.category }),
|
|
123
|
+
/* @__PURE__ */ jsxRuntime.jsx(DBox, { as: "h3", className: vui.cn("font-semibold leading-snug"), children: post.title }),
|
|
124
|
+
/* @__PURE__ */ jsxRuntime.jsx(DBox, { as: "p", color: "muted", className: vui.cn("text-sm"), children: post.excerpt }),
|
|
125
|
+
/* @__PURE__ */ jsxRuntime.jsx(DBox, { as: "time", dateTime: post.date, color: "muted", className: vui.cn("text-xs"), children: post.date })
|
|
126
|
+
] }) })
|
|
127
|
+
] }) }, i)) })
|
|
128
|
+
] }) });
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// src/blog/BlogGrid/default.ts
|
|
132
|
+
var BlogGridDefaultContent = {
|
|
133
|
+
heading: "From the blog",
|
|
134
|
+
posts: [
|
|
135
|
+
{ title: "Designing for composability", excerpt: "Modular thinking at scale.", date: "2026-05-01", category: "Design", image: { src: "https://placehold.co/480x320", alt: "Design post" } },
|
|
136
|
+
{ title: "Type-safe content at runtime", excerpt: "Zod as single source of truth.", date: "2026-04-18", image: { src: "https://placehold.co/480x320", alt: "Types post" } },
|
|
137
|
+
{ title: "Tree-shaking section blocks", excerpt: "Lean bundles, per-category entry points.", date: "2026-04-05", category: "Engineering", image: { src: "https://placehold.co/480x320", alt: "Bundling post" } }
|
|
138
|
+
]
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
exports.BlogGrid = BlogGrid;
|
|
142
|
+
exports.BlogGridContentSchema = BlogGridContentSchema;
|
|
143
|
+
exports.BlogGridDefaultContent = BlogGridDefaultContent;
|
|
144
|
+
exports.BlogSplit = BlogSplit;
|
|
145
|
+
exports.BlogSplitContentSchema = BlogSplitContentSchema;
|
|
146
|
+
exports.BlogSplitDefaultContent = BlogSplitDefaultContent;
|
|
147
|
+
//# sourceMappingURL=index.cjs.map
|
|
148
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/primitives.ts","../../src/theme.ts","../../src/shared/schemas.ts","../../src/blog/BlogSplit/schema.ts","../../src/blog/BlogSplit/index.tsx","../../src/blog/BlogSplit/default.ts","../../src/blog/BlogGrid/schema.ts","../../src/blog/BlogGrid/index.tsx","../../src/blog/BlogGrid/default.ts"],"names":["dsl","Box","Stack","Grid","Inline","z","jsxs","cn","jsx","Badge","BlogPostSchema","Card","CardContent"],"mappings":"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","file":"index.cjs","sourcesContent":["// SPDX-License-Identifier: MIT\n// Copyright (c) 2026 bvasilenko\nimport { type ElementType } from \"react\";\nimport { dsl } from \"@booga/vdsl\";\nimport { Box, Stack, Grid, Inline } from \"@booga/vui\";\n\n// PolymorphicComponent is not structurally assignable to ElementType; dsl() uses\n// createElement() at runtime which accepts any callable, so the bridge is safe.\nexport const DBox = dsl(Box as unknown as ElementType);\nexport const DStack = dsl(Stack as unknown as ElementType);\nexport const DGrid = dsl(Grid as unknown as ElementType);\nexport const DInline = dsl(Inline as unknown as ElementType);\n","// SPDX-License-Identifier: MIT\n// Copyright (c) 2026 bvasilenko\nimport { type CSSProperties } from \"react\";\nimport { type ThemeOverride } from \"./types\";\n\nexport function themeStyle(theme: ThemeOverride | undefined): CSSProperties | undefined {\n if (!theme) return undefined;\n return Object.fromEntries(\n Object.entries(theme).map(([k, v]) => [`--v-${k}`, v])\n ) as CSSProperties;\n}\n\nexport function clampedGridCols(n: number): 1 | 2 | 3 | 4 | 5 | 6 {\n return Math.max(1, Math.min(6, Math.round(n))) as 1 | 2 | 3 | 4 | 5 | 6;\n}\n","// SPDX-License-Identifier: MIT\n// Copyright (c) 2026 bvasilenko\nimport { z } from \"zod\";\n\nexport const CtaSchema = z.object({\n label: z.string(),\n href: z.string(),\n}).strict();\n\nexport const ImageSchema = z.object({\n src: z.string(),\n alt: z.string(),\n}).strict();\n\nexport const AvatarSchema = ImageSchema;\n\nexport type Cta = z.infer<typeof CtaSchema>;\nexport type Image = z.infer<typeof ImageSchema>;\nexport type AvatarSrc = Image;\n","// SPDX-License-Identifier: MIT\n// Copyright (c) 2026 bvasilenko\nimport { z } from \"zod\";\nimport { ImageSchema } from \"../../shared/schemas\";\n\nconst BlogPostSchema = z.object({\n title: z.string(),\n excerpt: z.string(),\n date: z.string(),\n category: z.string().optional(),\n image: ImageSchema,\n}).strict();\n\nexport const BlogSplitContentSchema = z.object({\n heading: z.string(),\n posts: z.array(BlogPostSchema).min(1),\n}).strict();\n\nexport type BlogSplitContent = z.infer<typeof BlogSplitContentSchema>;\n","// SPDX-License-Identifier: MIT\n// Copyright (c) 2026 bvasilenko\nimport { Badge, cn } from \"@booga/vui\";\nimport { DBox, DGrid, DStack } from \"../../primitives\";\nimport { type BlockProps } from \"../../types\";\nimport { themeStyle } from \"../../theme\";\nimport { BlogSplitContentSchema, type BlogSplitContent } from \"./schema\";\n\nexport function BlogSplit({ content, theme }: BlockProps<BlogSplitContent>) {\n BlogSplitContentSchema.parse(content);\n const { heading, posts } = content;\n const [featured, ...rest] = posts;\n return (\n <DBox as=\"section\" aria-label={heading} style={themeStyle(theme)}>\n <DStack px={6} py={16} className={cn(\"max-w-6xl mx-auto gap-10\")}>\n <DBox as=\"h2\" className={cn(\"text-3xl font-bold tracking-tight\")}>{heading}</DBox>\n <DGrid columns={2} gap={8} align=\"start\">\n {featured && (\n <DBox as=\"article\">\n <DStack gap={4}>\n <DBox\n as=\"img\"\n src={featured.image.src}\n alt={featured.image.alt}\n className={cn(\"w-full rounded-lg object-cover aspect-video\")}\n />\n <DStack gap={2}>\n {featured.category && <Badge variant=\"secondary\">{featured.category}</Badge>}\n <DBox as=\"h3\" className={cn(\"text-xl font-semibold\")}>{featured.title}</DBox>\n <DBox as=\"p\" color=\"muted\">{featured.excerpt}</DBox>\n <DBox as=\"time\" dateTime={featured.date} color=\"muted\" className={cn(\"text-xs\")}>{featured.date}</DBox>\n </DStack>\n </DStack>\n </DBox>\n )}\n <DBox as=\"ul\" m={0} p={0} gap={6} display=\"flex\" className={cn(\"list-none flex-col\")}>\n {rest.map((post, i) => (\n <DBox as=\"li\" key={i}>\n <DBox as=\"article\">\n <DGrid columns={2} gap={4} align=\"start\">\n <DBox\n as=\"img\"\n src={post.image.src}\n alt={post.image.alt}\n className={cn(\"w-full rounded-md object-cover aspect-video\")}\n />\n <DStack gap={1}>\n {post.category && <Badge variant=\"secondary\">{post.category}</Badge>}\n <DBox as=\"h3\" className={cn(\"font-semibold leading-snug\")}>{post.title}</DBox>\n <DBox as=\"time\" dateTime={post.date} color=\"muted\" className={cn(\"text-xs\")}>{post.date}</DBox>\n </DStack>\n </DGrid>\n </DBox>\n </DBox>\n ))}\n </DBox>\n </DGrid>\n </DStack>\n </DBox>\n );\n}\n","// SPDX-License-Identifier: MIT\n// Copyright (c) 2026 bvasilenko\nimport { type BlogSplitContent } from \"./schema\";\n\nexport const BlogSplitDefaultContent: BlogSplitContent = {\n heading: \"Latest posts\",\n posts: [\n { title: \"Designing for composability\", excerpt: \"How modular thinking unlocks maintainable systems at scale.\", date: \"2026-05-01\", category: \"Design\", image: { src: \"https://placehold.co/600x400\", alt: \"Design systems post\" } },\n { title: \"Type-safe content at runtime\", excerpt: \"Zod schemas as the single source of truth for block content.\", date: \"2026-04-18\", image: { src: \"https://placehold.co/400x280\", alt: \"Type safety post\" } },\n { title: \"Tree-shaking section blocks\", excerpt: \"Per-category entry points and how they keep bundles lean.\", date: \"2026-04-05\", category: \"Engineering\", image: { src: \"https://placehold.co/400x280\", alt: \"Tree-shaking post\" } },\n ],\n};\n","// SPDX-License-Identifier: MIT\n// Copyright (c) 2026 bvasilenko\nimport { z } from \"zod\";\nimport { ImageSchema } from \"../../shared/schemas\";\n\nconst BlogPostSchema = z.object({\n title: z.string(),\n excerpt: z.string(),\n date: z.string(),\n category: z.string().optional(),\n image: ImageSchema,\n}).strict();\n\nexport const BlogGridContentSchema = z.object({\n heading: z.string(),\n posts: z.array(BlogPostSchema).min(1),\n}).strict();\n\nexport type BlogGridContent = z.infer<typeof BlogGridContentSchema>;\n","// SPDX-License-Identifier: MIT\n// Copyright (c) 2026 bvasilenko\nimport { Badge, Card, CardContent, cn } from \"@booga/vui\";\nimport { DBox, DGrid, DStack } from \"../../primitives\";\nimport { type BlockProps } from \"../../types\";\nimport { themeStyle } from \"../../theme\";\nimport { BlogGridContentSchema, type BlogGridContent } from \"./schema\";\n\nexport function BlogGrid({ content, theme }: BlockProps<BlogGridContent>) {\n BlogGridContentSchema.parse(content);\n const { heading, posts } = content;\n return (\n <DBox as=\"section\" aria-label={heading} style={themeStyle(theme)}>\n <DStack px={6} py={16} className={cn(\"max-w-6xl mx-auto gap-10\")}>\n <DBox as=\"h2\" className={cn(\"text-3xl font-bold tracking-tight\")}>{heading}</DBox>\n <DGrid columns={3} gap={6}>\n {posts.map((post, i) => (\n <Card key={i}>\n <DBox as=\"article\">\n <DBox\n as=\"img\"\n src={post.image.src}\n alt={post.image.alt}\n className={cn(\"w-full rounded-t-lg object-cover aspect-video\")}\n />\n <CardContent>\n <DStack gap={2} pt={2}>\n {post.category && <Badge variant=\"secondary\">{post.category}</Badge>}\n <DBox as=\"h3\" className={cn(\"font-semibold leading-snug\")}>{post.title}</DBox>\n <DBox as=\"p\" color=\"muted\" className={cn(\"text-sm\")}>{post.excerpt}</DBox>\n <DBox as=\"time\" dateTime={post.date} color=\"muted\" className={cn(\"text-xs\")}>{post.date}</DBox>\n </DStack>\n </CardContent>\n </DBox>\n </Card>\n ))}\n </DGrid>\n </DStack>\n </DBox>\n );\n}\n","// SPDX-License-Identifier: MIT\n// Copyright (c) 2026 bvasilenko\nimport { type BlogGridContent } from \"./schema\";\n\nexport const BlogGridDefaultContent: BlogGridContent = {\n heading: \"From the blog\",\n posts: [\n { title: \"Designing for composability\", excerpt: \"Modular thinking at scale.\", date: \"2026-05-01\", category: \"Design\", image: { src: \"https://placehold.co/480x320\", alt: \"Design post\" } },\n { title: \"Type-safe content at runtime\", excerpt: \"Zod as single source of truth.\", date: \"2026-04-18\", image: { src: \"https://placehold.co/480x320\", alt: \"Types post\" } },\n { title: \"Tree-shaking section blocks\", excerpt: \"Lean bundles, per-category entry points.\", date: \"2026-04-05\", category: \"Engineering\", image: { src: \"https://placehold.co/480x320\", alt: \"Bundling post\" } },\n ],\n};\n"]}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { a as BlockProps } from '../types-n6w6cZmP.cjs';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
import 'react';
|
|
5
|
+
|
|
6
|
+
declare const BlogSplitContentSchema: z.ZodObject<{
|
|
7
|
+
heading: z.ZodString;
|
|
8
|
+
posts: z.ZodArray<z.ZodObject<{
|
|
9
|
+
title: z.ZodString;
|
|
10
|
+
excerpt: z.ZodString;
|
|
11
|
+
date: z.ZodString;
|
|
12
|
+
category: z.ZodOptional<z.ZodString>;
|
|
13
|
+
image: z.ZodObject<{
|
|
14
|
+
src: z.ZodString;
|
|
15
|
+
alt: z.ZodString;
|
|
16
|
+
}, "strict", z.ZodTypeAny, {
|
|
17
|
+
src: string;
|
|
18
|
+
alt: string;
|
|
19
|
+
}, {
|
|
20
|
+
src: string;
|
|
21
|
+
alt: string;
|
|
22
|
+
}>;
|
|
23
|
+
}, "strict", z.ZodTypeAny, {
|
|
24
|
+
title: string;
|
|
25
|
+
image: {
|
|
26
|
+
src: string;
|
|
27
|
+
alt: string;
|
|
28
|
+
};
|
|
29
|
+
date: string;
|
|
30
|
+
excerpt: string;
|
|
31
|
+
category?: string | undefined;
|
|
32
|
+
}, {
|
|
33
|
+
title: string;
|
|
34
|
+
image: {
|
|
35
|
+
src: string;
|
|
36
|
+
alt: string;
|
|
37
|
+
};
|
|
38
|
+
date: string;
|
|
39
|
+
excerpt: string;
|
|
40
|
+
category?: string | undefined;
|
|
41
|
+
}>, "many">;
|
|
42
|
+
}, "strict", z.ZodTypeAny, {
|
|
43
|
+
heading: string;
|
|
44
|
+
posts: {
|
|
45
|
+
title: string;
|
|
46
|
+
image: {
|
|
47
|
+
src: string;
|
|
48
|
+
alt: string;
|
|
49
|
+
};
|
|
50
|
+
date: string;
|
|
51
|
+
excerpt: string;
|
|
52
|
+
category?: string | undefined;
|
|
53
|
+
}[];
|
|
54
|
+
}, {
|
|
55
|
+
heading: string;
|
|
56
|
+
posts: {
|
|
57
|
+
title: string;
|
|
58
|
+
image: {
|
|
59
|
+
src: string;
|
|
60
|
+
alt: string;
|
|
61
|
+
};
|
|
62
|
+
date: string;
|
|
63
|
+
excerpt: string;
|
|
64
|
+
category?: string | undefined;
|
|
65
|
+
}[];
|
|
66
|
+
}>;
|
|
67
|
+
type BlogSplitContent = z.infer<typeof BlogSplitContentSchema>;
|
|
68
|
+
|
|
69
|
+
declare function BlogSplit({ content, theme }: BlockProps<BlogSplitContent>): react_jsx_runtime.JSX.Element;
|
|
70
|
+
|
|
71
|
+
declare const BlogSplitDefaultContent: BlogSplitContent;
|
|
72
|
+
|
|
73
|
+
declare const BlogGridContentSchema: z.ZodObject<{
|
|
74
|
+
heading: z.ZodString;
|
|
75
|
+
posts: z.ZodArray<z.ZodObject<{
|
|
76
|
+
title: z.ZodString;
|
|
77
|
+
excerpt: z.ZodString;
|
|
78
|
+
date: z.ZodString;
|
|
79
|
+
category: z.ZodOptional<z.ZodString>;
|
|
80
|
+
image: z.ZodObject<{
|
|
81
|
+
src: z.ZodString;
|
|
82
|
+
alt: z.ZodString;
|
|
83
|
+
}, "strict", z.ZodTypeAny, {
|
|
84
|
+
src: string;
|
|
85
|
+
alt: string;
|
|
86
|
+
}, {
|
|
87
|
+
src: string;
|
|
88
|
+
alt: string;
|
|
89
|
+
}>;
|
|
90
|
+
}, "strict", z.ZodTypeAny, {
|
|
91
|
+
title: string;
|
|
92
|
+
image: {
|
|
93
|
+
src: string;
|
|
94
|
+
alt: string;
|
|
95
|
+
};
|
|
96
|
+
date: string;
|
|
97
|
+
excerpt: string;
|
|
98
|
+
category?: string | undefined;
|
|
99
|
+
}, {
|
|
100
|
+
title: string;
|
|
101
|
+
image: {
|
|
102
|
+
src: string;
|
|
103
|
+
alt: string;
|
|
104
|
+
};
|
|
105
|
+
date: string;
|
|
106
|
+
excerpt: string;
|
|
107
|
+
category?: string | undefined;
|
|
108
|
+
}>, "many">;
|
|
109
|
+
}, "strict", z.ZodTypeAny, {
|
|
110
|
+
heading: string;
|
|
111
|
+
posts: {
|
|
112
|
+
title: string;
|
|
113
|
+
image: {
|
|
114
|
+
src: string;
|
|
115
|
+
alt: string;
|
|
116
|
+
};
|
|
117
|
+
date: string;
|
|
118
|
+
excerpt: string;
|
|
119
|
+
category?: string | undefined;
|
|
120
|
+
}[];
|
|
121
|
+
}, {
|
|
122
|
+
heading: string;
|
|
123
|
+
posts: {
|
|
124
|
+
title: string;
|
|
125
|
+
image: {
|
|
126
|
+
src: string;
|
|
127
|
+
alt: string;
|
|
128
|
+
};
|
|
129
|
+
date: string;
|
|
130
|
+
excerpt: string;
|
|
131
|
+
category?: string | undefined;
|
|
132
|
+
}[];
|
|
133
|
+
}>;
|
|
134
|
+
type BlogGridContent = z.infer<typeof BlogGridContentSchema>;
|
|
135
|
+
|
|
136
|
+
declare function BlogGrid({ content, theme }: BlockProps<BlogGridContent>): react_jsx_runtime.JSX.Element;
|
|
137
|
+
|
|
138
|
+
declare const BlogGridDefaultContent: BlogGridContent;
|
|
139
|
+
|
|
140
|
+
export { BlogGrid, type BlogGridContent, BlogGridContentSchema, BlogGridDefaultContent, BlogSplit, type BlogSplitContent, BlogSplitContentSchema, BlogSplitDefaultContent };
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { a as BlockProps } from '../types-n6w6cZmP.js';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
import 'react';
|
|
5
|
+
|
|
6
|
+
declare const BlogSplitContentSchema: z.ZodObject<{
|
|
7
|
+
heading: z.ZodString;
|
|
8
|
+
posts: z.ZodArray<z.ZodObject<{
|
|
9
|
+
title: z.ZodString;
|
|
10
|
+
excerpt: z.ZodString;
|
|
11
|
+
date: z.ZodString;
|
|
12
|
+
category: z.ZodOptional<z.ZodString>;
|
|
13
|
+
image: z.ZodObject<{
|
|
14
|
+
src: z.ZodString;
|
|
15
|
+
alt: z.ZodString;
|
|
16
|
+
}, "strict", z.ZodTypeAny, {
|
|
17
|
+
src: string;
|
|
18
|
+
alt: string;
|
|
19
|
+
}, {
|
|
20
|
+
src: string;
|
|
21
|
+
alt: string;
|
|
22
|
+
}>;
|
|
23
|
+
}, "strict", z.ZodTypeAny, {
|
|
24
|
+
title: string;
|
|
25
|
+
image: {
|
|
26
|
+
src: string;
|
|
27
|
+
alt: string;
|
|
28
|
+
};
|
|
29
|
+
date: string;
|
|
30
|
+
excerpt: string;
|
|
31
|
+
category?: string | undefined;
|
|
32
|
+
}, {
|
|
33
|
+
title: string;
|
|
34
|
+
image: {
|
|
35
|
+
src: string;
|
|
36
|
+
alt: string;
|
|
37
|
+
};
|
|
38
|
+
date: string;
|
|
39
|
+
excerpt: string;
|
|
40
|
+
category?: string | undefined;
|
|
41
|
+
}>, "many">;
|
|
42
|
+
}, "strict", z.ZodTypeAny, {
|
|
43
|
+
heading: string;
|
|
44
|
+
posts: {
|
|
45
|
+
title: string;
|
|
46
|
+
image: {
|
|
47
|
+
src: string;
|
|
48
|
+
alt: string;
|
|
49
|
+
};
|
|
50
|
+
date: string;
|
|
51
|
+
excerpt: string;
|
|
52
|
+
category?: string | undefined;
|
|
53
|
+
}[];
|
|
54
|
+
}, {
|
|
55
|
+
heading: string;
|
|
56
|
+
posts: {
|
|
57
|
+
title: string;
|
|
58
|
+
image: {
|
|
59
|
+
src: string;
|
|
60
|
+
alt: string;
|
|
61
|
+
};
|
|
62
|
+
date: string;
|
|
63
|
+
excerpt: string;
|
|
64
|
+
category?: string | undefined;
|
|
65
|
+
}[];
|
|
66
|
+
}>;
|
|
67
|
+
type BlogSplitContent = z.infer<typeof BlogSplitContentSchema>;
|
|
68
|
+
|
|
69
|
+
declare function BlogSplit({ content, theme }: BlockProps<BlogSplitContent>): react_jsx_runtime.JSX.Element;
|
|
70
|
+
|
|
71
|
+
declare const BlogSplitDefaultContent: BlogSplitContent;
|
|
72
|
+
|
|
73
|
+
declare const BlogGridContentSchema: z.ZodObject<{
|
|
74
|
+
heading: z.ZodString;
|
|
75
|
+
posts: z.ZodArray<z.ZodObject<{
|
|
76
|
+
title: z.ZodString;
|
|
77
|
+
excerpt: z.ZodString;
|
|
78
|
+
date: z.ZodString;
|
|
79
|
+
category: z.ZodOptional<z.ZodString>;
|
|
80
|
+
image: z.ZodObject<{
|
|
81
|
+
src: z.ZodString;
|
|
82
|
+
alt: z.ZodString;
|
|
83
|
+
}, "strict", z.ZodTypeAny, {
|
|
84
|
+
src: string;
|
|
85
|
+
alt: string;
|
|
86
|
+
}, {
|
|
87
|
+
src: string;
|
|
88
|
+
alt: string;
|
|
89
|
+
}>;
|
|
90
|
+
}, "strict", z.ZodTypeAny, {
|
|
91
|
+
title: string;
|
|
92
|
+
image: {
|
|
93
|
+
src: string;
|
|
94
|
+
alt: string;
|
|
95
|
+
};
|
|
96
|
+
date: string;
|
|
97
|
+
excerpt: string;
|
|
98
|
+
category?: string | undefined;
|
|
99
|
+
}, {
|
|
100
|
+
title: string;
|
|
101
|
+
image: {
|
|
102
|
+
src: string;
|
|
103
|
+
alt: string;
|
|
104
|
+
};
|
|
105
|
+
date: string;
|
|
106
|
+
excerpt: string;
|
|
107
|
+
category?: string | undefined;
|
|
108
|
+
}>, "many">;
|
|
109
|
+
}, "strict", z.ZodTypeAny, {
|
|
110
|
+
heading: string;
|
|
111
|
+
posts: {
|
|
112
|
+
title: string;
|
|
113
|
+
image: {
|
|
114
|
+
src: string;
|
|
115
|
+
alt: string;
|
|
116
|
+
};
|
|
117
|
+
date: string;
|
|
118
|
+
excerpt: string;
|
|
119
|
+
category?: string | undefined;
|
|
120
|
+
}[];
|
|
121
|
+
}, {
|
|
122
|
+
heading: string;
|
|
123
|
+
posts: {
|
|
124
|
+
title: string;
|
|
125
|
+
image: {
|
|
126
|
+
src: string;
|
|
127
|
+
alt: string;
|
|
128
|
+
};
|
|
129
|
+
date: string;
|
|
130
|
+
excerpt: string;
|
|
131
|
+
category?: string | undefined;
|
|
132
|
+
}[];
|
|
133
|
+
}>;
|
|
134
|
+
type BlogGridContent = z.infer<typeof BlogGridContentSchema>;
|
|
135
|
+
|
|
136
|
+
declare function BlogGrid({ content, theme }: BlockProps<BlogGridContent>): react_jsx_runtime.JSX.Element;
|
|
137
|
+
|
|
138
|
+
declare const BlogGridDefaultContent: BlogGridContent;
|
|
139
|
+
|
|
140
|
+
export { BlogGrid, type BlogGridContent, BlogGridContentSchema, BlogGridDefaultContent, BlogSplit, type BlogSplitContent, BlogSplitContentSchema, BlogSplitDefaultContent };
|