v-uixy 1.5.0 → 1.7.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.
- package/package.json +1 -1
- package/templates/components/Alert/Alert.component.vue +53 -11
- package/templates/components/Alert/Alert.types.ts +2 -0
- package/templates/components/Alert/AlertItem.component.vue +21 -2
- package/templates/components/Button/Button.styles.ts +4 -4
- package/templates/components/Checkbox/Checkbox.component.vue +19 -5
- package/templates/components/Checkbox/Checkbox.styles.ts +10 -0
- package/templates/components/Checkbox/Checkbox.types.ts +1 -0
- package/templates/components/DatePicker/DatePicker.component.vue +23 -3
- package/templates/components/DatePicker/DatePicker.types.ts +0 -1
- package/templates/components/DateRangePicker/DateRangePicker.component.vue +29 -4
- package/templates/components/DateRangePicker/DateRangePicker.types.ts +0 -1
- package/templates/components/FileUpload/FileUpload.component.vue +23 -13
- package/templates/components/Input/Input.component.vue +23 -13
- package/templates/components/Input/Input.types.ts +0 -1
- package/templates/components/Popover/Popover.component.vue +1 -1
- package/templates/components/Select/Select.component.vue +23 -14
- package/templates/components/Select/Select.types.ts +0 -1
- package/templates/components/Table/Table.component.vue +507 -0
- package/templates/components/Table/Table.styles.ts +140 -0
- package/templates/components/Table/Table.types.ts +98 -0
- package/templates/components/Table/index.ts +39 -0
- package/templates/components/Textarea/Textarea.component.vue +20 -14
- package/templates/components/Textarea/Textarea.types.ts +0 -1
- package/templates/components.json +6 -0
- package/templates/composables/usePosition.ts +6 -4
package/package.json
CHANGED
|
@@ -22,6 +22,8 @@
|
|
|
22
22
|
v-bind="alert"
|
|
23
23
|
:key="alert.id"
|
|
24
24
|
@close-alert="close(alert.id)"
|
|
25
|
+
@pause-timer="pauseTimer(alert.id)"
|
|
26
|
+
@resume-timer="resumeTimer(alert.id)"
|
|
25
27
|
/>
|
|
26
28
|
</motion.li>
|
|
27
29
|
</animate-presence>
|
|
@@ -41,9 +43,25 @@
|
|
|
41
43
|
|
|
42
44
|
const alerts = ref<UixyAlertItemProps[]>([]);
|
|
43
45
|
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
|
|
46
|
+
const ALERT_DURATION = 8000;
|
|
47
|
+
|
|
48
|
+
interface AlertTimeout {
|
|
49
|
+
id: string;
|
|
50
|
+
timeout: ReturnType<typeof setTimeout> | null;
|
|
51
|
+
remaining: number;
|
|
52
|
+
startedAt: number;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const timeouts = reactive<AlertTimeout[]>([]);
|
|
56
|
+
|
|
57
|
+
const startTimeout = (entry: AlertTimeout) => {
|
|
58
|
+
entry.startedAt = Date.now();
|
|
59
|
+
entry.timeout = setTimeout(() => {
|
|
60
|
+
alerts.value = alerts.value.filter((a) => a.id !== entry.id);
|
|
61
|
+
const index = timeouts.findIndex((t) => t.id === entry.id);
|
|
62
|
+
if (index !== -1) timeouts.splice(index, 1);
|
|
63
|
+
}, entry.remaining);
|
|
64
|
+
};
|
|
47
65
|
|
|
48
66
|
const push = (alert: Omit<UixyAlertItemProps, "id">) => {
|
|
49
67
|
const id = uuidv4();
|
|
@@ -56,20 +74,25 @@
|
|
|
56
74
|
},
|
|
57
75
|
];
|
|
58
76
|
|
|
59
|
-
|
|
77
|
+
const entry: AlertTimeout = {
|
|
60
78
|
id,
|
|
61
|
-
timeout:
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
}
|
|
79
|
+
timeout: null,
|
|
80
|
+
remaining: ALERT_DURATION,
|
|
81
|
+
startedAt: Date.now(),
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
timeouts.push(entry);
|
|
85
|
+
startTimeout(entry);
|
|
65
86
|
};
|
|
66
87
|
|
|
67
88
|
const close = (id: string) => {
|
|
68
89
|
alerts.value = alerts.value.filter((alert) => {
|
|
69
90
|
if (alert.id === id) {
|
|
70
|
-
const
|
|
71
|
-
if (
|
|
72
|
-
|
|
91
|
+
const index = timeouts.findIndex((t) => t.id === id);
|
|
92
|
+
if (index !== -1) {
|
|
93
|
+
const timeout = timeouts[index];
|
|
94
|
+
if (timeout.timeout) clearTimeout(timeout.timeout);
|
|
95
|
+
timeouts.splice(index, 1);
|
|
73
96
|
}
|
|
74
97
|
return false;
|
|
75
98
|
}
|
|
@@ -77,6 +100,25 @@
|
|
|
77
100
|
});
|
|
78
101
|
};
|
|
79
102
|
|
|
103
|
+
const pauseTimer = (id: string) => {
|
|
104
|
+
const entry = timeouts.find((t) => t.id === id);
|
|
105
|
+
if (!entry || !entry.timeout) return;
|
|
106
|
+
|
|
107
|
+
clearTimeout(entry.timeout);
|
|
108
|
+
entry.timeout = null;
|
|
109
|
+
entry.remaining = Math.max(
|
|
110
|
+
entry.remaining - (Date.now() - entry.startedAt),
|
|
111
|
+
0,
|
|
112
|
+
);
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
const resumeTimer = (id: string) => {
|
|
116
|
+
const entry = timeouts.find((t) => t.id === id);
|
|
117
|
+
if (!entry || entry.timeout) return;
|
|
118
|
+
|
|
119
|
+
startTimeout(entry);
|
|
120
|
+
};
|
|
121
|
+
|
|
80
122
|
provide("push-alert", push);
|
|
81
123
|
provide("close-alert", close);
|
|
82
124
|
</script>
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<uixy-card
|
|
3
3
|
class="relative flex w-full items-center justify-between gap-8 overflow-hidden bg-gray-200 py-4 shadow-xs dark:bg-black"
|
|
4
|
+
@mouseenter="handleMouseEnter"
|
|
5
|
+
@mouseleave="handleMouseLeave"
|
|
4
6
|
>
|
|
5
7
|
<div class="flex gap-4">
|
|
6
8
|
<uixy-icon v-if="props.icon" :name="props.icon" class="size-6 shrink-0" />
|
|
@@ -34,7 +36,12 @@
|
|
|
34
36
|
</template>
|
|
35
37
|
|
|
36
38
|
<script setup lang="ts">
|
|
37
|
-
import {
|
|
39
|
+
import {
|
|
40
|
+
motion,
|
|
41
|
+
useMotionValue,
|
|
42
|
+
animate,
|
|
43
|
+
type AnimationPlaybackControls,
|
|
44
|
+
} from "motion-v";
|
|
38
45
|
import { UixyButton, UixyIconButton, UixyIcon, UixyCard } from "..";
|
|
39
46
|
import type { UixyAlertItemProps, UixyAlertItemEmits } from "./Alert.types";
|
|
40
47
|
|
|
@@ -44,10 +51,22 @@
|
|
|
44
51
|
|
|
45
52
|
const width = useMotionValue("100%");
|
|
46
53
|
|
|
54
|
+
let controls: AnimationPlaybackControls | undefined;
|
|
55
|
+
|
|
47
56
|
onMounted(() => {
|
|
48
|
-
animate(width, "0%", {
|
|
57
|
+
controls = animate(width, "0%", {
|
|
49
58
|
duration: 8,
|
|
50
59
|
ease: "linear",
|
|
51
60
|
});
|
|
52
61
|
});
|
|
62
|
+
|
|
63
|
+
const handleMouseEnter = () => {
|
|
64
|
+
controls?.pause();
|
|
65
|
+
emit("pause-timer");
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const handleMouseLeave = () => {
|
|
69
|
+
controls?.play();
|
|
70
|
+
emit("resume-timer");
|
|
71
|
+
};
|
|
53
72
|
</script>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import styles from "~/utils/styles";
|
|
2
2
|
|
|
3
3
|
export const buttonStyles = styles(
|
|
4
|
-
"relative cursor-pointer
|
|
4
|
+
"relative cursor-pointer font-500 transition-all duration-200 ease-in-out hover:shadow-xs flex items-center justify-center gap-2 disabled:pointer-events-none border border-transparent",
|
|
5
5
|
{
|
|
6
6
|
variant: {
|
|
7
7
|
primary:
|
|
@@ -14,9 +14,9 @@ export const buttonStyles = styles(
|
|
|
14
14
|
"dark:hover:text-gray-100 hover:bg-gray-200 dark:hover:bg-gray-800 disabled:text-gray-700",
|
|
15
15
|
},
|
|
16
16
|
size: {
|
|
17
|
-
sm: "
|
|
18
|
-
md: "px-6
|
|
19
|
-
lg: "
|
|
17
|
+
sm: "h-7 px-4 text-button-sm",
|
|
18
|
+
md: "h-8 px-6 text-button-md",
|
|
19
|
+
lg: "h-10 px-8 text-button-lg",
|
|
20
20
|
},
|
|
21
21
|
rounded: {
|
|
22
22
|
true: "rounded-full",
|
|
@@ -2,14 +2,15 @@
|
|
|
2
2
|
<label :class="checkboxStyles($attrs.class as string)">
|
|
3
3
|
<div class="relative flex items-center justify-center">
|
|
4
4
|
<input
|
|
5
|
+
ref="inputRef"
|
|
5
6
|
type="checkbox"
|
|
6
7
|
:disabled="props.disabled"
|
|
7
8
|
v-model="checked"
|
|
8
|
-
class="
|
|
9
|
+
:class="inputStyles({ indeterminate: !!props.indeterminate })"
|
|
9
10
|
/>
|
|
10
11
|
<animate-presence>
|
|
11
12
|
<motion.div
|
|
12
|
-
v-if="checked"
|
|
13
|
+
v-if="checked || props.indeterminate"
|
|
13
14
|
:initial="{ opacity: 0 }"
|
|
14
15
|
:animate="{ opacity: 1 }"
|
|
15
16
|
:exit="{ opacity: 0 }"
|
|
@@ -17,11 +18,11 @@
|
|
|
17
18
|
class="pointer-events-none absolute"
|
|
18
19
|
>
|
|
19
20
|
<uixy-icon
|
|
20
|
-
name="check"
|
|
21
|
+
:name="props.indeterminate ? 'minus' : 'check'"
|
|
21
22
|
:class="
|
|
22
23
|
iconStyles({
|
|
23
24
|
disabled: !!props.disabled,
|
|
24
|
-
checked: checked,
|
|
25
|
+
checked: checked || props.indeterminate,
|
|
25
26
|
})
|
|
26
27
|
"
|
|
27
28
|
/>
|
|
@@ -41,9 +42,22 @@
|
|
|
41
42
|
import { motion, AnimatePresence } from "motion-v";
|
|
42
43
|
import { UixyIcon } from "../Icon";
|
|
43
44
|
import type { UixyCheckboxProps } from "./Checkbox.types";
|
|
44
|
-
import {
|
|
45
|
+
import {
|
|
46
|
+
checkboxStyles,
|
|
47
|
+
inputStyles,
|
|
48
|
+
iconStyles,
|
|
49
|
+
labelStyles,
|
|
50
|
+
} from "./Checkbox.styles";
|
|
45
51
|
|
|
46
52
|
const props = defineProps<UixyCheckboxProps>();
|
|
47
53
|
|
|
48
54
|
const checked = defineModel<boolean>("checked");
|
|
55
|
+
|
|
56
|
+
const inputRef = ref<HTMLInputElement | null>(null);
|
|
57
|
+
|
|
58
|
+
watchEffect(() => {
|
|
59
|
+
if (inputRef.value) {
|
|
60
|
+
inputRef.value.indeterminate = !!props.indeterminate;
|
|
61
|
+
}
|
|
62
|
+
});
|
|
49
63
|
</script>
|
|
@@ -2,6 +2,16 @@ import styles from "~/utils/styles";
|
|
|
2
2
|
|
|
3
3
|
export const checkboxStyles = styles("flex items-center gap-2");
|
|
4
4
|
|
|
5
|
+
export const inputStyles = styles(
|
|
6
|
+
"size-4 cursor-pointer appearance-none rounded-1 border border-black transition-all duration-150 ease-in-out checked:bg-black hover:bg-gray-300 checked:hover:bg-gray-800 disabled:pointer-events-none disabled:border-gray-500 disabled:bg-gray-300 checked:disabled:bg-gray-500 dark:border-gray-100 dark:checked:bg-gray-100 dark:hover:bg-gray-800 dark:checked:hover:bg-gray-200 dark:disabled:border-gray-600 dark:disabled:bg-gray-900 dark:checked:disabled:bg-gray-600",
|
|
7
|
+
{
|
|
8
|
+
indeterminate: {
|
|
9
|
+
true: "bg-black hover:bg-gray-800 disabled:bg-gray-300 dark:bg-gray-100 dark:hover:bg-gray-200 dark:disabled:bg-gray-900",
|
|
10
|
+
false: "",
|
|
11
|
+
},
|
|
12
|
+
},
|
|
13
|
+
);
|
|
14
|
+
|
|
5
15
|
export const iconStyles = styles("h-3 w-3", {
|
|
6
16
|
disabled: {
|
|
7
17
|
true: "text-gray-500",
|
|
@@ -33,9 +33,29 @@
|
|
|
33
33
|
/>
|
|
34
34
|
</div>
|
|
35
35
|
|
|
36
|
-
<
|
|
37
|
-
<
|
|
38
|
-
|
|
36
|
+
<animate-presence mode="wait" :initial="false">
|
|
37
|
+
<motion.div
|
|
38
|
+
v-if="!!helperText"
|
|
39
|
+
class="overflow-hidden"
|
|
40
|
+
:initial="{ height: 0 }"
|
|
41
|
+
:animate="{ height: 'auto' }"
|
|
42
|
+
:exit="{ height: 0 }"
|
|
43
|
+
:transition="{ duration: 0.1, ease: 'easeInOut' }"
|
|
44
|
+
>
|
|
45
|
+
<animate-presence mode="wait" :initial="false">
|
|
46
|
+
<motion.p
|
|
47
|
+
:key="status + helperText"
|
|
48
|
+
:class="helperStyles({ status })"
|
|
49
|
+
:initial="{ opacity: 0, y: -4 }"
|
|
50
|
+
:animate="{ opacity: 1, y: 0 }"
|
|
51
|
+
:exit="{ opacity: 0, y: 4 }"
|
|
52
|
+
:transition="{ duration: 0.12, ease: 'easeInOut', delay: 0.1 }"
|
|
53
|
+
>
|
|
54
|
+
{{ helperText }}
|
|
55
|
+
</motion.p>
|
|
56
|
+
</animate-presence>
|
|
57
|
+
</motion.div>
|
|
58
|
+
</animate-presence>
|
|
39
59
|
|
|
40
60
|
<teleport to="body">
|
|
41
61
|
<animate-presence>
|
|
@@ -19,7 +19,12 @@
|
|
|
19
19
|
:class="triggerIconStyles({ disabled: props.disabled })"
|
|
20
20
|
/>
|
|
21
21
|
<span
|
|
22
|
-
:class="
|
|
22
|
+
:class="
|
|
23
|
+
triggerValueStyles({
|
|
24
|
+
placeholder: !hasValue,
|
|
25
|
+
disabled: props.disabled,
|
|
26
|
+
})
|
|
27
|
+
"
|
|
23
28
|
>
|
|
24
29
|
{{ displayValue }}
|
|
25
30
|
</span>
|
|
@@ -31,9 +36,29 @@
|
|
|
31
36
|
/>
|
|
32
37
|
</div>
|
|
33
38
|
|
|
34
|
-
<
|
|
35
|
-
<
|
|
36
|
-
|
|
39
|
+
<animate-presence mode="wait" :initial="false">
|
|
40
|
+
<motion.div
|
|
41
|
+
v-if="!!helperText"
|
|
42
|
+
class="overflow-hidden"
|
|
43
|
+
:initial="{ height: 0 }"
|
|
44
|
+
:animate="{ height: 'auto' }"
|
|
45
|
+
:exit="{ height: 0 }"
|
|
46
|
+
:transition="{ duration: 0.1, ease: 'easeInOut' }"
|
|
47
|
+
>
|
|
48
|
+
<animate-presence mode="wait" :initial="false">
|
|
49
|
+
<motion.p
|
|
50
|
+
:key="status + helperText"
|
|
51
|
+
:class="helperStyles({ status })"
|
|
52
|
+
:initial="{ opacity: 0, y: -4 }"
|
|
53
|
+
:animate="{ opacity: 1, y: 0 }"
|
|
54
|
+
:exit="{ opacity: 0, y: 4 }"
|
|
55
|
+
:transition="{ duration: 0.12, ease: 'easeInOut', delay: 0.1 }"
|
|
56
|
+
>
|
|
57
|
+
{{ helperText }}
|
|
58
|
+
</motion.p>
|
|
59
|
+
</animate-presence>
|
|
60
|
+
</motion.div>
|
|
61
|
+
</animate-presence>
|
|
37
62
|
|
|
38
63
|
<teleport to="body">
|
|
39
64
|
<animate-presence>
|
|
@@ -78,19 +78,29 @@
|
|
|
78
78
|
</div>
|
|
79
79
|
</div>
|
|
80
80
|
|
|
81
|
-
<
|
|
82
|
-
<
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
81
|
+
<animate-presence mode="wait" :initial="false">
|
|
82
|
+
<motion.div
|
|
83
|
+
v-if="!!text"
|
|
84
|
+
class="overflow-hidden"
|
|
85
|
+
:initial="{ height: 0 }"
|
|
86
|
+
:animate="{ height: 'auto' }"
|
|
87
|
+
:exit="{ height: 0 }"
|
|
88
|
+
:transition="{ duration: 0.1, ease: 'easeInOut' }"
|
|
89
|
+
>
|
|
90
|
+
<animate-presence mode="wait" :initial="false">
|
|
91
|
+
<motion.p
|
|
92
|
+
:key="status + text"
|
|
93
|
+
:class="helperStyles({ status })"
|
|
94
|
+
:initial="{ opacity: 0, y: -4 }"
|
|
95
|
+
:animate="{ opacity: 1, y: 0 }"
|
|
96
|
+
:exit="{ opacity: 0, y: 4 }"
|
|
97
|
+
:transition="{ duration: 0.12, ease: 'easeInOut', delay: 0.1 }"
|
|
98
|
+
>
|
|
99
|
+
{{ text }}
|
|
100
|
+
</motion.p>
|
|
101
|
+
</animate-presence>
|
|
102
|
+
</motion.div>
|
|
103
|
+
</animate-presence>
|
|
94
104
|
</div>
|
|
95
105
|
</template>
|
|
96
106
|
|
|
@@ -27,19 +27,29 @@
|
|
|
27
27
|
{{ props.label }}
|
|
28
28
|
</label>
|
|
29
29
|
</div>
|
|
30
|
-
<
|
|
31
|
-
<
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
30
|
+
<animate-presence mode="wait" :initial="false">
|
|
31
|
+
<motion.div
|
|
32
|
+
v-if="!!text"
|
|
33
|
+
class="overflow-hidden"
|
|
34
|
+
:initial="{ height: 0 }"
|
|
35
|
+
:animate="{ height: 'auto' }"
|
|
36
|
+
:exit="{ height: 0 }"
|
|
37
|
+
:transition="{ duration: 0.1, ease: 'easeInOut' }"
|
|
38
|
+
>
|
|
39
|
+
<animate-presence mode="wait" :initial="false">
|
|
40
|
+
<motion.p
|
|
41
|
+
:key="status + text"
|
|
42
|
+
:class="helperStyles({ status })"
|
|
43
|
+
:initial="{ opacity: 0, y: -4 }"
|
|
44
|
+
:animate="{ opacity: 1, y: 0 }"
|
|
45
|
+
:exit="{ opacity: 0, y: 4 }"
|
|
46
|
+
:transition="{ duration: 0.12, ease: 'easeInOut', delay: 0.1 }"
|
|
47
|
+
>
|
|
48
|
+
{{ text }}
|
|
49
|
+
</motion.p>
|
|
50
|
+
</animate-presence>
|
|
51
|
+
</motion.div>
|
|
52
|
+
</animate-presence>
|
|
43
53
|
</div>
|
|
44
54
|
</template>
|
|
45
55
|
|
|
@@ -63,7 +63,6 @@
|
|
|
63
63
|
icon="search"
|
|
64
64
|
iconPositon="right"
|
|
65
65
|
placeholder="Search..."
|
|
66
|
-
hide-helper
|
|
67
66
|
/>
|
|
68
67
|
</div>
|
|
69
68
|
|
|
@@ -140,19 +139,29 @@
|
|
|
140
139
|
{{ props.label }}
|
|
141
140
|
</div>
|
|
142
141
|
</div>
|
|
143
|
-
<
|
|
144
|
-
<
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
142
|
+
<animate-presence mode="wait" :initial="false">
|
|
143
|
+
<motion.div
|
|
144
|
+
v-if="!!text"
|
|
145
|
+
class="overflow-hidden"
|
|
146
|
+
:initial="{ height: 0 }"
|
|
147
|
+
:animate="{ height: 'auto' }"
|
|
148
|
+
:exit="{ height: 0 }"
|
|
149
|
+
:transition="{ duration: 0.1, ease: 'easeInOut' }"
|
|
150
|
+
>
|
|
151
|
+
<animate-presence mode="wait" :initial="false">
|
|
152
|
+
<motion.p
|
|
153
|
+
:key="status + text"
|
|
154
|
+
:class="helperStyles({ status })"
|
|
155
|
+
:initial="{ opacity: 0, y: -4 }"
|
|
156
|
+
:animate="{ opacity: 1, y: 0 }"
|
|
157
|
+
:exit="{ opacity: 0, y: 4 }"
|
|
158
|
+
:transition="{ duration: 0.12, ease: 'easeInOut', delay: 0.1 }"
|
|
159
|
+
>
|
|
160
|
+
{{ text }}
|
|
161
|
+
</motion.p>
|
|
162
|
+
</animate-presence>
|
|
163
|
+
</motion.div>
|
|
164
|
+
</animate-presence>
|
|
156
165
|
</div>
|
|
157
166
|
</template>
|
|
158
167
|
|