winduum 0.7.2 → 0.8.0-next.10
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/main.css +1 -1
- package/dist/tailwind.css +1 -1
- package/package.json +58 -19
- package/plugin/{tailwind.cjs → index.cjs} +2 -2
- package/plugin/{tailwind.d.ts → index.d.ts} +6 -0
- package/plugin/{tailwind.js → index.js} +2 -2
- package/src/common.d.ts +2 -0
- package/src/components/carousel/content.css +30 -0
- package/src/components/carousel/default.css +3 -0
- package/src/components/carousel/index.css +2 -0
- package/src/components/carousel/index.d.ts +40 -0
- package/src/components/carousel/index.js +221 -0
- package/src/components/compare/index.d.ts +8 -0
- package/src/components/compare/index.js +9 -15
- package/src/components/details/index.d.ts +9 -0
- package/src/components/details/index.js +4 -10
- package/src/components/dialog/index.d.ts +30 -0
- package/src/components/dialog/index.js +32 -40
- package/src/components/drawer/content.css +10 -0
- package/src/components/drawer/default.css +37 -0
- package/src/components/drawer/index.css +2 -0
- package/src/components/drawer/index.d.ts +13 -0
- package/src/components/drawer/index.js +52 -0
- package/src/components/form/index.d.ts +26 -0
- package/src/components/form/index.js +105 -0
- package/src/components/index.css +2 -0
- package/src/components/toaster/index.d.ts +30 -0
- package/src/components/toaster/index.js +6 -14
- package/src/ui/control/invalid.css +1 -1
- package/src/ui/control/select.css +2 -2
- package/src/ui/progress/default.css +6 -3
- package/src/ui/range/index.d.ts +19 -0
- package/src/ui/range/index.js +24 -38
- package/src/utilities/ripple/index.d.ts +1 -0
- package/src/utilities/ripple/index.js +11 -15
- package/src/utilities/swap/index.d.ts +1 -0
- package/src/utilities/swap/index.js +0 -4
- package/tailwind.config.js +1 -1
- package/types/index.d.ts +235 -0
- package/types/index.d.ts.map +92 -0
- package/src/components/compare/types/index.d.ts +0 -17
- package/src/components/details/types/index.d.ts +0 -4
- package/src/components/dialog/types/index.d.ts +0 -22
- package/src/components/toaster/types/index.d.ts +0 -25
- package/src/main.js +0 -1
- package/src/ui/range/types/index.d.ts +0 -16
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
.c-carousel-content {
|
|
2
|
+
display: flex;
|
|
3
|
+
overflow: auto;
|
|
4
|
+
user-select: none;
|
|
5
|
+
scrollbar-width: none;
|
|
6
|
+
-webkit-overflow-scrolling: touch;
|
|
7
|
+
overscroll-behavior-x: none;
|
|
8
|
+
position: relative;
|
|
9
|
+
scroll-behavior: smooth;
|
|
10
|
+
scroll-snap-type: x mandatory;
|
|
11
|
+
|
|
12
|
+
&::-webkit-scrollbar {
|
|
13
|
+
display: none;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
& > :where(*) {
|
|
17
|
+
flex: 0 0 auto;
|
|
18
|
+
scroll-snap-align: start;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
&:is(.grabbing) {
|
|
22
|
+
&, & * {
|
|
23
|
+
cursor: grabbing;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
& a {
|
|
27
|
+
pointer-events: none;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export interface ObserveCarouselOptions {
|
|
2
|
+
visibleClass?: string
|
|
3
|
+
observerOptions?: {
|
|
4
|
+
rootMargin?: string
|
|
5
|
+
threshold?: number | number[]
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface PaginationCarouselOptions {
|
|
10
|
+
element?: HTMLElement | Element
|
|
11
|
+
itemContent?: string
|
|
12
|
+
activeClass?: string
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface ScrollCarouselOptions {
|
|
16
|
+
observe?: ObserveCarouselOptions
|
|
17
|
+
pagination?: PaginationCarouselOptions
|
|
18
|
+
progressElement?: HTMLProgressElement | Element
|
|
19
|
+
counterMinElement?: HTMLElement | Element
|
|
20
|
+
counterMaxElement?: HTMLElement | Element
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface AutoplayCarouselOptions {
|
|
24
|
+
delay?: number
|
|
25
|
+
pauseElements?: HTMLElement[] | Element[]
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface DragCarouselOptions {
|
|
29
|
+
activeClass?: string
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function scrollPrev(element: HTMLElement | Element): void
|
|
33
|
+
export function scrollNext(element: HTMLElement | Element): void
|
|
34
|
+
export function scrollTo(element: HTMLElement | Element, selected?: number): void
|
|
35
|
+
export function getItemCount(element: HTMLElement | Element, scrollWidth?: number, mathFloor?: boolean): number
|
|
36
|
+
export function observeCarousel(element: HTMLElement | Element, options?: ObserveCarouselOptions): void
|
|
37
|
+
export function scrollCarousel(element: HTMLElement | Element, options?: ScrollCarouselOptions): void
|
|
38
|
+
export function paginationCarousel(element: HTMLElement | Element, options?: PaginationCarouselOptions): void
|
|
39
|
+
export function autoplayCarousel(element: HTMLElement | Element, options?: AutoplayCarouselOptions): void
|
|
40
|
+
export function dragCarousel(element: HTMLElement | Element, options?: DragCarouselOptions): void
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @param {HTMLElement | Element} element
|
|
3
|
+
* @param {number} index
|
|
4
|
+
* @returns void
|
|
5
|
+
*/
|
|
6
|
+
export const scrollTo = (element, index = 0) => {
|
|
7
|
+
element.scroll({ left: element?.children[index]?.offsetLeft })
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @param {HTMLElement | Element & { _activeIndex: number }} element
|
|
12
|
+
* @returns void
|
|
13
|
+
*/
|
|
14
|
+
export const scrollPrev = (element) => {
|
|
15
|
+
scrollTo(element, element._activeIndex - 1)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @param {HTMLElement | Element & { _activeIndex: number }} element
|
|
20
|
+
* @returns void
|
|
21
|
+
*/
|
|
22
|
+
export const scrollNext = (element) => {
|
|
23
|
+
scrollTo(element, element._activeIndex + 1)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* @param {HTMLElement | Element} element
|
|
28
|
+
* @param {number} scrollWidth
|
|
29
|
+
* @param {boolean} mathFloor
|
|
30
|
+
* @returns number
|
|
31
|
+
*/
|
|
32
|
+
export const getItemCount = (element, scrollWidth = element.scrollWidth - element.clientWidth, mathFloor = false) => {
|
|
33
|
+
const gap = parseInt(getComputedStyle(element).rowGap)
|
|
34
|
+
const mathRound = (value, floor) => floor ? Math.floor(value) : Math.ceil(value)
|
|
35
|
+
|
|
36
|
+
return [...element.children].reduce((count, children) => {
|
|
37
|
+
if (mathRound(scrollWidth / (children.offsetWidth + (isNaN(gap) ? 0 : gap)), mathFloor) > count) {
|
|
38
|
+
return count + 1
|
|
39
|
+
} else {
|
|
40
|
+
return count
|
|
41
|
+
}
|
|
42
|
+
}, 0) + 1
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* @param {HTMLElement | Element} element
|
|
47
|
+
* @param {import("./").ObserveCarouselOptions} options
|
|
48
|
+
* @returns void
|
|
49
|
+
*/
|
|
50
|
+
export const observeCarousel = (element, options = {}) => {
|
|
51
|
+
options = {
|
|
52
|
+
visibleClass: 'visible',
|
|
53
|
+
observerOptions: {},
|
|
54
|
+
...options
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
element._observer = new IntersectionObserver(entries => {
|
|
58
|
+
entries.forEach(entry => {
|
|
59
|
+
entry.target.classList.toggle(options.visibleClass, entry.isIntersecting)
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
const activeElement = [...element.children].find(children => children.classList.contains(options.visibleClass))
|
|
63
|
+
|
|
64
|
+
if (activeElement) {
|
|
65
|
+
element._activeIndex = [...element.children].indexOf(activeElement)
|
|
66
|
+
}
|
|
67
|
+
}, {
|
|
68
|
+
root: element,
|
|
69
|
+
threshold: 0.5,
|
|
70
|
+
...options.observerOptions
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
;[...element.children].forEach(children => element._observer.observe(children))
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* @param {HTMLElement | Element} element
|
|
78
|
+
* @param {import("./").ScrollCarouselOptions} options
|
|
79
|
+
* @returns void
|
|
80
|
+
*/
|
|
81
|
+
export const scrollCarousel = (element, options = {}) => {
|
|
82
|
+
options.pagination = {
|
|
83
|
+
activeClass: 'active',
|
|
84
|
+
...options.pagination
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const activeItem = getItemCount(element, element.scrollLeft, element.scrollLeft < element._lastScrollLeft)
|
|
88
|
+
const activeItemMax = getItemCount(element)
|
|
89
|
+
|
|
90
|
+
if (options?.pagination?.element) {
|
|
91
|
+
;[...options.pagination.element.children].forEach(children => children.classList.remove(options.pagination.activeClass))
|
|
92
|
+
|
|
93
|
+
options.pagination.element.children[activeItem - 1]?.classList.add(options.pagination.activeClass)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (options.progressElement) {
|
|
97
|
+
options.progressElement.value = activeItem / activeItemMax * 100
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (options.counterMinElement) {
|
|
101
|
+
options.counterMinElement.innerHTML = `${activeItem}`
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (options.counterMaxElement) {
|
|
105
|
+
options.counterMaxElement.innerHTML = `${activeItemMax}`
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
element._lastScrollLeft = element.scrollLeft <= 0 ? 0 : element.scrollLeft
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* @param {HTMLElement | Element} element
|
|
113
|
+
* @param {import("./").PaginationCarouselOptions} options
|
|
114
|
+
* @returns void
|
|
115
|
+
*/
|
|
116
|
+
export const paginationCarousel = (element, options = {}) => {
|
|
117
|
+
options = {
|
|
118
|
+
itemContent: '<div aria-hidden="true"></div>',
|
|
119
|
+
activeClass: 'active',
|
|
120
|
+
...options
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (!options.element) return
|
|
124
|
+
|
|
125
|
+
options.element.insertAdjacentHTML('beforeend', [...Array(getItemCount(element))].map(
|
|
126
|
+
() => options.itemContent
|
|
127
|
+
).join(''))
|
|
128
|
+
|
|
129
|
+
;[...options.element.children].forEach((children, i) => {
|
|
130
|
+
(i === 0) && children.classList.add(options.activeClass)
|
|
131
|
+
children.addEventListener('click', ({ currentTarget }) => {
|
|
132
|
+
scrollTo(element, [...options.element.children].indexOf(currentTarget))
|
|
133
|
+
})
|
|
134
|
+
})
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* @param {HTMLElement | Element} element
|
|
139
|
+
* @param {import("./").AutoplayCarouselOptions} options
|
|
140
|
+
* @returns void
|
|
141
|
+
*/
|
|
142
|
+
export const autoplayCarousel = (element, options = {}) => {
|
|
143
|
+
options = {
|
|
144
|
+
delay: 4000,
|
|
145
|
+
pauseElements: [],
|
|
146
|
+
...options
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
let paused
|
|
150
|
+
|
|
151
|
+
options.pauseElements.forEach(element => {
|
|
152
|
+
element?.addEventListener('mouseenter', () => (paused = true))
|
|
153
|
+
element?.addEventListener('mouseleave', () => (paused = false))
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
setInterval(() => {
|
|
157
|
+
if (paused) return
|
|
158
|
+
|
|
159
|
+
if (element.scrollLeft < element.scrollWidth - element.clientWidth) {
|
|
160
|
+
scrollNext(element)
|
|
161
|
+
} else {
|
|
162
|
+
scrollTo(element, 0)
|
|
163
|
+
}
|
|
164
|
+
}, options.delay)
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* @param {HTMLElement | Element & { _activeIndex: number }} element
|
|
169
|
+
* @param {import("./").DragCarouselOptions} options
|
|
170
|
+
* @returns void
|
|
171
|
+
*/
|
|
172
|
+
export const dragCarousel = (element, options = {}) => {
|
|
173
|
+
options = {
|
|
174
|
+
activeClass: 'grabbing',
|
|
175
|
+
...options
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
if (!matchMedia('(hover: hover) and (pointer: fine)').matches) {
|
|
179
|
+
return
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
let isDown
|
|
183
|
+
let startX
|
|
184
|
+
let scrollLeft
|
|
185
|
+
let timeout
|
|
186
|
+
|
|
187
|
+
const endGrabbing = () => {
|
|
188
|
+
isDown = false
|
|
189
|
+
element.classList.remove(options.activeClass)
|
|
190
|
+
|
|
191
|
+
scrollTo(element, element._activeIndex)
|
|
192
|
+
|
|
193
|
+
clearTimeout(timeout)
|
|
194
|
+
|
|
195
|
+
timeout = setTimeout(() => {
|
|
196
|
+
element.style.scrollSnapType = ''
|
|
197
|
+
}, 300)
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
element.addEventListener('mouseleave', endGrabbing)
|
|
201
|
+
|
|
202
|
+
element.addEventListener('mouseup', endGrabbing)
|
|
203
|
+
|
|
204
|
+
element.addEventListener('mousedown', ({ pageX }) => {
|
|
205
|
+
isDown = true
|
|
206
|
+
startX = pageX - element.offsetLeft
|
|
207
|
+
scrollLeft = element.scrollLeft
|
|
208
|
+
})
|
|
209
|
+
|
|
210
|
+
element.addEventListener('mousemove', e => {
|
|
211
|
+
if (!isDown) return
|
|
212
|
+
e.preventDefault()
|
|
213
|
+
|
|
214
|
+
const x = e.pageX - element.offsetLeft
|
|
215
|
+
|
|
216
|
+
element.classList.add(options.activeClass)
|
|
217
|
+
element.style.scrollSnapType = 'unset'
|
|
218
|
+
element.scroll({ left: scrollLeft - ((x - startX) * 1.25), behavior: 'instant' })
|
|
219
|
+
element.ondragstart = e => e.preventDefault()
|
|
220
|
+
})
|
|
221
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export interface SetPositionOptions {
|
|
2
|
+
selector?: string
|
|
3
|
+
positionProperty?: string
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export function setPosition(event: Event, options?: SetPositionOptions): void
|
|
7
|
+
export function setKeyboardStep(event: KeyboardEvent, step?: string): void
|
|
8
|
+
export function setMouseStep(event: MouseEvent, step?: string): void
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @param {
|
|
3
|
-
* @param {import("./
|
|
2
|
+
* @param {Event & { currentTarget: HTMLElement | Element }} event
|
|
3
|
+
* @param {import("./").SetPositionOptions} options
|
|
4
4
|
* @returns void
|
|
5
5
|
*/
|
|
6
6
|
export const setPosition = ({ currentTarget }, options = {}) => {
|
|
@@ -10,31 +10,25 @@ export const setPosition = ({ currentTarget }, options = {}) => {
|
|
|
10
10
|
...options
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
currentTarget
|
|
13
|
+
currentTarget?.closest(selector)?.style.setProperty(positionProperty, `${currentTarget.value}%`)
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
|
-
* @param {
|
|
18
|
-
* @param {
|
|
17
|
+
* @param {KeyboardEvent & { currentTarget: HTMLInputElement | EventTarget }} event
|
|
18
|
+
* @param {string} step
|
|
19
19
|
* @returns void
|
|
20
20
|
*/
|
|
21
|
-
export const setKeyboardStep = ({ key, currentTarget }, step = 10) => {
|
|
21
|
+
export const setKeyboardStep = ({ key, currentTarget }, step = '10') => {
|
|
22
22
|
if (key?.toLowerCase() !== 'arrowright' && key?.toLowerCase() !== 'arrowleft') return
|
|
23
23
|
|
|
24
24
|
currentTarget.step = step
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
/**
|
|
28
|
-
* @param {
|
|
29
|
-
* @param {
|
|
28
|
+
* @param {MouseEvent & { currentTarget: HTMLInputElement | EventTarget }} event
|
|
29
|
+
* @param {string} step
|
|
30
30
|
* @returns void
|
|
31
31
|
*/
|
|
32
|
-
export const setMouseStep = ({ currentTarget }, step = 0.1) => {
|
|
32
|
+
export const setMouseStep = ({ currentTarget }, step = '0.1') => {
|
|
33
33
|
currentTarget.step = step
|
|
34
34
|
}
|
|
35
|
-
|
|
36
|
-
export default {
|
|
37
|
-
setPosition,
|
|
38
|
-
setKeyboardStep,
|
|
39
|
-
setMouseStep
|
|
40
|
-
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export interface DefaultOptions {
|
|
2
|
+
selector?: string
|
|
3
|
+
summarySelector?: string
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export const defaultOptions: DefaultOptions
|
|
7
|
+
export function showDetails(selector: HTMLInputElement | HTMLElement, options?: DefaultOptions): Promise<void>
|
|
8
|
+
export function closeDetails(selector: HTMLInputElement | HTMLElement, options?: DefaultOptions): Promise<void>
|
|
9
|
+
export function toggleDetails(selector: HTMLInputElement | HTMLElement, options?: DefaultOptions): Promise<void>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @type {import("./
|
|
2
|
+
* @type {import("./").DefaultOptions}
|
|
3
3
|
*/
|
|
4
4
|
export const defaultOptions = {
|
|
5
5
|
selector: 'details',
|
|
@@ -8,7 +8,7 @@ export const defaultOptions = {
|
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* @param {HTMLInputElement | HTMLElement} element
|
|
11
|
-
* @param {import("./
|
|
11
|
+
* @param {import("./").DefaultOptions} options
|
|
12
12
|
* @returns Promise<void>
|
|
13
13
|
*/
|
|
14
14
|
export const showDetails = async (element, options = {}) => {
|
|
@@ -31,7 +31,7 @@ export const showDetails = async (element, options = {}) => {
|
|
|
31
31
|
|
|
32
32
|
/**
|
|
33
33
|
* @param {HTMLInputElement | HTMLElement} element
|
|
34
|
-
* @param {import("./
|
|
34
|
+
* @param {import("./").DefaultOptions} options
|
|
35
35
|
* @returns Promise<void>
|
|
36
36
|
*/
|
|
37
37
|
export const closeDetails = async (element, options = {}) => {
|
|
@@ -56,7 +56,7 @@ export const closeDetails = async (element, options = {}) => {
|
|
|
56
56
|
|
|
57
57
|
/**
|
|
58
58
|
* @param {HTMLInputElement | HTMLElement} element
|
|
59
|
-
* @param {import("./
|
|
59
|
+
* @param {import("./").DefaultOptions} options
|
|
60
60
|
* @returns Promise<void>
|
|
61
61
|
*/
|
|
62
62
|
export const toggleDetails = async (element, options = {}) => {
|
|
@@ -75,9 +75,3 @@ export const toggleDetails = async (element, options = {}) => {
|
|
|
75
75
|
await closeDetails(element, options)
|
|
76
76
|
}
|
|
77
77
|
}
|
|
78
|
-
|
|
79
|
-
export default {
|
|
80
|
-
showDetails,
|
|
81
|
-
closeDetails,
|
|
82
|
-
toggleDetails
|
|
83
|
-
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export interface DialogElement extends HTMLDialogElement {
|
|
2
|
+
_dialogHasEvents: boolean
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export interface DefaultOptions {
|
|
6
|
+
remove?: boolean | null
|
|
7
|
+
closable?: boolean | null
|
|
8
|
+
openClass?: string
|
|
9
|
+
scrollbarWidthProperty?: string
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface InsertDialogOptions {
|
|
13
|
+
selector?: string | null
|
|
14
|
+
class?: string | null
|
|
15
|
+
append?: boolean | null
|
|
16
|
+
show?: DefaultOptions
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface FetchDialogOptions {
|
|
20
|
+
url: string
|
|
21
|
+
insert?: InsertDialogOptions
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export const defaultOptions: DefaultOptions
|
|
25
|
+
export function dialogSelector(selector: string): HTMLDialogElement
|
|
26
|
+
export function dismissDialog(element: HTMLDialogElement, options?: DefaultOptions): Promise<void>
|
|
27
|
+
export function showDialog(element: DialogElement, options?: DefaultOptions): Promise<void>
|
|
28
|
+
export function closeDialog(element: HTMLDialogElement, options?: DefaultOptions): Promise<void>
|
|
29
|
+
export function insertDialog(content: string, options?: InsertDialogOptions): Promise<void>
|
|
30
|
+
export function fetchDialog({ url, insert }: FetchDialogOptions): Promise<void>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { animationsFinished } from '../../common.js'
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* @type {import("./
|
|
4
|
+
* @type {import("./").DefaultOptions}
|
|
5
5
|
*/
|
|
6
6
|
export const defaultOptions = {
|
|
7
7
|
openClass: 'visible',
|
|
@@ -11,22 +11,23 @@ export const defaultOptions = {
|
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* @param {string} selector.
|
|
14
|
+
* @return HTMLDialogElement
|
|
14
15
|
*/
|
|
15
16
|
export const dialogSelector = selector => document.querySelectorAll(selector)[document.querySelectorAll(selector).length - 1]
|
|
16
17
|
|
|
17
18
|
/**
|
|
18
19
|
* Dismisses a dialog.
|
|
19
|
-
* @param {HTMLDialogElement}
|
|
20
|
-
* @param {import("./
|
|
20
|
+
* @param {HTMLDialogElement} element - The dialog element to dismiss.
|
|
21
|
+
* @param {import("./").DefaultOptions} options - The options for closing the dialog.
|
|
21
22
|
* @returns Promise<void>
|
|
22
23
|
*/
|
|
23
|
-
export const dismissDialog = async (
|
|
24
|
-
await animationsFinished(
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
24
|
+
export const dismissDialog = async (element, options = defaultOptions) => {
|
|
25
|
+
await animationsFinished(element)
|
|
26
|
+
element.inert = true
|
|
27
|
+
element.classList.remove(options.openClass)
|
|
28
|
+
element.dispatchEvent(new CustomEvent('c-dialog:dismiss'))
|
|
28
29
|
|
|
29
|
-
options.remove &&
|
|
30
|
+
options.remove && element.remove()
|
|
30
31
|
|
|
31
32
|
if (!document.querySelector('dialog[open]')) {
|
|
32
33
|
document.documentElement.style.removeProperty(options.scrollbarWidthProperty)
|
|
@@ -35,11 +36,11 @@ export const dismissDialog = async (selector, options = defaultOptions) => {
|
|
|
35
36
|
|
|
36
37
|
/**
|
|
37
38
|
* Shows a dialog.
|
|
38
|
-
* @param {import("./
|
|
39
|
-
* @param {import("./
|
|
39
|
+
* @param {HTMLDialogElement | import("./").DialogElement} element - The dialog element to show.
|
|
40
|
+
* @param {import("./").DefaultOptions} options - The options for showing the dialog.
|
|
40
41
|
* @returns Promise<void>
|
|
41
42
|
*/
|
|
42
|
-
export const showDialog = async (
|
|
43
|
+
export const showDialog = async (element, options = {}) => {
|
|
43
44
|
options = {
|
|
44
45
|
closable: true,
|
|
45
46
|
...defaultOptions,
|
|
@@ -48,54 +49,54 @@ export const showDialog = async (selector, options = {}) => {
|
|
|
48
49
|
|
|
49
50
|
document.documentElement.style.setProperty(options.scrollbarWidthProperty, `${window.innerWidth - document.body.clientWidth}px`)
|
|
50
51
|
|
|
51
|
-
if (!
|
|
52
|
-
|
|
52
|
+
if (!element?._dialogHasEvents) {
|
|
53
|
+
element.addEventListener('keydown', (e) => {
|
|
53
54
|
if (e.key === 'Escape') {
|
|
54
55
|
e.preventDefault()
|
|
55
|
-
options.closable && closeDialog(
|
|
56
|
+
options.closable && closeDialog(element, options)
|
|
56
57
|
}
|
|
57
58
|
})
|
|
58
59
|
|
|
59
|
-
|
|
60
|
+
element.addEventListener('click', ({ target }) => {
|
|
60
61
|
if (target.nodeName === 'DIALOG' && options.closable) {
|
|
61
|
-
closeDialog(
|
|
62
|
+
closeDialog(element, options)
|
|
62
63
|
}
|
|
63
64
|
})
|
|
64
65
|
|
|
65
|
-
|
|
66
|
+
element._dialogHasEvents = true
|
|
66
67
|
}
|
|
67
68
|
|
|
68
|
-
|
|
69
|
-
|
|
69
|
+
element.inert = false
|
|
70
|
+
element.classList.add(options.openClass)
|
|
70
71
|
|
|
71
72
|
window.HTMLDialogElement
|
|
72
|
-
?
|
|
73
|
-
:
|
|
73
|
+
? element.showModal()
|
|
74
|
+
: element.setAttribute('open', '')
|
|
74
75
|
}
|
|
75
76
|
|
|
76
77
|
/**
|
|
77
78
|
* Closes and dismisses a dialog.
|
|
78
|
-
* @param {HTMLDialogElement}
|
|
79
|
-
* @param {import("./
|
|
79
|
+
* @param {HTMLDialogElement} element - The dialog element to dismiss.
|
|
80
|
+
* @param {import("./").DefaultOptions} options - The options for closing the dialog.
|
|
80
81
|
* @returns Promise<void>
|
|
81
82
|
*/
|
|
82
|
-
export const closeDialog = async (
|
|
83
|
+
export const closeDialog = async (element, options = {}) => {
|
|
83
84
|
options = {
|
|
84
85
|
...defaultOptions,
|
|
85
86
|
...options
|
|
86
87
|
}
|
|
87
88
|
|
|
88
89
|
window.HTMLDialogElement
|
|
89
|
-
?
|
|
90
|
-
:
|
|
90
|
+
? element.close()
|
|
91
|
+
: element.removeAttribute('open')
|
|
91
92
|
|
|
92
|
-
await dismissDialog(
|
|
93
|
+
await dismissDialog(element, options)
|
|
93
94
|
}
|
|
94
95
|
|
|
95
96
|
/**
|
|
96
97
|
* Inserts a dialog into the DOM.
|
|
97
98
|
* @param {string} content - The HTML content to insert into the dialog.
|
|
98
|
-
* @param {import("./
|
|
99
|
+
* @param {import("./").InsertDialogOptions} options - The options for inserting the dialog.
|
|
99
100
|
* @returns Promise<void>
|
|
100
101
|
*/
|
|
101
102
|
export const insertDialog = async (content, options = {}) => {
|
|
@@ -109,7 +110,7 @@ export const insertDialog = async (content, options = {}) => {
|
|
|
109
110
|
...options
|
|
110
111
|
}
|
|
111
112
|
|
|
112
|
-
const dialog = new DOMParser().parseFromString(content, 'text/html').body.
|
|
113
|
+
const dialog = new DOMParser().parseFromString(content, 'text/html').body.firstElementChild
|
|
113
114
|
dialog.classList.add(options.class)
|
|
114
115
|
|
|
115
116
|
if (!dialogSelector(options.selector) || options.append) {
|
|
@@ -123,19 +124,10 @@ export const insertDialog = async (content, options = {}) => {
|
|
|
123
124
|
|
|
124
125
|
/**
|
|
125
126
|
* Fetches a dialog from a URL and inserts it into the DOM.
|
|
126
|
-
* @param {import("./
|
|
127
|
+
* @param {import("./").FetchDialogOptions} options - The options for fetching and inserting the dialog.
|
|
127
128
|
*/
|
|
128
129
|
export const fetchDialog = async ({ url, insert = {} }) => {
|
|
129
130
|
await fetch(url, { headers: { 'X-Requested-With': 'XMLHttpRequest' } })
|
|
130
131
|
.then(response => response.json())
|
|
131
132
|
.then(async ({ content }) => await insertDialog(content, insert))
|
|
132
133
|
}
|
|
133
|
-
|
|
134
|
-
export default {
|
|
135
|
-
defaultOptions,
|
|
136
|
-
dismissDialog,
|
|
137
|
-
showDialog,
|
|
138
|
-
closeDialog,
|
|
139
|
-
insertDialog,
|
|
140
|
-
fetchDialog
|
|
141
|
-
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
.c-drawer-content {
|
|
2
|
+
--c-drawer-content-width: calc(100vw - 4rem);
|
|
3
|
+
--c-drawer-content-height: 100%;
|
|
4
|
+
|
|
5
|
+
width: var(--c-drawer-content-width);
|
|
6
|
+
height: var(--c-drawer-content-height);
|
|
7
|
+
flex-shrink: 0;
|
|
8
|
+
scroll-snap-align: end;
|
|
9
|
+
background-color: var(--color-body-primary);
|
|
10
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
.c-drawer {
|
|
2
|
+
--c-drawer-bg-opacity: 0.75;
|
|
3
|
+
--tw-bg-opacity: 0;
|
|
4
|
+
|
|
5
|
+
z-index: var(--z-30);
|
|
6
|
+
position: fixed;
|
|
7
|
+
inset: 0;
|
|
8
|
+
display: flex;
|
|
9
|
+
overflow: auto hidden;
|
|
10
|
+
background-color: color-mix(in srgb, var(--color-dark) calc(var(--tw-bg-opacity) * var(--c-drawer-bg-opacity) * 100%), transparent);
|
|
11
|
+
scrollbar-width: none;
|
|
12
|
+
scroll-behavior: smooth;
|
|
13
|
+
-webkit-overflow-scrolling: touch;
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
&::-webkit-scrollbar {
|
|
17
|
+
display: none;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
&::after {
|
|
21
|
+
content: "";
|
|
22
|
+
min-width: 100vw;
|
|
23
|
+
scroll-snap-align: end;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
&[inert] {
|
|
27
|
+
pointer-events: none;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
&.flex-col {
|
|
31
|
+
overflow: hidden auto;
|
|
32
|
+
|
|
33
|
+
&::after {
|
|
34
|
+
min-height: 100dvh;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface ScrollDrawerOptions {
|
|
2
|
+
snapClass?: string
|
|
3
|
+
opacityProperty?: string
|
|
4
|
+
opacityRatio?: number
|
|
5
|
+
scrollOpen?: number
|
|
6
|
+
scrollClose?: number
|
|
7
|
+
scrollSize?: number
|
|
8
|
+
scrollDirection?:number
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function showDrawer(element: HTMLElement | Element, distance: number, direction: 'left' | 'top'): void
|
|
12
|
+
export function closeDrawer(element: HTMLElement | Element, distance: number, direction: 'left' | 'top'): void
|
|
13
|
+
export function scrollDrawer(element: HTMLElement | Element, options: ScrollDrawerOptions): void
|