@nanisoft/prism-ui 0.5.1 → 0.7.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.
Files changed (132) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/blocks/cta-01/cta.d.ts +66 -6
  3. package/dist/blocks/cta-01/cta.d.ts.map +1 -1
  4. package/dist/blocks/cta-01/cta.js +8 -3
  5. package/dist/blocks/cta-01/index.d.ts +1 -0
  6. package/dist/blocks/cta-01/index.d.ts.map +1 -1
  7. package/dist/blocks/feature-grid-01/feature-grid.d.ts +57 -6
  8. package/dist/blocks/feature-grid-01/feature-grid.d.ts.map +1 -1
  9. package/dist/blocks/feature-grid-01/feature-grid.js +12 -2
  10. package/dist/blocks/feature-grid-01/index.d.ts +1 -0
  11. package/dist/blocks/feature-grid-01/index.d.ts.map +1 -1
  12. package/dist/blocks/hero-01/hero.d.ts +30 -1
  13. package/dist/blocks/hero-01/hero.d.ts.map +1 -1
  14. package/dist/blocks/hero-01/hero.js +14 -2
  15. package/dist/blocks/index.d.ts +10 -0
  16. package/dist/blocks/index.d.ts.map +1 -1
  17. package/dist/blocks/index.js +9 -0
  18. package/dist/blocks/instrument-panel-01/index.d.ts +3 -0
  19. package/dist/blocks/instrument-panel-01/index.d.ts.map +1 -0
  20. package/dist/blocks/instrument-panel-01/index.js +1 -0
  21. package/dist/blocks/instrument-panel-01/instrument-panel.d.ts +114 -0
  22. package/dist/blocks/instrument-panel-01/instrument-panel.d.ts.map +1 -0
  23. package/dist/blocks/instrument-panel-01/instrument-panel.js +64 -0
  24. package/dist/blocks/logo-strip-01/index.d.ts +3 -0
  25. package/dist/blocks/logo-strip-01/index.d.ts.map +1 -0
  26. package/dist/blocks/logo-strip-01/index.js +1 -0
  27. package/dist/blocks/logo-strip-01/logo-strip.d.ts +84 -0
  28. package/dist/blocks/logo-strip-01/logo-strip.d.ts.map +1 -0
  29. package/dist/blocks/logo-strip-01/logo-strip.js +40 -0
  30. package/dist/blocks/note-grid-01/index.d.ts +3 -0
  31. package/dist/blocks/note-grid-01/index.d.ts.map +1 -0
  32. package/dist/blocks/note-grid-01/index.js +1 -0
  33. package/dist/blocks/note-grid-01/note-grid.d.ts +79 -0
  34. package/dist/blocks/note-grid-01/note-grid.d.ts.map +1 -0
  35. package/dist/blocks/note-grid-01/note-grid.js +37 -0
  36. package/dist/blocks/pricing-01/pricing.js +1 -1
  37. package/dist/blocks/process-rail-01/index.d.ts +3 -0
  38. package/dist/blocks/process-rail-01/index.d.ts.map +1 -0
  39. package/dist/blocks/process-rail-01/index.js +1 -0
  40. package/dist/blocks/process-rail-01/process-rail.d.ts +99 -0
  41. package/dist/blocks/process-rail-01/process-rail.d.ts.map +1 -0
  42. package/dist/blocks/process-rail-01/process-rail.js +58 -0
  43. package/dist/blocks/product-grid-01/index.d.ts +3 -0
  44. package/dist/blocks/product-grid-01/index.d.ts.map +1 -0
  45. package/dist/blocks/product-grid-01/index.js +1 -0
  46. package/dist/blocks/product-grid-01/product-grid.d.ts +114 -0
  47. package/dist/blocks/product-grid-01/product-grid.d.ts.map +1 -0
  48. package/dist/blocks/product-grid-01/product-grid.js +51 -0
  49. package/dist/blocks/site-footer/index.d.ts +3 -0
  50. package/dist/blocks/site-footer/index.d.ts.map +1 -0
  51. package/dist/blocks/site-footer/index.js +1 -0
  52. package/dist/blocks/site-footer/site-footer.d.ts +135 -0
  53. package/dist/blocks/site-footer/site-footer.d.ts.map +1 -0
  54. package/dist/blocks/site-footer/site-footer.js +41 -0
  55. package/dist/blocks/site-header/index.d.ts +3 -0
  56. package/dist/blocks/site-header/index.d.ts.map +1 -0
  57. package/dist/blocks/site-header/index.js +1 -0
  58. package/dist/blocks/site-header/site-header.d.ts +142 -0
  59. package/dist/blocks/site-header/site-header.d.ts.map +1 -0
  60. package/dist/blocks/site-header/site-header.js +46 -0
  61. package/dist/blocks/stack-grid-01/index.d.ts +3 -0
  62. package/dist/blocks/stack-grid-01/index.d.ts.map +1 -0
  63. package/dist/blocks/stack-grid-01/index.js +1 -0
  64. package/dist/blocks/stack-grid-01/stack-grid.d.ts +118 -0
  65. package/dist/blocks/stack-grid-01/stack-grid.d.ts.map +1 -0
  66. package/dist/blocks/stack-grid-01/stack-grid.js +49 -0
  67. package/dist/blocks/status-ledger-01/index.d.ts +3 -0
  68. package/dist/blocks/status-ledger-01/index.d.ts.map +1 -0
  69. package/dist/blocks/status-ledger-01/index.js +1 -0
  70. package/dist/blocks/status-ledger-01/status-ledger.d.ts +131 -0
  71. package/dist/blocks/status-ledger-01/status-ledger.d.ts.map +1 -0
  72. package/dist/blocks/status-ledger-01/status-ledger.js +80 -0
  73. package/dist/catalog.d.ts.map +1 -1
  74. package/dist/catalog.js +180 -0
  75. package/dist/components/index.d.ts +11 -0
  76. package/dist/components/index.d.ts.map +1 -1
  77. package/dist/components/index.js +6 -0
  78. package/dist/components/ui/card.d.ts +25 -0
  79. package/dist/components/ui/card.d.ts.map +1 -1
  80. package/dist/components/ui/card.js +25 -0
  81. package/dist/components/ui/cta-link.d.ts +45 -0
  82. package/dist/components/ui/cta-link.d.ts.map +1 -0
  83. package/dist/components/ui/cta-link.js +81 -0
  84. package/dist/components/ui/diagram.d.ts +154 -0
  85. package/dist/components/ui/diagram.d.ts.map +1 -0
  86. package/dist/components/ui/diagram.js +150 -0
  87. package/dist/components/ui/fact-list.d.ts +90 -0
  88. package/dist/components/ui/fact-list.d.ts.map +1 -0
  89. package/dist/components/ui/fact-list.js +38 -0
  90. package/dist/components/ui/product-mark.d.ts +115 -0
  91. package/dist/components/ui/product-mark.d.ts.map +1 -0
  92. package/dist/components/ui/product-mark.js +82 -0
  93. package/dist/components/ui/product-switcher.d.ts +108 -0
  94. package/dist/components/ui/product-switcher.d.ts.map +1 -0
  95. package/dist/components/ui/product-switcher.js +47 -0
  96. package/dist/components/ui/prose.d.ts +88 -0
  97. package/dist/components/ui/prose.d.ts.map +1 -0
  98. package/dist/components/ui/prose.js +53 -0
  99. package/dist/components/ui/section.d.ts +24 -1
  100. package/dist/components/ui/section.d.ts.map +1 -1
  101. package/dist/components/ui/section.js +11 -2
  102. package/dist/components/ui/slider.d.ts.map +1 -1
  103. package/dist/components/ui/slider.js +7 -1
  104. package/dist/index.d.ts +24 -0
  105. package/dist/index.d.ts.map +1 -1
  106. package/dist/index.js +17 -0
  107. package/dist/pages/blog-post-page/index.d.ts +174 -0
  108. package/dist/pages/blog-post-page/index.d.ts.map +1 -0
  109. package/dist/pages/blog-post-page/index.js +49 -0
  110. package/dist/pages/docs-shell/docs-shell.d.ts +250 -0
  111. package/dist/pages/docs-shell/docs-shell.d.ts.map +1 -0
  112. package/dist/pages/docs-shell/docs-shell.js +197 -0
  113. package/dist/pages/docs-shell/index.d.ts +3 -0
  114. package/dist/pages/docs-shell/index.d.ts.map +1 -0
  115. package/dist/pages/docs-shell/index.js +1 -0
  116. package/dist/pages/index.d.ts +13 -2
  117. package/dist/pages/index.d.ts.map +1 -1
  118. package/dist/pages/index.js +10 -2
  119. package/dist/pages/not-found-page/index.d.ts +112 -0
  120. package/dist/pages/not-found-page/index.d.ts.map +1 -0
  121. package/dist/pages/not-found-page/index.js +46 -0
  122. package/dist/provider/provider.d.ts +5 -0
  123. package/dist/provider/provider.d.ts.map +1 -1
  124. package/dist/provider/provider.js +129 -38
  125. package/dist/provider/theme-script.d.ts +41 -3
  126. package/dist/provider/theme-script.d.ts.map +1 -1
  127. package/dist/provider/theme-script.js +68 -17
  128. package/dist/styles.css +555 -12
  129. package/dist/theming/index.d.ts +132 -2
  130. package/dist/theming/index.d.ts.map +1 -1
  131. package/dist/theming/index.js +127 -1
  132. package/package.json +14 -4
