@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.
- package/README.md +136 -2
- package/dist/_variables.scss +197 -0
- package/dist/base.css +106 -0
- package/dist/components/Alert/Alert.d.ts +18 -0
- package/dist/components/Alert/Alert.js +57 -0
- package/dist/components/Alert/Alert.js.map +1 -0
- package/dist/components/Alert/Alert.module.js +17 -0
- package/dist/components/Alert/Alert.module.js.map +1 -0
- package/dist/components/Avatar/Avatar.d.ts +14 -0
- package/dist/components/Avatar/Avatar.js +29 -0
- package/dist/components/Avatar/Avatar.js.map +1 -0
- package/dist/components/Avatar/Avatar.module.js +12 -0
- package/dist/components/Avatar/Avatar.module.js.map +1 -0
- package/dist/components/Brand/Brand.d.ts +32 -0
- package/dist/components/Brand/Brand.js +60 -0
- package/dist/components/Brand/Brand.js.map +1 -0
- package/dist/components/Brand/Brand.module.js +10 -0
- package/dist/components/Brand/Brand.module.js.map +1 -0
- package/dist/components/Breadcrumbs/Breadcrumbs.d.ts +20 -0
- package/dist/components/Breadcrumbs/Breadcrumbs.js +31 -0
- package/dist/components/Breadcrumbs/Breadcrumbs.js.map +1 -0
- package/dist/components/Breadcrumbs/Breadcrumbs.module.js +9 -0
- package/dist/components/Breadcrumbs/Breadcrumbs.module.js.map +1 -0
- package/dist/components/Button/Button.d.ts +33 -0
- package/dist/components/Button/Button.js +66 -0
- package/dist/components/Button/Button.js.map +1 -0
- package/dist/components/Button/Button.module.js +19 -0
- package/dist/components/Button/Button.module.js.map +1 -0
- package/dist/components/Card/Card.d.ts +20 -0
- package/dist/components/Card/Card.js +29 -0
- package/dist/components/Card/Card.js.map +1 -0
- package/dist/components/Card/Card.module.js +10 -0
- package/dist/components/Card/Card.module.js.map +1 -0
- package/dist/components/CaseStudy/CaseStudy.d.ts +37 -0
- package/dist/components/CaseStudy/CaseStudy.js +84 -0
- package/dist/components/CaseStudy/CaseStudy.js.map +1 -0
- package/dist/components/CaseStudy/CaseStudy.module.js +17 -0
- package/dist/components/CaseStudy/CaseStudy.module.js.map +1 -0
- package/dist/components/Choice/Choice.d.ts +33 -0
- package/dist/components/Choice/Choice.js +127 -0
- package/dist/components/Choice/Choice.js.map +1 -0
- package/dist/components/Choice/Choice.module.js +18 -0
- package/dist/components/Choice/Choice.module.js.map +1 -0
- package/dist/components/ContactIcon/ContactIcon.d.ts +16 -0
- package/dist/components/ContactIcon/ContactIcon.js +60 -0
- package/dist/components/ContactIcon/ContactIcon.js.map +1 -0
- package/dist/components/ContactIcon/ContactIcon.module.js +5 -0
- package/dist/components/ContactIcon/ContactIcon.module.js.map +1 -0
- package/dist/components/Field/Field.d.ts +29 -0
- package/dist/components/Field/Field.js +101 -0
- package/dist/components/Field/Field.js.map +1 -0
- package/dist/components/Field/Field.module.js +17 -0
- package/dist/components/Field/Field.module.js.map +1 -0
- package/dist/components/Layout/Layout.d.ts +50 -0
- package/dist/components/Layout/Layout.js +76 -0
- package/dist/components/Layout/Layout.js.map +1 -0
- package/dist/components/Layout/Layout.module.js +20 -0
- package/dist/components/Layout/Layout.module.js.map +1 -0
- package/dist/components/ListRow/ListRow.d.ts +35 -0
- package/dist/components/ListRow/ListRow.js +61 -0
- package/dist/components/ListRow/ListRow.js.map +1 -0
- package/dist/components/ListRow/ListRow.module.js +17 -0
- package/dist/components/ListRow/ListRow.module.js.map +1 -0
- package/dist/components/MediaGallery/MediaGallery.d.ts +31 -0
- package/dist/components/MediaGallery/MediaGallery.js +72 -0
- package/dist/components/MediaGallery/MediaGallery.js.map +1 -0
- package/dist/components/MediaGallery/MediaGallery.module.js +14 -0
- package/dist/components/MediaGallery/MediaGallery.module.js.map +1 -0
- package/dist/components/MenuRail/MenuRail.d.ts +20 -0
- package/dist/components/MenuRail/MenuRail.js +33 -0
- package/dist/components/MenuRail/MenuRail.js.map +1 -0
- package/dist/components/MenuRail/MenuRail.module.js +11 -0
- package/dist/components/MenuRail/MenuRail.module.js.map +1 -0
- package/dist/components/Modal/Modal.d.ts +23 -0
- package/dist/components/Modal/Modal.js +57 -0
- package/dist/components/Modal/Modal.js.map +1 -0
- package/dist/components/Modal/Modal.module.js +17 -0
- package/dist/components/Modal/Modal.module.js.map +1 -0
- package/dist/components/PageTools/PageTools.d.ts +19 -0
- package/dist/components/PageTools/PageTools.js +39 -0
- package/dist/components/PageTools/PageTools.js.map +1 -0
- package/dist/components/PageTools/PageTools.module.js +9 -0
- package/dist/components/PageTools/PageTools.module.js.map +1 -0
- package/dist/components/Panel/Panel.d.ts +20 -0
- package/dist/components/Panel/Panel.js +65 -0
- package/dist/components/Panel/Panel.js.map +1 -0
- package/dist/components/Panel/Panel.module.js +10 -0
- package/dist/components/Panel/Panel.module.js.map +1 -0
- package/dist/components/Panel/PanelBar.d.ts +24 -0
- package/dist/components/Panel/PanelBar.js +45 -0
- package/dist/components/Panel/PanelBar.js.map +1 -0
- package/dist/components/Panel/PanelBar.module.js +12 -0
- package/dist/components/Panel/PanelBar.module.js.map +1 -0
- package/dist/components/Panel/stageContext.d.ts +7 -0
- package/dist/components/Panel/stageContext.js +10 -0
- package/dist/components/Panel/stageContext.js.map +1 -0
- package/dist/components/Progress/Progress.d.ts +14 -0
- package/dist/components/Progress/Progress.js +33 -0
- package/dist/components/Progress/Progress.js.map +1 -0
- package/dist/components/Progress/Progress.module.js +13 -0
- package/dist/components/Progress/Progress.module.js.map +1 -0
- package/dist/components/Prose/Prose.d.ts +13 -0
- package/dist/components/Prose/Prose.js +18 -0
- package/dist/components/Prose/Prose.js.map +1 -0
- package/dist/components/Prose/Prose.module.js +5 -0
- package/dist/components/Prose/Prose.module.js.map +1 -0
- package/dist/components/ScreenshotCarousel/Lightbox.d.ts +19 -0
- package/dist/components/ScreenshotCarousel/Lightbox.js +119 -0
- package/dist/components/ScreenshotCarousel/Lightbox.js.map +1 -0
- package/dist/components/ScreenshotCarousel/ScreenshotCarousel.d.ts +25 -0
- package/dist/components/ScreenshotCarousel/ScreenshotCarousel.js +119 -0
- package/dist/components/ScreenshotCarousel/ScreenshotCarousel.js.map +1 -0
- package/dist/components/ScreenshotCarousel/ScreenshotCarousel.module.js +23 -0
- package/dist/components/ScreenshotCarousel/ScreenshotCarousel.module.js.map +1 -0
- package/dist/components/SegmentedControl/SegmentedControl.d.ts +20 -0
- package/dist/components/SegmentedControl/SegmentedControl.js +23 -0
- package/dist/components/SegmentedControl/SegmentedControl.js.map +1 -0
- package/dist/components/SegmentedControl/SegmentedControl.module.js +8 -0
- package/dist/components/SegmentedControl/SegmentedControl.module.js.map +1 -0
- package/dist/components/Skeleton/Skeleton.d.ts +17 -0
- package/dist/components/Skeleton/Skeleton.js +26 -0
- package/dist/components/Skeleton/Skeleton.js.map +1 -0
- package/dist/components/Skeleton/Skeleton.module.js +11 -0
- package/dist/components/Skeleton/Skeleton.module.js.map +1 -0
- package/dist/components/Table/Pagination.d.ts +16 -0
- package/dist/components/Table/Pagination.js +83 -0
- package/dist/components/Table/Pagination.js.map +1 -0
- package/dist/components/Table/Pagination.module.js +15 -0
- package/dist/components/Table/Pagination.module.js.map +1 -0
- package/dist/components/Table/Table.d.ts +46 -0
- package/dist/components/Table/Table.js +121 -0
- package/dist/components/Table/Table.js.map +1 -0
- package/dist/components/Table/Table.module.js +24 -0
- package/dist/components/Table/Table.module.js.map +1 -0
- package/dist/components/Tabs/Tabs.d.ts +22 -0
- package/dist/components/Tabs/Tabs.js +52 -0
- package/dist/components/Tabs/Tabs.js.map +1 -0
- package/dist/components/Tabs/Tabs.module.js +10 -0
- package/dist/components/Tabs/Tabs.module.js.map +1 -0
- package/dist/components/Tag/Tag.d.ts +21 -0
- package/dist/components/Tag/Tag.js +22 -0
- package/dist/components/Tag/Tag.js.map +1 -0
- package/dist/components/Tag/Tag.module.js +14 -0
- package/dist/components/Tag/Tag.module.js.map +1 -0
- package/dist/components/Text/Text.d.ts +17 -0
- package/dist/components/Text/Text.js +28 -0
- package/dist/components/Text/Text.js.map +1 -0
- package/dist/components/Text/Text.module.js +21 -0
- package/dist/components/Text/Text.module.js.map +1 -0
- package/dist/components/Toast/Toast.d.ts +31 -0
- package/dist/components/Toast/Toast.js +118 -0
- package/dist/components/Toast/Toast.js.map +1 -0
- package/dist/components/Toast/Toast.module.js +18 -0
- package/dist/components/Toast/Toast.module.js.map +1 -0
- package/dist/components/Tooltip/Tooltip.d.ts +19 -0
- package/dist/components/Tooltip/Tooltip.js +35 -0
- package/dist/components/Tooltip/Tooltip.js.map +1 -0
- package/dist/components/Tooltip/Tooltip.module.js +11 -0
- package/dist/components/Tooltip/Tooltip.module.js.map +1 -0
- package/dist/components/VideoPlayer/VideoPlayer.d.ts +24 -0
- package/dist/components/VideoPlayer/VideoPlayer.js +37 -0
- package/dist/components/VideoPlayer/VideoPlayer.js.map +1 -0
- package/dist/components/VideoPlayer/VideoPlayer.module.js +8 -0
- package/dist/components/VideoPlayer/VideoPlayer.module.js.map +1 -0
- package/dist/components.css +2 -0
- package/dist/hooks/mood.d.ts +101 -0
- package/dist/hooks/mood.js +139 -0
- package/dist/hooks/mood.js.map +1 -0
- package/dist/hooks/motion.d.ts +10 -0
- package/dist/hooks/motion.js +27 -0
- package/dist/hooks/motion.js.map +1 -0
- package/dist/hooks/motionSetting.d.ts +21 -0
- package/dist/hooks/motionSetting.js +41 -0
- package/dist/hooks/motionSetting.js.map +1 -0
- package/dist/index.d.ts +59 -0
- package/dist/index.js +40 -0
- package/dist/kit.d.ts +8 -0
- package/dist/kit.js +7 -0
- package/dist/motion/Backdrop.d.ts +13 -0
- package/dist/motion/Backdrop.js +15 -0
- package/dist/motion/Backdrop.js.map +1 -0
- package/dist/motion/Backdrop.module.js +8 -0
- package/dist/motion/Backdrop.module.js.map +1 -0
- package/dist/motion/LiveClock.d.ts +2 -0
- package/dist/motion/LiveClock.js +32 -0
- package/dist/motion/LiveClock.js.map +1 -0
- package/dist/motion/LiveClock.module.js +8 -0
- package/dist/motion/LiveClock.module.js.map +1 -0
- package/dist/motion/Magnet.d.ts +10 -0
- package/dist/motion/Magnet.js +36 -0
- package/dist/motion/Magnet.js.map +1 -0
- package/dist/motion/Magnet.module.js +5 -0
- package/dist/motion/Magnet.module.js.map +1 -0
- package/dist/motion/Mark.d.ts +7 -0
- package/dist/motion/Mark.js +22 -0
- package/dist/motion/Mark.js.map +1 -0
- package/dist/motion/Mark.module.js +5 -0
- package/dist/motion/Mark.module.js.map +1 -0
- package/dist/motion/PageEffects.d.ts +2 -0
- package/dist/motion/PageEffects.js +8 -0
- package/dist/motion/PageEffects.js.map +1 -0
- package/dist/motion/Reveal.d.ts +13 -0
- package/dist/motion/Reveal.js +24 -0
- package/dist/motion/Reveal.js.map +1 -0
- package/dist/motion/Reveal.module.js +6 -0
- package/dist/motion/Reveal.module.js.map +1 -0
- package/dist/motion/TextReveal.d.ts +18 -0
- package/dist/motion/TextReveal.js +13 -0
- package/dist/motion/TextReveal.js.map +1 -0
- package/dist/motion/TiltCard.d.ts +14 -0
- package/dist/motion/TiltCard.js +34 -0
- package/dist/motion/TiltCard.js.map +1 -0
- package/dist/motion/TiltCard.module.js +9 -0
- package/dist/motion/TiltCard.module.js.map +1 -0
- package/dist/motion/ripple.d.ts +15 -0
- package/dist/motion/ripple.js +12 -0
- package/dist/motion/ripple.js.map +1 -0
- package/dist/motion/swap.d.ts +8 -0
- package/dist/motion/swap.js +26 -0
- package/dist/motion/swap.js.map +1 -0
- package/dist/motion/useTextReveal.d.ts +9 -0
- package/dist/motion/useTextReveal.js +9 -0
- package/dist/motion/useTextReveal.js.map +1 -0
- package/dist/motion.d.ts +16 -0
- package/dist/motion.js +13 -0
- package/dist/node_modules/simple-icons/index.js +284 -0
- package/dist/provider/ThemeProvider.d.ts +64 -0
- package/dist/provider/ThemeProvider.js +71 -0
- package/dist/provider/ThemeProvider.js.map +1 -0
- package/dist/provider/mark.d.ts +38 -0
- package/dist/provider/mark.js +40 -0
- package/dist/provider/mark.js.map +1 -0
- package/dist/styles.css +364 -0
- package/dist/tokens.css +254 -0
- package/dist/tokens.d.ts +1146 -0
- package/dist/tokens.js +1146 -0
- package/dist/utils/clock.d.ts +2 -0
- package/dist/utils/clock.js +9 -0
- package/dist/utils/clock.js.map +1 -0
- package/dist/utils/contact.d.ts +28 -0
- package/dist/utils/contact.js +157 -0
- package/dist/utils/contact.js.map +1 -0
- package/dist/utils/cx.d.ts +2 -0
- package/dist/utils/cx.js +8 -0
- package/dist/utils/cx.js.map +1 -0
- package/dist/utils/pageList.d.ts +2 -0
- package/dist/utils/pageList.js +28 -0
- package/dist/utils/pageList.js.map +1 -0
- package/fonts.css +2 -0
- package/package.json +113 -4
- package/scripts/build-tokens.mjs +389 -0
- package/scripts/conformance.mjs +67 -0
- package/scss/_index.scss +15 -0
- package/scss/_mixins.scss +198 -0
- package/scss/base.scss +78 -0
- package/theme.json +8 -0
- package/tokens/color.json +96 -0
- package/tokens/layout.json +29 -0
- package/tokens/motion.json +18 -0
- package/tokens/shape.json +53 -0
- package/tokens/space.json +19 -0
- package/tokens/themes/dark.json +81 -0
- package/tokens/themes/light.json +106 -0
- package/tokens/typography.json +226 -0
package/README.md
CHANGED
|
@@ -1,3 +1,137 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @rnine/core
|
|
2
2
|
|
|
3
|
-
|
|
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 {};
|