vueless 0.0.146 → 0.0.148

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vueless",
3
- "version": "0.0.146",
3
+ "version": "0.0.148",
4
4
  "license": "MIT",
5
5
  "description": "Vue Styleless Component Framework.",
6
6
  "homepage": "https://vueless.com",
@@ -1,16 +1,46 @@
1
+ import { computed } from "vue";
1
2
  import useUI from "../../composable.ui";
3
+ import { cva } from "../../service.ui";
2
4
 
3
5
  import defaultConfig from "../configs/default.config";
4
6
 
5
7
  export function useAttrs(props) {
6
8
  const { config, getAttrs } = useUI(defaultConfig, () => props.config);
9
+ const { label, items } = config.value;
7
10
 
8
- const wrapperAttrs = getAttrs("wrapper");
9
- const toggleItemAttrs = getAttrs("toggleItem", { isComponent: true });
11
+ const cvaItems = cva({
12
+ base: items.base,
13
+ variants: items.variants,
14
+ compoundVariants: items.compoundVariants,
15
+ });
16
+
17
+ const cvaLabel = cva({
18
+ base: label.base,
19
+ variants: label.variants,
20
+ compoundVariants: label.compoundVariants,
21
+ });
22
+
23
+ const itemsClasses = computed(() =>
24
+ cvaItems({
25
+ size: props.size,
26
+ separated: props.separated,
27
+ }),
28
+ );
29
+
30
+ const labelClasses = computed(() =>
31
+ cvaLabel({
32
+ block: props.block,
33
+ }),
34
+ );
35
+
36
+ const labelAttrs = getAttrs("label", { isComponent: true, classes: labelClasses });
37
+ const itemsAttrs = getAttrs("items", { classes: itemsClasses });
38
+ const itemAttrs = getAttrs("item", { isComponent: true });
10
39
 
11
40
  return {
12
41
  config,
13
- wrapperAttrs,
14
- toggleItemAttrs,
42
+ labelAttrs,
43
+ itemsAttrs,
44
+ itemAttrs,
15
45
  };
16
46
  }
@@ -1,18 +1,44 @@
1
1
  export default /*tw*/ {
2
- wrapper: `
3
- flex gap-px
4
- [&>*:first-child]:rounded-l-lg [&>*:first-child]:rounded-r-none
5
- [&>*:last-child]:rounded-r-lg [&>*:last-child]:rounded-l-none
6
- `,
7
- toggleItem: "",
2
+ label: {
3
+ base: "flex flex-wrap",
4
+ variants: {
5
+ block: {
6
+ true: "w-full",
7
+ },
8
+ },
9
+ },
10
+ items: {
11
+ base: "flex flex-wrap",
12
+ variants: {
13
+ size: {
14
+ "2xs": "gap-2",
15
+ xs: "gap-3",
16
+ sm: "gap-4",
17
+ md: "gap-5",
18
+ lg: "gap-6",
19
+ xl: "gap-7",
20
+ },
21
+ separated: {
22
+ false: `
23
+ gap-px flex-nowrap
24
+ [&>*:first-child]:rounded-l-lg [&>*:first-child]:rounded-r-none
25
+ [&>*:last-child]:rounded-r-lg [&>*:last-child]:rounded-l-none
26
+ `,
27
+ },
28
+ },
29
+ },
30
+ item: "",
8
31
  defaultVariants: {
9
32
  color: "brand",
10
33
  variant: "primary",
34
+ labelAlign: "top",
11
35
  size: "md",
12
36
  block: false,
13
37
  pill: false,
14
38
  square: false,
15
39
  filled: false,
40
+ disabled: false,
16
41
  multiple: false,
42
+ separated: false,
17
43
  },
18
44
  };
@@ -1,24 +1,35 @@
1
1
  <template>
