daisy-ui-kit 5.0.0-pre.3 → 5.0.0-pre.30
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 +29 -0
- package/app/components/Alert.vue +36 -0
- package/app/components/Avatar.vue +131 -0
- package/app/components/AvatarGroup.vue +22 -0
- package/app/components/Badge.vue +72 -0
- package/app/components/Breadcrumbs.vue +7 -0
- package/app/components/Button.vue +140 -0
- package/app/components/Calendar.vue +175 -0
- package/app/components/CalendarInput.vue +275 -0
- package/app/components/CalendarSkeleton.vue +87 -0
- package/app/components/Card.vue +51 -0
- package/app/components/CardActions.vue +13 -0
- package/app/components/CardBody.vue +13 -0
- package/app/components/CardTitle.vue +11 -0
- package/app/components/Carousel.vue +24 -0
- package/app/components/CarouselItem.vue +5 -0
- package/app/components/Chat.vue +26 -0
- package/app/components/ChatBubble.vue +31 -0
- package/app/components/ChatFooter.vue +5 -0
- package/app/components/ChatHeader.vue +5 -0
- package/app/components/ChatImage.vue +5 -0
- package/app/components/Checkbox.vue +51 -0
- package/app/components/Collapse.vue +75 -0
- package/app/components/CollapseContent.vue +5 -0
- package/app/components/CollapseTitle.vue +15 -0
- package/app/components/Countdown.vue +15 -0
- package/app/components/CountdownTimers.vue +69 -0
- package/app/components/Counter.vue +21 -0
- package/app/components/Crumb.vue +5 -0
- package/app/components/DaisyLink.vue +56 -0
- package/app/components/Diff.vue +11 -0
- package/app/components/Divider.vue +43 -0
- package/app/components/Dock.vue +57 -0
- package/app/components/DockItem.vue +27 -0
- package/app/components/DockLabel.vue +5 -0
- package/app/components/Drawer.vue +50 -0
- package/app/components/DrawerContent.vue +20 -0
- package/app/components/DrawerSide.vue +21 -0
- package/app/components/Dropdown.vue +106 -0
- package/app/components/DropdownButton.vue +23 -0
- package/app/components/DropdownContent.vue +127 -0
- package/app/components/DropdownTarget.vue +21 -0
- 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 +20 -0
- package/app/components/FileInput.vue +53 -0
- package/app/components/Filter.vue +129 -0
- package/app/components/Flex.vue +89 -0
- package/app/components/FlexItem.vue +62 -0
- package/app/components/Footer.vue +31 -0
- package/app/components/FooterTitle.vue +18 -0
- package/app/components/FormControl.vue +5 -0
- package/app/components/Hero.vue +18 -0
- package/app/components/HeroContent.vue +18 -0
- package/app/components/HeroOverlay.vue +5 -0
- package/app/components/Hover3D.vue +22 -0
- package/app/components/HoverGallery.vue +11 -0
- package/app/components/Indicator.vue +20 -0
- package/app/components/IndicatorItem.vue +43 -0
- package/app/components/Input.vue +116 -0
- package/app/components/Join.vue +5 -0
- package/app/components/Kbd.vue +25 -0
- package/app/components/Label.vue +100 -0
- package/app/components/List.vue +5 -0
- package/app/components/ListColGrow.vue +5 -0
- package/app/components/ListColWrap.vue +5 -0
- package/app/components/ListRow.vue +5 -0
- package/app/components/LoadingBall.vue +42 -0
- package/app/components/LoadingBars.vue +42 -0
- package/app/components/LoadingDots.vue +42 -0
- package/app/components/LoadingInfinity.vue +42 -0
- package/app/components/LoadingRing.vue +42 -0
- package/app/components/LoadingSpinner.vue +42 -0
- package/app/components/Mask.vue +49 -0
- package/app/components/Menu.vue +30 -0
- package/app/components/MenuExpand.vue +92 -0
- package/app/components/MenuExpandToggle.vue +20 -0
- package/app/components/MenuItem.vue +39 -0
- package/app/components/MenuTitle.vue +5 -0
- package/app/components/MockupBrowser.vue +5 -0
- package/app/components/MockupBrowserToolbar.vue +5 -0
- package/app/components/MockupCode.vue +4 -0
- package/app/components/MockupPhone.vue +14 -0
- package/app/components/MockupWindow.vue +5 -0
- package/app/components/Modal.vue +63 -0
- package/app/components/ModalAction.vue +5 -0
- package/app/components/ModalBox.vue +5 -0
- package/app/components/NavButton.vue +12 -0
- package/app/components/Navbar.vue +12 -0
- package/app/components/NavbarCenter.vue +11 -0
- package/app/components/NavbarEnd.vue +11 -0
- package/app/components/NavbarStart.vue +11 -0
- package/app/components/Progress.vue +46 -0
- package/app/components/Prose.vue +37 -0
- package/app/components/RadialProgress.vue +36 -0
- package/app/components/Radio.vue +69 -0
- package/app/components/RadioGroup.vue +47 -0
- package/app/components/Range.vue +201 -0
- package/app/components/RangeMeasure.vue +87 -0
- package/app/components/RangeMeasureTick.vue +69 -0
- package/app/components/Rating.vue +197 -0
- package/app/components/Select.vue +101 -0
- package/app/components/Skeleton.vue +5 -0
- package/app/components/SkeletonText.vue +11 -0
- package/app/components/Stack.vue +30 -0
- package/app/components/Stat.vue +19 -0
- package/app/components/StatActions.vue +5 -0
- package/app/components/StatDesc.vue +5 -0
- package/app/components/StatFigure.vue +5 -0
- package/app/components/StatTitle.vue +5 -0
- package/app/components/StatValue.vue +5 -0
- package/app/components/Stats.vue +5 -0
- package/app/components/Status.vue +43 -0
- package/app/components/Step.vue +34 -0
- package/app/components/StepIcon.vue +5 -0
- package/app/components/Steps.vue +23 -0
- package/app/components/Swap.vue +56 -0
- package/app/components/Tab.vue +56 -0
- package/app/components/TabContent.vue +29 -0
- package/app/components/Table.vue +32 -0
- package/app/components/Tabs.vue +53 -0
- package/app/components/Text.vue +166 -0
- package/app/components/TextArea.vue +106 -0
- package/app/components/TextRotate.vue +24 -0
- package/app/components/ThemeController.vue +45 -0
- package/app/components/ThemeProvider.vue +302 -0
- package/app/components/ThemeTile.vue +50 -0
- package/app/components/Timeline.vue +22 -0
- package/app/components/TimelineEnd.vue +14 -0
- package/app/components/TimelineItem.vue +5 -0
- package/app/components/TimelineLine.vue +29 -0
- package/app/components/TimelineMiddle.vue +5 -0
- package/app/components/TimelineStart.vue +14 -0
- package/app/components/Toast.vue +67 -0
- package/app/components/Toggle.vue +60 -0
- package/app/components/Tooltip.vue +137 -0
- package/app/components/TooltipContent.vue +283 -0
- package/app/components/TooltipTarget.vue +20 -0
- package/app/components/ValidatorHint.vue +5 -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 +131 -0
- package/app/composables/use-toast.ts +345 -0
- package/app/composables/useSearch.ts +22 -0
- package/app/utils/drawer-utils.ts +34 -0
- package/app/utils/position-area.ts +40 -0
- package/nuxt.d.ts +13 -0
- package/nuxt.js +31 -0
- package/package.json +50 -22
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { CalendarOptions } from '../composables/use-calendar'
|
|
3
|
+
import { computed, ref, useId, watch } from 'vue'
|
|
4
|
+
import { useCalendar } from '../composables/use-calendar'
|
|
5
|
+
|
|
6
|
+
const props = defineProps<{
|
|
7
|
+
/** Bound value: Date object or ISO string or null */
|
|
8
|
+
modelValue?: Date | string | number | null
|
|
9
|
+
/** Calendar options */
|
|
10
|
+
options?: CalendarOptions
|
|
11
|
+
/** If true, default to today when no value provided */
|
|
12
|
+
autoDefault?: boolean
|
|
13
|
+
placeholder?: string
|
|
14
|
+
disabled?: boolean
|
|
15
|
+
validator?: boolean
|
|
16
|
+
join?: boolean
|
|
17
|
+
color?: string
|
|
18
|
+
primary?: boolean
|
|
19
|
+
secondary?: boolean
|
|
20
|
+
accent?: boolean
|
|
21
|
+
info?: boolean
|
|
22
|
+
success?: boolean
|
|
23
|
+
warning?: boolean
|
|
24
|
+
error?: boolean
|
|
25
|
+
ghost?: boolean
|
|
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
|
+
const emit = defineEmits<{
|
|
35
|
+
(e: 'update:modelValue', v: Date | null): void
|
|
36
|
+
(e: 'update:inputValue', v: string | null): void
|
|
37
|
+
}>()
|
|
38
|
+
|
|
39
|
+
const uniqueId = useId()
|
|
40
|
+
const popoverId = `calendar-popover-${uniqueId}`
|
|
41
|
+
const anchorName = `--calendar-anchor-${uniqueId}`
|
|
42
|
+
const inputRef = ref<HTMLInputElement | null>(null)
|
|
43
|
+
const popoverRef = ref<HTMLElement | null>(null)
|
|
44
|
+
|
|
45
|
+
// Parse date from various input types
|
|
46
|
+
function parseDate(value: Date | string | number | null | undefined): Date | null {
|
|
47
|
+
if (!value) return null
|
|
48
|
+
if (value instanceof Date) return value
|
|
49
|
+
const d = new Date(value)
|
|
50
|
+
return Number.isNaN(d.getTime()) ? null : d
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const initialDate = computed(() => {
|
|
54
|
+
const parsed = parseDate(props.modelValue)
|
|
55
|
+
if (parsed) return parsed
|
|
56
|
+
if (props.autoDefault) return new Date()
|
|
57
|
+
return null
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
const {
|
|
61
|
+
selectedDate,
|
|
62
|
+
viewMonth,
|
|
63
|
+
viewYear,
|
|
64
|
+
monthName,
|
|
65
|
+
weekdayHeaders,
|
|
66
|
+
weekdayHeadersFull,
|
|
67
|
+
calendarDays,
|
|
68
|
+
prevMonth,
|
|
69
|
+
nextMonth,
|
|
70
|
+
selectDate,
|
|
71
|
+
goToDate,
|
|
72
|
+
formatDate,
|
|
73
|
+
} = useCalendar(initialDate.value, props.options)
|
|
74
|
+
|
|
75
|
+
// Input display value
|
|
76
|
+
const inputValue = computed(() => formatDate('D MMM YYYY'))
|
|
77
|
+
|
|
78
|
+
// Sync selectedDate back to modelValue
|
|
79
|
+
watch(selectedDate, date => {
|
|
80
|
+
emit('update:modelValue', date)
|
|
81
|
+
emit('update:inputValue', formatDate('D MMM YYYY'))
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
// Watch for external modelValue changes
|
|
85
|
+
watch(
|
|
86
|
+
() => props.modelValue,
|
|
87
|
+
newValue => {
|
|
88
|
+
const parsed = parseDate(newValue)
|
|
89
|
+
if (parsed && (!selectedDate.value || parsed.getTime() !== selectedDate.value.getTime())) {
|
|
90
|
+
selectDate(parsed)
|
|
91
|
+
goToDate(parsed)
|
|
92
|
+
} else if (!newValue && selectedDate.value) {
|
|
93
|
+
selectedDate.value = null
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
function handleDayClick(day: (typeof calendarDays.value)[0]) {
|
|
99
|
+
if (day.isDisabled) return
|
|
100
|
+
selectDate(day.date)
|
|
101
|
+
popoverRef.value?.hidePopover()
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function handleClick() {
|
|
105
|
+
// Sync view to selected date when opening
|
|
106
|
+
if (selectedDate.value) {
|
|
107
|
+
goToDate(selectedDate.value)
|
|
108
|
+
}
|
|
109
|
+
popoverRef.value?.togglePopover()
|
|
110
|
+
}
|
|
111
|
+
</script>
|
|
112
|
+
|
|
113
|
+
<template>
|
|
114
|
+
<div class="relative inline-block">
|
|
115
|
+
<input
|
|
116
|
+
ref="inputRef"
|
|
117
|
+
type="text"
|
|
118
|
+
readonly
|
|
119
|
+
:value="inputValue"
|
|
120
|
+
:placeholder="props.placeholder"
|
|
121
|
+
:disabled="props.disabled"
|
|
122
|
+
class="input cursor-pointer"
|
|
123
|
+
:class="[
|
|
124
|
+
{ validator: props.validator },
|
|
125
|
+
{ 'input-primary': props.primary || props.color === 'primary' },
|
|
126
|
+
{ 'input-secondary': props.secondary || props.color === 'secondary' },
|
|
127
|
+
{ 'input-accent': props.accent || props.color === 'accent' },
|
|
128
|
+
{ 'input-info': props.info || props.color === 'info' },
|
|
129
|
+
{ 'input-success': props.success || props.color === 'success' },
|
|
130
|
+
{ 'input-warning': props.warning || props.color === 'warning' },
|
|
131
|
+
{ 'input-error': props.error || props.color === 'error' },
|
|
132
|
+
{ 'input-ghost': props.ghost },
|
|
133
|
+
{ 'input-xl': props.xl || props.size === 'xl' },
|
|
134
|
+
{ 'input-lg': props.lg || props.size === 'lg' },
|
|
135
|
+
{ 'input-md': props.md || props.size === 'md' },
|
|
136
|
+
{ 'input-sm': props.sm || props.size === 'sm' },
|
|
137
|
+
{ 'input-xs': props.xs || props.size === 'xs' },
|
|
138
|
+
{ 'join-item': props.join },
|
|
139
|
+
]"
|
|
140
|
+
:style="{ 'anchor-name': anchorName } as any"
|
|
141
|
+
v-bind="$attrs"
|
|
142
|
+
@click="handleClick"
|
|
143
|
+
/>
|
|
144
|
+
|
|
145
|
+
<!-- Dropdown calendar using Popover API -->
|
|
146
|
+
<div
|
|
147
|
+
:id="popoverId"
|
|
148
|
+
ref="popoverRef"
|
|
149
|
+
popover="auto"
|
|
150
|
+
class="pika-single calendar-popover"
|
|
151
|
+
:style="{ 'position-anchor': anchorName } as any"
|
|
152
|
+
>
|
|
153
|
+
<div class="pika-lendar">
|
|
154
|
+
<!-- Header with navigation -->
|
|
155
|
+
<div class="pika-title">
|
|
156
|
+
<div class="pika-label">
|
|
157
|
+
{{ monthName }}
|
|
158
|
+
<select
|
|
159
|
+
class="pika-select pika-select-month"
|
|
160
|
+
:value="viewMonth"
|
|
161
|
+
@change="
|
|
162
|
+
e => {
|
|
163
|
+
const target = e.target as HTMLSelectElement
|
|
164
|
+
const newMonth = parseInt(target.value, 10)
|
|
165
|
+
const d = new Date(viewYear, newMonth, 1)
|
|
166
|
+
goToDate(d)
|
|
167
|
+
}
|
|
168
|
+
"
|
|
169
|
+
>
|
|
170
|
+
<option
|
|
171
|
+
v-for="(m, i) in [
|
|
172
|
+
'January',
|
|
173
|
+
'February',
|
|
174
|
+
'March',
|
|
175
|
+
'April',
|
|
176
|
+
'May',
|
|
177
|
+
'June',
|
|
178
|
+
'July',
|
|
179
|
+
'August',
|
|
180
|
+
'September',
|
|
181
|
+
'October',
|
|
182
|
+
'November',
|
|
183
|
+
'December',
|
|
184
|
+
]"
|
|
185
|
+
:key="i"
|
|
186
|
+
:value="i"
|
|
187
|
+
>
|
|
188
|
+
{{ m }}
|
|
189
|
+
</option>
|
|
190
|
+
</select>
|
|
191
|
+
</div>
|
|
192
|
+
<div class="pika-label">
|
|
193
|
+
{{ viewYear }}
|
|
194
|
+
<select
|
|
195
|
+
class="pika-select pika-select-year"
|
|
196
|
+
:value="viewYear"
|
|
197
|
+
@change="
|
|
198
|
+
e => {
|
|
199
|
+
const target = e.target as HTMLSelectElement
|
|
200
|
+
const newYear = parseInt(target.value, 10)
|
|
201
|
+
const d = new Date(newYear, viewMonth, 1)
|
|
202
|
+
goToDate(d)
|
|
203
|
+
}
|
|
204
|
+
"
|
|
205
|
+
>
|
|
206
|
+
<option v-for="y in Array.from({ length: 21 }, (_, i) => viewYear - 10 + i)" :key="y" :value="y">
|
|
207
|
+
{{ y }}
|
|
208
|
+
</option>
|
|
209
|
+
</select>
|
|
210
|
+
</div>
|
|
211
|
+
<button type="button" class="pika-prev" @click="prevMonth">Previous Month</button>
|
|
212
|
+
<button type="button" class="pika-next" @click="nextMonth">Next Month</button>
|
|
213
|
+
</div>
|
|
214
|
+
|
|
215
|
+
<!-- Calendar grid -->
|
|
216
|
+
<table class="pika-table" role="grid">
|
|
217
|
+
<thead>
|
|
218
|
+
<tr>
|
|
219
|
+
<th v-for="(day, i) in weekdayHeaders" :key="i" scope="col">
|
|
220
|
+
<abbr :title="weekdayHeadersFull[i]">{{ day }}</abbr>
|
|
221
|
+
</th>
|
|
222
|
+
</tr>
|
|
223
|
+
</thead>
|
|
224
|
+
<tbody>
|
|
225
|
+
<tr v-for="week in 6" :key="week" class="pika-row">
|
|
226
|
+
<td
|
|
227
|
+
v-for="dayIndex in 7"
|
|
228
|
+
:key="dayIndex"
|
|
229
|
+
:class="{
|
|
230
|
+
'is-today': calendarDays[(week - 1) * 7 + dayIndex - 1]?.isToday,
|
|
231
|
+
'is-selected': calendarDays[(week - 1) * 7 + dayIndex - 1]?.isSelected,
|
|
232
|
+
'is-disabled': calendarDays[(week - 1) * 7 + dayIndex - 1]?.isDisabled,
|
|
233
|
+
'is-outside-current-month': calendarDays[(week - 1) * 7 + dayIndex - 1]?.isOutsideMonth,
|
|
234
|
+
}"
|
|
235
|
+
:aria-selected="calendarDays[(week - 1) * 7 + dayIndex - 1]?.isSelected"
|
|
236
|
+
>
|
|
237
|
+
<button
|
|
238
|
+
type="button"
|
|
239
|
+
class="pika-button pika-day"
|
|
240
|
+
:disabled="calendarDays[(week - 1) * 7 + dayIndex - 1]?.isDisabled"
|
|
241
|
+
@click="handleDayClick(calendarDays[(week - 1) * 7 + dayIndex - 1]!)"
|
|
242
|
+
>
|
|
243
|
+
{{ calendarDays[(week - 1) * 7 + dayIndex - 1]?.day }}
|
|
244
|
+
</button>
|
|
245
|
+
</td>
|
|
246
|
+
</tr>
|
|
247
|
+
</tbody>
|
|
248
|
+
</table>
|
|
249
|
+
</div>
|
|
250
|
+
</div>
|
|
251
|
+
</div>
|
|
252
|
+
</template>
|
|
253
|
+
|
|
254
|
+
<style>
|
|
255
|
+
.calendar-popover[popover] {
|
|
256
|
+
position-area: block-end span-inline-end;
|
|
257
|
+
position-try-fallbacks:
|
|
258
|
+
flip-block,
|
|
259
|
+
flip-inline,
|
|
260
|
+
flip-block flip-inline;
|
|
261
|
+
margin: 0;
|
|
262
|
+
margin-top: 0.25rem;
|
|
263
|
+
/* Reset default popover styles */
|
|
264
|
+
border: none;
|
|
265
|
+
inset: auto;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
.calendar-popover[popover]:popover-open {
|
|
269
|
+
position: fixed;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
.calendar-popover[popover]:not(:popover-open) {
|
|
273
|
+
display: none;
|
|
274
|
+
}
|
|
275
|
+
</style>
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import Skeleton from './Skeleton.vue'
|
|
3
|
+
|
|
4
|
+
const props = defineProps<{
|
|
5
|
+
numberOfMonths?: number
|
|
6
|
+
date?: Date
|
|
7
|
+
firstDay?: number // 0 = Sunday, 1 = Monday, etc. (matches Pikaday's firstDay option)
|
|
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
|
+
})
|
|
48
|
+
</script>
|
|
49
|
+
|
|
50
|
+
<template>
|
|
51
|
+
<Skeleton col class="bg-base-200 rounded-box">
|
|
52
|
+
<div
|
|
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"
|
|
56
|
+
:class="{
|
|
57
|
+
'-mt-3.5': idx > 0,
|
|
58
|
+
}"
|
|
59
|
+
>
|
|
60
|
+
<Flex justify-between items-center class="mb-3 px-2">
|
|
61
|
+
<span
|
|
62
|
+
class="size-4 rounded-full bg-base-300 inline-block"
|
|
63
|
+
:class="{
|
|
64
|
+
'bg-base-300': idx === 0,
|
|
65
|
+
'bg-transparent': idx !== 0,
|
|
66
|
+
}"
|
|
67
|
+
/>
|
|
68
|
+
<span class="h-5 w-20 rounded-full bg-base-300 inline-block" />
|
|
69
|
+
<span
|
|
70
|
+
class="size-4 rounded-full bg-base-300 inline-block"
|
|
71
|
+
:class="{
|
|
72
|
+
'bg-base-300': idx === weeksPerMonth.length - 1,
|
|
73
|
+
'bg-transparent': idx !== weeksPerMonth.length - 1,
|
|
74
|
+
}"
|
|
75
|
+
/>
|
|
76
|
+
</Flex>
|
|
77
|
+
<Flex col class="h-full">
|
|
78
|
+
<div class="grid grid-cols-7 gap-[4px] mb-3 flex-shrink-0">
|
|
79
|
+
<span v-for="d in 7" :key="`dow-${d}`" class="size-4 rounded-full bg-base-300 mx-auto block" />
|
|
80
|
+
</div>
|
|
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" />
|
|
83
|
+
</div>
|
|
84
|
+
</Flex>
|
|
85
|
+
</div>
|
|
86
|
+
</Skeleton>
|
|
87
|
+
</template>
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { computed, resolveComponent } from 'vue'
|
|
3
|
+
|
|
4
|
+
defineOptions({
|
|
5
|
+
inheritAttrs: false,
|
|
6
|
+
})
|
|
7
|
+
|
|
8
|
+
const { is = 'div', ...props } = defineProps<{
|
|
9
|
+
is?: string
|
|
10
|
+
border?: boolean
|
|
11
|
+
dash?: boolean
|
|
12
|
+
side?: boolean
|
|
13
|
+
imageFull?: boolean
|
|
14
|
+
size?: 'xl' | 'lg' | 'md' | 'sm' | 'xs'
|
|
15
|
+
xl?: boolean
|
|
16
|
+
lg?: boolean
|
|
17
|
+
md?: boolean
|
|
18
|
+
sm?: boolean
|
|
19
|
+
xs?: boolean
|
|
20
|
+
}>()
|
|
21
|
+
|
|
22
|
+
const NuxtLink = resolveComponent('NuxtLink')
|
|
23
|
+
const RouterLink = resolveComponent('RouterLink')
|
|
24
|
+
|
|
25
|
+
const resolvedComponent = computed(() => {
|
|
26
|
+
if (is === 'NuxtLink') return NuxtLink
|
|
27
|
+
if (is === 'RouterLink') return RouterLink
|
|
28
|
+
return is
|
|
29
|
+
})
|
|
30
|
+
</script>
|
|
31
|
+
|
|
32
|
+
<template>
|
|
33
|
+
<component
|
|
34
|
+
:is="resolvedComponent"
|
|
35
|
+
v-bind="$attrs"
|
|
36
|
+
class="card"
|
|
37
|
+
:class="{
|
|
38
|
+
'card-border': props.border,
|
|
39
|
+
'card-side': props.side,
|
|
40
|
+
'image-full': props.imageFull,
|
|
41
|
+
|
|
42
|
+
'card-xl': props.xl || props.size === 'xl',
|
|
43
|
+
'card-lg': props.lg || props.size === 'lg',
|
|
44
|
+
'card-md': props.md || props.size === 'md',
|
|
45
|
+
'card-sm': props.sm || props.size === 'sm',
|
|
46
|
+
'card-xs': props.xs || props.size === 'xs',
|
|
47
|
+
}"
|
|
48
|
+
>
|
|
49
|
+
<slot />
|
|
50
|
+
</component>
|
|
51
|
+
</template>
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
const { snapTo, center, end, vertical } = defineProps<{
|
|
3
|
+
snapTo?: 'center' | 'end'
|
|
4
|
+
center?: boolean
|
|
5
|
+
end?: boolean
|
|
6
|
+
orientation?: 'horizontal' | 'vertical'
|
|
7
|
+
horizontal?: boolean
|
|
8
|
+
vertical?: boolean
|
|
9
|
+
}>()
|
|
10
|
+
</script>
|
|
11
|
+
|
|
12
|
+
<template>
|
|
13
|
+
<div
|
|
14
|
+
class="carousel"
|
|
15
|
+
:class="{
|
|
16
|
+
'carousel-center': center || snapTo === 'center',
|
|
17
|
+
'carousel-end': end || snapTo === 'end',
|
|
18
|
+
'carousel-horizontal': horizontal || orientation === 'horizontal',
|
|
19
|
+
'carousel-vertical': vertical || orientation === 'vertical',
|
|
20
|
+
}"
|
|
21
|
+
>
|
|
22
|
+
<slot />
|
|
23
|
+
</div>
|
|
24
|
+
</template>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
const {
|
|
3
|
+
pre,
|
|
4
|
+
align = 'start',
|
|
5
|
+
start,
|
|
6
|
+
end,
|
|
7
|
+
} = defineProps<{
|
|
8
|
+
pre?: boolean
|
|
9
|
+
align?: string
|
|
10
|
+
start?: boolean
|
|
11
|
+
end?: boolean
|
|
12
|
+
}>()
|
|
13
|
+
</script>
|
|
14
|
+
|
|
15
|
+
<template>
|
|
16
|
+
<div
|
|
17
|
+
class="chat"
|
|
18
|
+
:class="{
|
|
19
|
+
'chat-start': start || (!end && align === 'start'),
|
|
20
|
+
'chat-end': end || align === 'end',
|
|
21
|
+
'whitespace-pre': pre,
|
|
22
|
+
}"
|
|
23
|
+
>
|
|
24
|
+
<slot />
|
|
25
|
+
</div>
|
|
26
|
+
</template>
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
const { color, neutral, primary, secondary, accent, info, success, warning, error } = defineProps<{
|
|
3
|
+
color?: string
|
|
4
|
+
neutral?: boolean
|
|
5
|
+
primary?: boolean
|
|
6
|
+
secondary?: boolean
|
|
7
|
+
accent?: boolean
|
|
8
|
+
info?: boolean
|
|
9
|
+
success?: boolean
|
|
10
|
+
warning?: boolean
|
|
11
|
+
error?: boolean
|
|
12
|
+
}>()
|
|
13
|
+
</script>
|
|
14
|
+
|
|
15
|
+
<template>
|
|
16
|
+
<div
|
|
17
|
+
class="chat-bubble"
|
|
18
|
+
:class="{
|
|
19
|
+
'chat-bubble-neutral': neutral || color === 'neutral',
|
|
20
|
+
'chat-bubble-primary': primary || color === 'primary',
|
|
21
|
+
'chat-bubble-secondary': secondary || color === 'secondary',
|
|
22
|
+
'chat-bubble-accent': accent || color === 'accent',
|
|
23
|
+
'chat-bubble-info': info || color === 'info',
|
|
24
|
+
'chat-bubble-success': success || color === 'success',
|
|
25
|
+
'chat-bubble-warning': warning || color === 'warning',
|
|
26
|
+
'chat-bubble-error': error || color === 'error',
|
|
27
|
+
}"
|
|
28
|
+
>
|
|
29
|
+
<slot />
|
|
30
|
+
</div>
|
|
31
|
+
</template>
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { computed } from 'vue'
|
|
3
|
+
|
|
4
|
+
const props = defineProps<{
|
|
5
|
+
modelValue?: any
|
|
6
|
+
themeController?: boolean
|
|
7
|
+
|
|
8
|
+
color?: string
|
|
9
|
+
primary?: boolean
|
|
10
|
+
secondary?: boolean
|
|
11
|
+
accent?: boolean
|
|
12
|
+
success?: boolean
|
|
13
|
+
warning?: boolean
|
|
14
|
+
info?: boolean
|
|
15
|
+
error?: boolean
|
|
16
|
+
|
|
17
|
+
size?: string
|
|
18
|
+
lg?: boolean
|
|
19
|
+
md?: boolean
|
|
20
|
+
sm?: boolean
|
|
21
|
+
xs?: boolean
|
|
22
|
+
}>()
|
|
23
|
+
const emit = defineEmits(['update:modelValue'])
|
|
24
|
+
|
|
25
|
+
const currentValue = computed({
|
|
26
|
+
get: () => props.modelValue,
|
|
27
|
+
set: (val: string) => emit('update:modelValue', val),
|
|
28
|
+
})
|
|
29
|
+
</script>
|
|
30
|
+
|
|
31
|
+
<template>
|
|
32
|
+
<input
|
|
33
|
+
v-model="currentValue"
|
|
34
|
+
type="checkbox"
|
|
35
|
+
class="checkbox"
|
|
36
|
+
:class="{
|
|
37
|
+
'checkbox-primary': primary || color === 'primary',
|
|
38
|
+
'checkbox-secondary': secondary || color === 'secondary',
|
|
39
|
+
'checkbox-accent': accent || color === 'accent',
|
|
40
|
+
'checkbox-success': success || color === 'success',
|
|
41
|
+
'checkbox-warning': warning || color === 'warning',
|
|
42
|
+
'checkbox-info': info || color === 'info',
|
|
43
|
+
'checkbox-error': error || color === 'error',
|
|
44
|
+
'checkbox-xs': xs || size === 'xs',
|
|
45
|
+
'checkbox-sm': sm || size === 'sm',
|
|
46
|
+
'checkbox-md': md || size === 'md',
|
|
47
|
+
'checkbox-lg': lg || size === 'lg',
|
|
48
|
+
'theme-controller': themeController,
|
|
49
|
+
}"
|
|
50
|
+
/>
|
|
51
|
+
</template>
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { computed, inject, provide, ref, useId, watch } from 'vue'
|
|
3
|
+
|
|
4
|
+
const props = defineProps<{
|
|
5
|
+
variant?: 'arrow' | 'plus'
|
|
6
|
+
arrow?: boolean
|
|
7
|
+
plus?: boolean
|
|
8
|
+
open?: boolean
|
|
9
|
+
close?: boolean
|
|
10
|
+
toggle?: boolean
|
|
11
|
+
value?: any
|
|
12
|
+
}>()
|
|
13
|
+
|
|
14
|
+
const isOpen = defineModel('open', { default: false })
|
|
15
|
+
|
|
16
|
+
const accordionValue = inject('accordion-value', ref(null))
|
|
17
|
+
const useAccordion = accordionValue.value !== null
|
|
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-${useId()}`
|
|
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
|
+
|
|
39
|
+
function handleClick() {
|
|
40
|
+
// Only handle clicks for accordion mode
|
|
41
|
+
if (useAccordion) {
|
|
42
|
+
accordionValue.value = props.value
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const isChecked = computed(() => {
|
|
47
|
+
if (useAccordion) {
|
|
48
|
+
return accordionValue.value === props.value
|
|
49
|
+
}
|
|
50
|
+
return internalChecked.value
|
|
51
|
+
})
|
|
52
|
+
</script>
|
|
53
|
+
|
|
54
|
+
<template>
|
|
55
|
+
<div
|
|
56
|
+
:tabindex="props.toggle || useAccordion ? undefined : 0"
|
|
57
|
+
class="collapse"
|
|
58
|
+
:class="[
|
|
59
|
+
{ 'collapse-arrow': props.arrow || props.variant === 'arrow' },
|
|
60
|
+
{ 'collapse-plus': props.plus || props.variant === 'plus' },
|
|
61
|
+
{ 'collapse-open': (props.open && !props.close) || (useAccordion && accordionValue === props.value) },
|
|
62
|
+
{ 'collapse-close': props.close },
|
|
63
|
+
]"
|
|
64
|
+
@click="useAccordion ? handleClick : undefined"
|
|
65
|
+
>
|
|
66
|
+
<input
|
|
67
|
+
v-if="props.toggle || useAccordion"
|
|
68
|
+
:id="checkboxId"
|
|
69
|
+
v-model="internalChecked"
|
|
70
|
+
:type="useAccordion ? 'radio' : 'checkbox'"
|
|
71
|
+
:checked="useAccordion ? isChecked : undefined"
|
|
72
|
+
/>
|
|
73
|
+
<slot />
|
|
74
|
+
</div>
|
|
75
|
+
</template>
|