@vsreact/core 0.0.1 → 0.0.3
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/dist/animation.d.ts +38 -0
- package/dist/animation.js +90 -0
- package/dist/bridge.d.ts +7 -0
- package/dist/bridge.js +49 -0
- package/dist/controls.d.ts +126 -0
- package/dist/controls.js +130 -0
- package/dist/cx.d.ts +6 -0
- package/dist/cx.js +26 -0
- package/dist/hooks.d.ts +8 -0
- package/dist/hooks.js +15 -0
- package/dist/hostConfig.d.ts +44 -0
- package/dist/hostConfig.js +118 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.js +13 -0
- package/dist/native.d.ts +6 -0
- package/dist/native.js +16 -0
- package/dist/parameters.d.ts +12 -0
- package/dist/parameters.js +33 -0
- package/dist/primitives.d.ts +70 -0
- package/dist/primitives.js +20 -0
- package/dist/render.d.ts +5 -0
- package/dist/render.js +22 -0
- package/dist/runtime.d.ts +10 -0
- package/dist/runtime.js +68 -0
- package/dist/theme.d.ts +5 -0
- package/dist/theme.js +156 -0
- package/dist/tw.d.ts +13 -0
- package/dist/tw.js +264 -0
- package/package.json +31 -4
- package/src/animation.test.tsx +56 -1
- package/src/animation.ts +71 -0
- package/src/controls.test.tsx +131 -0
- package/src/controls.tsx +352 -19
- package/src/cx.ts +33 -0
- package/src/hooks.ts +18 -0
- package/src/index.ts +50 -24
- package/src/runtime.ts +4 -1
- package/src/theme.ts +76 -1
- package/src/tw.test.ts +26 -0
- package/src/tw.ts +4 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import "./runtime";
|
|
2
|
+
import "./bridge";
|
|
3
|
+
export { View, Text, Image, TextInput, NativeView } from "./primitives";
|
|
4
|
+
export type { CommonProps, TextProps, ImageProps, TextInputProps, NativeViewProps, } from "./primitives";
|
|
5
|
+
export { render, unmount } from "./render";
|
|
6
|
+
export { native } from "./native";
|
|
7
|
+
export { useNativeEvent } from "./hooks";
|
|
8
|
+
export { configureTheme, tw } from "./tw";
|
|
9
|
+
export type { Style, ResolvedClasses } from "./tw";
|
|
10
|
+
export { cx } from "./cx";
|
|
11
|
+
export type { ClassValue } from "./cx";
|
|
12
|
+
export { useTween, useSpring, springStep, lerp, Easing } from "./animation";
|
|
13
|
+
export type { TweenOptions, SpringOptions, EasingFn } from "./animation";
|
|
14
|
+
export { useParameter } from "./parameters";
|
|
15
|
+
export type { ParameterState, ParameterHandle } from "./parameters";
|
|
16
|
+
export { Knob, Slider, Toggle, XYPad, Segmented, ParamKnob, ParamSlider, ParamToggle, ParamXYPad, ParamSegmented, dragToValue, } from "./controls";
|
|
17
|
+
export type { KnobProps, SliderProps, ToggleProps, XYPadProps, SegmentedProps, ParamKnobProps, ParamSliderProps, ParamToggleProps, ParamXYPadProps, ParamSegmentedProps, } from "./controls";
|
|
18
|
+
export type { DragEventPayload } from "./primitives";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// @vsreact/core public API. runtime must load first — it installs the
|
|
2
|
+
// timer/console/microtask shims react depends on inside QuickJS.
|
|
3
|
+
import "./runtime";
|
|
4
|
+
import "./bridge";
|
|
5
|
+
export { View, Text, Image, TextInput, NativeView } from "./primitives";
|
|
6
|
+
export { render, unmount } from "./render";
|
|
7
|
+
export { native } from "./native";
|
|
8
|
+
export { useNativeEvent } from "./hooks";
|
|
9
|
+
export { configureTheme, tw } from "./tw";
|
|
10
|
+
export { cx } from "./cx";
|
|
11
|
+
export { useTween, useSpring, springStep, lerp, Easing } from "./animation";
|
|
12
|
+
export { useParameter } from "./parameters";
|
|
13
|
+
export { Knob, Slider, Toggle, XYPad, Segmented, ParamKnob, ParamSlider, ParamToggle, ParamXYPad, ParamSegmented, dragToValue, } from "./controls";
|
package/dist/native.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare const native: {
|
|
2
|
+
/** Synchronously invokes a C++ handler registered in RootOptions.onNativeCall. */
|
|
3
|
+
call(name: string, args?: unknown): any;
|
|
4
|
+
/** Subscribes to events pushed from C++ via RootView::sendNativeEvent. */
|
|
5
|
+
on(name: string, cb: (payload: any) => void): () => void;
|
|
6
|
+
};
|
package/dist/native.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// App-level messaging with the C++ host.
|
|
2
|
+
import { addNativeListener } from "./bridge";
|
|
3
|
+
export const native = {
|
|
4
|
+
/** Synchronously invokes a C++ handler registered in RootOptions.onNativeCall. */
|
|
5
|
+
call(name, args) {
|
|
6
|
+
const fn = globalThis.__vsreact_nativeCall;
|
|
7
|
+
if (typeof fn !== "function")
|
|
8
|
+
return undefined;
|
|
9
|
+
const json = fn(name, JSON.stringify(args ?? null));
|
|
10
|
+
return json ? JSON.parse(json) : undefined;
|
|
11
|
+
},
|
|
12
|
+
/** Subscribes to events pushed from C++ via RootView::sendNativeEvent. */
|
|
13
|
+
on(name, cb) {
|
|
14
|
+
return addNativeListener(name, cb);
|
|
15
|
+
},
|
|
16
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface ParameterState {
|
|
2
|
+
value: number;
|
|
3
|
+
text: string;
|
|
4
|
+
name: string;
|
|
5
|
+
label: string;
|
|
6
|
+
}
|
|
7
|
+
export interface ParameterHandle extends ParameterState {
|
|
8
|
+
set: (normalized: number) => void;
|
|
9
|
+
begin: () => void;
|
|
10
|
+
end: () => void;
|
|
11
|
+
}
|
|
12
|
+
export declare function useParameter(id: string): ParameterHandle;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// useParameter — two-way binding to a juce::AudioProcessorValueTreeState
|
|
2
|
+
// parameter through vsreact::ParameterBridge. Values are normalized 0..1.
|
|
3
|
+
import { useCallback, useEffect, useState } from "react";
|
|
4
|
+
import { native } from "./native";
|
|
5
|
+
export function useParameter(id) {
|
|
6
|
+
const [state, setState] = useState(() => {
|
|
7
|
+
const initial = native.call("param:get", { id });
|
|
8
|
+
return initial && typeof initial.value === "number"
|
|
9
|
+
? {
|
|
10
|
+
value: initial.value,
|
|
11
|
+
text: String(initial.text ?? ""),
|
|
12
|
+
name: String(initial.name ?? id),
|
|
13
|
+
label: String(initial.label ?? ""),
|
|
14
|
+
}
|
|
15
|
+
: { value: 0, text: "", name: id, label: "" };
|
|
16
|
+
});
|
|
17
|
+
useEffect(() => native.on("param", (p) => {
|
|
18
|
+
if (p?.id === id)
|
|
19
|
+
setState((s) => ({ ...s, value: Number(p.value), text: String(p.text ?? "") }));
|
|
20
|
+
}), [id]);
|
|
21
|
+
const set = useCallback((normalized) => {
|
|
22
|
+
const value = Math.min(1, Math.max(0, normalized));
|
|
23
|
+
setState((s) => ({ ...s, value }));
|
|
24
|
+
native.call("param:set", { id, value });
|
|
25
|
+
}, [id]);
|
|
26
|
+
const begin = useCallback(() => {
|
|
27
|
+
native.call("param:begin", { id });
|
|
28
|
+
}, [id]);
|
|
29
|
+
const end = useCallback(() => {
|
|
30
|
+
native.call("param:end", { id });
|
|
31
|
+
}, [id]);
|
|
32
|
+
return { ...state, set, begin, end };
|
|
33
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
import type { Style } from "./tw";
|
|
3
|
+
export interface DragEventPayload {
|
|
4
|
+
/** Delta from the drag start, in root coordinates. */
|
|
5
|
+
dx: number;
|
|
6
|
+
dy: number;
|
|
7
|
+
/** Current pointer position in root coordinates. */
|
|
8
|
+
x: number;
|
|
9
|
+
y: number;
|
|
10
|
+
}
|
|
11
|
+
export interface CommonProps {
|
|
12
|
+
className?: string;
|
|
13
|
+
style?: Style;
|
|
14
|
+
children?: ReactNode;
|
|
15
|
+
/** Resets the scroll offset of an overflow-y-scroll container. */
|
|
16
|
+
scrollTop?: number;
|
|
17
|
+
onClick?: () => void;
|
|
18
|
+
onMouseEnter?: () => void;
|
|
19
|
+
onMouseLeave?: () => void;
|
|
20
|
+
onMouseDown?: () => void;
|
|
21
|
+
onMouseUp?: () => void;
|
|
22
|
+
onDragStart?: (e: DragEventPayload) => void;
|
|
23
|
+
onDrag?: (e: DragEventPayload) => void;
|
|
24
|
+
onDragEnd?: (e: DragEventPayload) => void;
|
|
25
|
+
}
|
|
26
|
+
export declare function View(props: CommonProps): import("react").ReactElement<CommonProps, string | import("react").JSXElementConstructor<any>>;
|
|
27
|
+
export interface TextProps extends Omit<CommonProps, "children"> {
|
|
28
|
+
children?: ReactNode;
|
|
29
|
+
}
|
|
30
|
+
export declare function Text(props: TextProps): import("react").ReactElement<TextProps, string | import("react").JSXElementConstructor<any>>;
|
|
31
|
+
export interface ImageProps extends CommonProps {
|
|
32
|
+
src: string;
|
|
33
|
+
}
|
|
34
|
+
export declare function Image(props: ImageProps): import("react").ReactElement<ImageProps, string | import("react").JSXElementConstructor<any>>;
|
|
35
|
+
export interface TextInputProps extends Omit<CommonProps, "children" | "onChange" | "onSubmit"> {
|
|
36
|
+
value?: string;
|
|
37
|
+
defaultValue?: string;
|
|
38
|
+
placeholder?: string;
|
|
39
|
+
disabled?: boolean;
|
|
40
|
+
onChange?: (value: string) => void;
|
|
41
|
+
onSubmit?: (value: string) => void;
|
|
42
|
+
onFocus?: () => void;
|
|
43
|
+
onBlur?: () => void;
|
|
44
|
+
}
|
|
45
|
+
export declare function TextInput({ onChange, onSubmit, ...rest }: TextInputProps): import("react").ReactElement<{
|
|
46
|
+
onChange: ((payload: any) => void) | undefined;
|
|
47
|
+
onSubmit: ((payload: any) => void) | undefined;
|
|
48
|
+
value?: string;
|
|
49
|
+
defaultValue?: string;
|
|
50
|
+
placeholder?: string;
|
|
51
|
+
disabled?: boolean;
|
|
52
|
+
onFocus?: () => void;
|
|
53
|
+
onBlur?: () => void;
|
|
54
|
+
style?: Style | undefined;
|
|
55
|
+
className?: string | undefined;
|
|
56
|
+
scrollTop?: number | undefined;
|
|
57
|
+
onClick?: (() => void) | undefined;
|
|
58
|
+
onMouseEnter?: (() => void) | undefined;
|
|
59
|
+
onMouseLeave?: (() => void) | undefined;
|
|
60
|
+
onMouseDown?: (() => void) | undefined;
|
|
61
|
+
onMouseUp?: (() => void) | undefined;
|
|
62
|
+
onDragStart?: ((e: DragEventPayload) => void) | undefined;
|
|
63
|
+
onDrag?: ((e: DragEventPayload) => void) | undefined;
|
|
64
|
+
onDragEnd?: ((e: DragEventPayload) => void) | undefined;
|
|
65
|
+
}, string | import("react").JSXElementConstructor<any>>;
|
|
66
|
+
export interface NativeViewProps extends CommonProps {
|
|
67
|
+
/** Id of a component factory registered in the C++ NativeRegistry. */
|
|
68
|
+
nativeId: string;
|
|
69
|
+
}
|
|
70
|
+
export declare function NativeView(props: NativeViewProps): import("react").ReactElement<NativeViewProps, string | import("react").JSXElementConstructor<any>>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { createElement } from "react";
|
|
2
|
+
export function View(props) {
|
|
3
|
+
return createElement("vs-view", props);
|
|
4
|
+
}
|
|
5
|
+
export function Text(props) {
|
|
6
|
+
return createElement("vs-text", props);
|
|
7
|
+
}
|
|
8
|
+
export function Image(props) {
|
|
9
|
+
return createElement("vs-image", props);
|
|
10
|
+
}
|
|
11
|
+
export function TextInput({ onChange, onSubmit, ...rest }) {
|
|
12
|
+
return createElement("vs-textinput", {
|
|
13
|
+
...rest,
|
|
14
|
+
onChange: onChange ? (payload) => onChange(String(payload?.value ?? "")) : undefined,
|
|
15
|
+
onSubmit: onSubmit ? (payload) => onSubmit(String(payload?.value ?? "")) : undefined,
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
export function NativeView(props) {
|
|
19
|
+
return createElement("vs-native", props);
|
|
20
|
+
}
|
package/dist/render.d.ts
ADDED
package/dist/render.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import Reconciler from "react-reconciler";
|
|
2
|
+
import { LegacyRoot } from "react-reconciler/constants";
|
|
3
|
+
import { hostConfig } from "./hostConfig";
|
|
4
|
+
import { flushOps } from "./bridge";
|
|
5
|
+
const reconciler = Reconciler(hostConfig);
|
|
6
|
+
let container = null;
|
|
7
|
+
/** Mounts (or re-renders) the app into the plugin window. */
|
|
8
|
+
export function render(element) {
|
|
9
|
+
if (!container) {
|
|
10
|
+
container = reconciler.createContainer({}, LegacyRoot, null, false, null, "vsreact", (error) => console.error("[vsreact] recoverable error:", error), null);
|
|
11
|
+
}
|
|
12
|
+
reconciler.updateContainer(element, container, null, null);
|
|
13
|
+
flushOps();
|
|
14
|
+
}
|
|
15
|
+
/** Unmounts the current app (used by hot reload teardown). */
|
|
16
|
+
export function unmount() {
|
|
17
|
+
if (container) {
|
|
18
|
+
reconciler.updateContainer(null, container, null, null);
|
|
19
|
+
flushOps();
|
|
20
|
+
container = null;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export type NativeFns = {
|
|
2
|
+
__vsreact_flush(json: string): void;
|
|
3
|
+
__vsreact_nativeCall(name: string, argsJson: string): string;
|
|
4
|
+
__vsreact_log(level: string, msg: string): void;
|
|
5
|
+
__vsreact_setTimer(id: number, ms: number): void;
|
|
6
|
+
__vsreact_clearTimer(id: number): void;
|
|
7
|
+
};
|
|
8
|
+
export declare const isHosted: boolean;
|
|
9
|
+
/** Called by bridge.ts when C++ dispatches {kind:"timer",id}. */
|
|
10
|
+
export declare function fireTimer(id: number): void;
|
package/dist/runtime.js
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
// Environment shims for QuickJS. This module MUST be imported before react —
|
|
2
|
+
// it provides the timer/console/microtask facilities react and the scheduler
|
|
3
|
+
// expect. The __vsreact_* natives are registered by the C++ host; when absent
|
|
4
|
+
// (e.g. under `bun test`) the shims fall back to the platform implementations.
|
|
5
|
+
const g = globalThis;
|
|
6
|
+
export const isHosted = typeof g.__vsreact_setTimer === "function";
|
|
7
|
+
let nextTimerId = 1;
|
|
8
|
+
const timers = new Map();
|
|
9
|
+
/** Called by bridge.ts when C++ dispatches {kind:"timer",id}. */
|
|
10
|
+
export function fireTimer(id) {
|
|
11
|
+
const entry = timers.get(id);
|
|
12
|
+
if (!entry)
|
|
13
|
+
return;
|
|
14
|
+
if (entry.intervalMs !== undefined)
|
|
15
|
+
g.__vsreact_setTimer(id, entry.intervalMs);
|
|
16
|
+
else
|
|
17
|
+
timers.delete(id);
|
|
18
|
+
entry.cb(...entry.args);
|
|
19
|
+
}
|
|
20
|
+
function stringify(value) {
|
|
21
|
+
if (typeof value === "string")
|
|
22
|
+
return value;
|
|
23
|
+
if (value instanceof Error)
|
|
24
|
+
return `${value.message}\n${value.stack ?? ""}`;
|
|
25
|
+
try {
|
|
26
|
+
return JSON.stringify(value) ?? String(value);
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
return String(value);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
if (isHosted) {
|
|
33
|
+
g.setTimeout = ((cb, ms = 0, ...args) => {
|
|
34
|
+
const id = nextTimerId++;
|
|
35
|
+
timers.set(id, { cb, args });
|
|
36
|
+
g.__vsreact_setTimer(id, Math.max(0, ms | 0));
|
|
37
|
+
return id;
|
|
38
|
+
});
|
|
39
|
+
g.setInterval = ((cb, ms = 0, ...args) => {
|
|
40
|
+
const id = nextTimerId++;
|
|
41
|
+
const intervalMs = Math.max(1, ms | 0);
|
|
42
|
+
timers.set(id, { cb, args, intervalMs });
|
|
43
|
+
g.__vsreact_setTimer(id, intervalMs);
|
|
44
|
+
return id;
|
|
45
|
+
});
|
|
46
|
+
g.clearTimeout = g.clearInterval = ((id) => {
|
|
47
|
+
if (id !== undefined && timers.delete(id))
|
|
48
|
+
g.__vsreact_clearTimer(id);
|
|
49
|
+
});
|
|
50
|
+
const makeLog = (level) => (...args) => g.__vsreact_log(level, args.map(stringify).join(" "));
|
|
51
|
+
g.console = {
|
|
52
|
+
log: makeLog("log"),
|
|
53
|
+
info: makeLog("info"),
|
|
54
|
+
debug: makeLog("debug"),
|
|
55
|
+
warn: makeLog("warn"),
|
|
56
|
+
error: makeLog("error"),
|
|
57
|
+
};
|
|
58
|
+
g.queueMicrotask ??= (cb) => {
|
|
59
|
+
Promise.resolve().then(cb);
|
|
60
|
+
};
|
|
61
|
+
g.performance ??= { now: () => Date.now() };
|
|
62
|
+
// Typed loosely on purpose: the dist build has no Node/Bun types, and the
|
|
63
|
+
// shim only exists for libraries that probe NODE_ENV.
|
|
64
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
65
|
+
g.process ??= { env: { NODE_ENV: "production" } };
|
|
66
|
+
g.self ??= g;
|
|
67
|
+
g.global ??= g;
|
|
68
|
+
}
|
package/dist/theme.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export type ThemeColors = Record<string, string>;
|
|
2
|
+
export declare function setThemeColors(colors: ThemeColors): void;
|
|
3
|
+
/** Resolves a color name ("zinc-900", "white", "accent", "lime-400/20",
|
|
4
|
+
"[#c6f135]") to "#rrggbb"/"#rrggbbaa", or undefined if unknown. */
|
|
5
|
+
export declare function resolveColor(name: string): string | undefined;
|
package/dist/theme.js
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
// The full Tailwind v3 color palette.
|
|
2
|
+
const palettes = {
|
|
3
|
+
slate: {
|
|
4
|
+
"50": "#f8fafc", "100": "#f1f5f9", "200": "#e2e8f0", "300": "#cbd5e1",
|
|
5
|
+
"400": "#94a3b8", "500": "#64748b", "600": "#475569", "700": "#334155",
|
|
6
|
+
"800": "#1e293b", "900": "#0f172a", "950": "#020617",
|
|
7
|
+
},
|
|
8
|
+
gray: {
|
|
9
|
+
"50": "#f9fafb", "100": "#f3f4f6", "200": "#e5e7eb", "300": "#d1d5db",
|
|
10
|
+
"400": "#9ca3af", "500": "#6b7280", "600": "#4b5563", "700": "#374151",
|
|
11
|
+
"800": "#1f2937", "900": "#111827", "950": "#030712",
|
|
12
|
+
},
|
|
13
|
+
stone: {
|
|
14
|
+
"50": "#fafaf9", "100": "#f5f5f4", "200": "#e7e5e4", "300": "#d6d3d1",
|
|
15
|
+
"400": "#a8a29e", "500": "#78716c", "600": "#57534e", "700": "#44403c",
|
|
16
|
+
"800": "#292524", "900": "#1c1917", "950": "#0c0a09",
|
|
17
|
+
},
|
|
18
|
+
orange: {
|
|
19
|
+
"50": "#fff7ed", "100": "#ffedd5", "200": "#fed7aa", "300": "#fdba74",
|
|
20
|
+
"400": "#fb923c", "500": "#f97316", "600": "#ea580c", "700": "#c2410c",
|
|
21
|
+
"800": "#9a3412", "900": "#7c2d12", "950": "#431407",
|
|
22
|
+
},
|
|
23
|
+
yellow: {
|
|
24
|
+
"50": "#fefce8", "100": "#fef9c3", "200": "#fef08a", "300": "#fde047",
|
|
25
|
+
"400": "#facc15", "500": "#eab308", "600": "#ca8a04", "700": "#a16207",
|
|
26
|
+
"800": "#854d0e", "900": "#713f12", "950": "#422006",
|
|
27
|
+
},
|
|
28
|
+
green: {
|
|
29
|
+
"50": "#f0fdf4", "100": "#dcfce7", "200": "#bbf7d0", "300": "#86efac",
|
|
30
|
+
"400": "#4ade80", "500": "#22c55e", "600": "#16a34a", "700": "#15803d",
|
|
31
|
+
"800": "#166534", "900": "#14532d", "950": "#052e16",
|
|
32
|
+
},
|
|
33
|
+
teal: {
|
|
34
|
+
"50": "#f0fdfa", "100": "#ccfbf1", "200": "#99f6e4", "300": "#5eead4",
|
|
35
|
+
"400": "#2dd4bf", "500": "#14b8a6", "600": "#0d9488", "700": "#0f766e",
|
|
36
|
+
"800": "#115e59", "900": "#134e4a", "950": "#042f2e",
|
|
37
|
+
},
|
|
38
|
+
cyan: {
|
|
39
|
+
"50": "#ecfeff", "100": "#cffafe", "200": "#a5f3fc", "300": "#67e8f9",
|
|
40
|
+
"400": "#22d3ee", "500": "#06b6d4", "600": "#0891b2", "700": "#0e7490",
|
|
41
|
+
"800": "#155e75", "900": "#164e63", "950": "#083344",
|
|
42
|
+
},
|
|
43
|
+
blue: {
|
|
44
|
+
"50": "#eff6ff", "100": "#dbeafe", "200": "#bfdbfe", "300": "#93c5fd",
|
|
45
|
+
"400": "#60a5fa", "500": "#3b82f6", "600": "#2563eb", "700": "#1d4ed8",
|
|
46
|
+
"800": "#1e40af", "900": "#1e3a8a", "950": "#172554",
|
|
47
|
+
},
|
|
48
|
+
indigo: {
|
|
49
|
+
"50": "#eef2ff", "100": "#e0e7ff", "200": "#c7d2fe", "300": "#a5b4fc",
|
|
50
|
+
"400": "#818cf8", "500": "#6366f1", "600": "#4f46e5", "700": "#4338ca",
|
|
51
|
+
"800": "#3730a3", "900": "#312e81", "950": "#1e1b4b",
|
|
52
|
+
},
|
|
53
|
+
violet: {
|
|
54
|
+
"50": "#f5f3ff", "100": "#ede9fe", "200": "#ddd6fe", "300": "#c4b5fd",
|
|
55
|
+
"400": "#a78bfa", "500": "#8b5cf6", "600": "#7c3aed", "700": "#6d28d9",
|
|
56
|
+
"800": "#5b21b6", "900": "#4c1d95", "950": "#2e1065",
|
|
57
|
+
},
|
|
58
|
+
purple: {
|
|
59
|
+
"50": "#faf5ff", "100": "#f3e8ff", "200": "#e9d5ff", "300": "#d8b4fe",
|
|
60
|
+
"400": "#c084fc", "500": "#a855f7", "600": "#9333ea", "700": "#7e22ce",
|
|
61
|
+
"800": "#6b21a8", "900": "#581c87", "950": "#3b0764",
|
|
62
|
+
},
|
|
63
|
+
fuchsia: {
|
|
64
|
+
"50": "#fdf4ff", "100": "#fae8ff", "200": "#f5d0fe", "300": "#f0abfc",
|
|
65
|
+
"400": "#e879f9", "500": "#d946ef", "600": "#c026d3", "700": "#a21caf",
|
|
66
|
+
"800": "#86198f", "900": "#701a75", "950": "#4a044e",
|
|
67
|
+
},
|
|
68
|
+
pink: {
|
|
69
|
+
"50": "#fdf2f8", "100": "#fce7f3", "200": "#fbcfe8", "300": "#f9a8d4",
|
|
70
|
+
"400": "#f472b6", "500": "#ec4899", "600": "#db2777", "700": "#be185d",
|
|
71
|
+
"800": "#9d174d", "900": "#831843", "950": "#500724",
|
|
72
|
+
},
|
|
73
|
+
rose: {
|
|
74
|
+
"50": "#fff1f2", "100": "#ffe4e6", "200": "#fecdd3", "300": "#fda4af",
|
|
75
|
+
"400": "#fb7185", "500": "#f43f5e", "600": "#e11d48", "700": "#be123c",
|
|
76
|
+
"800": "#9f1239", "900": "#881337", "950": "#4c0519",
|
|
77
|
+
},
|
|
78
|
+
zinc: {
|
|
79
|
+
"50": "#fafafa", "100": "#f4f4f5", "200": "#e4e4e7", "300": "#d4d4d8",
|
|
80
|
+
"400": "#a1a1aa", "500": "#71717a", "600": "#52525b", "700": "#3f3f46",
|
|
81
|
+
"800": "#27272a", "900": "#18181b", "950": "#09090b",
|
|
82
|
+
},
|
|
83
|
+
neutral: {
|
|
84
|
+
"50": "#fafafa", "100": "#f5f5f5", "200": "#e5e5e5", "300": "#d4d4d4",
|
|
85
|
+
"400": "#a3a3a3", "500": "#737373", "600": "#525252", "700": "#404040",
|
|
86
|
+
"800": "#262626", "900": "#171717", "950": "#0a0a0a",
|
|
87
|
+
},
|
|
88
|
+
lime: {
|
|
89
|
+
"50": "#f7fee7", "100": "#ecfccb", "200": "#d9f99d", "300": "#bef264",
|
|
90
|
+
"400": "#a3e635", "500": "#84cc16", "600": "#65a30d", "700": "#4d7c0f",
|
|
91
|
+
"800": "#3f6212", "900": "#365314", "950": "#1a2e05",
|
|
92
|
+
},
|
|
93
|
+
red: {
|
|
94
|
+
"50": "#fef2f2", "100": "#fee2e2", "200": "#fecaca", "300": "#fca5a5",
|
|
95
|
+
"400": "#f87171", "500": "#ef4444", "600": "#dc2626", "700": "#b91c1c",
|
|
96
|
+
"800": "#991b1b", "900": "#7f1d1d", "950": "#450a0a",
|
|
97
|
+
},
|
|
98
|
+
amber: {
|
|
99
|
+
"50": "#fffbeb", "100": "#fef3c7", "200": "#fde68a", "300": "#fcd34d",
|
|
100
|
+
"400": "#fbbf24", "500": "#f59e0b", "600": "#d97706", "700": "#b45309",
|
|
101
|
+
"800": "#92400e", "900": "#78350f", "950": "#451a03",
|
|
102
|
+
},
|
|
103
|
+
emerald: {
|
|
104
|
+
"50": "#ecfdf5", "100": "#d1fae5", "200": "#a7f3d0", "300": "#6ee7b7",
|
|
105
|
+
"400": "#34d399", "500": "#10b981", "600": "#059669", "700": "#047857",
|
|
106
|
+
"800": "#065f46", "900": "#064e3b", "950": "#022c22",
|
|
107
|
+
},
|
|
108
|
+
sky: {
|
|
109
|
+
"50": "#f0f9ff", "100": "#e0f2fe", "200": "#bae6fd", "300": "#7dd3fc",
|
|
110
|
+
"400": "#38bdf8", "500": "#0ea5e9", "600": "#0284c7", "700": "#0369a1",
|
|
111
|
+
"800": "#075985", "900": "#0c4a6e", "950": "#082f49",
|
|
112
|
+
},
|
|
113
|
+
};
|
|
114
|
+
let themeColors = {};
|
|
115
|
+
export function setThemeColors(colors) {
|
|
116
|
+
themeColors = { ...themeColors };
|
|
117
|
+
for (const [name, value] of Object.entries(colors))
|
|
118
|
+
themeColors[name] = value.toLowerCase();
|
|
119
|
+
}
|
|
120
|
+
/** Resolves a color name ("zinc-900", "white", "accent", "lime-400/20",
|
|
121
|
+
"[#c6f135]") to "#rrggbb"/"#rrggbbaa", or undefined if unknown. */
|
|
122
|
+
export function resolveColor(name) {
|
|
123
|
+
let base = name;
|
|
124
|
+
let alpha;
|
|
125
|
+
const slash = name.lastIndexOf("/");
|
|
126
|
+
if (slash > 0) {
|
|
127
|
+
const pct = Number(name.slice(slash + 1));
|
|
128
|
+
if (Number.isFinite(pct)) {
|
|
129
|
+
base = name.slice(0, slash);
|
|
130
|
+
alpha = Math.round((pct / 100) * 255)
|
|
131
|
+
.toString(16)
|
|
132
|
+
.padStart(2, "0");
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
let hex;
|
|
136
|
+
if (base.startsWith("[#") && base.endsWith("]"))
|
|
137
|
+
hex = base.slice(1, -1).toLowerCase();
|
|
138
|
+
else if (base === "white")
|
|
139
|
+
hex = "#ffffff";
|
|
140
|
+
else if (base === "black")
|
|
141
|
+
hex = "#000000";
|
|
142
|
+
else if (base === "transparent")
|
|
143
|
+
hex = "#00000000";
|
|
144
|
+
else if (themeColors[base])
|
|
145
|
+
hex = themeColors[base];
|
|
146
|
+
else {
|
|
147
|
+
const dash = base.lastIndexOf("-");
|
|
148
|
+
if (dash > 0) {
|
|
149
|
+
const palette = palettes[base.slice(0, dash)];
|
|
150
|
+
hex = palette?.[base.slice(dash + 1)];
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
if (hex === undefined)
|
|
154
|
+
return undefined;
|
|
155
|
+
return alpha !== undefined && hex.length === 7 ? hex + alpha : hex;
|
|
156
|
+
}
|
package/dist/tw.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type ThemeColors } from "./theme";
|
|
2
|
+
export type StyleValue = string | number;
|
|
3
|
+
export type Style = Record<string, StyleValue>;
|
|
4
|
+
export interface ResolvedClasses {
|
|
5
|
+
style: Style;
|
|
6
|
+
hoverStyle?: Style;
|
|
7
|
+
activeStyle?: Style;
|
|
8
|
+
focusStyle?: Style;
|
|
9
|
+
}
|
|
10
|
+
export declare function configureTheme(theme: {
|
|
11
|
+
colors?: ThemeColors;
|
|
12
|
+
}): void;
|
|
13
|
+
export declare function tw(classes: string): ResolvedClasses;
|