2
- <div :data-cy="dataCy" v-bind="wrapperAttrs">
3
- <!-- @slot Use it to add UToggleItem directly. -->
4
- <slot>
5
- <UToggleItem
6
- v-for="(item, index) in options"
7
- :key="item.value"
8
- :name="name"
9
- :model-value="item.value"
10
- :value="item.value"
11
- :label="item.label"
12
- :data-cy="`${dataCy}-item-${index}`"
13
- v-bind="toggleItemAttrs"
14
- />
15
- </slot>
16
- </div>
2
+ <ULabel
3
+ :size="labelSize"
4
+ :label="label"
5
+ :description="description"
6
+ :align="labelAlign"
7
+ :disabled="disabled"
8
+ :data-cy="dataCy"
9
+ v-bind="labelAttrs"
10
+ >
11
+ <div v-bind="itemsAttrs">
12
+ <!-- @slot Use it to add UToggleItem directly. -->
13
+ <slot>
14
+ <UToggleItem
15
+ v-for="(item, index) in options"
16
+ :key="item.value"
17
+ :name="name"
18
+ :model-value="item.value"
19
+ :value="item.value"
20
+ :label="item.label"
21
+ :data-cy="`${dataCy}-item-${index}`"
22
+ v-bind="itemAttrs"
23
+ />
24
+ </slot>
25
+ </div>
26
+ </ULabel>
17
27
  </template>
18
28
 
19
29
  <script setup>
20
30
  import { computed, provide, readonly } from "vue";
21
31
 
32
+ import ULabel from "../ui.form-label";
22
33
  import UToggleItem from "../ui.button-toggle-item";
23
34
  import UIService from "../service.ui";
24
35
 
