@streamscloud/kit 0.1.12-1772032209109 → 0.1.12
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.
- package/dist/core/toastr/index.d.ts +1 -1
- package/dist/core/toastr/toastr.scss +0 -38
- package/dist/core/toastr/toastr.svelte.d.ts +1 -1
- package/dist/core/toastr/toastr.svelte.js +6 -13
- package/dist/core/toastr/types.d.ts +0 -2
- package/dist/ui/cropper/image-editor-dialog/cmp.image-editor-dialog.svelte +2 -2
- package/dist/ui/dialog/cmp.dialog-container.svelte +12 -12
- package/dist/ui/dialog/dialog-data.d.ts +0 -2
- package/dist/ui/dialog/dialog-mount.d.ts +1 -1
- package/dist/ui/dialog/dialog-mount.js +2 -2
- package/dist/ui/dialog/dialogs.svelte.d.ts +0 -3
- package/dist/ui/dialog/dialogs.svelte.js +2 -21
- package/dist/ui/dialog/index.d.ts +1 -1
- package/dist/ui/dialog/index.js +1 -1
- package/dist/ui/dialog/types.svelte.d.ts +14 -3
- package/dist/ui/dialog/types.svelte.js +18 -3
- package/dist/ui/player/carousel/cmp.carousel.svelte +2 -2
- package/dist/ui/player/carousel/cmp.carousel.svelte.d.ts +1 -1
- package/dist/ui/video/cmp.video.svelte +7 -16
- package/package.json +1 -14
- package/dist/ui/form-group/cmp.form-group-label.svelte +0 -25
- package/dist/ui/form-group/cmp.form-group-label.svelte.d.ts +0 -8
- package/dist/ui/form-group/cmp.form-group-note.svelte +0 -16
- package/dist/ui/form-group/cmp.form-group-note.svelte.d.ts +0 -7
- package/dist/ui/form-group/cmp.form-group.svelte +0 -16
- package/dist/ui/form-group/cmp.form-group.svelte.d.ts +0 -8
- package/dist/ui/form-group/index.d.ts +0 -3
- package/dist/ui/form-group/index.js +0 -3
- package/dist/ui/html-block/cmp.html-block.svelte +0 -112
- package/dist/ui/html-block/cmp.html-block.svelte.d.ts +0 -7
- package/dist/ui/html-block/index.d.ts +0 -1
- package/dist/ui/html-block/index.js +0 -1
- package/dist/ui/media-viewer-dialog/cmp.media-viewer-dialog.svelte +0 -50
- package/dist/ui/media-viewer-dialog/cmp.media-viewer-dialog.svelte.d.ts +0 -9
- package/dist/ui/media-viewer-dialog/index.d.ts +0 -13
- package/dist/ui/media-viewer-dialog/index.js +0 -17
- package/dist/ui/media-viewer-dialog/media-viewer-item.svelte +0 -61
- package/dist/ui/media-viewer-dialog/media-viewer-item.svelte.d.ts +0 -7
- package/dist/ui/media-viewer-dialog/types.d.ts +0 -13
- package/dist/ui/media-viewer-dialog/types.js +0 -1
|
@@ -26,41 +26,3 @@
|
|
|
26
26
|
color: var(--info-bg);
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
|
-
|
|
30
|
-
// Theme classes — override svelte-sonner color variables per-toast.
|
|
31
|
-
// Applied via the `class` option when an explicit theme is passed to Toastr methods.
|
|
32
|
-
.sc-toast--light {
|
|
33
|
-
--normal-bg: #fff;
|
|
34
|
-
--normal-border: hsl(0, 0%, 93%);
|
|
35
|
-
--normal-text: hsl(0, 0%, 9%);
|
|
36
|
-
--success-bg: hsl(143, 85%, 96%);
|
|
37
|
-
--success-border: hsl(145, 92%, 87%);
|
|
38
|
-
--success-text: hsl(140, 100%, 27%);
|
|
39
|
-
--info-bg: hsl(208, 100%, 97%);
|
|
40
|
-
--info-border: hsl(221, 91%, 93%);
|
|
41
|
-
--info-text: hsl(210, 92%, 45%);
|
|
42
|
-
--warning-bg: hsl(49, 100%, 97%);
|
|
43
|
-
--warning-border: hsl(49, 91%, 84%);
|
|
44
|
-
--warning-text: hsl(31, 92%, 45%);
|
|
45
|
-
--error-bg: hsl(359, 100%, 97%);
|
|
46
|
-
--error-border: hsl(359, 100%, 94%);
|
|
47
|
-
--error-text: hsl(360, 100%, 45%);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
.sc-toast--dark {
|
|
51
|
-
--normal-bg: #000;
|
|
52
|
-
--normal-border: hsl(0, 0%, 20%);
|
|
53
|
-
--normal-text: hsl(0, 0%, 99%);
|
|
54
|
-
--success-bg: hsl(150, 100%, 6%);
|
|
55
|
-
--success-border: hsl(147, 100%, 12%);
|
|
56
|
-
--success-text: hsl(150, 86%, 65%);
|
|
57
|
-
--info-bg: hsl(215, 100%, 6%);
|
|
58
|
-
--info-border: hsl(223, 43%, 17%);
|
|
59
|
-
--info-text: hsl(216, 87%, 65%);
|
|
60
|
-
--warning-bg: hsl(64, 100%, 6%);
|
|
61
|
-
--warning-border: hsl(60, 100%, 9%);
|
|
62
|
-
--warning-text: hsl(46, 87%, 65%);
|
|
63
|
-
--error-bg: hsl(358, 76%, 10%);
|
|
64
|
-
--error-border: hsl(357, 89%, 16%);
|
|
65
|
-
--error-text: hsl(358, 100%, 81%);
|
|
66
|
-
}
|
|
@@ -4,5 +4,5 @@ export declare class Toastr {
|
|
|
4
4
|
static success(message: string, options?: ToastrOptions): Promise<void>;
|
|
5
5
|
static warning(message: string, options?: ToastrOptions): Promise<void>;
|
|
6
6
|
static info(message: string, options?: ToastrOptions): Promise<void>;
|
|
7
|
-
static promise<T>(promise: Promise<T> | (() => Promise<T>), messages: ToastrPromiseMessages<T
|
|
7
|
+
static promise<T>(promise: Promise<T> | (() => Promise<T>), messages: ToastrPromiseMessages<T>): Promise<void>;
|
|
8
8
|
}
|
|
@@ -1,30 +1,23 @@
|
|
|
1
1
|
import { ToasterHost } from './toaster-host.svelte';
|
|
2
|
-
const toExternalToast = (options) => {
|
|
3
|
-
if (!options) {
|
|
4
|
-
return {};
|
|
5
|
-
}
|
|
6
|
-
const { theme, ...rest } = options;
|
|
7
|
-
return { ...rest, class: theme ? `sc-toast--${theme}` : undefined };
|
|
8
|
-
};
|
|
9
2
|
export class Toastr {
|
|
10
3
|
static async error(message, options) {
|
|
11
4
|
const toast = await ToasterHost.ensure();
|
|
12
|
-
toast.error(message,
|
|
5
|
+
toast.error(message, options);
|
|
13
6
|
}
|
|
14
7
|
static async success(message, options) {
|
|
15
8
|
const toast = await ToasterHost.ensure();
|
|
16
|
-
toast.success(message,
|
|
9
|
+
toast.success(message, options);
|
|
17
10
|
}
|
|
18
11
|
static async warning(message, options) {
|
|
19
12
|
const toast = await ToasterHost.ensure();
|
|
20
|
-
toast.warning(message,
|
|
13
|
+
toast.warning(message, options);
|
|
21
14
|
}
|
|
22
15
|
static async info(message, options) {
|
|
23
16
|
const toast = await ToasterHost.ensure();
|
|
24
|
-
toast.info(message,
|
|
17
|
+
toast.info(message, options);
|
|
25
18
|
}
|
|
26
|
-
static async promise(promise, messages
|
|
19
|
+
static async promise(promise, messages) {
|
|
27
20
|
const toast = await ToasterHost.ensure();
|
|
28
|
-
toast.promise(promise,
|
|
21
|
+
toast.promise(promise, messages);
|
|
29
22
|
}
|
|
30
23
|
}
|
|
@@ -2,12 +2,10 @@ export interface ToastrAction {
|
|
|
2
2
|
label: string;
|
|
3
3
|
onClick: () => void;
|
|
4
4
|
}
|
|
5
|
-
export type ToastrTheme = 'light' | 'dark';
|
|
6
5
|
export interface ToastrOptions {
|
|
7
6
|
action?: ToastrAction;
|
|
8
7
|
description?: string;
|
|
9
8
|
duration?: number;
|
|
10
|
-
theme?: ToastrTheme;
|
|
11
9
|
}
|
|
12
10
|
export interface ToastrPromiseMessages<T> {
|
|
13
11
|
loading: string;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script lang="ts">import { FileWithBlobDataHelper } from '../../../core/files';
|
|
2
2
|
import { Toastr } from '../../../core/toastr';
|
|
3
|
-
import { Dialog, DialogButton, DialogCancelButton } from '../../dialog';
|
|
3
|
+
import { Dialog, DialogButton, DialogCancelButton, DialogSize } from '../../dialog';
|
|
4
4
|
import { ImgCropper, ImgCropperControls, ImgCropperToolbar, ImgCropperView } from '../img-cropper';
|
|
5
5
|
import { ImageEditorDialogLocalization } from './image-editor-dialog-localization';
|
|
6
6
|
import { untrack } from 'svelte';
|
|
@@ -37,7 +37,7 @@ const cancel = () => {
|
|
|
37
37
|
};
|
|
38
38
|
$effect(() => untrack(() => {
|
|
39
39
|
controller.updateSettings({ closeOnClickOutside: false, closeOnEsc: true });
|
|
40
|
-
controller.updateContainerSettings({ size:
|
|
40
|
+
controller.updateContainerSettings({ size: DialogSize.FullHD });
|
|
41
41
|
}));
|
|
42
42
|
</script>
|
|
43
43
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script lang="ts" generics="TResult = void, TCancelResult = void, TData = void">import { Dialogs } from './dialogs.svelte';
|
|
2
|
-
import {
|
|
2
|
+
import { DialogPosition, DialogSize } from './types.svelte';
|
|
3
3
|
import { untrack } from 'svelte';
|
|
4
4
|
let { dialog } = $props();
|
|
5
5
|
let dialogElement = $state();
|
|
@@ -57,7 +57,7 @@ $effect(() => {
|
|
|
57
57
|
});
|
|
58
58
|
const size = $derived(dialog.controller.containerSettings.size);
|
|
59
59
|
const position = $derived(dialog.controller.containerSettings.position);
|
|
60
|
-
const isCustomWidth = $derived(!
|
|
60
|
+
const isCustomWidth = $derived(!Object.values(DialogSize).includes(size));
|
|
61
61
|
const customWidth = $derived(isCustomWidth ? size : null);
|
|
62
62
|
</script>
|
|
63
63
|
|
|
@@ -65,16 +65,16 @@ const customWidth = $derived(isCustomWidth ? size : null);
|
|
|
65
65
|
bind:this={dialogElement}
|
|
66
66
|
class="dialog-container"
|
|
67
67
|
class:dialog-container--inactive={!isActive}
|
|
68
|
-
class:dialog-container--size-small={size ===
|
|
69
|
-
class:dialog-container--size-medium={size ===
|
|
70
|
-
class:dialog-container--size-default={size ===
|
|
71
|
-
class:dialog-container--size-large={size ===
|
|
72
|
-
class:dialog-container--size-fullhd={size ===
|
|
73
|
-
class:dialog-container--size-auto={size ===
|
|
74
|
-
class:dialog-container--position-center={position ===
|
|
75
|
-
class:dialog-container--position-center-top={position ===
|
|
76
|
-
class:dialog-container--position-full-screen={position ===
|
|
77
|
-
class:dialog-container--position-full-height={position ===
|
|
68
|
+
class:dialog-container--size-small={size === DialogSize.Small}
|
|
69
|
+
class:dialog-container--size-medium={size === DialogSize.Medium}
|
|
70
|
+
class:dialog-container--size-default={size === DialogSize.Default}
|
|
71
|
+
class:dialog-container--size-large={size === DialogSize.Large}
|
|
72
|
+
class:dialog-container--size-fullhd={size === DialogSize.FullHD}
|
|
73
|
+
class:dialog-container--size-auto={size === DialogSize.Auto}
|
|
74
|
+
class:dialog-container--position-center={position === DialogPosition.Center}
|
|
75
|
+
class:dialog-container--position-center-top={position === DialogPosition.CenterTop}
|
|
76
|
+
class:dialog-container--position-full-screen={position === DialogPosition.FullScreen}
|
|
77
|
+
class:dialog-container--position-full-height={position === DialogPosition.FullHeight}
|
|
78
78
|
onkeydown={handleKeydown}
|
|
79
79
|
oncancel={handleCancel}
|
|
80
80
|
onclick={handleBackdropClick}
|
|
@@ -23,7 +23,5 @@ export type DialogInit<TData = void, TResult = void, TCancelResult = void> = {
|
|
|
23
23
|
data?: TData;
|
|
24
24
|
explicitSettings?: Partial<DialogSettings>;
|
|
25
25
|
containerSettings?: Partial<DialogContainerSettings>;
|
|
26
|
-
/** Mount target for the dialog element. Useful for shadow DOM isolation. Defaults to `document.body`. */
|
|
27
|
-
host?: ParentNode;
|
|
28
26
|
};
|
|
29
27
|
export {};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { AnyDialogData } from './dialog-data';
|
|
2
|
-
export declare const mountDialog: (dialog: AnyDialogData
|
|
2
|
+
export declare const mountDialog: (dialog: AnyDialogData) => void;
|
|
3
3
|
export declare const unmountDialog: (dialog: AnyDialogData) => void;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { default as DialogContainer } from './cmp.dialog-container.svelte';
|
|
2
2
|
import { mount, unmount } from 'svelte';
|
|
3
|
-
export const mountDialog = (dialog
|
|
3
|
+
export const mountDialog = (dialog) => {
|
|
4
4
|
const hostElement = document.createElement('div');
|
|
5
5
|
hostElement.setAttribute('data-dialog-host', String(dialog.id));
|
|
6
|
-
|
|
6
|
+
document.body.appendChild(hostElement);
|
|
7
7
|
const component = mount(DialogContainer, {
|
|
8
8
|
target: hostElement,
|
|
9
9
|
props: { dialog }
|
|
@@ -3,14 +3,11 @@ import { type DialogResult } from './types.svelte';
|
|
|
3
3
|
export declare class DialogsContainer {
|
|
4
4
|
private _dialogs;
|
|
5
5
|
private _mountModule;
|
|
6
|
-
private _savedOverflow;
|
|
7
6
|
get all(): ReadonlyArray<AnyDialogData>;
|
|
8
7
|
get active(): AnyDialogData | null;
|
|
9
8
|
get count(): number;
|
|
10
9
|
open: <TData = void, TResult = void, TCancelResult = void>(init: DialogInit<TData, TResult, TCancelResult>, id?: number) => Promise<DialogResult<TResult, TCancelResult>>;
|
|
11
10
|
close: (id: number) => void;
|
|
12
11
|
closeAll: () => void;
|
|
13
|
-
private lockBodyScroll;
|
|
14
|
-
private unlockBodyScroll;
|
|
15
12
|
}
|
|
16
13
|
export declare const Dialogs: DialogsContainer;
|
|
@@ -5,7 +5,6 @@ import {} from './types.svelte';
|
|
|
5
5
|
export class DialogsContainer {
|
|
6
6
|
_dialogs = $state.raw([]);
|
|
7
7
|
_mountModule = null;
|
|
8
|
-
_savedOverflow = null;
|
|
9
8
|
get all() {
|
|
10
9
|
return this._dialogs;
|
|
11
10
|
}
|
|
@@ -19,7 +18,7 @@ export class DialogsContainer {
|
|
|
19
18
|
if (!this._mountModule) {
|
|
20
19
|
this._mountModule = await import('./dialog-mount');
|
|
21
20
|
}
|
|
22
|
-
const { view, data, explicitSettings, containerSettings
|
|
21
|
+
const { view, data, explicitSettings, containerSettings } = init;
|
|
23
22
|
const controller = new DialogController({
|
|
24
23
|
id,
|
|
25
24
|
onClose: () => {
|
|
@@ -27,9 +26,6 @@ export class DialogsContainer {
|
|
|
27
26
|
if (dialog) {
|
|
28
27
|
this._mountModule?.unmountDialog(dialog);
|
|
29
28
|
this._dialogs = this._dialogs.filter((d) => d.id !== id);
|
|
30
|
-
if (this._dialogs.length === 0) {
|
|
31
|
-
this.unlockBodyScroll();
|
|
32
|
-
}
|
|
33
29
|
}
|
|
34
30
|
},
|
|
35
31
|
settings: explicitSettings,
|
|
@@ -42,8 +38,7 @@ export class DialogsContainer {
|
|
|
42
38
|
controller
|
|
43
39
|
};
|
|
44
40
|
this._dialogs = [...this._dialogs, newDialog];
|
|
45
|
-
this.
|
|
46
|
-
this._mountModule.mountDialog(newDialog, host);
|
|
41
|
+
this._mountModule.mountDialog(newDialog);
|
|
47
42
|
return controller.openedPromise;
|
|
48
43
|
};
|
|
49
44
|
close = (id) => {
|
|
@@ -58,20 +53,6 @@ export class DialogsContainer {
|
|
|
58
53
|
dialog.controller.cancel();
|
|
59
54
|
}
|
|
60
55
|
};
|
|
61
|
-
lockBodyScroll = () => {
|
|
62
|
-
if (this._savedOverflow !== null) {
|
|
63
|
-
return;
|
|
64
|
-
}
|
|
65
|
-
this._savedOverflow = document.body.style.overflow;
|
|
66
|
-
document.body.style.overflow = 'hidden';
|
|
67
|
-
};
|
|
68
|
-
unlockBodyScroll = () => {
|
|
69
|
-
if (this._savedOverflow === null) {
|
|
70
|
-
return;
|
|
71
|
-
}
|
|
72
|
-
document.body.style.overflow = this._savedOverflow;
|
|
73
|
-
this._savedOverflow = null;
|
|
74
|
-
};
|
|
75
56
|
}
|
|
76
57
|
const createDialogsSingleton = () => {
|
|
77
58
|
if (!isBrowser()) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { Dialogs } from './dialogs.svelte';
|
|
2
2
|
export { DialogController } from './dialog-controller';
|
|
3
|
-
export {
|
|
3
|
+
export { DialogSize, DialogPosition, type DialogResult } from './types.svelte';
|
|
4
4
|
export { default as Dialog } from './cmp.dialog.svelte';
|
|
5
5
|
export { default as DialogButton } from './cmp.dialog-button.svelte';
|
|
6
6
|
export { default as DialogCancelButton } from './cmp.dialog-cancel-button.svelte';
|
package/dist/ui/dialog/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { Dialogs } from './dialogs.svelte';
|
|
2
2
|
export { DialogController } from './dialog-controller';
|
|
3
|
-
export {
|
|
3
|
+
export { DialogSize, DialogPosition } from './types.svelte';
|
|
4
4
|
export { default as Dialog } from './cmp.dialog.svelte';
|
|
5
5
|
export { default as DialogButton } from './cmp.dialog-button.svelte';
|
|
6
6
|
export { default as DialogCancelButton } from './cmp.dialog-cancel-button.svelte';
|
|
@@ -1,6 +1,17 @@
|
|
|
1
|
-
export
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
export declare enum DialogSize {
|
|
2
|
+
Small = "small",
|
|
3
|
+
Medium = "medium",
|
|
4
|
+
Default = "default",
|
|
5
|
+
Large = "large",
|
|
6
|
+
FullHD = "fullhd",
|
|
7
|
+
Auto = "auto"
|
|
8
|
+
}
|
|
9
|
+
export declare enum DialogPosition {
|
|
10
|
+
Center = "center",
|
|
11
|
+
CenterTop = "center-top",
|
|
12
|
+
FullScreen = "full-screen",
|
|
13
|
+
FullHeight = "full-height"
|
|
14
|
+
}
|
|
4
15
|
export declare class DialogSettings {
|
|
5
16
|
closeOnClickOutside: boolean;
|
|
6
17
|
closeOnEsc: boolean;
|
|
@@ -1,10 +1,25 @@
|
|
|
1
|
-
export
|
|
1
|
+
export var DialogSize;
|
|
2
|
+
(function (DialogSize) {
|
|
3
|
+
DialogSize["Small"] = "small";
|
|
4
|
+
DialogSize["Medium"] = "medium";
|
|
5
|
+
DialogSize["Default"] = "default";
|
|
6
|
+
DialogSize["Large"] = "large";
|
|
7
|
+
DialogSize["FullHD"] = "fullhd";
|
|
8
|
+
DialogSize["Auto"] = "auto";
|
|
9
|
+
})(DialogSize || (DialogSize = {}));
|
|
10
|
+
export var DialogPosition;
|
|
11
|
+
(function (DialogPosition) {
|
|
12
|
+
DialogPosition["Center"] = "center";
|
|
13
|
+
DialogPosition["CenterTop"] = "center-top";
|
|
14
|
+
DialogPosition["FullScreen"] = "full-screen";
|
|
15
|
+
DialogPosition["FullHeight"] = "full-height";
|
|
16
|
+
})(DialogPosition || (DialogPosition = {}));
|
|
2
17
|
export class DialogSettings {
|
|
3
18
|
closeOnClickOutside = $state(false);
|
|
4
19
|
closeOnEsc = $state(false);
|
|
5
20
|
nonCancelable = $state(false);
|
|
6
21
|
}
|
|
7
22
|
export class DialogContainerSettings {
|
|
8
|
-
size = $state(
|
|
9
|
-
position = $state(
|
|
23
|
+
size = $state(DialogSize.Default);
|
|
24
|
+
position = $state(DialogPosition.CenterTop);
|
|
10
25
|
}
|
|
@@ -260,7 +260,7 @@ A horizontal slide carousel with infinite looping, touch swipe support, keyboard
|
|
|
260
260
|
### CSS Custom Properties
|
|
261
261
|
| Property | Description | Default |
|
|
262
262
|
|---|---|---|
|
|
263
|
-
| `--sc-kit--carousel--button-color` | Navigation arrow button background | `
|
|
263
|
+
| `--sc-kit--carousel--button-color` | Navigation arrow button background | `neutral-400` |
|
|
264
264
|
| `--sc-kit--carousel--dot-color` | Dot indicator color (fill when active, border when inactive) | `white` |
|
|
265
265
|
| `--sc-kit--carousel--dot-size` | Dot indicator diameter | `0.5rem` |
|
|
266
266
|
| `--sc-kit--carousel--text-color` | Arrow button icon and counter text color | `white` |
|
|
@@ -269,7 +269,7 @@ A horizontal slide carousel with infinite looping, touch swipe support, keyboard
|
|
|
269
269
|
<style>@charset "UTF-8";
|
|
270
270
|
.carousel {
|
|
271
271
|
/* Public API */
|
|
272
|
-
--_carousel--button-color: var(--sc-kit--carousel--button-color,
|
|
272
|
+
--_carousel--button-color: var(--sc-kit--carousel--button-color, #9ca3af);
|
|
273
273
|
--_carousel--dot-color: var(--sc-kit--carousel--dot-color, #ffffff);
|
|
274
274
|
--_carousel--dot-size: var(--sc-kit--carousel--dot-size, 0.5rem);
|
|
275
275
|
--_carousel--text-color: var(--sc-kit--carousel--text-color, #ffffff);
|
|
@@ -46,7 +46,7 @@ interface $$IsomorphicComponent {
|
|
|
46
46
|
* ### CSS Custom Properties
|
|
47
47
|
* | Property | Description | Default |
|
|
48
48
|
* |---|---|---|
|
|
49
|
-
* | `--sc-kit--carousel--button-color` | Navigation arrow button background | `
|
|
49
|
+
* | `--sc-kit--carousel--button-color` | Navigation arrow button background | `neutral-400` |
|
|
50
50
|
* | `--sc-kit--carousel--dot-color` | Dot indicator color (fill when active, border when inactive) | `white` |
|
|
51
51
|
* | `--sc-kit--carousel--dot-size` | Dot indicator diameter | `0.5rem` |
|
|
52
52
|
* | `--sc-kit--carousel--text-color` | Arrow button icon and counter text color | `white` |
|
|
@@ -8,11 +8,10 @@ import IconSpeaker from '@fluentui/svg-icons/icons/speaker_2_20_regular.svg?raw'
|
|
|
8
8
|
import IconSpeakerMute from '@fluentui/svg-icons/icons/speaker_mute_20_regular.svg?raw';
|
|
9
9
|
import { untrack } from 'svelte';
|
|
10
10
|
import { fade } from 'svelte/transition';
|
|
11
|
-
let { src, poster, id = randomNanoid(), controls =
|
|
11
|
+
let { src, poster, id = randomNanoid(), controls = true, autoplay = false, loop = false, inert = false, allowPreloading = false, hideSpeaker = false, hidePlayButton = false, intersectionContainer, scrubberPosition = 'bottom', on } = $props();
|
|
12
12
|
let video = $state(null);
|
|
13
13
|
let videoContainerRef = $state(null);
|
|
14
14
|
let showControlsOnHover = $state(false);
|
|
15
|
-
let showProgressOnHover = $state(false);
|
|
16
15
|
let isVideoPaused = $state(true);
|
|
17
16
|
let percentageCompleted = $state(0);
|
|
18
17
|
let everActivated = $state(false);
|
|
@@ -247,13 +246,7 @@ const handleSeek = (percent) => {
|
|
|
247
246
|
<img class="video__poster" src={poster} alt="" />
|
|
248
247
|
{/if}
|
|
249
248
|
{#if !controls || !everActivated}
|
|
250
|
-
<div
|
|
251
|
-
class="video__overlay"
|
|
252
|
-
onclick={togglePlay}
|
|
253
|
-
onkeydown={() => ({})}
|
|
254
|
-
onmouseenter={() => (showControlsOnHover = true)}
|
|
255
|
-
onmouseleave={() => (showControlsOnHover = false)}
|
|
256
|
-
role="none">
|
|
249
|
+
<div class="video__overlay" onclick={togglePlay} onkeydown={() => ({})} role="none">
|
|
257
250
|
{#if isVideoPaused && !hidePlayButton}
|
|
258
251
|
<button type="button" aria-label="play" class="video__playback-button" onclick={togglePlay} onkeydown={() => ({})}>
|
|
259
252
|
<Icon src={IconPlay} color="white" />
|
|
@@ -263,7 +256,6 @@ const handleSeek = (percent) => {
|
|
|
263
256
|
<Icon src={IconPause} color="white" />
|
|
264
257
|
</button>
|
|
265
258
|
{/if}
|
|
266
|
-
|
|
267
259
|
{#if (showControlsOnHover || MediaVolumeManager.isMuted) && !hideSpeaker}
|
|
268
260
|
<button type="button" aria-label={MediaVolumeManager.isMuted ? 'mute' : 'unmute'} class="video__mute-button" onclick={toggleMute}>
|
|
269
261
|
{#if MediaVolumeManager.isMuted}
|
|
@@ -279,10 +271,10 @@ const handleSeek = (percent) => {
|
|
|
279
271
|
class="video__progress-container"
|
|
280
272
|
class:video__progress-container--top={scrubberPosition === 'top'}
|
|
281
273
|
class:video__progress-container--bottom={scrubberPosition === 'bottom'}
|
|
282
|
-
onmouseenter={() => (
|
|
283
|
-
onmouseleave={() => (
|
|
274
|
+
onmouseenter={() => (showControlsOnHover = true)}
|
|
275
|
+
onmouseleave={() => (showControlsOnHover = false)}
|
|
284
276
|
role="none">
|
|
285
|
-
{#if
|
|
277
|
+
{#if showControlsOnHover || (!showControlsOnHover && isVideoPaused)}
|
|
286
278
|
<div
|
|
287
279
|
class="video__seek-bar"
|
|
288
280
|
transition:fade={{ duration: isVideoPaused ? 0 : 300 }}
|
|
@@ -329,12 +321,12 @@ A full-featured video player with custom overlay controls, play/pause, mute, see
|
|
|
329
321
|
background: var(--_video--background-color);
|
|
330
322
|
}
|
|
331
323
|
.video__playback-button {
|
|
332
|
-
--sc-kit--icon--size: 2.5rem;
|
|
333
324
|
--sc-kit--icon--filter: drop-shadow(1px 1px #000000);
|
|
334
325
|
position: absolute;
|
|
335
326
|
top: 50%;
|
|
336
327
|
left: 50%;
|
|
337
328
|
transform: translate(-50%, -50%);
|
|
329
|
+
font-size: 2em;
|
|
338
330
|
}
|
|
339
331
|
.video__playback-button--pause {
|
|
340
332
|
/* Set 'container-type: inline-size;' to reference container*/
|
|
@@ -345,11 +337,10 @@ A full-featured video player with custom overlay controls, play/pause, mute, see
|
|
|
345
337
|
}
|
|
346
338
|
}
|
|
347
339
|
.video__mute-button {
|
|
348
|
-
--sc-kit--icon--size: 1.25rem;
|
|
349
|
-
--sc-kit--icon--filter: drop-shadow(1px 1px #000000);
|
|
350
340
|
position: absolute;
|
|
351
341
|
top: 0.625em;
|
|
352
342
|
right: 0.625em;
|
|
343
|
+
font-size: 1em;
|
|
353
344
|
z-index: 1;
|
|
354
345
|
}
|
|
355
346
|
.video__poster {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@streamscloud/kit",
|
|
3
|
-
"version": "0.1.12
|
|
3
|
+
"version": "0.1.12",
|
|
4
4
|
"author": "StreamsCloud",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -17,7 +17,6 @@
|
|
|
17
17
|
"pack": "npm run build && npm pack",
|
|
18
18
|
"preview": "vite preview",
|
|
19
19
|
"check": "svelte-check --tsconfig ./tsconfig.app.json && tsc -p tsconfig.node.json",
|
|
20
|
-
"check:strict": "svelte-check --tsconfig ./tsconfig.app.json --fail-on-warnings --output machine && eslint . --format codeframe --max-warnings 0 && prettier --check --plugin prettier-plugin-svelte --cache .",
|
|
21
20
|
"lint": "prettier --check --plugin prettier-plugin-svelte . && eslint .",
|
|
22
21
|
"lint-format": "prettier --write --plugin prettier-plugin-svelte . && eslint --fix .",
|
|
23
22
|
"format": "prettier --write --plugin prettier-plugin-svelte ."
|
|
@@ -105,10 +104,6 @@
|
|
|
105
104
|
"types": "./dist/ui/dialog/index.d.ts",
|
|
106
105
|
"svelte": "./dist/ui/dialog/index.js"
|
|
107
106
|
},
|
|
108
|
-
"./ui/form-group": {
|
|
109
|
-
"types": "./dist/ui/form-group/index.d.ts",
|
|
110
|
-
"svelte": "./dist/ui/form-group/index.js"
|
|
111
|
-
},
|
|
112
107
|
"./ui/dropdown": {
|
|
113
108
|
"types": "./dist/ui/dropdown/index.d.ts",
|
|
114
109
|
"svelte": "./dist/ui/dropdown/index.js"
|
|
@@ -117,10 +112,6 @@
|
|
|
117
112
|
"types": "./dist/ui/dynamic-component/index.d.ts",
|
|
118
113
|
"svelte": "./dist/ui/dynamic-component/index.js"
|
|
119
114
|
},
|
|
120
|
-
"./ui/html-block": {
|
|
121
|
-
"types": "./dist/ui/html-block/index.d.ts",
|
|
122
|
-
"svelte": "./dist/ui/html-block/index.js"
|
|
123
|
-
},
|
|
124
115
|
"./ui/icon": {
|
|
125
116
|
"types": "./dist/ui/icon/index.d.ts",
|
|
126
117
|
"svelte": "./dist/ui/icon/index.js"
|
|
@@ -153,10 +144,6 @@
|
|
|
153
144
|
"types": "./dist/ui/media-playback/index.d.ts",
|
|
154
145
|
"svelte": "./dist/ui/media-playback/index.js"
|
|
155
146
|
},
|
|
156
|
-
"./ui/media-viewer-dialog": {
|
|
157
|
-
"types": "./dist/ui/media-viewer-dialog/index.d.ts",
|
|
158
|
-
"svelte": "./dist/ui/media-viewer-dialog/index.js"
|
|
159
|
-
},
|
|
160
147
|
"./ui/player/buttons": {
|
|
161
148
|
"types": "./dist/ui/player/buttons/index.d.ts",
|
|
162
149
|
"svelte": "./dist/ui/player/buttons/index.js"
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
<script lang="ts">let { withTooltip = false, children } = $props();
|
|
2
|
-
export {};
|
|
3
|
-
</script>
|
|
4
|
-
|
|
5
|
-
<div class="form-group-label" class:form-group-label--with-tooltip={withTooltip}>
|
|
6
|
-
{@render children()}
|
|
7
|
-
</div>
|
|
8
|
-
|
|
9
|
-
<style>.form-group-label {
|
|
10
|
-
--_form-group--label--font-size: var(--sc-kit--form-group--label--font-size, 0.875rem);
|
|
11
|
-
--_form-group--label--font-weight: var(--sc-kit--form-group--label--font-weight, 400);
|
|
12
|
-
--_form-group--label--color: var(--sc-kit--form-group--label--color);
|
|
13
|
-
--_form-group--label--margin-bottom: var(--sc-kit--form-group--label--margin-bottom, 0.5rem);
|
|
14
|
-
font-size: var(--_form-group--label--font-size);
|
|
15
|
-
padding: 0;
|
|
16
|
-
margin-bottom: var(--_form-group--label--margin-bottom);
|
|
17
|
-
font-weight: var(--_form-group--label--font-weight);
|
|
18
|
-
display: block;
|
|
19
|
-
color: var(--_form-group--label--color);
|
|
20
|
-
}
|
|
21
|
-
.form-group-label--with-tooltip {
|
|
22
|
-
display: flex;
|
|
23
|
-
align-items: center;
|
|
24
|
-
gap: 0.25rem;
|
|
25
|
-
}</style>
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
<script lang="ts">let { children } = $props();
|
|
2
|
-
export {};
|
|
3
|
-
</script>
|
|
4
|
-
|
|
5
|
-
<div class="form-group-note">
|
|
6
|
-
{@render children()}
|
|
7
|
-
</div>
|
|
8
|
-
|
|
9
|
-
<style>.form-group-note {
|
|
10
|
-
--_form-group--note--font-size: var(--sc-kit--form-group--note--font-size, 0.875rem);
|
|
11
|
-
--_form-group--note--font-weight: var(--sc-kit--form-group--note--font-weight, 300);
|
|
12
|
-
margin-top: 0.5rem;
|
|
13
|
-
color: #9ca3af;
|
|
14
|
-
font-size: var(--_form-group--note--font-size);
|
|
15
|
-
font-weight: var(--_form-group--note--font-weight);
|
|
16
|
-
}</style>
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
<script lang="ts">let { noMargin = false, children } = $props();
|
|
2
|
-
export {};
|
|
3
|
-
</script>
|
|
4
|
-
|
|
5
|
-
<div class="form-group" class:form-group--no-margin={noMargin}>
|
|
6
|
-
{@render children()}
|
|
7
|
-
</div>
|
|
8
|
-
|
|
9
|
-
<style>.form-group {
|
|
10
|
-
--_form-group--margin-bottom: var(--sc-kit--form-group--margin-bottom, 1.25rem);
|
|
11
|
-
display: block;
|
|
12
|
-
margin-bottom: var(--_form-group--margin-bottom);
|
|
13
|
-
}
|
|
14
|
-
.form-group--no-margin {
|
|
15
|
-
margin-bottom: 0;
|
|
16
|
-
}</style>
|
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
<script lang="ts">let { children } = $props();
|
|
2
|
-
export {};
|
|
3
|
-
</script>
|
|
4
|
-
|
|
5
|
-
<div class="html-block">
|
|
6
|
-
{@render children()}
|
|
7
|
-
</div>
|
|
8
|
-
|
|
9
|
-
<style>.html-block {
|
|
10
|
-
display: contents;
|
|
11
|
-
word-break: break-word;
|
|
12
|
-
font-size: 0.875em;
|
|
13
|
-
line-height: 1.4;
|
|
14
|
-
font-weight: normal;
|
|
15
|
-
color: light-dark(#2e2e2e, #ffffff);
|
|
16
|
-
}
|
|
17
|
-
.html-block :global(h1) {
|
|
18
|
-
font-size: 1.5em;
|
|
19
|
-
line-height: 1.4;
|
|
20
|
-
font-weight: 600;
|
|
21
|
-
color: light-dark(#2e2e2e, #ffffff);
|
|
22
|
-
}
|
|
23
|
-
.html-block :global(h2) {
|
|
24
|
-
font-size: 1.375em;
|
|
25
|
-
line-height: 1.4;
|
|
26
|
-
font-weight: 600;
|
|
27
|
-
color: light-dark(#2e2e2e, #ffffff);
|
|
28
|
-
}
|
|
29
|
-
.html-block :global(h3) {
|
|
30
|
-
font-size: 1.25em;
|
|
31
|
-
line-height: 1.4;
|
|
32
|
-
font-weight: 600;
|
|
33
|
-
color: light-dark(#2e2e2e, #ffffff);
|
|
34
|
-
}
|
|
35
|
-
.html-block :global(h4) {
|
|
36
|
-
font-size: 1.125em;
|
|
37
|
-
line-height: 1.4;
|
|
38
|
-
font-weight: 500;
|
|
39
|
-
color: light-dark(#2e2e2e, #ffffff);
|
|
40
|
-
}
|
|
41
|
-
.html-block :global(h5) {
|
|
42
|
-
font-size: 1.0625em;
|
|
43
|
-
line-height: 1.4;
|
|
44
|
-
font-weight: 500;
|
|
45
|
-
color: light-dark(#2e2e2e, #ffffff);
|
|
46
|
-
}
|
|
47
|
-
.html-block :global(h6) {
|
|
48
|
-
font-size: 1em;
|
|
49
|
-
line-height: 1.4;
|
|
50
|
-
font-weight: 500;
|
|
51
|
-
color: light-dark(#2e2e2e, #ffffff);
|
|
52
|
-
}
|
|
53
|
-
.html-block :global(a) {
|
|
54
|
-
font-size: 1em;
|
|
55
|
-
line-height: 1.4;
|
|
56
|
-
font-weight: normal;
|
|
57
|
-
color: light-dark(#2e2e2e, #ffffff);
|
|
58
|
-
color: light-dark(#144ab0, #5a8dec);
|
|
59
|
-
}
|
|
60
|
-
.html-block :global(pre) {
|
|
61
|
-
font-family: monospace;
|
|
62
|
-
white-space: pre-wrap;
|
|
63
|
-
margin: 1em 0;
|
|
64
|
-
font-size: 1em;
|
|
65
|
-
line-height: 1;
|
|
66
|
-
font-weight: normal;
|
|
67
|
-
color: light-dark(#2e2e2e, #ffffff);
|
|
68
|
-
}
|
|
69
|
-
.html-block :global(ul) :global(> li),
|
|
70
|
-
.html-block :global(ol) :global(> li) {
|
|
71
|
-
list-style: inherit;
|
|
72
|
-
margin-left: 1em;
|
|
73
|
-
position: relative;
|
|
74
|
-
font-size: 1em;
|
|
75
|
-
line-height: 1.4;
|
|
76
|
-
font-weight: normal;
|
|
77
|
-
color: light-dark(#2e2e2e, #ffffff);
|
|
78
|
-
}
|
|
79
|
-
.html-block :global(ol) {
|
|
80
|
-
list-style-type: decimal;
|
|
81
|
-
}
|
|
82
|
-
.html-block :global(ol) :global(> li > ol) {
|
|
83
|
-
list-style-type: lower-alpha;
|
|
84
|
-
}
|
|
85
|
-
.html-block :global(table) {
|
|
86
|
-
max-width: 100%;
|
|
87
|
-
}
|
|
88
|
-
.html-block :global(table),
|
|
89
|
-
.html-block :global(tbody),
|
|
90
|
-
.html-block :global(thead),
|
|
91
|
-
.html-block :global(tr),
|
|
92
|
-
.html-block :global(th),
|
|
93
|
-
.html-block :global(td) {
|
|
94
|
-
border-width: initial;
|
|
95
|
-
border-style: inherit;
|
|
96
|
-
border-color: inherit;
|
|
97
|
-
}
|
|
98
|
-
.html-block :global(ul:not([style*='list-style-type'])),
|
|
99
|
-
.html-block :global(ul:not([style*='list-style-type']) > li > ul:not([style*='list-style-type'])) {
|
|
100
|
-
list-style-type: none;
|
|
101
|
-
}
|
|
102
|
-
.html-block :global(ul:not([style*='list-style-type']) > li:before),
|
|
103
|
-
.html-block :global(ul:not([style*='list-style-type']) > li > ul:not([style*='list-style-type']) > li:before) {
|
|
104
|
-
content: "-";
|
|
105
|
-
text-indent: -1em;
|
|
106
|
-
position: absolute;
|
|
107
|
-
font-weight: bold;
|
|
108
|
-
}
|
|
109
|
-
.html-block :global(ul[style*='list-style-type'] > li:before),
|
|
110
|
-
.html-block :global(ul > li > ul[style*='list-style-type'] > li:before) {
|
|
111
|
-
content: none;
|
|
112
|
-
}</style>
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { default as HtmlBlock } from './cmp.html-block.svelte';
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { default as HtmlBlock } from './cmp.html-block.svelte';
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
<script lang="ts">import { DialogCloseButton } from '../dialog';
|
|
2
|
-
import { Carousel } from '../player/carousel';
|
|
3
|
-
import { default as MediaViewerItem } from './media-viewer-item.svelte';
|
|
4
|
-
import { untrack } from 'svelte';
|
|
5
|
-
const { controller, data } = $props();
|
|
6
|
-
$effect(() => untrack(() => {
|
|
7
|
-
controller.updateSettings({ closeOnEsc: true, closeOnClickOutside: true });
|
|
8
|
-
controller.updateContainerSettings({ position: 'full-screen' });
|
|
9
|
-
}));
|
|
10
|
-
</script>
|
|
11
|
-
|
|
12
|
-
<div class="media-viewer-dialog" style:--media-viewer-dialog--background--opacity={data.backgroundOpacity}>
|
|
13
|
-
<div class="media-viewer-dialog__close">
|
|
14
|
-
<DialogCloseButton controller={controller} />
|
|
15
|
-
</div>
|
|
16
|
-
|
|
17
|
-
<div class="media-viewer-dialog__content">
|
|
18
|
-
{#if data.items.length === 1}
|
|
19
|
-
<MediaViewerItem item={data.items[0]} />
|
|
20
|
-
{:else}
|
|
21
|
-
<Carousel items={data.items} initialIndex={data.index} mode="arrows-with-counts" on={{ indexChanged: () => {} }}>
|
|
22
|
-
{#snippet children(item)}
|
|
23
|
-
<MediaViewerItem item={item} />
|
|
24
|
-
{/snippet}
|
|
25
|
-
</Carousel>
|
|
26
|
-
{/if}
|
|
27
|
-
</div>
|
|
28
|
-
</div>
|
|
29
|
-
|
|
30
|
-
<style>.media-viewer-dialog {
|
|
31
|
-
--_media-viewer-dialog--background--opacity: var(--media-viewer-dialog--background--opacity, 0.6);
|
|
32
|
-
--sc-kit--dialog-close-button--color: #ffffff;
|
|
33
|
-
display: flex;
|
|
34
|
-
flex-direction: column;
|
|
35
|
-
width: 100%;
|
|
36
|
-
height: 100%;
|
|
37
|
-
background: rgba(0, 0, 0, var(--_media-viewer-dialog--background--opacity));
|
|
38
|
-
position: relative;
|
|
39
|
-
padding: 0.625rem;
|
|
40
|
-
}
|
|
41
|
-
.media-viewer-dialog__close {
|
|
42
|
-
position: absolute;
|
|
43
|
-
top: 0.75rem;
|
|
44
|
-
right: 0.75rem;
|
|
45
|
-
z-index: 10;
|
|
46
|
-
}
|
|
47
|
-
.media-viewer-dialog__content {
|
|
48
|
-
flex: 1;
|
|
49
|
-
min-height: 0;
|
|
50
|
-
}</style>
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { type DialogController } from '../dialog';
|
|
2
|
-
import type { MediaViewerData } from './types';
|
|
3
|
-
type Props = {
|
|
4
|
-
controller: DialogController;
|
|
5
|
-
data: MediaViewerData;
|
|
6
|
-
};
|
|
7
|
-
declare const Cmp: import("svelte").Component<Props, {}, "">;
|
|
8
|
-
type Cmp = ReturnType<typeof Cmp>;
|
|
9
|
-
export default Cmp;
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { type DialogResult } from '../dialog';
|
|
2
|
-
import type { MediaViewerData } from './types';
|
|
3
|
-
/**
|
|
4
|
-
* Opens a full-screen media viewer dialog for images and videos.
|
|
5
|
-
* Single item renders directly; multiple items display in a carousel with arrow navigation.
|
|
6
|
-
*
|
|
7
|
-
* ### Options
|
|
8
|
-
* - `items` — array of media items to display
|
|
9
|
-
* - `index` — zero-based index of the initially visible item
|
|
10
|
-
* - `backgroundOpacity` — backdrop opacity (default `0.6`)
|
|
11
|
-
*/
|
|
12
|
-
export declare const openMediaViewer: (data: MediaViewerData) => Promise<DialogResult<void>>;
|
|
13
|
-
export type { MediaViewerData, MediaViewerItem, MediaViewerItemType } from './types';
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { Dialogs } from '../dialog';
|
|
2
|
-
import { default as MediaViewerDialog } from './cmp.media-viewer-dialog.svelte';
|
|
3
|
-
/**
|
|
4
|
-
* Opens a full-screen media viewer dialog for images and videos.
|
|
5
|
-
* Single item renders directly; multiple items display in a carousel with arrow navigation.
|
|
6
|
-
*
|
|
7
|
-
* ### Options
|
|
8
|
-
* - `items` — array of media items to display
|
|
9
|
-
* - `index` — zero-based index of the initially visible item
|
|
10
|
-
* - `backgroundOpacity` — backdrop opacity (default `0.6`)
|
|
11
|
-
*/
|
|
12
|
-
export const openMediaViewer = (data) => {
|
|
13
|
-
return Dialogs.open({
|
|
14
|
-
view: MediaViewerDialog,
|
|
15
|
-
data
|
|
16
|
-
});
|
|
17
|
-
};
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
<script lang="ts">import { Image } from '../image';
|
|
2
|
-
import { Video } from '../video';
|
|
3
|
-
const { item } = $props();
|
|
4
|
-
let containerWidth = $state(0);
|
|
5
|
-
let containerHeight = $state(0);
|
|
6
|
-
const fittedSize = $derived.by(() => {
|
|
7
|
-
if (containerWidth === 0 || containerHeight === 0) {
|
|
8
|
-
return { width: 0, height: 0 };
|
|
9
|
-
}
|
|
10
|
-
const aspectRatio = item.width / item.height;
|
|
11
|
-
const containerRatio = containerWidth / containerHeight;
|
|
12
|
-
if (aspectRatio > containerRatio) {
|
|
13
|
-
const width = containerWidth;
|
|
14
|
-
const height = width / aspectRatio;
|
|
15
|
-
return { width, height };
|
|
16
|
-
}
|
|
17
|
-
const height = containerHeight;
|
|
18
|
-
const width = height * aspectRatio;
|
|
19
|
-
return { width, height };
|
|
20
|
-
});
|
|
21
|
-
const observeResize = (node) => {
|
|
22
|
-
const observer = new ResizeObserver((entries) => {
|
|
23
|
-
const entry = entries[0];
|
|
24
|
-
if (entry) {
|
|
25
|
-
containerWidth = entry.contentRect.width;
|
|
26
|
-
containerHeight = entry.contentRect.height;
|
|
27
|
-
}
|
|
28
|
-
});
|
|
29
|
-
observer.observe(node);
|
|
30
|
-
return {
|
|
31
|
-
destroy: () => observer.disconnect()
|
|
32
|
-
};
|
|
33
|
-
};
|
|
34
|
-
</script>
|
|
35
|
-
|
|
36
|
-
<div class="media-viewer-item" use:observeResize>
|
|
37
|
-
{#if fittedSize.width > 0 && fittedSize.height > 0}
|
|
38
|
-
<div class="media-viewer-item__media" style:width="{fittedSize.width}px" style:height="{fittedSize.height}px">
|
|
39
|
-
{#if item.type === 'image'}
|
|
40
|
-
<Image src={item.url} alt="" />
|
|
41
|
-
{:else}
|
|
42
|
-
<Video src={item.url} poster={item.thumbnailUrl} autoplay="on-appearance" />
|
|
43
|
-
{/if}
|
|
44
|
-
</div>
|
|
45
|
-
{/if}
|
|
46
|
-
</div>
|
|
47
|
-
|
|
48
|
-
<style>.media-viewer-item {
|
|
49
|
-
--sc-kit--image--object-fit: contain;
|
|
50
|
-
--sc-kit--video--media-fit: contain;
|
|
51
|
-
display: flex;
|
|
52
|
-
align-items: center;
|
|
53
|
-
justify-content: center;
|
|
54
|
-
width: 100%;
|
|
55
|
-
height: 100%;
|
|
56
|
-
}
|
|
57
|
-
.media-viewer-item__media {
|
|
58
|
-
flex-shrink: 0;
|
|
59
|
-
overflow: hidden;
|
|
60
|
-
border-radius: 0.375rem;
|
|
61
|
-
}</style>
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
export type MediaViewerItemType = 'image' | 'video';
|
|
2
|
-
export type MediaViewerItem = {
|
|
3
|
-
url: string;
|
|
4
|
-
thumbnailUrl: string | null;
|
|
5
|
-
type: MediaViewerItemType;
|
|
6
|
-
width: number;
|
|
7
|
-
height: number;
|
|
8
|
-
};
|
|
9
|
-
export type MediaViewerData = {
|
|
10
|
-
items: MediaViewerItem[];
|
|
11
|
-
index: number;
|
|
12
|
-
backgroundOpacity?: number;
|
|
13
|
-
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|