@rnine/core 0.0.0-stage → 0.1.1

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 (264) hide show
  1. package/README.md +136 -2
  2. package/dist/_variables.scss +197 -0
  3. package/dist/base.css +106 -0
  4. package/dist/components/Alert/Alert.d.ts +18 -0
  5. package/dist/components/Alert/Alert.js +57 -0
  6. package/dist/components/Alert/Alert.js.map +1 -0
  7. package/dist/components/Alert/Alert.module.js +17 -0
  8. package/dist/components/Alert/Alert.module.js.map +1 -0
  9. package/dist/components/Avatar/Avatar.d.ts +14 -0
  10. package/dist/components/Avatar/Avatar.js +29 -0
  11. package/dist/components/Avatar/Avatar.js.map +1 -0
  12. package/dist/components/Avatar/Avatar.module.js +12 -0
  13. package/dist/components/Avatar/Avatar.module.js.map +1 -0
  14. package/dist/components/Brand/Brand.d.ts +32 -0
  15. package/dist/components/Brand/Brand.js +60 -0
  16. package/dist/components/Brand/Brand.js.map +1 -0
  17. package/dist/components/Brand/Brand.module.js +10 -0
  18. package/dist/components/Brand/Brand.module.js.map +1 -0
  19. package/dist/components/Breadcrumbs/Breadcrumbs.d.ts +20 -0
  20. package/dist/components/Breadcrumbs/Breadcrumbs.js +31 -0
  21. package/dist/components/Breadcrumbs/Breadcrumbs.js.map +1 -0
  22. package/dist/components/Breadcrumbs/Breadcrumbs.module.js +9 -0
  23. package/dist/components/Breadcrumbs/Breadcrumbs.module.js.map +1 -0
  24. package/dist/components/Button/Button.d.ts +33 -0
  25. package/dist/components/Button/Button.js +66 -0
  26. package/dist/components/Button/Button.js.map +1 -0
  27. package/dist/components/Button/Button.module.js +19 -0
  28. package/dist/components/Button/Button.module.js.map +1 -0
  29. package/dist/components/Card/Card.d.ts +20 -0
  30. package/dist/components/Card/Card.js +29 -0
  31. package/dist/components/Card/Card.js.map +1 -0
  32. package/dist/components/Card/Card.module.js +10 -0
  33. package/dist/components/Card/Card.module.js.map +1 -0
  34. package/dist/components/CaseStudy/CaseStudy.d.ts +37 -0
  35. package/dist/components/CaseStudy/CaseStudy.js +84 -0
  36. package/dist/components/CaseStudy/CaseStudy.js.map +1 -0
  37. package/dist/components/CaseStudy/CaseStudy.module.js +17 -0
  38. package/dist/components/CaseStudy/CaseStudy.module.js.map +1 -0
  39. package/dist/components/Choice/Choice.d.ts +33 -0
  40. package/dist/components/Choice/Choice.js +127 -0
  41. package/dist/components/Choice/Choice.js.map +1 -0
  42. package/dist/components/Choice/Choice.module.js +18 -0
  43. package/dist/components/Choice/Choice.module.js.map +1 -0
  44. package/dist/components/ContactIcon/ContactIcon.d.ts +16 -0
  45. package/dist/components/ContactIcon/ContactIcon.js +60 -0
  46. package/dist/components/ContactIcon/ContactIcon.js.map +1 -0
  47. package/dist/components/ContactIcon/ContactIcon.module.js +5 -0
  48. package/dist/components/ContactIcon/ContactIcon.module.js.map +1 -0
  49. package/dist/components/Field/Field.d.ts +29 -0
  50. package/dist/components/Field/Field.js +101 -0
  51. package/dist/components/Field/Field.js.map +1 -0
  52. package/dist/components/Field/Field.module.js +17 -0
  53. package/dist/components/Field/Field.module.js.map +1 -0
  54. package/dist/components/Layout/Layout.d.ts +50 -0
  55. package/dist/components/Layout/Layout.js +76 -0
  56. package/dist/components/Layout/Layout.js.map +1 -0
  57. package/dist/components/Layout/Layout.module.js +20 -0
  58. package/dist/components/Layout/Layout.module.js.map +1 -0
  59. package/dist/components/ListRow/ListRow.d.ts +35 -0
  60. package/dist/components/ListRow/ListRow.js +61 -0
  61. package/dist/components/ListRow/ListRow.js.map +1 -0
  62. package/dist/components/ListRow/ListRow.module.js +17 -0
  63. package/dist/components/ListRow/ListRow.module.js.map +1 -0
  64. package/dist/components/MediaGallery/MediaGallery.d.ts +31 -0
  65. package/dist/components/MediaGallery/MediaGallery.js +72 -0
  66. package/dist/components/MediaGallery/MediaGallery.js.map +1 -0
  67. package/dist/components/MediaGallery/MediaGallery.module.js +14 -0
  68. package/dist/components/MediaGallery/MediaGallery.module.js.map +1 -0
  69. package/dist/components/MenuRail/MenuRail.d.ts +20 -0
  70. package/dist/components/MenuRail/MenuRail.js +33 -0
  71. package/dist/components/MenuRail/MenuRail.js.map +1 -0
  72. package/dist/components/MenuRail/MenuRail.module.js +11 -0
  73. package/dist/components/MenuRail/MenuRail.module.js.map +1 -0
  74. package/dist/components/Modal/Modal.d.ts +23 -0
  75. package/dist/components/Modal/Modal.js +57 -0
  76. package/dist/components/Modal/Modal.js.map +1 -0
  77. package/dist/components/Modal/Modal.module.js +17 -0
  78. package/dist/components/Modal/Modal.module.js.map +1 -0
  79. package/dist/components/PageTools/PageTools.d.ts +19 -0
  80. package/dist/components/PageTools/PageTools.js +39 -0
  81. package/dist/components/PageTools/PageTools.js.map +1 -0
  82. package/dist/components/PageTools/PageTools.module.js +9 -0
  83. package/dist/components/PageTools/PageTools.module.js.map +1 -0
  84. package/dist/components/Panel/Panel.d.ts +20 -0
  85. package/dist/components/Panel/Panel.js +65 -0
  86. package/dist/components/Panel/Panel.js.map +1 -0
  87. package/dist/components/Panel/Panel.module.js +10 -0
  88. package/dist/components/Panel/Panel.module.js.map +1 -0
  89. package/dist/components/Panel/PanelBar.d.ts +24 -0
  90. package/dist/components/Panel/PanelBar.js +45 -0
  91. package/dist/components/Panel/PanelBar.js.map +1 -0
  92. package/dist/components/Panel/PanelBar.module.js +12 -0
  93. package/dist/components/Panel/PanelBar.module.js.map +1 -0
  94. package/dist/components/Panel/stageContext.d.ts +7 -0
  95. package/dist/components/Panel/stageContext.js +10 -0
  96. package/dist/components/Panel/stageContext.js.map +1 -0
  97. package/dist/components/Progress/Progress.d.ts +14 -0
  98. package/dist/components/Progress/Progress.js +33 -0
  99. package/dist/components/Progress/Progress.js.map +1 -0
  100. package/dist/components/Progress/Progress.module.js +13 -0
  101. package/dist/components/Progress/Progress.module.js.map +1 -0
  102. package/dist/components/Prose/Prose.d.ts +13 -0
  103. package/dist/components/Prose/Prose.js +18 -0
  104. package/dist/components/Prose/Prose.js.map +1 -0
  105. package/dist/components/Prose/Prose.module.js +5 -0
  106. package/dist/components/Prose/Prose.module.js.map +1 -0
  107. package/dist/components/ScreenshotCarousel/Lightbox.d.ts +19 -0
  108. package/dist/components/ScreenshotCarousel/Lightbox.js +119 -0
  109. package/dist/components/ScreenshotCarousel/Lightbox.js.map +1 -0
  110. package/dist/components/ScreenshotCarousel/ScreenshotCarousel.d.ts +25 -0
  111. package/dist/components/ScreenshotCarousel/ScreenshotCarousel.js +119 -0
  112. package/dist/components/ScreenshotCarousel/ScreenshotCarousel.js.map +1 -0
  113. package/dist/components/ScreenshotCarousel/ScreenshotCarousel.module.js +23 -0
  114. package/dist/components/ScreenshotCarousel/ScreenshotCarousel.module.js.map +1 -0
  115. package/dist/components/SegmentedControl/SegmentedControl.d.ts +20 -0
  116. package/dist/components/SegmentedControl/SegmentedControl.js +23 -0
  117. package/dist/components/SegmentedControl/SegmentedControl.js.map +1 -0
  118. package/dist/components/SegmentedControl/SegmentedControl.module.js +8 -0
  119. package/dist/components/SegmentedControl/SegmentedControl.module.js.map +1 -0
  120. package/dist/components/Skeleton/Skeleton.d.ts +17 -0
  121. package/dist/components/Skeleton/Skeleton.js +26 -0
  122. package/dist/components/Skeleton/Skeleton.js.map +1 -0
  123. package/dist/components/Skeleton/Skeleton.module.js +11 -0
  124. package/dist/components/Skeleton/Skeleton.module.js.map +1 -0
  125. package/dist/components/Table/Pagination.d.ts +16 -0
  126. package/dist/components/Table/Pagination.js +83 -0
  127. package/dist/components/Table/Pagination.js.map +1 -0
  128. package/dist/components/Table/Pagination.module.js +15 -0
  129. package/dist/components/Table/Pagination.module.js.map +1 -0
  130. package/dist/components/Table/Table.d.ts +46 -0
  131. package/dist/components/Table/Table.js +121 -0
  132. package/dist/components/Table/Table.js.map +1 -0
  133. package/dist/components/Table/Table.module.js +24 -0
  134. package/dist/components/Table/Table.module.js.map +1 -0
  135. package/dist/components/Tabs/Tabs.d.ts +22 -0
  136. package/dist/components/Tabs/Tabs.js +52 -0
  137. package/dist/components/Tabs/Tabs.js.map +1 -0
  138. package/dist/components/Tabs/Tabs.module.js +10 -0
  139. package/dist/components/Tabs/Tabs.module.js.map +1 -0
  140. package/dist/components/Tag/Tag.d.ts +21 -0
  141. package/dist/components/Tag/Tag.js +22 -0
  142. package/dist/components/Tag/Tag.js.map +1 -0
  143. package/dist/components/Tag/Tag.module.js +14 -0
  144. package/dist/components/Tag/Tag.module.js.map +1 -0
  145. package/dist/components/Text/Text.d.ts +17 -0
  146. package/dist/components/Text/Text.js +28 -0
  147. package/dist/components/Text/Text.js.map +1 -0
  148. package/dist/components/Text/Text.module.js +21 -0
  149. package/dist/components/Text/Text.module.js.map +1 -0
  150. package/dist/components/Toast/Toast.d.ts +31 -0
  151. package/dist/components/Toast/Toast.js +118 -0
  152. package/dist/components/Toast/Toast.js.map +1 -0
  153. package/dist/components/Toast/Toast.module.js +18 -0
  154. package/dist/components/Toast/Toast.module.js.map +1 -0
  155. package/dist/components/Tooltip/Tooltip.d.ts +19 -0
  156. package/dist/components/Tooltip/Tooltip.js +35 -0
  157. package/dist/components/Tooltip/Tooltip.js.map +1 -0
  158. package/dist/components/Tooltip/Tooltip.module.js +11 -0
  159. package/dist/components/Tooltip/Tooltip.module.js.map +1 -0
  160. package/dist/components/VideoPlayer/VideoPlayer.d.ts +24 -0
  161. package/dist/components/VideoPlayer/VideoPlayer.js +37 -0
  162. package/dist/components/VideoPlayer/VideoPlayer.js.map +1 -0
  163. package/dist/components/VideoPlayer/VideoPlayer.module.js +8 -0
  164. package/dist/components/VideoPlayer/VideoPlayer.module.js.map +1 -0
  165. package/dist/components.css +2 -0
  166. package/dist/hooks/mood.d.ts +101 -0
  167. package/dist/hooks/mood.js +139 -0
  168. package/dist/hooks/mood.js.map +1 -0
  169. package/dist/hooks/motion.d.ts +10 -0
  170. package/dist/hooks/motion.js +27 -0
  171. package/dist/hooks/motion.js.map +1 -0
  172. package/dist/hooks/motionSetting.d.ts +21 -0
  173. package/dist/hooks/motionSetting.js +41 -0
  174. package/dist/hooks/motionSetting.js.map +1 -0
  175. package/dist/index.d.ts +59 -0
  176. package/dist/index.js +40 -0
  177. package/dist/kit.d.ts +8 -0
  178. package/dist/kit.js +7 -0
  179. package/dist/motion/Backdrop.d.ts +13 -0
  180. package/dist/motion/Backdrop.js +15 -0
  181. package/dist/motion/Backdrop.js.map +1 -0
  182. package/dist/motion/Backdrop.module.js +8 -0
  183. package/dist/motion/Backdrop.module.js.map +1 -0
  184. package/dist/motion/LiveClock.d.ts +2 -0
  185. package/dist/motion/LiveClock.js +32 -0
  186. package/dist/motion/LiveClock.js.map +1 -0
  187. package/dist/motion/LiveClock.module.js +8 -0
  188. package/dist/motion/LiveClock.module.js.map +1 -0
  189. package/dist/motion/Magnet.d.ts +10 -0
  190. package/dist/motion/Magnet.js +36 -0
  191. package/dist/motion/Magnet.js.map +1 -0
  192. package/dist/motion/Magnet.module.js +5 -0
  193. package/dist/motion/Magnet.module.js.map +1 -0
  194. package/dist/motion/Mark.d.ts +7 -0
  195. package/dist/motion/Mark.js +22 -0
  196. package/dist/motion/Mark.js.map +1 -0
  197. package/dist/motion/Mark.module.js +5 -0
  198. package/dist/motion/Mark.module.js.map +1 -0
  199. package/dist/motion/PageEffects.d.ts +2 -0
  200. package/dist/motion/PageEffects.js +8 -0
  201. package/dist/motion/PageEffects.js.map +1 -0
  202. package/dist/motion/Reveal.d.ts +13 -0
  203. package/dist/motion/Reveal.js +24 -0
  204. package/dist/motion/Reveal.js.map +1 -0
  205. package/dist/motion/Reveal.module.js +6 -0
  206. package/dist/motion/Reveal.module.js.map +1 -0
  207. package/dist/motion/TextReveal.d.ts +18 -0
  208. package/dist/motion/TextReveal.js +13 -0
  209. package/dist/motion/TextReveal.js.map +1 -0
  210. package/dist/motion/TiltCard.d.ts +14 -0
  211. package/dist/motion/TiltCard.js +34 -0
  212. package/dist/motion/TiltCard.js.map +1 -0
  213. package/dist/motion/TiltCard.module.js +9 -0
  214. package/dist/motion/TiltCard.module.js.map +1 -0
  215. package/dist/motion/ripple.d.ts +15 -0
  216. package/dist/motion/ripple.js +12 -0
  217. package/dist/motion/ripple.js.map +1 -0
  218. package/dist/motion/swap.d.ts +8 -0
  219. package/dist/motion/swap.js +26 -0
  220. package/dist/motion/swap.js.map +1 -0
  221. package/dist/motion/useTextReveal.d.ts +9 -0
  222. package/dist/motion/useTextReveal.js +9 -0
  223. package/dist/motion/useTextReveal.js.map +1 -0
  224. package/dist/motion.d.ts +16 -0
  225. package/dist/motion.js +13 -0
  226. package/dist/node_modules/simple-icons/index.js +284 -0
  227. package/dist/provider/ThemeProvider.d.ts +64 -0
  228. package/dist/provider/ThemeProvider.js +71 -0
  229. package/dist/provider/ThemeProvider.js.map +1 -0
  230. package/dist/provider/mark.d.ts +38 -0
  231. package/dist/provider/mark.js +40 -0
  232. package/dist/provider/mark.js.map +1 -0
  233. package/dist/styles.css +364 -0
  234. package/dist/tokens.css +254 -0
  235. package/dist/tokens.d.ts +1146 -0
  236. package/dist/tokens.js +1146 -0
  237. package/dist/utils/clock.d.ts +2 -0
  238. package/dist/utils/clock.js +9 -0
  239. package/dist/utils/clock.js.map +1 -0
  240. package/dist/utils/contact.d.ts +28 -0
  241. package/dist/utils/contact.js +157 -0
  242. package/dist/utils/contact.js.map +1 -0
  243. package/dist/utils/cx.d.ts +2 -0
  244. package/dist/utils/cx.js +8 -0
  245. package/dist/utils/cx.js.map +1 -0
  246. package/dist/utils/pageList.d.ts +2 -0
  247. package/dist/utils/pageList.js +28 -0
  248. package/dist/utils/pageList.js.map +1 -0
  249. package/fonts.css +2 -0
  250. package/package.json +113 -4
  251. package/scripts/build-tokens.mjs +389 -0
  252. package/scripts/conformance.mjs +67 -0
  253. package/scss/_index.scss +15 -0
  254. package/scss/_mixins.scss +198 -0
  255. package/scss/base.scss +78 -0
  256. package/theme.json +8 -0
  257. package/tokens/color.json +96 -0
  258. package/tokens/layout.json +29 -0
  259. package/tokens/motion.json +18 -0
  260. package/tokens/shape.json +53 -0
  261. package/tokens/space.json +19 -0
  262. package/tokens/themes/dark.json +81 -0
  263. package/tokens/themes/light.json +106 -0
  264. package/tokens/typography.json +226 -0
