vueless 0.0.14 → 0.0.16

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 (40) hide show
  1. package/package.json +1 -1
  2. package/ui.button/index.vue +16 -3
  3. package/ui.button-link/index.vue +6 -3
  4. package/ui.container-page/configs/default.config.js +1 -1
  5. package/ui.data-table/index.vue +1 -1
  6. package/ui.data-table-cell/configs/default.config.js +2 -2
  7. package/ui.dropdown-badge/index.vue +11 -1
  8. package/ui.dropdown-button/index.vue +14 -2
  9. package/ui.dropdown-link/index.vue +11 -1
  10. package/ui.form-calendar/configs/default.config.js +1 -1
  11. package/ui.form-checkbox/index.vue +1 -1
  12. package/ui.form-color-picker/index.vue +1 -1
  13. package/ui.form-date-picker-range/configs/default.config.js +4 -4
  14. package/ui.form-input/configs/default.config.js +1 -1
  15. package/ui.form-input/index.vue +5 -8
  16. package/ui.form-input-file/configs/default.config.js +1 -1
  17. package/ui.form-input-file/index.vue +4 -8
  18. package/ui.form-input-rating/configs/default.config.js +1 -1
  19. package/ui.form-input-rating/index.vue +3 -7
  20. package/ui.form-label/configs/default.config.js +2 -0
  21. package/ui.form-label/index.vue +3 -3
  22. package/ui.form-radio/index.vue +5 -3
  23. package/ui.form-radio-card/composables/attrs.composable.js +3 -1
  24. package/ui.form-radio-card/configs/default.config.js +8 -2
  25. package/ui.form-radio-card/index.vue +26 -40
  26. package/ui.form-select/configs/default.config.js +3 -3
  27. package/ui.form-select/index.vue +7 -18
  28. package/ui.form-switch/index.vue +1 -1
  29. package/ui.form-textarea/index.vue +2 -2
  30. package/ui.notify/index.vue +3 -3
  31. package/ui.other-loader-top/composables/attrs.composable.js +32 -0
  32. package/ui.other-loader-top/configs/default.config.js +20 -0
  33. package/ui.other-loader-top/constants/index.js +8 -0
  34. package/ui.other-loader-top/index.vue +230 -0
  35. package/ui.other-loader-top/services/loaderTop.service.js +31 -0
  36. package/ui.text-badge/index.vue +7 -0
  37. package/web-types.json +36 -132
  38. package/ui.loader-top/components/TopProgress.vue +0 -277
  39. package/ui.loader-top/index.vue +0 -221
  40. /package/{ui.loader-top → ui.other-loader-top}/store/index.js +0 -0
@@ -4,8 +4,8 @@
4
4
  :for="id"
5
5
  :size="size"
6
6
  :label="label"
7
- :error="errorMessage"
8
- :description="descriptionMessage"
7
+ :error="error"
8
+ :description="description"
9
9
  :align="labelAlign"
10
10
  :disabled="disabled"
11
11
  :data-cy="dataCy"
