vueless 0.0.690 → 0.0.692

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/constants.js CHANGED
@@ -22,6 +22,8 @@ export const DEFAULT_RING_OFFSET = 0; /* pixels */
22
22
  export const DEFAULT_RING_OFFSET_COLOR_LIGHT = "#ffffff"; // white
23
23
  export const DEFAULT_RING_OFFSET_COLOR_DARK = "#111827"; // gray-900
24
24
  export const DEFAULT_ROUNDING = 8; /* pixels */
25
+ export const ROUNDING_DECREMENT = 4; /* pixels */
26
+ export const ROUNDING_INCREMENT = 6; /* pixels */
25
27
 
26
28
  /* Vueless supported colors and shades */
27
29
  export const COLOR_SHADES = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950];
@@ -237,3 +239,294 @@ export const TAILWIND_VARIANT_DELIMITER = ":";
237
239
  export const TAILWIND_VARIANT_DELIMITER_REG_EXP = /:(?![^[]*])/;
238
240
  export const JAVASCRIPT_EXT = ".js";
239
241
  export const TYPESCRIPT_EXT = ".ts";
242
+
243
+ /* Default tailwind colors */
244
+ export const TAILWIND_COLORS = {
245
+ slate: {
246
+ 50: "#f8fafc",
247
+ 100: "#f1f5f9",
248
+ 200: "#e2e8f0",
249
+ 300: "#cbd5e1",
250
+ 400: "#94a3b8",
251
+ 500: "#64748b",
252
+ 600: "#475569",
253
+ 700: "#334155",
254
+ 800: "#1e293b",
255
+ 900: "#0f172a",
256
+ 950: "#020617",
257
+ },
258
+ /* ex. `gray` color */
259
+ cool: {
260
+ 50: "#f9fafb",
261
+ 100: "#f3f4f6",
262
+ 200: "#e5e7eb",
263
+ 300: "#d1d5db",
264
+ 400: "#9ca3af",
265
+ 500: "#6b7280",
266
+ 600: "#4b5563",
267
+ 700: "#374151",
268
+ 800: "#1f2937",
269
+ 900: "#111827",
270
+ 950: "#030712",
271
+ },
272
+ zinc: {
273
+ 50: "#fafafa",
274
+ 100: "#f4f4f5",
275
+ 200: "#e4e4e7",
276
+ 300: "#d4d4d8",
277
+ 400: "#a1a1aa",
278
+ 500: "#71717a",
279
+ 600: "#52525b",
280
+ 700: "#3f3f46",
281
+ 800: "#27272a",
282
+ 900: "#18181b",
283
+ 950: "#09090b",
284
+ },
285
+ neutral: {
286
+ 50: "#fafafa",
287
+ 100: "#f5f5f5",
288
+ 200: "#e5e5e5",
289
+ 300: "#d4d4d4",
290
+ 400: "#a3a3a3",
291
+ 500: "#737373",
292
+ 600: "#525252",
293
+ 700: "#404040",
294
+ 800: "#262626",
295
+ 900: "#171717",
296
+ 950: "#0a0a0a",
297
+ },
298
+ stone: {
299
+ 50: "#fafaf9",
300
+ 100: "#f5f5f4",
301
+ 200: "#e7e5e4",
302
+ 300: "#d6d3d1",
303
+ 400: "#a8a29e",
304
+ 500: "#78716c",
305
+ 600: "#57534e",
306
+ 700: "#44403c",
307
+ 800: "#292524",
308
+ 900: "#1c1917",
309
+ 950: "#0c0a09",
310
+ },
311
+ red: {
312
+ 50: "#fef2f2",
313
+ 100: "#fee2e2",
314
+ 200: "#fecaca",
315
+ 300: "#fca5a5",
316
+ 400: "#f87171",
317
+ 500: "#ef4444",
318
+ 600: "#dc2626",
319
+ 700: "#b91c1c",
320
+ 800: "#991b1b",
321
+ 900: "#7f1d1d",
322
+ 950: "#450a0a",
323
+ },
324
+ orange: {
325
+ 50: "#fff7ed",
326
+ 100: "#ffedd5",
327
+ 200: "#fed7aa",
328
+ 300: "#fdba74",
329
+ 400: "#fb923c",
330
+ 500: "#f97316",
331
+ 600: "#ea580c",
332
+ 700: "#c2410c",
333
+ 800: "#9a3412",
334
+ 900: "#7c2d12",
335
+ 950: "#431407",
336
+ },
337
+ amber: {
338
+ 50: "#fffbeb",
339
+ 100: "#fef3c7",
340
+ 200: "#fde68a",
341
+ 300: "#fcd34d",
342
+ 400: "#fbbf24",
343
+ 500: "#f59e0b",
344
+ 600: "#d97706",
345
+ 700: "#b45309",
346
+ 800: "#92400e",
347
+ 900: "#78350f",
348
+ 950: "#451a03",
349
+ },
350
+ yellow: {
351
+ 50: "#fefce8",
352
+ 100: "#fef9c3",
353
+ 200: "#fef08a",
354
+ 300: "#fde047",
355
+ 400: "#facc15",
356
+ 500: "#eab308",
357
+ 600: "#ca8a04",
358
+ 700: "#a16207",
359
+ 800: "#854d0e",
360
+ 900: "#713f12",
361
+ 950: "#422006",
362
+ },
363
+ lime: {
364
+ 50: "#f7fee7",
365
+ 100: "#ecfccb",
366
+ 200: "#d9f99d",
367
+ 300: "#bef264",
368
+ 400: "#a3e635",
369
+ 500: "#84cc16",
370
+ 600: "#65a30d",
371
+ 700: "#4d7c0f",
372
+ 800: "#3f6212",
373
+ 900: "#365314",
374
+ 950: "#1a2e05",
375
+ },
376
+ green: {
377
+ 50: "#f0fdf4",
378
+ 100: "#dcfce7",
379
+ 200: "#bbf7d0",
380
+ 300: "#86efac",
381
+ 400: "#4ade80",
382
+ 500: "#22c55e",
383
+ 600: "#16a34a",
384
+ 700: "#15803d",
385
+ 800: "#166534",
386
+ 900: "#14532d",
387
+ 950: "#052e16",
388
+ },
389
+ emerald: {
390
+ 50: "#ecfdf5",
391
+ 100: "#d1fae5",
392
+ 200: "#a7f3d0",
393
+ 300: "#6ee7b7",
394
+ 400: "#34d399",
395
+ 500: "#10b981",
396
+ 600: "#059669",
397
+ 700: "#047857",
398
+ 800: "#065f46",
399
+ 900: "#064e3b",
400
+ 950: "#022c22",
401
+ },
402
+ teal: {
403
+ 50: "#f0fdfa",
404
+ 100: "#ccfbf1",
405
+ 200: "#99f6e4",
406
+ 300: "#5eead4",
407
+ 400: "#2dd4bf",
408
+ 500: "#14b8a6",
409
+ 600: "#0d9488",
410
+ 700: "#0f766e",
411
+ 800: "#115e59",
412
+ 900: "#134e4a",
413
+ 950: "#042f2e",
414
+ },
415
+ cyan: {
416
+ 50: "#ecfeff",
417
+ 100: "#cffafe",
418
+ 200: "#a5f3fc",
419
+ 300: "#67e8f9",
420
+ 400: "#22d3ee",
421
+ 500: "#06b6d4",
422
+ 600: "#0891b2",
423
+ 700: "#0e7490",
424
+ 800: "#155e75",
425
+ 900: "#164e63",
426
+ 950: "#083344",
427
+ },
428
+ sky: {
429
+ 50: "#f0f9ff",
430
+ 100: "#e0f2fe",
431
+ 200: "#bae6fd",
432
+ 300: "#7dd3fc",
433
+ 400: "#38bdf8",
434
+ 500: "#0ea5e9",
435
+ 600: "#0284c7",
436
+ 700: "#0369a1",
437
+ 800: "#075985",
438
+ 900: "#0c4a6e",
439
+ 950: "#082f49",
440
+ },
441
+ blue: {
442
+ 50: "#eff6ff",
443
+ 100: "#dbeafe",
444
+ 200: "#bfdbfe",
445
+ 300: "#93c5fd",
446
+ 400: "#60a5fa",
447
+ 500: "#3b82f6",
448
+ 600: "#2563eb",
449
+ 700: "#1d4ed8",
450
+ 800: "#1e40af",
451
+ 900: "#1e3a8a",
452
+ 950: "#172554",
453
+ },
454
+ indigo: {
455
+ 50: "#eef2ff",
456
+ 100: "#e0e7ff",
457
+ 200: "#c7d2fe",
458
+ 300: "#a5b4fc",
459
+ 400: "#818cf8",
460
+ 500: "#6366f1",
461
+ 600: "#4f46e5",
462
+ 700: "#4338ca",
463
+ 800: "#3730a3",
464
+ 900: "#312e81",
465
+ 950: "#1e1b4b",
466
+ },
467
+ violet: {
468
+ 50: "#f5f3ff",
469
+ 100: "#ede9fe",
470
+ 200: "#ddd6fe",
471
+ 300: "#c4b5fd",
472
+ 400: "#a78bfa",
473
+ 500: "#8b5cf6",
474
+ 600: "#7c3aed",
475
+ 700: "#6d28d9",
476
+ 800: "#5b21b6",
477
+ 900: "#4c1d95",
478
+ 950: "#2e1065",
479
+ },
480
+ purple: {
481
+ 50: "#faf5ff",
482
+ 100: "#f3e8ff",
483
+ 200: "#e9d5ff",
484
+ 300: "#d8b4fe",
485
+ 400: "#c084fc",
486
+ 500: "#a855f7",
487
+ 600: "#9333ea",
488
+ 700: "#7e22ce",
489
+ 800: "#6b21a8",
490
+ 900: "#581c87",
491
+ 950: "#3b0764",
492
+ },
493
+ fuchsia: {
494
+ 50: "#fdf4ff",
495
+ 100: "#fae8ff",
496
+ 200: "#f5d0fe",
497
+ 300: "#f0abfc",
498
+ 400: "#e879f9",
499
+ 500: "#d946ef",
500
+ 600: "#c026d3",
501
+ 700: "#a21caf",
502
+ 800: "#86198f",
503
+ 900: "#701a75",
504
+ 950: "#4a044e",
505
+ },
506
+ pink: {
507
+ 50: "#fdf2f8",
508
+ 100: "#fce7f3",
509
+ 200: "#fbcfe8",
510
+ 300: "#f9a8d4",
511
+ 400: "#f472b6",
512
+ 500: "#ec4899",
513
+ 600: "#db2777",
514
+ 700: "#be185d",
515
+ 800: "#9d174d",
516
+ 900: "#831843",
517
+ 950: "#500724",
518
+ },
519
+ rose: {
520
+ 50: "#fff1f2",
521
+ 100: "#ffe4e6",
522
+ 200: "#fecdd3",
523
+ 300: "#fda4af",
524
+ 400: "#fb7185",
525
+ 500: "#f43f5e",
526
+ 600: "#e11d48",
527
+ 700: "#be123c",
528
+ 800: "#9f1239",
529
+ 900: "#881337",
530
+ 950: "#4c0519",
531
+ },
532
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vueless",
3
- "version": "0.0.690",
3
+ "version": "0.0.692",
4
4
  "license": "MIT",
5
5
  "description": "Vue Styleless UI Component Library, powered by Tailwind CSS.",
6
6
  "keywords": [
package/plugin-vite.js CHANGED
@@ -62,7 +62,7 @@ export const Vueless = function (options = {}) {
62
62
  "process.env": {},
63
63
  },
64
64
  optimizeDeps: {
65
- include: ["tailwindcss/colors.js", ...(!isVuelessEnv ? ["vueless/preset-tailwind"] : [])],
65
+ include: [...(!isVuelessEnv ? ["vueless/preset-tailwind"] : [])],
66
66
  },
67
67
  }),
