@krizaka/ui 2.9.0 → 2.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +41 -5
- package/dist/blocks.css +247 -0
- package/dist/catalogue-page.d.ts +34 -0
- package/dist/catalogue-page.js +26 -0
- package/dist/catalogue-page.js.map +1 -0
- package/dist/changelog-page.d.ts +50 -0
- package/dist/changelog-page.js +27 -0
- package/dist/changelog-page.js.map +1 -0
- package/dist/{chunk-NOVUREEC.js → chunk-JZPVUJIX.js} +25 -3
- package/dist/chunk-JZPVUJIX.js.map +1 -0
- package/dist/chunk-KNBYZGSQ.js +11 -0
- package/dist/chunk-KNBYZGSQ.js.map +1 -0
- package/dist/component-page.d.ts +41 -0
- package/dist/component-page.js +17 -0
- package/dist/component-page.js.map +1 -0
- package/dist/contact-page.d.ts +31 -0
- package/dist/contact-page.js +26 -0
- package/dist/contact-page.js.map +1 -0
- package/dist/docs-article-page.d.ts +54 -0
- package/dist/docs-article-page.js +29 -0
- package/dist/docs-article-page.js.map +1 -0
- package/dist/docs-hub-page.d.ts +72 -0
- package/dist/docs-hub-page.js +45 -0
- package/dist/docs-hub-page.js.map +1 -0
- package/dist/error-page.d.ts +22 -0
- package/dist/error-page.js +23 -0
- package/dist/error-page.js.map +1 -0
- package/dist/gallery-page.d.ts +50 -0
- package/dist/gallery-page.js +30 -0
- package/dist/gallery-page.js.map +1 -0
- package/dist/{geometry-CXrAW34x.d.ts → geometry-CbOU4rtL.d.ts} +4 -4
- package/dist/how-it-works-page.d.ts +48 -0
- package/dist/how-it-works-page.js +28 -0
- package/dist/how-it-works-page.js.map +1 -0
- package/dist/index.d.ts +11 -2
- package/dist/index.js +93 -5
- package/dist/index.js.map +1 -1
- package/dist/landing-page.d.ts +58 -0
- package/dist/landing-page.js +42 -0
- package/dist/landing-page.js.map +1 -0
- package/dist/legal-page.d.ts +34 -0
- package/dist/legal-page.js +18 -0
- package/dist/legal-page.js.map +1 -0
- package/dist/longform-page.d.ts +42 -0
- package/dist/longform-page.js +29 -0
- package/dist/longform-page.js.map +1 -0
- package/dist/mascot-quote.d.ts +4 -4
- package/dist/mascot-quote.js +23 -1
- package/dist/mascot-quote.js.map +1 -1
- package/dist/mascot-state.d.ts +2 -2
- package/dist/mascot-state.js +1 -1
- package/dist/mascot-state.js.map +1 -1
- package/dist/mascots.d.ts +4 -4
- package/dist/mascots.js +1 -1
- package/dist/native.d.ts +16 -9
- package/dist/native.js +183 -74
- package/dist/native.js.map +1 -1
- package/dist/pricing-page.d.ts +62 -0
- package/dist/pricing-page.js +71 -0
- package/dist/pricing-page.js.map +1 -0
- package/dist/product-page.d.ts +83 -0
- package/dist/product-page.js +60 -0
- package/dist/product-page.js.map +1 -0
- package/dist/status-page.d.ts +42 -0
- package/dist/status-page.js +28 -0
- package/dist/status-page.js.map +1 -0
- package/package.json +233 -7
- package/registry/achievement.json +1 -1
- package/registry/action-bar.json +1 -1
- package/registry/alert.json +1 -1
- package/registry/app-shell.json +1 -1
- package/registry/argument-card.json +1 -1
- package/registry/audio-player.json +1 -1
- package/registry/auth-layout.json +1 -1
- package/registry/avatar.json +1 -1
- package/registry/badge.json +1 -1
- package/registry/button.json +1 -1
- package/registry/card-grid.json +1 -1
- package/registry/card.json +1 -1
- package/registry/catalogue-page.json +240 -0
- package/registry/changelog-page.json +226 -0
- package/registry/checkbox.json +1 -1
- package/registry/chip-link.json +1 -1
- package/registry/chip.json +1 -1
- package/registry/choice-grid.json +1 -1
- package/registry/code-block.json +1 -1
- package/registry/combobox.json +1 -1
- package/registry/command.json +1 -1
- package/registry/component-page.json +227 -0
- package/registry/confirm-button.json +1 -1
- package/registry/contact-page.json +212 -0
- package/registry/continue-prompt.json +1 -1
- package/registry/countdown.json +1 -1
- package/registry/cta-panel.json +1 -1
- package/registry/dashboard-layout.json +1 -1
- package/registry/data-table.json +1 -1
- package/registry/date-picker.json +1 -1
- package/registry/decision-list.json +1 -1
- package/registry/detail-layout.json +1 -1
- package/registry/dialog.json +1 -1
- package/registry/docs-article-page.json +242 -0
- package/registry/docs-hub-page.json +270 -0
- package/registry/docs-layout.json +1 -1
- package/registry/dropdown-menu.json +1 -1
- package/registry/empty-state.json +1 -1
- package/registry/error-page.json +183 -0
- package/registry/examples/catalogue-page/components.d.ts +4 -0
- package/registry/examples/catalogue-page/components.js +33 -0
- package/registry/examples/catalogue-page/components.tsx +36 -0
- package/registry/examples/changelog-page/releases.d.ts +4 -0
- package/registry/examples/changelog-page/releases.js +44 -0
- package/registry/examples/changelog-page/releases.tsx +39 -0
- package/registry/examples/component-page/button.d.ts +4 -0
- package/registry/examples/component-page/button.js +33 -0
- package/registry/examples/component-page/button.tsx +30 -0
- package/registry/examples/contact-page/team.d.ts +4 -0
- package/registry/examples/contact-page/team.js +39 -0
- package/registry/examples/contact-page/team.tsx +38 -0
- package/registry/examples/docs-article-page/cli.d.ts +4 -0
- package/registry/examples/docs-article-page/cli.js +33 -0
- package/registry/examples/docs-article-page/cli.tsx +38 -0
- package/registry/examples/docs-hub-page/krizaka.d.ts +4 -0
- package/registry/examples/docs-hub-page/krizaka.js +46 -0
- package/registry/examples/docs-hub-page/krizaka.tsx +37 -0
- package/registry/examples/error-page/not-found.d.ts +4 -0
- package/registry/examples/error-page/not-found.js +24 -0
- package/registry/examples/error-page/not-found.tsx +19 -0
- package/registry/examples/gallery-page/made-here.d.ts +4 -0
- package/registry/examples/gallery-page/made-here.js +34 -0
- package/registry/examples/gallery-page/made-here.tsx +32 -0
- package/registry/examples/how-it-works-page/orazaka.d.ts +4 -0
- package/registry/examples/how-it-works-page/orazaka.js +30 -0
- package/registry/examples/how-it-works-page/orazaka.tsx +26 -0
- package/registry/examples/landing-page/krizaka.d.ts +4 -0
- package/registry/examples/landing-page/krizaka.js +44 -0
- package/registry/examples/landing-page/krizaka.tsx +44 -0
- package/registry/examples/legal-page/privacy.d.ts +4 -0
- package/registry/examples/legal-page/privacy.js +24 -0
- package/registry/examples/legal-page/privacy.tsx +19 -0
- package/registry/examples/longform-page/story.d.ts +4 -0
- package/registry/examples/longform-page/story.js +38 -0
- package/registry/examples/longform-page/story.tsx +35 -0
- package/registry/examples/mascots/crane.d.ts +4 -0
- package/registry/examples/mascots/crane.js +19 -0
- package/registry/examples/mascots/crane.tsx +18 -0
- package/registry/examples/mascots/flock.tsx +2 -1
- package/registry/examples/mascots/native/crane.d.ts +4 -0
- package/registry/examples/mascots/native/crane.dark.png +0 -0
- package/registry/examples/mascots/native/crane.js +21 -0
- package/registry/examples/mascots/native/crane.light.png +0 -0
- package/registry/examples/mascots/native/crane.tsx +18 -0
- package/registry/examples/pricing-page/credits.d.ts +4 -0
- package/registry/examples/pricing-page/credits.js +41 -0
- package/registry/examples/pricing-page/credits.tsx +33 -0
- package/registry/examples/product-page/orazaka.d.ts +4 -0
- package/registry/examples/product-page/orazaka.js +44 -0
- package/registry/examples/product-page/orazaka.tsx +36 -0
- package/registry/examples/status-page/building.d.ts +4 -0
- package/registry/examples/status-page/building.js +29 -0
- package/registry/examples/status-page/building.tsx +25 -0
- package/registry/examples/status-page/operational.d.ts +4 -0
- package/registry/examples/status-page/operational.js +26 -0
- package/registry/examples/status-page/operational.tsx +20 -0
- package/registry/field.json +1 -1
- package/registry/file-upload.json +1 -1
- package/registry/filter-bar.json +1 -1
- package/registry/gallery-page.json +256 -0
- package/registry/glow-card.json +1 -1
- package/registry/goal-gauge.json +1 -1
- package/registry/how-it-works-page.json +242 -0
- package/registry/image-cropper.json +1 -1
- package/registry/index.json +309 -5
- package/registry/iso.json +1 -1
- package/registry/kbd.json +1 -1
- package/registry/landing-page.json +242 -0
- package/registry/landscape.json +1 -1
- package/registry/legal-page.json +199 -0
- package/registry/link-card.json +1 -1
- package/registry/loader.json +1 -1
- package/registry/longform-page.json +213 -0
- package/registry/marketing-layout.json +1 -1
- package/registry/marquee.json +1 -1
- package/registry/mascot-quote.json +6 -6
- package/registry/mascot-state.json +34 -34
- package/registry/mascots.json +41 -21
- package/registry/media-capture.json +1 -1
- package/registry/meter.json +1 -1
- package/registry/nav-bar.json +1 -1
- package/registry/number-ticker.json +1 -1
- package/registry/page-header.json +1 -1
- package/registry/page-hero.json +1 -1
- package/registry/page.json +1 -1
- package/registry/pagination.json +1 -1
- package/registry/pointer-light.json +1 -1
- package/registry/popover.json +1 -1
- package/registry/pricing-page.json +245 -0
- package/registry/product-page.json +319 -0
- package/registry/profile-card.json +1 -1
- package/registry/progress.json +1 -1
- package/registry/promise-card.json +1 -1
- package/registry/radio-group.json +1 -1
- package/registry/scroll-stage.json +1 -1
- package/registry/search-field.json +1 -1
- package/registry/section-backdrop.json +1 -1
- package/registry/separator.json +1 -1
- package/registry/settings-layout.json +1 -1
- package/registry/skeleton.json +1 -1
- package/registry/slider.json +1 -1
- package/registry/slot.json +1 -1
- package/registry/spinner.json +1 -1
- package/registry/split-view.json +1 -1
- package/registry/stage-banner.json +1 -1
- package/registry/stat.json +1 -1
- package/registry/status-page.json +263 -0
- package/registry/stepper.json +1 -1
- package/registry/switch.json +1 -1
- package/registry/tabs.json +1 -1
- package/registry/tag-input.json +1 -1
- package/registry/terminal-replay.json +1 -1
- package/registry/theme.json +1 -1
- package/registry/toast.json +1 -1
- package/registry/toc.json +1 -1
- package/registry/tooltip.json +1 -1
- package/registry/video-player.json +1 -1
- package/registry/video-trimmer.json +1 -1
- package/dist/chunk-NOVUREEC.js.map +0 -1
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
|
|
3
|
+
interface PricingPlan {
|
|
4
|
+
/** A stable key. */
|
|
5
|
+
id: string;
|
|
6
|
+
/** Its name. */
|
|
7
|
+
name: React.ReactNode;
|
|
8
|
+
/** Its price (`€29`, `Free`, `Custom`). */
|
|
9
|
+
price: React.ReactNode;
|
|
10
|
+
/** Under the price: the unit (`per month · 12,000 credits`). */
|
|
11
|
+
unit?: React.ReactNode;
|
|
12
|
+
/** What it includes, a few lines. */
|
|
13
|
+
features: readonly React.ReactNode[];
|
|
14
|
+
/** Its action (a cut Button or link; the featured one primary). */
|
|
15
|
+
action: React.ReactNode;
|
|
16
|
+
/** The plan most people choose: lifted and lit. */
|
|
17
|
+
featured?: boolean;
|
|
18
|
+
/** Its badge (`Most chosen`). */
|
|
19
|
+
badge?: React.ReactNode;
|
|
20
|
+
}
|
|
21
|
+
type PricingPageProps = Omit<React.HTMLAttributes<HTMLElement>, "title"> & {
|
|
22
|
+
/** The brand the page wears (`.brand-<id>`). */
|
|
23
|
+
brand?: string;
|
|
24
|
+
/** A mono line above the title. */
|
|
25
|
+
eyebrow?: React.ReactNode;
|
|
26
|
+
/** The page's `h1`. */
|
|
27
|
+
title: React.ReactNode;
|
|
28
|
+
/** One sentence under it. */
|
|
29
|
+
lead?: React.ReactNode;
|
|
30
|
+
/** Above the plans: a period switch (monthly · yearly), a currency. */
|
|
31
|
+
toolbar?: React.ReactNode;
|
|
32
|
+
/** The plans' accessible name (`Plans`). */
|
|
33
|
+
plansLabel: string;
|
|
34
|
+
/** The plans. */
|
|
35
|
+
plans: readonly PricingPlan[];
|
|
36
|
+
/** The comparison: its caption, columns (the plans' names) and rows (a feature and a cell per plan). */
|
|
37
|
+
compare?: {
|
|
38
|
+
caption: React.ReactNode;
|
|
39
|
+
columns: readonly React.ReactNode[];
|
|
40
|
+
rows: readonly {
|
|
41
|
+
feature: React.ReactNode;
|
|
42
|
+
cells: readonly React.ReactNode[];
|
|
43
|
+
}[];
|
|
44
|
+
};
|
|
45
|
+
/** What a credit buys, the credits left: a Meter, a sentence. */
|
|
46
|
+
credits?: {
|
|
47
|
+
title: React.ReactNode;
|
|
48
|
+
children: React.ReactNode;
|
|
49
|
+
};
|
|
50
|
+
/** The questions, folded. */
|
|
51
|
+
faq?: {
|
|
52
|
+
title: React.ReactNode;
|
|
53
|
+
items: readonly {
|
|
54
|
+
question: React.ReactNode;
|
|
55
|
+
answer: React.ReactNode;
|
|
56
|
+
}[];
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
/** A pricing page: plans (the featured one lifted), the comparison, credits, the questions. */
|
|
60
|
+
declare function PricingPage({ brand, eyebrow, title, lead, toolbar, plansLabel, plans, compare, credits, faq, className, ...props }: PricingPageProps): React.JSX.Element;
|
|
61
|
+
|
|
62
|
+
export { PricingPage, type PricingPageProps, type PricingPlan };
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import {
|
|
2
|
+
cn
|
|
3
|
+
} from "./chunk-KNBYZGSQ.js";
|
|
4
|
+
|
|
5
|
+
// src/pricing-page/pricing-page.tsx
|
|
6
|
+
import { Section } from "@krizaka/ui/page";
|
|
7
|
+
import { PageHero } from "@krizaka/ui/page-hero";
|
|
8
|
+
|
|
9
|
+
// src/glyphs.tsx
|
|
10
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
11
|
+
function Glyph({ className = "h-4 w-4", fill, children }) {
|
|
12
|
+
return /* @__PURE__ */ jsx(
|
|
13
|
+
"svg",
|
|
14
|
+
{
|
|
15
|
+
viewBox: "0 0 24 24",
|
|
16
|
+
className,
|
|
17
|
+
fill: fill ? "currentColor" : "none",
|
|
18
|
+
stroke: fill ? "none" : "currentColor",
|
|
19
|
+
strokeWidth: "2",
|
|
20
|
+
strokeLinecap: "round",
|
|
21
|
+
strokeLinejoin: "round",
|
|
22
|
+
"aria-hidden": true,
|
|
23
|
+
focusable: "false",
|
|
24
|
+
children
|
|
25
|
+
}
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
var CheckGlyph = (p) => /* @__PURE__ */ jsx(Glyph, { ...p, children: /* @__PURE__ */ jsx("path", { d: "M20 6 9 17l-5-5" }) });
|
|
29
|
+
|
|
30
|
+
// src/pricing-page/pricing-page.tsx
|
|
31
|
+
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
32
|
+
function PricingPage({ brand, eyebrow, title, lead, toolbar, plansLabel, plans, compare, credits, faq, className, ...props }) {
|
|
33
|
+
return /* @__PURE__ */ jsxs2("div", { className: cn(brand && "brand-" + brand, className), ...props, children: [
|
|
34
|
+
/* @__PURE__ */ jsx2(PageHero, { eyebrow, title, lead, align: "center", backdrop: "plain", children: toolbar }),
|
|
35
|
+
/* @__PURE__ */ jsx2(Section, { "aria-label": plansLabel, spacing: "sm", children: /* @__PURE__ */ jsx2("ul", { className: "kz-tpl-plans", children: plans.map((p) => /* @__PURE__ */ jsx2("li", { children: /* @__PURE__ */ jsxs2("div", { className: "kz-tpl-plan", "data-featured": p.featured ? "" : void 0, children: [
|
|
36
|
+
/* @__PURE__ */ jsxs2("div", { className: "kz-tpl-collection-head", children: [
|
|
37
|
+
/* @__PURE__ */ jsx2("h2", { children: p.name }),
|
|
38
|
+
p.badge && /* @__PURE__ */ jsx2("span", { className: "kz-fact", "data-tone": "ok", children: p.badge })
|
|
39
|
+
] }),
|
|
40
|
+
/* @__PURE__ */ jsxs2("p", { className: "kz-tpl-price", children: [
|
|
41
|
+
p.price,
|
|
42
|
+
p.unit && /* @__PURE__ */ jsx2("small", { children: p.unit })
|
|
43
|
+
] }),
|
|
44
|
+
/* @__PURE__ */ jsx2("ul", { children: p.features.map((f, i) => /* @__PURE__ */ jsxs2("li", { children: [
|
|
45
|
+
/* @__PURE__ */ jsx2(CheckGlyph, { className: "h-4 w-4" }),
|
|
46
|
+
/* @__PURE__ */ jsx2("span", { children: f })
|
|
47
|
+
] }, i)) }),
|
|
48
|
+
/* @__PURE__ */ jsx2("div", { children: p.action })
|
|
49
|
+
] }) }, p.id)) }) }),
|
|
50
|
+
compare && /* @__PURE__ */ jsx2(Section, { "aria-label": typeof compare.caption === "string" ? compare.caption : void 0, spacing: "sm", divider: true, children: /* @__PURE__ */ jsx2("div", { className: "kz-tpl-scroll", tabIndex: 0, children: /* @__PURE__ */ jsxs2("table", { className: "kz-tpl-compare", children: [
|
|
51
|
+
/* @__PURE__ */ jsx2("caption", { className: "kz-label kz-tpl-caption", children: compare.caption }),
|
|
52
|
+
/* @__PURE__ */ jsx2("thead", { children: /* @__PURE__ */ jsxs2("tr", { children: [
|
|
53
|
+
/* @__PURE__ */ jsx2("td", {}),
|
|
54
|
+
compare.columns.map((c, i) => /* @__PURE__ */ jsx2("th", { scope: "col", children: c }, i))
|
|
55
|
+
] }) }),
|
|
56
|
+
/* @__PURE__ */ jsx2("tbody", { children: compare.rows.map((r, i) => /* @__PURE__ */ jsxs2("tr", { children: [
|
|
57
|
+
/* @__PURE__ */ jsx2("th", { scope: "row", children: r.feature }),
|
|
58
|
+
r.cells.map((cell, j) => /* @__PURE__ */ jsx2("td", { children: cell }, j))
|
|
59
|
+
] }, i)) })
|
|
60
|
+
] }) }) }),
|
|
61
|
+
credits && /* @__PURE__ */ jsx2(Section, { id: "credits", title: credits.title, headingSize: "sm", spacing: "sm", divider: true, children: credits.children }),
|
|
62
|
+
faq && /* @__PURE__ */ jsx2(Section, { id: "faq", title: faq.title, headingSize: "sm", spacing: "sm", divider: true, children: /* @__PURE__ */ jsx2("div", { className: "kz-tpl-faq", children: faq.items.map((q, i) => /* @__PURE__ */ jsxs2("details", { children: [
|
|
63
|
+
/* @__PURE__ */ jsx2("summary", { children: q.question }),
|
|
64
|
+
/* @__PURE__ */ jsx2("div", { children: q.answer })
|
|
65
|
+
] }, i)) }) })
|
|
66
|
+
] });
|
|
67
|
+
}
|
|
68
|
+
export {
|
|
69
|
+
PricingPage
|
|
70
|
+
};
|
|
71
|
+
//# sourceMappingURL=pricing-page.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/pricing-page/pricing-page.tsx","../src/glyphs.tsx"],"sourcesContent":["// Server-safe. Plans and what they cost (blocks.css `.kz-tpl-plans`, `.kz-tpl-compare`, `.kz-tpl-faq`): the hero, the\n// plans side by side — the featured one lifted, lit by the brand — the comparison as a table that scrolls on a phone,\n// what a credit buys, and the questions people ask, folded.\nimport { Section } from \"@krizaka/ui/page\";\nimport { PageHero } from \"@krizaka/ui/page-hero\";\nimport type * as React from \"react\";\n\nimport { cn } from \"../cn\";\nimport { CheckGlyph } from \"../glyphs\";\n\nexport interface PricingPlan {\n /** A stable key. */\n id: string;\n /** Its name. */\n name: React.ReactNode;\n /** Its price (`€29`, `Free`, `Custom`). */\n price: React.ReactNode;\n /** Under the price: the unit (`per month · 12,000 credits`). */\n unit?: React.ReactNode;\n /** What it includes, a few lines. */\n features: readonly React.ReactNode[];\n /** Its action (a cut Button or link; the featured one primary). */\n action: React.ReactNode;\n /** The plan most people choose: lifted and lit. */\n featured?: boolean;\n /** Its badge (`Most chosen`). */\n badge?: React.ReactNode;\n}\n\nexport type PricingPageProps = Omit<React.HTMLAttributes<HTMLElement>, \"title\"> & {\n /** The brand the page wears (`.brand-<id>`). */\n brand?: string;\n /** A mono line above the title. */\n eyebrow?: React.ReactNode;\n /** The page's `h1`. */\n title: React.ReactNode;\n /** One sentence under it. */\n lead?: React.ReactNode;\n /** Above the plans: a period switch (monthly · yearly), a currency. */\n toolbar?: React.ReactNode;\n /** The plans' accessible name (`Plans`). */\n plansLabel: string;\n /** The plans. */\n plans: readonly PricingPlan[];\n /** The comparison: its caption, columns (the plans' names) and rows (a feature and a cell per plan). */\n compare?: { caption: React.ReactNode; columns: readonly React.ReactNode[]; rows: readonly { feature: React.ReactNode; cells: readonly React.ReactNode[] }[] };\n /** What a credit buys, the credits left: a Meter, a sentence. */\n credits?: { title: React.ReactNode; children: React.ReactNode };\n /** The questions, folded. */\n faq?: { title: React.ReactNode; items: readonly { question: React.ReactNode; answer: React.ReactNode }[] };\n};\n\n/** A pricing page: plans (the featured one lifted), the comparison, credits, the questions. */\nexport function PricingPage({ brand, eyebrow, title, lead, toolbar, plansLabel, plans, compare, credits, faq, className, ...props }: PricingPageProps) {\n return (\n <div className={cn(brand && \"brand-\" + brand, className)} {...props}>\n <PageHero eyebrow={eyebrow} title={title} lead={lead} align=\"center\" backdrop=\"plain\">\n {toolbar}\n </PageHero>\n <Section aria-label={plansLabel} spacing=\"sm\">\n <ul className=\"kz-tpl-plans\">\n {plans.map((p) => (\n <li key={p.id}>\n <div className=\"kz-tpl-plan\" data-featured={p.featured ? \"\" : undefined}>\n <div className=\"kz-tpl-collection-head\">\n <h2>{p.name}</h2>\n {p.badge && <span className=\"kz-fact\" data-tone=\"ok\">{p.badge}</span>}\n </div>\n <p className=\"kz-tpl-price\">\n {p.price}\n {p.unit && <small>{p.unit}</small>}\n </p>\n <ul>\n {p.features.map((f, i) => (\n <li key={i}>\n <CheckGlyph className=\"h-4 w-4\" />\n <span>{f}</span>\n </li>\n ))}\n </ul>\n <div>{p.action}</div>\n </div>\n </li>\n ))}\n </ul>\n </Section>\n {compare && (\n <Section aria-label={typeof compare.caption === \"string\" ? compare.caption : undefined} spacing=\"sm\" divider>\n <div className=\"kz-tpl-scroll\" tabIndex={0}>\n <table className=\"kz-tpl-compare\">\n <caption className=\"kz-label kz-tpl-caption\">{compare.caption}</caption>\n <thead>\n <tr>\n <td />\n {compare.columns.map((c, i) => (\n <th key={i} scope=\"col\">\n {c}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {compare.rows.map((r, i) => (\n <tr key={i}>\n <th scope=\"row\">{r.feature}</th>\n {r.cells.map((cell, j) => (\n <td key={j}>{cell}</td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n </Section>\n )}\n {credits && (\n <Section id=\"credits\" title={credits.title} headingSize=\"sm\" spacing=\"sm\" divider>\n {credits.children}\n </Section>\n )}\n {faq && (\n <Section id=\"faq\" title={faq.title} headingSize=\"sm\" spacing=\"sm\" divider>\n <div className=\"kz-tpl-faq\">\n {faq.items.map((q, i) => (\n <details key={i}>\n <summary>{q.question}</summary>\n <div>{q.answer}</div>\n </details>\n ))}\n </div>\n </Section>\n )}\n </div>\n );\n}\n","// The small line glyphs the data and media primitives draw (play, volume, search, chevrons…): decorative, 24-unit\n// box, `currentColor`, sized by the caller's class. Shared by the entries that need them; never exported on its own —\n// a product draws its own icons with @krizaka/icons.\nimport type * as React from \"react\";\n\ntype GlyphProps = { className?: string };\n\nfunction Glyph({ className = \"h-4 w-4\", fill, children }: GlyphProps & { fill?: boolean; children: React.ReactNode }) {\n return (\n <svg\n viewBox=\"0 0 24 24\"\n className={className}\n fill={fill ? \"currentColor\" : \"none\"}\n stroke={fill ? \"none\" : \"currentColor\"}\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden\n focusable=\"false\"\n >\n {children}\n </svg>\n );\n}\n\nexport const PlayGlyph = (p: GlyphProps) => (\n <Glyph {...p} fill>\n <path d=\"M8 5.5v13a1 1 0 0 0 1.5.86l10.4-6.5a1 1 0 0 0 0-1.72L9.5 4.64A1 1 0 0 0 8 5.5Z\" />\n </Glyph>\n);\nexport const PauseGlyph = (p: GlyphProps) => (\n <Glyph {...p} fill>\n <rect x=\"6\" y=\"5\" width=\"4\" height=\"14\" rx=\"1\" />\n <rect x=\"14\" y=\"5\" width=\"4\" height=\"14\" rx=\"1\" />\n </Glyph>\n);\nexport const VolumeGlyph = ({ muted, ...p }: GlyphProps & { muted?: boolean }) => (\n <Glyph {...p}>\n <path d=\"M11 5 6 9H3v6h3l5 4V5Z\" />\n {muted ? <path d=\"m22 9-6 6m0-6 6 6\" /> : <path d=\"M15.5 8.5a5 5 0 0 1 0 7M18.5 5.5a9 9 0 0 1 0 13\" />}\n </Glyph>\n);\nexport const FullscreenGlyph = ({ exit, ...p }: GlyphProps & { exit?: boolean }) => (\n <Glyph {...p}>\n {exit ? <path d=\"M9 4v5H4m11-5v5h5M9 20v-5H4m11 5v-5h5\" /> : <path d=\"M4 9V4h5m6 0h5v5M4 15v5h5m11-5v5h-5\" />}\n </Glyph>\n);\nexport const CaptionsGlyph = (p: GlyphProps) => (\n <Glyph {...p}>\n <rect x=\"3\" y=\"5\" width=\"18\" height=\"14\" rx=\"2\" />\n <path d=\"M10 10.5a2 2 0 1 0 0 3M17 10.5a2 2 0 1 0 0 3\" />\n </Glyph>\n);\nexport const PipGlyph = (p: GlyphProps) => (\n <Glyph {...p}>\n <rect x=\"3\" y=\"5\" width=\"18\" height=\"14\" rx=\"2\" />\n <rect x=\"12\" y=\"12\" width=\"6\" height=\"4\" rx=\"1\" />\n </Glyph>\n);\nexport const SearchGlyph = (p: GlyphProps) => (\n <Glyph {...p}>\n <circle cx=\"11\" cy=\"11\" r=\"7\" />\n <path d=\"m20 20-3.5-3.5\" />\n </Glyph>\n);\nexport const CloseGlyph = (p: GlyphProps) => (\n <Glyph {...p}>\n <path d=\"M18 6 6 18M6 6l12 12\" />\n </Glyph>\n);\nexport const ChevronGlyph = ({ direction = \"down\", ...p }: GlyphProps & { direction?: \"left\" | \"right\" | \"up\" | \"down\" }) => (\n <Glyph {...p}>\n <path d={{ left: \"m15 6-6 6 6 6\", right: \"m9 6 6 6-6 6\", up: \"m6 15 6-6 6 6\", down: \"m6 9 6 6 6-6\" }[direction]} />\n </Glyph>\n);\nexport const CheckGlyph = (p: GlyphProps) => (\n <Glyph {...p}>\n <path d=\"M20 6 9 17l-5-5\" />\n </Glyph>\n);\nexport const PlusGlyph = (p: GlyphProps) => (\n <Glyph {...p}>\n <path d=\"M12 5v14M5 12h14\" />\n </Glyph>\n);\nexport const CalendarGlyph = (p: GlyphProps) => (\n <Glyph {...p}>\n <rect x=\"3\" y=\"5\" width=\"18\" height=\"16\" rx=\"2\" />\n <path d=\"M3 10h18M8 3v4M16 3v4\" />\n </Glyph>\n);\nexport const UploadGlyph = (p: GlyphProps) => (\n <Glyph {...p}>\n <path d=\"M12 16V4m0 0L7 9m5-5 5 5\" />\n <path d=\"M4 16v2a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-2\" />\n </Glyph>\n);\nexport const FileGlyph = (p: GlyphProps) => (\n <Glyph {...p}>\n <path d=\"M14 3H7a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V8l-5-5Z\" />\n <path d=\"M14 3v5h5\" />\n </Glyph>\n);\nexport const CameraGlyph = (p: GlyphProps) => (\n <Glyph {...p}>\n <path d=\"M4 8h3l2-3h6l2 3h3a1 1 0 0 1 1 1v10a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V9a1 1 0 0 1 1-1Z\" />\n <circle cx=\"12\" cy=\"13.5\" r=\"3.5\" />\n </Glyph>\n);\nexport const FlipGlyph = (p: GlyphProps) => (\n <Glyph {...p}>\n <path d=\"M4 12a8 8 0 0 1 14-5.3M20 12a8 8 0 0 1-14 5.3\" />\n <path d=\"M18 3v4h-4M6 21v-4h4\" />\n </Glyph>\n);\nexport const RetryGlyph = (p: GlyphProps) => (\n <Glyph {...p}>\n <path d=\"M4 12a8 8 0 1 0 2.3-5.7L4 8.5\" />\n <path d=\"M4 4v4.5h4.5\" />\n </Glyph>\n);\nexport const SortGlyph = ({ direction, ...p }: GlyphProps & { direction?: \"ascending\" | \"descending\" }) => (\n <Glyph {...p}>\n {direction === \"ascending\" ? <path d=\"m7 14 5-5 5 5\" /> : direction === \"descending\" ? <path d=\"m7 10 5 5 5-5\" /> : <path d=\"m8 9 4-4 4 4M8 15l4 4 4-4\" />}\n </Glyph>\n);\nexport const ArrowGlyph = ({ direction = \"right\", ...p }: GlyphProps & { direction?: \"left\" | \"right\" }) => (\n <Glyph {...p}>\n <path d={direction === \"left\" ? \"M19 12H5m0 0 6-6m-6 6 6 6\" : \"M5 12h14m0 0-6-6m6 6-6 6\"} />\n </Glyph>\n);\nexport const ExternalGlyph = (p: GlyphProps) => (\n <Glyph {...p}>\n <path d=\"M14 4h6v6M20 4l-9 9\" />\n <path d=\"M18 14v4a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4\" />\n </Glyph>\n);\nexport const WarningGlyph = (p: GlyphProps) => (\n <Glyph {...p}>\n <path d=\"M12 4 2.5 20h19L12 4Z\" />\n <path d=\"M12 10v4M12 17.2v.1\" />\n </Glyph>\n);\nexport const CopyGlyph = (p: GlyphProps) => (\n <Glyph {...p}>\n <rect x=\"9\" y=\"9\" width=\"11\" height=\"11\" rx=\"2\" />\n <path d=\"M15 9V6a2 2 0 0 0-2-2H6a2 2 0 0 0-2 2v7a2 2 0 0 0 2 2h3\" />\n </Glyph>\n);\n"],"mappings":"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","names":["jsx","jsxs"]}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { Decision } from '@krizaka/ui/decision-list';
|
|
2
|
+
import { MascotBird } from '@krizaka/ui/mascots';
|
|
3
|
+
import { Fact } from '@krizaka/ui/page';
|
|
4
|
+
import { LinkComponent } from '@krizaka/ui/page-hero';
|
|
5
|
+
import * as React from 'react';
|
|
6
|
+
|
|
7
|
+
interface ProductReason {
|
|
8
|
+
/** A stable key (the card's anchor). */
|
|
9
|
+
id: string;
|
|
10
|
+
/** Its name. */
|
|
11
|
+
title: React.ReactNode;
|
|
12
|
+
/** The trap elsewhere, in one line. */
|
|
13
|
+
trap: React.ReactNode;
|
|
14
|
+
/** The signature icon. */
|
|
15
|
+
icon?: React.ReactNode;
|
|
16
|
+
/** The bird in the corner (whose rule it is). */
|
|
17
|
+
mark?: React.ReactNode;
|
|
18
|
+
/** Where the long version lives (a page) — or nothing, and the card stays its face. */
|
|
19
|
+
href?: string;
|
|
20
|
+
}
|
|
21
|
+
type ProductPageProps = Omit<React.HTMLAttributes<HTMLElement>, "title"> & {
|
|
22
|
+
/** The product's brand (`orazaka`, `orochia`…): the page wears `.brand-<id>`. */
|
|
23
|
+
brand?: string;
|
|
24
|
+
/** The product's mark and name, above the title. */
|
|
25
|
+
mark?: React.ReactNode;
|
|
26
|
+
/** The promise: the page's `h1`. */
|
|
27
|
+
title: React.ReactNode;
|
|
28
|
+
/** One or two sentences under it. */
|
|
29
|
+
lead?: React.ReactNode;
|
|
30
|
+
/** Facts under the lead (open source, a law it keeps). */
|
|
31
|
+
facts?: readonly Fact[];
|
|
32
|
+
/** The hero's actions. */
|
|
33
|
+
actions?: React.ReactNode;
|
|
34
|
+
/** The product alive, in a window beside the words. */
|
|
35
|
+
visual?: React.ReactNode;
|
|
36
|
+
/** The window's caption. */
|
|
37
|
+
visualLabel?: React.ReactNode;
|
|
38
|
+
/** The reasons' section heading. */
|
|
39
|
+
reasonsHeading: {
|
|
40
|
+
eyebrow?: React.ReactNode;
|
|
41
|
+
title: React.ReactNode;
|
|
42
|
+
lead?: React.ReactNode;
|
|
43
|
+
};
|
|
44
|
+
/** The words of the cards: the trap's label (read, not shown) and the way in. */
|
|
45
|
+
reasonLabels: {
|
|
46
|
+
trap: string;
|
|
47
|
+
more: React.ReactNode;
|
|
48
|
+
};
|
|
49
|
+
/** The traps it removes. */
|
|
50
|
+
reasons: readonly ProductReason[];
|
|
51
|
+
/** The decisions' section: heading, decisions and their four labels. */
|
|
52
|
+
decisions?: {
|
|
53
|
+
eyebrow?: React.ReactNode;
|
|
54
|
+
title: React.ReactNode;
|
|
55
|
+
items: readonly Decision[];
|
|
56
|
+
labels: {
|
|
57
|
+
chose: React.ReactNode;
|
|
58
|
+
refused: React.ReactNode;
|
|
59
|
+
because: React.ReactNode;
|
|
60
|
+
cost: React.ReactNode;
|
|
61
|
+
};
|
|
62
|
+
};
|
|
63
|
+
/** The promise a bird keeps, under the decisions. */
|
|
64
|
+
promise?: {
|
|
65
|
+
bird: MascotBird;
|
|
66
|
+
label: React.ReactNode;
|
|
67
|
+
text: React.ReactNode;
|
|
68
|
+
};
|
|
69
|
+
/** More sections between the decisions and the closing call (the tour, the platform, a comparison). */
|
|
70
|
+
children?: React.ReactNode;
|
|
71
|
+
/** The closing call. */
|
|
72
|
+
closing?: {
|
|
73
|
+
title: React.ReactNode;
|
|
74
|
+
body?: React.ReactNode;
|
|
75
|
+
actions: React.ReactNode;
|
|
76
|
+
};
|
|
77
|
+
/** The app's link component (Next's `Link`). */
|
|
78
|
+
linkAs?: LinkComponent;
|
|
79
|
+
};
|
|
80
|
+
/** A product's overview: split hero, traps as compact cards, decisions with their cost, the bird's promise, closing call. */
|
|
81
|
+
declare function ProductPage({ brand, mark, title, lead, facts, actions, visual, visualLabel, reasonsHeading, reasonLabels, reasons, decisions, promise, closing, linkAs, className, children, ...props }: ProductPageProps): React.JSX.Element;
|
|
82
|
+
|
|
83
|
+
export { ProductPage, type ProductPageProps, type ProductReason };
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import {
|
|
2
|
+
cn
|
|
3
|
+
} from "./chunk-KNBYZGSQ.js";
|
|
4
|
+
|
|
5
|
+
// src/product-page/product-page.tsx
|
|
6
|
+
import { ArgumentCard } from "@krizaka/ui/argument-card";
|
|
7
|
+
import { CardGrid } from "@krizaka/ui/card-grid";
|
|
8
|
+
import { CtaPanel } from "@krizaka/ui/cta-panel";
|
|
9
|
+
import { DecisionList } from "@krizaka/ui/decision-list";
|
|
10
|
+
import { MascotQuote } from "@krizaka/ui/mascot-quote";
|
|
11
|
+
import { Facts, Page, Section } from "@krizaka/ui/page";
|
|
12
|
+
import { SectionBackdrop } from "@krizaka/ui/section-backdrop";
|
|
13
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
14
|
+
function ProductPage({ brand, mark, title, lead, facts, actions, visual, visualLabel, reasonsHeading, reasonLabels, reasons, decisions, promise, closing, linkAs, className, children, ...props }) {
|
|
15
|
+
return /* @__PURE__ */ jsxs("div", { className: cn(brand && "brand-" + brand, className), ...props, children: [
|
|
16
|
+
/* @__PURE__ */ jsx(SectionBackdrop, { as: "header", grid: true, className: "kz-hero", children: /* @__PURE__ */ jsx(Page, { children: /* @__PURE__ */ jsxs("div", { className: visual ? "kz-tpl-split" : void 0, children: [
|
|
17
|
+
/* @__PURE__ */ jsxs("div", { className: "kz-hero-text", children: [
|
|
18
|
+
mark && /* @__PURE__ */ jsx("p", { className: "kz-eyebrow", children: mark }),
|
|
19
|
+
/* @__PURE__ */ jsx("h1", { className: "kz-hero-title", children: title }),
|
|
20
|
+
lead && /* @__PURE__ */ jsx("p", { className: "kz-hero-lead", children: lead }),
|
|
21
|
+
(facts || actions) && /* @__PURE__ */ jsxs("div", { className: "kz-hero-extra", children: [
|
|
22
|
+
facts && /* @__PURE__ */ jsx(Facts, { items: facts }),
|
|
23
|
+
actions && /* @__PURE__ */ jsx("div", { className: "kz-tpl-actions", children: actions })
|
|
24
|
+
] })
|
|
25
|
+
] }),
|
|
26
|
+
visual && /* @__PURE__ */ jsxs("figure", { className: "kz-tpl-stage", children: [
|
|
27
|
+
/* @__PURE__ */ jsxs("div", { className: "kz-tpl-stage-bar", "aria-hidden": true, children: [
|
|
28
|
+
/* @__PURE__ */ jsx("i", {}),
|
|
29
|
+
/* @__PURE__ */ jsx("i", {}),
|
|
30
|
+
/* @__PURE__ */ jsx("i", {}),
|
|
31
|
+
visualLabel && /* @__PURE__ */ jsx("span", { children: visualLabel })
|
|
32
|
+
] }),
|
|
33
|
+
visual
|
|
34
|
+
] })
|
|
35
|
+
] }) }) }),
|
|
36
|
+
/* @__PURE__ */ jsx(Section, { id: "why", eyebrow: reasonsHeading.eyebrow, title: reasonsHeading.title, lead: reasonsHeading.lead, reveal: true, children: /* @__PURE__ */ jsx(CardGrid, { min: 260, fit: "fit", children: reasons.map((r) => /* @__PURE__ */ jsx(
|
|
37
|
+
ArgumentCard,
|
|
38
|
+
{
|
|
39
|
+
id: `why-${r.id}`,
|
|
40
|
+
icon: r.icon,
|
|
41
|
+
title: r.title,
|
|
42
|
+
mark: r.mark,
|
|
43
|
+
hook: { label: reasonLabels.trap, text: r.trap },
|
|
44
|
+
more: r.href ? { href: r.href, label: reasonLabels.more } : void 0,
|
|
45
|
+
linkAs
|
|
46
|
+
},
|
|
47
|
+
r.id
|
|
48
|
+
)) }) }),
|
|
49
|
+
decisions && /* @__PURE__ */ jsxs(Section, { id: "decisions", eyebrow: decisions.eyebrow, title: decisions.title, divider: true, reveal: true, children: [
|
|
50
|
+
/* @__PURE__ */ jsx(DecisionList, { decisions: decisions.items, labels: decisions.labels }),
|
|
51
|
+
promise && /* @__PURE__ */ jsx("div", { className: "kz-tpl-promise", children: /* @__PURE__ */ jsx(MascotQuote, { variant: "callout", bird: promise.bird, mood: "welcome", label: promise.label, children: promise.text }) })
|
|
52
|
+
] }),
|
|
53
|
+
children,
|
|
54
|
+
closing && /* @__PURE__ */ jsx(Section, { spacing: "sm", "aria-labelledby": "product-closing", children: /* @__PURE__ */ jsx(CtaPanel, { id: "product-closing", title: closing.title, body: closing.body, reveal: true, children: closing.actions }) })
|
|
55
|
+
] });
|
|
56
|
+
}
|
|
57
|
+
export {
|
|
58
|
+
ProductPage
|
|
59
|
+
};
|
|
60
|
+
//# sourceMappingURL=product-page.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/product-page/product-page.tsx"],"sourcesContent":["// Server-safe. A product's overview: the hero with the product's mark, its promise, facts and main action beside a live\n// window of the product; the traps it removes as compact argument cards; its decisions with their cost; the promise a\n// bird keeps; the closing call. Under the product's brand (`brand` → `.brand-<id>`).\nimport { ArgumentCard } from \"@krizaka/ui/argument-card\";\nimport { CardGrid } from \"@krizaka/ui/card-grid\";\nimport { CtaPanel } from \"@krizaka/ui/cta-panel\";\nimport { type Decision, DecisionList } from \"@krizaka/ui/decision-list\";\nimport { MascotQuote } from \"@krizaka/ui/mascot-quote\";\nimport type { MascotBird } from \"@krizaka/ui/mascots\";\nimport { type Fact, Facts, Page, Section } from \"@krizaka/ui/page\";\nimport type { LinkComponent } from \"@krizaka/ui/page-hero\";\nimport { SectionBackdrop } from \"@krizaka/ui/section-backdrop\";\nimport type * as React from \"react\";\n\nimport { cn } from \"../cn\";\n\nexport interface ProductReason {\n /** A stable key (the card's anchor). */\n id: string;\n /** Its name. */\n title: React.ReactNode;\n /** The trap elsewhere, in one line. */\n trap: React.ReactNode;\n /** The signature icon. */\n icon?: React.ReactNode;\n /** The bird in the corner (whose rule it is). */\n mark?: React.ReactNode;\n /** Where the long version lives (a page) — or nothing, and the card stays its face. */\n href?: string;\n}\n\nexport type ProductPageProps = Omit<React.HTMLAttributes<HTMLElement>, \"title\"> & {\n /** The product's brand (`orazaka`, `orochia`…): the page wears `.brand-<id>`. */\n brand?: string;\n /** The product's mark and name, above the title. */\n mark?: React.ReactNode;\n /** The promise: the page's `h1`. */\n title: React.ReactNode;\n /** One or two sentences under it. */\n lead?: React.ReactNode;\n /** Facts under the lead (open source, a law it keeps). */\n facts?: readonly Fact[];\n /** The hero's actions. */\n actions?: React.ReactNode;\n /** The product alive, in a window beside the words. */\n visual?: React.ReactNode;\n /** The window's caption. */\n visualLabel?: React.ReactNode;\n /** The reasons' section heading. */\n reasonsHeading: { eyebrow?: React.ReactNode; title: React.ReactNode; lead?: React.ReactNode };\n /** The words of the cards: the trap's label (read, not shown) and the way in. */\n reasonLabels: { trap: string; more: React.ReactNode };\n /** The traps it removes. */\n reasons: readonly ProductReason[];\n /** The decisions' section: heading, decisions and their four labels. */\n decisions?: { eyebrow?: React.ReactNode; title: React.ReactNode; items: readonly Decision[]; labels: { chose: React.ReactNode; refused: React.ReactNode; because: React.ReactNode; cost: React.ReactNode } };\n /** The promise a bird keeps, under the decisions. */\n promise?: { bird: MascotBird; label: React.ReactNode; text: React.ReactNode };\n /** More sections between the decisions and the closing call (the tour, the platform, a comparison). */\n children?: React.ReactNode;\n /** The closing call. */\n closing?: { title: React.ReactNode; body?: React.ReactNode; actions: React.ReactNode };\n /** The app's link component (Next's `Link`). */\n linkAs?: LinkComponent;\n};\n\n/** A product's overview: split hero, traps as compact cards, decisions with their cost, the bird's promise, closing call. */\nexport function ProductPage({ brand, mark, title, lead, facts, actions, visual, visualLabel, reasonsHeading, reasonLabels, reasons, decisions, promise, closing, linkAs, className, children, ...props }: ProductPageProps) {\n return (\n <div className={cn(brand && \"brand-\" + brand, className)} {...props}>\n <SectionBackdrop as=\"header\" grid className=\"kz-hero\">\n <Page>\n <div className={visual ? \"kz-tpl-split\" : undefined}>\n <div className=\"kz-hero-text\">\n {mark && <p className=\"kz-eyebrow\">{mark}</p>}\n <h1 className=\"kz-hero-title\">{title}</h1>\n {lead && <p className=\"kz-hero-lead\">{lead}</p>}\n {(facts || actions) && (\n <div className=\"kz-hero-extra\">\n {facts && <Facts items={facts} />}\n {actions && <div className=\"kz-tpl-actions\">{actions}</div>}\n </div>\n )}\n </div>\n {visual && (\n <figure className=\"kz-tpl-stage\">\n <div className=\"kz-tpl-stage-bar\" aria-hidden>\n <i />\n <i />\n <i />\n {visualLabel && <span>{visualLabel}</span>}\n </div>\n {visual}\n </figure>\n )}\n </div>\n </Page>\n </SectionBackdrop>\n <Section id=\"why\" eyebrow={reasonsHeading.eyebrow} title={reasonsHeading.title} lead={reasonsHeading.lead} reveal>\n <CardGrid min={260} fit=\"fit\">\n {reasons.map((r) => (\n <ArgumentCard\n key={r.id}\n id={`why-${r.id}`}\n icon={r.icon}\n title={r.title}\n mark={r.mark}\n hook={{ label: reasonLabels.trap, text: r.trap }}\n more={r.href ? { href: r.href, label: reasonLabels.more } : undefined}\n linkAs={linkAs}\n />\n ))}\n </CardGrid>\n </Section>\n {decisions && (\n <Section id=\"decisions\" eyebrow={decisions.eyebrow} title={decisions.title} divider reveal>\n <DecisionList decisions={decisions.items} labels={decisions.labels} />\n {promise && (\n <div className=\"kz-tpl-promise\">\n <MascotQuote variant=\"callout\" bird={promise.bird} mood=\"welcome\" label={promise.label}>\n {promise.text}\n </MascotQuote>\n </div>\n )}\n </Section>\n )}\n {children}\n {closing && (\n <Section spacing=\"sm\" aria-labelledby=\"product-closing\">\n <CtaPanel id=\"product-closing\" title={closing.title} body={closing.body} reveal>\n {closing.actions}\n </CtaPanel>\n </Section>\n )}\n </div>\n );\n}\n"],"mappings":";;;;;AAGA,SAAS,oBAAoB;AAC7B,SAAS,gBAAgB;AACzB,SAAS,gBAAgB;AACzB,SAAwB,oBAAoB;AAC5C,SAAS,mBAAmB;AAE5B,SAAoB,OAAO,MAAM,eAAe;AAEhD,SAAS,uBAAuB;AA+DT,cAIP,YAJO;AAPhB,SAAS,YAAY,EAAE,OAAO,MAAM,OAAO,MAAM,OAAO,SAAS,QAAQ,aAAa,gBAAgB,cAAc,SAAS,WAAW,SAAS,SAAS,QAAQ,WAAW,UAAU,GAAG,MAAM,GAAqB;AAC1N,SACE,qBAAC,SAAI,WAAW,GAAG,SAAS,WAAW,OAAO,SAAS,GAAI,GAAG,OAC5D;AAAA,wBAAC,mBAAgB,IAAG,UAAS,MAAI,MAAC,WAAU,WAC1C,8BAAC,QACC,+BAAC,SAAI,WAAW,SAAS,iBAAiB,QACxC;AAAA,2BAAC,SAAI,WAAU,gBACZ;AAAA,gBAAQ,oBAAC,OAAE,WAAU,cAAc,gBAAK;AAAA,QACzC,oBAAC,QAAG,WAAU,iBAAiB,iBAAM;AAAA,QACpC,QAAQ,oBAAC,OAAE,WAAU,gBAAgB,gBAAK;AAAA,SACzC,SAAS,YACT,qBAAC,SAAI,WAAU,iBACZ;AAAA,mBAAS,oBAAC,SAAM,OAAO,OAAO;AAAA,UAC9B,WAAW,oBAAC,SAAI,WAAU,kBAAkB,mBAAQ;AAAA,WACvD;AAAA,SAEJ;AAAA,MACC,UACC,qBAAC,YAAO,WAAU,gBAChB;AAAA,6BAAC,SAAI,WAAU,oBAAmB,eAAW,MAC3C;AAAA,8BAAC,OAAE;AAAA,UACH,oBAAC,OAAE;AAAA,UACH,oBAAC,OAAE;AAAA,UACF,eAAe,oBAAC,UAAM,uBAAY;AAAA,WACrC;AAAA,QACC;AAAA,SACH;AAAA,OAEJ,GACF,GACF;AAAA,IACA,oBAAC,WAAQ,IAAG,OAAM,SAAS,eAAe,SAAS,OAAO,eAAe,OAAO,MAAM,eAAe,MAAM,QAAM,MAC/G,8BAAC,YAAS,KAAK,KAAK,KAAI,OACrB,kBAAQ,IAAI,CAAC,MACZ;AAAA,MAAC;AAAA;AAAA,QAEC,IAAI,OAAO,EAAE,EAAE;AAAA,QACf,MAAM,EAAE;AAAA,QACR,OAAO,EAAE;AAAA,QACT,MAAM,EAAE;AAAA,QACR,MAAM,EAAE,OAAO,aAAa,MAAM,MAAM,EAAE,KAAK;AAAA,QAC/C,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,OAAO,aAAa,KAAK,IAAI;AAAA,QAC5D;AAAA;AAAA,MAPK,EAAE;AAAA,IAQT,CACD,GACH,GACF;AAAA,IACC,aACC,qBAAC,WAAQ,IAAG,aAAY,SAAS,UAAU,SAAS,OAAO,UAAU,OAAO,SAAO,MAAC,QAAM,MACxF;AAAA,0BAAC,gBAAa,WAAW,UAAU,OAAO,QAAQ,UAAU,QAAQ;AAAA,MACnE,WACC,oBAAC,SAAI,WAAU,kBACb,8BAAC,eAAY,SAAQ,WAAU,MAAM,QAAQ,MAAM,MAAK,WAAU,OAAO,QAAQ,OAC9E,kBAAQ,MACX,GACF;AAAA,OAEJ;AAAA,IAED;AAAA,IACA,WACC,oBAAC,WAAQ,SAAQ,MAAK,mBAAgB,mBACpC,8BAAC,YAAS,IAAG,mBAAkB,OAAO,QAAQ,OAAO,MAAM,QAAQ,MAAM,QAAM,MAC5E,kBAAQ,SACX,GACF;AAAA,KAEJ;AAEJ;","names":[]}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { LinkComponent } from '@krizaka/ui/page-hero';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
|
|
4
|
+
type ServiceState = "operational" | "degraded" | "outage" | "building";
|
|
5
|
+
type StatusPageProps = Omit<React.HTMLAttributes<HTMLElement>, "title"> & {
|
|
6
|
+
/** The way back. */
|
|
7
|
+
back?: {
|
|
8
|
+
href: string;
|
|
9
|
+
label: string;
|
|
10
|
+
};
|
|
11
|
+
/** A mono line above the title. */
|
|
12
|
+
eyebrow?: React.ReactNode;
|
|
13
|
+
/** The page's `h1` (`Status`, `Yazakia is on its way`). */
|
|
14
|
+
title: React.ReactNode;
|
|
15
|
+
/** One sentence under it. */
|
|
16
|
+
lead?: React.ReactNode;
|
|
17
|
+
/** Beside the hero: a bird (the pigeon that delivers, the duck that builds). */
|
|
18
|
+
aside?: React.ReactNode;
|
|
19
|
+
/** The overall state. */
|
|
20
|
+
state: ServiceState;
|
|
21
|
+
/** The overall state, in words (`All systems operational`). */
|
|
22
|
+
stateLabel: React.ReactNode;
|
|
23
|
+
/** When it was checked (`Checked 2 min ago`). */
|
|
24
|
+
checked?: React.ReactNode;
|
|
25
|
+
/** The services and their states, in words: `{ id, name, state, label }`. */
|
|
26
|
+
services?: readonly {
|
|
27
|
+
id: string;
|
|
28
|
+
name: React.ReactNode;
|
|
29
|
+
state: ServiceState;
|
|
30
|
+
label: React.ReactNode;
|
|
31
|
+
}[];
|
|
32
|
+
/** The services list's accessible name (`Services`). */
|
|
33
|
+
servicesLabel?: string;
|
|
34
|
+
/** Under the services: the incidents (a ChangelogPage's entries, a list), or for `building` the progress and the way to follow. */
|
|
35
|
+
children?: React.ReactNode;
|
|
36
|
+
/** The app's link component (Next's `Link`). */
|
|
37
|
+
linkAs?: LinkComponent;
|
|
38
|
+
};
|
|
39
|
+
/** A status page — or an « under construction » one: the overall state, each service, then incidents or progress. */
|
|
40
|
+
declare function StatusPage({ back, eyebrow, title, lead, aside, state, stateLabel, checked, services, servicesLabel, linkAs, children, ...props }: StatusPageProps): React.JSX.Element;
|
|
41
|
+
|
|
42
|
+
export { type ServiceState, StatusPage, type StatusPageProps };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// src/status-page/status-page.tsx
|
|
2
|
+
import { Page, Section } from "@krizaka/ui/page";
|
|
3
|
+
import { PageHero } from "@krizaka/ui/page-hero";
|
|
4
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
function StatusPage({ back, eyebrow, title, lead, aside, state, stateLabel, checked, services, servicesLabel = "Services", linkAs, children, ...props }) {
|
|
6
|
+
return /* @__PURE__ */ jsxs("div", { ...props, children: [
|
|
7
|
+
/* @__PURE__ */ jsx(PageHero, { back, linkAs, eyebrow, title, lead, aside, backdrop: "plain" }),
|
|
8
|
+
/* @__PURE__ */ jsxs(Page, { className: "kz-tpl-longform", children: [
|
|
9
|
+
/* @__PURE__ */ jsxs("div", { className: "kz-tpl-state", "data-state": state, role: "status", children: [
|
|
10
|
+
/* @__PURE__ */ jsx("span", { className: "kz-tpl-dot", "aria-hidden": true }),
|
|
11
|
+
/* @__PURE__ */ jsx("strong", { children: stateLabel }),
|
|
12
|
+
checked && /* @__PURE__ */ jsx("span", { className: "kz-tpl-count", children: checked })
|
|
13
|
+
] }),
|
|
14
|
+
services && services.length > 0 && /* @__PURE__ */ jsx("ul", { className: "kz-tpl-services", "aria-label": servicesLabel, children: services.map((s) => /* @__PURE__ */ jsxs("li", { children: [
|
|
15
|
+
/* @__PURE__ */ jsx("span", { children: s.name }),
|
|
16
|
+
/* @__PURE__ */ jsxs("small", { children: [
|
|
17
|
+
/* @__PURE__ */ jsx("span", { className: "kz-tpl-dot", "data-state": s.state, "aria-hidden": true }),
|
|
18
|
+
s.label
|
|
19
|
+
] })
|
|
20
|
+
] }, s.id)) })
|
|
21
|
+
] }),
|
|
22
|
+
children && /* @__PURE__ */ jsx(Section, { spacing: "sm", children })
|
|
23
|
+
] });
|
|
24
|
+
}
|
|
25
|
+
export {
|
|
26
|
+
StatusPage
|
|
27
|
+
};
|
|
28
|
+
//# sourceMappingURL=status-page.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/status-page/status-page.tsx"],"sourcesContent":["// Server-safe. Where things stand (blocks.css `.kz-tpl-state`, `.kz-tpl-services`): the overall state in words and\n// colour, each service on its line, the incidents under them — or, for something not built yet (`state=\"building\"`),\n// what is coming, its progress and how to hear about it, the bird beside it. A state is always said in words.\nimport { Page, Section } from \"@krizaka/ui/page\";\nimport type { LinkComponent } from \"@krizaka/ui/page-hero\";\nimport { PageHero } from \"@krizaka/ui/page-hero\";\nimport type * as React from \"react\";\n\nexport type ServiceState = \"operational\" | \"degraded\" | \"outage\" | \"building\";\n\nexport type StatusPageProps = Omit<React.HTMLAttributes<HTMLElement>, \"title\"> & {\n /** The way back. */\n back?: { href: string; label: string };\n /** A mono line above the title. */\n eyebrow?: React.ReactNode;\n /** The page's `h1` (`Status`, `Yazakia is on its way`). */\n title: React.ReactNode;\n /** One sentence under it. */\n lead?: React.ReactNode;\n /** Beside the hero: a bird (the pigeon that delivers, the duck that builds). */\n aside?: React.ReactNode;\n /** The overall state. */\n state: ServiceState;\n /** The overall state, in words (`All systems operational`). */\n stateLabel: React.ReactNode;\n /** When it was checked (`Checked 2 min ago`). */\n checked?: React.ReactNode;\n /** The services and their states, in words: `{ id, name, state, label }`. */\n services?: readonly { id: string; name: React.ReactNode; state: ServiceState; label: React.ReactNode }[];\n /** The services list's accessible name (`Services`). */\n servicesLabel?: string;\n /** Under the services: the incidents (a ChangelogPage's entries, a list), or for `building` the progress and the way to follow. */\n children?: React.ReactNode;\n /** The app's link component (Next's `Link`). */\n linkAs?: LinkComponent;\n};\n\n/** A status page — or an « under construction » one: the overall state, each service, then incidents or progress. */\nexport function StatusPage({ back, eyebrow, title, lead, aside, state, stateLabel, checked, services, servicesLabel = \"Services\", linkAs, children, ...props }: StatusPageProps) {\n return (\n <div {...props}>\n <PageHero back={back} linkAs={linkAs} eyebrow={eyebrow} title={title} lead={lead} aside={aside} backdrop=\"plain\" />\n <Page className=\"kz-tpl-longform\">\n <div className=\"kz-tpl-state\" data-state={state} role=\"status\">\n <span className=\"kz-tpl-dot\" aria-hidden />\n <strong>{stateLabel}</strong>\n {checked && <span className=\"kz-tpl-count\">{checked}</span>}\n </div>\n {services && services.length > 0 && (\n <ul className=\"kz-tpl-services\" aria-label={servicesLabel}>\n {services.map((s) => (\n <li key={s.id}>\n <span>{s.name}</span>\n <small>\n <span className=\"kz-tpl-dot\" data-state={s.state} aria-hidden />\n {s.label}\n </small>\n </li>\n ))}\n </ul>\n )}\n </Page>\n {children && <Section spacing=\"sm\">{children}</Section>}\n </div>\n );\n}\n"],"mappings":";AAGA,SAAS,MAAM,eAAe;AAE9B,SAAS,gBAAgB;AAoCnB,cAEE,YAFF;AAHC,SAAS,WAAW,EAAE,MAAM,SAAS,OAAO,MAAM,OAAO,OAAO,YAAY,SAAS,UAAU,gBAAgB,YAAY,QAAQ,UAAU,GAAG,MAAM,GAAoB;AAC/K,SACE,qBAAC,SAAK,GAAG,OACP;AAAA,wBAAC,YAAS,MAAY,QAAgB,SAAkB,OAAc,MAAY,OAAc,UAAS,SAAQ;AAAA,IACjH,qBAAC,QAAK,WAAU,mBACd;AAAA,2BAAC,SAAI,WAAU,gBAAe,cAAY,OAAO,MAAK,UACpD;AAAA,4BAAC,UAAK,WAAU,cAAa,eAAW,MAAC;AAAA,QACzC,oBAAC,YAAQ,sBAAW;AAAA,QACnB,WAAW,oBAAC,UAAK,WAAU,gBAAgB,mBAAQ;AAAA,SACtD;AAAA,MACC,YAAY,SAAS,SAAS,KAC7B,oBAAC,QAAG,WAAU,mBAAkB,cAAY,eACzC,mBAAS,IAAI,CAAC,MACb,qBAAC,QACC;AAAA,4BAAC,UAAM,YAAE,MAAK;AAAA,QACd,qBAAC,WACC;AAAA,8BAAC,UAAK,WAAU,cAAa,cAAY,EAAE,OAAO,eAAW,MAAC;AAAA,UAC7D,EAAE;AAAA,WACL;AAAA,WALO,EAAE,EAMX,CACD,GACH;AAAA,OAEJ;AAAA,IACC,YAAY,oBAAC,WAAQ,SAAQ,MAAM,UAAS;AAAA,KAC/C;AAEJ;","names":[]}
|