polymorph-ui-components 0.1.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 (242) hide show
  1. package/README.md +354 -0
  2. package/dist/Accordion/Accordion.svelte +28 -0
  3. package/dist/Accordion/Accordion.svelte.d.ts +4 -0
  4. package/dist/Accordion/properties.d.ts +7 -0
  5. package/dist/Accordion/properties.js +1 -0
  6. package/dist/Animations/ModalAnimation.svelte +55 -0
  7. package/dist/Animations/ModalAnimation.svelte.d.ts +12 -0
  8. package/dist/Animations/OverlayAnimation.svelte +14 -0
  9. package/dist/Animations/OverlayAnimation.svelte.d.ts +7 -0
  10. package/dist/Avatar/Avatar.svelte +122 -0
  11. package/dist/Avatar/Avatar.svelte.d.ts +4 -0
  12. package/dist/Avatar/properties.d.ts +15 -0
  13. package/dist/Avatar/properties.js +1 -0
  14. package/dist/Badge/Badge.svelte +53 -0
  15. package/dist/Badge/Badge.svelte.d.ts +4 -0
  16. package/dist/Badge/properties.d.ts +6 -0
  17. package/dist/Badge/properties.js +1 -0
  18. package/dist/Banner/Banner.svelte +158 -0
  19. package/dist/Banner/Banner.svelte.d.ts +4 -0
  20. package/dist/Banner/properties.d.ts +19 -0
  21. package/dist/Banner/properties.js +1 -0
  22. package/dist/Book/Book.svelte +281 -0
  23. package/dist/Book/Book.svelte.d.ts +4 -0
  24. package/dist/Book/properties.d.ts +24 -0
  25. package/dist/Book/properties.js +1 -0
  26. package/dist/Browser/Browser.svelte +176 -0
  27. package/dist/Browser/Browser.svelte.d.ts +3 -0
  28. package/dist/Browser/properties.d.ts +14 -0
  29. package/dist/Browser/properties.js +1 -0
  30. package/dist/Button/Button.svelte +153 -0
  31. package/dist/Button/Button.svelte.d.ts +4 -0
  32. package/dist/Button/properties.d.ts +24 -0
  33. package/dist/Button/properties.js +1 -0
  34. package/dist/Calendar/Calendar.svelte +477 -0
  35. package/dist/Calendar/Calendar.svelte.d.ts +4 -0
  36. package/dist/Calendar/properties.d.ts +30 -0
  37. package/dist/Calendar/properties.js +1 -0
  38. package/dist/Carousel/Carousel.svelte +258 -0
  39. package/dist/Carousel/Carousel.svelte.d.ts +4 -0
  40. package/dist/Carousel/properties.d.ts +20 -0
  41. package/dist/Carousel/properties.js +1 -0
  42. package/dist/CheckListItem/CheckListItem.svelte +65 -0
  43. package/dist/CheckListItem/CheckListItem.svelte.d.ts +4 -0
  44. package/dist/CheckListItem/properties.d.ts +15 -0
  45. package/dist/CheckListItem/properties.js +1 -0
  46. package/dist/Checkbox/Checkbox.svelte +157 -0
  47. package/dist/Checkbox/Checkbox.svelte.d.ts +4 -0
  48. package/dist/Checkbox/properties.d.ts +17 -0
  49. package/dist/Checkbox/properties.js +1 -0
  50. package/dist/Choicebox/Choicebox.svelte +85 -0
  51. package/dist/Choicebox/Choicebox.svelte.d.ts +4 -0
  52. package/dist/Choicebox/properties.d.ts +14 -0
  53. package/dist/Choicebox/properties.js +1 -0
  54. package/dist/ColorPicker/ColorPicker.svelte +583 -0
  55. package/dist/ColorPicker/ColorPicker.svelte.d.ts +4 -0
  56. package/dist/ColorPicker/properties.d.ts +15 -0
  57. package/dist/ColorPicker/properties.js +1 -0
  58. package/dist/Combobox/Combobox.svelte +432 -0
  59. package/dist/Combobox/Combobox.svelte.d.ts +6 -0
  60. package/dist/Combobox/properties.d.ts +42 -0
  61. package/dist/Combobox/properties.js +1 -0
  62. package/dist/CommandMenu/CommandMenu.svelte +452 -0
  63. package/dist/CommandMenu/CommandMenu.svelte.d.ts +4 -0
  64. package/dist/CommandMenu/properties.d.ts +26 -0
  65. package/dist/CommandMenu/properties.js +1 -0
  66. package/dist/ContextMenu/ContextMenu.svelte +308 -0
  67. package/dist/ContextMenu/ContextMenu.svelte.d.ts +4 -0
  68. package/dist/ContextMenu/properties.d.ts +26 -0
  69. package/dist/ContextMenu/properties.js +1 -0
  70. package/dist/Gauge/Gauge.svelte +70 -0
  71. package/dist/Gauge/Gauge.svelte.d.ts +4 -0
  72. package/dist/Gauge/properties.d.ts +9 -0
  73. package/dist/Gauge/properties.js +1 -0
  74. package/dist/GridItem/GridItem.svelte +145 -0
  75. package/dist/GridItem/GridItem.svelte.d.ts +4 -0
  76. package/dist/GridItem/properties.d.ts +15 -0
  77. package/dist/GridItem/properties.js +1 -0
  78. package/dist/Icon/Icon.svelte +61 -0
  79. package/dist/Icon/Icon.svelte.d.ts +4 -0
  80. package/dist/Icon/properties.d.ts +12 -0
  81. package/dist/Icon/properties.js +1 -0
  82. package/dist/IconStack/IconStack.svelte +55 -0
  83. package/dist/IconStack/IconStack.svelte.d.ts +4 -0
  84. package/dist/IconStack/properties.d.ts +9 -0
  85. package/dist/IconStack/properties.js +1 -0
  86. package/dist/Img/Img.svelte +37 -0
  87. package/dist/Img/Img.svelte.d.ts +4 -0
  88. package/dist/Img/properties.d.ts +13 -0
  89. package/dist/Img/properties.js +1 -0
  90. package/dist/Input/Input.svelte +349 -0
  91. package/dist/Input/Input.svelte.d.ts +8 -0
  92. package/dist/Input/properties.d.ts +45 -0
  93. package/dist/Input/properties.js +1 -0
  94. package/dist/InputButton/InputButton.svelte +252 -0
  95. package/dist/InputButton/InputButton.svelte.d.ts +7 -0
  96. package/dist/InputButton/properties.d.ts +22 -0
  97. package/dist/InputButton/properties.js +1 -0
  98. package/dist/KeyboardInput/KeyboardInput.svelte +93 -0
  99. package/dist/KeyboardInput/KeyboardInput.svelte.d.ts +4 -0
  100. package/dist/KeyboardInput/properties.d.ts +12 -0
  101. package/dist/KeyboardInput/properties.js +1 -0
  102. package/dist/ListItem/ListItem.svelte +309 -0
  103. package/dist/ListItem/ListItem.svelte.d.ts +4 -0
  104. package/dist/ListItem/properties.d.ts +34 -0
  105. package/dist/ListItem/properties.js +1 -0
  106. package/dist/Loader/Loader.svelte +90 -0
  107. package/dist/Loader/Loader.svelte.d.ts +4 -0
  108. package/dist/Loader/properties.d.ts +4 -0
  109. package/dist/Loader/properties.js +1 -0
  110. package/dist/LoadingDots/LoadingDots.svelte +59 -0
  111. package/dist/LoadingDots/LoadingDots.svelte.d.ts +3 -0
  112. package/dist/LoadingDots/properties.d.ts +8 -0
  113. package/dist/LoadingDots/properties.js +1 -0
  114. package/dist/Menu/Menu.svelte +356 -0
  115. package/dist/Menu/Menu.svelte.d.ts +4 -0
  116. package/dist/Menu/properties.d.ts +28 -0
  117. package/dist/Menu/properties.js +1 -0
  118. package/dist/Modal/Modal.svelte +357 -0
  119. package/dist/Modal/Modal.svelte.d.ts +4 -0
  120. package/dist/Modal/properties.d.ts +39 -0
  121. package/dist/Modal/properties.js +1 -0
  122. package/dist/Pagination/Pagination.svelte +148 -0
  123. package/dist/Pagination/Pagination.svelte.d.ts +4 -0
  124. package/dist/Pagination/properties.d.ts +14 -0
  125. package/dist/Pagination/properties.js +1 -0
  126. package/dist/Phone/Phone.svelte +234 -0
  127. package/dist/Phone/Phone.svelte.d.ts +3 -0
  128. package/dist/Phone/properties.d.ts +11 -0
  129. package/dist/Phone/properties.js +1 -0
  130. package/dist/Pill/Pill.svelte +130 -0
  131. package/dist/Pill/Pill.svelte.d.ts +4 -0
  132. package/dist/Pill/properties.d.ts +16 -0
  133. package/dist/Pill/properties.js +1 -0
  134. package/dist/Progress/Progress.svelte +68 -0
  135. package/dist/Progress/Progress.svelte.d.ts +4 -0
  136. package/dist/Progress/properties.d.ts +10 -0
  137. package/dist/Progress/properties.js +1 -0
  138. package/dist/Radio/Radio.svelte +124 -0
  139. package/dist/Radio/Radio.svelte.d.ts +4 -0
  140. package/dist/Radio/properties.d.ts +15 -0
  141. package/dist/Radio/properties.js +1 -0
  142. package/dist/RelativeTime/RelativeTime.svelte +109 -0
  143. package/dist/RelativeTime/RelativeTime.svelte.d.ts +4 -0
  144. package/dist/RelativeTime/properties.d.ts +13 -0
  145. package/dist/RelativeTime/properties.js +1 -0
  146. package/dist/Scroller/Scroller.svelte +390 -0
  147. package/dist/Scroller/Scroller.svelte.d.ts +4 -0
  148. package/dist/Scroller/properties.d.ts +30 -0
  149. package/dist/Scroller/properties.js +1 -0
  150. package/dist/Select/Select.svelte +472 -0
  151. package/dist/Select/Select.svelte.d.ts +4 -0
  152. package/dist/Select/properties.d.ts +20 -0
  153. package/dist/Select/properties.js +1 -0
  154. package/dist/Sheet/Sheet.svelte +264 -0
  155. package/dist/Sheet/Sheet.svelte.d.ts +4 -0
  156. package/dist/Sheet/properties.d.ts +19 -0
  157. package/dist/Sheet/properties.js +1 -0
  158. package/dist/Shimmer/Shimmer.svelte +44 -0
  159. package/dist/Shimmer/Shimmer.svelte.d.ts +4 -0
  160. package/dist/Shimmer/properties.d.ts +4 -0
  161. package/dist/Shimmer/properties.js +1 -0
  162. package/dist/Slider/Slider.svelte +147 -0
  163. package/dist/Slider/Slider.svelte.d.ts +4 -0
  164. package/dist/Slider/properties.d.ts +17 -0
  165. package/dist/Slider/properties.js +1 -0
  166. package/dist/Snippet/Snippet.svelte +123 -0
  167. package/dist/Snippet/Snippet.svelte.d.ts +4 -0
  168. package/dist/Snippet/properties.d.ts +15 -0
  169. package/dist/Snippet/properties.js +1 -0
  170. package/dist/SplitButton/SplitButton.svelte +145 -0
  171. package/dist/SplitButton/SplitButton.svelte.d.ts +4 -0
  172. package/dist/SplitButton/properties.d.ts +17 -0
  173. package/dist/SplitButton/properties.js +1 -0
  174. package/dist/SplitInput/SplitInput.svelte +225 -0
  175. package/dist/SplitInput/SplitInput.svelte.d.ts +7 -0
  176. package/dist/SplitInput/properties.d.ts +20 -0
  177. package/dist/SplitInput/properties.js +1 -0
  178. package/dist/Stepper/Step.svelte +88 -0
  179. package/dist/Stepper/Step.svelte.d.ts +4 -0
  180. package/dist/Stepper/Stepper.svelte +64 -0
  181. package/dist/Stepper/Stepper.svelte.d.ts +4 -0
  182. package/dist/Stepper/properties.d.ts +27 -0
  183. package/dist/Stepper/properties.js +1 -0
  184. package/dist/Table/Table.svelte +357 -0
  185. package/dist/Table/Table.svelte.d.ts +4 -0
  186. package/dist/Table/properties.d.ts +26 -0
  187. package/dist/Table/properties.js +1 -0
  188. package/dist/Tabs/Tabs.svelte +303 -0
  189. package/dist/Tabs/Tabs.svelte.d.ts +4 -0
  190. package/dist/Tabs/properties.d.ts +30 -0
  191. package/dist/Tabs/properties.js +1 -0
  192. package/dist/ThemeSwitcher/ThemeSwitcher.svelte +249 -0
  193. package/dist/ThemeSwitcher/ThemeSwitcher.svelte.d.ts +4 -0
  194. package/dist/ThemeSwitcher/properties.d.ts +19 -0
  195. package/dist/ThemeSwitcher/properties.js +1 -0
  196. package/dist/Toast/Toast.svelte +220 -0
  197. package/dist/Toast/Toast.svelte.d.ts +4 -0
  198. package/dist/Toast/properties.d.ts +24 -0
  199. package/dist/Toast/properties.js +1 -0
  200. package/dist/Toggle/Toggle.svelte +99 -0
  201. package/dist/Toggle/Toggle.svelte.d.ts +4 -0
  202. package/dist/Toggle/properties.d.ts +9 -0
  203. package/dist/Toggle/properties.js +1 -0
  204. package/dist/Toolbar/Toolbar.svelte +142 -0
  205. package/dist/Toolbar/Toolbar.svelte.d.ts +4 -0
  206. package/dist/Toolbar/properties.d.ts +16 -0
  207. package/dist/Toolbar/properties.js +1 -0
  208. package/dist/Tooltip/Tooltip.svelte +153 -0
  209. package/dist/Tooltip/Tooltip.svelte.d.ts +4 -0
  210. package/dist/Tooltip/properties.d.ts +13 -0
  211. package/dist/Tooltip/properties.js +1 -0
  212. package/dist/assets/back.svg +3 -0
  213. package/dist/assets/battery.svg +5 -0
  214. package/dist/assets/checkmark.svg +3 -0
  215. package/dist/assets/chevron-down-sm.svg +3 -0
  216. package/dist/assets/chevron-down.svg +3 -0
  217. package/dist/assets/chevron-left-lg.svg +3 -0
  218. package/dist/assets/chevron-left.svg +3 -0
  219. package/dist/assets/chevron-right-lg.svg +3 -0
  220. package/dist/assets/chevron-right.svg +3 -0
  221. package/dist/assets/chevron-up.svg +3 -0
  222. package/dist/assets/close.svg +4 -0
  223. package/dist/assets/copy.svg +4 -0
  224. package/dist/assets/error-circle.svg +5 -0
  225. package/dist/assets/lock.svg +3 -0
  226. package/dist/assets/minus.svg +3 -0
  227. package/dist/assets/monitor.svg +5 -0
  228. package/dist/assets/moon.svg +3 -0
  229. package/dist/assets/palette.svg +7 -0
  230. package/dist/assets/search.svg +4 -0
  231. package/dist/assets/signal.svg +6 -0
  232. package/dist/assets/sort-default.svg +4 -0
  233. package/dist/assets/sun.svg +11 -0
  234. package/dist/assets/swap-vertical.svg +6 -0
  235. package/dist/assets/wifi.svg +3 -0
  236. package/dist/index.d.ts +103 -0
  237. package/dist/index.js +55 -0
  238. package/dist/types.d.ts +42 -0
  239. package/dist/types.js +1 -0
  240. package/dist/utils.d.ts +28 -0
  241. package/dist/utils.js +294 -0
  242. package/package.json +91 -0
