daisy-ui-kit 5.0.0-pre.9 → 5.0.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/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 +19 -1
- package/app/components/Button.vue +66 -46
- package/app/components/Calendar.vue +151 -42
- package/app/components/CalendarInput.vue +229 -130
- package/app/components/CalendarSkeleton.vue +51 -10
- package/app/components/Card.vue +20 -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 +38 -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 +14 -3
- package/app/components/DaisyLink.vue +33 -15
- package/app/components/Dock.vue +5 -6
- package/app/components/DockItem.vue +5 -3
- 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 -20
- package/app/components/DropdownTarget.vue +10 -3
- 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 +5 -4
- package/app/components/FileInput.vue +1 -1
- package/app/components/Filter.vue +45 -38
- package/app/components/Flex.vue +8 -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 +12 -5
- package/app/components/IndicatorItem.vue +21 -14
- package/app/components/Input.vue +44 -47
- package/app/components/Kbd.vue +2 -1
- package/app/components/Label.vue +32 -29
- package/app/components/MenuExpand.vue +5 -13
- 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 +186 -46
- package/app/components/RangeMeasure.vue +33 -30
- package/app/components/RangeMeasureTick.vue +4 -5
- package/app/components/Rating.vue +70 -53
- package/app/components/Select.vue +44 -47
- package/app/components/SkeletonText.vue +11 -0
- package/app/components/Stack.vue +5 -0
- package/app/components/Steps.vue +7 -2
- package/app/components/Swap.vue +4 -10
- package/app/components/Tab.vue +23 -5
- package/app/components/Text.vue +47 -23
- package/app/components/TextArea.vue +75 -30
- 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 +3 -8
- package/app/components/Toggle.vue +2 -2
- package/app/components/Tooltip.vue +111 -21
- package/app/components/TooltipContent.vue +279 -1
- package/app/components/TooltipTarget.vue +20 -0
- package/app/composables/__tests__/use-calendar.test.ts +239 -0
- package/app/composables/use-calendar.ts +288 -0
- package/app/composables/use-daisy-theme.ts +140 -0
- package/app/composables/use-toast.ts +345 -0
- package/app/composables/useSearch.ts +22 -0
- package/app/utils/drawer-utils.ts +15 -13
- package/app/utils/position-area.ts +40 -0
- package/nuxt.d.ts +13 -0
- package/nuxt.js +12 -9
- package/package.json +40 -29
- package/app/utils/random-string.ts +0 -19
package/app/components/Swap.vue
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { nextTick, ref, watch } from 'vue'
|
|
2
|
+
import { nextTick, ref, watch } from 'vue'
|
|
3
3
|
|
|
4
4
|
const props = defineProps<{
|
|
5
5
|
modelValue?: boolean | null
|
|
@@ -13,7 +13,7 @@ const checkbox = ref<HTMLInputElement | null>(null)
|
|
|
13
13
|
// Keep the checkbox's indeterminate property in sync with modelValue
|
|
14
14
|
watch(
|
|
15
15
|
() => props.modelValue,
|
|
16
|
-
|
|
16
|
+
val => {
|
|
17
17
|
nextTick(() => {
|
|
18
18
|
if (checkbox.value) {
|
|
19
19
|
checkbox.value.indeterminate = val === null
|
|
@@ -28,8 +28,7 @@ function updateValue(event: Event) {
|
|
|
28
28
|
// If indeterminate, toggle to checked
|
|
29
29
|
if (props.modelValue === null) {
|
|
30
30
|
emit('update:modelValue', true)
|
|
31
|
-
}
|
|
32
|
-
else {
|
|
31
|
+
} else {
|
|
33
32
|
emit('update:modelValue', input.checked)
|
|
34
33
|
}
|
|
35
34
|
}
|
|
@@ -43,12 +42,7 @@ function updateValue(event: Event) {
|
|
|
43
42
|
'swap-flip': flip,
|
|
44
43
|
}"
|
|
45
44
|
>
|
|
46
|
-
<input
|
|
47
|
-
ref="checkbox"
|
|
48
|
-
type="checkbox"
|
|
49
|
-
:checked="modelValue === true"
|
|
50
|
-
@change="updateValue"
|
|
51
|
-
>
|
|
45
|
+
<input ref="checkbox" type="checkbox" :checked="modelValue === true" @change="updateValue" />
|
|
52
46
|
<div class="swap-indeterminate">
|
|
53
47
|
<slot name="indeterminate" />
|
|
54
48
|
</div>
|
package/app/components/Tab.vue
CHANGED
|
@@ -1,13 +1,30 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { inject } from 'vue'
|
|
2
|
+
import { computed, inject, resolveComponent } from 'vue'
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
defineOptions({
|
|
5
|
+
inheritAttrs: false,
|
|
6
|
+
})
|
|
7
|
+
|
|
8
|
+
const {
|
|
9
|
+
is = 'label',
|
|
10
|
+
name,
|
|
11
|
+
...props
|
|
12
|
+
} = defineProps<{
|
|
13
|
+
is?: string
|
|
6
14
|
name?: string
|
|
7
15
|
active?: boolean
|
|
8
16
|
disabled?: boolean
|
|
9
17
|
}>()
|
|
10
18
|
|
|
19
|
+
const NuxtLink = resolveComponent('NuxtLink')
|
|
20
|
+
const RouterLink = resolveComponent('RouterLink')
|
|
21
|
+
|
|
22
|
+
const resolvedComponent = computed(() => {
|
|
23
|
+
if (is === 'NuxtLink') return NuxtLink
|
|
24
|
+
if (is === 'RouterLink') return RouterLink
|
|
25
|
+
return is
|
|
26
|
+
})
|
|
27
|
+
|
|
11
28
|
const tabManager: any = inject('tabManager')
|
|
12
29
|
if (!tabManager.currentTab.value) {
|
|
13
30
|
tabManager.currentTab.value = name
|
|
@@ -16,7 +33,8 @@ if (!tabManager.currentTab.value) {
|
|
|
16
33
|
|
|
17
34
|
<template>
|
|
18
35
|
<component
|
|
19
|
-
:is="
|
|
36
|
+
:is="resolvedComponent"
|
|
37
|
+
v-bind="$attrs"
|
|
20
38
|
class="tab"
|
|
21
39
|
:class="{
|
|
22
40
|
'tab-active': props.active || tabManager.currentTab.value === name,
|
|
@@ -30,7 +48,7 @@ if (!tabManager.currentTab.value) {
|
|
|
30
48
|
:value="name"
|
|
31
49
|
:checked="tabManager.currentTab.value === name"
|
|
32
50
|
@change="() => (tabManager.currentTab.value = name)"
|
|
33
|
-
|
|
51
|
+
/>
|
|
34
52
|
|
|
35
53
|
<slot v-if="$slots.default" />
|
|
36
54
|
<span v-else>{{ name }}</span>
|
package/app/components/Text.vue
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
import { computed, resolveComponent } from 'vue'
|
|
3
|
+
|
|
4
|
+
defineOptions({
|
|
5
|
+
inheritAttrs: false,
|
|
6
|
+
})
|
|
7
|
+
|
|
2
8
|
const props = defineProps<{
|
|
3
9
|
is?: string
|
|
4
10
|
join?: boolean
|
|
@@ -8,7 +14,23 @@ const props = defineProps<{
|
|
|
8
14
|
inlineBlock?: boolean
|
|
9
15
|
label?: boolean
|
|
10
16
|
|
|
11
|
-
color?:
|
|
17
|
+
color?:
|
|
18
|
+
| 'neutral'
|
|
19
|
+
| 'primary'
|
|
20
|
+
| 'secondary'
|
|
21
|
+
| 'accent'
|
|
22
|
+
| 'info'
|
|
23
|
+
| 'success'
|
|
24
|
+
| 'warning'
|
|
25
|
+
| 'error'
|
|
26
|
+
| 'primary-content'
|
|
27
|
+
| 'secondary-content'
|
|
28
|
+
| 'neutral-content'
|
|
29
|
+
| 'accent-content'
|
|
30
|
+
| 'info-content'
|
|
31
|
+
| 'success-content'
|
|
32
|
+
| 'warning-content'
|
|
33
|
+
| 'error-content'
|
|
12
34
|
neutral?: boolean
|
|
13
35
|
primary?: boolean
|
|
14
36
|
secondary?: boolean
|
|
@@ -26,7 +48,7 @@ const props = defineProps<{
|
|
|
26
48
|
warningContent?: boolean
|
|
27
49
|
errorContent?: boolean
|
|
28
50
|
|
|
29
|
-
size?:
|
|
51
|
+
size?: '9xl' | '8xl' | '7xl' | '6xl' | '5xl' | '4xl' | '3xl' | '2xl' | 'xl' | 'lg' | 'md' | 'sm' | 'xs'
|
|
30
52
|
xl?: boolean
|
|
31
53
|
lg?: boolean
|
|
32
54
|
md?: boolean
|
|
@@ -50,7 +72,7 @@ const props = defineProps<{
|
|
|
50
72
|
serif?: boolean
|
|
51
73
|
mono?: boolean
|
|
52
74
|
|
|
53
|
-
weight?:
|
|
75
|
+
weight?: 'thin' | 'extralight' | 'light' | 'normal' | 'medium' | 'semibold' | 'bold' | 'extrabold' | 'black'
|
|
54
76
|
thin?: boolean
|
|
55
77
|
extralight?: boolean
|
|
56
78
|
light?: boolean
|
|
@@ -61,40 +83,42 @@ const props = defineProps<{
|
|
|
61
83
|
extrabold?: boolean
|
|
62
84
|
black?: boolean
|
|
63
85
|
}>()
|
|
86
|
+
const NuxtLink = resolveComponent('NuxtLink')
|
|
87
|
+
const RouterLink = resolveComponent('RouterLink')
|
|
88
|
+
|
|
89
|
+
const resolvedComponent = computed(() => {
|
|
90
|
+
if (props.is === 'NuxtLink') return NuxtLink
|
|
91
|
+
if (props.is === 'RouterLink') return RouterLink
|
|
92
|
+
return props.is || 'span'
|
|
93
|
+
})
|
|
64
94
|
</script>
|
|
65
95
|
|
|
66
96
|
<template>
|
|
67
97
|
<component
|
|
68
|
-
:is="
|
|
69
|
-
v-bind="label ? { 'data-role': 'label' } : {}"
|
|
98
|
+
:is="resolvedComponent"
|
|
99
|
+
v-bind="{ ...$attrs, ...(label ? { 'data-role': 'label' } : {}) }"
|
|
70
100
|
:class="{
|
|
71
101
|
'join-item': join,
|
|
72
102
|
|
|
73
|
-
|
|
74
|
-
|
|
103
|
+
block,
|
|
104
|
+
inline,
|
|
75
105
|
'inline-block': inlineBlock,
|
|
76
|
-
|
|
106
|
+
label,
|
|
77
107
|
|
|
78
108
|
'text-primary': primary || color === 'primary',
|
|
79
|
-
'text-primary-content':
|
|
80
|
-
primaryContent || color === 'primary-content',
|
|
109
|
+
'text-primary-content': primaryContent || color === 'primary-content',
|
|
81
110
|
'text-secondary': secondary || color === 'secondary',
|
|
82
|
-
'text-secondary-content':
|
|
83
|
-
secondaryContent || color === 'secondary-content',
|
|
111
|
+
'text-secondary-content': secondaryContent || color === 'secondary-content',
|
|
84
112
|
'text-neutral': neutral || color === 'neutral',
|
|
85
|
-
'text-neutral-content':
|
|
86
|
-
neutralContent || color === 'neutral-content',
|
|
113
|
+
'text-neutral-content': neutralContent || color === 'neutral-content',
|
|
87
114
|
'text-accent': accent || color === 'accent',
|
|
88
|
-
'text-accent-content':
|
|
89
|
-
accentContent || color === 'accent-content',
|
|
115
|
+
'text-accent-content': accentContent || color === 'accent-content',
|
|
90
116
|
'text-info': info || color === 'info',
|
|
91
117
|
'text-info-content': infoContent || color === 'info-content',
|
|
92
118
|
'text-success': success || color === 'success',
|
|
93
|
-
'text-success-content':
|
|
94
|
-
successContent || color === 'success-content',
|
|
119
|
+
'text-success-content': successContent || color === 'success-content',
|
|
95
120
|
'text-warning': warning || color === 'warning',
|
|
96
|
-
'text-warning-content':
|
|
97
|
-
warningContent || color === 'warning-content',
|
|
121
|
+
'text-warning-content': warningContent || color === 'warning-content',
|
|
98
122
|
'text-error': error || color === 'error',
|
|
99
123
|
'text-error-content': errorContent || color === 'error-content',
|
|
100
124
|
|
|
@@ -117,9 +141,9 @@ const props = defineProps<{
|
|
|
117
141
|
'text-right': right || align === 'right',
|
|
118
142
|
'text-justify': justify || align === 'justify',
|
|
119
143
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
144
|
+
uppercase: uppercase || props.case === 'upper',
|
|
145
|
+
lowercase: lowercase || props.case === 'lower',
|
|
146
|
+
capitalize: capitalize || props.case === 'capitalize',
|
|
123
147
|
'normal-case': normalCase || props.case === 'normal',
|
|
124
148
|
|
|
125
149
|
'font-sans': sans || font === 'sans',
|
|
@@ -1,39 +1,79 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
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
|
-
|
|
2
|
+
import { nextTick, onMounted, ref, watch } from 'vue'
|
|
3
|
+
|
|
4
|
+
const props = withDefaults(
|
|
5
|
+
defineProps<{
|
|
6
|
+
modelValue?: string
|
|
7
|
+
placeholder?: string
|
|
8
|
+
type?: 'text' | 'phone' | 'email' | 'search'
|
|
9
|
+
rows?: number
|
|
10
|
+
autoExpand?: boolean
|
|
11
|
+
|
|
12
|
+
color?: string
|
|
13
|
+
neutral?: boolean
|
|
14
|
+
primary?: boolean
|
|
15
|
+
secondary?: boolean
|
|
16
|
+
accent?: boolean
|
|
17
|
+
info?: boolean
|
|
18
|
+
success?: boolean
|
|
19
|
+
warning?: boolean
|
|
20
|
+
error?: boolean
|
|
21
|
+
|
|
22
|
+
ghost?: boolean
|
|
23
|
+
disabled?: boolean
|
|
24
|
+
validator?: boolean
|
|
25
|
+
|
|
26
|
+
size?: 'xl' | 'lg' | 'md' | 'sm' | 'xs'
|
|
27
|
+
xl?: boolean
|
|
28
|
+
lg?: boolean
|
|
29
|
+
md?: boolean
|
|
30
|
+
sm?: boolean
|
|
31
|
+
xs?: boolean
|
|
32
|
+
}>(),
|
|
33
|
+
{
|
|
34
|
+
type: 'text',
|
|
35
|
+
rows: 2,
|
|
36
|
+
},
|
|
37
|
+
)
|
|
30
38
|
defineEmits(['update:modelValue'])
|
|
39
|
+
|
|
40
|
+
const textareaRef = ref<HTMLTextAreaElement | null>(null)
|
|
41
|
+
|
|
42
|
+
let minHeight = 0
|
|
43
|
+
|
|
44
|
+
function adjustHeight() {
|
|
45
|
+
if (!props.autoExpand || !textareaRef.value) return
|
|
46
|
+
const el = textareaRef.value
|
|
47
|
+
|
|
48
|
+
// Capture the initial rendered height as minimum (respects rows attribute)
|
|
49
|
+
if (minHeight === 0) {
|
|
50
|
+
minHeight = el.offsetHeight
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
el.style.height = 'auto'
|
|
54
|
+
el.style.height = `${Math.max(el.scrollHeight, minHeight)}px`
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
watch(
|
|
58
|
+
() => props.modelValue,
|
|
59
|
+
() => {
|
|
60
|
+
nextTick(adjustHeight)
|
|
61
|
+
},
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
onMounted(() => {
|
|
65
|
+
if (props.autoExpand) {
|
|
66
|
+
nextTick(adjustHeight)
|
|
67
|
+
}
|
|
68
|
+
})
|
|
31
69
|
</script>
|
|
32
70
|
|
|
33
71
|
<template>
|
|
34
72
|
<textarea
|
|
73
|
+
ref="textareaRef"
|
|
35
74
|
:value="modelValue"
|
|
36
75
|
:type="type"
|
|
76
|
+
:rows="rows"
|
|
37
77
|
:placeholder="placeholder"
|
|
38
78
|
:disabled="disabled"
|
|
39
79
|
class="textarea"
|
|
@@ -48,7 +88,7 @@ defineEmits(['update:modelValue'])
|
|
|
48
88
|
'textarea-error': props.error || props.color === 'error',
|
|
49
89
|
|
|
50
90
|
'textarea-ghost': props.ghost,
|
|
51
|
-
|
|
91
|
+
validator: props.validator,
|
|
52
92
|
|
|
53
93
|
'textarea-xl': props.xl || props.size === 'xl',
|
|
54
94
|
'textarea-lg': props.lg || props.size === 'lg',
|
|
@@ -56,6 +96,11 @@ defineEmits(['update:modelValue'])
|
|
|
56
96
|
'textarea-sm': props.sm || props.size === 'sm',
|
|
57
97
|
'textarea-xs': props.xs || props.size === 'xs',
|
|
58
98
|
}"
|
|
59
|
-
@input="
|
|
99
|
+
@input="
|
|
100
|
+
event => {
|
|
101
|
+
$emit('update:modelValue', (event.target as HTMLTextAreaElement).value)
|
|
102
|
+
adjustHeight()
|
|
103
|
+
}
|
|
104
|
+
"
|
|
60
105
|
/>
|
|
61
106
|
</template>
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { computed } from 'vue'
|
|
3
|
+
|
|
4
|
+
const props = defineProps<{
|
|
5
|
+
is?: any
|
|
6
|
+
center?: boolean
|
|
7
|
+
duration?: number
|
|
8
|
+
}>()
|
|
9
|
+
|
|
10
|
+
const style = computed(() => {
|
|
11
|
+
if (props.duration) {
|
|
12
|
+
return { animationDuration: `${props.duration}ms` }
|
|
13
|
+
}
|
|
14
|
+
return undefined
|
|
15
|
+
})
|
|
16
|
+
</script>
|
|
17
|
+
|
|
18
|
+
<template>
|
|
19
|
+
<component :is="props.is || 'span'" class="text-rotate" :style="style">
|
|
20
|
+
<span :class="{ 'justify-items-center': props.center }">
|
|
21
|
+
<slot />
|
|
22
|
+
</span>
|
|
23
|
+
</component>
|
|
24
|
+
</template>
|
|
@@ -18,16 +18,15 @@ const props = defineProps<{
|
|
|
18
18
|
storage?: <T>(key: string, initial: T) => import('vue').Ref<T>
|
|
19
19
|
}>()
|
|
20
20
|
|
|
21
|
-
const themeOptions =
|
|
22
|
-
? { themes: props.themes || [], defaultTheme: props.defaultTheme }
|
|
23
|
-
: undefined
|
|
21
|
+
const themeOptions =
|
|
22
|
+
props.themes || props.defaultTheme ? { themes: props.themes || [], defaultTheme: props.defaultTheme } : undefined
|
|
24
23
|
|
|
25
24
|
const { theme, effectiveTheme, themes, setTheme, cycleTheme, registerTheme, removeTheme } = useDaisyTheme(
|
|
26
25
|
props.storage,
|
|
27
26
|
themeOptions,
|
|
28
27
|
)
|
|
29
28
|
|
|
30
|
-
const availableThemes = computed(() => themes.value.map(t => typeof t === 'string' ? t : t.theme))
|
|
29
|
+
const availableThemes = computed(() => themes.value.map(t => (typeof t === 'string' ? t : t.theme)))
|
|
31
30
|
</script>
|
|
32
31
|
|
|
33
32
|
<template>
|
|
@@ -19,7 +19,12 @@ function cssVarToCamel(str: string): string {
|
|
|
19
19
|
function dataAttrToCamel(str: string): string {
|
|
20
20
|
return str.replace(/-([a-z0-9])/g, (_, c: string) => c.toUpperCase())
|
|
21
21
|
}
|
|
22
|
-
function parseThemeString(themeString?: string): {
|
|
22
|
+
function parseThemeString(themeString?: string): {
|
|
23
|
+
style: Record<string, string>
|
|
24
|
+
dataAttrs: Record<string, string>
|
|
25
|
+
dataTheme: string | undefined
|
|
26
|
+
allAttrs: Record<string, string>
|
|
27
|
+
} {
|
|
23
28
|
if (!themeString) {
|
|
24
29
|
return { style: {}, dataAttrs: {}, dataTheme: undefined, allAttrs: {} }
|
|
25
30
|
}
|
|
@@ -33,10 +38,14 @@ function parseThemeString(themeString?: string): { style: Record<string, string>
|
|
|
33
38
|
const allAttrs: Record<string, string> = {}
|
|
34
39
|
|
|
35
40
|
// Remove @plugin ... { and closing } if present
|
|
36
|
-
const str = themeString
|
|
41
|
+
const str = themeString
|
|
42
|
+
.trim()
|
|
43
|
+
.replace(/^@plugin[^{}]*\{/, '')
|
|
44
|
+
.replace(/\}$/, '')
|
|
45
|
+
.trim()
|
|
37
46
|
|
|
38
47
|
// works with or without newline characters
|
|
39
|
-
str.split(/[\n;]/).forEach(
|
|
48
|
+
str.split(/[\n;]/).forEach(line => {
|
|
40
49
|
const trimmed = line.trim()
|
|
41
50
|
if (!trimmed || trimmed.startsWith('//')) {
|
|
42
51
|
return
|
|
@@ -57,12 +66,10 @@ function parseThemeString(themeString?: string): { style: Record<string, string>
|
|
|
57
66
|
if (varNamePattern.test(key)) {
|
|
58
67
|
style[key] = value
|
|
59
68
|
allAttrs[cssVarToCamel(key)] = value
|
|
60
|
-
}
|
|
61
|
-
else if (key === 'name') {
|
|
69
|
+
} else if (key === 'name') {
|
|
62
70
|
dataTheme = value.replace(/"/g, '')
|
|
63
71
|
allAttrs.dataTheme = dataTheme
|
|
64
|
-
}
|
|
65
|
-
else if (attrNamePattern.test(key)) {
|
|
72
|
+
} else if (attrNamePattern.test(key)) {
|
|
66
73
|
const attrKey = `data-${key.replace(/[^\w-]/g, '')}`
|
|
67
74
|
const attrVal = value.replace(/"/g, '')
|
|
68
75
|
dataAttrs[attrKey] = attrVal
|
|
@@ -78,7 +85,7 @@ const parsed = computed(() => parseThemeString(props.dataTheme ?? props.cssVars)
|
|
|
78
85
|
|
|
79
86
|
const themeVars = ref<Record<string, string>>({})
|
|
80
87
|
let observers: MutationObserver[] = []
|
|
81
|
-
let themeControllerInputs: Array<{ el: HTMLInputElement
|
|
88
|
+
let themeControllerInputs: Array<{ el: HTMLInputElement; listener: () => void }> = []
|
|
82
89
|
let themeControllerDomObserver: MutationObserver | null = null
|
|
83
90
|
|
|
84
91
|
// Converts a themeAttrs object to a DaisyUI theme string
|
|
@@ -88,15 +95,16 @@ function toThemeString(attrs: Record<string, string>, opts?: { asPlugin?: boolea
|
|
|
88
95
|
for (const [key, value] of Object.entries(attrs)) {
|
|
89
96
|
if (key === 'dataTheme') {
|
|
90
97
|
lines.push(`name: "${value}";`)
|
|
91
|
-
}
|
|
92
|
-
else if (key.startsWith('data')) {
|
|
98
|
+
} else if (key.startsWith('data')) {
|
|
93
99
|
// Convert dataFooBar -> foo-bar
|
|
94
|
-
const attr = key
|
|
100
|
+
const attr = key
|
|
101
|
+
.slice(4)
|
|
102
|
+
.replace(/([A-Z])/g, '-$1')
|
|
103
|
+
.toLowerCase()
|
|
95
104
|
if (attr !== 'theme') {
|
|
96
105
|
lines.push(`${attr}: ${value};`)
|
|
97
106
|
}
|
|
98
|
-
}
|
|
99
|
-
else {
|
|
107
|
+
} else {
|
|
100
108
|
// Convert camelCase to --kebab-case
|
|
101
109
|
const cssVar = `--${key.replace(/([A-Z])/g, '-$1').toLowerCase()}`
|
|
102
110
|
lines.push(`${cssVar}: ${value};`)
|
|
@@ -207,8 +215,10 @@ function setupSnoop(rootEl: HTMLElement): void {
|
|
|
207
215
|
})
|
|
208
216
|
themeControllerInputs = []
|
|
209
217
|
// Find all matching inputs in the document
|
|
210
|
-
const inputs = Array.from(
|
|
211
|
-
|
|
218
|
+
const inputs = Array.from(
|
|
219
|
+
document.querySelectorAll('input[type="checkbox"].theme-controller, input[type="radio"].theme-controller'),
|
|
220
|
+
) as HTMLInputElement[]
|
|
221
|
+
inputs.forEach(el => {
|
|
212
222
|
const listener = () => updateVars()
|
|
213
223
|
el.addEventListener('change', listener)
|
|
214
224
|
themeControllerInputs.push({ el, listener })
|
|
@@ -226,9 +236,13 @@ function setupSnoop(rootEl: HTMLElement): void {
|
|
|
226
236
|
themeControllerDomObserver.observe(document.body, { childList: true, subtree: true })
|
|
227
237
|
|
|
228
238
|
// Watch for applied style changes (parsed.style)
|
|
229
|
-
watch(
|
|
230
|
-
|
|
231
|
-
|
|
239
|
+
watch(
|
|
240
|
+
() => parsed.value.style,
|
|
241
|
+
() => {
|
|
242
|
+
nextTick(() => updateVars())
|
|
243
|
+
},
|
|
244
|
+
{ immediate: false, deep: true },
|
|
245
|
+
)
|
|
232
246
|
updateVars()
|
|
233
247
|
}
|
|
234
248
|
|
|
@@ -236,21 +250,22 @@ const rootEl = ref<HTMLElement | null>(null)
|
|
|
236
250
|
|
|
237
251
|
const isClient = typeof window !== 'undefined' && typeof document !== 'undefined'
|
|
238
252
|
|
|
239
|
-
watch(
|
|
240
|
-
() => props.snoop,
|
|
241
|
-
() =>
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
}
|
|
253
|
+
watch(
|
|
254
|
+
[() => props.snoop, () => rootEl.value],
|
|
255
|
+
([snoop, el]) => {
|
|
256
|
+
if (isClient) {
|
|
257
|
+
// Clean up previous observers if any
|
|
258
|
+
observers.forEach((o: MutationObserver) => o.disconnect())
|
|
259
|
+
observers = []
|
|
260
|
+
if (snoop && el) {
|
|
261
|
+
nextTick(() => {
|
|
262
|
+
setupSnoop(el)
|
|
263
|
+
})
|
|
264
|
+
}
|
|
251
265
|
}
|
|
252
|
-
}
|
|
253
|
-
|
|
266
|
+
},
|
|
267
|
+
{ immediate: true },
|
|
268
|
+
)
|
|
254
269
|
|
|
255
270
|
onUnmounted(() => {
|
|
256
271
|
observers.forEach((o: MutationObserver) => o.disconnect())
|
package/app/components/Toast.vue
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import type { Toast } from '
|
|
2
|
+
import type { Toast } from '../composables/use-toast'
|
|
3
3
|
import { computed } from 'vue'
|
|
4
|
-
import { useToast } from '
|
|
4
|
+
import { useToast } from '../composables/use-toast'
|
|
5
5
|
|
|
6
6
|
// Explicit slot typing (Vue 3.4+ / Volar)
|
|
7
7
|
interface ToastSlotProps {
|
|
@@ -61,12 +61,7 @@ const visibleToasts = computed(() => toasts.value ?? [])
|
|
|
61
61
|
'toast-bottom': props.bottom || props.vAlign === 'bottom',
|
|
62
62
|
}"
|
|
63
63
|
>
|
|
64
|
-
<slot
|
|
65
|
-
v-for="toast in visibleToasts"
|
|
66
|
-
:key="toast.id"
|
|
67
|
-
:toast="toast"
|
|
68
|
-
:remove-toast="removeToast"
|
|
69
|
-
/>
|
|
64
|
+
<slot v-for="toast in visibleToasts" :key="toast.id" :toast="toast" :remove-toast="removeToast" />
|
|
70
65
|
<slot />
|
|
71
66
|
</div>
|
|
72
67
|
</template>
|
|
@@ -40,7 +40,7 @@ const currentValue = computed({
|
|
|
40
40
|
class="toggle"
|
|
41
41
|
:disabled="disabled"
|
|
42
42
|
:class="{
|
|
43
|
-
|
|
43
|
+
validator,
|
|
44
44
|
'toggle-neutral': neutral || color === 'neutral',
|
|
45
45
|
'toggle-primary': primary || color === 'primary',
|
|
46
46
|
'toggle-secondary': secondary || color === 'secondary',
|
|
@@ -56,5 +56,5 @@ const currentValue = computed({
|
|
|
56
56
|
'toggle-xl': xl || size === 'xl',
|
|
57
57
|
'theme-controller': themeController,
|
|
58
58
|
}"
|
|
59
|
-
|
|
59
|
+
/>
|
|
60
60
|
</template>
|