@antify/ui-module 1.5.1 → 1.6.0

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 (30) hide show
  1. package/dist/module.json +1 -1
  2. package/dist/runtime/components/AntAlert.vue +14 -5
  3. package/dist/runtime/components/AntContent.vue +16 -0
  4. package/dist/runtime/components/AntPagination.vue +8 -3
  5. package/dist/runtime/components/__stories/AntAlert.stories.d.ts +1 -0
  6. package/dist/runtime/components/__stories/AntAlert.stories.mjs +15 -9
  7. package/dist/runtime/components/__stories/AntContent.stories.d.ts +6 -0
  8. package/dist/runtime/components/__stories/AntContent.stories.mjs +26 -0
  9. package/dist/runtime/components/crud/AntCrudTableNav.vue +11 -2
  10. package/dist/runtime/components/crud/__stories/AntCrudTableNav.stories.mjs +1 -1
  11. package/dist/runtime/components/form/AntNumberInput.vue +6 -2
  12. package/dist/runtime/components/form/AntSelect.vue +3 -3
  13. package/dist/runtime/components/form/AntTagInput.vue +7 -7
  14. package/dist/runtime/components/form/Elements/AntField.vue +24 -21
  15. package/dist/runtime/components/form/Elements/AntInputDescription.vue +5 -5
  16. package/dist/runtime/components/form/__stories/AntNumberInput.stories.d.ts +1 -0
  17. package/dist/runtime/components/form/__stories/AntNumberInput.stories.mjs +7 -0
  18. package/dist/runtime/components/layouts/AntNavLeftLayout.vue +2 -2
  19. package/dist/runtime/components/layouts/__stories/AntNavLeftLayout.stories.mjs +1 -1
  20. package/package.json +1 -1
  21. package/src/runtime/components/AntAlert.vue +14 -5
  22. package/src/runtime/components/AntContent.vue +16 -0
  23. package/src/runtime/components/AntPagination.vue +8 -3
  24. package/src/runtime/components/crud/AntCrudTableNav.vue +11 -2
  25. package/src/runtime/components/form/AntNumberInput.vue +6 -2
  26. package/src/runtime/components/form/AntSelect.vue +3 -3
  27. package/src/runtime/components/form/AntTagInput.vue +7 -7
  28. package/src/runtime/components/form/Elements/AntField.vue +24 -21
  29. package/src/runtime/components/form/Elements/AntInputDescription.vue +5 -5
  30. package/src/runtime/components/layouts/AntNavLeftLayout.vue +2 -2
package/dist/module.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "ui-module",
3
3
  "configKey": "uiModule",
4
- "version": "1.5.1"
4
+ "version": "1.6.0"
5
5
  }
@@ -18,17 +18,19 @@ import {IconSize} from './__types';
18
18
  defineEmits(['close']);
19
19
 
20
20
  const props = withDefaults(defineProps<{
21
- title: string,
21
+ title?: string | null,
22
22
  colorType?: InputColorType,
23
23
  icon?: boolean,
24
24
  expanded?: boolean,
25
- questionMarkText?: string,
25
+ questionMarkText?: string | null,
26
26
  skeleton?: boolean,
27
27
  dismissBtn?: boolean,
28
28
  }>(), {
29
+ title: null,
29
30
  colorType: InputColorType.base,
30
31
  icon: true,
31
32
  expanded: false,
33
+ questionMarkText: null,
32
34
  skeleton: false,
33
35
  dismissBtn: true,
34
36
  });
