sprintify-ui 0.6.32 → 0.6.33

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.
Files changed (80) hide show
  1. package/dist/sprintify-ui.es.js +11685 -11472
  2. package/dist/style.css +1 -1
  3. package/dist/tailwindcss/button.js +260 -0
  4. package/dist/tailwindcss/index.js +16 -301
  5. package/dist/tailwindcss/input.js +24 -0
  6. package/dist/tailwindcss/overlay.js +13 -0
  7. package/dist/tailwindcss/theme.js +46 -0
  8. package/dist/types/src/components/BaseActionItemButton.vue.d.ts +2 -2
  9. package/dist/types/src/components/BaseAddressForm.vue.d.ts +10 -0
  10. package/dist/types/src/components/BaseAutocomplete.vue.d.ts +10 -10
  11. package/dist/types/src/components/BaseAutocompleteDrawer.vue.d.ts +3 -3
  12. package/dist/types/src/components/BaseAutocompleteFetch.vue.d.ts +6 -6
  13. package/dist/types/src/components/BaseAvatarGroup.vue.d.ts +1 -1
  14. package/dist/types/src/components/BaseBelongsTo.vue.d.ts +6 -6
  15. package/dist/types/src/components/BaseBelongsToFetch.vue.d.ts +6 -6
  16. package/dist/types/src/components/BaseButton.vue.d.ts +12 -12
  17. package/dist/types/src/components/BaseButtonGroup.vue.d.ts +24 -24
  18. package/dist/types/src/components/BaseCalendar.vue.d.ts +1 -1
  19. package/dist/types/src/components/BaseColor.vue.d.ts +19 -0
  20. package/dist/types/src/components/BaseDataIterator.vue.d.ts +1 -1
  21. package/dist/types/src/components/BaseDataIteratorSectionColumns.vue.d.ts +4 -4
  22. package/dist/types/src/components/BaseDataTable.vue.d.ts +1 -1
  23. package/dist/types/src/components/BaseDropdownAutocomplete.vue.d.ts +1 -1
  24. package/dist/types/src/components/BaseField.vue.d.ts +13 -3
  25. package/dist/types/src/components/BaseInput.vue.d.ts +35 -4
  26. package/dist/types/src/components/BaseInputError.vue.d.ts +14 -1
  27. package/dist/types/src/components/BaseInputLabel.vue.d.ts +15 -5
  28. package/dist/types/src/components/BaseLayoutSidebarConfigurable.vue.d.ts +1 -1
  29. package/dist/types/src/components/BaseLayoutStackedConfigurable.vue.d.ts +1 -1
  30. package/dist/types/src/components/BaseLoadingCover.vue.d.ts +1 -1
  31. package/dist/types/src/components/BaseMediaGallery.vue.d.ts +1 -1
  32. package/dist/types/src/components/BaseMediaListItem.vue.d.ts +1 -1
  33. package/dist/types/src/components/BaseMediaPictures.vue.d.ts +1 -1
  34. package/dist/types/src/components/BaseMediaPicturesItem.vue.d.ts +1 -1
  35. package/dist/types/src/components/BaseMenu.vue.d.ts +1 -1
  36. package/dist/types/src/components/BaseMenuItem.vue.d.ts +1 -1
  37. package/dist/types/src/components/BaseNavbar.vue.d.ts +1 -1
  38. package/dist/types/src/components/BaseNavbarItemContent.vue.d.ts +1 -1
  39. package/dist/types/src/components/BaseNavbarSideItemContent.vue.d.ts +1 -1
  40. package/dist/types/src/components/BaseSelect.vue.d.ts +27 -0
  41. package/dist/types/src/components/BaseSideNavigation.vue.d.ts +3 -3
  42. package/dist/types/src/components/BaseSwitch.vue.d.ts +1 -1
  43. package/dist/types/src/components/BaseTable.vue.d.ts +1 -1
  44. package/dist/types/src/components/BaseTabs.vue.d.ts +3 -3
  45. package/dist/types/src/components/BaseTagAutocomplete.vue.d.ts +3 -3
  46. package/dist/types/src/composables/field.d.ts +3 -0
  47. package/dist/types/src/composables/inputSize.d.ts +6 -0
  48. package/dist/types/src/utils/sizes.d.ts +19 -0
  49. package/package.json +1 -1
  50. package/src/assets/form.css +1 -1
  51. package/src/components/BaseAddressForm.stories.js +7 -2
  52. package/src/components/BaseAddressForm.vue +64 -37
  53. package/src/components/BaseAutocomplete.stories.js +1 -1
  54. package/src/components/BaseAutocomplete.vue +86 -96
  55. package/src/components/BaseAutocompleteDrawer.vue +3 -2
  56. package/src/components/BaseAutocompleteFetch.stories.js +1 -1
  57. package/src/components/BaseAutocompleteFetch.vue +3 -2
  58. package/src/components/BaseBelongsTo.stories.js +1 -1
  59. package/src/components/BaseBelongsTo.vue +3 -2
  60. package/src/components/BaseBelongsToFetch.vue +3 -2
  61. package/src/components/BaseButton.stories.js +21 -0
  62. package/src/components/BaseButton.vue +42 -6
  63. package/src/components/BaseButtonGroup.stories.js +31 -1
  64. package/src/components/BaseButtonGroup.vue +46 -33
  65. package/src/components/BaseColor.stories.js +22 -0
  66. package/src/components/BaseColor.vue +28 -25
  67. package/src/components/BaseDropdown.stories.js +2 -3
  68. package/src/components/BaseDropdownAutocomplete.vue +2 -2
  69. package/src/components/BaseField.vue +19 -8
  70. package/src/components/BaseInput.stories.js +35 -1
  71. package/src/components/BaseInput.vue +154 -74
  72. package/src/components/BaseInputError.vue +32 -2
  73. package/src/components/BaseInputLabel.vue +36 -9
  74. package/src/components/BaseSelect.stories.js +34 -0
  75. package/src/components/BaseSelect.vue +57 -8
  76. package/src/components/BaseTagAutocomplete.vue +3 -2
  77. package/src/components/BaseTimelineItem.stories.js +1 -3
  78. package/src/composables/field.ts +20 -0
  79. package/src/composables/inputSize.ts +29 -0
  80. package/src/utils/sizes.ts +21 -0