68
68
 
@@ -4,13 +4,13 @@
4
4
  */
5
5
  import { merge } from "lodash-es";
6
6
  import forms from "@tailwindcss/forms";
7
- import colors from "tailwindcss/colors.js";
8
7
  import {
9
8
  COLOR_SHADES,
10
9
  BRAND_COLOR,
11
10
  GRAY_COLOR,
12
11
  COOL_COLOR,
13
12
  DARK_MODE_SELECTOR,
13
+ TAILWIND_COLORS,
14
14
  DEFAULT_ROUNDING,
15
15
  DEFAULT_RING,
16
16
  DEFAULT_RING_OFFSET,
@@ -74,7 +74,6 @@ export const vuelessTailwindConfig = {
74
74
  colors: {
75
75
  [BRAND_COLOR]: brandColors || {},
76
76
  [GRAY_COLOR]: grayColors || {},
77
- [COOL_COLOR]: { ...(colors[GRAY_COLOR] || {}) },
78
77
  },
79
78
  spacing: {
80
79
  "safe-top": "env(safe-area-inset-top)",
@@ -176,16 +175,17 @@ function getPalette(color) {
176
175
  * @returns { Object } - `tailwind-config-viewer` color replacement object.
177
176
  */
178
177
  function getReplacementColors(color, tailwindColor) {
179
- if (tailwindColor === GRAYSCALE_COLOR || tailwindColor === COOL_COLOR) {
180
- tailwindColor = GRAY_COLOR;
178
+ if (tailwindColor === GRAYSCALE_COLOR) {
179
+ tailwindColor = COOL_COLOR;
181
180
  }
182
181
 
183
182
  const varsPalette = {
184
- [twColorWithOpacity(`--vl-color-${color}-default`)]: colors[tailwindColor][600],
183
+ [twColorWithOpacity(`--vl-color-${color}-default`)]: TAILWIND_COLORS[tailwindColor][600],
185
184
  };
186
185
 
187
186
  COLOR_SHADES.forEach((shade) => {
188
- varsPalette[twColorWithOpacity(`--vl-color-${color}-${shade}`)] = colors[tailwindColor][shade];
187
+ varsPalette[twColorWithOpacity(`--vl-color-${color}-${shade}`)] =
188
+ TAILWIND_COLORS[tailwindColor][shade];
189
189
  });
190
190
 
191
191
  return varsPalette;
@@ -199,7 +199,7 @@ export const Slots: StoryFn<UButtonArgs> = (args) => ({
199
199
  <UIcon
200
200
  name="heart_plus"
201
201
  size="sm"
202
- color="green"
202
+ color="inherit"
203
203
  :variant="isDarkMode ? 'dark' : 'default'"
204
204
  />
205
205
  </template>
@@ -210,7 +210,7 @@ export const Slots: StoryFn<UButtonArgs> = (args) => ({
210
210
  <UIcon
211
211
  name="settings"
212
212
  size="sm"
213
- color="green"
213
+ color="inherit"
214
214
  :variant="isDarkMode ? 'dark' : 'default'"
215
215
  />
216
216
  </template>
@@ -221,7 +221,7 @@ export const Slots: StoryFn<UButtonArgs> = (args) => ({
221
221
  <UIcon
222
222
  name="delete"
223
223
  size="sm"
224
- color="green"
224
+ color="inherit"
225
225
  :variant="isDarkMode ? 'dark' : 'default'"
226
226
  />
227
227
  </template>
@@ -2,14 +2,11 @@ export default /*tw*/ {
2
2
  inputLabel: "{ULabel}",
3
3
  wrapper: {
4
4
  base: `
5
- w-full bg-white relative flex border border-gray-300 rounded-dynamic-sm transition
5
+ w-full bg-white relative flex border border-gray-300 rounded-dynamic transition
6
6
  hover:border-gray-400 hover:focus-within:border-brand-500 focus-within:border-brand-500
7
7
  focus-within:ring-dynamic focus-within:ring-offset-dynamic focus-within:ring-brand-700/15
8
8
  `,
9
9
  variants: {
10
- labelAlign: {
11
- topInside: "rounded-dynamic",
12
- },
13
10
  error: {
14
11
  true: `
15
12
  border-red-300 bg-red-50
@@ -9,6 +9,8 @@ import UInput from "../../ui.form-input/UInput.vue";
9
9
  import UIcon from "../../ui.image-icon/UIcon.vue";
10
10
  import UButton from "../../ui.button/UButton.vue";
11
11
  import UCol from "../../ui.container-col/UCol.vue";
12
+ import URow from "../../ui.container-row/URow.vue";
13
+ import UAvatar from "../../ui.image-avatar/UAvatar.vue";
12
14
 
13
15
  import type { Meta, StoryFn } from "@storybook/vue3";
14
16
  import type { Props } from "../types.ts";
@@ -36,14 +38,18 @@ export default {
36
38
  } as Meta;
37
39
 
38
40
  const DefaultTemplate: StoryFn<UInputArgs> = (args: UInputArgs) => ({
39
- components: { UInput, UIcon, UButton },
41
+ components: { UInput, UIcon },
40
42
  setup() {
41
43
  const slots = getSlotNames(UInput.__name);
42
44
 
43
45
  return { args, slots };
44
46
  },
45
47
  template: `
46
- <UInput v-bind="args" v-model="args.modelValue">
48
+ <UInput
49
+ v-bind="args"
50
+ v-model="args.modelValue"
51
+ class="max-w-96"
52
+ >
47
53
  ${args.slotTemplate || getSlotsFragment("")}
48
54
  </UInput>
49
55
  `,
@@ -52,19 +58,58 @@ const DefaultTemplate: StoryFn<UInputArgs> = (args: UInputArgs) => ({
52
58
  const EnumVariantTemplate: StoryFn<UInputArgs> = (args: UInputArgs, { argTypes }) => ({
53
59
  components: { UInput, UCol },
54
60
  setup() {
61
+ function getDescription(option: string) {
62
+ switch (option) {
63
+ case "string":
64
+ return "Only letters are allowed";
65
+ case "number":
66
+ return "Numbers are allowed (including decimals)";
67
+ case "integer":
68
+ return "Only integers are allowed";
69
+ case "stringAndNumber":
70
+ return "Letters and numbers are allowed";
71
+ case "symbol":
72
+ return "Special characters are allowed";
73
+ default:
74
+ return "";
75
+ }
76
+ }
77
+
78
+ let filteredOptions = argTypes?.[args.enum]?.options;
79
+
80
+ if (args.enum === "labelAlign") {
81
+ filteredOptions = argTypes?.[args.enum]?.options?.filter(
82
+ (item) => item !== "right" && item !== "topWithDesc",
83
+ );
84
+ }
85
+
55
86
  return {
56
87
  args,
57
- options: argTypes?.[args.enum]?.options,
88
+ filteredOptions,
89
+ getDescription,
58
90
  };
59
91
  },
60
92
  template: `
61
93
  <UCol>
62
94
  <UInput
63
- v-for="(option, index) in options"
95
+ v-for="(option, index) in filteredOptions"
64
96
  :key="index"
65
97
  v-bind="args"
66
98
  :[args.enum]="option"
67
99
  :label="option"
100
+ :description="getDescription(option)"
101
+ class="max-w-96"
102
+ />
103
+
104
+ <UInput
105
+ v-if="args.enum === 'validationRule'"
106
+ v-bind="args"
107
+ validation-rule="^#([a-fA-F0-9]{3,4}|[a-fA-F0-9]{6}|[a-fA-F0-9]{8})$"
108
+ label="Custom RegExp"
109
+ description="Enter a valid hex color code (e.g., #FF5733)"
110
+ labelAlign="topWithDesc"
111
+ placeholder="#FF5733"
112
+ class="max-w-96"
68
113
  />
69
114
  </UCol>
70
115
  `,
@@ -73,23 +118,20 @@ const EnumVariantTemplate: StoryFn<UInputArgs> = (args: UInputArgs, { argTypes }
73
118
  export const Default = DefaultTemplate.bind({});
74
119
  Default.args = {};
75
120
 
76
- export const Disabled = DefaultTemplate.bind({});
77
- Disabled.args = { disabled: true };
121
+ export const Placeholder = DefaultTemplate.bind({});
122
+ Placeholder.args = { placeholder: "Type something here..." };
78
123
 
79
124
  export const Description = DefaultTemplate.bind({});
80
- Description.args = { description: "some description text" };
125
+ Description.args = { description: "Provide additional details if necessary." };
81
126
 
82
127
  export const Error = DefaultTemplate.bind({});
83
- Error.args = { error: "some error text" };
84
-
85
- export const Placeholder = DefaultTemplate.bind({});
86
- Placeholder.args = { placeholder: "some placeholder text" };
128
+ Error.args = { error: "This field is required. Please enter a value." };
87
129
 
88
130
  export const Readonly = DefaultTemplate.bind({});
89
- Readonly.args = { readonly: true, modelValue: "some value for read" };
131
+ Readonly.args = { readonly: true, modelValue: "Pre-filled content that cannot be changed" };
90
132
 
91
- export const NoAutocomplete = DefaultTemplate.bind({});
92
- NoAutocomplete.args = { noAutocomplete: true };
133
+ export const Disabled = DefaultTemplate.bind({});
134
+ Disabled.args = { disabled: true };
93
135
 
94
136
  export const TypePassword = DefaultTemplate.bind({});
95
137
  TypePassword.args = { type: "password" };
@@ -101,28 +143,57 @@ export const Sizes = EnumVariantTemplate.bind({});
101
143
  Sizes.args = { enum: "size" };
102
144
 
103
145
  export const ValidationRules = EnumVariantTemplate.bind({});
104
- ValidationRules.args = { enum: "validationRule" };
105
-
106
- export const LeftIcon = DefaultTemplate.bind({});
107
- LeftIcon.args = { leftIcon: "star" };
108
-
109
- export const RightIcon = DefaultTemplate.bind({});
110
- RightIcon.args = { rightIcon: "star" };
146
+ ValidationRules.args = { enum: "validationRule", labelAlign: "topWithDesc" };
147
+ ValidationRules.parameters = {
148
+ docs: {
149
+ description: {
150
+ story:
151
+ "`validationRule` prop prevents some characters from input. You can use predefined values or your own RegExp.",
152
+ },
153
+ },
154
+ };
111
155
 
112
- export const LeftSlot = DefaultTemplate.bind({});
113
- LeftSlot.args = {
114
- slotTemplate: `
115
- <template #left>
116
- <UIcon name="star" />
117
- </template>
156
+ export const IconProps: StoryFn<UInputArgs> = (args) => ({
157
+ components: { UInput, URow },
158
+ setup() {
159
+ return { args };
160
+ },
161
+ template: `
162
+ <URow>
163
+ <UInput
164
+ v-bind="args"
165
+ left-icon="feedback"
166
+ label="Your opinion"
167
+ placeholder="Share your feedback with us"
168
+ />
169
+ <UInput
170
+ v-bind="args"
171
+ right-icon="person"
172
+ label="Username"
173
+ placeholder="Enter your username"
174
+ />
175
+ </URow>
118
176
  `,
119
- };
177
+ });
120
178
 
121
- export const RightSlot = DefaultTemplate.bind({});
122
- RightSlot.args = {
123
- slotTemplate: `
124
- <template #right>
125
- <UIcon name="star" />
126
- </template>
179
+ export const Slots: StoryFn<UInputArgs> = (args) => ({
180
+ components: { UInput, URow, UButton, UAvatar },
181
+ setup() {
182
+ return { args };
183
+ },
184
+ template: `
185
+ <URow no-mobile>
186
+ <UInput v-bind="args">
187
+ <template #left>
188
+ <UAvatar />
189
+ </template>
190
+ </UInput>
191
+
192
+ <UInput v-bind="args" :config="{ rightSlot: 'pr-0' }">
193
+ <template #right>
194
+ <UButton label="Search" size="sm" class="rounded-l-none h-full" />
195
+ </template>
196
+ </UInput>
197
+ </URow>
127
198
  `,
128
- };
199
+ });
@@ -1,11 +1,10 @@
1
1
  <script setup lang="ts">
2
2
  import { computed } from "vue";
3
- import colors from "tailwindcss/colors.js";
4
3
 
5
4
  import useUI from "../composables/useUI.ts";
6
5
 
7
6
  import defaultConfig from "./config.ts";
8
- import { GRAY_COLORS } from "../constants.js";
7
+ import { GRAY_COLORS, TAILWIND_COLORS } from "../constants.js";
9
8
 
10
9
  import type { StepperProgressProps, Config } from "./types.ts";
11
10
 
@@ -16,18 +15,21 @@ const props = withDefaults(defineProps<StepperProgressProps>(), {
16
15
  });
17
16
 
18
17
  const stepperColor = computed(() => {
19
- const isValidColor = (color: string): color is keyof typeof colors => color in colors;
20
- const isGrayColor = (color: string): color is keyof typeof colors => GRAY_COLORS.includes(color);
18
+ const isValidColor = (color: string): color is keyof typeof TAILWIND_COLORS =>
19
+ color in TAILWIND_COLORS;
20
+
21
+ const isGrayColor = (color: string): color is keyof typeof TAILWIND_COLORS =>
22
+ GRAY_COLORS.includes(color);
21
23
 
22
24
  if (isValidColor(props.color)) {
23
- return colors[props.color][500];
25
+ return TAILWIND_COLORS[props.color][500];
24
26
  }
25
27
 
26
28
  if (isGrayColor(props.color)) {
27
- return colors[props.color][900];
29
+ return TAILWIND_COLORS[props.color][900];
28
30
  }
29
31
 
30
- return colors.zinc[900];
32
+ return TAILWIND_COLORS.cool[900];
31
33
  });
32
34
 
33
35
  /**
package/utils/theme.ts CHANGED
@@ -1,17 +1,15 @@
1
1
  import { merge } from "lodash-es";
2
- import tailwindColors from "tailwindcss/colors.js";
3
2
 
4
3
  import { tailwindConfig } from "./tailwindConfig.ts";
5
4
  import { vuelessConfig } from "./ui.ts";
6
5
  import { isSSR, isCSR } from "./helper.ts";
7
6
  import {
8
7
  PX_IN_REM,
9
- COOL_COLOR,
10
- GRAY_COLOR,
11
8
  COLOR_MODE_KEY,
12
9
  LIGHT_MODE_SELECTOR,
13
10
  DARK_MODE_SELECTOR,
14
11
  GRAYSCALE_COLOR,
12
+ TAILWIND_COLORS,
15
13
  DEFAULT_RING,
16
14
  DEFAULT_RING_OFFSET,
17
15
  DEFAULT_ROUNDING,
@@ -19,6 +17,8 @@ import {
19
17
  DEFAULT_GRAY_COLOR,
20
18
  DEFAULT_RING_OFFSET_COLOR_LIGHT,
21
19
  DEFAULT_RING_OFFSET_COLOR_DARK,
20
+ ROUNDING_DECREMENT,
21
+ ROUNDING_INCREMENT,
22
22
  } from "../constants.js";
23
23
 
24
24
  import type {
@@ -31,7 +31,7 @@ import type {
31
31
 
32
32
  import { ColorMode } from "../types.ts";
33
33
 
34
- type DefaultColors = typeof tailwindColors;
34
+ type DefaultColors = typeof TAILWIND_COLORS;
35
35
 
36
36
  interface Colors extends DefaultColors {
37
37
  [key: string]: Partial<TailwindColorShades> | string;
@@ -110,15 +110,16 @@ export function getSelectedGrayColor() {
110
110
  export function setTheme(config: Config = {}) {
111
111
  setColorMode(vuelessConfig.colorMode || config.colorMode || ColorMode.Light);
112
112
 
113
- const rounding = config.rounding ?? vuelessConfig.rounding ?? DEFAULT_ROUNDING;
114
- const roundingSm = config.roundingSm ?? vuelessConfig.roundingSm ?? rounding / 2;
115
- const roundingLg = config.roundingLg ?? vuelessConfig.roundingLg ?? rounding * 2;
116
- const isDarkMode = isCSR && document.documentElement.classList.contains(DARK_MODE_SELECTOR);
113
+ const { roundingSm, rounding, roundingLg } = getRoundings(
114
+ config.roundingSm ?? vuelessConfig.roundingSm,
115
+ config.rounding ?? vuelessConfig.rounding,
116
+ config.roundingLg ?? vuelessConfig.roundingLg,
117
+ );
117
118
 
118
119
  let brand: BrandColors =
119
120
  config.brand ?? getSelectedBrandColor() ?? vuelessConfig.brand ?? DEFAULT_BRAND_COLOR;
120
121
 
121
- let gray: GrayColors =
122
+ const gray: GrayColors =
122
123
  config.gray ?? getSelectedGrayColor() ?? vuelessConfig.gray ?? DEFAULT_GRAY_COLOR;
123
124
 
124
125
  const ring = config.ring ?? vuelessConfig.ring ?? DEFAULT_RING;
@@ -134,30 +135,20 @@ export function setTheme(config: Config = {}) {
134
135
  vuelessConfig.ringOffsetColorLight ??
135
136
  DEFAULT_RING_OFFSET_COLOR_LIGHT;
136
137
 
138
+ const isDarkMode = isCSR && document.documentElement.classList.contains(DARK_MODE_SELECTOR);
139
+ const defaultRingOffsetColor = isDarkMode ? ringOffsetColorDark : ringOffsetColorLight;
137
140
  const defaultBrandShade = isDarkMode ? 400 : 600;
138
141
  const defaultGrayShade = isDarkMode ? 400 : 600;
139
- const defaultRingOffsetColor = isDarkMode ? ringOffsetColorDark : ringOffsetColorLight;
140
142
 
141
143
  isCSR && localStorage.setItem("brand", brand);
142
144
  isCSR && localStorage.setItem("gray", gray);
143
145
 
144
- if (gray === COOL_COLOR) {
145
- gray = GRAY_COLOR;
146
- }
147
-
148
146
  if (brand === GRAYSCALE_COLOR) {
149
147
  brand = gray;
150
148
  }
151
149
 
152
- /* Remove deprecated color aliases. */
153
- delete (tailwindColors as Partial<DefaultColors>).lightBlue;
154
- delete (tailwindColors as Partial<DefaultColors>).warmGray;
155
- delete (tailwindColors as Partial<DefaultColors>).trueGray;
156
- delete (tailwindColors as Partial<DefaultColors>).coolGray;
157
- delete (tailwindColors as Partial<DefaultColors>).blueGray;
158
-
159
150
  const colors: Colors = merge(
160
- tailwindColors as Colors,
151
+ TAILWIND_COLORS as Colors,
161
152
  tailwindConfig?.theme?.extend?.colors || {},
162
153
  vuelessConfig.tailwindTheme?.extend?.colors || {},
163
154
  );
@@ -180,8 +171,8 @@ export function setTheme(config: Config = {}) {
180
171
  "--vl-rounding-sm": `${Number(roundingSm) / PX_IN_REM}rem`,
181
172
  "--vl-rounding": `${Number(rounding) / PX_IN_REM}rem`,
182
173
  "--vl-rounding-lg": `${Number(roundingLg) / PX_IN_REM}rem`,
183
- "--vl-ring": `${ring}px`,
184
- "--vl-ring-offset": `${ringOffset}px`,
174
+ "--vl-ring": `${Math.max(0, ring)}px`,
175
+ "--vl-ring-offset": `${Math.max(0, ringOffset)}px`,
185
176
  "--vl-ring-offset-color": convertHexInRgb(defaultRingOffsetColor),
186
177
  "--vl-color-gray-default": convertHexInRgb(colors[gray]?.[defaultBrandShade]),
187
178
  "--vl-color-brand-default": convertHexInRgb(colors[brand]?.[defaultGrayShade]),
@@ -240,3 +231,27 @@ export function convertHexInRgb(hex?: string) {
240
231
 
241
232
  return color.length === 6 || color.length === 3 ? `${r}, ${g}, ${b}` : "";
242
233
  }
234
+
235
+ function getRoundings(sm?: number, md?: number, lg?: number) {
236
+ const rounding = Math.max(0, md ?? DEFAULT_ROUNDING);
237
+ let roundingSm = Math.max(0, rounding - ROUNDING_DECREMENT);
238
+ let roundingLg = Math.max(0, rounding + ROUNDING_INCREMENT);
239
+
240
+ if (rounding === ROUNDING_INCREMENT) {
241
+ roundingSm = ROUNDING_DECREMENT;
242
+ }
243
+
244
+ if (rounding === ROUNDING_DECREMENT) {
245
+ roundingSm = ROUNDING_INCREMENT - ROUNDING_DECREMENT;
246
+ }
247
+
248
+ if (rounding === 0) {
249
+ roundingLg = ROUNDING_INCREMENT - ROUNDING_DECREMENT;
250
+ }
251
+
252
+ return {
253
+ rounding,
254
+ roundingSm: sm === undefined ? roundingSm : Math.max(0, sm),
255
+ roundingLg: lg === undefined ? roundingLg : Math.max(0, lg),
256
+ };
257
+ }