@cloudgrid-io/ui 0.0.2 → 0.2.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 (187) hide show
  1. package/README.md +109 -0
  2. package/dist/blocks/agent-prompt.d.ts +37 -0
  3. package/dist/blocks/agent-prompt.d.ts.map +1 -0
  4. package/dist/blocks/agent-prompt.js +53 -0
  5. package/dist/blocks/agent-prompt.js.map +1 -0
  6. package/dist/blocks/card-grid.d.ts +38 -0
  7. package/dist/blocks/card-grid.d.ts.map +1 -0
  8. package/dist/blocks/card-grid.js +32 -0
  9. package/dist/blocks/card-grid.js.map +1 -0
  10. package/dist/blocks/compare-table.d.ts +13 -0
  11. package/dist/blocks/compare-table.d.ts.map +1 -0
  12. package/dist/blocks/compare-table.js +55 -0
  13. package/dist/blocks/compare-table.js.map +1 -0
  14. package/dist/blocks/creation-tile.d.ts +57 -0
  15. package/dist/blocks/creation-tile.d.ts.map +1 -0
  16. package/dist/blocks/creation-tile.js +32 -0
  17. package/dist/blocks/creation-tile.js.map +1 -0
  18. package/dist/blocks/cta-banner.d.ts +31 -0
  19. package/dist/blocks/cta-banner.d.ts.map +1 -0
  20. package/dist/blocks/cta-banner.js +31 -0
  21. package/dist/blocks/cta-banner.js.map +1 -0
  22. package/dist/blocks/drop-zone.d.ts +54 -0
  23. package/dist/blocks/drop-zone.d.ts.map +1 -0
  24. package/dist/blocks/drop-zone.js +121 -0
  25. package/dist/blocks/drop-zone.js.map +1 -0
  26. package/dist/blocks/feature-cells.d.ts +46 -0
  27. package/dist/blocks/feature-cells.d.ts.map +1 -0
  28. package/dist/blocks/feature-cells.js +46 -0
  29. package/dist/blocks/feature-cells.js.map +1 -0
  30. package/dist/blocks/hub-index.d.ts +55 -0
  31. package/dist/blocks/hub-index.d.ts.map +1 -0
  32. package/dist/blocks/hub-index.js +22 -0
  33. package/dist/blocks/hub-index.js.map +1 -0
  34. package/dist/blocks/logo.d.ts +24 -0
  35. package/dist/blocks/logo.d.ts.map +1 -0
  36. package/dist/blocks/logo.js +34 -0
  37. package/dist/blocks/logo.js.map +1 -0
  38. package/dist/blocks/option-card.d.ts +31 -0
  39. package/dist/blocks/option-card.d.ts.map +1 -0
  40. package/dist/blocks/option-card.js +32 -0
  41. package/dist/blocks/option-card.js.map +1 -0
  42. package/dist/blocks/page-heading.d.ts +33 -0
  43. package/dist/blocks/page-heading.d.ts.map +1 -0
  44. package/dist/blocks/page-heading.js +30 -0
  45. package/dist/blocks/page-heading.js.map +1 -0
  46. package/dist/blocks/plug-method.d.ts +76 -0
  47. package/dist/blocks/plug-method.d.ts.map +1 -0
  48. package/dist/blocks/plug-method.js +30 -0
  49. package/dist/blocks/plug-method.js.map +1 -0
  50. package/dist/blocks/pricing-tier-cards.d.ts +47 -0
  51. package/dist/blocks/pricing-tier-cards.d.ts.map +1 -0
  52. package/dist/blocks/pricing-tier-cards.js +12 -0
  53. package/dist/blocks/pricing-tier-cards.js.map +1 -0
  54. package/dist/blocks/pricing-tiers.d.ts +29 -0
  55. package/dist/blocks/pricing-tiers.d.ts.map +1 -0
  56. package/dist/blocks/pricing-tiers.js +30 -0
  57. package/dist/blocks/pricing-tiers.js.map +1 -0
  58. package/dist/blocks/quote.d.ts +27 -0
  59. package/dist/blocks/quote.d.ts.map +1 -0
  60. package/dist/blocks/quote.js +28 -0
  61. package/dist/blocks/quote.js.map +1 -0
  62. package/dist/blocks/rich-text.d.ts +38 -0
  63. package/dist/blocks/rich-text.d.ts.map +1 -0
  64. package/dist/blocks/rich-text.js +39 -0
  65. package/dist/blocks/rich-text.js.map +1 -0
  66. package/dist/blocks/stage-panel.d.ts +5 -0
  67. package/dist/blocks/stage-panel.d.ts.map +1 -0
  68. package/dist/blocks/stage-panel.js +30 -0
  69. package/dist/blocks/stage-panel.js.map +1 -0
  70. package/dist/blocks/step-item.d.ts +24 -0
  71. package/dist/blocks/step-item.d.ts.map +1 -0
  72. package/dist/blocks/step-item.js +34 -0
  73. package/dist/blocks/step-item.js.map +1 -0
  74. package/dist/blocks/tool-logo.d.ts +15 -0
  75. package/dist/blocks/tool-logo.d.ts.map +1 -0
  76. package/dist/blocks/tool-logo.js +59 -0
  77. package/dist/blocks/tool-logo.js.map +1 -0
  78. package/dist/blocks/tool-marks.d.ts +120 -0
  79. package/dist/blocks/tool-marks.d.ts.map +1 -0
  80. package/dist/blocks/tool-marks.js +94 -0
  81. package/dist/blocks/tool-marks.js.map +1 -0
  82. package/dist/index.d.ts +45 -0
  83. package/dist/index.d.ts.map +1 -0
  84. package/dist/index.js +63 -0
  85. package/dist/index.js.map +1 -0
  86. package/dist/lib/cloudgrid-cn.d.ts +65 -0
  87. package/dist/lib/cloudgrid-cn.d.ts.map +1 -0
  88. package/dist/lib/cloudgrid-cn.js +90 -0
  89. package/dist/lib/cloudgrid-cn.js.map +1 -0
  90. package/dist/tokens/base.json +119 -38
  91. package/dist/tokens/surface-ink.json +63 -0
  92. package/dist/tokens/surface-panel.json +63 -0
  93. package/dist/tokens.css +115 -19
  94. package/dist/tokens.json +20 -2
  95. package/dist/ui/accordion.d.ts +7 -0
  96. package/dist/ui/accordion.d.ts.map +1 -0
  97. package/dist/ui/accordion.js +19 -0
  98. package/dist/ui/accordion.js.map +1 -0
  99. package/dist/ui/badge.d.ts +8 -0
  100. package/dist/ui/badge.d.ts.map +1 -0
  101. package/dist/ui/badge.js +34 -0
  102. package/dist/ui/badge.js.map +1 -0
  103. package/dist/ui/button.d.ts +9 -0
  104. package/dist/ui/button.d.ts.map +1 -0
  105. package/dist/ui/button.js +35 -0
  106. package/dist/ui/button.js.map +1 -0
  107. package/dist/ui/card.d.ts +12 -0
  108. package/dist/ui/card.d.ts.map +1 -0
  109. package/dist/ui/card.js +26 -0
  110. package/dist/ui/card.js.map +1 -0
  111. package/dist/ui/carousel.d.ts +37 -0
  112. package/dist/ui/carousel.d.ts.map +1 -0
  113. package/dist/ui/carousel.js +34 -0
  114. package/dist/ui/carousel.js.map +1 -0
  115. package/dist/ui/checkbox.d.ts +4 -0
  116. package/dist/ui/checkbox.d.ts.map +1 -0
  117. package/dist/ui/checkbox.js +10 -0
  118. package/dist/ui/checkbox.js.map +1 -0
  119. package/dist/ui/code-block.d.ts +9 -0
  120. package/dist/ui/code-block.d.ts.map +1 -0
  121. package/dist/ui/code-block.js +57 -0
  122. package/dist/ui/code-block.js.map +1 -0
  123. package/dist/ui/combobox.d.ts +25 -0
  124. package/dist/ui/combobox.d.ts.map +1 -0
  125. package/dist/ui/combobox.js +59 -0
  126. package/dist/ui/combobox.js.map +1 -0
  127. package/dist/ui/dialog.d.ts +18 -0
  128. package/dist/ui/dialog.d.ts.map +1 -0
  129. package/dist/ui/dialog.js +39 -0
  130. package/dist/ui/dialog.js.map +1 -0
  131. package/dist/ui/dropdown-menu.d.ts +30 -0
  132. package/dist/ui/dropdown-menu.d.ts.map +1 -0
  133. package/dist/ui/dropdown-menu.js +53 -0
  134. package/dist/ui/dropdown-menu.js.map +1 -0
  135. package/dist/ui/input-group.d.ts +19 -0
  136. package/dist/ui/input-group.d.ts.map +1 -0
  137. package/dist/ui/input-group.js +59 -0
  138. package/dist/ui/input-group.js.map +1 -0
  139. package/dist/ui/input.d.ts +4 -0
  140. package/dist/ui/input.d.ts.map +1 -0
  141. package/dist/ui/input.js +9 -0
  142. package/dist/ui/input.js.map +1 -0
  143. package/dist/ui/number-field.d.ts +10 -0
  144. package/dist/ui/number-field.d.ts.map +1 -0
  145. package/dist/ui/number-field.js +39 -0
  146. package/dist/ui/number-field.js.map +1 -0
  147. package/dist/ui/panel.d.ts +36 -0
  148. package/dist/ui/panel.d.ts.map +1 -0
  149. package/dist/ui/panel.js +39 -0
  150. package/dist/ui/panel.js.map +1 -0
  151. package/dist/ui/select.d.ts +16 -0
  152. package/dist/ui/select.d.ts.map +1 -0
  153. package/dist/ui/select.js +36 -0
  154. package/dist/ui/select.js.map +1 -0
  155. package/dist/ui/separator.d.ts +4 -0
  156. package/dist/ui/separator.d.ts.map +1 -0
  157. package/dist/ui/separator.js +9 -0
  158. package/dist/ui/separator.js.map +1 -0
  159. package/dist/ui/skeleton.d.ts +3 -0
  160. package/dist/ui/skeleton.d.ts.map +1 -0
  161. package/dist/ui/skeleton.js +7 -0
  162. package/dist/ui/skeleton.js.map +1 -0
  163. package/dist/ui/sonner.d.ts +4 -0
  164. package/dist/ui/sonner.d.ts.map +1 -0
  165. package/dist/ui/sonner.js +36 -0
  166. package/dist/ui/sonner.js.map +1 -0
  167. package/dist/ui/switch.d.ts +6 -0
  168. package/dist/ui/switch.d.ts.map +1 -0
  169. package/dist/ui/switch.js +9 -0
  170. package/dist/ui/switch.js.map +1 -0
  171. package/dist/ui/table.d.ts +11 -0
  172. package/dist/ui/table.d.ts.map +1 -0
  173. package/dist/ui/table.js +30 -0
  174. package/dist/ui/table.js.map +1 -0
  175. package/dist/ui/tabs.d.ts +11 -0
  176. package/dist/ui/tabs.d.ts.map +1 -0
  177. package/dist/ui/tabs.js +38 -0
  178. package/dist/ui/tabs.js.map +1 -0
  179. package/dist/ui/textarea.d.ts +4 -0
  180. package/dist/ui/textarea.d.ts.map +1 -0
  181. package/dist/ui/textarea.js +8 -0
  182. package/dist/ui/textarea.js.map +1 -0
  183. package/dist/ui/tooltip.d.ts +8 -0
  184. package/dist/ui/tooltip.d.ts.map +1 -0
  185. package/dist/ui/tooltip.js +37 -0
  186. package/dist/ui/tooltip.js.map +1 -0
  187. package/package.json +42 -8
