@lumen-design/calendar 0.0.2
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/dist/Calendar.svelte +115 -0
- package/dist/index.js +3 -0
- package/package.json +34 -0
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import Icon from '@lumen-design/icon'
|
|
3
|
+
import { ChevronLeft, ChevronRight, ChevronsLeft, ChevronsRight } from 'lucide'
|
|
4
|
+
|
|
5
|
+
interface Props {
|
|
6
|
+
modelValue?: Date
|
|
7
|
+
class?: string
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
let { modelValue = $bindable(new Date()), class: cls = '', ...attrs }: Props = $props()
|
|
11
|
+
|
|
12
|
+
let currentDate = $state(new Date(modelValue))
|
|
13
|
+
|
|
14
|
+
const weekDays = ['日', '一', '二', '三', '四', '五', '六']
|
|
15
|
+
|
|
16
|
+
const year = $derived(currentDate.getFullYear())
|
|
17
|
+
const month = $derived(currentDate.getMonth())
|
|
18
|
+
|
|
19
|
+
const getDaysInMonth = (y: number, m: number): number => new Date(y, m + 1, 0).getDate()
|
|
20
|
+
|
|
21
|
+
const calendarDays = $derived.by(() => {
|
|
22
|
+
const days: { date: number; month: 'prev' | 'current' | 'next'; fullDate: Date }[] = []
|
|
23
|
+
const daysInMonth = getDaysInMonth(year, month)
|
|
24
|
+
const firstDay = new Date(year, month, 1).getDay()
|
|
25
|
+
const prevMonthDays = getDaysInMonth(year, month - 1)
|
|
26
|
+
|
|
27
|
+
for (let i = firstDay - 1; i >= 0; i--) {
|
|
28
|
+
const date = prevMonthDays - i
|
|
29
|
+
days.push({ date, month: 'prev', fullDate: new Date(year, month - 1, date) })
|
|
30
|
+
}
|
|
31
|
+
for (let i = 1; i <= daysInMonth; i++) {
|
|
32
|
+
days.push({ date: i, month: 'current', fullDate: new Date(year, month, i) })
|
|
33
|
+
}
|
|
34
|
+
const remaining = 42 - days.length
|
|
35
|
+
for (let i = 1; i <= remaining; i++) {
|
|
36
|
+
days.push({ date: i, month: 'next', fullDate: new Date(year, month + 1, i) })
|
|
37
|
+
}
|
|
38
|
+
return days
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
const today = $derived.by(() => {
|
|
42
|
+
const d = new Date()
|
|
43
|
+
return { y: d.getFullYear(), m: d.getMonth(), d: d.getDate() }
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
const selected = $derived({ y: modelValue.getFullYear(), m: modelValue.getMonth(), d: modelValue.getDate() })
|
|
47
|
+
|
|
48
|
+
const isToday = (date: Date): boolean => date.getDate() === today.d && date.getMonth() === today.m && date.getFullYear() === today.y
|
|
49
|
+
|
|
50
|
+
const isSelected = (date: Date): boolean => date.getDate() === selected.d && date.getMonth() === selected.m && date.getFullYear() === selected.y
|
|
51
|
+
|
|
52
|
+
const selectDate = (day: { date: number; month: 'prev' | 'current' | 'next'; fullDate: Date }): void => {
|
|
53
|
+
modelValue = day.fullDate
|
|
54
|
+
if (day.month !== 'current') currentDate = new Date(day.fullDate)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const goToToday = (): void => {
|
|
58
|
+
const t = new Date()
|
|
59
|
+
modelValue = t
|
|
60
|
+
currentDate = new Date(t)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const classes = $derived(`lm-calendar${cls ? ` ${cls}` : ''}`)
|
|
64
|
+
</script>
|
|
65
|
+
|
|
66
|
+
<div class={classes} {...attrs}>
|
|
67
|
+
<div class="lm-calendar__header">
|
|
68
|
+
<div class="lm-calendar__nav">
|
|
69
|
+
<button class="lm-calendar__btn" onclick={() => (currentDate = new Date(year - 1, month, 1))} aria-label="上一年">
|
|
70
|
+
<Icon icon={ChevronsLeft} size={16} />
|
|
71
|
+
</button>
|
|
72
|
+
<button class="lm-calendar__btn" onclick={() => (currentDate = new Date(year, month - 1, 1))} aria-label="上个月">
|
|
73
|
+
<Icon icon={ChevronLeft} size={14} />
|
|
74
|
+
</button>
|
|
75
|
+
</div>
|
|
76
|
+
<div class="lm-calendar__title">
|
|
77
|
+
{year}年 {month + 1}月
|
|
78
|
+
</div>
|
|
79
|
+
<div class="lm-calendar__nav">
|
|
80
|
+
<button class="lm-calendar__btn" onclick={() => (currentDate = new Date(year, month + 1, 1))} aria-label="下个月">
|
|
81
|
+
<Icon icon={ChevronRight} size={14} />
|
|
82
|
+
</button>
|
|
83
|
+
<button class="lm-calendar__btn" onclick={() => (currentDate = new Date(year + 1, month, 1))} aria-label="下一年">
|
|
84
|
+
<Icon icon={ChevronsRight} size={16} />
|
|
85
|
+
</button>
|
|
86
|
+
</div>
|
|
87
|
+
</div>
|
|
88
|
+
|
|
89
|
+
<div class="lm-calendar__body">
|
|
90
|
+
<div class="lm-calendar__weekdays">
|
|
91
|
+
{#each weekDays as day}
|
|
92
|
+
<div class="lm-calendar__weekday">{day}</div>
|
|
93
|
+
{/each}
|
|
94
|
+
</div>
|
|
95
|
+
<div class="lm-calendar__days" role="grid">
|
|
96
|
+
{#each calendarDays as day}
|
|
97
|
+
<button
|
|
98
|
+
type="button"
|
|
99
|
+
class="lm-calendar__day"
|
|
100
|
+
class:is-other-month={day.month !== 'current'}
|
|
101
|
+
class:is-today={isToday(day.fullDate)}
|
|
102
|
+
class:is-selected={isSelected(day.fullDate)}
|
|
103
|
+
aria-pressed={isSelected(day.fullDate)}
|
|
104
|
+
onclick={() => selectDate(day)}
|
|
105
|
+
>
|
|
106
|
+
{day.date}
|
|
107
|
+
</button>
|
|
108
|
+
{/each}
|
|
109
|
+
</div>
|
|
110
|
+
</div>
|
|
111
|
+
|
|
112
|
+
<div class="lm-calendar__footer">
|
|
113
|
+
<button class="lm-calendar__today" onclick={goToToday}>今天</button>
|
|
114
|
+
</div>
|
|
115
|
+
</div>
|
package/dist/index.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@lumen-design/calendar",
|
|
3
|
+
"version": "0.0.2",
|
|
4
|
+
"description": "Calendar component for Lumen UI",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"module": "dist/index.js",
|
|
8
|
+
"types": "dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"svelte": "./dist/index.js",
|
|
13
|
+
"import": "./dist/index.js"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist"
|
|
18
|
+
],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "svelte-package -i src -o dist --types",
|
|
21
|
+
"build:watch": "svelte-package -i src -o dist --types -w"
|
|
22
|
+
},
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"@lumen-design/icon": "0.0.2",
|
|
25
|
+
"lucide": "^0.563.0"
|
|
26
|
+
},
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"@sveltejs/package": "^2.5.7",
|
|
29
|
+
"svelte": "5.48.2"
|
|
30
|
+
},
|
|
31
|
+
"peerDependencies": {
|
|
32
|
+
"svelte": "^5.0.0"
|
|
33
|
+
}
|
|
34
|
+
}
|