vueless 1.0.2-beta.40 → 1.0.2-beta.42

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": "1.0.2-beta.40",
3
+ "version": "1.0.2-beta.42",
4
4
  "license": "MIT",
5
5
  "description": "Vue Styleless UI Component Library, powered by Tailwind CSS.",
6
6
  "keywords": [
@@ -19,7 +19,7 @@ export default /*tw*/ {
19
19
  lg: "size-6",
20
20
  },
21
21
  error: {
22
- true: "!border-error focus:outline-error",
22
+ true: "!border-error focus-visible:outline-error",
23
23
  },
24
24
  },
25
25
  },
@@ -8,7 +8,6 @@ import {
8
8
 
9
9
  import UCheckbox from "../../ui.form-checkbox/UCheckbox.vue";
10
10
  import UCheckboxGroup from "../../ui.form-checkbox-group/UCheckboxGroup.vue";
11
- import UBadge from "../../ui.text-badge/UBadge.vue";
12
11
  import UCol from "../../ui.container-col/UCol.vue";
13
12
  import UIcon from "../../ui.image-icon/UIcon.vue";
14
13
  import ULink from "../../ui.button-link/ULink.vue";
@@ -42,7 +41,7 @@ export default {
42
41
  } as Meta;
43
42
 
44
43
  const DefaultTemplate: StoryFn<UCheckboxArgs> = (args: UCheckboxArgs) => ({
45
- components: { UCheckbox, UBadge, UIcon, ULink, UText, URow, UChip },
44
+ components: { UCheckbox, UIcon, ULink, UText, URow, UChip },
46
45
  setup: () => ({ args, slots: getSlotNames(UCheckbox.__name) }),
47
46
  template: `
48
47
  <UCheckbox v-bind="args" v-model="args.modelValue">
@@ -52,19 +51,11 @@ const DefaultTemplate: StoryFn<UCheckboxArgs> = (args: UCheckboxArgs) => ({
52
51
  });
53
52
 
54
53
  const ValueTypesTemplate: StoryFn<UCheckboxArgs> = (args: UCheckboxArgs) => ({
55
- components: { UCheckbox, UCheckboxGroup, UCol },
56
- setup() {
57
- return { args };
58
- },
59
- data() {
60
- return {
61
- defaultValue: false,
62
- arrayValue: [],
63
- customValue: { vue: "less" },
64
- };
65
- },
54
+ components: { UCheckbox, UCheckboxGroup, URow },
55
+ setup: () => ({ args }),
56
+ data: () => ({ defaultValue: false, customValue: { vue: "less" } }),
66
57
  template: `
67
- <UCol gap="xl">
58
+ <URow gap="xl">
68
59
  <UCheckbox
69
60
  v-bind="args"
70
61
  v-model="defaultValue"
@@ -80,28 +71,7 @@ const ValueTypesTemplate: StoryFn<UCheckboxArgs> = (args: UCheckboxArgs) => ({
80
71
  :description="JSON.stringify(customValue)"
81
72
  label="Custom"
82
73
  />
83
-
84
- <div>
85
- <UCheckboxGroup name="checkboxGroup" label="Checkbox group">
86
- <UCheckbox
87
- v-bind="args"
88
- v-model="arrayValue"
89
- :value="{ key: 'value' }"
90
- label="Array with object value"
91
- />
92
- <UCheckbox
93
- v-bind="args"
94
- v-model="arrayValue"
95
- value="someString"
96
- label="Array with custom string value"
97
- />
98
- </UCheckboxGroup>
99
-
100
- <span class="font-normal text-muted text-small pl-0 mt-1">
101
- {{ arrayValue }}
102
- </span>
103
- </div>
104
- </UCol>
74
+ </URow>
105
75
  `,
106
76
  });
107
77
 
@@ -126,8 +96,17 @@ Default.args = {};
126
96
  export const Description = DefaultTemplate.bind({});
127
97
  Description.args = { description: "Receive updates and exclusive offers directly to your inbox." };
128
98
 
129
- export const Error = DefaultTemplate.bind({});
130
- Error.args = { error: "Please agree to the Terms and Conditions before proceeding." };
99
+ export const Error: StoryFn<UCheckboxArgs> = (args: UCheckboxArgs) => ({
100
+ components: { UCheckbox },
101
+ setup: () => ({ args }),
102
+ template: `
103
+ <UCheckbox
104
+ v-bind="args"
105
+ v-model="args.modelValue"
106
+ :error="args.modelValue ? '' : 'Please agree to the Terms and Conditions before proceeding.'"
107
+ />
108
+ `,
109
+ });
131
110
 
132
111
  export const Disabled = DefaultTemplate.bind({});
133
112
  Disabled.args = { disabled: true };
@@ -179,7 +158,7 @@ export const BottomSlot = DefaultTemplate.bind({});
179
158
  BottomSlot.args = {
180
159
  slotTemplate: `
181
160
  <template #bottom>
182
- <UChip icon="arrow_outward" size="3xs" class="mt-2">
161
+ <UChip icon="arrow_outward" size="sm" class="mt-2">
183
162
  <ULink label="Learn more" size="sm" class="mr-1.5" />
184
163
  </UChip>
185
164
  </template>
@@ -1,3 +1,5 @@
1
+ import { ref } from "vue";
2
+
1
3
  import {
2
4
  getArgs,
3
5
  getArgTypes,
@@ -18,12 +20,10 @@ import UIcon from "../../ui.image-icon/UIcon.vue";
18
20
 
19
21
  import type { Meta, StoryFn } from "@storybook/vue3";
20
22
  import type { Props } from "../types.ts";
21
- import type { UnknownObject, UnknownArray } from "../../types.ts";
22
23
 
23
24
  interface UCheckboxGroupArgs extends Props {
24
25
  slotTemplate?: string;
25
26
  enum: "size" | "color";
26
- value?: boolean | string | number | UnknownArray | UnknownObject;
27
27
  }
28
28
 
29
29
  export default {
@@ -37,7 +37,6 @@ export default {
37
37
  { label: "SMS Alerts", value: "sms" },
38
38
  { label: "Push Notifications", value: "push" },
39
39
  ],
40
- value: [],
41
40
  },
42
41
  argTypes: {
43
42
  ...getArgTypes(UCheckboxGroup.__name),
@@ -50,35 +49,27 @@ export default {
50
49
  } as Meta;
51
50
 
52
51
  const DefaultTemplate: StoryFn<UCheckboxGroupArgs> = (args: UCheckboxGroupArgs) => ({
53
- components: { UCheckboxGroup, UCheckbox, UAlert, URow, UCol, UBadge, UText, ULink, UIcon },
54
- setup: () => ({ args, slots: getSlotNames(UCheckboxGroup.__name) }),
52
+ components: { UCheckboxGroup, UCheckbox, URow, UCol, UBadge, UText, ULink, UIcon },
53
+ setup: () => ({ args, slots: getSlotNames(UCheckboxGroup.__name), modelValue: ref([]) }),
55
54
  template: `
56
- <UCol>
57
- <UCheckboxGroup v-bind="args" v-model="args.value">
58
- ${args.slotTemplate || getSlotsFragment("")}
59
- </UCheckboxGroup>
60
-
61
- <URow>
62
- <UAlert size="sm" variant="ghost" color="success" bordered>
63
- <p>Selected value: {{ args.value }}</p>
64
- </UAlert>
65
- </URow>
66
- </UCol>
55
+ <UCheckboxGroup v-bind="args" v-model="modelValue">
56
+ ${args.slotTemplate || getSlotsFragment("")}
57
+ </UCheckboxGroup>
67
58
  `,
68
59
  });
69
60
 
70
61
  const EnumTemplate: StoryFn<UCheckboxGroupArgs> = (args: UCheckboxGroupArgs, { argTypes }) => ({
71
- components: { UCheckboxGroup, UCol },
72
- setup: () => ({ args, argTypes, getArgs }),
62
+ components: { UCheckboxGroup, URow },
63
+ setup: () => ({ args, argTypes, getArgs, modelValue: ref([]) }),
73
64
  template: `
74
- <UCol>
65
+ <URow>
75
66
  <UCheckboxGroup
76
67
  v-for="option in argTypes?.[args.enum]?.options"
77
68
  v-bind="getArgs(args, option)"
78
69
  :key="option"
79
- v-model="args.value"
70
+ v-model="modelValue"
80
71
  />
81
- </UCol>
72
+ </URow>
82
73
  `,
83
74
  });
84
75
 
@@ -91,13 +82,39 @@ Description.args = {
91
82
  description: "You may select multiple options that best fit your preferences.",
92
83
  };
93
84
 
94
- export const Error = DefaultTemplate.bind({});
95
- Error.args = { name: "Error", error: "some error" };
85
+ export const Error: StoryFn<UCheckboxGroupArgs> = (args: UCheckboxGroupArgs) => ({
86
+ components: { UCheckboxGroup },
87
+ setup: () => ({ args, modelValue: ref([]) }),
88
+ template: `
89
+ <UCheckboxGroup
90
+ name="Error"
91
+ v-bind="args"
92
+ v-model="modelValue"
93
+ :error="modelValue.length ? '' : 'At least one option must be selected.'"
94
+ />
95
+ `,
96
+ });
96
97
 
97
98
  export const Disabled = DefaultTemplate.bind({});
98
99
  Disabled.args = { name: "Disabled", disabled: true };
99
100
 
100
- export const Options = DefaultTemplate.bind({});
101
+ export const Options: StoryFn<UCheckboxGroupArgs> = (args: UCheckboxGroupArgs) => ({
102
+ components: { UCheckboxGroup, UCol, UAlert },
103
+ setup: () => ({ args, modelValue: ref([]) }),
104
+ template: `
105
+ <UCol>
106
+ <UCheckboxGroup v-bind="args" v-model="modelValue" />
107
+
108
+ <UAlert
109
+ :description="modelValue"
110
+ size="sm"
111
+ variant="ghost"
112
+ color="success"
113
+ bordered
114
+ />
115
+ </UCol>
116
+ `,
117
+ });
101
118
  Options.args = {
102
119
  name: "Options",
103
120
  options: [
@@ -125,6 +142,7 @@ Sizes.args = { enum: "size", name: "Sizes", label: "{enumValue}" };
125
142
 
126
143
  export const LabelSlot = DefaultTemplate.bind({});
127
144
  LabelSlot.args = {
145
+ name: "LabelSlot",
128
146
  slotTemplate: `
129
147
  <template #label>
130
148
  <URow gap="2xs" align="center">
@@ -94,4 +94,4 @@ export const Sizes = EnumTemplate.bind({});
94
94
  Sizes.args = { enum: "size" };
95
95
 
96
96
  export const Colors = EnumTemplate.bind({});
97
- Colors.args = { enum: "color" };
97
+ Colors.args = { enum: "color", modelValue: true };
@@ -26,24 +26,24 @@ export default {
26
26
  modelValue: "",
27
27
  colors: /*tw*/ {
28
28
  grayscale: "bg-grayscale",
29
- neutral: "bg-neutral-600",
30
- red: "bg-red-600",
31
- orange: "bg-orange-600",
32
- amber: "bg-amber-600",
33
- yellow: "bg-yellow-600",
34
- lime: "bg-lime-600",
35
- green: "bg-green-600",
36
- emerald: "bg-emerald-600",
37
- teal: "bg-teal-600",
38
- cyan: "bg-cyan-600",
39
- sky: "bg-sky-600",
40
- blue: "bg-blue-600",
41
- indigo: "bg-indigo-600",
42
- violet: "bg-violet-600",
43
- purple: "bg-purple-600",
44
- fuchsia: "bg-fuchsia-600",
45
- pink: "bg-pink-600",
46
- rose: "bg-rose-600",
29
+ neutral: "bg-neutral-600 dark:bg-neutral-400",
30
+ red: "bg-red-600 dark:bg-red-400",
31
+ orange: "bg-orange-600 dark:bg-orange-400",
32
+ amber: "bg-amber-600 dark:bg-amber-400",
33
+ yellow: "bg-yellow-600 dark:bg-yellow-400",
34
+ lime: "bg-lime-600 dark:bg-lime-400",
35
+ green: "bg-green-600 dark:bg-green-400",
36
+ emerald: "bg-emerald-600 dark:bg-emerald-400",
37
+ teal: "bg-teal-600 dark:bg-teal-400",
38
+ cyan: "bg-cyan-600 dark:bg-cyan-400",
39
+ sky: "bg-sky-600 dark:bg-sky-400",
40
+ blue: "bg-blue-600 dark:bg-blue-400",
41
+ indigo: "bg-indigo-600 dark:bg-indigo-400",
42
+ violet: "bg-violet-600 dark:bg-violet-400",
43
+ purple: "bg-purple-600 dark:bg-purple-400",
44
+ fuchsia: "bg-fuchsia-600 dark:bg-fuchsia-400",
45
+ pink: "bg-pink-600 dark:bg-pink-400",
46
+ rose: "bg-rose-600 dark:bg-rose-400",
47
47
  },
48
48
  },
49
49
  argTypes: {
@@ -137,8 +137,18 @@ Placeholder.args = { placeholder: "MM/DD/YYYY" };
137
137
  export const Description = DefaultTemplate.bind({});
138
138
  Description.args = { description: "Please choose a date from the calendar." };
139
139
 
140
- export const Error = DefaultTemplate.bind({});
141
- Error.args = { error: "Please select a valid date." };
140
+ export const Error: StoryFn<DefaultUDatePickerArgs> = (args: DefaultUDatePickerArgs) => ({
141
+ components: { UDatePicker, UIcon },
142
+ setup: () => ({ args, slots: getSlotNames(COMPONENT_NAME) }),
143
+ template: `
144
+ <UDatePicker
145
+ open-direction-y="bottom"
146
+ v-bind="args"
147
+ v-model="args.modelValue"
148
+ :error="args.modelValue ? '' : 'Please select a valid date.'"
149
+ />
150
+ `,
151
+ });
142
152
 
143
153
  export const Disabled = DefaultTemplate.bind({});
144
154
  Disabled.args = { disabled: true };
@@ -202,6 +202,10 @@ function setLabelPosition() {
202
202
  const shouldAlignLabelOnTop = !hasSlotContent(slots["left"]) && !props.leftIcon;
203
203
 
204
204
  if (props.labelAlign === "top" || shouldAlignLabelOnTop) {
205
+ if (labelComponentRef.value?.labelElement) {
206
+ labelComponentRef.value.labelElement.style.left = "";
207
+ }
208
+
205
209
  return;
206
210
  }
207
211
 
@@ -94,11 +94,7 @@ export const Error: StoryFn<UInputArgs> = (args: UInputArgs) => ({
94
94
  });
95
95
 
96
96
  export const Readonly = DefaultTemplate.bind({});
97
- Readonly.args = {
98
- readonly: true,
99
- label: "Readonly data",
100
- modelValue: "Pre-filled content that cannot be changed",
101
- };
97
+ Readonly.args = { readonly: true };
102
98
 
103
99
  export const Disabled = DefaultTemplate.bind({});
104
100
  Disabled.args = { disabled: true };
@@ -1,3 +1,5 @@
1
+ import { ref } from "vue";
2
+
1
3
  import {
2
4
  getArgs,
3
5
  getArgTypes,
@@ -40,7 +42,7 @@ export default {
40
42
 
41
43
  const DefaultTemplate: StoryFn<UInputFileArgs> = (args: UInputFileArgs) => ({
42
44
  components: { UInputFile },
43
- setup: () => ({ args, slots: getSlotNames(UInputFile.__name), files: [] }),
45
+ setup: () => ({ args, slots: getSlotNames(UInputFile.__name), files: ref([]) }),
44
46
  template: `
45
47
  <UInputFile v-bind="args" v-model="files">
46
48
  ${args.slotTemplate || getSlotsFragment("")}
@@ -50,13 +52,14 @@ const DefaultTemplate: StoryFn<UInputFileArgs> = (args: UInputFileArgs) => ({
50
52
 
51
53
  const EnumTemplate: StoryFn<UInputFileArgs> = (args: UInputFileArgs, { argTypes }) => ({
52
54
  components: { UInputFile, UCol },
53
- setup: () => ({ args, argTypes, getArgs }),
55
+ setup: () => ({ args, argTypes, getArgs, files: ref([]) }),
54
56
  template: `
55
57
  <UCol gap="2xl">
56
58
  <UInputFile
57
59
  v-for="option in argTypes?.[args.enum]?.options"
58
60
  v-bind="getArgs(args, option)"
59
61
  :key="option"
62
+ v-model="files"
60
63
  />
61
64
  </UCol>
62
65
  `,
@@ -28,7 +28,8 @@ export default {
28
28
  title: "Form Inputs & Controls / Input Password",
29
29
  component: UInputPassword,
30
30
  args: {
31
- modelValue: "",
31
+ modelValue: "VuelessUI",
32
+ label: "Password",
32
33
  },
33
34
  argTypes: {
34
35
  ...getArgTypes(UInputPassword.__name),
@@ -73,11 +74,8 @@ const EnumTemplate: StoryFn<UInputPasswordArgs> = (args: UInputPasswordArgs, { a
73
74
  export const Default = DefaultTemplate.bind({});
74
75
  Default.args = {};
75
76
 
76
- export const Label = DefaultTemplate.bind({});
77
- Label.args = { label: "Password" };
78
-
79
77
  export const Placeholder = DefaultTemplate.bind({});
80
- Placeholder.args = { placeholder: "Enter your password" };
78
+ Placeholder.args = { placeholder: "Enter your password", modelValue: "" };
81
79
 
82
80
  export const Description = DefaultTemplate.bind({});
83
81
  Description.args = { description: "Use at least 8 characters, including a number and a symbol." };
@@ -32,7 +32,8 @@ export default {
32
32
  ...getArgTypes(UInputSearch.__name),
33
33
  },
34
34
  args: {
35
- modelValue: "Which UI library is the best?",
35
+ modelValue: "Wireless headphones",
36
+ label: "Search for products, brands, or categories",
36
37
  },
37
38
  parameters: {
38
39
  docs: {
@@ -74,14 +75,11 @@ const EnumTemplate: StoryFn<UInputSearchArgs> = (args: UInputSearchArgs, { argTy
74
75
  export const Default = DefaultTemplate.bind({});
75
76
  Default.args = {};
76
77
 
77
- export const Label = DefaultTemplate.bind({});
78
- Label.args = { label: "Search for product or primary" };
79
-
80
78
  export const Placeholder = DefaultTemplate.bind({});
81
79
  Placeholder.args = { modelValue: "", placeholder: "Type to search..." };
82
80
 
83
81
  export const Description = DefaultTemplate.bind({});
84
- Description.args = { description: "Search for additional details." };
82
+ Description.args = { description: "Find exactly what you're looking for with a quick search." };
85
83
 
86
84
  export const Error: StoryFn<UInputSearchArgs> = (args: UInputSearchArgs) => ({
87
85
  components: { UInputSearch },
@@ -114,7 +114,7 @@ const { getDataTest, wrapperAttrs, contentAttrs, labelAttrs, descriptionAttrs, e
114
114
 
115
115
  <div
116
116
  v-if="isShownError"
117
- v-bind="descriptionAttrs"
117
+ v-bind="errorAttrs"
118
118
  :data-test="getDataTest('error')"
119
119
  v-text="error"
120
120
  />
@@ -96,7 +96,7 @@ For.args = {
96
96
  for: "input-id",
97
97
  slotTemplate: `
98
98
  <template #default>
99
- <input class="px-4 py-2 text-sm text-black rounded-small" id="input-id" />
99
+ <input id="input-id" class="py-2px-3 bg-transparent border-lifted rounded-medium" />
100
100
  </template>
101
101
  `,
102
102
  };
@@ -108,9 +108,6 @@ For.parameters = {
108
108
  },
109
109
  };
110
110
 
111
- export const Centred = DefaultTemplate.bind({});
112
- Centred.args = { centred: true };
113
-
114
111
  export const Sizes = EnumTemplate.bind({});
115
112
  Sizes.args = { enum: "size" };
116
113
 
@@ -150,6 +150,8 @@ watch(
150
150
  const wrapperBorderBottom = parseFloat(wrapperStyle.borderBottomWidth || "0");
151
151
  const wrapperGap = parseFloat(wrapperStyle.gap || "0");
152
152
 
153
+ const addOptionHeight = addOptionRef.value?.getBoundingClientRect().height || 0;
154
+
153
155
  const inputEl = listboxInputRef.value?.input as HTMLInputElement | undefined;
154
156
  let listboxInputHeight = 0;
155
157
 
@@ -159,7 +161,9 @@ watch(
159
161
 
160
162
  if (inputEl) {
161
163
  const listboxInputStyle = getComputedStyle(inputEl);
162
- const listboxInputLabelStyle = getComputedStyle(inputEl?.parentElement);
164
+ const listboxInputLabelStyle = inputEl.parentElement
165
+ ? getComputedStyle(inputEl.parentElement)
166
+ : undefined;
163
167
  const listboxInputWrapperStyle = getComputedStyle(
164
168
  inputEl.parentElement?.parentElement?.parentElement as Element,
165
169
  );
@@ -168,12 +172,13 @@ watch(
168
172
 
169
173
  listboxInputWrapperPaddingTop = parseFloat(listboxInputWrapperStyle.paddingTop || "0");
170
174
 
171
- listboxInputBorderTop = parseFloat(listboxInputLabelStyle.borderTop || "0");
172
- listboxInputBorderBottom = parseFloat(listboxInputLabelStyle.borderBottom || "0");
175
+ listboxInputBorderTop = parseFloat(listboxInputLabelStyle?.borderTop || "0");
176
+ listboxInputBorderBottom = parseFloat(listboxInputLabelStyle?.borderBottom || "0");
173
177
  }
174
178
 
175
179
  wrapperMaxHeight.value = `${
176
180
  maxHeight +
181
+ addOptionHeight +
177
182
  (props.searchable ? wrapperGap : 0) +
178
183
  wrapperPaddingTop +
179
184
  wrapperPaddingBottom +
@@ -316,9 +321,7 @@ function onClickOption(rawOption: Option) {
316
321
  }
317
322
 
318
323
  function onInputSearchBlur(event: FocusEvent) {
319
- if (props.searchable) {
320
- emit("searchBlur", event);
321
- }
324
+ emit("searchBlur", event);
322
325
  }
323
326
 
324
327
  defineExpose({