cssints 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/LICENSE +21 -0
- package/README.md +178 -2
- package/dist/author-types-C1AhsnrT.d.mts +80 -0
- package/dist/check.d.mts +22 -0
- package/dist/check.mjs +37 -0
- package/dist/color-BYIxVLlS.mjs +29 -0
- package/dist/color-C8OzjAeg.mjs +2 -0
- package/dist/contrast-BUKVao74.mjs +83 -0
- package/dist/derived.d.mts +14 -0
- package/dist/derived.mjs +391 -0
- package/dist/errors-D4ZbcwRo.d.mts +32 -0
- package/dist/frame-BoBKjgBB.mjs +92 -0
- package/dist/frame.d.mts +72 -0
- package/dist/frame.mjs +2 -0
- package/dist/index.d.mts +34 -0
- package/dist/index.mjs +1132 -0
- package/dist/instrument-Bdtk2INz.mjs +172 -0
- package/dist/lib-2OEIfPAE.d.mts +9 -0
- package/dist/lowered-CeoXbm0P.mjs +28 -0
- package/dist/node-CdhAGmF3.d.mts +229 -0
- package/dist/parent-vars.d.mts +13 -0
- package/dist/parent-vars.mjs +65 -0
- package/dist/plugin-types.d.mts +377 -0
- package/dist/plugin.d.mts +3 -0
- package/dist/plugin.mjs +30 -0
- package/dist/registry-n9JCX4pl.mjs +72 -0
- package/dist/runtime-CTvuM-Hm.d.mts +5 -0
- package/dist/runtime.d.mts +18 -0
- package/dist/runtime.mjs +21 -0
- package/dist/scope-oWEaWE9n.d.mts +2095 -0
- package/dist/sheet-CO7a-mdA.mjs +756 -0
- package/dist/surface.d.mts +228 -0
- package/dist/surface.mjs +101 -0
- package/dist/theme-BGEbFAYh.mjs +906 -0
- package/dist/theme-types-DHdtTZhz.d.mts +1803 -0
- package/dist/trace-otlp-CbKFDsn9.mjs +14 -0
- package/dist/tui-types.d.mts +181 -0
- package/dist/tui.d.mts +30 -0
- package/dist/tui.mjs +399 -0
- package/dist/types.d.mts +2 -0
- package/dist/vite.d.mts +118 -0
- package/dist/vite.mjs +980 -0
- package/docs/API.md +1148 -0
- package/package.json +81 -4
- package/skills/cssints/SKILL.md +200 -0
- package/skills/cssints/references/errors.md +85 -0
- package/skills/cssints/references/plugins.md +91 -0
- package/skills/cssints/references/tokens.md +91 -0
- package/skills/cssints-plugin/SKILL.md +177 -0
- package/skills/cssints-plugin/references/table.md +124 -0
- package/skills/cssints-plugin/references/testing.md +122 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Layer, ManagedRuntime } from "effect";
|
|
2
|
+
import { FetchHttpClient } from "effect/http";
|
|
3
|
+
import { OtlpSerialization, OtlpTracer } from "effect/observability";
|
|
4
|
+
//#region src/trace-otlp.ts
|
|
5
|
+
const start = (url) => {
|
|
6
|
+
const runtime = ManagedRuntime.make(OtlpTracer.layer({
|
|
7
|
+
url: `${url}/v1/traces`,
|
|
8
|
+
resource: { serviceName: "cssints" },
|
|
9
|
+
exportInterval: "500 millis"
|
|
10
|
+
}).pipe(Layer.provide([OtlpSerialization.layerJson, FetchHttpClient.layer])));
|
|
11
|
+
return runtime.context().then(() => runtime);
|
|
12
|
+
};
|
|
13
|
+
//#endregion
|
|
14
|
+
export { start };
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { $p as Part, Xp as Check, d as createTokens, u as createGlobalTheme } from "./theme-types-DHdtTZhz.mjs";
|
|
2
|
+
//#region src/tui-types.d.ts
|
|
3
|
+
type Percent = `${number}%`;
|
|
4
|
+
/** A number of cells (columns across, rows down) or a percentage of the parent. */
|
|
5
|
+
export type Cells = number | Percent;
|
|
6
|
+
/** Cells, or `auto`. */
|
|
7
|
+
export type Size = Cells | "auto";
|
|
8
|
+
export type BorderKind = "single" | "double" | "rounded" | "heavy";
|
|
9
|
+
export type Align = "auto" | "flex-start" | "center" | "flex-end" | "stretch" | "baseline" | "space-between" | "space-around" | "space-evenly";
|
|
10
|
+
export type Justify = "flex-start" | "center" | "flex-end" | "space-between" | "space-around" | "space-evenly";
|
|
11
|
+
/** The CSS cursor keywords a terminal takes over OSC 22. */
|
|
12
|
+
export type Cursor = "auto" | "default" | "none" | "context-menu" | "help" | "pointer" | "progress" | "wait" | "cell" | "crosshair" | "text" | "vertical-text" | "alias" | "copy" | "move" | "no-drop" | "not-allowed" | "grab" | "grabbing" | "all-scroll" | "col-resize" | "row-resize" | "n-resize" | "e-resize" | "s-resize" | "w-resize" | "ne-resize" | "nw-resize" | "se-resize" | "sw-resize" | "ew-resize" | "ns-resize" | "nesw-resize" | "nwse-resize" | "zoom-in" | "zoom-out";
|
|
13
|
+
/** The props of a terminal style, renderer-neutral: colours are `#rrggbb` or `#rrggbbaa`, lengths are cells. */
|
|
14
|
+
export interface TuiProps {
|
|
15
|
+
color?: string;
|
|
16
|
+
backgroundColor?: string;
|
|
17
|
+
borderColor?: string;
|
|
18
|
+
caretColor?: string;
|
|
19
|
+
bold?: boolean;
|
|
20
|
+
dim?: boolean;
|
|
21
|
+
italic?: boolean;
|
|
22
|
+
underline?: boolean;
|
|
23
|
+
strikethrough?: boolean;
|
|
24
|
+
textAlign?: "left" | "center" | "right";
|
|
25
|
+
border?: boolean;
|
|
26
|
+
borderStyle?: BorderKind;
|
|
27
|
+
paddingTop?: Cells;
|
|
28
|
+
paddingRight?: Cells;
|
|
29
|
+
paddingBottom?: Cells;
|
|
30
|
+
paddingLeft?: Cells;
|
|
31
|
+
marginTop?: Size;
|
|
32
|
+
marginRight?: Size;
|
|
33
|
+
marginBottom?: Size;
|
|
34
|
+
marginLeft?: Size;
|
|
35
|
+
gap?: Cells;
|
|
36
|
+
rowGap?: Cells;
|
|
37
|
+
columnGap?: Cells;
|
|
38
|
+
width?: Size;
|
|
39
|
+
height?: Size;
|
|
40
|
+
minWidth?: Size;
|
|
41
|
+
maxWidth?: Size;
|
|
42
|
+
minHeight?: Size;
|
|
43
|
+
maxHeight?: Size;
|
|
44
|
+
flexBasis?: Size;
|
|
45
|
+
flexDirection?: "row" | "column" | "row-reverse" | "column-reverse";
|
|
46
|
+
flexWrap?: "nowrap" | "wrap" | "wrap-reverse";
|
|
47
|
+
justifyContent?: Justify;
|
|
48
|
+
alignItems?: Align;
|
|
49
|
+
alignSelf?: Align;
|
|
50
|
+
flexGrow?: number;
|
|
51
|
+
flexShrink?: number;
|
|
52
|
+
position?: "relative" | "absolute";
|
|
53
|
+
top?: Size;
|
|
54
|
+
right?: Size;
|
|
55
|
+
bottom?: Size;
|
|
56
|
+
left?: Size;
|
|
57
|
+
overflow?: "visible" | "hidden" | "scroll";
|
|
58
|
+
visible?: boolean;
|
|
59
|
+
opacity?: number;
|
|
60
|
+
zIndex?: number;
|
|
61
|
+
cursor?: Cursor;
|
|
62
|
+
caretShape?: "auto" | "bar" | "block" | "underscore";
|
|
63
|
+
caretAnimation?: "auto" | "manual";
|
|
64
|
+
}
|
|
65
|
+
/** Props with their state overlays. */
|
|
66
|
+
export interface TuiLayer extends TuiProps {
|
|
67
|
+
":hover"?: TuiProps;
|
|
68
|
+
":focus"?: TuiProps;
|
|
69
|
+
":active"?: TuiProps;
|
|
70
|
+
}
|
|
71
|
+
type ColourKey = "color" | "backgroundColor" | "borderColor" | "caretColor";
|
|
72
|
+
/** The token (`color-bg` for `var(--color-bg)`) of each colour prop set to one, per state: what a run-time theme sets. */
|
|
73
|
+
export interface TuiVars extends Partial<Record<ColourKey, string>> {
|
|
74
|
+
":hover"?: Partial<Record<ColourKey, string>>;
|
|
75
|
+
":focus"?: Partial<Record<ColourKey, string>>;
|
|
76
|
+
":active"?: Partial<Record<ColourKey, string>>;
|
|
77
|
+
}
|
|
78
|
+
/** What a terminal style compiles to: its props, state overlays, what each theme (by name) changes, its tokens. */
|
|
79
|
+
export interface TuiShape extends TuiLayer {
|
|
80
|
+
themes?: Record<string, TuiLayer>;
|
|
81
|
+
vars?: TuiVars;
|
|
82
|
+
}
|
|
83
|
+
/** What every member of cssints/tui returns. Only members make one (`cn()` takes no object literal). */
|
|
84
|
+
export type TuiStyle = TuiShape & {
|
|
85
|
+
readonly "~tui": true;
|
|
86
|
+
};
|
|
87
|
+
/** A colour: parts are checked against the web's `color` grammar; a colour token fits. */
|
|
88
|
+
export type Colour = <const A extends readonly Part[]>(...parts: Check<"color", A>) => TuiStyle;
|
|
89
|
+
type One<V> = (value: V) => TuiStyle;
|
|
90
|
+
/** 1 to 4 values: top, right, bottom, left, as in CSS. */
|
|
91
|
+
type Sides<V> = (...values: [V] | [V, V] | [V, V, V] | [V, V, V, V]) => TuiStyle;
|
|
92
|
+
/** 1 or 2 values: the start and end of the inline or block axis. */
|
|
93
|
+
type Pair<V> = (...values: [V] | [V, V]) => TuiStyle;
|
|
94
|
+
export declare const color: Colour;
|
|
95
|
+
export declare const backgroundColor: Colour;
|
|
96
|
+
/** `background-color`. */
|
|
97
|
+
export declare const bg: Colour;
|
|
98
|
+
export declare const borderColor: Colour;
|
|
99
|
+
export declare const caretColor: Colour;
|
|
100
|
+
/** `bold`, `normal`, or `lighter`: the terminal's dim. */
|
|
101
|
+
export declare const fontWeight: One<"bold" | "normal" | "lighter">;
|
|
102
|
+
export declare const fontStyle: One<"italic" | "normal">;
|
|
103
|
+
type Decoration = ["none"] | ["underline"] | ["line-through"] | ["underline", "line-through"] | ["line-through", "underline"];
|
|
104
|
+
export declare const textDecoration: (...line: Decoration) => TuiStyle;
|
|
105
|
+
export declare const textDecorationLine: (...line: Decoration) => TuiStyle;
|
|
106
|
+
export declare const textAlign: One<"left" | "center" | "right">;
|
|
107
|
+
/** `solid` (a single line), `double`, `rounded`, `heavy`, or `none`. */
|
|
108
|
+
type BorderWord = "solid" | "double" | "rounded" | "heavy" | "none";
|
|
109
|
+
export declare const borderStyle: One<BorderWord>;
|
|
110
|
+
/** A border of that style, and its colour. */
|
|
111
|
+
export declare const border: {
|
|
112
|
+
(style: BorderWord): TuiStyle;
|
|
113
|
+
<const A extends readonly Part[]>(style: Exclude<BorderWord, "none">, ...color: Check<"color", A>): TuiStyle;
|
|
114
|
+
};
|
|
115
|
+
export declare const padding: Sides<Cells>;
|
|
116
|
+
export declare const p: Sides<Cells>;
|
|
117
|
+
export declare const paddingInline: Pair<Cells>;
|
|
118
|
+
export declare const paddingBlock: Pair<Cells>;
|
|
119
|
+
export declare const paddingTop: One<Cells>;
|
|
120
|
+
export declare const paddingRight: One<Cells>;
|
|
121
|
+
export declare const paddingBottom: One<Cells>;
|
|
122
|
+
export declare const paddingLeft: One<Cells>;
|
|
123
|
+
export declare const pt: One<Cells>;
|
|
124
|
+
export declare const pr: One<Cells>;
|
|
125
|
+
export declare const pb: One<Cells>;
|
|
126
|
+
export declare const pl: One<Cells>;
|
|
127
|
+
export declare const margin: Sides<Size>;
|
|
128
|
+
export declare const m: Sides<Size>;
|
|
129
|
+
export declare const marginInline: Pair<Size>;
|
|
130
|
+
export declare const marginBlock: Pair<Size>;
|
|
131
|
+
export declare const marginTop: One<Size>;
|
|
132
|
+
export declare const marginRight: One<Size>;
|
|
133
|
+
export declare const marginBottom: One<Size>;
|
|
134
|
+
export declare const marginLeft: One<Size>;
|
|
135
|
+
export declare const mt: One<Size>;
|
|
136
|
+
export declare const mr: One<Size>;
|
|
137
|
+
export declare const mb: One<Size>;
|
|
138
|
+
export declare const ml: One<Size>;
|
|
139
|
+
export declare const gap: One<Cells>;
|
|
140
|
+
export declare const rowGap: One<Cells>;
|
|
141
|
+
export declare const columnGap: One<Cells>;
|
|
142
|
+
export declare const width: One<Size>;
|
|
143
|
+
export declare const height: One<Size>;
|
|
144
|
+
export declare const minWidth: One<Size>;
|
|
145
|
+
export declare const maxWidth: One<Size>;
|
|
146
|
+
export declare const minHeight: One<Size>;
|
|
147
|
+
export declare const maxHeight: One<Size>;
|
|
148
|
+
export declare const flexBasis: One<Size>;
|
|
149
|
+
export declare const flexDirection: One<NonNullable<TuiProps["flexDirection"]>>;
|
|
150
|
+
export declare const flexWrap: One<NonNullable<TuiProps["flexWrap"]>>;
|
|
151
|
+
export declare const justifyContent: One<Justify>;
|
|
152
|
+
export declare const alignItems: One<Align>;
|
|
153
|
+
export declare const alignSelf: One<Align>;
|
|
154
|
+
export declare const flexGrow: One<number>;
|
|
155
|
+
export declare const flexShrink: One<number>;
|
|
156
|
+
export declare const position: One<"relative" | "absolute">;
|
|
157
|
+
export declare const top: One<Size>;
|
|
158
|
+
export declare const right: One<Size>;
|
|
159
|
+
export declare const bottom: One<Size>;
|
|
160
|
+
export declare const left: One<Size>;
|
|
161
|
+
export declare const overflow: One<"visible" | "hidden" | "scroll">;
|
|
162
|
+
/** `flex` (shown) or `none` (hidden, out of the layout). */
|
|
163
|
+
export declare const display: One<"flex" | "none">;
|
|
164
|
+
export declare const opacity: One<number>;
|
|
165
|
+
export declare const zIndex: One<number>;
|
|
166
|
+
/** The mouse pointer over the element: set on over, back to `default` on out. */
|
|
167
|
+
export declare const cursor: One<Cursor>;
|
|
168
|
+
/** The caret of a focused editable: `bar`, `block`, `underscore`, or the terminal's `auto`. */
|
|
169
|
+
export declare const caretShape: One<"auto" | "bar" | "block" | "underscore">;
|
|
170
|
+
/** `auto` blinks, `manual` is steady. */
|
|
171
|
+
export declare const caretAnimation: One<"auto" | "manual">;
|
|
172
|
+
/** Merges styles in argument order: a later prop wins. */
|
|
173
|
+
export declare const cn: (...styles: TuiStyle[]) => TuiStyle;
|
|
174
|
+
/** The styles while the pointer is over the element (`onMouseOver` to `onMouseOut`). */
|
|
175
|
+
export declare const hover: (...styles: TuiStyle[]) => TuiStyle;
|
|
176
|
+
/** The styles while the element has focus. */
|
|
177
|
+
export declare const focus: (...styles: TuiStyle[]) => TuiStyle;
|
|
178
|
+
/** The styles while a mouse button is down on the element. */
|
|
179
|
+
export declare const active: (...styles: TuiStyle[]) => TuiStyle;
|
|
180
|
+
//#endregion
|
|
181
|
+
export { createGlobalTheme, createTokens };
|
package/dist/tui.d.mts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import "./node-CdhAGmF3.mjs";
|
|
2
|
+
import "./lib-2OEIfPAE.mjs";
|
|
3
|
+
import { CSSStyleValue } from "@cssints/css-grammar/values";
|
|
4
|
+
import { Effect } from "effect";
|
|
5
|
+
import { DtcgType } from "@cssints/css-grammar/token";
|
|
6
|
+
//#region src/theme.d.ts
|
|
7
|
+
export declare const createTokens: (...args: unknown[]) => unknown;
|
|
8
|
+
export declare const createGlobalTheme: (...args: unknown[]) => Readonly<{
|
|
9
|
+
__done: true;
|
|
10
|
+
}>;
|
|
11
|
+
//#endregion
|
|
12
|
+
//#region src/tui.d.ts
|
|
13
|
+
type State = "" | ":hover" | ":focus" | ":active";
|
|
14
|
+
type Value = string | number | boolean;
|
|
15
|
+
/** One prop: its key, its value (a colour is CSS text, resolved per theme at the site), and the state it is under. */
|
|
16
|
+
type Entry = [key: string, value: Value, state: State, colour?: true];
|
|
17
|
+
interface TuiNode {
|
|
18
|
+
__tui: Entry[];
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Merges styles in argument order: a later prop wins.
|
|
22
|
+
*
|
|
23
|
+
* @returns {TuiNode} the merged style
|
|
24
|
+
*/
|
|
25
|
+
export declare const cn: (...styles: unknown[]) => TuiNode;
|
|
26
|
+
export declare const hover: (...styles: unknown[]) => TuiNode;
|
|
27
|
+
export declare const focus: (...styles: unknown[]) => TuiNode;
|
|
28
|
+
export declare const active: (...styles: unknown[]) => TuiNode;
|
|
29
|
+
export declare const color: ((...parts: unknown[]) => TuiNode) | undefined, backgroundColor: ((...parts: unknown[]) => TuiNode) | undefined, bg: ((...parts: unknown[]) => TuiNode) | undefined, borderColor: ((...parts: unknown[]) => TuiNode) | undefined, caretColor: ((...parts: unknown[]) => TuiNode) | undefined, fontWeight: ((...parts: unknown[]) => TuiNode) | undefined, fontStyle: ((...parts: unknown[]) => TuiNode) | undefined, textDecoration: ((...parts: unknown[]) => TuiNode) | undefined, textDecorationLine: ((...parts: unknown[]) => TuiNode) | undefined, textAlign: ((...parts: unknown[]) => TuiNode) | undefined, borderStyle: ((...parts: unknown[]) => TuiNode) | undefined, border: ((...parts: unknown[]) => TuiNode) | undefined, padding: ((...parts: unknown[]) => TuiNode) | undefined, p: ((...parts: unknown[]) => TuiNode) | undefined, paddingInline: ((...parts: unknown[]) => TuiNode) | undefined, paddingBlock: ((...parts: unknown[]) => TuiNode) | undefined, paddingTop: ((...parts: unknown[]) => TuiNode) | undefined, paddingRight: ((...parts: unknown[]) => TuiNode) | undefined, paddingBottom: ((...parts: unknown[]) => TuiNode) | undefined, paddingLeft: ((...parts: unknown[]) => TuiNode) | undefined, pt: ((...parts: unknown[]) => TuiNode) | undefined, pr: ((...parts: unknown[]) => TuiNode) | undefined, pb: ((...parts: unknown[]) => TuiNode) | undefined, pl: ((...parts: unknown[]) => TuiNode) | undefined, margin: ((...parts: unknown[]) => TuiNode) | undefined, m: ((...parts: unknown[]) => TuiNode) | undefined, marginInline: ((...parts: unknown[]) => TuiNode) | undefined, marginBlock: ((...parts: unknown[]) => TuiNode) | undefined, marginTop: ((...parts: unknown[]) => TuiNode) | undefined, marginRight: ((...parts: unknown[]) => TuiNode) | undefined, marginBottom: ((...parts: unknown[]) => TuiNode) | undefined, marginLeft: ((...parts: unknown[]) => TuiNode) | undefined, mt: ((...parts: unknown[]) => TuiNode) | undefined, mr: ((...parts: unknown[]) => TuiNode) | undefined, mb: ((...parts: unknown[]) => TuiNode) | undefined, ml: ((...parts: unknown[]) => TuiNode) | undefined, top: ((...parts: unknown[]) => TuiNode) | undefined, right: ((...parts: unknown[]) => TuiNode) | undefined, bottom: ((...parts: unknown[]) => TuiNode) | undefined, left: ((...parts: unknown[]) => TuiNode) | undefined, gap: ((...parts: unknown[]) => TuiNode) | undefined, rowGap: ((...parts: unknown[]) => TuiNode) | undefined, columnGap: ((...parts: unknown[]) => TuiNode) | undefined, width: ((...parts: unknown[]) => TuiNode) | undefined, height: ((...parts: unknown[]) => TuiNode) | undefined, minWidth: ((...parts: unknown[]) => TuiNode) | undefined, maxWidth: ((...parts: unknown[]) => TuiNode) | undefined, minHeight: ((...parts: unknown[]) => TuiNode) | undefined, maxHeight: ((...parts: unknown[]) => TuiNode) | undefined, flexBasis: ((...parts: unknown[]) => TuiNode) | undefined, flexDirection: ((...parts: unknown[]) => TuiNode) | undefined, flexWrap: ((...parts: unknown[]) => TuiNode) | undefined, justifyContent: ((...parts: unknown[]) => TuiNode) | undefined, alignItems: ((...parts: unknown[]) => TuiNode) | undefined, alignSelf: ((...parts: unknown[]) => TuiNode) | undefined, flexGrow: ((...parts: unknown[]) => TuiNode) | undefined, flexShrink: ((...parts: unknown[]) => TuiNode) | undefined, position: ((...parts: unknown[]) => TuiNode) | undefined, overflow: ((...parts: unknown[]) => TuiNode) | undefined, display: ((...parts: unknown[]) => TuiNode) | undefined, opacity: ((...parts: unknown[]) => TuiNode) | undefined, zIndex: ((...parts: unknown[]) => TuiNode) | undefined, cursor: ((...parts: unknown[]) => TuiNode) | undefined, caretShape: ((...parts: unknown[]) => TuiNode) | undefined, caretAnimation: ((...parts: unknown[]) => TuiNode) | undefined;
|
|
30
|
+
//#endregion
|
package/dist/tui.mjs
ADDED
|
@@ -0,0 +1,399 @@
|
|
|
1
|
+
import { a as registry } from "./registry-n9JCX4pl.mjs";
|
|
2
|
+
import { O as fail, a as createTokens, i as createGlobalTheme } from "./theme-BGEbFAYh.mjs";
|
|
3
|
+
import { g as evaluate, h as css } from "./sheet-CO7a-mdA.mjs";
|
|
4
|
+
import { n as valueOf, t as together } from "./contrast-BUKVao74.mjs";
|
|
5
|
+
import { n as parseColor } from "./color-BYIxVLlS.mjs";
|
|
6
|
+
import { Formatter } from "effect";
|
|
7
|
+
import { clampRgb, formatHex, formatHex8 } from "culori/fn";
|
|
8
|
+
//#region src/tui.ts
|
|
9
|
+
const isTui = (v) => !!v && typeof v === "object" && Array.isArray(v.__tui);
|
|
10
|
+
const node = (entries) => ({ __tui: entries });
|
|
11
|
+
const say = (v) => typeof v === "string" ? `"${v}"` : Formatter.formatJson(v);
|
|
12
|
+
const PERCENT = /^-?(?:\d+\.?\d*|\.\d+)%$/;
|
|
13
|
+
const LENGTH = /^-?(?:\d+\.?\d*|\.\d+)[a-z]+$/i;
|
|
14
|
+
const cells = (auto, percent = true) => (prop, v) => {
|
|
15
|
+
if (typeof v === "number" && Number.isFinite(v)) return v;
|
|
16
|
+
if (typeof v === "string") {
|
|
17
|
+
if (percent && PERCENT.test(v)) return v;
|
|
18
|
+
if (auto && v === "auto") return v;
|
|
19
|
+
if (LENGTH.test(v)) throw fail(`cssints: ${prop}: a terminal counts cells: write a number, not ${say(v)}`);
|
|
20
|
+
}
|
|
21
|
+
throw fail(`cssints: ${prop}: unexpected ${say(v)}, expected a number of cells${percent ? ", N%" : ""}${auto ? " or auto" : ""}`);
|
|
22
|
+
};
|
|
23
|
+
const number = (min, max = Infinity, integer = false) => (prop, v) => {
|
|
24
|
+
if (typeof v === "number" && v >= min && v <= max && (!integer || Number.isInteger(v))) return v;
|
|
25
|
+
throw fail(`cssints: ${prop}: unexpected ${say(v)}, expected ${integer ? "an integer" : "a number"}${max < Infinity ? ` from ${min} to ${max}` : min > -Infinity ? ` of at least ${min}` : ""}`);
|
|
26
|
+
};
|
|
27
|
+
const keyword = (...words) => (prop, v) => {
|
|
28
|
+
if (typeof v === "string" && words.includes(v)) return v;
|
|
29
|
+
throw fail(`cssints: ${prop}: unexpected ${say(v)}, expected ${words.join(" | ")}`);
|
|
30
|
+
};
|
|
31
|
+
const hexOf = (text) => {
|
|
32
|
+
let c = parseColor(text);
|
|
33
|
+
if (!c && /\b(?:color-mix|from)\b/.test(text)) {
|
|
34
|
+
let rgb;
|
|
35
|
+
try {
|
|
36
|
+
rgb = css(evaluate(text));
|
|
37
|
+
} catch {
|
|
38
|
+
rgb = void 0;
|
|
39
|
+
}
|
|
40
|
+
c = rgb === void 0 ? void 0 : parseColor(rgb);
|
|
41
|
+
}
|
|
42
|
+
if (!c) return void 0;
|
|
43
|
+
const clipped = clampRgb(c);
|
|
44
|
+
return (c.alpha ?? 1) < 1 ? formatHex8(clipped) : formatHex(clipped);
|
|
45
|
+
};
|
|
46
|
+
const VAR = /var\((--[\w-]+)\)/g;
|
|
47
|
+
const colour = (prop, v) => {
|
|
48
|
+
const text = String(v);
|
|
49
|
+
for (const [, name] of text.matchAll(VAR)) {
|
|
50
|
+
const def = registry.defs.get(name);
|
|
51
|
+
if (!def) throw fail(`cssints: ${prop}: ${name} is no token of createTokens`);
|
|
52
|
+
if (def.kind !== "color" && text === `var(${name})`) throw fail(`cssints: ${prop}: ${def.path} is a ${def.kind} token, not a colour`);
|
|
53
|
+
}
|
|
54
|
+
if (!text.includes("var(") && hexOf(text) === void 0) throw fail(`cssints: ${prop}: ${say(v)} is not a colour a terminal can show (a name, hex, rgb(), hsl(), oklch(), color-mix(); not currentColor, a system colour or light-dark())`);
|
|
55
|
+
return text;
|
|
56
|
+
};
|
|
57
|
+
const one = (key, read, isColour = false) => (prop, parts) => {
|
|
58
|
+
if (parts.length !== 1) throw fail(`cssints: ${prop} takes one value, got ${parts.length}`);
|
|
59
|
+
return [isColour ? [
|
|
60
|
+
key,
|
|
61
|
+
read(prop, parts[0]),
|
|
62
|
+
"",
|
|
63
|
+
true
|
|
64
|
+
] : [
|
|
65
|
+
key,
|
|
66
|
+
read(prop, parts[0]),
|
|
67
|
+
""
|
|
68
|
+
]];
|
|
69
|
+
};
|
|
70
|
+
const sides = (base, read, which = [
|
|
71
|
+
"Top",
|
|
72
|
+
"Right",
|
|
73
|
+
"Bottom",
|
|
74
|
+
"Left"
|
|
75
|
+
]) => (prop, parts) => {
|
|
76
|
+
const n = which.length === 4 ? 4 : 2;
|
|
77
|
+
if (parts.length < 1 || parts.length > n) throw fail(`cssints: ${prop} takes 1 to ${n} values, got ${parts.length}`);
|
|
78
|
+
const v = parts.map((p) => read(prop, p));
|
|
79
|
+
const at = n === 4 ? [
|
|
80
|
+
v[0],
|
|
81
|
+
v[1] ?? v[0],
|
|
82
|
+
v[2] ?? v[0],
|
|
83
|
+
v[3] ?? v[1] ?? v[0]
|
|
84
|
+
] : [v[0], v[1] ?? v[0]];
|
|
85
|
+
return which.map((s, i) => [
|
|
86
|
+
`${base}${s}`,
|
|
87
|
+
at[i],
|
|
88
|
+
""
|
|
89
|
+
]);
|
|
90
|
+
};
|
|
91
|
+
const flags = (table, many = false) => (prop, parts) => {
|
|
92
|
+
if (parts.length < 1 || !many && parts.length > 1) throw fail(`cssints: ${prop} takes ${many ? "a value" : "one value"}, got ${parts.length}`);
|
|
93
|
+
const out = {};
|
|
94
|
+
for (const p of parts) {
|
|
95
|
+
const set = typeof p === "string" ? table[p] : void 0;
|
|
96
|
+
if (!set || parts.length > 1 && p === "none") throw fail(`cssints: ${prop}: unexpected ${say(p)}, expected ${Object.keys(table).join(" | ")}`);
|
|
97
|
+
for (const [k, b] of Object.entries(set)) out[k] = parts.length > 1 && out[k] || b;
|
|
98
|
+
}
|
|
99
|
+
return Object.entries(out).map(([k, b]) => [
|
|
100
|
+
k,
|
|
101
|
+
b,
|
|
102
|
+
""
|
|
103
|
+
]);
|
|
104
|
+
};
|
|
105
|
+
const BORDER = {
|
|
106
|
+
none: [[
|
|
107
|
+
"border",
|
|
108
|
+
false,
|
|
109
|
+
""
|
|
110
|
+
]],
|
|
111
|
+
solid: [[
|
|
112
|
+
"border",
|
|
113
|
+
true,
|
|
114
|
+
""
|
|
115
|
+
], [
|
|
116
|
+
"borderStyle",
|
|
117
|
+
"single",
|
|
118
|
+
""
|
|
119
|
+
]],
|
|
120
|
+
double: [[
|
|
121
|
+
"border",
|
|
122
|
+
true,
|
|
123
|
+
""
|
|
124
|
+
], [
|
|
125
|
+
"borderStyle",
|
|
126
|
+
"double",
|
|
127
|
+
""
|
|
128
|
+
]],
|
|
129
|
+
rounded: [[
|
|
130
|
+
"border",
|
|
131
|
+
true,
|
|
132
|
+
""
|
|
133
|
+
], [
|
|
134
|
+
"borderStyle",
|
|
135
|
+
"rounded",
|
|
136
|
+
""
|
|
137
|
+
]],
|
|
138
|
+
heavy: [[
|
|
139
|
+
"border",
|
|
140
|
+
true,
|
|
141
|
+
""
|
|
142
|
+
], [
|
|
143
|
+
"borderStyle",
|
|
144
|
+
"heavy",
|
|
145
|
+
""
|
|
146
|
+
]]
|
|
147
|
+
};
|
|
148
|
+
const borderStyleOf = (prop, v) => {
|
|
149
|
+
const e = typeof v === "string" ? BORDER[v] : void 0;
|
|
150
|
+
if (!e) throw fail(`cssints: ${prop}: unexpected ${say(v)}, expected ${Object.keys(BORDER).join(" | ")}`);
|
|
151
|
+
return e;
|
|
152
|
+
};
|
|
153
|
+
const SIZE = cells(true);
|
|
154
|
+
const EDGE = cells(false);
|
|
155
|
+
const ALIGN = [
|
|
156
|
+
"auto",
|
|
157
|
+
"flex-start",
|
|
158
|
+
"center",
|
|
159
|
+
"flex-end",
|
|
160
|
+
"stretch",
|
|
161
|
+
"baseline",
|
|
162
|
+
"space-between",
|
|
163
|
+
"space-around",
|
|
164
|
+
"space-evenly"
|
|
165
|
+
];
|
|
166
|
+
const JUSTIFY = [
|
|
167
|
+
"flex-start",
|
|
168
|
+
"center",
|
|
169
|
+
"flex-end",
|
|
170
|
+
"space-between",
|
|
171
|
+
"space-around",
|
|
172
|
+
"space-evenly"
|
|
173
|
+
];
|
|
174
|
+
const CURSORS = [
|
|
175
|
+
"auto",
|
|
176
|
+
"default",
|
|
177
|
+
"none",
|
|
178
|
+
"context-menu",
|
|
179
|
+
"help",
|
|
180
|
+
"pointer",
|
|
181
|
+
"progress",
|
|
182
|
+
"wait",
|
|
183
|
+
"cell",
|
|
184
|
+
"crosshair",
|
|
185
|
+
"text",
|
|
186
|
+
"vertical-text",
|
|
187
|
+
"alias",
|
|
188
|
+
"copy",
|
|
189
|
+
"move",
|
|
190
|
+
"no-drop",
|
|
191
|
+
"not-allowed",
|
|
192
|
+
"grab",
|
|
193
|
+
"grabbing",
|
|
194
|
+
"all-scroll",
|
|
195
|
+
"col-resize",
|
|
196
|
+
"row-resize",
|
|
197
|
+
"n-resize",
|
|
198
|
+
"e-resize",
|
|
199
|
+
"s-resize",
|
|
200
|
+
"w-resize",
|
|
201
|
+
"ne-resize",
|
|
202
|
+
"nw-resize",
|
|
203
|
+
"se-resize",
|
|
204
|
+
"sw-resize",
|
|
205
|
+
"ew-resize",
|
|
206
|
+
"ns-resize",
|
|
207
|
+
"nesw-resize",
|
|
208
|
+
"nwse-resize",
|
|
209
|
+
"zoom-in",
|
|
210
|
+
"zoom-out"
|
|
211
|
+
];
|
|
212
|
+
const MEMBERS = {
|
|
213
|
+
color: one("color", colour, true),
|
|
214
|
+
backgroundColor: one("backgroundColor", colour, true),
|
|
215
|
+
bg: one("backgroundColor", colour, true),
|
|
216
|
+
borderColor: one("borderColor", colour, true),
|
|
217
|
+
caretColor: one("caretColor", colour, true),
|
|
218
|
+
fontWeight: flags({
|
|
219
|
+
bold: {
|
|
220
|
+
bold: true,
|
|
221
|
+
dim: false
|
|
222
|
+
},
|
|
223
|
+
normal: {
|
|
224
|
+
bold: false,
|
|
225
|
+
dim: false
|
|
226
|
+
},
|
|
227
|
+
lighter: {
|
|
228
|
+
bold: false,
|
|
229
|
+
dim: true
|
|
230
|
+
}
|
|
231
|
+
}),
|
|
232
|
+
fontStyle: flags({
|
|
233
|
+
italic: { italic: true },
|
|
234
|
+
normal: { italic: false }
|
|
235
|
+
}),
|
|
236
|
+
textDecoration: flags({
|
|
237
|
+
underline: {
|
|
238
|
+
underline: true,
|
|
239
|
+
strikethrough: false
|
|
240
|
+
},
|
|
241
|
+
"line-through": {
|
|
242
|
+
underline: false,
|
|
243
|
+
strikethrough: true
|
|
244
|
+
},
|
|
245
|
+
none: {
|
|
246
|
+
underline: false,
|
|
247
|
+
strikethrough: false
|
|
248
|
+
}
|
|
249
|
+
}, true),
|
|
250
|
+
textAlign: one("textAlign", keyword("left", "center", "right")),
|
|
251
|
+
borderStyle: (prop, parts) => {
|
|
252
|
+
if (parts.length !== 1) throw fail(`cssints: ${prop} takes one value, got ${parts.length}`);
|
|
253
|
+
return borderStyleOf(prop, parts[0]);
|
|
254
|
+
},
|
|
255
|
+
border: (prop, parts) => {
|
|
256
|
+
if (parts.length < 1 || parts.length > 2) throw fail(`cssints: ${prop} takes a style and an optional colour, got ${parts.length} values`);
|
|
257
|
+
const style = borderStyleOf(prop, parts[0]);
|
|
258
|
+
if (parts.length === 2 && parts[0] === "none") throw fail(`cssints: ${prop}: a colour of no border`);
|
|
259
|
+
return parts.length === 2 ? [...style, [
|
|
260
|
+
"borderColor",
|
|
261
|
+
colour(prop, parts[1]),
|
|
262
|
+
"",
|
|
263
|
+
true
|
|
264
|
+
]] : style;
|
|
265
|
+
},
|
|
266
|
+
padding: sides("padding", EDGE),
|
|
267
|
+
p: sides("padding", EDGE),
|
|
268
|
+
paddingInline: sides("padding", EDGE, ["Left", "Right"]),
|
|
269
|
+
paddingBlock: sides("padding", EDGE, ["Top", "Bottom"]),
|
|
270
|
+
margin: sides("margin", SIZE),
|
|
271
|
+
m: sides("margin", SIZE),
|
|
272
|
+
marginInline: sides("margin", SIZE, ["Left", "Right"]),
|
|
273
|
+
marginBlock: sides("margin", SIZE, ["Top", "Bottom"]),
|
|
274
|
+
...Object.fromEntries([
|
|
275
|
+
"Top",
|
|
276
|
+
"Right",
|
|
277
|
+
"Bottom",
|
|
278
|
+
"Left"
|
|
279
|
+
].flatMap((s) => [
|
|
280
|
+
[`padding${s}`, one(`padding${s}`, EDGE)],
|
|
281
|
+
[`p${s[0].toLowerCase()}`, one(`padding${s}`, EDGE)],
|
|
282
|
+
[`margin${s}`, one(`margin${s}`, SIZE)],
|
|
283
|
+
[`m${s[0].toLowerCase()}`, one(`margin${s}`, SIZE)],
|
|
284
|
+
[s.toLowerCase(), one(s.toLowerCase(), SIZE)]
|
|
285
|
+
])),
|
|
286
|
+
gap: one("gap", EDGE),
|
|
287
|
+
rowGap: one("rowGap", EDGE),
|
|
288
|
+
columnGap: one("columnGap", EDGE),
|
|
289
|
+
...Object.fromEntries([
|
|
290
|
+
"width",
|
|
291
|
+
"height",
|
|
292
|
+
"minWidth",
|
|
293
|
+
"maxWidth",
|
|
294
|
+
"minHeight",
|
|
295
|
+
"maxHeight",
|
|
296
|
+
"flexBasis"
|
|
297
|
+
].map((k) => [k, one(k, SIZE)])),
|
|
298
|
+
flexDirection: one("flexDirection", keyword("row", "column", "row-reverse", "column-reverse")),
|
|
299
|
+
flexWrap: one("flexWrap", keyword("nowrap", "wrap", "wrap-reverse")),
|
|
300
|
+
justifyContent: one("justifyContent", keyword(...JUSTIFY)),
|
|
301
|
+
alignItems: one("alignItems", keyword(...ALIGN)),
|
|
302
|
+
alignSelf: one("alignSelf", keyword(...ALIGN)),
|
|
303
|
+
flexGrow: one("flexGrow", number(0)),
|
|
304
|
+
flexShrink: one("flexShrink", number(0)),
|
|
305
|
+
position: one("position", keyword("relative", "absolute")),
|
|
306
|
+
overflow: one("overflow", keyword("visible", "hidden", "scroll")),
|
|
307
|
+
display: (prop, parts) => {
|
|
308
|
+
const [d] = one("visible", keyword("flex", "none"))(prop, parts);
|
|
309
|
+
return [[
|
|
310
|
+
"visible",
|
|
311
|
+
d[1] === "flex",
|
|
312
|
+
""
|
|
313
|
+
]];
|
|
314
|
+
},
|
|
315
|
+
opacity: one("opacity", number(0, 1)),
|
|
316
|
+
zIndex: one("zIndex", number(-Infinity, Infinity, true)),
|
|
317
|
+
cursor: one("cursor", keyword(...CURSORS)),
|
|
318
|
+
caretShape: one("caretShape", keyword("auto", "bar", "block", "underscore")),
|
|
319
|
+
caretAnimation: one("caretAnimation", keyword("auto", "manual"))
|
|
320
|
+
};
|
|
321
|
+
MEMBERS.textDecorationLine = MEMBERS.textDecoration;
|
|
322
|
+
const member = (name, build) => (...parts) => {
|
|
323
|
+
if (parts.some(isTui)) throw fail(`cssints: ${name}: a style is not a value`);
|
|
324
|
+
return node(build(name, parts));
|
|
325
|
+
};
|
|
326
|
+
const stylesOf = (what, styles) => {
|
|
327
|
+
const bad = styles.find((s) => !isTui(s));
|
|
328
|
+
if (bad !== void 0 || !styles.length) throw fail(`cssints: ${what} takes styles of cssints/tui, got ${bad === void 0 ? "nothing" : say(bad)}`);
|
|
329
|
+
return styles.flatMap((s) => s.__tui);
|
|
330
|
+
};
|
|
331
|
+
/**
|
|
332
|
+
* Merges styles in argument order: a later prop wins.
|
|
333
|
+
*
|
|
334
|
+
* @returns {TuiNode} the merged style
|
|
335
|
+
*/
|
|
336
|
+
const cn = (...styles) => node(stylesOf("cn()", styles));
|
|
337
|
+
const state = (s) => (...styles) => node(stylesOf(s, styles).map(([k, v, inner, c]) => {
|
|
338
|
+
if (inner) throw fail(`cssints: ${s} wraps ${inner}: terminal states do not nest (one state per style)`);
|
|
339
|
+
return c ? [
|
|
340
|
+
k,
|
|
341
|
+
v,
|
|
342
|
+
s,
|
|
343
|
+
c
|
|
344
|
+
] : [
|
|
345
|
+
k,
|
|
346
|
+
v,
|
|
347
|
+
s
|
|
348
|
+
];
|
|
349
|
+
}));
|
|
350
|
+
const hover = state(":hover");
|
|
351
|
+
const focus = state(":focus");
|
|
352
|
+
const active = state(":active");
|
|
353
|
+
const { color, backgroundColor, bg, borderColor, caretColor, fontWeight, fontStyle, textDecoration, textDecorationLine, textAlign, borderStyle, border, padding, p, paddingInline, paddingBlock, paddingTop, paddingRight, paddingBottom, paddingLeft, pt, pr, pb, pl, margin, m, marginInline, marginBlock, marginTop, marginRight, marginBottom, marginLeft, mt, mr, mb, ml, top, right, bottom, left, gap, rowGap, columnGap, width, height, minWidth, maxWidth, minHeight, maxHeight, flexBasis, flexDirection, flexWrap, justifyContent, alignItems, alignSelf, flexGrow, flexShrink, position, overflow, display, opacity, zIndex, cursor, caretShape, caretAnimation } = Object.fromEntries(Object.entries(MEMBERS).map(([k, b]) => [k, member(k, b)]));
|
|
354
|
+
const put = (out, state, key, value) => {
|
|
355
|
+
if (!state) out[key] = value;
|
|
356
|
+
else (out[state] ??= {})[key] = value;
|
|
357
|
+
};
|
|
358
|
+
const resolved = (text, values) => {
|
|
359
|
+
const flat = text.replace(VAR, (m, n) => valueOf(registry, n, values) ?? m);
|
|
360
|
+
const hex = hexOf(flat);
|
|
361
|
+
if (hex === void 0) throw fail(`cssints: ${say(text)} is ${say(flat)} here, not a colour a terminal can show`);
|
|
362
|
+
return hex;
|
|
363
|
+
};
|
|
364
|
+
const LONE = /^var\(--([\w-]+)\)$/;
|
|
365
|
+
const replacement = (n) => {
|
|
366
|
+
const out = {};
|
|
367
|
+
const vars = {};
|
|
368
|
+
for (const [k, v, s, c] of n.__tui) {
|
|
369
|
+
put(out, s, k, c ? resolved(String(v)) : v);
|
|
370
|
+
const token = c ? LONE.exec(String(v))?.[1] : void 0;
|
|
371
|
+
if (token) put(vars, s, k, token);
|
|
372
|
+
else if (c) delete (s ? vars[s] ?? {} : vars)[k];
|
|
373
|
+
}
|
|
374
|
+
const tokens = n.__tui.filter((e) => e[3] && String(e[1]).includes("var("));
|
|
375
|
+
if (tokens.length) {
|
|
376
|
+
const themes = {};
|
|
377
|
+
for (const { label, values } of together(registry)) {
|
|
378
|
+
if (label.startsWith("@")) continue;
|
|
379
|
+
const overlay = {};
|
|
380
|
+
for (const [k, v, s] of tokens) {
|
|
381
|
+
const was = s ? out[s][k] : out[k];
|
|
382
|
+
const now = resolved(String(v), values);
|
|
383
|
+
if (now !== was) put(overlay, s, k, now);
|
|
384
|
+
}
|
|
385
|
+
if (Object.keys(overlay).length) themes[label] = overlay;
|
|
386
|
+
}
|
|
387
|
+
if (Object.keys(themes).length) out.themes = themes;
|
|
388
|
+
}
|
|
389
|
+
for (const s of [
|
|
390
|
+
":hover",
|
|
391
|
+
":focus",
|
|
392
|
+
":active"
|
|
393
|
+
]) if (vars[s] && !Object.keys(vars[s]).length) delete vars[s];
|
|
394
|
+
if (Object.keys(vars).length) out.vars = vars;
|
|
395
|
+
return `(${Formatter.formatJson(out)})`;
|
|
396
|
+
};
|
|
397
|
+
registry.tui = (v) => isTui(v) ? replacement(v) : void 0;
|
|
398
|
+
//#endregion
|
|
399
|
+
export { active, alignItems, alignSelf, backgroundColor, bg, border, borderColor, borderStyle, bottom, caretAnimation, caretColor, caretShape, cn, color, columnGap, createGlobalTheme, createTokens, cursor, display, flexBasis, flexDirection, flexGrow, flexShrink, flexWrap, focus, fontStyle, fontWeight, gap, height, hover, justifyContent, left, m, margin, marginBlock, marginBottom, marginInline, marginLeft, marginRight, marginTop, maxHeight, maxWidth, mb, minHeight, minWidth, ml, mr, mt, opacity, overflow, p, padding, paddingBlock, paddingBottom, paddingInline, paddingLeft, paddingRight, paddingTop, pb, pl, position, pr, pt, right, rowGap, textAlign, textDecoration, textDecorationLine, top, width, zIndex };
|