@streamscloud/kit 0.0.1-1770839905472 → 0.0.1-1770848433096

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.
@@ -0,0 +1,5 @@
1
+ import type { Action } from 'svelte/action';
2
+ export declare const horizontalWheelScroll: Action<HTMLElement, {
3
+ isolateScroll: boolean;
4
+ speed?: number;
5
+ } | undefined>;
@@ -0,0 +1,20 @@
1
+ export const horizontalWheelScroll = (node, param = { isolateScroll: true, speed: 1 }) => {
2
+ const onWheel = (event) => {
3
+ const canScrollX = node.scrollWidth > node.clientWidth;
4
+ if (!canScrollX) {
5
+ return;
6
+ }
7
+ const delta = Math.abs(event.deltaX) > Math.abs(event.deltaY) ? event.deltaX : event.deltaY;
8
+ node.scrollBy({ left: delta * (param.speed ?? 1), behavior: 'smooth' });
9
+ if (param.isolateScroll) {
10
+ event.preventDefault();
11
+ event.stopPropagation();
12
+ }
13
+ };
14
+ node.addEventListener('wheel', onWheel, { passive: false });
15
+ return {
16
+ destroy() {
17
+ node.removeEventListener('wheel', onWheel);
18
+ }
19
+ };
20
+ };
@@ -0,0 +1,2 @@
1
+ export { horizontalWheelScroll } from './horizontal-wheel-scroll';
2
+ export { swallowTouch } from './swallow-touch';
@@ -0,0 +1,2 @@
1
+ export { horizontalWheelScroll } from './horizontal-wheel-scroll';
2
+ export { swallowTouch } from './swallow-touch';
@@ -0,0 +1,2 @@
1
+ import type { Action } from 'svelte/action';
2
+ export declare const swallowTouch: Action;
@@ -0,0 +1,17 @@
1
+ export const swallowTouch = (node) => {
2
+ const stopAll = (e) => {
3
+ e.stopPropagation();
4
+ };
5
+ node.addEventListener('touchstart', stopAll, { passive: false });
6
+ node.addEventListener('touchmove', stopAll, { passive: false });
7
+ node.addEventListener('touchend', stopAll, { passive: false });
8
+ node.addEventListener('touchcancel', stopAll, { passive: false });
9
+ return {
10
+ destroy() {
11
+ node.removeEventListener('touchstart', stopAll);
12
+ node.removeEventListener('touchmove', stopAll);
13
+ node.removeEventListener('touchend', stopAll);
14
+ node.removeEventListener('touchcancel', stopAll);
15
+ }
16
+ };
17
+ };
@@ -0,0 +1,79 @@
1
+ <script lang="ts">import { Loading } from '../loading';
2
+ let { loadMore, container = null, actuationOffset = '', children, loading } = $props();
3
+ let isLoading = $state(false);
4
+ let paginationTrigger = $state(null);
5
+ let itemsContainer = $state(null);
6
+ $effect(() => {
7
+ if (!paginationTrigger || !itemsContainer) {
8
+ return;
9
+ }
10
+ const trigger = paginationTrigger;
11
+ const items = itemsContainer;
12
+ const intersectionObserver = new IntersectionObserver((e) => {
13
+ const [entries] = e;
14
+ if (entries.isIntersecting) {
15
+ void onLoadMore();
16
+ }
17
+ }, {
18
+ root: container,
19
+ rootMargin: actuationOffset
20
+ });
21
+ // Re-observe trigger on container resize to force IntersectionObserver
22
+ // to re-evaluate visibility — it won't fire on its own when siblings resize
23
+ const resizeObserver = new ResizeObserver(() => {
24
+ intersectionObserver.unobserve(trigger);
25
+ intersectionObserver.observe(trigger);
26
+ });
27
+ resizeObserver.observe(items);
28
+ return () => {
29
+ resizeObserver.disconnect();
30
+ intersectionObserver.disconnect();
31
+ };
32
+ });
33
+ const onLoadMore = async () => {
34
+ if (isLoading) {
35
+ return;
36
+ }
37
+ isLoading = true;
38
+ try {
39
+ await loadMore();
40
+ }
41
+ finally {
42
+ isLoading = false;
43
+ }
44
+ };
45
+ </script>
46
+
47
+ <div class="infinite-scrolling">
48
+ <div bind:this={itemsContainer}>
49
+ {@render children()}
50
+ </div>
51
+
52
+ <div class="infinite-scrolling__pagination-trigger" bind:this={paginationTrigger}></div>
53
+ {#if isLoading}
54
+ {#if loading}
55
+ {@render loading()}
56
+ {:else}
57
+ <div class="infinite-scrolling__loading-container">
58
+ <Loading timeout={500} />
59
+ </div>
60
+ {/if}
61
+ {/if}
62
+ </div>
63
+
64
+ <style>.infinite-scrolling {
65
+ --_infinite-scrolling--overflow-y: var(--infinite-scrolling--overflow-y, initial);
66
+ overflow-y: var(--_infinite-scrolling--overflow-y);
67
+ min-height: 2.625em;
68
+ position: relative;
69
+ width: 100%;
70
+ }
71
+ .infinite-scrolling__pagination-trigger {
72
+ border: 1px solid transparent;
73
+ }
74
+ .infinite-scrolling__loading-container {
75
+ position: absolute;
76
+ bottom: 0.3125em;
77
+ left: 50%;
78
+ transform: translateX(-50%);
79
+ }</style>
@@ -0,0 +1,14 @@
1
+ import type { Snippet } from 'svelte';
2
+ type Props = {
3
+ loadMore: () => Promise<unknown>;
4
+ /**
5
+ * Must be passed only if viewport is less than scrolling container
6
+ */
7
+ container?: HTMLElement | null;
8
+ actuationOffset?: string;
9
+ children: Snippet;
10
+ loading?: Snippet;
11
+ };
12
+ declare const Cmp: import("svelte").Component<Props, {}, "">;
13
+ type Cmp = ReturnType<typeof Cmp>;
14
+ export default Cmp;
@@ -0,0 +1 @@
1
+ export { default as InfiniteScrolling } from './cmp.infinite-scrolling.svelte';
@@ -0,0 +1 @@
1
+ export { default as InfiniteScrolling } from './cmp.infinite-scrolling.svelte';
@@ -1,8 +1,8 @@
1
- <script lang="ts">import { onMount } from 'svelte';
2
- let { positionFixedCenter = false, positionAbsoluteCenter = false, blocking = false, timeout = 0 } = $props();
1
+ <script lang="ts">let { positionFixedCenter = false, positionAbsoluteCenter = false, blocking = false, timeout = 0 } = $props();
3
2
  let visible = $state(false);
4
- onMount(() => {
5
- setTimeout(() => (visible = true), timeout);
3
+ $effect(() => {
4
+ const timer = setTimeout(() => (visible = true), timeout);
5
+ return () => clearTimeout(timer);
6
6
  });
7
7
  </script>
8
8
 
@@ -0,0 +1,28 @@
1
+ <script lang="ts">let { value } = $props();
2
+ const cssWidth = $derived(`${100 * (value <= 1 ? value : 1)}%`);
3
+ </script>
4
+
5
+ <div class="progress">
6
+ <span class="progress__value" class:progress__value--animated={value > 0.01 && value < 0.96} style:width={cssWidth}> &nbsp; </span>
7
+ </div>
8
+
9
+ <style>.progress {
10
+ --_progress--height: var(--progress--height, 0.25em);
11
+ --_progress--back-color: var(--progress--back-color, #9ca3af);
12
+ --_progress--front-color: var(--progress--front-color, #ffffff);
13
+ --_progress--box-shadow: var(--progress--box-shadow, 0 2px 3px rgba(0, 0, 0, 0.25) inset);
14
+ --_progress--border-radius: var(--progress--border-radius, 0);
15
+ width: 100%;
16
+ background: var(--_progress--back-color);
17
+ height: var(--_progress--height);
18
+ box-shadow: var(--_progress--box-shadow);
19
+ border-radius: var(--_progress--border-radius);
20
+ }
21
+ .progress__value {
22
+ background: var(--_progress--front-color);
23
+ display: inline-block;
24
+ height: 100%;
25
+ }
26
+ .progress__value--animated {
27
+ transition: width 600ms;
28
+ }</style>
@@ -0,0 +1,7 @@
1
+ type Props = {
2
+ /** 0-1 */
3
+ value: number;
4
+ };
5
+ declare const Cmp: import("svelte").Component<Props, {}, "">;
6
+ type Cmp = ReturnType<typeof Cmp>;
7
+ export default Cmp;
@@ -0,0 +1 @@
1
+ export { default as Progress } from './cmp.progress.svelte';
@@ -0,0 +1 @@
1
+ export { default as Progress } from './cmp.progress.svelte';
@@ -0,0 +1,155 @@
1
+ <script lang="ts">let { value, listenParentClicks = false, on } = $props();
2
+ let seekBarRef = $state(null);
3
+ let scrubberRef = $state(null);
4
+ let progressRef = $state(null);
5
+ let isDragging = $state(false);
6
+ const cssValue = $derived(`${100 * (value <= 1 ? value : 1)}%`);
7
+ const handleSeek = (e) => {
8
+ if (!progressRef) {
9
+ return;
10
+ }
11
+ e.stopPropagation();
12
+ const { left, width } = progressRef.getBoundingClientRect();
13
+ const x = e.clientX - left;
14
+ const percent = Math.max(0, Math.min(1, x / width));
15
+ on?.seek(percent);
16
+ };
17
+ const handleParentClick = (e) => {
18
+ e.preventDefault();
19
+ e.stopPropagation();
20
+ if (!progressRef || !seekBarRef || isDragging) {
21
+ return;
22
+ }
23
+ const seekBarRect = progressRef.getBoundingClientRect();
24
+ if (e.clientX >= seekBarRect.left && e.clientX <= seekBarRect.right) {
25
+ const x = e.clientX - seekBarRect.left;
26
+ const percent = Math.max(0, Math.min(1, x / seekBarRect.width));
27
+ on?.seek(percent);
28
+ }
29
+ };
30
+ const onMouseMove = (e) => {
31
+ if (isDragging) {
32
+ handleSeek(e);
33
+ }
34
+ };
35
+ const onMouseUp = () => {
36
+ isDragging = false;
37
+ window.removeEventListener('mousemove', onMouseMove);
38
+ window.removeEventListener('mouseup', onMouseUp);
39
+ scrubberRef?.blur();
40
+ on?.dragEnd?.();
41
+ };
42
+ const onMouseDown = (e) => {
43
+ isDragging = true;
44
+ on?.dragStart?.();
45
+ handleSeek(e);
46
+ window.addEventListener('mousemove', onMouseMove);
47
+ window.addEventListener('mouseup', onMouseUp);
48
+ scrubberRef?.blur();
49
+ };
50
+ const handleScrubberKeyDown = (event) => {
51
+ const step = 0.05;
52
+ let newValue;
53
+ if (event.key === /*@wc-ignore*/ 'ArrowLeft') {
54
+ newValue = Math.max(0, value - step);
55
+ }
56
+ else if (event.key === /*@wc-ignore*/ 'ArrowRight') {
57
+ newValue = Math.min(1, value + step);
58
+ }
59
+ else if (event.key === /*@wc-ignore*/ 'Home') {
60
+ newValue = 0;
61
+ }
62
+ else if (event.key === /*@wc-ignore*/ 'End') {
63
+ newValue = 1;
64
+ }
65
+ if (newValue !== undefined) {
66
+ event.preventDefault();
67
+ on?.seek(newValue);
68
+ }
69
+ };
70
+ $effect(() => {
71
+ if (!listenParentClicks || !seekBarRef) {
72
+ return;
73
+ }
74
+ const parent = seekBarRef.parentElement;
75
+ if (!parent) {
76
+ return;
77
+ }
78
+ parent.addEventListener('click', handleParentClick);
79
+ return () => {
80
+ parent.removeEventListener('click', handleParentClick);
81
+ };
82
+ });
83
+ $effect(() => {
84
+ return () => {
85
+ window.removeEventListener('mousemove', onMouseMove);
86
+ window.removeEventListener('mouseup', onMouseUp);
87
+ };
88
+ });
89
+ </script>
90
+
91
+ <div class="seek-bar" onmousedown={onMouseDown} onkeydown={() => ({})} role="none" bind:this={seekBarRef}>
92
+ <div class="seek-bar__container" bind:this={progressRef}>
93
+ <span class="seek-bar__value" style:width={cssValue}> &nbsp; </span>
94
+ <div
95
+ class="seek-bar__scrubber"
96
+ bind:this={scrubberRef}
97
+ class:is-dragging={isDragging}
98
+ style:left={cssValue}
99
+ role="slider"
100
+ tabindex="0"
101
+ aria-valuemin="0"
102
+ aria-valuemax="1"
103
+ aria-valuenow={value}
104
+ aria-label="Media position slider"
105
+ onkeydown={handleScrubberKeyDown}>
106
+ </div>
107
+ </div>
108
+ </div>
109
+
110
+ <style>.seek-bar {
111
+ cursor: pointer;
112
+ position: relative;
113
+ padding: 0.3125rem 0;
114
+ --_seek-bar--container-color: var(--seek-bar--container-color, #9ca3af);
115
+ --_seek-bar--value-color: var(--seek-bar--value-color, #ffffff);
116
+ --_seek-bar--scrubber-color: var(--seek-bar--scrubber-color, #ffffff);
117
+ --_seek-bar--scrubber-border-color: var(--seek-bar--scrubber-border-color, #9ca3af);
118
+ --_seek-bar--scrubber-opacity: 0;
119
+ }
120
+ .seek-bar:hover {
121
+ --_seek-bar--scrubber-opacity: 1;
122
+ }
123
+ .seek-bar__container {
124
+ width: 100%;
125
+ background: var(--_seek-bar--container-color);
126
+ height: 0.3125rem;
127
+ position: relative;
128
+ }
129
+ .seek-bar__value {
130
+ background: var(--_seek-bar--value-color);
131
+ border-color: var(--_seek-bar--container-color);
132
+ border-width: 0.0625rem;
133
+ display: inline-block;
134
+ height: 100%;
135
+ }
136
+ .seek-bar__scrubber {
137
+ position: absolute;
138
+ top: 50%;
139
+ width: 0.75rem;
140
+ height: 0.75rem;
141
+ background: var(--_seek-bar--scrubber-color);
142
+ border-color: var(--_seek-bar--scrubber-border-color);
143
+ border-width: 0.0625rem;
144
+ border-radius: 50%;
145
+ transform: translate(-50%, -50%);
146
+ z-index: 1;
147
+ opacity: var(--_seek-bar--scrubber-opacity);
148
+ transition: opacity 0.2s ease-in-out;
149
+ }
150
+ .seek-bar__scrubber.is-dragging, .seek-bar__scrubber:focus {
151
+ --_seek-bar--scrubber-opacity: 1;
152
+ }
153
+ .seek-bar__scrubber:focus-visible {
154
+ outline: none;
155
+ }</style>
@@ -0,0 +1,13 @@
1
+ type Props = {
2
+ /** 0-1 */
3
+ value: number;
4
+ listenParentClicks?: boolean;
5
+ on: {
6
+ seek: (e: number) => void;
7
+ dragStart?: () => void;
8
+ dragEnd?: () => void;
9
+ };
10
+ };
11
+ declare const Cmp: import("svelte").Component<Props, {}, "">;
12
+ type Cmp = ReturnType<typeof Cmp>;
13
+ export default Cmp;
@@ -0,0 +1 @@
1
+ export { default as SeekBar } from './cmp.seek-bar.svelte';
@@ -0,0 +1 @@
1
+ export { default as SeekBar } from './cmp.seek-bar.svelte';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@streamscloud/kit",
3
- "version": "0.0.1-1770839905472",
3
+ "version": "0.0.1-1770848433096",
4
4
  "author": "StreamsCloud",
5
5
  "repository": {
6
6
  "type": "git",
@@ -28,42 +28,42 @@
28
28
  "**/*.css"
29
29
  ],
30
30
  "exports": {
31
+ "./button": {
32
+ "types": "./dist/ui/button/index.d.ts",
33
+ "svelte": "./dist/ui/button/index.js"
34
+ },
31
35
  "./core": {
32
36
  "types": "./dist/core/index.d.ts",
33
37
  "svelte": "./dist/core/index.js"
34
38
  },
39
+ "./core/actions": {
40
+ "types": "./dist/core/actions/index.d.ts",
41
+ "svelte": "./dist/core/actions/index.js"
42
+ },
35
43
  "./core/css": {
36
44
  "types": "./dist/core/css/index.d.ts",
37
45
  "svelte": "./dist/core/css/index.js"
38
46
  },
39
- "./core/i18n": {
40
- "types": "./dist/core/i18n/index.d.ts",
41
- "svelte": "./dist/core/i18n/index.js"
42
- },
43
- "./core/transitions": {
44
- "types": "./dist/core/transitions/index.d.ts",
45
- "svelte": "./dist/core/transitions/index.js"
46
- },
47
- "./core/utils": {
48
- "types": "./dist/core/utils/index.d.ts",
49
- "svelte": "./dist/core/utils/index.js"
47
+ "./core/data-loaders": {
48
+ "types": "./dist/core/data-loaders/index.d.ts",
49
+ "svelte": "./dist/core/data-loaders/index.js"
50
50
  },
51
51
  "./core/files": {
52
52
  "types": "./dist/core/files/index.d.ts",
53
53
  "svelte": "./dist/core/files/index.js"
54
54
  },
55
+ "./core/i18n": {
56
+ "types": "./dist/core/i18n/index.d.ts",
57
+ "svelte": "./dist/core/i18n/index.js"
58
+ },
59
+ "./core/media": {
60
+ "types": "./dist/core/media/index.d.ts",
61
+ "svelte": "./dist/core/media/index.js"
62
+ },
55
63
  "./core/repository": {
56
64
  "types": "./dist/core/repository/index.d.ts",
57
65
  "svelte": "./dist/core/repository/index.js"
58
66
  },
59
- "./core/data-loaders": {
60
- "types": "./dist/core/data-loaders/index.d.ts",
61
- "svelte": "./dist/core/data-loaders/index.js"
62
- },
63
- "./core/validation": {
64
- "types": "./dist/core/validation/index.d.ts",
65
- "svelte": "./dist/core/validation/index.js"
66
- },
67
67
  "./core/theme": {
68
68
  "types": "./dist/core/theme/index.d.ts",
69
69
  "svelte": "./dist/core/theme/index.js"
@@ -72,14 +72,22 @@
72
72
  "types": "./dist/core/toastr/index.d.ts",
73
73
  "svelte": "./dist/core/toastr/index.js"
74
74
  },
75
+ "./core/transitions": {
76
+ "types": "./dist/core/transitions/index.d.ts",
77
+ "svelte": "./dist/core/transitions/index.js"
78
+ },
79
+ "./core/utils": {
80
+ "types": "./dist/core/utils/index.d.ts",
81
+ "svelte": "./dist/core/utils/index.js"
82
+ },
83
+ "./core/validation": {
84
+ "types": "./dist/core/validation/index.d.ts",
85
+ "svelte": "./dist/core/validation/index.js"
86
+ },
75
87
  "./dialog": {
76
88
  "types": "./dist/ui/dialog/index.d.ts",
77
89
  "svelte": "./dist/ui/dialog/index.js"
78
90
  },
79
- "./button": {
80
- "types": "./dist/ui/button/index.d.ts",
81
- "svelte": "./dist/ui/button/index.js"
82
- },
83
91
  "./icon": {
84
92
  "types": "./dist/ui/icon/index.d.ts",
85
93
  "svelte": "./dist/ui/icon/index.js"
@@ -88,17 +96,31 @@
88
96
  "types": "./dist/ui/image/index.d.ts",
89
97
  "svelte": "./dist/ui/image/index.js"
90
98
  },
99
+ "./infinite-scrolling": {
100
+ "types": "./dist/ui/infinite-scrolling/index.d.ts",
101
+ "svelte": "./dist/ui/infinite-scrolling/index.js"
102
+ },
91
103
  "./loading": {
92
104
  "types": "./dist/ui/loading/index.d.ts",
93
105
  "svelte": "./dist/ui/loading/index.js"
94
106
  },
107
+ "./progress": {
108
+ "types": "./dist/ui/progress/index.d.ts",
109
+ "svelte": "./dist/ui/progress/index.js"
110
+ },
95
111
  "./proportional-container": {
96
112
  "types": "./dist/ui/proportional-container/index.d.ts",
97
113
  "svelte": "./dist/ui/proportional-container/index.js"
98
114
  },
99
- "./core/media": {
100
- "types": "./dist/core/media/index.d.ts",
101
- "svelte": "./dist/core/media/index.js"
115
+ "./seek-bar": {
116
+ "types": "./dist/ui/seek-bar/index.d.ts",
117
+ "svelte": "./dist/ui/seek-bar/index.js"
118
+ },
119
+ "./styles/base": {
120
+ "sass": "./dist/styles/_index.scss"
121
+ },
122
+ "./styles/colors": {
123
+ "sass": "./dist/styles/_colors.scss"
102
124
  },
103
125
  "./styles/functions": {
104
126
  "sass": "./dist/styles/_functions.scss"
@@ -106,17 +128,11 @@
106
128
  "./styles/mixins": {
107
129
  "sass": "./dist/styles/_mixins.scss"
108
130
  },
109
- "./styles/colors": {
110
- "sass": "./dist/styles/_colors.scss"
111
- },
131
+ "./styles/normalize.css": "./dist/styles/normalize.css",
132
+ "./styles/reset.css": "./dist/styles/reset.css",
112
133
  "./styles/responsive": {
113
134
  "sass": "./dist/styles/_responsive.scss"
114
135
  },
115
- "./styles/base": {
116
- "sass": "./dist/styles/_index.scss"
117
- },
118
- "./styles/normalize.css": "./dist/styles/normalize.css",
119
- "./styles/reset.css": "./dist/styles/reset.css",
120
136
  "./styles/theme": {
121
137
  "sass": "./dist/styles/_theme.scss"
122
138
  }