@krizaka/ui 3.28.0 → 3.30.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 (183) hide show
  1. package/README.md +2 -0
  2. package/dist/blocks.css +2 -0
  3. package/dist/{chunk-OUWPBSSL.js → chunk-GYKQ52HX.js} +7 -8
  4. package/dist/chunk-GYKQ52HX.js.map +1 -0
  5. package/dist/docs-hub-page.d.ts +7 -1
  6. package/dist/docs-hub-page.js +2 -2
  7. package/dist/docs-hub-page.js.map +1 -1
  8. package/dist/engine-flow.d.ts +97 -0
  9. package/dist/engine-flow.js +214 -0
  10. package/dist/engine-flow.js.map +1 -0
  11. package/dist/motion.css +121 -1
  12. package/dist/native.d.ts +21 -5
  13. package/dist/native.js +65 -32
  14. package/dist/native.js.map +1 -1
  15. package/dist/nav-bar.d.ts +12 -3
  16. package/dist/nav-bar.js +18 -11
  17. package/dist/nav-bar.js.map +1 -1
  18. package/dist/site-footer.d.ts +1 -1
  19. package/dist/site-footer.js +1 -1
  20. package/dist/{sites-CHp_vELn.d.ts → sites-B4prB793.d.ts} +2 -2
  21. package/dist/sites.d.ts +2 -2
  22. package/dist/sites.js +6 -7
  23. package/dist/sites.js.map +1 -1
  24. package/package.json +20 -6
  25. package/registry/account-menu.json +1 -1
  26. package/registry/achievement.json +1 -1
  27. package/registry/action-bar.json +1 -1
  28. package/registry/activity-feed.json +1 -1
  29. package/registry/alert.json +1 -1
  30. package/registry/app-header.json +1 -1
  31. package/registry/app-shell.json +1 -1
  32. package/registry/argument-card.json +1 -1
  33. package/registry/audio-player.json +1 -1
  34. package/registry/auth-layout.json +1 -1
  35. package/registry/avatar.json +1 -1
  36. package/registry/badge.json +1 -1
  37. package/registry/button.json +1 -1
  38. package/registry/captcha.json +1 -1
  39. package/registry/card-grid.json +1 -1
  40. package/registry/card.json +1 -1
  41. package/registry/catalogue-page.json +1 -1
  42. package/registry/changelog-page.json +1 -1
  43. package/registry/chat.json +55 -8
  44. package/registry/checkbox.json +1 -1
  45. package/registry/chip-link.json +1 -1
  46. package/registry/chip-row.json +1 -1
  47. package/registry/chip.json +1 -1
  48. package/registry/choice-grid.json +1 -1
  49. package/registry/code-block.json +1 -1
  50. package/registry/combobox.json +1 -1
  51. package/registry/command.json +1 -1
  52. package/registry/comparison-table.json +1 -1
  53. package/registry/component-page.json +1 -1
  54. package/registry/confirm-button.json +1 -1
  55. package/registry/contact-page.json +1 -1
  56. package/registry/continue-prompt.json +1 -1
  57. package/registry/countdown.json +1 -1
  58. package/registry/cover-hero.json +1 -1
  59. package/registry/cta-panel.json +1 -1
  60. package/registry/dashboard-layout.json +1 -1
  61. package/registry/data-table.json +1 -1
  62. package/registry/date-picker.json +1 -1
  63. package/registry/decision-list.json +1 -1
  64. package/registry/description-list.json +1 -1
  65. package/registry/detail-layout.json +1 -1
  66. package/registry/dialog.json +1 -1
  67. package/registry/docs-article-page.json +1 -1
  68. package/registry/docs-hub-page.json +16 -2
  69. package/registry/docs-layout.json +1 -1
  70. package/registry/docs-nav.json +1 -1
  71. package/registry/document-viewer.json +1 -1
  72. package/registry/dropdown-menu.json +1 -1
  73. package/registry/empty-state.json +1 -1
  74. package/registry/engine-flow.json +280 -0
  75. package/registry/error-page.json +1 -1
  76. package/registry/examples/chat/native/assistant.d.ts +4 -0
  77. package/registry/examples/chat/native/assistant.dark.png +0 -0
  78. package/registry/examples/chat/native/assistant.js +32 -0
  79. package/registry/examples/chat/native/assistant.light.png +0 -0
  80. package/registry/examples/chat/native/assistant.tsx +28 -0
  81. package/registry/examples/engine-flow/compact.d.ts +4 -0
  82. package/registry/examples/engine-flow/compact.js +33 -0
  83. package/registry/examples/engine-flow/compact.tsx +30 -0
  84. package/registry/examples/engine-flow/radial.d.ts +4 -0
  85. package/registry/examples/engine-flow/radial.js +37 -0
  86. package/registry/examples/engine-flow/radial.tsx +32 -0
  87. package/registry/field.json +1 -1
  88. package/registry/file-upload.json +1 -1
  89. package/registry/filter-bar.json +1 -1
  90. package/registry/force-update-screen.json +1 -1
  91. package/registry/form.json +1 -1
  92. package/registry/gallery-page.json +1 -1
  93. package/registry/genui.json +1 -1
  94. package/registry/glow-card.json +1 -1
  95. package/registry/goal-gauge.json +1 -1
  96. package/registry/how-it-works-page.json +1 -1
  97. package/registry/image-cropper.json +1 -1
  98. package/registry/index.json +37 -6
  99. package/registry/iso.json +3 -3
  100. package/registry/kanban.json +1 -1
  101. package/registry/kbd.json +1 -1
  102. package/registry/landing-page.json +1 -1
  103. package/registry/landscape.json +1 -1
  104. package/registry/language-switch.json +1 -1
  105. package/registry/legal-page.json +1 -1
  106. package/registry/link-card.json +1 -1
  107. package/registry/list.json +1 -1
  108. package/registry/loader.json +1 -1
  109. package/registry/longform-page.json +1 -1
  110. package/registry/maintenance-screen.json +1 -1
  111. package/registry/map.json +2 -2
  112. package/registry/markdown.json +1 -1
  113. package/registry/marketing-layout.json +1 -1
  114. package/registry/marquee.json +1 -1
  115. package/registry/mascot-quote.json +1 -1
  116. package/registry/mascot-state.json +1 -1
  117. package/registry/mascots.json +1 -1
  118. package/registry/match-dialog.json +1 -1
  119. package/registry/media-capture.json +1 -1
  120. package/registry/media-gallery.json +1 -1
  121. package/registry/media-grid.json +1 -1
  122. package/registry/meta-row.json +1 -1
  123. package/registry/meter.json +1 -1
  124. package/registry/nav-bar.json +31 -3
  125. package/registry/number-ticker.json +1 -1
  126. package/registry/opening-hours.json +1 -1
  127. package/registry/page-header.json +1 -1
  128. package/registry/page-hero.json +1 -1
  129. package/registry/page.json +1 -1
  130. package/registry/pagination.json +1 -1
  131. package/registry/photo-grid.json +1 -1
  132. package/registry/pointer-light.json +1 -1
  133. package/registry/popover.json +1 -1
  134. package/registry/pricing-page.json +1 -1
  135. package/registry/product-page.json +1 -1
  136. package/registry/profile-card.json +1 -1
  137. package/registry/progress.json +1 -1
  138. package/registry/promise-card.json +1 -1
  139. package/registry/radio-group.json +1 -1
  140. package/registry/rail-nav.json +2 -2
  141. package/registry/recipes.json +1 -1
  142. package/registry/scroll-stage.json +1 -1
  143. package/registry/search-field.json +1 -1
  144. package/registry/section-backdrop.json +1 -1
  145. package/registry/separator.json +1 -1
  146. package/registry/service-card.json +1 -1
  147. package/registry/settings-layout.json +1 -1
  148. package/registry/showcase.json +1 -1
  149. package/registry/site-footer.json +2 -2
  150. package/registry/sites.json +2 -2
  151. package/registry/skeleton.json +1 -1
  152. package/registry/skip-link.json +1 -1
  153. package/registry/slider.json +1 -1
  154. package/registry/slot-picker.json +1 -1
  155. package/registry/slot.json +1 -1
  156. package/registry/spinner.json +1 -1
  157. package/registry/split-view.json +1 -1
  158. package/registry/stage-banner.json +1 -1
  159. package/registry/stat.json +1 -1
  160. package/registry/status-page.json +1 -1
  161. package/registry/step-progress.json +1 -1
  162. package/registry/step-showcase.json +1 -1
  163. package/registry/stepper.json +1 -1
  164. package/registry/sticky-action.json +1 -1
  165. package/registry/swipe-deck.json +1 -1
  166. package/registry/switch.json +1 -1
  167. package/registry/tabs.json +1 -1
  168. package/registry/tag-input.json +1 -1
  169. package/registry/tag-selector.json +1 -1
  170. package/registry/terminal-replay.json +1 -1
  171. package/registry/theme.json +1 -1
  172. package/registry/toast.json +1 -1
  173. package/registry/toc.json +1 -1
  174. package/registry/tooltip.json +1 -1
  175. package/registry/tree-view.json +1 -1
  176. package/registry/update-prompt.json +1 -1
  177. package/registry/verified-badge.json +1 -1
  178. package/registry/vertical-video.json +1 -1
  179. package/registry/video-player.json +1 -1
  180. package/registry/video-trimmer.json +1 -1
  181. package/registry/virtual.json +1 -1
  182. package/registry/waveform.json +1 -1
  183. package/dist/chunk-OUWPBSSL.js.map +0 -1
package/README.md CHANGED
@@ -176,6 +176,7 @@ light or a product's — is a set of tokens.
176
176
  | `@krizaka/ui/achievement` | `Achievement` (`title`, `eyebrow`, `badge`, `replaced`, `locked`), `AchievementList`, `Emblem` (`sword` · `mirror` · `jewel`) | server |
177
177
  | `@krizaka/ui/landscape` | `Landscape` (`tone` own · brand, `flock`, `phoenix`, `animated`, `position`, `fade`): the Krizaka valley at dusk, decorative | client |
178
178
  | `@krizaka/ui/glow-card` | `GlowCard` (`glow` border·spotlight·both, `alive`, `asChild`) | client |
179
+ | `@krizaka/ui/engine-flow` | `EngineFlow` (`label`, `hub`, `nodes` with `flow` in·out·both, `planned`, `status`, `description`, `href`; `layout` radial·top-to-bottom·left-to-right, `compactLayout` under 560 px, `particles`, `conduit` bezier·straight, `hint`, `speed`): an engine and the apps it serves, photons along SVG conduits (motion.css), no animation frame | client |
179
180
  | `@krizaka/ui/marquee` | `Marquee` (`label`, `pauseLabel`, `playLabel`, `speed` px/s, `direction`, `fade`, `defaultPaused`) | client |
180
181
  | `@krizaka/ui/section-backdrop` | `SectionBackdrop` (`as`, `direction` down·up, `dome`, `grid`, `media` blurred for depth of field, `animated`): a page section on the brand's section gradient — see `@krizaka/tokens` BRAND.md, "Visual language" | server |
181
182
  | `@krizaka/ui/mascots` | `Mascot` (`bird` falcon·owl·duck·flamingo·pigeon·lovebird·crane, `mood` welcome·thinking·success·empty·error, `tone` brand·own, `size`, `animated`, `title`), `MASCOT_BIRDS`, `MASCOT_MOODS`: the Krizaka flock, in the host brand's accent — one bird at a moment that matters (onboarding, a long wait, a success, an empty list, an error); native `Mascot` in `/native` | client |
