@streamscloud/kit 0.0.1-1770815159445 → 0.0.1-1770823200886

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,9 @@
1
+ export declare class ImageHelper {
2
+ static checkIsVertical: (url: string) => Promise<boolean>;
3
+ static computeRatio: (src: string) => Promise<ImageSize | null>;
4
+ static getRatio: (metadata: ImageSize) => number;
5
+ }
6
+ export type ImageSize = {
7
+ width: number;
8
+ height: number;
9
+ };
@@ -0,0 +1,30 @@
1
+ export class ImageHelper {
2
+ static checkIsVertical = async (url) => {
3
+ const ratio = await ImageHelper.computeRatio(url);
4
+ if (!ratio) {
5
+ return false;
6
+ }
7
+ return ratio.height >= ratio.width;
8
+ };
9
+ static computeRatio = async (src) => {
10
+ const setRatio = (imageElement, resolveFn) => {
11
+ if (!imageElement || !imageElement.width) {
12
+ resolveFn(null);
13
+ }
14
+ else {
15
+ resolveFn({ width: imageElement.width, height: imageElement.height });
16
+ }
17
+ };
18
+ return new Promise((resolve) => {
19
+ const imageElement = new Image();
20
+ imageElement.onload = () => {
21
+ setRatio(imageElement, resolve);
22
+ };
23
+ imageElement.onerror = () => {
24
+ setRatio(null, resolve);
25
+ };
26
+ imageElement.src = src;
27
+ });
28
+ };
29
+ static getRatio = (metadata) => metadata.width / metadata.height;
30
+ }
@@ -0,0 +1,2 @@
1
+ export { ImageHelper } from './image-helper';
2
+ export type { ImageSize } from './image-helper';
@@ -0,0 +1 @@
1
+ export { ImageHelper } from './image-helper';
@@ -1,5 +1,7 @@
1
+ type Toast = typeof import('svelte-sonner').toast;
1
2
  export declare class ToasterHost {
2
- private static _ready;
3
+ private static _toast;
3
4
  private static _mountPromise;
4
- static ensure(): Promise<void>;
5
+ static ensure(): Promise<Toast>;
5
6
  }
7
+ export {};
@@ -1,20 +1,20 @@
1
1
  import { AppTheme } from '../theme';
2
2
  import { mount, tick } from 'svelte';
3
- import { Toaster } from 'svelte-sonner';
4
3
  export class ToasterHost {
5
- static _ready = false;
4
+ static _toast = null;
6
5
  static _mountPromise = null;
7
6
  static async ensure() {
8
- if (this._ready) {
9
- return;
7
+ if (this._toast) {
8
+ return this._toast;
10
9
  }
11
10
  if (this._mountPromise) {
12
11
  return this._mountPromise;
13
12
  }
14
13
  if (typeof document === 'undefined') {
15
- return;
14
+ throw new Error('ToasterHost requires a browser environment');
16
15
  }
17
16
  this._mountPromise = (async () => {
17
+ const { Toaster, toast } = await import('svelte-sonner');
18
18
  const container = document.createElement('div');
19
19
  container.id = 'toastr-container';
20
20
  document.body.appendChild(container);
@@ -33,7 +33,8 @@ export class ToasterHost {
33
33
  }
34
34
  });
35
35
  await tick();
36
- this._ready = true;
36
+ this._toast = toast;
37
+ return toast;
37
38
  })();
38
39
  return this._mountPromise;
39
40
  }
@@ -1,24 +1,23 @@
1
1
  import { ToasterHost } from './toaster-host.svelte';
2
- import { toast } from 'svelte-sonner';
3
2
  export class Toastr {
4
3
  static async error(message, options) {
5
- await ToasterHost.ensure();
4
+ const toast = await ToasterHost.ensure();
6
5
  toast.error(message, patchOptions(options));
7
6
  }
8
7
  static async success(message, options) {
9
- await ToasterHost.ensure();
8
+ const toast = await ToasterHost.ensure();
10
9
  toast.success(message, patchOptions(options));
11
10
  }
12
11
  static async warning(message, options) {
13
- await ToasterHost.ensure();
12
+ const toast = await ToasterHost.ensure();
14
13
  toast.warning(message, patchOptions(options));
15
14
  }
16
15
  static async info(message, options) {
17
- await ToasterHost.ensure();
16
+ const toast = await ToasterHost.ensure();
18
17
  toast.info(message, patchOptions(options));
19
18
  }
20
19
  static async promise(promise, messages) {
21
- await ToasterHost.ensure();
20
+ const toast = await ToasterHost.ensure();
22
21
  toast.promise(promise, messages);
23
22
  }
24
23
  }