@@ -0,0 +1,76 @@
1
+ import * as React from "react";
2
+ /**
3
+ * One install method rendered as the terminal session it becomes: the command as
4
+ * a prompt line, the steps as a transcript, the tools as a marks rail. The
5
+ * operator killed an earlier card-and-form layout for this (2026-08-06 in v0):
6
+ * three near-identical cards over a two-column form read as settings, a session
7
+ * reads as the thing actually happening.
8
+ *
9
+ * Ported from v0's `site/PlugMethod`, the last component of the #7 inventory.
10
+ *
11
+ * ## It owns no surface, on purpose
12
+ *
13
+ * v0 rendered this inside the /plug console's ink and hardcoded thirteen
14
+ * white-derived rgba() values on that assumption. Here every colour is a semantic
15
+ * token or derived from `currentColor`, so the component is honest on ink AND on
16
+ * panel, and the caller supplies the surface:
17
+ *
18
+ * <div data-cg-surface="ink" className="bg-code text-ink ...">
19
+ * <PlugMethod ... />
20
+ * </div>
21
+ *
22
+ * `text-ink` on the container is required, not decorative (rule 3: text does not
23
+ * flip by inheritance).
24
+ *
25
+ * ## What changed from v0's API
26
+ *
27
+ * - v0 passed a `method` object because the console maps CMS tabs onto it, and
28
+ * its `label` was the tab's, rendered by the console rather than here. The
29
+ * registry version takes flat props and no tab label, per the batch
30
+ * convention: site CMS shapes stay on the site.
31
+ * - v0's tools were bare names resolved against marks shipped with the library.
32
+ * This library ships no third-party marks (#47), so each tool optionally
33
+ * carries its own `mark`, passed through to `ToolLogo`, whose monogram
34
+ * fallback covers the rest.
35
+ * - The copy interaction matches `AgentPrompt`, not v0: the result is also
36
+ * written to a polite live region, because a flipped label is invisible to a
37
+ * screen reader that has already read the button. The failure path stays
38
+ * honest: "copy blocked by browser" beats a button that appears to do nothing.
39
+ *
40
+ * The transcript keeps StepItem's accessibility shape rather than composing it:
41
+ * the numerals are `aria-hidden` because the `<ol>` does the numbering, and the
42
+ * `role="list"` is explicit because WebKit drops the implicit role when
43
+ * list-style is none. Not composed, because StepItem's title is `heading-sm` and
44
+ * this transcript is deliberately body-sized: a session, not a pitch.
45
+ */
46
+ type PlugMethodStep = {
47
+ title: string;
48
+ body: string;
49
+ };
50
+ type PlugMethodTool = {
51
+ name: string;
52
+ /** The vendor's mark, if the caller has one to show. Monogram otherwise. */
53
+ mark?: React.ReactNode;
54
+ };
55
+ declare function PlugMethod({ lead, command, commandLabel, exampleLabel, steps, prompt, tools, toolsLabel, note, copyLabel, className, ...props }: Omit<React.ComponentProps<"div">, "ref"> & {
56
+ lead: string;
57
+ /** The one command. Rendered as a prompt line with a copy button. */
58
+ command: string;
59
+ /** Mono comment above the command, e.g. "run it from the repo you already have". */
60
+ commandLabel: string;
61
+ /** Mono comment introducing the transcript, e.g. "what happens next". */
62
+ exampleLabel: string;
63
+ steps: PlugMethodStep[];
64
+ /** The dashed pill: a first prompt to hand an agent, copied on press. */
65
+ prompt: {
66
+ command: string;
67
+ label: string;
68
+ };
69
+ tools: PlugMethodTool[];
70
+ toolsLabel: string;
71
+ note: string;
72
+ copyLabel?: string;
73
+ }): React.JSX.Element;
74
+ export { PlugMethod };
75
+ export type { PlugMethodStep, PlugMethodTool };
76
+ //# sourceMappingURL=plug-method.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plug-method.d.ts","sourceRoot":"","sources":["../../src/blocks/plug-method.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAK9B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AAEH,KAAK,cAAc,GAAG;IACpB,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AAED,KAAK,cAAc,GAAG;IACpB,IAAI,EAAE,MAAM,CAAA;IACZ,4EAA4E;IAC5E,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;CACvB,CAAA;AAED,iBAAS,UAAU,CAAC,EAClB,IAAI,EACJ,OAAO,EACP,YAAY,EACZ,YAAY,EACZ,KAAK,EACL,MAAM,EACN,KAAK,EACL,UAAU,EACV,IAAI,EACJ,SAAkB,EAClB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,GAAG;IAC5C,IAAI,EAAE,MAAM,CAAA;IACZ,qEAAqE;IACrE,OAAO,EAAE,MAAM,CAAA;IACf,oFAAoF;IACpF,YAAY,EAAE,MAAM,CAAA;IACpB,yEAAyE;IACzE,YAAY,EAAE,MAAM,CAAA;IACpB,KAAK,EAAE,cAAc,EAAE,CAAA;IACvB,yEAAyE;IACzE,MAAM,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAA;IAC1C,KAAK,EAAE,cAAc,EAAE,CAAA;IACvB,UAAU,EAAE,MAAM,CAAA;IAClB,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,qBA0GA;AAED,OAAO,EAAE,UAAU,EAAE,CAAA;AACrB,YAAY,EAAE,cAAc,EAAE,cAAc,EAAE,CAAA"}
@@ -0,0 +1,30 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import { cn } from "../lib/cloudgrid-cn.js";
5
+ import { ToolLogo } from "./tool-logo.js";
6
+ function PlugMethod({ lead, command, commandLabel, exampleLabel, steps, prompt, tools, toolsLabel, note, copyLabel = "Copy", className, ...props }) {
7
+ // One feedback slot per copy surface, so copying the command does not flip the
8
+ // prompt pill's hint. Same 1600ms window as AgentPrompt and v0's copy island.
9
+ const [feedback, setFeedback] = React.useState({});
10
+ const timer = React.useRef(undefined);
11
+ // Cleared on unmount, or the timeout fires a state update against a component
12
+ // that is gone when someone navigates within the window.
13
+ React.useEffect(() => () => clearTimeout(timer.current), []);
14
+ const copy = (slot, text) => async () => {
15
+ let message;
16
+ try {
17
+ await navigator.clipboard.writeText(text);
18
+ message = "copied ✓";
19
+ }
20
+ catch {
21
+ message = "copy blocked by browser";
22
+ }
23
+ setFeedback({ [slot]: message });
24
+ clearTimeout(timer.current);
25
+ timer.current = setTimeout(() => setFeedback({}), 1600);
26
+ };
27
+ return (_jsxs("div", { "data-slot": "plug-method", className: cn("grid gap-6", className), ...props, children: [_jsx("p", { className: "m-0 max-w-measure text-body-md text-body", children: lead }), _jsxs("div", { className: "grid gap-2", children: [_jsxs("span", { className: "font-mono text-caption text-faint", children: ["# ", commandLabel] }), _jsxs("div", { className: "flex items-center gap-3 rounded-md border border-hairline bg-[color-mix(in_oklch,currentColor_4%,transparent)] py-3 pr-3 pl-4", children: [_jsx("span", { "aria-hidden": "true", className: "shrink-0 font-mono font-bold text-lime", children: "$" }), _jsx("code", { className: "min-w-0 flex-1 overflow-x-auto font-mono text-mono whitespace-nowrap text-ink [scrollbar-width:none]", children: command }), _jsx("button", { type: "button", onClick: copy("cmd", command), className: "ml-auto shrink-0 rounded-pill bg-lime px-3.5 py-1 text-caption font-bold text-on-accent transition-colors hover:bg-lime-press focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring", children: feedback.cmd ?? copyLabel })] })] }), _jsxs("p", { className: "-mb-3 m-0 font-mono text-caption text-faint", children: ["# ", exampleLabel] }), _jsx("ol", { role: "list", className: "m-0 grid list-none gap-4 p-0", children: steps.map((step, i) => (_jsxs("li", { className: "flex items-start gap-4", children: [_jsx("span", { "aria-hidden": "true", className: "mt-0.5 flex size-6 shrink-0 items-center justify-center rounded-pill bg-cyan font-mono text-caption font-bold text-on-accent", children: i + 1 }), _jsxs("span", { className: "grid gap-0.5", children: [_jsx("span", { className: "font-medium text-ink", children: step.title }), _jsx("span", { className: "text-body-sm text-body", children: step.body })] })] }, step.title))) }), _jsxs("button", { type: "button", onClick: copy("prompt", prompt.command), className: "inline-flex w-fit max-w-full flex-wrap items-center gap-3 rounded-pill border border-dashed border-[color-mix(in_oklch,currentColor_30%,transparent)] bg-transparent px-5 py-3 text-left font-mono text-mono text-body transition-colors hover:border-cyan hover:text-ink focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring", children: [_jsx("span", { "aria-hidden": "true", className: "shrink-0 font-bold text-lime", children: ">" }), prompt.command, _jsx("span", { className: "font-sans text-caption font-bold text-cyan", children: feedback.prompt ?? prompt.label })] }), _jsxs("div", { className: "grid gap-3 border-t border-hairline pt-5", children: [_jsx("span", { className: "text-caption font-medium text-faint", children: toolsLabel }), _jsx("ul", { role: "list", className: "m-0 flex list-none flex-wrap gap-2 p-0", children: tools.map((tool) => (_jsxs("li", { className: "inline-flex items-center gap-2 rounded-pill border border-hairline px-3 py-1 text-caption text-body", children: [_jsx(ToolLogo, { name: tool.name, mark: tool.mark, size: 15 }), tool.name] }, tool.name))) })] }), _jsx("p", { className: "m-0 max-w-measure text-caption text-faint", children: note }), _jsx("span", { "aria-live": "polite", className: "sr-only", children: feedback.cmd ?? feedback.prompt })] }));
28
+ }
29
+ export { PlugMethod };
30
+ //# sourceMappingURL=plug-method.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plug-method.js","sourceRoot":"","sources":["../../src/blocks/plug-method.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Pricing tiers as cards. Ported from v0's `site/PricingTierCards`.
3
+ *
4
+ * Prices are honest text from the caller's data, never numbers computed here. The
5
+ * featured tier gets the accent ring, which matches the compare matrix's CloudGrid
6
+ * column.
7
+ *
8
+ * ## Three changes from v0
9
+ *
10
+ * The check mark was a Phosphor SVG inlined as a string and rendered with
11
+ * `dangerouslySetInnerHTML`. It is lucide's `Check` now, for the same two reasons
12
+ * as `FeatureCells`: this registry declares lucide and already depends on it, and
13
+ * innerHTML for decoration is a sharp tool used for nothing.
14
+ *
15
+ * The CTA is a real anchor wearing `buttonVariants` rather than a `Button` with an
16
+ * `href` prop. Our `Button` is a Base UI button and has no `href`; a link that
17
+ * looks like a button should be an `<a>`, so it works with middle-click, "open in
18
+ * new tab" and a screen reader announcing a link rather than a button. The href
19
+ * comes from the caller's own tier data, so no route is being guessed.
20
+ *
21
+ * `dataCta` is dropped, as in `OptionCard`: the site's analytics vocabulary does
22
+ * not belong in a registry component's API. It still works through the anchor's
23
+ * own props if a caller wants it.
24
+ *
25
+ * The price uses `font-heavy`, which only exists because the display weight was
26
+ * unreachable until #42 — `--font-display` and `--font-weight-display` both
27
+ * compile to `font-display` and the family wins.
28
+ */
29
+ type PricingTier = {
30
+ name: string;
31
+ audience: string;
32
+ price: string;
33
+ priceNote: string;
34
+ blurb: string;
35
+ bullets: string[];
36
+ cta: {
37
+ label: string;
38
+ href: string;
39
+ };
40
+ featured: boolean;
41
+ };
42
+ declare function PricingTierCards({ tiers, className, ...props }: Omit<React.ComponentProps<"div">, "ref"> & {
43
+ tiers: PricingTier[];
44
+ }): import("react").JSX.Element;
45
+ export { PricingTierCards };
46
+ export type { PricingTier };
47
+ //# sourceMappingURL=pricing-tier-cards.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pricing-tier-cards.d.ts","sourceRoot":"","sources":["../../src/blocks/pricing-tier-cards.tsx"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,KAAK,WAAW,GAAG;IACjB,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,GAAG,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAA;IACpC,QAAQ,EAAE,OAAO,CAAA;CAClB,CAAA;AAED,iBAAS,gBAAgB,CAAC,EACxB,KAAK,EACL,SAAS,EACT,GAAG,KAAK,EACT,EAAE,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,GAAG;IAC5C,KAAK,EAAE,WAAW,EAAE,CAAA;CACrB,+BA8DA;AAED,OAAO,EAAE,gBAAgB,EAAE,CAAA;AAC3B,YAAY,EAAE,WAAW,EAAE,CAAA"}
@@ -0,0 +1,12 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Check } from "lucide-react";
3
+ import { buttonVariants } from "../ui/button.js";
4
+ import { cn } from "../lib/cloudgrid-cn.js";
5
+ function PricingTierCards({ tiers, className, ...props }) {
6
+ return (_jsx("div", { "data-slot": "pricing-tier-cards",
7
+ // auto-fit rather than a fixed column count: the number of tiers is the
8
+ // caller's, so the grid has to work for two as well as five.
9
+ className: cn("grid gap-5 [grid-template-columns:repeat(auto-fit,minmax(min(100%,18rem),1fr))]", className), ...props, children: tiers.map((tier) => (_jsxs("article", { "data-featured": tier.featured || undefined, className: cn("flex flex-col gap-3 rounded-xl border border-hairline bg-card p-6 text-ink", tier.featured && "border-brand bg-brand-tint"), children: [_jsx("p", { className: "m-0 text-label font-medium text-ink", children: tier.name }), tier.audience ? (_jsx("p", { className: "m-0 text-body-sm text-faint", children: tier.audience })) : null, _jsxs("p", { className: "m-0 font-display text-display-sm font-heavy text-ink", children: [tier.price, tier.priceNote ? (_jsx("span", { className: "ml-1 font-body text-body-sm font-medium text-body", children: tier.priceNote })) : null] }), _jsx("p", { className: "m-0 text-body-sm text-body", children: tier.blurb }), _jsx("ul", { role: "list", className: "m-0 grid list-none gap-2 p-0", children: tier.bullets.map((line) => (_jsxs("li", { className: "flex items-start gap-2 text-body-sm text-body", children: [_jsx(Check, { "aria-hidden": "true", className: "mt-1 size-3.5 shrink-0 text-brand" }), line] }, line))) }), _jsx("a", { href: tier.cta.href, className: cn(buttonVariants({ variant: tier.featured ? "default" : "outline" }), "mt-auto w-full no-underline"), children: tier.cta.label })] }, tier.name))) }));
10
+ }
11
+ export { PricingTierCards };
12
+ //# sourceMappingURL=pricing-tier-cards.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pricing-tier-cards.js","sourceRoot":"","sources":["../../src/blocks/pricing-tier-cards.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAA;AAEpC,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AACrD,OAAO,EAAE,EAAE,EAAE,MAAM,oBAAoB,CAAA;AAyCvC,SAAS,gBAAgB,CAAC,EACxB,KAAK,EACL,SAAS,EACT,GAAG,KAAK,EAGT;IACC,OAAO,CACL,2BACY,oBAAoB;QAC9B,wEAAwE;QACxE,6DAA6D;QAC7D,SAAS,EAAE,EAAE,CACX,iFAAiF,EACjF,SAAS,CACV,KACG,KAAK,YAER,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CACnB,oCAEiB,IAAI,CAAC,QAAQ,IAAI,SAAS,EACzC,SAAS,EAAE,EAAE,CACX,4EAA4E,EAC5E,IAAI,CAAC,QAAQ,IAAI,4BAA4B,CAC9C,aAED,YAAG,SAAS,EAAC,qCAAqC,YAAE,IAAI,CAAC,IAAI,GAAK,EACjE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CACf,YAAG,SAAS,EAAC,6BAA6B,YAAE,IAAI,CAAC,QAAQ,GAAK,CAC/D,CAAC,CAAC,CAAC,IAAI,EAER,aAAG,SAAS,EAAC,sDAAsD,aAChE,IAAI,CAAC,KAAK,EACV,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAChB,eAAM,SAAS,EAAC,mDAAmD,YAChE,IAAI,CAAC,SAAS,GACV,CACR,CAAC,CAAC,CAAC,IAAI,IACN,EAEJ,YAAG,SAAS,EAAC,4BAA4B,YAAE,IAAI,CAAC,KAAK,GAAK,EAE1D,aAAI,IAAI,EAAC,MAAM,EAAC,SAAS,EAAC,8BAA8B,YACrD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAC1B,cAAe,SAAS,EAAC,+CAA+C,aACtE,KAAC,KAAK,mBAAa,MAAM,EAAC,SAAS,EAAC,mCAAmC,GAAG,EACzE,IAAI,KAFE,IAAI,CAGR,CACN,CAAC,GACC,EAKL,YACE,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,EACnB,SAAS,EAAE,EAAE,CACX,cAAc,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,EAClE,6BAA6B,CAC9B,YAEA,IAAI,CAAC,GAAG,CAAC,KAAK,GACb,KA3CC,IAAI,CAAC,IAAI,CA4CN,CACX,CAAC,GACE,CACP,CAAA;AACH,CAAC;AAED,OAAO,EAAE,gBAAgB,EAAE,CAAA"}
@@ -0,0 +1,29 @@
1
+ import { type PricingTier } from "./pricing-tier-cards.js";
2
+ /**
3
+ * A titled pricing section. Ported from v0's `core/PricingTiers`.
4
+ *
5
+ * It is deliberately thin, and worth saying why it exists at all rather than
6
+ * telling callers to write two lines themselves.
7
+ *
8
+ * v0's version was a `band` plus a `container` plus an optional `h2` plus a
9
+ * max-width plus `PricingTierCards`. Strip the page wrappers, as every port here
10
+ * does, and what remains is a heading and a width. Its own header admitted the
11
+ * awkwardness: *"the band is generic and lives in core, the cards were flagged
12
+ * site-flavored during the extraction, and this import crosses that line
13
+ * internally."*
14
+ *
15
+ * It is kept because the width is not arbitrary. `--cg-column-wide` is a SOURCE
16
+ * measurement from the 1440px frames, and a pricing grid set to the full page
17
+ * width reads wrong at large sizes in a way that is not obvious until you see it.
18
+ * Encoding that once is the whole value; a caller reaching for
19
+ * `max-w-wide` themselves is a caller who has to know it exists.
20
+ *
21
+ * Compose `PricingTierCards` directly for a bespoke pricing page, which is what v0
22
+ * did too.
23
+ */
24
+ declare function PricingTiers({ title, tiers, className, ...props }: Omit<React.ComponentProps<"section">, "ref"> & {
25
+ title?: string;
26
+ tiers: PricingTier[];
27
+ }): import("react").JSX.Element;
28
+ export { PricingTiers };
29
+ //# sourceMappingURL=pricing-tiers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pricing-tiers.d.ts","sourceRoot":"","sources":["../../src/blocks/pricing-tiers.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAoB,KAAK,WAAW,EAAE,MAAM,kCAAkC,CAAA;AAGrF;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,iBAAS,YAAY,CAAC,EACpB,KAAK,EACL,KAAK,EACL,SAAS,EACT,GAAG,KAAK,EACT,EAAE,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,SAAS,CAAC,EAAE,KAAK,CAAC,GAAG;IAChD,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,WAAW,EAAE,CAAA;CACrB,+BAWA;AAED,OAAO,EAAE,YAAY,EAAE,CAAA"}
@@ -0,0 +1,30 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { PricingTierCards } from "./pricing-tier-cards.js";
3
+ import { cn } from "../lib/cloudgrid-cn.js";
4
+ /**
5
+ * A titled pricing section. Ported from v0's `core/PricingTiers`.
6
+ *
7
+ * It is deliberately thin, and worth saying why it exists at all rather than
8
+ * telling callers to write two lines themselves.
9
+ *
10
+ * v0's version was a `band` plus a `container` plus an optional `h2` plus a
11
+ * max-width plus `PricingTierCards`. Strip the page wrappers, as every port here
12
+ * does, and what remains is a heading and a width. Its own header admitted the
13
+ * awkwardness: *"the band is generic and lives in core, the cards were flagged
14
+ * site-flavored during the extraction, and this import crosses that line
15
+ * internally."*
16
+ *
17
+ * It is kept because the width is not arbitrary. `--cg-column-wide` is a SOURCE
18
+ * measurement from the 1440px frames, and a pricing grid set to the full page
19
+ * width reads wrong at large sizes in a way that is not obvious until you see it.
20
+ * Encoding that once is the whole value; a caller reaching for
21
+ * `max-w-wide` themselves is a caller who has to know it exists.
22
+ *
23
+ * Compose `PricingTierCards` directly for a bespoke pricing page, which is what v0
24
+ * did too.
25
+ */
26
+ function PricingTiers({ title, tiers, className, ...props }) {
27
+ return (_jsxs("section", { "data-slot": "pricing-tiers", className: cn("flex flex-col gap-8", className), ...props, children: [title ? _jsx("h2", { className: "m-0 text-heading-lg font-medium text-ink", children: title }) : null, _jsx(PricingTierCards, { tiers: tiers, className: "max-w-wide" })] }));
28
+ }
29
+ export { PricingTiers };
30
+ //# sourceMappingURL=pricing-tiers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pricing-tiers.js","sourceRoot":"","sources":["../../src/blocks/pricing-tiers.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,gBAAgB,EAAoB,MAAM,kCAAkC,CAAA;AACrF,OAAO,EAAE,EAAE,EAAE,MAAM,oBAAoB,CAAA;AAEvC;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,SAAS,YAAY,CAAC,EACpB,KAAK,EACL,KAAK,EACL,SAAS,EACT,GAAG,KAAK,EAIT;IACC,OAAO,CACL,gCACY,eAAe,EACzB,SAAS,EAAE,EAAE,CAAC,qBAAqB,EAAE,SAAS,CAAC,KAC3C,KAAK,aAER,KAAK,CAAC,CAAC,CAAC,aAAI,SAAS,EAAC,0CAA0C,YAAE,KAAK,GAAM,CAAC,CAAC,CAAC,IAAI,EACrF,KAAC,gBAAgB,IAAC,KAAK,EAAE,KAAK,EAAE,SAAS,EAAC,YAAY,GAAG,IACjD,CACX,CAAA;AACH,CAAC;AAED,OAAO,EAAE,YAAY,EAAE,CAAA"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * A pull quote on the reading measure, with an optional mono attribution.
3
+ *
4
+ * Ported from v0's `core/Quote`. Two deliberate changes.
5
+ *
6
+ * v0 wrapped this in its own `band` and `container` classes, which are the
7
+ * site's page-level layout. A registry component has no business imposing page
8
+ * layout on a consumer, so they are dropped: this renders a `<figure>` on the
9
+ * measure and nothing more. Put it inside whatever section wrapper the
10
+ * consuming page already has.
11
+ *
12
+ * v0's `mx-auto` went with them, for the same reason: centring is page layout.
13
+ * On the measure inside a left-aligned section it read as a mistake. Add
14
+ * `className="mx-auto"` if the page wants it centred.
15
+ *
16
+ * v0 sized the quote with `clamp(1.25rem, 3vw, 1.75rem)`, which is 20px to 28px
17
+ * and lands on no step of the brand scale. Expressed here as a responsive pair
18
+ * that does: heading-md (20px) to heading-lg (24px). Slightly smaller at the top
19
+ * end than v0, and on the ramp, which the brand asks for. An arbitrary
20
+ * `text-[clamp(...)]` would also be caught by the type-scale assertion.
21
+ */
22
+ declare function Quote({ text, attribution, className, ...props }: React.ComponentProps<"figure"> & {
23
+ text: string;
24
+ attribution?: string;
25
+ }): import("react").JSX.Element;
26
+ export { Quote };
27
+ //# sourceMappingURL=quote.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quote.d.ts","sourceRoot":"","sources":["../../src/blocks/quote.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,iBAAS,KAAK,CAAC,EACb,IAAI,EACJ,WAAW,EACX,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,QAAQ,CAAC,GAAG;IAClC,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,+BAiBA;AAED,OAAO,EAAE,KAAK,EAAE,CAAA"}
@@ -0,0 +1,28 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { cn } from "../lib/cloudgrid-cn.js";
3
+ /**
4
+ * A pull quote on the reading measure, with an optional mono attribution.
5
+ *
6
+ * Ported from v0's `core/Quote`. Two deliberate changes.
7
+ *
8
+ * v0 wrapped this in its own `band` and `container` classes, which are the
9
+ * site's page-level layout. A registry component has no business imposing page
10
+ * layout on a consumer, so they are dropped: this renders a `<figure>` on the
11
+ * measure and nothing more. Put it inside whatever section wrapper the
12
+ * consuming page already has.
13
+ *
14
+ * v0's `mx-auto` went with them, for the same reason: centring is page layout.
15
+ * On the measure inside a left-aligned section it read as a mistake. Add
16
+ * `className="mx-auto"` if the page wants it centred.
17
+ *
18
+ * v0 sized the quote with `clamp(1.25rem, 3vw, 1.75rem)`, which is 20px to 28px
19
+ * and lands on no step of the brand scale. Expressed here as a responsive pair
20
+ * that does: heading-md (20px) to heading-lg (24px). Slightly smaller at the top
21
+ * end than v0, and on the ramp, which the brand asks for. An arbitrary
22
+ * `text-[clamp(...)]` would also be caught by the type-scale assertion.
23
+ */
24
+ function Quote({ text, attribution, className, ...props }) {
25
+ return (_jsxs("figure", { "data-slot": "quote", className: cn("max-w-(--cg-measure) text-ink", className), ...props, children: [_jsx("blockquote", { className: "m-0 text-heading-md leading-snug text-balance md:text-heading-lg", children: text }), attribution ? (_jsx("figcaption", { className: "mt-4 font-mono text-mono text-body", children: attribution })) : null] }));
26
+ }
27
+ export { Quote };
28
+ //# sourceMappingURL=quote.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quote.js","sourceRoot":"","sources":["../../src/blocks/quote.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,oBAAoB,CAAA;AAEvC;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,SAAS,KAAK,CAAC,EACb,IAAI,EACJ,WAAW,EACX,SAAS,EACT,GAAG,KAAK,EAIT;IACC,OAAO,CACL,+BACY,OAAO,EACjB,SAAS,EAAE,EAAE,CAAC,+BAA+B,EAAE,SAAS,CAAC,KACrD,KAAK,aAIT,qBAAY,SAAS,EAAC,kEAAkE,YACrF,IAAI,GACM,EACZ,WAAW,CAAC,CAAC,CAAC,CACb,qBAAY,SAAS,EAAC,oCAAoC,YAAE,WAAW,GAAc,CACtF,CAAC,CAAC,CAAC,IAAI,IACD,CACV,CAAA;AACH,CAAC;AAED,OAAO,EAAE,KAAK,EAAE,CAAA"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Typography for HTML you did not write: the output of a markdown parser or a CMS,
3
+ * where the tags arrive as-is and there is nowhere to put a class.
4
+ *
5
+ * The styling is `@cloudgrid-io/ui/prose.css`, which this component's registry
6
+ * entry imports for you. It is plain CSS in the tokens package rather than here, so
7
+ * the Astro site can use the same recipe without pulling a React component.
8
+ *
9
+ * ## It does not parse markdown, and that is the point
10
+ *
11
+ * v0's version took a markdown string, ran `marked.parse()`, and injected the
12
+ * result. Its own header carried the warning:
13
+ *
14
+ * > TRUST NOTE: the result is injected as HTML. Markdown permits raw HTML, so
15
+ * > `markdown` must come from a trusted source, never unsanitised user input.
16
+ *
17
+ * A registry ships source into other people's repositories. Shipping a component
18
+ * that runs a parser and injects the output, with a comment asking the reader to
19
+ * only pass trusted input, is putting a footgun in someone else's codebase and
20
+ * hoping they read the label. It would also drag `marked` into every consumer's
21
+ * dependencies for a component many of them would use with a CMS instead.
22
+ *
23
+ * So this takes **already-rendered HTML**. The parse stays at the call site, where
24
+ * the caller already knows where the content came from, which is the only place
25
+ * that judgement can honestly be made. `dangerouslySetInnerHTML` is still what
26
+ * renders it, and it is still on the caller to have sanitised anything untrusted:
27
+ * the difference is that the decision is now visible in their code rather than
28
+ * buried in ours.
29
+ *
30
+ * Prefer `children` where you have real elements. It skips the innerHTML path
31
+ * entirely and still gets the typography.
32
+ */
33
+ declare function RichText({ html, className, children, ...props }: Omit<React.ComponentProps<"div">, "ref" | "dangerouslySetInnerHTML"> & {
34
+ /** Rendered, trusted HTML. Sanitise before this if the source is not yours. */
35
+ html?: string;
36
+ }): import("react").JSX.Element;
37
+ export { RichText };
38
+ //# sourceMappingURL=rich-text.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rich-text.d.ts","sourceRoot":"","sources":["../../src/blocks/rich-text.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,iBAAS,QAAQ,CAAC,EAChB,IAAI,EACJ,SAAS,EACT,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,KAAK,GAAG,yBAAyB,CAAC,GAAG;IACxE,+EAA+E;IAC/E,IAAI,CAAC,EAAE,MAAM,CAAA;CACd,+BAcA;AAED,OAAO,EAAE,QAAQ,EAAE,CAAA"}
@@ -0,0 +1,39 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { cn } from "../lib/cloudgrid-cn.js";
3
+ /**
4
+ * Typography for HTML you did not write: the output of a markdown parser or a CMS,
5
+ * where the tags arrive as-is and there is nowhere to put a class.
6
+ *
7
+ * The styling is `@cloudgrid-io/ui/prose.css`, which this component's registry
8
+ * entry imports for you. It is plain CSS in the tokens package rather than here, so
9
+ * the Astro site can use the same recipe without pulling a React component.
10
+ *
11
+ * ## It does not parse markdown, and that is the point
12
+ *
13
+ * v0's version took a markdown string, ran `marked.parse()`, and injected the
14
+ * result. Its own header carried the warning:
15
+ *
16
+ * > TRUST NOTE: the result is injected as HTML. Markdown permits raw HTML, so
17
+ * > `markdown` must come from a trusted source, never unsanitised user input.
18
+ *
19
+ * A registry ships source into other people's repositories. Shipping a component
20
+ * that runs a parser and injects the output, with a comment asking the reader to
21
+ * only pass trusted input, is putting a footgun in someone else's codebase and
22
+ * hoping they read the label. It would also drag `marked` into every consumer's
23
+ * dependencies for a component many of them would use with a CMS instead.
24
+ *
25
+ * So this takes **already-rendered HTML**. The parse stays at the call site, where
26
+ * the caller already knows where the content came from, which is the only place
27
+ * that judgement can honestly be made. `dangerouslySetInnerHTML` is still what
28
+ * renders it, and it is still on the caller to have sanitised anything untrusted:
29
+ * the difference is that the decision is now visible in their code rather than
30
+ * buried in ours.
31
+ *
32
+ * Prefer `children` where you have real elements. It skips the innerHTML path
33
+ * entirely and still gets the typography.
34
+ */
35
+ function RichText({ html, className, children, ...props }) {
36
+ return (_jsx("div", { "data-slot": "rich-text", className: cn("prose", className), ...(html !== undefined ? { dangerouslySetInnerHTML: { __html: html } } : {}), ...props, children: html !== undefined ? undefined : children }));
37
+ }
38
+ export { RichText };
39
+ //# sourceMappingURL=rich-text.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rich-text.js","sourceRoot":"","sources":["../../src/blocks/rich-text.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,oBAAoB,CAAA;AAEvC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,SAAS,QAAQ,CAAC,EAChB,IAAI,EACJ,SAAS,EACT,QAAQ,EACR,GAAG,KAAK,EAIT;IACC,OAAO,CACL,2BACY,WAAW,EACrB,SAAS,EAAE,EAAE,CAAC,OAAO,EAAE,SAAS,CAAC,KAI7B,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,uBAAuB,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,KACzE,KAAK,YAER,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,GACtC,CACP,CAAA;AACH,CAAC;AAED,OAAO,EAAE,QAAQ,EAAE,CAAA"}
@@ -0,0 +1,5 @@
1
+ declare function StagePanel({ shadow, className, children, ...props }: Omit<React.ComponentProps<"section">, "ref"> & {
2
+ shadow?: boolean;
3
+ }): import("react").JSX.Element;
4
+ export { StagePanel };
5
+ //# sourceMappingURL=stage-panel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stage-panel.d.ts","sourceRoot":"","sources":["../../src/blocks/stage-panel.tsx"],"names":[],"mappings":"AA4BA,iBAAS,UAAU,CAAC,EAClB,MAAa,EACb,SAAS,EACT,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,SAAS,CAAC,EAAE,KAAK,CAAC,GAAG;IAChD,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB,+BAyBA;AAED,OAAO,EAAE,UAAU,EAAE,CAAA"}
@@ -0,0 +1,30 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Panel } from "../ui/panel.js";
3
+ import { cn } from "../lib/cloudgrid-cn.js";
4
+ /**
5
+ * The purple stage: a `Panel` carrying its own texture, a white hairline grid plus
6
+ * the wordmark's socket, both drawn in CSS and inline SVG so nothing loads.
7
+ *
8
+ * Ported from v0's `site/StagePanel`. Kept on the operator's instruction recorded
9
+ * in its header: the first-seats pitch left the homepage, but "definitely keep
10
+ * this element in our design system", especially the background.
11
+ *
12
+ * v0 drew the texture with `rgba(255, 255, 255, 0.07)` and `rgba(255, 255, 255,
13
+ * 0.1)`. Both are literal colours, which the literal gate correctly refuses. They
14
+ * are derived from `currentColor` here instead, which inside a panel already
15
+ * resolves to the flipped text colour, so the texture is white on purple without a
16
+ * hardcoded white anywhere, and it follows the surface if this is ever used on
17
+ * ink. `color-mix(in oklch, ...)` rather than `oklch(...)`, which the gate also
18
+ * bans, and the same construction `button.tsx` already uses.
19
+ *
20
+ * The socket is `aria-hidden`, as is the grid: both are texture, and a screen
21
+ * reader announcing a decorative wordmark twice per page is noise.
22
+ */
23
+ /** The socket from the brand wordmark, the "o" of CloudGrid. Same path the favicon
24
+ * carries, so it is replaced from the brand asset rather than edited. */
25
+ const SOCKET_PATH = "M73.507 15.918C79.2174 15.918 83.9637 17.7685 87.6718 21.3962C91.4541 25.0239 93.3088 29.6883 93.3088 35.4631C93.3088 41.2378 91.454 45.9761 87.6718 49.6038C85.0356 52.1829 81.8742 53.8602 78.215 54.6154C77.054 54.855 76.0252 53.9204 76.0252 52.7349V47.5482C76.0252 46.6336 76.6575 45.8569 77.493 45.4848C81.0368 43.9067 83.2962 40.1577 83.2962 35.4872C83.2962 34.0556 83.0947 32.7167 82.7167 31.5015C82.5932 31.1043 82.2168 30.8479 81.8008 30.8479H80.8927V27.1501C80.8923 25.785 79.7842 24.6784 78.4167 24.6783C77.0492 24.6783 75.941 25.785 75.9407 27.1501V30.8479H71.3901V27.1501C71.3897 25.785 70.2801 24.6783 68.9126 24.6783C67.5454 24.6787 66.4369 25.7852 66.4366 27.1501V30.8479H65.2899C64.88 30.8479 64.5075 31.0968 64.381 31.4867C63.9866 32.7028 63.7916 34.0384 63.7916 35.4872C63.7916 38.5967 64.6821 41.188 66.5362 43.261C67.4434 44.239 68.4572 44.9856 69.5949 45.4935C70.4337 45.868 71.0717 46.6457 71.0717 47.5643V52.7493C71.0717 53.9323 70.0469 54.8663 68.8877 54.6302C65.2186 53.8826 62.07 52.2003 59.416 49.6038C55.708 45.9761 53.8545 41.2377 53.8545 35.4631C53.8545 29.6884 55.708 25.0239 59.416 21.3962C63.1241 17.7685 67.7966 15.918 73.507 15.918Z";
26
+ function StagePanel({ shadow = true, className, children, ...props }) {
27
+ return (_jsxs(Panel, { inset: "flush", shadow: shadow, "data-slot": "stage-panel", className: cn("relative overflow-hidden", className), ...props, children: [_jsx("span", { "aria-hidden": "true", className: "pointer-events-none absolute inset-0 [background-image:repeating-linear-gradient(to_right,color-mix(in_oklch,currentColor_7%,transparent)_0_1px,transparent_1px_64px),repeating-linear-gradient(to_bottom,color-mix(in_oklch,currentColor_7%,transparent)_0_1px,transparent_1px_64px)]" }), _jsx("span", { "aria-hidden": "true", className: "pointer-events-none absolute -right-[3%] -bottom-[14%] w-[clamp(180px,24vw,300px)] text-[color-mix(in_oklch,currentColor_10%,transparent)]", children: _jsx("svg", { viewBox: "41.58 3.28 64 64", fill: "currentColor", className: "h-auto w-full", children: _jsx("path", { d: SOCKET_PATH }) }) }), _jsx("div", { className: "relative", children: children })] }));
28
+ }
29
+ export { StagePanel };
30
+ //# sourceMappingURL=stage-panel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stage-panel.js","sourceRoot":"","sources":["../../src/blocks/stage-panel.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAA;AAC3C,OAAO,EAAE,EAAE,EAAE,MAAM,oBAAoB,CAAA;AAEvC;;;;;;;;;;;;;;;;;;GAkBG;AAEH;0EAC0E;AAC1E,MAAM,WAAW,GACf,+oCAA+oC,CAAA;AAEjpC,SAAS,UAAU,CAAC,EAClB,MAAM,GAAG,IAAI,EACb,SAAS,EACT,QAAQ,EACR,GAAG,KAAK,EAGT;IACC,OAAO,CACL,MAAC,KAAK,IACJ,KAAK,EAAC,OAAO,EACb,MAAM,EAAE,MAAM,eACJ,aAAa,EACvB,SAAS,EAAE,EAAE,CAAC,0BAA0B,EAAE,SAAS,CAAC,KAChD,KAAK,aAET,8BACc,MAAM,EAClB,SAAS,EAAC,wRAAwR,GAClS,EACF,8BACc,MAAM,EAClB,SAAS,EAAC,4IAA4I,YAEtJ,cAAK,OAAO,EAAC,kBAAkB,EAAC,IAAI,EAAC,cAAc,EAAC,SAAS,EAAC,eAAe,YAC3E,eAAM,CAAC,EAAE,WAAW,GAAI,GACpB,GACD,EAEP,cAAK,SAAS,EAAC,UAAU,YAAE,QAAQ,GAAO,IACpC,CACT,CAAA;AACH,CAAC;AAED,OAAO,EAAE,UAAU,EAAE,CAAA"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * One numbered step. Renders an `<li>`, so wrap a set in an `<ol>`.
3
+ *
4
+ * That wrapping is not cosmetic. The numeral badge is `aria-hidden`, because the
5
+ * `<ol>` already numbers the list for a screen reader and reading "1 1 Plug it"
6
+ * is worse than reading "1 Plug it". Drop one of these outside an `<ol>` and the
7
+ * numbers stop existing for anyone not looking at the screen. `StepList` below
8
+ * exists so that is the easy path rather than the remembered one.
9
+ *
10
+ * Ported from v0's `core/StepItem`, keeping its note: the numeral is the cyan
11
+ * "go" accent, so a step list is usually the one cyan thing on its page. Do not
12
+ * put an accent button beside one.
13
+ *
14
+ * One deliberate change. v0's badge is 26px, which is on no step of the 4px
15
+ * spacing ramp. This is 24px (`size-6`), which is. Two pixels, and it stops the
16
+ * component being the reason someone thinks the ramp has exceptions.
17
+ */
18
+ declare function StepList({ className, ...props }: React.ComponentProps<"ol">): import("react").JSX.Element;
19
+ declare function StepItem({ index, title, className, children, ...props }: React.ComponentProps<"li"> & {
20
+ index: number;
21
+ title: string;
22
+ }): import("react").JSX.Element;
23
+ export { StepItem, StepList };
24
+ //# sourceMappingURL=step-item.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"step-item.d.ts","sourceRoot":"","sources":["../../src/blocks/step-item.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;GAgBG;AACH,iBAAS,QAAQ,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,IAAI,CAAC,+BAepE;AAED,iBAAS,QAAQ,CAAC,EAChB,KAAK,EACL,KAAK,EACL,SAAS,EACT,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,IAAI,CAAC,GAAG;IAC9B,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;CACd,+BAqBA;AAED,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAA"}
@@ -0,0 +1,34 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { cn } from "../lib/cloudgrid-cn.js";
3
+ /**
4
+ * One numbered step. Renders an `<li>`, so wrap a set in an `<ol>`.
5
+ *
6
+ * That wrapping is not cosmetic. The numeral badge is `aria-hidden`, because the
7
+ * `<ol>` already numbers the list for a screen reader and reading "1 1 Plug it"
8
+ * is worse than reading "1 Plug it". Drop one of these outside an `<ol>` and the
9
+ * numbers stop existing for anyone not looking at the screen. `StepList` below
10
+ * exists so that is the easy path rather than the remembered one.
11
+ *
12
+ * Ported from v0's `core/StepItem`, keeping its note: the numeral is the cyan
13
+ * "go" accent, so a step list is usually the one cyan thing on its page. Do not
14
+ * put an accent button beside one.
15
+ *
16
+ * One deliberate change. v0's badge is 26px, which is on no step of the 4px
17
+ * spacing ramp. This is 24px (`size-6`), which is. Two pixels, and it stops the
18
+ * component being the reason someone thinks the ramp has exceptions.
19
+ */
20
+ function StepList({ className, ...props }) {
21
+ return (_jsx("ol", {
22
+ // Explicit, and load-bearing. WebKit drops the implicit `list` role from an
23
+ // <ol> when list-style is none, and the numeral in each item is aria-hidden
24
+ // because the list is supposed to be doing the numbering. Without this,
25
+ // VoiceOver gets neither: the badge is hidden and the enumeration is gone,
26
+ // which is the exact outcome StepItem's comment exists to prevent. Raised
27
+ // in review on #42.
28
+ role: "list", "data-slot": "step-list", className: cn("flex list-none flex-col gap-5 p-0", className), ...props }));
29
+ }
30
+ function StepItem({ index, title, className, children, ...props }) {
31
+ return (_jsxs("li", { "data-slot": "step-item", className: cn("flex items-start gap-4", className), ...props, children: [_jsx("span", { "aria-hidden": "true", className: "flex size-6 shrink-0 items-center justify-center rounded-pill bg-cyan text-caption font-bold text-on-accent", children: index }), _jsxs("div", { className: "flex min-w-0 flex-1 flex-col gap-2", children: [_jsx("span", { className: "text-heading-sm font-medium text-ink", children: title }), children ? _jsx("div", { className: "text-body-sm text-body", children: children }) : null] })] }));
32
+ }
33
+ export { StepItem, StepList };
34
+ //# sourceMappingURL=step-item.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"step-item.js","sourceRoot":"","sources":["../../src/blocks/step-item.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,oBAAoB,CAAA;AAEvC;;;;;;;;;;;;;;;;GAgBG;AACH,SAAS,QAAQ,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAA8B;IACnE,OAAO,CACL;QACE,4EAA4E;QAC5E,4EAA4E;QAC5E,wEAAwE;QACxE,2EAA2E;QAC3E,0EAA0E;QAC1E,oBAAoB;QACpB,IAAI,EAAC,MAAM,eACD,WAAW,EACrB,SAAS,EAAE,EAAE,CAAC,mCAAmC,EAAE,SAAS,CAAC,KACzD,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED,SAAS,QAAQ,CAAC,EAChB,KAAK,EACL,KAAK,EACL,SAAS,EACT,QAAQ,EACR,GAAG,KAAK,EAIT;IACC,OAAO,CACL,2BACY,WAAW,EACrB,SAAS,EAAE,EAAE,CAAC,wBAAwB,EAAE,SAAS,CAAC,KAC9C,KAAK,aAET,8BACc,MAAM,EAClB,SAAS,EAAC,6GAA6G,YAEtH,KAAK,GACD,EACP,eAAK,SAAS,EAAC,oCAAoC,aACjD,eAAM,SAAS,EAAC,sCAAsC,YAAE,KAAK,GAAQ,EAGpE,QAAQ,CAAC,CAAC,CAAC,cAAK,SAAS,EAAC,wBAAwB,YAAE,QAAQ,GAAO,CAAC,CAAC,CAAC,IAAI,IACvE,IACH,CACN,CAAA;AACH,CAAC;AAED,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAA"}
@@ -0,0 +1,15 @@
1
+ declare function ToolLogo({ name, mark, hex, size, tone, opticalScale, className, ...props }: Omit<React.ComponentProps<"span">, "ref"> & {
2
+ /** Display name. Used for the monogram fallback and nothing else. */
3
+ name: string;
4
+ /** The vendor's own mark. An inline SVG, sized by this component. */
5
+ mark?: React.ReactNode;
6
+ /** The vendor's brand hex, without the leading #. Ignored if too dark for ink. */
7
+ hex?: string;
8
+ size?: number;
9
+ /** `ink` ignores the brand hex and follows currentColor everywhere. */
10
+ tone?: "brand" | "ink";
11
+ /** Nudge for artwork that sits deep in its viewBox. 1.16 suits some sets. */
12
+ opticalScale?: number;
13
+ }): import("react").JSX.Element;
14
+ export { ToolLogo };
15
+ //# sourceMappingURL=tool-logo.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-logo.d.ts","sourceRoot":"","sources":["../../src/blocks/tool-logo.tsx"],"names":[],"mappings":"AAgDA,iBAAS,QAAQ,CAAC,EAChB,IAAI,EACJ,IAAI,EACJ,GAAG,EACH,IAAS,EACT,IAAc,EACd,YAAgB,EAChB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,EAAE,KAAK,CAAC,GAAG;IAC7C,qEAAqE;IACrE,IAAI,EAAE,MAAM,CAAA;IACZ,qEAAqE;IACrE,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACtB,kFAAkF;IAClF,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,uEAAuE;IACvE,IAAI,CAAC,EAAE,OAAO,GAAG,KAAK,CAAA;IACtB,6EAA6E;IAC7E,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB,+BA8CA;AAED,OAAO,EAAE,QAAQ,EAAE,CAAA"}