@@ -495,6 +496,7 @@ import { MotionObserver, RotatingWord } from "@krizaka/ui";
495
496
  | `kz-spotlight` | A soft bloom following the pointer across a card |
496
497
  | `kz-lift` | A card rising under the pointer |
497
498
  | `kz-gradient-text`, `kz-marquee` | Drifting gradient text, endless bands |
499
+ | `kz-flow` | EngineFlow's conduits and photons: paused off screen, held while settling, still under reduced motion |
498
500
  | `kz-overlay`, `kz-dialog`, `kz-pop`, `kz-fade` | Backdrops, dialogs (from the bottom on phones), menus, views swapped in place |
499
501
  | `kz-progress` | The indeterminate progress bar's travelling segment |
500
502
  | `kz-backdrop`, `kz-backdrop-drift`, `-dome`, `-grid`, `-media` | The layers of `SectionBackdrop`: the brand's section gradient, the slow light drift (40 s), the dome, the perspective grid, the blurred foreground |
package/dist/blocks.css CHANGED
@@ -708,6 +708,8 @@ a.kz-fact:focus-visible { outline: 2px solid var(--kz-ring, var(--kz-accent)); o
708
708
  border-top: 1px solid var(--kz-border-subtle); }
709
709
  .kz-tpl-collection ul a { display: inline-flex; min-height: 28px; align-items: center; padding: 0 10px; border-radius: 999px; font-size: 12.5px; font-weight: 600;
710
710
  text-decoration: none; color: var(--kz-text-primary); background: var(--kz-surface-2); border: 1px solid var(--kz-border-subtle); }
