@yarcl/react 0.1.0 → 0.2.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 +14 -2
- package/{src/apply.ts → dist/apply.d.ts} +4 -23
- package/dist/apply.js +37 -0
- package/dist/classes.d.ts +13 -0
- package/dist/classes.js +22 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +58 -0
- package/dist/color.js +49 -32
- package/dist/components/Accordion.d.ts +96 -0
- package/dist/components/Accordion.js +148 -0
- package/dist/components/Alert.d.ts +60 -0
- package/dist/components/Alert.js +61 -0
- package/dist/components/Avatar.d.ts +100 -0
- package/dist/components/Avatar.js +89 -0
- package/dist/components/Badge.d.ts +44 -0
- package/dist/components/Badge.js +43 -0
- package/dist/components/Breadcrumb.d.ts +77 -0
- package/dist/components/Breadcrumb.js +126 -0
- package/dist/components/Button.d.ts +18 -0
- package/dist/components/Button.js +33 -0
- package/dist/components/ButtonGroup.d.ts +29 -0
- package/dist/components/ButtonGroup.js +37 -0
- package/dist/components/Card.d.ts +36 -0
- package/dist/components/Card.js +26 -0
- package/dist/components/Checkbox.d.ts +28 -0
- package/dist/components/Checkbox.js +38 -0
- package/dist/components/Combobox.d.ts +75 -0
- package/dist/components/Combobox.js +362 -0
- package/dist/components/CommandPalette.d.ts +92 -0
- package/dist/components/CommandPalette.js +293 -0
- package/dist/components/DatePicker.d.ts +157 -0
- package/dist/components/DatePicker.js +230 -0
- package/dist/components/Dialog.d.ts +25 -0
- package/dist/components/Dialog.js +29 -0
- package/dist/components/Divider.d.ts +23 -0
- package/dist/components/Divider.js +25 -0
- package/dist/components/Drawer.d.ts +21 -0
- package/dist/components/Drawer.js +25 -0
- package/dist/components/EmptyState.d.ts +51 -0
- package/dist/components/EmptyState.js +47 -0
- package/dist/components/Field.d.ts +27 -0
- package/dist/components/Field.js +59 -0
- package/dist/components/Heading.d.ts +26 -0
- package/dist/components/Heading.js +25 -0
- package/dist/components/HoverCard.d.ts +47 -0
- package/dist/components/HoverCard.js +53 -0
- package/dist/components/IconButton.d.ts +19 -0
- package/dist/components/IconButton.js +32 -0
- package/dist/components/Inline.d.ts +21 -0
- package/dist/components/Inline.js +24 -0
- package/dist/components/Input.d.ts +19 -0
- package/dist/components/Input.js +25 -0
- package/dist/components/Label.d.ts +46 -0
- package/dist/components/Label.js +33 -0
- package/dist/components/Link.d.ts +27 -0
- package/dist/components/Link.js +26 -0
- package/dist/components/Menu.d.ts +73 -0
- package/dist/components/Menu.js +143 -0
- package/dist/components/Modal.d.ts +45 -0
- package/dist/components/Modal.js +110 -0
- package/dist/components/NumberInput.d.ts +49 -0
- package/dist/components/NumberInput.js +130 -0
- package/dist/components/Pagination.d.ts +86 -0
- package/dist/components/Pagination.js +119 -0
- package/dist/components/Popover.d.ts +72 -0
- package/dist/components/Popover.js +87 -0
- package/dist/components/Progress.d.ts +60 -0
- package/dist/components/Progress.js +59 -0
- package/dist/components/Radio.d.ts +32 -0
- package/dist/components/Radio.js +47 -0
- package/dist/components/RadioGroup.d.ts +57 -0
- package/dist/components/RadioGroup.js +68 -0
- package/dist/components/Select.d.ts +47 -0
- package/dist/components/Select.js +138 -0
- package/dist/components/Skeleton.d.ts +46 -0
- package/dist/components/Skeleton.js +40 -0
- package/dist/components/Slider.d.ts +126 -0
- package/dist/components/Slider.js +166 -0
- package/dist/components/Spinner.d.ts +23 -0
- package/dist/components/Spinner.js +23 -0
- package/dist/components/Stack.d.ts +35 -0
- package/dist/components/Stack.js +24 -0
- package/dist/components/Switch.d.ts +27 -0
- package/dist/components/Switch.js +33 -0
- package/dist/components/Table.d.ts +71 -0
- package/dist/components/Table.js +61 -0
- package/dist/components/Tabs.d.ts +66 -0
- package/dist/components/Tabs.js +109 -0
- package/dist/components/Text.d.ts +32 -0
- package/dist/components/Text.js +28 -0
- package/dist/components/Textarea.d.ts +15 -0
- package/dist/components/Textarea.js +24 -0
- package/dist/components/Toast.d.ts +90 -0
- package/dist/components/Toast.js +156 -0
- package/dist/components/ToggleGroup.d.ts +79 -0
- package/dist/components/ToggleGroup.js +101 -0
- package/dist/components/Tooltip.d.ts +46 -0
- package/dist/components/Tooltip.js +62 -0
- package/dist/components/VisuallyHidden.d.ts +18 -0
- package/dist/components/VisuallyHidden.js +22 -0
- package/dist/contrast.d.ts +32 -0
- package/dist/css.d.ts +2 -2
- package/dist/css.js +193 -157
- package/dist/define.d.ts +40 -15
- package/dist/define.js +30 -27
- package/dist/demo.d.ts +2 -0
- package/dist/demo.js +2 -0
- package/dist/esbuild.cjs +5 -0
- package/dist/esbuild.d.ts +4 -0
- package/dist/esbuild.js +6 -0
- package/dist/field-context.d.ts +16 -0
- package/dist/field-context.js +17 -0
- package/dist/floating.d.ts +12 -0
- package/dist/floating.js +52 -0
- package/dist/hooks.d.ts +1 -0
- package/dist/hooks.js +12 -0
- package/{src/index.ts → dist/index.d.ts} +11 -33
- package/dist/index.js +50 -0
- package/dist/init.d.ts +18 -0
- package/dist/init.js +224 -0
- package/dist/plugin.d.ts +10 -26
- package/dist/plugin.js +152 -78
- package/dist/reference/DemoYarcl.d.ts +12 -0
- package/dist/reference/DemoYarcl.js +312 -0
- package/dist/reference/DesignReference.d.ts +24 -0
- package/dist/reference/DesignReference.js +403 -0
- package/dist/reference/index.js +2 -0
- package/dist/rollup.cjs +5 -0
- package/dist/rollup.d.ts +4 -0
- package/dist/rollup.js +6 -0
- package/dist/rspack.cjs +5 -0
- package/dist/rspack.d.ts +4 -0
- package/dist/rspack.js +6 -0
- package/dist/runtime.d.ts +13 -0
- package/dist/runtime.js +30 -0
- package/dist/setup.d.ts +6 -0
- package/dist/setup.js +33 -0
- package/{src → dist}/styles.css +224 -106
- package/dist/themes/bloom.d.ts +295 -0
- package/dist/themes/bloom.js +202 -0
- package/dist/themes/brutalist.d.ts +277 -0
- package/dist/themes/brutalist.js +199 -0
- package/dist/themes/compact.d.ts +274 -0
- package/dist/themes/compact.js +200 -0
- package/dist/themes/contract.d.ts +23 -0
- package/dist/themes/editorial.d.ts +277 -0
- package/dist/themes/editorial.js +183 -0
- package/dist/themes/index.d.ts +1425 -0
- package/dist/themes/index.js +45 -0
- package/{src/types.ts → dist/types.d.ts} +40 -37
- package/dist/vite.cjs +5 -0
- package/dist/vite.d.ts +4 -0
- package/dist/vite.js +6 -0
- package/dist/webpack.cjs +5 -0
- package/dist/webpack.d.ts +4 -0
- package/dist/webpack.js +6 -0
- package/dist/yarcl.config.d.ts +276 -0
- package/dist/yarcl.config.js +273 -0
- package/package.json +69 -17
- package/src/classes.ts +0 -23
- package/src/color.ts +0 -48
- package/src/components/Accordion.tsx +0 -274
- package/src/components/Alert.tsx +0 -85
- package/src/components/Badge.tsx +0 -79
- package/src/components/Breadcrumb.tsx +0 -239
- package/src/components/Button.tsx +0 -58
- package/src/components/ButtonGroup.tsx +0 -61
- package/src/components/Card.tsx +0 -50
- package/src/components/Checkbox.tsx +0 -49
- package/src/components/Combobox.tsx +0 -522
- package/src/components/CommandPalette.tsx +0 -452
- package/src/components/DatePicker.tsx +0 -432
- package/src/components/Dialog.tsx +0 -39
- package/src/components/Divider.tsx +0 -34
- package/src/components/Drawer.tsx +0 -31
- package/src/components/Field.tsx +0 -61
- package/src/components/Heading.tsx +0 -40
- package/src/components/HoverCard.tsx +0 -108
- package/src/components/IconButton.tsx +0 -59
- package/src/components/Inline.tsx +0 -42
- package/src/components/Input.tsx +0 -28
- package/src/components/Label.tsx +0 -58
- package/src/components/Link.tsx +0 -41
- package/src/components/Menu.tsx +0 -207
- package/src/components/Modal.tsx +0 -164
- package/src/components/NumberInput.tsx +0 -208
- package/src/components/Pagination.tsx +0 -227
- package/src/components/Popover.tsx +0 -140
- package/src/components/Progress.tsx +0 -122
- package/src/components/Radio.tsx +0 -59
- package/src/components/RadioGroup.tsx +0 -114
- package/src/components/Select.tsx +0 -197
- package/src/components/Skeleton.tsx +0 -95
- package/src/components/Slider.tsx +0 -315
- package/src/components/Spinner.tsx +0 -38
- package/src/components/Stack.tsx +0 -57
- package/src/components/Switch.tsx +0 -42
- package/src/components/Table.tsx +0 -99
- package/src/components/Tabs.tsx +0 -159
- package/src/components/Text.tsx +0 -67
- package/src/components/Textarea.tsx +0 -26
- package/src/components/Toast.tsx +0 -190
- package/src/components/ToggleGroup.tsx +0 -227
- package/src/components/Tooltip.tsx +0 -78
- package/src/contrast.ts +0 -82
- package/src/css.ts +0 -228
- package/src/define.check.ts +0 -259
- package/src/define.ts +0 -379
- package/src/field-context.ts +0 -31
- package/src/floating.tsx +0 -61
- package/src/hooks.ts +0 -19
- package/src/plugin.ts +0 -94
- package/src/reference/DesignReference.tsx +0 -374
- package/src/runtime.ts +0 -38
- package/src/themes/bloom.ts +0 -72
- package/src/themes/brutalist.ts +0 -63
- package/src/themes/compact.ts +0 -63
- package/src/themes/contract.ts +0 -24
- package/src/themes/editorial.ts +0 -55
- package/src/themes/index.ts +0 -47
- package/src/yarcl.config.ts +0 -104
- /package/{src/reference/index.ts → dist/reference/index.d.ts} +0 -0
- /package/{src → dist}/reference/reference.css +0 -0
package/README.md
CHANGED
|
@@ -2,6 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
Yet another react component library. Your config file is the design system: every key becomes a typed prop and a rendered style.
|
|
4
4
|
|
|
5
|
+
From an existing React project using Vite, webpack, Rspack, Rollup or esbuild, run:
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
npx @yarcl/react init
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
This installs the package, adds the detected build plugin and TypeScript path mapping, and creates `src/yarcl.config.ts`. The equivalent commands are `pnpm dlx @yarcl/react init`, `yarn dlx @yarcl/react init` and `bunx @yarcl/react init`.
|
|
12
|
+
|
|
13
|
+
For manual setup:
|
|
14
|
+
|
|
5
15
|
```sh
|
|
6
16
|
npm install @yarcl/react
|
|
7
17
|
```
|
|
@@ -10,17 +20,19 @@ npm install @yarcl/react
|
|
|
10
20
|
// vite.config.ts
|
|
11
21
|
import react from '@vitejs/plugin-react';
|
|
12
22
|
import { defineConfig } from 'vite';
|
|
13
|
-
import
|
|
23
|
+
import yarcl from '@yarcl/react/vite';
|
|
14
24
|
|
|
15
25
|
export default defineConfig({ plugins: [react(), yarcl({ config: 'src/yarcl.config.ts' })] });
|
|
16
26
|
```
|
|
17
27
|
|
|
28
|
+
For webpack, Rspack, Rollup or esbuild, import the plugin from the matching `@yarcl/react/<build-tool>` entry point.
|
|
29
|
+
|
|
18
30
|
```jsonc
|
|
19
31
|
// tsconfig.json
|
|
20
32
|
{
|
|
21
33
|
"compilerOptions": {
|
|
22
34
|
"paths": {
|
|
23
|
-
"@yarcl/config": ["./src/yarcl.config.ts", "./node_modules/@yarcl/react/
|
|
35
|
+
"@yarcl/config": ["./src/yarcl.config.ts", "./node_modules/@yarcl/react/dist/yarcl.config.d.ts"]
|
|
24
36
|
}
|
|
25
37
|
}
|
|
26
38
|
}
|
|
@@ -1,17 +1,11 @@
|
|
|
1
1
|
import { generateCss } from './css';
|
|
2
2
|
import type { YarclShape } from './define';
|
|
3
|
-
import { setActiveConfig } from './runtime';
|
|
4
|
-
|
|
5
3
|
export { generateCss };
|
|
6
|
-
|
|
7
|
-
const STYLE_ID = 'yarcl-theme';
|
|
8
|
-
|
|
9
4
|
/** Options for {@link applyTheme}. */
|
|
10
5
|
export interface ApplyThemeOptions {
|
|
11
|
-
|
|
12
|
-
|
|
6
|
+
/** Receives contrast warnings for the theme's colors. */
|
|
7
|
+
onWarning?: (message: string) => void;
|
|
13
8
|
}
|
|
14
|
-
|
|
15
9
|
/**
|
|
16
10
|
* Switches the whole app to another theme at runtime, without a rebuild.
|
|
17
11
|
*
|
|
@@ -28,19 +22,6 @@ export interface ApplyThemeOptions {
|
|
|
28
22
|
* applyTheme(themes.editorial);
|
|
29
23
|
* ```
|
|
30
24
|
*/
|
|
31
|
-
export function applyTheme(theme: YarclShape, { onWarning }
|
|
32
|
-
let style = document.getElementById(STYLE_ID);
|
|
33
|
-
if (!style) {
|
|
34
|
-
style = document.createElement('style');
|
|
35
|
-
style.id = STYLE_ID;
|
|
36
|
-
}
|
|
37
|
-
document.head.appendChild(style);
|
|
38
|
-
style.textContent = generateCss(theme, onWarning);
|
|
39
|
-
setActiveConfig(theme);
|
|
40
|
-
}
|
|
41
|
-
|
|
25
|
+
export declare function applyTheme(theme: YarclShape, { onWarning }?: ApplyThemeOptions): void;
|
|
42
26
|
/** Removes a theme applied with {@link applyTheme} and returns to the build-time config and styles. */
|
|
43
|
-
export function resetTheme()
|
|
44
|
-
document.getElementById(STYLE_ID)?.remove();
|
|
45
|
-
setActiveConfig(null);
|
|
46
|
-
}
|
|
27
|
+
export declare function resetTheme(): void;
|
package/dist/apply.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { setActiveConfig } from "./runtime.js";
|
|
2
|
+
import { generateCss } from "./css.js";
|
|
3
|
+
//#region src/apply.ts
|
|
4
|
+
var STYLE_ID = "yarcl-theme";
|
|
5
|
+
/**
|
|
6
|
+
* Switches the whole app to another theme at runtime, without a rebuild.
|
|
7
|
+
*
|
|
8
|
+
* Injects the theme's generated CSS (replacing the build-time styles) and makes components read
|
|
9
|
+
* their defaults (`defaults`, `components`, heading levels) from the theme, re-rendering them.
|
|
10
|
+
* The theme must define the keys your app uses; bundled themes share the defaults' keys
|
|
11
|
+
* (`ThemeContract`), so any of them can replace another.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```ts
|
|
15
|
+
* import { applyTheme } from '@yarcl/react/css';
|
|
16
|
+
* import { themes } from '@yarcl/react/themes';
|
|
17
|
+
*
|
|
18
|
+
* applyTheme(themes.editorial);
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
function applyTheme(theme, { onWarning } = {}) {
|
|
22
|
+
let style = document.getElementById(STYLE_ID);
|
|
23
|
+
if (!style) {
|
|
24
|
+
style = document.createElement("style");
|
|
25
|
+
style.id = STYLE_ID;
|
|
26
|
+
}
|
|
27
|
+
document.head.appendChild(style);
|
|
28
|
+
style.textContent = generateCss(theme, onWarning);
|
|
29
|
+
setActiveConfig(theme);
|
|
30
|
+
}
|
|
31
|
+
/** Removes a theme applied with {@link applyTheme} and returns to the build-time config and styles. */
|
|
32
|
+
function resetTheme() {
|
|
33
|
+
document.getElementById(STYLE_ID)?.remove();
|
|
34
|
+
setActiveConfig(null);
|
|
35
|
+
}
|
|
36
|
+
//#endregion
|
|
37
|
+
export { applyTheme, generateCss, resetTheme };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Color, Density, Radius, Shadow, Size, Spacing, TextStyle, Variant } from './types';
|
|
2
|
+
import type { ComponentName } from './define';
|
|
3
|
+
export declare function cx(...parts: (string | false | null | undefined)[]): string;
|
|
4
|
+
export declare const sizeClass: (size?: Size, component?: ComponentName) => string;
|
|
5
|
+
export declare function radiusClass(radius?: Radius | 'size', size?: Size): string | undefined;
|
|
6
|
+
export declare const colorClass: (color?: Color) => string;
|
|
7
|
+
export declare const variantClass: (variant?: Variant) => string;
|
|
8
|
+
export declare const gapClass: (gap?: Spacing) => string;
|
|
9
|
+
export declare const paddingClass: (padding?: Spacing) => string;
|
|
10
|
+
export declare const shadowClass: (shadow?: Shadow) => string | undefined;
|
|
11
|
+
export declare const typeClass: (style: TextStyle) => string;
|
|
12
|
+
export declare const densityClass: (density?: Density) => string;
|
|
13
|
+
export declare const softVariantClass: (variant?: Variant) => string;
|
package/dist/classes.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { activeConfig } from "./runtime.js";
|
|
2
|
+
//#region src/classes.ts
|
|
3
|
+
function cx(...parts) {
|
|
4
|
+
return parts.filter(Boolean).join(" ");
|
|
5
|
+
}
|
|
6
|
+
var sizeClass = (size = activeConfig().defaults.size, component) => `yarcl-size-${size}${component ? ` yarcl-sized-${component}` : ""}`;
|
|
7
|
+
function radiusClass(radius, size) {
|
|
8
|
+
const value = radius ?? activeConfig().defaults.radius;
|
|
9
|
+
if (value !== "size") return `yarcl-radius-${value}`;
|
|
10
|
+
const match = size ?? activeConfig().defaults.size;
|
|
11
|
+
return match in activeConfig().radii ? `yarcl-radius-${match}` : void 0;
|
|
12
|
+
}
|
|
13
|
+
var colorClass = (color = activeConfig().defaults.color) => `yarcl-color-${color}`;
|
|
14
|
+
var variantClass = (variant = activeConfig().defaults.variant) => `yarcl-variant-${variant}`;
|
|
15
|
+
var gapClass = (gap = activeConfig().defaults.gap) => `yarcl-gap-${gap}`;
|
|
16
|
+
var paddingClass = (padding = activeConfig().defaults.padding) => `yarcl-padding-${padding}`;
|
|
17
|
+
var shadowClass = (shadow) => shadow && `yarcl-shadow-${shadow}`;
|
|
18
|
+
var typeClass = (style) => `yarcl-type-${style}`;
|
|
19
|
+
var densityClass = (density = activeConfig().defaults.density) => `yarcl-density-${density}`;
|
|
20
|
+
var softVariantClass = (variant = activeConfig().defaults.softVariant) => `yarcl-variant-${variant}`;
|
|
21
|
+
//#endregion
|
|
22
|
+
export { colorClass, cx, densityClass, gapClass, paddingClass, radiusClass, shadowClass, sizeClass, softVariantClass, typeClass, variantClass };
|
package/dist/cli.d.ts
ADDED
package/dist/cli.js
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { initProject } from "./init.js";
|
|
3
|
+
import { readFile } from "node:fs/promises";
|
|
4
|
+
import { dirname, resolve } from "node:path";
|
|
5
|
+
import { error, log } from "node:console";
|
|
6
|
+
import process from "node:process";
|
|
7
|
+
import { fileURLToPath } from "node:url";
|
|
8
|
+
//#region src/cli.ts
|
|
9
|
+
var buildTools = /* @__PURE__ */ new Set([
|
|
10
|
+
"vite",
|
|
11
|
+
"webpack",
|
|
12
|
+
"rspack",
|
|
13
|
+
"rollup",
|
|
14
|
+
"esbuild"
|
|
15
|
+
]);
|
|
16
|
+
function usage() {
|
|
17
|
+
log("Usage: yarcl init [--config <path>] [--root <path>] [--bundler <name>] [--skip-install]");
|
|
18
|
+
}
|
|
19
|
+
function option(args, name) {
|
|
20
|
+
const index = args.indexOf(name);
|
|
21
|
+
if (index < 0) return void 0;
|
|
22
|
+
const value = args[index + 1];
|
|
23
|
+
if (!value || value.startsWith("--")) throw new Error(`yarcl: ${name} requires a value.`);
|
|
24
|
+
return value;
|
|
25
|
+
}
|
|
26
|
+
async function main() {
|
|
27
|
+
const args = process.argv.slice(2);
|
|
28
|
+
if (args.includes("--help") || args.includes("-h")) {
|
|
29
|
+
usage();
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
if (args[0] !== "init") {
|
|
33
|
+
usage();
|
|
34
|
+
process.exitCode = 1;
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
const packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
|
38
|
+
const manifest = JSON.parse(await readFile(resolve(packageRoot, "package.json"), "utf8"));
|
|
39
|
+
const configPath = option(args, "--config");
|
|
40
|
+
const requestedBuildTool = option(args, "--bundler");
|
|
41
|
+
if (requestedBuildTool && !buildTools.has(requestedBuildTool)) throw new Error(`yarcl: Unsupported bundler "${requestedBuildTool}". Use vite, webpack, rspack, rollup or esbuild.`);
|
|
42
|
+
const root = resolve(option(args, "--root") ?? process.cwd());
|
|
43
|
+
const result = await initProject({
|
|
44
|
+
root,
|
|
45
|
+
configPath,
|
|
46
|
+
configProvided: configPath !== void 0,
|
|
47
|
+
buildTool: requestedBuildTool,
|
|
48
|
+
install: !args.includes("--skip-install"),
|
|
49
|
+
version: manifest.version
|
|
50
|
+
});
|
|
51
|
+
log(`yarcl configured ${result.configPath}`);
|
|
52
|
+
log(`Updated ${result.buildConfig.slice(root.length + 1)} and ${result.tsconfig.slice(root.length + 1)}`);
|
|
53
|
+
}
|
|
54
|
+
main().catch((cause) => {
|
|
55
|
+
error(cause instanceof Error ? cause.message : cause);
|
|
56
|
+
process.exitCode = 1;
|
|
57
|
+
});
|
|
58
|
+
//#endregion
|
package/dist/color.js
CHANGED
|
@@ -1,41 +1,58 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
//#region src/color.ts
|
|
2
|
+
function parseHex(value) {
|
|
3
|
+
const hex = value.trim().replace(/^#/, "");
|
|
4
|
+
if (!/^([0-9a-f]{3}|[0-9a-f]{6})$/i.test(hex)) return null;
|
|
5
|
+
const full = hex.length === 3 ? [...hex].map((c) => c + c).join("") : hex;
|
|
6
|
+
return [
|
|
7
|
+
0,
|
|
8
|
+
2,
|
|
9
|
+
4
|
|
10
|
+
].map((i) => parseInt(full.slice(i, i + 2), 16));
|
|
7
11
|
}
|
|
8
12
|
function luminance([r, g, b]) {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
13
|
+
const [lr, lg, lb] = [
|
|
14
|
+
r,
|
|
15
|
+
g,
|
|
16
|
+
b
|
|
17
|
+
].map((c) => {
|
|
18
|
+
const s = c / 255;
|
|
19
|
+
return s <= .03928 ? s / 12.92 : ((s + .055) / 1.055) ** 2.4;
|
|
20
|
+
});
|
|
21
|
+
return .2126 * lr + .7152 * lg + .0722 * lb;
|
|
14
22
|
}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
23
|
+
function contrast(a, b) {
|
|
24
|
+
const [hi, lo] = [luminance(a), luminance(b)].sort((x, y) => y - x);
|
|
25
|
+
return (hi + .05) / (lo + .05);
|
|
18
26
|
}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
27
|
+
var WHITE = [
|
|
28
|
+
255,
|
|
29
|
+
255,
|
|
30
|
+
255
|
|
31
|
+
];
|
|
32
|
+
var BLACK = [
|
|
33
|
+
0,
|
|
34
|
+
0,
|
|
35
|
+
0
|
|
36
|
+
];
|
|
37
|
+
function mix(a, b, amount) {
|
|
38
|
+
return a.map((channel, i) => Math.round(channel + (b[i] - channel) * amount));
|
|
23
39
|
}
|
|
24
|
-
|
|
25
|
-
|
|
40
|
+
function toHex(rgb) {
|
|
41
|
+
return `#${rgb.map((c) => c.toString(16).padStart(2, "0")).join("")}`;
|
|
26
42
|
}
|
|
27
43
|
/**
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
return toward;
|
|
44
|
+
* The color, mixed toward `toward` in small steps until it reaches `min` contrast
|
|
45
|
+
* against every background. Returns the color unchanged when it already passes.
|
|
46
|
+
*/
|
|
47
|
+
function readableText(color, backgrounds, toward, min) {
|
|
48
|
+
for (let step = 0; step <= 20; step++) {
|
|
49
|
+
const candidate = mix(color, toward, step / 20);
|
|
50
|
+
if (backgrounds.every((bg) => contrast(candidate, bg) >= min)) return candidate;
|
|
51
|
+
}
|
|
52
|
+
return toward;
|
|
38
53
|
}
|
|
39
|
-
|
|
40
|
-
|
|
54
|
+
function readableOn(background) {
|
|
55
|
+
return contrast(background, WHITE) >= contrast(background, BLACK) ? "#ffffff" : "#000000";
|
|
41
56
|
}
|
|
57
|
+
//#endregion
|
|
58
|
+
export { contrast, mix, parseHex, readableOn, readableText, toHex };
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { type ComponentProps, type ReactNode } from 'react';
|
|
2
|
+
import type { Color, ComponentSize, Radius } from '../types';
|
|
3
|
+
/** Props shared by both forms of {@link AccordionProps}. */
|
|
4
|
+
export interface AccordionBaseProps extends Omit<ComponentProps<'div'>, 'defaultValue' | 'color'> {
|
|
5
|
+
/**
|
|
6
|
+
* Trigger height, padding and font size, from the `sizes` config.
|
|
7
|
+
* @default config.defaults.size
|
|
8
|
+
*/
|
|
9
|
+
size?: ComponentSize<'Accordion'>;
|
|
10
|
+
/**
|
|
11
|
+
* Corner radius of the outer frame, from the `radii` config, or `'size'` to match the size.
|
|
12
|
+
* @default config.defaults.radius
|
|
13
|
+
*/
|
|
14
|
+
radius?: Radius | 'size';
|
|
15
|
+
/**
|
|
16
|
+
* Color of the open item's indicator, from the `colors` config.
|
|
17
|
+
* @default config.defaults.color
|
|
18
|
+
*/
|
|
19
|
+
color?: Color;
|
|
20
|
+
/** Disables every item. */
|
|
21
|
+
disabled?: boolean;
|
|
22
|
+
/** `Accordion.Item`s. */
|
|
23
|
+
children?: ReactNode;
|
|
24
|
+
}
|
|
25
|
+
/** Props for {@link Accordion}. `type` decides whether one or many items can be open. */
|
|
26
|
+
export type AccordionProps = AccordionBaseProps & ({
|
|
27
|
+
/** One item open at a time. */
|
|
28
|
+
type: 'single';
|
|
29
|
+
/** Open item (controlled), or `null` when all are closed. */
|
|
30
|
+
value?: string | null;
|
|
31
|
+
/** Initially open item (uncontrolled). */
|
|
32
|
+
defaultValue?: string | null;
|
|
33
|
+
/** Called with the open item, or `null` when it closes. */
|
|
34
|
+
onValueChange?: (value: string | null) => void;
|
|
35
|
+
/**
|
|
36
|
+
* Lets the open item close, leaving all closed. When `false`, one item always stays open.
|
|
37
|
+
* @default true
|
|
38
|
+
*/
|
|
39
|
+
collapsible?: boolean;
|
|
40
|
+
} | {
|
|
41
|
+
/** Any number of items open. */
|
|
42
|
+
type: 'multiple';
|
|
43
|
+
/** Open items (controlled). */
|
|
44
|
+
value?: string[];
|
|
45
|
+
/** Initially open items (uncontrolled). */
|
|
46
|
+
defaultValue?: string[];
|
|
47
|
+
/** Called with all open items. */
|
|
48
|
+
onValueChange?: (value: string[]) => void;
|
|
49
|
+
collapsible?: never;
|
|
50
|
+
});
|
|
51
|
+
declare function AccordionRoot(props: AccordionProps): import("react").JSX.Element;
|
|
52
|
+
/** Props for `Accordion.Item`. */
|
|
53
|
+
export interface AccordionItemProps extends Omit<ComponentProps<'div'>, 'value'> {
|
|
54
|
+
/** Identifies the item in the accordion's value. */
|
|
55
|
+
value: string;
|
|
56
|
+
/** Prevents opening or closing this item. */
|
|
57
|
+
disabled?: boolean;
|
|
58
|
+
}
|
|
59
|
+
declare function AccordionItem({ value, disabled, className, ...props }: AccordionItemProps): import("react").JSX.Element;
|
|
60
|
+
/** Props for `Accordion.Trigger`. */
|
|
61
|
+
export interface AccordionTriggerProps extends ComponentProps<'button'> {
|
|
62
|
+
/**
|
|
63
|
+
* Level of the heading that wraps the button, to fit the page outline.
|
|
64
|
+
* @default 3
|
|
65
|
+
*/
|
|
66
|
+
level?: 1 | 2 | 3 | 4 | 5 | 6;
|
|
67
|
+
}
|
|
68
|
+
declare function AccordionTrigger({ level, className, onClick, children, ...props }: AccordionTriggerProps): import("react").JSX.Element;
|
|
69
|
+
/** Props for `Accordion.Content`. */
|
|
70
|
+
export type AccordionContentProps = ComponentProps<'div'>;
|
|
71
|
+
declare function AccordionContent({ className, children, ...props }: AccordionContentProps): import("react").JSX.Element;
|
|
72
|
+
/**
|
|
73
|
+
* Stacked sections that expand and collapse. Each trigger is a button inside a heading;
|
|
74
|
+
* Up and Down move between triggers, Home and End jump to the ends. The panel height animates
|
|
75
|
+
* with the `motion` tokens, and snaps when reduced motion is preferred.
|
|
76
|
+
*
|
|
77
|
+
* @example
|
|
78
|
+
* ```tsx
|
|
79
|
+
* <Accordion type="single" defaultValue="shipping">
|
|
80
|
+
* <Accordion.Item value="shipping">
|
|
81
|
+
* <Accordion.Trigger>Shipping</Accordion.Trigger>
|
|
82
|
+
* <Accordion.Content>Orders ship within two working days.</Accordion.Content>
|
|
83
|
+
* </Accordion.Item>
|
|
84
|
+
* <Accordion.Item value="returns">
|
|
85
|
+
* <Accordion.Trigger>Returns</Accordion.Trigger>
|
|
86
|
+
* <Accordion.Content>Free returns within 30 days.</Accordion.Content>
|
|
87
|
+
* </Accordion.Item>
|
|
88
|
+
* </Accordion>
|
|
89
|
+
* ```
|
|
90
|
+
*/
|
|
91
|
+
export declare const Accordion: typeof AccordionRoot & {
|
|
92
|
+
Item: typeof AccordionItem;
|
|
93
|
+
Trigger: typeof AccordionTrigger;
|
|
94
|
+
Content: typeof AccordionContent;
|
|
95
|
+
};
|
|
96
|
+
export {};
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { useDefaults } from "../runtime.js";
|
|
2
|
+
import { colorClass, cx, radiusClass, sizeClass } from "../classes.js";
|
|
3
|
+
import { useControllable } from "../hooks.js";
|
|
4
|
+
import { ChevronIcon } from "../floating.js";
|
|
5
|
+
import { createContext, useContext, useId } from "react";
|
|
6
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
//#region src/components/Accordion.tsx
|
|
8
|
+
var AccordionContext = createContext(null);
|
|
9
|
+
var AccordionItemContext = createContext(null);
|
|
10
|
+
function useAccordionContext(component) {
|
|
11
|
+
const context = useContext(AccordionContext);
|
|
12
|
+
if (!context) throw new Error(`yarcl: <${component}> must be inside <Accordion>`);
|
|
13
|
+
return context;
|
|
14
|
+
}
|
|
15
|
+
function useItemContext(component) {
|
|
16
|
+
const context = useContext(AccordionItemContext);
|
|
17
|
+
if (!context) throw new Error(`yarcl: <${component}> must be inside <Accordion.Item>`);
|
|
18
|
+
return context;
|
|
19
|
+
}
|
|
20
|
+
var toArray = (value) => value == null ? [] : Array.isArray(value) ? value : [value];
|
|
21
|
+
function AccordionRoot(props) {
|
|
22
|
+
const own = useDefaults("Accordion");
|
|
23
|
+
const { type, value, defaultValue, onValueChange, collapsible = true, size, radius, color, disabled, className, onKeyDown, ...rest } = props;
|
|
24
|
+
const [open, setOpen] = useControllable(value === void 0 ? void 0 : toArray(value), toArray(defaultValue), (next) => type === "multiple" ? onValueChange?.(next) : onValueChange?.(next[0] ?? null));
|
|
25
|
+
const baseId = useId();
|
|
26
|
+
const idFor = (kind, v) => `${baseId}-${kind}-${v.replace(/[^\w-]/g, "_")}`;
|
|
27
|
+
function toggle(item) {
|
|
28
|
+
const on = open.includes(item);
|
|
29
|
+
if (type === "multiple") setOpen(on ? open.filter((v) => v !== item) : [...open, item]);
|
|
30
|
+
else if (!on) setOpen([item]);
|
|
31
|
+
else if (collapsible) setOpen([]);
|
|
32
|
+
}
|
|
33
|
+
function handleKeyDown(event) {
|
|
34
|
+
onKeyDown?.(event);
|
|
35
|
+
const root = event.currentTarget;
|
|
36
|
+
const triggers = [...root.querySelectorAll(".yarcl-accordion-trigger:not(:disabled)")].filter((trigger) => trigger.closest(".yarcl-accordion") === root);
|
|
37
|
+
const current = triggers.indexOf(document.activeElement);
|
|
38
|
+
if (current === -1) return;
|
|
39
|
+
const next = {
|
|
40
|
+
ArrowDown: (current + 1) % triggers.length,
|
|
41
|
+
ArrowUp: (current - 1 + triggers.length) % triggers.length,
|
|
42
|
+
Home: 0,
|
|
43
|
+
End: triggers.length - 1
|
|
44
|
+
}[event.key];
|
|
45
|
+
if (next === void 0) return;
|
|
46
|
+
event.preventDefault();
|
|
47
|
+
triggers[next].focus();
|
|
48
|
+
}
|
|
49
|
+
const resolvedSize = size ?? own.size;
|
|
50
|
+
return /* @__PURE__ */ jsx(AccordionContext.Provider, {
|
|
51
|
+
value: {
|
|
52
|
+
open,
|
|
53
|
+
toggle,
|
|
54
|
+
disabled,
|
|
55
|
+
idFor
|
|
56
|
+
},
|
|
57
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
58
|
+
className: cx("yarcl-accordion", sizeClass(resolvedSize, "Accordion"), radiusClass(radius ?? own.radius, resolvedSize), colorClass(color ?? own.color), className),
|
|
59
|
+
onKeyDown: handleKeyDown,
|
|
60
|
+
...rest
|
|
61
|
+
})
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
function AccordionItem({ value, disabled, className, ...props }) {
|
|
65
|
+
const context = useAccordionContext("Accordion.Item");
|
|
66
|
+
const open = context.open.includes(value);
|
|
67
|
+
const itemDisabled = disabled || context.disabled;
|
|
68
|
+
return /* @__PURE__ */ jsx(AccordionItemContext.Provider, {
|
|
69
|
+
value: {
|
|
70
|
+
value,
|
|
71
|
+
open,
|
|
72
|
+
disabled: itemDisabled
|
|
73
|
+
},
|
|
74
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
75
|
+
"data-state": open ? "open" : "closed",
|
|
76
|
+
"data-disabled": itemDisabled || void 0,
|
|
77
|
+
className: cx("yarcl-accordion-item", className),
|
|
78
|
+
...props
|
|
79
|
+
})
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
function AccordionTrigger({ level = 3, className, onClick, children, ...props }) {
|
|
83
|
+
const context = useAccordionContext("Accordion.Trigger");
|
|
84
|
+
const item = useItemContext("Accordion.Trigger");
|
|
85
|
+
const Heading = `h${level}`;
|
|
86
|
+
return /* @__PURE__ */ jsx(Heading, {
|
|
87
|
+
className: "yarcl-accordion-heading",
|
|
88
|
+
children: /* @__PURE__ */ jsxs("button", {
|
|
89
|
+
type: "button",
|
|
90
|
+
id: context.idFor("trigger", item.value),
|
|
91
|
+
"aria-controls": context.idFor("content", item.value),
|
|
92
|
+
"aria-expanded": item.open,
|
|
93
|
+
disabled: item.disabled,
|
|
94
|
+
className: cx("yarcl-accordion-trigger", className),
|
|
95
|
+
onClick: (event) => {
|
|
96
|
+
onClick?.(event);
|
|
97
|
+
if (!event.defaultPrevented) context.toggle(item.value);
|
|
98
|
+
},
|
|
99
|
+
...props,
|
|
100
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
101
|
+
className: "yarcl-accordion-label",
|
|
102
|
+
children
|
|
103
|
+
}), /* @__PURE__ */ jsx(ChevronIcon, {})]
|
|
104
|
+
})
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
function AccordionContent({ className, children, ...props }) {
|
|
108
|
+
const context = useAccordionContext("Accordion.Content");
|
|
109
|
+
const item = useItemContext("Accordion.Content");
|
|
110
|
+
return /* @__PURE__ */ jsx("div", {
|
|
111
|
+
role: "region",
|
|
112
|
+
id: context.idFor("content", item.value),
|
|
113
|
+
"aria-labelledby": context.idFor("trigger", item.value),
|
|
114
|
+
"data-state": item.open ? "open" : "closed",
|
|
115
|
+
className: cx("yarcl-accordion-content", className),
|
|
116
|
+
...props,
|
|
117
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
118
|
+
className: "yarcl-accordion-body",
|
|
119
|
+
children
|
|
120
|
+
})
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Stacked sections that expand and collapse. Each trigger is a button inside a heading;
|
|
125
|
+
* Up and Down move between triggers, Home and End jump to the ends. The panel height animates
|
|
126
|
+
* with the `motion` tokens, and snaps when reduced motion is preferred.
|
|
127
|
+
*
|
|
128
|
+
* @example
|
|
129
|
+
* ```tsx
|
|
130
|
+
* <Accordion type="single" defaultValue="shipping">
|
|
131
|
+
* <Accordion.Item value="shipping">
|
|
132
|
+
* <Accordion.Trigger>Shipping</Accordion.Trigger>
|
|
133
|
+
* <Accordion.Content>Orders ship within two working days.</Accordion.Content>
|
|
134
|
+
* </Accordion.Item>
|
|
135
|
+
* <Accordion.Item value="returns">
|
|
136
|
+
* <Accordion.Trigger>Returns</Accordion.Trigger>
|
|
137
|
+
* <Accordion.Content>Free returns within 30 days.</Accordion.Content>
|
|
138
|
+
* </Accordion.Item>
|
|
139
|
+
* </Accordion>
|
|
140
|
+
* ```
|
|
141
|
+
*/
|
|
142
|
+
var Accordion = Object.assign(AccordionRoot, {
|
|
143
|
+
Item: AccordionItem,
|
|
144
|
+
Trigger: AccordionTrigger,
|
|
145
|
+
Content: AccordionContent
|
|
146
|
+
});
|
|
147
|
+
//#endregion
|
|
148
|
+
export { Accordion };
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { ComponentProps, ReactNode } from 'react';
|
|
2
|
+
import type { Color, Radius, Spacing, TextStyle, Variant } from '../types';
|
|
3
|
+
/** Props for {@link Alert}. */
|
|
4
|
+
export interface AlertProps extends Omit<ComponentProps<'div'>, 'color' | 'title'> {
|
|
5
|
+
/** Bold first line. */
|
|
6
|
+
title?: ReactNode;
|
|
7
|
+
/** Icon shown before the text. */
|
|
8
|
+
icon?: ReactNode;
|
|
9
|
+
/** Actions shown after the text, e.g. a {@link Button} or {@link Link}. */
|
|
10
|
+
action?: ReactNode;
|
|
11
|
+
/**
|
|
12
|
+
* Semantic color, from the `colors` config.
|
|
13
|
+
* @default config.defaults.color
|
|
14
|
+
*/
|
|
15
|
+
color?: Color;
|
|
16
|
+
/**
|
|
17
|
+
* Style recipe, from the `variants` config.
|
|
18
|
+
* @default config.defaults.softVariant
|
|
19
|
+
*/
|
|
20
|
+
variant?: Variant;
|
|
21
|
+
/**
|
|
22
|
+
* Corner radius, from the `radii` config.
|
|
23
|
+
* @default config.defaults.radius
|
|
24
|
+
*/
|
|
25
|
+
radius?: Radius;
|
|
26
|
+
/**
|
|
27
|
+
* Space between the icon, text, action and dismiss button, from the `spacing` config.
|
|
28
|
+
* @default config.components.Alert.gap ?? config.defaults.gap
|
|
29
|
+
*/
|
|
30
|
+
gap?: Spacing;
|
|
31
|
+
/**
|
|
32
|
+
* Inner spacing, from the `spacing` config.
|
|
33
|
+
* @default config.components.Alert.padding ?? config.defaults.padding
|
|
34
|
+
*/
|
|
35
|
+
padding?: Spacing;
|
|
36
|
+
/**
|
|
37
|
+
* Typography style, from the `typography.styles` config.
|
|
38
|
+
* @default config.components.Alert.textStyle ?? config.defaults.labelStyle
|
|
39
|
+
*/
|
|
40
|
+
textStyle?: TextStyle;
|
|
41
|
+
/** Shows a dismiss button. Called when it is pressed; hide the alert in response. */
|
|
42
|
+
onDismiss?: () => void;
|
|
43
|
+
/**
|
|
44
|
+
* Announces the alert when it appears: `'polite'` (`role="status"`) or `'assertive'` (`role="alert"`).
|
|
45
|
+
* Leave unset for messages present on page load.
|
|
46
|
+
*/
|
|
47
|
+
live?: 'polite' | 'assertive';
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* An inline message that stays on the page, e.g. a warning above a form.
|
|
51
|
+
* For transient messages use {@link toast}.
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```tsx
|
|
55
|
+
* <Alert color="warning" title="Trial ends in 3 days" action={<Button size="sm">Upgrade</Button>}>
|
|
56
|
+
* Add a payment method to keep your projects.
|
|
57
|
+
* </Alert>
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
export declare function Alert({ title, icon, action, color, variant, radius, gap, padding, textStyle, onDismiss, live, className, children, ...props }: AlertProps): import("react").JSX.Element;
|