@yelison/forma-ui 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/CHANGELOG.md +19 -0
- package/LICENSE +21 -0
- package/README.md +243 -2
- package/dist/base.css +25 -0
- package/dist/components/Badge/Badge.d.ts +14 -0
- package/dist/components/Badge/Badge.js +12 -0
- package/dist/components/Badge/Badge.module.css.js +11 -0
- package/dist/components/Badge/index.d.ts +1 -0
- package/dist/components/Button/Button.d.ts +23 -0
- package/dist/components/Button/Button.js +34 -0
- package/dist/components/Button/Button.module.css.js +13 -0
- package/dist/components/Button/IconButton.d.ts +17 -0
- package/dist/components/Button/IconButton.js +20 -0
- package/dist/components/Button/IconButton.module.css.js +8 -0
- package/dist/components/Button/buttonClassName.d.ts +17 -0
- package/dist/components/Button/buttonClassName.js +8 -0
- package/dist/components/Button/index.d.ts +3 -0
- package/dist/components/Dialog/Dialog.d.ts +51 -0
- package/dist/components/Dialog/Dialog.js +38 -0
- package/dist/components/Dialog/Dialog.module.css.js +12 -0
- package/dist/components/Dialog/index.d.ts +1 -0
- package/dist/components/Field/Field.d.ts +42 -0
- package/dist/components/Field/Field.js +40 -0
- package/dist/components/Field/Field.module.css.js +9 -0
- package/dist/components/Field/control.module.css.js +4 -0
- package/dist/components/Field/index.d.ts +1 -0
- package/dist/components/Icon/Icon.d.ts +19 -0
- package/dist/components/Icon/Icon.js +27 -0
- package/dist/components/Icon/index.d.ts +1 -0
- package/dist/components/Icon/paths.d.ts +26 -0
- package/dist/components/Icon/paths.js +32 -0
- package/dist/components/Input/Input.d.ts +24 -0
- package/dist/components/Input/Input.js +23 -0
- package/dist/components/Input/index.d.ts +1 -0
- package/dist/components/Tooltip/Tooltip.d.ts +65 -0
- package/dist/components/Tooltip/Tooltip.js +51 -0
- package/dist/components/Tooltip/Tooltip.module.css.js +4 -0
- package/dist/components/Tooltip/activeTooltip.d.ts +4 -0
- package/dist/components/Tooltip/activeTooltip.js +10 -0
- package/dist/components/Tooltip/index.d.ts +1 -0
- package/dist/contrast-pairs.json +368 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +19 -0
- package/dist/lib/cx.d.ts +4 -0
- package/dist/lib/cx.js +6 -0
- package/dist/lib/position.d.ts +22 -0
- package/dist/lib/position.js +21 -0
- package/dist/lib/scrollLock.d.ts +13 -0
- package/dist/lib/scrollLock.js +22 -0
- package/dist/lib/useFloating.d.ts +25 -0
- package/dist/lib/useFloating.js +48 -0
- package/dist/lib/useModalDialog.d.ts +15 -0
- package/dist/lib/useModalDialog.js +42 -0
- package/dist/provider/FormaProvider.d.ts +17 -0
- package/dist/provider/FormaProvider.js +16 -0
- package/dist/provider/index.d.ts +3 -0
- package/dist/provider/strings.d.ts +14 -0
- package/dist/provider/strings.js +7 -0
- package/dist/provider/stringsContext.d.ts +6 -0
- package/dist/provider/stringsContext.js +6 -0
- package/dist/provider/useFormaStrings.d.ts +3 -0
- package/dist/provider/useFormaStrings.js +8 -0
- package/dist/styles.css +2 -0
- package/dist/theme/index.d.ts +5 -0
- package/dist/theme/themeScript.d.ts +21 -0
- package/dist/theme/themeScript.js +7 -0
- package/dist/theme/themeStore.d.ts +42 -0
- package/dist/theme/themeStore.js +55 -0
- package/dist/theme/useTheme.d.ts +21 -0
- package/dist/theme/useTheme.js +16 -0
- package/dist/tokens/contrast.d.ts +12 -0
- package/dist/tokens/contrast.js +25 -0
- package/dist/tokens/tokens.d.ts +2 -0
- package/dist/tokens/tokens.js +4 -0
- package/dist/tokens.css +156 -0
- package/dist/tokens.json +154 -0
- package/package.json +95 -4
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type FormaStrings } from './strings.js';
|
|
2
|
+
/**
|
|
3
|
+
* Holds the library's text. Private: components read it with `useFormaStrings` and `FormaProvider` writes it.
|
|
4
|
+
* The pure annotation lets a consumer's bundler drop the context when nothing imports the provider or the hook.
|
|
5
|
+
*/
|
|
6
|
+
export declare const StringsContext: import("react").Context<FormaStrings>;
|
package/dist/styles.css
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
.forma-badge{box-sizing:border-box;min-height:var(--badge-min-height);padding:var(--space-4);border-radius:var(--radius-control);font:var(--font-caption);white-space:nowrap;align-items:center;display:inline-flex}.forma-badge__blue{background:var(--color-blue-bg);color:var(--color-blue-ink)}.forma-badge__green{background:var(--color-green-bg);color:var(--color-green-ink)}.forma-badge__amber{background:var(--color-amber-bg);color:var(--color-amber-ink)}.forma-badge__red{background:var(--color-red-bg);color:var(--color-red-ink)}.forma-badge__neutral{background:var(--color-bg);color:var(--color-muted)}.forma-field{box-sizing:border-box;gap:var(--space-6);flex-direction:column;min-width:0;display:flex}.forma-field__label{font:var(--font-label);color:var(--color-ink)}.forma-field__hint{font:var(--font-caption);color:var(--color-muted)}.forma-field__error{font:var(--font-caption);color:var(--color-red-ink)}:where(.forma-field-control){box-sizing:border-box;width:100%;min-height:var(--control-height);padding:0 var(--space-12);border:1px solid var(--color-line);border-radius:var(--radius-control);background:var(--color-surface);color:var(--color-ink);font:var(--font-body);transition:background-color var(--duration-fast) ease, border-color var(--duration-fast) ease}.forma-field-control::placeholder{color:var(--color-muted);opacity:1}.forma-field-control:hover:not(:disabled,:focus,[readonly]){background:var(--color-surface-hover)}.forma-field-control:focus-visible{border-color:var(--color-focus);outline:var(--focus-ring);outline-offset:0}.forma-field-control[aria-invalid=true]{border-color:var(--color-red-ink)}.forma-field-control[aria-invalid=true]:focus-visible{outline-color:var(--color-red-ink)}.forma-field-control[readonly]{background:var(--color-bg);border-style:dashed}.forma-field-control:disabled{background:var(--color-bg);color:var(--color-muted);cursor:not-allowed}@media (prefers-reduced-motion:reduce){.forma-field-control{transition:none}}.forma-button{box-sizing:border-box;justify-content:center;align-items:center;gap:var(--space-8);min-height:var(--button-height);padding:0 var(--space-8);border-radius:var(--radius-control);font:var(--font-label);white-space:nowrap;cursor:pointer;transition:background-color var(--duration-fast) ease, border-color var(--duration-fast) ease;border:1px solid #0000;text-decoration:none;display:inline-flex}.forma-button:focus-visible{outline:var(--focus-ring);outline-offset:2px}.forma-button:where(:disabled,[aria-disabled=true]){cursor:not-allowed}.forma-button:where([aria-busy=true]){cursor:progress}.forma-button__block{width:100%}.forma-button__primary{background:var(--color-brand);color:var(--color-on-brand)}.forma-button__primary:where(:not(:disabled,[aria-disabled=true]):hover){background:var(--color-brand-hover)}.forma-button__secondary{background:var(--color-surface);border-color:var(--color-line);color:var(--color-ink)}.forma-button__ghost{color:var(--color-ink);background:0 0}.forma-button__danger{background:var(--color-red-bg);color:var(--color-red-ink)}.forma-button__secondary:where(:not(:disabled,[aria-disabled=true]):hover),.forma-button__ghost:where(:not(:disabled,[aria-disabled=true]):hover),.forma-button__danger:where(:not(:disabled,[aria-disabled=true]):hover){background:var(--color-surface-hover)}.forma-button:where(:disabled){background:var(--color-disabled);border-color:#0000}.forma-button__secondary:where(:disabled),.forma-button__danger:where(:disabled),.forma-button__ghost:where(:disabled){color:var(--color-muted)}.forma-button__spinner{box-sizing:border-box;width:var(--spinner-size);height:var(--spinner-size);border-radius:var(--radius-round);border:2px solid;border-right-color:#0000;animation:.8s linear infinite forma-button__spin}@keyframes forma-button__spin{to{transform:rotate(360deg)}}@media (prefers-reduced-motion:reduce){.forma-button__spinner{animation:none}}.forma-button-icon-button{box-sizing:border-box;width:var(--touch-target);height:var(--touch-target);border-radius:var(--radius-control);color:var(--color-muted);cursor:pointer;transition:background-color var(--duration-fast) ease, color var(--duration-fast) ease;background:0 0;border:0;flex-shrink:0;place-items:center;padding:0;display:inline-grid}.forma-button-icon-button:focus-visible{outline:var(--focus-ring);outline-offset:2px}.forma-button-icon-button:where(:not(:disabled):hover){background:var(--color-surface-hover);color:var(--color-ink)}.forma-button-icon-button:where(:disabled){cursor:not-allowed;opacity:.45}.forma-button-icon-button__icons{--icon-size:20px;--icon-overlap:.7;align-items:center;display:inline-flex}.forma-button-icon-button__icons>svg{width:var(--icon-size);height:var(--icon-size)}.forma-button-icon-button__icons>svg+svg{margin-inline-start:calc(var(--icon-size) * var(--icon-overlap) * -1)}.forma-button-icon-button__flip{transform:scaleX(-1)}.forma-tooltip{box-sizing:border-box;z-index:var(--z-tooltip);max-width:var(--tooltip-max-width);padding:var(--space-8);border-radius:var(--radius-control);background:var(--color-nav);color:var(--color-nav-ink);font:var(--font-caption)}.forma-dialog{box-sizing:border-box;width:min(var(--dialog-width), calc(100% - 2 * var(--space-16)));max-width:none;max-height:calc(100dvh - 2 * var(--space-16));border:1px solid var(--color-line);border-radius:var(--radius-panel);background:var(--color-surface);color:var(--color-ink);box-shadow:var(--shadow-popover);padding:0}.forma-dialog:where([open]){animation:forma-dialog__enter var(--duration-base) ease-out}.forma-dialog::backdrop{background:color-mix(in srgb, var(--color-overlay) calc(var(--overlay-opacity) * 100%), transparent)}.forma-dialog__wide{width:min(var(--dialog-width-wide), calc(100% - 2 * var(--space-16)))}.forma-dialog__content{box-sizing:border-box;gap:var(--space-16);padding:var(--space-24);flex-direction:column;display:flex}.forma-dialog__title{font:var(--font-section);margin:0}.forma-dialog__description{font:var(--font-body);color:var(--color-muted);margin:0}.forma-dialog__footer{justify-content:flex-end;gap:var(--space-12);flex-wrap:wrap;display:flex}@keyframes forma-dialog__enter{0%{opacity:0;transform:translateY(8px)scale(.98)}}@media (prefers-reduced-motion:reduce){.forma-dialog:where([open]){animation:none}}
|
|
2
|
+
/*$vite$:1*/
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { createThemeStore } from './themeStore.js';
|
|
2
|
+
export type { ResolvedTheme, ThemePreference, ThemeStore, ThemeStoreOptions } from './themeStore.js';
|
|
3
|
+
export { themeScript } from './themeScript.js';
|
|
4
|
+
export { useTheme } from './useTheme.js';
|
|
5
|
+
export type { UseThemeResult } from './useTheme.js';
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { ThemeStoreOptions } from './themeStore.js';
|
|
2
|
+
/**
|
|
3
|
+
* The first-paint script: a string for an inline `<script>` in `<head>`, before the stylesheet paints. It sets the
|
|
4
|
+
* stored `light` or `dark` on `<html>` before React renders, so a reload does not flash the theme the operating system
|
|
5
|
+
* prefers. Any other stored value, or none, leaves the attribute off and `prefers-color-scheme` decides, as it does
|
|
6
|
+
* for `system` in `createThemeStore`.
|
|
7
|
+
*
|
|
8
|
+
* It has no dependencies, leaves no global behind and never throws: its only variable is block-scoped, so it neither
|
|
9
|
+
* overwrites nor clashes with a global of the page, and storage that cannot be read just leaves the page as the system
|
|
10
|
+
* has it.
|
|
11
|
+
* The options are the ones of `createThemeStore`, and they must be the same. Any `storageKey` and `attribute` are
|
|
12
|
+
* safe to pass, whatever characters they hold.
|
|
13
|
+
*
|
|
14
|
+
* It has to be in the HTML that is served, in `<head>` before the stylesheet paints: a `<script>` that React renders
|
|
15
|
+
* on the client does not run, and one that React renders on the server comes out HTML-escaped.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* // In index.html, or in a `transformIndexHtml` hook:
|
|
19
|
+
* const html = `<script>${themeScript({ storageKey: 'my-app-theme' })}</script>`
|
|
20
|
+
*/
|
|
21
|
+
export declare function themeScript({ storageKey, attribute }: ThemeStoreOptions): string;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
//#region src/theme/themeScript.ts
|
|
2
|
+
var e = (e) => JSON.stringify(e).replaceAll("<", "\\u003c");
|
|
3
|
+
function t({ storageKey: t, attribute: n = "data-theme" }) {
|
|
4
|
+
return `try{const t=localStorage.getItem(${e(t)});if(t==="light"||t==="dark")document.documentElement.setAttribute(${e(n)},t)}catch{}`;
|
|
5
|
+
}
|
|
6
|
+
//#endregion
|
|
7
|
+
export { t as themeScript };
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/** What the user chose: a fixed theme, or `system` to follow the operating system. */
|
|
2
|
+
export type ThemePreference = 'light' | 'dark' | 'system';
|
|
3
|
+
/** The theme that is actually painted. */
|
|
4
|
+
export type ResolvedTheme = 'light' | 'dark';
|
|
5
|
+
/** Options of {@link createThemeStore}. */
|
|
6
|
+
export interface ThemeStoreOptions {
|
|
7
|
+
/** The `localStorage` key that holds the preference. The inline script from `themeScript` must use the same key. */
|
|
8
|
+
storageKey: string;
|
|
9
|
+
/**
|
|
10
|
+
* The attribute that `light` and `dark` set on `<html>`; `system` removes it. Defaults to `'data-theme'`, which is
|
|
11
|
+
* the one the selectors in `tokens.css` listen to: another attribute only makes sense with your own stylesheet.
|
|
12
|
+
*/
|
|
13
|
+
attribute?: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* An external store with the theme preference. It is the shape that `useSyncExternalStore` takes, so every method is
|
|
17
|
+
* a stable function that needs no `this`.
|
|
18
|
+
*/
|
|
19
|
+
export interface ThemeStore {
|
|
20
|
+
/** The stored preference. A missing, unreadable or unknown stored value is `system`. */
|
|
21
|
+
getPreference(): ThemePreference;
|
|
22
|
+
/** The theme that is painted: the preference, or the operating system's when the preference is `system`. */
|
|
23
|
+
getResolved(): ResolvedTheme;
|
|
24
|
+
/**
|
|
25
|
+
* Saves the preference and applies it to `<html>` right away. When storage is unavailable (private mode, blocked)
|
|
26
|
+
* the choice lasts in memory, for this store only.
|
|
27
|
+
*/
|
|
28
|
+
setPreference(preference: ThemePreference): void;
|
|
29
|
+
/**
|
|
30
|
+
* Calls `listener` when the preference changes, here or in another tab, and when the operating system switches
|
|
31
|
+
* between light and dark. While anyone is subscribed the store also keeps `<html>` in line with the stored value.
|
|
32
|
+
* Returns the function that unsubscribes.
|
|
33
|
+
*/
|
|
34
|
+
subscribe(listener: () => void): () => void;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Creates the theme store of one application. Each store has its own listeners and in-memory fallback: stores with
|
|
38
|
+
* different keys do not wake each other, although two stores that write the same `attribute` share the document.
|
|
39
|
+
*
|
|
40
|
+
* Creating a store has no effect on the page: the document is touched when a preference is set or someone subscribes.
|
|
41
|
+
*/
|
|
42
|
+
export declare function createThemeStore({ storageKey, attribute }: ThemeStoreOptions): ThemeStore;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
//#region src/theme/themeStore.ts
|
|
2
|
+
var e = "(prefers-color-scheme: dark)";
|
|
3
|
+
function t({ storageKey: t, attribute: n = "data-theme" }) {
|
|
4
|
+
let r = /* @__PURE__ */ new Set(), i = null, a;
|
|
5
|
+
function o() {
|
|
6
|
+
try {
|
|
7
|
+
let e = localStorage.getItem(t);
|
|
8
|
+
return e === "light" || e === "dark" ? e : "system";
|
|
9
|
+
} catch {
|
|
10
|
+
return "system";
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
function s(e) {
|
|
14
|
+
try {
|
|
15
|
+
e === "system" ? localStorage.removeItem(t) : localStorage.setItem(t, e);
|
|
16
|
+
} catch {}
|
|
17
|
+
}
|
|
18
|
+
let c = () => i ?? o(), l = () => window.matchMedia(e).matches ? "dark" : "light";
|
|
19
|
+
function u() {
|
|
20
|
+
let e = c();
|
|
21
|
+
return e === "system" ? l() : e;
|
|
22
|
+
}
|
|
23
|
+
function d() {
|
|
24
|
+
let e = document.documentElement, t = c();
|
|
25
|
+
t === "system" ? e.removeAttribute(n) : e.setAttribute(n, t);
|
|
26
|
+
}
|
|
27
|
+
let f = () => r.forEach((e) => e());
|
|
28
|
+
function p() {
|
|
29
|
+
d(), f();
|
|
30
|
+
}
|
|
31
|
+
function m() {
|
|
32
|
+
let n = window.matchMedia(e), r = (e) => {
|
|
33
|
+
(e.key === null || e.key === t) && p();
|
|
34
|
+
};
|
|
35
|
+
return window.addEventListener("storage", r), n.addEventListener("change", f), d(), () => {
|
|
36
|
+
window.removeEventListener("storage", r), n.removeEventListener("change", f);
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
function h(e) {
|
|
40
|
+
s(e), i = o() === e ? null : e, p();
|
|
41
|
+
}
|
|
42
|
+
function g(e) {
|
|
43
|
+
return r.add(e), a ??= m(), () => {
|
|
44
|
+
r.delete(e), r.size === 0 && (a?.(), a = void 0);
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
getPreference: c,
|
|
49
|
+
getResolved: u,
|
|
50
|
+
setPreference: h,
|
|
51
|
+
subscribe: g
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
//#endregion
|
|
55
|
+
export { t as createThemeStore };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { ResolvedTheme, ThemePreference, ThemeStore } from './themeStore.js';
|
|
2
|
+
/** What {@link useTheme} returns. */
|
|
3
|
+
export interface UseThemeResult {
|
|
4
|
+
/** What the user chose. `system` until they pick a theme, and whenever the stored value is not valid. */
|
|
5
|
+
preference: ThemePreference;
|
|
6
|
+
/** The theme that is painted now; it follows the operating system while the preference is `system`. */
|
|
7
|
+
resolved: ResolvedTheme;
|
|
8
|
+
/** Saves a preference and applies it to the document. */
|
|
9
|
+
setPreference(preference: ThemePreference): void;
|
|
10
|
+
/** Switches to the theme that is not painted when it is called. Its identity changes only with the store. */
|
|
11
|
+
toggle(): void;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Reads a theme store in a component. Every component that reads the same store sees the same preference, and the
|
|
15
|
+
* preference follows other tabs and the operating system.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* const themeStore = createThemeStore({ storageKey: 'my-app-theme' })
|
|
19
|
+
* const { resolved, toggle } = useTheme(themeStore)
|
|
20
|
+
*/
|
|
21
|
+
export declare function useTheme(store: ThemeStore): UseThemeResult;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { useCallback as e, useSyncExternalStore as t } from "react";
|
|
2
|
+
//#region src/theme/useTheme.ts
|
|
3
|
+
var n = () => "system", r = () => "light";
|
|
4
|
+
function i(i) {
|
|
5
|
+
let a = t(i.subscribe, i.getPreference, n), o = t(i.subscribe, i.getResolved, r), s = e(() => {
|
|
6
|
+
i.setPreference(i.getResolved() === "dark" ? "light" : "dark");
|
|
7
|
+
}, [i]);
|
|
8
|
+
return {
|
|
9
|
+
preference: a,
|
|
10
|
+
resolved: o,
|
|
11
|
+
setPreference: i.setPreference,
|
|
12
|
+
toggle: s
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
//#endregion
|
|
16
|
+
export { i as useTheme };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Relative luminance of a `#rgb` or `#rrggbb` color: 0 for black, 1 for white.
|
|
3
|
+
*
|
|
4
|
+
* @throws Error on anything but `#rgb` or `#rrggbb`, such as the `rgb(...)` that `getComputedStyle` returns.
|
|
5
|
+
*/
|
|
6
|
+
export declare function relativeLuminance(color: string): number;
|
|
7
|
+
/**
|
|
8
|
+
* Contrast ratio of two `#rgb` or `#rrggbb` colors, from 1 (identical) to 21 (black on white), in either order.
|
|
9
|
+
*
|
|
10
|
+
* @throws Error on anything but `#rgb` or `#rrggbb`, such as the `rgb(...)` that `getComputedStyle` returns.
|
|
11
|
+
*/
|
|
12
|
+
export declare function contrastRatio(first: string, second: string): number;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
//#region src/tokens/contrast.ts
|
|
2
|
+
function e(e) {
|
|
3
|
+
let t = e / 255;
|
|
4
|
+
return t <= .04045 ? t / 12.92 : ((t + .055) / 1.055) ** 2.4;
|
|
5
|
+
}
|
|
6
|
+
function t(e) {
|
|
7
|
+
let t = /^#([0-9a-f]{3}|[0-9a-f]{6})$/i.exec(e)?.[1];
|
|
8
|
+
if (t === void 0) throw Error(`Not a #rgb or #rrggbb color: "${e}"`);
|
|
9
|
+
let n = parseInt(t.length === 3 ? [...t].map((e) => e + e).join("") : t, 16);
|
|
10
|
+
return [
|
|
11
|
+
n >> 16 & 255,
|
|
12
|
+
n >> 8 & 255,
|
|
13
|
+
n & 255
|
|
14
|
+
];
|
|
15
|
+
}
|
|
16
|
+
function n(n) {
|
|
17
|
+
let [r, i, a] = t(n);
|
|
18
|
+
return .2126 * e(r) + .7152 * e(i) + .0722 * e(a);
|
|
19
|
+
}
|
|
20
|
+
function r(e, t) {
|
|
21
|
+
let [r, i] = [n(e), n(t)];
|
|
22
|
+
return (Math.max(r, i) + .05) / (Math.min(r, i) + .05);
|
|
23
|
+
}
|
|
24
|
+
//#endregion
|
|
25
|
+
export { r as contrastRatio, n as relativeLuminance };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export declare const tokenNames: readonly ["--color-bg", "--color-surface", "--color-ink", "--color-muted", "--color-line", "--color-nav", "--color-nav-active", "--color-nav-text", "--color-brand", "--color-brand-hover", "--color-link", "--color-blue-bg", "--color-blue-ink", "--color-green-bg", "--color-green-ink", "--color-amber-bg", "--color-amber-ink", "--color-red-bg", "--color-red-ink", "--color-on-brand", "--color-nav-ink", "--color-focus", "--color-surface-hover", "--color-disabled", "--color-overlay", "--color-progress-track", "--font-family", "--font-caption", "--font-body", "--font-label", "--font-strong", "--font-section", "--font-title", "--font-title-mobile", "--font-metric", "--font-logo", "--space-0", "--space-1", "--space-2", "--space-4", "--space-6", "--space-8", "--space-12", "--space-16", "--space-20", "--space-24", "--space-28", "--space-32", "--space-40", "--space-48", "--space-64", "--radius-panel", "--radius-control", "--radius-small", "--radius-round", "--control-height", "--button-height", "--touch-target", "--badge-min-height", "--spinner-size", "--tooltip-max-width", "--dialog-width", "--dialog-width-wide", "--duration-fast", "--duration-base", "--overlay-opacity", "--focus-ring", "--shadow-popover", "--z-sticky", "--z-dropdown", "--z-menu", "--z-tooltip", "--z-toast", "--z-overlay"];
|
|
2
|
+
export type TokenName = (typeof tokenNames)[number];
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
//#region src/tokens/tokens.ts
|
|
2
|
+
var e = /* @__PURE__ */ "--color-bg.--color-surface.--color-ink.--color-muted.--color-line.--color-nav.--color-nav-active.--color-nav-text.--color-brand.--color-brand-hover.--color-link.--color-blue-bg.--color-blue-ink.--color-green-bg.--color-green-ink.--color-amber-bg.--color-amber-ink.--color-red-bg.--color-red-ink.--color-on-brand.--color-nav-ink.--color-focus.--color-surface-hover.--color-disabled.--color-overlay.--color-progress-track.--font-family.--font-caption.--font-body.--font-label.--font-strong.--font-section.--font-title.--font-title-mobile.--font-metric.--font-logo.--space-0.--space-1.--space-2.--space-4.--space-6.--space-8.--space-12.--space-16.--space-20.--space-24.--space-28.--space-32.--space-40.--space-48.--space-64.--radius-panel.--radius-control.--radius-small.--radius-round.--control-height.--button-height.--touch-target.--badge-min-height.--spinner-size.--tooltip-max-width.--dialog-width.--dialog-width-wide.--duration-fast.--duration-base.--overlay-opacity.--focus-ring.--shadow-popover.--z-sticky.--z-dropdown.--z-menu.--z-tooltip.--z-toast.--z-overlay".split(".");
|
|
3
|
+
//#endregion
|
|
4
|
+
export { e as tokenNames };
|
package/dist/tokens.css
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/* Generated by scripts/build-tokens.ts from tokens/*.tokens.json. Do not edit by hand:
|
|
2
|
+
* change the source and run `npm run build:tokens -w @yelison/forma-ui`. */
|
|
3
|
+
|
|
4
|
+
:root {
|
|
5
|
+
color-scheme: light;
|
|
6
|
+
|
|
7
|
+
--color-bg: #f5f7fb;
|
|
8
|
+
--color-surface: #ffffff;
|
|
9
|
+
--color-ink: #17243d;
|
|
10
|
+
--color-muted: #616d81;
|
|
11
|
+
--color-line: #e4e9f1;
|
|
12
|
+
--color-nav: #111e35;
|
|
13
|
+
--color-nav-active: #263b5d;
|
|
14
|
+
--color-nav-text: #a8b7d0;
|
|
15
|
+
--color-brand: #3569f6;
|
|
16
|
+
--color-brand-hover: #3161e0;
|
|
17
|
+
--color-link: var(--color-blue-ink);
|
|
18
|
+
--color-blue-bg: #ebf1ff;
|
|
19
|
+
--color-blue-ink: #2455cd;
|
|
20
|
+
--color-green-bg: #e7f6ee;
|
|
21
|
+
--color-green-ink: #187349;
|
|
22
|
+
--color-amber-bg: #fff3dd;
|
|
23
|
+
--color-amber-ink: #94600d;
|
|
24
|
+
--color-red-bg: #fdecec;
|
|
25
|
+
--color-red-ink: #b63535;
|
|
26
|
+
--color-on-brand: #ffffff;
|
|
27
|
+
--color-nav-ink: #ffffff;
|
|
28
|
+
--color-focus: #3569f6;
|
|
29
|
+
--color-surface-hover: #edf2fa;
|
|
30
|
+
--color-disabled: #d2dae7;
|
|
31
|
+
--color-overlay: #0b1220;
|
|
32
|
+
--color-progress-track: var(--color-line);
|
|
33
|
+
|
|
34
|
+
--font-family: 'Inter Variable', Inter, system-ui, -apple-system, 'Segoe UI', sans-serif;
|
|
35
|
+
--font-caption: 400 12px/17px var(--font-family);
|
|
36
|
+
--font-body: 400 14px/20px var(--font-family);
|
|
37
|
+
--font-label: 500 14px/20px var(--font-family);
|
|
38
|
+
--font-strong: 600 14px/20px var(--font-family);
|
|
39
|
+
--font-section: 600 17px/24px var(--font-family);
|
|
40
|
+
--font-title: 700 30px/42px var(--font-family);
|
|
41
|
+
--font-title-mobile: 700 24px/32px var(--font-family);
|
|
42
|
+
--font-metric: 600 30px/42px var(--font-family);
|
|
43
|
+
--font-logo: 700 25px/35px var(--font-family);
|
|
44
|
+
|
|
45
|
+
--space-0: 0px;
|
|
46
|
+
--space-1: 1px;
|
|
47
|
+
--space-2: 2px;
|
|
48
|
+
--space-4: 4px;
|
|
49
|
+
--space-6: 6px;
|
|
50
|
+
--space-8: 8px;
|
|
51
|
+
--space-12: 12px;
|
|
52
|
+
--space-16: 16px;
|
|
53
|
+
--space-20: 20px;
|
|
54
|
+
--space-24: 24px;
|
|
55
|
+
--space-28: 28px;
|
|
56
|
+
--space-32: 32px;
|
|
57
|
+
--space-40: 40px;
|
|
58
|
+
--space-48: 48px;
|
|
59
|
+
--space-64: 64px;
|
|
60
|
+
--radius-panel: 12px;
|
|
61
|
+
--radius-control: 8px;
|
|
62
|
+
--radius-small: 4px;
|
|
63
|
+
--radius-round: 999px;
|
|
64
|
+
--control-height: 40px;
|
|
65
|
+
--button-height: 42px;
|
|
66
|
+
--touch-target: 44px;
|
|
67
|
+
--badge-min-height: 28px;
|
|
68
|
+
--spinner-size: 16px;
|
|
69
|
+
--tooltip-max-width: 240px;
|
|
70
|
+
--dialog-width: 440px;
|
|
71
|
+
--dialog-width-wide: 640px;
|
|
72
|
+
|
|
73
|
+
--duration-fast: 120ms;
|
|
74
|
+
--duration-base: 200ms;
|
|
75
|
+
--overlay-opacity: 0.55;
|
|
76
|
+
--focus-ring: 2px solid var(--color-focus);
|
|
77
|
+
--shadow-popover: 0 8px 24px rgb(11 18 32 / 0.16);
|
|
78
|
+
|
|
79
|
+
--z-sticky: 20;
|
|
80
|
+
--z-dropdown: 30;
|
|
81
|
+
--z-menu: 80;
|
|
82
|
+
--z-tooltip: 90;
|
|
83
|
+
--z-toast: 100;
|
|
84
|
+
--z-overlay: 200;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
@media (max-width: 767.98px) {
|
|
88
|
+
:root {
|
|
89
|
+
--control-height: var(--touch-target);
|
|
90
|
+
--button-height: var(--touch-target);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
@media (prefers-color-scheme: dark) {
|
|
95
|
+
:root:not([data-theme='light']) {
|
|
96
|
+
color-scheme: dark;
|
|
97
|
+
|
|
98
|
+
--color-bg: #0b1220;
|
|
99
|
+
--color-surface: #141f32;
|
|
100
|
+
--color-ink: #e7edf8;
|
|
101
|
+
--color-muted: #a0afc5;
|
|
102
|
+
--color-line: #2a3951;
|
|
103
|
+
--color-nav: #0a101c;
|
|
104
|
+
--color-nav-active: #233652;
|
|
105
|
+
--color-nav-text: #a8b7d0;
|
|
106
|
+
--color-brand: #3068ff;
|
|
107
|
+
--color-brand-hover: #2a5ee6;
|
|
108
|
+
--color-link: var(--color-blue-ink);
|
|
109
|
+
--color-blue-bg: #1a2c4e;
|
|
110
|
+
--color-blue-ink: #9bbcff;
|
|
111
|
+
--color-green-bg: #173a30;
|
|
112
|
+
--color-green-ink: #8edcb5;
|
|
113
|
+
--color-amber-bg: #3d311b;
|
|
114
|
+
--color-amber-ink: #f2ce85;
|
|
115
|
+
--color-red-bg: #3f242b;
|
|
116
|
+
--color-red-ink: #ffacb3;
|
|
117
|
+
--color-on-brand: #ffffff;
|
|
118
|
+
--color-nav-ink: #ffffff;
|
|
119
|
+
--color-focus: #9bbcff;
|
|
120
|
+
--color-surface-hover: #1d2b42;
|
|
121
|
+
--color-disabled: #34445c;
|
|
122
|
+
--color-overlay: #000000;
|
|
123
|
+
--color-progress-track: #202b3d;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
:root[data-theme='dark'] {
|
|
128
|
+
color-scheme: dark;
|
|
129
|
+
|
|
130
|
+
--color-bg: #0b1220;
|
|
131
|
+
--color-surface: #141f32;
|
|
132
|
+
--color-ink: #e7edf8;
|
|
133
|
+
--color-muted: #a0afc5;
|
|
134
|
+
--color-line: #2a3951;
|
|
135
|
+
--color-nav: #0a101c;
|
|
136
|
+
--color-nav-active: #233652;
|
|
137
|
+
--color-nav-text: #a8b7d0;
|
|
138
|
+
--color-brand: #3068ff;
|
|
139
|
+
--color-brand-hover: #2a5ee6;
|
|
140
|
+
--color-link: var(--color-blue-ink);
|
|
141
|
+
--color-blue-bg: #1a2c4e;
|
|
142
|
+
--color-blue-ink: #9bbcff;
|
|
143
|
+
--color-green-bg: #173a30;
|
|
144
|
+
--color-green-ink: #8edcb5;
|
|
145
|
+
--color-amber-bg: #3d311b;
|
|
146
|
+
--color-amber-ink: #f2ce85;
|
|
147
|
+
--color-red-bg: #3f242b;
|
|
148
|
+
--color-red-ink: #ffacb3;
|
|
149
|
+
--color-on-brand: #ffffff;
|
|
150
|
+
--color-nav-ink: #ffffff;
|
|
151
|
+
--color-focus: #9bbcff;
|
|
152
|
+
--color-surface-hover: #1d2b42;
|
|
153
|
+
--color-disabled: #34445c;
|
|
154
|
+
--color-overlay: #000000;
|
|
155
|
+
--color-progress-track: #202b3d;
|
|
156
|
+
}
|
package/dist/tokens.json
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
{
|
|
2
|
+
"light": {
|
|
3
|
+
"--color-bg": "#f5f7fb",
|
|
4
|
+
"--color-surface": "#ffffff",
|
|
5
|
+
"--color-ink": "#17243d",
|
|
6
|
+
"--color-muted": "#616d81",
|
|
7
|
+
"--color-line": "#e4e9f1",
|
|
8
|
+
"--color-nav": "#111e35",
|
|
9
|
+
"--color-nav-active": "#263b5d",
|
|
10
|
+
"--color-nav-text": "#a8b7d0",
|
|
11
|
+
"--color-brand": "#3569f6",
|
|
12
|
+
"--color-brand-hover": "#3161e0",
|
|
13
|
+
"--color-link": "#2455cd",
|
|
14
|
+
"--color-blue-bg": "#ebf1ff",
|
|
15
|
+
"--color-blue-ink": "#2455cd",
|
|
16
|
+
"--color-green-bg": "#e7f6ee",
|
|
17
|
+
"--color-green-ink": "#187349",
|
|
18
|
+
"--color-amber-bg": "#fff3dd",
|
|
19
|
+
"--color-amber-ink": "#94600d",
|
|
20
|
+
"--color-red-bg": "#fdecec",
|
|
21
|
+
"--color-red-ink": "#b63535",
|
|
22
|
+
"--color-on-brand": "#ffffff",
|
|
23
|
+
"--color-nav-ink": "#ffffff",
|
|
24
|
+
"--color-focus": "#3569f6",
|
|
25
|
+
"--color-surface-hover": "#edf2fa",
|
|
26
|
+
"--color-disabled": "#d2dae7",
|
|
27
|
+
"--color-overlay": "#0b1220",
|
|
28
|
+
"--color-progress-track": "#e4e9f1",
|
|
29
|
+
"--font-family": "'Inter Variable', Inter, system-ui, -apple-system, 'Segoe UI', sans-serif",
|
|
30
|
+
"--font-caption": "400 12px/17px 'Inter Variable', Inter, system-ui, -apple-system, 'Segoe UI', sans-serif",
|
|
31
|
+
"--font-body": "400 14px/20px 'Inter Variable', Inter, system-ui, -apple-system, 'Segoe UI', sans-serif",
|
|
32
|
+
"--font-label": "500 14px/20px 'Inter Variable', Inter, system-ui, -apple-system, 'Segoe UI', sans-serif",
|
|
33
|
+
"--font-strong": "600 14px/20px 'Inter Variable', Inter, system-ui, -apple-system, 'Segoe UI', sans-serif",
|
|
34
|
+
"--font-section": "600 17px/24px 'Inter Variable', Inter, system-ui, -apple-system, 'Segoe UI', sans-serif",
|
|
35
|
+
"--font-title": "700 30px/42px 'Inter Variable', Inter, system-ui, -apple-system, 'Segoe UI', sans-serif",
|
|
36
|
+
"--font-title-mobile": "700 24px/32px 'Inter Variable', Inter, system-ui, -apple-system, 'Segoe UI', sans-serif",
|
|
37
|
+
"--font-metric": "600 30px/42px 'Inter Variable', Inter, system-ui, -apple-system, 'Segoe UI', sans-serif",
|
|
38
|
+
"--font-logo": "700 25px/35px 'Inter Variable', Inter, system-ui, -apple-system, 'Segoe UI', sans-serif",
|
|
39
|
+
"--space-0": "0px",
|
|
40
|
+
"--space-1": "1px",
|
|
41
|
+
"--space-2": "2px",
|
|
42
|
+
"--space-4": "4px",
|
|
43
|
+
"--space-6": "6px",
|
|
44
|
+
"--space-8": "8px",
|
|
45
|
+
"--space-12": "12px",
|
|
46
|
+
"--space-16": "16px",
|
|
47
|
+
"--space-20": "20px",
|
|
48
|
+
"--space-24": "24px",
|
|
49
|
+
"--space-28": "28px",
|
|
50
|
+
"--space-32": "32px",
|
|
51
|
+
"--space-40": "40px",
|
|
52
|
+
"--space-48": "48px",
|
|
53
|
+
"--space-64": "64px",
|
|
54
|
+
"--radius-panel": "12px",
|
|
55
|
+
"--radius-control": "8px",
|
|
56
|
+
"--radius-small": "4px",
|
|
57
|
+
"--radius-round": "999px",
|
|
58
|
+
"--control-height": "40px",
|
|
59
|
+
"--button-height": "42px",
|
|
60
|
+
"--touch-target": "44px",
|
|
61
|
+
"--badge-min-height": "28px",
|
|
62
|
+
"--spinner-size": "16px",
|
|
63
|
+
"--tooltip-max-width": "240px",
|
|
64
|
+
"--dialog-width": "440px",
|
|
65
|
+
"--dialog-width-wide": "640px",
|
|
66
|
+
"--duration-fast": "120ms",
|
|
67
|
+
"--duration-base": "200ms",
|
|
68
|
+
"--overlay-opacity": "0.55",
|
|
69
|
+
"--focus-ring": "2px solid #3569f6",
|
|
70
|
+
"--shadow-popover": "0 8px 24px rgb(11 18 32 / 0.16)",
|
|
71
|
+
"--z-sticky": "20",
|
|
72
|
+
"--z-dropdown": "30",
|
|
73
|
+
"--z-menu": "80",
|
|
74
|
+
"--z-tooltip": "90",
|
|
75
|
+
"--z-toast": "100",
|
|
76
|
+
"--z-overlay": "200"
|
|
77
|
+
},
|
|
78
|
+
"dark": {
|
|
79
|
+
"--color-bg": "#0b1220",
|
|
80
|
+
"--color-surface": "#141f32",
|
|
81
|
+
"--color-ink": "#e7edf8",
|
|
82
|
+
"--color-muted": "#a0afc5",
|
|
83
|
+
"--color-line": "#2a3951",
|
|
84
|
+
"--color-nav": "#0a101c",
|
|
85
|
+
"--color-nav-active": "#233652",
|
|
86
|
+
"--color-nav-text": "#a8b7d0",
|
|
87
|
+
"--color-brand": "#3068ff",
|
|
88
|
+
"--color-brand-hover": "#2a5ee6",
|
|
89
|
+
"--color-link": "#9bbcff",
|
|
90
|
+
"--color-blue-bg": "#1a2c4e",
|
|
91
|
+
"--color-blue-ink": "#9bbcff",
|
|
92
|
+
"--color-green-bg": "#173a30",
|
|
93
|
+
"--color-green-ink": "#8edcb5",
|
|
94
|
+
"--color-amber-bg": "#3d311b",
|
|
95
|
+
"--color-amber-ink": "#f2ce85",
|
|
96
|
+
"--color-red-bg": "#3f242b",
|
|
97
|
+
"--color-red-ink": "#ffacb3",
|
|
98
|
+
"--color-on-brand": "#ffffff",
|
|
99
|
+
"--color-nav-ink": "#ffffff",
|
|
100
|
+
"--color-focus": "#9bbcff",
|
|
101
|
+
"--color-surface-hover": "#1d2b42",
|
|
102
|
+
"--color-disabled": "#34445c",
|
|
103
|
+
"--color-overlay": "#000000",
|
|
104
|
+
"--color-progress-track": "#202b3d",
|
|
105
|
+
"--font-family": "'Inter Variable', Inter, system-ui, -apple-system, 'Segoe UI', sans-serif",
|
|
106
|
+
"--font-caption": "400 12px/17px 'Inter Variable', Inter, system-ui, -apple-system, 'Segoe UI', sans-serif",
|
|
107
|
+
"--font-body": "400 14px/20px 'Inter Variable', Inter, system-ui, -apple-system, 'Segoe UI', sans-serif",
|
|
108
|
+
"--font-label": "500 14px/20px 'Inter Variable', Inter, system-ui, -apple-system, 'Segoe UI', sans-serif",
|
|
109
|
+
"--font-strong": "600 14px/20px 'Inter Variable', Inter, system-ui, -apple-system, 'Segoe UI', sans-serif",
|
|
110
|
+
"--font-section": "600 17px/24px 'Inter Variable', Inter, system-ui, -apple-system, 'Segoe UI', sans-serif",
|
|
111
|
+
"--font-title": "700 30px/42px 'Inter Variable', Inter, system-ui, -apple-system, 'Segoe UI', sans-serif",
|
|
112
|
+
"--font-title-mobile": "700 24px/32px 'Inter Variable', Inter, system-ui, -apple-system, 'Segoe UI', sans-serif",
|
|
113
|
+
"--font-metric": "600 30px/42px 'Inter Variable', Inter, system-ui, -apple-system, 'Segoe UI', sans-serif",
|
|
114
|
+
"--font-logo": "700 25px/35px 'Inter Variable', Inter, system-ui, -apple-system, 'Segoe UI', sans-serif",
|
|
115
|
+
"--space-0": "0px",
|
|
116
|
+
"--space-1": "1px",
|
|
117
|
+
"--space-2": "2px",
|
|
118
|
+
"--space-4": "4px",
|
|
119
|
+
"--space-6": "6px",
|
|
120
|
+
"--space-8": "8px",
|
|
121
|
+
"--space-12": "12px",
|
|
122
|
+
"--space-16": "16px",
|
|
123
|
+
"--space-20": "20px",
|
|
124
|
+
"--space-24": "24px",
|
|
125
|
+
"--space-28": "28px",
|
|
126
|
+
"--space-32": "32px",
|
|
127
|
+
"--space-40": "40px",
|
|
128
|
+
"--space-48": "48px",
|
|
129
|
+
"--space-64": "64px",
|
|
130
|
+
"--radius-panel": "12px",
|
|
131
|
+
"--radius-control": "8px",
|
|
132
|
+
"--radius-small": "4px",
|
|
133
|
+
"--radius-round": "999px",
|
|
134
|
+
"--control-height": "40px",
|
|
135
|
+
"--button-height": "42px",
|
|
136
|
+
"--touch-target": "44px",
|
|
137
|
+
"--badge-min-height": "28px",
|
|
138
|
+
"--spinner-size": "16px",
|
|
139
|
+
"--tooltip-max-width": "240px",
|
|
140
|
+
"--dialog-width": "440px",
|
|
141
|
+
"--dialog-width-wide": "640px",
|
|
142
|
+
"--duration-fast": "120ms",
|
|
143
|
+
"--duration-base": "200ms",
|
|
144
|
+
"--overlay-opacity": "0.55",
|
|
145
|
+
"--focus-ring": "2px solid #9bbcff",
|
|
146
|
+
"--shadow-popover": "0 8px 24px rgb(11 18 32 / 0.16)",
|
|
147
|
+
"--z-sticky": "20",
|
|
148
|
+
"--z-dropdown": "30",
|
|
149
|
+
"--z-menu": "80",
|
|
150
|
+
"--z-tooltip": "90",
|
|
151
|
+
"--z-toast": "100",
|
|
152
|
+
"--z-overlay": "200"
|
|
153
|
+
}
|
|
154
|
+
}
|