711
+ .kz-tpl-collection[data-links="stack"] ul { display: grid; justify-items: start; }
712
+ .kz-tpl-collection[data-links="stack"] ul a { max-width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
711
713
  .kz-tpl-collection ul a:hover { border-color: var(--kz-accent); }
712
714
  .kz-tpl-collection ul a:focus-visible { outline: 2px solid var(--kz-ring, var(--kz-accent)); outline-offset: 2px; }
713
715
  @media (hover: hover) and (prefers-reduced-motion: no-preference) {
@@ -22,9 +22,8 @@ var sites = [
22
22
  site({ id: "yasakia", name: "Yasakia", url: "https://dev.yasakia.com", kind: "product", group: "products", status: "development", mark: "yasakia", repo: "https://github.com/krizaka/yasakia" }),
23
23
  site({ id: "yororis", name: "Yororis", url: "https://dev.yororis.com", kind: "product", group: "products", status: "construction", mark: "yororis", repo: "https://github.com/krizaka/yororis" }),
24
24
  site({ id: "yomizaka", name: "Yomizaka", url: "https://dev.yomizaka.com", kind: "product", group: "products", status: "development", mark: "yomizaka", repo: "https://github.com/krizaka/yomizaka" }),
25
- // In development: nothing deployed yet, so the address is the repository (never a dead link to an unborn dev site).
26
- site({ id: "kachizaka", name: "Kachizaka", url: "https://github.com/krizaka/kachizaka", kind: "product", group: "products", status: "development", mark: "kachizaka", repo: "https://github.com/krizaka/kachizaka" }),
27
- site({ id: "akinaza", name: "Akinaza", url: "https://github.com/krizaka/akinaza", kind: "product", group: "products", status: "development", mark: "akinaza", repo: "https://github.com/krizaka/akinaza" }),
25
+ site({ id: "kachizaka", name: "Kachizaka", url: "https://dev.kachizaka.com", kind: "product", group: "products", status: "development", mark: "kachizaka", repo: "https://github.com/krizaka/kachizaka" }),
26
+ site({ id: "akinaza", name: "Akinaza", url: "https://dev.akinaza.com", kind: "product", group: "products", status: "development", mark: "akinaza", repo: "https://github.com/krizaka/akinaza" }),
28
27
  site({ id: "ui", name: "Krizaka UI", url: "https://ui.krizaka.com", kind: "open-source", group: "open-source", status: "released", mark: "krizaka", repo: "https://github.com/krizaka/krizaka-ui" }),
29
28
  site({ id: "java", name: "Krizaka Java", url: "https://java.krizaka.com", kind: "open-source", group: "open-source", status: "released", mark: "krizaka", repo: "https://github.com/krizaka/krizaka-build" }),
30
29
  site({ id: "github", name: "GitHub", url: "https://github.com/krizaka", kind: "open-source", group: "github", status: "released", mark: "github", repo: "https://github.com/krizaka" })
@@ -46,9 +45,9 @@ var familyLabels = {
46
45
  current: "You are here",
47
46
  descriptions: {
48
47
  krizaka: "The company: our products, our open source, our story.",
49
- orazaka: "Sovereign AI, on your own servers.",
48
+ orazaka: "Sovereign AI on your own servers: chat, documents, images and video \u2014 and the engine under the other products.",
50
49
  orochia: "A video platform for creators.",
51
- yasakia: "The dating app where you talk first.",
50
+ yasakia: "Meet real people: introductions, and photos checked before you see them.",
52
51
  yororis: "A listening space with a face and a voice.",
53
52
  yomizaka: "Yomizaka reads your leases, contracts and invoices.",
54
53
  kachizaka: "Predictions among friends \u2014 live data, in real time.",
@@ -68,9 +67,9 @@ var familyLabels = {
68
67
  current: "Vous \xEAtes ici",
69
68
  descriptions: {
70
69
  krizaka: "La compagnie : nos produits, notre open source, notre histoire.",
71
- orazaka: "L\u2019IA souveraine, sur vos propres serveurs.",
70
+ orazaka: "L\u2019IA souveraine sur vos propres serveurs : conversation, documents, images et vid\xE9o \u2014 et le moteur des autres produits.",
72
71
  orochia: "Une plateforme vid\xE9o pour les cr\xE9ateurs.",
73
- yasakia: "L\u2019app de rencontre o\xF9 l\u2019on se parle d\u2019abord.",
72
+ yasakia: "Rencontrez de vraies personnes : des pr\xE9sentations, et des photos v\xE9rifi\xE9es avant que vous les voyiez.",
74
73
  yororis: "Un espace d\u2019\xE9coute avec un visage et une voix.",
75
74
  yomizaka: "Yomizaka lit vos baux, contrats et factures.",
76
75
  kachizaka: "Les pronostics entre amis \u2014 des donn\xE9es en direct.",
@@ -92,4 +91,4 @@ export {
92
91
  sitesByGroup,
93
92
  familyLabels
94
93
  };
95
- //# sourceMappingURL=chunk-OUWPBSSL.js.map
94
+ //# sourceMappingURL=chunk-GYKQ52HX.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/family-mark.tsx","../src/sites/sites.ts"],"sourcesContent":["// The mark of a site of the family (`@krizaka/ui/sites`): its brand's `ProductLogo`, still (a list of marks never\n// moves), or GitHub's, in the text colour. Shared by `NavBar.Family` and `SiteFooter` — not an entry of its own.\nimport type * as React from \"react\";\n\nimport { ProductLogo } from \"./marks/ProductLogo\";\nimport type { SiteMark } from \"./sites/sites\";\n\n/** GitHub's mark, in the text colour (both themes). */\nexport function GitHubGlyph({ size = 16, className }: { size?: number; className?: string }) {\n return (\n <svg viewBox=\"0 0 16 16\" width={size} height={size} fill=\"currentColor\" aria-hidden className={className}>\n <path d=\"M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8Z\" />\n </svg>\n );\n}\n\n/** A site's mark, decorative (its name is always written beside it). */\nexport function FamilyMark({ mark, size }: { mark: SiteMark; size: number }): React.ReactElement {\n if (mark === \"github\") return <GitHubGlyph size={Math.round(size * 0.8)} />;\n return <ProductLogo id={mark} size={size} animated={false} />;\n}\n","// Server-safe: plain data. The Krizaka family — every site Krizaka runs, once. The family switcher of the bar\n// (`NavBar.Family`) and the common footer (`SiteFooter`) both read it, so adding a site is one release of this package:\n// every bar and every footer of the family follow.\n//\n// The words of the family (a site's one line, the groups, the statuses, the footer's signature) are brand data, written\n// here in English and French (`familyLabels`) — a site passes the set of its locale, or its own translation.\n\n/** A site of the family. */\nexport type SiteId = \"krizaka\" | \"orazaka\" | \"orochia\" | \"yasakia\" | \"yororis\" | \"yomizaka\" | \"kachizaka\" | \"akinaza\" | \"ui\" | \"java\" | \"github\";\n\n/** What a site is: the company, a product, or an open-source project. It chooses the footer's signature line. */\nexport type SiteKind = \"company\" | \"product\" | \"open-source\";\n\n/**\n * `released`: open to visit. `upcoming`: announced, not released yet (said \"Coming soon\"). `construction`: under\n * construction — nothing offered (a QA-only app may run; the public page says so). `development`: being built in the\n * open, with a dev site (said \"In development\"). A site with none yet would use its repository as its address.\n */\nexport type SiteStatus = \"released\" | \"upcoming\" | \"construction\" | \"development\";\n\n/** The groups of the family, in reading order: Krizaka · Products · Open source · GitHub. */\nexport type SiteGroup = \"krizaka\" | \"products\" | \"open-source\" | \"github\";\n\n/** The mark a site wears: a brand of `ProductLogo` (Krizaka UI and Krizaka Java wear Krizaka's), or GitHub's. */\nexport type SiteMark = \"krizaka\" | \"orazaka\" | \"orochia\" | \"yasakia\" | \"yororis\" | \"yomizaka\" | \"kachizaka\" | \"akinaza\" | \"github\";\n\nexport interface Site {\n readonly id: SiteId;\n /** The name, never translated. */\n readonly name: string;\n /** The address of the site (its home). */\n readonly url: string;\n /** The address without the scheme, as people say it (`ui.krizaka.com`). */\n readonly host: string;\n readonly kind: SiteKind;\n readonly group: SiteGroup;\n readonly status: SiteStatus;\n readonly mark: SiteMark;\n /** The repository the site is built from. */\n readonly repo: string;\n}\n\nconst site = (s: Omit<Site, \"host\">): Site => ({ ...s, host: s.url.replace(/^https?:\\/\\//, \"\").replace(/\\/$/, \"\") });\n\n/** Every site of the family, in reading order (the group order, then the order inside each group). */\nexport const sites: readonly Site[] = [\n site({ id: \"krizaka\", name: \"Krizaka\", url: \"https://www.krizaka.com\", kind: \"company\", group: \"krizaka\", status: \"released\", mark: \"krizaka\", repo: \"https://github.com/krizaka/krizaka-com\" }),\n site({ id: \"orazaka\", name: \"Orazaka\", url: \"https://dev.orazaka.com\", kind: \"product\", group: \"products\", status: \"released\", mark: \"orazaka\", repo: \"https://github.com/krizaka/orazaka\" }),\n site({ id: \"orochia\", name: \"Orochia\", url: \"https://dev.orochia.com\", kind: \"product\", group: \"products\", status: \"released\", mark: \"orochia\", repo: \"https://github.com/krizaka/orochia\" }),\n site({ id: \"yasakia\", name: \"Yasakia\", url: \"https://dev.yasakia.com\", kind: \"product\", group: \"products\", status: \"development\", mark: \"yasakia\", repo: \"https://github.com/krizaka/yasakia\" }),\n site({ id: \"yororis\", name: \"Yororis\", url: \"https://dev.yororis.com\", kind: \"product\", group: \"products\", status: \"construction\", mark: \"yororis\", repo: \"https://github.com/krizaka/yororis\" }),\n site({ id: \"yomizaka\", name: \"Yomizaka\", url: \"https://dev.yomizaka.com\", kind: \"product\", group: \"products\", status: \"development\", mark: \"yomizaka\", repo: \"https://github.com/krizaka/yomizaka\" }),\n site({ id: \"kachizaka\", name: \"Kachizaka\", url: \"https://dev.kachizaka.com\", kind: \"product\", group: \"products\", status: \"development\", mark: \"kachizaka\", repo: \"https://github.com/krizaka/kachizaka\" }),\n site({ id: \"akinaza\", name: \"Akinaza\", url: \"https://dev.akinaza.com\", kind: \"product\", group: \"products\", status: \"development\", mark: \"akinaza\", repo: \"https://github.com/krizaka/akinaza\" }),\n site({ id: \"ui\", name: \"Krizaka UI\", url: \"https://ui.krizaka.com\", kind: \"open-source\", group: \"open-source\", status: \"released\", mark: \"krizaka\", repo: \"https://github.com/krizaka/krizaka-ui\" }),\n site({ id: \"java\", name: \"Krizaka Java\", url: \"https://java.krizaka.com\", kind: \"open-source\", group: \"open-source\", status: \"released\", mark: \"krizaka\", repo: \"https://github.com/krizaka/krizaka-build\" }),\n site({ id: \"github\", name: \"GitHub\", url: \"https://github.com/krizaka\", kind: \"open-source\", group: \"github\", status: \"released\", mark: \"github\", repo: \"https://github.com/krizaka\" }),\n];\n\n/** The groups, in reading order. */\nexport const siteGroups: readonly SiteGroup[] = [\"krizaka\", \"products\", \"open-source\", \"github\"];\n\n/** A site by id. */\nexport function siteById(id: SiteId): Site {\n const found = sites.find((s) => s.id === id);\n if (!found) throw new Error(`Unknown Krizaka site \"${id}\".`);\n return found;\n}\n\n/** The family grouped, in reading order: `[{ group, sites }]`, empty groups left out. */\nexport function sitesByGroup(): { group: SiteGroup; sites: Site[] }[] {\n return siteGroups.map((group) => ({ group, sites: sites.filter((s) => s.group === group) })).filter((g) => g.sites.length > 0);\n}\n\n/** The languages the family's words are written in. */\nexport type SiteLocale = \"en\" | \"fr\";\n\n/** The words of the family: the switcher, the footer, each site's one line. */\nexport interface FamilyLabels {\n /** The family's name: the switcher's navigation and its button, the footer's navigation (“Krizaka family”). */\n family: string;\n /** The heading of each group. */\n groups: Record<SiteGroup, string>;\n /** The badge of a site that is not released. */\n status: Record<Exclude<SiteStatus, \"released\">, string>;\n /** Says which site is the current one (“You are here”). */\n current: string;\n /** One line per site: what it is. */\n descriptions: Record<SiteId, string>;\n /** The footer's signature, by the kind of the current site (“A Krizaka product”). */\n signature: Record<SiteKind, string>;\n /** The footer's place line (“Made in Montréal”). */\n place: string;\n /** The accessible name of the version (“Version”). */\n version: string;\n}\n\n/** The family's words in English and French. Pass `familyLabels[locale]`, or your own translation of the same shape. */\nexport const familyLabels: Record<SiteLocale, FamilyLabels> = {\n en: {\n family: \"Krizaka family\",\n groups: { krizaka: \"Krizaka\", products: \"Products\", \"open-source\": \"Open source\", github: \"GitHub\" },\n status: { upcoming: \"Coming soon\", construction: \"Under construction\", development: \"In development\" },\n current: \"You are here\",\n descriptions: {\n krizaka: \"The company: our products, our open source, our story.\",\n orazaka: \"Sovereign AI on your own servers: chat, documents, images and video — and the engine under the other products.\",\n orochia: \"A video platform for creators.\",\n yasakia: \"Meet real people: introductions, and photos checked before you see them.\",\n yororis: \"A listening space with a face and a voice.\",\n yomizaka: \"Yomizaka reads your leases, contracts and invoices.\",\n kachizaka: \"Predictions among friends — live data, in real time.\",\n akinaza: \"Running a shop in Québec, for less — Loi 25 by design.\",\n ui: \"Components, tokens, icons and charts — web and React Native.\",\n java: \"Spring Boot building blocks on Maven Central.\",\n github: \"Every repository, in the open.\",\n },\n signature: { company: \"A Krizaka company\", product: \"A Krizaka product\", \"open-source\": \"A Krizaka open-source project\" },\n place: \"Made in Montréal\",\n version: \"Version\",\n },\n fr: {\n family: \"Famille Krizaka\",\n groups: { krizaka: \"Krizaka\", products: \"Produits\", \"open-source\": \"Open source\", github: \"GitHub\" },\n status: { upcoming: \"Bientôt\", construction: \"En construction\", development: \"En développement\" },\n current: \"Vous êtes ici\",\n descriptions: {\n krizaka: \"La compagnie : nos produits, notre open source, notre histoire.\",\n orazaka: \"L’IA souveraine sur vos propres serveurs : conversation, documents, images et vidéo — et le moteur des autres produits.\",\n orochia: \"Une plateforme vidéo pour les créateurs.\",\n yasakia: \"Rencontrez de vraies personnes : des présentations, et des photos vérifiées avant que vous les voyiez.\",\n yororis: \"Un espace d’écoute avec un visage et une voix.\",\n yomizaka: \"Yomizaka lit vos baux, contrats et factures.\",\n kachizaka: \"Les pronostics entre amis — des données en direct.\",\n akinaza: \"Tenir une boutique au Québec, pour moins cher — Loi 25 dès la conception.\",\n ui: \"Composants, jetons, icônes et graphiques — web et React Native.\",\n java: \"Des briques Spring Boot sur Maven Central.\",\n github: \"Tous les dépôts, au grand jour.\",\n },\n signature: { company: \"Une compagnie Krizaka\", product: \"Un produit Krizaka\", \"open-source\": \"Un projet open source de Krizaka\" },\n place: \"Fait à Montréal\",\n version: \"Version\",\n },\n};\n"],"mappings":";;;;;;AAWM;AAHC,SAAS,YAAY,EAAE,OAAO,IAAI,UAAU,GAA0C;AAC3F,SACE,oBAAC,SAAI,SAAQ,aAAY,OAAO,MAAM,QAAQ,MAAM,MAAK,gBAAe,eAAW,MAAC,WAClF,8BAAC,UAAK,GAAE,8jBAA6jB,GACvkB;AAEJ;AAGO,SAAS,WAAW,EAAE,MAAM,KAAK,GAAyD;AAC/F,MAAI,SAAS,SAAU,QAAO,oBAAC,eAAY,MAAM,KAAK,MAAM,OAAO,GAAG,GAAG;AACzE,SAAO,oBAAC,eAAY,IAAI,MAAM,MAAY,UAAU,OAAO;AAC7D;;;ACsBA,IAAM,OAAO,CAAC,OAAiC,EAAE,GAAG,GAAG,MAAM,EAAE,IAAI,QAAQ,gBAAgB,EAAE,EAAE,QAAQ,OAAO,EAAE,EAAE;AAG3G,IAAM,QAAyB;AAAA,EACpC,KAAK,EAAE,IAAI,WAAW,MAAM,WAAW,KAAK,2BAA2B,MAAM,WAAW,OAAO,WAAW,QAAQ,YAAY,MAAM,WAAW,MAAM,yCAAyC,CAAC;AAAA,EAC/L,KAAK,EAAE,IAAI,WAAW,MAAM,WAAW,KAAK,2BAA2B,MAAM,WAAW,OAAO,YAAY,QAAQ,YAAY,MAAM,WAAW,MAAM,qCAAqC,CAAC;AAAA,EAC5L,KAAK,EAAE,IAAI,WAAW,MAAM,WAAW,KAAK,2BAA2B,MAAM,WAAW,OAAO,YAAY,QAAQ,YAAY,MAAM,WAAW,MAAM,qCAAqC,CAAC;AAAA,EAC5L,KAAK,EAAE,IAAI,WAAW,MAAM,WAAW,KAAK,2BAA2B,MAAM,WAAW,OAAO,YAAY,QAAQ,eAAe,MAAM,WAAW,MAAM,qCAAqC,CAAC;AAAA,EAC/L,KAAK,EAAE,IAAI,WAAW,MAAM,WAAW,KAAK,2BAA2B,MAAM,WAAW,OAAO,YAAY,QAAQ,gBAAgB,MAAM,WAAW,MAAM,qCAAqC,CAAC;AAAA,EAChM,KAAK,EAAE,IAAI,YAAY,MAAM,YAAY,KAAK,4BAA4B,MAAM,WAAW,OAAO,YAAY,QAAQ,eAAe,MAAM,YAAY,MAAM,sCAAsC,CAAC;AAAA,EACpM,KAAK,EAAE,IAAI,aAAa,MAAM,aAAa,KAAK,6BAA6B,MAAM,WAAW,OAAO,YAAY,QAAQ,eAAe,MAAM,aAAa,MAAM,uCAAuC,CAAC;AAAA,EACzM,KAAK,EAAE,IAAI,WAAW,MAAM,WAAW,KAAK,2BAA2B,MAAM,WAAW,OAAO,YAAY,QAAQ,eAAe,MAAM,WAAW,MAAM,qCAAqC,CAAC;AAAA,EAC/L,KAAK,EAAE,IAAI,MAAM,MAAM,cAAc,KAAK,0BAA0B,MAAM,eAAe,OAAO,eAAe,QAAQ,YAAY,MAAM,WAAW,MAAM,wCAAwC,CAAC;AAAA,EACnM,KAAK,EAAE,IAAI,QAAQ,MAAM,gBAAgB,KAAK,4BAA4B,MAAM,eAAe,OAAO,eAAe,QAAQ,YAAY,MAAM,WAAW,MAAM,2CAA2C,CAAC;AAAA,EAC5M,KAAK,EAAE,IAAI,UAAU,MAAM,UAAU,KAAK,8BAA8B,MAAM,eAAe,OAAO,UAAU,QAAQ,YAAY,MAAM,UAAU,MAAM,6BAA6B,CAAC;AACxL;AAGO,IAAM,aAAmC,CAAC,WAAW,YAAY,eAAe,QAAQ;AAGxF,SAAS,SAAS,IAAkB;AACzC,QAAM,QAAQ,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE;AAC3C,MAAI,CAAC,MAAO,OAAM,IAAI,MAAM,yBAAyB,EAAE,IAAI;AAC3D,SAAO;AACT;AAGO,SAAS,eAAsD;AACpE,SAAO,WAAW,IAAI,CAAC,WAAW,EAAE,OAAO,OAAO,MAAM,OAAO,CAAC,MAAM,EAAE,UAAU,KAAK,EAAE,EAAE,EAAE,OAAO,CAAC,MAAM,EAAE,MAAM,SAAS,CAAC;AAC/H;AA0BO,IAAM,eAAiD;AAAA,EAC5D,IAAI;AAAA,IACF,QAAQ;AAAA,IACR,QAAQ,EAAE,SAAS,WAAW,UAAU,YAAY,eAAe,eAAe,QAAQ,SAAS;AAAA,IACnG,QAAQ,EAAE,UAAU,eAAe,cAAc,sBAAsB,aAAa,iBAAiB;AAAA,IACrG,SAAS;AAAA,IACT,cAAc;AAAA,MACZ,SAAS;AAAA,MACT,SAAS;AAAA,MACT,SAAS;AAAA,MACT,SAAS;AAAA,MACT,SAAS;AAAA,MACT,UAAU;AAAA,MACV,WAAW;AAAA,MACX,SAAS;AAAA,MACT,IAAI;AAAA,MACJ,MAAM;AAAA,MACN,QAAQ;AAAA,IACV;AAAA,IACA,WAAW,EAAE,SAAS,qBAAqB,SAAS,qBAAqB,eAAe,gCAAgC;AAAA,IACxH,OAAO;AAAA,IACP,SAAS;AAAA,EACX;AAAA,EACA,IAAI;AAAA,IACF,QAAQ;AAAA,IACR,QAAQ,EAAE,SAAS,WAAW,UAAU,YAAY,eAAe,eAAe,QAAQ,SAAS;AAAA,IACnG,QAAQ,EAAE,UAAU,cAAW,cAAc,mBAAmB,aAAa,sBAAmB;AAAA,IAChG,SAAS;AAAA,IACT,cAAc;AAAA,MACZ,SAAS;AAAA,MACT,SAAS;AAAA,MACT,SAAS;AAAA,MACT,SAAS;AAAA,MACT,SAAS;AAAA,MACT,UAAU;AAAA,MACV,WAAW;AAAA,MACX,SAAS;AAAA,MACT,IAAI;AAAA,MACJ,MAAM;AAAA,MACN,QAAQ;AAAA,IACV;AAAA,IACA,WAAW,EAAE,SAAS,yBAAyB,SAAS,sBAAsB,eAAe,mCAAmC;AAAA,IAChI,OAAO;AAAA,IACP,SAAS;AAAA,EACX;AACF;","names":[]}
@@ -65,8 +65,14 @@ type DocsHubPageProps = Omit<React.HTMLAttributes<HTMLElement>, "title"> & {
65
65
  };
66
66
  /** The app's link component (Next's `Link`) for internal addresses. */
67
67
  linkAs?: LinkComponent;
68
+ /**
69
+ * How a collection's quick links sit: `wrap` (pills in a row that wraps) or `stack` (one pill per line, so the first
70
+ * link of every card starts at the same height).
71
+ * @default "wrap"
72
+ */
73
+ linksLayout?: "wrap" | "stack";
68
74
  };
69
75
  /** A documentation hub: search first, the collections in their brand, quick starts, popular and new pages. */
70
- declare function DocsHubPage({ eyebrow, title, lead, search, searchHints, collectionsTitle, collections, quickstarts, popular, whatsNew, promise, linkAs, ...props }: DocsHubPageProps): React.JSX.Element;
76
+ declare function DocsHubPage({ eyebrow, title, lead, search, searchHints, collectionsTitle, collections, quickstarts, popular, whatsNew, promise, linkAs, linksLayout, ...props }: DocsHubPageProps): React.JSX.Element;
71
77
 
72
78
  export { type DocsCollection, type DocsHubLink, DocsHubPage, type DocsHubPageProps };
@@ -10,14 +10,14 @@ function List({ items, linkAs: Link = "a" }) {
10
10
  item.meta && /* @__PURE__ */ jsx("small", { children: item.meta })
11
11
  ] }) }, `${i}:${item.href}`)) });
