@vinicunca/unocss-preset 0.0.2 → 0.1.1

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/client.cjs CHANGED
@@ -1,5 +1,7 @@
1
1
  'use strict';
2
2
 
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
3
5
  function masonryGridPolyfill(selectors = ".masonry-grid") {
4
6
  const elements = [...document.querySelectorAll(selectors)];
5
7
  if (!elements.length) {
package/dist/index.cjs CHANGED
@@ -1,15 +1,16 @@
1
1
  'use strict';
2
2
 
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
3
5
  const jsUtilities = require('@vinicunca/js-utilities');
4
6
  const core = require('@unocss/core');
5
- const presetMini = require('@unocss/preset-mini');
6
- const unocss = require('unocss');
7
7
 
8
8
  const DEFAULT_PREFIX = "vin-";
9
9
  class PresetCore {
10
10
  constructor(options) {
11
- this.prefix = options.prefix ?? "";
12
- this.colorKeys = options.colorKeys ?? [];
11
+ this.prefix = options.prefix ?? DEFAULT_PREFIX;
12
+ this.classBase = options.classBase ?? "";
13
+ this.classProps = options.classProps ?? {};
13
14
  }
14
15
  genVariable(key = "") {
15
16
  return `--${this.prefix}${key}`;
@@ -21,14 +22,12 @@ class PresetCore {
21
22
  return prev;
22
23
  }, {});
23
24
  }
24
- getColorKeys() {
25
- return Array.from(new Set(this.colorKeys));
26
- }
27
25
  }
28
26
 
29
27
  class Color extends PresetCore {
30
28
  constructor(options) {
31
29
  super(options);
30
+ this.varTextOpacity = "--un-text-opacity";
32
31
  }
33
32
  getRules() {
34
33
  return [
@@ -38,17 +37,14 @@ class Color extends PresetCore {
38
37
  }
39
38
  getTextRule() {
40
39
  return [
41
- /^text-(?<body>(?:on-)?(?<color>.+))/,
40
+ /^text-brand-(?<body>(?:on-)?(?<color>.+))/,
42
41
  ({ groups }) => {
43
42
  const { body, color } = groups;
44
- if (!this.getColorKeys().includes(color)) {
45
- return;
46
- }
47
43
  const colorBody = /^on-[a-z]/.test(body) ? `on-${color}` : color;
48
44
  const colorVar = this.genVariable(`theme-${colorBody}`);
49
45
  return {
50
- "--un-color-opacity": 1,
51
- "color": `rgba(var(${colorVar}), var(--un-color-opacity))`
46
+ [this.varTextOpacity]: 1,
47
+ color: `rgba(var(${colorVar}), var(${this.varTextOpacity}))`
52
48
  };
53
49
  },
54
50
  { layer: "vinicunca" }
@@ -56,18 +52,15 @@ class Color extends PresetCore {
56
52
  }
57
53
  getBgRule() {
58
54
  return [
59
- /^bg-(.+)$/,
55
+ /^bg-brand-(.+)$/,
60
56
  ([, body]) => {
61
- if (!this.colorKeys.includes(body)) {
62
- return;
63
- }
64
57
  const bgColorVar = this.genVariable(`theme-${body}`);
65
58
  const colorVar = this.genVariable(`theme-on-${body}`);
66
59
  return {
67
- "--un-color-opacity": 1,
60
+ [this.varTextOpacity]: 1,
68
61
  "--un-bg-opacity": 1,
69
62
  "background-color": `rgba(var(${bgColorVar}),var(--un-bg-opacity))`,
70
- "color": `rgba(var(${colorVar}), var(--un-color-opacity))`
63
+ "color": `rgba(var(${colorVar}), var(${this.varTextOpacity}))`
71
64
  };
72
65
  },
73
66
  { layer: "vinicunca" }
@@ -143,7 +136,6 @@ const DEFAULT_THEME = {
143
136
  dark: false,
144
137
  colors: {
145
138
  "background": "#FFFFFF",
146
- "invert": "#000000",
147
139
  "surface": "#FFFFFF",
148
140
  "surface-variant": "#424242",
149
141
  "on-surface-variant": "#EEEEEE",
@@ -156,24 +148,23 @@ const DEFAULT_THEME = {
156
148
  },
157
149
  variables: {
158
150
  "border-color": "#000000",
159
- "border-opacity": 0.12,
160
- "high-emphasis-opacity": 0.87,
161
- "medium-emphasis-opacity": 0.6,
162
- "disabled-opacity": 0.38,
163
- "idle-opacity": 0.04,
164
- "hover-opacity": 0.04,
165
- "focus-opacity": 0.12,
166
- "selected-opacity": 0.08,
167
- "activated-opacity": 0.12,
168
- "pressed-opacity": 0.12,
169
- "dragged-opacity": 0.08
151
+ "opacity-border": 0.12,
152
+ "opacity-high-emphasis": 0.87,
153
+ "opacity-medium-emphasis": 0.6,
154
+ "opacity-disabled": 0.38,
155
+ "opacity-idle": 0.04,
156
+ "opacity-hover": 0.04,
157
+ "opacity-focus": 0.12,
158
+ "opacity-selected": 0.08,
159
+ "opacity-activated": 0.12,
160
+ "opacity-pressed": 0.12,
161
+ "opacity-dragged": 0.08
170
162
  }
171
163
  },
172
164
  dark: {
173
165
  dark: true,
174
166
  colors: {
175
167
  "background": "#121212",
176
- "invert": "#FFFFFF",
177
168
  "surface": "#212121",
178
169
  "surface-variant": "#BDBDBD",
179
170
  "on-surface-variant": "#424242",
@@ -186,17 +177,17 @@ const DEFAULT_THEME = {
186
177
  },
187
178
  variables: {
188
179
  "border-color": "#FFFFFF",
189
- "border-opacity": 0.12,
190
- "high-emphasis-opacity": 0.87,
191
- "medium-emphasis-opacity": 0.6,
192
- "disabled-opacity": 0.38,
193
- "idle-opacity": 0.1,
194
- "hover-opacity": 0.04,
195
- "focus-opacity": 0.12,
196
- "selected-opacity": 0.08,
197
- "activated-opacity": 0.12,
198
- "pressed-opacity": 0.16,
199
- "dragged-opacity": 0.08
180
+ "opacity-border": 0.12,
181
+ "opacity-high-emphasis": 0.87,
182
+ "opacity-medium-emphasis": 0.6,
183
+ "opacity-disabled": 0.38,
184
+ "opacity-idle": 0.1,
185
+ "opacity-hover": 0.04,
186
+ "opacity-focus": 0.12,
187
+ "opacity-selected": 0.08,
188
+ "opacity-activated": 0.12,
189
+ "opacity-pressed": 0.16,
190
+ "opacity-dragged": 0.08
200
191
  }
201
192
  }
202
193
  };
@@ -205,98 +196,7 @@ function createCssSelector({ selector, content }) {
205
196
  return `${selector} { ${content.join(" ")} }`;
206
197
  }
207
198
 
208
- function generateRGBs(colors) {
209
- const theme = {};
210
- for (const color of Object.keys(colors)) {
211
- let colorKey = color;
212
- if (/^on-[a-z]/.test(color)) {
213
- colorKey = jsUtilities.toCamelCase(color);
214
- }
215
- const data = presetMini.parseColor(color, {
216
- colors: {
217
- [colorKey]: colors[color]
218
- }
219
- });
220
- if (data?.cssColor?.components) {
221
- const colorValue = data.cssColor.components.join(",");
222
- theme[color] = colorValue;
223
- }
224
- }
225
- return theme;
226
- }
227
- function colorToInt(color) {
228
- let rgb;
229
- if (typeof color === "number") {
230
- rgb = color;
231
- } else if (typeof color === "string") {
232
- let c = color.startsWith("#") ? color.substring(1) : color;
233
- if (c.length === 3) {
234
- c = c.split("").map((char) => char + char).join("");
235
- }
236
- if (c.length !== 6 && c.length !== 8) {
237
- console.warn(`'${color}' is not a valid rgb color`);
238
- }
239
- rgb = parseInt(c, 16);
240
- } else {
241
- throw new TypeError(`Colors can only be numbers or strings, recieved ${color == null ? color : color.constructor.name} instead`);
242
- }
243
- if (rgb < 0) {
244
- console.warn(`Colors cannot be negative: '${color}'`);
245
- rgb = 0;
246
- } else if (rgb > 4294967295 || isNaN(rgb)) {
247
- console.warn(`'${color}' is not a valid rgb color`);
248
- rgb = 16777215;
249
- }
250
- return rgb;
251
- }
252
-
253
- const mainTRC = 2.4;
254
- const Rco = 0.2126729;
255
- const Gco = 0.7151522;
256
- const Bco = 0.072175;
257
- const normBG = 0.55;
258
- const normTXT = 0.58;
259
- const revTXT = 0.57;
260
- const revBG = 0.62;
261
- const blkThrs = 0.03;
262
- const blkClmp = 1.45;
263
- const deltaYmin = 5e-4;
264
- const scaleBoW = 1.25;
265
- const scaleWoB = 1.25;
266
- const loConThresh = 0.078;
267
- const loConFactor = 12.82051282051282;
268
- const loConOffset = 0.06;
269
- const loClip = 1e-3;
270
- function APCAcontrast(text, background) {
271
- const Rtxt = ((text >> 16 & 255) / 255) ** mainTRC;
272
- const Gtxt = ((text >> 8 & 255) / 255) ** mainTRC;
273
- const Btxt = ((text >> 0 & 255) / 255) ** mainTRC;
274
- const Rbg = ((background >> 16 & 255) / 255) ** mainTRC;
275
- const Gbg = ((background >> 8 & 255) / 255) ** mainTRC;
276
- const Bbg = ((background >> 0 & 255) / 255) ** mainTRC;
277
- let Ytxt = Rtxt * Rco + Gtxt * Gco + Btxt * Bco;
278
- let Ybg = Rbg * Rco + Gbg * Gco + Bbg * Bco;
279
- if (Ytxt <= blkThrs) {
280
- Ytxt += (blkThrs - Ytxt) ** blkClmp;
281
- }
282
- if (Ybg <= blkThrs) {
283
- Ybg += (blkThrs - Ybg) ** blkClmp;
284
- }
285
- if (Math.abs(Ybg - Ytxt) < deltaYmin) {
286
- return 0;
287
- }
288
- let outputContrast;
289
- if (Ybg > Ytxt) {
290
- const SAPC = (Ybg ** normBG - Ytxt ** normTXT) * scaleBoW;
291
- outputContrast = SAPC < loClip ? 0 : SAPC < loConThresh ? SAPC - SAPC * loConFactor * loConOffset : SAPC - loConOffset;
292
- } else {
293
- const SAPC = (Ybg ** revBG - Ytxt ** revTXT) * scaleWoB;
294
- outputContrast = SAPC > -loClip ? 0 : SAPC > -loConThresh ? SAPC - SAPC * loConFactor * loConOffset : SAPC + loConOffset;
295
- }
296
- return outputContrast * 100;
297
- }
298
-
299
- class Theme extends PresetCore {
199
+ class Brand extends PresetCore {
300
200
  constructor(options) {
301
201
  super(options);
302
202
  const parsedOptions = this.parseThemeOptions(options?.themes);
@@ -309,18 +209,39 @@ class Theme extends PresetCore {
309
209
  getCSS: () => {
310
210
  const lines = [];
311
211
  lines.push(createCssSelector({
312
- selector: "root:",
212
+ selector: ":root",
313
213
  content: [
314
214
  core.entriesToCss(Object.entries(this.remapVariables({ tokens: this.preflights })))
315
215
  ]
316
216
  }));
317
- return lines.join("");
217
+ lines.push(createCssSelector({
218
+ selector: ":root",
219
+ content: this.genCssVariables(this.themes.light)
220
+ }));
221
+ return lines.join("\n");
318
222
  }
319
223
  };
320
224
  }
321
- getRules() {
225
+ genCssVariables(theme) {
226
+ const lightOverlay = theme.dark ? 2 : 1;
227
+ const darkOverlay = theme.dark ? 1 : 2;
228
+ const themeVariables = {};
229
+ for (const [key, value] of Object.entries(theme.colors)) {
230
+ const rgb = jsUtilities.parseColor(value);
231
+ themeVariables[key] = `${rgb.r},${rgb.g},${rgb.b}`;
232
+ if (!key.startsWith("on-")) {
233
+ themeVariables[`${key}-overlay-multiplier`] = (jsUtilities.getLuma(value) > 0.18 ? lightOverlay : darkOverlay).toString();
234
+ }
235
+ }
236
+ const variables = {};
237
+ for (const [key, value] of Object.entries(theme.variables)) {
238
+ const color = typeof value === "string" && value.startsWith("#") ? jsUtilities.parseColor(value) : void 0;
239
+ const rgb = color ? `${color.r},${color.g},${color.b}` : void 0;
240
+ variables[key] = `${rgb ?? value}`;
241
+ }
322
242
  return [
323
- this.getVariablesRule()
243
+ core.entriesToCss(Object.entries(this.remapVariables({ tokens: themeVariables, key: "theme-" }))),
244
+ core.entriesToCss(Object.entries(this.remapVariables({ tokens: variables })))
324
245
  ];
325
246
  }
326
247
  parseThemeOptions(options) {
@@ -346,102 +267,93 @@ class Theme extends PresetCore {
346
267
  continue;
347
268
  }
348
269
  const onColor = `on-${color}`;
349
- const colorValue = colorToInt(theme.colors[color]);
350
- const blackContrast = Math.abs(APCAcontrast(0, colorValue));
351
- const whiteContrast = Math.abs(APCAcontrast(16777215, colorValue));
270
+ const colorValue = jsUtilities.parseColor(theme.colors[color]);
271
+ const blackContrast = Math.abs(jsUtilities.APCAContrast(jsUtilities.parseColor(0), colorValue));
272
+ const whiteContrast = Math.abs(jsUtilities.APCAContrast(jsUtilities.parseColor(16777215), colorValue));
352
273
  theme.colors[onColor] = whiteContrast > Math.min(blackContrast, 50) ? "#fff" : "#000";
353
- this.colorKeys.push(color);
354
274
  }
355
275
  }
356
276
  return acc;
357
277
  }
358
- getVariablesRule() {
359
- return [
360
- new RegExp(`^theme-(?<name>${Object.keys(this.themes).join("|")})$`),
361
- ({ groups }) => {
362
- if (!groups?.name) {
363
- return {};
364
- }
365
- const themeName = this.themes[groups.name];
366
- const themeColors = themeName.colors ?? {};
367
- const rgbs = generateRGBs(themeColors);
368
- return {
369
- "color-scheme": themeName.dark ? "dark" : "light",
370
- ...this.remapVariables({ tokens: rgbs, key: "theme-" }),
371
- ...this.remapVariables({ tokens: themeName.variables })
372
- };
373
- },
374
- { layer: "vinicunca" }
375
- ];
376
- }
377
278
  }
378
279
 
379
280
  class Button extends PresetCore {
380
281
  constructor(options) {
381
282
  super(options);
382
- this.sizes = options.sizes ?? {};
383
- this.variants = options.variants ?? {};
283
+ this.regexCache = {};
284
+ this.classPropsKeys = Object.keys(this.classProps);
285
+ this.regexes = {
286
+ core: new RegExp(`(?<!--)((?:${this.prefix}button)+?)(?:--\\[((?:[\\w\\s-])+?)\\](?!\\s*?=>))?`, "gm")
287
+ };
288
+ this.classPropsKeys.forEach((key) => {
289
+ this.regexes[key] = new RegExp(`${key}-(${Object.keys(this.classProps[key]).join("|")})`, "g");
290
+ });
384
291
  }
385
- transformClass(content) {
386
- const reSize = new RegExp(`(${Object.keys(this.sizes).join("|")})`);
387
- return content.replace(
388
- new RegExp(`(${this.prefix}button)(?:--\\[((?:[\\w\\s-])+?)\\])`, "gm"),
389
- (_from, pre, props = "") => {
390
- const results = [];
391
- const [size] = props.match(reSize) ?? [];
392
- const [variant] = props.match(/outline|text|circle/) ?? [];
393
- const [, color] = props.match(/brand-(\w+)/) ?? [];
394
- results.push(pre + `--size-${size ?? "default"}`);
395
- const variants = variant ?? "default";
396
- results.push(pre + `--variant-${variants}`);
397
- const hasVariants = variants !== "default";
398
- if (color) {
399
- if (hasVariants) {
400
- results.push(`${this.prefix}text-${color}`);
401
- results.push(`hover:${this.prefix}text-on-${color}`);
402
- results.push(`hover:before:${this.prefix}bg-${color}`);
292
+ makeRegexClass(key) {
293
+ if (!this.regexCache[key]) {
294
+ this.regexCache[key] = this.regexes[key];
295
+ }
296
+ this.regexCache[key].lastIndex = 0;
297
+ return this.regexCache[key];
298
+ }
299
+ parseButtonClasses(str) {
300
+ const regexCore = this.makeRegexClass("core");
301
+ let hasChanged = false;
302
+ let content = str.toString();
303
+ let depth = 5;
304
+ do {
305
+ const before = content;
306
+ content = content.replace(
307
+ regexCore,
308
+ (_from, _pre, body) => {
309
+ const results = [this.classBase];
310
+ if (body) {
311
+ const bodyContent = body.split(/\s/g).filter(Boolean);
312
+ this.classPropsKeys.forEach((propKey) => {
313
+ const propRegex = this.makeRegexClass(propKey);
314
+ const defaultValue = this.classProps[propKey].default || "";
315
+ let hasProp = true;
316
+ if (bodyContent.length) {
317
+ for (let idx = 0; idx < bodyContent.length; idx++) {
318
+ const propBody = bodyContent[idx];
319
+ const match = propRegex.exec(propBody);
320
+ if (match) {
321
+ const [, key] = match;
322
+ results.push(this.classProps[propKey][key]);
323
+ bodyContent.splice(idx, 1);
324
+ hasProp = true;
325
+ break;
326
+ }
327
+ hasProp = false;
328
+ }
329
+ if (!hasProp) {
330
+ results.push(defaultValue);
331
+ }
332
+ } else {
333
+ results.push(defaultValue);
334
+ }
335
+ });
403
336
  } else {
404
- results.push(`${this.prefix}bg-${color}`);
337
+ results.push(
338
+ ...this.classPropsKeys.map(
339
+ (key) => this.classProps[key].default || ""
340
+ )
341
+ );
405
342
  }
406
- } else if (hasVariants) {
407
- results.push(`hover:${this.prefix}text-on-invert`);
408
- results.push(`hover:before:${this.prefix}bg-invert`);
343
+ return results.join(" ").replace(/(\r\n|\n|\r)/gm, " ");
409
344
  }
410
- return results.join(" ");
411
- }
412
- );
413
- }
414
- getRules() {
415
- return [];
345
+ );
346
+ hasChanged = content !== before;
347
+ depth -= 1;
348
+ } while (hasChanged && depth);
349
+ return {
350
+ expanded: content.replace(/\s+/gm, " "),
351
+ hasChanged
352
+ };
416
353
  }
417
- getShortcuts() {
418
- return [
419
- [
420
- /^button$/,
421
- () => {
422
- const size = this.sizes.default ?? "";
423
- const variant = this.variants.default ?? "";
424
- return `${size} ${variant}`;
425
- },
426
- { layer: "vinicunca" }
427
- ],
428
- [
429
- new RegExp(`^button--size-(?<size>${Object.keys(this.sizes).join("|")})?$`),
430
- ({ groups }) => {
431
- const size = groups?.size || "default";
432
- return this.sizes[size] ?? "";
433
- },
434
- { layer: "vinicunca" }
435
- ],
436
- [
437
- new RegExp(`^button--variant-(?<variant>${Object.keys(this.variants).join("|")})?$`),
438
- ({ groups }) => {
439
- const variant = groups?.variant || "elevated";
440
- return this.variants[variant] ?? "";
441
- },
442
- { layer: "variants" }
443
- ]
444
- ];
354
+ transfromClasses(str) {
355
+ const { expanded } = this.parseButtonClasses(str.toString());
356
+ return str.length() ? str.overwrite(0, str.length(), expanded) : str;
445
357
  }
446
358
  }
447
359
 
@@ -458,7 +370,7 @@ class Overlay extends PresetCore {
458
370
  lines.push(createCssSelector({
459
371
  selector: `html.${this.scrollBlockedClass.name}`,
460
372
  content: [
461
- unocss.entriesToCss(Object.entries(this.scrollBlockedClass.html))
373
+ core.entriesToCss(Object.entries(this.scrollBlockedClass.html))
462
374
  ]
463
375
  }));
464
376
  return lines.join("");
@@ -479,25 +391,21 @@ class Overlay extends PresetCore {
479
391
 
480
392
  class VinicuncaConfig {
481
393
  constructor(options) {
482
- const { prefix, components, theme } = options;
483
- this.prefix = prefix ?? DEFAULT_PREFIX;
484
- this.theme = new Theme({
485
- prefix: this.prefix,
486
- ...theme
394
+ const { prefix, components, brands } = options;
395
+ this.brand = new Brand({
396
+ prefix,
397
+ ...brands
487
398
  });
488
- const colorKeys = this.theme.getColorKeys();
489
399
  this.color = new Color({
490
- prefix: this.prefix,
491
- colorKeys
400
+ prefix
492
401
  });
493
402
  this.elevation = new Elevation();
494
403
  this.button = new Button({
495
- prefix: this.prefix,
496
- colorKeys,
404
+ prefix,
497
405
  ...components?.button
498
406
  });
499
407
  this.overlay = new Overlay({
500
- prefix: this.prefix,
408
+ prefix,
501
409
  ...components?.overlay
502
410
  });
503
411
  }
@@ -505,15 +413,22 @@ class VinicuncaConfig {
505
413
  return {
506
414
  name: "unocss-preset-vinicunca",
507
415
  layers: {
508
- preflight: -2,
509
- vinicunca: -1,
416
+ preflight: -3,
417
+ vinicunca: -2,
510
418
  default: 0,
511
419
  variants: 1
512
420
  },
513
- prefix: this.prefix,
514
421
  preflights: this.definePreflights(),
515
422
  rules: this.defineRules(),
516
- shortcuts: this.defineShortcuts()
423
+ shortcuts: this.defineShortcuts(),
424
+ theme: {
425
+ letterSpacing: {
426
+ button: "0.0892857143em"
427
+ },
428
+ textIndent: {
429
+ button: "0.0892857143em"
430
+ }
431
+ }
517
432
  };
518
433
  }
519
434
  getTransformer() {
@@ -521,29 +436,23 @@ class VinicuncaConfig {
521
436
  name: "vinicunca-transformers",
522
437
  enforce: "pre",
523
438
  transform: (str) => {
524
- let content = str.toString();
525
- content = this.button.transformClass(content);
526
- str.overwrite(0, str.length(), content);
439
+ this.button.transfromClasses(str);
527
440
  }
528
441
  };
529
442
  }
530
443
  definePreflights() {
531
444
  return [
532
- this.theme.getPreflight(),
533
- this.overlay.getPreflight()
445
+ this.brand.getPreflight()
534
446
  ];
535
447
  }
536
448
  defineRules() {
537
449
  return [
538
- this.theme.getRules(),
539
450
  this.color.getRules(),
540
- this.elevation.getRules(),
541
- this.button.getRules()
451
+ this.elevation.getRules()
542
452
  ].flat(1);
543
453
  }
544
454
  defineShortcuts() {
545
455
  return [
546
- ...this.button.getShortcuts(),
547
456
  ...this.overlay.getShortcuts()
548
457
  ];
549
458
  }
package/dist/index.d.ts CHANGED
@@ -1,8 +1,9 @@
1
1
  import { DeepPartial, Preset, SourceCodeTransformer } from '@unocss/core';
2
2
 
3
- interface ButtonOptions {
4
- sizes?: Record<string, string>;
5
- variants?: Record<string, string>;
3
+ interface CoreOptions {
4
+ prefix?: string;
5
+ classBase?: string;
6
+ classProps?: Record<string, Record<string, string>>;
6
7
  }
7
8
 
8
9
  interface OverlayOptions {
@@ -58,16 +59,15 @@ interface ThemePreset {
58
59
 
59
60
  interface IConfigVinicunca {
60
61
  prefix?: string;
61
- theme?: ThemePreset;
62
+ brands?: ThemePreset;
62
63
  components?: {
63
- button?: ButtonOptions;
64
+ button?: CoreOptions;
64
65
  overlay?: OverlayOptions;
65
66
  };
66
67
  }
67
68
 
68
69
  declare class VinicuncaConfig {
69
- private prefix;
70
- private theme;
70
+ private brand;
71
71
  private color;
72
72
  private elevation;
73
73
  private button;
package/dist/index.mjs CHANGED
@@ -1,13 +1,12 @@
1
- import { toKebabCase, convertToUnit, toCamelCase, mergeDeep } from '@vinicunca/js-utilities';
1
+ import { toKebabCase, convertToUnit, parseColor, getLuma, mergeDeep, APCAContrast } from '@vinicunca/js-utilities';
2
2
  import { entriesToCss } from '@unocss/core';
3
- import { parseColor } from '@unocss/preset-mini';
4
- import { entriesToCss as entriesToCss$1 } from 'unocss';
5
3
 
6
4
  const DEFAULT_PREFIX = "vin-";
7
5
  class PresetCore {
8
6
  constructor(options) {
9
- this.prefix = options.prefix ?? "";
10
- this.colorKeys = options.colorKeys ?? [];
7
+ this.prefix = options.prefix ?? DEFAULT_PREFIX;
8
+ this.classBase = options.classBase ?? "";
9
+ this.classProps = options.classProps ?? {};
11
10
  }
12
11
  genVariable(key = "") {
13
12
  return `--${this.prefix}${key}`;
@@ -19,14 +18,12 @@ class PresetCore {
19
18
  return prev;
20
19
  }, {});
21
20
  }
22
- getColorKeys() {
23
- return Array.from(new Set(this.colorKeys));
24
- }
25
21
  }
26
22
 
27
23
  class Color extends PresetCore {
28
24
  constructor(options) {
29
25
  super(options);
26
+ this.varTextOpacity = "--un-text-opacity";
30
27
  }
31
28
  getRules() {
32
29
  return [
@@ -36,17 +33,14 @@ class Color extends PresetCore {
36
33
  }
37
34
  getTextRule() {
38
35
  return [
39
- /^text-(?<body>(?:on-)?(?<color>.+))/,
36
+ /^text-brand-(?<body>(?:on-)?(?<color>.+))/,
40
37
  ({ groups }) => {
41
38
  const { body, color } = groups;
42
- if (!this.getColorKeys().includes(color)) {
43
- return;
44
- }
45
39
  const colorBody = /^on-[a-z]/.test(body) ? `on-${color}` : color;
46
40
  const colorVar = this.genVariable(`theme-${colorBody}`);
47
41
  return {
48
- "--un-color-opacity": 1,
49
- "color": `rgba(var(${colorVar}), var(--un-color-opacity))`
42
+ [this.varTextOpacity]: 1,
43
+ color: `rgba(var(${colorVar}), var(${this.varTextOpacity}))`
50
44
  };
51
45
  },
52
46
  { layer: "vinicunca" }
@@ -54,18 +48,15 @@ class Color extends PresetCore {
54
48
  }
55
49
  getBgRule() {
56
50
  return [
57
- /^bg-(.+)$/,
51
+ /^bg-brand-(.+)$/,
58
52
  ([, body]) => {
59
- if (!this.colorKeys.includes(body)) {
60
- return;
61
- }
62
53
  const bgColorVar = this.genVariable(`theme-${body}`);
63
54
  const colorVar = this.genVariable(`theme-on-${body}`);
64
55
  return {
65
- "--un-color-opacity": 1,
56
+ [this.varTextOpacity]: 1,
66
57
  "--un-bg-opacity": 1,
67
58
  "background-color": `rgba(var(${bgColorVar}),var(--un-bg-opacity))`,
68
- "color": `rgba(var(${colorVar}), var(--un-color-opacity))`
59
+ "color": `rgba(var(${colorVar}), var(${this.varTextOpacity}))`
69
60
  };
70
61
  },
71
62
  { layer: "vinicunca" }
@@ -141,7 +132,6 @@ const DEFAULT_THEME = {
141
132
  dark: false,
142
133
  colors: {
143
134
  "background": "#FFFFFF",
144
- "invert": "#000000",
145
135
  "surface": "#FFFFFF",
146
136
  "surface-variant": "#424242",
147
137
  "on-surface-variant": "#EEEEEE",
@@ -154,24 +144,23 @@ const DEFAULT_THEME = {
154
144
  },
155
145
  variables: {
156
146
  "border-color": "#000000",
157
- "border-opacity": 0.12,
158
- "high-emphasis-opacity": 0.87,
159
- "medium-emphasis-opacity": 0.6,
160
- "disabled-opacity": 0.38,
161
- "idle-opacity": 0.04,
162
- "hover-opacity": 0.04,
163
- "focus-opacity": 0.12,
164
- "selected-opacity": 0.08,
165
- "activated-opacity": 0.12,
166
- "pressed-opacity": 0.12,
167
- "dragged-opacity": 0.08
147
+ "opacity-border": 0.12,
148
+ "opacity-high-emphasis": 0.87,
149
+ "opacity-medium-emphasis": 0.6,
150
+ "opacity-disabled": 0.38,
151
+ "opacity-idle": 0.04,
152
+ "opacity-hover": 0.04,
153
+ "opacity-focus": 0.12,
154
+ "opacity-selected": 0.08,
155
+ "opacity-activated": 0.12,
156
+ "opacity-pressed": 0.12,
157
+ "opacity-dragged": 0.08
168
158
  }
169
159
  },
170
160
  dark: {
171
161
  dark: true,
172
162
  colors: {
173
163
  "background": "#121212",
174
- "invert": "#FFFFFF",
175
164
  "surface": "#212121",
176
165
  "surface-variant": "#BDBDBD",
177
166
  "on-surface-variant": "#424242",
@@ -184,17 +173,17 @@ const DEFAULT_THEME = {
184
173
  },
185
174
  variables: {
186
175
  "border-color": "#FFFFFF",
187
- "border-opacity": 0.12,
188
- "high-emphasis-opacity": 0.87,
189
- "medium-emphasis-opacity": 0.6,
190
- "disabled-opacity": 0.38,
191
- "idle-opacity": 0.1,
192
- "hover-opacity": 0.04,
193
- "focus-opacity": 0.12,
194
- "selected-opacity": 0.08,
195
- "activated-opacity": 0.12,
196
- "pressed-opacity": 0.16,
197
- "dragged-opacity": 0.08
176
+ "opacity-border": 0.12,
177
+ "opacity-high-emphasis": 0.87,
178
+ "opacity-medium-emphasis": 0.6,
179
+ "opacity-disabled": 0.38,
180
+ "opacity-idle": 0.1,
181
+ "opacity-hover": 0.04,
182
+ "opacity-focus": 0.12,
183
+ "opacity-selected": 0.08,
184
+ "opacity-activated": 0.12,
185
+ "opacity-pressed": 0.16,
186
+ "opacity-dragged": 0.08
198
187
  }
199
188
  }
200
189
  };
@@ -203,98 +192,7 @@ function createCssSelector({ selector, content }) {
203
192
  return `${selector} { ${content.join(" ")} }`;
204
193
  }
205
194
 
206
- function generateRGBs(colors) {
207
- const theme = {};
208
- for (const color of Object.keys(colors)) {
209
- let colorKey = color;
210
- if (/^on-[a-z]/.test(color)) {
211
- colorKey = toCamelCase(color);
212
- }
213
- const data = parseColor(color, {
214
- colors: {
215
- [colorKey]: colors[color]
216
- }
217
- });
218
- if (data?.cssColor?.components) {
219
- const colorValue = data.cssColor.components.join(",");
220
- theme[color] = colorValue;
221
- }
222
- }
223
- return theme;
224
- }
225
- function colorToInt(color) {
226
- let rgb;
227
- if (typeof color === "number") {
228
- rgb = color;
229
- } else if (typeof color === "string") {
230
- let c = color.startsWith("#") ? color.substring(1) : color;
231
- if (c.length === 3) {
232
- c = c.split("").map((char) => char + char).join("");
233
- }
234
- if (c.length !== 6 && c.length !== 8) {
235
- console.warn(`'${color}' is not a valid rgb color`);
236
- }
237
- rgb = parseInt(c, 16);
238
- } else {
239
- throw new TypeError(`Colors can only be numbers or strings, recieved ${color == null ? color : color.constructor.name} instead`);
240
- }
241
- if (rgb < 0) {
242
- console.warn(`Colors cannot be negative: '${color}'`);
243
- rgb = 0;
244
- } else if (rgb > 4294967295 || isNaN(rgb)) {
245
- console.warn(`'${color}' is not a valid rgb color`);
246
- rgb = 16777215;
247
- }
248
- return rgb;
249
- }
250
-
251
- const mainTRC = 2.4;
252
- const Rco = 0.2126729;
253
- const Gco = 0.7151522;
254
- const Bco = 0.072175;
255
- const normBG = 0.55;
256
- const normTXT = 0.58;
257
- const revTXT = 0.57;
258
- const revBG = 0.62;
259
- const blkThrs = 0.03;
260
- const blkClmp = 1.45;
261
- const deltaYmin = 5e-4;
262
- const scaleBoW = 1.25;
263
- const scaleWoB = 1.25;
264
- const loConThresh = 0.078;
265
- const loConFactor = 12.82051282051282;
266
- const loConOffset = 0.06;
267
- const loClip = 1e-3;
268
- function APCAcontrast(text, background) {
269
- const Rtxt = ((text >> 16 & 255) / 255) ** mainTRC;
270
- const Gtxt = ((text >> 8 & 255) / 255) ** mainTRC;
271
- const Btxt = ((text >> 0 & 255) / 255) ** mainTRC;
272
- const Rbg = ((background >> 16 & 255) / 255) ** mainTRC;
273
- const Gbg = ((background >> 8 & 255) / 255) ** mainTRC;
274
- const Bbg = ((background >> 0 & 255) / 255) ** mainTRC;
275
- let Ytxt = Rtxt * Rco + Gtxt * Gco + Btxt * Bco;
276
- let Ybg = Rbg * Rco + Gbg * Gco + Bbg * Bco;
277
- if (Ytxt <= blkThrs) {
278
- Ytxt += (blkThrs - Ytxt) ** blkClmp;
279
- }
280
- if (Ybg <= blkThrs) {
281
- Ybg += (blkThrs - Ybg) ** blkClmp;
282
- }
283
- if (Math.abs(Ybg - Ytxt) < deltaYmin) {
284
- return 0;
285
- }
286
- let outputContrast;
287
- if (Ybg > Ytxt) {
288
- const SAPC = (Ybg ** normBG - Ytxt ** normTXT) * scaleBoW;
289
- outputContrast = SAPC < loClip ? 0 : SAPC < loConThresh ? SAPC - SAPC * loConFactor * loConOffset : SAPC - loConOffset;
290
- } else {
291
- const SAPC = (Ybg ** revBG - Ytxt ** revTXT) * scaleWoB;
292
- outputContrast = SAPC > -loClip ? 0 : SAPC > -loConThresh ? SAPC - SAPC * loConFactor * loConOffset : SAPC + loConOffset;
293
- }
294
- return outputContrast * 100;
295
- }
296
-
297
- class Theme extends PresetCore {
195
+ class Brand extends PresetCore {
298
196
  constructor(options) {
299
197
  super(options);
300
198
  const parsedOptions = this.parseThemeOptions(options?.themes);
@@ -307,18 +205,39 @@ class Theme extends PresetCore {
307
205
  getCSS: () => {
308
206
  const lines = [];
309
207
  lines.push(createCssSelector({
310
- selector: "root:",
208
+ selector: ":root",
311
209
  content: [
312
210
  entriesToCss(Object.entries(this.remapVariables({ tokens: this.preflights })))
313
211
  ]
314
212
  }));
315
- return lines.join("");
213
+ lines.push(createCssSelector({
214
+ selector: ":root",
215
+ content: this.genCssVariables(this.themes.light)
216
+ }));
217
+ return lines.join("\n");
316
218
  }
317
219
  };
318
220
  }
319
- getRules() {
221
+ genCssVariables(theme) {
222
+ const lightOverlay = theme.dark ? 2 : 1;
223
+ const darkOverlay = theme.dark ? 1 : 2;
224
+ const themeVariables = {};
225
+ for (const [key, value] of Object.entries(theme.colors)) {
226
+ const rgb = parseColor(value);
227
+ themeVariables[key] = `${rgb.r},${rgb.g},${rgb.b}`;
228
+ if (!key.startsWith("on-")) {
229
+ themeVariables[`${key}-overlay-multiplier`] = (getLuma(value) > 0.18 ? lightOverlay : darkOverlay).toString();
230
+ }
231
+ }
232
+ const variables = {};
233
+ for (const [key, value] of Object.entries(theme.variables)) {
234
+ const color = typeof value === "string" && value.startsWith("#") ? parseColor(value) : void 0;
235
+ const rgb = color ? `${color.r},${color.g},${color.b}` : void 0;
236
+ variables[key] = `${rgb ?? value}`;
237
+ }
320
238
  return [
321
- this.getVariablesRule()
239
+ entriesToCss(Object.entries(this.remapVariables({ tokens: themeVariables, key: "theme-" }))),
240
+ entriesToCss(Object.entries(this.remapVariables({ tokens: variables })))
322
241
  ];
323
242
  }
324
243
  parseThemeOptions(options) {
@@ -344,102 +263,93 @@ class Theme extends PresetCore {
344
263
  continue;
345
264
  }
346
265
  const onColor = `on-${color}`;
347
- const colorValue = colorToInt(theme.colors[color]);
348
- const blackContrast = Math.abs(APCAcontrast(0, colorValue));
349
- const whiteContrast = Math.abs(APCAcontrast(16777215, colorValue));
266
+ const colorValue = parseColor(theme.colors[color]);
267
+ const blackContrast = Math.abs(APCAContrast(parseColor(0), colorValue));
268
+ const whiteContrast = Math.abs(APCAContrast(parseColor(16777215), colorValue));
350
269
  theme.colors[onColor] = whiteContrast > Math.min(blackContrast, 50) ? "#fff" : "#000";
351
- this.colorKeys.push(color);
352
270
  }
353
271
  }
354
272
  return acc;
355
273
  }
356
- getVariablesRule() {
357
- return [
358
- new RegExp(`^theme-(?<name>${Object.keys(this.themes).join("|")})$`),
359
- ({ groups }) => {
360
- if (!groups?.name) {
361
- return {};
362
- }
363
- const themeName = this.themes[groups.name];
364
- const themeColors = themeName.colors ?? {};
365
- const rgbs = generateRGBs(themeColors);
366
- return {
367
- "color-scheme": themeName.dark ? "dark" : "light",
368
- ...this.remapVariables({ tokens: rgbs, key: "theme-" }),
369
- ...this.remapVariables({ tokens: themeName.variables })
370
- };
371
- },
372
- { layer: "vinicunca" }
373
- ];
374
- }
375
274
  }
376
275
 
377
276
  class Button extends PresetCore {
378
277
  constructor(options) {
379
278
  super(options);
380
- this.sizes = options.sizes ?? {};
381
- this.variants = options.variants ?? {};
279
+ this.regexCache = {};
280
+ this.classPropsKeys = Object.keys(this.classProps);
281
+ this.regexes = {
282
+ core: new RegExp(`(?<!--)((?:${this.prefix}button)+?)(?:--\\[((?:[\\w\\s-])+?)\\](?!\\s*?=>))?`, "gm")
283
+ };
284
+ this.classPropsKeys.forEach((key) => {
285
+ this.regexes[key] = new RegExp(`${key}-(${Object.keys(this.classProps[key]).join("|")})`, "g");
286
+ });
382
287
  }
383
- transformClass(content) {
384
- const reSize = new RegExp(`(${Object.keys(this.sizes).join("|")})`);
385
- return content.replace(
386
- new RegExp(`(${this.prefix}button)(?:--\\[((?:[\\w\\s-])+?)\\])`, "gm"),
387
- (_from, pre, props = "") => {
388
- const results = [];
389
- const [size] = props.match(reSize) ?? [];
390
- const [variant] = props.match(/outline|text|circle/) ?? [];
391
- const [, color] = props.match(/brand-(\w+)/) ?? [];
392
- results.push(pre + `--size-${size ?? "default"}`);
393
- const variants = variant ?? "default";
394
- results.push(pre + `--variant-${variants}`);
395
- const hasVariants = variants !== "default";
396
- if (color) {
397
- if (hasVariants) {
398
- results.push(`${this.prefix}text-${color}`);
399
- results.push(`hover:${this.prefix}text-on-${color}`);
400
- results.push(`hover:before:${this.prefix}bg-${color}`);
288
+ makeRegexClass(key) {
289
+ if (!this.regexCache[key]) {
290
+ this.regexCache[key] = this.regexes[key];
291
+ }
292
+ this.regexCache[key].lastIndex = 0;
293
+ return this.regexCache[key];
294
+ }
295
+ parseButtonClasses(str) {
296
+ const regexCore = this.makeRegexClass("core");
297
+ let hasChanged = false;
298
+ let content = str.toString();
299
+ let depth = 5;
300
+ do {
301
+ const before = content;
302
+ content = content.replace(
303
+ regexCore,
304
+ (_from, _pre, body) => {
305
+ const results = [this.classBase];
306
+ if (body) {
307
+ const bodyContent = body.split(/\s/g).filter(Boolean);
308
+ this.classPropsKeys.forEach((propKey) => {
309
+ const propRegex = this.makeRegexClass(propKey);
310
+ const defaultValue = this.classProps[propKey].default || "";
311
+ let hasProp = true;
312
+ if (bodyContent.length) {
313
+ for (let idx = 0; idx < bodyContent.length; idx++) {
314
+ const propBody = bodyContent[idx];
315
+ const match = propRegex.exec(propBody);
316
+ if (match) {
317
+ const [, key] = match;
318
+ results.push(this.classProps[propKey][key]);
319
+ bodyContent.splice(idx, 1);
320
+ hasProp = true;
321
+ break;
322
+ }
323
+ hasProp = false;
324
+ }
325
+ if (!hasProp) {
326
+ results.push(defaultValue);
327
+ }
328
+ } else {
329
+ results.push(defaultValue);
330
+ }
331
+ });
401
332
  } else {
402
- results.push(`${this.prefix}bg-${color}`);
333
+ results.push(
334
+ ...this.classPropsKeys.map(
335
+ (key) => this.classProps[key].default || ""
336
+ )
337
+ );
403
338
  }
404
- } else if (hasVariants) {
405
- results.push(`hover:${this.prefix}text-on-invert`);
406
- results.push(`hover:before:${this.prefix}bg-invert`);
339
+ return results.join(" ").replace(/(\r\n|\n|\r)/gm, " ");
407
340
  }
408
- return results.join(" ");
409
- }
410
- );
341
+ );
342
+ hasChanged = content !== before;
343
+ depth -= 1;
344
+ } while (hasChanged && depth);
345
+ return {
346
+ expanded: content.replace(/\s+/gm, " "),
347
+ hasChanged
348
+ };
411
349
  }
412
- getRules() {
413
- return [];
414
- }
415
- getShortcuts() {
416
- return [
417
- [
418
- /^button$/,
419
- () => {
420
- const size = this.sizes.default ?? "";
421
- const variant = this.variants.default ?? "";
422
- return `${size} ${variant}`;
423
- },
424
- { layer: "vinicunca" }
425
- ],
426
- [
427
- new RegExp(`^button--size-(?<size>${Object.keys(this.sizes).join("|")})?$`),
428
- ({ groups }) => {
429
- const size = groups?.size || "default";
430
- return this.sizes[size] ?? "";
431
- },
432
- { layer: "vinicunca" }
433
- ],
434
- [
435
- new RegExp(`^button--variant-(?<variant>${Object.keys(this.variants).join("|")})?$`),
436
- ({ groups }) => {
437
- const variant = groups?.variant || "elevated";
438
- return this.variants[variant] ?? "";
439
- },
440
- { layer: "variants" }
441
- ]
442
- ];
350
+ transfromClasses(str) {
351
+ const { expanded } = this.parseButtonClasses(str.toString());
352
+ return str.length() ? str.overwrite(0, str.length(), expanded) : str;
443
353
  }
444
354
  }
445
355
 
@@ -456,7 +366,7 @@ class Overlay extends PresetCore {
456
366
  lines.push(createCssSelector({
457
367
  selector: `html.${this.scrollBlockedClass.name}`,
458
368
  content: [
459
- entriesToCss$1(Object.entries(this.scrollBlockedClass.html))
369
+ entriesToCss(Object.entries(this.scrollBlockedClass.html))
460
370
  ]
461
371
  }));
462
372
  return lines.join("");
@@ -477,25 +387,21 @@ class Overlay extends PresetCore {
477
387
 
478
388
  class VinicuncaConfig {
479
389
  constructor(options) {
480
- const { prefix, components, theme } = options;
481
- this.prefix = prefix ?? DEFAULT_PREFIX;
482
- this.theme = new Theme({
483
- prefix: this.prefix,
484
- ...theme
390
+ const { prefix, components, brands } = options;
391
+ this.brand = new Brand({
392
+ prefix,
393
+ ...brands
485
394
  });
486
- const colorKeys = this.theme.getColorKeys();
487
395
  this.color = new Color({
488
- prefix: this.prefix,
489
- colorKeys
396
+ prefix
490
397
  });
491
398
  this.elevation = new Elevation();
492
399
  this.button = new Button({
493
- prefix: this.prefix,
494
- colorKeys,
400
+ prefix,
495
401
  ...components?.button
496
402
  });
497
403
  this.overlay = new Overlay({
498
- prefix: this.prefix,
404
+ prefix,
499
405
  ...components?.overlay
500
406
  });
501
407
  }
@@ -503,15 +409,22 @@ class VinicuncaConfig {
503
409
  return {
504
410
  name: "unocss-preset-vinicunca",
505
411
  layers: {
506
- preflight: -2,
507
- vinicunca: -1,
412
+ preflight: -3,
413
+ vinicunca: -2,
508
414
  default: 0,
509
415
  variants: 1
510
416
  },
511
- prefix: this.prefix,
512
417
  preflights: this.definePreflights(),
513
418
  rules: this.defineRules(),
514
- shortcuts: this.defineShortcuts()
419
+ shortcuts: this.defineShortcuts(),
420
+ theme: {
421
+ letterSpacing: {
422
+ button: "0.0892857143em"
423
+ },
424
+ textIndent: {
425
+ button: "0.0892857143em"
426
+ }
427
+ }
515
428
  };
516
429
  }
517
430
  getTransformer() {
@@ -519,29 +432,23 @@ class VinicuncaConfig {
519
432
  name: "vinicunca-transformers",
520
433
  enforce: "pre",
521
434
  transform: (str) => {
522
- let content = str.toString();
523
- content = this.button.transformClass(content);
524
- str.overwrite(0, str.length(), content);
435
+ this.button.transfromClasses(str);
525
436
  }
526
437
  };
527
438
  }
528
439
  definePreflights() {
529
440
  return [
530
- this.theme.getPreflight(),
531
- this.overlay.getPreflight()
441
+ this.brand.getPreflight()
532
442
  ];
533
443
  }
534
444
  defineRules() {
535
445
  return [
536
- this.theme.getRules(),
537
446
  this.color.getRules(),
538
- this.elevation.getRules(),
539
- this.button.getRules()
447
+ this.elevation.getRules()
540
448
  ].flat(1);
541
449
  }
542
450
  defineShortcuts() {
543
451
  return [
544
- ...this.button.getShortcuts(),
545
452
  ...this.overlay.getShortcuts()
546
453
  ];
547
454
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vinicunca/unocss-preset",
3
- "version": "0.0.2",
3
+ "version": "0.1.1",
4
4
  "packageManager": "pnpm@7.15.2",
5
5
  "description": "UnoCSS custom preset",
6
6
  "author": "praburangki<https://github.com/praburangki>",
@@ -46,27 +46,27 @@
46
46
  "styles"
47
47
  ],
48
48
  "peerDependencies": {
49
- "unocss": "*",
50
- "@vinicunca/js-utilities": "*"
49
+ "@vinicunca/js-utilities": "*",
50
+ "unocss": "*"
51
51
  },
52
52
  "devDependencies": {
53
53
  "@commitlint/cli": "^17.4.2",
54
54
  "@commitlint/config-conventional": "^17.4.2",
55
- "@vinicunca/eslint-config": "^1.6.2",
56
- "@vinicunca/js-utilities": "^2.6.4",
57
- "bumpp": "^8.2.1",
55
+ "@vinicunca/eslint-config": "^1.7.1",
56
+ "@vinicunca/js-utilities": "^3.0.0",
57
+ "bumpp": "^9.1.0",
58
58
  "commitizen": "^4.2.6",
59
59
  "conventional-changelog-cli": "^2.2.2",
60
60
  "cz-customizable": "^7.0.0",
61
- "eslint": "^8.32.0",
62
- "eslint-define-config": "^1.14.0",
61
+ "eslint": "^8.37.0",
62
+ "eslint-define-config": "^1.17.0",
63
63
  "husky": "^8.0.3",
64
64
  "is-ci": "^3.0.1",
65
- "lint-staged": "^13.1.0",
66
- "typescript": "^4.9.4",
67
- "unbuild": "^1.1.1",
68
- "unocss": "^0.49.0",
69
- "vitest": "^0.28.2"
65
+ "lint-staged": "^13.2.0",
66
+ "typescript": "^5.0.3",
67
+ "unbuild": "^0.8.11",
68
+ "unocss": "^0.50.6",
69
+ "vitest": "^0.29.8"
70
70
  },
71
71
  "publishConfig": {
72
72
  "access": "public"