package/README.md CHANGED
@@ -1,3 +1,137 @@
1
- # Temporary Holding Version
1
+ # @rnine/core
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ **Docs and every component, live: [ui.rnine.dev](https://ui.rnine.dev)** (Storybook)
4
+
5
+ The shared core of the design system libraries. Every library (like
6
+ [`@rnine/nineos`](../nineos)) is built on it and exports everything it exports, with
7
+ the same props, in its own look. On its own, core is a complete library too, in
8
+ **Plain**: system fonts, neutral grays, one blue accent, rounded corners.
9
+
10
+ What's in it:
11
+
12
+ - **Components** every library shares: buttons, fields, cards, tables, modals, toasts,
13
+ panels, the menu rail, media, layout, the mood and motion toggles, ...
14
+ - **Effects by role**: `TextReveal`, `Backdrop`, `Mark`, `PageEffects`, `swapIn`/`swapOut`.
15
+ Core components draw with the library's version (Plain's are still or simple fades).
16
+ - **The mood engine**: two moods per library, one per color scheme, kept on
17
+ `<html data-scheme="light|dark">`, saved in the browser and optionally shared across
18
+ subdomains, with a first-paint boot script.
19
+ - **The SCSS API**: tokens as variables, `type()`, `up()`/`down()`, `corner()`,
20
+ `ornament()`, `corner-ornament()`, `texture()`, `hairline()`, `glass()`, `focus-ring()`,
21
+ `keyframes()`, ...
22
+ - **The token build tool** (`@rnine/core/build-tokens`) and **conformance checks**
23
+ (`@rnine/core/conformance`) for building a library of your own.
24
+
25
+ ## Use it in an app
26
+
27
+ ```bash
28
+ npm install @rnine/core react react-dom # or a library built on it, e.g. @rnine/nineos
29
+ # sass too, to use the SCSS API
30
+ ```
31
+
32
+ ```tsx
33
+ // entry file, once
34
+ import '@rnine/core/fonts.css'; // Plain uses system fonts: nothing to load (other libraries load theirs)
35
+ import '@rnine/core/styles.css'; // tokens, base styles, shared keyframes, every component
36
+ import { ThemeProvider } from '@rnine/core';
37
+ import markSvg from './mark.svg?raw';
38
+
39
+ createRoot(root).render(
40
+ <ThemeProvider
41
+ mark={{ full: markSvg }} // your logo, drawn by Mark (default: a placeholder frame)
42
+ mood={{ cookieDomain: 'example.com' }} // optional: share the chosen mood across subdomains
43
+ >
44
+ <App />
45
+ </ThemeProvider>,
46
+ );
47
+ ```
48
+
49
+ The mood is saved in `localStorage` and a cookie, both named `mood` unless you pass
50
+ `mood={{ storageKey }}`. Auto follows the library's rule (Plain: the system's light/dark
51
+ setting; NineOS: light by day, dark at night for a dark system); `mood={{ auto }}`
52
+ overrides it. To have the right mood on the first paint, put the library's
53
+ `moodBootScript()` output (with the same key) in an inline `<script>` in your
54
+ `index.html` `<head>`.
55
+
56
+ ```tsx
57
+ // anywhere
58
+ import { Button, Card, Section, TextField, useMood } from '@rnine/core';
59
+ import { Backdrop, Magnet, TextReveal } from '@rnine/core/motion';
60
+ ```
61
+
62
+ ```scss
63
+ // in any SCSS module
64
+ @use "@rnine/core/scss" as r9;
65
+
66
+ .button {
67
+ @include r9.type(label);
68
+ @include r9.corner(md);
69
+ background: r9.$accent;
70
+ color: r9.$on-accent;
71
+ @include r9.up(md) { padding-inline: r9.$space-6; }
72
+ }
73
+ ```
74
+
75
+ ## Entry points
76
+
77
+ | Import | What |
78
+ |---|---|
79
+ | `@rnine/core` | Components, `ThemeProvider`, `MarkProvider`, `Mark`, mood and motion hooks (`useMood`, `configureMood`, `moodBootScript`, ...) |
80
+ | `@rnine/core/motion` | `TextReveal`, `useTextReveal`, `Backdrop`, `Mark`, `PageEffects`, `swapIn`/`swapOut`, `Magnet`, `TiltCard`, `Reveal`, `LiveClock`, `rippleAt` |
81
+ | `@rnine/core/styles.css` | Plain's tokens, base styles and every component's styles (one file) |
82
+ | `@rnine/core/scss` | The SCSS API, with Plain's tokens |
83
+ | `@rnine/core/tokens` | Plain's tokens as data |
84
+ | `@rnine/core/kit` | For building a library: `ThemeRoot`, `ThemeConfigProvider`, `MarkArt`, `cx`, ... |
85
+ | `@rnine/core/build-tokens` | The token build tool (Node) |
86
+ | `@rnine/core/conformance` | Contract and contrast checks for a library's tests (Node) |
87
+ | `@rnine/core/base.css`, `components.css` | The parts of `styles.css` a library bundles after its own tokens |
88
+
89
+ ## Build a library on core
90
+
91
+ A library has its own tokens (the same names as core's; color primitives are its own),
92
+ a `theme.json` (its name, its two moods' names, its Auto rule), its versions of the role
93
+ effects, and any components of its own. See [`@rnine/nineos`](../nineos) for a complete one:
94
+
95
+ - `scripts/build.mjs`: `buildTokens({ root, contract })` from `@rnine/core/build-tokens`
96
+ (it fails if a token core components read is missing), then bundle `styles.css` as
97
+ tokens, core's `base.css`, its own base, core's `components.css`, its own components.
98
+ - `src/index.ts`: `export * from '@rnine/core'`, then its own `ThemeProvider`
99
+ (`<ThemeRoot config={...} />` from `@rnine/core/kit`), `Mark`, `moodBootScript`, and
100
+ its additions. `src/motion.ts` likewise over `@rnine/core/motion`.
101
+ - Tests: `contractProblems`, `contrastChecks` and `missingExports` from
102
+ `@rnine/core/conformance`.
103
+
104
+ ## Add a component to core
105
+
106
+ ```
107
+ src/components/Name/
108
+ Name.tsx the component; props documented with JSDoc
109
+ Name.module.scss styles: only tokens and the shared mixins (@use "@rnine/core/scss" as r9)
110
+ Name.stories.tsx every state; the docs description names the component's accent element
111
+ Name.test.tsx behavior and accessible names (Testing Library)
112
+ ```
113
+
114
+ Then export it from `src/index.ts`. Rules:
115
+
116
+ - Style with tokens and the shared mixins only, so every library's look applies: mood
117
+ roles (never hex), `corner()` for shapes, `ornament()` for the accent mark.
118
+ - At least one accent element (`r9.$accent`), named in the story docs.
119
+ - Both moods work with no extra code.
120
+ - Motion only inside `@include r9.motion-safe`, or JS gated by `useReducedMotion()`.
121
+ - Visible labels, keyboard support, `:focus-visible` rings, 44px touch targets.
122
+ - Cut corners clip outlines: draw focus inside (`box-shadow: inset 0 0 0 2px r9.$accent`).
123
+
124
+ ```bash
125
+ yarn workspace @rnine/core test # component tests, Plain's contrast and keyframes
126
+ yarn workspace @rnine/core build # tokens, then vite build, types, styles.css
127
+ ```
128
+
129
+ Its stories show in the NineOS Storybook (`yarn workspace @rnine/nineos storybook`).
130
+
131
+ ## Build output
132
+
133
+ `scripts/build.mjs` builds the tokens and `base.css`; `vite build` (library mode) writes one
134
+ ES module per source file to `dist/` (so apps only bundle what they import) and
135
+ `dist/components.css`; `tsc -p tsconfig.build.json` adds the type declarations; then
136
+ `scripts/build.mjs --bundle` writes `dist/styles.css`. React is a peer dependency;
137
+ lucide-react and dompurify stay external.
@@ -0,0 +1,197 @@
1
+ // Plain tokens for SCSS. Generated by @rnine/core/build-tokens. Do not edit.
2
+ // Every variable points at a CSS custom property, so the mood switches at
3
+ // runtime (data-scheme="light" | "dark"). Media queries need plain values: use $breakpoints.
4
+
5
+ // Primitives and scales
6
+ $color-gray-0: var(--r9-color-gray-0);
7
+ $color-gray-10: var(--r9-color-gray-10);
8
+ $color-gray-25: var(--r9-color-gray-25);
9
+ $color-gray-50: var(--r9-color-gray-50);
10
+ $color-gray-100: var(--r9-color-gray-100);
11
+ $color-gray-300: var(--r9-color-gray-300);
12
+ $color-gray-500: var(--r9-color-gray-500);
13
+ $color-gray-600: var(--r9-color-gray-600);
14
+ $color-gray-800: var(--r9-color-gray-800);
15
+ $color-gray-850: var(--r9-color-gray-850);
16
+ $color-gray-900: var(--r9-color-gray-900);
17
+ $color-gray-950: var(--r9-color-gray-950);
18
+ $color-gray-975: var(--r9-color-gray-975);
19
+ $color-blue-300: var(--r9-color-blue-300);
20
+ $color-blue-400: var(--r9-color-blue-400);
21
+ $color-blue-600: var(--r9-color-blue-600);
22
+ $color-blue-700: var(--r9-color-blue-700);
23
+ $color-cyan-300: var(--r9-color-cyan-300);
24
+ $color-cyan-500: var(--r9-color-cyan-500);
25
+ $color-cyan-700: var(--r9-color-cyan-700);
26
+ $color-green-400: var(--r9-color-green-400);
27
+ $color-green-700: var(--r9-color-green-700);
28
+ $color-amber-400: var(--r9-color-amber-400);
29
+ $color-amber-700: var(--r9-color-amber-700);
30
+ $color-red-400: var(--r9-color-red-400);
31
+ $color-red-700: var(--r9-color-red-700);
32
+ $breakpoint-sm: var(--r9-breakpoint-sm);
33
+ $breakpoint-md: var(--r9-breakpoint-md);
34
+ $breakpoint-lg: var(--r9-breakpoint-lg);
35
+ $container-max: var(--r9-container-max);
36
+ $container-text: var(--r9-container-text);
37
+ $container-gutter: var(--r9-container-gutter);
38
+ $header-height: var(--r9-header-height);
39
+ $z-base: var(--r9-z-base);
40
+ $z-raised: var(--r9-z-raised);
41
+ $z-sticky: var(--r9-z-sticky);
42
+ $z-overlay: var(--r9-z-overlay);
43
+ $z-modal: var(--r9-z-modal);
44
+ $z-toast: var(--r9-z-toast);
45
+ $z-fx: var(--r9-z-fx);
46
+ $duration-instant: var(--r9-duration-instant);
47
+ $duration-fast: var(--r9-duration-fast);
48
+ $duration-base: var(--r9-duration-base);
49
+ $duration-slow: var(--r9-duration-slow);
50
+ $duration-slower: var(--r9-duration-slower);
51
+ $duration-ambient: var(--r9-duration-ambient);
52
+ $easing-out: var(--r9-easing-out);
53
+ $easing-in-out: var(--r9-easing-in-out);
54
+ $easing-linear: var(--r9-easing-linear);
55
+ $corner-sm: var(--r9-corner-sm);
56
+ $corner-md: var(--r9-corner-md);
57
+ $corner-lg: var(--r9-corner-lg);
58
+ $shape-cut: var(--r9-shape-cut);
59
+ $shape-round: var(--r9-shape-round);
60
+ $radius-none: var(--r9-radius-none);
61
+ $radius-xs: var(--r9-radius-xs);
62
+ $radius-full: var(--r9-radius-full);
63
+ $border-hair: var(--r9-border-hair);
64
+ $border-strong: var(--r9-border-strong);
65
+ $space-0: var(--r9-space-0);
66
+ $space-1: var(--r9-space-1);
67
+ $space-2: var(--r9-space-2);
68
+ $space-3: var(--r9-space-3);
69
+ $space-4: var(--r9-space-4);
70
+ $space-5: var(--r9-space-5);
71
+ $space-6: var(--r9-space-6);
72
+ $space-8: var(--r9-space-8);
73
+ $space-10: var(--r9-space-10);
74
+ $space-12: var(--r9-space-12);
75
+ $space-16: var(--r9-space-16);
76
+ $space-20: var(--r9-space-20);
77
+ $space-24: var(--r9-space-24);
78
+ $font-display: var(--r9-font-display);
79
+ $font-body: var(--r9-font-body);
80
+ $font-mono: var(--r9-font-mono);
81
+ $font-size-xs: var(--r9-font-size-xs);
82
+ $font-size-sm: var(--r9-font-size-sm);
83
+ $font-size-base: var(--r9-font-size-base);
84
+ $font-size-md: var(--r9-font-size-md);
85
+ $font-size-lg: var(--r9-font-size-lg);
86
+ $font-size-xl: var(--r9-font-size-xl);
87
+ $font-size-2xl: var(--r9-font-size-2xl);
88
+ $font-size-3xl: var(--r9-font-size-3xl);
89
+ $font-size-4xl: var(--r9-font-size-4xl);
90
+ $font-size-5xl: var(--r9-font-size-5xl);
91
+ $font-weight-regular: var(--r9-font-weight-regular);
92
+ $font-weight-medium: var(--r9-font-weight-medium);
93
+ $font-weight-semibold: var(--r9-font-weight-semibold);
94
+ $font-weight-bold: var(--r9-font-weight-bold);
95
+ $leading-tight: var(--r9-leading-tight);
96
+ $leading-snug: var(--r9-leading-snug);
97
+ $leading-normal: var(--r9-leading-normal);
98
+ $tracking-tight: var(--r9-tracking-tight);
99
+ $tracking-normal: var(--r9-tracking-normal);
100
+ $tracking-wide: var(--r9-tracking-wide);
101
+ $tracking-wider: var(--r9-tracking-wider);
102
+ $tracking-mark: var(--r9-tracking-mark);
103
+
104
+ // Mood roles
105
+ $bg: var(--r9-bg);
106
+ $surface: var(--r9-surface);
107
+ $surface-raised: var(--r9-surface-raised);
108
+ $glass: var(--r9-glass);
109
+ $fg: var(--r9-fg);
110
+ $fg-muted: var(--r9-fg-muted);
111
+ $fg-subtle: var(--r9-fg-subtle);
112
+ $line: var(--r9-line);
113
+ $line-strong: var(--r9-line-strong);
114
+ $accent: var(--r9-accent);
115
+ $accent-hover: var(--r9-accent-hover);
116
+ $accent-text: var(--r9-accent-text);
117
+ $on-accent: var(--r9-on-accent);
118
+ $accent-soft: var(--r9-accent-soft);
119
+ $signal: var(--r9-signal);
120
+ $signal-text: var(--r9-signal-text);
121
+ $inverse-bg: var(--r9-inverse-bg);
122
+ $inverse-fg: var(--r9-inverse-fg);
123
+ $success: var(--r9-success);
124
+ $warning: var(--r9-warning);
125
+ $danger: var(--r9-danger);
126
+ $dot: var(--r9-dot);
127
+ $scan: var(--r9-scan);
128
+ $sheen: var(--r9-sheen);
129
+ $selection: var(--r9-selection);
130
+
131
+ $space: (
132
+ "0": var(--r9-space-0),
133
+ "1": var(--r9-space-1),
134
+ "2": var(--r9-space-2),
135
+ "3": var(--r9-space-3),
136
+ "4": var(--r9-space-4),
137
+ "5": var(--r9-space-5),
138
+ "6": var(--r9-space-6),
139
+ "8": var(--r9-space-8),
140
+ "10": var(--r9-space-10),
141
+ "12": var(--r9-space-12),
142
+ "16": var(--r9-space-16),
143
+ "20": var(--r9-space-20),
144
+ "24": var(--r9-space-24),
145
+ );
146
+
147
+ $corner: (
148
+ "sm": var(--r9-corner-sm),
149
+ "md": var(--r9-corner-md),
150
+ "lg": var(--r9-corner-lg),
151
+ );
152
+
153
+ $durations: (
154
+ "instant": var(--r9-duration-instant),
155
+ "fast": var(--r9-duration-fast),
156
+ "base": var(--r9-duration-base),
157
+ "slow": var(--r9-duration-slow),
158
+ "slower": var(--r9-duration-slower),
159
+ "ambient": var(--r9-duration-ambient),
160
+ );
161
+
162
+ $easings: (
163
+ "out": var(--r9-easing-out),
164
+ "in-out": var(--r9-easing-in-out),
165
+ "linear": var(--r9-easing-linear),
166
+ );
167
+
168
+ $z-index: (
169
+ "base": var(--r9-z-base),
170
+ "raised": var(--r9-z-raised),
171
+ "sticky": var(--r9-z-sticky),
172
+ "overlay": var(--r9-z-overlay),
173
+ "modal": var(--r9-z-modal),
174
+ "toast": var(--r9-z-toast),
175
+ "fx": var(--r9-z-fx),
176
+ );
177
+
178
+ $breakpoints: (
179
+ "sm": 640px,
180
+ "md": 900px,
181
+ "lg": 1200px,
182
+ );
183
+
184
+ $type-roles: (
185
+ "display": ("font-family": var(--r9-type-display-font-family), "font-weight": var(--r9-type-display-font-weight), "font-size": var(--r9-type-display-font-size), "line-height": var(--r9-type-display-line-height), "letter-spacing": var(--r9-type-display-letter-spacing)),
186
+ "h1": ("font-family": var(--r9-type-h1-font-family), "font-weight": var(--r9-type-h1-font-weight), "font-size": var(--r9-type-h1-font-size), "line-height": var(--r9-type-h1-line-height), "letter-spacing": var(--r9-type-h1-letter-spacing)),
187
+ "h2": ("font-family": var(--r9-type-h2-font-family), "font-weight": var(--r9-type-h2-font-weight), "font-size": var(--r9-type-h2-font-size), "line-height": var(--r9-type-h2-line-height), "letter-spacing": var(--r9-type-h2-letter-spacing)),
188
+ "h3": ("font-family": var(--r9-type-h3-font-family), "font-weight": var(--r9-type-h3-font-weight), "font-size": var(--r9-type-h3-font-size), "line-height": var(--r9-type-h3-line-height), "letter-spacing": var(--r9-type-h3-letter-spacing)),
189
+ "h4": ("font-family": var(--r9-type-h4-font-family), "font-weight": var(--r9-type-h4-font-weight), "font-size": var(--r9-type-h4-font-size), "line-height": var(--r9-type-h4-line-height), "letter-spacing": var(--r9-type-h4-letter-spacing)),
190
+ "body-lg": ("font-family": var(--r9-type-body-lg-font-family), "font-weight": var(--r9-type-body-lg-font-weight), "font-size": var(--r9-type-body-lg-font-size), "line-height": var(--r9-type-body-lg-line-height), "letter-spacing": var(--r9-type-body-lg-letter-spacing)),
191
+ "body": ("font-family": var(--r9-type-body-font-family), "font-weight": var(--r9-type-body-font-weight), "font-size": var(--r9-type-body-font-size), "line-height": var(--r9-type-body-line-height), "letter-spacing": var(--r9-type-body-letter-spacing)),
192
+ "body-sm": ("font-family": var(--r9-type-body-sm-font-family), "font-weight": var(--r9-type-body-sm-font-weight), "font-size": var(--r9-type-body-sm-font-size), "line-height": var(--r9-type-body-sm-line-height), "letter-spacing": var(--r9-type-body-sm-letter-spacing)),
193
+ "label": ("font-family": var(--r9-type-label-font-family), "font-weight": var(--r9-type-label-font-weight), "font-size": var(--r9-type-label-font-size), "line-height": var(--r9-type-label-line-height), "letter-spacing": var(--r9-type-label-letter-spacing)),
194
+ "code": ("font-family": var(--r9-type-code-font-family), "font-weight": var(--r9-type-code-font-weight), "font-size": var(--r9-type-code-font-size), "line-height": var(--r9-type-code-line-height), "letter-spacing": var(--r9-type-code-letter-spacing)),
195
+ "caption": ("font-family": var(--r9-type-caption-font-family), "font-weight": var(--r9-type-caption-font-weight), "font-size": var(--r9-type-caption-font-size), "line-height": var(--r9-type-caption-line-height), "letter-spacing": var(--r9-type-caption-letter-spacing)),
196
+ "wordmark": ("font-family": var(--r9-type-wordmark-font-family), "font-weight": var(--r9-type-wordmark-font-weight), "font-size": var(--r9-type-wordmark-font-size), "line-height": var(--r9-type-wordmark-line-height), "letter-spacing": var(--r9-type-wordmark-letter-spacing)),
197
+ );
package/dist/base.css ADDED
@@ -0,0 +1,106 @@
1
+ /* Base element styles and shared keyframes. Generated from scss/base.scss. */
2
+ *,
3
+ *::before,
4
+ *::after {
5
+ box-sizing: border-box;
6
+ }
7
+
8
+ html {
9
+ -webkit-text-size-adjust: 100%;
10
+ text-size-adjust: 100%;
11
+ }
12
+
13
+ body {
14
+ margin: 0;
15
+ background: var(--r9-bg);
16
+ color: var(--r9-fg);
17
+ font-family: var(--r9-type-body-font-family);
18
+ font-weight: var(--r9-type-body-font-weight);
19
+ font-size: var(--r9-type-body-font-size);
20
+ line-height: var(--r9-type-body-line-height);
21
+ letter-spacing: var(--r9-type-body-letter-spacing);
22
+ -webkit-font-smoothing: antialiased;
23
+ text-rendering: optimizeLegibility;
24
+ }
25
+
26
+ h1, h2, h3, h4, h5, h6 {
27
+ margin: 0;
28
+ font-family: var(--r9-font-display);
29
+ text-wrap: balance;
30
+ }
31
+
32
+ p {
33
+ margin: 0;
34
+ }
35
+
36
+ img, svg, video, canvas {
37
+ max-width: 100%;
38
+ }
39
+
40
+ code, kbd, samp, pre {
41
+ font-family: var(--r9-font-mono);
42
+ }
43
+
44
+ a {
45
+ color: inherit;
46
+ }
47
+
48
+ ::selection {
49
+ background: var(--r9-selection);
50
+ }
51
+
52
+ :focus-visible {
53
+ outline: 2px solid var(--r9-accent);
54
+ outline-offset: 3px;
55
+ }
56
+
57
+ @keyframes r9-reveal {
58
+ from {
59
+ opacity: 0;
60
+ transform: translateY(14px);
61
+ }
62
+ to {
63
+ opacity: 1;
64
+ transform: none;
65
+ }
66
+ }
67
+ @keyframes r9-pulse {
68
+ 0%, 100% {
69
+ opacity: 1;
70
+ }
71
+ 50% {
72
+ opacity: 0.25;
73
+ }
74
+ }
75
+ @keyframes r9-blink {
76
+ 50% {
77
+ opacity: 0;
78
+ }
79
+ }
80
+ @keyframes r9-sheen {
81
+ 0% {
82
+ background-position: 120% 0;
83
+ }
84
+ 45%, 100% {
85
+ background-position: -30% 0;
86
+ }
87
+ }
88
+ :root[data-motion=reduced] *,
89
+ :root[data-motion=reduced] *::before,
90
+ :root[data-motion=reduced] *::after {
91
+ animation-duration: 0.01ms !important;
92
+ animation-iteration-count: 1 !important;
93
+ transition-duration: 0.01ms !important;
94
+ scroll-behavior: auto !important;
95
+ }
96
+
97
+ @media (prefers-reduced-motion: reduce) {
98
+ *,
99
+ *::before,
100
+ *::after {
101
+ animation-duration: 0.01ms !important;
102
+ animation-iteration-count: 1 !important;
103
+ transition-duration: 0.01ms !important;
104
+ scroll-behavior: auto !important;
105
+ }
106
+ }
@@ -0,0 +1,18 @@
1
+ import type { HTMLAttributes, ReactNode } from 'react';
2
+ export type AlertTone = 'info' | 'success' | 'warning' | 'danger';
3
+ type Props = Omit<HTMLAttributes<HTMLDivElement>, 'title'> & {
4
+ tone?: AlertTone;
5
+ title: ReactNode;
6
+ children?: ReactNode;
7
+ /** Shows a close button. */
8
+ onDismiss?: () => void;
9
+ /** Buttons or links under the message. */
10
+ actions?: ReactNode;
11
+ };
12
+ /**
13
+ * A message about something that happened or needs attention. Status color
14
+ * on the edge and icon, never color alone. Accent element: the mark after
15
+ * the title. Danger alerts interrupt screen readers; the rest are polite.
16
+ */
17
+ export declare function Alert({ tone, title, children, onDismiss, actions, className, ...rest }: Props): import("react").JSX.Element;
18
+ export {};
@@ -0,0 +1,57 @@
1
+ import { cx as e } from "../../utils/cx.js";
2
+ import t from "./Alert.module.js";
3
+ import { jsx as n, jsxs as r } from "react/jsx-runtime";
4
+ import { Check as i, Info as a, OctagonAlert as o, TriangleAlert as s, X as c } from "lucide-react";
5
+ //#region src/components/Alert/Alert.tsx
6
+ var l = {
7
+ info: a,
8
+ success: i,
9
+ warning: s,
10
+ danger: o
11
+ };
12
+ function u({ tone: i = "info", title: a, children: o, onDismiss: s, actions: u, className: d, ...f }) {
13
+ let p = l[i];
14
+ return /* @__PURE__ */ r("div", {
15
+ ...f,
16
+ role: i === "danger" ? "alert" : "status",
17
+ className: e(t.alert, t[i], d),
18
+ children: [
19
+ /* @__PURE__ */ n(p, {
20
+ className: t.icon,
21
+ strokeWidth: 1.5,
22
+ "aria-hidden": "true"
23
+ }),
24
+ /* @__PURE__ */ r("div", {
25
+ className: t.body,
26
+ children: [
27
+ /* @__PURE__ */ n("p", {
28
+ className: t.title,
29
+ children: a
30
+ }),
31
+ o && /* @__PURE__ */ n("div", {
32
+ className: t.message,
33
+ children: o
34
+ }),
35
+ u && /* @__PURE__ */ n("div", {
36
+ className: t.actions,
37
+ children: u
38
+ })
39
+ ]
40
+ }),
41
+ s && /* @__PURE__ */ n("button", {
42
+ type: "button",
43
+ className: t.dismiss,
44
+ onClick: s,
45
+ "aria-label": "Dismiss",
46
+ children: /* @__PURE__ */ n(c, {
47
+ strokeWidth: 1.5,
48
+ "aria-hidden": "true"
49
+ })
50
+ })
51
+ ]
52
+ });
53
+ }
54
+ //#endregion
55
+ export { u as Alert };
56
+
57
+ //# sourceMappingURL=Alert.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Alert.js","names":[],"sources":["../../../src/components/Alert/Alert.tsx"],"sourcesContent":["import type { HTMLAttributes, ReactNode } from 'react';\nimport { Check, Info, OctagonAlert, TriangleAlert, X } from 'lucide-react';\nimport { cx } from '../../utils/cx';\nimport styles from './Alert.module.scss';\n\nexport type AlertTone = 'info' | 'success' | 'warning' | 'danger';\n\ntype Props = Omit<HTMLAttributes<HTMLDivElement>, 'title'> & {\n tone?: AlertTone;\n title: ReactNode;\n children?: ReactNode;\n /** Shows a close button. */\n onDismiss?: () => void;\n /** Buttons or links under the message. */\n actions?: ReactNode;\n};\n\nconst ICONS = { info: Info, success: Check, warning: TriangleAlert, danger: OctagonAlert };\n\n/**\n * A message about something that happened or needs attention. Status color\n * on the edge and icon, never color alone. Accent element: the mark after\n * the title. Danger alerts interrupt screen readers; the rest are polite.\n */\nexport function Alert({ tone = 'info', title, children, onDismiss, actions, className, ...rest }: Props) {\n const Icon = ICONS[tone];\n return (\n <div {...rest} role={tone === 'danger' ? 'alert' : 'status'} className={cx(styles.alert, styles[tone], className)}>\n <Icon className={styles.icon} strokeWidth={1.5} aria-hidden=\"true\" />\n <div className={styles.body}>\n <p className={styles.title}>{title}</p>\n {children && <div className={styles.message}>{children}</div>}\n {actions && <div className={styles.actions}>{actions}</div>}\n </div>\n {onDismiss && (\n <button type=\"button\" className={styles.dismiss} onClick={onDismiss} aria-label=\"Dismiss\">\n <X strokeWidth={1.5} aria-hidden=\"true\" />\n </button>\n )}\n </div>\n );\n}\n"],"mappings":";;;;;AAiBA,IAAM,IAAQ;CAAE,MAAM;CAAM,SAAS;CAAO,SAAS;CAAe,QAAQ;AAAa;AAOzF,SAAgB,EAAM,EAAE,UAAO,QAAQ,UAAO,aAAU,cAAW,YAAS,cAAW,GAAG,KAAe;CACvG,IAAM,IAAO,EAAM;CACnB,OACE,kBAAC,OAAD;EAAK,GAAI;EAAM,MAAM,MAAS,WAAW,UAAU;EAAU,WAAW,EAAG,EAAO,OAAO,EAAO,IAAO,CAAS;YAAhH;GACE,kBAAC,GAAD;IAAM,WAAW,EAAO;IAAM,aAAa;IAAK,eAAY;GAAQ,CAAA;GACpE,kBAAC,OAAD;IAAK,WAAW,EAAO;cAAvB;KACE,kBAAC,KAAD;MAAG,WAAW,EAAO;gBAAQ;KAAS,CAAA;KACrC,KAAY,kBAAC,OAAD;MAAK,WAAW,EAAO;MAAU;KAAc,CAAA;KAC3D,KAAW,kBAAC,OAAD;MAAK,WAAW,EAAO;gBAAU;KAAa,CAAA;IACvD;;GACJ,KACC,kBAAC,UAAD;IAAQ,MAAK;IAAS,WAAW,EAAO;IAAS,SAAS;IAAW,cAAW;cAC9E,kBAAC,GAAD;KAAG,aAAa;KAAK,eAAY;IAAQ,CAAA;GACnC,CAAA;EAEP;;AAET"}
@@ -0,0 +1,17 @@
1
+ var e = {
2
+ alert: "r9-Alert-module_alert_zP4AL",
3
+ info: "r9-Alert-module_info_-J-F1",
4
+ success: "r9-Alert-module_success_lftZT",
5
+ warning: "r9-Alert-module_warning_uOpos",
6
+ danger: "r9-Alert-module_danger_53-01",
7
+ icon: "r9-Alert-module_icon_RUu7X",
8
+ body: "r9-Alert-module_body_IOnct",
9
+ title: "r9-Alert-module_title_QHuwO",
10
+ message: "r9-Alert-module_message_Wd9FZ",
11
+ actions: "r9-Alert-module_actions_6On2P",
12
+ dismiss: "r9-Alert-module_dismiss_4orzR"
13
+ };
14
+ //#endregion
15
+ export { e as default };
16
+
17
+ //# sourceMappingURL=Alert.module.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Alert.module.js","names":[],"sources":["../../../src/components/Alert/Alert.module.scss"],"sourcesContent":["@use \"@rnine/core/scss\" as r9;\n\n.alert {\n --tone: #{r9.$signal};\n display: flex;\n align-items: flex-start;\n gap: r9.$space-3;\n padding: r9.$space-4;\n background: r9.$surface;\n @include r9.hairline;\n border-left: 3px solid var(--tone);\n min-width: 0;\n}\n\n.info { --tone: #{r9.$signal-text}; }\n.success { --tone: #{r9.$success}; }\n.warning { --tone: #{r9.$warning}; }\n.danger { --tone: #{r9.$danger}; }\n\n.icon {\n flex: none;\n width: 20px;\n height: 20px;\n margin-top: 1px;\n color: var(--tone);\n}\n\n.body {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: r9.$space-1;\n}\n\n// The alert's accent mark follows its title\n.title {\n margin: 0;\n display: inline-flex;\n align-items: center;\n gap: r9.$space-2;\n font-weight: r9.$font-weight-semibold;\n\n &::after { @include r9.ornament(5px); }\n}\n\n.message {\n @include r9.type(body-sm);\n color: r9.$fg-muted;\n}\n\n.actions {\n display: flex;\n flex-wrap: wrap;\n gap: r9.$space-4;\n margin-top: r9.$space-2;\n}\n\n.dismiss {\n flex: none;\n display: grid;\n place-items: center;\n width: 32px;\n height: 32px;\n margin: -6px -6px 0 0;\n padding: 0;\n border: 0;\n background: transparent;\n color: r9.$fg-muted;\n cursor: pointer;\n\n svg { width: 18px; height: 18px; }\n &:hover { color: r9.$accent-text; }\n &:focus-visible { @include r9.focus-ring(0); }\n}\n"],"mappings":""}
@@ -0,0 +1,14 @@
1
+ type Props = {
2
+ /** Person's name: the image's alt text and the source of the initials. */
3
+ name: string;
4
+ src?: string;
5
+ size?: 'sm' | 'md' | 'lg';
6
+ className?: string;
7
+ };
8
+ /**
9
+ * A person's picture, or their initials when there is none (or it fails to
10
+ * load). Round, whatever the library's corners. Accent element: the
11
+ * initials tile, or the ring around a photo.
12
+ */
13
+ export declare function Avatar({ name, src, size, className }: Props): import("react").JSX.Element;
14
+ export {};
@@ -0,0 +1,29 @@
1
+ import { cx as e } from "../../utils/cx.js";
2
+ import t from "./Avatar.module.js";
3
+ import { useState as n } from "react";
4
+ import { jsx as r } from "react/jsx-runtime";
5
+ //#region src/components/Avatar/Avatar.tsx
6
+ function i(e) {
7
+ let t = e.trim().split(/\s+/).filter(Boolean);
8
+ return t.length === 0 ? "?" : `${t[0][0]}${t.length > 1 ? t[t.length - 1][0] : t[0][1] ?? ""}`.toUpperCase();
9
+ }
10
+ function a({ name: a, src: o, size: s = "md", className: c }) {
11
+ let [l, u] = n(!1), d = o && !l;
12
+ return /* @__PURE__ */ r("span", {
13
+ className: e(t.avatar, t[s], d ? t.photo : t.initials, c),
14
+ children: d ? /* @__PURE__ */ r("img", {
15
+ src: o,
16
+ alt: a,
17
+ loading: "lazy",
18
+ onError: () => u(!0)
19
+ }) : /* @__PURE__ */ r("span", {
20
+ role: "img",
21
+ "aria-label": a,
22
+ children: i(a)
23
+ })
24
+ });
25
+ }
26
+ //#endregion
27
+ export { a as Avatar };
28
+
29
+ //# sourceMappingURL=Avatar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Avatar.js","names":[],"sources":["../../../src/components/Avatar/Avatar.tsx"],"sourcesContent":["import { useState } from 'react';\nimport { cx } from '../../utils/cx';\nimport styles from './Avatar.module.scss';\n\ntype Props = {\n /** Person's name: the image's alt text and the source of the initials. */\n name: string;\n src?: string;\n size?: 'sm' | 'md' | 'lg';\n className?: string;\n};\n\nfunction initials(name: string) {\n const parts = name.trim().split(/\\s+/).filter(Boolean);\n if (parts.length === 0) return '?';\n const first = parts[0][0];\n const last = parts.length > 1 ? parts[parts.length - 1][0] : parts[0][1] ?? '';\n return `${first}${last}`.toUpperCase();\n}\n\n/**\n * A person's picture, or their initials when there is none (or it fails to\n * load). Round, whatever the library's corners. Accent element: the\n * initials tile, or the ring around a photo.\n */\nexport function Avatar({ name, src, size = 'md', className }: Props) {\n const [failed, setFailed] = useState(false);\n const showImage = src && !failed;\n return (\n <span className={cx(styles.avatar, styles[size], showImage ? styles.photo : styles.initials, className)}>\n {showImage ? (\n <img src={src} alt={name} loading=\"lazy\" onError={() => setFailed(true)} />\n ) : (\n <span role=\"img\" aria-label={name}>{initials(name)}</span>\n )}\n </span>\n );\n}\n"],"mappings":";;;;;AAYA,SAAS,EAAS,GAAc;CAC9B,IAAM,IAAQ,EAAK,KAAK,EAAE,MAAM,KAAK,EAAE,OAAO,OAAO;CAIrD,OAHI,EAAM,WAAW,IAAU,MAGxB,GAFO,EAAM,GAAG,KACV,EAAM,SAAS,IAAI,EAAM,EAAM,SAAS,GAAG,KAAK,EAAM,GAAG,MAAM,KACnD,YAAY;AACvC;AAOA,SAAgB,EAAO,EAAE,SAAM,QAAK,UAAO,MAAM,gBAAoB;CACnE,IAAM,CAAC,GAAQ,KAAa,EAAS,EAAK,GACpC,IAAY,KAAO,CAAC;CAC1B,OACE,kBAAC,QAAD;EAAM,WAAW,EAAG,EAAO,QAAQ,EAAO,IAAO,IAAY,EAAO,QAAQ,EAAO,UAAU,CAAS;YACnG,IACC,kBAAC,OAAD;GAAU;GAAK,KAAK;GAAM,SAAQ;GAAO,eAAe,EAAU,EAAI;EAAI,CAAA,IAE1E,kBAAC,QAAD;GAAM,MAAK;GAAM,cAAY;aAAO,EAAS,CAAI;EAAQ,CAAA;CAEvD,CAAA;AAEV"}
@@ -0,0 +1,12 @@
1
+ var e = {
2
+ avatar: "r9-Avatar-module_avatar_5-kP8",
3
+ sm: "r9-Avatar-module_sm_8TB22",
4
+ md: "r9-Avatar-module_md_zeW0d",
5
+ lg: "r9-Avatar-module_lg_MWKN-",
6
+ initials: "r9-Avatar-module_initials_rYuAj",
7
+ photo: "r9-Avatar-module_photo_iMez8"
8
+ };
9
+ //#endregion
10
+ export { e as default };
11
+
12
+ //# sourceMappingURL=Avatar.module.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Avatar.module.js","names":[],"sources":["../../../src/components/Avatar/Avatar.module.scss"],"sourcesContent":["@use \"@rnine/core/scss\" as r9;\n\n.avatar {\n --size: 40px;\n position: relative;\n display: inline-grid;\n place-items: center;\n flex: none;\n width: var(--size);\n height: var(--size);\n border-radius: r9.$radius-full;\n overflow: hidden;\n font-family: r9.$font-display;\n font-weight: r9.$font-weight-semibold;\n font-size: calc(var(--size) * 0.38);\n line-height: 1;\n\n img {\n width: 100%;\n height: 100%;\n object-fit: cover;\n border-radius: inherit;\n }\n}\n\n.sm { --size: 28px; }\n.md { --size: 40px; }\n.lg { --size: 64px; }\n\n.initials {\n background: r9.$accent;\n color: r9.$on-accent;\n}\n\n// A thin accent ring, separated from the photo by the page color\n.photo {\n overflow: visible;\n box-shadow: 0 0 0 2px r9.$bg, 0 0 0 3px r9.$accent;\n}\n"],"mappings":""}
@@ -0,0 +1,32 @@
1
+ import type { HTMLAttributes, ReactNode } from 'react';
2
+ type WordmarkProps = HTMLAttributes<HTMLSpanElement> & {
3
+ /** Text to set as a wordmark. Default: the library's name. */
4
+ children?: ReactNode;
5
+ size?: 'sm' | 'md' | 'lg';
6
+ };
7
+ /** Wide-tracked uppercase wordmark in the display font (N I N E O S). */
8
+ export declare function Wordmark({ children, size, className, ...rest }: WordmarkProps): import("react").JSX.Element;
9
+ type MoodToggleProps = {
10
+ className?: string;
11
+ label?: string; /** Leave out "Auto" (e.g. in a tight HUD). */
12
+ withAuto?: boolean;
13
+ };
14
+ /**
15
+ * Auto / light mood / dark mood switch, labeled with the library's mood
16
+ * names (NineOS: Auto, Clear, Cipher). Auto follows the library's Auto rule;
17
+ * a click on a mood sets data-scheme on <html> and saves the choice in the
18
+ * browser. Accent element: the selected option's underline.
19
+ */
20
+ export declare function MoodToggle({ className, label, withAuto }: MoodToggleProps): import("react").JSX.Element;
21
+ /**
22
+ * Motion | Still: the viewer's own switch for movement (the backdrop,
23
+ * revealing titles, swaps, page effects), for anyone who wants it calmer without
24
+ * changing their system. Remembered in the browser. When the system already
25
+ * asks for reduced motion, it shows Still and can't be turned back on here.
26
+ * Accent element: the selected option's underline.
27
+ */
28
+ export declare function MotionToggle({ className, label }: {
29
+ className?: string;
30
+ label?: string;
31
+ }): import("react").JSX.Element;
32
+ export {};