@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
package/dist/index.js ADDED
@@ -0,0 +1,117 @@
1
+ // src/index.ts
2
+
3
+ export { DEFAULT_LEVEL, FIXED_COLOURS, INK_WEIGHT, LEVELS, PALETTE_HUES, SYSTEM_LEVEL, THEME_LEVELS, assertNever, isThemeLevel, nextLevel } from "./theme/levels.js";
4
+ import {
5
+ MEDIA,
6
+ CSS_MEDIUM,
7
+ MEDIA_DEFINITIONS,
8
+ isMedium
9
+ } from "./theme/media.js";
10
+ export { MAXIMUM_NEUTRAL_CHROMA, MINIMUM_RATIO, WEB_FLOOR, apcaContrast, auditContrast, auditHueAgreement, auditSelectionDevices, auditTextHierarchy, composite, contrastRatio, parseColor, relativeLuminance } from "./theme/contrast.js";
11
+ import { ANSI_SLOTS, SLOTS, ansiScheme } from "./theme/ansi.js";
12
+ export { HEADING_EMPHASIS, accentVar, borderVar, fontVar, semanticTokens, surfaceVar, textVar } from "./lib/theme.js";
13
+ export { RECOMMENDED_COLOURS, RECOMMENDED_COLOUR_CLASSES, RECOMMENDED_COLOUR_NAMESPACES, RECOMMENDED_COLOUR_PROPERTIES, RECOMMENDED_COLOUR_ROLES, RECOMMENDED_COLOUR_VARS, getRecommendedColours, isRecommendedColourClass } from "./theme/recommended.js";
14
+ import { cn } from "./lib/recipe.js";
15
+ export { Slugger, childrenToText, slugify } from "./lib/slug.js";
16
+ export { useCopyToClipboard } from "./hooks/useCopyToClipboard.js";
17
+ export { useActiveHeading } from "./hooks/useActiveHeading.js";
18
+ export { Button } from "./components/Button.js";
19
+ export { Card } from "./components/Card.js";
20
+ export { Badge } from "./components/Badge.js";
21
+ export { ReportDetails, ReportDocument, ReportSection } from "./components/ReportDocument.js";
22
+ import { TOKEN_RULES, scanRules, scanTokenRules } from "./lib/tokenRules.js";
23
+ export { Avatar } from "./components/Avatar.js";
24
+ export { PageTitle } from "./components/PageTitle.js";
25
+ export { PageHeader } from "./components/PageHeader.js";
26
+ export { Tag } from "./components/Tag.js";
27
+ export { Pagination } from "./components/Pagination.js";
28
+ export { Tabs, TabsList, TabsPanel, TabsTab } from "./components/Tabs.js";
29
+ export { SectionContainer } from "./components/SectionContainer.js";
30
+ export { DIVIDER_PATTERNS, Divider } from "./components/Divider.js";
31
+ export { AsciiDivider } from "./components/AsciiDivider.js";
32
+ export { ThemeProvider, useOptionalTheme, useTheme } from "./components/ThemeProvider.js";
33
+ export { THEME_ATTRIBUTE, THEME_STORAGE_KEY, getThemeInitScript } from "./components/themeInitScript.js";
34
+ export { BracketText } from "./components/BracketText.js";
35
+ export { NoteBlock } from "./components/NoteBlock.js";
36
+ export { TLDR } from "./components/TLDR.js";
37
+ import { Input, TextArea } from "./components/Input.js";
38
+ export { Select } from "./components/Select.js";
39
+ export { Checkbox } from "./components/Checkbox.js";
40
+ export { Switch } from "./components/Switch.js";
41
+ export { Fieldset, Legend } from "./components/Fieldset.js";
42
+ export { Radio, RadioGroup } from "./components/RadioGroup.js";
43
+ export { ErrorSummary } from "./components/ErrorSummary.js";
44
+ export { Swatch, SwatchGroup } from "./components/Swatch.js";
45
+ export { StatCard } from "./components/StatCard.js";
46
+ export { Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow } from "./components/Table.js";
47
+ export { DataTable } from "./components/DataTable.js";
48
+ export { Modal } from "./components/Modal.js";
49
+ export { AlertDialog } from "./components/AlertDialog.js";
50
+ export { Drawer } from "./components/Drawer.js";
51
+ export { AppMain, AppShell, AppSidebar, AppSidebarNav, AppTopbar } from "./components/AppShell.js";
52
+ export { Spinner } from "./components/Spinner.js";
53
+ export { Skeleton } from "./components/Skeleton.js";
54
+ export { Progress } from "./components/Progress.js";
55
+ export { EmptyState } from "./components/EmptyState.js";
56
+ export { NotFoundPage, ServerErrorPage, StatusPage } from "./components/StatusPage.js";
57
+ export { Tooltip } from "./components/Tooltip.js";
58
+ export { Popover } from "./components/Popover.js";
59
+ export { Menu, MenuItem, MenuRadioGroup, MenuRadioItem, MenuSeparator } from "./components/Menu.js";
60
+ import {
61
+ LinkProvider,
62
+ SiteLink,
63
+ isExternalHref,
64
+ useIsCurrentHref,
65
+ useLinkComponent
66
+ } from "./components/LinkProvider.js";
67
+ export { SiteHeader } from "./components/SiteHeader.js";
68
+ export { SiteNav, SiteNavItem } from "./components/SiteNav.js";
69
+ export { MobileNav } from "./components/MobileNav.js";
70
+ export { SiteFooter } from "./components/SiteFooter.js";
71
+ export { Hero } from "./components/marketing/Hero.js";
72
+ export { Feature, FeatureGrid } from "./components/marketing/FeatureGrid.js";
73
+ export { PricingGrid, PricingTier } from "./components/marketing/PricingGrid.js";
74
+ export { CTASection } from "./components/marketing/CTASection.js";
75
+ export { ToastProvider, useOptionalToast, useToast } from "./components/Toast.js";
76
+ export { NERD_GLYPHS, NerdIcon } from "./components/NerdIcon.js";
77
+ export { BlueskyIcon, GitHubIcon, LinkedInIcon, MailIcon, SocialIcon, XIcon } from "./components/SocialIcon.js";
78
+ export { Glyph } from "./components/Glyph.js";
79
+ export { AsciiGauge } from "./components/AsciiGauge.js";
80
+ export { TelemetryGauge } from "./components/TelemetryGauge.js";
81
+ export { TickerTape } from "./components/TickerTape.js";
82
+ export { BarChart, ResponsiveChartContainer } from "./components/BarChart.js";
83
+ export { Sparkline } from "./components/Sparkline.js";
84
+ export { ChartTooltip, useChartTooltip } from "./components/ChartTooltip.js";
85
+ export { BulletChart } from "./components/BulletChart.js";
86
+ export { Slide } from "./components/slides/Slide.js";
87
+ export { SLIDE_DECK_HOTKEYS, SlideDeck } from "./components/slides/SlideDeck.js";
88
+ export { BlogPost } from "./components/blog/BlogPost.js";
89
+ export { LoremIpsumPost } from "./components/blog/LoremIpsumPost.js";
90
+ export { MetadataGrid } from "./components/MetadataGrid.js";
91
+ export { TrackCard } from "./components/TrackCard.js";
92
+ export { ColophonCard } from "./components/ColophonCard.js";
93
+ export { DEFAULT_EXPERIMENTS, ExperimentsView } from "./components/experiments/ExperimentsView.js";
94
+ export { DesignSandbox } from "./components/experiments/DesignSandbox.js";
95
+ export { DEFAULT_DEPLOY_LOG, DEFAULT_PRICING_TIERS, SaasLandingPage } from "./components/saas/SaasLandingPage.js";
96
+ export { ActivityGrid, AnchorHeading, BeforeAfter, Breadcrumbs, ChangeSummary, CodeBlock, CodeBlockAttachment, CodeTab, CodeTabs, Decision, DocPager, DocsHeader, DocsLayout, DocsLink, DocsLinkProvider, DocsSidebar, DrawingSheet, Event, FigureFrame, FileChangeTree, FlowDiagram, GanttChart, IndexedSection, Line, MetricStrip, Node, Option, Path, Prose, Slope, Step, Steps, SwatchCompare, TableOfContents, Term, TermGrid, Terminal, Timeline, TokenTable, TreeDiagram, UptimeStrip, collectHeadings, createAnchorHeading, mdxComponents, useDocsLinkComponent } from "./components/docs/index.js";
97
+ export {
98
+ ANSI_SLOTS,
99
+ CSS_MEDIUM,
100
+ Input,
101
+ LinkProvider,
102
+ MEDIA,
103
+ MEDIA_DEFINITIONS,
104
+ SLOTS,
105
+ SiteLink,
106
+ TOKEN_RULES,
107
+ TextArea,
108
+ ansiScheme,
109
+ cn,
110
+ isExternalHref,
111
+ isMedium,
112
+ scanRules,
113
+ scanTokenRules,
114
+ useIsCurrentHref,
115
+ useLinkComponent
116
+ };
117
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["// @rtkelly-labs/design-system main entrypoint\n\nexport * from './tokens';\n\n// The theme ladder — the single source for level names, level colours, and the\n// contrast arithmetic that gates them.\nexport * from './theme/levels';\nexport {\n MEDIA,\n CSS_MEDIUM,\n MEDIA_DEFINITIONS,\n isMedium,\n} from './theme/media';\nexport type {\n Medium,\n MediumDefinition,\n TypeStep,\n TypeStepName,\n Motion,\n} from './theme/media';\nexport * from './theme/contrast';\nexport { ANSI_SLOTS, SLOTS, ansiScheme } from './theme/ansi';\nexport type { AnsiSlot, AnsiScheme, AnsiChrome } from './theme/ansi';\n\n// Semantic theming — prefer these over the raw palette in `tokens`.\nexport * from './lib/theme';\nexport * from './theme/recommended';\n// Only `cn` is public. `recipe`'s type comes from the library that implements\n// it, so exporting it would put that library back into the published .d.ts and\n// make replacing it a breaking change. Components import it directly.\nexport { cn } from './lib/recipe';\nexport type { ClassInput } from './lib/recipe';\nexport * from './lib/slug';\n\n// Hooks\nexport * from './hooks/useCopyToClipboard';\nexport * from './hooks/useActiveHeading';\n\n// Primitives & Callouts\nexport * from './components/Button';\nexport * from './components/Card';\nexport * from './components/Badge';\n// The report frame — the page a generated report is built in. Separate from\n// the docs components because a report is written by a tool and read once,\n// where a docs page is written by a person and read often: the frame owns the\n// measure, the header strip and the print behaviour, and everything inside it\n// is ordinary composition.\nexport * from './components/ReportDocument';\n\n// The colour-instead-of-role rules, and the scanner over them. Published\n// because a tool generating markup against this system should be able to hold\n// itself to the same rule the system holds itself to — the report generator\n// lints at budget zero with exactly these.\nexport { TOKEN_RULES, scanRules, scanTokenRules } from './lib/tokenRules';\nexport type { Finding, TokenRule } from './lib/tokenRules';\nexport * from './components/Avatar';\nexport * from './components/PageTitle';\nexport * from './components/PageHeader';\nexport * from './components/Tag';\nexport * from './components/Pagination';\n// The tablist. There is exactly one in this tree: `CodeTabs` renders through\n// it rather than hand-rolling a second keyboard model — see #240, and #163 for\n// why it is first-party rather than a wrapper over Base UI.\nexport * from './components/Tabs';\nexport * from './components/SectionContainer';\nexport * from './components/Divider';\nexport * from './components/AsciiDivider';\nexport * from './components/ThemeProvider';\n// Server-safe: a root layout calls `getThemeInitScript`, and that layout is a\n// server component under the Next App Router. See the module's header.\nexport * from './components/themeInitScript';\nexport * from './components/BracketText';\nexport * from './components/NoteBlock';\nexport * from './components/TLDR';\n// Named rather than `export *`: `Input.tsx` also exports the field recipe\n// `Select` draws its trigger with, and a recipe's type is `tailwind-variants`'.\nexport { Input, TextArea } from './components/Input';\nexport type { InputProps, TextAreaProps } from './components/Input';\n// One of a fixed set (#164): the same field as `Input`, with a listbox this\n// system paints instead of the operating system's, and `native` for the\n// platform picker when that is the better phone experience.\nexport * from './components/Select';\n// The booleans, added together: one capability in two presentations,\n// composing the same Field as the text controls above.\nexport * from './components/Checkbox';\nexport * from './components/Switch';\n// The groups (#239): `Fieldset` and `Legend` are the set's label, description\n// and error on the same Field contract, and `RadioGroup` / `Radio` are the\n// choose-one control built on that frame rather than beside it.\nexport * from './components/Fieldset';\nexport * from './components/RadioGroup';\n// The form-level half of validation (issue 50): the field errors above,\n// gathered at the top of the form as links that move focus to each field.\nexport * from './components/ErrorSummary';\nexport * from './components/Swatch';\nexport * from './components/StatCard';\nexport * from './components/Table';\nexport * from './components/DataTable';\nexport * from './components/Modal';\nexport * from './components/AlertDialog';\nexport * from './components/Drawer';\n\n// The application layout (#247): sidebar, topbar and main as five composable\n// pieces, with the sidebar off-canvas in a `Drawer` below desktop width.\nexport * from './components/AppShell';\n\n// System feedback — the three states an application has besides \"loaded\".\n// One vocabulary on purpose: the same motion tokens, the same reduced-motion\n// rule, the same muted surface, so a loading card and an empty table read as\n// the same system rather than as two consumers' guesses.\nexport * from './components/Spinner';\nexport * from './components/Skeleton';\nexport * from './components/Progress';\nexport * from './components/EmptyState';\n// The page-level states (#251) — 404, 500, maintenance, offline, unauthorized\n// — as `EmptyState` in a page frame, not a component family of their own.\nexport * from './components/StatusPage';\n\n// The floating set (#166): anchored to a trigger, positioned by the same\n// engine, dismissed by the same stack as the dialogs above. `Tooltip` labels,\n// `Popover` shows content, `Menu` offers actions.\nexport * from './components/Tooltip';\nexport * from './components/Popover';\nexport * from './components/Menu';\n\n// Site chrome (issue 246): the banner, the navigation in its two widths, and\n// the footer — layouts and landmarks that hold no items of their own. The\n// link adapter is the package's one, shared with the docs chrome: a router's\n// `Link` and its current-route test are injected once and reach both.\nexport {\n LinkProvider,\n SiteLink,\n isExternalHref,\n useIsCurrentHref,\n useLinkComponent,\n} from './components/LinkProvider';\nexport type {\n LinkComponentProps,\n LinkProviderProps,\n SiteLinkProps,\n} from './components/LinkProvider';\nexport * from './components/SiteHeader';\nexport * from './components/SiteNav';\nexport * from './components/MobileNav';\nexport * from './components/SiteFooter';\n\n// Marketing sections (issue 248): the parts a landing page is composed from.\n// Layouts that hold no copy — `SaasLandingPage` below is one composition of\n// them, and the `SaaS/LandingPage` stories build two more.\nexport * from './components/marketing/Hero';\nexport * from './components/marketing/FeatureGrid';\nexport * from './components/marketing/PricingGrid';\nexport * from './components/marketing/CTASection';\n\n// Transient notifications. Not an overlay: a toast shares neither the\n// positioning nor the dismissal model of Tooltip/Popover/Menu — it is a queue,\n// a live region and a lifetime (#243).\nexport * from './components/Toast';\n\nexport * from './components/NerdIcon';\nexport * from './components/SocialIcon';\nexport * from './components/Glyph';\n\n// Terminal & Monospace Telemetry Primitives\nexport * from './components/AsciiGauge';\nexport * from './components/TelemetryGauge';\nexport * from './components/TickerTape';\n\n// Chart Primitives & Trend Visualizers\nexport * from './components/BarChart';\nexport * from './components/Sparkline';\nexport * from './components/ChartTooltip';\nexport * from './components/BulletChart';\n\n// Slides & Presentation Deck Engine\nexport * from './components/slides/Slide';\nexport * from './components/slides/SlideDeck';\n\n// Blog & Editorial Post Foundations\nexport * from './components/blog/BlogPost';\nexport * from './components/blog/LoremIpsumPost';\nexport * from './components/MetadataGrid';\nexport * from './components/TrackCard';\nexport * from './components/ColophonCard';\n\n// Experiments Page & Design System Sandbox\nexport * from './components/experiments/ExperimentsView';\nexport * from './components/experiments/DesignSandbox';\n\n// SaaS Landing Pages\nexport * from './components/saas/SaasLandingPage';\n\n// Documentation Portal Chrome & MDX Rendering\nexport * from './components/docs';\n"],"mappings":";AAEA,cAAc;AAId,cAAc;AACd;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAQP,cAAc;AACd,SAAS,YAAY,OAAO,kBAAkB;AAI9C,cAAc;AACd,cAAc;AAId,SAAS,UAAU;AAEnB,cAAc;AAGd,cAAc;AACd,cAAc;AAGd,cAAc;AACd,cAAc;AACd,cAAc;AAMd,cAAc;AAMd,SAAS,aAAa,WAAW,sBAAsB;AAEvD,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AAId,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AAGd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AAGd,SAAS,OAAO,gBAAgB;AAKhC,cAAc;AAGd,cAAc;AACd,cAAc;AAId,cAAc;AACd,cAAc;AAGd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AAId,cAAc;AAMd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AAGd,cAAc;AAKd,cAAc;AACd,cAAc;AACd,cAAc;AAMd;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAMP,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AAKd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AAKd,cAAc;AAEd,cAAc;AACd,cAAc;AACd,cAAc;AAGd,cAAc;AACd,cAAc;AACd,cAAc;AAGd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AAGd,cAAc;AACd,cAAc;AAGd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AAGd,cAAc;AACd,cAAc;AAGd,cAAc;AAGd,cAAc;","names":[]}
@@ -0,0 +1,87 @@
1
+ // src/lib/accentClasses.ts
2
+ var CANONICAL = {
3
+ primary: "accent-primary",
4
+ secondary: "accent-secondary",
5
+ tertiary: "accent-tertiary",
6
+ quiet: "accent-quiet",
7
+ info: "intent-info",
8
+ success: "intent-success",
9
+ warning: "intent-warning",
10
+ danger: "intent-danger"
11
+ };
12
+ function canonicalAccent(token, fallback = "primary") {
13
+ return CANONICAL[token ?? fallback] ?? CANONICAL.primary;
14
+ }
15
+ var TEXT = {
16
+ "accent-primary": "text-accent-primary",
17
+ "accent-secondary": "text-accent-secondary",
18
+ "accent-tertiary": "text-accent-tertiary",
19
+ "accent-quiet": "text-accent-quiet",
20
+ "intent-info": "text-intent-info",
21
+ "intent-success": "text-intent-success",
22
+ "intent-warning": "text-intent-warning",
23
+ "intent-danger": "text-intent-danger"
24
+ };
25
+ var FOCUS_RING = {
26
+ "accent-primary": "focus:border-accent-primary focus:ring-accent-primary",
27
+ "accent-secondary": "focus:border-accent-secondary focus:ring-accent-secondary",
28
+ "accent-tertiary": "focus:border-accent-tertiary focus:ring-accent-tertiary",
29
+ "accent-quiet": "focus:border-accent-quiet focus:ring-accent-quiet",
30
+ "intent-info": "focus:border-intent-info focus:ring-intent-info",
31
+ "intent-success": "focus:border-intent-success focus:ring-intent-success",
32
+ "intent-warning": "focus:border-intent-warning focus:ring-intent-warning",
33
+ "intent-danger": "focus:border-intent-danger focus:ring-intent-danger"
34
+ };
35
+ var FILL = {
36
+ "accent-primary": "bg-accent-primary text-content-inverse",
37
+ "accent-secondary": "bg-accent-secondary text-content-inverse",
38
+ "accent-tertiary": "bg-accent-tertiary text-content-inverse",
39
+ "accent-quiet": "bg-accent-quiet text-content-inverse",
40
+ "intent-info": "bg-intent-info text-content-inverse",
41
+ "intent-success": "bg-intent-success text-content-inverse",
42
+ "intent-warning": "bg-intent-warning text-content-inverse",
43
+ "intent-danger": "bg-intent-danger text-content-inverse"
44
+ };
45
+ var FILL_HOVER = {
46
+ "accent-primary": "hover:bg-accent-secondary",
47
+ "accent-secondary": "hover:bg-accent-tertiary",
48
+ "accent-tertiary": "hover:bg-accent-primary",
49
+ "accent-quiet": "hover:bg-accent-primary",
50
+ "intent-info": "hover:bg-accent-secondary",
51
+ "intent-success": "hover:bg-accent-secondary",
52
+ "intent-warning": "hover:bg-accent-tertiary",
53
+ "intent-danger": "hover:bg-accent-primary"
54
+ };
55
+ var HOVER_EDGE = {
56
+ "accent-primary": "hover:border-accent-primary hover:shadow-hard-accent-primary",
57
+ "accent-secondary": "hover:border-accent-secondary hover:shadow-hard-accent-secondary",
58
+ "accent-tertiary": "hover:border-accent-tertiary hover:shadow-hard-accent-tertiary",
59
+ "accent-quiet": "hover:border-accent-quiet hover:shadow-hard-accent-quiet",
60
+ "intent-info": "hover:border-intent-info hover:shadow-hard-intent-info",
61
+ "intent-success": "hover:border-intent-success hover:shadow-hard-intent-success",
62
+ "intent-warning": "hover:border-intent-warning hover:shadow-hard-intent-warning",
63
+ "intent-danger": "hover:border-intent-danger hover:shadow-hard-intent-danger"
64
+ };
65
+ function accentTextClass(token, fallback) {
66
+ return TEXT[canonicalAccent(token, fallback)];
67
+ }
68
+ function accentFocusClass(token, fallback) {
69
+ return FOCUS_RING[canonicalAccent(token, fallback)];
70
+ }
71
+ function accentHoverEdgeClass(token, fallback) {
72
+ return HOVER_EDGE[canonicalAccent(token, fallback)];
73
+ }
74
+ function accentFillClass(token, fallback) {
75
+ const role = canonicalAccent(token, fallback);
76
+ return `${FILL[role]} ${FILL_HOVER[role]}`;
77
+ }
78
+ var ACCENT_CLASS_MAPS = { TEXT, FOCUS_RING, HOVER_EDGE, FILL, FILL_HOVER };
79
+ export {
80
+ ACCENT_CLASS_MAPS,
81
+ accentFillClass,
82
+ accentFocusClass,
83
+ accentHoverEdgeClass,
84
+ accentTextClass,
85
+ canonicalAccent
86
+ };
87
+ //# sourceMappingURL=accentClasses.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/lib/accentClasses.ts"],"sourcesContent":["/**\n * Accent tokens as Tailwind utility classes.\n *\n * `accentVar()` in `./theme` covers inline styles. Components built from\n * utility classes need the same mapping as literal class strings, because\n * Tailwind's scanner reads source text — a template literal like\n * `text-${role}` produces no CSS at all. Every class below is therefore\n * spelled out, and the 12 accepted tokens collapse onto 8 canonical roles\n * first so each map stays one entry per role rather than one per alias.\n */\n\nimport type { AccentToken } from './theme';\n\n/** The role an accent token names, as it appears in Tailwind class names. */\nexport type CanonicalAccent =\n | 'accent-primary'\n | 'accent-secondary'\n | 'accent-tertiary'\n | 'accent-quiet'\n | 'intent-info'\n | 'intent-success'\n | 'intent-warning'\n | 'intent-danger';\n\n/** Every accepted token mapped to its role. */\nconst CANONICAL: Record<AccentToken, CanonicalAccent> = {\n primary: 'accent-primary',\n secondary: 'accent-secondary',\n tertiary: 'accent-tertiary',\n quiet: 'accent-quiet',\n info: 'intent-info',\n success: 'intent-success',\n warning: 'intent-warning',\n danger: 'intent-danger',\n};\n\n/**\n * Resolve any accent token to its role. Mirrors `accentVar()`: an unrecognised\n * token degrades to the primary accent rather than throwing, so a mistyped prop\n * renders something legible instead of dropping the class entirely.\n */\nexport function canonicalAccent(\n token: AccentToken | undefined,\n fallback: AccentToken = 'primary',\n): CanonicalAccent {\n return CANONICAL[token ?? fallback] ?? CANONICAL.primary;\n}\n\nconst TEXT: Record<CanonicalAccent, string> = {\n 'accent-primary': 'text-accent-primary',\n 'accent-secondary': 'text-accent-secondary',\n 'accent-tertiary': 'text-accent-tertiary',\n 'accent-quiet': 'text-accent-quiet',\n 'intent-info': 'text-intent-info',\n 'intent-success': 'text-intent-success',\n 'intent-warning': 'text-intent-warning',\n 'intent-danger': 'text-intent-danger',\n};\n\nconst FOCUS_RING: Record<CanonicalAccent, string> = {\n 'accent-primary': 'focus:border-accent-primary focus:ring-accent-primary',\n 'accent-secondary': 'focus:border-accent-secondary focus:ring-accent-secondary',\n 'accent-tertiary': 'focus:border-accent-tertiary focus:ring-accent-tertiary',\n 'accent-quiet': 'focus:border-accent-quiet focus:ring-accent-quiet',\n 'intent-info': 'focus:border-intent-info focus:ring-intent-info',\n 'intent-success': 'focus:border-intent-success focus:ring-intent-success',\n 'intent-warning': 'focus:border-intent-warning focus:ring-intent-warning',\n 'intent-danger': 'focus:border-intent-danger focus:ring-intent-danger',\n};\n\n/**\n * A filled chip: the role as a background, with `text.inverse` on it.\n *\n * `text.inverse` is why this is a map and not a template — `check:contrast`\n * measures `text.inverse` against every accent and intent precisely because\n * this pairing exists, so the two must not be able to disagree.\n */\nconst FILL: Record<CanonicalAccent, string> = {\n 'accent-primary': 'bg-accent-primary text-content-inverse',\n 'accent-secondary': 'bg-accent-secondary text-content-inverse',\n 'accent-tertiary': 'bg-accent-tertiary text-content-inverse',\n 'accent-quiet': 'bg-accent-quiet text-content-inverse',\n 'intent-info': 'bg-intent-info text-content-inverse',\n 'intent-success': 'bg-intent-success text-content-inverse',\n 'intent-warning': 'bg-intent-warning text-content-inverse',\n 'intent-danger': 'bg-intent-danger text-content-inverse',\n};\n\n/**\n * The hover fill, which deliberately names a *different* role from the one it\n * hovers off — `Tag` rotates through the emphasis accents so a row of chips\n * animates rather than merely dimming.\n *\n * Kept separate from {@link FILL} for that reason: every other map here emits\n * one role per token and is tested for it, and folding the rotation in would\n * have to relax that test for all of them. This is the one map where naming a\n * second role is the point rather than a bug.\n *\n * The rotation itself is a visual choice with no deeper rationale, which is\n * worth stating — it came from `Tag`, was the only table in the repo that had\n * it, and is now written once instead of being re-derived.\n */\nconst FILL_HOVER: Record<CanonicalAccent, string> = {\n 'accent-primary': 'hover:bg-accent-secondary',\n 'accent-secondary': 'hover:bg-accent-tertiary',\n 'accent-tertiary': 'hover:bg-accent-primary',\n 'accent-quiet': 'hover:bg-accent-primary',\n 'intent-info': 'hover:bg-accent-secondary',\n 'intent-success': 'hover:bg-accent-secondary',\n 'intent-warning': 'hover:bg-accent-tertiary',\n 'intent-danger': 'hover:bg-accent-primary',\n};\n\nconst HOVER_EDGE: Record<CanonicalAccent, string> = {\n 'accent-primary': 'hover:border-accent-primary hover:shadow-hard-accent-primary',\n 'accent-secondary': 'hover:border-accent-secondary hover:shadow-hard-accent-secondary',\n 'accent-tertiary': 'hover:border-accent-tertiary hover:shadow-hard-accent-tertiary',\n 'accent-quiet': 'hover:border-accent-quiet hover:shadow-hard-accent-quiet',\n 'intent-info': 'hover:border-intent-info hover:shadow-hard-intent-info',\n 'intent-success': 'hover:border-intent-success hover:shadow-hard-intent-success',\n 'intent-warning': 'hover:border-intent-warning hover:shadow-hard-intent-warning',\n 'intent-danger': 'hover:border-intent-danger hover:shadow-hard-intent-danger',\n};\n\n/** Foreground colour for an accent token. */\nexport function accentTextClass(token: AccentToken | undefined, fallback?: AccentToken): string {\n return TEXT[canonicalAccent(token, fallback)];\n}\n\n/** Focus border + ring for form controls. */\nexport function accentFocusClass(token: AccentToken | undefined, fallback?: AccentToken): string {\n return FOCUS_RING[canonicalAccent(token, fallback)];\n}\n\n/** Hover border + hard offset shadow, for cards that lift on hover. */\nexport function accentHoverEdgeClass(\n token: AccentToken | undefined,\n fallback?: AccentToken,\n): string {\n return HOVER_EDGE[canonicalAccent(token, fallback)];\n}\n\n/** Exposed for tests, which assert every role is spelled out in every map. */\n/** Filled chip, with the hover rotation. */\nexport function accentFillClass(token: AccentToken | undefined, fallback?: AccentToken): string {\n const role = canonicalAccent(token, fallback);\n return `${FILL[role]} ${FILL_HOVER[role]}`;\n}\n\nexport const ACCENT_CLASS_MAPS = { TEXT, FOCUS_RING, HOVER_EDGE, FILL, FILL_HOVER } as const;\n"],"mappings":";AAyBA,IAAM,YAAkD;AAAA,EACtD,SAAS;AAAA,EACT,WAAW;AAAA,EACX,UAAU;AAAA,EACV,OAAO;AAAA,EACP,MAAM;AAAA,EACN,SAAS;AAAA,EACT,SAAS;AAAA,EACT,QAAQ;AACV;AAOO,SAAS,gBACd,OACA,WAAwB,WACP;AACjB,SAAO,UAAU,SAAS,QAAQ,KAAK,UAAU;AACnD;AAEA,IAAM,OAAwC;AAAA,EAC5C,kBAAkB;AAAA,EAClB,oBAAoB;AAAA,EACpB,mBAAmB;AAAA,EACnB,gBAAgB;AAAA,EAChB,eAAe;AAAA,EACf,kBAAkB;AAAA,EAClB,kBAAkB;AAAA,EAClB,iBAAiB;AACnB;AAEA,IAAM,aAA8C;AAAA,EAClD,kBAAkB;AAAA,EAClB,oBAAoB;AAAA,EACpB,mBAAmB;AAAA,EACnB,gBAAgB;AAAA,EAChB,eAAe;AAAA,EACf,kBAAkB;AAAA,EAClB,kBAAkB;AAAA,EAClB,iBAAiB;AACnB;AASA,IAAM,OAAwC;AAAA,EAC5C,kBAAkB;AAAA,EAClB,oBAAoB;AAAA,EACpB,mBAAmB;AAAA,EACnB,gBAAgB;AAAA,EAChB,eAAe;AAAA,EACf,kBAAkB;AAAA,EAClB,kBAAkB;AAAA,EAClB,iBAAiB;AACnB;AAgBA,IAAM,aAA8C;AAAA,EAClD,kBAAkB;AAAA,EAClB,oBAAoB;AAAA,EACpB,mBAAmB;AAAA,EACnB,gBAAgB;AAAA,EAChB,eAAe;AAAA,EACf,kBAAkB;AAAA,EAClB,kBAAkB;AAAA,EAClB,iBAAiB;AACnB;AAEA,IAAM,aAA8C;AAAA,EAClD,kBAAkB;AAAA,EAClB,oBAAoB;AAAA,EACpB,mBAAmB;AAAA,EACnB,gBAAgB;AAAA,EAChB,eAAe;AAAA,EACf,kBAAkB;AAAA,EAClB,kBAAkB;AAAA,EAClB,iBAAiB;AACnB;AAGO,SAAS,gBAAgB,OAAgC,UAAgC;AAC9F,SAAO,KAAK,gBAAgB,OAAO,QAAQ,CAAC;AAC9C;AAGO,SAAS,iBAAiB,OAAgC,UAAgC;AAC/F,SAAO,WAAW,gBAAgB,OAAO,QAAQ,CAAC;AACpD;AAGO,SAAS,qBACd,OACA,UACQ;AACR,SAAO,WAAW,gBAAgB,OAAO,QAAQ,CAAC;AACpD;AAIO,SAAS,gBAAgB,OAAgC,UAAgC;AAC9F,QAAM,OAAO,gBAAgB,OAAO,QAAQ;AAC5C,SAAO,GAAG,KAAK,IAAI,CAAC,IAAI,WAAW,IAAI,CAAC;AAC1C;AAEO,IAAM,oBAAoB,EAAE,MAAM,YAAY,YAAY,MAAM,WAAW;","names":[]}
@@ -0,0 +1,33 @@
1
+ // src/lib/recipe.ts
2
+ import { createTV, cn as merge } from "tailwind-variants";
3
+ var mergeConfig = {
4
+ extend: {
5
+ theme: {
6
+ shadow: [
7
+ "hard-sm",
8
+ "hard-md",
9
+ "hard-lg",
10
+ // The role-named hard shadows belong in the same group: a card that
11
+ // sets `shadow-hard-accent-primary` on hover still needs
12
+ // `shadow-none` to be able to clear it.
13
+ "hard-accent-primary",
14
+ "hard-accent-secondary",
15
+ "hard-accent-tertiary",
16
+ "hard-accent-quiet",
17
+ "hard-intent-info",
18
+ "hard-intent-success",
19
+ "hard-intent-warning",
20
+ "hard-intent-danger"
21
+ ]
22
+ }
23
+ }
24
+ };
25
+ var recipe = createTV({ twMergeConfig: mergeConfig });
26
+ function cn(...inputs) {
27
+ return merge(...inputs) ?? "";
28
+ }
29
+ export {
30
+ cn,
31
+ recipe
32
+ };
33
+ //# sourceMappingURL=recipe.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/lib/recipe.ts"],"sourcesContent":["/**\n * The style recipe builder every component uses.\n *\n * A *recipe* is the set of class strings one component needs: a base, one entry\n * per element it renders (a \"slot\"), and the variants that switch between them.\n * `src/components/Input.tsx` is the worked example.\n *\n * ## Why a builder at all\n *\n * Components used to compose classes by appending the consumer's `className` to\n * the end of a template string. That does nothing. Tailwind decides which of two\n * conflicting utilities wins by **CSS source order**, not by the order they\n * appear in the class attribute — so a consumer passing `bg-surface-raised` to a\n * component whose base is `bg-surface-base` got whichever the stylesheet\n * happened to emit later. Every `className` prop in this package was unreliable\n * in exactly that way.\n *\n * A recipe resolves conflicts before the class string reaches the DOM, so the\n * caller's value genuinely wins. That is a correctness fix, not an ergonomic one.\n *\n * ## The engine is an implementation detail\n *\n * `tailwind-variants` is what currently builds these, chosen because most\n * components here style more than one element — a field is a label, a control\n * and a message — and the alternatives model one element per recipe. It is not\n * part of this package's vocabulary or its public types: components import\n * `recipe` from here, and nothing downstream names the library. Swapping it is\n * then an edit to this file rather than to thirty components.\n */\n\nimport { createTV, cn as merge } from 'tailwind-variants';\n\n/**\n * Almost nothing needs declaring here, which is worth knowing before anyone\n * adds to it: the class merger classifies our semantic tokens correctly with no\n * configuration at all. `bg-surface-raised` beats `bg-surface-base`,\n * `text-accent-primary` beats `text-content-primary`, and — the case that\n * actually matters — a colour and a size in the same `text-*` position are\n * recognised as different properties, so `text-content-primary text-sm`\n * survives intact.\n *\n * The hard shadows are the exception. `shadow-hard-md` is read as a custom\n * shadow value while `shadow-none` is read as box-shadow, so without this the\n * two would both survive and the CSS would arbitrate — meaning `shadow-none`\n * could not reliably clear a hard shadow. Declaring the scale puts them in one\n * group.\n *\n * Not exported from the package: it describes the merger's config format, which\n * is exactly the detail this module exists to contain.\n */\nconst mergeConfig = {\n extend: {\n theme: {\n shadow: [\n 'hard-sm',\n 'hard-md',\n 'hard-lg',\n // The role-named hard shadows belong in the same group: a card that\n // sets `shadow-hard-accent-primary` on hover still needs\n // `shadow-none` to be able to clear it.\n 'hard-accent-primary',\n 'hard-accent-secondary',\n 'hard-accent-tertiary',\n 'hard-accent-quiet',\n 'hard-intent-info',\n 'hard-intent-success',\n 'hard-intent-warning',\n 'hard-intent-danger',\n ],\n },\n },\n} as const;\n\n/**\n * Build a component's styles.\n *\n * ```ts\n * const field = recipe({\n * slots: { root: 'flex flex-col', label: 'text-xs uppercase' },\n * variants: { invalid: { true: { label: 'text-intent-danger' } } },\n * });\n *\n * const styles = field({ invalid: true });\n * <label className={styles.label({ class: className })} />\n * ```\n *\n * Deliberately not re-exported from the package entrypoint. Its type comes from\n * the underlying library, so exporting it would put that library back into the\n * published `.d.ts` and make it a breaking change to replace.\n */\nexport const recipe = createTV({ twMergeConfig: mergeConfig });\n\n/** Anything accepted as a class: strings, falsy values, arrays, or nested ones. */\nexport type ClassInput = string | number | null | undefined | false | ClassInput[];\n\n/**\n * Join class names, resolving Tailwind conflicts so the last value wins.\n *\n * For one-off composition outside a recipe — and for consumers building their\n * own components on this system, which is why the signature is written out here\n * rather than inherited from the library.\n */\nexport function cn(...inputs: ClassInput[]): string {\n // The underlying merger returns `undefined` when everything is filtered out.\n // A `className` of `undefined` is legal in React but awkward to compose with,\n // so this narrows to a string — which is also why the signature is written\n // here rather than inherited.\n return merge(...(inputs as Parameters<typeof merge>)) ?? '';\n}\n"],"mappings":";AA8BA,SAAS,UAAU,MAAM,aAAa;AAoBtC,IAAM,cAAc;AAAA,EAClB,QAAQ;AAAA,IACN,OAAO;AAAA,MACL,QAAQ;AAAA,QACN;AAAA,QACA;AAAA,QACA;AAAA;AAAA;AAAA;AAAA,QAIA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAmBO,IAAM,SAAS,SAAS,EAAE,eAAe,YAAY,CAAC;AAYtD,SAAS,MAAM,QAA8B;AAKlD,SAAO,MAAM,GAAI,MAAmC,KAAK;AAC3D;","names":[]}
@@ -0,0 +1,39 @@
1
+ // src/lib/slug.ts
2
+ var STRIP = /[ -⸀-⹿\\'!"#$%&()*+,./:;<=>?@[\]^`{|}~–—‘’“”]/g;
3
+ function slugify(value) {
4
+ return value.trim().toLowerCase().replace(STRIP, "").replace(/\s/g, "-");
5
+ }
6
+ var Slugger = class {
7
+ seen = /* @__PURE__ */ new Map();
8
+ slug(value) {
9
+ const base = slugify(value);
10
+ const count = this.seen.get(base);
11
+ if (count === void 0) {
12
+ this.seen.set(base, 0);
13
+ return base;
14
+ }
15
+ const next = count + 1;
16
+ this.seen.set(base, next);
17
+ return `${base}-${next}`;
18
+ }
19
+ reset() {
20
+ this.seen.clear();
21
+ }
22
+ };
23
+ function childrenToText(node) {
24
+ if (node === null || node === void 0 || typeof node === "boolean") return "";
25
+ if (typeof node === "string") return node;
26
+ if (typeof node === "number") return String(node);
27
+ if (Array.isArray(node)) return node.map(childrenToText).join("");
28
+ if (typeof node === "object" && "props" in node) {
29
+ const props = node.props;
30
+ if (props && "children" in props) return childrenToText(props.children);
31
+ }
32
+ return "";
33
+ }
34
+ export {
35
+ Slugger,
36
+ childrenToText,
37
+ slugify
38
+ };
39
+ //# sourceMappingURL=slug.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/lib/slug.ts"],"sourcesContent":["/**\n * Heading slug generation, kept deliberately compatible with `github-slugger`\n * (the slugger behind `rehype-slug`).\n *\n * The docs pipeline generates heading `id`s at build time via `rehype-slug`,\n * but the same ids have to be derivable on the client — the table of contents,\n * the scroll-spy observer, and the copy-link affordance all need to agree on\n * what `#some-heading` refers to. Reimplementing the same rules here means a\n * runtime-built TOC lands on the same anchors as a remark-built one.\n */\n\n/**\n * Characters github-slugger strips outright. Kept as an explicit class rather\n * than a `\\W` negation so that accented latin, CJK, and emoji-adjacent glyphs\n * survive the same way they do on GitHub.\n */\nconst STRIP =\n /[ -⸀-⹿\\\\'!\"#$%&()*+,./:;<=>?@[\\]^`{|}~–—‘’“”]/g;\n\n/** Slugify a single heading string. Does not deduplicate — see {@link Slugger}. */\nexport function slugify(value: string): string {\n return value\n .trim()\n .toLowerCase()\n .replace(STRIP, '')\n .replace(/\\s/g, '-');\n}\n\n/**\n * Stateful slugger that appends `-1`, `-2`, … to repeated headings, matching\n * `github-slugger`. Create one per document; reuse across documents would leak\n * counts between pages and desynchronise the anchors from the rendered HTML.\n */\nexport class Slugger {\n private readonly seen = new Map<string, number>();\n\n slug(value: string): string {\n const base = slugify(value);\n const count = this.seen.get(base);\n\n if (count === undefined) {\n this.seen.set(base, 0);\n return base;\n }\n\n const next = count + 1;\n this.seen.set(base, next);\n return `${base}-${next}`;\n }\n\n reset(): void {\n this.seen.clear();\n }\n}\n\n/**\n * Extract the plain text of a React child tree so a heading rendered as\n * `<h2>The <code>tvs</code> CLI</h2>` still slugs to `the-tvs-cli`.\n *\n * Only walks strings, numbers, arrays, and elements with `children` in props —\n * anything else (a component that renders text internally) is invisible here,\n * which is why {@link AnchorHeading} also accepts an explicit `id`.\n */\nexport function childrenToText(node: unknown): string {\n if (node === null || node === undefined || typeof node === 'boolean') return '';\n if (typeof node === 'string') return node;\n if (typeof node === 'number') return String(node);\n if (Array.isArray(node)) return node.map(childrenToText).join('');\n\n if (typeof node === 'object' && 'props' in node) {\n const props = (node as { props?: { children?: unknown } }).props;\n if (props && 'children' in props) return childrenToText(props.children);\n }\n\n return '';\n}\n"],"mappings":";AAgBA,IAAM,QACJ;AAGK,SAAS,QAAQ,OAAuB;AAC7C,SAAO,MACJ,KAAK,EACL,YAAY,EACZ,QAAQ,OAAO,EAAE,EACjB,QAAQ,OAAO,GAAG;AACvB;AAOO,IAAM,UAAN,MAAc;AAAA,EACF,OAAO,oBAAI,IAAoB;AAAA,EAEhD,KAAK,OAAuB;AAC1B,UAAM,OAAO,QAAQ,KAAK;AAC1B,UAAM,QAAQ,KAAK,KAAK,IAAI,IAAI;AAEhC,QAAI,UAAU,QAAW;AACvB,WAAK,KAAK,IAAI,MAAM,CAAC;AACrB,aAAO;AAAA,IACT;AAEA,UAAM,OAAO,QAAQ;AACrB,SAAK,KAAK,IAAI,MAAM,IAAI;AACxB,WAAO,GAAG,IAAI,IAAI,IAAI;AAAA,EACxB;AAAA,EAEA,QAAc;AACZ,SAAK,KAAK,MAAM;AAAA,EAClB;AACF;AAUO,SAAS,eAAe,MAAuB;AACpD,MAAI,SAAS,QAAQ,SAAS,UAAa,OAAO,SAAS,UAAW,QAAO;AAC7E,MAAI,OAAO,SAAS,SAAU,QAAO;AACrC,MAAI,OAAO,SAAS,SAAU,QAAO,OAAO,IAAI;AAChD,MAAI,MAAM,QAAQ,IAAI,EAAG,QAAO,KAAK,IAAI,cAAc,EAAE,KAAK,EAAE;AAEhE,MAAI,OAAO,SAAS,YAAY,WAAW,MAAM;AAC/C,UAAM,QAAS,KAA4C;AAC3D,QAAI,SAAS,cAAc,MAAO,QAAO,eAAe,MAAM,QAAQ;AAAA,EACxE;AAEA,SAAO;AACT;","names":[]}
@@ -0,0 +1,76 @@
1
+ // src/lib/theme.ts
2
+ var EMPHASIS_VARS = {
3
+ primary: "var(--ds-accent-primary)",
4
+ secondary: "var(--ds-accent-secondary)",
5
+ tertiary: "var(--ds-accent-tertiary)",
6
+ quiet: "var(--ds-accent-quiet)"
7
+ };
8
+ var INTENT_VARS = {
9
+ info: "var(--ds-intent-info)",
10
+ success: "var(--ds-intent-success)",
11
+ warning: "var(--ds-intent-warning)",
12
+ danger: "var(--ds-intent-danger)"
13
+ };
14
+ var SURFACE_VARS = {
15
+ base: "var(--ds-surface-base)",
16
+ raised: "var(--ds-surface-raised)",
17
+ sunken: "var(--ds-surface-sunken)",
18
+ overlay: "var(--ds-surface-overlay)"
19
+ };
20
+ var TEXT_VARS = {
21
+ primary: "var(--ds-text-primary)",
22
+ secondary: "var(--ds-text-secondary)",
23
+ muted: "var(--ds-text-muted)",
24
+ inverse: "var(--ds-text-inverse)"
25
+ };
26
+ var BORDER_VARS = {
27
+ strong: "var(--ds-border-strong)",
28
+ default: "var(--ds-border-default)",
29
+ subtle: "var(--ds-border-subtle)"
30
+ };
31
+ function accentVar(token, fallback = "primary") {
32
+ const resolved = token ?? fallback;
33
+ return EMPHASIS_VARS[resolved] ?? INTENT_VARS[resolved] ?? EMPHASIS_VARS.primary;
34
+ }
35
+ function surfaceVar(token = "base") {
36
+ return SURFACE_VARS[token] ?? SURFACE_VARS.base;
37
+ }
38
+ function textVar(token = "primary") {
39
+ return TEXT_VARS[token] ?? TEXT_VARS.primary;
40
+ }
41
+ function borderVar(token = "strong") {
42
+ return BORDER_VARS[token] ?? BORDER_VARS.strong;
43
+ }
44
+ var fontVar = {
45
+ display: "var(--ds-font-display)",
46
+ body: "var(--ds-font-body)",
47
+ mono: "var(--ds-font-mono)",
48
+ pixel: "var(--ds-font-pixel)"
49
+ };
50
+ var HEADING_EMPHASIS = {
51
+ 1: "primary",
52
+ 2: "primary",
53
+ 3: "secondary",
54
+ 4: "tertiary",
55
+ 5: "quiet",
56
+ 6: "quiet"
57
+ };
58
+ var semanticTokens = {
59
+ accent: EMPHASIS_VARS,
60
+ intent: INTENT_VARS,
61
+ surface: SURFACE_VARS,
62
+ text: TEXT_VARS,
63
+ border: BORDER_VARS,
64
+ font: fontVar,
65
+ shadowColor: "var(--ds-shadow-color)"
66
+ };
67
+ export {
68
+ HEADING_EMPHASIS,
69
+ accentVar,
70
+ borderVar,
71
+ fontVar,
72
+ semanticTokens,
73
+ surfaceVar,
74
+ textVar
75
+ };
76
+ //# sourceMappingURL=theme.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/lib/theme.ts"],"sourcesContent":["/**\n * Semantic theming layer.\n *\n * Components should describe *what a thing is* — a primary accent, a danger\n * state, a raised surface — never which colour it happens to be. The brutalist\n * palette (cyan/pink/yellow/green) is one mapping of those roles; `.dim` and\n * `.sketch` are others, and a future mode is a third. Referencing\n * `var(--brutalist-cyan)` directly hard-codes today's mapping into every\n * component and makes retheming a find-and-replace across the package.\n *\n * The CSS variables below are declared in `theme.css` and resolve through the\n * raw palette, so they follow every mode swap automatically.\n */\n\n/**\n * Visual weight within a hierarchy. Use for decorative and navigational\n * emphasis — which of several things should draw the eye first — not for\n * meaning. `quiet` is the de-emphasised step, not a fifth colour.\n */\nexport type Emphasis = 'primary' | 'secondary' | 'tertiary' | 'quiet';\n\n/**\n * Communicated meaning. Use when the colour carries information the reader\n * must act on; these survive retheming because their semantics are fixed even\n * when their hues are not.\n */\nexport type Intent = 'info' | 'success' | 'warning' | 'danger';\n\n/**\n * Background elevation. `base` is the page, `raised` sits above it (cards,\n * header, drawers), `sunken` is inset (code wells), `overlay` is modal.\n */\nexport type Surface = 'base' | 'raised' | 'sunken' | 'overlay';\n\n/** Text prominence, coarsest to faintest. */\nexport type TextTone = 'primary' | 'secondary' | 'muted' | 'inverse';\n\n/** Rule weight. `strong` is the full-contrast brutalist border. */\nexport type BorderTone = 'strong' | 'default' | 'subtle';\n\n/**\n * Palette names accepted by components predating the semantic layer.\n *\n * @deprecated Pass an {@link Emphasis} or {@link Intent} instead. These remain\n * accepted so existing consumers keep compiling, and they resolve to the same\n * values, but they defeat the point of the abstraction.\n */\n/**\n * A colour's *appearance*, independent of any job — the vocabulary a Target\n * addresses when it has no notion of jobs. A terminal has sixteen positions\n * named by colour and no concept of a keyword.\n *\n * Declared below the Role vocabulary and referenced by it, never the reverse:\n * Hue -> Role is a declared lookup, Role -> Hue is a guess. See\n * `docs/adr/0001-hues-declared-below-roles.md`.\n *\n * **A Hue in component code is a defect.** Components address Roles only.\n * Ten is the ceiling rather than a comfortable middle — the tightest pair\n * already sits at deltaE 0.049. See `docs/palette-provenance.md`.\n */\nexport type Hue =\n | 'red'\n | 'orange'\n | 'yellow'\n | 'green'\n | 'teal'\n | 'cyan'\n | 'blue'\n | 'violet'\n | 'magenta'\n | 'pink';\n\n/**\n * The eight ANSI base slots a terminal needs, beyond which `bright` variants\n * fill the upper eight. `black` and `white` come from `FIXED_COLOURS`.\n */\nexport type AnsiHue = Extract<Hue, 'red' | 'green' | 'yellow' | 'blue' | 'magenta' | 'cyan'>;\n\n/**\n * What a Role points at in the Hue vocabulary.\n *\n * `'neutral'` is not a cop-out: some Roles genuinely are not hues.\n * `accent.quiet` is a warm or cool grey by design, and the palette has no\n * neutral ramp to point it at. Saying so explicitly keeps the map exhaustive —\n * a new Emphasis is still a compile error — while letting the gate distinguish\n * \"declared as not-a-hue\" from \"forgot to wire it up\", which a `Partial` could\n * not.\n */\nexport type HueRef = Hue | 'neutral';\n\n\n/** Anything a component's `accent`-style prop will take. */\nexport type AccentToken = Emphasis | Intent;\n\nconst EMPHASIS_VARS: Record<Emphasis, string> = {\n primary: 'var(--ds-accent-primary)',\n secondary: 'var(--ds-accent-secondary)',\n tertiary: 'var(--ds-accent-tertiary)',\n quiet: 'var(--ds-accent-quiet)',\n};\n\nconst INTENT_VARS: Record<Intent, string> = {\n info: 'var(--ds-intent-info)',\n success: 'var(--ds-intent-success)',\n warning: 'var(--ds-intent-warning)',\n danger: 'var(--ds-intent-danger)',\n};\n\nconst SURFACE_VARS: Record<Surface, string> = {\n base: 'var(--ds-surface-base)',\n raised: 'var(--ds-surface-raised)',\n sunken: 'var(--ds-surface-sunken)',\n overlay: 'var(--ds-surface-overlay)',\n};\n\nconst TEXT_VARS: Record<TextTone, string> = {\n primary: 'var(--ds-text-primary)',\n secondary: 'var(--ds-text-secondary)',\n muted: 'var(--ds-text-muted)',\n inverse: 'var(--ds-text-inverse)',\n};\n\nconst BORDER_VARS: Record<BorderTone, string> = {\n strong: 'var(--ds-border-strong)',\n default: 'var(--ds-border-default)',\n subtle: 'var(--ds-border-subtle)',\n};\n\n/**\n * Resolve any accent token to the CSS variable expression that renders it.\n *\n * Unknown values fall back to the primary accent rather than throwing —\n * a mistyped prop should degrade to something legible, not blank out a\n * component's colour and leave `color: undefined` on the element.\n */\nexport function accentVar(token: AccentToken | undefined, fallback: AccentToken = 'primary'): string {\n const resolved = token ?? fallback;\n return (\n EMPHASIS_VARS[resolved as Emphasis] ??\n INTENT_VARS[resolved as Intent] ??\n EMPHASIS_VARS.primary\n );\n}\n\nexport function surfaceVar(token: Surface = 'base'): string {\n return SURFACE_VARS[token] ?? SURFACE_VARS.base;\n}\n\nexport function textVar(token: TextTone = 'primary'): string {\n return TEXT_VARS[token] ?? TEXT_VARS.primary;\n}\n\nexport function borderVar(token: BorderTone = 'strong'): string {\n return BORDER_VARS[token] ?? BORDER_VARS.strong;\n}\n\n/** Semantic font roles. */\nexport const fontVar = {\n display: 'var(--ds-font-display)',\n body: 'var(--ds-font-body)',\n mono: 'var(--ds-font-mono)',\n pixel: 'var(--ds-font-pixel)',\n} as const;\n\n/**\n * Default emphasis per heading level, so a document's colour hierarchy follows\n * its structural hierarchy without every call site restating it.\n */\nexport const HEADING_EMPHASIS: Record<1 | 2 | 3 | 4 | 5 | 6, Emphasis> = {\n 1: 'primary',\n 2: 'primary',\n 3: 'secondary',\n 4: 'tertiary',\n 5: 'quiet',\n 6: 'quiet',\n};\n\n/**\n * The full semantic token surface, as CSS variable expressions. Useful for\n * inline styles and for consumers building their own components on the system.\n */\nexport const semanticTokens = {\n accent: EMPHASIS_VARS,\n intent: INTENT_VARS,\n surface: SURFACE_VARS,\n text: TEXT_VARS,\n border: BORDER_VARS,\n font: fontVar,\n shadowColor: 'var(--ds-shadow-color)',\n} as const;\n"],"mappings":";AA8FA,IAAM,gBAA0C;AAAA,EAC9C,SAAS;AAAA,EACT,WAAW;AAAA,EACX,UAAU;AAAA,EACV,OAAO;AACT;AAEA,IAAM,cAAsC;AAAA,EAC1C,MAAM;AAAA,EACN,SAAS;AAAA,EACT,SAAS;AAAA,EACT,QAAQ;AACV;AAEA,IAAM,eAAwC;AAAA,EAC5C,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,SAAS;AACX;AAEA,IAAM,YAAsC;AAAA,EAC1C,SAAS;AAAA,EACT,WAAW;AAAA,EACX,OAAO;AAAA,EACP,SAAS;AACX;AAEA,IAAM,cAA0C;AAAA,EAC9C,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,QAAQ;AACV;AASO,SAAS,UAAU,OAAgC,WAAwB,WAAmB;AACnG,QAAM,WAAW,SAAS;AAC1B,SACE,cAAc,QAAoB,KAClC,YAAY,QAAkB,KAC9B,cAAc;AAElB;AAEO,SAAS,WAAW,QAAiB,QAAgB;AAC1D,SAAO,aAAa,KAAK,KAAK,aAAa;AAC7C;AAEO,SAAS,QAAQ,QAAkB,WAAmB;AAC3D,SAAO,UAAU,KAAK,KAAK,UAAU;AACvC;AAEO,SAAS,UAAU,QAAoB,UAAkB;AAC9D,SAAO,YAAY,KAAK,KAAK,YAAY;AAC3C;AAGO,IAAM,UAAU;AAAA,EACrB,SAAS;AAAA,EACT,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AACT;AAMO,IAAM,mBAA4D;AAAA,EACvE,GAAG;AAAA,EACH,GAAG;AAAA,EACH,GAAG;AAAA,EACH,GAAG;AAAA,EACH,GAAG;AAAA,EACH,GAAG;AACL;AAMO,IAAM,iBAAiB;AAAA,EAC5B,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,aAAa;AACf;","names":[]}
@@ -0,0 +1,51 @@
1
+ // src/lib/tokenRules.ts
2
+ var TOKEN_RULES = [
3
+ {
4
+ id: "hex",
5
+ label: "Hex literals",
6
+ pattern: /#[0-9a-fA-F]{3,8}\b/g,
7
+ fix: "Use a --ds-* token or a semantic utility (bg-surface-raised, text-accent-primary)."
8
+ },
9
+ {
10
+ id: "rawPalette",
11
+ label: "Literal Tailwind palette utilities",
12
+ pattern: /\b(?:bg|text|border|divide|placeholder|ring|from|to|via)-(?:white|black|zinc|gray|slate|neutral|stone|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose)(?:-\d{2,3})?(?:\/\d{1,3})?\b/g,
13
+ fix: "Use the semantic utilities: bg-surface-*, text-content-*, border-edge-*, text-intent-*."
14
+ },
15
+ {
16
+ id: "legacyAlias",
17
+ label: "Legacy brutalist-* colour aliases",
18
+ // `brutalist-card` / `-btn` / `-badge` are component classes in styles.css,
19
+ // already written against roles — they are not colour names and stay.
20
+ pattern: /\bbrutalist-(?:cyan|neonCyan|pink|yellow|neonGreen|green|cyberOrange|darkBg|shadow-color)\b/g,
21
+ fix: "Use accent-*/intent-* utilities or --ds-* tokens. Blocks removing the compat block in theme.css."
22
+ },
23
+ {
24
+ id: "darkVariant",
25
+ label: "dark: colour variants",
26
+ pattern: /\bdark:(?:bg|text|border|divide|placeholder|ring|from|to|via)-/g,
27
+ fix: 'Tokens switch on their own. dark: is only for non-colour utilities, and means "midnight or dim" now.'
28
+ }
29
+ ];
30
+ function scanRules(source, rules) {
31
+ const findings = [];
32
+ source.split("\n").forEach((line, index) => {
33
+ const text = line.trim();
34
+ if (text.startsWith("*") || text.startsWith("//") || text.startsWith("/*")) return;
35
+ for (const rule of rules) {
36
+ for (const match of text.match(rule.pattern) ?? []) {
37
+ findings.push({ ruleId: rule.id, line: index + 1, match, text });
38
+ }
39
+ }
40
+ });
41
+ return findings;
42
+ }
43
+ function scanTokenRules(source) {
44
+ return scanRules(source, TOKEN_RULES);
45
+ }
46
+ export {
47
+ TOKEN_RULES,
48
+ scanRules,
49
+ scanTokenRules
50
+ };
51
+ //# sourceMappingURL=tokenRules.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/lib/tokenRules.ts"],"sourcesContent":["/**\n * The rules that say a colour must be addressed as a role.\n *\n * These live here, in one place, because two very different things enforce them:\n *\n * - `scripts/check-tokens.mjs` runs them over `src/components` and\n * `src/stories` as a **ratchet**. Those files carry pre-existing debt, so\n * each rule has a budget and CI fails only when a number rises.\n * - `@rtkelly-labs/design-system-report`'s linter runs them over a report's TSX\n * at **budget zero**. A\n * report is new code written today; there is no debt to grandfather, and a\n * hex literal in one renders identically on `midnight` and on `white`, which\n * is the whole failure the ladder exists to prevent.\n *\n * The check script imports this `.ts` file directly — Node strips the types.\n * That is worth preserving: the previous arrangement had the rules written out\n * in a script, so anything else wanting them had to copy the regexes, and a copy\n * is a rule that silently stops matching the original.\n */\n\nexport interface TokenRule {\n id: 'hex' | 'rawPalette' | 'legacyAlias' | 'darkVariant';\n label: string;\n /** Global, so callers must use `match`/`matchAll`, which reset `lastIndex`. */\n pattern: RegExp;\n fix: string;\n}\n\nexport const TOKEN_RULES: readonly TokenRule[] = [\n {\n id: 'hex',\n label: 'Hex literals',\n pattern: /#[0-9a-fA-F]{3,8}\\b/g,\n fix: 'Use a --ds-* token or a semantic utility (bg-surface-raised, text-accent-primary).',\n },\n {\n id: 'rawPalette',\n label: 'Literal Tailwind palette utilities',\n pattern:\n /\\b(?:bg|text|border|divide|placeholder|ring|from|to|via)-(?:white|black|zinc|gray|slate|neutral|stone|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose)(?:-\\d{2,3})?(?:\\/\\d{1,3})?\\b/g,\n fix: 'Use the semantic utilities: bg-surface-*, text-content-*, border-edge-*, text-intent-*.',\n },\n {\n id: 'legacyAlias',\n label: 'Legacy brutalist-* colour aliases',\n // `brutalist-card` / `-btn` / `-badge` are component classes in styles.css,\n // already written against roles — they are not colour names and stay.\n pattern: /\\bbrutalist-(?:cyan|neonCyan|pink|yellow|neonGreen|green|cyberOrange|darkBg|shadow-color)\\b/g,\n fix: 'Use accent-*/intent-* utilities or --ds-* tokens. Blocks removing the compat block in theme.css.',\n },\n {\n id: 'darkVariant',\n label: 'dark: colour variants',\n pattern: /\\bdark:(?:bg|text|border|divide|placeholder|ring|from|to|via)-/g,\n fix: 'Tokens switch on their own. dark: is only for non-colour utilities, and means \"midnight or dim\" now.',\n },\n];\n\nexport interface Finding<Id extends string = string> {\n ruleId: Id;\n line: number;\n match: string;\n /** The trimmed source line, for pointing at the offence. */\n text: string;\n}\n\n/**\n * Line-by-line rule matching, shared by the ratchet and the report linter.\n *\n * Comment lines are skipped, and that is not a loophole being left open: this\n * very file, `AGENTS.md`'s examples and the rules' own `fix` strings all name\n * the forbidden patterns in prose. Without the skip the checker's first finding\n * would be itself.\n *\n * Matching against the *trimmed* line rather than the raw one is safe because no\n * rule can match leading whitespace, and it means the reported `text` is what\n * gets printed under the finding.\n */\nexport function scanRules<Id extends string>(\n source: string,\n rules: readonly { id: Id; pattern: RegExp }[],\n): Finding<Id>[] {\n const findings: Finding<Id>[] = [];\n source.split('\\n').forEach((line, index) => {\n const text = line.trim();\n if (text.startsWith('*') || text.startsWith('//') || text.startsWith('/*')) return;\n for (const rule of rules) {\n for (const match of text.match(rule.pattern) ?? []) {\n findings.push({ ruleId: rule.id, line: index + 1, match, text });\n }\n }\n });\n return findings;\n}\n\n/** Every colour-instead-of-role violation in one file's source. */\nexport function scanTokenRules(source: string): Finding<TokenRule['id']>[] {\n return scanRules(source, TOKEN_RULES);\n}\n"],"mappings":";AA4BO,IAAM,cAAoC;AAAA,EAC/C;AAAA,IACE,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,SAAS;AAAA,IACT,KAAK;AAAA,EACP;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,SACE;AAAA,IACF,KAAK;AAAA,EACP;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,OAAO;AAAA;AAAA;AAAA,IAGP,SAAS;AAAA,IACT,KAAK;AAAA,EACP;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,SAAS;AAAA,IACT,KAAK;AAAA,EACP;AACF;AAsBO,SAAS,UACd,QACA,OACe;AACf,QAAM,WAA0B,CAAC;AACjC,SAAO,MAAM,IAAI,EAAE,QAAQ,CAAC,MAAM,UAAU;AAC1C,UAAM,OAAO,KAAK,KAAK;AACvB,QAAI,KAAK,WAAW,GAAG,KAAK,KAAK,WAAW,IAAI,KAAK,KAAK,WAAW,IAAI,EAAG;AAC5E,eAAW,QAAQ,OAAO;AACxB,iBAAW,SAAS,KAAK,MAAM,KAAK,OAAO,KAAK,CAAC,GAAG;AAClD,iBAAS,KAAK,EAAE,QAAQ,KAAK,IAAI,MAAM,QAAQ,GAAG,OAAO,KAAK,CAAC;AAAA,MACjE;AAAA,IACF;AAAA,EACF,CAAC;AACD,SAAO;AACT;AAGO,SAAS,eAAe,QAA4C;AACzE,SAAO,UAAU,QAAQ,WAAW;AACtC;","names":[]}