@@ -2,10 +2,18 @@ import { createFieldStory } from '../../.storybook/utils';
2
2
  import BaseColor from './BaseColor.vue';
3
3
  import ShowValue from '../../.storybook/components/ShowValue.vue';
4
4
 
5
+ const sizes = ['xs', 'sm', 'md'];
6
+
5
7
  export default {
6
8
  title: 'Form/BaseColor',
7
9
  component: BaseColor,
8
10
  decorators: [() => ({ template: '<div class="mb-36"><story/></div>' })],
11
+ argTypes: {
12
+ size: {
13
+ control: { type: 'select' },
14
+ options: sizes,
15
+ },
16
+ },
9
17
  };
10
18
 
11
19
  const Template = (args) => ({
@@ -39,6 +47,20 @@ Disabled.args = {
39
47
  modelValue: '#16a34a',
40
48
  };
41
49
 
50
+ export const Sizes = (args) => ({
51
+ components: { BaseColor },
52
+ setup() {
53
+ const value = ref(null);
54
+ return { args, sizes, value };
55
+ },
56
+ template: `
57
+ <div v-for="size in sizes" :key="size" class="mb-4">
58
+ <p class="text-xs text-slate-600 leading-tight mb-1"> {{ size }}</p>
59
+ <BaseColor v-bind="args" v-model="value" :size="size"></BaseColor>
60
+ </div>
61
+ `,
62
+ });
63
+
42
64
  export const Field = createFieldStory({
43
65
  component: BaseColor,
44
66
  componentName: 'BaseColor',
@@ -5,36 +5,28 @@
5
5
  :disabled="disabled"
6
6
  value-key="value"
7
7
  label-key="label"
8
+ :size="size"
8
9
  :required="required"
9
10
  :options="colorOptions"
10
11
  :multiple="multiple"
11
12
  :button-type="buttonType"
12
- tw-button=""
13
- tw-button-selected=""
14
- tw-button-unselected=""
13
+ :button-color="buttonColor"
14
+ tw-button="p-0 aspect-1 justify-center items-center"
15
15
  @update:model-value="(value) => transformModelValue(value)"
16
16
  >
17
17
  <template #option="option">
18
18
  <div
19
- :style="{ backgroundColor: option.option.value + '' }"
20
- class="box-border rounded-md border p-3"
21
- :class="[
22
- option.selected.value
23
- ? option.option.option.hasLowContrast
24
- ? 'text-slate-700'
25
- : 'text-white'
26
- : 'text-transparent',
27
- disabled ? ' cursor-not-allowed opacity-50' : '',
28
- option.option.option.hasLowContrast
29
- ? 'border-slate-400'
30
- : 'border-transparent',
31
- ]"
19
+ v-if="option.selected.value"
20
+ class="overflow-hidden flex h-full"
32
21
  >
33
22
  <BaseIcon
34
23
  icon="heroicons-solid:check-circle"
35
- class="h-5 w-5"
24
+ class="block leading-none"
25
+ width="18"
26
+ height="18"
36
27
  />
37
28
  </div>
29
+ <div v-else />
38
30
  </template>
39
31
  </BaseButtonGroup>
40
32
  </div>
@@ -48,6 +40,7 @@ import { useField } from '@/composables/field';
48
40
  import { Option } from '@/types';
49
41
  import { palette } from '@/utils/colors';
50
42
  import { getContrast } from 'color2k';
43
+ import { Size } from '@/utils/sizes';
51
44
 
52
45
  const props = defineProps({
53
46
  modelValue: {
@@ -64,6 +57,10 @@ const props = defineProps({
64
57
  default: false,
65
58
  type: Boolean,
66
59
  },
60
+ size: {
61
+ default: undefined,
62
+ type: String as PropType<Size>,
63
+ },
67
64
  buttonType: {
68
65
  default: 'button',
69
66
  type: String as PropType<'button' | 'submit'>,
@@ -74,6 +71,12 @@ const props = defineProps({
74
71
  return Object.values(palette).map((p) => p.high.backgroundColor);
75
72
  },
76
73
  },
74
+ buttonColor: {
75
+ default(option: Option, selected: boolean) {
76
+ return option.value;
77
+ },
78
+ type: Function as PropType<(option: Option, selected: boolean) => string>,
79
+ },
77
80
  multiple: {
78
81
  default: false,
79
82
  type: Boolean,
@@ -107,15 +110,15 @@ function hasLowContrast(color: string): boolean {
107
110
  const normalizeModelValue = computed(() => {
108
111
  return isArray(props.modelValue)
109
112
  ? props.modelValue?.map((m) => {
110
- return {
111
- label: m,
112
- value: m,
113
- };
114
- })
115
- : {
116
- label: props.modelValue,
117
- value: props.modelValue,
113
+ return {
114
+ label: m,
115
+ value: m,
118
116
  };
117
+ })
118
+ : {
119
+ label: props.modelValue,
120
+ value: props.modelValue,
121
+ };
119
122
  });
120
123
 
121
124
  const { emitUpdate } = useField({
@@ -93,7 +93,6 @@ export const WithAutocomplete = (args) => ({
93
93
  size="xs"
94
94
  :options="options"
95
95
  :inline="true"
96
- :visibleFocus="false"
97
96
  dropdownShow="always"
98
97
  :showModelValue="false"
99
98
  focus-on-mount
@@ -143,14 +142,14 @@ export const ModalWithScroll = (args) => ({
143
142
  },
144
143
  template: `
145
144
  <BaseModalCenter v-model="open">
146
- <div class="p-10 bg-white">
145
+ <div class="p-10">
147
146
  <BaseDropdown v-bind="args">
148
147
  <template #button>
149
148
  <div class="btn btn-primary">Click me</div>
150
149
  </template>
151
150
  <template #dropdown>
152
151
  <div
153
- class="bg-white shadow py-1 px-1 rounded"
152
+ class="bg-white ring-1 shadow-xl ring-black ring-opacity-10 py-1 px-1 rounded-md"
154
153
  style="max-height: 200px; overflow: auto;"
155
154
  data-scroll-lock-scrollable>
156
155
  <button type="button" v-for="item in items" :key="item.label" class="block text-sm px-4 py-1.5">{{ item.label }}</button>
@@ -13,7 +13,7 @@
13
13
  </template>
14
14
  <template #dropdown="{ close }">
15
15
  <div
16
- class="inline-block w-[320px] overflow-hidden rounded-md ring-1 ring-black ring-opacity-10 bg-white px-2 pt-2 shadow-2xl"
16
+ class="inline-block w-[320px] overflow-hidden input-rounded ring-1 ring-black ring-opacity-10 bg-white px-2 pt-2 shadow-2xl"
17
17
  >
18
18
  <component
19
19
  :is="componentName"
@@ -33,7 +33,7 @@
33
33
  <template #option="optionProps">
34
34
  <div
35
35
  :class="[optionProps.active ? 'bg-slate-100' : 'bg-white']"
36
- class="mb-px flex items-center rounded px-1 py-1"
36
+ class="mb-px flex items-center input-rounded px-1 py-1"
37
37
  >
38
38
  <div class="flex grow items-center">
39
39
  <slot
@@ -4,7 +4,8 @@
4
4
  v-if="labelNormalized"
5
5
  :label="labelNormalized"
6
6
  :required="required"
7
- :class="labelClassInternal"
7
+ :size="inputSize.size.value"
8
+ :class="labelClassInternalMerged"
8
9
  :help="help"
9
10
  />
10
11
 
@@ -19,6 +20,7 @@
19
20
  <template v-if="errorMessage">
20
21
  <BaseInputError
21
22
  v-if="errorTypeInternal == 'default'"
23
+ :size="inputSize.size.value"
22
24
  class="mt-1"
23
25
  >
24
26
  {{ errorMessage }}
@@ -40,6 +42,9 @@ import { PropType } from 'vue';
40
42
  import BaseAlert from './BaseAlert.vue';
41
43
  import BaseInputError from './BaseInputError.vue';
42
44
  import BaseInputLabel from './BaseInputLabel.vue';
45
+ import { useInputSize } from '@/composables/inputSize';
46
+ import { Size } from '@/utils/sizes';
47
+ import { ClassNameValue, twMerge } from 'tailwind-merge';
43
48
 
44
49
  const props = defineProps({
45
50
  name: {
@@ -50,6 +55,10 @@ const props = defineProps({
50
55
  type: String,
51
56
  default: '',
52
57
  },
58
+ size: {
59
+ default: undefined,
60
+ type: String as PropType<Size>,
61
+ },
53
62
  required: {
54
63
  type: Boolean,
55
64
  default: false,
@@ -68,25 +77,26 @@ const props = defineProps({
68
77
  },
69
78
  labelClass: {
70
79
  default: '',
71
- type: [String, Array, Object] as PropType<
72
- string | string[] | Record<string, boolean>
73
- >,
80
+ type: [String, Array] as PropType<ClassNameValue>,
74
81
  },
75
82
  });
76
83
 
77
84
  const errorTypeInternal = ref(props.errorType);
78
85
 
86
+ const inputSize = useInputSize(computed(() => props.size));
87
+
79
88
  function setErrorType(errorType: 'default' | 'alert' | null) {
80
89
  if (errorType != null) {
81
90
  errorTypeInternal.value = errorType;
82
91
  }
83
92
  }
84
93
 
85
- const labelClassInternal = ref(props.labelClass);
94
+ const labelClassInternal = ref<any>('');
95
+ const labelClassInternalMerged = computed(() => {
96
+ return twMerge(labelClassInternal.value, props.labelClass);
97
+ });
86
98
 
87
- function setLabelClass(
88
- labelClass: string | string[] | Record<string, boolean> | null
89
- ) {
99
+ function setLabelClass(labelClass: ClassNameValue) {
90
100
  if (labelClass != null) {
91
101
  labelClassInternal.value = labelClass;
92
102
  }
@@ -122,6 +132,7 @@ const errorMessage = computed((): string | null | undefined => {
122
132
 
123
133
  provide('field:name', readonly(ref(props.name)));
124
134
  provide('field:required', readonly(ref(props.required)));
135
+ provide('field:size', readonly(inputSize.size));
125
136
  provide('field:onUpdate', fieldOnUpdate);
126
137
  provide('field:errorMessage', errorMessage);
127
138
  provide('field:setErrorType', setErrorType);
@@ -19,6 +19,10 @@ export default {
19
19
  placeholder: 'Enter your name',
20
20
  },
21
21
  argTypes: {
22
+ size: {
23
+ control: { type: 'select' },
24
+ options: ['xs', 'sm', 'md'],
25
+ },
22
26
  mask: {
23
27
  control: { type: 'select' },
24
28
  options: [
@@ -144,12 +148,42 @@ CustomMask.args = {
144
148
  mask: (value) => (value.startsWith('1') ? '#-#' : '##-##'),
145
149
  };
146
150
 
151
+ const CustomClassesT = (args) => ({
152
+ components: { BaseInput, ShowValue },
153
+ setup() {
154
+ const value = ref(null);
155
+ return { args, value };
156
+ },
157
+ template: `
158
+ <BaseInput v-model="value" v-bind="args" suffix="$$$" class="w-full bg-green-100 text-green-700 border-green-700 focus-within:border-red-500 focus-within:ring-red-800 placeholder:text-green-400 shadow-xl"></BaseInput>
159
+ <ShowValue :value="value" />
160
+ `,
161
+ });
162
+
163
+ export const CustomClasses = CustomClassesT.bind({});
164
+
147
165
  export const Field = createFieldStory({
148
166
  component: BaseInput,
149
167
  componentName: 'BaseInput',
150
168
  label: 'Name',
151
169
  });
152
170
 
171
+ const TemplateSizes = (args) => ({
172
+ components: { BaseInput, ShowValue },
173
+ setup() {
174
+ const value = ref(null);
175
+ const sizes = ['xs', 'sm', 'md'];
176
+ return { args, value, sizes };
177
+ },
178
+ template: `
179
+ <div v-for="size in sizes" :key="size" class="mb-4">
180
+ <p class="text-xs text-slate-600 leading-tight mb-1">btn {{ size }}</p>
181
+ <BaseInput v-model="value" v-bind="args" :size="size" class="w-full"></BaseInput>
182
+ </div>
183
+ `,
184
+ });
185
+
186
+ export const Sizes = TemplateSizes.bind({});
153
187
 
154
188
  const FocusTemplate = (args) => ({
155
189
  components: { BaseInput },
@@ -161,7 +195,7 @@ const FocusTemplate = (args) => ({
161
195
  template: `
162
196
  <BaseInput ref="input" v-model="value" v-bind="args" class="w-full"></BaseInput>
163
197
 
164
- <button @click="input.focus()" class="mt-4 underline">Focus</button>
198
+ <button @click="input.focus()" class="mt-4 btn btn-sm">Focus</button>
165
199
  `,
166
200
  });
167
201
 
@@ -1,27 +1,23 @@
1
1
  <template>
2
- <div
3
- class="inline-flex rounded border"
4
- :class="[borderColor]"
5
- >
6
- <div
7
- v-if="iconLeft"
8
- class="flex shrink-0 items-center justify-center rounded-l border-r px-3 transition-colors"
9
- :class="[borderColor, backgroundColor, textColor]"
10
- >
11
- <BaseIcon :icon="iconLeft" />
12
- </div>
13
- <div
14
- v-if="prefix"
15
- class="flex shrink-0 items-center justify-center border-r px-4 transition-colors"
16
- :class="[
17
- iconLeft ? '' : 'rounded-l',
18
- borderColor,
19
- backgroundColor,
20
- textColor,
21
- ]"
22
- >
23
- {{ prefix }}
2
+ <div :class="classes">
3
+ <div :class="decorationWrapClasses">
4
+ <div
5
+ v-if="iconLeft"
6
+ :class="decorationClasses"
7
+ >
8
+ <BaseIcon
9
+ :icon="iconLeft"
10
+ :class="iconClasses"
11
+ />
12
+ </div>
13
+ <div
14
+ v-if="prefix"
15
+ :class="decorationClasses"
16
+ >
17
+ {{ prefix }}
18
+ </div>
24
19
  </div>
20
+
25
21
  <input
26
22
  v-if="maskOptions"
27
23
  ref="input"
@@ -30,12 +26,10 @@
30
26
  :value="modelValue"
31
27
  :type="type"
32
28
  :autocomplete="autocomplete ? 'on' : 'off'"
33
- :class="{
34
- 'rounded-l': emptyLeft,
35
- 'rounded-r': emptyRight,
36
- 'w-full border-none bg-white outline-none focus:z-[1] focus:ring-2 focus:ring-primary-600 focus:ring-offset-1 disabled:cursor-not-allowed disabled:text-slate-300': true,
37
- }"
38
- @input="update"
29
+ :class="baseClasses"
30
+ @input="onInput"
31
+ @click="onClick"
32
+ @keydown="onKeydown"
39
33
  >
40
34
  <input
41
35
  v-else
@@ -44,31 +38,27 @@
44
38
  :value="modelValue"
45
39
  :type="type"
46
40
  :autocomplete="autocomplete ? 'on' : 'off'"
47
- :class="{
48
- 'rounded-l': emptyLeft,
49
- 'rounded-r': emptyRight,
50
- 'w-full border-none bg-white outline-none focus:z-[1] focus:ring-2 focus:ring-primary-600 focus:ring-offset-1 disabled:cursor-not-allowed disabled:text-slate-300': true,
51
- }"
52
- @input="update"
53
- >
54
- <div
55
- v-if="suffix"
56
- class="flex shrink-0 items-center justify-center border-l px-4 transition-colors"
57
- :class="[
58
- iconRight ? '' : 'rounded-r',
59
- borderColor,
60
- backgroundColor,
61
- textColor,
62
- ]"
41
+ :class="baseClasses"
42
+ @input="onInput"
43
+ @click="onClick"
44
+ @keydown="onKeydown"
63
45
  >
64
- {{ suffix }}
65
- </div>
66
- <div
67
- v-if="iconRight"
68
- class="flex shrink-0 items-center justify-center rounded-r border-l px-3 transition-colors"
69
- :class="[borderColor, backgroundColor, textColor]"
70
- >
71
- <BaseIcon :icon="iconRight" />
46
+ <div :class="decorationWrapClasses">
47
+ <div
48
+ v-if="suffix"
49
+ :class="decorationClasses"
50
+ >
51
+ {{ suffix }}
52
+ </div>
53
+ <div
54
+ v-if="iconRight"
55
+ :class="decorationClasses"
56
+ >
57
+ <BaseIcon
58
+ :icon="iconRight"
59
+ :class="iconClasses"
60
+ />
61
+ </div>
72
62
  </div>
73
63
  </div>
74
64
  </template>
@@ -79,12 +69,22 @@ import { PropType } from 'vue';
79
69
  import { Icon as BaseIcon } from '@iconify/vue';
80
70
  import { useField } from '@/composables/field';
81
71
  import { vMaska } from 'maska';
72
+ import { Size, sizes } from '@/utils/sizes';
73
+ import { twMerge } from 'tailwind-merge';
74
+
75
+ defineOptions({
76
+ inheritAttrs: false,
77
+ })
82
78
 
83
79
  const props = defineProps({
84
80
  modelValue: {
85
81
  default: '',
86
82
  type: [String, Number, null] as PropType<string | number | null>,
87
83
  },
84
+ class: {
85
+ default: '',
86
+ type: [String, Array] as PropType<string | string[]>,
87
+ },
88
88
  type: {
89
89
  type: String,
90
90
  default: 'text',
@@ -140,6 +140,10 @@ const props = defineProps({
140
140
  default: false,
141
141
  type: Boolean,
142
142
  },
143
+ size: {
144
+ default: undefined,
145
+ type: String as PropType<Size>,
146
+ },
143
147
  min: {
144
148
  default: undefined,
145
149
  type: [null, Number] as PropType<undefined | null | number>,
@@ -154,9 +158,22 @@ const props = defineProps({
154
158
  return null;
155
159
  },
156
160
  },
161
+ visibleFocus: {
162
+ default: true,
163
+ type: Boolean,
164
+ },
157
165
  });
158
166
 
159
167
  const input = ref<HTMLInputElement | null>(null);
168
+ const focus = ref(false);
169
+
170
+ const hasLeftDecoration = computed(() => {
171
+ return props.iconLeft || props.prefix;
172
+ });
173
+
174
+ const hasRightDecoration = computed(() => {
175
+ return props.iconRight || props.suffix;
176
+ });
160
177
 
161
178
  const maskOptions = computed(() => {
162
179
  if (props.mask) {
@@ -167,14 +184,6 @@ const maskOptions = computed(() => {
167
184
  return undefined;
168
185
  });
169
186
 
170
- const emptyLeft = computed(() => {
171
- return !props.iconLeft && !props.prefix;
172
- });
173
-
174
- const emptyRight = computed(() => {
175
- return !props.iconRight && !props.suffix;
176
- });
177
-
178
187
  const bindings = computed<any>(() => {
179
188
  return {
180
189
  name: nameInternal.value,
@@ -184,7 +193,6 @@ const bindings = computed<any>(() => {
184
193
  disabled: props.disabled,
185
194
  placeholder: props.placeholder,
186
195
  required: requiredInternal.value,
187
-
188
196
  onKeydown(event: KeyboardEvent) {
189
197
  if (event.code == 'Enter' && props.preventSubmit) {
190
198
  event.preventDefault();
@@ -192,9 +200,11 @@ const bindings = computed<any>(() => {
192
200
  },
193
201
  onFocus: (e: Event) => {
194
202
  emit('focus', e);
203
+ focus.value = true;
195
204
  },
196
205
  onBlur: (e: Event) => {
197
206
  emit('blur', e);
207
+ focus.value = false;
198
208
  },
199
209
  };
200
210
  });
@@ -219,17 +229,18 @@ const maskInternal = computed(() => {
219
229
  return props.mask;
220
230
  });
221
231
 
222
- const emit = defineEmits(['update:modelValue', 'focus', 'blur']);
232
+ const emit = defineEmits(['update:modelValue', 'focus', 'blur', 'click', 'keydown']);
223
233
 
224
- const { nameInternal, requiredInternal, hasErrorInternal, emitUpdate } =
234
+ const { nameInternal, requiredInternal, hasErrorInternal, emitUpdate, sizeInternal } =
225
235
  useField({
226
236
  name: computed(() => props.name),
227
237
  required: computed(() => props.required),
228
238
  hasError: computed(() => props.hasError),
239
+ size: computed(() => props.size),
229
240
  emit: emit,
230
241
  });
231
242
 
232
- function update(event: any | null) {
243
+ function onInput(event: any | null) {
233
244
  if (event === null) {
234
245
  emitUpdate(null);
235
246
  }
@@ -237,28 +248,97 @@ function update(event: any | null) {
237
248
  return emitUpdate(get(event, 'target.value', ''));
238
249
  }
239
250
 
240
- const borderColor = computed(() => {
241
- return hasErrorInternal.value ? 'border-red-500' : 'border-slate-300';
251
+ function onClick(event: MouseEvent) {
252
+ emit('click', event);
253
+ }
254
+
255
+ function onKeydown(event: KeyboardEvent) {
256
+ emit('keydown', event);
257
+ }
258
+
259
+ const classes = computed(() => {
260
+ const base = `inline-flex bg-white input-rounded border transition-colors duration-200`;
261
+ const border = hasErrorInternal.value ? 'border-red-500' : 'border-slate-300';
262
+ const disabled = props.disabled ? 'cursor-not-allowed text-slate-300' : '';
263
+ const sizeConfig = sizes[sizeInternal.value];
264
+ let focusClass = '';
265
+ if (props.visibleFocus) {
266
+ if (hasErrorInternal.value) {
267
+ focusClass = 'focus-within:input-focus-error';
268
+ } else {
269
+ focusClass = 'focus-within:input-focus';
270
+ }
271
+ }
272
+
273
+ return twMerge([
274
+ base,
275
+ border,
276
+ disabled,
277
+ sizeConfig.height,
278
+ sizeConfig.fontSize,
279
+ focusClass,
280
+ props.class,
281
+ ]);
242
282
  });
243
283
 
244
- const backgroundColor = computed(() => {
245
- return hasErrorInternal.value ? 'bg-red-100' : 'bg-slate-100';
284
+ const baseClasses = computed(() => {
285
+ const base = `border-none outline-none bg-transparent grow min-w-0 focus:border-none focus:outline-none focus:ring-0`;
286
+ const sizeConfig = sizes[sizeInternal.value];
287
+ const disabled = props.disabled ? 'cursor-not-allowed text-slate-300' : '';
288
+
289
+ const paddingX = {
290
+ xs: [hasLeftDecoration.value ? 'pl-1.5' : 'pl-2', hasRightDecoration.value ? 'pr-1.5' : 'pr-2'],
291
+ sm: [hasLeftDecoration.value ? 'pl-2' : 'pl-2.5', hasRightDecoration.value ? 'pr-2' : 'pr-2.5'],
292
+ md: [hasLeftDecoration.value ? 'pl-2.5' : 'pl-3', hasRightDecoration.value ? 'pr-2.5' : 'pr-3'],
293
+ }[sizeInternal.value];
294
+
295
+ return [
296
+ base,
297
+ disabled,
298
+ paddingX,
299
+ sizeConfig.fontSize,
300
+ ];
301
+ });
302
+
303
+ const decorationWrapClasses = computed(() => {
304
+ const base = `flex items-center justify-center empty:hidden`;
305
+ const spacing = {
306
+ xs: 'first:pl-2 last:pr-2 gap-1',
307
+ sm: 'first:pl-2.5 last:pr-2.5 gap-2',
308
+ md: 'first:pl-3 last:pr-3 gap-3',
309
+ }[sizeInternal.value];
310
+
311
+ return [
312
+ base,
313
+ spacing,
314
+ ];
246
315
  });
247
316
 
248
- const textColor = computed(() => {
249
- return hasErrorInternal.value ? 'text-red-800' : 'text-slate-600';
317
+ const decorationClasses = computed(() => {
318
+ const base = `flex items-center justify-center`;
319
+ const textColor = hasErrorInternal.value ? 'text-red-800' : 'text-slate-500';
320
+
321
+ return `${base} ${textColor}`;
322
+ });
323
+
324
+ const iconClasses = computed(() => {
325
+ const sizeConfig = sizes[sizeInternal.value];
326
+
327
+ return [
328
+ sizeConfig.iconSize,
329
+ ];
250
330
  });
251
331
 
252
- function focus() {
332
+ function focusAction() {
253
333
  input.value?.focus();
254
334
  }
255
335
 
256
- function blur() {
336
+ function blurAction() {
257
337
  input.value?.blur();
258
338
  }
259
339
 
260
340
  defineExpose({
261
- focus,
262
- blur,
341
+ focus: focusAction,
342
+ blur: blurAction,
263
343
  });
264
344
  </script>