daisy-ui-kit 5.0.0-pre.10 → 5.0.0-pre.11
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/app/components/Accordion.vue +8 -5
- package/app/components/Alert.vue +2 -1
- package/app/components/Avatar.vue +10 -7
- package/app/components/AvatarGroup.vue +6 -2
- package/app/components/Badge.vue +14 -1
- package/app/components/Button.vue +60 -45
- package/app/components/Calendar.vue +24 -1
- package/app/components/CalendarInput.vue +2 -2
- package/app/components/CalendarSkeleton.vue +51 -10
- package/app/components/Card.vue +15 -2
- package/app/components/CardActions.vue +1 -1
- package/app/components/CardBody.vue +1 -1
- package/app/components/CardTitle.vue +1 -1
- package/app/components/Carousel.vue +2 -1
- package/app/components/Chat.vue +6 -1
- package/app/components/Checkbox.vue +1 -1
- package/app/components/Collapse.vue +37 -5
- package/app/components/CollapseTitle.vue +11 -1
- package/app/components/Countdown.vue +3 -3
- package/app/components/CountdownTimers.vue +4 -7
- package/app/components/Counter.vue +13 -2
- package/app/components/DaisyLink.vue +29 -15
- package/app/components/Dock.vue +1 -1
- package/app/components/DockItem.vue +1 -1
- package/app/components/Drawer.vue +15 -12
- package/app/components/DrawerContent.vue +9 -6
- package/app/components/DrawerSide.vue +9 -6
- package/app/components/Dropdown.vue +61 -50
- package/app/components/DropdownButton.vue +11 -4
- package/app/components/DropdownContent.vue +90 -19
- package/app/components/DropdownTarget.vue +9 -2
- package/app/components/Fab.vue +16 -0
- package/app/components/FabClose.vue +18 -0
- package/app/components/FabMainAction.vue +5 -0
- package/app/components/FabTrigger.vue +117 -0
- package/app/components/Fieldset.vue +1 -4
- package/app/components/FileInput.vue +1 -1
- package/app/components/Filter.vue +35 -32
- package/app/components/Flex.vue +3 -1
- package/app/components/FlexItem.vue +30 -27
- package/app/components/Footer.vue +16 -12
- package/app/components/FooterTitle.vue +8 -5
- package/app/components/Hero.vue +9 -6
- package/app/components/HeroContent.vue +9 -6
- package/app/components/Hover3D.vue +22 -0
- package/app/components/HoverGallery.vue +11 -0
- package/app/components/Indicator.vue +8 -5
- package/app/components/IndicatorItem.vue +16 -13
- package/app/components/Input.vue +47 -40
- package/app/components/Kbd.vue +2 -1
- package/app/components/Label.vue +32 -29
- package/app/components/MenuExpand.vue +1 -7
- package/app/components/MenuExpandToggle.vue +7 -1
- package/app/components/MenuItem.vue +6 -4
- package/app/components/Modal.vue +23 -17
- package/app/components/Progress.vue +13 -1
- package/app/components/Prose.vue +7 -2
- package/app/components/RadialProgress.vue +8 -8
- package/app/components/Radio.vue +1 -1
- package/app/components/RadioGroup.vue +2 -2
- package/app/components/Range.vue +2 -2
- package/app/components/RangeMeasure.vue +33 -30
- package/app/components/Rating.vue +70 -53
- package/app/components/Select.vue +44 -47
- package/app/components/SkeletonText.vue +11 -0
- package/app/components/Steps.vue +7 -2
- package/app/components/Swap.vue +4 -10
- package/app/components/Tab.vue +18 -5
- package/app/components/Text.vue +42 -22
- package/app/components/TextArea.vue +30 -27
- package/app/components/TextRotate.vue +24 -0
- package/app/components/ThemeController.vue +3 -4
- package/app/components/ThemeProvider.vue +47 -32
- package/app/components/TimelineLine.vue +1 -1
- package/app/components/TimelineStart.vue +2 -1
- package/app/components/Toast.vue +1 -6
- package/app/components/Toggle.vue +2 -2
- package/app/components/Tooltip.vue +2 -1
- package/app/utils/drawer-utils.ts +15 -13
- package/app/utils/position-area.ts +41 -0
- package/package.json +9 -7
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { provide, ref, watch } from 'vue'
|
|
2
|
+
import { provide, ref, watch } from 'vue'
|
|
3
3
|
|
|
4
4
|
const props = defineProps<{
|
|
5
5
|
modelValue?: string | number
|
|
@@ -7,10 +7,13 @@ const props = defineProps<{
|
|
|
7
7
|
const emit = defineEmits(['update:modelValue'])
|
|
8
8
|
|
|
9
9
|
const value = ref(props.modelValue)
|
|
10
|
-
watch(
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
watch(
|
|
11
|
+
() => props.modelValue,
|
|
12
|
+
val => {
|
|
13
|
+
value.value = val
|
|
14
|
+
},
|
|
15
|
+
)
|
|
16
|
+
watch(value, val => {
|
|
14
17
|
if (props.modelValue !== val) {
|
|
15
18
|
emit('update:modelValue', val)
|
|
16
19
|
}
|
package/app/components/Alert.vue
CHANGED
|
@@ -51,7 +51,7 @@ const maskShapeKeys = [
|
|
|
51
51
|
'mask-half-2',
|
|
52
52
|
] as const
|
|
53
53
|
|
|
54
|
-
type AvatarClassKey = typeof maskShapeKeys[number] | 'rounded-box' | 'avatar-online' | 'avatar-offline'
|
|
54
|
+
type AvatarClassKey = (typeof maskShapeKeys)[number] | 'rounded-box' | 'avatar-online' | 'avatar-offline'
|
|
55
55
|
|
|
56
56
|
const avatarClasses = computed<Record<AvatarClassKey, boolean>>(() => {
|
|
57
57
|
const mask: Record<AvatarClassKey, boolean> = {
|
|
@@ -86,18 +86,17 @@ const color = computed(() => {
|
|
|
86
86
|
})
|
|
87
87
|
|
|
88
88
|
function contrastingColor(color: any) {
|
|
89
|
-
return
|
|
89
|
+
return luma(color) >= 155 ? '000' : 'fff'
|
|
90
90
|
}
|
|
91
91
|
// color can be a hx string or an array of RGB values 0-255
|
|
92
92
|
function luma(color: any) {
|
|
93
|
-
const rgb =
|
|
94
|
-
return
|
|
93
|
+
const rgb = typeof color === 'string' ? hexToRGBArray(color) : color
|
|
94
|
+
return 0.2126 * rgb[0] + 0.7152 * rgb[1] + 0.0722 * rgb[2] // SMPTE C, Rec. 709 weightings
|
|
95
95
|
}
|
|
96
96
|
function hexToRGBArray(color: any) {
|
|
97
97
|
if (color.length === 3) {
|
|
98
98
|
color = color.charAt(0) + color.charAt(0) + color.charAt(1) + color.charAt(1) + color.charAt(2) + color.charAt(2)
|
|
99
|
-
}
|
|
100
|
-
else if (color.length !== 6) {
|
|
99
|
+
} else if (color.length !== 6) {
|
|
101
100
|
throw new Error(`Invalid hex color: ${color}`)
|
|
102
101
|
}
|
|
103
102
|
const rgb = []
|
|
@@ -110,7 +109,11 @@ function hexToRGBArray(color: any) {
|
|
|
110
109
|
|
|
111
110
|
<template>
|
|
112
111
|
<div class="avatar">
|
|
113
|
-
<Mask
|
|
112
|
+
<Mask
|
|
113
|
+
:style="{ backgroundColor, color }"
|
|
114
|
+
class="w-full h-full avatar-mask aspect-square"
|
|
115
|
+
:class="[avatarClasses, maskClasses]"
|
|
116
|
+
>
|
|
114
117
|
<slot />
|
|
115
118
|
</Mask>
|
|
116
119
|
</div>
|
|
@@ -8,8 +8,12 @@ const props = defineProps<{
|
|
|
8
8
|
|
|
9
9
|
<template>
|
|
10
10
|
<div
|
|
11
|
-
class="avatar-group"
|
|
12
|
-
|
|
11
|
+
class="avatar-group"
|
|
12
|
+
:class="{
|
|
13
|
+
'flex-row':
|
|
14
|
+
props.orientation === 'horizontal' ||
|
|
15
|
+
props.horizontal ||
|
|
16
|
+
(!props.orientation && !props.vertical && !props.horizontal),
|
|
13
17
|
'flex-col': props.orientation === 'vertical' || props.vertical,
|
|
14
18
|
}"
|
|
15
19
|
>
|
package/app/components/Badge.vue
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
import { computed } from 'vue'
|
|
3
|
+
|
|
2
4
|
const { is = 'div', ...props } = defineProps<{
|
|
3
5
|
is?: string
|
|
4
6
|
outline?: boolean
|
|
@@ -23,11 +25,22 @@ const { is = 'div', ...props } = defineProps<{
|
|
|
23
25
|
warning?: boolean
|
|
24
26
|
error?: boolean
|
|
25
27
|
}>()
|
|
28
|
+
|
|
29
|
+
const NuxtLink = resolveComponent('NuxtLink')
|
|
30
|
+
const RouterLink = resolveComponent('RouterLink')
|
|
31
|
+
|
|
32
|
+
const resolvedComponent = computed(() => {
|
|
33
|
+
if (is === 'NuxtLink') return NuxtLink
|
|
34
|
+
if (is === 'RouterLink') return RouterLink
|
|
35
|
+
return is
|
|
36
|
+
})
|
|
26
37
|
</script>
|
|
27
38
|
|
|
28
39
|
<template>
|
|
29
40
|
<component
|
|
30
|
-
:is="
|
|
41
|
+
:is="resolvedComponent"
|
|
42
|
+
class="badge"
|
|
43
|
+
:class="{
|
|
31
44
|
'badge-outline': props.outline,
|
|
32
45
|
'badge-ghost': props.ghost,
|
|
33
46
|
'badge-soft': props.soft,
|
|
@@ -1,52 +1,67 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { computed } from 'vue'
|
|
3
3
|
|
|
4
|
-
const props = withDefaults(
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
4
|
+
const props = withDefaults(
|
|
5
|
+
defineProps<{
|
|
6
|
+
is?: string
|
|
7
|
+
join?: boolean
|
|
8
|
+
|
|
9
|
+
color?: string
|
|
10
|
+
neutral?: boolean
|
|
11
|
+
primary?: boolean
|
|
12
|
+
secondary?: boolean
|
|
13
|
+
accent?: boolean
|
|
14
|
+
info?: boolean
|
|
15
|
+
success?: boolean
|
|
16
|
+
warning?: boolean
|
|
17
|
+
error?: boolean
|
|
18
|
+
|
|
19
|
+
ghost?: boolean
|
|
20
|
+
link?: boolean
|
|
21
|
+
glass?: boolean
|
|
22
|
+
outline?: boolean
|
|
23
|
+
dash?: boolean
|
|
24
|
+
soft?: boolean
|
|
25
|
+
disabled?: boolean
|
|
26
|
+
|
|
27
|
+
shape?: 'circle' | 'square' | 'wide' | 'block'
|
|
28
|
+
circle?: boolean
|
|
29
|
+
square?: boolean
|
|
30
|
+
wide?: boolean
|
|
31
|
+
block?: boolean
|
|
32
|
+
|
|
33
|
+
noAnimation?: boolean
|
|
34
|
+
active?: boolean
|
|
35
|
+
|
|
36
|
+
size?: 'lg' | 'md' | 'sm' | 'xs' | 'xl'
|
|
37
|
+
xl?: boolean
|
|
38
|
+
lg?: boolean
|
|
39
|
+
md?: boolean
|
|
40
|
+
sm?: boolean
|
|
41
|
+
xs?: boolean
|
|
42
|
+
|
|
43
|
+
type?: 'button' | 'submit' | 'reset'
|
|
44
|
+
}>(),
|
|
45
|
+
{
|
|
46
|
+
type: 'button',
|
|
47
|
+
},
|
|
48
|
+
)
|
|
49
|
+
const NuxtLink = resolveComponent('NuxtLink')
|
|
50
|
+
const RouterLink = resolveComponent('RouterLink')
|
|
46
51
|
|
|
47
52
|
// Accessibility: Determine if rendering a native button
|
|
48
53
|
const isButton = computed(() => (props.is || 'button') === 'button')
|
|
49
54
|
|
|
55
|
+
// Resolve the component to render
|
|
56
|
+
const resolvedComponent = computed(() => {
|
|
57
|
+
if (!props.is || props.is === 'button' || props.is === 'a') {
|
|
58
|
+
return props.is || 'button'
|
|
59
|
+
}
|
|
60
|
+
if (props.is === 'NuxtLink') return NuxtLink
|
|
61
|
+
if (props.is === 'RouterLink') return RouterLink
|
|
62
|
+
return props.is
|
|
63
|
+
})
|
|
64
|
+
|
|
50
65
|
// Accessibility: Keyboard event handler for custom elements
|
|
51
66
|
function onKeydown(e: KeyboardEvent) {
|
|
52
67
|
if (props.disabled) {
|
|
@@ -62,8 +77,8 @@ function onKeydown(e: KeyboardEvent) {
|
|
|
62
77
|
|
|
63
78
|
<template>
|
|
64
79
|
<component
|
|
65
|
-
:is="
|
|
66
|
-
:type="type"
|
|
80
|
+
:is="resolvedComponent"
|
|
81
|
+
:type="isButton ? type : undefined"
|
|
67
82
|
:disabled="isButton && disabled ? true : undefined"
|
|
68
83
|
:aria-disabled="!isButton && disabled ? true : undefined"
|
|
69
84
|
:tabindex="!isButton ? (disabled ? -1 : 0) : undefined"
|
|
@@ -90,7 +105,7 @@ function onKeydown(e: KeyboardEvent) {
|
|
|
90
105
|
'text-warning': !disabled && (warning || color === 'warning') && link,
|
|
91
106
|
'text-error': !disabled && (error || color === 'error') && link,
|
|
92
107
|
|
|
93
|
-
|
|
108
|
+
glass: !disabled && glass,
|
|
94
109
|
|
|
95
110
|
'btn-circle': circle || shape === 'circle',
|
|
96
111
|
'btn-square': square || shape === 'square',
|
|
@@ -23,6 +23,24 @@ const defaultOptions: Partial<PikadayOptions> = {
|
|
|
23
23
|
format: 'D MMM YYYY',
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
+
// Determine the date to use for the skeleton
|
|
27
|
+
const skeletonDate = computed(() => {
|
|
28
|
+
// Try to use modelValue if it's a Date
|
|
29
|
+
if (props.modelValue instanceof Date) {
|
|
30
|
+
return props.modelValue
|
|
31
|
+
}
|
|
32
|
+
// Try to parse modelValue if it's a string
|
|
33
|
+
if (typeof props.modelValue === 'string') {
|
|
34
|
+
return new Date(props.modelValue)
|
|
35
|
+
}
|
|
36
|
+
// Use defaultDate from options if provided
|
|
37
|
+
if (props.options?.defaultDate instanceof Date) {
|
|
38
|
+
return props.options.defaultDate
|
|
39
|
+
}
|
|
40
|
+
// Fall back to today
|
|
41
|
+
return new Date()
|
|
42
|
+
})
|
|
43
|
+
|
|
26
44
|
function handleSelect(date: Date) {
|
|
27
45
|
emit('update:modelValue', date)
|
|
28
46
|
}
|
|
@@ -50,7 +68,12 @@ onMounted(async () => {
|
|
|
50
68
|
<template>
|
|
51
69
|
<div class="relative w-[270px] h-[270px]">
|
|
52
70
|
<div class="absolute inset-0">
|
|
53
|
-
<CalendarSkeleton
|
|
71
|
+
<CalendarSkeleton
|
|
72
|
+
:number-of-months="options?.numberOfMonths ?? 1"
|
|
73
|
+
:date="skeletonDate"
|
|
74
|
+
:first-day="options?.firstDay"
|
|
75
|
+
:class="loading ? '' : 'opacity-0 pointer-events-none transition-opacity duration-300'"
|
|
76
|
+
/>
|
|
54
77
|
</div>
|
|
55
78
|
<div ref="containerRef" class="absolute inset-0 inline-block w-full h-full" />
|
|
56
79
|
<span class="pika-single hidden" />
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { onMounted, ref, watch } from 'vue'
|
|
3
|
-
import type { ComponentPublicInstance, Ref } from 'vue'
|
|
4
2
|
import type { PikadayOptions } from 'pikaday'
|
|
3
|
+
import type { ComponentPublicInstance } from 'vue'
|
|
4
|
+
import { onMounted, ref, watch } from 'vue'
|
|
5
5
|
|
|
6
6
|
import { usePikaday } from '~/composables/use-pikaday'
|
|
7
7
|
|
|
@@ -1,17 +1,58 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import Skeleton from './Skeleton.vue'
|
|
3
3
|
|
|
4
|
-
const
|
|
4
|
+
const props = defineProps<{
|
|
5
5
|
numberOfMonths?: number
|
|
6
|
+
date?: Date
|
|
7
|
+
firstDay?: number // 0 = Sunday, 1 = Monday, etc. (matches Pikaday's firstDay option)
|
|
6
8
|
}>()
|
|
9
|
+
|
|
10
|
+
// Calculate the number of weeks needed for a given month
|
|
11
|
+
function getWeeksInMonth(date: Date, weekStartDay: number = 0): number {
|
|
12
|
+
const year = date.getFullYear()
|
|
13
|
+
const month = date.getMonth()
|
|
14
|
+
|
|
15
|
+
// Get first day of month
|
|
16
|
+
const firstDay = new Date(year, month, 1)
|
|
17
|
+
const firstDayOfWeek = firstDay.getDay()
|
|
18
|
+
|
|
19
|
+
// Get last day of month
|
|
20
|
+
const lastDay = new Date(year, month + 1, 0)
|
|
21
|
+
const daysInMonth = lastDay.getDate()
|
|
22
|
+
|
|
23
|
+
// Calculate offset based on what day the week starts on
|
|
24
|
+
// If week starts on Monday (1) and month starts on Sunday (0), offset is 6
|
|
25
|
+
// If week starts on Sunday (0) and month starts on Sunday (0), offset is 0
|
|
26
|
+
const offset = (firstDayOfWeek - weekStartDay + 7) % 7
|
|
27
|
+
|
|
28
|
+
// Calculate total cells needed (days in month + offset from first day)
|
|
29
|
+
const totalCells = daysInMonth + offset
|
|
30
|
+
|
|
31
|
+
// Return number of weeks (rows) needed
|
|
32
|
+
return Math.ceil(totalCells / 7)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Calculate weeks for each month being displayed
|
|
36
|
+
const weeksPerMonth = computed(() => {
|
|
37
|
+
const baseDate = props.date || new Date()
|
|
38
|
+
const weekStartDay = props.firstDay ?? 0
|
|
39
|
+
const weeks: number[] = []
|
|
40
|
+
|
|
41
|
+
for (let i = 0; i < (props.numberOfMonths || 1); i++) {
|
|
42
|
+
const monthDate = new Date(baseDate.getFullYear(), baseDate.getMonth() + i, 1)
|
|
43
|
+
weeks.push(getWeeksInMonth(monthDate, weekStartDay))
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return weeks
|
|
47
|
+
})
|
|
7
48
|
</script>
|
|
8
49
|
|
|
9
50
|
<template>
|
|
10
51
|
<Skeleton col class="bg-base-200 rounded-box">
|
|
11
52
|
<div
|
|
12
|
-
v-for="(
|
|
13
|
-
:key="`calendar-${
|
|
14
|
-
class="w-[270px]
|
|
53
|
+
v-for="(weeks, idx) in weeksPerMonth"
|
|
54
|
+
:key="`calendar-${idx}`"
|
|
55
|
+
class="w-[270px] px-3 py-[14px] mx-auto flex flex-col gap-2"
|
|
15
56
|
:class="{
|
|
16
57
|
'-mt-3.5': idx > 0,
|
|
17
58
|
}"
|
|
@@ -28,17 +69,17 @@ const { numberOfMonths = 1 } = defineProps<{
|
|
|
28
69
|
<span
|
|
29
70
|
class="size-4 rounded-full bg-base-300 inline-block"
|
|
30
71
|
:class="{
|
|
31
|
-
'bg-base-300': idx ===
|
|
32
|
-
'bg-transparent': idx !==
|
|
72
|
+
'bg-base-300': idx === weeksPerMonth.length - 1,
|
|
73
|
+
'bg-transparent': idx !== weeksPerMonth.length - 1,
|
|
33
74
|
}"
|
|
34
75
|
/>
|
|
35
76
|
</Flex>
|
|
36
|
-
<Flex col
|
|
37
|
-
<div class="grid grid-cols-7 gap-[4px] mb-
|
|
77
|
+
<Flex col class="h-full">
|
|
78
|
+
<div class="grid grid-cols-7 gap-[4px] mb-3 flex-shrink-0">
|
|
38
79
|
<span v-for="d in 7" :key="`dow-${d}`" class="size-4 rounded-full bg-base-300 mx-auto block" />
|
|
39
80
|
</div>
|
|
40
|
-
<div class="grid grid-cols-7 gap-[
|
|
41
|
-
<span v-for="i in
|
|
81
|
+
<div class="grid grid-cols-7 gap-y-[8px] gap-x-[4px]">
|
|
82
|
+
<span v-for="i in weeks * 7" :key="`day-${i}`" class="size-7 rounded-full bg-base-300 block mx-auto" />
|
|
42
83
|
</div>
|
|
43
84
|
</Flex>
|
|
44
85
|
</div>
|
package/app/components/Card.vue
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
import { computed } from 'vue'
|
|
3
|
+
|
|
2
4
|
const { is = 'div', ...props } = defineProps<{
|
|
3
|
-
is?:
|
|
5
|
+
is?: string
|
|
4
6
|
border?: boolean
|
|
5
7
|
dash?: boolean
|
|
6
8
|
side?: boolean
|
|
@@ -12,11 +14,22 @@ const { is = 'div', ...props } = defineProps<{
|
|
|
12
14
|
sm?: boolean
|
|
13
15
|
xs?: boolean
|
|
14
16
|
}>()
|
|
17
|
+
|
|
18
|
+
const NuxtLink = resolveComponent('NuxtLink')
|
|
19
|
+
const RouterLink = resolveComponent('RouterLink')
|
|
20
|
+
|
|
21
|
+
const resolvedComponent = computed(() => {
|
|
22
|
+
if (is === 'NuxtLink') return NuxtLink
|
|
23
|
+
if (is === 'RouterLink') return RouterLink
|
|
24
|
+
return is
|
|
25
|
+
})
|
|
15
26
|
</script>
|
|
16
27
|
|
|
17
28
|
<template>
|
|
18
29
|
<component
|
|
19
|
-
:is="
|
|
30
|
+
:is="resolvedComponent"
|
|
31
|
+
class="card"
|
|
32
|
+
:class="{
|
|
20
33
|
'card-border': props.border,
|
|
21
34
|
'card-side': props.side,
|
|
22
35
|
'image-full': props.imageFull,
|
|
@@ -11,7 +11,8 @@ const { snapTo, center, end, vertical } = defineProps<{
|
|
|
11
11
|
|
|
12
12
|
<template>
|
|
13
13
|
<div
|
|
14
|
-
class="carousel"
|
|
14
|
+
class="carousel"
|
|
15
|
+
:class="{
|
|
15
16
|
'carousel-center': center || snapTo === 'center',
|
|
16
17
|
'carousel-end': end || snapTo === 'end',
|
|
17
18
|
'carousel-horizontal': horizontal || orientation === 'horizontal',
|
package/app/components/Chat.vue
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { inject, ref } from 'vue'
|
|
2
|
+
import { inject, provide, ref, watch } from 'vue'
|
|
3
3
|
|
|
4
4
|
const props = defineProps<{
|
|
5
5
|
variant?: 'arrow' | 'plus'
|
|
@@ -11,19 +11,49 @@ const props = defineProps<{
|
|
|
11
11
|
value?: any
|
|
12
12
|
}>()
|
|
13
13
|
|
|
14
|
+
const isOpen = defineModel('open', { default: false })
|
|
15
|
+
|
|
14
16
|
const accordionValue = inject('accordion-value', ref(null))
|
|
15
17
|
const useAccordion = accordionValue.value !== null
|
|
16
18
|
|
|
19
|
+
// Internal state for toggle mode
|
|
20
|
+
const internalChecked = ref(props.open || false)
|
|
21
|
+
|
|
22
|
+
// Generate unique ID for checkbox
|
|
23
|
+
const checkboxId = `collapse-${Math.random().toString(36).substr(2, 9)}`
|
|
24
|
+
provide('collapseCheckboxId', checkboxId)
|
|
25
|
+
provide('collapseToggle', props.toggle || useAccordion)
|
|
26
|
+
|
|
27
|
+
// Sync internal state with modelValue
|
|
28
|
+
watch(
|
|
29
|
+
() => isOpen.value,
|
|
30
|
+
newVal => {
|
|
31
|
+
internalChecked.value = newVal
|
|
32
|
+
},
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
watch(internalChecked, newVal => {
|
|
36
|
+
isOpen.value = newVal
|
|
37
|
+
})
|
|
38
|
+
|
|
17
39
|
function handleClick() {
|
|
40
|
+
// Only handle clicks for accordion mode
|
|
18
41
|
if (useAccordion) {
|
|
19
42
|
accordionValue.value = props.value
|
|
20
43
|
}
|
|
21
44
|
}
|
|
45
|
+
|
|
46
|
+
const isChecked = computed(() => {
|
|
47
|
+
if (useAccordion) {
|
|
48
|
+
return accordionValue.value === props.value
|
|
49
|
+
}
|
|
50
|
+
return internalChecked.value
|
|
51
|
+
})
|
|
22
52
|
</script>
|
|
23
53
|
|
|
24
54
|
<template>
|
|
25
55
|
<div
|
|
26
|
-
tabindex="0"
|
|
56
|
+
:tabindex="props.toggle || useAccordion ? undefined : 0"
|
|
27
57
|
class="collapse"
|
|
28
58
|
:class="[
|
|
29
59
|
{ 'collapse-arrow': props.arrow || props.variant === 'arrow' },
|
|
@@ -31,13 +61,15 @@ function handleClick() {
|
|
|
31
61
|
{ 'collapse-open': (props.open && !props.close) || (useAccordion && accordionValue === props.value) },
|
|
32
62
|
{ 'collapse-close': props.close },
|
|
33
63
|
]"
|
|
34
|
-
@click="handleClick"
|
|
64
|
+
@click="useAccordion ? handleClick : undefined"
|
|
35
65
|
>
|
|
36
66
|
<input
|
|
37
67
|
v-if="props.toggle || useAccordion"
|
|
68
|
+
:id="checkboxId"
|
|
69
|
+
v-model="internalChecked"
|
|
38
70
|
:type="useAccordion ? 'radio' : 'checkbox'"
|
|
39
|
-
:checked="useAccordion ?
|
|
40
|
-
|
|
71
|
+
:checked="useAccordion ? isChecked : undefined"
|
|
72
|
+
/>
|
|
41
73
|
<slot />
|
|
42
74
|
</div>
|
|
43
75
|
</template>
|
|
@@ -1,5 +1,15 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { inject } from 'vue'
|
|
3
|
+
|
|
4
|
+
const checkboxId = inject('collapseCheckboxId', null)
|
|
5
|
+
const hasToggle = inject('collapseToggle', false)
|
|
6
|
+
</script>
|
|
7
|
+
|
|
1
8
|
<template>
|
|
2
|
-
<
|
|
9
|
+
<label v-if="hasToggle && checkboxId" :for="checkboxId" class="collapse-title">
|
|
10
|
+
<slot />
|
|
11
|
+
</label>
|
|
12
|
+
<div v-else class="collapse-title">
|
|
3
13
|
<slot />
|
|
4
14
|
</div>
|
|
5
15
|
</template>
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { computed } from 'vue'
|
|
2
|
+
import { computed } from 'vue'
|
|
3
3
|
|
|
4
|
-
const
|
|
4
|
+
const props = defineProps<{
|
|
5
5
|
is?: any
|
|
6
6
|
}>()
|
|
7
7
|
|
|
8
|
-
const tag = computed(() => is)
|
|
8
|
+
const tag = computed(() => props.is || 'span')
|
|
9
9
|
</script>
|
|
10
10
|
|
|
11
11
|
<template>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { useIntervalFn } from '@vueuse/core'
|
|
3
|
-
import { computed, ref, watch } from 'vue'
|
|
2
|
+
import { useIntervalFn } from '@vueuse/core'
|
|
3
|
+
import { computed, ref, watch } from 'vue'
|
|
4
4
|
|
|
5
5
|
const { durationInSeconds = 0, untilDate } = defineProps<{
|
|
6
6
|
durationInSeconds?: number
|
|
@@ -29,7 +29,7 @@ useIntervalFn(() => {
|
|
|
29
29
|
timeLeft.value = calcTimeLeft()
|
|
30
30
|
}, 1000)
|
|
31
31
|
|
|
32
|
-
watch(timeLeft,
|
|
32
|
+
watch(timeLeft, val => {
|
|
33
33
|
if (val === 0) {
|
|
34
34
|
emit('done')
|
|
35
35
|
}
|
|
@@ -42,10 +42,7 @@ const totalDays = computed(() => Math.floor(totalHours.value / 24))
|
|
|
42
42
|
const totalWeeks = computed(() => Math.floor(totalDays.value / 7))
|
|
43
43
|
const totalMonths = computed(() => {
|
|
44
44
|
const now = new Date()
|
|
45
|
-
return (
|
|
46
|
-
(targetDate.value.getFullYear() - now.getFullYear()) * 12
|
|
47
|
-
+ (targetDate.value.getMonth() - now.getMonth())
|
|
48
|
-
)
|
|
45
|
+
return (targetDate.value.getFullYear() - now.getFullYear()) * 12 + (targetDate.value.getMonth() - now.getMonth())
|
|
49
46
|
})
|
|
50
47
|
const split = computed(() => {
|
|
51
48
|
const days = totalDays.value
|
|
@@ -1,10 +1,21 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
|
|
2
|
+
import { computed } from 'vue'
|
|
3
|
+
|
|
4
|
+
const props = defineProps<{
|
|
3
5
|
value: number
|
|
4
6
|
is?: any
|
|
7
|
+
digits?: 2 | 3
|
|
5
8
|
}>()
|
|
9
|
+
|
|
10
|
+
const style = computed(() => {
|
|
11
|
+
let css = `--value:${props.value};`
|
|
12
|
+
if (props.digits) {
|
|
13
|
+
css += `--digits:${props.digits};`
|
|
14
|
+
}
|
|
15
|
+
return css
|
|
16
|
+
})
|
|
6
17
|
</script>
|
|
7
18
|
|
|
8
19
|
<template>
|
|
9
|
-
<component :is="is" v-bind="$attrs" :style="
|
|
20
|
+
<component :is="props.is || 'span'" v-bind="$attrs" :style="style" />
|
|
10
21
|
</template>
|