@@ -244,11 +244,12 @@ const props = defineProps({
244
244
  },
245
245
 
246
246
  /**
247
- * Show label outside the select block.
247
+ * Set label placement related from the default slot.
248
+ * @values top, topInside, topWithDesc, bottom, left, right
248
249
  */
249
- labelOutside: {
250
- type: Boolean,
251
- default: UIService.get(defaultConfig, USelect).default.labelOutside,
250
+ labelAlign: {
251
+ type: String,
252
+ default: UIService.get(defaultConfig, USelect).default.labelAlign,
252
253
  },
253
254
 
254
255
  /**
@@ -506,10 +507,6 @@ const isSelectedValueLabelVisible = computed(() => {
506
507
  return !props.multiple && isLocalValue.value && (!isOpen.value || !props.searchable);
507
508
  });
508
509
 
509
- const labelAlign = computed(() => {
510
- return props.labelOutside ? "top" : "topInside";
511
- });
512
-
513
510
  const filteredOptions = computed(() => {
514
511
  const normalizedSearch = search.value.toLowerCase().trim();
515
512
 
@@ -561,14 +558,6 @@ const isLocalValue = computed(() => {
561
558
  : Boolean(String(localValue.value));
562
559
  });
563
560
 
564
- const errorMessage = computed(() => {
565
- return !isOpen.value && props.error ? props.error : "";
566
- });
567
-
568
- const descriptionMessage = computed(() => {
569
- return !isOpen.value && props.description ? props.description : "";
570
- });
571
-
572
561
  watch(search, () => onSearchChange);
573
562
  watch(
574
563
  localValue,
@@ -61,7 +61,7 @@ const props = defineProps({
61
61
 
62
62
  /**
63
63
  * Label alignment.
64
- * @values left, right
64
+ * @values top, topInside, topWithDesc, bottom, left, right
65
65
  */
66
66
  labelAlign: {
67
67
  type: String,
@@ -99,8 +99,8 @@ const props = defineProps({
99
99
  },
100
100
 
101
101
  /**
102
- * Input label place (above the input box or inside of it).
103
- * @values topInside, top
102
+ * Set label placement related from the default slot.
103
+ * @values top, topInside, topWithDesc, bottom, left, right
104
104
  */
105
105
  labelAlign: {
106
106
  type: String,
@@ -1,7 +1,7 @@
1
1
  <template>
2
2
  <notifications
3
3
  group="notify"
4
- class="vueless-notify !top-3 mt-safe-top !w-full px-3 max-md:!left-0 md:!w-[22rem] md:px-0 lg:!top-4 lg:!mt-0"
4
+ class="vueless-notify mt-safe-top !top-3 !w-full px-3 max-md:!left-0 md:!w-[22rem] md:px-0 lg:!top-4 lg:!mt-0"
5
5
  :position="position"
6
6
  >
7
7
  <template #body="{ item, close: onClickClose }">
@@ -145,8 +145,8 @@ export default {
145
145
 
146
146
  const NOTIFY_CLASS = "vueless-notify";
147
147
  const classes = globalComponentConfig.UNotify?.positionClasses;
148
- const pageWidth = getOffsetWidth(classes.page);
149
- const asideWidth = getOffsetWidth(classes.aside);
148
+ const pageWidth = getOffsetWidth(classes.page || "UNotifyPage");
149
+ const asideWidth = getOffsetWidth(classes.aside || "UNotifyAside");
150
150
  const notifyWidth = getOffsetWidth(NOTIFY_CLASS);
151
151
 
152
152
  if (!pageWidth) return;
@@ -0,0 +1,32 @@
1
+ import useUI from "vueless/composable.ui";
2
+ import { cva } from "vueless/service.ui";
3
+
4
+ import defaultConfig from "../configs/default.config";
5
+ import { computed } from "vue";
6
+
7
+ export function useAttrs(props) {
8
+ const { config, getAttrs, setColor } = useUI(defaultConfig, () => props.config);
9
+ const { progress } = config.value;
10
+
11
+ const cvaProgress = cva({
12
+ base: progress.base,
13
+ variants: progress.variants,
14
+ compoundVariants: progress.compoundVariants,
15
+ });
16
+
17
+ const progressClasses = computed(() =>
18
+ setColor(
19
+ cvaProgress({
20
+ position: props.position,
21
+ color: props.color,
22
+ }),
23
+ props.color,
24
+ ),
25
+ );
26
+
27
+ const progressAttrs = getAttrs("progress", { classes: progressClasses.value });
28
+
29
+ return {
30
+ progressAttrs,
31
+ };
32
+ }
@@ -0,0 +1,20 @@
1
+ export default /*tw*/ {
2
+ progress: {
3
+ base: "top-0 left-0 right-0 fixed h-[3px] transition-all ease-linear bg-{color}-500",
4
+ variants: {
5
+ position: {
6
+ fixed: "fixed",
7
+ absolute: "absolute",
8
+ },
9
+ error: {
10
+ true: "bg-red-500",
11
+ },
12
+ },
13
+ },
14
+ progressMobile: "mt-safe-top mx-3 rounded max-w-[calc(100%-1.5rem)]",
15
+ defaultVariants: {
16
+ color: "blue",
17
+ position: "fixed",
18
+ },
19
+ safelist: (colors) => [{ pattern: `bg-(${colors})-500` }],
20
+ };
@@ -0,0 +1,8 @@
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 ULoaderTop = "ULoaderTop";
6
+
7
+ export const MAXIMUM = 97.5;
8
+ export const SPEED = 150;
@@ -0,0 +1,230 @@
1
+ <template>
2
+ <Transition :css="false" @beforeEnter="beforeEnter" @enter="enter" @afterEnter="afterEnter">
3
+ <div v-if="show" v-bind="progressAttrs" :style="barStyle" />
4
+ </Transition>
5
+ </template>
6
+
7
+ <script setup>
8
+ import { computed, onBeforeUnmount, watch, ref } from "vue";
9
+
10
+ import { useStore } from "vuex";
11
+
12
+ import UIService, { isMobileApp } from "../service.ui";
13
+ import { clamp, queue } from "./services/loaderTop.service";
14
+
15
+ import { ULoaderTop, MAXIMUM, SPEED } from "./constants";
16
+ import defaultConfig from "./configs/default.config";
17
+ import { useAttrs } from "./composables/attrs.composable";
18
+
19
+ defineOptions({ name: "ULoaderTop" });
20
+
21
+ const props = defineProps({
22
+ /**
23
+ * The name of API resource (endpoint URI).
24
+ */
25
+ resourceNames: {
26
+ type: [String, Array],
27
+ default: "",
28
+ },
29
+
30
+ /**
31
+ * Loader position.
32
+ * @values fixed, absolute, relative
33
+ */
34
+ position: {
35
+ type: String,
36
+ default: UIService.get(defaultConfig, ULoaderTop).default.position,
37
+ },
38
+
39
+ /**
40
+ * The color of the loader stripe.
41
+ * @values gray, red, orange, yellow, green, blue, violet, fuchsia
42
+ */
43
+ color: {
44
+ type: String,
45
+ default: UIService.get(defaultConfig, ULoaderTop).default.color,
46
+ },
47
+ });
48
+
49
+ const store = useStore();
50
+
51
+ const error = ref(false);
52
+ const show = ref(false);
53
+ const progress = ref(0);
54
+ const opacity = ref(1);
55
+ const status = ref(null);
56
+
57
+ const { progressAttrs } = useAttrs(props, { error, isMobileApp });
58
+
59
+ const loaderRequestQueue = computed(() => store.state.loaderTop.loaderRequestQueue);
60
+ const isLoading = computed(() => store.state.loaderTop.isLoading);
61
+ const componentLoaderRequestQueue = computed(
62
+ () => store.state.loaderTop.componentLoaderRequestQueue,
63
+ );
64
+
65
+ const isStarted = computed(() => {
66
+ return typeof status.value === "number";
67
+ });
68
+
69
+ const barStyle = computed(() => {
70
+ return {
71
+ width: `${progress.value}%`,
72
+ opacity: `${opacity.value}`,
73
+ };
74
+ });
75
+
76
+ const resourceNamesArray = computed(() => {
77
+ return Array.isArray(props.resourceNames) ? [...props.resourceNames] : [props.resourceNames];
78
+ });
79
+
80
+ watch(loaderRequestQueue, onChangeRequestsQueue, { deep: true });
81
+ watch(isLoading, onChangeLoadingState, { deep: true });
82
+
83
+ if (props.resourceNames) {
84
+ store.commit("loaderTop/SET_COMPONENT_REQUEST_QUEUE", resourceNamesArray.value);
85
+ }
86
+
87
+ onBeforeUnmount(() => {
88
+ if (props.resourceNames) {
89
+ store.commit("loaderTop/REMOVE_COMPONENT_REQUEST_QUEUE");
90
+ }
91
+ });
92
+
93
+ function requestWithoutQuery(request) {
94
+ const [requestWithoutQuery] = request.split("?");
95
+
96
+ return requestWithoutQuery;
97
+ }
98
+
99
+ function onChangeLoadingState() {
100
+ if (!props.resourceNames && isStarted.value && show.value && !isLoading.value) {
101
+ done();
102
+ }
103
+ }
104
+
105
+ function onChangeRequestsQueue() {
106
+ let isActiveRequests = false;
107
+
108
+ if (props.resourceNames) {
109
+ resourceNamesArray.value.forEach((item) => {
110
+ if (!isActiveRequests) {
111
+ const activeRequest = loaderRequestQueue.value.find(
112
+ (request) => requestWithoutQuery(request) === item,
113
+ );
114
+
115
+ isActiveRequests = !!activeRequest;
116
+ }
117
+ });
118
+
119
+ if (isActiveRequests && !isStarted.value) {
120
+ start();
121
+ } else if (!isActiveRequests && isStarted.value && show.value) {
122
+ done();
123
+ }
124
+ } else {
125
+ loaderRequestQueue.value.forEach((item) => {
126
+ const activeRequest = componentLoaderRequestQueue.value.find(
127
+ (request) => request === requestWithoutQuery(item),
128
+ );
129
+
130
+ isActiveRequests = !activeRequest;
131
+ });
132
+
133
+ if (isLoading.value && isActiveRequests && !isStarted.value) {
134
+ start();
135
+ }
136
+ }
137
+ }
138
+
139
+ function beforeEnter() {
140
+ opacity.value = 0;
141
+ progress.value = 0;
142
+ }
143
+
144
+ function enter(el, done) {
145
+ opacity.value = 1;
146
+ done();
147
+ }
148
+
149
+ function afterEnter() {
150
+ runStart();
151
+ }
152
+
153
+ function work() {
154
+ setTimeout(() => {
155
+ if (!isStarted.value) {
156
+ return;
157
+ }
158
+
159
+ increase();
160
+ work();
161
+ }, 100);
162
+ }
163
+
164
+ function runStart() {
165
+ status.value = progress.value === 100 ? null : progress.value;
166
+
167
+ work();
168
+ }
169
+
170
+ function start() {
171
+ if (show.value) {
172
+ runStart();
173
+ } else {
174
+ show.value = true;
175
+ }
176
+ }
177
+
178
+ function set(amount) {
179
+ let currentProgress;
180
+
181
+ if (isStarted.value) {
182
+ currentProgress = amount < progress.value ? clamp(amount, 0, 100) : clamp(amount, 0.8, 100);
183
+ } else {
184
+ currentProgress = 0;
185
+ }
186
+
187
+ status.value = currentProgress === 100 ? null : currentProgress;
188
+
189
+ queue((next) => {
190
+ progress.value = currentProgress;
191
+
192
+ if (currentProgress === 100) {
193
+ setTimeout(() => {
194
+ opacity.value = 0;
195
+ setTimeout(() => {
196
+ show.value = false;
197
+ error.value = false;
198
+ next();
199
+ }, SPEED);
200
+ }, SPEED);
201
+ } else {
202
+ setTimeout(next, SPEED);
203
+ }
204
+ });
205
+ }
206
+
207
+ function increase(amount) {
208
+ const currentProgress = progress.value;
209
+
210
+ if (currentProgress < 100 && typeof amount !== "number") {
211
+ if (currentProgress >= 0 && currentProgress < 25) {
212
+ amount = Math.random() * 3 + 3;
213
+ } else if (currentProgress >= 25 && currentProgress < 50) {
214
+ amount = Math.random() * 3;
215
+ } else if (currentProgress >= 50 && currentProgress < 85) {
216
+ amount = Math.random() * 2;
217
+ } else if (currentProgress >= 85 && currentProgress < 99) {
218
+ amount = 0.5;
219
+ } else {
220
+ amount = 0;
221
+ }
222
+ }
223
+
224
+ set(clamp(currentProgress + amount, 0, MAXIMUM));
225
+ }
226
+
227
+ function done() {
228
+ set(100);
229
+ }
230
+ </script>
@@ -0,0 +1,31 @@
1
+ export function clamp(n, min, max) {
2
+ if (n < min) {
3
+ return min;
4
+ }
5
+
6
+ if (n > max) {
7
+ return max;
8
+ }
9
+
10
+ return n;
11
+ }
12
+
13
+ export const queue = (() => {
14
+ let pending = [];
15
+
16
+ function next() {
17
+ let fn = pending.shift();
18
+
19
+ if (fn) {
20
+ fn(next);
21
+ }
22
+ }
23
+
24
+ return (fn) => {
25
+ pending.push(fn);
26
+
27
+ if (pending.length === 1) {
28
+ next();
29
+ }
30
+ };
31
+ })();
@@ -1,5 +1,6 @@
1
1
  <template>
2
2
  <div
3
+ ref="wrapperRef"
3
4
  tabindex="1"
4
5
  :data-cy="dataCy"
5
6
  v-bind="wrapperAttrs"
@@ -26,6 +27,8 @@
26
27
  </template>
27
28
 
28
29
  <script setup>
30
+ import { ref } from "vue";
31
+
29
32
  import UIService from "../service.ui";
30
33
 
31
34
  import { UBadge } from "./constants";
@@ -102,6 +105,10 @@ const emit = defineEmits(["focus", "keydown", "blur", "click"]);
102
105
 
103
106
  const { bodyAttrs, wrapperAttrs, hasSlotContent } = useAttrs(props);
104
107
 
108
+ const wrapperRef = ref(null);
109
+
110
+ defineExpose({ wrapperRef });
111
+
105
112
  function onFocus() {
106
113
  emit("focus");
107
114
  }