12
12
  }
13
- function DocsHubPage({ eyebrow, title, lead, search, searchHints, collectionsTitle, collections, quickstarts, popular, whatsNew, promise, linkAs, ...props }) {
13
+ function DocsHubPage({ eyebrow, title, lead, search, searchHints, collectionsTitle, collections, quickstarts, popular, whatsNew, promise, linkAs, linksLayout = "wrap", ...props }) {
14
14
  const L = linkAs ?? "a";
15
15
  return /* @__PURE__ */ jsxs("div", { ...props, children: [
16
16
  /* @__PURE__ */ jsx(PageHero, { eyebrow, title, lead, align: "center", backdrop: "grid", children: (search || searchHints) && /* @__PURE__ */ jsxs("div", { className: "kz-tpl-hub-search", children: [
17
17
  search,
18
18
  searchHints && /* @__PURE__ */ jsx("div", { className: "kz-tpl-hub-hints", children: searchHints })
19
19
  ] }) }),
20
- /* @__PURE__ */ jsx(Section, { id: "collections", title: collectionsTitle, headingSize: "sm", spacing: "sm", children: /* @__PURE__ */ jsx("ul", { className: "kz-tpl-collections", children: collections.map((c) => /* @__PURE__ */ jsx("li", { className: c.brand ? "brand-" + c.brand : void 0, children: /* @__PURE__ */ jsxs("div", { className: "kz-tpl-collection", children: [
20
+ /* @__PURE__ */ jsx(Section, { id: "collections", title: collectionsTitle, headingSize: "sm", spacing: "sm", children: /* @__PURE__ */ jsx("ul", { className: "kz-tpl-collections", children: collections.map((c) => /* @__PURE__ */ jsx("li", { className: c.brand ? "brand-" + c.brand : void 0, children: /* @__PURE__ */ jsxs("div", { className: "kz-tpl-collection", "data-links": linksLayout, children: [
21
21
  /* @__PURE__ */ jsxs("div", { className: "kz-tpl-collection-head", children: [
22
22
  c.mark && /* @__PURE__ */ jsx("span", { "aria-hidden": true, children: c.mark }),
23
23
  /* @__PURE__ */ jsx(L, { href: c.href, children: c.title })
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/docs-hub-page/docs-hub-page.tsx"],"sourcesContent":["// Server-safe. The entry of a documentation (blocks.css `.kz-tpl-hub-*`, `.kz-tpl-collections`): the search in the\n// middle of the hero, the collections each in its product's brand with its quick links, the quick starts beside the\n// most read pages, what is new from the registries, and the owl's promise. One column on a phone, the search first.\nimport { MascotQuote } from \"@krizaka/ui/mascot-quote\";\nimport { Section } from \"@krizaka/ui/page\";\nimport type { LinkComponent } from \"@krizaka/ui/page-hero\";\nimport { PageHero } from \"@krizaka/ui/page-hero\";\nimport * as React from \"react\";\n\nexport interface DocsCollection {\n /** A stable key. */\n id: string;\n /** The product's brand (`orazaka`…): the panel wears `.brand-<id>`. */\n brand?: string;\n /** The product's mark. */\n mark?: React.ReactNode;\n /** The collection's name: a link to its home. */\n title: string;\n /** Where it starts. */\n href: string;\n /** What it covers, in one sentence. */\n description?: React.ReactNode;\n /** Its most useful pages (three or four). */\n links?: readonly { href: string; label: string }[];\n}\n\nexport interface DocsHubLink {\n /** Where it leads. */\n href: string;\n /** The page's title. */\n title: React.ReactNode;\n /** On the right, in mono: a collection, a version, a date. */\n meta?: React.ReactNode;\n}\n\nexport type DocsHubPageProps = Omit<React.HTMLAttributes<HTMLElement>, \"title\"> & {\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 /** The search, front and centre (a SearchField, a button that opens the command palette). */\n search?: React.ReactNode;\n /** Under the search: what people look for (a few links or keys). */\n searchHints?: React.ReactNode;\n /** The collections' heading. */\n collectionsTitle: React.ReactNode;\n /** The collections, each in its brand. */\n collections: readonly DocsCollection[];\n /** The quick starts: a title and their samples (CodeBlocks, CodeTabs). */\n quickstarts?: { title: React.ReactNode; children: React.ReactNode };\n /** The most read pages. */\n popular?: { title: React.ReactNode; items: readonly DocsHubLink[] };\n /** What is new (releases from the registries, published pages). */\n whatsNew?: { title: React.ReactNode; items: readonly DocsHubLink[] };\n /** The owl's promise at the foot: what this documentation guarantees. */\n promise?: { label: React.ReactNode; text: React.ReactNode };\n /** The app's link component (Next's `Link`) for internal addresses. */\n linkAs?: LinkComponent;\n};\n\nfunction List({ items, linkAs: Link = \"a\" }: { items: readonly DocsHubLink[]; linkAs?: LinkComponent }) {\n const L = Link as React.ElementType;\n return (\n <ul className=\"kz-tpl-links\">\n {items.map((item, i) => (\n <li key={`${i}:${item.href}`}>\n <L href={item.href}>\n <strong>{item.title}</strong>\n {item.meta && <small>{item.meta}</small>}\n </L>\n </li>\n ))}\n </ul>\n );\n}\n\n/** A documentation hub: search first, the collections in their brand, quick starts, popular and new pages. */\nexport function DocsHubPage({ eyebrow, title, lead, search, searchHints, collectionsTitle, collections, quickstarts, popular, whatsNew, promise, linkAs, ...props }: DocsHubPageProps) {\n const L = (linkAs ?? \"a\") as React.ElementType;\n return (\n <div {...props}>\n <PageHero eyebrow={eyebrow} title={title} lead={lead} align=\"center\" backdrop=\"grid\">\n {(search || searchHints) && (\n <div className=\"kz-tpl-hub-search\">\n {search}\n {searchHints && <div className=\"kz-tpl-hub-hints\">{searchHints}</div>}\n </div>\n )}\n </PageHero>\n <Section id=\"collections\" title={collectionsTitle} headingSize=\"sm\" spacing=\"sm\">\n <ul className=\"kz-tpl-collections\">\n {collections.map((c) => (\n <li key={c.id} className={c.brand ? \"brand-\" + c.brand : undefined}>\n <div className=\"kz-tpl-collection\">\n <div className=\"kz-tpl-collection-head\">\n {c.mark && <span aria-hidden>{c.mark}</span>}\n <L href={c.href}>{c.title}</L>\n </div>\n {c.description && <p>{c.description}</p>}\n {c.links && c.links.length > 0 && (\n <ul aria-label={c.title}>\n {c.links.map((l) => (\n <li key={l.href}>\n <L href={l.href}>{l.label}</L>\n </li>\n ))}\n </ul>\n )}\n </div>\n </li>\n ))}\n </ul>\n </Section>\n {(quickstarts || popular) && (\n <Section spacing=\"sm\" divider aria-label={typeof quickstarts?.title === \"string\" ? quickstarts.title : undefined}>\n <div className=\"kz-tpl-two\">\n {quickstarts && (\n <div className=\"kz-tpl-stack\">\n <h2 className=\"kz-heading-title kz-tpl-h2\">{quickstarts.title}</h2>\n {quickstarts.children}\n </div>\n )}\n {popular && (\n <div className=\"kz-tpl-stack\">\n <h2 className=\"kz-heading-title kz-tpl-h2\">{popular.title}</h2>\n <List items={popular.items} linkAs={linkAs} />\n </div>\n )}\n </div>\n </Section>\n )}\n {whatsNew && (\n <Section id=\"whats-new\" title={whatsNew.title} headingSize=\"sm\" spacing=\"sm\" divider>\n <List items={whatsNew.items} linkAs={linkAs} />\n </Section>\n )}\n {promise && (\n <Section spacing=\"sm\" aria-label={typeof promise.label === \"string\" ? promise.label : undefined}>\n <MascotQuote variant=\"callout\" bird=\"owl\" mood=\"welcome\" label={promise.label}>\n {promise.text}\n </MascotQuote>\n </Section>\n )}\n </div>\n );\n}\n"],"mappings":";AAGA,SAAS,mBAAmB;AAC5B,SAAS,eAAe;AAExB,SAAS,gBAAgB;AA8Df,SACE,KADF;AANV,SAAS,KAAK,EAAE,OAAO,QAAQ,OAAO,IAAI,GAA8D;AACtG,QAAM,IAAI;AACV,SACE,oBAAC,QAAG,WAAU,gBACX,gBAAM,IAAI,CAAC,MAAM,MAChB,oBAAC,QACC,+BAAC,KAAE,MAAM,KAAK,MACZ;AAAA,wBAAC,YAAQ,eAAK,OAAM;AAAA,IACnB,KAAK,QAAQ,oBAAC,WAAO,eAAK,MAAK;AAAA,KAClC,KAJO,GAAG,CAAC,IAAI,KAAK,IAAI,EAK1B,CACD,GACH;AAEJ;AAGO,SAAS,YAAY,EAAE,SAAS,OAAO,MAAM,QAAQ,aAAa,kBAAkB,aAAa,aAAa,SAAS,UAAU,SAAS,QAAQ,GAAG,MAAM,GAAqB;AACrL,QAAM,IAAK,UAAU;AACrB,SACE,qBAAC,SAAK,GAAG,OACP;AAAA,wBAAC,YAAS,SAAkB,OAAc,MAAY,OAAM,UAAS,UAAS,QAC1E,qBAAU,gBACV,qBAAC,SAAI,WAAU,qBACZ;AAAA;AAAA,MACA,eAAe,oBAAC,SAAI,WAAU,oBAAoB,uBAAY;AAAA,OACjE,GAEJ;AAAA,IACA,oBAAC,WAAQ,IAAG,eAAc,OAAO,kBAAkB,aAAY,MAAK,SAAQ,MAC1E,8BAAC,QAAG,WAAU,sBACX,sBAAY,IAAI,CAAC,MAChB,oBAAC,QAAc,WAAW,EAAE,QAAQ,WAAW,EAAE,QAAQ,QACvD,+BAAC,SAAI,WAAU,qBACb;AAAA,2BAAC,SAAI,WAAU,0BACZ;AAAA,UAAE,QAAQ,oBAAC,UAAK,eAAW,MAAE,YAAE,MAAK;AAAA,QACrC,oBAAC,KAAE,MAAM,EAAE,MAAO,YAAE,OAAM;AAAA,SAC5B;AAAA,MACC,EAAE,eAAe,oBAAC,OAAG,YAAE,aAAY;AAAA,MACnC,EAAE,SAAS,EAAE,MAAM,SAAS,KAC3B,oBAAC,QAAG,cAAY,EAAE,OACf,YAAE,MAAM,IAAI,CAAC,MACZ,oBAAC,QACC,8BAAC,KAAE,MAAM,EAAE,MAAO,YAAE,OAAM,KADnB,EAAE,IAEX,CACD,GACH;AAAA,OAEJ,KAhBO,EAAE,EAiBX,CACD,GACH,GACF;AAAA,KACE,eAAe,YACf,oBAAC,WAAQ,SAAQ,MAAK,SAAO,MAAC,cAAY,OAAO,aAAa,UAAU,WAAW,YAAY,QAAQ,QACrG,+BAAC,SAAI,WAAU,cACZ;AAAA,qBACC,qBAAC,SAAI,WAAU,gBACb;AAAA,4BAAC,QAAG,WAAU,8BAA8B,sBAAY,OAAM;AAAA,QAC7D,YAAY;AAAA,SACf;AAAA,MAED,WACC,qBAAC,SAAI,WAAU,gBACb;AAAA,4BAAC,QAAG,WAAU,8BAA8B,kBAAQ,OAAM;AAAA,QAC1D,oBAAC,QAAK,OAAO,QAAQ,OAAO,QAAgB;AAAA,SAC9C;AAAA,OAEJ,GACF;AAAA,IAED,YACC,oBAAC,WAAQ,IAAG,aAAY,OAAO,SAAS,OAAO,aAAY,MAAK,SAAQ,MAAK,SAAO,MAClF,8BAAC,QAAK,OAAO,SAAS,OAAO,QAAgB,GAC/C;AAAA,IAED,WACC,oBAAC,WAAQ,SAAQ,MAAK,cAAY,OAAO,QAAQ,UAAU,WAAW,QAAQ,QAAQ,QACpF,8BAAC,eAAY,SAAQ,WAAU,MAAK,OAAM,MAAK,WAAU,OAAO,QAAQ,OACrE,kBAAQ,MACX,GACF;AAAA,KAEJ;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../src/docs-hub-page/docs-hub-page.tsx"],"sourcesContent":["// Server-safe. The entry of a documentation (blocks.css `.kz-tpl-hub-*`, `.kz-tpl-collections`): the search in the\n// middle of the hero, the collections each in its product's brand with its quick links, the quick starts beside the\n// most read pages, what is new from the registries, and the owl's promise. One column on a phone, the search first.\nimport { MascotQuote } from \"@krizaka/ui/mascot-quote\";\nimport { Section } from \"@krizaka/ui/page\";\nimport type { LinkComponent } from \"@krizaka/ui/page-hero\";\nimport { PageHero } from \"@krizaka/ui/page-hero\";\nimport * as React from \"react\";\n\nexport interface DocsCollection {\n /** A stable key. */\n id: string;\n /** The product's brand (`orazaka`…): the panel wears `.brand-<id>`. */\n brand?: string;\n /** The product's mark. */\n mark?: React.ReactNode;\n /** The collection's name: a link to its home. */\n title: string;\n /** Where it starts. */\n href: string;\n /** What it covers, in one sentence. */\n description?: React.ReactNode;\n /** Its most useful pages (three or four). */\n links?: readonly { href: string; label: string }[];\n}\n\nexport interface DocsHubLink {\n /** Where it leads. */\n href: string;\n /** The page's title. */\n title: React.ReactNode;\n /** On the right, in mono: a collection, a version, a date. */\n meta?: React.ReactNode;\n}\n\nexport type DocsHubPageProps = Omit<React.HTMLAttributes<HTMLElement>, \"title\"> & {\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 /** The search, front and centre (a SearchField, a button that opens the command palette). */\n search?: React.ReactNode;\n /** Under the search: what people look for (a few links or keys). */\n searchHints?: React.ReactNode;\n /** The collections' heading. */\n collectionsTitle: React.ReactNode;\n /** The collections, each in its brand. */\n collections: readonly DocsCollection[];\n /** The quick starts: a title and their samples (CodeBlocks, CodeTabs). */\n quickstarts?: { title: React.ReactNode; children: React.ReactNode };\n /** The most read pages. */\n popular?: { title: React.ReactNode; items: readonly DocsHubLink[] };\n /** What is new (releases from the registries, published pages). */\n whatsNew?: { title: React.ReactNode; items: readonly DocsHubLink[] };\n /** The owl's promise at the foot: what this documentation guarantees. */\n promise?: { label: React.ReactNode; text: React.ReactNode };\n /** The app's link component (Next's `Link`) for internal addresses. */\n linkAs?: LinkComponent;\n /**\n * How a collection's quick links sit: `wrap` (pills in a row that wraps) or `stack` (one pill per line, so the first\n * link of every card starts at the same height).\n * @default \"wrap\"\n */\n linksLayout?: \"wrap\" | \"stack\";\n};\n\nfunction List({ items, linkAs: Link = \"a\" }: { items: readonly DocsHubLink[]; linkAs?: LinkComponent }) {\n const L = Link as React.ElementType;\n return (\n <ul className=\"kz-tpl-links\">\n {items.map((item, i) => (\n <li key={`${i}:${item.href}`}>\n <L href={item.href}>\n <strong>{item.title}</strong>\n {item.meta && <small>{item.meta}</small>}\n </L>\n </li>\n ))}\n </ul>\n );\n}\n\n/** A documentation hub: search first, the collections in their brand, quick starts, popular and new pages. */\nexport function DocsHubPage({ eyebrow, title, lead, search, searchHints, collectionsTitle, collections, quickstarts, popular, whatsNew, promise, linkAs, linksLayout = \"wrap\", ...props }: DocsHubPageProps) {\n const L = (linkAs ?? \"a\") as React.ElementType;\n return (\n <div {...props}>\n <PageHero eyebrow={eyebrow} title={title} lead={lead} align=\"center\" backdrop=\"grid\">\n {(search || searchHints) && (\n <div className=\"kz-tpl-hub-search\">\n {search}\n {searchHints && <div className=\"kz-tpl-hub-hints\">{searchHints}</div>}\n </div>\n )}\n </PageHero>\n <Section id=\"collections\" title={collectionsTitle} headingSize=\"sm\" spacing=\"sm\">\n <ul className=\"kz-tpl-collections\">\n {collections.map((c) => (\n <li key={c.id} className={c.brand ? \"brand-\" + c.brand : undefined}>\n <div className=\"kz-tpl-collection\" data-links={linksLayout}>\n <div className=\"kz-tpl-collection-head\">\n {c.mark && <span aria-hidden>{c.mark}</span>}\n <L href={c.href}>{c.title}</L>\n </div>\n {c.description && <p>{c.description}</p>}\n {c.links && c.links.length > 0 && (\n <ul aria-label={c.title}>\n {c.links.map((l) => (\n <li key={l.href}>\n <L href={l.href}>{l.label}</L>\n </li>\n ))}\n </ul>\n )}\n </div>\n </li>\n ))}\n </ul>\n </Section>\n {(quickstarts || popular) && (\n <Section spacing=\"sm\" divider aria-label={typeof quickstarts?.title === \"string\" ? quickstarts.title : undefined}>\n <div className=\"kz-tpl-two\">\n {quickstarts && (\n <div className=\"kz-tpl-stack\">\n <h2 className=\"kz-heading-title kz-tpl-h2\">{quickstarts.title}</h2>\n {quickstarts.children}\n </div>\n )}\n {popular && (\n <div className=\"kz-tpl-stack\">\n <h2 className=\"kz-heading-title kz-tpl-h2\">{popular.title}</h2>\n <List items={popular.items} linkAs={linkAs} />\n </div>\n )}\n </div>\n </Section>\n )}\n {whatsNew && (\n <Section id=\"whats-new\" title={whatsNew.title} headingSize=\"sm\" spacing=\"sm\" divider>\n <List items={whatsNew.items} linkAs={linkAs} />\n </Section>\n )}\n {promise && (\n <Section spacing=\"sm\" aria-label={typeof promise.label === \"string\" ? promise.label : undefined}>\n <MascotQuote variant=\"callout\" bird=\"owl\" mood=\"welcome\" label={promise.label}>\n {promise.text}\n </MascotQuote>\n </Section>\n )}\n </div>\n );\n}\n"],"mappings":";AAGA,SAAS,mBAAmB;AAC5B,SAAS,eAAe;AAExB,SAAS,gBAAgB;AAoEf,SACE,KADF;AANV,SAAS,KAAK,EAAE,OAAO,QAAQ,OAAO,IAAI,GAA8D;AACtG,QAAM,IAAI;AACV,SACE,oBAAC,QAAG,WAAU,gBACX,gBAAM,IAAI,CAAC,MAAM,MAChB,oBAAC,QACC,+BAAC,KAAE,MAAM,KAAK,MACZ;AAAA,wBAAC,YAAQ,eAAK,OAAM;AAAA,IACnB,KAAK,QAAQ,oBAAC,WAAO,eAAK,MAAK;AAAA,KAClC,KAJO,GAAG,CAAC,IAAI,KAAK,IAAI,EAK1B,CACD,GACH;AAEJ;AAGO,SAAS,YAAY,EAAE,SAAS,OAAO,MAAM,QAAQ,aAAa,kBAAkB,aAAa,aAAa,SAAS,UAAU,SAAS,QAAQ,cAAc,QAAQ,GAAG,MAAM,GAAqB;AAC3M,QAAM,IAAK,UAAU;AACrB,SACE,qBAAC,SAAK,GAAG,OACP;AAAA,wBAAC,YAAS,SAAkB,OAAc,MAAY,OAAM,UAAS,UAAS,QAC1E,qBAAU,gBACV,qBAAC,SAAI,WAAU,qBACZ;AAAA;AAAA,MACA,eAAe,oBAAC,SAAI,WAAU,oBAAoB,uBAAY;AAAA,OACjE,GAEJ;AAAA,IACA,oBAAC,WAAQ,IAAG,eAAc,OAAO,kBAAkB,aAAY,MAAK,SAAQ,MAC1E,8BAAC,QAAG,WAAU,sBACX,sBAAY,IAAI,CAAC,MAChB,oBAAC,QAAc,WAAW,EAAE,QAAQ,WAAW,EAAE,QAAQ,QACvD,+BAAC,SAAI,WAAU,qBAAoB,cAAY,aAC7C;AAAA,2BAAC,SAAI,WAAU,0BACZ;AAAA,UAAE,QAAQ,oBAAC,UAAK,eAAW,MAAE,YAAE,MAAK;AAAA,QACrC,oBAAC,KAAE,MAAM,EAAE,MAAO,YAAE,OAAM;AAAA,SAC5B;AAAA,MACC,EAAE,eAAe,oBAAC,OAAG,YAAE,aAAY;AAAA,MACnC,EAAE,SAAS,EAAE,MAAM,SAAS,KAC3B,oBAAC,QAAG,cAAY,EAAE,OACf,YAAE,MAAM,IAAI,CAAC,MACZ,oBAAC,QACC,8BAAC,KAAE,MAAM,EAAE,MAAO,YAAE,OAAM,KADnB,EAAE,IAEX,CACD,GACH;AAAA,OAEJ,KAhBO,EAAE,EAiBX,CACD,GACH,GACF;AAAA,KACE,eAAe,YACf,oBAAC,WAAQ,SAAQ,MAAK,SAAO,MAAC,cAAY,OAAO,aAAa,UAAU,WAAW,YAAY,QAAQ,QACrG,+BAAC,SAAI,WAAU,cACZ;AAAA,qBACC,qBAAC,SAAI,WAAU,gBACb;AAAA,4BAAC,QAAG,WAAU,8BAA8B,sBAAY,OAAM;AAAA,QAC7D,YAAY;AAAA,SACf;AAAA,MAED,WACC,qBAAC,SAAI,WAAU,gBACb;AAAA,4BAAC,QAAG,WAAU,8BAA8B,kBAAQ,OAAM;AAAA,QAC1D,oBAAC,QAAK,OAAO,QAAQ,OAAO,QAAgB;AAAA,SAC9C;AAAA,OAEJ,GACF;AAAA,IAED,YACC,oBAAC,WAAQ,IAAG,aAAY,OAAO,SAAS,OAAO,aAAY,MAAK,SAAQ,MAAK,SAAO,MAClF,8BAAC,QAAK,OAAO,SAAS,OAAO,QAAgB,GAC/C;AAAA,IAED,WACC,oBAAC,WAAQ,SAAQ,MAAK,cAAY,OAAO,QAAQ,UAAU,WAAW,QAAQ,QAAQ,QACpF,8BAAC,eAAY,SAAQ,WAAU,MAAK,OAAM,MAAK,WAAU,OAAO,QAAQ,OACrE,kBAAQ,MACX,GACF;AAAA,KAEJ;AAEJ;","names":[]}
@@ -0,0 +1,97 @@
1
+ import * as React from 'react';
2
+
3
+ /** How the nodes are placed around the hub. */
4
+ type FlowLayout = "radial" | "top-to-bottom" | "left-to-right";
5
+ /** The shape of a conduit: an S-shaped cubic Bézier, or a straight line. */
6
+ type FlowConduit = "bezier" | "straight";
7
+ interface FlowPoint {
8
+ x: number;
9
+ y: number;
10
+ }
11
+ interface FlowGeometry {
12
+ /** The box: 100 units wide, `height` units high (the stage keeps this aspect ratio, so nothing is distorted). */
13
+ width: number;
14
+ height: number;
15
+ hub: FlowPoint;
16
+ nodes: FlowPoint[];
17
+ /** One path per node, from the node to the hub. */
18
+ paths: string[];
19
+ /** The length of each path, in units. */
20
+ lengths: number[];
21
+ }
22
+ /** The box height per layout (the width is always 100). */
23
+ declare const FLOW_HEIGHT: Record<FlowLayout, number>;
24
+ /** The positions of `count` nodes around the hub. */
25
+ declare function flowPositions(layout: FlowLayout, count: number): {
26
+ hub: FlowPoint;
27
+ nodes: FlowPoint[];
28
+ };
29
+ /** The whole geometry of a flow: positions, conduits (node → hub) and their lengths. */
30
+ declare function flowGeometry(layout: FlowLayout, count: number, conduit?: FlowConduit): FlowGeometry;
31
+
32
+ interface EngineFlowNode {
33
+ /** A stable id (`orochia`). */
34
+ id: string;
35
+ /** Its name, the button's accessible name ("Orochia"). */
36
+ label: string;
37
+ /** Its mark (a `ProductLogo`), decorative. */
38
+ mark?: React.ReactNode;
39
+ /** One line: what it uses the engine for — shown when the node is pointed at or focused. */
40
+ description?: React.ReactNode;
41
+ /** Where it lives (its site). */
42
+ href?: string;
43
+ /** The link's words ("Visit dev.orochia.com"); defaults to the label. */
44
+ linkLabel?: React.ReactNode;
45
+ /** Opens the link in a new tab. */
46
+ external?: boolean;
47
+ /** What travels: `in` towards the hub, `out` back from it, `both`.
48
+ * @default "in" */
49
+ flow?: "in" | "out" | "both";
50
+ /** Not wired yet: drawn dim, its conduit dashed and still, no photon. */
51
+ planned?: boolean;
52
+ /** A word beside the name in the detail line ("planned"), passed translated. */
53
+ status?: React.ReactNode;
54
+ /** Its brand scope (`brand-orochia`): its conduit, photons and ring take its `--kz-accent`. */
55
+ className?: string;
56
+ }
57
+ interface EngineFlowHub {
58
+ /** The engine's name ("Orazaka"). */
59
+ label: string;
60
+ /** Its mark, decorative. */
61
+ mark?: React.ReactNode;
62
+ /** A line under the name ("the engine"). */
63
+ caption?: React.ReactNode;
64
+ /** Its brand scope; the photons coming back take its accent. */
65
+ className?: string;
66
+ }
67
+ type EngineFlowProps = Omit<React.ComponentProps<"figure">, "children"> & {
68
+ /** What the figure shows ("Orazaka and the products it powers"), passed translated. */
69
+ label: string;
70
+ /** The engine, at the hub. */
71
+ hub: EngineFlowHub;
72
+ /** The apps around it. */
73
+ nodes: readonly EngineFlowNode[];
74
+ /** How the nodes sit around the hub.
75
+ * @default "radial" */
76
+ layout?: FlowLayout;
77
+ /** The layout under a 560 px wide container (a phone); `false` keeps `layout` everywhere.
78
+ * @default "top-to-bottom" */
79
+ compactLayout?: FlowLayout | false;
80
+ /** `photons` travel the conduits; `none` draws them still.
81
+ * @default "photons" */
82
+ particles?: "photons" | "none";
83
+ /** The conduits' shape.
84
+ * @default "bezier" */
85
+ conduit?: FlowConduit;
86
+ /** The detail line before a node is chosen ("Point at a product"). */
87
+ hint?: React.ReactNode;
88
+ /** The node shown in the detail line at first. */
89
+ defaultActive?: string;
90
+ /** Photon speed, in units per second (the stage is 100 units wide).
91
+ * @default 16 */
92
+ speed?: number;
93
+ };
94
+ /** An engine at the hub and the apps it serves, with what travels between them. */
95
+ declare function EngineFlow({ label, hub, nodes, layout, compactLayout, particles, conduit, hint, defaultActive, speed, className, ...props }: EngineFlowProps): React.JSX.Element;
96
+
97
+ export { EngineFlow, type EngineFlowHub, type EngineFlowNode, type EngineFlowProps, FLOW_HEIGHT, type FlowConduit, type FlowGeometry, type FlowLayout, type FlowPoint, flowGeometry, flowPositions };
@@ -0,0 +1,214 @@
1
+ "use client";
2
+ import {
3
+ cn
4
+ } from "./chunk-NSLXEDIS.js";
5
+
6
+ // src/engine-flow/engine-flow.tsx
7
+ import * as React from "react";
8
+
9
+ // src/engine-flow/geometry.ts
10
+ var FLOW_HEIGHT = { radial: 60, "top-to-bottom": 92, "left-to-right": 56 };
11
+ var r2 = (n) => Math.round(n * 100) / 100;
12
+ var pt = (p) => `${r2(p.x)} ${r2(p.y)}`;
13
+ function cubicLength(a, b, c, d) {
14
+ let length = 0;
15
+ let prev = a;
16
+ for (let i = 1; i <= 32; i++) {
17
+ const t = i / 32;
18
+ const u = 1 - t;
19
+ const p = {
20
+ x: u * u * u * a.x + 3 * u * u * t * b.x + 3 * u * t * t * c.x + t * t * t * d.x,
21
+ y: u * u * u * a.y + 3 * u * u * t * b.y + 3 * u * t * t * c.y + t * t * t * d.y
22
+ };
23
+ length += Math.hypot(p.x - prev.x, p.y - prev.y);
24
+ prev = p;
25
+ }
26
+ return length;
27
+ }
28
+ function flowPositions(layout, count) {
29
+ const height = FLOW_HEIGHT[layout];
30
+ const n = Math.max(0, count);
31
+ if (layout === "top-to-bottom") {
32
+ return { hub: { x: 50, y: 72 }, nodes: Array.from({ length: n }, (_, i) => ({ x: (i + 0.5) * 100 / n, y: 13 })) };
33
+ }
34
+ if (layout === "left-to-right") {
35
+ return { hub: { x: 80, y: height / 2 }, nodes: Array.from({ length: n }, (_, i) => ({ x: 12, y: (i + 0.5) * height / n })) };
36
+ }
37
+ const hub = { x: 50, y: height / 2 };
38
+ const start = n % 2 === 0 ? -90 + 180 / Math.max(n, 1) : -90;
39
+ return {
40
+ hub,
41
+ nodes: Array.from({ length: n }, (_, i) => {
42
+ const a = (start + 360 / n * i) * Math.PI / 180;
43
+ return { x: hub.x + 37 * Math.cos(a), y: hub.y + 20 * Math.sin(a) };
44
+ })
45
+ };
46
+ }
47
+ function flowGeometry(layout, count, conduit = "bezier") {
48
+ const { hub, nodes } = flowPositions(layout, count);
49
+ const paths = [];
50
+ const lengths = [];
51
+ for (const p of nodes) {
52
+ const end = layout === "top-to-bottom" ? { x: hub.x + (p.x - hub.x) * 0.18, y: hub.y } : layout === "left-to-right" ? { x: hub.x, y: hub.y + (p.y - hub.y) * 0.18 } : hub;
53
+ if (conduit === "straight") {
54
+ paths.push(`M${pt(p)} L${pt(end)}`);
55
+ lengths.push(Math.hypot(end.x - p.x, end.y - p.y));
56
+ continue;
57
+ }
58
+ let c1;
59
+ let c2;
60
+ if (layout === "top-to-bottom") {
61
+ const mid = (p.y + end.y) / 2;
62
+ c1 = { x: p.x, y: mid };
63
+ c2 = { x: end.x, y: mid };
64
+ } else if (layout === "left-to-right") {
65
+ const mid = (p.x + end.x) / 2;
66
+ c1 = { x: mid, y: p.y };
67
+ c2 = { x: mid, y: end.y };
68
+ } else {
69
+ const dx = end.x - p.x;
70
+ const dy = end.y - p.y;
71
+ const len = Math.hypot(dx, dy) || 1;
72
+ const k = 0.14 * len;
73
+ const nx = -dy / len;
74
+ const ny = dx / len;
75
+ c1 = { x: p.x + dx * 0.35 + nx * k, y: p.y + dy * 0.35 + ny * k };
76
+ c2 = { x: p.x + dx * 0.65 - nx * k, y: p.y + dy * 0.65 - ny * k };
77
+ }
78
+ paths.push(`M${pt(p)} C${pt(c1)} ${pt(c2)} ${pt(end)}`);
79
+ lengths.push(cubicLength(p, c1, c2, end));
80
+ }
81
+ return { width: 100, height: FLOW_HEIGHT[layout], hub, nodes, paths, lengths };
82
+ }
83
+
84
+ // src/engine-flow/engine-flow.tsx
85
+ import { Fragment as Fragment2, jsx, jsxs } from "react/jsx-runtime";
86
+ function Stage({
87
+ layout,
88
+ variant,
89
+ nodes,
90
+ hub,
91
+ conduit,
92
+ particles,
93
+ speed,
94
+ active,
95
+ onActive,
96
+ detailId
97
+ }) {
98
+ const g = flowGeometry(layout, nodes.length, conduit);
99
+ const pct = (v, of) => `${(v / of * 100).toFixed(3)}%`;
100
+ return /* @__PURE__ */ jsxs("div", { className: "kz-flow-stage", "data-variant": variant, "data-layout": layout, style: { aspectRatio: `${g.width} / ${g.height}` }, children: [
101
+ /* @__PURE__ */ jsx("svg", { viewBox: `0 0 ${g.width} ${g.height}`, "aria-hidden": "true", focusable: "false", children: nodes.map((node, i) => {
102
+ const flow = node.flow ?? "in";
103
+ const length = g.lengths[i] ?? 0;
104
+ const gap = length / Math.min(4, Math.max(2, Math.round(length / 16)));
105
+ const timing = (dir) => ({
106
+ "--kz-flow-gap": gap.toFixed(3),
107
+ animationDuration: `${(gap / speed).toFixed(2)}s`,
108
+ animationDelay: `${(-((i * 0.37 + (dir === "out" ? 0.5 : 0)) % 1) * (gap / speed)).toFixed(2)}s`
109
+ });
110
+ const lanes = node.planned || particles === "none" ? [] : flow === "both" ? ["in", "out"] : [flow];
111
+ return /* @__PURE__ */ jsxs(
112
+ "g",
113
+ {
114
+ className: cn("kz-flow-link", node.className),
115
+ "data-flow": flow,
116
+ "data-planned": node.planned ? "" : void 0,
117
+ "data-active": active === node.id ? "" : void 0,
118
+ children: [
119
+ /* @__PURE__ */ jsx("path", { className: "kz-flow-wire", d: g.paths[i] }),
120
+ lanes.map((dir) => /* @__PURE__ */ jsxs(React.Fragment, { children: [
121
+ /* @__PURE__ */ jsx("path", { className: "kz-flow-photon kz-loop", "data-dir": dir, "data-halo": "", d: g.paths[i], style: timing(dir) }),
122
+ /* @__PURE__ */ jsx("path", { className: "kz-flow-photon kz-loop", "data-dir": dir, d: g.paths[i], style: timing(dir) })
123
+ ] }, dir))
124
+ ]
125
+ },
126
+ node.id
127
+ );
128
+ }) }),
129
+ /* @__PURE__ */ jsxs("div", { className: cn("kz-flow-hub", hub.className), style: { left: pct(g.hub.x, g.width), top: pct(g.hub.y, g.height) }, children: [
130
+ hub.mark ? /* @__PURE__ */ jsx("span", { className: "kz-flow-hub-mark", children: hub.mark }) : null,
131
+ /* @__PURE__ */ jsx("span", { className: "kz-flow-hub-label", children: hub.label }),
132
+ hub.caption ? /* @__PURE__ */ jsx("span", { className: "kz-flow-hub-caption", children: hub.caption }) : null
133
+ ] }),
134
+ /* @__PURE__ */ jsx("ul", { className: "kz-flow-nodes", children: nodes.map((node, i) => {
135
+ const p = g.nodes[i];
136
+ const on = active === node.id;
137
+ return /* @__PURE__ */ jsx("li", { style: { left: pct(p.x, g.width), top: pct(p.y, g.height) }, children: /* @__PURE__ */ jsxs(
138
+ "button",
139
+ {
140
+ type: "button",
141
+ className: cn("kz-flow-node", node.className),
142
+ "data-active": on ? "" : void 0,
143
+ "data-planned": node.planned ? "" : void 0,
144
+ "aria-pressed": on,
145
+ "aria-controls": detailId,
146
+ onPointerEnter: () => onActive(node.id),
147
+ onFocus: () => onActive(node.id),
148
+ onClick: () => onActive(node.id),
149
+ children: [
150
+ node.mark ? /* @__PURE__ */ jsx("span", { className: "kz-flow-node-mark", "aria-hidden": "true", children: node.mark }) : null,
151
+ /* @__PURE__ */ jsx("span", { className: "kz-flow-node-label", children: node.label })
152
+ ]
153
+ }
154
+ ) }, node.id);
155
+ }) })
156
+ ] });
157
+ }
158
+ function EngineFlow({
159
+ label,
160
+ hub,
161
+ nodes,
162
+ layout = "radial",
163
+ compactLayout = "top-to-bottom",
164
+ particles = "photons",
165
+ conduit = "bezier",
166
+ hint,
167
+ defaultActive,
168
+ speed = 16,
169
+ className,
170
+ ...props
171
+ }) {
172
+ const [active, setActive] = React.useState(defaultActive);
173
+ const detailId = `${React.useId()}-detail`;
174
+ const chosen = nodes.find((n) => n.id === active);
175
+ const compact = compactLayout && compactLayout !== layout ? compactLayout : void 0;
176
+ const stage = { nodes, hub, conduit, particles, speed: Math.max(1, speed), active, onActive: setActive, detailId };
177
+ return /* @__PURE__ */ jsxs(
178
+ "figure",
179
+ {
180
+ "aria-label": label,
181
+ className: cn("kz-flow", className),
182
+ "data-motion-scope": "",
183
+ "data-active": chosen ? "" : void 0,
184
+ "data-compact": compact ? "" : void 0,
185
+ ...props,
186
+ children: [
187
+ /* @__PURE__ */ jsx(Stage, { layout, variant: "wide", ...stage }),
188
+ compact ? /* @__PURE__ */ jsx(Stage, { layout: compact, variant: "compact", ...stage }) : null,
189
+ /* @__PURE__ */ jsx("figcaption", { id: detailId, className: cn("kz-flow-detail", chosen?.className), "aria-live": "polite", children: chosen ? /* @__PURE__ */ jsxs(Fragment2, { children: [
190
+ /* @__PURE__ */ jsx("strong", { children: chosen.label }),
191
+ chosen.status ? /* @__PURE__ */ jsx("span", { className: "kz-flow-status", children: chosen.status }) : null,
192
+ chosen.description ? /* @__PURE__ */ jsxs("span", { children: [
193
+ " ",
194
+ chosen.description
195
+ ] }) : null,
196
+ chosen.href ? /* @__PURE__ */ jsxs(Fragment2, { children: [
197
+ " ",
198
+ /* @__PURE__ */ jsxs("a", { href: chosen.href, ...chosen.external ? { target: "_blank", rel: "noopener" } : {}, children: [
199
+ chosen.linkLabel ?? chosen.label,
200
+ /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: " \u2192" })
201
+ ] })
202
+ ] }) : null
203
+ ] }) : hint })
204
+ ]
205
+ }
206
+ );
207
+ }
208
+ export {
209
+ EngineFlow,
210
+ FLOW_HEIGHT,
211
+ flowGeometry,
212
+ flowPositions
213
+ };
214
+ //# sourceMappingURL=engine-flow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/engine-flow/engine-flow.tsx","../src/engine-flow/geometry.ts"],"sourcesContent":["// Client (the node a visitor points at or focuses). An engine at the hub and the apps it serves around it: one conduit\n// per app, and photons that travel it — towards the hub (`in`: requests), back (`out`: results) or both — in the app's\n// brand colour going in and the hub's coming back. A planned app is drawn dim, its conduit dashed and still.\n//\n// Motion is the Krizaka signature's (motion.css): CSS animations of `stroke-dashoffset`, no animation frame, no canvas;\n// paused off screen (`data-motion-scope` → MotionObserver's `data-offscreen`), held while the page settles (`kz-loop`),\n// a still frame under reduced motion (the photons rest along their conduit). The stage keeps its aspect ratio and the\n// detail line its height: no layout shift.\n//\n// Accessible: the drawing is hidden from assistive technology; every node is a real button named by its label, and the\n// detail line (polite live region) says the chosen node's description with its link. Pair it with a text version (a\n// list) in the page: the figure is a picture of it.\nimport * as React from \"react\";\n\nimport { cn } from \"../cn\";\nimport { type FlowConduit, flowGeometry, type FlowLayout } from \"./geometry\";\n\nexport interface EngineFlowNode {\n /** A stable id (`orochia`). */\n id: string;\n /** Its name, the button's accessible name (\"Orochia\"). */\n label: string;\n /** Its mark (a `ProductLogo`), decorative. */\n mark?: React.ReactNode;\n /** One line: what it uses the engine for — shown when the node is pointed at or focused. */\n description?: React.ReactNode;\n /** Where it lives (its site). */\n href?: string;\n /** The link's words (\"Visit dev.orochia.com\"); defaults to the label. */\n linkLabel?: React.ReactNode;\n /** Opens the link in a new tab. */\n external?: boolean;\n /** What travels: `in` towards the hub, `out` back from it, `both`.\n * @default \"in\" */\n flow?: \"in\" | \"out\" | \"both\";\n /** Not wired yet: drawn dim, its conduit dashed and still, no photon. */\n planned?: boolean;\n /** A word beside the name in the detail line (\"planned\"), passed translated. */\n status?: React.ReactNode;\n /** Its brand scope (`brand-orochia`): its conduit, photons and ring take its `--kz-accent`. */\n className?: string;\n}\n\nexport interface EngineFlowHub {\n /** The engine's name (\"Orazaka\"). */\n label: string;\n /** Its mark, decorative. */\n mark?: React.ReactNode;\n /** A line under the name (\"the engine\"). */\n caption?: React.ReactNode;\n /** Its brand scope; the photons coming back take its accent. */\n className?: string;\n}\n\nexport type EngineFlowProps = Omit<React.ComponentProps<\"figure\">, \"children\"> & {\n /** What the figure shows (\"Orazaka and the products it powers\"), passed translated. */\n label: string;\n /** The engine, at the hub. */\n hub: EngineFlowHub;\n /** The apps around it. */\n nodes: readonly EngineFlowNode[];\n /** How the nodes sit around the hub.\n * @default \"radial\" */\n layout?: FlowLayout;\n /** The layout under a 560 px wide container (a phone); `false` keeps `layout` everywhere.\n * @default \"top-to-bottom\" */\n compactLayout?: FlowLayout | false;\n /** `photons` travel the conduits; `none` draws them still.\n * @default \"photons\" */\n particles?: \"photons\" | \"none\";\n /** The conduits' shape.\n * @default \"bezier\" */\n conduit?: FlowConduit;\n /** The detail line before a node is chosen (\"Point at a product\"). */\n hint?: React.ReactNode;\n /** The node shown in the detail line at first. */\n defaultActive?: string;\n /** Photon speed, in units per second (the stage is 100 units wide).\n * @default 16 */\n speed?: number;\n};\n\nfunction Stage({\n layout,\n variant,\n nodes,\n hub,\n conduit,\n particles,\n speed,\n active,\n onActive,\n detailId,\n}: {\n layout: FlowLayout;\n variant: \"wide\" | \"compact\";\n nodes: readonly EngineFlowNode[];\n hub: EngineFlowHub;\n conduit: FlowConduit;\n particles: \"photons\" | \"none\";\n speed: number;\n active: string | undefined;\n onActive: (id: string) => void;\n detailId: string;\n}) {\n const g = flowGeometry(layout, nodes.length, conduit);\n const pct = (v: number, of: number) => `${((v / of) * 100).toFixed(3)}%`;\n return (\n <div className=\"kz-flow-stage\" data-variant={variant} data-layout={layout} style={{ aspectRatio: `${g.width} / ${g.height}` }}>\n <svg viewBox={`0 0 ${g.width} ${g.height}`} aria-hidden=\"true\" focusable=\"false\">\n {nodes.map((node, i) => {\n const flow = node.flow ?? \"in\";\n const length = g.lengths[i] ?? 0;\n // Two to four photons per conduit, evenly spaced; the same speed on every conduit.\n const gap = length / Math.min(4, Math.max(2, Math.round(length / 16)));\n const timing = (dir: \"in\" | \"out\") =>\n ({\n \"--kz-flow-gap\": gap.toFixed(3),\n animationDuration: `${(gap / speed).toFixed(2)}s`,\n animationDelay: `${(-((i * 0.37 + (dir === \"out\" ? 0.5 : 0)) % 1) * (gap / speed)).toFixed(2)}s`,\n }) as React.CSSProperties;\n const lanes = node.planned || particles === \"none\" ? [] : flow === \"both\" ? ([\"in\", \"out\"] as const) : [flow];\n return (\n <g\n key={node.id}\n className={cn(\"kz-flow-link\", node.className)}\n data-flow={flow}\n data-planned={node.planned ? \"\" : undefined}\n data-active={active === node.id ? \"\" : undefined}\n >\n <path className=\"kz-flow-wire\" d={g.paths[i]} />\n {lanes.map((dir) => (\n <React.Fragment key={dir}>\n <path className=\"kz-flow-photon kz-loop\" data-dir={dir} data-halo=\"\" d={g.paths[i]} style={timing(dir)} />\n <path className=\"kz-flow-photon kz-loop\" data-dir={dir} d={g.paths[i]} style={timing(dir)} />\n </React.Fragment>\n ))}\n </g>\n );\n })}\n </svg>\n <div className={cn(\"kz-flow-hub\", hub.className)} style={{ left: pct(g.hub.x, g.width), top: pct(g.hub.y, g.height) }}>\n {hub.mark ? <span className=\"kz-flow-hub-mark\">{hub.mark}</span> : null}\n <span className=\"kz-flow-hub-label\">{hub.label}</span>\n {hub.caption ? <span className=\"kz-flow-hub-caption\">{hub.caption}</span> : null}\n </div>\n <ul className=\"kz-flow-nodes\">\n {nodes.map((node, i) => {\n const p = g.nodes[i]!;\n const on = active === node.id;\n return (\n <li key={node.id} style={{ left: pct(p.x, g.width), top: pct(p.y, g.height) }}>\n <button\n type=\"button\"\n className={cn(\"kz-flow-node\", node.className)}\n data-active={on ? \"\" : undefined}\n data-planned={node.planned ? \"\" : undefined}\n aria-pressed={on}\n aria-controls={detailId}\n onPointerEnter={() => onActive(node.id)}\n onFocus={() => onActive(node.id)}\n onClick={() => onActive(node.id)}\n >\n {node.mark ? (\n <span className=\"kz-flow-node-mark\" aria-hidden=\"true\">\n {node.mark}\n </span>\n ) : null}\n <span className=\"kz-flow-node-label\">{node.label}</span>\n </button>\n </li>\n );\n })}\n </ul>\n </div>\n );\n}\n\n/** An engine at the hub and the apps it serves, with what travels between them. */\nexport function EngineFlow({\n label,\n hub,\n nodes,\n layout = \"radial\",\n compactLayout = \"top-to-bottom\",\n particles = \"photons\",\n conduit = \"bezier\",\n hint,\n defaultActive,\n speed = 16,\n className,\n ...props\n}: EngineFlowProps) {\n const [active, setActive] = React.useState<string | undefined>(defaultActive);\n const detailId = `${React.useId()}-detail`;\n const chosen = nodes.find((n) => n.id === active);\n const compact = compactLayout && compactLayout !== layout ? compactLayout : undefined;\n const stage = { nodes, hub, conduit, particles, speed: Math.max(1, speed), active, onActive: setActive, detailId };\n return (\n <figure\n aria-label={label}\n className={cn(\"kz-flow\", className)}\n data-motion-scope=\"\"\n data-active={chosen ? \"\" : undefined}\n data-compact={compact ? \"\" : undefined}\n {...props}\n >\n <Stage layout={layout} variant=\"wide\" {...stage} />\n {compact ? <Stage layout={compact} variant=\"compact\" {...stage} /> : null}\n <figcaption id={detailId} className={cn(\"kz-flow-detail\", chosen?.className)} aria-live=\"polite\">\n {chosen ? (\n <>\n <strong>{chosen.label}</strong>\n {chosen.status ? <span className=\"kz-flow-status\">{chosen.status}</span> : null}\n {chosen.description ? <span> {chosen.description}</span> : null}\n {chosen.href ? (\n <>\n {\" \"}\n <a href={chosen.href} {...(chosen.external ? { target: \"_blank\", rel: \"noopener\" } : {})}>\n {chosen.linkLabel ?? chosen.label}\n <span aria-hidden=\"true\"> →</span>\n </a>\n </>\n ) : null}\n </>\n ) : (\n hint\n )}\n </figcaption>\n </figure>\n );\n}\n","// Server-safe, pure. The geometry of EngineFlow: where the hub and the nodes sit in a box 100 units wide, and the\n// conduit from each node to the hub (an SVG path drawn node → hub, and its length, so photons travel at one speed on\n// every conduit). No DOM: the same numbers on the server and in the browser.\n\n/** How the nodes are placed around the hub. */\nexport type FlowLayout = \"radial\" | \"top-to-bottom\" | \"left-to-right\";\n/** The shape of a conduit: an S-shaped cubic Bézier, or a straight line. */\nexport type FlowConduit = \"bezier\" | \"straight\";\n\nexport interface FlowPoint {\n x: number;\n y: number;\n}\n\nexport interface FlowGeometry {\n /** The box: 100 units wide, `height` units high (the stage keeps this aspect ratio, so nothing is distorted). */\n width: number;\n height: number;\n hub: FlowPoint;\n nodes: FlowPoint[];\n /** One path per node, from the node to the hub. */\n paths: string[];\n /** The length of each path, in units. */\n lengths: number[];\n}\n\n/** The box height per layout (the width is always 100). */\nexport const FLOW_HEIGHT: Record<FlowLayout, number> = { radial: 60, \"top-to-bottom\": 92, \"left-to-right\": 56 };\n\nconst r2 = (n: number) => Math.round(n * 100) / 100;\nconst pt = (p: FlowPoint) => `${r2(p.x)} ${r2(p.y)}`;\n\nfunction cubicLength(a: FlowPoint, b: FlowPoint, c: FlowPoint, d: FlowPoint): number {\n let length = 0;\n let prev = a;\n for (let i = 1; i <= 32; i++) {\n const t = i / 32;\n const u = 1 - t;\n const p = {\n x: u * u * u * a.x + 3 * u * u * t * b.x + 3 * u * t * t * c.x + t * t * t * d.x,\n y: u * u * u * a.y + 3 * u * u * t * b.y + 3 * u * t * t * c.y + t * t * t * d.y,\n };\n length += Math.hypot(p.x - prev.x, p.y - prev.y);\n prev = p;\n }\n return length;\n}\n\n/** The positions of `count` nodes around the hub. */\nexport function flowPositions(layout: FlowLayout, count: number): { hub: FlowPoint; nodes: FlowPoint[] } {\n const height = FLOW_HEIGHT[layout];\n const n = Math.max(0, count);\n if (layout === \"top-to-bottom\") {\n return { hub: { x: 50, y: 72 }, nodes: Array.from({ length: n }, (_, i) => ({ x: ((i + 0.5) * 100) / n, y: 13 })) };\n }\n if (layout === \"left-to-right\") {\n return { hub: { x: 80, y: height / 2 }, nodes: Array.from({ length: n }, (_, i) => ({ x: 12, y: ((i + 0.5) * height) / n })) };\n }\n // Radial: on an ellipse around the centre; an even count puts two nodes level with the hub (more room for labels).\n const hub = { x: 50, y: height / 2 };\n const start = n % 2 === 0 ? -90 + 180 / Math.max(n, 1) : -90;\n return {\n hub,\n nodes: Array.from({ length: n }, (_, i) => {\n const a = ((start + (360 / n) * i) * Math.PI) / 180;\n return { x: hub.x + 37 * Math.cos(a), y: hub.y + 20 * Math.sin(a) };\n }),\n };\n}\n\n/** The whole geometry of a flow: positions, conduits (node → hub) and their lengths. */\nexport function flowGeometry(layout: FlowLayout, count: number, conduit: FlowConduit = \"bezier\"): FlowGeometry {\n const { hub, nodes } = flowPositions(layout, count);\n const paths: string[] = [];\n const lengths: number[] = [];\n for (const p of nodes) {\n // Each conduit lands on its own point of the hub (a fan), so the lines stay apart where they meet.\n const end =\n layout === \"top-to-bottom\"\n ? { x: hub.x + (p.x - hub.x) * 0.18, y: hub.y }\n : layout === \"left-to-right\"\n ? { x: hub.x, y: hub.y + (p.y - hub.y) * 0.18 }\n : hub;\n if (conduit === \"straight\") {\n paths.push(`M${pt(p)} L${pt(end)}`);\n lengths.push(Math.hypot(end.x - p.x, end.y - p.y));\n continue;\n }\n let c1: FlowPoint;\n let c2: FlowPoint;\n if (layout === \"top-to-bottom\") {\n const mid = (p.y + end.y) / 2;\n c1 = { x: p.x, y: mid };\n c2 = { x: end.x, y: mid };\n } else if (layout === \"left-to-right\") {\n const mid = (p.x + end.x) / 2;\n c1 = { x: mid, y: p.y };\n c2 = { x: mid, y: end.y };\n } else {\n // An S: leave the node bending one way, reach the hub bending the other.\n const dx = end.x - p.x;\n const dy = end.y - p.y;\n const len = Math.hypot(dx, dy) || 1;\n const k = 0.14 * len;\n const nx = -dy / len;\n const ny = dx / len;\n c1 = { x: p.x + dx * 0.35 + nx * k, y: p.y + dy * 0.35 + ny * k };\n c2 = { x: p.x + dx * 0.65 - nx * k, y: p.y + dy * 0.65 - ny * k };\n }\n paths.push(`M${pt(p)} C${pt(c1)} ${pt(c2)} ${pt(end)}`);\n lengths.push(cubicLength(p, c1, c2, end));\n }\n return { width: 100, height: FLOW_HEIGHT[layout], hub, nodes, paths, lengths };\n}\n"],"mappings":"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","names":["Fragment"]}