webcoreui 1.3.0 → 1.4.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.
Files changed (49) hide show
  1. package/README.md +6 -3
  2. package/astro.d.ts +6 -0
  3. package/astro.js +4 -0
  4. package/components/Accordion/Accordion.astro +1 -0
  5. package/components/Accordion/Accordion.svelte +1 -1
  6. package/components/Accordion/Accordion.tsx +1 -1
  7. package/components/Accordion/accordion.ts +1 -0
  8. package/components/Avatar/Avatar.astro +4 -2
  9. package/components/Avatar/Avatar.svelte +6 -4
  10. package/components/Avatar/Avatar.tsx +4 -2
  11. package/components/Checkbox/Checkbox.svelte +2 -0
  12. package/components/Checkbox/Checkbox.tsx +0 -2
  13. package/components/Checkbox/checkbox.ts +3 -1
  14. package/components/Collapsible/collapsible.ts +1 -1
  15. package/components/DataTable/DataTable.astro +4 -4
  16. package/components/DataTable/DataTable.svelte +1 -1
  17. package/components/DataTable/DataTable.tsx +1 -1
  18. package/components/Image/Image.astro +45 -0
  19. package/components/Image/Image.svelte +51 -0
  20. package/components/Image/Image.tsx +52 -0
  21. package/components/Image/image.module.scss +47 -0
  22. package/components/Image/image.ts +13 -0
  23. package/components/ImageLoader/ImageLoader.astro +82 -0
  24. package/components/ImageLoader/ImageLoader.svelte +72 -0
  25. package/components/ImageLoader/ImageLoader.tsx +82 -0
  26. package/components/ImageLoader/imageloader.module.scss +13 -0
  27. package/components/ImageLoader/imageloader.ts +6 -0
  28. package/components/Input/input.ts +2 -2
  29. package/components/Popover/popover.module.scss +4 -2
  30. package/components/RangeSlider/RangeSlider.svelte +3 -3
  31. package/components/RangeSlider/RangeSlider.tsx +1 -1
  32. package/components/Switch/Switch.svelte +2 -0
  33. package/components/Switch/Switch.tsx +0 -2
  34. package/components/Switch/switch.module.scss +1 -0
  35. package/components/Switch/switch.ts +3 -1
  36. package/components/Textarea/Textarea.svelte +2 -0
  37. package/components/Textarea/textarea.ts +7 -6
  38. package/components/ThemeSwitcher/themeswitcher.module.scss +1 -0
  39. package/components/ThemeSwitcher/themeswitcher.ts +1 -0
  40. package/index.d.ts +12 -5
  41. package/package.json +22 -22
  42. package/react.d.ts +6 -0
  43. package/react.js +4 -0
  44. package/scss/resets.scss +2 -0
  45. package/svelte.d.ts +6 -0
  46. package/svelte.js +4 -0
  47. package/utils/DOMUtils.ts +3 -3
  48. package/utils/modal.ts +2 -2
  49. package/utils/popover.ts +87 -46
package/utils/popover.ts CHANGED
@@ -14,6 +14,12 @@ export type PopoverPosition = 'top'
14
14
  | 'bottom-start'
15
15
  | 'bottom-end'
16
16
 