@@ -0,0 +1,109 @@
1
+ <script lang="ts">
2
+ import type { RelativeTimeProperties } from './properties';
3
+ import Tooltip from '../Tooltip/Tooltip.svelte';
4
+ import { onMount } from 'svelte';
5
+
6
+ let {
7
+ date,
8
+ locale,
9
+ format = 'long',
10
+ updateInterval = 60000,
11
+ tooltip = false,
12
+ testId,
13
+ classes
14
+ }: RelativeTimeProperties = $props();
15
+
16
+ let resolvedDate = $derived(date instanceof Date ? date : new Date(date));
17
+
18
+ let isoString = $derived(resolvedDate.toISOString());
19
+
20
+ let fullDateText = $derived(
21
+ resolvedDate.toLocaleString(locale, {
22
+ dateStyle: 'full',
23
+ timeStyle: 'short'
24
+ })
25
+ );
26
+
27
+ let relativeText = $state('');
28
+
29
+ function computeRelativeTime(): string {
30
+ const now = Date.now();
31
+ const target = resolvedDate.getTime();
32
+ const diffMs = target - now;
33
+ const absDiffMs = Math.abs(diffMs);
34
+
35
+ const seconds = Math.round(absDiffMs / 1000);
36
+ const minutes = Math.round(absDiffMs / 60000);
37
+ const hours = Math.round(absDiffMs / 3600000);
38
+ const days = Math.round(absDiffMs / 86400000);
39
+ const weeks = Math.round(absDiffMs / 604800000);
40
+ const months = Math.round(absDiffMs / 2592000000);
41
+ const years = Math.round(absDiffMs / 31536000000);
42
+
43
+ const formatter = new Intl.RelativeTimeFormat(locale, { style: format });
44
+
45
+ let unit: Intl.RelativeTimeFormatUnit;
46
+ let value: number;
47
+
48
+ if (seconds < 60) {
49
+ unit = 'second';
50
+ value = seconds;
51
+ } else if (minutes < 60) {
52
+ unit = 'minute';
53
+ value = minutes;
54
+ } else if (hours < 24) {
55
+ unit = 'hour';
56
+ value = hours;
57
+ } else if (days < 7) {
58
+ unit = 'day';
59
+ value = days;
60
+ } else if (weeks < 4) {
61
+ unit = 'week';
62
+ value = weeks;
63
+ } else if (months < 12) {
64
+ unit = 'month';
65
+ value = months;
66
+ } else {
67
+ unit = 'year';
68
+ value = years;
69
+ }
70
+
71
+ const sign = diffMs < 0 ? -1 : 1;
72
+ return formatter.format(sign * value, unit);
73
+ }
74
+
75
+ function updateRelativeTime() {
76
+ relativeText = computeRelativeTime();
77
+ }
78
+
79
+ onMount(() => {
80
+ updateRelativeTime();
81
+
82
+ if (updateInterval > 0) {
83
+ const intervalId = setInterval(updateRelativeTime, updateInterval);
84
+ return () => clearInterval(intervalId);
85
+ }
86
+ });
87
+ </script>
88
+
89
+ {#if tooltip}
90
+ <Tooltip text={fullDateText}>
91
+ <time class="relative-time {classes ?? ''}" datetime={isoString} data-pw={testId}>
92
+ {relativeText}
93
+ </time>
94
+ </Tooltip>
95
+ {:else}
96
+ <time class="relative-time {classes ?? ''}" datetime={isoString} data-pw={testId}>
97
+ {relativeText}
98
+ </time>
99
+ {/if}
100
+
101
+ <style>
102
+ .relative-time {
103
+ font-size: var(--relative-time-font-size, 14px);
104
+ font-weight: var(--relative-time-font-weight, 400);
105
+ font-family: var(--relative-time-font-family);
106
+ color: var(--relative-time-color, inherit);
107
+ cursor: var(--relative-time-cursor, default);
108
+ }
109
+ </style>
@@ -0,0 +1,4 @@
1
+ import type { RelativeTimeProperties } from './properties';
2
+ declare const RelativeTime: import("svelte").Component<RelativeTimeProperties, {}, "">;
3
+ type RelativeTime = ReturnType<typeof RelativeTime>;
4
+ export default RelativeTime;
@@ -0,0 +1,13 @@
1
+ export type RelativeTimeFormat = 'long' | 'short' | 'narrow';
2
+ export type MandatoryRelativeTimeProperties = {
3
+ date: Date | string | number;
4
+ };
5
+ export type OptionalRelativeTimeProperties = {
6
+ locale?: string;
7
+ format?: RelativeTimeFormat;
8
+ updateInterval?: number;
9
+ tooltip?: boolean;
10
+ testId?: string;
11
+ classes?: string;
12
+ };
13
+ export type RelativeTimeProperties = MandatoryRelativeTimeProperties & OptionalRelativeTimeProperties;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,390 @@
1
+ <script lang="ts">
2
+ import { onMount } from 'svelte';
3
+ import type { ScrollerProperties, ScrollPosition } from './properties';
4
+ import Button from '../Button/Button.svelte';
5
+ import chevronLeft from '../assets/chevron-left.svg?raw';
6
+ import chevronRight from '../assets/chevron-right.svg?raw';
7
+ import chevronUp from '../assets/chevron-up.svg?raw';
8
+ import chevronDown from '../assets/chevron-down.svg?raw';
9
+
10
+ let {
11
+ children,
12
+ direction = 'horizontal',
13
+ scrollAmount,
14
+ showArrows = true,
15
+ showGradient = true,
16
+ dragToScroll = false,
17
+ snapToItem = false,
18
+ hideScrollbar = true,
19
+ hideArrowsOnTouch = true,
20
+ smoothScroll = true,
21
+ testId,
22
+ arrowPrevious,
23
+ arrowNext,
24
+ onscrollposition,
25
+ classes
26
+ }: ScrollerProperties = $props();
27
+
28
+ let containerEl: HTMLDivElement | null = $state(null);
29
+ let canScrollPrev = $state(false);
30
+ let canScrollNext = $state(false);
31
+ let isTouchDevice = $state(false);
32
+ let isDragging = $state(false);
33
+ let dragStartPos = 0;
34
+ let dragScrollStart = 0;
35
+ let resizeObserver: ResizeObserver | null = null;
36
+
37
+ function getScrollProps(el: HTMLElement) {
38
+ if (direction === 'horizontal') {
39
+ return {
40
+ scrollOffset: el.scrollLeft,
41
+ scrollSize: el.scrollWidth,
42
+ clientSize: el.clientWidth
43
+ };
44
+ }
45
+ return {
46
+ scrollOffset: el.scrollTop,
47
+ scrollSize: el.scrollHeight,
48
+ clientSize: el.clientHeight
49
+ };
50
+ }
51
+
52
+ function updateScrollState() {
53
+ if (containerEl === null) {
54
+ return;
55
+ }
56
+ const { scrollOffset, scrollSize, clientSize } = getScrollProps(containerEl);
57
+ canScrollPrev = scrollOffset > 1;
58
+ canScrollNext = scrollOffset < scrollSize - clientSize - 1;
59
+
60
+ if (typeof onscrollposition === 'function') {
61
+ const maxScroll = scrollSize - clientSize;
62
+ const position: ScrollPosition = {
63
+ scrollOffset,
64
+ scrollSize,
65
+ clientSize,
66
+ progress: maxScroll > 0 ? scrollOffset / maxScroll : 0
67
+ };
68
+ onscrollposition(position);
69
+ }
70
+ }
71
+
72
+ function scrollBy(delta: number) {
73
+ if (containerEl === null) {
74
+ return;
75
+ }
76
+ const { clientSize } = getScrollProps(containerEl);
77
+ const amount = scrollAmount ?? clientSize;
78
+ const options: ScrollToOptions = {
79
+ behavior: smoothScroll ? 'smooth' : 'auto'
80
+ };
81
+ if (direction === 'horizontal') {
82
+ options.left = delta * amount;
83
+ } else {
84
+ options.top = delta * amount;
85
+ }
86
+ containerEl.scrollBy(options);
87
+ }
88
+
89
+ function scrollPrev() {
90
+ scrollBy(-1);
91
+ }
92
+
93
+ function scrollNext() {
94
+ scrollBy(1);
95
+ }
96
+
97
+ function handleDragStart(event: MouseEvent) {
98
+ if (!dragToScroll || containerEl === null) {
99
+ return;
100
+ }
101
+ isDragging = true;
102
+ dragStartPos = direction === 'horizontal' ? event.clientX : event.clientY;
103
+ dragScrollStart = direction === 'horizontal' ? containerEl.scrollLeft : containerEl.scrollTop;
104
+ containerEl.style.scrollBehavior = 'auto';
105
+ containerEl.style.userSelect = 'none';
106
+ }
107
+
108
+ function handleDragMove(event: MouseEvent) {
109
+ if (!isDragging || containerEl === null) {
110
+ return;
111
+ }
112
+ const currentPos = direction === 'horizontal' ? event.clientX : event.clientY;
113
+ const delta = dragStartPos - currentPos;
114
+ if (direction === 'horizontal') {
115
+ containerEl.scrollLeft = dragScrollStart + delta;
116
+ } else {
117
+ containerEl.scrollTop = dragScrollStart + delta;
118
+ }
119
+ }
120
+
121
+ function handleDragEnd() {
122
+ if (!isDragging || containerEl === null) {
123
+ return;
124
+ }
125
+ isDragging = false;
126
+ containerEl.style.scrollBehavior = smoothScroll ? 'smooth' : 'auto';
127
+ containerEl.style.userSelect = '';
128
+ }
129
+
130
+ onMount(() => {
131
+ isTouchDevice = 'ontouchstart' in window || navigator.maxTouchPoints > 0;
132
+ if (containerEl !== null) {
133
+ updateScrollState();
134
+ resizeObserver = new ResizeObserver(() => {
135
+ updateScrollState();
136
+ });
137
+ resizeObserver.observe(containerEl);
138
+
139
+ if (dragToScroll) {
140
+ window.addEventListener('mousemove', handleDragMove);
141
+ window.addEventListener('mouseup', handleDragEnd);
142
+ }
143
+ }
144
+ return () => {
145
+ resizeObserver?.disconnect();
146
+ if (dragToScroll) {
147
+ window.removeEventListener('mousemove', handleDragMove);
148
+ window.removeEventListener('mouseup', handleDragEnd);
149
+ }
150
+ };
151
+ });
152
+
153
+ let showArrowControls = $derived(showArrows && !(hideArrowsOnTouch && isTouchDevice));
154
+ let showGradientOverlay = $derived(showGradient && !(hideArrowsOnTouch && isTouchDevice));
155
+ </script>
156
+
157
+ <div
158
+ class="scroller {classes ?? ''}"
159
+ class:horizontal={direction === 'horizontal'}
160
+ class:vertical={direction === 'vertical'}
161
+ data-pw={testId}
162
+ >
163
+ {#if showArrowControls && canScrollPrev}
164
+ <div class="arrow arrow-prev">
165
+ <Button
166
+ onclick={scrollPrev}
167
+ ariaLabel="Scroll previous"
168
+ {...typeof testId === 'string' ? { testId: `${testId}-prev` } : {}}
169
+ >
170
+ {#if typeof arrowPrevious === 'function'}
171
+ {@render arrowPrevious()}
172
+ {:else}
173
+ <span class="arrow-icon">
174
+ <!-- eslint-disable svelte/no-at-html-tags -->
175
+ {@html direction === 'horizontal' ? chevronLeft : chevronUp}
176
+ </span>
177
+ {/if}
178
+ </Button>
179
+ </div>
180
+ {/if}
181
+
182
+ {#if showGradientOverlay && canScrollPrev}
183
+ <div class="gradient gradient-start"></div>
184
+ {/if}
185
+
186
+ <!-- svelte-ignore a11y_no_noninteractive_element_interactions -->
187
+ <div
188
+ class="scroll-container"
189
+ class:hide-scrollbar={hideScrollbar}
190
+ class:snap={snapToItem}
191
+ class:dragging={isDragging}
192
+ bind:this={containerEl}
193
+ onscroll={updateScrollState}
194
+ onmousedown={dragToScroll ? handleDragStart : null}
195
+ role="region"
196
+ tabindex="-1"
197
+ >
198
+ {@render children()}
199
+ </div>
200
+
201
+ {#if showGradientOverlay && canScrollNext}
202
+ <div class="gradient gradient-end"></div>
203
+ {/if}
204
+
205
+ {#if showArrowControls && canScrollNext}
206
+ <div class="arrow arrow-next">
207
+ <Button
208
+ onclick={scrollNext}
209
+ ariaLabel="Scroll next"
210
+ {...typeof testId === 'string' ? { testId: `${testId}-next` } : {}}
211
+ >
212
+ {#if typeof arrowNext === 'function'}
213
+ {@render arrowNext()}
214
+ {:else}
215
+ <span class="arrow-icon">
216
+ <!-- eslint-disable svelte/no-at-html-tags -->
217
+ {@html direction === 'horizontal' ? chevronRight : chevronDown}
218
+ </span>
219
+ {/if}
220
+ </Button>
221
+ </div>
222
+ {/if}
223
+ </div>
224
+
225
+ <style>
226
+ .scroller {
227
+ position: relative;
228
+ display: flex;
229
+ width: var(--scroller-width, 100%);
230
+ height: var(--scroller-height, fit-content);
231
+ }
232
+
233
+ .scroller.horizontal {
234
+ flex-direction: row;
235
+ align-items: center;
236
+ }
237
+
238
+ .scroller.vertical {
239
+ flex-direction: column;
240
+ align-items: stretch;
241
+ }
242
+
243
+ .scroll-container {
244
+ flex: 1;
245
+ display: flex;
246
+ overflow: auto;
247
+ gap: var(--scroller-gap, 0px);
248
+ padding: var(--scroller-padding, 0px);
249
+ }
250
+
251
+ .scroller.horizontal .scroll-container {
252
+ flex-direction: row;
253
+ overflow-x: auto;
254
+ overflow-y: hidden;
255
+ scroll-behavior: var(--scroller-scroll-behavior, smooth);
256
+ }
257
+
258
+ .scroller.vertical .scroll-container {
259
+ flex-direction: column;
260
+ overflow-y: auto;
261
+ overflow-x: hidden;
262
+ scroll-behavior: var(--scroller-scroll-behavior, smooth);
263
+ }
264
+
265
+ .scroll-container.snap {
266
+ scroll-snap-type: var(--scroller-snap-type, x mandatory);
267
+ }
268
+
269
+ .scroller.vertical .scroll-container.snap {
270
+ scroll-snap-type: var(--scroller-snap-type, y mandatory);
271
+ }
272
+
273
+ .scroll-container.hide-scrollbar {
274
+ -ms-overflow-style: none;
275
+ scrollbar-width: none;
276
+ }
277
+
278
+ .scroll-container.hide-scrollbar::-webkit-scrollbar {
279
+ display: none;
280
+ }
281
+
282
+ .scroll-container.dragging {
283
+ cursor: grabbing;
284
+ }
285
+
286
+ .arrow {
287
+ display: flex;
288
+ align-items: center;
289
+ justify-content: center;
290
+ flex-shrink: 0;
291
+ z-index: 1;
292
+ margin: var(--scroller-arrow-margin, 0px);
293
+
294
+ --button-width: var(--scroller-arrow-size, 32px);
295
+ --button-height: var(--scroller-arrow-size, 32px);
296
+ --button-border-radius: var(--scroller-arrow-border-radius, 50%);
297
+ --button-color: var(--scroller-arrow-background, #ffffff);
298
+ --button-border: var(--scroller-arrow-border, 1px solid currentColor);
299
+ --button-text-color: var(--scroller-arrow-color, currentColor);
300
+ --button-padding: var(--scroller-arrow-padding, 4px);
301
+ --button-box-shadow: var(--scroller-arrow-box-shadow, 0 1px 3px rgba(0, 0, 0, 0.12));
302
+ --button-hover-color: var(--scroller-arrow-hover-background, transparent);
303
+ --button-hover-text-color: var(
304
+ --scroller-arrow-hover-color,
305
+ var(--scroller-arrow-color, currentColor)
306
+ );
307
+ }
308
+
309
+ .arrow-icon {
310
+ display: flex;
311
+ align-items: center;
312
+ justify-content: center;
313
+ line-height: 0;
314
+ }
315
+
316
+ .arrow-icon :global(svg) {
317
+ width: var(--scroller-arrow-icon-size, 16px);
318
+ height: var(--scroller-arrow-icon-size, 16px);
319
+ }
320
+
321
+ .gradient {
322
+ position: absolute;
323
+ z-index: 1;
324
+ pointer-events: none;
325
+ }
326
+
327
+ .scroller.horizontal .gradient {
328
+ top: 0;
329
+ bottom: 0;
330
+ width: var(--scroller-gradient-size, 80px);
331
+ }
332
+
333
+ .scroller.horizontal .gradient-start {
334
+ left: var(--scroller-arrow-size, 32px);
335
+ background: var(
336
+ --scroller-gradient-start,
337
+ linear-gradient(
338
+ to right,
339
+ rgba(255, 255, 255, 1) 0%,
340
+ rgba(255, 255, 255, 0.5) 40%,
341
+ rgba(255, 255, 255, 0) 100%
342
+ )
343
+ );
344
+ }
345
+
346
+ .scroller.horizontal .gradient-end {
347
+ right: var(--scroller-arrow-size, 32px);
348
+ background: var(
349
+ --scroller-gradient-end,
350
+ linear-gradient(
351
+ to left,
352
+ rgba(255, 255, 255, 1) 0%,
353
+ rgba(255, 255, 255, 0.5) 40%,
354
+ rgba(255, 255, 255, 0) 100%
355
+ )
356
+ );
357
+ }
358
+
359
+ .scroller.vertical .gradient {
360
+ left: 0;
361
+ right: 0;
362
+ height: var(--scroller-gradient-size, 80px);
363
+ }
364
+
365
+ .scroller.vertical .gradient-start {
366
+ top: var(--scroller-arrow-size, 32px);
367
+ background: var(
368
+ --scroller-gradient-start,
369
+ linear-gradient(
370
+ to bottom,
371
+ rgba(255, 255, 255, 1) 0%,
372
+ rgba(255, 255, 255, 0.5) 40%,
373
+ rgba(255, 255, 255, 0) 100%
374
+ )
375
+ );
376
+ }
377
+
378
+ .scroller.vertical .gradient-end {
379
+ bottom: var(--scroller-arrow-size, 32px);
380
+ background: var(
381
+ --scroller-gradient-end,
382
+ linear-gradient(
383
+ to top,
384
+ rgba(255, 255, 255, 1) 0%,
385
+ rgba(255, 255, 255, 0.5) 40%,
386
+ rgba(255, 255, 255, 0) 100%
387
+ )
388
+ );
389
+ }
390
+ </style>
@@ -0,0 +1,4 @@
1
+ import type { ScrollerProperties } from './properties';
2
+ declare const Scroller: import("svelte").Component<ScrollerProperties, {}, "">;
3
+ type Scroller = ReturnType<typeof Scroller>;
4
+ export default Scroller;
@@ -0,0 +1,30 @@
1
+ import type { Snippet } from 'svelte';
2
+ export type ScrollDirection = 'horizontal' | 'vertical';
3
+ export type ScrollPosition = {
4
+ scrollOffset: number;
5
+ scrollSize: number;
6
+ clientSize: number;
7
+ progress: number;
8
+ };
9
+ export type ScrollerProperties = OptionalScrollerProperties & ScrollerEventProperties & MandatoryScrollerProperties;
10
+ export type MandatoryScrollerProperties = {
11
+ children: Snippet;
12
+ };
13
+ export type OptionalScrollerProperties = {
14
+ direction?: ScrollDirection;
15
+ scrollAmount?: number;
16
+ showArrows?: boolean;
17
+ showGradient?: boolean;
18
+ dragToScroll?: boolean;
19
+ snapToItem?: boolean;
20
+ hideScrollbar?: boolean;
21
+ hideArrowsOnTouch?: boolean;
22
+ smoothScroll?: boolean;
23
+ testId?: string;
24
+ arrowPrevious?: Snippet;
25
+ arrowNext?: Snippet;
26
+ classes?: string;
27
+ };
28
+ export type ScrollerEventProperties = {
29
+ onscrollposition?: (position: ScrollPosition) => void;
30
+ };
@@ -0,0 +1 @@
1
+ export {};