eva-css-ycode 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 +170 -0
- package/dist/cli.js +443 -0
- package/dist/index.d.mts +56 -0
- package/dist/index.d.ts +56 -0
- package/dist/index.js +372 -0
- package/dist/index.mjs +342 -0
- package/package.json +30 -0
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
// src/clamp.ts
|
|
2
|
+
function round2(n) {
|
|
3
|
+
return Math.round(n * 100) / 100;
|
|
4
|
+
}
|
|
5
|
+
function getPercent(size, screen, ratio = 100) {
|
|
6
|
+
return round2(size / screen * ratio);
|
|
7
|
+
}
|
|
8
|
+
function toRem(size) {
|
|
9
|
+
return size / 16;
|
|
10
|
+
}
|
|
11
|
+
function getMinRem(percent, min) {
|
|
12
|
+
return round2(percent * min);
|
|
13
|
+
}
|
|
14
|
+
function getMaxRem(percent, max) {
|
|
15
|
+
return round2(percent * max);
|
|
16
|
+
}
|
|
17
|
+
function getVW(percent) {
|
|
18
|
+
return round2(percent);
|
|
19
|
+
}
|
|
20
|
+
function getFinalMinDiv(size, ratio) {
|
|
21
|
+
return round2(size / ratio);
|
|
22
|
+
}
|
|
23
|
+
function getFinalMinMulti(size, ratio) {
|
|
24
|
+
return round2(size * ratio);
|
|
25
|
+
}
|
|
26
|
+
function vwLight(calcPercent, sizeRem) {
|
|
27
|
+
return {
|
|
28
|
+
vw: round2(getVW(calcPercent) / 4),
|
|
29
|
+
offset: round2(sizeRem / 1.33)
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
function vwMedium(calcPercent, sizeRem) {
|
|
33
|
+
return {
|
|
34
|
+
vw: round2(getVW(calcPercent) / 2),
|
|
35
|
+
offset: round2(sizeRem / 2)
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
function vwStrong(calcPercent, sizeRem) {
|
|
39
|
+
return {
|
|
40
|
+
vw: round2(getVW(calcPercent) / 1.33),
|
|
41
|
+
offset: round2(sizeRem / 4)
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
function vwExtrem(calcPercentEz, remMin) {
|
|
45
|
+
return {
|
|
46
|
+
vw: getVW(calcPercentEz),
|
|
47
|
+
offset: round2(-remMin)
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
function formatClamp(min, fluid, max) {
|
|
51
|
+
const minStr = `${round2(min)}rem`;
|
|
52
|
+
const maxStr = `${round2(max)}rem`;
|
|
53
|
+
const sign = fluid.offset >= 0 ? "+" : "-";
|
|
54
|
+
const absOffset = round2(Math.abs(fluid.offset));
|
|
55
|
+
const fluidStr = `${fluid.vw}vw ${sign} ${absOffset}rem`;
|
|
56
|
+
return `clamp(${minStr}, ${fluidStr}, ${maxStr})`;
|
|
57
|
+
}
|
|
58
|
+
function generateSpacingClamp(sizePx, screen, phi, min, max, ez, intensity) {
|
|
59
|
+
const calcPercent = getPercent(sizePx, screen);
|
|
60
|
+
const calcPercentEz = getPercent(sizePx, screen, ez);
|
|
61
|
+
const sizeRem = toRem(sizePx);
|
|
62
|
+
const remMin = getMinRem(calcPercent, min);
|
|
63
|
+
const remMax = getMaxRem(calcPercent, max);
|
|
64
|
+
switch (intensity) {
|
|
65
|
+
// __ = extreme (most fluid)
|
|
66
|
+
case "__": {
|
|
67
|
+
const fluid = vwExtrem(calcPercentEz, remMin);
|
|
68
|
+
return formatClamp(min, fluid, remMax);
|
|
69
|
+
}
|
|
70
|
+
// _ = strong
|
|
71
|
+
case "_": {
|
|
72
|
+
const finalMin = getFinalMinDiv(remMin, phi);
|
|
73
|
+
const fluid = vwStrong(calcPercent, sizeRem);
|
|
74
|
+
return formatClamp(finalMin, fluid, remMax);
|
|
75
|
+
}
|
|
76
|
+
// '' = normal (default)
|
|
77
|
+
case "": {
|
|
78
|
+
const fluid = vwMedium(calcPercent, sizeRem);
|
|
79
|
+
return formatClamp(remMin, fluid, remMax);
|
|
80
|
+
}
|
|
81
|
+
// - = light (least fluid)
|
|
82
|
+
case "-": {
|
|
83
|
+
const finalMin = getFinalMinMulti(remMin, phi);
|
|
84
|
+
const fluid = vwLight(calcPercent, sizeRem);
|
|
85
|
+
return formatClamp(finalMin, fluid, remMax);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
function generateFontClamp(sizePx, screen, phi, min, max, intensity) {
|
|
90
|
+
const calcPercent = getPercent(sizePx, screen);
|
|
91
|
+
const sizeRem = toRem(sizePx);
|
|
92
|
+
const remMin = getMinRem(calcPercent, min);
|
|
93
|
+
const remMax = getMaxRem(calcPercent, max);
|
|
94
|
+
switch (intensity) {
|
|
95
|
+
// __ = most fluid (uses vw-strong + min/phi)
|
|
96
|
+
case "__": {
|
|
97
|
+
const finalMin = getFinalMinDiv(remMin, phi);
|
|
98
|
+
const fluid = vwStrong(calcPercent, sizeRem);
|
|
99
|
+
return formatClamp(finalMin, fluid, remMax);
|
|
100
|
+
}
|
|
101
|
+
// _ = medium (uses vw-medium + remMin)
|
|
102
|
+
case "_": {
|
|
103
|
+
const fluid = vwMedium(calcPercent, sizeRem);
|
|
104
|
+
return formatClamp(remMin, fluid, remMax);
|
|
105
|
+
}
|
|
106
|
+
// '' = least fluid (uses vw-light + min*phi)
|
|
107
|
+
case "": {
|
|
108
|
+
const finalMin = getFinalMinMulti(remMin, phi);
|
|
109
|
+
const fluid = vwLight(calcPercent, sizeRem);
|
|
110
|
+
return formatClamp(finalMin, fluid, remMax);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// src/types.ts
|
|
116
|
+
var PROPERTY_MAP = {
|
|
117
|
+
// Sizing
|
|
118
|
+
h: "height",
|
|
119
|
+
w: "width",
|
|
120
|
+
"min-h": "min-height",
|
|
121
|
+
"min-w": "min-width",
|
|
122
|
+
"max-w": "max-width",
|
|
123
|
+
"max-h": "max-height",
|
|
124
|
+
// Padding
|
|
125
|
+
p: "padding",
|
|
126
|
+
px: "padding-inline",
|
|
127
|
+
py: "padding-block",
|
|
128
|
+
pt: "padding-top",
|
|
129
|
+
pr: "padding-right",
|
|
130
|
+
pb: "padding-bottom",
|
|
131
|
+
pl: "padding-left",
|
|
132
|
+
// Margin
|
|
133
|
+
m: "margin",
|
|
134
|
+
mx: "margin-inline",
|
|
135
|
+
my: "margin-block",
|
|
136
|
+
mt: "margin-top",
|
|
137
|
+
mr: "margin-right",
|
|
138
|
+
mb: "margin-bottom",
|
|
139
|
+
ml: "margin-left",
|
|
140
|
+
// Layout
|
|
141
|
+
gap: "gap",
|
|
142
|
+
// Borders
|
|
143
|
+
rounded: "border-radius"
|
|
144
|
+
};
|
|
145
|
+
var FONT_PROPERTY_MAP = {
|
|
146
|
+
text: "font-size"
|
|
147
|
+
};
|
|
148
|
+
var SPACING_INTENSITIES = ["__", "_", "", "-"];
|
|
149
|
+
var FONT_INTENSITIES = ["__", "_", ""];
|
|
150
|
+
var DATA_EVA_MAP = {
|
|
151
|
+
extreme: "__",
|
|
152
|
+
strong: "_",
|
|
153
|
+
// normal = default (no data-eva needed)
|
|
154
|
+
light: "-"
|
|
155
|
+
};
|
|
156
|
+
var DATA_EVA_FONT_MAP = {
|
|
157
|
+
extreme: "__",
|
|
158
|
+
strong: "_"
|
|
159
|
+
// normal = default (no data-eva needed)
|
|
160
|
+
};
|
|
161
|
+
function resolveConfig(config) {
|
|
162
|
+
return {
|
|
163
|
+
sizes: config.sizes,
|
|
164
|
+
fontSizes: config.fontSizes,
|
|
165
|
+
screen: config.screen ?? 1440,
|
|
166
|
+
phi: config.phi ?? 1.61803398875,
|
|
167
|
+
fontPhi: config.fontPhi ?? 1.3,
|
|
168
|
+
min: config.min ?? 0.5,
|
|
169
|
+
fontMin: config.fontMin ?? 0.5,
|
|
170
|
+
max: config.max ?? 1,
|
|
171
|
+
ez: config.ez ?? 142.4,
|
|
172
|
+
defaultIntensity: config.defaultIntensity ?? ""
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// src/generator.ts
|
|
177
|
+
function escapeTwClass(prefix, value) {
|
|
178
|
+
return `.${prefix}-\\[${value}\\]`;
|
|
179
|
+
}
|
|
180
|
+
function generateRootVars(cfg) {
|
|
181
|
+
const lines = [":root {"];
|
|
182
|
+
for (const size of cfg.sizes) {
|
|
183
|
+
lines.push(` /* ---- ${size}px ---- */`);
|
|
184
|
+
for (const intensity of SPACING_INTENSITIES) {
|
|
185
|
+
const clamp = generateSpacingClamp(
|
|
186
|
+
size,
|
|
187
|
+
cfg.screen,
|
|
188
|
+
cfg.phi,
|
|
189
|
+
cfg.min,
|
|
190
|
+
cfg.max,
|
|
191
|
+
cfg.ez,
|
|
192
|
+
intensity
|
|
193
|
+
);
|
|
194
|
+
lines.push(` --${size}${intensity}: ${clamp};`);
|
|
195
|
+
}
|
|
196
|
+
lines.push("");
|
|
197
|
+
}
|
|
198
|
+
for (const size of cfg.fontSizes) {
|
|
199
|
+
lines.push(` /* ---- fs-${size}px ---- */`);
|
|
200
|
+
for (const intensity of FONT_INTENSITIES) {
|
|
201
|
+
const clamp = generateFontClamp(
|
|
202
|
+
size,
|
|
203
|
+
cfg.screen,
|
|
204
|
+
cfg.fontPhi,
|
|
205
|
+
cfg.fontMin,
|
|
206
|
+
cfg.max,
|
|
207
|
+
intensity
|
|
208
|
+
);
|
|
209
|
+
lines.push(` --fs-${size}${intensity}: ${clamp};`);
|
|
210
|
+
}
|
|
211
|
+
lines.push("");
|
|
212
|
+
}
|
|
213
|
+
lines.push("}");
|
|
214
|
+
return lines.join("\n");
|
|
215
|
+
}
|
|
216
|
+
function generateDefaultOverrides(cfg) {
|
|
217
|
+
const lines = [];
|
|
218
|
+
const suffix = cfg.defaultIntensity;
|
|
219
|
+
for (const size of cfg.sizes) {
|
|
220
|
+
lines.push(`/* ---- ${size}px ---- */`);
|
|
221
|
+
const varRef = `var(--${size}${suffix})`;
|
|
222
|
+
for (const [twPrefix, cssProp] of Object.entries(PROPERTY_MAP)) {
|
|
223
|
+
lines.push(`${escapeTwClass(twPrefix, `${size}px`)} { ${cssProp}: ${varRef} }`);
|
|
224
|
+
}
|
|
225
|
+
lines.push("");
|
|
226
|
+
}
|
|
227
|
+
const fontSuffix = cfg.defaultIntensity === "-" ? "" : cfg.defaultIntensity;
|
|
228
|
+
for (const size of cfg.fontSizes) {
|
|
229
|
+
const varRef = `var(--fs-${size}${fontSuffix})`;
|
|
230
|
+
for (const [twPrefix, cssProp] of Object.entries(FONT_PROPERTY_MAP)) {
|
|
231
|
+
lines.push(`${escapeTwClass(twPrefix, `${size}px`)} { ${cssProp}: ${varRef} }`);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
lines.push("");
|
|
235
|
+
const allSizes = /* @__PURE__ */ new Set([...cfg.sizes]);
|
|
236
|
+
const remEntries = [];
|
|
237
|
+
for (const size of allSizes) {
|
|
238
|
+
const rem = size / 16;
|
|
239
|
+
if (rem === Math.round(rem * 100) / 100 && rem > 0) {
|
|
240
|
+
remEntries.push({ rem, size });
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
if (remEntries.length > 0) {
|
|
244
|
+
lines.push("/* ---- rem mappings ---- */");
|
|
245
|
+
for (const { rem, size } of remEntries) {
|
|
246
|
+
const remStr = rem % 1 === 0 ? `${rem}rem` : `${rem}rem`;
|
|
247
|
+
const varRef = `var(--${size}${suffix})`;
|
|
248
|
+
for (const [twPrefix, cssProp] of Object.entries(PROPERTY_MAP)) {
|
|
249
|
+
lines.push(`${escapeTwClass(twPrefix, remStr)} { ${cssProp}: ${varRef} }`);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
lines.push("");
|
|
253
|
+
}
|
|
254
|
+
const fontRemEntries = [];
|
|
255
|
+
for (const size of cfg.fontSizes) {
|
|
256
|
+
const rem = size / 16;
|
|
257
|
+
if (rem === Math.round(rem * 100) / 100 && rem > 0) {
|
|
258
|
+
fontRemEntries.push({ rem, size });
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
if (fontRemEntries.length > 0) {
|
|
262
|
+
for (const { rem, size } of fontRemEntries) {
|
|
263
|
+
const remStr = rem % 1 === 0 ? `${rem}rem` : `${rem}rem`;
|
|
264
|
+
const varRef = `var(--fs-${size}${fontSuffix})`;
|
|
265
|
+
for (const [twPrefix, cssProp] of Object.entries(FONT_PROPERTY_MAP)) {
|
|
266
|
+
lines.push(`${escapeTwClass(twPrefix, remStr)} { ${cssProp}: ${varRef} }`);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
lines.push("");
|
|
270
|
+
}
|
|
271
|
+
return lines.join("\n");
|
|
272
|
+
}
|
|
273
|
+
function generateResponsiveOverrides(cfg) {
|
|
274
|
+
const lines = [];
|
|
275
|
+
const suffix = cfg.defaultIntensity;
|
|
276
|
+
const fontSuffix = cfg.defaultIntensity === "-" ? "" : cfg.defaultIntensity;
|
|
277
|
+
lines.push("/* ---- max-md responsive overrides ---- */");
|
|
278
|
+
lines.push("@media (width < 48rem) {");
|
|
279
|
+
for (const size of cfg.sizes) {
|
|
280
|
+
const varRef = `var(--${size}${suffix})`;
|
|
281
|
+
for (const [twPrefix, cssProp] of Object.entries(PROPERTY_MAP)) {
|
|
282
|
+
lines.push(` .max-md\\:${twPrefix}-\\[${size}px\\] { ${cssProp}: ${varRef} }`);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
for (const size of cfg.fontSizes) {
|
|
286
|
+
const varRef = `var(--fs-${size}${fontSuffix})`;
|
|
287
|
+
for (const [twPrefix, cssProp] of Object.entries(FONT_PROPERTY_MAP)) {
|
|
288
|
+
lines.push(` .max-md\\:${twPrefix}-\\[${size}px\\] { ${cssProp}: ${varRef} }`);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
lines.push("}");
|
|
292
|
+
lines.push("");
|
|
293
|
+
return lines.join("\n");
|
|
294
|
+
}
|
|
295
|
+
function generateIntensitySelectors(cfg) {
|
|
296
|
+
const lines = [];
|
|
297
|
+
for (const [evaValue, intensity] of Object.entries(DATA_EVA_MAP)) {
|
|
298
|
+
lines.push(`/* ---- data-eva="${evaValue}" (${intensity}) ---- */`);
|
|
299
|
+
for (const size of cfg.sizes) {
|
|
300
|
+
const varRef = `var(--${size}${intensity})`;
|
|
301
|
+
for (const [twPrefix, cssProp] of Object.entries(PROPERTY_MAP)) {
|
|
302
|
+
lines.push(`[data-eva="${evaValue}"] ${escapeTwClass(twPrefix, `${size}px`)} { ${cssProp}: ${varRef} }`);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
lines.push("");
|
|
306
|
+
}
|
|
307
|
+
for (const [evaValue, intensity] of Object.entries(DATA_EVA_FONT_MAP)) {
|
|
308
|
+
for (const size of cfg.fontSizes) {
|
|
309
|
+
const varRef = `var(--fs-${size}${intensity})`;
|
|
310
|
+
for (const [twPrefix, cssProp] of Object.entries(FONT_PROPERTY_MAP)) {
|
|
311
|
+
lines.push(`[data-eva="${evaValue}"] ${escapeTwClass(twPrefix, `${size}px`)} { ${cssProp}: ${varRef} }`);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
lines.push("");
|
|
316
|
+
return lines.join("\n");
|
|
317
|
+
}
|
|
318
|
+
function generateBridge(config) {
|
|
319
|
+
const cfg = resolveConfig(config);
|
|
320
|
+
const sections = [
|
|
321
|
+
"/* =============================================================",
|
|
322
|
+
" EVA CSS \xD7 yCode \u2014 Fluid Bridge",
|
|
323
|
+
" Generated by eva-css-ycode",
|
|
324
|
+
" ============================================================= */",
|
|
325
|
+
"",
|
|
326
|
+
"/* Section A \u2014 CSS Custom Properties */",
|
|
327
|
+
generateRootVars(cfg),
|
|
328
|
+
"",
|
|
329
|
+
"/* Section B \u2014 Tailwind Arbitrary Class Overrides */",
|
|
330
|
+
generateDefaultOverrides(cfg),
|
|
331
|
+
generateResponsiveOverrides(cfg),
|
|
332
|
+
"/* Section C \u2014 Per-Section Intensity Selectors */",
|
|
333
|
+
generateIntensitySelectors(cfg)
|
|
334
|
+
];
|
|
335
|
+
return sections.join("\n");
|
|
336
|
+
}
|
|
337
|
+
export {
|
|
338
|
+
FONT_PROPERTY_MAP,
|
|
339
|
+
PROPERTY_MAP,
|
|
340
|
+
generateBridge,
|
|
341
|
+
resolveConfig
|
|
342
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "eva-css-ycode",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Fluid design tokens bridge for yCode — converts Tailwind pixel values to clamp()",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.mjs",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"bin": {
|
|
9
|
+
"eva-ycode": "dist/cli.js"
|
|
10
|
+
},
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"import": "./dist/index.mjs",
|
|
15
|
+
"require": "./dist/index.js"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"files": ["dist"],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "tsup",
|
|
21
|
+
"dev": "tsup --watch",
|
|
22
|
+
"test": "node --test src/**/*.test.ts"
|
|
23
|
+
},
|
|
24
|
+
"keywords": ["eva-css", "ycode", "tailwind", "fluid", "clamp", "responsive"],
|
|
25
|
+
"license": "MIT",
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"tsup": "^8.0.0",
|
|
28
|
+
"typescript": "^5.4.0"
|
|
29
|
+
}
|
|
30
|
+
}
|