@ratio-ui/core 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +117 -2
- package/dist/base.css +2 -0
- package/dist/catalogue.json +179 -0
- package/dist/components/icon/Icon.d.ts +34 -0
- package/dist/components/icon/Icon.js +56 -0
- package/dist/components/icon/glyphs.js +95 -0
- package/dist/components/icon/index.d.ts +3 -0
- package/dist/components/icon/index.js +1 -0
- package/dist/components/icon/registry.d.ts +6 -0
- package/dist/components/icon/registry.js +70 -0
- package/dist/components/inline/Inline.d.ts +22 -0
- package/dist/components/inline/Inline.js +30 -0
- package/dist/components/inline/index.d.ts +3 -0
- package/dist/components/inline/index.js +1 -0
- package/dist/components/stack/Stack.d.ts +18 -0
- package/dist/components/stack/Stack.js +22 -0
- package/dist/components/stack/index.d.ts +3 -0
- package/dist/components/stack/index.js +1 -0
- package/dist/components/text/Text.d.ts +33 -0
- package/dist/components/text/Text.js +43 -0
- package/dist/components/text/index.d.ts +2 -0
- package/dist/components/text/index.js +1 -0
- package/dist/fonts/OFL.txt +93 -0
- package/dist/fonts/inter-latin-400-normal.woff2 +0 -0
- package/dist/fonts/inter-latin-500-normal.woff2 +0 -0
- package/dist/fonts/inter-latin-600-normal.woff2 +0 -0
- package/dist/fonts/inter-latin-ext-400-normal.woff2 +0 -0
- package/dist/fonts/inter-latin-ext-500-normal.woff2 +0 -0
- package/dist/fonts/inter-latin-ext-600-normal.woff2 +0 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +5 -0
- package/dist/lib/cn.js +41 -0
- package/dist/lib/space.d.ts +10 -0
- package/dist/lib/space.js +23 -0
- package/dist/styles.css +2 -0
- package/package.json +127 -4
package/README.md
CHANGED
|
@@ -1,3 +1,118 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @ratio-ui/core
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
React components for Ratio apps: the admin and the apps in its ecosystem. One set of design tokens, one stylesheet and accessible components, drawn to the Ratio design system, so that a screen looks the same wherever it is built.
|
|
4
|
+
|
|
5
|
+
The package is at its foundation (wave 0): the tokens, the theme, the Inter typeface and the components `Icon`, `Stack`, `Inline` and `Text`. Components built on shadcn/ui and Base UI follow in later waves.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
npm i @ratio-ui/core
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
React 19.3 or later is a peer dependency (`react` and `react-dom`, `^19.3.0`). The package is ESM only and needs no Tailwind in the app: the stylesheet is built. Browsers are those that Tailwind CSS 4 supports: Safari 16.4, Chrome 111 and Firefox 128 or later.
|
|
14
|
+
|
|
15
|
+
```tsx
|
|
16
|
+
import '@ratio-ui/core/styles.css'
|
|
17
|
+
import { Stack, Text } from '@ratio-ui/core'
|
|
18
|
+
|
|
19
|
+
export function Heading() {
|
|
20
|
+
return (
|
|
21
|
+
<Stack gap={4}>
|
|
22
|
+
<Text as="h1" variant="h1">
|
|
23
|
+
Settlements
|
|
24
|
+
</Text>
|
|
25
|
+
<Text tone="subdued">Paid out every weekday</Text>
|
|
26
|
+
</Stack>
|
|
27
|
+
)
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
- Import `styles.css` once, at the entry of the app. It holds the tokens, the Inter font faces and every class the components use.
|
|
32
|
+
- `@ratio-ui/core/base.css` is optional: Tailwind's preflight, then the typeface, text colour and white background of the page. Import it next to `styles.css` in an app that wants Ratio's look on the whole page.
|
|
33
|
+
- Each component has an entry of its own (`@ratio-ui/core/icon`, `/inline`, `/stack` and `/text`) as well as the main one.
|
|
34
|
+
- `@ratio-ui/core/catalogue.json` lists every component with its props, when to use it and an example.
|
|
35
|
+
|
|
36
|
+
## Components take no className
|
|
37
|
+
|
|
38
|
+
Components accept no `className` and no `style`, so a screen cannot restyle them and every screen keeps the same look. Layout and type go through the components that own them:
|
|
39
|
+
|
|
40
|
+
- `Stack` and `Inline` space their children by a step of the design system's scale: 0, 1, 2, 4, 6, 7, 8, 11, 12, 14, 24, 32 or 80 px. Any other number is a type error.
|
|
41
|
+
- `Text` sets type and colour from the design system's 13 text styles.
|
|
42
|
+
- `Icon` draws a glyph by name.
|
|
43
|
+
|
|
44
|
+
Assemble screens from the catalogue. When a piece is missing, ask for it to be added to the library rather than styling around it.
|
|
45
|
+
|
|
46
|
+
## Isolation
|
|
47
|
+
|
|
48
|
+
The stylesheet is built to sit inside an app without either side changing the other:
|
|
49
|
+
|
|
50
|
+
- Every class carries an `rt:` prefix and every custom property an `--rt-` prefix, so an app's own Tailwind classes, its own copy of shadcn and its own `--primary` or `--radius` cannot collide with Ratio's.
|
|
51
|
+
- Every size is in px, so an app that sets `html { font-size: 62.5% }` does not resize Ratio.
|
|
52
|
+
- The stylesheet ships unlayered, and its reset applies only to elements that carry an `rt:` class, at the specificity of one class. That beats an app's bare element rules (`button { padding: 10px }`) and Tailwind's preflight. It is not `!important`, because Base UI places popups with inline styles that an `!important` rule would override. Utilities come after the reset and win over it.
|
|
53
|
+
|
|
54
|
+
A browser test holds the guarantee: it loads Tailwind's preflight and a host sheet (element rules, a 62.5% root size and its own variables) before Ratio's stylesheet, and compares the computed styles of Ratio's elements with those on a clean page (`test/browser/isolation.browser.test.tsx`).
|
|
55
|
+
|
|
56
|
+
**The limit.** An app selector that is more specific than one class and reaches an element that Ratio renders, such as `.page button` or `#app h2`, still wins. No stylesheet can prevent that. Write an app's rules for bare elements with `:where()`, which adds no specificity (`:where(.page) button`), or put them in a cascade layer: Ratio's rules are unlayered, and an unlayered rule beats a layered one whatever the specificity.
|
|
57
|
+
|
|
58
|
+
## Versioning
|
|
59
|
+
|
|
60
|
+
The package follows semantic versioning, with this rule for what is breaking, written down before the first release:
|
|
61
|
+
|
|
62
|
+
- **Major**: removing a prop, a variant or a token, or any change that moves layout (heights, spacing, radius).
|
|
63
|
+
- **Minor**: a colour or ring change within the existing tokens.
|
|
64
|
+
- **Patch**: fixes.
|
|
65
|
+
- A deprecated prop keeps working for one major version, with a console warning.
|
|
66
|
+
|
|
67
|
+
Additions (a new component, prop or variant) are minor, as in any semantic version.
|
|
68
|
+
|
|
69
|
+
Changes are recorded with [Changesets](https://github.com/changesets/changesets). A pull request that changes the library adds a changeset (`npm run changeset`) that says which of the three it is, and one that touches nothing the package ships adds an empty one (`npm run changeset -- --empty`). `npm run api:check` fails when the built package's public API differs from the committed report in `api/report.d.ts`, so a removed or narrowed prop cannot reach a minor release unseen.
|
|
70
|
+
|
|
71
|
+
## Development
|
|
72
|
+
|
|
73
|
+
Node 24 (see `.nvmrc`) and npm 11. Install with `npm ci`. Playwright's Chromium runs the browser tests and the story tests: install it once with `npx playwright install chromium`.
|
|
74
|
+
|
|
75
|
+
| Command | What it does |
|
|
76
|
+
| --- | --- |
|
|
77
|
+
| `npm run ci` | Every check that CI runs, in CI's order: lint, typecheck, `generate -- --check`, tests, build, pack test, package check, API check, size |
|
|
78
|
+
| `npm run lint` | ESLint with no warnings allowed, and Stylelint |
|
|
79
|
+
| `npm run typecheck` | `tsc --noEmit` over the source, scripts, tests and Storybook setup |
|
|
80
|
+
| `npm test` | The unit, browser and Storybook tests |
|
|
81
|
+
| `npm run test:unit` | Unit tests in Node |
|
|
82
|
+
| `npm run test:browser` | Component tests in Chromium |
|
|
83
|
+
| `npm run test:storybook` | Every story renders in Chromium and passes axe |
|
|
84
|
+
| `npm run storybook` | Storybook on port 6006 |
|
|
85
|
+
| `npm run build-storybook` | A static Storybook |
|
|
86
|
+
| `npm run generate` | Rewrites `src/index.ts`, the `exports` of `package.json` and `catalogue.json` from the component folders. `npm run generate -- --check` only compares |
|
|
87
|
+
| `npm run build` | `dist/`: ESM and types, `styles.css`, `base.css`, the Inter files and `catalogue.json` |
|
|
88
|
+
| `npm run build:css` | The stylesheets and fonts only |
|
|
89
|
+
| `npm run test:pack` | Installs the packed tarball in a fixture app that type-checks and builds it. It needs `dist` and fetches vite, typescript and Tabler from the npm registry, so a cold cache takes minutes |
|
|
90
|
+
| `npm run check:package` | publint and Are the Types Wrong? on the tarball |
|
|
91
|
+
| `npm run api:report` | Rewrites `api/report.d.ts` from `dist` |
|
|
92
|
+
| `npm run api:check` | Fails when the public API differs from `api/report.d.ts` |
|
|
93
|
+
| `npm run size` | Gzip size of every entry against `size-budget.json` |
|
|
94
|
+
| `npm run test:vrt` | Screenshots every story in the pinned Linux browser and compares it with its baseline |
|
|
95
|
+
| `npm run test:vrt:update` | Rewrites the baselines after an intended visual change |
|
|
96
|
+
| `npm run intake` | Takes shadcn components in as a dated snapshot (see `AGENTS.md`) |
|
|
97
|
+
| `npm run changeset` | Adds a changeset |
|
|
98
|
+
| `npm run version-packages` | `changeset version`, then `npm run generate`. The release workflow runs it |
|
|
99
|
+
|
|
100
|
+
`test:pack` checks that `dist/index.js` exists, not that `dist` is current with `src`, so it needs `npm run build` first. `npm run ci` builds before it packs.
|
|
101
|
+
|
|
102
|
+
### Visual regression
|
|
103
|
+
|
|
104
|
+
Docker must be running for `npm run test:vrt`. It starts a container of the Playwright 1.64.1 image (`ratio-ui-pw`), screenshots every story at 1440 px (desktop) and 390 px (phone) wide, compares each with its PNG in `test/vrt/__screenshots__` and stops the container.
|
|
105
|
+
|
|
106
|
+
- `npm run test:vrt:update` follows an intended visual change. Review its PNG diff before committing it.
|
|
107
|
+
- The baselines are screenshots of the stories as rendered, without running `play`: a state that needs an interaction has to be a story of its own.
|
|
108
|
+
- A story must not depend on the viewport size. The runner grows the page to the whole story and fails loudly if its size changes, which is what viewport units (`vw`, `vh`), media queries and fixed positioning do.
|
|
109
|
+
- At Vitest's default threshold a small hex edit is not caught by a screenshot, so the token tests pin the hex values.
|
|
110
|
+
- Until the repository has CI, the baselines are the linux/arm64 renders recorded on a laptop. Once it has CI, CI's x86_64 render becomes the source of truth: run the `vrt-update` workflow once and commit its artifact. A run on an arm64 machine can then differ from those baselines by anti-aliasing, so CI's `vrt` job is the verdict.
|
|
111
|
+
|
|
112
|
+
## Design
|
|
113
|
+
|
|
114
|
+
The Ratio design system is the source of truth for every value, and it wins where the dashboard design differs from it. Its files and the plan the library follows are kept in the source repository under `docs/spec`, which the package does not ship.
|
|
115
|
+
|
|
116
|
+
## Licence
|
|
117
|
+
|
|
118
|
+
UNLICENSED: all rights reserved. The Inter typeface bundled in `dist/fonts` is under the SIL Open Font License, whose text is `dist/fonts/OFL.txt` in the package. The owners may choose an open licence later.
|
package/dist/base.css
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */
|
|
2
|
+
@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Noto Sans,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;line-height:1.5}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-feature-settings:normal;font-variation-settings:normal;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring:where(:not(iframe)){outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}html{font-family:var(--rt-typeface);color:var(--rt-foreground);background-color:var(--rt-page);color-scheme:light}}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "0.1.0",
|
|
3
|
+
"components": [
|
|
4
|
+
{
|
|
5
|
+
"name": "Icon",
|
|
6
|
+
"import": "import { Icon } from '@ratio-ui/core'",
|
|
7
|
+
"description": "Draws one icon of the registry: the design system's own glyphs, filled in a single colour, and Tabler's icons for the rest, drawn with a 1.5px line at every size. The icon is a square box of 8, 12 or 16px and takes the colour of its tone.",
|
|
8
|
+
"props": [
|
|
9
|
+
{
|
|
10
|
+
"name": "name",
|
|
11
|
+
"type": "\"alert-triangle\" | \"check\" | \"chevron-left\" | \"chevron-right\" | \"export\" | \"info-circle\" | \"nav-caret-down\" | \"nav-chevron\" | \"nav-home\" | \"nav-product\" | \"nav-product-2\" | \"nav-shortcut\" | \"plus\" | \"search\" | \"x\"",
|
|
12
|
+
"required": true,
|
|
13
|
+
"description": "Which icon to draw, by name."
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"name": "size",
|
|
17
|
+
"type": "8 | 12 | 16",
|
|
18
|
+
"required": false,
|
|
19
|
+
"default": "12",
|
|
20
|
+
"description": "The square box in px: 8, 12 or 16. Defaults to 12, the size inside controls."
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"name": "tone",
|
|
24
|
+
"type": "\"current\" | \"icon\" | \"primary\" | \"subdued\"",
|
|
25
|
+
"required": false,
|
|
26
|
+
"default": "current",
|
|
27
|
+
"description": "The colour. current, the default, takes the colour of the text around the icon; the other tones set their own."
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"name": "label",
|
|
31
|
+
"type": "string",
|
|
32
|
+
"required": false,
|
|
33
|
+
"description": "The accessible name. With a label the icon is an image that assistive technology announces under that name. Without one it is decoration, hidden from assistive technology, and the text beside it has to say what it means."
|
|
34
|
+
}
|
|
35
|
+
],
|
|
36
|
+
"usage": {
|
|
37
|
+
"whenToUse": "- A glyph beside a label inside a control: the plus on a main button, the magnifier in a search field, the export tray on a secondary button. Use size 12\n- The side navigation: the nav glyphs at size 16, and the disclosure caret (nav-chevron or nav-caret-down, one glyph under two names) at size 8\n- Pagination: chevron-left and chevron-right at size 8\n- A mark that Tabler supplies: check, x, alert-triangle and info-circle. They are drawn with a 1.5px line at every size, so they sit beside the design system's own glyphs without looking heavier\n- Meaning that lives only in the icon: pass label. The icon is then an image that assistive technology announces under that name. Without a label it is decoration and is hidden from assistive technology\n- Colour: tone current, the default, takes the colour of the text around the icon. icon is the design system's icon ink, subdued is its subdued text ink and primary is the accent\n- Chevron geometry (design question 9): the design system has no vector for its pagination chevrons, only a 1.5px CSS caret in an 8px box, so chevron-left and chevron-right stand in. Each is the outline of a line 1.5 units wide with round ends, two legs at 45 degrees, each 2.5 units across and 2.5 down, through (2.75, 1.5), (5.25, 4) and (2.75, 6.5) in an 8 unit box. They scale like every filled glyph, so draw them at size 8, and expect them to be replaced when the designer sends real vectors",
|
|
38
|
+
"whenNotToUse": "- Decoration that adds no meaning. An icon next to text that already says the same thing is hidden from assistive technology, so leave the label off, and leave the icon out when it adds nothing\n- An icon the registry does not have. Components accept no className or style, and icons come from the registry only, so a new one is a registry entry: the design system's glyph first, Tabler for the rest\n- An icon-only control without a name. Pass label, or give the control its own accessible name\n- A size other than 8, 12 or 16, or a colour other than the four tones. There is no red, no destructive colour and no third accent: an error is marked with the alert-triangle glyph beside its message, not with a colour\n- Emoji, or unicode arrows and symbols, as icons. Inter's web subsets do not hold them and the design system bans them",
|
|
39
|
+
"example": "import { Icon } from '@ratio-ui/core'\n\n// Beside text that names it: decoration, hidden from assistive technology\n<button type=\"button\">\n <Icon name=\"plus\" />\n Add product\n</button>\n\n// Alone: the label is the accessible name\n<Icon name=\"search\" tone=\"icon\" label=\"Search\" />\n\n// Pagination chevrons are drawn for an 8px box\n<Icon name=\"chevron-right\" size={8} />"
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"name": "Inline",
|
|
44
|
+
"import": "import { Inline } from '@ratio-ui/core'",
|
|
45
|
+
"description": "Lays its children out in a row with a fixed space between them. It takes no className and no style: the gap is a step of the design system's spacing scale, and the layout is the only styling it has.",
|
|
46
|
+
"props": [
|
|
47
|
+
{
|
|
48
|
+
"name": "gap",
|
|
49
|
+
"type": "0 | 1 | 2 | 4 | 6 | 7 | 8 | 11 | 12 | 14 | 24 | 32 | 80",
|
|
50
|
+
"required": true,
|
|
51
|
+
"description": "The space between children, a step of the design system's scale in px: 0, 1, 2, 4, 6, 7, 8, 11, 12, 14, 24, 32 or 80."
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"name": "align",
|
|
55
|
+
"type": "\"baseline\" | \"center\" | \"end\" | \"start\" | \"stretch\"",
|
|
56
|
+
"required": false,
|
|
57
|
+
"default": "center",
|
|
58
|
+
"description": "How children line up across the row, which is the vertical axis. Defaults to center."
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
"name": "justify",
|
|
62
|
+
"type": "\"between\" | \"center\" | \"end\" | \"start\"",
|
|
63
|
+
"required": false,
|
|
64
|
+
"default": "start",
|
|
65
|
+
"description": "How children spread along the row, which is the horizontal axis. Defaults to start."
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"name": "wrap",
|
|
69
|
+
"type": "boolean",
|
|
70
|
+
"required": false,
|
|
71
|
+
"default": "false",
|
|
72
|
+
"description": "Whether children move to a new line when the row is full. Defaults to false, which keeps one line."
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
"name": "as",
|
|
76
|
+
"type": "\"aside\" | \"div\" | \"fieldset\" | \"footer\" | \"form\" | \"header\" | \"li\" | \"main\" | \"nav\" | \"ol\" | \"section\" | \"ul\"",
|
|
77
|
+
"required": false,
|
|
78
|
+
"default": "div",
|
|
79
|
+
"description": "The element to render. Defaults to div; use a list, landmark or form element where the content is one."
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
"name": "ref",
|
|
83
|
+
"type": "Ref<HTMLElement>",
|
|
84
|
+
"required": false,
|
|
85
|
+
"description": "Receives the rendered element."
|
|
86
|
+
}
|
|
87
|
+
],
|
|
88
|
+
"usage": {
|
|
89
|
+
"whenToUse": "- Children side by side with a fixed space between them: a toolbar, a row of tags, a label next to a value\n- Children that spread along the row (`justify`: start, center, end or between) or move to the next line when the row is full (`wrap`)\n- A gap taken from the design system's spacing scale: 0, 1, 2, 4, 6, 7, 8, 11, 12, 14, 24, 32 or 80 px\n- A row that is also a list or a landmark: `as` renders `ul`, `ol`, `li`, `nav`, `header`, `footer`, `main`, `aside`, `section`, `form` or `fieldset` instead of `div`",
|
|
90
|
+
"whenNotToUse": "- Children one under another: use Stack\n- Columns that have to line up from one row to the next: Inline lays out one row at a time, and wave 0 has no grid\n- Space around one child or at the edge of a container: Inline spaces siblings only, and has no padding or margin\n- Styling: Inline takes no `className` and no `style`\n- A list without markers: `as=\"ul\"` and `as=\"ol\"` leave the browser's list markers as they are",
|
|
91
|
+
"example": "<Inline gap={8} justify=\"between\" wrap>\n <div>Orders</div>\n <Inline gap={4}>\n <div>Export</div>\n <div>Filter</div>\n </Inline>\n</Inline>"
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
"name": "Stack",
|
|
96
|
+
"import": "import { Stack } from '@ratio-ui/core'",
|
|
97
|
+
"description": "Lays its children out in a column with a fixed space between them. It takes no className and no style: the gap is a step of the design system's spacing scale, and the layout is the only styling it has.",
|
|
98
|
+
"props": [
|
|
99
|
+
{
|
|
100
|
+
"name": "gap",
|
|
101
|
+
"type": "0 | 1 | 2 | 4 | 6 | 7 | 8 | 11 | 12 | 14 | 24 | 32 | 80",
|
|
102
|
+
"required": true,
|
|
103
|
+
"description": "The space between children, a step of the design system's scale in px: 0, 1, 2, 4, 6, 7, 8, 11, 12, 14, 24, 32 or 80."
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
"name": "align",
|
|
107
|
+
"type": "\"center\" | \"end\" | \"start\" | \"stretch\"",
|
|
108
|
+
"required": false,
|
|
109
|
+
"default": "stretch",
|
|
110
|
+
"description": "How children line up across the stack, which is the horizontal axis. Defaults to stretch, which fills the width."
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
"name": "as",
|
|
114
|
+
"type": "\"aside\" | \"div\" | \"fieldset\" | \"footer\" | \"form\" | \"header\" | \"li\" | \"main\" | \"nav\" | \"ol\" | \"section\" | \"ul\"",
|
|
115
|
+
"required": false,
|
|
116
|
+
"default": "div",
|
|
117
|
+
"description": "The element to render. Defaults to div; use a list, landmark or form element where the content is one."
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
"name": "ref",
|
|
121
|
+
"type": "Ref<HTMLElement>",
|
|
122
|
+
"required": false,
|
|
123
|
+
"description": "Receives the rendered element."
|
|
124
|
+
}
|
|
125
|
+
],
|
|
126
|
+
"usage": {
|
|
127
|
+
"whenToUse": "- Children one under another with a fixed space between them: form fields, the parts of a card, page sections\n- A gap taken from the design system's spacing scale: 0, 1, 2, 4, 6, 7, 8, 11, 12, 14, 24, 32 or 80 px\n- A column that is also a list or a landmark: `as` renders `ul`, `ol`, `li`, `nav`, `header`, `footer`, `main`, `aside`, `section`, `form` or `fieldset` instead of `div`",
|
|
128
|
+
"whenNotToUse": "- Children side by side: use Inline\n- Space around one child or at the edge of a container: Stack spaces siblings only, and has no padding or margin\n- A gap that is not on the scale: 10 or 16 is a type error, so use the nearest step\n- Styling: Stack takes no `className` and no `style`\n- A list without markers: `as=\"ul\"` and `as=\"ol\"` leave the browser's list markers as they are",
|
|
129
|
+
"example": "<Stack gap={12}>\n <div>Settlement summary</div>\n <Stack gap={4} align=\"start\">\n <div>Paid out every weekday</div>\n <div>Next payout on Monday</div>\n </Stack>\n</Stack>"
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
"name": "Text",
|
|
134
|
+
"import": "import { Text } from '@ratio-ui/core'",
|
|
135
|
+
"description": "Sets text in one of the design system's type styles and one of its colours. It takes no className and no style: the variant and the tone are the only ways to change how text looks, so every text on a screen comes from the type scale.",
|
|
136
|
+
"props": [
|
|
137
|
+
{
|
|
138
|
+
"name": "variant",
|
|
139
|
+
"type": "\"b1\" | \"b2\" | \"b3\" | \"b4\" | \"c1\" | \"c2\" | \"c3\" | \"display\" | \"h1\" | \"h5\" | \"label\" | \"s1\" | \"s2\"",
|
|
140
|
+
"required": false,
|
|
141
|
+
"default": "b3",
|
|
142
|
+
"description": "The text style: size, line height, weight and letter spacing. Defaults to b3, the body text."
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
"name": "tone",
|
|
146
|
+
"type": "\"default\" | \"inherit\" | \"muted\" | \"primary\" | \"subdued\"",
|
|
147
|
+
"required": false,
|
|
148
|
+
"default": "default",
|
|
149
|
+
"description": "The colour of the text. Defaults to default, which depends on the variant."
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
"name": "as",
|
|
153
|
+
"type": "\"dd\" | \"div\" | \"dt\" | \"em\" | \"h1\" | \"h2\" | \"h3\" | \"h4\" | \"h5\" | \"h6\" | \"legend\" | \"p\" | \"span\" | \"strong\"",
|
|
154
|
+
"required": false,
|
|
155
|
+
"default": "span",
|
|
156
|
+
"description": "The element to render. Defaults to span; use p for a paragraph and h1 to h6 for a heading, whatever the variant looks like."
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
"name": "truncate",
|
|
160
|
+
"type": "boolean",
|
|
161
|
+
"required": false,
|
|
162
|
+
"default": "false",
|
|
163
|
+
"description": "Keeps the text on one line and ends it with an ellipsis where it does not fit. This shows only when the element is a block, so pair it with p or div. Defaults to false."
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
"name": "ref",
|
|
167
|
+
"type": "Ref<HTMLElement>",
|
|
168
|
+
"required": false,
|
|
169
|
+
"description": "Receives the rendered element."
|
|
170
|
+
}
|
|
171
|
+
],
|
|
172
|
+
"usage": {
|
|
173
|
+
"whenToUse": "- Any text on a screen: every label, heading, value and hint is set with Text, because components take no `className` and no `style`\n- A style from the design system's type scale: `variant` is one of display, h1, h5, s1, s2, b1, b2, b3, b4, c1, c2, c3 or label, and b3 is the default\n- A colour from the design system's text colours: `tone` is default, subdued, muted, primary or inherit\n- A heading, paragraph or list term that must look like another style: `as` picks the element (span, p, div, strong, em, h1 to h6, legend, dt or dd) and `variant` picks the look, so the two are chosen apart\n- A single line that is cut with an ellipsis: `truncate`, on a block element such as `as=\"p\"` or `as=\"div\"`",
|
|
174
|
+
"whenNotToUse": "- Text in a button: buttons take the design system's two button styles, which are not Text variants\n- A colour that is not a tone: `color` is a type error, and so are `className` and `style`\n- A style that is not in the type scale: `variant=\"h2\"` is a type error, so pick the nearest of the 13\n- Space around text: use Stack or Inline\n- Several lines cut at a number of lines: `truncate` keeps one line",
|
|
175
|
+
"example": "<Text as=\"h1\" variant=\"h1\">Settlements</Text>\n<Text tone=\"subdued\">Paid out every weekday</Text>"
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
]
|
|
179
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { IconName } from "./registry.js";
|
|
2
|
+
import { JSX, SVGAttributes } from "react";
|
|
3
|
+
/** The square box an icon is drawn in, in px: 8 for chevrons, 12 inside controls and 16 in the side navigation. */
|
|
4
|
+
export type IconSize = 8 | 12 | 16;
|
|
5
|
+
/**
|
|
6
|
+
* The ink of an icon. current takes the colour of the text around it, icon is the design system's icon ink, subdued is
|
|
7
|
+
* its subdued text ink and primary is the accent.
|
|
8
|
+
*/
|
|
9
|
+
export type IconTone = 'current' | 'icon' | 'subdued' | 'primary';
|
|
10
|
+
/**
|
|
11
|
+
* Props of Icon. Other SVG attributes, such as id and data-*, pass through to the svg. The icon owns its box (width,
|
|
12
|
+
* height, viewBox), its paint (fill, stroke) and its line (strokeWidth, strokeLinecap, strokeLinejoin), so a value
|
|
13
|
+
* passed for one of those is ignored. Name the icon with label, not aria-label: its role and aria-hidden follow the
|
|
14
|
+
* label.
|
|
15
|
+
*/
|
|
16
|
+
export interface IconProps extends Omit<SVGAttributes<SVGSVGElement>, 'className' | 'style' | 'color' | 'children'> {
|
|
17
|
+
/** Which icon to draw, by name. */
|
|
18
|
+
name: IconName;
|
|
19
|
+
/** The square box in px: 8, 12 or 16. Defaults to 12, the size inside controls. */
|
|
20
|
+
size?: IconSize;
|
|
21
|
+
/** The colour. current, the default, takes the colour of the text around the icon; the other tones set their own. */
|
|
22
|
+
tone?: IconTone;
|
|
23
|
+
/**
|
|
24
|
+
* The accessible name. With a label the icon is an image that assistive technology announces under that name. Without
|
|
25
|
+
* one it is decoration, hidden from assistive technology, and the text beside it has to say what it means.
|
|
26
|
+
*/
|
|
27
|
+
label?: string;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Draws one icon of the registry: the design system's own glyphs, filled in a single colour, and Tabler's icons for the
|
|
31
|
+
* rest, drawn with a 1.5px line at every size. The icon is a square box of 8, 12 or 16px and takes the colour of its
|
|
32
|
+
* tone.
|
|
33
|
+
*/
|
|
34
|
+
export declare function Icon({ name, size, tone, label, ...rest }: IconProps): JSX.Element;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { cn } from "../../lib/cn.js";
|
|
2
|
+
import { ICONS } from "./registry.js";
|
|
3
|
+
import { jsx } from "react/jsx-runtime";
|
|
4
|
+
// src/components/icon/Icon.tsx
|
|
5
|
+
const TONE_CLASSES = {
|
|
6
|
+
current: "",
|
|
7
|
+
icon: "rt:text-icon",
|
|
8
|
+
subdued: "rt:text-foreground-subdued",
|
|
9
|
+
primary: "rt:text-primary"
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Draws one icon of the registry: the design system's own glyphs, filled in a single colour, and Tabler's icons for the
|
|
13
|
+
* rest, drawn with a 1.5px line at every size. The icon is a square box of 8, 12 or 16px and takes the colour of its
|
|
14
|
+
* tone.
|
|
15
|
+
*/
|
|
16
|
+
function Icon({ name, size = 12, tone = "current", label, ...rest }) {
|
|
17
|
+
const entry = ICONS[name];
|
|
18
|
+
const own = {
|
|
19
|
+
width: size,
|
|
20
|
+
height: size,
|
|
21
|
+
className: cn("rt:inline-block rt:align-baseline rt:shrink-0", TONE_CLASSES[tone]),
|
|
22
|
+
...label ? {
|
|
23
|
+
role: "img",
|
|
24
|
+
"aria-label": label
|
|
25
|
+
} : {
|
|
26
|
+
"aria-hidden": true,
|
|
27
|
+
focusable: false
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
if (entry.kind === "tabler") {
|
|
31
|
+
const line = 36 / size;
|
|
32
|
+
return /* @__PURE__ */ jsx(entry.component, {
|
|
33
|
+
...rest,
|
|
34
|
+
...own,
|
|
35
|
+
viewBox: "0 0 24 24",
|
|
36
|
+
fill: "none",
|
|
37
|
+
stroke: line,
|
|
38
|
+
strokeWidth: line,
|
|
39
|
+
strokeLinecap: "round",
|
|
40
|
+
strokeLinejoin: "round"
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
return /* @__PURE__ */ jsx("svg", {
|
|
44
|
+
...rest,
|
|
45
|
+
...own,
|
|
46
|
+
viewBox: entry.glyph.viewBox,
|
|
47
|
+
fill: "currentColor",
|
|
48
|
+
stroke: "none",
|
|
49
|
+
children: entry.glyph.paths.map(({ d, fillRule, transform }) => /* @__PURE__ */ jsx("path", {
|
|
50
|
+
d,
|
|
51
|
+
fillRule,
|
|
52
|
+
transform
|
|
53
|
+
}, d))
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
export { Icon };
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
// src/components/icon/glyphs.ts
|
|
2
|
+
/**
|
|
3
|
+
* plus.svg. The file is a 10 unit box and the design system draws the glyph in a 12px box, so the viewBox is the file's
|
|
4
|
+
* box grown by one unit on every side: the glyph sits centred in the 12px box, and the viewBox is the one change.
|
|
5
|
+
*/
|
|
6
|
+
const PLUS = {
|
|
7
|
+
viewBox: "-1 -1 12 12",
|
|
8
|
+
paths: [{
|
|
9
|
+
d: "M 5.726 0.726 C 5.726 0.534 5.65 0.349 5.514 0.213 C 5.377 0.077 5.193 0 5 0 C 4.807 0 4.623 0.077 4.486 0.213 C 4.35 0.349 4.274 0.534 4.274 0.726 L 4.274 4.274 L 0.726 4.274 C 0.534 4.274 0.349 4.35 0.213 4.486 C 0.077 4.623 0 4.807 0 5 C 0 5.193 0.077 5.377 0.213 5.514 C 0.349 5.65 0.534 5.726 0.726 5.726 L 4.274 5.726 L 4.274 9.274 C 4.274 9.466 4.35 9.651 4.486 9.787 C 4.623 9.923 4.807 10 5 10 C 5.193 10 5.377 9.923 5.514 9.787 C 5.65 9.651 5.726 9.466 5.726 9.274 L 5.726 5.726 L 9.274 5.726 C 9.466 5.726 9.651 5.65 9.787 5.514 C 9.923 5.377 10 5.193 10 5 C 10 4.807 9.923 4.623 9.787 4.486 C 9.651 4.35 9.466 4.274 9.274 4.274 L 5.726 4.274 L 5.726 0.726 Z",
|
|
10
|
+
fillRule: "nonzero"
|
|
11
|
+
}]
|
|
12
|
+
};
|
|
13
|
+
/** search.svg, drawn in its own viewBox. */
|
|
14
|
+
const SEARCH = {
|
|
15
|
+
viewBox: "0 0 12.001 12.001",
|
|
16
|
+
paths: [{
|
|
17
|
+
d: "M 7.883 9.085 C 6.86 9.807 5.603 10.119 4.361 9.959 C 3.119 9.799 1.982 9.179 1.176 8.221 C 0.369 7.263 -0.049 6.038 0.005 4.787 C 0.058 3.535 0.579 2.35 1.464 1.464 C 2.35 0.579 3.535 0.058 4.787 0.005 C 6.038 -0.049 7.263 0.369 8.221 1.176 C 9.179 1.982 9.799 3.119 9.959 4.361 C 10.119 5.603 9.807 6.86 9.085 7.883 L 11.751 10.549 C 11.83 10.628 11.893 10.721 11.936 10.825 C 11.979 10.928 12.001 11.038 12.001 11.15 C 12.001 11.262 11.979 11.372 11.936 11.476 C 11.893 11.579 11.83 11.672 11.751 11.751 C 11.672 11.83 11.579 11.893 11.476 11.936 C 11.372 11.979 11.262 12.001 11.15 12.001 C 11.038 12.001 10.928 11.979 10.825 11.936 C 10.721 11.893 10.628 11.83 10.549 11.751 L 7.883 9.085 Z M 8.3 5 C 8.3 5.875 7.952 6.715 7.334 7.334 C 6.715 7.952 5.875 8.3 5 8.3 C 4.125 8.3 3.285 7.952 2.667 7.334 C 2.048 6.715 1.7 5.875 1.7 5 C 1.7 4.125 2.048 3.285 2.667 2.667 C 3.285 2.048 4.125 1.7 5 1.7 C 5.875 1.7 6.715 2.048 7.334 2.667 C 7.952 3.285 8.3 4.125 8.3 5 Z",
|
|
18
|
+
fillRule: "evenodd"
|
|
19
|
+
}]
|
|
20
|
+
};
|
|
21
|
+
/** export.svg, drawn in its own viewBox. */
|
|
22
|
+
const EXPORT = {
|
|
23
|
+
viewBox: "0 0 12 12",
|
|
24
|
+
paths: [{
|
|
25
|
+
d: "M 11.4 0 C 11.04 0 10.8 0.24 10.8 0.6 L 10.8 3 C 10.8 3.36 10.56 3.6 10.2 3.6 L 1.8 3.6 C 1.44 3.6 1.2 3.36 1.2 3 L 1.2 0.6 C 1.2 0.24 0.96 0 0.6 0 C 0.24 0 0 0.24 0 0.6 L 0 3 C 0 4.02 0.78 4.8 1.8 4.8 L 10.2 4.8 C 11.22 4.8 12 4.02 12 3 L 12 0.6 C 12 0.24 11.76 0 11.4 0 Z",
|
|
26
|
+
fillRule: "nonzero",
|
|
27
|
+
transform: "translate(0 7.185)"
|
|
28
|
+
}, {
|
|
29
|
+
d: "M 2.4 2.025 L 1.02 3.405 C 0.78 3.645 0.42 3.645 0.18 3.405 C -0.06 3.165 -0.06 2.805 0.18 2.565 L 2.58 0.165 C 2.64 0.105 2.7 0.045 2.76 0.045 C 2.94 -0.015 3.12 -0.015 3.24 0.045 C 3.3 0.045 3.36 0.105 3.42 0.165 L 5.82 2.565 C 6.06 2.805 6.06 3.165 5.82 3.405 C 5.58 3.645 5.22 3.645 4.98 3.405 L 3.6 2.025 L 3.6 7.785 C 3.6 8.145 3.36 8.385 3 8.385 C 2.64 8.385 2.4 8.145 2.4 7.785 L 2.4 2.025 Z",
|
|
30
|
+
fillRule: "nonzero",
|
|
31
|
+
transform: "matrix(1,0,0,-1,3,8.385)"
|
|
32
|
+
}]
|
|
33
|
+
};
|
|
34
|
+
/** nav-home.svg, drawn in its own viewBox. */
|
|
35
|
+
const NAV_HOME = {
|
|
36
|
+
viewBox: "0 0 15 16",
|
|
37
|
+
paths: [{
|
|
38
|
+
d: "M 2.5 16 C 2.172 16 1.847 15.935 1.543 15.81 C 1.24 15.684 0.964 15.5 0.732 15.268 C 0.263 14.799 0 14.163 0 13.5 L 0 5.548 C 0 5.225 0.079 4.906 0.229 4.62 C 0.379 4.334 0.596 4.088 0.862 3.904 L 5.986 0.356 C 6.321 0.124 6.718 0 7.125 0 L 7.875 0 C 8.282 0 8.679 0.124 9.014 0.356 L 14.138 3.904 C 14.404 4.088 14.621 4.334 14.771 4.62 C 14.921 4.906 15 5.225 15 5.548 L 15 13.5 C 15 14.163 14.737 14.799 14.268 15.268 C 13.799 15.737 13.163 16 12.5 16 L 2.5 16 Z M 4.5 14.5 L 2.5 14.5 C 2.235 14.5 1.98 14.395 1.793 14.207 C 1.605 14.02 1.5 13.765 1.5 13.5 L 1.5 5.548 C 1.5 5.467 1.52 5.388 1.557 5.316 C 1.594 5.244 1.649 5.183 1.715 5.137 L 6.84 1.589 C 6.924 1.531 7.023 1.5 7.125 1.5 L 7.875 1.5 C 7.977 1.5 8.076 1.531 8.16 1.589 L 13.285 5.137 C 13.351 5.183 13.405 5.244 13.443 5.316 C 13.48 5.387 13.5 5.466 13.5 5.547 L 13.5 13.5 C 13.5 13.765 13.395 14.02 13.207 14.207 C 13.02 14.395 12.765 14.5 12.5 14.5 L 10.5 14.5 L 10.5 8 C 10.5 7.735 10.395 7.48 10.207 7.293 C 10.02 7.105 9.765 7 9.5 7 L 5.5 7 C 5.235 7 4.98 7.105 4.793 7.293 C 4.605 7.48 4.5 7.735 4.5 8 L 4.5 14.5 Z M 6 14.5 L 9 14.5 L 9 8.5 L 6 8.5 L 6 14.5 Z",
|
|
39
|
+
fillRule: "evenodd"
|
|
40
|
+
}]
|
|
41
|
+
};
|
|
42
|
+
/** nav-shortcut.svg, drawn in its own viewBox. */
|
|
43
|
+
const NAV_SHORTCUT = {
|
|
44
|
+
viewBox: "0 0 14 14",
|
|
45
|
+
paths: [{
|
|
46
|
+
d: "M 14 7 C 14 8.857 13.263 10.637 11.95 11.95 C 10.637 13.263 8.857 14 7 14 C 5.143 14 3.363 13.263 2.05 11.95 C 0.737 10.637 0 8.857 0 7 C 0 5.143 0.737 3.363 2.05 2.05 C 3.363 0.737 5.143 0 7 0 C 10.876 0 14 3.134 14 7 Z M 12.5 7 C 12.5 8.459 11.921 9.858 10.889 10.889 C 9.858 11.921 8.459 12.5 7 12.5 C 5.541 12.5 4.142 11.921 3.111 10.889 C 2.079 9.858 1.5 8.459 1.5 7 C 1.5 5.541 2.079 4.142 3.111 3.111 C 4.142 2.079 5.541 1.5 7 1.5 C 10.046 1.5 12.5 3.96 12.5 7 Z",
|
|
47
|
+
fillRule: "evenodd"
|
|
48
|
+
}]
|
|
49
|
+
};
|
|
50
|
+
/** nav-product.svg, drawn in its own viewBox. */
|
|
51
|
+
const NAV_PRODUCT = {
|
|
52
|
+
viewBox: "0 0 16 15.842",
|
|
53
|
+
paths: [{
|
|
54
|
+
d: "M 0 3.726 C 0 2.926 0.545 2.25 1.306 2.046 L 1.324 2.042 L 10.552 0.055 C 10.702 0.017 10.852 0 11 0 C 11.927 0.006 12.75 0.733 12.75 1.74 L 12.75 4.342 L 13.5 4.342 C 14.163 4.342 14.799 4.605 15.268 5.074 C 15.737 5.543 16 6.179 16 6.842 L 16 13.342 C 16 14.005 15.737 14.641 15.268 15.11 C 14.799 15.579 14.163 15.842 13.5 15.842 L 2.5 15.842 C 1.837 15.842 1.201 15.579 0.732 15.11 C 0.263 14.641 0 14.005 0 13.342 L 0 3.726 Z M 10.913 1.512 C 11.112 1.46 11.25 1.602 11.25 1.742 L 11.25 4.342 L 2.5 4.342 C 2.144 4.342 1.806 4.416 1.5 4.55 L 1.5 3.726 C 1.5 3.634 1.559 3.537 1.681 3.499 L 10.897 1.515 L 10.913 1.512 Z M 1.5 6.842 L 1.5 13.342 C 1.5 13.607 1.605 13.862 1.793 14.049 C 1.98 14.237 2.235 14.342 2.5 14.342 L 13.5 14.342 C 13.765 14.342 14.02 14.237 14.207 14.049 C 14.395 13.862 14.5 13.607 14.5 13.342 L 14.5 6.842 C 14.5 6.577 14.395 6.322 14.207 6.135 C 14.02 5.947 13.765 5.842 13.5 5.842 L 2.5 5.842 C 2.235 5.842 1.98 5.947 1.793 6.135 C 1.605 6.322 1.5 6.577 1.5 6.842 Z",
|
|
55
|
+
fillRule: "evenodd"
|
|
56
|
+
}]
|
|
57
|
+
};
|
|
58
|
+
/** nav-product-2.svg, drawn in its own viewBox. */
|
|
59
|
+
const NAV_PRODUCT_2 = {
|
|
60
|
+
viewBox: "0 0 16 15.842",
|
|
61
|
+
paths: [{
|
|
62
|
+
d: "M 10.897 1.515 L 1.681 3.499 C 1.559 3.537 1.5 3.634 1.5 3.726 L 1.5 4.55 C 1.815 4.412 2.156 4.342 2.5 4.342 L 11.25 4.342 L 11.25 1.74 C 11.25 1.6 11.112 1.459 10.913 1.51 M 1.323 2.042 L 10.553 0.055 C 10.703 0.017 10.853 0 11.001 0 C 11.928 0.006 12.751 0.733 12.751 1.74 L 12.751 4.342 L 13.501 4.342 C 14.164 4.342 14.799 4.606 15.268 5.075 C 15.737 5.543 16 6.179 16 6.842 L 16 13.342 C 16 14.005 15.737 14.641 15.268 15.11 C 14.799 15.579 14.163 15.842 13.5 15.842 L 2.5 15.842 C 1.837 15.842 1.201 15.579 0.732 15.11 C 0.263 14.641 0 14.005 0 13.342 L 0 3.726 C 0 2.926 0.545 2.25 1.306 2.046 L 1.324 2.042 L 1.323 2.042 Z M 1.5 13.342 L 1.5 6.842 C 1.5 6.577 1.605 6.322 1.793 6.135 C 1.98 5.947 2.235 5.842 2.5 5.842 L 13.5 5.842 C 13.765 5.842 14.02 5.947 14.207 6.135 C 14.395 6.322 14.5 6.577 14.5 6.842 L 14.5 13.342 C 14.5 13.607 14.395 13.862 14.207 14.049 C 14.02 14.237 13.765 14.342 13.5 14.342 L 2.5 14.342 C 2.235 14.342 1.98 14.237 1.793 14.049 C 1.605 13.862 1.5 13.607 1.5 13.342 Z M 13 10.092 C 13 10.78 12.437 11.342 11.75 11.342 C 11.062 11.342 10.5 10.792 10.5 10.092 C 10.5 9.404 11.063 8.842 11.75 8.842 C 12.438 8.842 13 9.404 13 10.092 Z",
|
|
63
|
+
fillRule: "evenodd"
|
|
64
|
+
}]
|
|
65
|
+
};
|
|
66
|
+
/** nav-chevron.svg, drawn in its own viewBox. nav-caret-down.svg holds the same path, so both names use this glyph. */
|
|
67
|
+
const NAV_CHEVRON = {
|
|
68
|
+
viewBox: "0 0 7.235 4.498",
|
|
69
|
+
paths: [{
|
|
70
|
+
d: "M 0.231 0.208 C 0.087 0.345 0.004 0.534 0 0.733 C -0.004 0.932 0.071 1.124 0.209 1.268 L 3.084 4.268 C 3.154 4.34 3.238 4.398 3.331 4.438 C 3.423 4.478 3.524 4.498 3.625 4.498 C 3.726 4.498 3.826 4.478 3.919 4.438 C 4.012 4.398 4.096 4.34 4.166 4.268 L 7.041 1.274 C 7.172 1.129 7.241 0.939 7.234 0.744 C 7.227 0.549 7.145 0.364 7.004 0.229 C 6.863 0.094 6.675 0.019 6.48 0.02 C 6.285 0.021 6.098 0.099 5.959 0.236 L 3.625 2.664 L 1.292 0.231 C 1.154 0.087 0.965 0.004 0.766 0 C 0.567 -0.004 0.375 0.071 0.232 0.209 L 0.231 0.208 Z",
|
|
71
|
+
fillRule: "evenodd"
|
|
72
|
+
}]
|
|
73
|
+
};
|
|
74
|
+
/**
|
|
75
|
+
* The right chevron. The design system draws its pagination chevrons as a 1.5px CSS caret in an 8px box and has no
|
|
76
|
+
* vector for them (design question 9), so this is a stand-in, to be replaced when the designer sends real vectors. It
|
|
77
|
+
* is the outline of a line 1.5 units wide with round ends: two legs at 45 degrees, each 2.5 units across and 2.5
|
|
78
|
+
* down, from (2.75, 1.5) through (5.25, 4) to (2.75, 6.5) in an 8 unit box, which centres the caret in the box.
|
|
79
|
+
*/
|
|
80
|
+
const CHEVRON_RIGHT = {
|
|
81
|
+
viewBox: "0 0 8 8",
|
|
82
|
+
paths: [{
|
|
83
|
+
d: "M3.2803 0.9697L5.7803 3.4697A0.75 0.75 0 0 1 5.7803 4.5303L3.2803 7.0303A0.75 0.75 0 0 1 2.2197 5.9697L4.1893 4L2.2197 2.0303A0.75 0.75 0 0 1 3.2803 0.9697Z",
|
|
84
|
+
fillRule: "nonzero"
|
|
85
|
+
}]
|
|
86
|
+
};
|
|
87
|
+
/** The left chevron: the right chevron mirrored in x = 4. */
|
|
88
|
+
const CHEVRON_LEFT = {
|
|
89
|
+
viewBox: "0 0 8 8",
|
|
90
|
+
paths: [{
|
|
91
|
+
d: "M4.7197 0.9697L2.2197 3.4697A0.75 0.75 0 0 0 2.2197 4.5303L4.7197 7.0303A0.75 0.75 0 0 0 5.7803 5.9697L3.8107 4L5.7803 2.0303A0.75 0.75 0 0 0 4.7197 0.9697Z",
|
|
92
|
+
fillRule: "nonzero"
|
|
93
|
+
}]
|
|
94
|
+
};
|
|
95
|
+
export { CHEVRON_LEFT, CHEVRON_RIGHT, EXPORT, NAV_CHEVRON, NAV_HOME, NAV_PRODUCT, NAV_PRODUCT_2, NAV_SHORTCUT, PLUS, SEARCH };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Icon } from "./Icon.js";
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import "@tabler/icons-react";
|
|
2
|
+
/**
|
|
3
|
+
* The name of an icon. The design system's own glyphs come first (plus, search, export, the two pagination chevrons and
|
|
4
|
+
* the five navigation glyphs); check, x, alert-triangle and info-circle are Tabler icons drawn with a 1.5px line.
|
|
5
|
+
*/
|
|
6
|
+
export type IconName = 'plus' | 'search' | 'export' | 'chevron-left' | 'chevron-right' | 'nav-home' | 'nav-shortcut' | 'nav-product' | 'nav-product-2' | 'nav-chevron' | 'nav-caret-down' | 'check' | 'x' | 'alert-triangle' | 'info-circle';
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { CHEVRON_LEFT, CHEVRON_RIGHT, EXPORT, NAV_CHEVRON, NAV_HOME, NAV_PRODUCT, NAV_PRODUCT_2, NAV_SHORTCUT, PLUS, SEARCH } from "./glyphs.js";
|
|
2
|
+
import { IconAlertTriangle, IconCheck, IconInfoCircle, IconX } from "@tabler/icons-react";
|
|
3
|
+
// src/components/icon/registry.ts
|
|
4
|
+
/**
|
|
5
|
+
* Every icon by name. nav-chevron and nav-caret-down are one glyph under two names, as in the design system, whose
|
|
6
|
+
* two files hold the same path.
|
|
7
|
+
*/
|
|
8
|
+
const ICONS = {
|
|
9
|
+
plus: {
|
|
10
|
+
kind: "glyph",
|
|
11
|
+
glyph: PLUS
|
|
12
|
+
},
|
|
13
|
+
search: {
|
|
14
|
+
kind: "glyph",
|
|
15
|
+
glyph: SEARCH
|
|
16
|
+
},
|
|
17
|
+
export: {
|
|
18
|
+
kind: "glyph",
|
|
19
|
+
glyph: EXPORT
|
|
20
|
+
},
|
|
21
|
+
"chevron-left": {
|
|
22
|
+
kind: "glyph",
|
|
23
|
+
glyph: CHEVRON_LEFT
|
|
24
|
+
},
|
|
25
|
+
"chevron-right": {
|
|
26
|
+
kind: "glyph",
|
|
27
|
+
glyph: CHEVRON_RIGHT
|
|
28
|
+
},
|
|
29
|
+
"nav-home": {
|
|
30
|
+
kind: "glyph",
|
|
31
|
+
glyph: NAV_HOME
|
|
32
|
+
},
|
|
33
|
+
"nav-shortcut": {
|
|
34
|
+
kind: "glyph",
|
|
35
|
+
glyph: NAV_SHORTCUT
|
|
36
|
+
},
|
|
37
|
+
"nav-product": {
|
|
38
|
+
kind: "glyph",
|
|
39
|
+
glyph: NAV_PRODUCT
|
|
40
|
+
},
|
|
41
|
+
"nav-product-2": {
|
|
42
|
+
kind: "glyph",
|
|
43
|
+
glyph: NAV_PRODUCT_2
|
|
44
|
+
},
|
|
45
|
+
"nav-chevron": {
|
|
46
|
+
kind: "glyph",
|
|
47
|
+
glyph: NAV_CHEVRON
|
|
48
|
+
},
|
|
49
|
+
"nav-caret-down": {
|
|
50
|
+
kind: "glyph",
|
|
51
|
+
glyph: NAV_CHEVRON
|
|
52
|
+
},
|
|
53
|
+
check: {
|
|
54
|
+
kind: "tabler",
|
|
55
|
+
component: IconCheck
|
|
56
|
+
},
|
|
57
|
+
x: {
|
|
58
|
+
kind: "tabler",
|
|
59
|
+
component: IconX
|
|
60
|
+
},
|
|
61
|
+
"alert-triangle": {
|
|
62
|
+
kind: "tabler",
|
|
63
|
+
component: IconAlertTriangle
|
|
64
|
+
},
|
|
65
|
+
"info-circle": {
|
|
66
|
+
kind: "tabler",
|
|
67
|
+
component: IconInfoCircle
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
export { ICONS };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { LayoutElement, Space } from "../../lib/space.js";
|
|
2
|
+
import { HTMLAttributes, JSX, Ref } from "react";
|
|
3
|
+
/** The props of Inline: the HTML attributes of its element, except className and style, with the gap that it needs. */
|
|
4
|
+
export type InlineProps = Omit<HTMLAttributes<HTMLElement>, 'className' | 'style'> & {
|
|
5
|
+
/** The space between children, a step of the design system's scale in px: 0, 1, 2, 4, 6, 7, 8, 11, 12, 14, 24, 32 or 80. */
|
|
6
|
+
gap: Space;
|
|
7
|
+
/** How children line up across the row, which is the vertical axis. Defaults to center. */
|
|
8
|
+
align?: 'start' | 'center' | 'end' | 'baseline' | 'stretch';
|
|
9
|
+
/** How children spread along the row, which is the horizontal axis. Defaults to start. */
|
|
10
|
+
justify?: 'start' | 'center' | 'end' | 'between';
|
|
11
|
+
/** Whether children move to a new line when the row is full. Defaults to false, which keeps one line. */
|
|
12
|
+
wrap?: boolean;
|
|
13
|
+
/** The element to render. Defaults to div; use a list, landmark or form element where the content is one. */
|
|
14
|
+
as?: LayoutElement;
|
|
15
|
+
/** Receives the rendered element. */
|
|
16
|
+
ref?: Ref<HTMLElement>;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Lays its children out in a row with a fixed space between them. It takes no className and no style: the gap is a step
|
|
20
|
+
* of the design system's spacing scale, and the layout is the only styling it has.
|
|
21
|
+
*/
|
|
22
|
+
export declare function Inline({ gap, align, justify, wrap, as, ref, ...rest }: InlineProps): JSX.Element;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { cn } from "../../lib/cn.js";
|
|
2
|
+
import { GAP } from "../../lib/space.js";
|
|
3
|
+
import { createElement } from "react";
|
|
4
|
+
// src/components/inline/Inline.tsx
|
|
5
|
+
const ALIGN_CLASSES = {
|
|
6
|
+
start: "rt:items-start",
|
|
7
|
+
center: "rt:items-center",
|
|
8
|
+
end: "rt:items-end",
|
|
9
|
+
baseline: "rt:items-baseline",
|
|
10
|
+
stretch: "rt:items-stretch"
|
|
11
|
+
};
|
|
12
|
+
const JUSTIFY_CLASSES = {
|
|
13
|
+
start: "rt:justify-start",
|
|
14
|
+
center: "rt:justify-center",
|
|
15
|
+
end: "rt:justify-end",
|
|
16
|
+
between: "rt:justify-between"
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Lays its children out in a row with a fixed space between them. It takes no className and no style: the gap is a step
|
|
20
|
+
* of the design system's spacing scale, and the layout is the only styling it has.
|
|
21
|
+
*/
|
|
22
|
+
function Inline({ gap, align = "center", justify = "start", wrap = false, as = "div", ref, ...rest }) {
|
|
23
|
+
const className = cn("rt:flex", GAP[gap], ALIGN_CLASSES[align], JUSTIFY_CLASSES[justify], wrap && "rt:flex-wrap");
|
|
24
|
+
return createElement(as, {
|
|
25
|
+
...rest,
|
|
26
|
+
ref,
|
|
27
|
+
className
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
export { Inline };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Inline } from "./Inline.js";
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { LayoutElement, Space } from "../../lib/space.js";
|
|
2
|
+
import { HTMLAttributes, JSX, Ref } from "react";
|
|
3
|
+
/** The props of Stack: the HTML attributes of its element, except className and style, with the gap that it needs. */
|
|
4
|
+
export type StackProps = Omit<HTMLAttributes<HTMLElement>, 'className' | 'style'> & {
|
|
5
|
+
/** The space between children, a step of the design system's scale in px: 0, 1, 2, 4, 6, 7, 8, 11, 12, 14, 24, 32 or 80. */
|
|
6
|
+
gap: Space;
|
|
7
|
+
/** How children line up across the stack, which is the horizontal axis. Defaults to stretch, which fills the width. */
|
|
8
|
+
align?: 'start' | 'center' | 'end' | 'stretch';
|
|
9
|
+
/** The element to render. Defaults to div; use a list, landmark or form element where the content is one. */
|
|
10
|
+
as?: LayoutElement;
|
|
11
|
+
/** Receives the rendered element. */
|
|
12
|
+
ref?: Ref<HTMLElement>;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Lays its children out in a column with a fixed space between them. It takes no className and no style: the gap is a
|
|
16
|
+
* step of the design system's spacing scale, and the layout is the only styling it has.
|
|
17
|
+
*/
|
|
18
|
+
export declare function Stack({ gap, align, as, ref, ...rest }: StackProps): JSX.Element;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { cn } from "../../lib/cn.js";
|
|
2
|
+
import { GAP } from "../../lib/space.js";
|
|
3
|
+
import { createElement } from "react";
|
|
4
|
+
// src/components/stack/Stack.tsx
|
|
5
|
+
const ALIGN_CLASSES = {
|
|
6
|
+
start: "rt:items-start",
|
|
7
|
+
center: "rt:items-center",
|
|
8
|
+
end: "rt:items-end",
|
|
9
|
+
stretch: "rt:items-stretch"
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Lays its children out in a column with a fixed space between them. It takes no className and no style: the gap is a
|
|
13
|
+
* step of the design system's spacing scale, and the layout is the only styling it has.
|
|
14
|
+
*/
|
|
15
|
+
function Stack({ gap, align = "stretch", as = "div", ref, ...rest }) {
|
|
16
|
+
return createElement(as, {
|
|
17
|
+
...rest,
|
|
18
|
+
ref,
|
|
19
|
+
className: cn("rt:flex rt:flex-col", GAP[gap], ALIGN_CLASSES[align])
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
export { Stack };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Stack } from "./Stack.js";
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { HTMLAttributes, JSX, Ref } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* One of the design system's 13 text styles, named as in its type scale: display, the headings h1 and h5, the subtitles s1
|
|
4
|
+
* and s2, the body styles b1 to b4, the captions c1 to c3, and the label, which is set in capitals. The design system's
|
|
5
|
+
* two button styles are not among them: buttons take those.
|
|
6
|
+
*/
|
|
7
|
+
export type TextVariant = 'display' | 'h1' | 'h5' | 's1' | 's2' | 'b1' | 'b2' | 'b3' | 'b4' | 'c1' | 'c2' | 'c3' | 'label';
|
|
8
|
+
/**
|
|
9
|
+
* The colour of the text. Default is the body colour for b3 and b4 and the strong colour for every other style, as in the
|
|
10
|
+
* design system. Inherit sets no colour, so the text takes the colour of its parent.
|
|
11
|
+
*/
|
|
12
|
+
export type TextTone = 'default' | 'subdued' | 'muted' | 'primary' | 'inherit';
|
|
13
|
+
/** The props of Text: the HTML attributes of its element, except className, style and color, with the style and tone of the text. */
|
|
14
|
+
export type TextProps = Omit<HTMLAttributes<HTMLElement>, 'className' | 'style' | 'color'> & {
|
|
15
|
+
/** The text style: size, line height, weight and letter spacing. Defaults to b3, the body text. */
|
|
16
|
+
variant?: TextVariant;
|
|
17
|
+
/** The colour of the text. Defaults to default, which depends on the variant. */
|
|
18
|
+
tone?: TextTone;
|
|
19
|
+
/** The element to render. Defaults to span; use p for a paragraph and h1 to h6 for a heading, whatever the variant looks like. */
|
|
20
|
+
as?: 'span' | 'p' | 'div' | 'strong' | 'em' | 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'legend' | 'dt' | 'dd';
|
|
21
|
+
/**
|
|
22
|
+
* Keeps the text on one line and ends it with an ellipsis where it does not fit. This shows only when the element is a
|
|
23
|
+
* block, so pair it with p or div. Defaults to false.
|
|
24
|
+
*/
|
|
25
|
+
truncate?: boolean;
|
|
26
|
+
/** Receives the rendered element. */
|
|
27
|
+
ref?: Ref<HTMLElement>;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Sets text in one of the design system's type styles and one of its colours. It takes no className and no style: the
|
|
31
|
+
* variant and the tone are the only ways to change how text looks, so every text on a screen comes from the type scale.
|
|
32
|
+
*/
|
|
33
|
+
export declare function Text({ variant, tone, as, truncate, ref, ...rest }: TextProps): JSX.Element;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { cn } from "../../lib/cn.js";
|
|
2
|
+
import { createElement } from "react";
|
|
3
|
+
// src/components/text/Text.tsx
|
|
4
|
+
const VARIANT_CLASSES = {
|
|
5
|
+
display: "rt:text-display",
|
|
6
|
+
h1: "rt:text-h1",
|
|
7
|
+
h5: "rt:text-h5",
|
|
8
|
+
s1: "rt:text-s1",
|
|
9
|
+
s2: "rt:text-s2",
|
|
10
|
+
b1: "rt:text-b1",
|
|
11
|
+
b2: "rt:text-b2",
|
|
12
|
+
b3: "rt:text-b3",
|
|
13
|
+
b4: "rt:text-b4",
|
|
14
|
+
c1: "rt:text-c1",
|
|
15
|
+
c2: "rt:text-c2",
|
|
16
|
+
c3: "rt:text-c3",
|
|
17
|
+
label: "rt:text-label rt:uppercase"
|
|
18
|
+
};
|
|
19
|
+
const TONE_CLASSES = {
|
|
20
|
+
subdued: "rt:text-foreground-subdued",
|
|
21
|
+
muted: "rt:text-muted-foreground",
|
|
22
|
+
primary: "rt:text-primary",
|
|
23
|
+
inherit: ""
|
|
24
|
+
};
|
|
25
|
+
const DEFAULT_TONE_CLASSES = {
|
|
26
|
+
body: "rt:text-foreground",
|
|
27
|
+
strong: "rt:text-foreground-strong"
|
|
28
|
+
};
|
|
29
|
+
const BODY_VARIANTS = ["b3", "b4"];
|
|
30
|
+
/**
|
|
31
|
+
* Sets text in one of the design system's type styles and one of its colours. It takes no className and no style: the
|
|
32
|
+
* variant and the tone are the only ways to change how text looks, so every text on a screen comes from the type scale.
|
|
33
|
+
*/
|
|
34
|
+
function Text({ variant = "b3", tone = "default", as = "span", truncate = false, ref, ...rest }) {
|
|
35
|
+
const colour = tone === "default" ? DEFAULT_TONE_CLASSES[BODY_VARIANTS.includes(variant) ? "body" : "strong"] : TONE_CLASSES[tone];
|
|
36
|
+
const className = cn(VARIANT_CLASSES[variant], colour, truncate && "rt:truncate");
|
|
37
|
+
return createElement(as, {
|
|
38
|
+
...rest,
|
|
39
|
+
ref,
|
|
40
|
+
className
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
export { Text };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Text } from "./Text.js";
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
Copyright 2016 The Inter Project Authors (https://github.com/rsms/inter) Inter-Italic[opsz,wght].ttf: Copyright 2016 The Inter Project Authors (https://github.com/rsms/inter)
|
|
2
|
+
|
|
3
|
+
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
|
4
|
+
This license is copied below, and is also available with a FAQ at:
|
|
5
|
+
http://scripts.sil.org/OFL
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
-----------------------------------------------------------
|
|
9
|
+
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
|
10
|
+
-----------------------------------------------------------
|
|
11
|
+
|
|
12
|
+
PREAMBLE
|
|
13
|
+
The goals of the Open Font License (OFL) are to stimulate worldwide
|
|
14
|
+
development of collaborative font projects, to support the font creation
|
|
15
|
+
efforts of academic and linguistic communities, and to provide a free and
|
|
16
|
+
open framework in which fonts may be shared and improved in partnership
|
|
17
|
+
with others.
|
|
18
|
+
|
|
19
|
+
The OFL allows the licensed fonts to be used, studied, modified and
|
|
20
|
+
redistributed freely as long as they are not sold by themselves. The
|
|
21
|
+
fonts, including any derivative works, can be bundled, embedded,
|
|
22
|
+
redistributed and/or sold with any software provided that any reserved
|
|
23
|
+
names are not used by derivative works. The fonts and derivatives,
|
|
24
|
+
however, cannot be released under any other type of license. The
|
|
25
|
+
requirement for fonts to remain under this license does not apply
|
|
26
|
+
to any document created using the fonts or their derivatives.
|
|
27
|
+
|
|
28
|
+
DEFINITIONS
|
|
29
|
+
"Font Software" refers to the set of files released by the Copyright
|
|
30
|
+
Holder(s) under this license and clearly marked as such. This may
|
|
31
|
+
include source files, build scripts and documentation.
|
|
32
|
+
|
|
33
|
+
"Reserved Font Name" refers to any names specified as such after the
|
|
34
|
+
copyright statement(s).
|
|
35
|
+
|
|
36
|
+
"Original Version" refers to the collection of Font Software components as
|
|
37
|
+
distributed by the Copyright Holder(s).
|
|
38
|
+
|
|
39
|
+
"Modified Version" refers to any derivative made by adding to, deleting,
|
|
40
|
+
or substituting -- in part or in whole -- any of the components of the
|
|
41
|
+
Original Version, by changing formats or by porting the Font Software to a
|
|
42
|
+
new environment.
|
|
43
|
+
|
|
44
|
+
"Author" refers to any designer, engineer, programmer, technical
|
|
45
|
+
writer or other person who contributed to the Font Software.
|
|
46
|
+
|
|
47
|
+
PERMISSION & CONDITIONS
|
|
48
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
49
|
+
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
|
50
|
+
redistribute, and sell modified and unmodified copies of the Font
|
|
51
|
+
Software, subject to the following conditions:
|
|
52
|
+
|
|
53
|
+
1) Neither the Font Software nor any of its individual components,
|
|
54
|
+
in Original or Modified Versions, may be sold by itself.
|
|
55
|
+
|
|
56
|
+
2) Original or Modified Versions of the Font Software may be bundled,
|
|
57
|
+
redistributed and/or sold with any software, provided that each copy
|
|
58
|
+
contains the above copyright notice and this license. These can be
|
|
59
|
+
included either as stand-alone text files, human-readable headers or
|
|
60
|
+
in the appropriate machine-readable metadata fields within text or
|
|
61
|
+
binary files as long as those fields can be easily viewed by the user.
|
|
62
|
+
|
|
63
|
+
3) No Modified Version of the Font Software may use the Reserved Font
|
|
64
|
+
Name(s) unless explicit written permission is granted by the corresponding
|
|
65
|
+
Copyright Holder. This restriction only applies to the primary font name as
|
|
66
|
+
presented to the users.
|
|
67
|
+
|
|
68
|
+
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
|
69
|
+
Software shall not be used to promote, endorse or advertise any
|
|
70
|
+
Modified Version, except to acknowledge the contribution(s) of the
|
|
71
|
+
Copyright Holder(s) and the Author(s) or with their explicit written
|
|
72
|
+
permission.
|
|
73
|
+
|
|
74
|
+
5) The Font Software, modified or unmodified, in part or in whole,
|
|
75
|
+
must be distributed entirely under this license, and must not be
|
|
76
|
+
distributed under any other license. The requirement for fonts to
|
|
77
|
+
remain under this license does not apply to any document created
|
|
78
|
+
using the Font Software.
|
|
79
|
+
|
|
80
|
+
TERMINATION
|
|
81
|
+
This license becomes null and void if any of the above conditions are
|
|
82
|
+
not met.
|
|
83
|
+
|
|
84
|
+
DISCLAIMER
|
|
85
|
+
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
86
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
|
87
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
|
88
|
+
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
|
89
|
+
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
90
|
+
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
|
91
|
+
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
92
|
+
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
|
93
|
+
OTHER DEALINGS IN THE FONT SOFTWARE.
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { IconName } from "./components/icon/registry.js";
|
|
2
|
+
import { Icon, IconProps, IconSize, IconTone } from "./components/icon/Icon.js";
|
|
3
|
+
import "./components/icon/index.js";
|
|
4
|
+
import { Space } from "./lib/space.js";
|
|
5
|
+
import { Inline, InlineProps } from "./components/inline/Inline.js";
|
|
6
|
+
import "./components/inline/index.js";
|
|
7
|
+
import { Stack, StackProps } from "./components/stack/Stack.js";
|
|
8
|
+
import "./components/stack/index.js";
|
|
9
|
+
import { Text, TextProps, TextTone, TextVariant } from "./components/text/Text.js";
|
|
10
|
+
import "./components/text/index.js";
|
|
11
|
+
export { Icon, type IconName, type IconProps, type IconSize, type IconTone, Inline, type InlineProps, type Space, Stack, type StackProps, Text, type TextProps, type TextTone, type TextVariant };
|
package/dist/index.js
ADDED
package/dist/lib/cn.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { clsx } from "clsx";
|
|
2
|
+
import { extendTailwindMerge } from "tailwind-merge";
|
|
3
|
+
// src/lib/cn.ts
|
|
4
|
+
const twMerge = extendTailwindMerge({
|
|
5
|
+
prefix: "rt",
|
|
6
|
+
extend: { theme: {
|
|
7
|
+
text: [
|
|
8
|
+
"display",
|
|
9
|
+
"h1",
|
|
10
|
+
"h5",
|
|
11
|
+
"s1",
|
|
12
|
+
"s2",
|
|
13
|
+
"b1",
|
|
14
|
+
"b2",
|
|
15
|
+
"b3",
|
|
16
|
+
"b4",
|
|
17
|
+
"c1",
|
|
18
|
+
"c2",
|
|
19
|
+
"c3",
|
|
20
|
+
"label",
|
|
21
|
+
"btn",
|
|
22
|
+
"btn-sm"
|
|
23
|
+
],
|
|
24
|
+
shadow: [
|
|
25
|
+
"ring-subtle",
|
|
26
|
+
"ring-focus",
|
|
27
|
+
"ring-strong",
|
|
28
|
+
"ring-hairline",
|
|
29
|
+
"ring-accent-hairline"
|
|
30
|
+
],
|
|
31
|
+
container: ["content"]
|
|
32
|
+
} }
|
|
33
|
+
});
|
|
34
|
+
/**
|
|
35
|
+
* Joins class values the way clsx does, then drops every rt: utility that a later one overrides.
|
|
36
|
+
* Classes without the rt: prefix pass through unchanged.
|
|
37
|
+
*/
|
|
38
|
+
function cn(...inputs) {
|
|
39
|
+
return twMerge(clsx(inputs));
|
|
40
|
+
}
|
|
41
|
+
export { cn };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A step of the design system's spacing scale, in px. It is the only gap that Stack and Inline accept, so a gap that the
|
|
3
|
+
* design system does not have (10, 16) is a type error.
|
|
4
|
+
*/
|
|
5
|
+
export type Space = 0 | 1 | 2 | 4 | 6 | 7 | 8 | 11 | 12 | 14 | 24 | 32 | 80;
|
|
6
|
+
/**
|
|
7
|
+
* The elements that a layout component can render as: containers, lists and landmarks. Inline and interactive elements
|
|
8
|
+
* are left out, because a flex container is not one of them.
|
|
9
|
+
*/
|
|
10
|
+
export type LayoutElement = 'div' | 'section' | 'ul' | 'ol' | 'li' | 'nav' | 'header' | 'footer' | 'main' | 'aside' | 'form' | 'fieldset';
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// src/lib/space.ts
|
|
2
|
+
/**
|
|
3
|
+
* The gap class of each step. Every class is written out in full: Tailwind finds a class by reading the source text, so
|
|
4
|
+
* one built from a template (gap- plus a number) would never reach the stylesheet. This file is scanned, because the
|
|
5
|
+
* shipped styles.css reads the code of src/lib. The base is 4px, so step 7 is gap-1.75 and step 80 is gap-20; step 1 is
|
|
6
|
+
* gap-px, which is 1px and not a multiple of the base.
|
|
7
|
+
*/
|
|
8
|
+
const GAP = {
|
|
9
|
+
0: "rt:gap-0",
|
|
10
|
+
1: "rt:gap-px",
|
|
11
|
+
2: "rt:gap-0.5",
|
|
12
|
+
4: "rt:gap-1",
|
|
13
|
+
6: "rt:gap-1.5",
|
|
14
|
+
7: "rt:gap-1.75",
|
|
15
|
+
8: "rt:gap-2",
|
|
16
|
+
11: "rt:gap-2.75",
|
|
17
|
+
12: "rt:gap-3",
|
|
18
|
+
14: "rt:gap-3.5",
|
|
19
|
+
24: "rt:gap-6",
|
|
20
|
+
32: "rt:gap-8",
|
|
21
|
+
80: "rt:gap-20"
|
|
22
|
+
};
|
|
23
|
+
export { GAP };
|
package/dist/styles.css
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */
|
|
2
|
+
@font-face{font-family:Inter;font-style:normal;font-display:swap;font-weight:400;src:url(./fonts/inter-latin-ext-400-normal.woff2)format("woff2");unicode-range:U+100-2BA,U+2BD-2C5,U+2C7-2CC,U+2CE-2D7,U+2DD-2FF,U+304,U+308,U+329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Inter;font-style:normal;font-display:swap;font-weight:400;src:url(./fonts/inter-latin-400-normal.woff2)format("woff2");unicode-range:U+??,U+131,U+152-153,U+2BB-2BC,U+2C6,U+2DA,U+2DC,U+304,U+308,U+329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Inter;font-style:normal;font-display:swap;font-weight:500;src:url(./fonts/inter-latin-ext-500-normal.woff2)format("woff2");unicode-range:U+100-2BA,U+2BD-2C5,U+2C7-2CC,U+2CE-2D7,U+2DD-2FF,U+304,U+308,U+329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Inter;font-style:normal;font-display:swap;font-weight:500;src:url(./fonts/inter-latin-500-normal.woff2)format("woff2");unicode-range:U+??,U+131,U+152-153,U+2BB-2BC,U+2C6,U+2DA,U+2DC,U+304,U+308,U+329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Inter;font-style:normal;font-display:swap;font-weight:600;src:url(./fonts/inter-latin-ext-600-normal.woff2)format("woff2");unicode-range:U+100-2BA,U+2BD-2C5,U+2C7-2CC,U+2CE-2D7,U+2DD-2FF,U+304,U+308,U+329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Inter;font-style:normal;font-display:swap;font-weight:600;src:url(./fonts/inter-latin-600-normal.woff2)format("woff2");unicode-range:U+??,U+131,U+152-153,U+2BB-2BC,U+2C6,U+2DA,U+2DC,U+304,U+308,U+329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}:root{--rt-white:#fff;--rt-blue-600:#3f53fe;--rt-blue-700:#2e40e3;--rt-blue-100:#dde0ff;--rt-ink-900:#131927;--rt-ink-800:#1a2c44;--rt-ink-700:#273951;--rt-ink-600:#344054;--rt-ink-550:#3c4f69;--rt-ink-500:#545969;--rt-ink-450:#667691;--rt-ink-800-a60:#1a2c4499;--rt-line-100:#ecf1f6;--rt-line-150:#dde5ee;--rt-line-200:#e5e7ea;--rt-line-250:#e8e8e8;--rt-green-100:#eafcdd;--rt-green-300:#a8f170;--rt-green-800:#217005;--rt-amber-100:#fff3e2;--rt-amber-400:#f7a62d;--rt-amber-600:#e88b00;--rt-typeface:"Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;--rt-page:var(--rt-white);--rt-background:var(--rt-white);--rt-card:var(--rt-white);--rt-card-foreground:var(--rt-ink-800);--rt-popover:var(--rt-white);--rt-popover-foreground:var(--rt-ink-800);--rt-foreground:var(--rt-ink-800);--rt-foreground-strong:var(--rt-ink-900);--rt-foreground-emphasis:var(--rt-ink-600);--rt-foreground-subdued:var(--rt-ink-550);--rt-muted-foreground:var(--rt-ink-450);--rt-icon:var(--rt-ink-500);--rt-tab-inactive:var(--rt-ink-800-a60);--rt-primary:var(--rt-blue-600);--rt-primary-foreground:var(--rt-white);--rt-primary-hover:var(--rt-blue-700);--rt-primary-tint:var(--rt-blue-100);--rt-secondary:transparent;--rt-secondary-foreground:var(--rt-ink-700);--rt-muted:var(--rt-line-100);--rt-accent:var(--rt-line-100);--rt-accent-foreground:var(--rt-ink-900);--rt-border:var(--rt-line-100);--rt-border-strong:var(--rt-line-250);--rt-divider:var(--rt-line-200);--rt-input:var(--rt-line-100);--rt-control:var(--rt-line-150);--rt-ring:var(--rt-blue-600);--rt-success:var(--rt-green-800);--rt-success-tint:var(--rt-green-100);--rt-success-border:var(--rt-green-300);--rt-warning:var(--rt-amber-600);--rt-warning-tint:var(--rt-amber-100);--rt-warning-border:var(--rt-amber-400);--rt-sidebar:var(--rt-white);--rt-sidebar-foreground:var(--rt-ink-800);--rt-sidebar-primary:var(--rt-blue-600);--rt-sidebar-primary-foreground:var(--rt-white);--rt-sidebar-accent:var(--rt-line-100);--rt-sidebar-accent-foreground:var(--rt-ink-800);--rt-sidebar-border:var(--rt-line-100);--rt-sidebar-ring:var(--rt-blue-600)}[class^=rt\:],[class*=" rt:"],[class^=rt\:]:before,[class*=" rt:"]:before,[class^=rt\:]:after,[class*=" rt:"]:after{box-sizing:border-box;font-family:var(--rt-typeface);border:0 solid;margin:0;padding:0}:root,:host{--rt-spacing:4px;--rt-text-display:48px;--rt-text-display--line-height:58px;--rt-text-display--font-weight:600;--rt-text-display--letter-spacing:0px;--rt-text-h1:34px;--rt-text-h1--line-height:40px;--rt-text-h1--font-weight:600;--rt-text-h1--letter-spacing:0px;--rt-text-h5:28px;--rt-text-h5--line-height:34px;--rt-text-h5--font-weight:600;--rt-text-h5--letter-spacing:0px;--rt-text-s1:28px;--rt-text-s1--line-height:34px;--rt-text-s1--font-weight:600;--rt-text-s1--letter-spacing:0px;--rt-text-s2:24px;--rt-text-s2--line-height:28px;--rt-text-s2--font-weight:600;--rt-text-s2--letter-spacing:0px;--rt-text-b1:12px;--rt-text-b1--line-height:20px;--rt-text-b1--font-weight:400;--rt-text-b1--letter-spacing:0px;--rt-text-b2:12px;--rt-text-b2--line-height:20px;--rt-text-b2--font-weight:500;--rt-text-b2--letter-spacing:0px;--rt-text-b3:14px;--rt-text-b3--line-height:20px;--rt-text-b3--font-weight:400;--rt-text-b3--letter-spacing:-.15px;--rt-text-b4:14px;--rt-text-b4--line-height:20px;--rt-text-b4--font-weight:600;--rt-text-b4--letter-spacing:-.15px;--rt-text-c1:12px;--rt-text-c1--line-height:16px;--rt-text-c1--font-weight:400;--rt-text-c1--letter-spacing:0px;--rt-text-c2:12px;--rt-text-c2--line-height:16px;--rt-text-c2--font-weight:500;--rt-text-c2--letter-spacing:0px;--rt-text-c3:14px;--rt-text-c3--line-height:16px;--rt-text-c3--font-weight:500;--rt-text-c3--letter-spacing:0px;--rt-text-label:12px;--rt-text-label--line-height:16px;--rt-text-label--font-weight:500;--rt-text-label--letter-spacing:0px;--rt-shadow-ring-subtle:inset 0 0 0 1px var(--rt-input), 0 0 0 1px var(--rt-input);--rt-shadow-ring-focus:inset 0 0 0 1px var(--rt-ring), 0 0 0 1px var(--rt-input);--rt-shadow-ring-strong:inset 0 0 0 1px var(--rt-border-strong);--rt-shadow-ring-hairline:inset 0 0 0 .5px var(--rt-control), 0 0 0 .5px var(--rt-control);--rt-shadow-ring-accent-hairline:inset 0 0 0 .5px var(--rt-primary), 0 0 0 .5px var(--rt-primary)}.rt\:flex{display:flex}.rt\:inline-block{display:inline-block}.rt\:shrink-0{flex-shrink:0}.rt\:flex-col{flex-direction:column}.rt\:flex-wrap{flex-wrap:wrap}.rt\:items-baseline{align-items:baseline}.rt\:items-center{align-items:center}.rt\:items-end{align-items:flex-end}.rt\:items-start{align-items:flex-start}.rt\:items-stretch{align-items:stretch}.rt\:justify-between{justify-content:space-between}.rt\:justify-center{justify-content:center}.rt\:justify-end{justify-content:flex-end}.rt\:justify-start{justify-content:flex-start}.rt\:gap-0{gap:0}.rt\:gap-0\.5{gap:calc(var(--rt-spacing) * .5)}.rt\:gap-1{gap:var(--rt-spacing)}.rt\:gap-1\.5{gap:calc(var(--rt-spacing) * 1.5)}.rt\:gap-1\.75{gap:calc(var(--rt-spacing) * 1.75)}.rt\:gap-2{gap:calc(var(--rt-spacing) * 2)}.rt\:gap-2\.75{gap:calc(var(--rt-spacing) * 2.75)}.rt\:gap-3{gap:calc(var(--rt-spacing) * 3)}.rt\:gap-3\.5{gap:calc(var(--rt-spacing) * 3.5)}.rt\:gap-6{gap:calc(var(--rt-spacing) * 6)}.rt\:gap-8{gap:calc(var(--rt-spacing) * 8)}.rt\:gap-20{gap:calc(var(--rt-spacing) * 20)}.rt\:gap-px{gap:1px}.rt\:truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.rt\:align-baseline{vertical-align:baseline}.rt\:text-b1{font-size:var(--rt-text-b1);line-height:var(--tw-leading,var(--rt-text-b1--line-height));letter-spacing:var(--tw-tracking,var(--rt-text-b1--letter-spacing));font-weight:var(--tw-font-weight,var(--rt-text-b1--font-weight))}.rt\:text-b2{font-size:var(--rt-text-b2);line-height:var(--tw-leading,var(--rt-text-b2--line-height));letter-spacing:var(--tw-tracking,var(--rt-text-b2--letter-spacing));font-weight:var(--tw-font-weight,var(--rt-text-b2--font-weight))}.rt\:text-b3{font-size:var(--rt-text-b3);line-height:var(--tw-leading,var(--rt-text-b3--line-height));letter-spacing:var(--tw-tracking,var(--rt-text-b3--letter-spacing));font-weight:var(--tw-font-weight,var(--rt-text-b3--font-weight))}.rt\:text-b4{font-size:var(--rt-text-b4);line-height:var(--tw-leading,var(--rt-text-b4--line-height));letter-spacing:var(--tw-tracking,var(--rt-text-b4--letter-spacing));font-weight:var(--tw-font-weight,var(--rt-text-b4--font-weight))}.rt\:text-c1{font-size:var(--rt-text-c1);line-height:var(--tw-leading,var(--rt-text-c1--line-height));letter-spacing:var(--tw-tracking,var(--rt-text-c1--letter-spacing));font-weight:var(--tw-font-weight,var(--rt-text-c1--font-weight))}.rt\:text-c2{font-size:var(--rt-text-c2);line-height:var(--tw-leading,var(--rt-text-c2--line-height));letter-spacing:var(--tw-tracking,var(--rt-text-c2--letter-spacing));font-weight:var(--tw-font-weight,var(--rt-text-c2--font-weight))}.rt\:text-c3{font-size:var(--rt-text-c3);line-height:var(--tw-leading,var(--rt-text-c3--line-height));letter-spacing:var(--tw-tracking,var(--rt-text-c3--letter-spacing));font-weight:var(--tw-font-weight,var(--rt-text-c3--font-weight))}.rt\:text-display{font-size:var(--rt-text-display);line-height:var(--tw-leading,var(--rt-text-display--line-height));letter-spacing:var(--tw-tracking,var(--rt-text-display--letter-spacing));font-weight:var(--tw-font-weight,var(--rt-text-display--font-weight))}.rt\:text-h1{font-size:var(--rt-text-h1);line-height:var(--tw-leading,var(--rt-text-h1--line-height));letter-spacing:var(--tw-tracking,var(--rt-text-h1--letter-spacing));font-weight:var(--tw-font-weight,var(--rt-text-h1--font-weight))}.rt\:text-h5{font-size:var(--rt-text-h5);line-height:var(--tw-leading,var(--rt-text-h5--line-height));letter-spacing:var(--tw-tracking,var(--rt-text-h5--letter-spacing));font-weight:var(--tw-font-weight,var(--rt-text-h5--font-weight))}.rt\:text-label{font-size:var(--rt-text-label);line-height:var(--tw-leading,var(--rt-text-label--line-height));letter-spacing:var(--tw-tracking,var(--rt-text-label--letter-spacing));font-weight:var(--tw-font-weight,var(--rt-text-label--font-weight))}.rt\:text-s1{font-size:var(--rt-text-s1);line-height:var(--tw-leading,var(--rt-text-s1--line-height));letter-spacing:var(--tw-tracking,var(--rt-text-s1--letter-spacing));font-weight:var(--tw-font-weight,var(--rt-text-s1--font-weight))}.rt\:text-s2{font-size:var(--rt-text-s2);line-height:var(--tw-leading,var(--rt-text-s2--line-height));letter-spacing:var(--tw-tracking,var(--rt-text-s2--letter-spacing));font-weight:var(--tw-font-weight,var(--rt-text-s2--font-weight))}.rt\:text-foreground{color:var(--rt-foreground)}.rt\:text-foreground-strong{color:var(--rt-foreground-strong)}.rt\:text-foreground-subdued{color:var(--rt-foreground-subdued)}.rt\:text-icon{color:var(--rt-icon)}.rt\:text-muted-foreground{color:var(--rt-muted-foreground)}.rt\:text-primary{color:var(--rt-primary)}.rt\:uppercase{text-transform:uppercase}
|
package/package.json
CHANGED
|
@@ -1,6 +1,129 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ratio-ui/core",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "React components for Ratio apps: one set of design tokens, one built stylesheet and accessible components, drawn to the Ratio design system",
|
|
5
|
+
"private": false,
|
|
6
|
+
"license": "UNLICENSED",
|
|
7
|
+
"publishConfig": {
|
|
8
|
+
"access": "public"
|
|
9
|
+
},
|
|
10
|
+
"type": "module",
|
|
11
|
+
"files": [
|
|
12
|
+
"dist"
|
|
13
|
+
],
|
|
14
|
+
"engines": {
|
|
15
|
+
"node": ">=22.12"
|
|
16
|
+
},
|
|
17
|
+
"sideEffects": [
|
|
18
|
+
"**/*.css"
|
|
19
|
+
],
|
|
20
|
+
"scripts": {
|
|
21
|
+
"build:css": "tsx scripts/build-css.ts",
|
|
22
|
+
"typecheck": "tsc --noEmit",
|
|
23
|
+
"lint": "eslint . --max-warnings 0 && stylelint \"src/**/*.css\" \".storybook/**/*.css\"",
|
|
24
|
+
"generate": "tsx scripts/generate.ts",
|
|
25
|
+
"test": "vitest run --project unit --project browser --project storybook",
|
|
26
|
+
"test:unit": "vitest run --project unit",
|
|
27
|
+
"storybook": "storybook dev -p 6006",
|
|
28
|
+
"build-storybook": "storybook build",
|
|
29
|
+
"test:browser": "vitest run --project browser",
|
|
30
|
+
"test:storybook": "vitest run --project storybook",
|
|
31
|
+
"test:vrt": "bash scripts/vrt.sh",
|
|
32
|
+
"test:vrt:update": "bash scripts/vrt.sh -u",
|
|
33
|
+
"intake": "tsx scripts/intake.ts",
|
|
34
|
+
"test:pack": "vitest run --project pack",
|
|
35
|
+
"build": "tsdown && tsx scripts/build-css.ts && cp catalogue.json dist/",
|
|
36
|
+
"check:package": "publint --strict && attw --pack --profile esm-only --exclude-entrypoints ./styles.css ./base.css",
|
|
37
|
+
"api:report": "tsx scripts/api-report.ts",
|
|
38
|
+
"api:check": "tsx scripts/api-report.ts --check",
|
|
39
|
+
"size": "tsx scripts/size.ts",
|
|
40
|
+
"ci": "npm run lint && npm run typecheck && npm run generate -- --check && npm test && npm run build && npm run test:pack && npm run check:package && npm run api:check && npm run size",
|
|
41
|
+
"changeset": "changeset",
|
|
42
|
+
"version-packages": "changeset version && npm run generate"
|
|
43
|
+
},
|
|
44
|
+
"peerDependencies": {
|
|
45
|
+
"react": "^19.3.0",
|
|
46
|
+
"react-dom": "^19.3.0"
|
|
47
|
+
},
|
|
48
|
+
"devDependencies": {
|
|
49
|
+
"@arethetypeswrong/cli": "0.18.5",
|
|
50
|
+
"@base-ui/react": "1.9.0",
|
|
51
|
+
"@changesets/cli": "3.0.3",
|
|
52
|
+
"@emnapi/core": "1.11.3",
|
|
53
|
+
"@emnapi/runtime": "1.11.3",
|
|
54
|
+
"@eslint-react/eslint-plugin": "5.28.8",
|
|
55
|
+
"@fontsource/inter": "5.3.0",
|
|
56
|
+
"@storybook/addon-a11y": "10.6.5",
|
|
57
|
+
"@storybook/addon-docs": "10.6.5",
|
|
58
|
+
"@storybook/addon-mcp": "10.6.5",
|
|
59
|
+
"@storybook/addon-vitest": "10.6.5",
|
|
60
|
+
"@storybook/react-vite": "10.6.5",
|
|
61
|
+
"@tailwindcss/cli": "4.3.3",
|
|
62
|
+
"@tailwindcss/node": "4.3.3",
|
|
63
|
+
"@tailwindcss/vite": "4.3.3",
|
|
64
|
+
"@types/fontkit": "2.0.9",
|
|
65
|
+
"@types/node": "24.19.2",
|
|
66
|
+
"@types/react": "19.3.0",
|
|
67
|
+
"@types/react-dom": "19.3.0",
|
|
68
|
+
"@vitejs/plugin-react": "6.1.2",
|
|
69
|
+
"@vitest/browser": "5.0.5",
|
|
70
|
+
"@vitest/browser-playwright": "5.0.5",
|
|
71
|
+
"axe-core": "4.14.0",
|
|
72
|
+
"class-variance-authority": "0.7.1",
|
|
73
|
+
"eslint": "10.13.0",
|
|
74
|
+
"eslint-plugin-better-tailwindcss": "4.10.0",
|
|
75
|
+
"eslint-plugin-jsx-a11y-x": "0.2.0",
|
|
76
|
+
"eslint-plugin-react-hooks": "7.1.1",
|
|
77
|
+
"eslint-plugin-storybook": "10.6.5",
|
|
78
|
+
"fontkit": "2.0.4",
|
|
79
|
+
"playwright": "1.64.1",
|
|
80
|
+
"postcss": "8.5.32",
|
|
81
|
+
"publint": "0.3.25",
|
|
82
|
+
"react": "19.3.1",
|
|
83
|
+
"react-docgen-typescript": "2.4.0",
|
|
84
|
+
"react-dom": "19.3.1",
|
|
85
|
+
"storybook": "10.6.5",
|
|
86
|
+
"stylelint": "17.16.0",
|
|
87
|
+
"stylelint-config-standard": "40.0.0",
|
|
88
|
+
"tailwindcss": "4.3.3",
|
|
89
|
+
"tsdown": "0.23.3",
|
|
90
|
+
"tsx": "4.23.15",
|
|
91
|
+
"typescript": "6.0.3",
|
|
92
|
+
"typescript-eslint": "8.72.1",
|
|
93
|
+
"vite": "8.3.5",
|
|
94
|
+
"vitest": "5.0.5",
|
|
95
|
+
"vitest-browser-react": "2.3.0"
|
|
96
|
+
},
|
|
97
|
+
"dependencies": {
|
|
98
|
+
"@tabler/icons-react": "3.50.0",
|
|
99
|
+
"clsx": "2.1.1",
|
|
100
|
+
"tailwind-merge": "3.7.0"
|
|
101
|
+
},
|
|
102
|
+
"exports": {
|
|
103
|
+
".": {
|
|
104
|
+
"types": "./dist/index.d.ts",
|
|
105
|
+
"default": "./dist/index.js"
|
|
106
|
+
},
|
|
107
|
+
"./icon": {
|
|
108
|
+
"types": "./dist/components/icon/index.d.ts",
|
|
109
|
+
"default": "./dist/components/icon/index.js"
|
|
110
|
+
},
|
|
111
|
+
"./inline": {
|
|
112
|
+
"types": "./dist/components/inline/index.d.ts",
|
|
113
|
+
"default": "./dist/components/inline/index.js"
|
|
114
|
+
},
|
|
115
|
+
"./stack": {
|
|
116
|
+
"types": "./dist/components/stack/index.d.ts",
|
|
117
|
+
"default": "./dist/components/stack/index.js"
|
|
118
|
+
},
|
|
119
|
+
"./text": {
|
|
120
|
+
"types": "./dist/components/text/index.d.ts",
|
|
121
|
+
"default": "./dist/components/text/index.js"
|
|
122
|
+
},
|
|
123
|
+
"./styles.css": "./dist/styles.css",
|
|
124
|
+
"./base.css": "./dist/base.css",
|
|
125
|
+
"./fonts/*": "./dist/fonts/*",
|
|
126
|
+
"./catalogue.json": "./dist/catalogue.json",
|
|
127
|
+
"./package.json": "./package.json"
|
|
128
|
+
}
|
|
129
|
+
}
|