@rtkelly-labs/design-system 0.0.0-bootstrap.0 → 0.16.0-dev.0.37dedac

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 (284) hide show
  1. package/CHANGELOG.md +347 -0
  2. package/LICENSE +21 -0
  3. package/README.md +317 -2
  4. package/dist/components/AlertDialog.js +95 -0
  5. package/dist/components/AlertDialog.js.map +1 -0
  6. package/dist/components/AppShell.js +261 -0
  7. package/dist/components/AppShell.js.map +1 -0
  8. package/dist/components/AsciiDivider.js +8 -0
  9. package/dist/components/AsciiDivider.js.map +1 -0
  10. package/dist/components/AsciiGauge.js +130 -0
  11. package/dist/components/AsciiGauge.js.map +1 -0
  12. package/dist/components/Avatar.js +87 -0
  13. package/dist/components/Avatar.js.map +1 -0
  14. package/dist/components/Badge.js +25 -0
  15. package/dist/components/Badge.js.map +1 -0
  16. package/dist/components/BarChart.js +288 -0
  17. package/dist/components/BarChart.js.map +1 -0
  18. package/dist/components/BracketText.js +23 -0
  19. package/dist/components/BracketText.js.map +1 -0
  20. package/dist/components/BulletChart.js +50 -0
  21. package/dist/components/BulletChart.js.map +1 -0
  22. package/dist/components/Button.js +130 -0
  23. package/dist/components/Button.js.map +1 -0
  24. package/dist/components/Card.js +181 -0
  25. package/dist/components/Card.js.map +1 -0
  26. package/dist/components/ChartTooltip.js +54 -0
  27. package/dist/components/ChartTooltip.js.map +1 -0
  28. package/dist/components/Checkbox.js +55 -0
  29. package/dist/components/Checkbox.js.map +1 -0
  30. package/dist/components/ColophonCard.js +122 -0
  31. package/dist/components/ColophonCard.js.map +1 -0
  32. package/dist/components/DataTable.js +299 -0
  33. package/dist/components/DataTable.js.map +1 -0
  34. package/dist/components/Divider.js +42 -0
  35. package/dist/components/Divider.js.map +1 -0
  36. package/dist/components/Drawer.js +81 -0
  37. package/dist/components/Drawer.js.map +1 -0
  38. package/dist/components/EmptyState.js +39 -0
  39. package/dist/components/EmptyState.js.map +1 -0
  40. package/dist/components/ErrorSummary.js +122 -0
  41. package/dist/components/ErrorSummary.js.map +1 -0
  42. package/dist/components/Fieldset.js +37 -0
  43. package/dist/components/Fieldset.js.map +1 -0
  44. package/dist/components/Glyph.js +60 -0
  45. package/dist/components/Glyph.js.map +1 -0
  46. package/dist/components/Input.js +111 -0
  47. package/dist/components/Input.js.map +1 -0
  48. package/dist/components/LinkProvider.js +76 -0
  49. package/dist/components/LinkProvider.js.map +1 -0
  50. package/dist/components/Menu.js +144 -0
  51. package/dist/components/Menu.js.map +1 -0
  52. package/dist/components/MetadataGrid.js +184 -0
  53. package/dist/components/MetadataGrid.js.map +1 -0
  54. package/dist/components/MobileNav.js +120 -0
  55. package/dist/components/MobileNav.js.map +1 -0
  56. package/dist/components/Modal.js +79 -0
  57. package/dist/components/Modal.js.map +1 -0
  58. package/dist/components/NerdIcon.js +177 -0
  59. package/dist/components/NerdIcon.js.map +1 -0
  60. package/dist/components/NoteBlock.js +84 -0
  61. package/dist/components/NoteBlock.js.map +1 -0
  62. package/dist/components/PageHeader.js +34 -0
  63. package/dist/components/PageHeader.js.map +1 -0
  64. package/dist/components/PageTitle.js +21 -0
  65. package/dist/components/PageTitle.js.map +1 -0
  66. package/dist/components/Pagination.js +96 -0
  67. package/dist/components/Pagination.js.map +1 -0
  68. package/dist/components/Popover.js +87 -0
  69. package/dist/components/Popover.js.map +1 -0
  70. package/dist/components/Progress.js +83 -0
  71. package/dist/components/Progress.js.map +1 -0
  72. package/dist/components/RadioGroup.js +74 -0
  73. package/dist/components/RadioGroup.js.map +1 -0
  74. package/dist/components/ReportDocument.js +75 -0
  75. package/dist/components/ReportDocument.js.map +1 -0
  76. package/dist/components/SectionContainer.js +18 -0
  77. package/dist/components/SectionContainer.js.map +1 -0
  78. package/dist/components/Select.js +199 -0
  79. package/dist/components/Select.js.map +1 -0
  80. package/dist/components/SiteFooter.js +29 -0
  81. package/dist/components/SiteFooter.js.map +1 -0
  82. package/dist/components/SiteHeader.js +59 -0
  83. package/dist/components/SiteHeader.js.map +1 -0
  84. package/dist/components/SiteNav.js +141 -0
  85. package/dist/components/SiteNav.js.map +1 -0
  86. package/dist/components/Skeleton.js +51 -0
  87. package/dist/components/Skeleton.js.map +1 -0
  88. package/dist/components/SocialIcon.js +77 -0
  89. package/dist/components/SocialIcon.js.map +1 -0
  90. package/dist/components/Sparkline.js +104 -0
  91. package/dist/components/Sparkline.js.map +1 -0
  92. package/dist/components/Spinner.js +65 -0
  93. package/dist/components/Spinner.js.map +1 -0
  94. package/dist/components/StatCard.js +53 -0
  95. package/dist/components/StatCard.js.map +1 -0
  96. package/dist/components/StatusPage.js +99 -0
  97. package/dist/components/StatusPage.js.map +1 -0
  98. package/dist/components/Swatch.js +55 -0
  99. package/dist/components/Swatch.js.map +1 -0
  100. package/dist/components/Switch.js +53 -0
  101. package/dist/components/Switch.js.map +1 -0
  102. package/dist/components/TLDR.js +53 -0
  103. package/dist/components/TLDR.js.map +1 -0
  104. package/dist/components/Table.js +155 -0
  105. package/dist/components/Table.js.map +1 -0
  106. package/dist/components/Tabs.js +325 -0
  107. package/dist/components/Tabs.js.map +1 -0
  108. package/dist/components/Tag.js +19 -0
  109. package/dist/components/Tag.js.map +1 -0
  110. package/dist/components/TelemetryGauge.js +112 -0
  111. package/dist/components/TelemetryGauge.js.map +1 -0
  112. package/dist/components/ThemeProvider.js +87 -0
  113. package/dist/components/ThemeProvider.js.map +1 -0
  114. package/dist/components/TickerTape.js +196 -0
  115. package/dist/components/TickerTape.js.map +1 -0
  116. package/dist/components/Toast.js +200 -0
  117. package/dist/components/Toast.js.map +1 -0
  118. package/dist/components/Tooltip.js +69 -0
  119. package/dist/components/Tooltip.js.map +1 -0
  120. package/dist/components/TrackCard.js +206 -0
  121. package/dist/components/TrackCard.js.map +1 -0
  122. package/dist/components/blog/BlogPost.js +116 -0
  123. package/dist/components/blog/BlogPost.js.map +1 -0
  124. package/dist/components/blog/LoremIpsumPost.js +62 -0
  125. package/dist/components/blog/LoremIpsumPost.js.map +1 -0
  126. package/dist/components/blog/author.js +25 -0
  127. package/dist/components/blog/author.js.map +1 -0
  128. package/dist/components/booleanControl.js +50 -0
  129. package/dist/components/booleanControl.js.map +1 -0
  130. package/dist/components/dialogPopupRef.js +28 -0
  131. package/dist/components/dialogPopupRef.js.map +1 -0
  132. package/dist/components/dialogSurface.js +75 -0
  133. package/dist/components/dialogSurface.js.map +1 -0
  134. package/dist/components/docs/AnchorHeading.js +80 -0
  135. package/dist/components/docs/AnchorHeading.js.map +1 -0
  136. package/dist/components/docs/Breadcrumbs.js +26 -0
  137. package/dist/components/docs/Breadcrumbs.js.map +1 -0
  138. package/dist/components/docs/CodeBlock.js +63 -0
  139. package/dist/components/docs/CodeBlock.js.map +1 -0
  140. package/dist/components/docs/CodeTabs.js +71 -0
  141. package/dist/components/docs/CodeTabs.js.map +1 -0
  142. package/dist/components/docs/DocPager.js +28 -0
  143. package/dist/components/docs/DocPager.js.map +1 -0
  144. package/dist/components/docs/DocsHeader.js +124 -0
  145. package/dist/components/docs/DocsHeader.js.map +1 -0
  146. package/dist/components/docs/DocsLayout.js +61 -0
  147. package/dist/components/docs/DocsLayout.js.map +1 -0
  148. package/dist/components/docs/DocsLinkProvider.js +25 -0
  149. package/dist/components/docs/DocsLinkProvider.js.map +1 -0
  150. package/dist/components/docs/DocsSidebar.js +147 -0
  151. package/dist/components/docs/DocsSidebar.js.map +1 -0
  152. package/dist/components/docs/Prose.js +56 -0
  153. package/dist/components/docs/Prose.js.map +1 -0
  154. package/dist/components/docs/TableOfContents.js +71 -0
  155. package/dist/components/docs/TableOfContents.js.map +1 -0
  156. package/dist/components/docs/codeTabsStore.js +75 -0
  157. package/dist/components/docs/codeTabsStore.js.map +1 -0
  158. package/dist/components/docs/figures/ActivityGrid.js +116 -0
  159. package/dist/components/docs/figures/ActivityGrid.js.map +1 -0
  160. package/dist/components/docs/figures/BeforeAfter.js +64 -0
  161. package/dist/components/docs/figures/BeforeAfter.js.map +1 -0
  162. package/dist/components/docs/figures/ChangeSummary.js +74 -0
  163. package/dist/components/docs/figures/ChangeSummary.js.map +1 -0
  164. package/dist/components/docs/figures/Decision.js +34 -0
  165. package/dist/components/docs/figures/Decision.js.map +1 -0
  166. package/dist/components/docs/figures/DrawingSheet.js +37 -0
  167. package/dist/components/docs/figures/DrawingSheet.js.map +1 -0
  168. package/dist/components/docs/figures/FigureFrame.js +226 -0
  169. package/dist/components/docs/figures/FigureFrame.js.map +1 -0
  170. package/dist/components/docs/figures/FileChangeTree.js +134 -0
  171. package/dist/components/docs/figures/FileChangeTree.js.map +1 -0
  172. package/dist/components/docs/figures/FlowDiagram.js +82 -0
  173. package/dist/components/docs/figures/FlowDiagram.js.map +1 -0
  174. package/dist/components/docs/figures/GanttChart.js +79 -0
  175. package/dist/components/docs/figures/GanttChart.js.map +1 -0
  176. package/dist/components/docs/figures/IndexedSection.js +45 -0
  177. package/dist/components/docs/figures/IndexedSection.js.map +1 -0
  178. package/dist/components/docs/figures/MetricStrip.js +23 -0
  179. package/dist/components/docs/figures/MetricStrip.js.map +1 -0
  180. package/dist/components/docs/figures/Steps.js +58 -0
  181. package/dist/components/docs/figures/Steps.js.map +1 -0
  182. package/dist/components/docs/figures/SwatchCompare.js +42 -0
  183. package/dist/components/docs/figures/SwatchCompare.js.map +1 -0
  184. package/dist/components/docs/figures/TermGrid.js +22 -0
  185. package/dist/components/docs/figures/TermGrid.js.map +1 -0
  186. package/dist/components/docs/figures/Terminal.js +37 -0
  187. package/dist/components/docs/figures/Terminal.js.map +1 -0
  188. package/dist/components/docs/figures/Timeline.js +61 -0
  189. package/dist/components/docs/figures/Timeline.js.map +1 -0
  190. package/dist/components/docs/figures/TokenTable.js +42 -0
  191. package/dist/components/docs/figures/TokenTable.js.map +1 -0
  192. package/dist/components/docs/figures/TreeDiagram.js +76 -0
  193. package/dist/components/docs/figures/TreeDiagram.js.map +1 -0
  194. package/dist/components/docs/figures/UptimeStrip.js +68 -0
  195. package/dist/components/docs/figures/UptimeStrip.js.map +1 -0
  196. package/dist/components/docs/figures/index.js +24 -0
  197. package/dist/components/docs/figures/index.js.map +1 -0
  198. package/dist/components/docs/index.js +15 -0
  199. package/dist/components/docs/index.js.map +1 -0
  200. package/dist/components/docs/mdxComponents.js +108 -0
  201. package/dist/components/docs/mdxComponents.js.map +1 -0
  202. package/dist/components/experiments/DesignSandbox.js +206 -0
  203. package/dist/components/experiments/DesignSandbox.js.map +1 -0
  204. package/dist/components/experiments/ExperimentsView.js +138 -0
  205. package/dist/components/experiments/ExperimentsView.js.map +1 -0
  206. package/dist/components/fieldFrame.js +200 -0
  207. package/dist/components/fieldFrame.js.map +1 -0
  208. package/dist/components/floatingSurface.js +35 -0
  209. package/dist/components/floatingSurface.js.map +1 -0
  210. package/dist/components/marketing/CTASection.js +47 -0
  211. package/dist/components/marketing/CTASection.js.map +1 -0
  212. package/dist/components/marketing/FeatureGrid.js +49 -0
  213. package/dist/components/marketing/FeatureGrid.js.map +1 -0
  214. package/dist/components/marketing/Hero.js +44 -0
  215. package/dist/components/marketing/Hero.js.map +1 -0
  216. package/dist/components/marketing/PricingGrid.js +65 -0
  217. package/dist/components/marketing/PricingGrid.js.map +1 -0
  218. package/dist/components/marketing/SectionGrid.js +51 -0
  219. package/dist/components/marketing/SectionGrid.js.map +1 -0
  220. package/dist/components/paginationRange.js +28 -0
  221. package/dist/components/paginationRange.js.map +1 -0
  222. package/dist/components/portalTheme.js +14 -0
  223. package/dist/components/portalTheme.js.map +1 -0
  224. package/dist/components/saas/SaasLandingPage.js +201 -0
  225. package/dist/components/saas/SaasLandingPage.js.map +1 -0
  226. package/dist/components/siteNavContext.js +24 -0
  227. package/dist/components/siteNavContext.js.map +1 -0
  228. package/dist/components/slides/Slide.js +84 -0
  229. package/dist/components/slides/Slide.js.map +1 -0
  230. package/dist/components/slides/SlideDeck.js +228 -0
  231. package/dist/components/slides/SlideDeck.js.map +1 -0
  232. package/dist/components/themeInitScript.js +16 -0
  233. package/dist/components/themeInitScript.js.map +1 -0
  234. package/dist/components/themeScope.js +9 -0
  235. package/dist/components/themeScope.js.map +1 -0
  236. package/dist/components/toastLifetime.js +21 -0
  237. package/dist/components/toastLifetime.js.map +1 -0
  238. package/dist/fonts/DSSymbols-OFL.txt +98 -0
  239. package/dist/fonts/DSSymbols-Regular.woff2 +0 -0
  240. package/dist/fonts/SymbolsNerdFontMono-Regular.woff2 +0 -0
  241. package/dist/hooks/useActiveHeading.js +59 -0
  242. package/dist/hooks/useActiveHeading.js.map +1 -0
  243. package/dist/hooks/useCopyToClipboard.js +58 -0
  244. package/dist/hooks/useCopyToClipboard.js.map +1 -0
  245. package/dist/index.d.ts +6394 -0
  246. package/dist/index.js +117 -0
  247. package/dist/index.js.map +1 -0
  248. package/dist/lib/accentClasses.js +87 -0
  249. package/dist/lib/accentClasses.js.map +1 -0
  250. package/dist/lib/recipe.js +33 -0
  251. package/dist/lib/recipe.js.map +1 -0
  252. package/dist/lib/slug.js +39 -0
  253. package/dist/lib/slug.js.map +1 -0
  254. package/dist/lib/theme.js +76 -0
  255. package/dist/lib/theme.js.map +1 -0
  256. package/dist/lib/tokenRules.js +51 -0
  257. package/dist/lib/tokenRules.js.map +1 -0
  258. package/dist/prose.css +766 -0
  259. package/dist/styles.css +203 -0
  260. package/dist/theme/ansi.js +77 -0
  261. package/dist/theme/ansi.js.map +1 -0
  262. package/dist/theme/contrast.js +342 -0
  263. package/dist/theme/contrast.js.map +1 -0
  264. package/dist/theme/levels.js +234 -0
  265. package/dist/theme/levels.js.map +1 -0
  266. package/dist/theme/media.js +115 -0
  267. package/dist/theme/media.js.map +1 -0
  268. package/dist/theme/recommended.js +105 -0
  269. package/dist/theme/recommended.js.map +1 -0
  270. package/dist/theme.css +538 -0
  271. package/dist/tokens.js +1 -0
  272. package/dist/tokens.js.map +1 -0
  273. package/package.json +209 -6
  274. package/skills/design-system-usage/SKILL.md +75 -0
  275. package/terminal/rtk-midnight.alacritty.toml +33 -0
  276. package/terminal/rtk-midnight.ghostty.conf +24 -0
  277. package/terminal/rtk-midnight.itermcolors +167 -0
  278. package/terminal/rtk-midnight.windows-terminal.json +23 -0
  279. package/terminal/rtk-sketch.alacritty.toml +33 -0
  280. package/terminal/rtk-sketch.ghostty.conf +24 -0
  281. package/terminal/rtk-sketch.itermcolors +167 -0
  282. package/terminal/rtk-sketch.windows-terminal.json +23 -0
  283. package/tokens/palette.midnight.tokens.json +477 -0
  284. package/tokens/palette.sketch.tokens.json +477 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/components/NerdIcon.tsx"],"sourcesContent":["import type { HTMLAttributes } from 'react';\nimport { cn, recipe } from '../lib/recipe';\n\n/**\n * Nerd Font Unicode Private Use Area (PUA) symbol codepoints.\n *\n * Sourced from standard Nerd Fonts v3 (Font Awesome, Devicons, Octicons, Codicons, Material Design).\n * Occupies exactly 1 character width (1ch) in monospace typography, guaranteeing\n * zero baseline drift and pixel-perfect terminal alignment.\n */\nexport const NERD_GLYPHS = {\n // Navigation & Sorting\n 'sort': '\\uf0dc', // \n 'sort-asc': '\\uf0de', // \n 'sort-desc': '\\uf0dd', // \n 'chevron-right': '\\uf054', // \n 'chevron-left': '\\uf053', // \n 'chevron-up': '\\uf077', // \n 'chevron-down': '\\uf078', // \n 'arrow-right': '\\uf061', // \n 'arrow-left': '\\uf060', // \n 'arrow-up': '\\uf062', // \n 'arrow-down': '\\uf063', // \n 'expand': '\\uf065', // \n 'compress': '\\uf066', // \n\n // Git & DevOps\n 'git-branch': '\\uf126', // \n 'git-commit': '\\uf417', // \n 'git-merge': '\\uf419', // \n 'git-pull-request': '\\uf407',// \n 'docker': '\\uf308', // \n 'kubernetes': '\\udb84\\udcfe',\n 'aws': '\\udb83\\ude0f',\n 'linux': '\\uf17c', // \n 'apple': '\\uf179', // \n 'windows': '\\uf17a', // \n 'database': '\\uf1c0', // \n 'server': '\\uf233', // \n 'terminal': '\\uf120', // \n 'code': '\\uf121', // \n 'bug': '\\uf188', // \n 'cpu': '\\uf4bc',\n 'ram': '\\uefc5',\n\n // System & Chrome Actions\n 'search': '\\uf002', // \n 'settings': '\\uf013', // \n 'check': '\\uf00c', // \n 'close': '\\uf00d', // \n 'alert': '\\uf071', // \n 'info': '\\uf05a', // \n 'help': '\\uf059', // \n 'refresh': '\\uf021', // \n 'sync': '\\uf46a', // \n 'copy': '\\uf0c5', // \n 'external-link': '\\uf08e', // \n 'trash': '\\uf1f8', // \n 'edit': '\\uf044', // \n 'plus': '\\uf067', // \n 'minus': '\\uf068', // \n 'filter': '\\uf0b0', // \n 'folder': '\\uf07b', // \n 'folder-open': '\\uf07c', // 📂\n 'file': '\\uf15b', // \n 'file-code': '\\uf1c9', // \n 'lock': '\\uf023', // \n 'unlock': '\\uf09c', // \n 'link': '\\uf0c1', // \n 'play': '\\uf04b', // \n 'pause': '\\uf04c', // \n 'stop': '\\uf04d', // \n} as const;\n\nexport type NerdIconName = keyof typeof NERD_GLYPHS;\n\nexport type NerdIconAccent =\n | 'primary'\n | 'secondary'\n | 'tertiary'\n | 'success'\n | 'warning'\n | 'danger'\n | 'info'\n | 'muted';\n\nconst iconStyles = recipe({\n slots: {\n root: 'inline-flex items-center font-mono select-none',\n symbol: 'font-mono text-center inline-block leading-none',\n },\n variants: {\n accent: {\n primary: { symbol: 'text-accent-primary' },\n secondary: { symbol: 'text-accent-secondary' },\n tertiary: { symbol: 'text-accent-tertiary' },\n success: { symbol: 'text-intent-success' },\n warning: { symbol: 'text-intent-warning' },\n danger: { symbol: 'text-intent-danger' },\n info: { symbol: 'text-intent-info' },\n muted: { symbol: 'text-content-muted' },\n },\n size: {\n xs: { symbol: 'text-[10px]' },\n sm: { symbol: 'text-xs' },\n md: { symbol: 'text-sm' },\n lg: { symbol: 'text-base' },\n xl: { symbol: 'text-lg' },\n },\n },\n defaultVariants: {\n size: 'md',\n },\n});\n\nexport interface NerdIconProps extends HTMLAttributes<HTMLSpanElement> {\n /** The named Nerd Font icon identifier. */\n name: NerdIconName;\n /** Optional semantic role accent color. */\n accent?: NerdIconAccent;\n /** Size scale of the icon symbol. */\n size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';\n /** Whether to enclose the glyph in brutalist monospace brackets: `[  ]` */\n bracketed?: boolean;\n /** Accessible label for screen readers. If omitted, icon is aria-hidden. */\n label?: string;\n}\n\n/**\n * Monospace Nerd Font developer glyph primitive.\n *\n * Renders high-density developer and system icons mapped directly into monospace\n * font metrics (1ch grid) with zero SVG layout shift.\n *\n * @example\n * ```tsx\n * // Inline Git branch glyph\n * <NerdIcon name=\"git-branch\" accent=\"primary\" />\n *\n * // Bracketed terminal button icon\n * <Button>\n * <NerdIcon name=\"terminal\" bracketed accent=\"secondary\" /> EXECUTE RUNTIME\n * </Button>\n * ```\n */\nexport function NerdIcon({\n name,\n accent,\n size,\n bracketed = false,\n label,\n className,\n ...props\n}: NerdIconProps) {\n const glyph = NERD_GLYPHS[name] || '?';\n const styles = iconStyles({ accent, size });\n\n return (\n <span data-slot=\"nerd-icon\"\n className={styles.root({ class: className })}\n role={label ? 'img' : undefined}\n aria-label={label}\n aria-hidden={!label}\n {...props}\n >\n {bracketed && <span className=\"text-content-muted font-bold mr-0.5\">[</span>}\n <span className={styles.symbol()}>{glyph}</span>\n {bracketed && <span className=\"text-content-muted font-bold ml-0.5\">]</span>}\n </span>\n );\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,84 @@
1
+ // src/components/NoteBlock.tsx
2
+ import { AlertCircle, CheckCircle2, Info, AlertTriangle } from "lucide-react";
3
+ import { semanticTokens } from "../lib/theme.js";
4
+ import { jsx, jsxs } from "react/jsx-runtime";
5
+ var NoteBlock = ({
6
+ type = "note",
7
+ title,
8
+ children
9
+ }) => {
10
+ const getStyle = () => {
11
+ switch (type) {
12
+ case "tip":
13
+ return {
14
+ borderColor: semanticTokens.intent.success,
15
+ color: semanticTokens.intent.success,
16
+ icon: CheckCircle2,
17
+ defaultTitle: "PRO TIP"
18
+ };
19
+ case "warning":
20
+ return {
21
+ borderColor: semanticTokens.intent.danger,
22
+ color: semanticTokens.intent.danger,
23
+ icon: AlertTriangle,
24
+ defaultTitle: "WARNING"
25
+ };
26
+ case "important":
27
+ return {
28
+ borderColor: semanticTokens.intent.warning,
29
+ color: semanticTokens.intent.warning,
30
+ icon: AlertCircle,
31
+ defaultTitle: "IMPORTANT"
32
+ };
33
+ default:
34
+ return {
35
+ borderColor: semanticTokens.intent.info,
36
+ color: semanticTokens.intent.info,
37
+ icon: Info,
38
+ defaultTitle: "NOTE"
39
+ };
40
+ }
41
+ };
42
+ const config = getStyle();
43
+ const Icon = config.icon;
44
+ return /* @__PURE__ */ jsxs(
45
+ "div",
46
+ {
47
+ "data-slot": "note-block",
48
+ style: {
49
+ margin: "1.5rem 0",
50
+ padding: "1.25rem 1.5rem",
51
+ border: `2px solid ${config.borderColor}`,
52
+ backgroundColor: semanticTokens.surface.base,
53
+ boxShadow: `4px 4px 0px 0px ${config.borderColor}`
54
+ },
55
+ children: [
56
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: "0.6rem", marginBottom: "0.6rem" }, children: [
57
+ /* @__PURE__ */ jsx(Icon, { size: 18, color: config.color }),
58
+ /* @__PURE__ */ jsxs(
59
+ "span",
60
+ {
61
+ style: {
62
+ fontFamily: semanticTokens.font.display,
63
+ fontWeight: 800,
64
+ fontSize: "0.875rem",
65
+ textTransform: "uppercase",
66
+ color: config.color
67
+ },
68
+ children: [
69
+ "[ ",
70
+ title || config.defaultTitle,
71
+ " ]"
72
+ ]
73
+ }
74
+ )
75
+ ] }),
76
+ /* @__PURE__ */ jsx("div", { style: { fontFamily: semanticTokens.font.mono, fontSize: "0.875rem", color: semanticTokens.text.primary, lineHeight: 1.6 }, children })
77
+ ]
78
+ }
79
+ );
80
+ };
81
+ export {
82
+ NoteBlock
83
+ };
84
+ //# sourceMappingURL=NoteBlock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/components/NoteBlock.tsx"],"sourcesContent":["import type React from 'react';\nimport { AlertCircle, CheckCircle2, Info, AlertTriangle } from 'lucide-react';\nimport { semanticTokens } from '../lib/theme';\n\nexport interface NoteBlockProps {\n type?: 'note' | 'tip' | 'warning' | 'important';\n title?: string;\n children: React.ReactNode;\n}\n\nexport const NoteBlock: React.FC<NoteBlockProps> = ({\n type = 'note',\n title,\n children\n}) => {\n const getStyle = () => {\n switch (type) {\n case 'tip':\n return {\n borderColor: semanticTokens.intent.success,\n color: semanticTokens.intent.success,\n icon: CheckCircle2,\n defaultTitle: 'PRO TIP'\n };\n case 'warning':\n return {\n borderColor: semanticTokens.intent.danger,\n color: semanticTokens.intent.danger,\n icon: AlertTriangle,\n defaultTitle: 'WARNING'\n };\n case 'important':\n return {\n borderColor: semanticTokens.intent.warning,\n color: semanticTokens.intent.warning,\n icon: AlertCircle,\n defaultTitle: 'IMPORTANT'\n };\n default:\n return {\n borderColor: semanticTokens.intent.info,\n color: semanticTokens.intent.info,\n icon: Info,\n defaultTitle: 'NOTE'\n };\n }\n };\n\n const config = getStyle();\n const Icon = config.icon;\n\n return (\n <div data-slot=\"note-block\"\n style={{\n margin: '1.5rem 0',\n padding: '1.25rem 1.5rem',\n border: `2px solid ${config.borderColor}`,\n backgroundColor: semanticTokens.surface.base,\n boxShadow: `4px 4px 0px 0px ${config.borderColor}`,\n }}\n >\n <div style={{ display: 'flex', alignItems: 'center', gap: '0.6rem', marginBottom: '0.6rem' }}>\n <Icon size={18} color={config.color} />\n <span\n style={{\n fontFamily: semanticTokens.font.display,\n fontWeight: 800,\n fontSize: '0.875rem',\n textTransform: 'uppercase',\n color: config.color,\n }}\n >\n [ {title || config.defaultTitle} ]\n </span>\n </div>\n <div style={{ fontFamily: semanticTokens.font.mono, fontSize: '0.875rem', color: semanticTokens.text.primary, lineHeight: 1.6 }}>\n {children}\n </div>\n </div>\n );\n};\n"],"mappings":";AACA,SAAS,aAAa,cAAc,MAAM,qBAAqB;AAC/D,SAAS,sBAAsB;AA4DvB,cACA,YADA;AApDD,IAAM,YAAsC,CAAC;AAAA,EAClD,OAAO;AAAA,EACP;AAAA,EACA;AACF,MAAM;AACJ,QAAM,WAAW,MAAM;AACrB,YAAQ,MAAM;AAAA,MACZ,KAAK;AACH,eAAO;AAAA,UACL,aAAa,eAAe,OAAO;AAAA,UACnC,OAAO,eAAe,OAAO;AAAA,UAC7B,MAAM;AAAA,UACN,cAAc;AAAA,QAChB;AAAA,MACF,KAAK;AACH,eAAO;AAAA,UACL,aAAa,eAAe,OAAO;AAAA,UACnC,OAAO,eAAe,OAAO;AAAA,UAC7B,MAAM;AAAA,UACN,cAAc;AAAA,QAChB;AAAA,MACF,KAAK;AACH,eAAO;AAAA,UACL,aAAa,eAAe,OAAO;AAAA,UACnC,OAAO,eAAe,OAAO;AAAA,UAC7B,MAAM;AAAA,UACN,cAAc;AAAA,QAChB;AAAA,MACF;AACE,eAAO;AAAA,UACL,aAAa,eAAe,OAAO;AAAA,UACnC,OAAO,eAAe,OAAO;AAAA,UAC7B,MAAM;AAAA,UACN,cAAc;AAAA,QAChB;AAAA,IACJ;AAAA,EACF;AAEA,QAAM,SAAS,SAAS;AACxB,QAAM,OAAO,OAAO;AAEpB,SACE;AAAA,IAAC;AAAA;AAAA,MAAI,aAAU;AAAA,MACb,OAAO;AAAA,QACL,QAAQ;AAAA,QACR,SAAS;AAAA,QACT,QAAQ,aAAa,OAAO,WAAW;AAAA,QACvC,iBAAiB,eAAe,QAAQ;AAAA,QACxC,WAAW,mBAAmB,OAAO,WAAW;AAAA,MAClD;AAAA,MAEA;AAAA,6BAAC,SAAI,OAAO,EAAE,SAAS,QAAQ,YAAY,UAAU,KAAK,UAAU,cAAc,SAAS,GACzF;AAAA,8BAAC,QAAK,MAAM,IAAI,OAAO,OAAO,OAAO;AAAA,UACrC;AAAA,YAAC;AAAA;AAAA,cACC,OAAO;AAAA,gBACL,YAAY,eAAe,KAAK;AAAA,gBAChC,YAAY;AAAA,gBACZ,UAAU;AAAA,gBACV,eAAe;AAAA,gBACf,OAAO,OAAO;AAAA,cAChB;AAAA,cACD;AAAA;AAAA,gBACI,SAAS,OAAO;AAAA,gBAAa;AAAA;AAAA;AAAA,UAClC;AAAA,WACF;AAAA,QACA,oBAAC,SAAI,OAAO,EAAE,YAAY,eAAe,KAAK,MAAM,UAAU,YAAY,OAAO,eAAe,KAAK,SAAS,YAAY,IAAI,GAC3H,UACH;AAAA;AAAA;AAAA,EACF;AAEJ;","names":[]}
@@ -0,0 +1,34 @@
1
+ // src/components/PageHeader.tsx
2
+ import { cn } from "../lib/recipe.js";
3
+ import { accentTextClass } from "../lib/accentClasses.js";
4
+ import { jsx, jsxs } from "react/jsx-runtime";
5
+ function PageHeader({
6
+ title,
7
+ subtitle,
8
+ icon: Icon,
9
+ accent = "primary",
10
+ children,
11
+ className = ""
12
+ }) {
13
+ const accentText = accentTextClass(accent);
14
+ return /* @__PURE__ */ jsxs("header", { "data-slot": "page-header", className: cn("bg-surface-raised px-6 pt-8 pb-10", className), children: [
15
+ /* @__PURE__ */ jsxs("div", { className: "mb-4 flex items-center gap-4", children: [
16
+ Icon && /* @__PURE__ */ jsx(Icon, { className: cn("h-10 w-10", accentText) }),
17
+ /* @__PURE__ */ jsxs("h1", { className: "font-display text-4xl font-bold uppercase text-content-primary md:text-6xl", children: [
18
+ "[ ",
19
+ title,
20
+ " ]"
21
+ ] })
22
+ ] }),
23
+ subtitle && /* @__PURE__ */ jsxs("p", { className: "mt-4 font-mono text-lg text-content-muted", children: [
24
+ /* @__PURE__ */ jsx("span", { className: accentText, children: ">" }),
25
+ " ",
26
+ subtitle
27
+ ] }),
28
+ children
29
+ ] });
30
+ }
31
+ export {
32
+ PageHeader
33
+ };
34
+ //# sourceMappingURL=PageHeader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/components/PageHeader.tsx"],"sourcesContent":["import type { ReactNode, ElementType } from 'react';\nimport { cn } from '../lib/recipe';\nimport { accentTextClass } from '../lib/accentClasses';\nimport type { AccentToken } from '../lib/theme';\n\n\nexport interface PageHeaderProps {\n /** Rendered bracketed + uppercased as `[ TITLE ]`. */\n title: string;\n /** Mono strapline under the title, prefixed with the `>` prompt glyph. */\n subtitle?: ReactNode;\n /** Optional leading glyph — a lucide icon or SVG component. */\n icon?: ElementType<{ className?: string }>;\n /** Themes the icon + prompt glyph. */\n accent?: AccentToken;\n /** Extra header content (badges, admin notes) below the subtitle. */\n children?: ReactNode;\n /** Custom container class name override. */\n className?: string;\n}\n\nexport function PageHeader({\n title,\n subtitle,\n icon: Icon,\n accent = 'primary',\n children,\n className = '',\n}: PageHeaderProps) {\n const accentText = accentTextClass(accent);\n\n return (\n <header data-slot=\"page-header\" className={cn('bg-surface-raised px-6 pt-8 pb-10', className)}>\n <div className=\"mb-4 flex items-center gap-4\">\n {Icon && <Icon className={cn('h-10 w-10', accentText)} />}\n <h1 className=\"font-display text-4xl font-bold uppercase text-content-primary md:text-6xl\">\n [ {title} ]\n </h1>\n </div>\n {subtitle && (\n <p className=\"mt-4 font-mono text-lg text-content-muted\">\n <span className={accentText}>&gt;</span> {subtitle}\n </p>\n )}\n {children}\n </header>\n );\n}\n"],"mappings":";AACA,SAAS,UAAU;AACnB,SAAS,uBAAuB;AAgCf,cACT,YADS;AAbV,SAAS,WAAW;AAAA,EACzB;AAAA,EACA;AAAA,EACA,MAAM;AAAA,EACN,SAAS;AAAA,EACT;AAAA,EACA,YAAY;AACd,GAAoB;AAClB,QAAM,aAAa,gBAAgB,MAAM;AAEzC,SACE,qBAAC,YAAO,aAAU,eAAc,WAAW,GAAG,qCAAqC,SAAS,GAC1F;AAAA,yBAAC,SAAI,WAAU,gCACZ;AAAA,cAAQ,oBAAC,QAAK,WAAW,GAAG,aAAa,UAAU,GAAG;AAAA,MACvD,qBAAC,QAAG,WAAU,8EAA6E;AAAA;AAAA,QACtF;AAAA,QAAM;AAAA,SACX;AAAA,OACF;AAAA,IACC,YACC,qBAAC,OAAE,WAAU,6CACX;AAAA,0BAAC,UAAK,WAAW,YAAY,eAAI;AAAA,MAAO;AAAA,MAAE;AAAA,OAC5C;AAAA,IAED;AAAA,KACH;AAEJ;","names":[]}
@@ -0,0 +1,21 @@
1
+ // src/components/PageTitle.tsx
2
+ import { BracketText } from "./BracketText.js";
3
+ import { cn } from "../lib/recipe.js";
4
+ import { jsx, jsxs } from "react/jsx-runtime";
5
+ function PageTitle({
6
+ children,
7
+ subtitle,
8
+ bracketed = true,
9
+ className = "",
10
+ ...props
11
+ }) {
12
+ const baseClasses = "text-3xl font-display font-bold leading-tight tracking-tight text-[var(--ds-text-primary)] uppercase sm:text-4xl md:text-5xl border-4 border-double border-[var(--ds-border-strong)] inline-block px-6 py-4";
13
+ return /* @__PURE__ */ jsxs("div", { "data-slot": "page-title", className: "mb-8", children: [
14
+ /* @__PURE__ */ jsx("h1", { className: cn(baseClasses, className), ...props, children: bracketed ? /* @__PURE__ */ jsx(BracketText, { children }) : children }),
15
+ subtitle && /* @__PURE__ */ jsx("p", { className: "mt-2 font-mono text-sm text-accent-primary", children: subtitle })
16
+ ] });
17
+ }
18
+ export {
19
+ PageTitle
20
+ };
21
+ //# sourceMappingURL=PageTitle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/components/PageTitle.tsx"],"sourcesContent":["import type { ReactNode, HTMLAttributes } from 'react';\nimport { BracketText } from './BracketText';\nimport { cn } from '../lib/recipe';\n\nexport interface PageTitleProps extends HTMLAttributes<HTMLHeadingElement> {\n children: ReactNode;\n subtitle?: string;\n bracketed?: boolean;\n className?: string;\n}\n\nexport function PageTitle({\n children,\n subtitle,\n bracketed = true,\n className = '',\n ...props\n}: PageTitleProps) {\n const baseClasses =\n 'text-3xl font-display font-bold leading-tight tracking-tight text-[var(--ds-text-primary)] uppercase sm:text-4xl md:text-5xl border-4 border-double border-[var(--ds-border-strong)] inline-block px-6 py-4';\n\n return (\n <div data-slot=\"page-title\" className=\"mb-8\">\n <h1 className={cn(baseClasses, className)} {...props}>\n {bracketed ? <BracketText>{children}</BracketText> : children}\n </h1>\n {subtitle && (\n <p className=\"mt-2 font-mono text-sm text-accent-primary\">\n {subtitle}\n </p>\n )}\n </div>\n );\n}\n"],"mappings":";AACA,SAAS,mBAAmB;AAC5B,SAAS,UAAU;AAoBf,SAEiB,KAFjB;AAXG,SAAS,UAAU;AAAA,EACxB;AAAA,EACA;AAAA,EACA,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,GAAG;AACL,GAAmB;AACjB,QAAM,cACJ;AAEF,SACE,qBAAC,SAAI,aAAU,cAAa,WAAU,QACpC;AAAA,wBAAC,QAAG,WAAW,GAAG,aAAa,SAAS,GAAI,GAAG,OAC5C,sBAAY,oBAAC,eAAa,UAAS,IAAiB,UACvD;AAAA,IACC,YACC,oBAAC,OAAE,WAAU,8CACV,oBACH;AAAA,KAEJ;AAEJ;","names":[]}
@@ -0,0 +1,96 @@
1
+ "use client";
2
+
3
+ // src/components/Pagination.tsx
4
+ import { forwardRef } from "react";
5
+ import { cn } from "../lib/recipe.js";
6
+ import { paginationRange } from "./paginationRange.js";
7
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
8
+ var activeBtnClasses = "border-2 border-edge-strong text-content-inverse px-6 py-3 font-bold uppercase shadow-hard-md hover:shadow-hard-lg active:translate-x-1 active:translate-y-1 active:shadow-none transition-all";
9
+ var disabledBtnClasses = "cursor-not-allowed opacity-50 border-2 border-edge-strong bg-surface-raised text-content-primary px-6 py-3 font-bold uppercase";
10
+ var pageItemClasses = "inline-block min-w-11 px-2 py-3 text-center font-bold border-2 border-edge-strong";
11
+ var endClasses = "whitespace-nowrap px-3 md:px-6";
12
+ var pageClasses = cn(activeBtnClasses, pageItemClasses, "bg-surface-base text-content-primary");
13
+ var currentPageClasses = cn(
14
+ pageItemClasses,
15
+ "bg-accent-secondary text-content-inverse translate-x-1 translate-y-1"
16
+ );
17
+ var Pagination = forwardRef(function Pagination2({ totalPages, currentPage, onPageChange, getPageHref, className = "", ...props }, ref) {
18
+ const current = Math.min(Math.max(currentPage, 1), totalPages);
19
+ const hasPrev = current > 1;
20
+ const hasNext = current < totalPages;
21
+ const prevPageNum = current - 1;
22
+ const nextPageNum = current + 1;
23
+ const items = paginationRange(totalPages, current);
24
+ const go = (page) => {
25
+ if (onPageChange) onPageChange(page);
26
+ };
27
+ const renderDisabledEnd = (label, text) => /* @__PURE__ */ jsx("button", { type: "button", className: cn(disabledBtnClasses, endClasses), "aria-disabled": "true", "aria-label": label, children: text });
28
+ const renderEnd = (page, rel, label, text, fill) => {
29
+ if (getPageHref) {
30
+ return /* @__PURE__ */ jsx("a", { href: getPageHref(page), rel, "aria-label": label, className: cn(activeBtnClasses, endClasses, fill), children: text });
31
+ }
32
+ return /* @__PURE__ */ jsx("button", { type: "button", onClick: () => go(page), className: cn(activeBtnClasses, endClasses, fill), "aria-label": label, children: text });
33
+ };
34
+ const renderPage = (page) => {
35
+ const isCurrent = page === current;
36
+ const label = `Page ${page}`;
37
+ const text = isCurrent ? /* @__PURE__ */ jsxs(Fragment, { children: [
38
+ /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "[" }),
39
+ page,
40
+ /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "]" })
41
+ ] }) : page;
42
+ const className2 = isCurrent ? currentPageClasses : pageClasses;
43
+ if (getPageHref) {
44
+ return /* @__PURE__ */ jsx(
45
+ "a",
46
+ {
47
+ href: getPageHref(page),
48
+ "aria-label": label,
49
+ "aria-current": isCurrent ? "page" : void 0,
50
+ className: className2,
51
+ "data-slot": "pagination-page",
52
+ children: text
53
+ }
54
+ );
55
+ }
56
+ return /* @__PURE__ */ jsx(
57
+ "button",
58
+ {
59
+ type: "button",
60
+ onClick: isCurrent ? void 0 : () => go(page),
61
+ "aria-label": label,
62
+ "aria-current": isCurrent ? "page" : void 0,
63
+ className: className2,
64
+ "data-slot": "pagination-page",
65
+ children: text
66
+ }
67
+ );
68
+ };
69
+ return /* @__PURE__ */ jsx(
70
+ "div",
71
+ {
72
+ ref,
73
+ "data-slot": "pagination",
74
+ className: cn("pt-6 pb-8 space-y-2 md:space-y-5", className),
75
+ ...props,
76
+ children: /* @__PURE__ */ jsxs("nav", { "data-slot": "pagination-nav", className: "flex justify-between items-center gap-4 font-mono", "aria-label": "Pagination Navigation", children: [
77
+ hasPrev ? renderEnd(prevPageNum, "prev", "Previous Page", /* @__PURE__ */ jsx(Fragment, { children: "<< PREV" }), "bg-accent-primary") : renderDisabledEnd("Previous Page", /* @__PURE__ */ jsx(Fragment, { children: "<< PREV" })),
78
+ /* @__PURE__ */ jsxs("span", { "data-slot": "pagination-status", className: "md:hidden whitespace-nowrap text-content-primary font-bold border-2 border-edge-strong px-3 py-3 bg-surface-base", children: [
79
+ "[ ",
80
+ current,
81
+ " / ",
82
+ totalPages,
83
+ " ]"
84
+ ] }),
85
+ /* @__PURE__ */ jsx("ul", { "data-slot": "pagination-list", className: "hidden md:flex items-center gap-3", children: items.map(
86
+ (item) => typeof item === "number" ? /* @__PURE__ */ jsx("li", { children: renderPage(item) }, item) : /* @__PURE__ */ jsx("li", { "aria-hidden": "true", "data-slot": "pagination-ellipsis", className: "min-w-11 px-2 py-3 text-center font-bold text-content-primary", children: "..." }, item)
87
+ ) }),
88
+ hasNext ? renderEnd(nextPageNum, "next", "Next Page", /* @__PURE__ */ jsx(Fragment, { children: "NEXT >>" }), "bg-accent-tertiary") : renderDisabledEnd("Next Page", /* @__PURE__ */ jsx(Fragment, { children: "NEXT >>" }))
89
+ ] })
90
+ }
91
+ );
92
+ });
93
+ export {
94
+ Pagination
95
+ };
96
+ //# sourceMappingURL=Pagination.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/components/Pagination.tsx"],"sourcesContent":["'use client';\n\nimport { forwardRef } from 'react';\nimport type { HTMLAttributes, ReactNode } from 'react';\nimport { cn } from '../lib/recipe';\nimport { paginationRange } from './paginationRange';\n\nexport interface PaginationProps extends Omit<HTMLAttributes<HTMLDivElement>, 'children'> {\n /** How many pages there are. The last page's number, not an index. */\n totalPages: number;\n /**\n * The page being shown, counted from 1. Marked `aria-current=\"page\"` in the\n * page list; out-of-range values render the nearest real page as current.\n */\n currentPage: number;\n /**\n * Callback mode: every control is a `<button type=\"button\">` and pressing one\n * calls this with the page it names. Pressing the current page does not call\n * it — there is nowhere to go.\n */\n onPageChange?: (page: number) => void;\n /**\n * Navigation mode: every control is an `<a>` to the URL this returns, so\n * paging survives middle-click and is crawlable. PREV and NEXT carry\n * `rel=\"prev\"` / `rel=\"next\"`. Takes precedence over `onPageChange` when both\n * are given. Deliberately a function rather than a router: the component\n * never imports one.\n */\n getPageHref?: (page: number) => string;\n /** Merged into the root's classes. For placement — margins, width — not colour. */\n className?: string;\n}\n\nconst activeBtnClasses =\n 'border-2 border-edge-strong text-content-inverse px-6 py-3 font-bold uppercase shadow-hard-md hover:shadow-hard-lg active:translate-x-1 active:translate-y-1 active:shadow-none transition-all';\nconst disabledBtnClasses =\n 'cursor-not-allowed opacity-50 border-2 border-edge-strong bg-surface-raised text-content-primary px-6 py-3 font-bold uppercase';\n\n/*\n * A page item shares the ends' press language and swaps their fill for the\n * resting surface. The current page is told apart three ways, only one of them\n * colour: it is bracketed, `[7]`, and it sits pressed in — offset, shadowless —\n * where the others stand proud. Brackets are this system's \"this one\" cue\n * (`Button`'s `bracketed`), so they read without a legend.\n *\n * The ellipses are `aria-hidden`: a gap is visual shorthand, and the page\n * labels either side of it already say what is missing.\n */\nconst pageItemClasses = 'inline-block min-w-11 px-2 py-3 text-center font-bold border-2 border-edge-strong';\n\n/*\n * PREV, NEXT and the status never wrap their own text. At a phone's width the\n * ends take half their `md` padding instead, which is what lets the three sit\n * on one line at 412px rather than breaking `<< PREV` over two.\n */\nconst endClasses = 'whitespace-nowrap px-3 md:px-6';\nconst pageClasses = cn(activeBtnClasses, pageItemClasses, 'bg-surface-base text-content-primary');\nconst currentPageClasses = cn(\n pageItemClasses,\n 'bg-accent-secondary text-content-inverse translate-x-1 translate-y-1',\n);\n\n/**\n * Previous / next paging with a numbered page list, in one of two modes.\n *\n * **Callback mode** — pass `onPageChange` and every control is a button. **Navigation\n * mode** — pass `getPageHref` and every control is a link, the same split `Button`\n * makes: paging with a URL is navigation and should behave like it. Neither mode\n * knows about a router, which is what lets any app use it.\n *\n * The page list is first, last, the current page with one neighbour either side,\n * and at most two ellipses — seven slots once there are more than seven pages,\n * whatever the current page, so the strip never changes width as the reader\n * clicks along it. Below the `md` breakpoint the list gives way to the\n * `[ 7 / 20 ]` status rather than wrapping onto a second line.\n *\n * At the ends PREV and NEXT stay in place and in the tab order, announced as\n * unavailable with `aria-disabled` rather than vanishing from it with `disabled`.\n *\n * ```tsx\n * <Pagination totalPages={20} currentPage={page} onPageChange={setPage} />\n * <Pagination totalPages={20} currentPage={7} getPageHref={(p) => `/blog/page/${p}`} />\n * ```\n */\nexport const Pagination = forwardRef<HTMLDivElement, PaginationProps>(function Pagination(\n { totalPages, currentPage, onPageChange, getPageHref, className = '', ...props },\n ref,\n) {\n // Normalised once, and everything below derives from it: the list, the end\n // controls and the compact status. Clamping only the list left PREV asking\n // for page 9 of 3 when a filter shrank `totalPages` under the caller.\n const current = Math.min(Math.max(currentPage, 1), totalPages);\n const hasPrev = current > 1;\n const hasNext = current < totalPages;\n const prevPageNum = current - 1;\n const nextPageNum = current + 1;\n const items = paginationRange(totalPages, current);\n\n const go = (page: number) => {\n if (onPageChange) onPageChange(page);\n };\n\n /*\n * An end with nowhere to go. A button in both modes — a link with no\n * destination is not a link — and `aria-disabled` rather than `disabled`, so\n * it stays focusable and a screen reader meets it and hears that it is\n * unavailable instead of finding it missing.\n */\n const renderDisabledEnd = (label: string, text: ReactNode): ReactNode => (\n <button type=\"button\" className={cn(disabledBtnClasses, endClasses)} aria-disabled=\"true\" aria-label={label}>\n {text}\n </button>\n );\n\n const renderEnd = (\n page: number,\n rel: 'prev' | 'next',\n label: string,\n text: ReactNode,\n fill: string,\n ): ReactNode => {\n if (getPageHref) {\n return (\n <a href={getPageHref(page)} rel={rel} aria-label={label} className={cn(activeBtnClasses, endClasses, fill)}>\n {text}\n </a>\n );\n }\n return (\n <button type=\"button\" onClick={() => go(page)} className={cn(activeBtnClasses, endClasses, fill)} aria-label={label}>\n {text}\n </button>\n );\n };\n\n const renderPage = (page: number): ReactNode => {\n const isCurrent = page === current;\n const label = `Page ${page}`;\n const text = isCurrent ? (\n <>\n <span aria-hidden=\"true\">[</span>\n {page}\n <span aria-hidden=\"true\">]</span>\n </>\n ) : (\n page\n );\n const className = isCurrent ? currentPageClasses : pageClasses;\n\n if (getPageHref) {\n return (\n <a\n href={getPageHref(page)}\n aria-label={label}\n aria-current={isCurrent ? 'page' : undefined}\n className={className}\n data-slot=\"pagination-page\"\n >\n {text}\n </a>\n );\n }\n return (\n <button\n type=\"button\"\n onClick={isCurrent ? undefined : () => go(page)}\n aria-label={label}\n aria-current={isCurrent ? 'page' : undefined}\n className={className}\n data-slot=\"pagination-page\"\n >\n {text}\n </button>\n );\n };\n\n return (\n <div\n ref={ref}\n data-slot=\"pagination\"\n className={cn('pt-6 pb-8 space-y-2 md:space-y-5', className)}\n {...props}\n >\n <nav data-slot=\"pagination-nav\" className=\"flex justify-between items-center gap-4 font-mono\" aria-label=\"Pagination Navigation\">\n {hasPrev\n ? renderEnd(prevPageNum, 'prev', 'Previous Page', <>&lt;&lt; PREV</>, 'bg-accent-primary')\n : renderDisabledEnd('Previous Page', <>&lt;&lt; PREV</>)}\n <span data-slot=\"pagination-status\" className=\"md:hidden whitespace-nowrap text-content-primary font-bold border-2 border-edge-strong px-3 py-3 bg-surface-base\">\n [ {current} / {totalPages} ]\n </span>\n <ul data-slot=\"pagination-list\" className=\"hidden md:flex items-center gap-3\">\n {items.map((item) =>\n typeof item === 'number' ? (\n <li key={item}>{renderPage(item)}</li>\n ) : (\n <li key={item} aria-hidden=\"true\" data-slot=\"pagination-ellipsis\" className=\"min-w-11 px-2 py-3 text-center font-bold text-content-primary\">\n ...\n </li>\n ),\n )}\n </ul>\n {hasNext\n ? renderEnd(nextPageNum, 'next', 'Next Page', <>NEXT &gt;&gt;</>, 'bg-accent-tertiary')\n : renderDisabledEnd('Next Page', <>NEXT &gt;&gt;</>)}\n </nav>\n </div>\n );\n});\n"],"mappings":"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","names":["Pagination","className"]}
@@ -0,0 +1,87 @@
1
+ "use client";
2
+
3
+ // src/components/Popover.tsx
4
+ import { forwardRef } from "react";
5
+ import { Popover as BasePopover } from "@base-ui/react/popover";
6
+ import { recipe } from "../lib/recipe.js";
7
+ import { usePortalThemeAttribute } from "./portalTheme.js";
8
+ import { floatingSurface, floatingParts } from "./floatingSurface.js";
9
+ import { jsx, jsxs } from "react/jsx-runtime";
10
+ var popover = recipe({
11
+ extend: floatingSurface,
12
+ slots: { popup: "w-80 max-h-(--available-height) overflow-y-auto" }
13
+ });
14
+ var Popover = forwardRef(function Popover2({
15
+ trigger,
16
+ title,
17
+ children,
18
+ side = "bottom",
19
+ align = "start",
20
+ open,
21
+ defaultOpen,
22
+ onOpenChange,
23
+ className,
24
+ ...props
25
+ }, ref) {
26
+ const styles = popover();
27
+ const parts = floatingParts();
28
+ const portalTheme = usePortalThemeAttribute();
29
+ return /* @__PURE__ */ jsxs(
30
+ BasePopover.Root,
31
+ {
32
+ open,
33
+ defaultOpen,
34
+ onOpenChange: onOpenChange ? (next) => onOpenChange(next) : void 0,
35
+ children: [
36
+ /* @__PURE__ */ jsx(BasePopover.Trigger, { render: trigger }),
37
+ /* @__PURE__ */ jsx(BasePopover.Portal, { children: /* @__PURE__ */ jsx(
38
+ BasePopover.Positioner,
39
+ {
40
+ ...portalTheme,
41
+ side,
42
+ align,
43
+ sideOffset: 8,
44
+ collisionPadding: 8,
45
+ "data-slot": "popover-positioner",
46
+ className: styles.positioner(),
47
+ children: /* @__PURE__ */ jsxs(
48
+ BasePopover.Popup,
49
+ {
50
+ ref,
51
+ "data-slot": "popover",
52
+ className: styles.popup({ class: className }),
53
+ ...props,
54
+ children: [
55
+ /* @__PURE__ */ jsxs("div", { "data-slot": "popover-header", className: parts.header(), children: [
56
+ /* @__PURE__ */ jsx(
57
+ BasePopover.Title,
58
+ {
59
+ "data-slot": "popover-title",
60
+ className: parts.title(),
61
+ render: /* @__PURE__ */ jsx("h3", { children: title })
62
+ }
63
+ ),
64
+ /* @__PURE__ */ jsx(
65
+ BasePopover.Close,
66
+ {
67
+ "data-slot": "popover-close",
68
+ className: parts.close(),
69
+ "aria-label": "Close",
70
+ children: "\xD7"
71
+ }
72
+ )
73
+ ] }),
74
+ /* @__PURE__ */ jsx("div", { "data-slot": "popover-body", className: parts.body(), children })
75
+ ]
76
+ }
77
+ )
78
+ }
79
+ ) })
80
+ ]
81
+ }
82
+ );
83
+ });
84
+ export {
85
+ Popover
86
+ };
87
+ //# sourceMappingURL=Popover.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/components/Popover.tsx"],"sourcesContent":["'use client';\n\nimport { forwardRef } from 'react';\nimport type { HTMLAttributes, ReactElement, ReactNode } from 'react';\nimport { Popover as BasePopover } from '@base-ui/react/popover';\nimport { recipe } from '../lib/recipe';\nimport { usePortalThemeAttribute } from './portalTheme';\nimport { floatingSurface, floatingParts } from './floatingSurface';\nimport type { OverlayAlign, OverlaySide } from './Tooltip';\n\nexport interface PopoverProps\n extends Omit<HTMLAttributes<HTMLDivElement>, 'title' | 'children' | 'className'> {\n /**\n * The control that opens it — one element that forwards its ref, such as\n * `Button`. It gets `aria-expanded` and `aria-haspopup`, and focus returns\n * to it when the popover closes.\n */\n trigger: ReactElement;\n /**\n * The heading, and the popover's accessible name: the popup is a\n * `role=\"dialog\"`, and a dialog without a name announces nothing about\n * what it is. Required for that reason.\n */\n title: string;\n /** The content. Anything — text, a form, a list of links. */\n children: ReactNode;\n /** The preferred side. `bottom` by default; flips when there is no room. */\n side?: OverlaySide;\n /** Alignment along the trigger's edge. `start` by default. */\n align?: OverlayAlign;\n /** Controlled open state. Leave unset and the popover manages its own. */\n open?: boolean;\n /** Open on first render, uncontrolled — for a story or a walkthrough. */\n defaultOpen?: boolean;\n /** Called with the next open state, whatever caused the change. */\n onOpenChange?: (open: boolean) => void;\n /** Merged into the popup's classes — a caller's `w-96` wins over `w-80`. */\n className?: string;\n}\n\n// A panel: a reading width, and a height capped at the room below (or above)\n// the trigger, scrolling inside rather than running off the viewport.\nconst popover = recipe({\n extend: floatingSurface,\n slots: { popup: 'w-80 max-h-(--available-height) overflow-y-auto' },\n});\n\n/**\n * Contextual content anchored to the control that asked for it.\n *\n * What a {@link Tooltip} cannot carry: content worth reading, content with\n * controls in it, content a touch user needs. It opens on press rather than\n * hover, so it works on every input, and it is a non-modal `role=\"dialog\"`\n * named by its `title` — the page stays live behind it, and nothing outside\n * it is hidden from assistive technology.\n *\n * Built on `@base-ui/react/popover`. Positioning, collision handling and the\n * dismissal stack are the primitive's; this is the surface and its header.\n *\n * ## Focus and dismissal\n *\n * Opening moves focus into the popover — to its first control, which is the\n * close button when the content has none of its own. Escape, a press outside,\n * or the close button dismisses it, and focus returns to the trigger.\n * Escape closes only the topmost surface: a popover opened inside a `Modal`\n * closes and leaves the modal standing, as `AlertDialog` does (#162).\n *\n * @example\n * ```tsx\n * <Popover trigger={<Button size=\"sm\">DETAILS</Button>} title=\"Build 1482\">\n * Passed 41 of 42 gates. `check:visual` is still running.\n * </Popover>\n * ```\n */\nexport const Popover = forwardRef<HTMLDivElement, PopoverProps>(function Popover(\n {\n trigger,\n title,\n children,\n side = 'bottom',\n align = 'start',\n open,\n defaultOpen,\n onOpenChange,\n className,\n ...props\n },\n ref,\n) {\n const styles = popover();\n const parts = floatingParts();\n\n const portalTheme = usePortalThemeAttribute();\n return (\n <BasePopover.Root\n open={open}\n defaultOpen={defaultOpen}\n onOpenChange={onOpenChange ? (next) => onOpenChange(next) : undefined}\n >\n <BasePopover.Trigger render={trigger} />\n <BasePopover.Portal>\n <BasePopover.Positioner\n {...portalTheme}\n side={side}\n align={align}\n sideOffset={8}\n collisionPadding={8}\n data-slot=\"popover-positioner\"\n className={styles.positioner()}\n >\n <BasePopover.Popup\n ref={ref}\n data-slot=\"popover\"\n className={styles.popup({ class: className })}\n {...props}\n >\n <div data-slot=\"popover-header\" className={parts.header()}>\n {/* The text sits on the render element, as `Modal`'s does, so\n the a11y lint can read the heading's content literally. */}\n <BasePopover.Title\n data-slot=\"popover-title\"\n className={parts.title()}\n render={<h3>{title}</h3>}\n />\n <BasePopover.Close\n data-slot=\"popover-close\"\n className={parts.close()}\n aria-label=\"Close\"\n >\n &times;\n </BasePopover.Close>\n </div>\n <div data-slot=\"popover-body\" className={parts.body()}>\n {children}\n </div>\n </BasePopover.Popup>\n </BasePopover.Positioner>\n </BasePopover.Portal>\n </BasePopover.Root>\n );\n});\n"],"mappings":";;;AAEA,SAAS,kBAAkB;AAE3B,SAAS,WAAW,mBAAmB;AACvC,SAAS,cAAc;AACvB,SAAS,+BAA+B;AACxC,SAAS,iBAAiB,qBAAqB;AA4FzC,cAiBM,YAjBN;AAzDN,IAAM,UAAU,OAAO;AAAA,EACrB,QAAQ;AAAA,EACR,OAAO,EAAE,OAAO,kDAAkD;AACpE,CAAC;AA6BM,IAAM,UAAU,WAAyC,SAASA,SACvE;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA,OAAO;AAAA,EACP,QAAQ;AAAA,EACR;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,GACA,KACA;AACA,QAAM,SAAS,QAAQ;AACvB,QAAM,QAAQ,cAAc;AAE5B,QAAM,cAAc,wBAAwB;AAC5C,SACE;AAAA,IAAC,YAAY;AAAA,IAAZ;AAAA,MACC;AAAA,MACA;AAAA,MACA,cAAc,eAAe,CAAC,SAAS,aAAa,IAAI,IAAI;AAAA,MAE5D;AAAA,4BAAC,YAAY,SAAZ,EAAoB,QAAQ,SAAS;AAAA,QACtC,oBAAC,YAAY,QAAZ,EACC;AAAA,UAAC,YAAY;AAAA,UAAZ;AAAA,YACE,GAAG;AAAA,YACJ;AAAA,YACA;AAAA,YACA,YAAY;AAAA,YACZ,kBAAkB;AAAA,YAClB,aAAU;AAAA,YACV,WAAW,OAAO,WAAW;AAAA,YAE7B;AAAA,cAAC,YAAY;AAAA,cAAZ;AAAA,gBACC;AAAA,gBACA,aAAU;AAAA,gBACV,WAAW,OAAO,MAAM,EAAE,OAAO,UAAU,CAAC;AAAA,gBAC3C,GAAG;AAAA,gBAEJ;AAAA,uCAAC,SAAI,aAAU,kBAAiB,WAAW,MAAM,OAAO,GAGtD;AAAA;AAAA,sBAAC,YAAY;AAAA,sBAAZ;AAAA,wBACC,aAAU;AAAA,wBACV,WAAW,MAAM,MAAM;AAAA,wBACvB,QAAQ,oBAAC,QAAI,iBAAM;AAAA;AAAA,oBACrB;AAAA,oBACA;AAAA,sBAAC,YAAY;AAAA,sBAAZ;AAAA,wBACC,aAAU;AAAA,wBACV,WAAW,MAAM,MAAM;AAAA,wBACvB,cAAW;AAAA,wBACZ;AAAA;AAAA,oBAED;AAAA,qBACF;AAAA,kBACA,oBAAC,SAAI,aAAU,gBAAe,WAAW,MAAM,KAAK,GACjD,UACH;AAAA;AAAA;AAAA,YACF;AAAA;AAAA,QACF,GACF;AAAA;AAAA;AAAA,EACF;AAEJ,CAAC;","names":["Popover"]}
@@ -0,0 +1,83 @@
1
+ // src/components/Progress.tsx
2
+ import { forwardRef } from "react";
3
+ import { Progress as BaseProgress } from "@base-ui/react/progress";
4
+ import { recipe } from "../lib/recipe.js";
5
+ import { accentTextClass } from "../lib/accentClasses.js";
6
+ import { jsx, jsxs } from "react/jsx-runtime";
7
+ var progress = recipe({
8
+ slots: {
9
+ root: "flex w-full flex-col gap-1.5 font-mono",
10
+ header: "flex items-baseline justify-between gap-3",
11
+ label: "text-xs font-bold uppercase tracking-wider text-content-secondary",
12
+ value: "text-xs font-bold tabular-nums text-content-primary",
13
+ /*
14
+ * `overflow-hidden` is load-bearing rather than tidy: the indeterminate
15
+ * indicator is a third of the track's width translated from `-100%` to
16
+ * `400%`, so without it the bar sweeps out through both ends of the well.
17
+ */
18
+ track: "relative h-3 w-full overflow-hidden border-2 border-edge-strong bg-surface-sunken",
19
+ /*
20
+ * Two states in one slot, switched by the data attributes Base UI sets on
21
+ * every part.
22
+ *
23
+ * Determinate: Base UI writes the width as an inline percentage, so the
24
+ * class only has to supply the height and the fill.
25
+ *
26
+ * Indeterminate: there is no width to write, so the class supplies one and
27
+ * sweeps it. Under `prefers-reduced-motion` the sweep becomes the same
28
+ * opacity pulse `Skeleton` uses and the bar fills the track — a *full*
29
+ * static bar rather than a third of one, because a third of a track
30
+ * sitting still reads as "33% done", which is a number this component does
31
+ * not have. Pulsing says "working, amount unknown", which is what
32
+ * `aria-valuetext` says too.
33
+ */
34
+ indicator: "h-full bg-current data-[indeterminate]:w-1/3 data-[indeterminate]:animate-ds-track motion-reduce:data-[indeterminate]:w-full motion-reduce:data-[indeterminate]:animate-ds-pulse"
35
+ }
36
+ });
37
+ var Progress = forwardRef(function Progress2({
38
+ value = null,
39
+ max = 100,
40
+ label,
41
+ hideLabel = false,
42
+ showValue = false,
43
+ accent = "primary",
44
+ className,
45
+ ...props
46
+ }, ref) {
47
+ const styles = progress();
48
+ return /* @__PURE__ */ jsxs(
49
+ BaseProgress.Root,
50
+ {
51
+ ref,
52
+ value: value ?? null,
53
+ max,
54
+ "data-slot": "progress",
55
+ className: styles.root({ class: className }),
56
+ ...props,
57
+ children: [
58
+ /* @__PURE__ */ jsxs("div", { "data-slot": "progress-header", className: styles.header(), children: [
59
+ /* @__PURE__ */ jsx(
60
+ BaseProgress.Label,
61
+ {
62
+ "data-slot": "progress-label",
63
+ className: styles.label({ class: hideLabel ? "sr-only" : void 0 }),
64
+ children: label
65
+ }
66
+ ),
67
+ showValue && /* @__PURE__ */ jsx(BaseProgress.Value, { "data-slot": "progress-value", className: styles.value() })
68
+ ] }),
69
+ /* @__PURE__ */ jsx(BaseProgress.Track, { "data-slot": "progress-track", className: styles.track(), children: /* @__PURE__ */ jsx(
70
+ BaseProgress.Indicator,
71
+ {
72
+ "data-slot": "progress-indicator",
73
+ className: styles.indicator({ class: accentTextClass(accent) })
74
+ }
75
+ ) })
76
+ ]
77
+ }
78
+ );
79
+ });
80
+ export {
81
+ Progress
82
+ };
83
+ //# sourceMappingURL=Progress.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/components/Progress.tsx"],"sourcesContent":["import { forwardRef } from 'react';\nimport type { HTMLAttributes } from 'react';\nimport { Progress as BaseProgress } from '@base-ui/react/progress';\nimport { recipe } from '../lib/recipe';\nimport { accentTextClass } from '../lib/accentClasses';\nimport type { AccentToken } from '../lib/theme';\n\n/**\n * A bar in a box. The track is a hard-edged well and the indicator fills it\n * from the leading edge — the same two-surface treatment `BulletChart` uses for\n * a measure against its range, so the two read as one family.\n *\n * `bg-current` on the indicator, with the accent applied as a text colour: one\n * accent table in `accentClasses` covers `Spinner`'s leading edge and this\n * fill, rather than a second map of `bg-*` classes that can disagree with it.\n */\nconst progress = recipe({\n slots: {\n root: 'flex w-full flex-col gap-1.5 font-mono',\n header: 'flex items-baseline justify-between gap-3',\n label: 'text-xs font-bold uppercase tracking-wider text-content-secondary',\n value: 'text-xs font-bold tabular-nums text-content-primary',\n /*\n * `overflow-hidden` is load-bearing rather than tidy: the indeterminate\n * indicator is a third of the track's width translated from `-100%` to\n * `400%`, so without it the bar sweeps out through both ends of the well.\n */\n track: 'relative h-3 w-full overflow-hidden border-2 border-edge-strong bg-surface-sunken',\n /*\n * Two states in one slot, switched by the data attributes Base UI sets on\n * every part.\n *\n * Determinate: Base UI writes the width as an inline percentage, so the\n * class only has to supply the height and the fill.\n *\n * Indeterminate: there is no width to write, so the class supplies one and\n * sweeps it. Under `prefers-reduced-motion` the sweep becomes the same\n * opacity pulse `Skeleton` uses and the bar fills the track — a *full*\n * static bar rather than a third of one, because a third of a track\n * sitting still reads as \"33% done\", which is a number this component does\n * not have. Pulsing says \"working, amount unknown\", which is what\n * `aria-valuetext` says too.\n */\n indicator:\n 'h-full bg-current data-[indeterminate]:w-1/3 data-[indeterminate]:animate-ds-track '\n + 'motion-reduce:data-[indeterminate]:w-full motion-reduce:data-[indeterminate]:animate-ds-pulse',\n },\n});\n\nexport interface ProgressProps\n extends Omit<HTMLAttributes<HTMLDivElement>, 'className' | 'children'> {\n /**\n * How far along, between `0` and `max`. Pass `null` — or leave it off — when\n * the fraction is genuinely unknown: that is the indeterminate state, and it\n * is announced as such rather than as zero. A bar pinned at 0% is a claim\n * that no work has been done.\n */\n value?: number | null;\n /** The value that means finished. Defaults to 100, so a bare `value` is a percentage. */\n max?: number;\n /**\n * What is progressing — \"Uploading evidence\", \"Rebuilding tokens\". Required,\n * and required as text rather than as a boolean or an id: it is the bar's\n * accessible name, and a progress bar with no name announces a number with\n * nothing attached to it.\n */\n label: string;\n /**\n * Keep the label as the accessible name but take it off the screen, for a bar\n * sitting under a heading that already says the same thing. The name survives;\n * only the second copy of it goes.\n */\n hideLabel?: boolean;\n /**\n * Show the formatted percentage beside the label. Off by default — in a list\n * of bars the numbers compete with the bars, and the bar is the faster read.\n * Indeterminate bars render nothing here, since there is no value to show.\n */\n showValue?: boolean;\n /**\n * Semantic colour for the fill. Accepts an `Emphasis` (`primary`…`quiet`) or\n * an `Intent` (`info`/`success`/`warning`/`danger`) — `intent.success` for a\n * completing job, `intent.warning` for a quota filling up.\n */\n accent?: AccentToken;\n /** Merged onto the wrapper — the width of the whole control, label included. */\n className?: string;\n}\n\n/**\n * Determinate and indeterminate progress, on Base UI's `progress`.\n *\n * Use it when a wait has a length: a file uploading, a batch job, a quota\n * filling. When the length is unknown but the wait is short, `Spinner` says the\n * same thing in less space; when the shape of what is arriving is known,\n * `Skeleton` says more than either.\n *\n * ## Why this one takes a primitive and the other three do not\n *\n * `Spinner`, `Skeleton` and `EmptyState` are markup and tokens. This is not:\n * `role=\"progressbar\"` has to carry `aria-valuenow`, `aria-valuemin` and\n * `aria-valuemax` that agree with the drawn width, drop `aria-valuenow`\n * entirely when indeterminate, and expose `aria-valuetext` so a screen reader\n * reads \"40%\" rather than \"40\". Hand-rolling that is where it goes wrong — most\n * often as a bar that keeps reporting a stale `aria-valuenow` while the fill\n * animates past it. `@base-ui/react/progress` owns the clamping, the\n * percentage, the formatting and the attributes, and this component owns the\n * surface.\n *\n * Nothing of Base UI's reaches the published API: the props below are this\n * package's own, and the parts are an implementation detail — one wrapper, per\n * the Base UI confinement rule.\n */\nexport const Progress = forwardRef<HTMLDivElement, ProgressProps>(function Progress(\n {\n value = null,\n max = 100,\n label,\n hideLabel = false,\n showValue = false,\n accent = 'primary',\n className,\n ...props\n },\n ref,\n) {\n const styles = progress();\n\n return (\n <BaseProgress.Root\n ref={ref}\n // `value ?? null` rather than `value`: Base UI reads `undefined` as a\n // missing required prop, and the API here treats \"not passed\" and\n // \"explicitly unknown\" as the same indeterminate state.\n value={value ?? null}\n max={max}\n data-slot=\"progress\"\n className={styles.root({ class: className })}\n {...props}\n >\n <div data-slot=\"progress-header\" className={styles.header()}>\n <BaseProgress.Label\n data-slot=\"progress-label\"\n // `sr-only` rather than not rendering it: the label is what\n // `aria-labelledby` points at, so removing it removes the name.\n className={styles.label({ class: hideLabel ? 'sr-only' : undefined })}\n >\n {label}\n </BaseProgress.Label>\n {showValue && (\n <BaseProgress.Value data-slot=\"progress-value\" className={styles.value()} />\n )}\n </div>\n\n <BaseProgress.Track data-slot=\"progress-track\" className={styles.track()}>\n <BaseProgress.Indicator\n data-slot=\"progress-indicator\"\n className={styles.indicator({ class: accentTextClass(accent) })}\n />\n </BaseProgress.Track>\n </BaseProgress.Root>\n );\n});\n"],"mappings":";AAAA,SAAS,kBAAkB;AAE3B,SAAS,YAAY,oBAAoB;AACzC,SAAS,cAAc;AACvB,SAAS,uBAAuB;AAwI1B,SACE,KADF;AA5HN,IAAM,WAAW,OAAO;AAAA,EACtB,OAAO;AAAA,IACL,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAMP,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAgBP,WACE;AAAA,EAEJ;AACF,CAAC;AAkEM,IAAM,WAAW,WAA0C,SAASA,UACzE;AAAA,EACE,QAAQ;AAAA,EACR,MAAM;AAAA,EACN;AAAA,EACA,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,SAAS;AAAA,EACT;AAAA,EACA,GAAG;AACL,GACA,KACA;AACA,QAAM,SAAS,SAAS;AAExB,SACE;AAAA,IAAC,aAAa;AAAA,IAAb;AAAA,MACC;AAAA,MAIA,OAAO,SAAS;AAAA,MAChB;AAAA,MACA,aAAU;AAAA,MACV,WAAW,OAAO,KAAK,EAAE,OAAO,UAAU,CAAC;AAAA,MAC1C,GAAG;AAAA,MAEJ;AAAA,6BAAC,SAAI,aAAU,mBAAkB,WAAW,OAAO,OAAO,GACxD;AAAA;AAAA,YAAC,aAAa;AAAA,YAAb;AAAA,cACC,aAAU;AAAA,cAGV,WAAW,OAAO,MAAM,EAAE,OAAO,YAAY,YAAY,OAAU,CAAC;AAAA,cAEnE;AAAA;AAAA,UACH;AAAA,UACC,aACC,oBAAC,aAAa,OAAb,EAAmB,aAAU,kBAAiB,WAAW,OAAO,MAAM,GAAG;AAAA,WAE9E;AAAA,QAEA,oBAAC,aAAa,OAAb,EAAmB,aAAU,kBAAiB,WAAW,OAAO,MAAM,GACrE;AAAA,UAAC,aAAa;AAAA,UAAb;AAAA,YACC,aAAU;AAAA,YACV,WAAW,OAAO,UAAU,EAAE,OAAO,gBAAgB,MAAM,EAAE,CAAC;AAAA;AAAA,QAChE,GACF;AAAA;AAAA;AAAA,EACF;AAEJ,CAAC;","names":["Progress"]}
@@ -0,0 +1,74 @@
1
+ "use client";
2
+
3
+ // src/components/RadioGroup.tsx
4
+ import { forwardRef } from "react";
5
+ import { Radio as BaseRadio } from "@base-ui/react/radio";
6
+ import { RadioGroup as BaseRadioGroup } from "@base-ui/react/radio-group";
7
+ import { cn } from "../lib/recipe.js";
8
+ import { booleanControl } from "./booleanControl.js";
9
+ import { FieldItem, GroupFrame, accentStyle } from "./fieldFrame.js";
10
+ import { Legend } from "./Fieldset.js";
11
+ import { jsx } from "react/jsx-runtime";
12
+ var RadioGroup = forwardRef(function RadioGroup2({
13
+ legend,
14
+ error,
15
+ helperText,
16
+ accent = "primary",
17
+ className,
18
+ style,
19
+ value,
20
+ defaultValue,
21
+ onValueChange,
22
+ name,
23
+ disabled,
24
+ readOnly,
25
+ required,
26
+ children,
27
+ ...props
28
+ }, ref) {
29
+ return /* @__PURE__ */ jsx(
30
+ GroupFrame,
31
+ {
32
+ ref,
33
+ legend: legend ? /* @__PURE__ */ jsx(Legend, { children: legend }) : void 0,
34
+ error,
35
+ helperText,
36
+ disabled,
37
+ className,
38
+ style: accentStyle(accent, style),
39
+ render: /* @__PURE__ */ jsx(
40
+ BaseRadioGroup,
41
+ {
42
+ name,
43
+ value,
44
+ defaultValue,
45
+ readOnly,
46
+ required,
47
+ onValueChange: (next) => onValueChange?.(next)
48
+ }
49
+ ),
50
+ ...props,
51
+ children
52
+ }
53
+ );
54
+ });
55
+ var Radio = forwardRef(function Radio2({ value, label, helperText, disabled, className, ...props }, ref) {
56
+ const styles = booleanControl({ shape: "dot" });
57
+ return /* @__PURE__ */ jsx(FieldItem, { label, helperText, disabled, children: /* @__PURE__ */ jsx(
58
+ BaseRadio.Root,
59
+ {
60
+ ref,
61
+ value,
62
+ disabled,
63
+ "data-slot": "radio",
64
+ className: cn(styles.control(), className),
65
+ ...props,
66
+ children: /* @__PURE__ */ jsx(BaseRadio.Indicator, { "data-slot": "radio-indicator", className: styles.mark() })
67
+ }
68
+ ) });
69
+ });
70
+ export {
71
+ Radio,
72
+ RadioGroup
73
+ };
74
+ //# sourceMappingURL=RadioGroup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/components/RadioGroup.tsx"],"sourcesContent":["'use client';\n\nimport { forwardRef } from 'react';\nimport type { HTMLAttributes, ReactNode, Ref } from 'react';\nimport { Radio as BaseRadio } from '@base-ui/react/radio';\nimport { RadioGroup as BaseRadioGroup } from '@base-ui/react/radio-group';\nimport { cn } from '../lib/recipe';\nimport type { AccentToken } from '../lib/theme';\nimport { booleanControl } from './booleanControl';\nimport { FieldItem, GroupFrame, accentStyle } from './fieldFrame';\nimport { Legend } from './Fieldset';\n\nexport interface RadioGroupProps\n extends Omit<HTMLAttributes<HTMLDivElement>, 'className' | 'children' | 'defaultValue' | 'onChange'> {\n /**\n * The question the set answers, rendered as a `Legend` and wired to the\n * `radiogroup` by `aria-labelledby` — the group's one accessible name. Omit\n * it only to place a `Legend` of your own among the children.\n */\n legend?: string;\n /**\n * The group's validation message. Its presence is also the invalid state:\n * `aria-invalid` on the `radiogroup`, the danger border on every option, and\n * a message that describes the group rather than any one option, read when\n * focus reaches an option. It is not a live region.\n */\n error?: string;\n /**\n * Standing guidance for the whole set, shown under it and replaced by\n * `error` while one is set. Guidance for a single option is that `Radio`'s\n * own `helperText`.\n */\n helperText?: string;\n /**\n * Semantic accent for the selected mark. Accepts an `Emphasis`\n * (`primary`…`quiet`) or an `Intent`; set once on the group and inherited by\n * every option as a custom property.\n */\n accent?: AccentToken;\n /** The selected option's `value`. Supplying it makes the group controlled; pair it with `onValueChange`. */\n value?: string;\n /** The option selected at first, for an uncontrolled group. Ignored when `value` is set. */\n defaultValue?: string;\n /** Called with the newly selected option's `value`. */\n onValueChange?: (value: string) => void;\n /**\n * The name the selected value is submitted under. One name for the group,\n * not one per option: Base UI gives every option's hidden input this name,\n * so a native form submits exactly the checked one.\n */\n name?: string;\n /** Disables every option. A single option takes its own `disabled`. */\n disabled?: boolean;\n /** Announces and renders the selection, but refuses to change it. */\n readOnly?: boolean;\n /** Requires a selection before the form submits; announced as `aria-required`. */\n required?: boolean;\n /** Merged onto the `radiogroup` element. */\n className?: string;\n /** The options — `Radio` elements, in the order arrow keys visit them. */\n children: ReactNode;\n}\n\n/**\n * Choose exactly one of a set: a legend, the options, and a description and\n * error for the set.\n *\n * Built on `Fieldset`'s frame rather than beside it. The group's label,\n * description and error are the fieldset contract — `error` is the message\n * and the invalid state, `helperText` gives way to it — and the only thing\n * this adds is what makes a set of options a *choice*: Base UI's `RadioGroup`\n * is rendered as the fieldset itself, so one element carries\n * `role=\"radiogroup\"`, the legend's `aria-labelledby`, the group's\n * `aria-describedby` and the roving focus.\n *\n * That focus model is the difference from \"several radios sharing a `name`\":\n * Tab enters the group once, at the selected option or the first enabled one,\n * and leaves it on the next Tab; the arrow keys move *and select* within the\n * set, wrapping at either end.\n *\n * Reach for it for two to about seven mutually exclusive options that should\n * all be visible at once. Many more is a `Select`; a yes/no is a `Checkbox`.\n *\n * ```tsx\n * <RadioGroup legend=\"Preferred deployment\" name=\"deployment\" defaultValue=\"self-hosted\">\n * <Radio value=\"cloud\" label=\"Cloud\" />\n * <Radio value=\"self-hosted\" label=\"Self-hosted\" />\n * <Radio value=\"hybrid\" label=\"Hybrid\" />\n * </RadioGroup>\n * ```\n */\nexport const RadioGroup = forwardRef<HTMLDivElement, RadioGroupProps>(function RadioGroup(\n {\n legend,\n error,\n helperText,\n accent = 'primary',\n className,\n style,\n value,\n defaultValue,\n onValueChange,\n name,\n disabled,\n readOnly,\n required,\n children,\n ...props\n },\n ref,\n) {\n return (\n <GroupFrame\n ref={ref as Ref<HTMLElement>}\n legend={legend ? <Legend>{legend}</Legend> : undefined}\n error={error}\n helperText={helperText}\n disabled={disabled}\n className={className}\n style={accentStyle(accent, style)}\n render={\n <BaseRadioGroup<string>\n name={name}\n value={value}\n defaultValue={defaultValue}\n readOnly={readOnly}\n required={required}\n // The new value only. Base UI's second argument is its own event\n // details type, and forwarding it would publish that type.\n onValueChange={(next) => onValueChange?.(next)}\n />\n }\n {...props}\n >\n {children}\n </GroupFrame>\n );\n});\n\nexport interface RadioProps extends Omit<HTMLAttributes<HTMLSpanElement>, 'className' | 'onChange'> {\n /** What the group's `value` becomes, and what a form submits, when this option is chosen. */\n value: string;\n /**\n * The option's visible label. The control renders inside it, so the words\n * are the hit target as well as the name.\n */\n label?: string;\n /** Guidance for this option alone, described on it and not on its siblings. */\n helperText?: string;\n /** Disables this option while leaving the rest of the group usable. */\n disabled?: boolean;\n /** Merged onto the control itself. */\n className?: string;\n}\n\n/**\n * One option of a `RadioGroup`.\n *\n * It has a label and may have guidance of its own, but no error: validity\n * belongs to the choice, not to one answer, so it is set on the group and\n * reaches every option from there. It must render inside a `RadioGroup`, whose\n * context supplies the `name`, the selection and the roving focus.\n *\n * Like `Checkbox`, the element is a `span role=\"radio\"` with a hidden native\n * input beside it, both Base UI's: the input is what a form submits, and the\n * span is what is focused and announced.\n *\n * ```tsx\n * <Radio value=\"hybrid\" label=\"Hybrid\" helperText=\"Control plane in our cloud\" />\n * ```\n */\nexport const Radio = forwardRef<HTMLSpanElement, RadioProps>(function Radio(\n { value, label, helperText, disabled, className, ...props },\n ref,\n) {\n const styles = booleanControl({ shape: 'dot' });\n\n return (\n <FieldItem label={label} helperText={helperText} disabled={disabled}>\n <BaseRadio.Root\n ref={ref}\n value={value}\n disabled={disabled}\n data-slot=\"radio\"\n className={cn(styles.control(), className)}\n {...props}\n >\n <BaseRadio.Indicator data-slot=\"radio-indicator\" className={styles.mark()} />\n </BaseRadio.Root>\n </FieldItem>\n );\n});\n"],"mappings":";;;AAEA,SAAS,kBAAkB;AAE3B,SAAS,SAAS,iBAAiB;AACnC,SAAS,cAAc,sBAAsB;AAC7C,SAAS,UAAU;AAEnB,SAAS,sBAAsB;AAC/B,SAAS,WAAW,YAAY,mBAAmB;AACnD,SAAS,cAAc;AAwGA;AAvBhB,IAAM,aAAa,WAA4C,SAASA,YAC7E;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA,SAAS;AAAA,EACT;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,GACA,KACA;AACA,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,QAAQ,SAAS,oBAAC,UAAQ,kBAAO,IAAY;AAAA,MAC7C;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,OAAO,YAAY,QAAQ,KAAK;AAAA,MAChC,QACE;AAAA,QAAC;AAAA;AAAA,UACC;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UAGA,eAAe,CAAC,SAAS,gBAAgB,IAAI;AAAA;AAAA,MAC/C;AAAA,MAED,GAAG;AAAA,MAEH;AAAA;AAAA,EACH;AAEJ,CAAC;AAkCM,IAAM,QAAQ,WAAwC,SAASC,OACpE,EAAE,OAAO,OAAO,YAAY,UAAU,WAAW,GAAG,MAAM,GAC1D,KACA;AACA,QAAM,SAAS,eAAe,EAAE,OAAO,MAAM,CAAC;AAE9C,SACE,oBAAC,aAAU,OAAc,YAAwB,UAC/C;AAAA,IAAC,UAAU;AAAA,IAAV;AAAA,MACC;AAAA,MACA;AAAA,MACA;AAAA,MACA,aAAU;AAAA,MACV,WAAW,GAAG,OAAO,QAAQ,GAAG,SAAS;AAAA,MACxC,GAAG;AAAA,MAEJ,8BAAC,UAAU,WAAV,EAAoB,aAAU,mBAAkB,WAAW,OAAO,KAAK,GAAG;AAAA;AAAA,EAC7E,GACF;AAEJ,CAAC;","names":["RadioGroup","Radio"]}