@@ -0,0 +1,26 @@
1
+ <script lang="ts">import RoundedImg from './cmp.image-rounded.svelte';
2
+ let { src, alt = '', ring = false, on } = $props();
3
+ </script>
4
+
5
+ <div class="round-img">
6
+ <div class="round-img__placer">
7
+ <RoundedImg src={src} alt={alt} ring={ring} on={on} />
8
+ </div>
9
+ </div>
10
+
11
+ <style>.round-img {
12
+ --_image--round--size: var(--image--round--size, 100%);
13
+ --image--rounded--inner--border-radius: 50%;
14
+ --image--rounded--outer--border-radius: 50%;
15
+ --image--rounded--image--border-radius: 50%;
16
+ --image--rounded--width: 100%;
17
+ --image--rounded--height: 100%;
18
+ display: inline-block;
19
+ width: var(--_image--round--size);
20
+ position: relative;
21
+ padding-bottom: var(--_image--round--size);
22
+ }
23
+ .round-img__placer {
24
+ position: absolute;
25
+ inset: 0;
26
+ }</style>
@@ -0,0 +1,11 @@
1
+ type Props = {
2
+ src: string | null | undefined;
3
+ alt?: string;
4
+ ring?: boolean;
5
+ on?: {
6
+ click: () => void;
7
+ };
8
+ };
9
+ declare const Cmp: import("svelte").Component<Props, {}, "">;
10
+ type Cmp = ReturnType<typeof Cmp>;
11
+ export default Cmp;
@@ -0,0 +1,62 @@
1
+ <script lang="ts">import Image from './cmp.image.svelte';
2
+ let { src, alt = '', ring = false, on } = $props();
3
+ </script>
4
+
5
+ <div class="rounded-img" class:rounded-img--stub={!src} class:rounded-img--no-ring={!ring}>
6
+ <div class="rounded-img__placer" onclick={() => on?.click()} onkeydown={() => ({})} role="none">
7
+ <Image src={src} alt={alt} showStubOnError={true} />
8
+ </div>
9
+ </div>
10
+
11
+ <style>.rounded-img {
12
+ --_image--rounded--size: var(--image--rounded--size, 100%);
13
+ --_image--rounded--width: var(--image--rounded--width, var(--_image--rounded--size));
14
+ --_image--rounded--height: var(--image--rounded--height, var(--_image--rounded--size));
15
+ --_image--rounded--image--border-radius: var(
16
+ --image--rounded--image--border-radius,
17
+ calc(var(--_image--rounded--inner--border-radius) - var(--_image--rounded--inner--border-width))
18
+ );
19
+ --_image--rounded--inner--border-color: var(--image--rounded--inner--border-color, light-dark(#ffffff, #121212));
20
+ --_image--rounded--inner--border-radius: var(
21
+ --image--rounded--inner--border-radius,
22
+ calc(var(--_image--rounded--outer--border-radius) - var(--_image--rounded--outer--border-width))
23
+ );
24
+ --_image--rounded--inner--border-width: var(--image--rounded--inner--border-width, 4px);
25
+ --_image--rounded--outer--border-color: var(
26
+ --image--rounded--outer--border-color,
27
+ linear-gradient(
28
+ light-dark(#144ab0, #5a8dec),
29
+ light-dark(#dfe9fb, #0c2d69)
30
+ )
31
+ );
32
+ --_image--rounded--outer--border-radius: var(--image--rounded--outer--border-radius, 2px);
33
+ --_image--rounded--outer--border-width: var(--image--rounded--outer--border-width, 2px);
34
+ --_image--rounded--stub--background: var(
35
+ --image--rounded--stub--background,
36
+ var(--sc-color--bg-images, light-dark(#d1d5db, #374151))
37
+ );
38
+ width: var(--_image--rounded--width);
39
+ height: var(--_image--rounded--height);
40
+ border-radius: var(--_image--rounded--outer--border-radius);
41
+ padding: var(--_image--rounded--outer--border-width);
42
+ background: var(--_image--rounded--outer--border-color);
43
+ overflow: hidden;
44
+ }
45
+ .rounded-img--stub {
46
+ background: var(--_image--rounded--stub--background);
47
+ }
48
+ .rounded-img--no-ring {
49
+ --_image--rounded--outer--border-width: 0;
50
+ --_image--rounded--inner--border-width: 0;
51
+ --_image--rounded--outer--border-color: transparent;
52
+ --_image--rounded--inner--border-color: transparent;
53
+ }
54
+ .rounded-img__placer {
55
+ width: 100%;
56
+ height: 100%;
57
+ border-radius: var(--_image--rounded--inner--border-radius);
58
+ padding: var(--_image--rounded--inner--border-width);
59
+ background: var(--_image--rounded--inner--border-color);
60
+ overflow: hidden;
61
+ --image--border-radius: var(--_image--rounded--image--border-radius);
62
+ }</style>
@@ -0,0 +1,11 @@
1
+ type Props = {
2
+ src: string | null | undefined;
3
+ alt?: string;
4
+ ring?: boolean;
5
+ on?: {
6
+ click: () => void;
7
+ };
8
+ };
9
+ declare const Cmp: import("svelte").Component<Props, {}, "">;
10
+ type Cmp = ReturnType<typeof Cmp>;
11
+ export default Cmp;
@@ -0,0 +1,20 @@
1
+ <script lang="ts">import { Icon } from '../icon';
2
+ import IconImage from '@fluentui/svg-icons/icons/image_20_regular.svg?raw';
3
+ </script>
4
+
5
+ <div class="image-stub">
6
+ <Icon src={IconImage} />
7
+ </div>
8
+
9
+ <style>.image-stub {
10
+ --_image-stub--color: var(--image-stub--color, var(--sc-color--bg-images, light-dark(#d1d5db, #374151)));
11
+ width: 100%;
12
+ height: 100%;
13
+ z-index: 2;
14
+ display: flex;
15
+ justify-content: center;
16
+ align-items: center;
17
+ color: var(--_image-stub--color);
18
+ border: 1px solid var(--_image-stub--color);
19
+ border-radius: 0.25rem;
20
+ }</style>
@@ -0,0 +1,18 @@
1
+ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
2
+ new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
3
+ $$bindings?: Bindings;
4
+ } & Exports;
5
+ (internal: unknown, props: {
6
+ $$events?: Events;
7
+ $$slots?: Slots;
8
+ }): Exports & {
9
+ $set?: any;
10
+ $on?: any;
11
+ };
12
+ z_$$bindings?: Bindings;
13
+ }
14
+ declare const Cmp: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
15
+ [evt: string]: CustomEvent<any>;
16
+ }, {}, {}, string>;
17
+ type Cmp = InstanceType<typeof Cmp>;
18
+ export default Cmp;
@@ -0,0 +1,71 @@
1
+ <script lang="ts">import { Icon } from '../icon';
2
+ import { calculateImageState, ImageState } from './image-state';
3
+ import IconImageOff from '@fluentui/svg-icons/icons/image_off_20_regular.svg?raw';
4
+ let { src, alt = '', showStubOnError = false, on, stub } = $props();
5
+ let hasError = $state(false);
6
+ const imageState = $derived(calculateImageState(src, hasError, showStubOnError));
7
+ const onLoad = () => {
8
+ hasError = false;
9
+ on?.load?.(true);
10
+ };
11
+ const onLoadError = () => {
12
+ hasError = true;
13
+ on?.load?.(false);
14
+ };
15
+ </script>
16
+
17
+ <div class="image">
18
+ {#if !!src}
19
+ <img class="image__img" class:image__img--hidden={imageState !== ImageState.showImage} src={src} alt={alt || ''} onload={onLoad} onerror={onLoadError} />
20
+ {/if}
21
+
22
+ {#if imageState === ImageState.showError}
23
+ <div class="image__load-error">
24
+ <Icon src={IconImageOff} />
25
+ </div>
26
+ {/if}
27
+
28
+ {#if imageState === ImageState.showStub}
29
+ {#if stub}
30
+ {@render stub()}
31
+ {:else}
32
+ <div class="image__img image__img--stub"></div>
33
+ {/if}
34
+ {/if}
35
+ </div>
36
+
37
+ <style>.image {
38
+ --_image--background: var(--image--background, transparent);
39
+ --_image--border-radius: var(--image--border-radius, 0);
40
+ --_image--object-fit: var(--image--object-fit, cover);
41
+ --_image--stub--background: var(
42
+ --image--stub--background,
43
+ var(--sc-color--bg-images, light-dark(#d1d5db, #374151))
44
+ );
45
+ position: relative;
46
+ width: 100%;
47
+ height: 100%;
48
+ overflow: hidden;
49
+ border-radius: var(--_image--border-radius);
50
+ background: var(--_image--background);
51
+ }
52
+ .image__img {
53
+ width: 100%;
54
+ height: 100%;
55
+ z-index: 2;
56
+ object-fit: var(--_image--object-fit);
57
+ }
58
+ .image__img--hidden {
59
+ display: none;
60
+ }
61
+ .image__img--stub {
62
+ background: var(--_image--stub--background);
63
+ }
64
+ .image__load-error {
65
+ position: absolute;
66
+ top: 50%;
67
+ left: 50%;
68
+ transform: translate(-50%, -50%);
69
+ font-size: 1.2em;
70
+ text-align: center;
71
+ }</style>
@@ -0,0 +1,13 @@
1
+ import type { Snippet } from 'svelte';
2
+ type Props = {
3
+ src: string | null | undefined;
4
+ alt?: string;
5
+ showStubOnError?: boolean;
6
+ on?: {
7
+ load?: (loadedSuccessfully: boolean) => void;
8
+ };
9
+ stub?: Snippet;
10
+ };
11
+ declare const Cmp: import("svelte").Component<Props, {}, "">;
12
+ type Cmp = ReturnType<typeof Cmp>;
13
+ export default Cmp;
@@ -0,0 +1,6 @@
1
+ export declare enum ImageState {
2
+ showImage = 0,
3
+ showError = 1,
4
+ showStub = 2
5
+ }
6
+ export declare const calculateImageState: (src: string | null | undefined, isError: boolean, showStubOnError: boolean) => ImageState;
@@ -0,0 +1,17 @@
1
+ export var ImageState;
2
+ (function (ImageState) {
3
+ ImageState[ImageState["showImage"] = 0] = "showImage";
4
+ ImageState[ImageState["showError"] = 1] = "showError";
5
+ ImageState[ImageState["showStub"] = 2] = "showStub";
6
+ })(ImageState || (ImageState = {}));
7
+ export const calculateImageState = (src, isError, showStubOnError) => {
8
+ if (isError && !showStubOnError) {
9
+ return ImageState.showError;
10
+ }
11
+ else if (!src || (isError && showStubOnError)) {
12
+ return ImageState.showStub;
13
+ }
14
+ else {
15
+ return ImageState.showImage;
16
+ }
17
+ };
@@ -0,0 +1,5 @@
1
+ export { default as Image } from './cmp.image.svelte';
2
+ export { default as ImageRound } from './cmp.image-round.svelte';
3
+ export { default as ImageRounded } from './cmp.image-rounded.svelte';
4
+ export { default as ImageStub } from './cmp.image-stub.svelte';
5
+ export { ImageState, calculateImageState } from './image-state';
@@ -0,0 +1,5 @@
1
+ export { default as Image } from './cmp.image.svelte';
2
+ export { default as ImageRound } from './cmp.image-round.svelte';
3
+ export { default as ImageRounded } from './cmp.image-rounded.svelte';
4
+ export { default as ImageStub } from './cmp.image-stub.svelte';
5
+ export { ImageState, calculateImageState } from './image-state';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@streamscloud/kit",
3
- "version": "0.0.1-1770815159445",
3
+ "version": "0.0.1-1770823200886",
4
4
  "author": "StreamsCloud",
5
5
  "repository": {
6
6
  "type": "git",
@@ -12,7 +12,7 @@
12
12
  "build": "svelte-package --tsconfig ./tsconfig.app.json && npm run build:css && prettier --write --plugin prettier-plugin-svelte . && eslint --fix .",
13
13
  "build:css": "sass dist/styles/_normalize.scss dist/styles/normalize.css --no-source-map && sass dist/styles/_reset.scss dist/styles/reset.css --no-source-map",
14
14
  "publish:prod": "npm run build && npm publish --access public --tag latest",
15
- "version:dev": "node -e \"const fs=require('fs');const pkg=require('./package.json');const base=(pkg.version.includes('-')?pkg.version.split('-')[0]:pkg.version);pkg.version=base+'-'+Date.now();fs.writeFileSync('package.json',JSON.stringify(pkg,null,2)+'\\n');\"",
15
+ "version:dev": "node -e \"const p=require('./package.json');p.version=p.version.split('-')[0]+'-'+Date.now();require('fs').writeFileSync('package.json',JSON.stringify(p,null,2)+'\\n')\"",
16
16
  "publish:dev": "npm run build && npm run version:dev && npm publish --tag next && git checkout -- package.json",
17
17
  "pack": "npm run build && npm pack",
18
18
  "preview": "vite preview",
@@ -84,6 +84,14 @@
84
84
  "types": "./dist/ui/icon/index.d.ts",
85
85
  "svelte": "./dist/ui/icon/index.js"
86
86
  },
87
+ "./image": {
88
+ "types": "./dist/ui/image/index.d.ts",
89
+ "svelte": "./dist/ui/image/index.js"
90
+ },
91
+ "./core/media": {
92
+ "types": "./dist/core/media/index.d.ts",
93
+ "svelte": "./dist/core/media/index.js"
94
+ },
87
95
  "./styles/functions": {
88
96
  "sass": "./dist/styles/_functions.scss"
89
97
  },
@@ -114,7 +122,7 @@
114
122
  "mime": "^4.1.0",
115
123
  "nanoid": "^5.1.6",
116
124
  "rfdc": "^1.4.1",
117
- "svelte": "^5.49.2",
125
+ "svelte": "^5.50.0",
118
126
  "svelte-sonner": "^1.0.7",
119
127
  "yup": "^1.7.1"
120
128
  },