eidos-ui 2.1.0 → 3.0.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 +66 -16
- package/dist/ThemeProvider.types-DgXN0gEH.d.cts +88 -0
- package/dist/ThemeProvider.types-DgXN0gEH.d.ts +88 -0
- package/dist/chunk-2ZY7M72Q.js +521 -0
- package/dist/chunk-2ZY7M72Q.js.map +1 -0
- package/dist/{chunk-W6IKHJ76.cjs → chunk-5BX4Q76D.cjs} +134 -126
- package/dist/chunk-5BX4Q76D.cjs.map +1 -0
- package/dist/chunk-H5HWFOWZ.js +390 -0
- package/dist/chunk-H5HWFOWZ.js.map +1 -0
- package/dist/{chunk-JV7Z3D3U.js → chunk-LEMCJW57.js} +134 -126
- package/dist/chunk-LEMCJW57.js.map +1 -0
- package/dist/chunk-SE7MWOC7.cjs +390 -0
- package/dist/chunk-SE7MWOC7.cjs.map +1 -0
- package/dist/chunk-U5FHQ73U.cjs +521 -0
- package/dist/chunk-U5FHQ73U.cjs.map +1 -0
- package/dist/color-picker/index.cjs +2 -2
- package/dist/color-picker/index.js +1 -1
- package/dist/fonts/JetBrains-Mono-OFL.txt +93 -0
- package/dist/fonts/Plus-Jakarta-Sans-OFL.txt +93 -0
- package/dist/fonts/jetbrains-mono-latin-ext-wght-normal.woff2 +0 -0
- package/dist/fonts/jetbrains-mono-latin-wght-normal.woff2 +0 -0
- package/dist/fonts/plus-jakarta-sans-latin-ext-wght-normal.woff2 +0 -0
- package/dist/fonts/plus-jakarta-sans-latin-wght-normal.woff2 +0 -0
- package/dist/fonts.css +32 -0
- package/dist/fonts.css.d.ts +2 -0
- package/dist/index.cjs +31 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +308 -102
- package/dist/index.d.cts +3 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +34 -8
- package/dist/theme-editor/index.cjs +22 -0
- package/dist/theme-editor/index.cjs.map +1 -0
- package/dist/theme-editor/index.d.cts +65 -0
- package/dist/theme-editor/index.d.ts +65 -0
- package/dist/theme-editor/index.js +22 -0
- package/dist/theme-editor/index.js.map +1 -0
- package/dist/theme-provider/index.cjs +27 -0
- package/dist/theme-provider/index.cjs.map +1 -0
- package/dist/theme-provider/index.d.cts +123 -0
- package/dist/theme-provider/index.d.ts +123 -0
- package/dist/theme-provider/index.js +27 -0
- package/dist/theme-provider/index.js.map +1 -0
- package/package.json +13 -3
- package/dist/chunk-JV7Z3D3U.js.map +0 -1
- package/dist/chunk-W6IKHJ76.cjs.map +0 -1
package/README.md
CHANGED
|
@@ -19,14 +19,14 @@
|
|
|
19
19
|
|
|
20
20
|
## Features
|
|
21
21
|
|
|
22
|
-
| |
|
|
23
|
-
| ------------------- |
|
|
24
|
-
| **Themeable** | Every design token is a CSS custom property
|
|
25
|
-
| **Type-safe** | Written in TypeScript with full prop typings exported for every component.
|
|
26
|
-
| **Tree-shakeable** | Per-component entry points (`eidos-ui/button`, `eidos-ui/table`, ...) keep bundles lean.
|
|
27
|
-
| **Icon-agnostic** | Works with any icon library - Lucide, MUI Icons, Font Awesome, Remix Icons, or your own.
|
|
28
|
-
| **Accessible** | Built with keyboard navigation and ARIA semantics in mind.
|
|
29
|
-
| **Optimized build** | Bundled with tsup, shipping both ESM and CJS with source maps and `.d.ts` files.
|
|
22
|
+
| | |
|
|
23
|
+
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
24
|
+
| **Themeable** | Every design token is a CSS custom property. Override them statically, or let users change the palette and typography at runtime with `ThemeProvider`. |
|
|
25
|
+
| **Type-safe** | Written in TypeScript with full prop typings exported for every component. |
|
|
26
|
+
| **Tree-shakeable** | Per-component entry points (`eidos-ui/button`, `eidos-ui/table`, ...) keep bundles lean. |
|
|
27
|
+
| **Icon-agnostic** | Works with any icon library - Lucide, MUI Icons, Font Awesome, Remix Icons, or your own. |
|
|
28
|
+
| **Accessible** | Built with keyboard navigation and ARIA semantics in mind. |
|
|
29
|
+
| **Optimized build** | Bundled with tsup, shipping both ESM and CJS with source maps and `.d.ts` files. |
|
|
30
30
|
|
|
31
31
|
## Installation
|
|
32
32
|
|
|
@@ -45,6 +45,7 @@ npm install lucide-react
|
|
|
45
45
|
```tsx
|
|
46
46
|
import { Button, Tooltip } from 'eidos-ui';
|
|
47
47
|
import 'eidos-ui/styles';
|
|
48
|
+
import 'eidos-ui/fonts'; // optional - bundled Plus Jakarta Sans + JetBrains Mono
|
|
48
49
|
|
|
49
50
|
function App() {
|
|
50
51
|
return (
|
|
@@ -91,6 +92,11 @@ These are the same groups used in Storybook, so the README and the docs sidebar
|
|
|
91
92
|
- Toolbar
|
|
92
93
|
- Breadcrumb
|
|
93
94
|
|
|
95
|
+
**Theming**
|
|
96
|
+
|
|
97
|
+
- ThemeProvider
|
|
98
|
+
- ThemeEditor
|
|
99
|
+
|
|
94
100
|
**Elements**
|
|
95
101
|
|
|
96
102
|
- Button
|
|
@@ -120,7 +126,6 @@ These are the same groups used in Storybook, so the README and the docs sidebar
|
|
|
120
126
|
- Switch
|
|
121
127
|
- Slider
|
|
122
128
|
- ColorPicker
|
|
123
|
-
- DatePicker
|
|
124
129
|
- OTPInput
|
|
125
130
|
- TagInput
|
|
126
131
|
- FileUpload
|
|
@@ -139,7 +144,9 @@ These are the same groups used in Storybook, so the README and the docs sidebar
|
|
|
139
144
|
**Data**
|
|
140
145
|
|
|
141
146
|
- Table
|
|
147
|
+
- TableFiltersDropdown
|
|
142
148
|
- DataGrid
|
|
149
|
+
- DatePicker
|
|
143
150
|
- Timeline
|
|
144
151
|
- VirtualList
|
|
145
152
|
|
|
@@ -180,15 +187,19 @@ npm run storybook
|
|
|
180
187
|
|
|
181
188
|
## Theming
|
|
182
189
|
|
|
183
|
-
|
|
190
|
+
Every design token is a CSS custom property. There are two ways to change them, depending on whether the theme is fixed at build time or chosen by the user.
|
|
191
|
+
|
|
192
|
+
### Static overrides
|
|
193
|
+
|
|
194
|
+
Redeclare any token in your own stylesheet:
|
|
184
195
|
|
|
185
196
|
```css
|
|
186
197
|
:root {
|
|
187
|
-
/*
|
|
188
|
-
--primary-color: #
|
|
189
|
-
--secondary-color: #
|
|
198
|
+
/* Colours - each family also has -dark, -light, -rgb and -contrast */
|
|
199
|
+
--primary-color: #5c5de8;
|
|
200
|
+
--secondary-color: #617087;
|
|
190
201
|
|
|
191
|
-
/* Spacing */
|
|
202
|
+
/* Spacing (em-based, so it scales with font size) */
|
|
192
203
|
--spacing-md: 1em;
|
|
193
204
|
--spacing-lg: 1.5em;
|
|
194
205
|
|
|
@@ -197,15 +208,54 @@ All design tokens are exposed as CSS custom properties, so themes can be overrid
|
|
|
197
208
|
}
|
|
198
209
|
```
|
|
199
210
|
|
|
200
|
-
Individual
|
|
211
|
+
Individual components can also be targeted directly, following each component's `eidos-<name>` BEM-style class names:
|
|
201
212
|
|
|
202
213
|
```css
|
|
203
214
|
.eidos-button--filled.eidos-button--primary {
|
|
204
215
|
border-radius: 20px;
|
|
205
|
-
background: linear-gradient(to right, #
|
|
216
|
+
background: linear-gradient(to right, #5c5de8, #8b5cf6);
|
|
206
217
|
}
|
|
207
218
|
```
|
|
208
219
|
|
|
220
|
+
### Runtime theming
|
|
221
|
+
|
|
222
|
+
`ThemeProvider` applies a theme at runtime — for a settings screen, a per-tenant palette, or a colour a user picks. Supply one base colour per family and the shades, tints, ramp steps and accessible foregrounds are derived from it:
|
|
223
|
+
|
|
224
|
+
```tsx
|
|
225
|
+
import { ThemeProvider, ThemeEditor } from 'eidos-ui';
|
|
226
|
+
|
|
227
|
+
<ThemeProvider defaultTheme={{ colors: { primary: '#0ea5e9' } }}>
|
|
228
|
+
<App />
|
|
229
|
+
</ThemeProvider>;
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
`ThemeEditor` is a ready-made panel for editing the active theme, with live WCAG contrast readouts per colour:
|
|
233
|
+
|
|
234
|
+
```tsx
|
|
235
|
+
<ThemeProvider theme={theme} onThemeChange={saveThemeForUser}>
|
|
236
|
+
<ThemeEditor />
|
|
237
|
+
<App />
|
|
238
|
+
</ThemeProvider>
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
Ten things are editable — seven colour bases, two font stacks, and a font scale. Tokens are written through the CSSOM to `document.documentElement`, which needs **no Content Security Policy allowance** and covers portaled overlays too. A theme equal to the preset writes nothing at all.
|
|
242
|
+
|
|
243
|
+
Use `useTheme()` to read or change it from your own UI, and `toCss()` to export the resolved tokens as a `:root` block you can paste into a stylesheet — useful for baking a theme in at build time.
|
|
244
|
+
|
|
245
|
+
### Fonts
|
|
246
|
+
|
|
247
|
+
The theme names Plus Jakarta Sans and JetBrains Mono, but a font stack only _names_ families — it cannot install them. Import the bundled copies to actually use them:
|
|
248
|
+
|
|
249
|
+
```ts
|
|
250
|
+
import 'eidos-ui/fonts';
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
This is a separate entry point because these are the only rules in the library that fetch a subresource; importing it means allowing `font-src 'self'` (already covered by `default-src 'self'`). Skip it and the stylesheet fetches nothing, falling back to system fonts.
|
|
254
|
+
|
|
255
|
+
For a font of your own, `registerFontFace(family, arrayBuffer)` registers one at runtime with no CSP allowance at all.
|
|
256
|
+
|
|
257
|
+
See the **Theming** and **Content Security Policy** pages in Storybook for the full reference.
|
|
258
|
+
|
|
209
259
|
## TypeScript
|
|
210
260
|
|
|
211
261
|
Every component ships with exported prop types:
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import React__default from 'react';
|
|
2
|
+
|
|
3
|
+
/** The seven themeable colour families. */
|
|
4
|
+
type ThemeColorKey = 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'info' | 'hyperlink';
|
|
5
|
+
/**
|
|
6
|
+
* A themeable colour: either a bare hex string, or an object that also pins the
|
|
7
|
+
* foreground to place on it.
|
|
8
|
+
*
|
|
9
|
+
* `contrast` exists because the provider writes tokens inline on
|
|
10
|
+
* `document.documentElement`, and inline styles beat author stylesheets - a
|
|
11
|
+
* consumer who must have a specific foreground could otherwise only override it
|
|
12
|
+
* with `!important`. Leave it unset to have it computed (see `pickContrast`).
|
|
13
|
+
*/
|
|
14
|
+
type ThemeColorValue = string | {
|
|
15
|
+
base: string;
|
|
16
|
+
contrast?: string;
|
|
17
|
+
};
|
|
18
|
+
type ThemeColors = Partial<Record<ThemeColorKey, ThemeColorValue>>;
|
|
19
|
+
/** A selectable font stack, as offered by `ThemeEditor`. */
|
|
20
|
+
interface ThemeFontOption {
|
|
21
|
+
/** Display name, e.g. "Plus Jakarta Sans". */
|
|
22
|
+
label: string;
|
|
23
|
+
/** The full CSS font stack written to the token. */
|
|
24
|
+
value: string;
|
|
25
|
+
}
|
|
26
|
+
interface ThemeTypography {
|
|
27
|
+
/** Replaces `--font-family-primary`. A full CSS font stack. */
|
|
28
|
+
fontFamily?: string;
|
|
29
|
+
/** Replaces `--font-family-mono`. A full CSS font stack. */
|
|
30
|
+
monoFamily?: string;
|
|
31
|
+
/**
|
|
32
|
+
* Multiplier applied to all eight `--font-size-*` tokens. 1 is the preset.
|
|
33
|
+
*
|
|
34
|
+
* Note that `--spacing-*` is declared in `em`, so this scales most padding
|
|
35
|
+
* and gaps along with the text rather than only the glyphs.
|
|
36
|
+
*/
|
|
37
|
+
fontScale?: number;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* A theme. Every field is optional and anything omitted falls back to
|
|
41
|
+
* `defaultTheme`, so a theme may be as small as one colour.
|
|
42
|
+
*
|
|
43
|
+
* Named `ThemeConfig` rather than `Theme` to avoid colliding with the `Theme`
|
|
44
|
+
* exported by MUI, styled-components and others in a consumer's namespace.
|
|
45
|
+
*/
|
|
46
|
+
interface ThemeConfig {
|
|
47
|
+
colors?: ThemeColors;
|
|
48
|
+
typography?: ThemeTypography;
|
|
49
|
+
}
|
|
50
|
+
/** A theme with every field populated - what the provider actually applies. */
|
|
51
|
+
interface ResolvedTheme {
|
|
52
|
+
colors: Record<ThemeColorKey, {
|
|
53
|
+
base: string;
|
|
54
|
+
contrast?: string;
|
|
55
|
+
}>;
|
|
56
|
+
typography: Required<ThemeTypography>;
|
|
57
|
+
}
|
|
58
|
+
interface ThemeContextValue {
|
|
59
|
+
/** The theme as supplied, with omitted fields left absent. */
|
|
60
|
+
theme: ThemeConfig;
|
|
61
|
+
/** The same theme with every field filled in from the preset. */
|
|
62
|
+
resolvedTheme: ResolvedTheme;
|
|
63
|
+
/** Replaces the whole theme. */
|
|
64
|
+
setTheme: (theme: ThemeConfig) => void;
|
|
65
|
+
/** Deep-merges a partial theme into the current one. */
|
|
66
|
+
updateTheme: (patch: ThemeConfig) => void;
|
|
67
|
+
/** Returns to the preset. */
|
|
68
|
+
resetTheme: () => void;
|
|
69
|
+
/** True when nothing differs from the preset, so no tokens are being written. */
|
|
70
|
+
isDefault: boolean;
|
|
71
|
+
/** The resolved theme as a `:root { … }` CSS block. */
|
|
72
|
+
toCss: () => string;
|
|
73
|
+
}
|
|
74
|
+
interface ThemeProviderProps {
|
|
75
|
+
children: React__default.ReactNode;
|
|
76
|
+
/**
|
|
77
|
+
* Controlled theme. Pair with `onThemeChange` and own persistence yourself -
|
|
78
|
+
* this is the mode to use when the theme comes from a user record on your
|
|
79
|
+
* server.
|
|
80
|
+
*/
|
|
81
|
+
theme?: ThemeConfig;
|
|
82
|
+
/** Initial theme for uncontrolled usage. Ignored when `theme` is supplied. */
|
|
83
|
+
defaultTheme?: ThemeConfig;
|
|
84
|
+
/** Fires whenever the theme changes, in both controlled and uncontrolled mode. */
|
|
85
|
+
onThemeChange?: (theme: ThemeConfig) => void;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export type { ResolvedTheme as R, ThemeColorKey as T, ThemeColorValue as a, ThemeColors as b, ThemeConfig as c, ThemeContextValue as d, ThemeFontOption as e, ThemeProviderProps as f, ThemeTypography as g };
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import React__default from 'react';
|
|
2
|
+
|
|
3
|
+
/** The seven themeable colour families. */
|
|
4
|
+
type ThemeColorKey = 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'info' | 'hyperlink';
|
|
5
|
+
/**
|
|
6
|
+
* A themeable colour: either a bare hex string, or an object that also pins the
|
|
7
|
+
* foreground to place on it.
|
|
8
|
+
*
|
|
9
|
+
* `contrast` exists because the provider writes tokens inline on
|
|
10
|
+
* `document.documentElement`, and inline styles beat author stylesheets - a
|
|
11
|
+
* consumer who must have a specific foreground could otherwise only override it
|
|
12
|
+
* with `!important`. Leave it unset to have it computed (see `pickContrast`).
|
|
13
|
+
*/
|
|
14
|
+
type ThemeColorValue = string | {
|
|
15
|
+
base: string;
|
|
16
|
+
contrast?: string;
|
|
17
|
+
};
|
|
18
|
+
type ThemeColors = Partial<Record<ThemeColorKey, ThemeColorValue>>;
|
|
19
|
+
/** A selectable font stack, as offered by `ThemeEditor`. */
|
|
20
|
+
interface ThemeFontOption {
|
|
21
|
+
/** Display name, e.g. "Plus Jakarta Sans". */
|
|
22
|
+
label: string;
|
|
23
|
+
/** The full CSS font stack written to the token. */
|
|
24
|
+
value: string;
|
|
25
|
+
}
|
|
26
|
+
interface ThemeTypography {
|
|
27
|
+
/** Replaces `--font-family-primary`. A full CSS font stack. */
|
|
28
|
+
fontFamily?: string;
|
|
29
|
+
/** Replaces `--font-family-mono`. A full CSS font stack. */
|
|
30
|
+
monoFamily?: string;
|
|
31
|
+
/**
|
|
32
|
+
* Multiplier applied to all eight `--font-size-*` tokens. 1 is the preset.
|
|
33
|
+
*
|
|
34
|
+
* Note that `--spacing-*` is declared in `em`, so this scales most padding
|
|
35
|
+
* and gaps along with the text rather than only the glyphs.
|
|
36
|
+
*/
|
|
37
|
+
fontScale?: number;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* A theme. Every field is optional and anything omitted falls back to
|
|
41
|
+
* `defaultTheme`, so a theme may be as small as one colour.
|
|
42
|
+
*
|
|
43
|
+
* Named `ThemeConfig` rather than `Theme` to avoid colliding with the `Theme`
|
|
44
|
+
* exported by MUI, styled-components and others in a consumer's namespace.
|
|
45
|
+
*/
|
|
46
|
+
interface ThemeConfig {
|
|
47
|
+
colors?: ThemeColors;
|
|
48
|
+
typography?: ThemeTypography;
|
|
49
|
+
}
|
|
50
|
+
/** A theme with every field populated - what the provider actually applies. */
|
|
51
|
+
interface ResolvedTheme {
|
|
52
|
+
colors: Record<ThemeColorKey, {
|
|
53
|
+
base: string;
|
|
54
|
+
contrast?: string;
|
|
55
|
+
}>;
|
|
56
|
+
typography: Required<ThemeTypography>;
|
|
57
|
+
}
|
|
58
|
+
interface ThemeContextValue {
|
|
59
|
+
/** The theme as supplied, with omitted fields left absent. */
|
|
60
|
+
theme: ThemeConfig;
|
|
61
|
+
/** The same theme with every field filled in from the preset. */
|
|
62
|
+
resolvedTheme: ResolvedTheme;
|
|
63
|
+
/** Replaces the whole theme. */
|
|
64
|
+
setTheme: (theme: ThemeConfig) => void;
|
|
65
|
+
/** Deep-merges a partial theme into the current one. */
|
|
66
|
+
updateTheme: (patch: ThemeConfig) => void;
|
|
67
|
+
/** Returns to the preset. */
|
|
68
|
+
resetTheme: () => void;
|
|
69
|
+
/** True when nothing differs from the preset, so no tokens are being written. */
|
|
70
|
+
isDefault: boolean;
|
|
71
|
+
/** The resolved theme as a `:root { … }` CSS block. */
|
|
72
|
+
toCss: () => string;
|
|
73
|
+
}
|
|
74
|
+
interface ThemeProviderProps {
|
|
75
|
+
children: React__default.ReactNode;
|
|
76
|
+
/**
|
|
77
|
+
* Controlled theme. Pair with `onThemeChange` and own persistence yourself -
|
|
78
|
+
* this is the mode to use when the theme comes from a user record on your
|
|
79
|
+
* server.
|
|
80
|
+
*/
|
|
81
|
+
theme?: ThemeConfig;
|
|
82
|
+
/** Initial theme for uncontrolled usage. Ignored when `theme` is supplied. */
|
|
83
|
+
defaultTheme?: ThemeConfig;
|
|
84
|
+
/** Fires whenever the theme changes, in both controlled and uncontrolled mode. */
|
|
85
|
+
onThemeChange?: (theme: ThemeConfig) => void;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export type { ResolvedTheme as R, ThemeColorKey as T, ThemeColorValue as a, ThemeColors as b, ThemeConfig as c, ThemeContextValue as d, ThemeFontOption as e, ThemeProviderProps as f, ThemeTypography as g };
|