@hiscovega/grisso 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +194 -0
- package/dist/grisso.css +1 -0
- package/lib/defaults.d.ts +7 -0
- package/lib/defaults.js +97 -0
- package/lib/generators.d.ts +20 -0
- package/lib/generators.js +49 -0
- package/lib/index.d.ts +9 -0
- package/lib/index.js +17 -0
- package/lib/partials/backgrounds.d.ts +2 -0
- package/lib/partials/backgrounds.js +64 -0
- package/lib/partials/borders.d.ts +2 -0
- package/lib/partials/borders.js +55 -0
- package/lib/partials/effects.d.ts +2 -0
- package/lib/partials/effects.js +17 -0
- package/lib/partials/flex-and-grid.d.ts +2 -0
- package/lib/partials/flex-and-grid.js +195 -0
- package/lib/partials/icons.d.ts +2 -0
- package/lib/partials/icons.js +5 -0
- package/lib/partials/index.d.ts +7 -0
- package/lib/partials/index.js +25 -0
- package/lib/partials/layout.d.ts +2 -0
- package/lib/partials/layout.js +126 -0
- package/lib/partials/sizing.d.ts +2 -0
- package/lib/partials/sizing.js +39 -0
- package/lib/partials/spacing.d.ts +2 -0
- package/lib/partials/spacing.js +24 -0
- package/lib/partials/typography.d.ts +2 -0
- package/lib/partials/typography.js +111 -0
- package/lib/resolve-config.d.ts +8 -0
- package/lib/resolve-config.js +54 -0
- package/lib/types.d.ts +25 -0
- package/lib/types.js +1 -0
- package/lib/utils.d.ts +12 -0
- package/lib/utils.js +20 -0
- package/package.json +49 -0
- package/plugin.js +77 -0
- package/tokens-example.css +80 -0
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { simpleClass, complexClass } from "../generators.js";
|
|
2
|
+
export default function layout(config) {
|
|
3
|
+
const { columns, breakpoints, spacing } = config;
|
|
4
|
+
let css = "";
|
|
5
|
+
// display
|
|
6
|
+
const display = {
|
|
7
|
+
block: "block",
|
|
8
|
+
inline: "inline",
|
|
9
|
+
"inline-block": "inline-block",
|
|
10
|
+
flex: "flex",
|
|
11
|
+
"inline-flex": "inline-flex",
|
|
12
|
+
grid: "grid",
|
|
13
|
+
"inline-grid": "inline-grid",
|
|
14
|
+
"inline-table": "inline-table",
|
|
15
|
+
table: "table",
|
|
16
|
+
"table-row": "table-row",
|
|
17
|
+
"table-caption": "table-caption",
|
|
18
|
+
"table-cell": "table-cell",
|
|
19
|
+
"table-column": "table-column",
|
|
20
|
+
"table-column-group": "table-column-group",
|
|
21
|
+
"table-footer-group": "table-footer-group",
|
|
22
|
+
"table-header-group": "table-header-group",
|
|
23
|
+
"table-row-group": "table-row-group",
|
|
24
|
+
contents: "contents",
|
|
25
|
+
"flow-root": "flow-root",
|
|
26
|
+
"list-item": "list-item",
|
|
27
|
+
hidden: "none",
|
|
28
|
+
};
|
|
29
|
+
css += complexClass("", "display", display, breakpoints);
|
|
30
|
+
// columns (numeric)
|
|
31
|
+
for (let i = 1; i <= columns; i++) {
|
|
32
|
+
css += simpleClass(`columns-${i}`, "columns", String(i), breakpoints);
|
|
33
|
+
}
|
|
34
|
+
// columns (spacing tokens)
|
|
35
|
+
css += complexClass("columns-", "columns", spacing, breakpoints);
|
|
36
|
+
// float
|
|
37
|
+
const float = {
|
|
38
|
+
left: "left",
|
|
39
|
+
right: "right",
|
|
40
|
+
none: "none",
|
|
41
|
+
};
|
|
42
|
+
css += complexClass("float-", "float", float, breakpoints);
|
|
43
|
+
// clear
|
|
44
|
+
const clear = {
|
|
45
|
+
left: "left",
|
|
46
|
+
right: "right",
|
|
47
|
+
both: "both",
|
|
48
|
+
none: "none",
|
|
49
|
+
};
|
|
50
|
+
css += complexClass("clear-", "clear", clear, breakpoints);
|
|
51
|
+
// object-fit
|
|
52
|
+
const objectFit = {
|
|
53
|
+
contain: "contain",
|
|
54
|
+
cover: "cover",
|
|
55
|
+
fill: "fill",
|
|
56
|
+
none: "none",
|
|
57
|
+
"scale-down": "scale-down",
|
|
58
|
+
};
|
|
59
|
+
css += complexClass("object-", "object-fit", objectFit, breakpoints);
|
|
60
|
+
// object-position
|
|
61
|
+
const objectPosition = {
|
|
62
|
+
bottom: "bottom",
|
|
63
|
+
center: "center",
|
|
64
|
+
left: "left",
|
|
65
|
+
"left-bottom": "left bottom",
|
|
66
|
+
"left-top": "left top",
|
|
67
|
+
right: "right",
|
|
68
|
+
"right-bottom": "right bottom",
|
|
69
|
+
"right-top": "right top",
|
|
70
|
+
top: "top",
|
|
71
|
+
};
|
|
72
|
+
css += complexClass("object-", "object-position", objectPosition, breakpoints);
|
|
73
|
+
// overflow
|
|
74
|
+
const overflow = {
|
|
75
|
+
auto: "auto",
|
|
76
|
+
hidden: "hidden",
|
|
77
|
+
clip: "clip",
|
|
78
|
+
visible: "visible",
|
|
79
|
+
scroll: "scroll",
|
|
80
|
+
};
|
|
81
|
+
css += complexClass("overflow-", "overflow", overflow, breakpoints);
|
|
82
|
+
css += complexClass("overflow-x-", "overflow-x", overflow, breakpoints);
|
|
83
|
+
css += complexClass("overflow-y-", "overflow-y", overflow, breakpoints);
|
|
84
|
+
// position
|
|
85
|
+
const position = {
|
|
86
|
+
static: "static",
|
|
87
|
+
fixed: "fixed",
|
|
88
|
+
absolute: "absolute",
|
|
89
|
+
relative: "relative",
|
|
90
|
+
sticky: "sticky",
|
|
91
|
+
};
|
|
92
|
+
css += complexClass("", "position", position, breakpoints);
|
|
93
|
+
// visibility
|
|
94
|
+
css += simpleClass("visible", "visibility", "visible", breakpoints);
|
|
95
|
+
css += simpleClass("invisible", "visibility", "hidden", breakpoints);
|
|
96
|
+
css += simpleClass("collapse", "visibility", "collapse", breakpoints);
|
|
97
|
+
// z-index
|
|
98
|
+
const zIndex = {
|
|
99
|
+
auto: "auto",
|
|
100
|
+
"0": "0",
|
|
101
|
+
"1": "10",
|
|
102
|
+
"20": "20",
|
|
103
|
+
"30": "30",
|
|
104
|
+
"40": "40",
|
|
105
|
+
"50": "50",
|
|
106
|
+
};
|
|
107
|
+
const zIndexNeg = {
|
|
108
|
+
"1": "-10",
|
|
109
|
+
"20": "-20",
|
|
110
|
+
"30": "-30",
|
|
111
|
+
"40": "-40",
|
|
112
|
+
"50": "-50",
|
|
113
|
+
};
|
|
114
|
+
css += complexClass("z-", "z-index", zIndex, breakpoints);
|
|
115
|
+
css += complexClass("-z-", "z-index", zIndexNeg, breakpoints);
|
|
116
|
+
// top/right/bottom/left
|
|
117
|
+
css += simpleClass("top-0", "top", "0", breakpoints);
|
|
118
|
+
css += simpleClass("right-0", "right", "0", breakpoints);
|
|
119
|
+
css += simpleClass("bottom-0", "bottom", "0", breakpoints);
|
|
120
|
+
css += simpleClass("left-0", "left", "0", breakpoints);
|
|
121
|
+
css += complexClass("top-", "top", spacing, breakpoints);
|
|
122
|
+
css += complexClass("right-", "right", spacing, breakpoints);
|
|
123
|
+
css += complexClass("bottom-", "bottom", spacing, breakpoints);
|
|
124
|
+
css += complexClass("left-", "left", spacing, breakpoints);
|
|
125
|
+
return css;
|
|
126
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { simpleClass, complexClass } from "../generators.js";
|
|
2
|
+
import { fractionPercent } from "../utils.js";
|
|
3
|
+
export default function sizing(config) {
|
|
4
|
+
const { columns, breakpoints } = config;
|
|
5
|
+
let css = "";
|
|
6
|
+
// width
|
|
7
|
+
const width = {
|
|
8
|
+
auto: "auto",
|
|
9
|
+
"0": "0",
|
|
10
|
+
full: "100%",
|
|
11
|
+
screen: "100vw",
|
|
12
|
+
min: "min-content",
|
|
13
|
+
max: "max-content",
|
|
14
|
+
fit: "fit-content",
|
|
15
|
+
};
|
|
16
|
+
css += complexClass("w-", "width", width, breakpoints);
|
|
17
|
+
for (let i = 1; i <= columns; i++) {
|
|
18
|
+
css += simpleClass(`w-${i}`, "width", fractionPercent(i, columns), breakpoints);
|
|
19
|
+
}
|
|
20
|
+
css += complexClass("min-w-", "min-width", width, breakpoints);
|
|
21
|
+
css += complexClass("max-w-", "max-width", width, breakpoints);
|
|
22
|
+
// height
|
|
23
|
+
const height = {
|
|
24
|
+
auto: "auto",
|
|
25
|
+
"0": "0",
|
|
26
|
+
full: "100%",
|
|
27
|
+
screen: "100vh",
|
|
28
|
+
min: "min-content",
|
|
29
|
+
max: "max-content",
|
|
30
|
+
fit: "fit-content",
|
|
31
|
+
};
|
|
32
|
+
css += complexClass("h-", "height", height, breakpoints);
|
|
33
|
+
for (let i = 1; i <= columns; i++) {
|
|
34
|
+
css += simpleClass(`h-${i}`, "height", fractionPercent(i, columns), breakpoints);
|
|
35
|
+
}
|
|
36
|
+
css += complexClass("min-h-", "min-height", height, breakpoints);
|
|
37
|
+
css += complexClass("max-h-", "max-height", height, breakpoints);
|
|
38
|
+
return css;
|
|
39
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { complexClass } from "../generators.js";
|
|
2
|
+
import { omit } from "../utils.js";
|
|
3
|
+
export default function spacingPartial(config) {
|
|
4
|
+
const { breakpoints, spacing } = config;
|
|
5
|
+
let css = "";
|
|
6
|
+
// margin (incluye "auto")
|
|
7
|
+
css += complexClass("m-", "margin", spacing, breakpoints);
|
|
8
|
+
css += complexClass("mt-", "margin-top", spacing, breakpoints);
|
|
9
|
+
css += complexClass("mr-", "margin-right", spacing, breakpoints);
|
|
10
|
+
css += complexClass("mb-", "margin-bottom", spacing, breakpoints);
|
|
11
|
+
css += complexClass("ml-", "margin-left", spacing, breakpoints);
|
|
12
|
+
css += complexClass("mx-", "margin-inline", spacing, breakpoints);
|
|
13
|
+
css += complexClass("my-", "margin-block", spacing, breakpoints);
|
|
14
|
+
// padding (sin "auto")
|
|
15
|
+
const padding = omit(spacing, "auto");
|
|
16
|
+
css += complexClass("p-", "padding", padding, breakpoints);
|
|
17
|
+
css += complexClass("pt-", "padding-top", padding, breakpoints);
|
|
18
|
+
css += complexClass("pr-", "padding-right", padding, breakpoints);
|
|
19
|
+
css += complexClass("pb-", "padding-bottom", padding, breakpoints);
|
|
20
|
+
css += complexClass("pl-", "padding-left", padding, breakpoints);
|
|
21
|
+
css += complexClass("px-", "padding-inline", padding, breakpoints);
|
|
22
|
+
css += complexClass("py-", "padding-block", padding, breakpoints);
|
|
23
|
+
return css;
|
|
24
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { simpleClass, complexClass, customClass } from "../generators.js";
|
|
2
|
+
import { omit } from "../utils.js";
|
|
3
|
+
export default function typography(config) {
|
|
4
|
+
const { breakpoints, foregroundColors, spacing } = config;
|
|
5
|
+
let css = "";
|
|
6
|
+
// text-color
|
|
7
|
+
css += complexClass("text-", "color", foregroundColors, breakpoints);
|
|
8
|
+
// text-align
|
|
9
|
+
const textAlign = {
|
|
10
|
+
left: "left",
|
|
11
|
+
center: "center",
|
|
12
|
+
right: "right",
|
|
13
|
+
justify: "justify",
|
|
14
|
+
start: "start",
|
|
15
|
+
end: "end",
|
|
16
|
+
};
|
|
17
|
+
css += complexClass("text-", "text-align", textAlign, breakpoints);
|
|
18
|
+
// text-transform
|
|
19
|
+
const textTransform = {
|
|
20
|
+
uppercase: "uppercase",
|
|
21
|
+
lowercase: "lowercase",
|
|
22
|
+
capitalize: "capitalize",
|
|
23
|
+
"normal-case": "none",
|
|
24
|
+
};
|
|
25
|
+
css += complexClass("", "text-transform", textTransform, breakpoints);
|
|
26
|
+
// text-overflow
|
|
27
|
+
const textOverflow = {
|
|
28
|
+
ellipsis: "ellipsis",
|
|
29
|
+
clip: "clip",
|
|
30
|
+
};
|
|
31
|
+
css += complexClass("text-", "text-overflow", textOverflow, breakpoints);
|
|
32
|
+
css += customClass("truncate", {
|
|
33
|
+
overflow: "hidden",
|
|
34
|
+
"text-overflow": "ellipsis",
|
|
35
|
+
"white-space": "nowrap",
|
|
36
|
+
}, breakpoints);
|
|
37
|
+
// vertical-align
|
|
38
|
+
const verticalAlign = {
|
|
39
|
+
baseline: "baseline",
|
|
40
|
+
top: "top",
|
|
41
|
+
middle: "middle",
|
|
42
|
+
bottom: "bottom",
|
|
43
|
+
"text-top": "text-top",
|
|
44
|
+
"text-bottom": "text-bottom",
|
|
45
|
+
sub: "sub",
|
|
46
|
+
super: "super",
|
|
47
|
+
};
|
|
48
|
+
css += complexClass("align-", "vertical-align", verticalAlign, breakpoints);
|
|
49
|
+
// white-space
|
|
50
|
+
const whiteSpace = {
|
|
51
|
+
normal: "normal",
|
|
52
|
+
nowrap: "nowrap",
|
|
53
|
+
pre: "pre",
|
|
54
|
+
"pre-line": "pre-line",
|
|
55
|
+
"pre-wrap": "pre-wrap",
|
|
56
|
+
"break-spaces": "break-spaces",
|
|
57
|
+
};
|
|
58
|
+
css += complexClass("whitespace-", "white-space", whiteSpace, breakpoints);
|
|
59
|
+
// word-break
|
|
60
|
+
const wordBreak = {
|
|
61
|
+
all: "break-all",
|
|
62
|
+
keep: "keep-all",
|
|
63
|
+
};
|
|
64
|
+
css += complexClass("break-", "word-break", wordBreak, breakpoints);
|
|
65
|
+
css += simpleClass("break-words", "overflow-wrap", "break-word", breakpoints);
|
|
66
|
+
css += customClass("break-normal", { "overflow-wrap": "normal", "word-break": "normal" }, breakpoints);
|
|
67
|
+
// font-smoothing
|
|
68
|
+
css += customClass("antialiased", {
|
|
69
|
+
"-webkit-font-smoothing": "antialiased",
|
|
70
|
+
"-moz-osx-font-smoothing": "grayscale",
|
|
71
|
+
}, breakpoints);
|
|
72
|
+
css += customClass("subpixel-antialiased", {
|
|
73
|
+
"-webkit-font-smoothing": "auto",
|
|
74
|
+
"-moz-osx-font-smoothing": "auto",
|
|
75
|
+
}, breakpoints);
|
|
76
|
+
// font-style
|
|
77
|
+
const fontStyle = {
|
|
78
|
+
italic: "italic",
|
|
79
|
+
"not-italic": "normal",
|
|
80
|
+
};
|
|
81
|
+
css += complexClass("", "font-style", fontStyle, breakpoints);
|
|
82
|
+
// font-weight
|
|
83
|
+
const fontWeight = {
|
|
84
|
+
thin: "100",
|
|
85
|
+
extralight: "200",
|
|
86
|
+
light: "200",
|
|
87
|
+
normal: "400",
|
|
88
|
+
medium: "500",
|
|
89
|
+
semibold: "600",
|
|
90
|
+
bold: "700",
|
|
91
|
+
extrabold: "800",
|
|
92
|
+
black: "900",
|
|
93
|
+
};
|
|
94
|
+
css += complexClass("font-", "font-weight", fontWeight, breakpoints);
|
|
95
|
+
// letter-spacing
|
|
96
|
+
const letterSpacing = omit(spacing, "auto");
|
|
97
|
+
css += complexClass("tracking-", "letter-spacing", letterSpacing, breakpoints);
|
|
98
|
+
// line-height
|
|
99
|
+
const lineHeight = omit(spacing, "auto", "zero");
|
|
100
|
+
const extendedLineHeight = {
|
|
101
|
+
...lineHeight,
|
|
102
|
+
none: "1",
|
|
103
|
+
tight: "1.25",
|
|
104
|
+
snug: "1.3755",
|
|
105
|
+
normal: "1.5",
|
|
106
|
+
relaxed: "1.625",
|
|
107
|
+
loose: "2",
|
|
108
|
+
};
|
|
109
|
+
css += complexClass("leading-", "line-height", extendedLineHeight, breakpoints);
|
|
110
|
+
return css;
|
|
111
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { GrissoConfig } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Resuelve la configuración de Grisso.
|
|
4
|
+
* Patrón Tailwind v3:
|
|
5
|
+
* - Top-level keys reemplazan los defaults completamente
|
|
6
|
+
* - `extend` mergea superficialmente con defaults
|
|
7
|
+
*/
|
|
8
|
+
export declare function resolveConfig(configPath?: string): Promise<GrissoConfig>;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { pathToFileURL } from "node:url";
|
|
3
|
+
import defaults from "./defaults.js";
|
|
4
|
+
/**
|
|
5
|
+
* Resuelve la configuración de Grisso.
|
|
6
|
+
* Patrón Tailwind v3:
|
|
7
|
+
* - Top-level keys reemplazan los defaults completamente
|
|
8
|
+
* - `extend` mergea superficialmente con defaults
|
|
9
|
+
*/
|
|
10
|
+
export async function resolveConfig(configPath) {
|
|
11
|
+
let userConfig;
|
|
12
|
+
if (configPath) {
|
|
13
|
+
const resolved = path.resolve(configPath);
|
|
14
|
+
const mod = await import(pathToFileURL(resolved).href);
|
|
15
|
+
userConfig = mod.default;
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
try {
|
|
19
|
+
const defaultPath = path.resolve(process.cwd(), "grisso.config.mjs");
|
|
20
|
+
const mod = await import(pathToFileURL(defaultPath).href);
|
|
21
|
+
userConfig = mod.default;
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return { ...defaults };
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
const { extend, ...overrides } = userConfig;
|
|
28
|
+
// Top-level keys reemplazan defaults completamente
|
|
29
|
+
const config = { ...defaults };
|
|
30
|
+
for (const [key, value] of Object.entries(overrides)) {
|
|
31
|
+
if (key in config) {
|
|
32
|
+
config[key] = value;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
// extend mergea superficialmente con defaults
|
|
36
|
+
if (extend && typeof extend === "object" && !Array.isArray(extend)) {
|
|
37
|
+
for (const [key, value] of Object.entries(extend)) {
|
|
38
|
+
const current = config[key];
|
|
39
|
+
if (key in config &&
|
|
40
|
+
typeof current === "object" &&
|
|
41
|
+
current !== null &&
|
|
42
|
+
!Array.isArray(current)) {
|
|
43
|
+
config[key] = {
|
|
44
|
+
...current,
|
|
45
|
+
...value,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
config[key] = value;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return config;
|
|
54
|
+
}
|
package/lib/types.d.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/** Mapa de breakpoints: nombre → media query */
|
|
2
|
+
export type Breakpoints = Record<string, string>;
|
|
3
|
+
/** Mapa de tokens: nombre → valor CSS */
|
|
4
|
+
export type TokenMap = Record<string, string>;
|
|
5
|
+
/** Mapa de declaraciones CSS: propiedad → valor */
|
|
6
|
+
export type Declarations = Record<string, string>;
|
|
7
|
+
/** Configuración completa de Grisso */
|
|
8
|
+
export interface GrissoConfig {
|
|
9
|
+
columns: number;
|
|
10
|
+
breakpoints: Breakpoints;
|
|
11
|
+
spacing: TokenMap;
|
|
12
|
+
brandColors: TokenMap;
|
|
13
|
+
foregroundColors: TokenMap;
|
|
14
|
+
iconColors: TokenMap;
|
|
15
|
+
supportColors: TokenMap;
|
|
16
|
+
backgroundColors: TokenMap;
|
|
17
|
+
overlayColors: TokenMap;
|
|
18
|
+
borderWidth: TokenMap;
|
|
19
|
+
opacity: TokenMap;
|
|
20
|
+
shadows: TokenMap;
|
|
21
|
+
borderColors: TokenMap;
|
|
22
|
+
[key: string]: unknown;
|
|
23
|
+
}
|
|
24
|
+
/** Función parcial que genera CSS a partir de la config */
|
|
25
|
+
export type PartialFn = (config: GrissoConfig) => string;
|
package/lib/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/lib/utils.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { TokenMap } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Elimina keys de un objeto.
|
|
4
|
+
* Equivalente a sass:map.remove()
|
|
5
|
+
*/
|
|
6
|
+
export declare function omit(obj: TokenMap, ...keys: string[]): TokenMap;
|
|
7
|
+
/**
|
|
8
|
+
* Calcula un porcentaje con 10 decimales (paridad con Dart Sass).
|
|
9
|
+
* fractionPercent(1, 12) → "8.3333333333%"
|
|
10
|
+
* fractionPercent(3, 12) → "25%"
|
|
11
|
+
*/
|
|
12
|
+
export declare function fractionPercent(numerator: number, denominator: number): string;
|
package/lib/utils.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Elimina keys de un objeto.
|
|
3
|
+
* Equivalente a sass:map.remove()
|
|
4
|
+
*/
|
|
5
|
+
export function omit(obj, ...keys) {
|
|
6
|
+
const result = { ...obj };
|
|
7
|
+
for (const key of keys) {
|
|
8
|
+
delete result[key];
|
|
9
|
+
}
|
|
10
|
+
return result;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Calcula un porcentaje con 10 decimales (paridad con Dart Sass).
|
|
14
|
+
* fractionPercent(1, 12) → "8.3333333333%"
|
|
15
|
+
* fractionPercent(3, 12) → "25%"
|
|
16
|
+
*/
|
|
17
|
+
export function fractionPercent(numerator, denominator) {
|
|
18
|
+
const value = ((numerator / denominator) * 100).toFixed(10);
|
|
19
|
+
return value.replace(/\.?0+$/, "") + "%";
|
|
20
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@hiscovega/grisso",
|
|
3
|
+
"description": "Griddo CSS utility class library",
|
|
4
|
+
"version": "1.0.0",
|
|
5
|
+
"license": "UNLICENSED",
|
|
6
|
+
"private": false,
|
|
7
|
+
"type": "module",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"style": "./dist/grisso.css"
|
|
11
|
+
},
|
|
12
|
+
"./plugin": "./plugin.js",
|
|
13
|
+
"./config": "./lib/defaults.js",
|
|
14
|
+
"./tokens-example.css": "./tokens-example.css"
|
|
15
|
+
},
|
|
16
|
+
"engines": {
|
|
17
|
+
"node": ">=24"
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"dist/",
|
|
21
|
+
"lib/",
|
|
22
|
+
"plugin.js",
|
|
23
|
+
"tokens-example.css",
|
|
24
|
+
"README.md"
|
|
25
|
+
],
|
|
26
|
+
"scripts": {
|
|
27
|
+
"build": "tsc && node scripts/build.js",
|
|
28
|
+
"typecheck": "tsc --noEmit",
|
|
29
|
+
"lint": "biome check .",
|
|
30
|
+
"lint:fix": "biome check --write .",
|
|
31
|
+
"playground": "npm run build && node scripts/build.js --config playground/grisso.config.mjs --content playground/index.html --content playground/example.module.css --output playground/grisso.css && open playground/index.html",
|
|
32
|
+
"prepublishOnly": "npm run build"
|
|
33
|
+
},
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"@fullhuman/postcss-purgecss": "^6.0.0"
|
|
36
|
+
},
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@biomejs/biome": "2.4.5",
|
|
39
|
+
"@types/node": "^25.3.3",
|
|
40
|
+
"postcss": "^8.4.47",
|
|
41
|
+
"postcss-cli": "^11.0.0",
|
|
42
|
+
"postcss-combine-duplicated-selectors": "^10.0.3",
|
|
43
|
+
"postcss-discard-empty": "^6.0.0",
|
|
44
|
+
"postcss-minify": "^1.1.0",
|
|
45
|
+
"postcss-preset-env": "^10.0.3",
|
|
46
|
+
"postcss-sort-media-queries": "^5.2.0",
|
|
47
|
+
"typescript": "^5.9.3"
|
|
48
|
+
}
|
|
49
|
+
}
|
package/plugin.js
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { generateCSS } from "./lib/index.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* PostCSS plugin de Grisso.
|
|
5
|
+
* Genera CSS desde JS y aplica tree-shaking usando PurgeCSS
|
|
6
|
+
* si se pasan rutas de contenido.
|
|
7
|
+
*
|
|
8
|
+
* @param {Object} options
|
|
9
|
+
* @param {string[]} [options.content] - Rutas glob de archivos a escanear para tree-shaking.
|
|
10
|
+
* Si se omite, se incluye todo el CSS de Grisso (útil en desarrollo).
|
|
11
|
+
* @param {string} [options.config] - Ruta a grisso.config.mjs del consumidor.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* // postcss.config.js del proyecto consumidor
|
|
15
|
+
* import grisso from "@griddo/grisso/plugin";
|
|
16
|
+
* export default {
|
|
17
|
+
* plugins: [
|
|
18
|
+
* grisso({ content: ["./src/**\/*.{js,ts,jsx,tsx,css}"] })
|
|
19
|
+
* ]
|
|
20
|
+
* }
|
|
21
|
+
*/
|
|
22
|
+
export default function grissoPlugin(options = {}) {
|
|
23
|
+
const { content, config: configPath } = options;
|
|
24
|
+
|
|
25
|
+
return {
|
|
26
|
+
postcssPlugin: "postcss-grisso",
|
|
27
|
+
async Once(root, { parse }) {
|
|
28
|
+
const grissoSource = await generateCSS(configPath);
|
|
29
|
+
|
|
30
|
+
if (!content || content.length === 0) {
|
|
31
|
+
// Sin tree-shaking: inyectar todo el CSS
|
|
32
|
+
const grissoRoot = parse(grissoSource);
|
|
33
|
+
grissoRoot.each((node) => root.prepend(node.clone()));
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Con tree-shaking: usar PurgeCSS para eliminar clases no usadas
|
|
38
|
+
const { PurgeCSS } = await import("purgecss");
|
|
39
|
+
|
|
40
|
+
const purgecss = new PurgeCSS();
|
|
41
|
+
const [result] = await purgecss.purge({
|
|
42
|
+
content,
|
|
43
|
+
css: [{ raw: grissoSource }],
|
|
44
|
+
extractors: [
|
|
45
|
+
{
|
|
46
|
+
// Extractor para uso directo en HTML/JSX: class="flex gap-md"
|
|
47
|
+
extractor: (content) => content.match(/[A-Za-z0-9_-]+/g) || [],
|
|
48
|
+
extensions: ["html", "jsx", "tsx", "js", "ts"],
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
// Extractor para CSS Modules: composes: flex gap-md from global
|
|
52
|
+
extractor: (content) => {
|
|
53
|
+
const matches = content.match(/composes:\s*([^;]+)\s*from\s+global/g) || [];
|
|
54
|
+
const classes = [];
|
|
55
|
+
for (const match of matches) {
|
|
56
|
+
const classStr = match.replace(/composes:\s*/, "").replace(/\s*from\s+global/, "");
|
|
57
|
+
classes.push(...classStr.trim().split(/\s+/));
|
|
58
|
+
}
|
|
59
|
+
return classes;
|
|
60
|
+
},
|
|
61
|
+
extensions: ["css"],
|
|
62
|
+
},
|
|
63
|
+
],
|
|
64
|
+
safelist: {
|
|
65
|
+
// Preservar clases de fondo (bg-) que pueden construirse dinámicamente
|
|
66
|
+
greedy: [/^bg-/],
|
|
67
|
+
},
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
const purgedCSS = result ? result.css : grissoSource;
|
|
71
|
+
const grissoRoot = parse(purgedCSS);
|
|
72
|
+
grissoRoot.each((node) => root.prepend(node.clone()));
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
grissoPlugin.postcss = true;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/* @griddo/grisso — tokens-example.css
|
|
2
|
+
Copia este archivo y adapta los valores a tu design system.
|
|
3
|
+
Define estas variables en :root o en el scope que prefieras.
|
|
4
|
+
|
|
5
|
+
Todas las clases de Grisso referencian estas custom properties,
|
|
6
|
+
por lo que cambiar estos valores afecta a toda la librería sin
|
|
7
|
+
necesidad de recompilar el SCSS.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
:root {
|
|
11
|
+
/* ─── Spacing ─────────────────────────────────────────────── */
|
|
12
|
+
--spc-4xs: 2px;
|
|
13
|
+
--spc-3xs: 4px;
|
|
14
|
+
--spc-2xs: 8px;
|
|
15
|
+
--spc-xs: 12px;
|
|
16
|
+
--spc-sm: 16px;
|
|
17
|
+
--spc-md: 24px;
|
|
18
|
+
--spc-lg: 32px;
|
|
19
|
+
--spc-xl: 40px;
|
|
20
|
+
--spc-2xl: 48px;
|
|
21
|
+
--spc-3xl: 64px;
|
|
22
|
+
--spc-4xl: 80px;
|
|
23
|
+
--spc-5xl: 96px;
|
|
24
|
+
|
|
25
|
+
/* ─── Colors: texto ───────────────────────────────────────── */
|
|
26
|
+
--text-1: #111827;
|
|
27
|
+
--text-2: #374151;
|
|
28
|
+
--text-3: #6b7280;
|
|
29
|
+
--text-4: #9ca3af;
|
|
30
|
+
|
|
31
|
+
/* ─── Colors: fondo ───────────────────────────────────────── */
|
|
32
|
+
--bg-ui: #ffffff;
|
|
33
|
+
--bg-1: #f9fafb;
|
|
34
|
+
--bg-2: #f3f4f6;
|
|
35
|
+
--bg-3: #e5e7eb;
|
|
36
|
+
--bg-4: #d1d5db;
|
|
37
|
+
--bg-5: #9ca3af;
|
|
38
|
+
--bg-disabled: #e5e7eb;
|
|
39
|
+
|
|
40
|
+
/* ─── Colors: bordes ──────────────────────────────────────── */
|
|
41
|
+
--border-1: #e5e7eb;
|
|
42
|
+
--border-2: #d1d5db;
|
|
43
|
+
--border-3: #9ca3af;
|
|
44
|
+
--border-4: #6b7280;
|
|
45
|
+
--border-disabled: #d1d5db;
|
|
46
|
+
|
|
47
|
+
/* ─── Colors: iconos ──────────────────────────────────────── */
|
|
48
|
+
--icon-1: #111827;
|
|
49
|
+
--icon-2: #374151;
|
|
50
|
+
--icon-3: #6b7280;
|
|
51
|
+
--icon-4: #9ca3af;
|
|
52
|
+
--icon-disabled: #d1d5db;
|
|
53
|
+
|
|
54
|
+
/* ─── Colors: overlays ────────────────────────────────────── */
|
|
55
|
+
--overlay-1: rgba(0 0 0 / 0.1);
|
|
56
|
+
--overlay-2: rgba(0 0 0 / 0.2);
|
|
57
|
+
--overlay-3: rgba(0 0 0 / 0.4);
|
|
58
|
+
--overlay-4: rgba(0 0 0 / 0.7);
|
|
59
|
+
|
|
60
|
+
/* ─── Border widths ───────────────────────────────────────── */
|
|
61
|
+
--border-width-none: 0px;
|
|
62
|
+
--border-width-xs: 1px;
|
|
63
|
+
--border-width-sm: 2px;
|
|
64
|
+
--border-width-md: 4px;
|
|
65
|
+
--border-width-lg: 8px;
|
|
66
|
+
|
|
67
|
+
/* ─── Opacidad ────────────────────────────────────────────── */
|
|
68
|
+
--opacity-1: 0.1;
|
|
69
|
+
--opacity-2: 0.2;
|
|
70
|
+
--opacity-3: 0.4;
|
|
71
|
+
--opacity-4: 0.6;
|
|
72
|
+
--opacity-5: 0.75;
|
|
73
|
+
--opacity-6: 0.9;
|
|
74
|
+
|
|
75
|
+
/* ─── Sombras ─────────────────────────────────────────────── */
|
|
76
|
+
--box-shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05);
|
|
77
|
+
--box-shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1);
|
|
78
|
+
--box-shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1);
|
|
79
|
+
--box-shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.1);
|
|
80
|
+
}
|