vueless 0.0.676 → 0.0.678

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
@@ -107,6 +107,7 @@ export const COMPONENTS = {
107
107
  UCalendar: "ui.form-calendar",
108
108
  UDatePicker: "ui.form-date-picker",
109
109
  UDatePickerRange: "ui.form-date-picker-range",
110
+ UColorPicker: "ui.form-color-picker",
110
111
  ULabel: "ui.form-label",
111
112
 
112
113
  /* Text & Content */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vueless",
3
- "version": "0.0.676",
3
+ "version": "0.0.678",
4
4
  "license": "MIT",
5
5
  "description": "Vue Styleless UI Component Library, powered by Tailwind CSS.",
6
6
  "keywords": [
@@ -0,0 +1,68 @@
1
+ <script setup lang="ts">
2
+ import { computed, useId } from "vue";
3
+
4
+ import { vTooltip } from "../directives";
5
+ import useUI from "../composables/useUI.ts";
6
+ import { getDefaults } from "../utils/ui.ts";
7
+
8
+ import UButton from "../ui.button/UButton.vue";
9
+
10
+ import { COMPONENT_NAME } from "./constants.ts";
11
+ import defaultConfig from "./config.ts";
12
+
13
+ import type { Props, Config } from "./types.ts";
14
+
15
+ defineOptions({ inheritAttrs: false });
16
+
17
+ const props = withDefaults(defineProps<Props>(), {
18
+ ...getDefaults<Props, Config>(defaultConfig, COMPONENT_NAME),
19
+ modelValue: "",
20
+ colors: () => ({}),
21
+ labels: () => ({}),
22
+ });
23
+
24
+ const emit = defineEmits([
25
+ /**
26
+ * Triggers when color value changes.
27
+ * @property {string} value
28
+ */
29
+ "update:modelValue",
30
+ ]);
31
+
32
+ const elementId = props.id || useId();
33
+
34
+ const selectedItem = computed({
35
+ get: () => props.modelValue,
36
+ set: (value) => emit("update:modelValue", value),
37
+ });
38
+
39
+ function onClickColor(color: string) {
40
+ selectedItem.value = color;
41
+ }
42
+
43
+ /**
44
+ * Get element / nested component attributes for each config token ✨
45
+ * Applies: `class`, `config`, redefined default `props` and dev `vl-...` attributes.
46
+ */
47
+ const { listAttrs, colorButtonAttrs, circleAttrs } = useUI<Config>(defaultConfig);
48
+ </script>
49
+
50
+ <template>
51
+ <div :id="elementId" v-bind="listAttrs">
52
+ <UButton
53
+ v-for="(colorClass, color) in colors"
54
+ :key="color"
55
+ v-tooltip="labels?.[color] || color"
56
+ square
57
+ size="xs"
58
+ :ring="false"
59
+ color="grayscale"
60
+ variant="thirdary"
61
+ :filled="selectedItem === color"
62
+ v-bind="colorButtonAttrs"
63
+ @click="onClickColor(color)"
64
+ >
65
+ <div :class="colorClass" v-bind="circleAttrs" />
66
+ </UButton>
67
+ </div>
68
+ </template>
@@ -0,0 +1,29 @@
1
+ export default /*tw*/ {
2
+ list: "flex flex-wrap gap-0.5",
3
+ colorButton: {
4
+ base: "{UButton}",
5
+ button: {
6
+ compoundVariants: [
7
+ {
8
+ filled: true,
9
+ variant: "thirdary",
10
+ color: "grayscale",
11
+ class: "focus:bg-gray-800/10 bg-gray-800/10 dark:focus:bg-gray-200/10 dark:bg-gray-200/10",
12
+ },
13
+ ],
14
+ },
15
+ },
16
+ circle: {
17
+ base: "rounded-full",
18
+ variants: {
19
+ size: {
20
+ sm: "size-4",
21
+ md: "size-5",
22
+ lg: "size-6",
23
+ },
24
+ },
25
+ },
26
+ defaults: {
27
+ size: "md",
28
+ },
29
+ };
@@ -0,0 +1,5 @@
1
+ /*
2
+ This const is needed to prevent the issue in script setup:
3
+ `defineProps` is referencing locally declared variables. (vue/valid-define-props)
4
+ */
5
+ export const COMPONENT_NAME = "UColorPicker";
@@ -0,0 +1,16 @@
1
+ import { Meta, Title, Subtitle, Description, Primary, Controls, Stories, Source } from "@storybook/blocks";
2
+ import { getSource } from "../../utils/storybook.ts";
3
+
4
+ import * as stories from "./stories.ts";
5
+ import defaultConfig from "../config.ts?raw"
6
+
7
+ <Meta of={stories} />
8
+ <Title of={stories} />
9
+ <Subtitle of={stories} />
10
+ <Description of={stories} />
11
+ <Primary of={stories} />
12
+ <Controls of={stories.Default} />
13
+ <Stories of={stories} />
14
+
15
+ ## Default config
16
+ <Source code={getSource(defaultConfig)} language="jsx" dark />
@@ -0,0 +1,97 @@
1
+ import {
2
+ getArgTypes,
3
+ getSlotNames,
4
+ getSlotsFragment,
5
+ getDocsDescription,
6
+ } from "../../utils/storybook.ts";
7
+
8
+ import UColorPicker from "../UColorPicker.vue";
9
+ import UCol from "../../ui.container-col/UCol.vue";
10
+ import UButton from "../../ui.button/UButton.vue";
11
+
12
+ import type { Meta, StoryFn } from "@storybook/vue3";
13
+ import type { Props } from "../types.ts";
14
+
15
+ interface UColorPickerArgs extends Props {
16
+ slotTemplate?: string;
17
+ enum: "size";
18
+ }
19
+
20
+ export default {
21
+ id: "3190",
22
+ title: "Form Inputs & Controls / Color Picker",
23
+ component: UColorPicker,
24
+ args: {
25
+ modelValue: "",
26
+ colors: {
27
+ grayscale: "bg-gray-900",
28
+ gray: "bg-gray-600",
29
+ red: "bg-red-600",
30
+ orange: "bg-orange-600",
31
+ amber: "bg-amber-600",
32
+ yellow: "bg-yellow-600",
33
+ lime: "bg-lime-600",
34
+ green: "bg-green-600",
35
+ emerald: "bg-emerald-600",
36
+ teal: "bg-teal-600",
37
+ cyan: "bg-cyan-600",
38
+ sky: "bg-sky-600",
39
+ blue: "bg-blue-600",
40
+ indigo: "bg-indigo-600",
41
+ violet: "bg-violet-600",
42
+ purple: "bg-purple-600",
43
+ fuchsia: "bg-fuchsia-600",
44
+ pink: "bg-pink-600",
45
+ rose: "bg-rose-600",
46
+ },
47
+ },
48
+ argTypes: {
49
+ ...getArgTypes(UColorPicker.__name),
50
+ },
51
+ parameters: {
52
+ docs: {
53
+ ...getDocsDescription(UColorPicker.__name),
54
+ },
55
+ },
56
+ } as Meta;
57
+
58
+ const DefaultTemplate: StoryFn<UColorPickerArgs> = (args: UColorPickerArgs) => ({
59
+ components: { UColorPicker, UButton, UCol },
60
+ setup() {
61
+ const slots = getSlotNames(UColorPicker.__name);
62
+
63
+ return { args, slots };
64
+ },
65
+ template: `
66
+ <UColorPicker v-bind="args" v-model="args.modelValue">
67
+ ${args.slotTemplate || getSlotsFragment("")}
68
+ </UColorPicker>
69
+ `,
70
+ });
71
+
72
+ const EnumVariantTemplate: StoryFn<UColorPickerArgs> = (args: UColorPickerArgs, { argTypes }) => ({
73
+ components: { UCol, UColorPicker },
74
+ setup() {
75
+ return {
76
+ args,
77
+ options: argTypes?.[args.enum]?.options,
78
+ };
79
+ },
80
+ template: `
81
+ <UCol>
82
+ <UColorPicker
83
+ v-for="(option, index) in options"
84
+ :key="index"
85
+ v-bind="args"
86
+ v-model="args.modelValue"
87
+ :[args.enum]="option"
88
+ />
89
+ </UCol>
90
+ `,
91
+ });
92
+
93
+ export const Default = DefaultTemplate.bind({});
94
+ Default.args = {};
95
+
96
+ export const Sizes = EnumVariantTemplate.bind({});
97
+ Sizes.args = { enum: "size" };
@@ -0,0 +1,42 @@
1
+ import defaultConfig from "./config.ts";
2
+
3
+ import type { BrandColors, GrayColors, ComponentConfig } from "../types.ts";
4
+
5
+ export type Config = typeof defaultConfig;
6
+
7
+ export interface Props {
8
+ /**
9
+ * Selected values.
10
+ */
11
+ modelValue: string;
12
+
13
+ /**
14
+ * Component size.
15
+ */
16
+ size?: "sm" | "md" | "lg";
17
+
18
+ /**
19
+ * Color list.
20
+ */
21
+ colors?: Record<BrandColors, string>;
22
+
23
+ /**
24
+ * Color labels.
25
+ */
26
+ labels?: Record<GrayColors, string>;
27
+
28
+ /**
29
+ * Unique element id.
30
+ */
31
+ id?: string;
32
+
33
+ /**
34
+ * Component config object.
35
+ */
36
+ config?: ComponentConfig<Config>;
37
+
38
+ /**
39
+ * Data-test attribute for automated testing.
40
+ */
41
+ dataTest?: string | null;
42
+ }
@@ -17,7 +17,7 @@ interface UInputFileArgs extends Props {
17
17
  }
18
18
 
19
19
  export default {
20
- id: "30232",
20
+ id: "3200",
21
21
  title: "Form Inputs & Controls / Input File",
22
22
  component: UInputFile,
23
23
  args: {
@@ -20,7 +20,7 @@ interface ULabelArgs extends Props {
20
20
  }
21
21
 
22
22
  export default {
23
- id: "3240",
23
+ id: "3210",
24
24
  title: "Form Inputs & Controls / Label",
25
25
  component: ULabel,
26
26
  args: {
@@ -1,26 +1,25 @@
1
1
  <script setup lang="ts">
2
- import { computed, useId, watch } from "vue";
2
+ import { computed, useId } from "vue";
3
3
 
4
- import { vTooltip } from "../directives";
5
4
  import useUI from "../composables/useUI.ts";
6
5
  import { getDefaults } from "../utils/ui.ts";
7
6
  import { setTheme, getSelectedBrandColor, getSelectedGrayColor } from "../utils/theme.ts";
8
7
  import { GRAYSCALE_COLOR } from "../constants.js";
9
8
 
10
9
  import UDivider from "../ui.container-divider/UDivider.vue";
11
- import UButton from "../ui.button/UButton.vue";
10
+ import UColorPicker from "../ui.form-color-picker/UColorPicker.vue";
12
11
 
13
12
  import { COMPONENT_NAME } from "./constants.ts";
14
13
  import defaultConfig from "./config.ts";
15
14
 
16
- import type { BrandColors, GrayColors } from "../types.ts";
17
15
  import type { Props, Config } from "./types.ts";
18
16
 
19
17
  defineOptions({ inheritAttrs: false });
20
18
 
21
19
  const props = withDefaults(defineProps<Props>(), {
22
20
  ...getDefaults<Props, Config>(defaultConfig, COMPONENT_NAME),
23
- modelValue: () => ["", ""],
21
+ brand: "",
22
+ gray: "",
24
23
  brandColors: () => ({}),
25
24
  grayColors: () => ({}),
26
25
  brandLabels: () => ({}),
@@ -29,78 +28,61 @@ const props = withDefaults(defineProps<Props>(), {
29
28
 
30
29
  const emit = defineEmits([
31
30
  /**
32
- * Triggers when color value changes.
31
+ * Triggers when the brand color changes.
33
32
  * @property {string} value
34
33
  */
35
- "update:modelValue",
34
+ "update:brand",
35
+
36
+ /**
37
+ * Triggers when the gray color changes.
38
+ * @property {string} value
39
+ */
40
+ "update:gray",
36
41
  ]);
37
42
 
38
43
  const elementId = props.id || useId();
39
44
 
40
- const selectedBrand = getSelectedBrandColor();
41
- const selectedGray = getSelectedGrayColor();
45
+ const selectedBrandColor = computed({
46
+ get: () => props.brand || getSelectedBrandColor(),
47
+ set: (brand: string) => {
48
+ const prevBrand = getSelectedBrandColor();
49
+ const isBrandGrayscale = brand === GRAYSCALE_COLOR;
50
+ const isPrevBrandGrayscale = prevBrand === GRAYSCALE_COLOR;
42
51
 
43
- const selectedItem = computed({
44
- get: () => {
45
- const [brand, gray] = props.modelValue;
52
+ if (brand !== prevBrand && (isBrandGrayscale || isPrevBrandGrayscale)) {
53
+ window.location.reload();
54
+ }
46
55
 
47
- return [brand || selectedBrand, gray || selectedGray];
56
+ setTheme({ brand });
57
+ emit("update:brand", brand);
48
58
  },
49
- set: (value) => emit("update:modelValue", value),
50
59
  });
51
60
 
52
- watch(selectedItem, (newValue, oldValue) => {
53
- const [oldBrand, oldGray] = oldValue;
54
- const [brand, gray] = newValue;
55
-
56
- if (oldBrand === brand && oldGray === gray) {
57
- return;
58
- }
59
-
60
- setTheme({ brand, gray });
61
-
62
- if (oldBrand !== brand && (brand === GRAYSCALE_COLOR || oldBrand === GRAYSCALE_COLOR)) {
63
- window.location.reload();
64
- }
61
+ const selectedGrayColor = computed({
62
+ get: () => props.gray || getSelectedGrayColor(),
63
+ set: (value: string) => {
64
+ setTheme({ gray: value });
65
+ emit("update:gray", value);
66
+ },
65
67
  });
66
68
 
67
- function onClickBrandColor(brand: BrandColors) {
68
- const [, gray] = selectedItem.value;
69
-
70
- selectedItem.value = [brand, gray];
71
- }
72
-
73
- function onClickGrayColor(gray: GrayColors) {
74
- const [brand] = selectedItem.value;
75
-
76
- selectedItem.value = [brand, gray];
77
- }
78
-
79
69
  /**
80
70
  * Get element / nested component attributes for each config token ✨
81
71
  * Applies: `class`, `config`, redefined default `props` and dev `vl-...` attributes.
82
72
  */
83
- const { listAttrs, colorButtonAttrs, circleAttrs, colorDividerAttrs } =
73
+ const { listAttrs, colorDividerAttrs, brandColorPickerAttrs, grayColorPickerAttrs } =
84
74
  useUI<Config>(defaultConfig);
85
75
  </script>
86
76
 
87
77
  <template>
88
78
  <div :id="elementId" v-bind="listAttrs">
89
- <UButton
90
- v-for="(brandColorClass, color) in brandColors"
91
- :key="color"
92
- v-tooltip="brandLabels?.[color] || color"
93
- square
94
- size="xs"
95
- :ring="false"
96
- color="grayscale"
97
- variant="thirdary"
98
- :filled="selectedItem[0] === color"
99
- v-bind="colorButtonAttrs"
100
- @click="onClickBrandColor(color)"
101
- >
102
- <div :class="brandColorClass" v-bind="circleAttrs" />
103
- </UButton>
79
+ <UColorPicker
80
+ v-model="selectedBrandColor"
81
+ :size="size"
82
+ :colors="brandColors"
83
+ :labels="brandLabels"
84
+ v-bind="brandColorPickerAttrs"
85
+ />
104
86
 
105
87
  <UDivider
106
88
  v-if="Object.keys(brandColors).length && Object.keys(grayColors).length"
@@ -108,20 +90,12 @@ const { listAttrs, colorButtonAttrs, circleAttrs, colorDividerAttrs } =
108
90
  v-bind="colorDividerAttrs"
109
91
  />
110
92
 
111
- <UButton
112
- v-for="(grayColorClass, color) in grayColors"
113
- :key="color"
114
- v-tooltip="brandLabels?.[color] || color"
115
- square
116
- size="xs"
117
- :ring="false"
118
- color="grayscale"
119
- variant="thirdary"
120
- :filled="selectedItem[1] === color"
121
- v-bind="colorButtonAttrs"
122
- @click="onClickGrayColor(color)"
123
- >
124
- <div :class="grayColorClass" v-bind="circleAttrs" />
125
- </UButton>
93
+ <UColorPicker
94
+ v-model="selectedGrayColor"
95
+ :size="size"
96
+ :colors="grayColors"
97
+ :labels="grayLabels"
98
+ v-bind="grayColorPickerAttrs"
99
+ />
126
100
  </div>
127
101
  </template>
@@ -1,28 +1,7 @@
1
1
  export default /*tw*/ {
2
2
  list: "flex flex-wrap gap-0.5",
3
- colorButton: {
4
- base: "{UButton}",
5
- button: {
6
- compoundVariants: [
7
- {
8
- filled: true,
9
- variant: "thirdary",
10
- color: "grayscale",
11
- class: "bg-gray-800/10 dark:bg-gray-200/10",
12
- },
13
- ],
14
- },
15
- },
16
- circle: {
17
- base: "rounded-full",
18
- variants: {
19
- size: {
20
- sm: "size-4",
21
- md: "size-5",
22
- lg: "size-6",
23
- },
24
- },
25
- },
3
+ brandColorPicker: "{UColorPicker}",
4
+ grayColorPicker: "{UColorPicker}",
26
5
  colorDivider: "{UDivider}",
27
6
  defaults: {
28
7
  size: "md",
@@ -22,10 +22,10 @@ export default {
22
22
  title: "Other / Theme Color Toggle",
23
23
  component: UThemeColorToggle,
24
24
  args: {
25
- modelValue: ["", ""],
25
+ brand: "",
26
+ gray: "",
26
27
  brandColors: {
27
28
  grayscale: "bg-gray-900",
28
- gray: "bg-gray-600",
29
29
  red: "bg-red-600",
30
30
  orange: "bg-orange-600",
31
31
  amber: "bg-amber-600",
@@ -71,7 +71,7 @@ const DefaultTemplate: StoryFn<UThemeColorToggleArgs> = (args: UThemeColorToggle
71
71
  },
72
72
  template: `
73
73
  <UCol>
74
- <UThemeColorToggle v-bind="args" v-model="args.modelValue">
74
+ <UThemeColorToggle v-bind="args" v-model:brand="args.brand" v-model:gray="args.gray">
75
75
  ${args.slotTemplate || getSlotsFragment("")}
76
76
  </UThemeColorToggle>
77
77
 
@@ -97,7 +97,8 @@ const EnumVariantTemplate: StoryFn<UThemeColorToggleArgs> = (
97
97
  v-for="(option, index) in options"
98
98
  :key="index"
99
99
  v-bind="args"
100
- v-model="args.modelValue"
100
+ v-model:brand="args.brand"
101
+ v-model:gray="args.gray"
101
102
  :[args.enum]="option"
102
103
  />
103
104
  </UCol>
@@ -6,9 +6,14 @@ export type Config = typeof defaultConfig;
6
6
 
7
7
  export interface Props {
8
8
  /**
9
- * Selected values.
9
+ * Selected brand color (v-model).
10
10
  */
11
- modelValue: [BrandColors, GrayColors];
11
+ brand: BrandColors;
12
+
13
+ /**
14
+ * Selected gray color (v-model).
15
+ */
16
+ gray: GrayColors;
12
17
 
13
18
  /**
14
19
  * Component size.
package/utils/theme.ts CHANGED
@@ -100,11 +100,11 @@ export function setColorMode(colorMode: `${ColorMode}`) {
100
100
  }
101
101
 
102
102
  export function getSelectedBrandColor() {
103
- return localStorage.getItem("brand") || undefined;
103
+ return (isCSR && localStorage.getItem("brand")) || undefined;
104
104
  }
105
105
 
106
106
  export function getSelectedGrayColor() {
107
- return localStorage.getItem("gray") || undefined;
107
+ return (isCSR && localStorage.getItem("gray")) || undefined;
108
108
  }
109
109
 
110
110
  export function setTheme(config: Config = {}) {
@@ -138,6 +138,9 @@ export function setTheme(config: Config = {}) {
138
138
  const defaultGrayShade = isDarkMode ? 400 : 600;
139
139
  const defaultRingOffsetColor = isDarkMode ? ringOffsetColorDark : ringOffsetColorLight;
140
140
 
141
+ isCSR && localStorage.setItem("brand", brand);
142
+ isCSR && localStorage.setItem("gray", gray);
143
+
141
144
  if (gray === COOL_COLOR) {
142
145
  gray = GRAY_COLOR;
143
146
  }
@@ -173,9 +176,6 @@ export function setTheme(config: Config = {}) {
173
176
  console.warn(`The gray color '${gray}' is missing in your palette.`);
174
177
  }
175
178
 
176
- localStorage.setItem("brand", brand);
177
- localStorage.setItem("gray", gray);
178
-
179
179
  const variables: Partial<VuelessCssVariables> = {
180
180
  "--vl-rounding-sm": `${Number(roundingSm) / PX_IN_REM}rem`,
181
181
  "--vl-rounding": `${Number(rounding) / PX_IN_REM}rem`,