17
+ export type PopoverInstance = {
18
+ close: () => void
19
+ destroy: () => void
20
+ remove: () => void
21
+ }
22
+
17
23
  export type PopoverCallback = {
18
24
  trigger: HTMLElement
19
25
  popover: HTMLElement
@@ -40,7 +46,7 @@ export const popover = ({
40
46
  closeOnEsc = true,
41
47
  onOpen,
42
48
  onClose
43
- }: Popover) => {
49
+ }: Popover): PopoverInstance | undefined => {
44
50
  const triggerDOM = document.querySelector(trigger) as HTMLElement
45
51
  const popoverDOM = document.querySelector(popover) as HTMLElement
46
52
 
@@ -51,7 +57,7 @@ export const popover = ({
51
57
  popoverDOM.dataset.position = position.split('-')[0]
52
58
  }
53
59
 
54
- const handleOpen = () => {
60
+ const getPosition = () => {
55
61
  const triggerPosition = triggerDOM.getBoundingClientRect()
56
62
  const popoverPosition = popoverDOM.getBoundingClientRect()
57
63
 
@@ -139,77 +145,105 @@ export const popover = ({
139
145
  }
140
146
  }
141
147
 
142
- const { top, left } = positions[position as keyof typeof positions] || positions.bottom
148
+ let finalPosition = position || 'bottom'
149
+ let { top, left } = positions[finalPosition]
150
+
151
+ const viewportTop = window.scrollY
152
+ const viewportBottom = window.scrollY + window.innerHeight
153
+ const viewportLeft = 0
154
+ const viewportRight = window.innerWidth
155
+
156
+ const overflowsTop = top < viewportTop
157
+ const overflowsBottom = top + popoverPosition.height > viewportBottom
158
+ const overflowsLeft = left < viewportLeft
159
+ const overflowsRight = left + popoverPosition.width > viewportRight
160
+
161
+ if (finalPosition.startsWith('bottom') && overflowsBottom) {
162
+ finalPosition = finalPosition.replace('bottom', 'top') as PopoverPosition
163
+ } else if (finalPosition.startsWith('top') && overflowsTop) {
164
+ finalPosition = finalPosition.replace('top', 'bottom') as PopoverPosition
165
+ } else if (finalPosition.startsWith('right') && overflowsRight) {
166
+ finalPosition = finalPosition.replace('right', 'left') as PopoverPosition
167
+ } else if (finalPosition.startsWith('left') && overflowsLeft) {
168
+ finalPosition = finalPosition.replace('left', 'right') as PopoverPosition
169
+ }
170
+
171
+ ({ top, left } = positions[finalPosition])
172
+
173
+ top = Math.max(viewportTop, Math.min(top, viewportBottom - popoverPosition.height))
174
+ left = Math.max(viewportLeft, Math.min(left, viewportRight - popoverPosition.width))
143
175
 
176
+ popoverDOM.dataset.position = finalPosition.split('-')[0]
177
+
178
+ return { top, left }
179
+ }
180
+
181
+ const handleOpen = () => {
182
+ const { top, left } = getPosition()
183
+
184
+ popoverDOM.dataset.noTransition = 'true'
144
185
  popoverDOM.style.top = `${top}px`
145
186
  popoverDOM.style.left = `${left}px`
146
187
 
147
- setTimeout(() => {
148
- popoverDOM.dataset.show = popoverDOM.dataset.show === 'true'
149
- ? ''
150
- : 'true'
151
- }, 0)
188
+ popoverDOM.getBoundingClientRect()
189
+ popoverDOM.removeAttribute('data-no-transition')
152
190
 
153
- setTimeout(() => {
154
- if (!popoverDOM.dataset.show) {
155
- popoverDOM.removeAttribute('data-show')
156
- }
157
- }, 300)
191
+ if (popoverDOM.dataset.show) {
192
+ popoverDOM.removeAttribute('data-show')
193
+ } else {
194
+ popoverDOM.dataset.show = 'true'
195
+ }
158
196
 
159
197
  onOpen?.({
160
198
  trigger: triggerDOM,
161
199
  popover: popoverDOM,
162
- position
200
+ position: popoverDOM.dataset.position as PopoverPosition
163
201
  })
164
202
  }
165
203
 
166
- const handleClose = (event: MouseEvent) => {
167
- const target = event.target as HTMLElement
168
- const hidePopover = !popoverDOM.contains(target)
169
- && !triggerDOM.contains(target)
170
- && popoverDOM.dataset.show
204
+ const closePopover = () => {
205
+ if (popoverDOM.dataset.show !== 'true') {
206
+ return
207
+ }
171
208
 
172
- if (hidePopover) {
173
- popoverDOM.dataset.show = ''
209
+ popoverDOM.removeAttribute('data-show')
210
+
211
+ const handleTransitionEnd = (e: TransitionEvent) => {
212
+ if (e.target !== popoverDOM) {
213
+ return
214
+ }
215
+
216
+ popoverDOM.removeEventListener('transitionend', handleTransitionEnd)
174
217
 
175
218
  onClose?.({
176
219
  trigger: triggerDOM,
177
220
  popover: popoverDOM,
178
- position
221
+ position: popoverDOM.dataset.position as PopoverPosition
179
222
  })
180
223
  }
181
224
 
182
- setTimeout(() => {
183
- if (!popoverDOM.dataset.show) {
184
- popoverDOM.removeAttribute('data-show')
185
- }
186
- }, 300)
225
+ popoverDOM.addEventListener('transitionend', handleTransitionEnd)
187
226
  }
188
227
 
189
- const handleCloseOnEsc = (event: KeyboardEvent) => {
190
- if (event.key === 'Escape' && popoverDOM.dataset.show) {
191
- popoverDOM.dataset.show = ''
228
+ const handleClose = (event: MouseEvent) => {
229
+ const target = event.target as HTMLElement
230
+ const hidePopover = !popoverDOM.contains(target)
231
+ && !triggerDOM.contains(target)
232
+ && popoverDOM.dataset.show
192
233
 
193
- onClose?.({
194
- trigger: triggerDOM,
195
- popover: popoverDOM,
196
- position
197
- })
234
+ if (hidePopover) {
235
+ closePopover()
236
+ }
237
+ }
198
238
 
199
- setTimeout(() => {
200
- popoverDOM.removeAttribute('data-show')
201
- }, 300)
239
+ const handleCloseOnEsc = (event: KeyboardEvent) => {
240
+ if (event.key === 'Escape' && popoverDOM.dataset.show) {
241
+ closePopover()
202
242
  }
203
243
  }
204
244
 
205
245
  const removeOnResize = debounce(() => {
206
- popoverDOM.dataset.show = ''
207
-
208
- setTimeout(() => {
209
- if (!popoverDOM.dataset.show) {
210
- popoverDOM.removeAttribute('data-show')
211
- }
212
- }, 300)
246
+ closePopover()
213
247
  })
214
248
 
215
249
  const observer = new ResizeObserver(() => {
@@ -230,7 +264,10 @@ export const popover = ({
230
264
  }
231
265
 
232
266
  return {
233
- remove() {
267
+ close() {
268
+ closePopover()
269
+ },
270
+ destroy() {
234
271
  triggerDOM.removeEventListener('click', handleOpen)
235
272
  observer.disconnect()
236
273
 
@@ -241,6 +278,10 @@ export const popover = ({
241
278
  if (closeOnEsc) {
242
279
  document.removeEventListener('keydown', handleCloseOnEsc)
243
280
  }
281
+ },
282
+ remove() {
283
+ popoverDOM.remove()
284
+ this.destroy()
244
285
  }
245
286
  }
246
287
  }