@@ -0,0 +1,3 @@
1
+ export { SiteFooter, default } from './site-footer';
2
+ export type { SiteFooterProps, SiteFooterColumn, SiteFooterLink, SiteFooterSocial } from './site-footer';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/blocks/site-footer/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AACnD,YAAY,EAAE,eAAe,EAAE,gBAAgB,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA"}
@@ -0,0 +1 @@
1
+ export { SiteFooter, default } from './site-footer';
@@ -0,0 +1,135 @@
1
+ import type { ReactNode } from 'react';
2
+ import { type ProductMarkProps } from '../../components/ui/product-mark';
3
+ /**
4
+ * One destination in a footer column.
5
+ *
6
+ * `href` is required. A footer link with no destination is a label, and a column
7
+ * of labels in a footer reads as a broken page rather than as an omission.
8
+ */
9
+ export type SiteFooterLink = {
10
+ /** The text of the link. */
11
+ label: string;
12
+ /** Where the link goes. */
13
+ href: string;
14
+ /**
15
+ * Opens the destination in a new browsing context, which defaults the link
16
+ * relationship to `noopener noreferrer`. Prism does not decide what counts as
17
+ * external, so the caller declares it.
18
+ */
19
+ newTab?: boolean;
20
+ };
21
+ /**
22
+ * One column of a footer's destinations: a title and the links under it.
23
+ *
24
+ * The title is required, because a column of links with no heading is a list
25
+ * that gives a reader no clue what the group is, and a footer's whole job is to
26
+ * be scannable rather than read.
27
+ */
28
+ export type SiteFooterColumn = {
29
+ /** The heading of the column, which names the group. */
30
+ title: string;
31
+ /** The destinations in the group, in the order a reader should meet them. */
32
+ links: readonly SiteFooterLink[];
33
+ };
34
+ /**
35
+ * One link out of the site: a destination with an icon beside its label.
36
+ *
37
+ * The icon is a `ReactNode` rather than a component name, because the icon is
38
+ * the consumer's: it is their brand's mark for a destination, not one of a set
39
+ * Prism owns. The label is still required, because an icon alone is not a
40
+ * destination a screen reader can announce.
41
+ */
42
+ export type SiteFooterSocial = {
43
+ /** The accessible name of the link, and the text beside the icon. */
44
+ label: string;
45
+ /** Where the link goes. */
46
+ href: string;
47
+ /**
48
+ * The mark drawn beside the label. `aria-hidden` is applied to it here, so an
49
+ * icon is a shape beside a word and never a second reading of the word.
50
+ */
51
+ icon?: ReactNode;
52
+ /**
53
+ * Opens the destination in a new browsing context, which defaults the link
54
+ * relationship to `noopener noreferrer`. A destination off the site is
55
+ * declared by the caller, because Prism does not parse URLs.
56
+ */
57
+ newTab?: boolean;
58
+ };
59
+ /**
60
+ * The props a SiteFooter takes.
61
+ *
62
+ * The product is required and nothing else is. A footer with no columns, no
63
+ * social links and no legal line is a valid footer: it is a brand lockup and
64
+ * nothing else, and one of the four NaniSoft sites is exactly that.
65
+ */
66
+ export type SiteFooterProps = {
67
+ /**
68
+ * The product this footer belongs to: the id, name and pack its `ProductMark`
69
+ * is drawn from. The footer renders the mark rather than taking a slot,
70
+ * because the brand lockup is the one part of a footer that is never
71
+ * product-specific and every consumer would otherwise reimplement it.
72
+ */
73
+ product: Pick<ProductMarkProps, 'id' | 'name' | 'pack'>;
74
+ /**
75
+ * The groups of destinations: the sections of this site, its documentation, and
76
+ * anywhere else the site sends a reader. Omit it for a footer that carries only
77
+ * the brand lockup.
78
+ */
79
+ columns?: readonly SiteFooterColumn[];
80
+ /**
81
+ * The links that leave the site. A `ReactNode` icon is drawn beside each label
82
+ * and hidden from assistive technology, so a screen reader announces the label
83
+ * once.
84
+ */
85
+ social?: readonly SiteFooterSocial[];
86
+ /**
87
+ * A slot for the line at the foot of the footer: a copyright, a licence, a
88
+ * version, a legal link. A slot rather than a prop, because every one of those
89
+ * is a fact about a specific product and about the year it was published, and a
90
+ * Block that held a year would be a Block that went stale.
91
+ */
92
+ legal?: ReactNode;
93
+ /**
94
+ * Layout only, exactly as on every Component. Changing a Prism-owned visual
95
+ * property from here is prohibited.
96
+ */
97
+ className?: string;
98
+ };
99
+ /**
100
+ * The footer of a product site: a brand lockup, grouped destinations, the links
101
+ * that leave the site, and an optional slot for the legal line.
102
+ *
103
+ * It is a Block and not a Component because it is a region of a page: it
104
+ * composes a `ProductMark` and two sets of links and owns the block they sit in.
105
+ * All four NaniSoft sites compose this exact footer in their root layout, and
106
+ * each one wrote its own column model, its own mark and its own current-page
107
+ * treatment.
108
+ *
109
+ * Every string is a prop and the Block ships none. There is no site name, no
110
+ * copyright, no year, no "built with" line and no default column: a footer that
111
+ * hardcoded any of them would hand every consumer a claim about a product that
112
+ * is not theirs and a year that was not this one.
113
+ *
114
+ * The columns are a grid that collapses to one column, and the brand lockup
115
+ * stays above them at every width. A footer read as three columns on a phone is
116
+ * three unreadable columns; a footer read as one column is a list a reader can
117
+ * scan, which is the only job a footer has on a narrow viewport.
118
+ *
119
+ * Each column is a `nav` with its own accessible name, taken from the column's
120
+ * title. A reader who navigates by landmark can therefore reach "Documentation"
121
+ * rather than arriving at one anonymous list of links.
122
+ *
123
+ * The social links open in a new browsing context by default, because a link that
124
+ * leaves the site and comes back is a reader who has lost the page they were on.
125
+ * That default is a decision this Block makes, and `newTab={false}` on one link
126
+ * overrides it: Prism does not decide which destinations are external, so the
127
+ * per-link prop wins over the default rather than the other way round.
128
+ *
129
+ * It is a server Component. It fetches nothing, it holds no state, and it
130
+ * imports no router: a consumer renders it from a server file and the links are
131
+ * plain anchors the consumer's own router can intercept.
132
+ */
133
+ export declare function SiteFooter({ product, columns, social, legal, className, }: SiteFooterProps): import("react").JSX.Element;
134
+ export default SiteFooter;
135
+ //# sourceMappingURL=site-footer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"site-footer.d.ts","sourceRoot":"","sources":["../../../src/blocks/site-footer/site-footer.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAEtC,OAAO,EAAe,KAAK,gBAAgB,EAAE,MAAM,kCAAkC,CAAA;AAGrF;;;;;GAKG;AACH,MAAM,MAAM,cAAc,GAAG;IAC3B,4BAA4B;IAC5B,KAAK,EAAE,MAAM,CAAA;IACb,2BAA2B;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ;;;;OAIG;IACH,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB,CAAA;AAED;;;;;;GAMG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,wDAAwD;IACxD,KAAK,EAAE,MAAM,CAAA;IACb,6EAA6E;IAC7E,KAAK,EAAE,SAAS,cAAc,EAAE,CAAA;CACjC,CAAA;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,qEAAqE;IACrE,KAAK,EAAE,MAAM,CAAA;IACb,2BAA2B;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ;;;OAGG;IACH,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB;;;;OAIG;IACH,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB,CAAA;AAED;;;;;;GAMG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B;;;;;OAKG;IACH,OAAO,EAAE,IAAI,CAAC,gBAAgB,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,CAAC,CAAA;IACvD;;;;OAIG;IACH,OAAO,CAAC,EAAE,SAAS,gBAAgB,EAAE,CAAA;IACrC;;;;OAIG;IACH,MAAM,CAAC,EAAE,SAAS,gBAAgB,EAAE,CAAA;IACpC;;;;;OAKG;IACH,KAAK,CAAC,EAAE,SAAS,CAAA;IACjB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,wBAAgB,UAAU,CAAC,EACzB,OAAO,EACP,OAAO,EACP,MAAM,EACN,KAAK,EACL,SAAS,GACV,EAAE,eAAe,+BA8DjB;AAED,eAAe,UAAU,CAAA"}
@@ -0,0 +1,41 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { ProductMark } from '../../components/ui/product-mark';
3
+ import { cn } from '../../lib/utils';
4
+ /**
5
+ * The footer of a product site: a brand lockup, grouped destinations, the links
6
+ * that leave the site, and an optional slot for the legal line.
7
+ *
8
+ * It is a Block and not a Component because it is a region of a page: it
9
+ * composes a `ProductMark` and two sets of links and owns the block they sit in.
10
+ * All four NaniSoft sites compose this exact footer in their root layout, and
11
+ * each one wrote its own column model, its own mark and its own current-page
12
+ * treatment.
13
+ *
14
+ * Every string is a prop and the Block ships none. There is no site name, no
15
+ * copyright, no year, no "built with" line and no default column: a footer that
16
+ * hardcoded any of them would hand every consumer a claim about a product that
17
+ * is not theirs and a year that was not this one.
18
+ *
19
+ * The columns are a grid that collapses to one column, and the brand lockup
20
+ * stays above them at every width. A footer read as three columns on a phone is
21
+ * three unreadable columns; a footer read as one column is a list a reader can
22
+ * scan, which is the only job a footer has on a narrow viewport.
23
+ *
24
+ * Each column is a `nav` with its own accessible name, taken from the column's
25
+ * title. A reader who navigates by landmark can therefore reach "Documentation"
26
+ * rather than arriving at one anonymous list of links.
27
+ *
28
+ * The social links open in a new browsing context by default, because a link that
29
+ * leaves the site and comes back is a reader who has lost the page they were on.
30
+ * That default is a decision this Block makes, and `newTab={false}` on one link
31
+ * overrides it: Prism does not decide which destinations are external, so the
32
+ * per-link prop wins over the default rather than the other way round.
33
+ *
34
+ * It is a server Component. It fetches nothing, it holds no state, and it
35
+ * imports no router: a consumer renders it from a server file and the links are
36
+ * plain anchors the consumer's own router can intercept.
37
+ */
38
+ export function SiteFooter({ product, columns, social, legal, className, }) {
39
+ return (_jsx("footer", { "data-slot": "site-footer", className: cn('border-border bg-background w-full border-t', className), children: _jsxs("div", { className: "mx-auto flex w-full max-w-6xl flex-col gap-10 px-6 py-12 lg:px-8", children: [_jsxs("div", { className: "flex flex-col gap-10 md:flex-row md:justify-between", children: [_jsxs("div", { className: "flex flex-col gap-4", children: [_jsx(ProductMark, { id: product.id, name: product.name, pack: product.pack, size: "lg" }), social && social.length > 0 ? (_jsx("ul", { className: "flex flex-wrap items-center gap-4", children: social.map((link) => (_jsx("li", { children: _jsxs("a", { href: link.href, rel: link.newTab === false ? undefined : 'noopener noreferrer', target: link.newTab === false ? undefined : '_blank', className: "text-muted-foreground hover:text-foreground inline-flex items-center gap-2 rounded-sm text-sm font-medium transition-colors duration-fast ease-out", children: [link.icon ? (_jsx("span", { "aria-hidden": true, className: "inline-flex items-center", children: link.icon })) : null, link.label] }) }, link.href))) })) : null] }), columns && columns.length > 0 ? (_jsx("div", { className: "grid gap-8 sm:grid-cols-2 lg:grid-cols-3", children: columns.map((column) => (_jsxs("nav", { "aria-label": column.title, className: "flex flex-col gap-3", children: [_jsx("h2", { className: "text-sm font-semibold", children: column.title }), _jsx("ul", { className: "flex flex-col gap-2", children: column.links.map((link) => (_jsx("li", { children: _jsx("a", { href: link.href, rel: link.newTab ? 'noopener noreferrer' : undefined, target: link.newTab ? '_blank' : undefined, className: "text-muted-foreground hover:text-foreground rounded-sm text-sm transition-colors duration-fast ease-out", children: link.label }) }, link.href))) })] }, column.title))) })) : null] }), legal ? _jsx("div", { className: "text-muted-foreground text-sm", children: legal }) : null] }) }));
40
+ }
41
+ export default SiteFooter;
@@ -0,0 +1,3 @@
1
+ export { SiteHeader, default } from './site-header';
2
+ export type { SiteHeaderProps, SiteHeaderLink } from './site-header';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/blocks/site-header/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AACnD,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA"}
@@ -0,0 +1 @@
1
+ export { SiteHeader, default } from './site-header';
@@ -0,0 +1,142 @@
1
+ import type { ReactNode } from 'react';
2
+ import { type SwitcherProduct } from '../../components/ui/product-switcher';
3
+ import { type ProductMarkProps } from '../../components/ui/product-mark';
4
+ /**
5
+ * One destination in the header's own navigation.
6
+ *
7
+ * `href` is required and `current` is opt-in. The header marks the current page
8
+ * with `aria-current="page"` rather than with a colour, so a link's state is
9
+ * carried by the attribute every assistive technology already reads and a reader
10
+ * who cannot see the colour still knows where they are.
11
+ */
12
+ export type SiteHeaderLink = {
13
+ /** The text of the link. */
14
+ label: string;
15
+ /** Where the link goes. */
16
+ href: string;
17
+ /**
18
+ * Marks this link as the page the reader is on. Set it on the one link whose
19
+ * destination is the current route; leave it off every other link.
20
+ */
21
+ current?: boolean;
22
+ /**
23
+ * Opens the destination in a new browsing context, which defaults the link
24
+ * relationship to `noopener noreferrer`. Prism does not decide what counts as
25
+ * external: a cross-origin destination is not by itself a reason to open a tab.
26
+ */
27
+ newTab?: boolean;
28
+ };
29
+ /**
30
+ * The props a SiteHeader takes.
31
+ *
32
+ * There is no product directory in this package, so the product the header is on
33
+ * is passed as the three facts its mark is drawn from rather than as an id this
34
+ * package would have to resolve. That is the same answer `ProductMark` gives,
35
+ * and for the same reason: a consumer that composes a set of its own products
36
+ * composes the header too.
37
+ *
38
+ * The product is the only required field but one. A header with no navigation, no
39
+ * switcher and no actions is a valid header: it is a brand lockup and nothing
40
+ * else, and one of the four NaniSoft sites is exactly that.
41
+ */
42
+ export type SiteHeaderProps = {
43
+ /**
44
+ * The product this header belongs to: the id, name and pack its `ProductMark`
45
+ * is drawn from. The header renders the mark itself rather than a slot, because
46
+ * a header whose brand lockup is a slot is a header every consumer has to
47
+ * reimplement, and that is the one part of a site header that is never
48
+ * product-specific.
49
+ */
50
+ product: Pick<ProductMarkProps, 'id' | 'name' | 'pack'>;
51
+ /**
52
+ * The set of products to move between, rendered as a `ProductSwitcher` between
53
+ * the mark and the navigation. Omit it on a site that is the only product, and
54
+ * pass it on a site that is one of several. A set of one renders one mark, so
55
+ * pass nothing rather than a switcher with a single member.
56
+ */
57
+ products?: readonly SwitcherProduct[];
58
+ /**
59
+ * The header's own destinations: the sections of this site. Omit it for a
60
+ * header that carries only the brand lockup.
61
+ */
62
+ nav?: readonly SiteHeaderLink[];
63
+ /**
64
+ * The accessible name of the site navigation, which is also the visible word a
65
+ * screen reader announces before the list.
66
+ *
67
+ * It is required rather than defaulted because it is a word a reader hears, and
68
+ * a Block that ships no copy ships no reader-facing copy either. A header that
69
+ * defaulted this would put its own name on every consumer's site navigation, and
70
+ * "Site" is right for a company site and wrong for a product that has a docs
71
+ * section it wants called something else.
72
+ */
73
+ navLabel: string;
74
+ /**
75
+ * The accessible name of the product switcher. Required whenever `products` is
76
+ * passed, for the same reason `navLabel` is: it is a word a reader hears, and a
77
+ * Block that ships no copy ships none of those either. Omit it and the switcher
78
+ * takes the site navigation's name, which is right when the two are the same set
79
+ * of places and wrong when they are not.
80
+ */
81
+ productsLabel?: string;
82
+ /**
83
+ * A slot for the controls a product owns on the right: an account menu, a sign
84
+ * in link, a mode toggle, a theme picker. A slot rather than a prop, because
85
+ * every one of those is application state and none of them is a fact a header
86
+ * can be told.
87
+ */
88
+ actions?: ReactNode;
89
+ /**
90
+ * Keeps the header at the top of the viewport as the page scrolls. Off by
91
+ * default, because a sticky header is a decision about a page rather than about
92
+ * a header, and a header that is sticky on a page with no scroll costs the
93
+ * reader a strip of their viewport.
94
+ */
95
+ sticky?: boolean;
96
+ /**
97
+ * Layout only, exactly as on every Component. Changing a Prism-owned visual
98
+ * property from here is prohibited.
99
+ */
100
+ className?: string;
101
+ };
102
+ /**
103
+ * The header of a product site: a brand lockup, an optional product switcher, the
104
+ * site's own navigation and an optional slot for application controls.
105
+ *
106
+ * It is a Block and not a Component because it is a region of a page rather than
107
+ * a control: it composes a `ProductMark`, a `ProductSwitcher` and a set of
108
+ * links, and it owns the bar they sit in. All four NaniSoft sites compose this
109
+ * exact bar in their root layout, and each one wrote its own: the mark in one
110
+ * place, the switcher in a popover in another, the navigation in a third, and
111
+ * each wrote the focus and current-page wiring separately.
112
+ *
113
+ * Every string is a prop and the Block ships none. There is no site name, no
114
+ * default navigation, no "sign in" and no product list: a header that hardcoded
115
+ * any of them would hand every consumer a claim about a product that is not
116
+ * theirs, which is the defect this Block exists to remove.
117
+ *
118
+ * The bar is one flex row that wraps. The brand lockup and the actions hold
119
+ * their ends, the switcher and the navigation sit in the middle and wrap onto a
120
+ * second line rather than overflowing, so a narrow viewport gets a taller header
121
+ * and never a clipped one. The brand lockup is the one element that never
122
+ * wraps: a wordmark broken across two lines is not a wordmark.
123
+ *
124
+ * The navigation is a `nav` with an accessible name and the switcher is a second
125
+ * `nav`, because a reader who navigates by landmark needs two regions rather than
126
+ * one region with two lists in it. The actions slot is not a region at all: it is
127
+ * whatever the consumer composed, and wrapping it in a landmark would be a claim
128
+ * about content this Block does not own.
129
+ *
130
+ * The bottom hairline is `border-border`, so the bar separates from the page by
131
+ * a line rather than by a fill change, which is how every surface in this system
132
+ * is separated: in the base pack `background` and `card` resolve to the same
133
+ * value, so a fill is not available as a separator.
134
+ *
135
+ * It is a server Component. It fetches nothing, it holds no state, and a page
136
+ * that renders it in a server file needs nothing from the provider mounted: the
137
+ * pack it wears is the pack of whatever boundary is above it, which is the
138
+ * mechanism the whole system uses.
139
+ */
140
+ export declare function SiteHeader({ product, products, nav, navLabel, productsLabel, actions, sticky, className, }: SiteHeaderProps): import("react").JSX.Element;
141
+ export default SiteHeader;
142
+ //# sourceMappingURL=site-header.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"site-header.d.ts","sourceRoot":"","sources":["../../../src/blocks/site-header/site-header.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAEtC,OAAO,EAEL,KAAK,eAAe,EACrB,MAAM,sCAAsC,CAAA;AAC7C,OAAO,EAAe,KAAK,gBAAgB,EAAE,MAAM,kCAAkC,CAAA;AAGrF;;;;;;;GAOG;AACH,MAAM,MAAM,cAAc,GAAG;IAC3B,4BAA4B;IAC5B,KAAK,EAAE,MAAM,CAAA;IACb,2BAA2B;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB;;;;OAIG;IACH,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB,CAAA;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B;;;;;;OAMG;IACH,OAAO,EAAE,IAAI,CAAC,gBAAgB,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,CAAC,CAAA;IACvD;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,SAAS,eAAe,EAAE,CAAA;IACrC;;;OAGG;IACH,GAAG,CAAC,EAAE,SAAS,cAAc,EAAE,CAAA;IAC/B;;;;;;;;;OASG;IACH,QAAQ,EAAE,MAAM,CAAA;IAChB;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,SAAS,CAAA;IACnB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,wBAAgB,UAAU,CAAC,EACzB,OAAO,EACP,QAAQ,EACR,GAAG,EACH,QAAQ,EACR,aAAa,EACb,OAAO,EACP,MAAc,EACd,SAAS,GACV,EAAE,eAAe,+BA+CjB;AAED,eAAe,UAAU,CAAA"}
@@ -0,0 +1,46 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { ProductSwitcher, } from '../../components/ui/product-switcher';
3
+ import { ProductMark } from '../../components/ui/product-mark';
4
+ import { cn } from '../../lib/utils';
5
+ /**
6
+ * The header of a product site: a brand lockup, an optional product switcher, the
7
+ * site's own navigation and an optional slot for application controls.
8
+ *
9
+ * It is a Block and not a Component because it is a region of a page rather than
10
+ * a control: it composes a `ProductMark`, a `ProductSwitcher` and a set of
11
+ * links, and it owns the bar they sit in. All four NaniSoft sites compose this
12
+ * exact bar in their root layout, and each one wrote its own: the mark in one
13
+ * place, the switcher in a popover in another, the navigation in a third, and
14
+ * each wrote the focus and current-page wiring separately.
15
+ *
16
+ * Every string is a prop and the Block ships none. There is no site name, no
17
+ * default navigation, no "sign in" and no product list: a header that hardcoded
18
+ * any of them would hand every consumer a claim about a product that is not
19
+ * theirs, which is the defect this Block exists to remove.
20
+ *
21
+ * The bar is one flex row that wraps. The brand lockup and the actions hold
22
+ * their ends, the switcher and the navigation sit in the middle and wrap onto a
23
+ * second line rather than overflowing, so a narrow viewport gets a taller header
24
+ * and never a clipped one. The brand lockup is the one element that never
25
+ * wraps: a wordmark broken across two lines is not a wordmark.
26
+ *
27
+ * The navigation is a `nav` with an accessible name and the switcher is a second
28
+ * `nav`, because a reader who navigates by landmark needs two regions rather than
29
+ * one region with two lists in it. The actions slot is not a region at all: it is
30
+ * whatever the consumer composed, and wrapping it in a landmark would be a claim
31
+ * about content this Block does not own.
32
+ *
33
+ * The bottom hairline is `border-border`, so the bar separates from the page by
34
+ * a line rather than by a fill change, which is how every surface in this system
35
+ * is separated: in the base pack `background` and `card` resolve to the same
36
+ * value, so a fill is not available as a separator.
37
+ *
38
+ * It is a server Component. It fetches nothing, it holds no state, and a page
39
+ * that renders it in a server file needs nothing from the provider mounted: the
40
+ * pack it wears is the pack of whatever boundary is above it, which is the
41
+ * mechanism the whole system uses.
42
+ */
43
+ export function SiteHeader({ product, products, nav, navLabel, productsLabel, actions, sticky = false, className, }) {
44
+ return (_jsx("header", { "data-slot": "site-header", className: cn('border-border bg-background w-full border-b', sticky && 'sticky top-0 z-30', className), children: _jsxs("div", { className: "mx-auto flex w-full max-w-6xl flex-wrap items-center gap-x-6 gap-y-3 px-6 py-3 lg:px-8", children: [_jsx("a", { href: "/", className: "flex shrink-0 items-center rounded-sm", children: _jsx(ProductMark, { id: product.id, name: product.name, pack: product.pack, size: "md" }) }), products && products.length > 0 ? (_jsx(ProductSwitcher, { products: products, currentId: product.id, size: "sm", label: productsLabel ?? navLabel })) : null, nav && nav.length > 0 ? (_jsx("nav", { "aria-label": navLabel, className: "flex flex-wrap items-center gap-x-5 gap-y-2", children: nav.map((link) => (_jsx("a", { href: link.href, "aria-current": link.current ? 'page' : undefined, rel: link.newTab ? 'noopener noreferrer' : undefined, target: link.newTab ? '_blank' : undefined, className: "text-muted-foreground hover:text-foreground rounded-sm text-sm font-medium transition-colors duration-fast ease-out", children: link.label }, link.href))) })) : null, actions ? (_jsx("div", { className: "ms-auto flex items-center gap-3", children: actions })) : null] }) }));
45
+ }
46
+ export default SiteHeader;
@@ -0,0 +1,3 @@
1
+ export { StackGrid01, default } from './stack-grid';
2
+ export type { StackGrid01Props, StackPart, StackOwn } from './stack-grid';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/blocks/stack-grid-01/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AACnD,YAAY,EAAE,gBAAgB,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA"}
@@ -0,0 +1 @@
1
+ export { StackGrid01, default } from './stack-grid';
@@ -0,0 +1,118 @@
1
+ import { type HeadingLevel } from '../../components/ui/section';
2
+ /**
3
+ * One part a product is assembled from: its name and the role it plays.
4
+ *
5
+ * Both are required, and a part with no role is a logo and a part with no name
6
+ * is a role. A survey grid is a claim that a set of parts is sufficient, and both
7
+ * halves of that claim are the caller's to make.
8
+ */
9
+ export type StackPart = {
10
+ /** The part's own name, as its authors spell it. */
11
+ name: string;
12
+ /**
13
+ * One phrase about what the part does here. It is a role rather than a
14
+ * description: the grid is a survey of what a product is built from, not a
15
+ * feature list, and a role that runs to a sentence turns a survey into prose.
16
+ */
17
+ role: string;
18
+ };
19
+ /**
20
+ * One thing a product built itself, rather than assembled: its name and one line
21
+ * about it.
22
+ *
23
+ * The two are required for the same reason `StackPart`'s are, and for one more:
24
+ * a grid of in-house work beside a grid of assembled parts is a claim that the
25
+ * work was NaniSoft's own, and that claim needs a name and a line under it to be
26
+ * a claim a reader can check.
27
+ */
28
+ export type StackOwn = {
29
+ /** The component's own name. */
30
+ name: string;
31
+ /** One line about what it does and why it is not assembled. */
32
+ blurb: string;
33
+ };
34
+ /**
35
+ * The props a StackGrid01 takes.
36
+ *
37
+ * Every string is a prop and the Block ships none: no part, no role, no blurb
38
+ * and no default "built in-house" mark. A grid that hardcoded a part list would
39
+ * hand every consumer a survey of somebody else's stack.
40
+ */
41
+ export type StackGrid01Props = {
42
+ /** Optional label above the section title. See the No-Default-Eyebrow Rule. */
43
+ eyebrow?: string;
44
+ /** The section title. Omit it for a grid composed under its own heading. */
45
+ title?: string;
46
+ /** One or two sentences under the title. */
47
+ description?: string;
48
+ /**
49
+ * The parts the product is assembled from, in the order a reader should meet
50
+ * them. Order is the caller's because it is a claim about which part matters
51
+ * first.
52
+ */
53
+ parts: readonly StackPart[];
54
+ /**
55
+ * The things the product built itself, in the order a reader should meet them.
56
+ * Omit it for a product that assembled everything, and pass it when the claim
57
+ * is that some of the work is its own.
58
+ */
59
+ own?: readonly StackOwn[];
60
+ /**
61
+ * The label on the in-house group, which is the claim the group makes. Omit it
62
+ * when the group is titled by the section itself, and pass a word you mean:
63
+ * "built in-house", "built by Nanisoft" and "our own" are three different
64
+ * claims and the Block does not choose between them.
65
+ */
66
+ ownLabel?: string;
67
+ /**
68
+ * The line under the grid, for the sentence that qualifies it: what is not
69
+ * here, or where to read the full list.
70
+ */
71
+ caption?: string;
72
+ /** Heading level for the section title. See `HeadingLevel`. */
73
+ headingLevel?: HeadingLevel;
74
+ /**
75
+ * Layout only, exactly as on every Component. Changing a Prism-owned visual
76
+ * property from here is prohibited.
77
+ */
78
+ className?: string;
79
+ };
80
+ /**
81
+ * A survey of what a product is assembled from, and what it built itself.
82
+ *
83
+ * Three of the four NaniSoft sites publish this section, and each one drew it by
84
+ * hand with the same two groups: a survey grid of composed parts, each a name
85
+ * and a role, and below it a second grid of the components the product wrote
86
+ * itself, each a name and a line about it. Three of them also drew the second
87
+ * group differently from the first - a dashed border, a different tile, a mark
88
+ * above the name - because the visual difference is the claim: *this part is
89
+ * ours*.
90
+ *
91
+ * That is what the `own` group is here. It is a separate prop and a separate
92
+ * grid rather than a flag on the part, because the difference is a claim about
93
+ * provenance and a claim is not a property of a row: a part that is assembled and
94
+ * a part that is built are the same kind of thing with a different answer to "who
95
+ * wrote it", and putting the answer in the row would make the two groups
96
+ * indistinguishable in the data as well as on screen.
97
+ *
98
+ * The two groups differ in weight rather than in colour. The composed parts are
99
+ * tiles on the muted surface; the in-house parts sit on the page with a
100
+ * `border-primary` hairline, which is the one place in this system where a border
101
+ * carries a pack's hue and it is paired with `shadow-md` because it is the one
102
+ * element that means *lifted*. No step in either group is a pastel fill: a pastel
103
+ * is a fill for a large area and never a signal, and a tile of pastel behind one
104
+ * word is a signal a reader has to learn.
105
+ *
106
+ * `ownLabel` is required when `own` is passed, because the group is a claim and
107
+ * the claim is the caller's words. Three of the four sites write three different
108
+ * ones, and the Block does not choose.
109
+ *
110
+ * A tile carries a name and a role and nothing else. A part whose role needs two
111
+ * lines belongs in the section's `description`, where it applies to the group
112
+ * rather than to one tile.
113
+ *
114
+ * It is a server Component: no hook, no state and no client code.
115
+ */
116
+ export declare function StackGrid01({ eyebrow, title, description, parts, own, ownLabel, caption, headingLevel, className, }: StackGrid01Props): import("react").JSX.Element;
117
+ export default StackGrid01;
118
+ //# sourceMappingURL=stack-grid.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stack-grid.d.ts","sourceRoot":"","sources":["../../../src/blocks/stack-grid-01/stack-grid.tsx"],"names":[],"mappings":"AACA,OAAO,EAA2B,KAAK,YAAY,EAAE,MAAM,6BAA6B,CAAA;AAGxF;;;;;;GAMG;AACH,MAAM,MAAM,SAAS,GAAG;IACtB,oDAAoD;IACpD,IAAI,EAAE,MAAM,CAAA;IACZ;;;;OAIG;IACH,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AAED;;;;;;;;GAQG;AACH,MAAM,MAAM,QAAQ,GAAG;IACrB,gCAAgC;IAChC,IAAI,EAAE,MAAM,CAAA;IACZ,+DAA+D;IAC/D,KAAK,EAAE,MAAM,CAAA;CACd,CAAA;AAED;;;;;;GAMG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,+EAA+E;IAC/E,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,4EAA4E;IAC5E,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,4CAA4C;IAC5C,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB;;;;OAIG;IACH,KAAK,EAAE,SAAS,SAAS,EAAE,CAAA;IAC3B;;;;OAIG;IACH,GAAG,CAAC,EAAE,SAAS,QAAQ,EAAE,CAAA;IACzB;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,+DAA+D;IAC/D,YAAY,CAAC,EAAE,YAAY,CAAA;IAC3B;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,wBAAgB,WAAW,CAAC,EAC1B,OAAO,EACP,KAAK,EACL,WAAW,EACX,KAAK,EACL,GAAG,EACH,QAAQ,EACR,OAAO,EACP,YAAmB,EACnB,SAAS,GACV,EAAE,gBAAgB,+BA4DlB;AAED,eAAe,WAAW,CAAA"}
@@ -0,0 +1,49 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Card, CardContent, CardHeader, CardTitle } from '../../components/ui/card';
3
+ import { Section, SectionHeading } from '../../components/ui/section';
4
+ import { cn } from '../../lib/utils';
5
+ /**
6
+ * A survey of what a product is assembled from, and what it built itself.
7
+ *
8
+ * Three of the four NaniSoft sites publish this section, and each one drew it by
9
+ * hand with the same two groups: a survey grid of composed parts, each a name
10
+ * and a role, and below it a second grid of the components the product wrote
11
+ * itself, each a name and a line about it. Three of them also drew the second
12
+ * group differently from the first - a dashed border, a different tile, a mark
13
+ * above the name - because the visual difference is the claim: *this part is
14
+ * ours*.
15
+ *
16
+ * That is what the `own` group is here. It is a separate prop and a separate
17
+ * grid rather than a flag on the part, because the difference is a claim about
18
+ * provenance and a claim is not a property of a row: a part that is assembled and
19
+ * a part that is built are the same kind of thing with a different answer to "who
20
+ * wrote it", and putting the answer in the row would make the two groups
21
+ * indistinguishable in the data as well as on screen.
22
+ *
23
+ * The two groups differ in weight rather than in colour. The composed parts are
24
+ * tiles on the muted surface; the in-house parts sit on the page with a
25
+ * `border-primary` hairline, which is the one place in this system where a border
26
+ * carries a pack's hue and it is paired with `shadow-md` because it is the one
27
+ * element that means *lifted*. No step in either group is a pastel fill: a pastel
28
+ * is a fill for a large area and never a signal, and a tile of pastel behind one
29
+ * word is a signal a reader has to learn.
30
+ *
31
+ * `ownLabel` is required when `own` is passed, because the group is a claim and
32
+ * the claim is the caller's words. Three of the four sites write three different
33
+ * ones, and the Block does not choose.
34
+ *
35
+ * A tile carries a name and a role and nothing else. A part whose role needs two
36
+ * lines belongs in the section's `description`, where it applies to the group
37
+ * rather than to one tile.
38
+ *
39
+ * It is a server Component: no hook, no state and no client code.
40
+ */
41
+ export function StackGrid01({ eyebrow, title, description, parts, own, ownLabel, caption, headingLevel = 'h2', className, }) {
42
+ if (own !== undefined && own.length > 0 && !ownLabel) {
43
+ throw new Error('StackGrid01: the in-house group was passed with no ownLabel, so the grid would make the claim ' +
44
+ '"this part is ours" in a shape and leave the words to a reader to infer. Pass the words you mean, ' +
45
+ 'or omit the group.');
46
+ }
47
+ return (_jsxs(Section, { children: [title ? (_jsx(SectionHeading, { as: headingLevel, align: "left", eyebrow: eyebrow, title: title, description: description, className: "mb-12" })) : null, _jsxs("div", { "data-slot": "stack-grid", className: cn('flex flex-col gap-10', className), children: [_jsx("ul", { className: "grid gap-3 sm:grid-cols-2 lg:grid-cols-4", children: parts.map((part) => (_jsx("li", { children: _jsxs(Card, { className: "bg-muted h-full gap-2 py-4", children: [_jsx(CardHeader, { className: "gap-1", children: _jsx(CardTitle, { className: "text-sm", children: part.name }) }), _jsx(CardContent, { children: _jsx("p", { className: "text-muted-foreground text-pretty text-xs", children: part.role }) })] }) }, part.name))) }), own && own.length > 0 ? (_jsx("ul", { "data-slot": "stack-grid-own", className: "grid gap-3 sm:grid-cols-2 lg:grid-cols-4", children: own.map((entry) => (_jsx("li", { children: _jsxs(Card, { className: "border-primary shadow-md h-full gap-2 py-4", children: [_jsxs(CardHeader, { className: "gap-1", children: [_jsx("span", { className: "text-muted-foreground font-mono text-xs", children: ownLabel }), _jsx(CardTitle, { className: "text-sm", children: entry.name })] }), _jsx(CardContent, { children: _jsx("p", { className: "text-muted-foreground text-pretty text-xs", children: entry.blurb }) })] }) }, entry.name))) })) : null] }), caption ? _jsx("p", { className: "text-muted-foreground mt-6 text-pretty text-sm", children: caption }) : null] }));
48
+ }
49
+ export default StackGrid01;
@@ -0,0 +1,3 @@
1
+ export { StatusLedger01, STATUS_TIERS, default } from './status-ledger';
2
+ export type { StatusLedger01Props, StatusRow, StatusTier } from './status-ledger';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/blocks/status-ledger-01/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAA;AACvE,YAAY,EAAE,mBAAmB,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA"}
@@ -0,0 +1 @@
1
+ export { StatusLedger01, STATUS_TIERS, default } from './status-ledger';