@@ -81,9 +83,14 @@ onMounted(() => {
81
83
  :class="classes"
82
84
  data-e2e="alert"
83
85
  >
84
- <AntSkeleton v-if="skeleton" absolute rounded/>
86
+ <AntSkeleton
87
+ v-if="skeleton"
88
+ absolute
89
+ rounded
90
+ />
85
91
 
86
92
  <div
93
+ v-if="icon || hasQuestionMark || dismissBtn || title"
87
94
  class="inline-flex items-center justify-between w-content gap-2.5"
88
95
  :class="{'invisible': skeleton}"
89
96
  >
@@ -95,7 +102,9 @@ onMounted(() => {
95
102
  :size="IconSize.sm"
96
103
  />
97
104
 
98
- <div :class="{'font-semibold': hasDefaultSlot}">
105
+ <div
106
+ :class="{'font-semibold': hasDefaultSlot}"
107
+ >
99
108
  <slot name="title">
100
109
  {{ title }}
101
110
  </slot>
@@ -131,7 +140,7 @@ onMounted(() => {
131
140
  </div>
132
141
 
133
142
  <div v-if="hasDefaultSlot">
134
- <slot/>
143
+ <slot />
135
144
  </div>
136
145
  </div>
137
146
  </template>
@@ -0,0 +1,16 @@
1
+ <script setup lang="ts">
2
+ withDefaults(defineProps<{
3
+ padding?: boolean
4
+ }>(), {
5
+ padding: true
6
+ })
7
+ </script>
8
+
9
+ <template>
10
+ <div
11
+ :class="{ 'p-2.5': padding }"
12
+ class="bg-white overflow-auto"
13
+ >
14
+ <slot />
15
+ </div>
16
+ </template>
@@ -162,7 +162,11 @@ const pagination = computed(() => {
162
162
  class="inline-flex relative"
163
163
  data-e2e="pagination"
164
164
  >
165
- <AntSkeleton v-if="skeleton" rounded absolute/>
165
+ <AntSkeleton
166
+ v-if="skeleton"
167
+ rounded
168
+ absolute
169
+ />
166
170
 
167
171
  <div
168
172
  class="inline-flex gap-px"
@@ -177,14 +181,15 @@ const pagination = computed(() => {
177
181
  />
178
182
 
179
183
  <AntButton
180
- v-for="(pageObj, index) in pagination"
184
+ v-for="(pageObj) in pagination"
185
+ :key="`pagination-button-${pageObj}`"
181
186
  :color-type="pageObj === page ? ColorType.primary : ColorType.base"
182
187
  :class="{'text-primary-500 z-10': pageObj === page}"
183
188
  :disabled="pageObj === '...'"
184
189
  :grouped="Grouped.center"
185
190
  :filled="pageObj !== page"
191
+ :readonly="pageObj === page"
186
192
  @click="() => page = pageObj"
187
- v-bind:key="`pagination-button-${index}`"
188
193
  >
189
194
  {{ pageObj }}
190
195
  </AntButton>
@@ -4,6 +4,7 @@ declare const meta: Meta<typeof AntAlert>;
4
4
  export default meta;
5
5
  type Story = StoryObj<typeof AntAlert>;
6
6
  export declare const Docs: Story;
7
+ export declare const WithOutTitle: Story;
7
8
  export declare const WithContent: Story;
8
9
  export declare const WithoutContent: Story;
9
10
  export declare const WithQuestionIcon: Story;
@@ -22,21 +22,27 @@ export const Docs = {
22
22
  return { args, logClick };
23
23
  },
24
24
  template: `
25
- <div class="p-4">
26
- <AntAlert v-bind="args" @close="logClick">
27
- Lorem ipsum dolor sit amet, consetetur sadipscing elitr, <br/>
28
- sed diam nonumy eirmod tempor invidunt <br/>
29
- ut labore et dolore magna aliquyam erat, <br/>
30
- sed diam voluptua. At vero eos et accusam et <br/>
31
- justo duo dolores et ea rebum. Stet clita kasd
32
- </AntAlert>
33
- </div>
25
+ <AntAlert v-bind="args" @close="logClick">
26
+ Lorem ipsum dolor sit amet, consetetur sadipscing elitr, <br/>
27
+ sed diam nonumy eirmod tempor invidunt <br/>
28
+ ut labore et dolore magna aliquyam erat, <br/>
29
+ sed diam voluptua. At vero eos et accusam et <br/>
30
+ justo duo dolores et ea rebum. Stet clita kasd
31
+ </AntAlert>
34
32
  `
35
33
  }),
36
34
  args: {
37
35
  title: "Lorem ipsum dolor"
38
36
  }
39
37
  };
38
+ export const WithOutTitle = {
39
+ render: Docs.render,
40
+ args: {
41
+ title: "",
42
+ dismissBtn: false,
43
+ icon: false
44
+ }
45
+ };
40
46
  export const WithContent = {
41
47
  render: Docs.render,
42
48
  args: {
@@ -0,0 +1,6 @@
1
+ import AntContent from '../AntContent.vue';
2
+ import { type Meta, type StoryObj } from '@storybook/vue3';
3
+ declare const meta: Meta<typeof AntContent>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof AntContent>;
6
+ export declare const Docs: Story;
@@ -0,0 +1,26 @@
1
+ import AntContent from "../AntContent.vue";
2
+ const meta = {
3
+ title: "Components/Content",
4
+ component: AntContent,
5
+ parameters: { controls: { sort: "requiredFirst" } },
6
+ argTypes: {}
7
+ };
8
+ export default meta;
9
+ export const Docs = {
10
+ parameters: {
11
+ chromatic: { disableSnapshot: false }
12
+ },
13
+ render: (args) => ({
14
+ components: { AntContent },
15
+ setup() {
16
+ return { args };
17
+ },
18
+ template: `
19
+ <div class="outline outline-neutral-300">
20
+ <AntContent v-bind="args" class="h-40">
21
+ <div class="slot h-60">SLOT</div>
22
+ </AntContent>
23
+ </div>`
24
+ }),
25
+ args: {}
26
+ };
@@ -68,7 +68,16 @@ const itemsPerPage = computed({
68
68
  })()
69
69
  }
70
70
  })
71
- const fromItems = computed(() => (itemsPerPage.value * (page.value - 1)))
71
+ const fromItems = computed(() => (itemsPerPage.value * (page.value - 1)) + 1)
72
+ const toItems = computed(() => {
73
+ const items = itemsPerPage.value * page.value;
74
+
75
+ if (page.value === pages.value && items > props.count) {
76
+ return props.count;
77
+ }
78
+
79
+ return itemsPerPage.value * page.value;
80
+ })
72
81
  const pages = computed(() => Math.ceil(props.count / itemsPerPage.value))
73
82
  const _fullWidth = ref(props.fullWidth)
74
83
 
@@ -119,7 +128,7 @@ watch(() => props.fullWidth, (val) => {
119
128
  absolute
120
129
  />
121
130
 
122
- <span class="font-medium">{{ fromItems }} - {{ itemsPerPage * page }}</span>
131
+ <span class="font-medium">{{ fromItems }} - {{ toItems }}</span>
123
132
  <span>of</span>
124
133
  <span
125
134
  class="font-medium"
@@ -23,7 +23,7 @@ export const Docs = {
23
23
  `
24
24
  }),
25
25
  args: {
26
- count: 1e6
26
+ count: 1000015
27
27
  }
28
28
  };
29
29
  export const fullWidth = {
@@ -27,6 +27,7 @@ const props = withDefaults(defineProps<{
27
27
  max?: number;
28
28
  limiter?: boolean;
29
29
  errors?: string[];
30
+ indicators?: boolean;
30
31
  }>(), {
31
32
  colorType: InputColorType.base,
32
33
  disabled: false,
@@ -34,7 +35,8 @@ const props = withDefaults(defineProps<{
34
35
  size: Size.md,
35
36
  steps: 1,
36
37
  limiter: false,
37
- errors: []
38
+ errors: [],
39
+ indicators: false
38
40
  });
39
41
  const emit = defineEmits(['update:modelValue', 'validate']);
40
42
  const _modelValue = useVModel(props, 'modelValue', emit);
@@ -127,6 +129,7 @@ function onButtonBlur() {
127
129
  class="flex relative"
128
130
  >
129
131
  <AntButton
132
+ v-if="indicators"
130
133
  :icon-left="faMinus"
131
134
  :grouped="Grouped.left"
132
135
  :color-type="buttonColorType"
@@ -140,7 +143,7 @@ function onButtonBlur() {
140
143
  <AntBaseInput
141
144
  v-model:value.number="_modelValue"
142
145
  :type="BaseInputType.number"
143
- :grouped="Grouped.center"
146
+ :grouped="indicators ? Grouped.center : Grouped.none"
144
147
  wrapper-class="flex-grow"
145
148
  :color-type="colorType"
146
149
  :size="size"
@@ -156,6 +159,7 @@ function onButtonBlur() {
156
159
  />
157
160
 
158
161
  <AntButton
162
+ v-if="indicators"
159
163
  :icon-left="faPlus"
160
164
  :grouped="Grouped.right"
161
165
  :color-type="buttonColorType"
@@ -45,7 +45,6 @@ const props = withDefaults(
45
45
  grouped?: Grouped;
46
46
  name?: string;
47
47
  wrapperClass?: string | Record<string, boolean>;
48
- showMessageOnError?: boolean;
49
48
  expanded?: boolean;
50
49
  }>(), {
51
50
  colorType: InputColorType.base,
@@ -54,7 +53,6 @@ const props = withDefaults(
54
53
  disabled: false,
55
54
  skeleton: false,
56
55
  nullable: false,
57
- showMessageOnError: true,
58
56
  expanded: true
59
57
  }
60
58
  );
@@ -154,6 +152,8 @@ const skeletonGrouped = computed(() => {
154
152
  const inputRef = ref<HTMLElement | null>(null);
155
153
  const dropDownRef = ref<HTMLElement | null>(null);
156
154
  const focusedDropDownItem = ref<string | number | null>(null);
155
+ // TODO:: Hotfix to prevent missing required prop warning. Fix it with https://github.com/antify/ui-module/issues/52
156
+ const dropDownFocused = ref(null);
157
157
 
158
158
  onMounted(() => {
159
159
  handleEnumValidation(props.size, Size, 'size');
@@ -203,7 +203,6 @@ function onClickRemoveButton() {
203
203
  :color-type="colorType"
204
204
  :validator="validator"
205
205
  :class="wrapperClass"
206
- :show-message-on-error="showMessageOnError"
207
206
  :expanded="expanded"
208
207
  label-for="noop"
209
208
  data-e2e="select"
@@ -280,6 +279,7 @@ function onClickRemoveButton() {
280
279
  ref="dropDownRef"
281
280
  v-model="_modelValue"
282
281
  v-model:open="isOpen"
282
+ v-model:focused="dropDownFocused"
283
283
  :options="options"
284
284
  :input-ref="inputRef"
285
285
  :size="size"
@@ -31,7 +31,6 @@ const props = withDefaults(
31
31
  skeleton?: boolean;
32
32
  validator?: FieldValidator;
33
33
  name?: string;
34
- showMessageOnError?: boolean;
35
34
  expanded?: boolean;
36
35
  icon?: IconDefinition;
37
36
  grouped?: Grouped;
@@ -53,7 +52,6 @@ const props = withDefaults(
53
52
  allowDuplicates: false,
54
53
  openOnFocus: true,
55
54
  autoCloseAfterSelection: false,
56
- showMessageOnError: true,
57
55
 
58
56
  placeholder: 'Add new tag'
59
57
  }
@@ -233,12 +231,11 @@ function filterDropDown() {
233
231
  :description="description"
234
232
  :color-type="colorType"
235
233
  :validator="validator"
236
- :show-message-on-error="showMessageOnError"
237
234
  :expanded="expanded"
238
235
  >
239
236
  <div
240
- class="relative w-full"
241
237
  v-on-click-outside="onClickOutside"
238
+ class="relative w-full"
242
239
  >
243
240
  <AntSkeleton
244
241
  v-if="skeleton"
@@ -264,12 +261,15 @@ function filterDropDown() {
264
261
 
265
262
  <!-- Input -->
266
263
  <div class="flex items-center gap-1 w-32 shrink grow">
267
- <AntIcon :icon="icon" :size="size === Size.sm ? IconSize.xs : IconSize.sm"/>
264
+ <AntIcon
265
+ :icon="icon"
266
+ :size="size === Size.sm ? IconSize.xs : IconSize.sm"
267
+ />
268
268
 
269
269
  <input
270
+ ref="inputRef"
270
271
  v-model="tagInput"
271
272
  type="text"
272
- ref="inputRef"
273
273
  :placeholder="placeholder"
274
274
  :class="inputClasses"
275
275
  :disabled="disabled"
@@ -283,9 +283,9 @@ function filterDropDown() {
283
283
 
284
284
  <AntDropDown
285
285
  v-if="filteredOptions && !disabled"
286
+ ref="dropDownRef"
286
287
  v-model:focused="focusedDropDownItem"
287
288
  v-model:open="dropDownOpen"
288
- ref="dropDownRef"
289
289
  :model-value="null"
290
290
  :auto-select-first-on-open="!allowCreate"
291
291
  :options="filteredOptions"
@@ -17,14 +17,12 @@ const props = withDefaults(defineProps<{
17
17
  limiterValue?: number;
18
18
  limiterMaxValue?: number;
19
19
  labelFor?: string;
20
- showMessageOnError?: boolean;
21
20
  errors?: string[];
22
21
  expanded?: boolean;
23
22
  }>(), {
24
23
  colorType: InputColorType.base,
25
24
  skeleton: false,
26
25
  size: Size.md,
27
- showMessageOnError: true,
28
26
  errors: () => [],
29
27
  expanded: true
30
28
  });
@@ -35,34 +33,35 @@ onMounted(() => {
35
33
  });
36
34
 
37
35
  const _errors = computed(() => props.skeleton ? [] : props.errors);
38
- const _colorType = computed(() => _errors.value.length > 0 ? InputColorType.danger : props.colorType)
36
+ const _colorType = computed(() => _errors.value.length > 0 ? InputColorType.danger : props.colorType);
39
37
  </script>
40
38
 
41
39
  <template>
42
40
  <div
43
- class="flex flex-col items-start gap-1.5"
44
- :class="{'w-full': expanded}"
41
+ class="flex flex-col items-start gap-1.5"
42
+ :class="{'w-full': expanded}"
45
43
  >
46
44
  <AntInputLabel
47
- :label="label"
48
- :size="size"
49
- :skeleton="skeleton"
50
- :for="labelFor"
51
- @clickContent="$emit('clickLabel')"
45
+ :label="label"
46
+ :size="size"
47
+ :skeleton="skeleton"
48
+ :for="labelFor"
49
+ @click-content="$emit('clickLabel')"
52
50
  >
53
51
  <div class="w-full">
54
- <slot/>
52
+ <slot />
55
53
  </div>
56
54
  </AntInputLabel>
57
55
 
58
56
  <div
59
- v-if="showMessageOnError && (description || _errors.length > 0)"
60
- class="flex justify-between w-full"
57
+ v-if="description || _errors.length > 0 || (limiterMaxValue !== undefined && limiterValue !== undefined)"
58
+ class="flex justify-between w-full"
61
59
  >
62
60
  <AntInputDescription
63
- :size="size"
64
- :skeleton="skeleton"
65
- :color-type="_colorType"
61
+ v-if="description || _errors.length > 0"
62
+ :size="size"
63
+ :skeleton="skeleton"
64
+ :color-type="_colorType"
66
65
  >
67
66
  <slot name="description">
68
67
  <template v-if="_errors.length === 1">
@@ -87,16 +86,20 @@ const _colorType = computed(() => _errors.value.length > 0 ? InputColorType.dang
87
86
  </slot>
88
87
  </AntInputDescription>
89
88
 
90
- <AntInputLimiter
91
- v-if="limiterMaxValue !== undefined && limiterValue !== undefined"
89
+ <div
90
+ v-if="limiterMaxValue !== undefined && limiterValue !== undefined"
91
+ class="flex flex-grow justify-end"
92
+ >
93
+ <AntInputLimiter
92
94
  :value="limiterValue"
93
95
  :max-value="limiterMaxValue"
94
96
  :color-type="_colorType"
95
97
  :size="size"
96
98
  :skeleton="skeleton"
97
- >
98
- {{ limiterValue }}/{{ limiterMaxValue }}
99
- </AntInputLimiter>
99
+ >
100
+ {{ limiterValue }}/{{ limiterMaxValue }}
101
+ </AntInputLimiter>
102
+ </div>
100
103
  </div>
101
104
  </div>
102
105
  </template>
@@ -40,16 +40,16 @@ onMounted(() => {
40
40
 
41
41
  <template>
42
42
  <div
43
- :class="classes"
43
+ :class="classes"
44
44
  >
45
45
  <span :class="{'invisible': skeleton}">
46
- <slot/>
46
+ <slot />
47
47
  </span>
48
48
 
49
49
  <AntSkeleton
50
- v-if="skeleton"
51
- absolute
52
- rounded
50
+ v-if="skeleton"
51
+ absolute
52
+ rounded
53
53
  />
54
54
  </div>
55
55
  </template>
@@ -5,3 +5,4 @@ export default meta;
5
5
  type Story = StoryObj<typeof AntNumberInput>;
6
6
  export declare const Docs: Story;
7
7
  export declare const Limited: Story;
8
+ export declare const WithoutIndicators: Story;
@@ -65,3 +65,10 @@ export const Limited = {
65
65
  ])
66
66
  }
67
67
  };
68
+ export const WithoutIndicators = {
69
+ render: Docs.render,
70
+ args: {
71
+ ...Docs.args,
72
+ indicators: false
73
+ }
74
+ };
@@ -13,7 +13,7 @@ const hasLogoImageSlot = computed(() => useSlots()['logo-image'] || false);
13
13
  </script>
14
14
 
15
15
  <template>
16
- <div class="flex gap-px bg-neutral-300 h-screen overflow-hidden">
16
+ <div class="flex gap-px bg-neutral-300 h-screen min-w-full overflow-y-hidden">
17
17
  <div class="flex flex-col gap-px bg-neutral-300 w-52 shrink-0">
18
18
  <component
19
19
  :is="logoRoute ? 'RouterLink' : 'div'"
@@ -29,7 +29,7 @@ const hasLogoImageSlot = computed(() => useSlots()['logo-image'] || false);
29
29
  />
30
30
  </div>
31
31
 
32
- <div class="flex-grow">
32
+ <div class="w-px flex-grow">
33
33
  <slot />
34
34
  </div>
35
35
  </div>
@@ -25,7 +25,7 @@ export const Docs = {
25
25
  <img src="/logo.svg" class="h-full w-full"/>
26
26
  </template>
27
27
 
28
- <div class="slot m-2.5">SLOT</div>
28
+ <div class="slot m-2.5 h-full !text-white !border-white">SLOT</div>
29
29
  </AntNavLeftLayout>
30
30
  `
31
31
  }),
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@antify/ui-module",
3
3
  "private": false,
4
- "version": "1.5.1",
4
+ "version": "1.6.0",
5
5
  "license": "MIT",
6
6
  "type": "module",
7
7
  "exports": {
@@ -18,17 +18,19 @@ import {IconSize} from './__types';
18
18
  defineEmits(['close']);
19
19
 
20
20
  const props = withDefaults(defineProps<{
21
- title: string,
21
+ title?: string | null,
22
22
  colorType?: InputColorType,
23
23
  icon?: boolean,
24
24
  expanded?: boolean,
25
- questionMarkText?: string,
25
+ questionMarkText?: string | null,
26
26
  skeleton?: boolean,
27
27
  dismissBtn?: boolean,
28
28
  }>(), {
29
+ title: null,
29
30
  colorType: InputColorType.base,
30
31
  icon: true,
31
32
  expanded: false,
33
+ questionMarkText: null,
32
34
  skeleton: false,
33
35
  dismissBtn: true,
34
36
  });
@@ -81,9 +83,14 @@ onMounted(() => {
81
83
  :class="classes"
82
84
  data-e2e="alert"
83
85
  >
84
- <AntSkeleton v-if="skeleton" absolute rounded/>
86
+ <AntSkeleton
87
+ v-if="skeleton"
88
+ absolute
89
+ rounded
90
+ />
85
91
 
86
92
  <div
93
+ v-if="icon || hasQuestionMark || dismissBtn || title"
87
94
  class="inline-flex items-center justify-between w-content gap-2.5"
88
95
  :class="{'invisible': skeleton}"
89
96
  >
@@ -95,7 +102,9 @@ onMounted(() => {
95
102
  :size="IconSize.sm"
96
103
  />
97
104
 
98
- <div :class="{'font-semibold': hasDefaultSlot}">
105
+ <div
106
+ :class="{'font-semibold': hasDefaultSlot}"
107
+ >
99
108
  <slot name="title">
100
109
  {{ title }}
101
110
  </slot>
@@ -131,7 +140,7 @@ onMounted(() => {
131
140
  </div>
132
141
 
133
142
  <div v-if="hasDefaultSlot">
134
- <slot/>
143
+ <slot />
135
144
  </div>
136
145
  </div>
137
146
  </template>
@@ -0,0 +1,16 @@
1
+ <script setup lang="ts">
2
+ withDefaults(defineProps<{
3
+ padding?: boolean
4
+ }>(), {
5
+ padding: true
6
+ })
7
+ </script>
8
+
9
+ <template>
10
+ <div
11
+ :class="{ 'p-2.5': padding }"
12
+ class="bg-white overflow-auto"
13
+ >
14
+ <slot />
15
+ </div>
16
+ </template>
@@ -162,7 +162,11 @@ const pagination = computed(() => {
162
162
  class="inline-flex relative"
163
163
  data-e2e="pagination"
164
164
  >
165
- <AntSkeleton v-if="skeleton" rounded absolute/>
165
+ <AntSkeleton
166
+ v-if="skeleton"
167
+ rounded
168
+ absolute
169
+ />
166
170
 
167
171
  <div
168
172
  class="inline-flex gap-px"
@@ -177,14 +181,15 @@ const pagination = computed(() => {
177
181
  />
178
182
 
179
183
  <AntButton
180
- v-for="(pageObj, index) in pagination"
184
+ v-for="(pageObj) in pagination"
185
+ :key="`pagination-button-${pageObj}`"
181
186
  :color-type="pageObj === page ? ColorType.primary : ColorType.base"
182
187
  :class="{'text-primary-500 z-10': pageObj === page}"
183
188
  :disabled="pageObj === '...'"
184
189
  :grouped="Grouped.center"
185
190
  :filled="pageObj !== page"
191
+ :readonly="pageObj === page"
186
192
  @click="() => page = pageObj"
187
- v-bind:key="`pagination-button-${index}`"
188
193
  >
189
194
  {{ pageObj }}
190
195
  </AntButton>
@@ -68,7 +68,16 @@ const itemsPerPage = computed({
68
68
  })()
69
69
  }
70
70
  })
71
- const fromItems = computed(() => (itemsPerPage.value * (page.value - 1)))
71
+ const fromItems = computed(() => (itemsPerPage.value * (page.value - 1)) + 1)
72
+ const toItems = computed(() => {
73
+ const items = itemsPerPage.value * page.value;
74
+
75
+ if (page.value === pages.value && items > props.count) {
76
+ return props.count;
77
+ }
78
+
79
+ return itemsPerPage.value * page.value;
80
+ })
72
81
  const pages = computed(() => Math.ceil(props.count / itemsPerPage.value))
73
82
  const _fullWidth = ref(props.fullWidth)
74
83
 
@@ -119,7 +128,7 @@ watch(() => props.fullWidth, (val) => {
119
128
  absolute
120
129
  />
121
130
 
122
- <span class="font-medium">{{ fromItems }} - {{ itemsPerPage * page }}</span>
131
+ <span class="font-medium">{{ fromItems }} - {{ toItems }}</span>
123
132
  <span>of</span>
124
133
  <span
125
134
  class="font-medium"
@@ -27,6 +27,7 @@ const props = withDefaults(defineProps<{
27
27
  max?: number;
28
28
  limiter?: boolean;
29
29
  errors?: string[];
30
+ indicators?: boolean;
30
31
  }>(), {
31
32
  colorType: InputColorType.base,
32
33
  disabled: false,
@@ -34,7 +35,8 @@ const props = withDefaults(defineProps<{
34
35
  size: Size.md,
35
36
  steps: 1,
36
37
  limiter: false,
37
- errors: []
38
+ errors: [],
39
+ indicators: false
38
40
  });
39
41
  const emit = defineEmits(['update:modelValue', 'validate']);
40
42
  const _modelValue = useVModel(props, 'modelValue', emit);
@@ -127,6 +129,7 @@ function onButtonBlur() {
127
129
  class="flex relative"
128
130
  >
129
131
  <AntButton
132
+ v-if="indicators"
130
133
  :icon-left="faMinus"
131
134
  :grouped="Grouped.left"
132
135
  :color-type="buttonColorType"
@@ -140,7 +143,7 @@ function onButtonBlur() {
140
143
  <AntBaseInput
141
144
  v-model:value.number="_modelValue"
142
145
  :type="BaseInputType.number"
143
- :grouped="Grouped.center"
146
+ :grouped="indicators ? Grouped.center : Grouped.none"
144
147
  wrapper-class="flex-grow"
145
148
  :color-type="colorType"
146
149
  :size="size"
@@ -156,6 +159,7 @@ function onButtonBlur() {
156
159
  />
157
160
 
158
161
  <AntButton
162
+ v-if="indicators"
159
163
  :icon-left="faPlus"
160
164
  :grouped="Grouped.right"
161
165
  :color-type="buttonColorType"
@@ -45,7 +45,6 @@ const props = withDefaults(
45
45
  grouped?: Grouped;
46
46
  name?: string;
47
47
  wrapperClass?: string | Record<string, boolean>;
48
- showMessageOnError?: boolean;
49
48
  expanded?: boolean;
50
49
  }>(), {
51
50
  colorType: InputColorType.base,
@@ -54,7 +53,6 @@ const props = withDefaults(
54
53
  disabled: false,
55
54
  skeleton: false,
56
55
  nullable: false,
57
- showMessageOnError: true,
58
56
  expanded: true
59
57
  }
60
58
  );
@@ -154,6 +152,8 @@ const skeletonGrouped = computed(() => {
154
152
  const inputRef = ref<HTMLElement | null>(null);
155
153
  const dropDownRef = ref<HTMLElement | null>(null);
156
154
  const focusedDropDownItem = ref<string | number | null>(null);
155
+ // TODO:: Hotfix to prevent missing required prop warning. Fix it with https://github.com/antify/ui-module/issues/52
156
+ const dropDownFocused = ref(null);
157
157
 
158
158
  onMounted(() => {
159
159
  handleEnumValidation(props.size, Size, 'size');
@@ -203,7 +203,6 @@ function onClickRemoveButton() {
203
203
  :color-type="colorType"
204
204
  :validator="validator"
205
205
  :class="wrapperClass"
206
- :show-message-on-error="showMessageOnError"
207
206
  :expanded="expanded"
208
207
  label-for="noop"
209
208
  data-e2e="select"
@@ -280,6 +279,7 @@ function onClickRemoveButton() {
280
279
  ref="dropDownRef"
281
280
  v-model="_modelValue"
282
281
  v-model:open="isOpen"
282
+ v-model:focused="dropDownFocused"
283
283
  :options="options"
284
284
  :input-ref="inputRef"
285
285
  :size="size"
@@ -31,7 +31,6 @@ const props = withDefaults(
31
31
  skeleton?: boolean;
32
32
  validator?: FieldValidator;
33
33
  name?: string;
34
- showMessageOnError?: boolean;
35
34
  expanded?: boolean;
36
35
  icon?: IconDefinition;
37
36
  grouped?: Grouped;
@@ -53,7 +52,6 @@ const props = withDefaults(
53
52
  allowDuplicates: false,
54
53
  openOnFocus: true,
55
54
  autoCloseAfterSelection: false,
56
- showMessageOnError: true,
57
55
 
58
56
  placeholder: 'Add new tag'
59
57
  }
@@ -233,12 +231,11 @@ function filterDropDown() {
233
231
  :description="description"
234
232
  :color-type="colorType"
235
233
  :validator="validator"
236
- :show-message-on-error="showMessageOnError"
237
234
  :expanded="expanded"
238
235
  >
239
236
  <div
240
- class="relative w-full"
241
237
  v-on-click-outside="onClickOutside"
238
+ class="relative w-full"
242
239
  >
243
240
  <AntSkeleton
244
241
  v-if="skeleton"
@@ -264,12 +261,15 @@ function filterDropDown() {
264
261
 
265
262
  <!-- Input -->
266
263
  <div class="flex items-center gap-1 w-32 shrink grow">
267
- <AntIcon :icon="icon" :size="size === Size.sm ? IconSize.xs : IconSize.sm"/>
264
+ <AntIcon
265
+ :icon="icon"
266
+ :size="size === Size.sm ? IconSize.xs : IconSize.sm"
267
+ />
268
268
 
269
269
  <input
270
+ ref="inputRef"
270
271
  v-model="tagInput"
271
272
  type="text"
272
- ref="inputRef"
273
273
  :placeholder="placeholder"
274
274
  :class="inputClasses"
275
275
  :disabled="disabled"
@@ -283,9 +283,9 @@ function filterDropDown() {
283
283
 
284
284
  <AntDropDown
285
285
  v-if="filteredOptions && !disabled"
286
+ ref="dropDownRef"
286
287
  v-model:focused="focusedDropDownItem"
287
288
  v-model:open="dropDownOpen"
288
- ref="dropDownRef"
289
289
  :model-value="null"
290
290
  :auto-select-first-on-open="!allowCreate"
291
291
  :options="filteredOptions"
@@ -17,14 +17,12 @@ const props = withDefaults(defineProps<{
17
17
  limiterValue?: number;
18
18
  limiterMaxValue?: number;
19
19
  labelFor?: string;
20
- showMessageOnError?: boolean;
21
20
  errors?: string[];
22
21
  expanded?: boolean;
23
22
  }>(), {
24
23
  colorType: InputColorType.base,
25
24
  skeleton: false,
26
25
  size: Size.md,
27
- showMessageOnError: true,
28
26
  errors: () => [],
29
27
  expanded: true
30
28
  });
@@ -35,34 +33,35 @@ onMounted(() => {
35
33
  });
36
34
 
37
35
  const _errors = computed(() => props.skeleton ? [] : props.errors);
38
- const _colorType = computed(() => _errors.value.length > 0 ? InputColorType.danger : props.colorType)
36
+ const _colorType = computed(() => _errors.value.length > 0 ? InputColorType.danger : props.colorType);
39
37
  </script>
40
38
 
41
39
  <template>
42
40
  <div
43
- class="flex flex-col items-start gap-1.5"
44
- :class="{'w-full': expanded}"
41
+ class="flex flex-col items-start gap-1.5"
42
+ :class="{'w-full': expanded}"
45
43
  >
46
44
  <AntInputLabel
47
- :label="label"
48
- :size="size"
49
- :skeleton="skeleton"
50
- :for="labelFor"
51
- @clickContent="$emit('clickLabel')"
45
+ :label="label"
46
+ :size="size"
47
+ :skeleton="skeleton"
48
+ :for="labelFor"
49
+ @click-content="$emit('clickLabel')"
52
50
  >
53
51
  <div class="w-full">
54
- <slot/>
52
+ <slot />
55
53
  </div>
56
54
  </AntInputLabel>
57
55
 
58
56
  <div
59
- v-if="showMessageOnError && (description || _errors.length > 0)"
60
- class="flex justify-between w-full"
57
+ v-if="description || _errors.length > 0 || (limiterMaxValue !== undefined && limiterValue !== undefined)"
58
+ class="flex justify-between w-full"
61
59
  >
62
60
  <AntInputDescription
63
- :size="size"
64
- :skeleton="skeleton"
65
- :color-type="_colorType"
61
+ v-if="description || _errors.length > 0"
62
+ :size="size"
63
+ :skeleton="skeleton"
64
+ :color-type="_colorType"
66
65
  >
67
66
  <slot name="description">
68
67
  <template v-if="_errors.length === 1">
@@ -87,16 +86,20 @@ const _colorType = computed(() => _errors.value.length > 0 ? InputColorType.dang
87
86
  </slot>
88
87
  </AntInputDescription>
89
88
 
90
- <AntInputLimiter
91
- v-if="limiterMaxValue !== undefined && limiterValue !== undefined"
89
+ <div
90
+ v-if="limiterMaxValue !== undefined && limiterValue !== undefined"
91
+ class="flex flex-grow justify-end"
92
+ >
93
+ <AntInputLimiter
92
94
  :value="limiterValue"
93
95
  :max-value="limiterMaxValue"
94
96
  :color-type="_colorType"
95
97
  :size="size"
96
98
  :skeleton="skeleton"
97
- >
98
- {{ limiterValue }}/{{ limiterMaxValue }}
99
- </AntInputLimiter>
99
+ >
100
+ {{ limiterValue }}/{{ limiterMaxValue }}
101
+ </AntInputLimiter>
102
+ </div>
100
103
  </div>
101
104
  </div>
102
105
  </template>
@@ -40,16 +40,16 @@ onMounted(() => {
40
40
 
41
41
  <template>
42
42
  <div
43
- :class="classes"
43
+ :class="classes"
44
44
  >
45
45
  <span :class="{'invisible': skeleton}">
46
- <slot/>
46
+ <slot />
47
47
  </span>
48
48
 
49
49
  <AntSkeleton
50
- v-if="skeleton"
51
- absolute
52
- rounded
50
+ v-if="skeleton"
51
+ absolute
52
+ rounded
53
53
  />
54
54
  </div>
55
55
  </template>
@@ -13,7 +13,7 @@ const hasLogoImageSlot = computed(() => useSlots()['logo-image'] || false);
13
13
  </script>
14
14
 
15
15
  <template>
16
- <div class="flex gap-px bg-neutral-300 h-screen overflow-hidden">
16
+ <div class="flex gap-px bg-neutral-300 h-screen min-w-full overflow-y-hidden">
17
17
  <div class="flex flex-col gap-px bg-neutral-300 w-52 shrink-0">
18
18
  <component
19
19
  :is="logoRoute ? 'RouterLink' : 'div'"
@@ -29,7 +29,7 @@ const hasLogoImageSlot = computed(() => useSlots()['logo-image'] || false);
29
29
  />
30
30
  </div>
31
31
 
32
- <div class="flex-grow">
32
+ <div class="w-px flex-grow">
33
33
  <slot />
34
34
  </div>
35
35
  </div>