vunor 0.0.11 → 0.0.13

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/nuxt.mjs CHANGED
@@ -8,6 +8,7 @@ var u = [
8
8
  "CardInner",
9
9
  "Checkbox",
10
10
  "Combobox",
11
+ "DevTools",
11
12
  "Icon",
12
13
  "Input",
13
14
  "InputShell",
@@ -21,9 +22,10 @@ var u = [
21
22
  "RadioGroup",
22
23
  "Select",
23
24
  "SelectBase",
24
- "Slider"
25
+ "Slider",
26
+ "Tabs"
25
27
  ];
26
- const o = u, d = a({
28
+ const n = u, d = a({
27
29
  meta: {
28
30
  name: "vunor/nuxt",
29
31
  configKey: "vunor",
@@ -35,9 +37,9 @@ const o = u, d = a({
35
37
  // prefix: '',
36
38
  components: !0
37
39
  },
38
- setup(n) {
39
- if (n.components) {
40
- const t = Array.isArray(n.components) ? o.filter((e) => n.components.includes(e)) : o;
40
+ setup(o) {
41
+ if (o.components) {
42
+ const t = Array.isArray(o.components) ? n.filter((e) => o.components.includes(e)) : n;
41
43
  for (const e of t)
42
44
  r({
43
45
  name: `Vu${e}`,
package/dist/theme.d.ts CHANGED
@@ -29,55 +29,60 @@ export declare const rawVunorShortcuts: TVunorShortcut[];
29
29
  declare const themeFactory: (opts: Required<TVunorUnoPresetOpts> & {
30
30
  palette?: TVunorPaletteOptions;
31
31
  }) => {
32
- colors: {
33
- [x: string]: string;
34
- };
35
- surfaces: Record<string, TVunorSurfaceConfig>;
36
- borderColor: string;
37
- reverseLightLayers: boolean;
38
- reverseDarkLayers: boolean;
39
- lineHeight: {
40
- fingertip: string;
41
- 'fingertip-half': string;
42
- 'fingertip-xs': string;
43
- 'fingertip-s': string;
44
- 'fingertip-m': string;
45
- 'fingertip-l': string;
46
- 'fingertip-xl': string;
47
- };
48
- spacing: Record<string, string>;
49
- fontWeight: Record<string, string>;
50
- actualFontHeightFactor: number;
51
- cardSpacingFactor: {
52
- regular: number;
53
- dense: number;
54
- };
55
- fontSize: Record<string, [TTypographyNames, Record<string, string>]>;
56
- width: Record<string, string>;
57
- height: Record<string, string>;
58
- maxWidth: Record<string, string>;
59
- maxHeight: Record<string, string>;
60
- minWidth: Record<string, string>;
61
- minHeight: Record<string, string>;
62
- borderRadius: {
63
- base: string;
64
- };
65
- animation: {
66
- durations: {
67
- 'slide-down-and-fade': string;
68
- 'slide-left-and-fade': string;
69
- 'slide-up-and-fade': string;
70
- 'slide-right-and-fade': string;
71
- 'zoom-fade-in': string;
32
+ paletteOpts: Required<TVunorPaletteOptions & {
33
+ colors: TVunorPaletteColor;
34
+ }>;
35
+ theme: {
36
+ colors: {
37
+ [x: string]: string;
38
+ };
39
+ surfaces: Record<string, TVunorSurfaceConfig>;
40
+ borderColor: string;
41
+ reverseLightLayers: boolean;
42
+ reverseDarkLayers: boolean;
43
+ lineHeight: {
44
+ fingertip: string;
45
+ 'fingertip-half': string;
46
+ 'fingertip-xs': string;
47
+ 'fingertip-s': string;
48
+ 'fingertip-m': string;
49
+ 'fingertip-l': string;
50
+ 'fingertip-xl': string;
51
+ };
52
+ spacing: Record<string, string>;
53
+ fontWeight: Record<string, string>;
54
+ actualFontHeightFactor: number;
55
+ cardSpacingFactor: {
56
+ regular: number;
57
+ dense: number;
58
+ };
59
+ fontSize: Record<string, [TTypographyNames, Record<string, string>]>;
60
+ width: Record<string, string>;
61
+ height: Record<string, string>;
62
+ maxWidth: Record<string, string>;
63
+ maxHeight: Record<string, string>;
64
+ minWidth: Record<string, string>;
65
+ minHeight: Record<string, string>;
66
+ borderRadius: {
67
+ base: string;
72
68
  };
73
- keyframes: {
74
- 'slide-down-and-fade': string;
75
- 'slide-left-and-fade': string;
76
- 'slide-up-and-fade': string;
77
- 'slide-right-and-fade': string;
78
- 'zoom-fade-in': string;
79
- 'loading-dashoffset': string;
80
- 'cb-appear': string;
69
+ animation: {
70
+ durations: {
71
+ 'slide-down-and-fade': string;
72
+ 'slide-left-and-fade': string;
73
+ 'slide-up-and-fade': string;
74
+ 'slide-right-and-fade': string;
75
+ 'zoom-fade-in': string;
76
+ };
77
+ keyframes: {
78
+ 'slide-down-and-fade': string;
79
+ 'slide-left-and-fade': string;
80
+ 'slide-up-and-fade': string;
81
+ 'slide-right-and-fade': string;
82
+ 'zoom-fade-in': string;
83
+ 'loading-dashoffset': string;
84
+ 'cb-appear': string;
85
+ };
81
86
  };
82
87
  };
83
88
  };
@@ -301,7 +306,7 @@ export declare interface TVunorShortcut {
301
306
  */
302
307
  export declare type TVunorSurfaceConfig = [string, string, string, string, string, string];
303
308
 
304
- export declare type TVunorTheme = ReturnType<typeof themeFactory> & Theme;
309
+ export declare type TVunorTheme = ReturnType<typeof themeFactory>['theme'] & Theme;
305
310
 
306
311
  declare interface TVunorUnoPresetOpts {
307
312
  spacingFactor?: number;
package/dist/theme.mjs CHANGED
@@ -1,7 +1,7 @@
1
- import A, { defu as F } from "defu";
2
- import { presetWind as C } from "unocss";
1
+ import N, { defu as F } from "defu";
2
+ import { presetWind as R } from "unocss";
3
3
  import { palitra as w, color as S } from "@prostojs/palitra";
4
- const f = (e) => e, L = f({
4
+ const f = (e) => e, A = f({
5
5
  btn: {
6
6
  "": "h-fingertip flex items-center justify-center px-$m gap-$xs select-none fw-bold tracking-wide relative",
7
7
  "[&.btn-round]:": "px-fingertip-half rounded-fingertip-half",
@@ -26,7 +26,7 @@ const f = (e) => e, L = f({
26
26
  "group-[.btn-square]/btn:": "font-size-1.5em m-0!",
27
27
  "group-[.btn-round.btn-square]/btn:": "m-0!"
28
28
  }
29
- }), N = [
29
+ }), L = [
30
30
  "h1",
31
31
  "h2",
32
32
  "h3",
@@ -39,7 +39,7 @@ const f = (e) => e, L = f({
39
39
  "body-s",
40
40
  "callout"
41
41
  ], D = f({
42
- card: `data-[rounded=true]:rounded-$card-spacing data-[dense=true]:card-dense! ${N.map((e) => `data-[level=${e}]:card-${e}`).join(" ")}`
42
+ card: `data-[rounded=true]:rounded-$card-spacing data-[dense=true]:card-dense! ${L.map((e) => `data-[level=${e}]:card-${e}`).join(" ")}`
43
43
  }), T = f({
44
44
  "checkbox-root": {
45
45
  "": "text-body select-none flex gap-$m cursor-default current-bg-scope-color-500 current-border-scope-color-500",
@@ -80,7 +80,7 @@ const f = (e) => e, L = f({
80
80
  }), I = f({
81
81
  "menu-root": "flex flex-col overflow-hidden",
82
82
  "menu-item": "justify-start c8-flat gap-$m w-full fw-400"
83
- }), X = f({
83
+ }), B = f({
84
84
  "rb-container": {
85
85
  "": "flex flex-col gap-$s text-body"
86
86
  },
@@ -110,7 +110,7 @@ const f = (e) => e, L = f({
110
110
  "": "select-none px-$s text-body leading-none lh-1.25em",
111
111
  "aria-[disabled=true]:": "scope-grey opacity-50 cursor-not-allowed"
112
112
  }
113
- }), Y = f({
113
+ }), X = f({
114
114
  "select-content": {
115
115
  "": "min-w-[60px] rounded-base surface-0 bg-current overflow-hidden shadow-xl z-[100] current-border-grey-400 border-current/20 ",
116
116
  "data-[design=round]:": "rounded-fingertip-half",
@@ -136,7 +136,7 @@ const f = (e) => e, L = f({
136
136
  "[&>span]:data-[state=checked]:": "text-scope-color-500 fw-700!"
137
137
  },
138
138
  "select-separator": "h-[1px] bg-grey-500/10 mx-$s"
139
- }), B = f({
139
+ }), Y = f({
140
140
  slider: {
141
141
  "": "relative flex items-center select-none touch-none min-w-2em min-h-2em"
142
142
  },
@@ -156,17 +156,21 @@ const f = (e) => e, L = f({
156
156
  "focus:": "outline-[0.5em]"
157
157
  }
158
158
  }
159
- }), E = [
159
+ }), E = f({
160
+ "tabs-indicator": "absolute left-0 h-[2px] bottom-0 w-[--radix-tabs-indicator-size] translate-x-[--radix-tabs-indicator-position] rounded-full transition-all duration-200 bg-scope-color-500",
161
+ tab: "h-fingertip rounded flex items-center justify-center px-$m gap-$m select-none"
162
+ }), U = [
160
163
  D,
161
164
  I,
162
- L,
165
+ A,
163
166
  T,
167
+ B,
164
168
  X,
165
- Y,
166
169
  q,
167
- B,
168
- M
169
- ], U = f({
170
+ Y,
171
+ M,
172
+ E
173
+ ], J = f({
170
174
  // FILLED
171
175
  "c8-filled": {
172
176
  "": "current-bg-scope-color-500 rounded-base current-text-white current-icon-white icon-current/100 bg-current text-current",
@@ -191,8 +195,8 @@ const f = (e) => e, L = f({
191
195
  "hover:": "c8-flat-hover",
192
196
  "focus-visible:": "c8-flat-hover",
193
197
  "data-[highlighted]:": "c8-flat-hover",
194
- "active:": "c8-flat-active",
195
- "data-[active]:": "c8-flat-active",
198
+ // 'active:': 'c8-flat-active',
199
+ // 'data-[active]:': 'c8-flat-active', // messes up with tabs
196
200
  "data-[selected=true]:": "c8-flat-selected",
197
201
  "aria-[selected=true]:": "c8-flat-selected",
198
202
  "aria-[pressed=true]:": "c8-flat-selected"
@@ -200,9 +204,9 @@ const f = (e) => e, L = f({
200
204
  "c8-flat-hover": {
201
205
  "not-([disabled]):": "bg-current/05"
202
206
  },
203
- "c8-flat-active": {
204
- "not-([disabled]):": "bg-current/10"
205
- },
207
+ // 'c8-flat-active': {
208
+ // 'not-([disabled]):': 'bg-current/10', // messes up with tabs
209
+ // },
206
210
  "c8-flat-selected": {
207
211
  "": "c8-flat-hover current-text-scope-color-500 text-current current-icon-scope-color-500 icon-current/100",
208
212
  "dark:": "current-text-scope-color-400 current-icon-scope-color-400"
@@ -380,22 +384,22 @@ const f = (e) => e, L = f({
380
384
  function h(e) {
381
385
  let t = "";
382
386
  for (const [r, o] of Object.entries(e)) {
383
- const c = H(o);
384
- t += `${c.map((n) => `${r}${n}`).join(" ")} `;
387
+ const c = C(o);
388
+ t += `${c.map((i) => `${r}${i}`).join(" ")} `;
385
389
  }
386
390
  return t.trim();
387
391
  }
388
- function H(e) {
392
+ function C(e) {
389
393
  if (typeof e == "string")
390
394
  return e.split(" ");
391
395
  if (Array.isArray(e))
392
396
  return e;
393
397
  const t = [];
394
398
  for (const [r, o] of Object.entries(e))
395
- t.push(...H(o).map((c) => `${r}${c}`));
399
+ t.push(...C(o).map((c) => `${r}${c}`));
396
400
  return t;
397
401
  }
398
- const J = (e, t) => {
402
+ const K = (e, t) => {
399
403
  const r = {}, o = /* @__PURE__ */ new Set([...Object.keys(t), ...Object.keys(e)]);
400
404
  for (const c of Array.from(o))
401
405
  if (!Object.prototype.hasOwnProperty.call(t, c))
@@ -403,11 +407,11 @@ const J = (e, t) => {
403
407
  else if (!Object.prototype.hasOwnProperty.call(e, c))
404
408
  r[c] = t[c];
405
409
  else {
406
- let n = t[c], i = e[c];
407
- Array.isArray(n) && (n = n.join(" ")), Array.isArray(i) && (i = i.join(" ")), typeof n == "string" && typeof i == "string" ? r[c] = `${i} ${n}` : typeof n == "object" && typeof i == "string" ? r[c] = `${i} ${h(n)}` : typeof n == "string" && typeof i == "object" ? r[c] = `${h(i)} ${n}` : typeof n == "object" && typeof i == "object" && (r[c] = `${h(i)} ${h(n)}`);
410
+ let i = t[c], n = e[c];
411
+ Array.isArray(i) && (i = i.join(" ")), Array.isArray(n) && (n = n.join(" ")), typeof i == "string" && typeof n == "string" ? r[c] = `${n} ${i}` : typeof i == "object" && typeof n == "string" ? r[c] = `${n} ${h(i)}` : typeof i == "string" && typeof n == "object" ? r[c] = `${h(n)} ${i}` : typeof i == "object" && typeof n == "object" && (r[c] = `${h(n)} ${h(i)}`);
408
412
  }
409
413
  return r;
410
- }, R = (e) => e.reduce((t, r) => J(t, r), {}), K = {
414
+ }, H = (e) => e.reduce((t, r) => K(t, r), {}), Q = {
411
415
  colors: {
412
416
  primary: { color: "#004eaf", preserveInputColor: !0, saturate: { dark: -0.2, light: -0.2 } },
413
417
  grey: { color: "#858892", saturate: { dark: 0, light: 0 } },
@@ -558,14 +562,14 @@ const J = (e, t) => {
558
562
  ]
559
563
  }
560
564
  };
561
- function Q(e) {
565
+ function Z(e) {
562
566
  var d, g, v, y, k, $, x;
563
567
  const t = (e == null ? void 0 : e.colors) || {};
564
568
  for (const z of Object.keys(t)) {
565
569
  const j = (d = e == null ? void 0 : e.colors) == null ? void 0 : d[z];
566
570
  typeof j == "string" && (t[z] = { color: j });
567
571
  }
568
- const r = A({ ...e, colors: t }, K), o = {
572
+ const r = N({ ...e, colors: t }, Q), o = {
569
573
  count: 5,
570
574
  preserveInputColor: !1,
571
575
  luminance: {
@@ -577,14 +581,14 @@ function Q(e) {
577
581
  vivid: r.layerPalette.vivid,
578
582
  suffixes: ["dark-0", "dark-1", "dark-2", "dark-3", "dark-4"]
579
583
  }, c = w(
580
- P(r.colors, r.layerPalette.desaturate),
584
+ O(r.colors, r.layerPalette.desaturate),
581
585
  o
582
586
  ).toStrings();
583
587
  o.suffixes = ["light-0", "light-1", "light-2", "light-3", "light-4"].reverse();
584
- const n = o.luminance.light - o.luminance.dark;
585
- o.luminance = { dark: 1 - n, light: 1, useMiddle: !1 };
586
- const i = w(
587
- P(r.colors, r.layerPalette.desaturate),
588
+ const i = o.luminance.light - o.luminance.dark;
589
+ o.luminance = { dark: 1 - i, light: 1, useMiddle: !1 };
590
+ const n = w(
591
+ O(r.colors, r.layerPalette.desaturate),
588
592
  o
589
593
  ).toStrings(), l = w(
590
594
  {
@@ -610,26 +614,27 @@ function Q(e) {
610
614
  }
611
615
  ).toStrings();
612
616
  return {
617
+ opts: r,
613
618
  colors: {
614
619
  ...c,
615
- ...i,
620
+ ...n,
616
621
  ...l
617
622
  },
618
623
  surfaces: r.surfaces
619
624
  };
620
625
  }
621
- function P(e, t = 0.5) {
626
+ function O(e, t = 0.5) {
622
627
  const r = {};
623
628
  for (const [o, c] of Object.entries(e)) {
624
- const n = typeof c == "string" ? c : c.color;
625
- if (n) {
626
- const [i, l, d] = S(n).hsl();
627
- r[o] = S(i, l * t, d, "hsl").hex();
629
+ const i = typeof c == "string" ? c : c.color;
630
+ if (i) {
631
+ const [n, l, d] = S(i).hsl();
632
+ r[o] = S(n, l * t, d, "hsl").hex();
628
633
  }
629
634
  }
630
635
  return r;
631
636
  }
632
- function Z() {
637
+ function _() {
633
638
  return [
634
639
  [
635
640
  /^layer-([0-4])$/,
@@ -660,11 +665,11 @@ function p(e, t = 0) {
660
665
  return Math.round(e * r) / r;
661
666
  }
662
667
  function m(e, t, r = 3) {
663
- var n;
664
- const o = Number.parseFloat(e), c = ((n = /(px|em|rem|%)$/.exec(e)) == null ? void 0 : n[1]) || "";
668
+ var i;
669
+ const o = Number.parseFloat(e), c = ((i = /(px|em|rem|%)$/.exec(e)) == null ? void 0 : i[1]) || "";
665
670
  return `${p(o * t, r)}${c}`;
666
671
  }
667
- const _ = {
672
+ const ee = {
668
673
  getCSS: ({ theme: e }) => `${b("body", e.fontSize.body) + // renderFontCss('label', theme.fontSize.label) +
669
674
  b("figcaption", e.fontSize.caption) + b("h1", e.fontSize.h1) + b("h2", e.fontSize.h2) + b("h3", e.fontSize.h3) + b("h4", e.fontSize.h4) + b("h5", e.fontSize.h5) + b("h6", e.fontSize.h6)}
670
675
  :root {
@@ -723,7 +728,7 @@ function s(e) {
723
728
  const [t, r, o, c] = S(e).rgba();
724
729
  return `${t} ${r} ${o}`;
725
730
  }
726
- function O(e) {
731
+ function P(e) {
727
732
  return {
728
733
  bg: "--un-bg-opacity",
729
734
  text: "--un-text-opacity",
@@ -747,7 +752,7 @@ function W(e) {
747
752
  caret: "caret-color"
748
753
  }[e];
749
754
  }
750
- const ee = [
755
+ const re = [
751
756
  [
752
757
  /^current-(text|bg|icon|border|outline|caret|hl)-(.+)$/,
753
758
  (e, { theme: t }) => {
@@ -772,13 +777,13 @@ const ee = [
772
777
  [
773
778
  /^(text|bg|icon|border|outline|caret|fill)-current(-text|-bg|-icon|-border|-outline|-caret|-hl)?(\/\d{1,3})?$/,
774
779
  (e, { theme: t }) => {
775
- const r = e[1], o = e[2] || `-${r}`, c = O(r), n = W(r), i = e[3], l = i ? Number(i.slice(1)) / 100 : 1, d = l === 1 ? `var(${c})` : l;
780
+ const r = e[1], o = e[2] || `-${r}`, c = P(r), i = W(r), n = e[3], l = n ? Number(n.slice(1)) / 100 : 1, d = l === 1 ? `var(${c})` : l;
776
781
  return r === "icon" ? {
777
782
  [c]: l,
778
783
  "--current-icon": o === "-hl" ? `var(--current${o})` : void 0
779
784
  } : {
780
785
  [c]: l,
781
- [n]: `rgb(var(--current${o}) / ${d})`
786
+ [i]: `rgb(var(--current${o}) / ${d})`
782
787
  };
783
788
  }
784
789
  ],
@@ -816,9 +821,9 @@ const ee = [
816
821
  [
817
822
  /^(bg|text|fill|stroke|border|outline|icon|caret)-scope-((?:color|dark|light|text|bg|white|black|icon)(?:-\d+)?)(\/\d{1,3})?$/,
818
823
  (e, { theme: t }) => {
819
- const r = W(e[1]), o = O(e[1]), c = e[2], n = e[3], i = n ? Number(n.slice(1)) / 100 : 1, l = c.startsWith("color") ? `grey-${c.slice(6)}` : `grey-${c}`, d = i === 1 ? `var(${o})` : i;
824
+ const r = W(e[1]), o = P(e[1]), c = e[2], i = e[3], n = i ? Number(i.slice(1)) / 100 : 1, l = c.startsWith("color") ? `grey-${c.slice(6)}` : `grey-${c}`, d = n === 1 ? `var(${o})` : n;
820
825
  return {
821
- [o]: i,
826
+ [o]: n,
822
827
  [r]: `rgb(var(--scope-${c}, ${t.colors[l] || ""}) / ${d})`
823
828
  };
824
829
  }
@@ -838,23 +843,23 @@ const ee = [
838
843
  color: "rgb(var(--current-icon) / var(--un-icon-opacity, 1))"
839
844
  })
840
845
  ]
841
- ], re = [
846
+ ], te = [
842
847
  [
843
848
  // special text margin (vertical) that compensates
844
849
  // the line height
845
850
  /^text-m([bty])?-(.*)$/,
846
851
  (e, { theme: t }) => {
847
- const r = e[1], o = e[2], c = r ? { y: ["top", "bottom"], t: ["top"], b: ["bottom"] }[r] : ["top", "bottom", "left", "right"], n = {};
852
+ const r = e[1], o = e[2], c = r ? { y: ["top", "bottom"], t: ["top"], b: ["bottom"] }[r] : ["top", "bottom", "left", "right"], i = {};
848
853
  if (t.spacing[o]) {
849
- for (const i of c)
850
- n[`margin-${i}`] = ["left", "right"].includes(i) ? t.spacing[o] : `calc(${t.spacing[o]} + var(--font-${i === "top" ? "tc" : "bc"}))`;
851
- return n;
854
+ for (const n of c)
855
+ i[`margin-${n}`] = ["left", "right"].includes(n) ? t.spacing[o] : `calc(${t.spacing[o]} + var(--font-${n === "top" ? "tc" : "bc"}))`;
856
+ return i;
852
857
  } else if (/^\d+(em|rem|px)?$/.test(o)) {
853
- let i = o;
854
- /^[\d.]+$/.test(o) && (i = `${Number(o) * 0.25}rem`);
858
+ let n = o;
859
+ /^[\d.]+$/.test(o) && (n = `${Number(o) * 0.25}rem`);
855
860
  for (const l of c)
856
- n[`margin-${l}`] = ["left", "right"].includes(l) ? i : `calc(${i} + var(--font-${l === "top" ? "tc" : "bc"}))`;
857
- return n;
861
+ i[`margin-${l}`] = ["left", "right"].includes(l) ? n : `calc(${n} + var(--font-${l === "top" ? "tc" : "bc"}))`;
862
+ return i;
858
863
  }
859
864
  },
860
865
  { layer: "utilities" }
@@ -912,7 +917,7 @@ const ee = [
912
917
  };
913
918
  }
914
919
  ]
915
- ], te = [...re, ...ee];
920
+ ], oe = [...te, ...re];
916
921
  function a(e, t = 1) {
917
922
  return t * 1.618 ** e;
918
923
  }
@@ -925,7 +930,7 @@ function u(e, t, r, o, c) {
925
930
  spacing: c
926
931
  };
927
932
  }
928
- const oe = {
933
+ const ce = {
929
934
  h1: (
930
935
  /* */
931
936
  u(
@@ -1081,8 +1086,8 @@ const oe = {
1081
1086
  )
1082
1087
  )
1083
1088
  };
1084
- function ce(e, t, r, o, c, n = 1, i = 0.5) {
1085
- const l = e * n, g = (o * e - l) / e, v = l / 2, y = l * i - v + g / 2, k = l * (1 - i) - v + g / 2, $ = p(y, 4), x = p(k, 4);
1089
+ function ne(e, t, r, o, c, i = 1, n = 0.5) {
1090
+ const l = e * i, g = (o * e - l) / e, v = l / 2, y = l * n - v + g / 2, k = l * (1 - n) - v + g / 2, $ = p(y, 4), x = p(k, 4);
1086
1091
  return {
1087
1092
  mt: $,
1088
1093
  mb: x,
@@ -1107,7 +1112,7 @@ function ce(e, t, r, o, c, n = 1, i = 0.5) {
1107
1112
  ]
1108
1113
  };
1109
1114
  }
1110
- const ne = (e) => {
1115
+ const ie = (e) => {
1111
1116
  const t = {
1112
1117
  // canonical
1113
1118
  $xxs: `${p(1 / e.spacingFactor ** 3, 3)}em`,
@@ -1149,7 +1154,7 @@ const ne = (e) => {
1149
1154
  base: e.baseRadius
1150
1155
  }, c = {
1151
1156
  $bold: "var(--font-bold)"
1152
- }, n = {
1157
+ }, i = {
1153
1158
  "card-header": [
1154
1159
  "var(--card-heading-size)",
1155
1160
  {
@@ -1166,7 +1171,7 @@ const ne = (e) => {
1166
1171
  };
1167
1172
  for (const [l, d] of Object.entries(e.typography))
1168
1173
  if (d != null && d.size) {
1169
- const g = ce(
1174
+ const g = ne(
1170
1175
  d.size || 1,
1171
1176
  d.weight || 400,
1172
1177
  d.boldWeight || 700,
@@ -1175,58 +1180,60 @@ const ne = (e) => {
1175
1180
  d.actualHeightFactor || e.actualFontHeightFactor,
1176
1181
  d.actualHeightTopBottomRatio || e.actualFontHeightTopBottomRatio
1177
1182
  );
1178
- n[l] = g.theme, t[l] = `${g.size}em`;
1183
+ i[l] = g.theme, t[l] = `${g.size}em`;
1179
1184
  }
1180
- const i = Q(e.palette);
1185
+ const n = Z(e.palette);
1181
1186
  return {
1182
- colors: i.colors,
1183
- surfaces: i.surfaces,
1184
- borderColor: "red",
1185
- reverseLightLayers: e.layers.reverseLight,
1186
- reverseDarkLayers: e.layers.reverseDark,
1187
- lineHeight: r,
1188
- spacing: t,
1189
- fontWeight: c,
1190
- actualFontHeightFactor: e.actualFontHeightFactor,
1191
- cardSpacingFactor: e.cardSpacingFactor,
1192
- fontSize: n,
1193
- width: t,
1194
- height: t,
1195
- maxWidth: t,
1196
- maxHeight: t,
1197
- minWidth: t,
1198
- minHeight: t,
1199
- borderRadius: o,
1200
- animation: {
1201
- durations: {
1202
- "slide-down-and-fade": "100ms",
1203
- "slide-left-and-fade": "100ms",
1204
- "slide-up-and-fade": "100ms",
1205
- "slide-right-and-fade": "100ms",
1206
- "zoom-fade-in": "100ms"
1207
- },
1208
- keyframes: {
1209
- "slide-down-and-fade": `{
1187
+ paletteOpts: n.opts,
1188
+ theme: {
1189
+ colors: n.colors,
1190
+ surfaces: n.surfaces,
1191
+ borderColor: "red",
1192
+ reverseLightLayers: e.layers.reverseLight,
1193
+ reverseDarkLayers: e.layers.reverseDark,
1194
+ lineHeight: r,
1195
+ spacing: t,
1196
+ fontWeight: c,
1197
+ actualFontHeightFactor: e.actualFontHeightFactor,
1198
+ cardSpacingFactor: e.cardSpacingFactor,
1199
+ fontSize: i,
1200
+ width: t,
1201
+ height: t,
1202
+ maxWidth: t,
1203
+ maxHeight: t,
1204
+ minWidth: t,
1205
+ minHeight: t,
1206
+ borderRadius: o,
1207
+ animation: {
1208
+ durations: {
1209
+ "slide-down-and-fade": "100ms",
1210
+ "slide-left-and-fade": "100ms",
1211
+ "slide-up-and-fade": "100ms",
1212
+ "slide-right-and-fade": "100ms",
1213
+ "zoom-fade-in": "100ms"
1214
+ },
1215
+ keyframes: {
1216
+ "slide-down-and-fade": `{
1210
1217
  from { opacity: 0; transform: translateY(-6px) }
1211
1218
  to { opacity: 1; transform: translateY(0) }
1212
1219
  }`,
1213
- "slide-left-and-fade": `{
1220
+ "slide-left-and-fade": `{
1214
1221
  from { opacity: 0; transform: translateX(6px) }
1215
1222
  to { opacity: 1; transform: translateX(0) }
1216
1223
  }`,
1217
- "slide-up-and-fade": `{
1224
+ "slide-up-and-fade": `{
1218
1225
  from { opacity: 0; transform: translateY(6px) }
1219
1226
  to { opacity: 1; transform: translateY(0) }
1220
1227
  }`,
1221
- "slide-right-and-fade": `{
1228
+ "slide-right-and-fade": `{
1222
1229
  from { opacity: 0; transform: translateX(-6px) }
1223
1230
  to { opacity: 1; transform: translateX(0) }
1224
1231
  }`,
1225
- "zoom-fade-in": `{
1232
+ "zoom-fade-in": `{
1226
1233
  from { opacity: 0; transform: scale(1.02) }
1227
1234
  to { opacity: 1; transform: scale(1) }
1228
1235
  }`,
1229
- "loading-dashoffset": `{
1236
+ "loading-dashoffset": `{
1230
1237
  from {
1231
1238
  stroke-dashoffset: 0;
1232
1239
  }
@@ -1234,7 +1241,7 @@ const ne = (e) => {
1234
1241
  stroke-dashoffset: -76;
1235
1242
  }
1236
1243
  }`,
1237
- "cb-appear": `{
1244
+ "cb-appear": `{
1238
1245
  from {
1239
1246
  clip-path: polygon(0 0, 0 0, 0 100%, 0 100%);
1240
1247
  }
@@ -1242,20 +1249,21 @@ const ne = (e) => {
1242
1249
  clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%);
1243
1250
  }
1244
1251
  }`
1252
+ }
1245
1253
  }
1254
+ // animation: {
1255
+ // slideDownAndFade: 'slideDownAndFade 400ms cubic-bezier(0.16, 1, 0.3, 1)',
1256
+ // slideLeftAndFade: 'slideLeftAndFade 400ms cubic-bezier(0.16, 1, 0.3, 1)',
1257
+ // slideUpAndFade: 'slideUpAndFade 400ms cubic-bezier(0.16, 1, 0.3, 1)',
1258
+ // slideRightAndFade: 'slideRightAndFade 400ms cubic-bezier(0.16, 1, 0.3, 1)',
1259
+ // },
1246
1260
  }
1247
- // animation: {
1248
- // slideDownAndFade: 'slideDownAndFade 400ms cubic-bezier(0.16, 1, 0.3, 1)',
1249
- // slideLeftAndFade: 'slideLeftAndFade 400ms cubic-bezier(0.16, 1, 0.3, 1)',
1250
- // slideUpAndFade: 'slideUpAndFade 400ms cubic-bezier(0.16, 1, 0.3, 1)',
1251
- // slideRightAndFade: 'slideRightAndFade 400ms cubic-bezier(0.16, 1, 0.3, 1)',
1252
- // },
1253
1261
  };
1254
1262
  };
1255
1263
  function V(e, t = 1) {
1256
1264
  return t * Math.sqrt(1.618) ** e;
1257
1265
  }
1258
- const ie = {
1266
+ const ae = {
1259
1267
  spacingFactor: 1.618,
1260
1268
  actualFontHeightFactor: 1,
1261
1269
  actualFontHeightTopBottomRatio: 0.52,
@@ -1263,7 +1271,7 @@ const ie = {
1263
1271
  regular: 1,
1264
1272
  dense: 0.6
1265
1273
  },
1266
- typography: oe,
1274
+ typography: ce,
1267
1275
  layers: {
1268
1276
  reverseDark: !1,
1269
1277
  reverseLight: !1
@@ -1276,14 +1284,18 @@ const ie = {
1276
1284
  xl: "4em"
1277
1285
  },
1278
1286
  baseRadius: `${p(1 / 1.618, 3)}em`
1279
- }, fe = (e) => {
1280
- const t = F(e, ie), r = ae();
1281
- r.preflights || (r.preflights = []), r.preflights.push(_), r.rules || (r.rules = []), r.rules.push(...te);
1282
- const o = Z();
1283
- return {
1287
+ }, ge = (e) => {
1288
+ const t = F(e, ae), r = le();
1289
+ r.preflights || (r.preflights = []), r.preflights.push(ee), r.rules || (r.rules = []), r.rules.push(...oe);
1290
+ const o = _(), c = ie(t);
1291
+ return r.preflights.push({
1292
+ getCSS: () => `__vunor_palette_options {background-image: url("data:image/gif;base64,${Buffer.from(
1293
+ JSON.stringify({ ...c.paletteOpts, surfaces: void 0 })
1294
+ ).toString("base64")}")}`
1295
+ }), {
1284
1296
  ...r,
1285
1297
  name: "vunor",
1286
- theme: F(ne(t), r.theme),
1298
+ theme: F(c.theme, r.theme),
1287
1299
  shortcuts: o,
1288
1300
  layers: {
1289
1301
  preflights: 0,
@@ -1293,26 +1305,26 @@ const ie = {
1293
1305
  }
1294
1306
  };
1295
1307
  };
1296
- function ae() {
1308
+ function le() {
1297
1309
  var t;
1298
- const e = C();
1310
+ const e = R();
1299
1311
  return (t = e.rules) == null || t.forEach((r) => {
1300
1312
  r[0] instanceof RegExp && (r[0].source.startsWith("^m-") || r[0].source.startsWith("^ma?") || r[0].source.startsWith("^p-?") || r[0].source.startsWith("^pa?")) && (r[2] = r[2] || {}, r[2].layer = "utilities");
1301
1313
  }), e;
1302
1314
  }
1303
- const le = [G, U, ...E], se = R(le);
1304
- function ge(e, t = se) {
1305
- const r = e ? R([t, e]) : t;
1315
+ const se = [G, J, ...U], de = H(se);
1316
+ function be(e, t = de) {
1317
+ const r = e ? H([t, e]) : t;
1306
1318
  for (const [o, c] of Object.entries(r))
1307
1319
  r[o] = typeof c == "string" ? c : h(c);
1308
1320
  return r;
1309
1321
  }
1310
1322
  export {
1311
1323
  f as defineShortcuts,
1312
- R as mergeVunorShortcuts,
1313
- se as mergedVunorShortcuts,
1314
- fe as presetVunor,
1315
- le as rawVunorShortcuts,
1324
+ H as mergeVunorShortcuts,
1325
+ de as mergedVunorShortcuts,
1326
+ ge as presetVunor,
1327
+ se as rawVunorShortcuts,
1316
1328
  h as toUnoShortcut,
1317
- ge as vunorShortcuts
1329
+ be as vunorShortcuts
1318
1330
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vunor",
3
- "version": "0.0.11",
3
+ "version": "0.0.13",
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "dev": "vite",
@@ -63,7 +63,8 @@
63
63
  "./RadioGroup.vue": "./src/components/RadioGroup/RadioGroup.vue",
64
64
  "./Select.vue": "./src/components/Select/Select.vue",
65
65
  "./SelectBase.vue": "./src/components/Select/SelectBase.vue",
66
- "./Slider.vue": "./src/components/Slider/Slider.vue"
66
+ "./Slider.vue": "./src/components/Slider/Slider.vue",
67
+ "./Tabs.vue": "./src/components/Tabs/Tabs.vue"
67
68
  },
68
69
  "devDependencies": {
69
70
  "@iconify/utils": "^2.1.23",
@@ -0,0 +1,374 @@
1
+ <script setup lang="ts">
2
+ import { ref, reactive, onMounted } from 'vue'
3
+ import { VuButton } from '../Button'
4
+ import { VuCard, VuCardHeader, VuCardInner } from '../Card'
5
+ import { TVunorPaletteColor, TVunorPaletteOptions } from '../../theme'
6
+ import { VuInput } from '../Input'
7
+ import VuSlider from '../Slider/Slider.vue'
8
+ import VuTabs from '../Tabs/Tabs.vue'
9
+ import { generatePalette } from '../../theme/palitra'
10
+ import { color } from '@prostojs/palitra'
11
+
12
+ function colorToRgbWithOpacity(c: string) {
13
+ const [r, g, b, a] = color(c).rgba()
14
+ return `${r} ${g} ${b}`
15
+ }
16
+
17
+ function debounce<T extends (...args: any[]) => any>(
18
+ func: T,
19
+ wait: number
20
+ ): (...args: Parameters<T>) => void {
21
+ let timeoutId: number | undefined
22
+
23
+ return (...args: Parameters<T>): void => {
24
+ if (timeoutId !== undefined) {
25
+ clearTimeout(timeoutId)
26
+ }
27
+
28
+ timeoutId = window.setTimeout(() => {
29
+ func(...args)
30
+ }, wait)
31
+ }
32
+ }
33
+
34
+ const props = defineProps<{
35
+ defaultOpen?: boolean
36
+ }>()
37
+
38
+ const modelValue = defineModel('open')
39
+ modelValue.value = !!props.defaultOpen
40
+
41
+ type TColor = TVunorPaletteColor & { name: string }
42
+ type TPalette = Required<
43
+ Omit<TVunorPaletteOptions, 'colors'> & { colors: Record<string, TVunorPaletteColor> }
44
+ >
45
+
46
+ const colors = ref<TColor[]>([])
47
+ const mainPalette = ref<TPalette['mainPalette']>({})
48
+ const layerPalette = ref<TPalette['layerPalette']>({})
49
+ const misc = ref<Pick<TPalette, 'darkest' | 'lightest' | 'layersDepth'>>({
50
+ darkest: 0.24,
51
+ lightest: 0.97,
52
+ layersDepth: 0.08,
53
+ })
54
+
55
+ const mainSlider = ref<[number, number, number]>([0, 0, 0])
56
+
57
+ function cleanup() {
58
+ const s = document.head.querySelector('style#vunor-palette-sandbox')
59
+ if (s) {
60
+ document.head.removeChild(s)
61
+ }
62
+ }
63
+
64
+ const apply = debounce(() => {
65
+ cleanup()
66
+ const opts = {
67
+ darkest: mainSlider.value[0],
68
+ lightest: mainSlider.value[2],
69
+ mainPalette: {
70
+ luminance: {
71
+ middle: mainSlider.value[1],
72
+ },
73
+ },
74
+ colors: {} as Record<string, TVunorPaletteColor>,
75
+ } as Exclude<Required<Parameters<typeof generatePalette>[0]>, undefined>
76
+
77
+ for (const c of colors.value) {
78
+ opts.colors[c.name as 'primary'] = c as TVunorPaletteColor
79
+ }
80
+
81
+ const { colors: result } = generatePalette(opts)
82
+
83
+ const newS = document.createElement('style')
84
+ newS.id = 'vunor-palette-sandbox'
85
+
86
+ const suffixes = ['50', '100', '200', '300', '400', '500', '600', '700', '800', '900']
87
+ const ld = [
88
+ 'light-0',
89
+ 'light-1',
90
+ 'light-2',
91
+ 'light-3',
92
+ 'light-4',
93
+ 'dark-0',
94
+ 'dark-1',
95
+ 'dark-2',
96
+ 'dark-3',
97
+ 'dark-4',
98
+ ]
99
+
100
+ for (const c of ['primary', 'secondary', 'grey', 'neutral', 'good', 'warn', 'error']) {
101
+ newS.innerText += `.scope-${c} {\n`
102
+ const col = result[c]!
103
+ for (const s of suffixes) {
104
+ newS.innerText += `--scope-color-${s}: ${
105
+ colorToRgbWithOpacity(result[`${c}-${s}`]!) || ''
106
+ };\n`
107
+ }
108
+ newS.innerText += `--scope-color: ${colorToRgbWithOpacity(col)};\n`
109
+ newS.innerText += `--current-hl: ${colorToRgbWithOpacity(result[`${c}-500`]!) || ''};\n`
110
+
111
+ for (const s of ld) {
112
+ newS.innerText += `--scope-${s}: ${colorToRgbWithOpacity(result[`${c}-${s}`]!) || ''};\n`
113
+ }
114
+ newS.innerText += '}\n'
115
+
116
+ for (const s of suffixes) {
117
+ newS.innerText += `.text-${c}-${s}{color:rgb(${colorToRgbWithOpacity(
118
+ result[`${c}-${s}`]!
119
+ )} / var(--un-text-opacity))}\n`
120
+ newS.innerText += `.bg-${c}-${s}{background-color:rgb(${colorToRgbWithOpacity(
121
+ result[`${c}-${s}`]!
122
+ )} / var(--un-bg-opacity))}\n`
123
+ newS.innerText += `.current-outline-${c}-${s}{--current-outline:${colorToRgbWithOpacity(
124
+ result[`${c}-${s}`]!
125
+ )};}\n`
126
+ newS.innerText += `.current-text-${c}-${s}{--current-text:${colorToRgbWithOpacity(
127
+ result[`${c}-${s}`]!
128
+ )};}\n`
129
+ newS.innerText += `.current-bg-${c}-${s}{--current-bg:${colorToRgbWithOpacity(
130
+ result[`${c}-${s}`]!
131
+ )};}\n`
132
+ newS.innerText += `.current-border-${c}-${s}{--current-border:${colorToRgbWithOpacity(
133
+ result[`${c}-${s}`]!
134
+ )};}\n`
135
+ newS.innerText += `.current-icon-${c}-${s}{--current-icon:${colorToRgbWithOpacity(
136
+ result[`${c}-${s}`]!
137
+ )};}\n`
138
+ }
139
+ }
140
+
141
+ document.head.appendChild(newS)
142
+ }, 100)
143
+
144
+ function reset() {
145
+ if (document?.head) {
146
+ cleanup()
147
+ // @ts-expect-error
148
+ const s = document.head.querySelector('style[data-vite-dev-id="\\/__uno.css"]').textContent
149
+ if (s) {
150
+ const base64 =
151
+ /__vunor_palette_options\s\{background-image:\surl\(\"data:image\/gif;base64,([^"]+)/.exec(
152
+ s
153
+ )?.[1]
154
+ if (base64) {
155
+ const paletteOpts = JSON.parse(atob(base64)) as TPalette
156
+ colors.value = []
157
+ mainPalette.value = { ...paletteOpts.mainPalette }
158
+ layerPalette.value = { ...paletteOpts.layerPalette }
159
+ misc.value = {
160
+ darkest: paletteOpts.darkest,
161
+ lightest: paletteOpts.lightest,
162
+ layersDepth: paletteOpts.layersDepth,
163
+ }
164
+ mainSlider.value = [
165
+ misc.value.darkest,
166
+ mainPalette.value.luminance!.middle!,
167
+ misc.value.lightest,
168
+ ]
169
+ for (const [name, val] of Object.entries(paletteOpts.colors)) {
170
+ colors.value.push({
171
+ color: val.color,
172
+ preserveInputColor:
173
+ val.preserveInputColor === paletteOpts.mainPalette.preserveInputColor
174
+ ? val.preserveInputColor
175
+ : undefined,
176
+ saturate: {
177
+ dark:
178
+ val.saturate?.dark === paletteOpts.mainPalette.saturate?.dark
179
+ ? val.saturate?.dark
180
+ : undefined,
181
+ light:
182
+ val.saturate?.light === paletteOpts.mainPalette.saturate?.light
183
+ ? val.saturate?.light
184
+ : undefined,
185
+ },
186
+ vivid: {
187
+ dark:
188
+ val.vivid?.dark === paletteOpts.mainPalette.vivid?.dark
189
+ ? val.vivid?.dark
190
+ : undefined,
191
+ light:
192
+ val.vivid?.light === paletteOpts.mainPalette.vivid?.light
193
+ ? val.vivid?.light
194
+ : undefined,
195
+ },
196
+ name,
197
+ })
198
+ }
199
+ }
200
+ }
201
+ }
202
+ }
203
+
204
+ onMounted(reset)
205
+
206
+ const tab = ref('colors')
207
+
208
+ // dragging the popup:
209
+ const down = ref(false)
210
+ const offset = reactive({
211
+ x: 12,
212
+ y: 12,
213
+ })
214
+
215
+ const grabbedAt = {
216
+ x: 0,
217
+ y: 0,
218
+ }
219
+ const prevPos = {
220
+ x: 0,
221
+ y: 0,
222
+ }
223
+
224
+ function onMouseDown(event: MouseEvent) {
225
+ down.value = true
226
+ grabbedAt.x = event.screenX
227
+ grabbedAt.y = event.screenY
228
+ window.addEventListener('mouseup', onMouseUp)
229
+ window.addEventListener('mousemove', onMouseMove)
230
+ prevPos.x = offset.x
231
+ prevPos.y = offset.y
232
+ }
233
+
234
+ function onMouseUp(event: MouseEvent) {
235
+ down.value = false
236
+ if (grabbedAt.x !== event.screenX || grabbedAt.y !== event.screenY) {
237
+ event.stopPropagation()
238
+ event.preventDefault()
239
+ } else {
240
+ modelValue.value = !modelValue.value
241
+ }
242
+ window.removeEventListener('mouseup', onMouseUp)
243
+ window.removeEventListener('mousemove', onMouseMove)
244
+ }
245
+
246
+ function onMouseMove(event: MouseEvent) {
247
+ offset.x = prevPos.x + event.screenX - grabbedAt.x
248
+ offset.y = prevPos.y + event.screenY - grabbedAt.y
249
+ }
250
+ </script>
251
+
252
+ <template>
253
+ <div
254
+ v-if="colors?.length > 0"
255
+ :style="{
256
+ transform: `translate(${offset.x}px, ${offset.y}px)`,
257
+ }"
258
+ class="fingertip-[2em] fixed left-0 top-0 max-w-screen max-h-screen text-11px"
259
+ :class="{
260
+ 'w-[30em] h-[40em]': modelValue,
261
+ 'w-[3em] h-[3em]': !modelValue,
262
+ }"
263
+ >
264
+ <VuCard
265
+ no-padding
266
+ rounded
267
+ level="h6"
268
+ class="layer-0 transition-all-200 w-[30em] h-[40em] border border-grey-500/50 overflow-clip flex flex-col transform-origin-tl"
269
+ :class="{
270
+ 'scale-100 shadow-md opacity-50 hover:opacity-100': modelValue,
271
+ 'scale-20 opacity-0 pointer-events-none': !modelValue,
272
+ }"
273
+ >
274
+ <VuCardInner
275
+ @mousedown="onMouseDown"
276
+ :class="{
277
+ 'cursor-grab': !down,
278
+ 'cursor-grabbing': down,
279
+ }"
280
+ class="layer-2 flex justify-between items-center fingertip-[1em] select-none"
281
+ >
282
+ <VuCardHeader class="text-mb-0 text-mt-0">Vunor Palette Sandbox</VuCardHeader>
283
+ <VuButton
284
+ icon="i--clear"
285
+ class="c8-flat btn-square rounded"
286
+ @mousedown.stop=""
287
+ @click.stop="modelValue = !modelValue"
288
+ />
289
+ </VuCardInner>
290
+
291
+ <VuCardInner class="layer-0 border-b">
292
+ <VuTabs
293
+ default-value="colors"
294
+ v-model="tab"
295
+ :tabs="[
296
+ { value: 'colors', label: 'Colors ' },
297
+ { value: 'main', label: 'Main Palette' },
298
+ { value: 'layers', label: 'Layers Palette' },
299
+ ]"
300
+ />
301
+ </VuCardInner>
302
+
303
+ <VuCardInner class="layer-0 flex-grow overflow-auto pt-$l">
304
+ <div class="text-primary-700">Test</div>
305
+ <!-- colors -->
306
+ <div v-if="tab === 'colors'">
307
+ <VuSlider
308
+ label="Darkest | Middle | Brightest"
309
+ :min="0"
310
+ :max="1"
311
+ :step="0.01"
312
+ :thumbs="3"
313
+ v-model="mainSlider"
314
+ class="mb-$l"
315
+ @update:model-value="apply"
316
+ />
317
+ <div v-for="c of colors" :key="c.name" class="flex items-center gap-$xs">
318
+ <VuInput
319
+ v-model="c.color"
320
+ stack-label
321
+ design="filled"
322
+ class="w-12em"
323
+ @update:model-value="apply"
324
+ >
325
+ <template v-slot:before>
326
+ <input
327
+ type="color"
328
+ :id="`vunor-color-${c.name}`"
329
+ v-model="c.color"
330
+ class="p-0 size-[2em] bg-transparent"
331
+ @input="apply"
332
+ />
333
+ </template>
334
+ </VuInput>
335
+ </div>
336
+ </div>
337
+ </VuCardInner>
338
+
339
+ <VuCardInner class="layer-2 flex justify-center">
340
+ <VuButton label="Reset All" @click="reset" class="c8-flat" />
341
+ </VuCardInner>
342
+ </VuCard>
343
+ <!-- prettier-ignore-attribute class -->
344
+ <div
345
+ class="absolute
346
+ shadow-[0_0_5px_2px_rgb(var(--scope-color-500))]
347
+ left-0
348
+ top-0
349
+ size-[3em]
350
+ rounded-full
351
+ transition-opacity-200
352
+ surface-500
353
+ flex
354
+ justify-center
355
+ items-center
356
+ current-outline-primary-700
357
+ outline-current
358
+ outline-[2px]
359
+ outline-solid
360
+ hover:opacity-100
361
+ cursor-pointer
362
+ select-none"
363
+ title="Vunor Palette Sandbox"
364
+ :class="{
365
+ 'opacity-0 pointer-events-none': modelValue,
366
+ 'opacity-50': !modelValue,
367
+ 'cursor-grabbing': down,
368
+ }"
369
+ @mousedown="onMouseDown"
370
+ >
371
+ <strong class="text-16px text-mb-0">V</strong>
372
+ </div>
373
+ </div>
374
+ </template>
@@ -0,0 +1,42 @@
1
+ <script setup lang="ts" generic="T extends { icon?: string; label?: string; value: string }">
2
+ import { TabsRoot, TabsList, TabsIndicator, TabsTrigger, TabsContent } from 'radix-vue'
3
+
4
+ withDefaults(
5
+ defineProps<{
6
+ tabs: T[]
7
+ defaultValue?: string
8
+ activationMode?: 'automatic' | 'manual'
9
+ dir?: 'ltr' | 'rtl'
10
+ indicator?: boolean
11
+ noContent?: boolean
12
+ orientation?: 'vertical' | 'horizontal'
13
+ tabsListClass?: string | Record<string, boolean> | string[]
14
+ tabGrow?: boolean
15
+ tabClass?: string
16
+ }>(),
17
+ {
18
+ tabsListClass: 'flex relative',
19
+ tabClass: 'c8-flat',
20
+ }
21
+ )
22
+
23
+ const modelValue = defineModel<string>()
24
+ </script>
25
+
26
+ <template>
27
+ <TabsRoot v-model="modelValue" :default-value :activation-mode :dir :orientation>
28
+ <TabsList :class="tabsListClass">
29
+ <TabsIndicator v-if="indicator" class="tabs-indicator"> </TabsIndicator>
30
+ <TabsTrigger v-for="tab of tabs" as-child :value="tab.value">
31
+ <slot v-bind="tab">
32
+ <div class="tab" :class="{ grow: tabGrow, [tabClass]: true }">
33
+ {{ tab.label ?? tab.value }}
34
+ </div>
35
+ </slot>
36
+ </TabsTrigger>
37
+ </TabsList>
38
+ <TabsContent v-if="!noContent" v-for="tab of tabs" as-child :value="tab.value">
39
+ <slot :name="tab.value"></slot>
40
+ </TabsContent>
41
+ </TabsRoot>
42
+ </template>
@@ -0,0 +1,7 @@
1
+ import { defineShortcuts } from '../../theme/utils/define-sc'
2
+
3
+ export const tabShortcuts = defineShortcuts({
4
+ 'tabs-indicator':
5
+ 'absolute left-0 h-[2px] bottom-0 w-[--radix-tabs-indicator-size] translate-x-[--radix-tabs-indicator-position] rounded-full transition-all duration-200 bg-scope-color-500',
6
+ 'tab': 'h-fingertip rounded flex items-center justify-center px-$m gap-$m select-none',
7
+ })
@@ -7,6 +7,7 @@ import { menuShortcuts } from './Menu/shortcuts'
7
7
  import { radioShortcuts } from './RadioGroup/shortcuts'
8
8
  import { selectShortcuts } from './Select/shortcuts'
9
9
  import { sliderShortcuts } from './Slider/shortcuts'
10
+ import { tabShortcuts } from './Tabs/shortcuts'
10
11
 
11
12
  export const shortcuts = [
12
13
  cardShortcuts,
@@ -18,4 +19,5 @@ export const shortcuts = [
18
19
  comboboxShortcuts,
19
20
  sliderShortcuts,
20
21
  loadingShortcuts,
22
+ tabShortcuts,
21
23
  ]