@marianmeres/stuic 3.37.0 → 3.38.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.
@@ -0,0 +1,98 @@
1
+ <script lang="ts" module>
2
+ import type { Snippet } from "svelte";
3
+
4
+ export interface ImageCyclerImage {
5
+ src: string;
6
+ alt?: string;
7
+ title?: string;
8
+ description?: string;
9
+ [key: string]: unknown;
10
+ }
11
+
12
+ export type ImageCyclerFit = "cover" | "contain" | "fill";
13
+
14
+ export interface Props {
15
+ images: ImageCyclerImage[];
16
+ fit?: ImageCyclerFit;
17
+ minWait?: number;
18
+ transitionDuration?: number;
19
+ onclick?: (image: ImageCyclerImage, index: number) => void;
20
+ title?: Snippet<[{ image: ImageCyclerImage; index: number; onclick: (() => void) | undefined }]>;
21
+ description?: Snippet<[{ image: ImageCyclerImage; index: number; onclick: (() => void) | undefined }]>;
22
+ unstyled?: boolean;
23
+ class?: string;
24
+ el?: HTMLElement;
25
+ }
26
+ </script>
27
+
28
+ <script lang="ts">
29
+ import { fade } from "svelte/transition";
30
+ import { preloadImg } from "../../utils/preload-img.js";
31
+ import { twMerge } from "../../utils/tw-merge.js";
32
+
33
+ let {
34
+ images,
35
+ fit = "cover",
36
+ minWait = 3000,
37
+ transitionDuration = 500,
38
+ onclick,
39
+ title,
40
+ description,
41
+ unstyled = false,
42
+ class: classProp,
43
+ el = $bindable(),
44
+ }: Props = $props();
45
+
46
+ let currentIndex = $state(0);
47
+
48
+ let _class = $derived(unstyled ? classProp : twMerge("stuic-image-cycler", classProp));
49
+
50
+ let _onclick = $derived(onclick ? () => onclick(images[currentIndex], currentIndex) : undefined);
51
+
52
+ $effect(() => {
53
+ const idx = currentIndex;
54
+ if (images.length <= 1) return;
55
+ let cancelled = false;
56
+ const nextIndex = (idx + 1) % images.length;
57
+ Promise.all([
58
+ preloadImg({ src: images[nextIndex].src }),
59
+ new Promise<void>((resolve) => setTimeout(resolve, minWait)),
60
+ ]).then(() => {
61
+ if (!cancelled) currentIndex = nextIndex;
62
+ });
63
+ return () => {
64
+ cancelled = true;
65
+ };
66
+ });
67
+ </script>
68
+
69
+ <div bind:this={el} class={_class}>
70
+ {#key currentIndex}
71
+ <div
72
+ class="stuic-image-cycler-bg"
73
+ data-fit={!unstyled ? fit : undefined}
74
+ style:background-image="url({images[currentIndex].src})"
75
+ role="img"
76
+ aria-label={images[currentIndex].alt ?? images[currentIndex].title ?? ""}
77
+ in:fade={{ duration: transitionDuration }}
78
+ out:fade={{ duration: transitionDuration }}
79
+ ></div>
80
+ {/key}
81
+
82
+ {#if title || description}
83
+ {#key currentIndex}
84
+ <div
85
+ class="stuic-image-cycler-meta"
86
+ in:fade={{ duration: transitionDuration }}
87
+ out:fade={{ duration: transitionDuration }}
88
+ >
89
+ {#if title}
90
+ {@render title({ image: images[currentIndex], index: currentIndex, onclick: _onclick })}
91
+ {/if}
92
+ {#if description}
93
+ {@render description({ image: images[currentIndex], index: currentIndex, onclick: _onclick })}
94
+ {/if}
95
+ </div>
96
+ {/key}
97
+ {/if}
98
+ </div>
@@ -0,0 +1,32 @@
1
+ import type { Snippet } from "svelte";
2
+ export interface ImageCyclerImage {
3
+ src: string;
4
+ alt?: string;
5
+ title?: string;
6
+ description?: string;
7
+ [key: string]: unknown;
8
+ }
9
+ export type ImageCyclerFit = "cover" | "contain" | "fill";
10
+ export interface Props {
11
+ images: ImageCyclerImage[];
12
+ fit?: ImageCyclerFit;
13
+ minWait?: number;
14
+ transitionDuration?: number;
15
+ onclick?: (image: ImageCyclerImage, index: number) => void;
16
+ title?: Snippet<[{
17
+ image: ImageCyclerImage;
18
+ index: number;
19
+ onclick: (() => void) | undefined;
20
+ }]>;
21
+ description?: Snippet<[{
22
+ image: ImageCyclerImage;
23
+ index: number;
24
+ onclick: (() => void) | undefined;
25
+ }]>;
26
+ unstyled?: boolean;
27
+ class?: string;
28
+ el?: HTMLElement;
29
+ }
30
+ declare const ImageCycler: import("svelte").Component<Props, {}, "el">;
31
+ type ImageCycler = ReturnType<typeof ImageCycler>;
32
+ export default ImageCycler;
@@ -0,0 +1,28 @@
1
+ :root {
2
+ --stuic-image-cycler-transition-duration: 500ms;
3
+ }
4
+
5
+ @layer components {
6
+ .stuic-image-cycler {
7
+ position: relative;
8
+ width: 100%;
9
+ height: 100%;
10
+ overflow: hidden;
11
+ }
12
+
13
+ .stuic-image-cycler-bg {
14
+ position: absolute;
15
+ inset: 0;
16
+ background-position: center;
17
+ background-repeat: no-repeat;
18
+ }
19
+
20
+ .stuic-image-cycler-bg[data-fit="cover"] { background-size: cover; }
21
+ .stuic-image-cycler-bg[data-fit="contain"] { background-size: contain; }
22
+ .stuic-image-cycler-bg[data-fit="fill"] { background-size: 100% 100%; }
23
+
24
+ .stuic-image-cycler-meta {
25
+ position: absolute;
26
+ inset: 0;
27
+ }
28
+ }
@@ -0,0 +1 @@
1
+ export { default as ImageCycler, type Props as ImageCyclerProps, type ImageCyclerImage, type ImageCyclerFit, } from "./ImageCycler.svelte";
@@ -0,0 +1 @@
1
+ export { default as ImageCycler, } from "./ImageCycler.svelte";
package/dist/index.css CHANGED
@@ -41,6 +41,7 @@ In practice:
41
41
  @import "./components/DismissibleMessage/index.css";
42
42
  @import "./components/DropdownMenu/index.css";
43
43
  @import "./components/H/index.css";
44
+ @import "./components/ImageCycler/index.css";
44
45
  @import "./components/IconSwap/index.css";
45
46
  @import "./components/Input/index.css";
46
47
  @import "./components/KbdShortcut/index.css";
package/dist/index.d.ts CHANGED
@@ -42,6 +42,7 @@ export * from "./components/DismissibleMessage/index.js";
42
42
  export * from "./components/Drawer/index.js";
43
43
  export * from "./components/DropdownMenu/index.js";
44
44
  export * from "./components/H/index.js";
45
+ export * from "./components/ImageCycler/index.js";
45
46
  export * from "./components/HoverExpandableWidth/index.js";
46
47
  export * from "./components/IconSwap/index.js";
47
48
  export * from "./components/Input/index.js";
package/dist/index.js CHANGED
@@ -43,6 +43,7 @@ export * from "./components/DismissibleMessage/index.js";
43
43
  export * from "./components/Drawer/index.js";
44
44
  export * from "./components/DropdownMenu/index.js";
45
45
  export * from "./components/H/index.js";
46
+ export * from "./components/ImageCycler/index.js";
46
47
  export * from "./components/HoverExpandableWidth/index.js";
47
48
  export * from "./components/IconSwap/index.js";
48
49
  export * from "./components/Input/index.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@marianmeres/stuic",
3
- "version": "3.37.0",
3
+ "version": "3.38.0",
4
4
  "files": [
5
5
  "dist",
6
6
  "!dist/**/*.test.*",