@@ -72,6 +83,31 @@ const props = defineProps({
72
83
  default: UIService.get(defaultConfig, UToggle).default.size,
73
84
  },
74
85
 
86
+ /**
87
+ * Toggle label.
88
+ */
89
+ label: {
90
+ type: String,
91
+ default: "",
92
+ },
93
+
94
+ /**
95
+ * Toggle description.
96
+ */
97
+ description: {
98
+ type: String,
99
+ default: "",
100
+ },
101
+
102
+ /**
103
+ * Label placement.
104
+ * @values top, topInside, topWithDesc, bottom, left, right
105
+ */
106
+ labelAlign: {
107
+ type: String,
108
+ default: UIService.get(defaultConfig, UToggle).default.labelAlign,
109
+ },
110
+
75
111
  /**
76
112
  * Make the toggle fill the width with its container.
77
113
  */
@@ -97,6 +133,22 @@ const props = defineProps({
97
133
  default: UIService.get(defaultConfig, UToggle).default.color,
98
134
  },
99
135
 
136
+ /**
137
+ * Separate toggle items.
138
+ */
139
+ separated: {
140
+ type: Boolean,
141
+ default: UIService.get(defaultConfig, UToggle).default.separated,
142
+ },
143
+
144
+ /**
145
+ * Make toggle disabled.
146
+ */
147
+ disabled: {
148
+ type: Boolean,
149
+ default: UIService.get(defaultConfig, UToggle).default.disabled,
150
+ },
151
+
100
152
  /**
101
153
  * Fill the background for thirdary variant.
102
154
  */
@@ -132,13 +184,26 @@ const props = defineProps({
132
184
 
133
185
  const emit = defineEmits(["update:modelValue"]);
134
186
 
135
- const { wrapperAttrs, toggleItemAttrs } = useAttrs(props);
187
+ const { labelAttrs, itemsAttrs, itemAttrs } = useAttrs(props);
136
188
 
137
189
  const selectedValue = computed({
138
190
  get: () => props.modelValue,
139
191
  set: (value) => emit("update:modelValue", value),
140
192
  });
141
193
 
194
+ const labelSize = computed(() => {
195
+ const sizes = {
196
+ "2xs": "sm",
197
+ xs: "sm",
198
+ sm: "md",
199
+ md: "md",
200
+ lg: "lg",
201
+ xl: "lg",
202
+ };
203
+
204
+ return sizes[props.size];
205
+ });
206
+
142
207
  const type = computed(() => {
143
208
  return props.multiple ? TYPE_CHECKBOX : TYPE_RADIO;
144
209
  });
@@ -150,10 +215,10 @@ function updateSelectedValue(value, checked) {
150
215
  return;
151
216
  }
152
217
 
153
- if (!checked) {
154
- selectedValue.value = selectedValue.value.filter((item) => item !== value);
155
- } else {
218
+ if (checked) {
156
219
  selectedValue.value.push(value);
220
+ } else {
221
+ selectedValue.value = selectedValue.value.filter((item) => String(item) !== String(value));
157
222
  }
158
223
  }
159
224
 
@@ -165,6 +230,7 @@ provide("toggleVariant", () => props.variant);
165
230
  provide("toggleColor", () => props.color);
166
231
  provide("toggleFilled", () => props.filled);
167
232
  provide("toggleDisabled", () => props.disabled);
233
+ provide("toggleSeparated", () => props.separated);
168
234
  provide("togglePill", () => props.pill);
169
235
  provide("toggleSquare", () => props.square);
170
236
 
@@ -1,13 +1,55 @@
1
+ import { computed, toValue } from "vue";
2
+ import { cx, cva } from "../../service.ui";
1
3
  import useUI from "../../composable.ui";
2
4
 
3
5
  import defaultConfig from "../configs/default.config";
4
6
 
5
- export function useAttrs(props) {
6
- const { getAttrs } = useUI(defaultConfig, () => props.config);
7
+ export function useAttrs(props, { selectedValue, separated, variant, color }) {
8
+ const { config, getAttrs, setColor } = useUI(defaultConfig, () => props.config);
9
+ const { button, selected } = config.value;
7
10
 
8
- const buttonAttrs = getAttrs("button");
11
+ const cvaButton = cva({
12
+ base: button.base,
13
+ variants: button.variants,
14
+ compoundVariants: button.compoundVariants,
15
+ });
16
+
17
+ const buttonClasses = computed(() =>
18
+ cvaButton({
19
+ separated: toValue(separated),
20
+ }),
21
+ );
22
+
23
+ const cvaSelected = cva({
24
+ base: selected.base,
25
+ variants: selected.variants,
26
+ compoundVariants: selected.compoundVariants,
27
+ });
28
+
29
+ const selectedClasses = computed(() =>
30
+ setColor(
31
+ cvaSelected({
32
+ color: toValue(color),
33
+ variant: toValue(variant),
34
+ }),
35
+ toValue(color),
36
+ ),
37
+ );
38
+
39
+ const buttonAttrsRaw = getAttrs("button", { isComponent: true, classes: buttonClasses });
9
40
  const inputAttrs = getAttrs("input");
10
41
 
42
+ const buttonAttrs = computed(() => {
43
+ const isSelected = Array.isArray(selectedValue.value)
44
+ ? selectedValue.value?.includes(props.value)
45
+ : selectedValue.value === props.value;
46
+
47
+ return {
48
+ ...buttonAttrsRaw.value,
49
+ class: cx([buttonAttrsRaw.value.class, isSelected && selectedClasses.value]),
50
+ };
51
+ });
52
+
11
53
  return {
12
54
  buttonAttrs,
13
55
  inputAttrs,
@@ -1,6 +1,31 @@
1
1
  export default /*tw*/ {
2
- button: "rounded-none",
3
- input: "p-0 m-0 size-0 invisible peer absolute",
2
+ button: {
3
+ base: "",
4
+ variants: {
5
+ separated: {
6
+ false: "!rounded-none",
7
+ },
8
+ },
9
+ },
10
+ input: "p-0 m-0 size-0 invisible absolute",
11
+ selected: {
12
+ base: "",
13
+ variants: {
14
+ variant: {
15
+ primary: "!bg-{color}-800 !border-{color}-800",
16
+ secondary: "!text-{color}-800 !border-{color}-800 bg-{color}-800 bg-opacity-10",
17
+ thirdary: "!text-{color}-800 !bg-{color}-800 !bg-opacity-10",
18
+ },
19
+ },
20
+ compoundVariants: [
21
+ { color: "grayscale", variant: "primary", class: "!bg-brand-700 !border-brand-700" },
22
+ { color: "grayscale", variant: "secondary", class: "!text-brand-700 !border-brand-700 !bg-brand-50 !bg-opacity-100" },
23
+ { color: "grayscale", variant: "thirdary", class: "!text-brand-700 !bg-brand-50" },
24
+ { color: "white", variant: "primary", class: "!text-brand-700 !border-brand-600 !bg-brand-50" },
25
+ { color: "white", variant: "secondary", class: "!text-brand-700 !border-brand-600 !bg-brand-50" },
26
+ { color: "white", variant: "thirdary", class: "!text-brand-700 !bg-brand-50" },
27
+ ],
28
+ },
4
29
  defaultVariants: {
5
30
  color: "brand",
6
31
  variant: "primary",
@@ -7,12 +7,12 @@
7
7
  :size="toValue(size)"
8
8
  :block="toValue(block)"
9
9
  :variant="toValue(variant)"
10
- :color="color"
11
- :pill="pill"
12
- :filled="filled"
13
- :square="square"
10
+ :color="toValue(color)"
11
+ :pill="toValue(pill)"
12
+ :filled="toValue(filled)"
13
+ :square="toValue(square)"
14
14
  v-bind="buttonAttrs"
15
- @click="onClickSetValue"
15
+ @click.stop="onClickSetValue"
16
16
  >
17
17
  <template #left>
18
18
  <slot name="left" />
@@ -25,8 +25,9 @@
25
25
  :name="name"
26
26
  :type="type"
27
27
  :value="value"
28
- :disabled="disabled"
28
+ :disabled="toValue(disabled)"
29
29
  v-bind="inputAttrs"
30
+ @click.stop
30
31
  />
31
32
 
32
33
  <slot name="default" />
@@ -123,13 +124,16 @@ const color = inject("toggleColor", UIService.get(defaultConfig, UToggleItem).de
123
124
  const filled = inject("toggleFilled", UIService.get(defaultConfig, UToggleItem).default.filled);
124
125
  const pill = inject("togglePill", UIService.get(defaultConfig, UToggleItem).default.pill);
125
126
  const square = inject("toggleSquare", UIService.get(defaultConfig, UToggleItem).default.square);
127
+ const separated = inject("toggleSeparated", false);
128
+ // eslint-disable-next-line vue/no-dupe-keys, prettier/prettier
129
+ const disabled = inject("toggleDisabled", UIService.get(defaultConfig, UToggleItem).default.disabled);
126
130
 
127
131
  const { selectedValue, updateSelectedValue } = inject("toggleSelectedValue", {});
128
132
 
129
- const { buttonAttrs, inputAttrs } = useAttrs(props);
130
-
131
133
  const selectedItem = ref("");
132
134
 
135
+ const { buttonAttrs, inputAttrs } = useAttrs(props, { selectedValue, separated, variant, color });
136
+
133
137
  onMounted(() => {
134
138
  if (type.value === TYPE_RADIO) {
135
139
  selectedItem.value = selectedValue ? selectedValue.value : selectedItem.value;
@@ -1,8 +1,8 @@
1
+ import { computed } from "vue";
1
2
  import useUI from "../../composable.ui";
2
3
  import { cva } from "../../service.ui";
3
4
 
4
5
  import defaultConfig from "../configs/default.config";
5
- import { computed } from "vue";
6
6
 
7
7
  export function useAttrs(props) {
8
8
  const { config, getAttrs, setColor } = useUI(defaultConfig, () => props.config);
package/web-types.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "framework": "vue",
3
3
  "name": "vueless",
4
- "version": "0.0.146",
4
+ "version": "0.0.148",
5
5
  "contributions": {
6
6
  "html": {
7
7
  "description-markup": "markdown",
@@ -7038,6 +7038,33 @@
7038
7038
  },
7039
7039
  "default": "md"
7040
7040
  },
7041
+ {
7042
+ "name": "label",
7043
+ "description": "Toggle label.",
7044
+ "value": {
7045
+ "kind": "expression",
7046
+ "type": "string"
7047
+ },
7048
+ "default": "\"\""
7049
+ },
7050
+ {
7051
+ "name": "description",
7052
+ "description": "Toggle description.",
7053
+ "value": {
7054
+ "kind": "expression",
7055
+ "type": "string"
7056
+ },
7057
+ "default": "\"\""
7058
+ },
7059
+ {
7060
+ "name": "labelAlign",
7061
+ "description": "Label placement.",
7062
+ "value": {
7063
+ "kind": "expression",
7064
+ "type": "'top' | 'topInside' | 'topWithDesc' | 'bottom' | 'left' | 'right'"
7065
+ },
7066
+ "default": "top"
7067
+ },
7041
7068
  {
7042
7069
  "name": "block",
7043
7070
  "description": "Make the toggle fill the width with its container.",
@@ -7065,6 +7092,24 @@
7065
7092
  },
7066
7093
  "default": "brand"
7067
7094
  },
7095
+ {
7096
+ "name": "separated",
7097
+ "description": "Separate toggle items.",
7098
+ "value": {
7099
+ "kind": "expression",
7100
+ "type": "boolean"
7101
+ },
7102
+ "default": "false"
7103
+ },
7104
+ {
7105
+ "name": "disabled",
7106
+ "description": "Make toggle disabled.",
7107
+ "value": {
7108
+ "kind": "expression",
7109
+ "type": "boolean"
7110
+ },
7111
+ "default": "false"
7112
+ },
7068
7113
  {
7069
7114
  "name": "filled",
7070
7115
  "description": "Fill the background for thirdary variant.",