@nanisoft/prism-ui 0.5.0 → 0.5.1
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/LICENSE +21 -0
- package/README.md +81 -0
- package/THIRD-PARTY-NOTICES.md +48 -0
- package/dist/.tsbuildinfo +1 -0
- package/dist/blocks/app-shell-01/app-shell.d.ts +38 -0
- package/dist/blocks/app-shell-01/app-shell.d.ts.map +1 -0
- package/dist/blocks/app-shell-01/app-shell.js +27 -0
- package/dist/blocks/app-shell-01/index.d.ts +3 -0
- package/dist/blocks/app-shell-01/index.d.ts.map +1 -0
- package/dist/blocks/app-shell-01/index.js +1 -0
- package/dist/blocks/auth-form-01/auth-form.d.ts +52 -0
- package/dist/blocks/auth-form-01/auth-form.d.ts.map +1 -0
- package/dist/blocks/auth-form-01/auth-form.js +23 -0
- package/dist/blocks/auth-form-01/index.d.ts +3 -0
- package/dist/blocks/auth-form-01/index.d.ts.map +1 -0
- package/dist/blocks/auth-form-01/index.js +1 -0
- package/dist/blocks/cta-01/cta.d.ts +23 -0
- package/dist/blocks/cta-01/cta.d.ts.map +1 -0
- package/dist/blocks/cta-01/cta.js +24 -0
- package/dist/blocks/cta-01/index.d.ts +2 -0
- package/dist/blocks/cta-01/index.d.ts.map +1 -0
- package/dist/blocks/cta-01/index.js +1 -0
- package/dist/blocks/data-table-01/data-table.d.ts +102 -0
- package/dist/blocks/data-table-01/data-table.d.ts.map +1 -0
- package/dist/blocks/data-table-01/data-table.js +116 -0
- package/dist/blocks/data-table-01/index.d.ts +3 -0
- package/dist/blocks/data-table-01/index.d.ts.map +1 -0
- package/dist/blocks/data-table-01/index.js +1 -0
- package/dist/blocks/feature-grid-01/feature-grid.d.ts +27 -0
- package/dist/blocks/feature-grid-01/feature-grid.d.ts.map +1 -0
- package/dist/blocks/feature-grid-01/feature-grid.js +14 -0
- package/dist/blocks/feature-grid-01/index.d.ts +2 -0
- package/dist/blocks/feature-grid-01/index.d.ts.map +1 -0
- package/dist/blocks/feature-grid-01/index.js +1 -0
- package/dist/blocks/hero-01/hero.d.ts +30 -0
- package/dist/blocks/hero-01/hero.d.ts.map +1 -0
- package/dist/blocks/hero-01/hero.js +12 -0
- package/dist/blocks/hero-01/index.d.ts +2 -0
- package/dist/blocks/hero-01/index.d.ts.map +1 -0
- package/dist/blocks/hero-01/index.js +1 -0
- package/dist/blocks/index.d.ts +18 -0
- package/dist/blocks/index.d.ts.map +1 -0
- package/dist/blocks/index.js +17 -0
- package/dist/blocks/page-header-01/index.d.ts +3 -0
- package/dist/blocks/page-header-01/index.d.ts.map +1 -0
- package/dist/blocks/page-header-01/index.js +1 -0
- package/dist/blocks/page-header-01/page-header.d.ts +48 -0
- package/dist/blocks/page-header-01/page-header.d.ts.map +1 -0
- package/dist/blocks/page-header-01/page-header.js +27 -0
- package/dist/blocks/pricing-01/index.d.ts +2 -0
- package/dist/blocks/pricing-01/index.d.ts.map +1 -0
- package/dist/blocks/pricing-01/index.js +1 -0
- package/dist/blocks/pricing-01/pricing.d.ts +35 -0
- package/dist/blocks/pricing-01/pricing.d.ts.map +1 -0
- package/dist/blocks/pricing-01/pricing.js +20 -0
- package/dist/blocks/settings-panel-01/index.d.ts +3 -0
- package/dist/blocks/settings-panel-01/index.d.ts.map +1 -0
- package/dist/blocks/settings-panel-01/index.js +1 -0
- package/dist/blocks/settings-panel-01/settings-panel.d.ts +71 -0
- package/dist/blocks/settings-panel-01/settings-panel.d.ts.map +1 -0
- package/dist/blocks/settings-panel-01/settings-panel.js +38 -0
- package/dist/blocks/stats-01/index.d.ts +2 -0
- package/dist/blocks/stats-01/index.d.ts.map +1 -0
- package/dist/blocks/stats-01/index.js +1 -0
- package/dist/blocks/stats-01/stats.d.ts +28 -0
- package/dist/blocks/stats-01/stats.d.ts.map +1 -0
- package/dist/blocks/stats-01/stats.js +27 -0
- package/dist/catalog.d.ts +28 -0
- package/dist/catalog.d.ts.map +1 -0
- package/dist/catalog.js +502 -0
- package/dist/components/index.d.ts +53 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/index.js +37 -0
- package/dist/components/ui/accordion.d.ts +65 -0
- package/dist/components/ui/accordion.d.ts.map +1 -0
- package/dist/components/ui/accordion.js +30 -0
- package/dist/components/ui/alert.d.ts +19 -0
- package/dist/components/ui/alert.d.ts.map +1 -0
- package/dist/components/ui/alert.js +31 -0
- package/dist/components/ui/avatar.d.ts +47 -0
- package/dist/components/ui/avatar.d.ts.map +1 -0
- package/dist/components/ui/avatar.js +30 -0
- package/dist/components/ui/badge.d.ts +14 -0
- package/dist/components/ui/badge.d.ts.map +1 -0
- package/dist/components/ui/badge.js +26 -0
- package/dist/components/ui/breadcrumb.d.ts +35 -0
- package/dist/components/ui/breadcrumb.d.ts.map +1 -0
- package/dist/components/ui/breadcrumb.js +48 -0
- package/dist/components/ui/button.d.ts +16 -0
- package/dist/components/ui/button.d.ts.map +1 -0
- package/dist/components/ui/button.js +63 -0
- package/dist/components/ui/card.d.ts +16 -0
- package/dist/components/ui/card.d.ts.map +1 -0
- package/dist/components/ui/card.js +28 -0
- package/dist/components/ui/checkbox.d.ts +43 -0
- package/dist/components/ui/checkbox.d.ts.map +1 -0
- package/dist/components/ui/checkbox.js +18 -0
- package/dist/components/ui/dialog.d.ts +81 -0
- package/dist/components/ui/dialog.d.ts.map +1 -0
- package/dist/components/ui/dialog.js +60 -0
- package/dist/components/ui/dropdown-menu.d.ts +189 -0
- package/dist/components/ui/dropdown-menu.d.ts.map +1 -0
- package/dist/components/ui/dropdown-menu.js +67 -0
- package/dist/components/ui/field.d.ts +36 -0
- package/dist/components/ui/field.d.ts.map +1 -0
- package/dist/components/ui/field.js +46 -0
- package/dist/components/ui/input.d.ts +12 -0
- package/dist/components/ui/input.d.ts.map +1 -0
- package/dist/components/ui/input.js +14 -0
- package/dist/components/ui/kbd.d.ts +10 -0
- package/dist/components/ui/kbd.d.ts.map +1 -0
- package/dist/components/ui/kbd.js +12 -0
- package/dist/components/ui/pagination.d.ts +40 -0
- package/dist/components/ui/pagination.d.ts.map +1 -0
- package/dist/components/ui/pagination.js +49 -0
- package/dist/components/ui/popover.d.ts +56 -0
- package/dist/components/ui/popover.d.ts.map +1 -0
- package/dist/components/ui/popover.js +25 -0
- package/dist/components/ui/progress.d.ts +38 -0
- package/dist/components/ui/progress.d.ts.map +1 -0
- package/dist/components/ui/progress.js +17 -0
- package/dist/components/ui/radio-group.d.ts +66 -0
- package/dist/components/ui/radio-group.d.ts.map +1 -0
- package/dist/components/ui/radio-group.js +30 -0
- package/dist/components/ui/section.d.ts +37 -0
- package/dist/components/ui/section.d.ts.map +1 -0
- package/dist/components/ui/section.js +12 -0
- package/dist/components/ui/select.d.ts +124 -0
- package/dist/components/ui/select.d.ts.map +1 -0
- package/dist/components/ui/select.js +47 -0
- package/dist/components/ui/separator.d.ts +16 -0
- package/dist/components/ui/separator.d.ts.map +1 -0
- package/dist/components/ui/separator.js +15 -0
- package/dist/components/ui/skeleton.d.ts +12 -0
- package/dist/components/ui/skeleton.d.ts.map +1 -0
- package/dist/components/ui/skeleton.js +14 -0
- package/dist/components/ui/slider.d.ts +43 -0
- package/dist/components/ui/slider.d.ts.map +1 -0
- package/dist/components/ui/slider.js +17 -0
- package/dist/components/ui/switch.d.ts +42 -0
- package/dist/components/ui/switch.d.ts.map +1 -0
- package/dist/components/ui/switch.js +16 -0
- package/dist/components/ui/table.d.ts +27 -0
- package/dist/components/ui/table.d.ts.map +1 -0
- package/dist/components/ui/table.js +43 -0
- package/dist/components/ui/tabs.d.ts +66 -0
- package/dist/components/ui/tabs.d.ts.map +1 -0
- package/dist/components/ui/tabs.js +29 -0
- package/dist/components/ui/textarea.d.ts +11 -0
- package/dist/components/ui/textarea.d.ts.map +1 -0
- package/dist/components/ui/textarea.js +13 -0
- package/dist/components/ui/tooltip.d.ts +63 -0
- package/dist/components/ui/tooltip.d.ts.map +1 -0
- package/dist/components/ui/tooltip.js +25 -0
- package/dist/components/ui/typography.d.ts +32 -0
- package/dist/components/ui/typography.d.ts.map +1 -0
- package/dist/components/ui/typography.js +51 -0
- package/dist/index.d.ts +55 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +51 -0
- package/dist/lib/utils.d.ts +3 -0
- package/dist/lib/utils.d.ts.map +1 -0
- package/dist/lib/utils.js +5 -0
- package/dist/pages/auth-page/index.d.ts +36 -0
- package/dist/pages/auth-page/index.d.ts.map +1 -0
- package/dist/pages/auth-page/index.js +23 -0
- package/dist/pages/dashboard-page/index.d.ts +36 -0
- package/dist/pages/dashboard-page/index.d.ts.map +1 -0
- package/dist/pages/dashboard-page/index.js +24 -0
- package/dist/pages/index.d.ts +17 -0
- package/dist/pages/index.d.ts.map +1 -0
- package/dist/pages/index.js +12 -0
- package/dist/pages/marketing-page/index.d.ts +43 -0
- package/dist/pages/marketing-page/index.d.ts.map +1 -0
- package/dist/pages/marketing-page/index.js +25 -0
- package/dist/pages/settings-page/index.d.ts +47 -0
- package/dist/pages/settings-page/index.d.ts.map +1 -0
- package/dist/pages/settings-page/index.js +24 -0
- package/dist/provider/index.d.ts +12 -0
- package/dist/provider/index.d.ts.map +1 -0
- package/dist/provider/index.js +9 -0
- package/dist/provider/provider.d.ts +37 -0
- package/dist/provider/provider.d.ts.map +1 -0
- package/dist/provider/provider.js +87 -0
- package/dist/provider/theme-script.d.ts +17 -0
- package/dist/provider/theme-script.d.ts.map +1 -0
- package/dist/provider/theme-script.js +28 -0
- package/dist/styles.css +2413 -0
- package/dist/theming/index.d.ts +43 -0
- package/dist/theming/index.d.ts.map +1 -0
- package/dist/theming/index.js +60 -0
- package/package.json +79 -18
- package/components.json +0 -21
- package/public/r/badge.json +0 -26
- package/public/r/button.json +0 -26
- package/public/r/card.json +0 -25
- package/public/r/cta-01.json +0 -44
- package/public/r/feature-grid-01.json +0 -44
- package/public/r/hero-01.json +0 -44
- package/public/r/pricing-01.json +0 -46
- package/public/r/registry.json +0 -294
- package/public/r/section.json +0 -25
- package/public/r/stats-01.json +0 -44
- package/registry.json +0 -294
- package/src/components/ds/blocks/cta-01/block.json +0 -8
- package/src/components/ds/blocks/cta-01/cta.tsx +0 -62
- package/src/components/ds/blocks/cta-01/index.tsx +0 -1
- package/src/components/ds/blocks/feature-grid-01/block.json +0 -8
- package/src/components/ds/blocks/feature-grid-01/feature-grid.tsx +0 -69
- package/src/components/ds/blocks/feature-grid-01/index.tsx +0 -1
- package/src/components/ds/blocks/hero-01/block.json +0 -8
- package/src/components/ds/blocks/hero-01/hero.tsx +0 -85
- package/src/components/ds/blocks/hero-01/index.tsx +0 -1
- package/src/components/ds/blocks/pricing-01/block.json +0 -8
- package/src/components/ds/blocks/pricing-01/index.tsx +0 -1
- package/src/components/ds/blocks/pricing-01/pricing.tsx +0 -122
- package/src/components/ds/blocks/section.meta.json +0 -6
- package/src/components/ds/blocks/section.tsx +0 -86
- package/src/components/ds/blocks/stats-01/block.json +0 -8
- package/src/components/ds/blocks/stats-01/index.tsx +0 -1
- package/src/components/ds/blocks/stats-01/stats.tsx +0 -92
- package/src/components/ui/badge.tsx +0 -37
- package/src/components/ui/button.tsx +0 -77
- package/src/components/ui/card.tsx +0 -65
- package/src/lib/utils.ts +0 -6
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Prism theming vocabulary: pack and mode are two independent axes.
|
|
3
|
+
*
|
|
4
|
+
* `data-pack` selects the palette and `.dark` selects the mode; neither implies
|
|
5
|
+
* the other (ticket 07). `default` is the selectable neutral pack id, and its
|
|
6
|
+
* markup is the absence of the attribute. Everything here is pure and
|
|
7
|
+
* isomorphic so a Server Component can render the declarative form without a
|
|
8
|
+
* client runtime. There is no theme factory and no override object: the pack
|
|
9
|
+
* and mode are the whole API.
|
|
10
|
+
*/
|
|
11
|
+
export declare const PACKS: readonly ["default", "blush", "mint", "lavender", "sky", "peach"];
|
|
12
|
+
export type PackId = (typeof PACKS)[number];
|
|
13
|
+
export declare const MODES: readonly ["light", "dark"];
|
|
14
|
+
export type Mode = (typeof MODES)[number];
|
|
15
|
+
export declare const PACK_ATTRIBUTE = "data-pack";
|
|
16
|
+
export declare const DEFAULT_STORAGE_KEY = "prism-theme";
|
|
17
|
+
/**
|
|
18
|
+
* Reads a persisted `{ pack, mode }` object.
|
|
19
|
+
*
|
|
20
|
+
* Returns `null` for anything that is not a valid pair, so a corrupt or
|
|
21
|
+
* superseded stored value falls back to the defaults rather than to a pack that
|
|
22
|
+
* does not exist. Parsing is deliberately strict: the store is owned by
|
|
23
|
+
* `PrismProvider`, which always writes this exact shape.
|
|
24
|
+
*/
|
|
25
|
+
export declare function parseStoredTheme(raw: string | null): {
|
|
26
|
+
pack: PackId;
|
|
27
|
+
mode: Mode;
|
|
28
|
+
} | null;
|
|
29
|
+
/**
|
|
30
|
+
* Turns a pack and mode into the two markup attributes that express them.
|
|
31
|
+
*
|
|
32
|
+
* Returns attributes, never CSS values: a Server Component spreads the result
|
|
33
|
+
* onto `<html>` and gets the declarative form with no client runtime. `default`
|
|
34
|
+
* is expressed by omitting `data-pack`; light is expressed by omitting `dark`.
|
|
35
|
+
*/
|
|
36
|
+
export declare function themeAttributes({ pack, mode, }: {
|
|
37
|
+
pack: PackId;
|
|
38
|
+
mode: Mode;
|
|
39
|
+
}): {
|
|
40
|
+
'data-pack'?: string;
|
|
41
|
+
className?: string;
|
|
42
|
+
};
|
|
43
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/theming/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,eAAO,MAAM,KAAK,mEAAoE,CAAA;AACtF,MAAM,MAAM,MAAM,GAAG,CAAC,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,CAAA;AAE3C,eAAO,MAAM,KAAK,4BAA6B,CAAA;AAC/C,MAAM,MAAM,IAAI,GAAG,CAAC,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,CAAA;AAEzC,eAAO,MAAM,cAAc,cAAc,CAAA;AACzC,eAAO,MAAM,mBAAmB,gBAAgB,CAAA;AAUhD;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,IAAI,CAAA;CAAE,GAAG,IAAI,CAgBxF;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,EAC9B,IAAI,EACJ,IAAI,GACL,EAAE;IACD,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,IAAI,CAAA;CACX,GAAG;IAAE,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CAK/C"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Prism theming vocabulary: pack and mode are two independent axes.
|
|
3
|
+
*
|
|
4
|
+
* `data-pack` selects the palette and `.dark` selects the mode; neither implies
|
|
5
|
+
* the other (ticket 07). `default` is the selectable neutral pack id, and its
|
|
6
|
+
* markup is the absence of the attribute. Everything here is pure and
|
|
7
|
+
* isomorphic so a Server Component can render the declarative form without a
|
|
8
|
+
* client runtime. There is no theme factory and no override object: the pack
|
|
9
|
+
* and mode are the whole API.
|
|
10
|
+
*/
|
|
11
|
+
export const PACKS = ['default', 'blush', 'mint', 'lavender', 'sky', 'peach'];
|
|
12
|
+
export const MODES = ['light', 'dark'];
|
|
13
|
+
export const PACK_ATTRIBUTE = 'data-pack';
|
|
14
|
+
export const DEFAULT_STORAGE_KEY = 'prism-theme';
|
|
15
|
+
function isPack(value) {
|
|
16
|
+
return typeof value === 'string' && PACKS.includes(value);
|
|
17
|
+
}
|
|
18
|
+
function isMode(value) {
|
|
19
|
+
return typeof value === 'string' && MODES.includes(value);
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Reads a persisted `{ pack, mode }` object.
|
|
23
|
+
*
|
|
24
|
+
* Returns `null` for anything that is not a valid pair, so a corrupt or
|
|
25
|
+
* superseded stored value falls back to the defaults rather than to a pack that
|
|
26
|
+
* does not exist. Parsing is deliberately strict: the store is owned by
|
|
27
|
+
* `PrismProvider`, which always writes this exact shape.
|
|
28
|
+
*/
|
|
29
|
+
export function parseStoredTheme(raw) {
|
|
30
|
+
if (!raw)
|
|
31
|
+
return null;
|
|
32
|
+
let parsed;
|
|
33
|
+
try {
|
|
34
|
+
parsed = JSON.parse(raw);
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
if (typeof parsed !== 'object' || parsed === null)
|
|
40
|
+
return null;
|
|
41
|
+
const { pack, mode } = parsed;
|
|
42
|
+
if (!isPack(pack) || !isMode(mode))
|
|
43
|
+
return null;
|
|
44
|
+
return { pack, mode };
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Turns a pack and mode into the two markup attributes that express them.
|
|
48
|
+
*
|
|
49
|
+
* Returns attributes, never CSS values: a Server Component spreads the result
|
|
50
|
+
* onto `<html>` and gets the declarative form with no client runtime. `default`
|
|
51
|
+
* is expressed by omitting `data-pack`; light is expressed by omitting `dark`.
|
|
52
|
+
*/
|
|
53
|
+
export function themeAttributes({ pack, mode, }) {
|
|
54
|
+
const attributes = {};
|
|
55
|
+
if (pack !== 'default')
|
|
56
|
+
attributes[PACK_ATTRIBUTE] = pack;
|
|
57
|
+
if (mode === 'dark')
|
|
58
|
+
attributes.className = 'dark';
|
|
59
|
+
return attributes;
|
|
60
|
+
}
|
package/package.json
CHANGED
|
@@ -1,48 +1,109 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nanisoft/prism-ui",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.1",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"description": "
|
|
5
|
+
"description": "Prism's React component, block and page library.",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"author": "NaniSoft",
|
|
8
8
|
"homepage": "https://prism.nanisoft.com",
|
|
9
9
|
"repository": {
|
|
10
10
|
"type": "git",
|
|
11
|
-
"url": "https://github.com/NaniSoft/prism.git",
|
|
11
|
+
"url": "git+https://github.com/NaniSoft/prism.git",
|
|
12
12
|
"directory": "packages/ui"
|
|
13
13
|
},
|
|
14
|
+
"sideEffects": [
|
|
15
|
+
"**/*.css"
|
|
16
|
+
],
|
|
17
|
+
"types": "./dist/index.d.ts",
|
|
14
18
|
"exports": {
|
|
15
|
-
"
|
|
16
|
-
|
|
19
|
+
".": {
|
|
20
|
+
"types": "./dist/index.d.ts",
|
|
21
|
+
"default": "./dist/index.js"
|
|
22
|
+
},
|
|
23
|
+
"./provider": {
|
|
24
|
+
"types": "./dist/provider/index.d.ts",
|
|
25
|
+
"default": "./dist/provider/index.js"
|
|
26
|
+
},
|
|
27
|
+
"./components": {
|
|
28
|
+
"types": "./dist/components/index.d.ts",
|
|
29
|
+
"default": "./dist/components/index.js"
|
|
30
|
+
},
|
|
31
|
+
"./components/*": {
|
|
32
|
+
"types": "./dist/components/ui/*.d.ts",
|
|
33
|
+
"default": "./dist/components/ui/*.js"
|
|
34
|
+
},
|
|
35
|
+
"./blocks": {
|
|
36
|
+
"types": "./dist/blocks/index.d.ts",
|
|
37
|
+
"default": "./dist/blocks/index.js"
|
|
38
|
+
},
|
|
39
|
+
"./blocks/*": {
|
|
40
|
+
"types": "./dist/blocks/*/index.d.ts",
|
|
41
|
+
"default": "./dist/blocks/*/index.js"
|
|
42
|
+
},
|
|
43
|
+
"./pages": {
|
|
44
|
+
"types": "./dist/pages/index.d.ts",
|
|
45
|
+
"default": "./dist/pages/index.js"
|
|
46
|
+
},
|
|
47
|
+
"./pages/*": {
|
|
48
|
+
"types": "./dist/pages/*/index.d.ts",
|
|
49
|
+
"default": "./dist/pages/*/index.js"
|
|
50
|
+
},
|
|
51
|
+
"./theming": {
|
|
52
|
+
"types": "./dist/theming/index.d.ts",
|
|
53
|
+
"default": "./dist/theming/index.js"
|
|
54
|
+
},
|
|
55
|
+
"./catalog": {
|
|
56
|
+
"types": "./dist/catalog.d.ts",
|
|
57
|
+
"default": "./dist/catalog.js"
|
|
58
|
+
},
|
|
59
|
+
"./styles.css": "./dist/styles.css",
|
|
17
60
|
"./package.json": "./package.json"
|
|
18
61
|
},
|
|
19
62
|
"files": [
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
"public/r",
|
|
23
|
-
"components.json"
|
|
63
|
+
"dist",
|
|
64
|
+
"THIRD-PARTY-NOTICES.md"
|
|
24
65
|
],
|
|
66
|
+
"engines": {
|
|
67
|
+
"node": ">=22.14.0"
|
|
68
|
+
},
|
|
25
69
|
"publishConfig": {
|
|
26
70
|
"access": "public"
|
|
27
71
|
},
|
|
28
|
-
"scripts": {
|
|
29
|
-
"sync": "node scripts/sync-registry.mjs",
|
|
30
|
-
"validate": "node scripts/validate-registry.mjs",
|
|
31
|
-
"build": "pnpm sync && pnpm validate && shadcn build",
|
|
32
|
-
"typecheck": "tsc --noEmit"
|
|
33
|
-
},
|
|
34
72
|
"dependencies": {
|
|
35
73
|
"@base-ui/react": "^1.0.0",
|
|
36
74
|
"class-variance-authority": "^0.7.1",
|
|
37
75
|
"clsx": "^2.1.1",
|
|
38
76
|
"lucide-react": "^0.545.0",
|
|
39
|
-
"tailwind-merge": "^3.3.1"
|
|
77
|
+
"tailwind-merge": "^3.3.1",
|
|
78
|
+
"@nanisoft/prism-tokens": "0.5.1"
|
|
40
79
|
},
|
|
41
80
|
"devDependencies": {
|
|
81
|
+
"@tailwindcss/postcss": "^4.3.3",
|
|
82
|
+
"@testing-library/dom": "^10.4.1",
|
|
83
|
+
"@testing-library/jest-dom": "^6.9.1",
|
|
84
|
+
"@testing-library/react": "^16.3.0",
|
|
85
|
+
"@testing-library/user-event": "^14.6.1",
|
|
42
86
|
"@types/node": "^22.0.0",
|
|
43
87
|
"@types/react": "^19.2.0",
|
|
44
88
|
"@types/react-dom": "^19.2.0",
|
|
89
|
+
"axe-core": "^4.13.0",
|
|
90
|
+
"esbuild": "^0.28.0",
|
|
91
|
+
"jsdom": "^26.1.0",
|
|
92
|
+
"postcss": "^8.5.28",
|
|
93
|
+
"react": "^19.2.0",
|
|
94
|
+
"react-dom": "^19.2.0",
|
|
45
95
|
"shadcn": "^3.6.0",
|
|
46
|
-
"
|
|
96
|
+
"tailwindcss": "^4.3.3",
|
|
97
|
+
"typescript": "^5.7.0",
|
|
98
|
+
"vitest": "^3.2.4"
|
|
99
|
+
},
|
|
100
|
+
"scripts": {
|
|
101
|
+
"sync": "node scripts/sync-registry.mjs",
|
|
102
|
+
"validate": "node scripts/validate-registry.mjs",
|
|
103
|
+
"build": "node scripts/build.mjs && pnpm sync && pnpm validate && shadcn build && node scripts/check-surface.mjs",
|
|
104
|
+
"check": "node scripts/validate-registry.mjs && node scripts/check-surface.mjs && node scripts/check-client-budget.mjs",
|
|
105
|
+
"check:client-budget": "node scripts/check-client-budget.mjs",
|
|
106
|
+
"test": "vitest run",
|
|
107
|
+
"typecheck": "tsc --noEmit"
|
|
47
108
|
}
|
|
48
|
-
}
|
|
109
|
+
}
|
package/components.json
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://ui.shadcn.com/schema.json",
|
|
3
|
-
"style": "base-nova",
|
|
4
|
-
"rsc": true,
|
|
5
|
-
"tsx": true,
|
|
6
|
-
"tailwind": {
|
|
7
|
-
"config": "",
|
|
8
|
-
"css": "src/app/globals.css",
|
|
9
|
-
"baseColor": "neutral",
|
|
10
|
-
"cssVariables": true,
|
|
11
|
-
"prefix": ""
|
|
12
|
-
},
|
|
13
|
-
"iconLibrary": "lucide",
|
|
14
|
-
"aliases": {
|
|
15
|
-
"components": "@/components",
|
|
16
|
-
"utils": "@/lib/utils",
|
|
17
|
-
"ui": "@/components/ui",
|
|
18
|
-
"lib": "@/lib",
|
|
19
|
-
"hooks": "@/hooks"
|
|
20
|
-
}
|
|
21
|
-
}
|
package/public/r/badge.json
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
|
3
|
-
"name": "badge",
|
|
4
|
-
"title": "Badge",
|
|
5
|
-
"description": "Shared badge primitive. Installed automatically as a dependency of any block that uses it.",
|
|
6
|
-
"dependencies": [
|
|
7
|
-
"class-variance-authority",
|
|
8
|
-
"clsx",
|
|
9
|
-
"tailwind-merge"
|
|
10
|
-
],
|
|
11
|
-
"files": [
|
|
12
|
-
{
|
|
13
|
-
"path": "src/components/ui/badge.tsx",
|
|
14
|
-
"content": "import { cva, type VariantProps } from 'class-variance-authority'\nimport type { ComponentProps } from 'react'\n\nimport { cn } from '@/lib/utils'\n\nconst badgeVariants = cva(\n 'inline-flex w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-md border px-2 py-0.5 text-xs font-medium whitespace-nowrap transition-colors',\n {\n variants: {\n variant: {\n default: 'bg-primary text-primary-foreground border-transparent',\n secondary: 'bg-secondary text-secondary-foreground border-transparent',\n destructive: 'bg-destructive text-destructive-foreground border-transparent',\n success: 'bg-success text-success-foreground border-transparent',\n warning: 'bg-warning text-warning-foreground border-transparent',\n outline: 'text-foreground border-border',\n },\n },\n defaultVariants: { variant: 'default' },\n },\n)\n\nfunction Badge({\n className,\n variant,\n ...props\n}: ComponentProps<'span'> & VariantProps<typeof badgeVariants>) {\n return (\n <span\n data-slot=\"badge\"\n className={cn(badgeVariants({ variant }), className)}\n {...props}\n />\n )\n}\n\nexport { Badge, badgeVariants }\n",
|
|
15
|
-
"type": "registry:component",
|
|
16
|
-
"target": "components/ui/badge.tsx"
|
|
17
|
-
},
|
|
18
|
-
{
|
|
19
|
-
"path": "src/lib/utils.ts",
|
|
20
|
-
"content": "import { type ClassValue, clsx } from 'clsx'\nimport { twMerge } from 'tailwind-merge'\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n",
|
|
21
|
-
"type": "registry:lib",
|
|
22
|
-
"target": "lib/utils.ts"
|
|
23
|
-
}
|
|
24
|
-
],
|
|
25
|
-
"type": "registry:component"
|
|
26
|
-
}
|
package/public/r/button.json
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
|
3
|
-
"name": "button",
|
|
4
|
-
"title": "Button",
|
|
5
|
-
"description": "Shared button primitive. Installed automatically as a dependency of any block that uses it.",
|
|
6
|
-
"dependencies": [
|
|
7
|
-
"class-variance-authority",
|
|
8
|
-
"clsx",
|
|
9
|
-
"tailwind-merge"
|
|
10
|
-
],
|
|
11
|
-
"files": [
|
|
12
|
-
{
|
|
13
|
-
"path": "src/components/ui/button.tsx",
|
|
14
|
-
"content": "import { cva, type VariantProps } from 'class-variance-authority'\nimport type { ComponentProps } from 'react'\n\nimport { cn } from '@/lib/utils'\n\nconst buttonVariants = cva(\n // The focus ring is `ring-ring` at full strength, not shadcn's stock\n // `focus-visible:ring-ring/50`. The token build pins `--ring` to a step that\n // clears 3:1 against the surface, and half alpha throws that away: 50% of this\n // ring composites to between 1.14:1 and 2.74:1 against every surface in all\n // six themes and clears 3:1 in none of them, which fails WCAG 1.4.11 on the one\n // indicator a keyboard user has. The stock value is kept here deliberately as a\n // deviation from upstream: a consumer's button must not fail the threshold the\n // ring exists to meet.\n \"inline-flex shrink-0 items-center justify-center gap-2 rounded-md text-sm font-medium outline-none transition-[color,box-shadow,background-color] disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:shrink-0 focus-visible:border-ring focus-visible:ring-ring focus-visible:ring-[3px] aria-invalid:ring-destructive/20 aria-invalid:border-destructive\",\n {\n variants: {\n variant: {\n default: 'bg-primary text-primary-foreground shadow-xs hover:bg-primary/90',\n destructive:\n 'bg-destructive text-destructive-foreground shadow-xs hover:bg-destructive/90',\n outline:\n 'border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground',\n secondary:\n 'bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80',\n ghost: 'hover:bg-accent hover:text-accent-foreground',\n // `primary` is a surface token, not a text token: in the pastel themes it\n // compiles to a light tint (e.g. #ec88a0) that fails 4.5:1 on the page\n // background. Link text uses the foreground and keeps the underline as its\n // affordance, so emphasis comes from weight rather than a failing colour.\n link: 'text-foreground underline-offset-4 hover:underline',\n },\n // Touch targets are enlarged by input method, not by viewport. The\n // metrics below are the designed desktop sizes and stay untouched for\n // mouse and trackpad; only a coarse pointer — finger or stylus — gets\n // the 44px iOS/Android HIG target. `pointer-coarse:` compiles to\n // `@media (pointer: coarse)` inside `@layer utilities`, which lands\n // after the base utility in the cascade, so it wins without needing\n // `!important` or a specificity fight.\n //\n // `min-w-11` is what makes the second axis safe: an icon-only `default`\n // is `size-4` plus `px-3` = 40px wide and an icon-only `sm` is `size-4`\n // plus `px-2.5` = 36px, so growing the height alone would still leave\n // both under 44px across. The coarse padding step on `default` lifts the\n // common cases clear of the floor outright, and `min-w-11` backstops\n // whatever content a consumer passes.\n size: {\n default:\n 'h-9 px-4 py-2 has-[>svg]:px-3 pointer-coarse:h-11 pointer-coarse:min-w-11 pointer-coarse:px-5 pointer-coarse:has-[>svg]:px-4',\n sm: 'h-8 gap-1.5 rounded-md px-3 has-[>svg]:px-2.5 pointer-coarse:h-11 pointer-coarse:min-w-11',\n lg: 'h-10 rounded-md px-6 has-[>svg]:px-4 pointer-coarse:h-11',\n icon: 'size-9 pointer-coarse:size-11',\n },\n },\n defaultVariants: {\n variant: 'default',\n size: 'default',\n },\n },\n)\n\nfunction Button({\n className,\n variant,\n size,\n ...props\n}: ComponentProps<'button'> & VariantProps<typeof buttonVariants>) {\n return (\n <button\n data-slot=\"button\"\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n )\n}\n\nexport { Button, buttonVariants }\n",
|
|
15
|
-
"type": "registry:component",
|
|
16
|
-
"target": "components/ui/button.tsx"
|
|
17
|
-
},
|
|
18
|
-
{
|
|
19
|
-
"path": "src/lib/utils.ts",
|
|
20
|
-
"content": "import { type ClassValue, clsx } from 'clsx'\nimport { twMerge } from 'tailwind-merge'\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n",
|
|
21
|
-
"type": "registry:lib",
|
|
22
|
-
"target": "lib/utils.ts"
|
|
23
|
-
}
|
|
24
|
-
],
|
|
25
|
-
"type": "registry:component"
|
|
26
|
-
}
|
package/public/r/card.json
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
|
3
|
-
"name": "card",
|
|
4
|
-
"title": "Card",
|
|
5
|
-
"description": "Shared card primitive. Installed automatically as a dependency of any block that uses it.",
|
|
6
|
-
"dependencies": [
|
|
7
|
-
"clsx",
|
|
8
|
-
"tailwind-merge"
|
|
9
|
-
],
|
|
10
|
-
"files": [
|
|
11
|
-
{
|
|
12
|
-
"path": "src/components/ui/card.tsx",
|
|
13
|
-
"content": "import type { ComponentProps } from 'react'\n\nimport { cn } from '@/lib/utils'\n\nfunction Card({ className, ...props }: ComponentProps<'div'>) {\n return (\n <div\n data-slot=\"card\"\n className={cn(\n 'bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm',\n className,\n )}\n {...props}\n />\n )\n}\n\nfunction CardHeader({ className, ...props }: ComponentProps<'div'>) {\n return (\n <div\n data-slot=\"card-header\"\n className={cn(\n '@container/card-header grid auto-rows-min items-start gap-1.5 px-6',\n className,\n )}\n {...props}\n />\n )\n}\n\nfunction CardTitle({ className, ...props }: ComponentProps<'div'>) {\n return (\n <div\n data-slot=\"card-title\"\n className={cn('font-semibold leading-none', className)}\n {...props}\n />\n )\n}\n\nfunction CardDescription({ className, ...props }: ComponentProps<'div'>) {\n return (\n <div\n data-slot=\"card-description\"\n className={cn('text-muted-foreground text-sm', className)}\n {...props}\n />\n )\n}\n\nfunction CardContent({ className, ...props }: ComponentProps<'div'>) {\n return <div data-slot=\"card-content\" className={cn('px-6', className)} {...props} />\n}\n\nfunction CardFooter({ className, ...props }: ComponentProps<'div'>) {\n return (\n <div\n data-slot=\"card-footer\"\n className={cn('flex items-center px-6', className)}\n {...props}\n />\n )\n}\n\nexport { Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter }\n",
|
|
14
|
-
"type": "registry:component",
|
|
15
|
-
"target": "components/ui/card.tsx"
|
|
16
|
-
},
|
|
17
|
-
{
|
|
18
|
-
"path": "src/lib/utils.ts",
|
|
19
|
-
"content": "import { type ClassValue, clsx } from 'clsx'\nimport { twMerge } from 'tailwind-merge'\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n",
|
|
20
|
-
"type": "registry:lib",
|
|
21
|
-
"target": "lib/utils.ts"
|
|
22
|
-
}
|
|
23
|
-
],
|
|
24
|
-
"type": "registry:component"
|
|
25
|
-
}
|
package/public/r/cta-01.json
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
|
3
|
-
"name": "cta-01",
|
|
4
|
-
"title": "CTA 01 - Filled Banner",
|
|
5
|
-
"description": "A closing call to action on a filled primary surface. Headline, supporting line and the action are passed in as props.",
|
|
6
|
-
"dependencies": [
|
|
7
|
-
"clsx",
|
|
8
|
-
"lucide-react",
|
|
9
|
-
"tailwind-merge"
|
|
10
|
-
],
|
|
11
|
-
"registryDependencies": [
|
|
12
|
-
"button"
|
|
13
|
-
],
|
|
14
|
-
"files": [
|
|
15
|
-
{
|
|
16
|
-
"path": "src/components/ds/blocks/cta-01/cta.tsx",
|
|
17
|
-
"content": "import { ArrowRight } from 'lucide-react'\n\nimport { Button } from '@/components/ui/button'\nimport { Section, type HeadingLevel } from '@/components/ds/blocks/section'\n\nexport type Cta01Props = {\n title: string\n description?: string\n action?: { label: string; href?: string; variant?: 'default' | 'secondary' | 'outline' }\n /** Heading level for the headline. See `HeadingLevel`. */\n headingLevel?: HeadingLevel\n}\n\n/**\n * A closing call to action on a filled primary surface.\n *\n * The copy and the action are props. It previously shipped the catalog's own\n * pitch (\"Start with one block, keep the tokens\") and a hardcoded \"Browse the\n * catalog\" button, both of which described the library rather than whatever\n * product installed the block.\n */\nexport function Cta01({ title, description, action, headingLevel = 'h2' }: Cta01Props) {\n /*\n * The same mechanism `SectionHeading` uses for its own `as` prop, which this\n * block cannot borrow: its copy sits on a filled `bg-primary` surface, where\n * `SectionHeading`'s muted-surface description colour and `gap-4` would be\n * wrong. So the tag is resolved here and the classes stay surface-specific\n * rather than the heading level being the reason the markup stays hardcoded.\n */\n const Heading = headingLevel\n\n return (\n <Section className=\"py-20\">\n <div className=\"bg-primary text-primary-foreground relative overflow-hidden rounded-2xl px-8 py-16 text-center\">\n <div\n aria-hidden\n className=\"from-primary-foreground/15 pointer-events-none absolute inset-0 bg-gradient-to-tr to-transparent\"\n />\n <div className=\"relative flex flex-col items-center gap-6\">\n <Heading className=\"max-w-2xl text-3xl font-semibold tracking-tight text-balance sm:text-4xl\">\n {title}\n </Heading>\n {description ? (\n <p className=\"max-w-xl text-lg text-pretty opacity-90\">{description}</p>\n ) : null}\n {action ? (\n <Button\n size=\"lg\"\n variant={action.variant ?? 'secondary'}\n className=\"group\"\n >\n {action.label}\n <ArrowRight className=\"motion-safe:transition-transform size-4 group-hover:translate-x-0.5\" />\n </Button>\n ) : null}\n </div>\n </div>\n </Section>\n )\n}\n\nexport default Cta01\n",
|
|
18
|
-
"type": "registry:component",
|
|
19
|
-
"target": "components/ds/blocks/cta-01/cta.tsx"
|
|
20
|
-
},
|
|
21
|
-
{
|
|
22
|
-
"path": "src/components/ds/blocks/cta-01/index.tsx",
|
|
23
|
-
"content": "export { Cta01, default } from './cta'\r\n",
|
|
24
|
-
"type": "registry:component",
|
|
25
|
-
"target": "components/ds/blocks/cta-01/index.tsx"
|
|
26
|
-
},
|
|
27
|
-
{
|
|
28
|
-
"path": "src/components/ds/blocks/section.tsx",
|
|
29
|
-
"content": "import type { ReactNode } from 'react'\nimport { cn } from '@/lib/utils'\n\n/**\n * Container primitive. Every block composes its own section from this so vertical\n * rhythm stays consistent across the catalog instead of being re-invented per block.\n */\nexport function Section({\n className,\n children,\n ...props\n}: React.ComponentProps<'section'>) {\n return (\n <section\n className={cn('py-16 sm:py-24', className)}\n {...props}\n >\n <div className=\"mx-auto w-full max-w-6xl px-6 lg:px-8\">\n {children}\n </div>\n </section>\n )\n}\n\n/**\n * The six heading levels a block can be composed at.\n *\n * Every block takes a `headingLevel` prop typed with this and forwards it to the\n * one heading it renders, so the surrounding document decides where the block\n * sits in the outline rather than the block deciding for itself. `h2` is the\n * default because a block is composed, not a page.\n *\n * A block rendered where the document *already* owns a heading for the same\n * content passes one level deeper. A catalog card already names the block in its\n * own `h2`, so the copy of the block embedded inside that card passes `h3`: the\n * embedded heading then reads as a child of the card that introduces it instead\n * of as a second, competing sibling. This is a fact about where the block was\n * placed, not about the block, which is why it is a prop and not a default.\n */\nexport type HeadingLevel = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'\n\nexport function SectionHeading({\n eyebrow,\n title,\n as: Heading = 'h2',\n description,\n align = 'center',\n className,\n}: {\n eyebrow?: ReactNode\n title: ReactNode\n description?: ReactNode\n align?: 'center' | 'left'\n /**\n * Heading level. Defaults to `h2` because blocks compose under a page heading.\n * A page that renders a block as its primary heading passes `as=\"h1\"` — a\n * document with no `h1` gives screen-reader and search engines no top-level\n * entry point.\n */\n as?: HeadingLevel\n className?: string\n}) {\n return (\n <div\n className={cn(\n 'flex flex-col gap-4',\n align === 'center' ? 'items-center text-center' : 'items-start text-left',\n className,\n )}\n >\n {eyebrow ? (\n <span className=\"text-muted-foreground text-sm font-medium tracking-wide uppercase\">\n {eyebrow}\n </span>\n ) : null}\n <Heading className=\"text-3xl font-semibold tracking-tight text-balance sm:text-4xl\">\n {title}\n </Heading>\n {description ? (\n <p className=\"text-muted-foreground max-w-2xl text-lg text-pretty\">\n {description}\n </p>\n ) : null}\n </div>\n )\n}\n",
|
|
30
|
-
"type": "registry:component",
|
|
31
|
-
"target": "components/ds/blocks/section.tsx"
|
|
32
|
-
},
|
|
33
|
-
{
|
|
34
|
-
"path": "src/lib/utils.ts",
|
|
35
|
-
"content": "import { type ClassValue, clsx } from 'clsx'\nimport { twMerge } from 'tailwind-merge'\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n",
|
|
36
|
-
"type": "registry:lib",
|
|
37
|
-
"target": "lib/utils.ts"
|
|
38
|
-
}
|
|
39
|
-
],
|
|
40
|
-
"categories": [
|
|
41
|
-
"marketing"
|
|
42
|
-
],
|
|
43
|
-
"type": "registry:block"
|
|
44
|
-
}
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
|
3
|
-
"name": "feature-grid-01",
|
|
4
|
-
"title": "Feature Grid 01 - Four Up With Icons",
|
|
5
|
-
"description": "A four-up feature grid with icon tiles. Pass the items in; the section heading is optional.",
|
|
6
|
-
"dependencies": [
|
|
7
|
-
"clsx",
|
|
8
|
-
"lucide-react",
|
|
9
|
-
"tailwind-merge"
|
|
10
|
-
],
|
|
11
|
-
"registryDependencies": [
|
|
12
|
-
"card"
|
|
13
|
-
],
|
|
14
|
-
"files": [
|
|
15
|
-
{
|
|
16
|
-
"path": "src/components/ds/blocks/feature-grid-01/feature-grid.tsx",
|
|
17
|
-
"content": "import type { LucideIcon } from 'lucide-react'\n\nimport { Card, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'\nimport { Section, SectionHeading, type HeadingLevel } from '@/components/ds/blocks/section'\n\nexport type Feature = {\n icon: LucideIcon\n title: string\n body: string\n}\n\nexport type FeatureGrid01Props = {\n eyebrow?: string\n title?: string\n description?: string\n features: Feature[]\n /** `icon` tiles read well at 2-up; `bare` leans on the type alone. */\n variant?: 'icon' | 'bare'\n /** Heading level for the section title. See `HeadingLevel`. */\n headingLevel?: HeadingLevel\n}\n\n/**\n * A grid of short feature blurbs.\n *\n * The feature list is a prop. It previously hardcoded the catalog's own selling\n * points under the heading \"Why this catalog\", so an installed block argued for\n * the library inside the consumer's product.\n */\nexport function FeatureGrid01({\n eyebrow,\n title,\n description,\n features,\n variant = 'icon',\n headingLevel = 'h2',\n}: FeatureGrid01Props) {\n return (\n <Section>\n {title ? (\n <SectionHeading\n as={headingLevel}\n eyebrow={eyebrow}\n title={title}\n description={description}\n className=\"mb-12\"\n />\n ) : null}\n\n <div className=\"grid gap-6 sm:grid-cols-2\">\n {features.map((feature) => (\n <Card key={feature.title} className=\"gap-4 py-6\">\n <CardHeader>\n {variant === 'icon' ? (\n <span className=\"bg-accent text-accent-foreground mb-2 flex size-10 items-center justify-center rounded-lg\">\n <feature.icon className=\"size-5\" />\n </span>\n ) : null}\n <CardTitle>{feature.title}</CardTitle>\n <CardDescription>{feature.body}</CardDescription>\n </CardHeader>\n </Card>\n ))}\n </div>\n </Section>\n )\n}\n\nexport default FeatureGrid01\n",
|
|
18
|
-
"type": "registry:component",
|
|
19
|
-
"target": "components/ds/blocks/feature-grid-01/feature-grid.tsx"
|
|
20
|
-
},
|
|
21
|
-
{
|
|
22
|
-
"path": "src/components/ds/blocks/feature-grid-01/index.tsx",
|
|
23
|
-
"content": "export { FeatureGrid01, default } from './feature-grid'\r\n",
|
|
24
|
-
"type": "registry:component",
|
|
25
|
-
"target": "components/ds/blocks/feature-grid-01/index.tsx"
|
|
26
|
-
},
|
|
27
|
-
{
|
|
28
|
-
"path": "src/components/ds/blocks/section.tsx",
|
|
29
|
-
"content": "import type { ReactNode } from 'react'\nimport { cn } from '@/lib/utils'\n\n/**\n * Container primitive. Every block composes its own section from this so vertical\n * rhythm stays consistent across the catalog instead of being re-invented per block.\n */\nexport function Section({\n className,\n children,\n ...props\n}: React.ComponentProps<'section'>) {\n return (\n <section\n className={cn('py-16 sm:py-24', className)}\n {...props}\n >\n <div className=\"mx-auto w-full max-w-6xl px-6 lg:px-8\">\n {children}\n </div>\n </section>\n )\n}\n\n/**\n * The six heading levels a block can be composed at.\n *\n * Every block takes a `headingLevel` prop typed with this and forwards it to the\n * one heading it renders, so the surrounding document decides where the block\n * sits in the outline rather than the block deciding for itself. `h2` is the\n * default because a block is composed, not a page.\n *\n * A block rendered where the document *already* owns a heading for the same\n * content passes one level deeper. A catalog card already names the block in its\n * own `h2`, so the copy of the block embedded inside that card passes `h3`: the\n * embedded heading then reads as a child of the card that introduces it instead\n * of as a second, competing sibling. This is a fact about where the block was\n * placed, not about the block, which is why it is a prop and not a default.\n */\nexport type HeadingLevel = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'\n\nexport function SectionHeading({\n eyebrow,\n title,\n as: Heading = 'h2',\n description,\n align = 'center',\n className,\n}: {\n eyebrow?: ReactNode\n title: ReactNode\n description?: ReactNode\n align?: 'center' | 'left'\n /**\n * Heading level. Defaults to `h2` because blocks compose under a page heading.\n * A page that renders a block as its primary heading passes `as=\"h1\"` — a\n * document with no `h1` gives screen-reader and search engines no top-level\n * entry point.\n */\n as?: HeadingLevel\n className?: string\n}) {\n return (\n <div\n className={cn(\n 'flex flex-col gap-4',\n align === 'center' ? 'items-center text-center' : 'items-start text-left',\n className,\n )}\n >\n {eyebrow ? (\n <span className=\"text-muted-foreground text-sm font-medium tracking-wide uppercase\">\n {eyebrow}\n </span>\n ) : null}\n <Heading className=\"text-3xl font-semibold tracking-tight text-balance sm:text-4xl\">\n {title}\n </Heading>\n {description ? (\n <p className=\"text-muted-foreground max-w-2xl text-lg text-pretty\">\n {description}\n </p>\n ) : null}\n </div>\n )\n}\n",
|
|
30
|
-
"type": "registry:component",
|
|
31
|
-
"target": "components/ds/blocks/section.tsx"
|
|
32
|
-
},
|
|
33
|
-
{
|
|
34
|
-
"path": "src/lib/utils.ts",
|
|
35
|
-
"content": "import { type ClassValue, clsx } from 'clsx'\nimport { twMerge } from 'tailwind-merge'\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n",
|
|
36
|
-
"type": "registry:lib",
|
|
37
|
-
"target": "lib/utils.ts"
|
|
38
|
-
}
|
|
39
|
-
],
|
|
40
|
-
"categories": [
|
|
41
|
-
"marketing"
|
|
42
|
-
],
|
|
43
|
-
"type": "registry:block"
|
|
44
|
-
}
|
package/public/r/hero-01.json
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
|
3
|
-
"name": "hero-01",
|
|
4
|
-
"title": "Hero 01 - Centered Marketing Hero",
|
|
5
|
-
"description": "A centered hero with an optional eyebrow, headline, supporting line and one or two actions. All copy is passed in as props.",
|
|
6
|
-
"dependencies": [
|
|
7
|
-
"clsx",
|
|
8
|
-
"lucide-react",
|
|
9
|
-
"tailwind-merge"
|
|
10
|
-
],
|
|
11
|
-
"registryDependencies": [
|
|
12
|
-
"button"
|
|
13
|
-
],
|
|
14
|
-
"files": [
|
|
15
|
-
{
|
|
16
|
-
"path": "src/components/ds/blocks/hero-01/hero.tsx",
|
|
17
|
-
"content": "import { ArrowRight } from 'lucide-react'\n\nimport { Button } from '@/components/ui/button'\nimport { Section, SectionHeading, type HeadingLevel } from '@/components/ds/blocks/section'\n\nexport type HeroAction = {\n label: string\n href?: string\n variant?: 'default' | 'outline' | 'secondary' | 'ghost'\n}\n\nexport type Hero01Props = {\n /**\n * Optional label above the headline. Intentionally has no default: an earlier\n * version shipped a hardcoded \"Now in open beta\" pill, which meant every\n * consumer who installed this block inherited a status badge making a claim\n * about their product. Pass one if you mean it.\n */\n eyebrow?: string\n title: string\n description?: string\n actions?: HeroAction[]\n /**\n * Heading level for the title. Defaults to `h2` because a block is composed,\n * not a page: it installs into a consumer's layout via `shadcn add` and renders\n * inside catalog previews, so the surrounding document already owns the `h1`.\n * A page that uses this block as its top-level heading opts in with\n * `headingLevel=\"h1\"`; a document that already names this section in its own\n * heading passes one level deeper. See `HeadingLevel`.\n */\n headingLevel?: HeadingLevel\n}\n\nexport function Hero01({\n eyebrow,\n title,\n description,\n actions = [],\n headingLevel = 'h2',\n}: Hero01Props) {\n return (\n <Section className=\"relative overflow-hidden\">\n <div\n aria-hidden\n className=\"from-primary/5 pointer-events-none absolute inset-0 -z-10 bg-gradient-to-b to-transparent\"\n />\n <div className=\"flex flex-col items-center gap-10 text-center\">\n {eyebrow ? (\n <span className=\"bg-muted text-muted-foreground rounded-full px-3 py-1 text-xs font-medium\">\n {eyebrow}\n </span>\n ) : null}\n\n <SectionHeading\n as={headingLevel}\n title={title}\n description={description}\n />\n\n {actions.length ? (\n <div className=\"flex flex-col gap-3 sm:flex-row\">\n {actions.map((action, index) => (\n // Positional, for the same reason as `pricing-01`'s feature list:\n // the label is display content, and two actions may share one.\n // Safe here because the list is static and never reordered.\n <Button\n key={index}\n size=\"lg\"\n variant={action.variant ?? (index === 0 ? 'default' : 'outline')}\n className=\"group\"\n >\n {action.label}\n {index === 0 ? (\n <ArrowRight className=\"motion-safe:transition-transform size-4 group-hover:translate-x-0.5\" />\n ) : null}\n </Button>\n ))}\n </div>\n ) : null}\n </div>\n </Section>\n )\n}\n\nexport default Hero01\n",
|
|
18
|
-
"type": "registry:component",
|
|
19
|
-
"target": "components/ds/blocks/hero-01/hero.tsx"
|
|
20
|
-
},
|
|
21
|
-
{
|
|
22
|
-
"path": "src/components/ds/blocks/hero-01/index.tsx",
|
|
23
|
-
"content": "export { Hero01, default } from './hero'\n",
|
|
24
|
-
"type": "registry:component",
|
|
25
|
-
"target": "components/ds/blocks/hero-01/index.tsx"
|
|
26
|
-
},
|
|
27
|
-
{
|
|
28
|
-
"path": "src/components/ds/blocks/section.tsx",
|
|
29
|
-
"content": "import type { ReactNode } from 'react'\nimport { cn } from '@/lib/utils'\n\n/**\n * Container primitive. Every block composes its own section from this so vertical\n * rhythm stays consistent across the catalog instead of being re-invented per block.\n */\nexport function Section({\n className,\n children,\n ...props\n}: React.ComponentProps<'section'>) {\n return (\n <section\n className={cn('py-16 sm:py-24', className)}\n {...props}\n >\n <div className=\"mx-auto w-full max-w-6xl px-6 lg:px-8\">\n {children}\n </div>\n </section>\n )\n}\n\n/**\n * The six heading levels a block can be composed at.\n *\n * Every block takes a `headingLevel` prop typed with this and forwards it to the\n * one heading it renders, so the surrounding document decides where the block\n * sits in the outline rather than the block deciding for itself. `h2` is the\n * default because a block is composed, not a page.\n *\n * A block rendered where the document *already* owns a heading for the same\n * content passes one level deeper. A catalog card already names the block in its\n * own `h2`, so the copy of the block embedded inside that card passes `h3`: the\n * embedded heading then reads as a child of the card that introduces it instead\n * of as a second, competing sibling. This is a fact about where the block was\n * placed, not about the block, which is why it is a prop and not a default.\n */\nexport type HeadingLevel = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'\n\nexport function SectionHeading({\n eyebrow,\n title,\n as: Heading = 'h2',\n description,\n align = 'center',\n className,\n}: {\n eyebrow?: ReactNode\n title: ReactNode\n description?: ReactNode\n align?: 'center' | 'left'\n /**\n * Heading level. Defaults to `h2` because blocks compose under a page heading.\n * A page that renders a block as its primary heading passes `as=\"h1\"` — a\n * document with no `h1` gives screen-reader and search engines no top-level\n * entry point.\n */\n as?: HeadingLevel\n className?: string\n}) {\n return (\n <div\n className={cn(\n 'flex flex-col gap-4',\n align === 'center' ? 'items-center text-center' : 'items-start text-left',\n className,\n )}\n >\n {eyebrow ? (\n <span className=\"text-muted-foreground text-sm font-medium tracking-wide uppercase\">\n {eyebrow}\n </span>\n ) : null}\n <Heading className=\"text-3xl font-semibold tracking-tight text-balance sm:text-4xl\">\n {title}\n </Heading>\n {description ? (\n <p className=\"text-muted-foreground max-w-2xl text-lg text-pretty\">\n {description}\n </p>\n ) : null}\n </div>\n )\n}\n",
|
|
30
|
-
"type": "registry:component",
|
|
31
|
-
"target": "components/ds/blocks/section.tsx"
|
|
32
|
-
},
|
|
33
|
-
{
|
|
34
|
-
"path": "src/lib/utils.ts",
|
|
35
|
-
"content": "import { type ClassValue, clsx } from 'clsx'\nimport { twMerge } from 'tailwind-merge'\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n",
|
|
36
|
-
"type": "registry:lib",
|
|
37
|
-
"target": "lib/utils.ts"
|
|
38
|
-
}
|
|
39
|
-
],
|
|
40
|
-
"categories": [
|
|
41
|
-
"marketing"
|
|
42
|
-
],
|
|
43
|
-
"type": "registry:block"
|
|
44
|
-
}
|
package/public/r/pricing-01.json
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
|
3
|
-
"name": "pricing-01",
|
|
4
|
-
"title": "Pricing 01 - Three Tier With Highlight",
|
|
5
|
-
"description": "A three-up plan comparison with one plan lifted. Plans, prices, features and actions are all passed in as props.",
|
|
6
|
-
"dependencies": [
|
|
7
|
-
"clsx",
|
|
8
|
-
"lucide-react",
|
|
9
|
-
"tailwind-merge"
|
|
10
|
-
],
|
|
11
|
-
"registryDependencies": [
|
|
12
|
-
"button",
|
|
13
|
-
"badge",
|
|
14
|
-
"card"
|
|
15
|
-
],
|
|
16
|
-
"files": [
|
|
17
|
-
{
|
|
18
|
-
"path": "src/components/ds/blocks/pricing-01/index.tsx",
|
|
19
|
-
"content": "export { Pricing01, default } from './pricing'\r\n",
|
|
20
|
-
"type": "registry:component",
|
|
21
|
-
"target": "components/ds/blocks/pricing-01/index.tsx"
|
|
22
|
-
},
|
|
23
|
-
{
|
|
24
|
-
"path": "src/components/ds/blocks/pricing-01/pricing.tsx",
|
|
25
|
-
"content": "import { Check } from 'lucide-react'\n\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport {\n Card,\n CardContent,\n CardDescription,\n CardFooter,\n CardHeader,\n CardTitle,\n} from '@/components/ui/card'\nimport { Section, SectionHeading, type HeadingLevel } from '@/components/ds/blocks/section'\n\nexport type Plan = {\n name: string\n price: string\n /** Rendered after the price, e.g. \" / month\". Omit for a one-off figure. */\n period?: string\n body?: string\n features: string[]\n cta: string\n /** Lifts the plan with a primary border and a filled button. */\n featured?: boolean\n /** Overrides the \"Popular\" badge on the featured plan. */\n badge?: string\n}\n\nexport type Pricing01Props = {\n eyebrow?: string\n title?: string\n description?: string\n plans: Plan[]\n /** Heading level for the section title. See `HeadingLevel`. */\n headingLevel?: HeadingLevel\n}\n\n/**\n * A three-up plan comparison.\n *\n * Every plan is a prop, including the price and the call to action. It previously\n * hardcoded \"$0 / $24 / $68\", \"Talk to us\", \"MIT licence\" and \"Figma library\",\n * and shipped a heading reading \"Pricing\" above a title already reading \"Pick a\n * plan\". A shared library has no plans to sell, so those strings described a\n * business that does not exist here, and every consumer who installed the block\n * inherited them.\n */\nexport function Pricing01({\n eyebrow,\n title,\n description,\n plans,\n headingLevel = 'h2',\n}: Pricing01Props) {\n return (\n <Section>\n {title ? (\n <SectionHeading\n as={headingLevel}\n eyebrow={eyebrow}\n title={title}\n description={description}\n className=\"mb-12\"\n />\n ) : null}\n\n <div className=\"grid gap-6 lg:grid-cols-3\">\n {plans.map((plan) => (\n <Card\n key={plan.name}\n className={plan.featured ? 'border-primary shadow-md' : undefined}\n >\n <CardHeader>\n <div className=\"flex items-center justify-between\">\n <CardTitle>{plan.name}</CardTitle>\n {plan.featured ? <Badge>{plan.badge ?? 'Popular'}</Badge> : null}\n </div>\n {plan.body ? <CardDescription>{plan.body}</CardDescription> : null}\n <p className=\"mt-2 text-3xl font-semibold tracking-tight\">\n {plan.price}\n {plan.period ? (\n <span className=\"text-muted-foreground text-sm font-normal\">\n {plan.period}\n </span>\n ) : null}\n </p>\n </CardHeader>\n\n <CardContent className=\"flex flex-col gap-3\">\n {/*\n Keyed by position, not by the feature string. The string is display\n content rather than identity, and a plan is free to list the same\n line twice; keying on it logged React's duplicate-key error and let\n React drop and reorder rows. `key={index}` is correct here because\n this list is static: it is rendered once from props and never\n reordered, filtered or appended to, so there is no state to\n preserve across a reorder that a positional key could lose.\n */}\n {plan.features.map((feature, index) => (\n <p key={index} className=\"flex items-start gap-2 text-sm\">\n <Check className=\"text-success mt-0.5 size-4 shrink-0\" />\n {feature}\n </p>\n ))}\n </CardContent>\n\n <CardFooter className=\"mt-auto\">\n <Button\n className=\"w-full\"\n variant={plan.featured ? 'default' : 'outline'}\n >\n {plan.cta}\n </Button>\n </CardFooter>\n </Card>\n ))}\n </div>\n </Section>\n )\n}\n\nexport default Pricing01\n",
|
|
26
|
-
"type": "registry:component",
|
|
27
|
-
"target": "components/ds/blocks/pricing-01/pricing.tsx"
|
|
28
|
-
},
|
|
29
|
-
{
|
|
30
|
-
"path": "src/components/ds/blocks/section.tsx",
|
|
31
|
-
"content": "import type { ReactNode } from 'react'\nimport { cn } from '@/lib/utils'\n\n/**\n * Container primitive. Every block composes its own section from this so vertical\n * rhythm stays consistent across the catalog instead of being re-invented per block.\n */\nexport function Section({\n className,\n children,\n ...props\n}: React.ComponentProps<'section'>) {\n return (\n <section\n className={cn('py-16 sm:py-24', className)}\n {...props}\n >\n <div className=\"mx-auto w-full max-w-6xl px-6 lg:px-8\">\n {children}\n </div>\n </section>\n )\n}\n\n/**\n * The six heading levels a block can be composed at.\n *\n * Every block takes a `headingLevel` prop typed with this and forwards it to the\n * one heading it renders, so the surrounding document decides where the block\n * sits in the outline rather than the block deciding for itself. `h2` is the\n * default because a block is composed, not a page.\n *\n * A block rendered where the document *already* owns a heading for the same\n * content passes one level deeper. A catalog card already names the block in its\n * own `h2`, so the copy of the block embedded inside that card passes `h3`: the\n * embedded heading then reads as a child of the card that introduces it instead\n * of as a second, competing sibling. This is a fact about where the block was\n * placed, not about the block, which is why it is a prop and not a default.\n */\nexport type HeadingLevel = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'\n\nexport function SectionHeading({\n eyebrow,\n title,\n as: Heading = 'h2',\n description,\n align = 'center',\n className,\n}: {\n eyebrow?: ReactNode\n title: ReactNode\n description?: ReactNode\n align?: 'center' | 'left'\n /**\n * Heading level. Defaults to `h2` because blocks compose under a page heading.\n * A page that renders a block as its primary heading passes `as=\"h1\"` — a\n * document with no `h1` gives screen-reader and search engines no top-level\n * entry point.\n */\n as?: HeadingLevel\n className?: string\n}) {\n return (\n <div\n className={cn(\n 'flex flex-col gap-4',\n align === 'center' ? 'items-center text-center' : 'items-start text-left',\n className,\n )}\n >\n {eyebrow ? (\n <span className=\"text-muted-foreground text-sm font-medium tracking-wide uppercase\">\n {eyebrow}\n </span>\n ) : null}\n <Heading className=\"text-3xl font-semibold tracking-tight text-balance sm:text-4xl\">\n {title}\n </Heading>\n {description ? (\n <p className=\"text-muted-foreground max-w-2xl text-lg text-pretty\">\n {description}\n </p>\n ) : null}\n </div>\n )\n}\n",
|
|
32
|
-
"type": "registry:component",
|
|
33
|
-
"target": "components/ds/blocks/section.tsx"
|
|
34
|
-
},
|
|
35
|
-
{
|
|
36
|
-
"path": "src/lib/utils.ts",
|
|
37
|
-
"content": "import { type ClassValue, clsx } from 'clsx'\nimport { twMerge } from 'tailwind-merge'\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n",
|
|
38
|
-
"type": "registry:lib",
|
|
39
|
-
"target": "lib/utils.ts"
|
|
40
|
-
}
|
|
41
|
-
],
|
|
42
|
-
"categories": [
|
|
43
|
-
"marketing"
|
|
44
|
-
],
|
|
45
|
-
"type": "registry:block"
|
|
46
|
-
}
|