@x33025/sveltely 0.1.7 → 0.1.9
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/actions/LoaderOverlay.svelte +44 -0
- package/dist/actions/LoaderOverlay.svelte.d.ts +6 -0
- package/dist/actions/loader.d.ts +11 -0
- package/dist/actions/loader.js +117 -0
- package/dist/components/Library/Grid/Grid.svelte +24 -15
- package/dist/components/Library/Grid/Grid.svelte.d.ts +2 -1
- package/dist/components/Library/GridItem/GridItem.svelte +16 -16
- package/dist/components/Library/GridItem/GridItem.svelte.d.ts +2 -1
- package/dist/components/Library/HStack/HStack.svelte +12 -6
- package/dist/components/Library/HStack/HStack.svelte.d.ts +2 -1
- package/dist/components/Library/Loader/Loader.demo.svelte +74 -0
- package/dist/components/Library/Loader/Loader.demo.svelte.d.ts +9 -0
- package/dist/components/Library/ScrollView/ScrollView.svelte +12 -2
- package/dist/components/Library/ScrollView/ScrollView.svelte.d.ts +2 -1
- package/dist/components/Library/VStack/VStack.svelte +12 -6
- package/dist/components/Library/VStack/VStack.svelte.d.ts +2 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.js +1 -0
- package/dist/style/layout.d.ts +2 -2
- package/dist/style/layout.js +3 -2
- package/dist/style/loader.d.ts +9 -0
- package/dist/style/loader.js +22 -0
- package/dist/style/surface.d.ts +2 -2
- package/dist/style/surface.js +3 -2
- package/dist/style.css +3 -0
- package/package.json +1 -1
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import Spinner from '../components/Library/Spinner/Spinner.svelte';
|
|
3
|
+
import VStack from '../components/Library/VStack/VStack.svelte';
|
|
4
|
+
|
|
5
|
+
type Props = {
|
|
6
|
+
text: string;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
let { text }: Props = $props();
|
|
10
|
+
</script>
|
|
11
|
+
|
|
12
|
+
<div class="sveltely-loader-overlay" role="status" aria-live="polite" aria-label={text}>
|
|
13
|
+
<VStack align="center" justify="center" gap="var(--sveltely-gap)">
|
|
14
|
+
<Spinner />
|
|
15
|
+
<span class="sveltely-loader-text">{text}</span>
|
|
16
|
+
</VStack>
|
|
17
|
+
</div>
|
|
18
|
+
|
|
19
|
+
<style>
|
|
20
|
+
.sveltely-loader-overlay {
|
|
21
|
+
position: absolute;
|
|
22
|
+
inset: 0;
|
|
23
|
+
z-index: 20;
|
|
24
|
+
display: flex;
|
|
25
|
+
align-items: center;
|
|
26
|
+
justify-content: center;
|
|
27
|
+
border-radius: inherit;
|
|
28
|
+
background: var(--sveltely-background-color, white);
|
|
29
|
+
color: var(--sveltely-primary-color, black);
|
|
30
|
+
padding: var(--sveltely-padding-y, 0.75rem) var(--sveltely-padding-x, 0.75rem);
|
|
31
|
+
pointer-events: auto;
|
|
32
|
+
text-align: center;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.sveltely-loader-text {
|
|
36
|
+
max-width: 100%;
|
|
37
|
+
overflow: hidden;
|
|
38
|
+
color: var(--sveltely-secondary-color, currentColor);
|
|
39
|
+
font-size: calc(var(--sveltely-font-size, 1rem) * 0.875);
|
|
40
|
+
line-height: 1.25;
|
|
41
|
+
text-overflow: ellipsis;
|
|
42
|
+
white-space: nowrap;
|
|
43
|
+
}
|
|
44
|
+
</style>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Action } from 'svelte/action';
|
|
2
|
+
type LoaderTrigger = boolean | PromiseLike<unknown> | null | undefined;
|
|
3
|
+
export type LoaderOptions = LoaderTrigger | [text: string, loading: LoaderTrigger] | {
|
|
4
|
+
text?: string;
|
|
5
|
+
loading?: LoaderTrigger;
|
|
6
|
+
active?: LoaderTrigger;
|
|
7
|
+
promise?: PromiseLike<unknown> | null;
|
|
8
|
+
disabled?: boolean;
|
|
9
|
+
};
|
|
10
|
+
export declare const loader: Action<HTMLElement, LoaderOptions>;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { mount, unmount } from 'svelte';
|
|
2
|
+
import LoaderOverlay from './LoaderOverlay.svelte';
|
|
3
|
+
const DEFAULT_TEXT = 'Loading';
|
|
4
|
+
const isPromiseLike = (value) => typeof value === 'object' &&
|
|
5
|
+
value !== null &&
|
|
6
|
+
'then' in value &&
|
|
7
|
+
typeof value.then === 'function';
|
|
8
|
+
const parseOptions = (value = false) => {
|
|
9
|
+
if (Array.isArray(value)) {
|
|
10
|
+
return {
|
|
11
|
+
text: value[0] || DEFAULT_TEXT,
|
|
12
|
+
loading: value[1],
|
|
13
|
+
disabled: false
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
if (typeof value === 'object' && value !== null && !isPromiseLike(value)) {
|
|
17
|
+
return {
|
|
18
|
+
text: value.text || DEFAULT_TEXT,
|
|
19
|
+
loading: value.loading ?? value.active ?? value.promise ?? false,
|
|
20
|
+
disabled: value.disabled ?? false
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
return {
|
|
24
|
+
text: DEFAULT_TEXT,
|
|
25
|
+
loading: value,
|
|
26
|
+
disabled: false
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
export const loader = (node, initialOptions = false) => {
|
|
30
|
+
if (typeof document === 'undefined') {
|
|
31
|
+
return {
|
|
32
|
+
update() { },
|
|
33
|
+
destroy() { }
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
const originalPosition = node.style.position;
|
|
37
|
+
const originalAriaBusy = node.getAttribute('aria-busy');
|
|
38
|
+
let options = parseOptions(initialOptions);
|
|
39
|
+
let overlay = null;
|
|
40
|
+
let overlayText = '';
|
|
41
|
+
let promiseVersion = 0;
|
|
42
|
+
let appliedPosition = false;
|
|
43
|
+
const ensureHostPosition = () => {
|
|
44
|
+
if (getComputedStyle(node).position !== 'static')
|
|
45
|
+
return;
|
|
46
|
+
node.style.position = 'relative';
|
|
47
|
+
appliedPosition = true;
|
|
48
|
+
};
|
|
49
|
+
const resetHostPosition = () => {
|
|
50
|
+
if (!appliedPosition)
|
|
51
|
+
return;
|
|
52
|
+
if (node.style.position === 'relative') {
|
|
53
|
+
node.style.position = originalPosition;
|
|
54
|
+
}
|
|
55
|
+
appliedPosition = false;
|
|
56
|
+
};
|
|
57
|
+
const show = () => {
|
|
58
|
+
ensureHostPosition();
|
|
59
|
+
node.setAttribute('aria-busy', 'true');
|
|
60
|
+
if (overlay && overlayText === options.text) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
if (overlay) {
|
|
64
|
+
void unmount(overlay);
|
|
65
|
+
}
|
|
66
|
+
overlayText = options.text;
|
|
67
|
+
overlay = mount(LoaderOverlay, {
|
|
68
|
+
target: node,
|
|
69
|
+
props: {
|
|
70
|
+
text: options.text
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
};
|
|
74
|
+
const hide = () => {
|
|
75
|
+
if (overlay) {
|
|
76
|
+
void unmount(overlay);
|
|
77
|
+
overlay = null;
|
|
78
|
+
overlayText = '';
|
|
79
|
+
}
|
|
80
|
+
if (originalAriaBusy === null) {
|
|
81
|
+
node.removeAttribute('aria-busy');
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
node.setAttribute('aria-busy', originalAriaBusy);
|
|
85
|
+
}
|
|
86
|
+
resetHostPosition();
|
|
87
|
+
};
|
|
88
|
+
const render = () => {
|
|
89
|
+
const currentVersion = ++promiseVersion;
|
|
90
|
+
if (options.disabled || !options.loading) {
|
|
91
|
+
hide();
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
show();
|
|
95
|
+
if (!isPromiseLike(options.loading))
|
|
96
|
+
return;
|
|
97
|
+
options.loading.then(() => {
|
|
98
|
+
if (currentVersion === promiseVersion)
|
|
99
|
+
hide();
|
|
100
|
+
}, () => {
|
|
101
|
+
if (currentVersion === promiseVersion)
|
|
102
|
+
hide();
|
|
103
|
+
});
|
|
104
|
+
};
|
|
105
|
+
render();
|
|
106
|
+
return {
|
|
107
|
+
update(nextOptions = false) {
|
|
108
|
+
options = parseOptions(nextOptions);
|
|
109
|
+
render();
|
|
110
|
+
},
|
|
111
|
+
destroy() {
|
|
112
|
+
promiseVersion++;
|
|
113
|
+
hide();
|
|
114
|
+
resetHostPosition();
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
};
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { Snippet } from 'svelte';
|
|
3
|
+
import { loader as loaderAction } from '../../../actions/loader';
|
|
4
|
+
import { extractLoaderProps, resolveLoaderOptions, type LoaderProps } from '../../../style/loader';
|
|
3
5
|
import { extractLayoutProps, layoutStyle, type LayoutProps } from '../../../style/layout';
|
|
4
6
|
import { extractStyleProps, surfaceStyle, type StyleProps } from '../../../style/surface';
|
|
5
7
|
|
|
@@ -10,27 +12,30 @@
|
|
|
10
12
|
autoRows?: number | string;
|
|
11
13
|
dense?: boolean;
|
|
12
14
|
} & LayoutProps &
|
|
13
|
-
StyleProps
|
|
15
|
+
StyleProps &
|
|
16
|
+
LoaderProps;
|
|
14
17
|
|
|
15
|
-
let {
|
|
16
|
-
children,
|
|
17
|
-
columns = 1,
|
|
18
|
-
rows,
|
|
19
|
-
autoRows,
|
|
20
|
-
dense = false,
|
|
21
|
-
...restProps
|
|
22
|
-
}: Props = $props();
|
|
18
|
+
let { children, columns = 1, rows, autoRows, dense = false, ...restProps }: Props = $props();
|
|
23
19
|
|
|
24
|
-
const
|
|
20
|
+
const extractedLoaderProps = $derived.by(() => extractLoaderProps(restProps));
|
|
21
|
+
const loaderProps = $derived(extractedLoaderProps.loaderProps);
|
|
22
|
+
const afterLoaderProps = $derived(extractedLoaderProps.restProps);
|
|
23
|
+
const loaderOptions = $derived.by(() => resolveLoaderOptions(loaderProps));
|
|
24
|
+
const extractedLayoutProps = $derived.by(() => extractLayoutProps(afterLoaderProps));
|
|
25
25
|
const layoutProps = $derived(extractedLayoutProps.layoutProps);
|
|
26
26
|
const afterLayoutProps = $derived(extractedLayoutProps.restProps);
|
|
27
27
|
const extractedStyleProps = $derived.by(() => extractStyleProps(afterLayoutProps));
|
|
28
28
|
const styleProps = $derived(extractedStyleProps.styleProps);
|
|
29
|
+
const props = $derived(extractedStyleProps.restProps);
|
|
29
30
|
const templateColumns = $derived(
|
|
30
31
|
typeof columns === 'number' ? `repeat(${columns}, minmax(0, 1fr))` : columns
|
|
31
32
|
);
|
|
32
33
|
const templateRows = $derived(
|
|
33
|
-
rows === undefined
|
|
34
|
+
rows === undefined
|
|
35
|
+
? undefined
|
|
36
|
+
: typeof rows === 'number'
|
|
37
|
+
? `repeat(${rows}, minmax(0, 1fr))`
|
|
38
|
+
: rows
|
|
34
39
|
);
|
|
35
40
|
const gridAutoRows = $derived(
|
|
36
41
|
autoRows === undefined ? undefined : typeof autoRows === 'number' ? `${autoRows}rem` : autoRows
|
|
@@ -48,7 +53,13 @@
|
|
|
48
53
|
);
|
|
49
54
|
</script>
|
|
50
55
|
|
|
51
|
-
<div
|
|
56
|
+
<div
|
|
57
|
+
class="grid"
|
|
58
|
+
class:grid-dense={dense}
|
|
59
|
+
style={rootStyle}
|
|
60
|
+
{...props}
|
|
61
|
+
use:loaderAction={loaderOptions}
|
|
62
|
+
>
|
|
52
63
|
{#if children}
|
|
53
64
|
{@render children()}
|
|
54
65
|
{/if}
|
|
@@ -62,9 +73,7 @@
|
|
|
62
73
|
align-items: stretch;
|
|
63
74
|
gap: var(--grid-gap, 0px);
|
|
64
75
|
border-radius: var(--grid-border-radius, 0px);
|
|
65
|
-
padding:
|
|
66
|
-
var(--grid-padding-y, 0px)
|
|
67
|
-
var(--grid-padding-x, 0px);
|
|
76
|
+
padding: var(--grid-padding-y, 0px) var(--grid-padding-x, 0px);
|
|
68
77
|
font-size: var(--grid-font-size, inherit);
|
|
69
78
|
}
|
|
70
79
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Snippet } from 'svelte';
|
|
2
|
+
import { type LoaderProps } from '../../../style/loader';
|
|
2
3
|
import { type LayoutProps } from '../../../style/layout';
|
|
3
4
|
import { type StyleProps } from '../../../style/surface';
|
|
4
5
|
type Props = {
|
|
@@ -7,7 +8,7 @@ type Props = {
|
|
|
7
8
|
rows?: number | string;
|
|
8
9
|
autoRows?: number | string;
|
|
9
10
|
dense?: boolean;
|
|
10
|
-
} & LayoutProps & StyleProps;
|
|
11
|
+
} & LayoutProps & StyleProps & LoaderProps;
|
|
11
12
|
declare const Grid: import("svelte").Component<Props, {}, "">;
|
|
12
13
|
type Grid = ReturnType<typeof Grid>;
|
|
13
14
|
export default Grid;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { Snippet } from 'svelte';
|
|
3
|
+
import { loader as loaderAction } from '../../../actions/loader';
|
|
4
|
+
import { extractLoaderProps, resolveLoaderOptions, type LoaderProps } from '../../../style/loader';
|
|
3
5
|
import { extractLayoutProps, layoutStyle, type LayoutProps } from '../../../style/layout';
|
|
4
6
|
import { extractStyleProps, surfaceStyle, type StyleProps } from '../../../style/surface';
|
|
5
7
|
|
|
@@ -11,23 +13,21 @@
|
|
|
11
13
|
rowSpan?: number;
|
|
12
14
|
area?: string;
|
|
13
15
|
} & LayoutProps &
|
|
14
|
-
StyleProps
|
|
16
|
+
StyleProps &
|
|
17
|
+
LoaderProps;
|
|
15
18
|
|
|
16
|
-
let {
|
|
17
|
-
children,
|
|
18
|
-
column,
|
|
19
|
-
row,
|
|
20
|
-
columnSpan,
|
|
21
|
-
rowSpan,
|
|
22
|
-
area,
|
|
23
|
-
...restProps
|
|
24
|
-
}: Props = $props();
|
|
19
|
+
let { children, column, row, columnSpan, rowSpan, area, ...restProps }: Props = $props();
|
|
25
20
|
|
|
26
|
-
const
|
|
21
|
+
const extractedLoaderProps = $derived.by(() => extractLoaderProps(restProps));
|
|
22
|
+
const loaderProps = $derived(extractedLoaderProps.loaderProps);
|
|
23
|
+
const afterLoaderProps = $derived(extractedLoaderProps.restProps);
|
|
24
|
+
const loaderOptions = $derived.by(() => resolveLoaderOptions(loaderProps));
|
|
25
|
+
const extractedLayoutProps = $derived.by(() => extractLayoutProps(afterLoaderProps));
|
|
27
26
|
const layoutProps = $derived(extractedLayoutProps.layoutProps);
|
|
28
27
|
const afterLayoutProps = $derived(extractedLayoutProps.restProps);
|
|
29
28
|
const extractedStyleProps = $derived.by(() => extractStyleProps(afterLayoutProps));
|
|
30
29
|
const styleProps = $derived(extractedStyleProps.styleProps);
|
|
30
|
+
const props = $derived(extractedStyleProps.restProps);
|
|
31
31
|
const rootStyle = $derived.by(() =>
|
|
32
32
|
[
|
|
33
33
|
column !== undefined ? `grid-column: ${column};` : '',
|
|
@@ -35,7 +35,9 @@
|
|
|
35
35
|
column === undefined && columnSpan !== undefined
|
|
36
36
|
? `grid-column: span ${columnSpan} / span ${columnSpan};`
|
|
37
37
|
: '',
|
|
38
|
-
row === undefined && rowSpan !== undefined
|
|
38
|
+
row === undefined && rowSpan !== undefined
|
|
39
|
+
? `grid-row: span ${rowSpan} / span ${rowSpan};`
|
|
40
|
+
: '',
|
|
39
41
|
area !== undefined ? `grid-area: ${area};` : '',
|
|
40
42
|
layoutStyle(layoutProps),
|
|
41
43
|
surfaceStyle(styleProps, 'grid-item')
|
|
@@ -45,7 +47,7 @@
|
|
|
45
47
|
);
|
|
46
48
|
</script>
|
|
47
49
|
|
|
48
|
-
<div class="grid-item" style={rootStyle}>
|
|
50
|
+
<div class="grid-item" style={rootStyle} {...props} use:loaderAction={loaderOptions}>
|
|
49
51
|
{#if children}
|
|
50
52
|
{@render children()}
|
|
51
53
|
{/if}
|
|
@@ -57,9 +59,7 @@
|
|
|
57
59
|
min-height: 0;
|
|
58
60
|
height: 100%;
|
|
59
61
|
border-radius: var(--grid-item-border-radius, 0px);
|
|
60
|
-
padding:
|
|
61
|
-
var(--grid-item-padding-y, 0px)
|
|
62
|
-
var(--grid-item-padding-x, 0px);
|
|
62
|
+
padding: var(--grid-item-padding-y, 0px) var(--grid-item-padding-x, 0px);
|
|
63
63
|
font-size: var(--grid-item-font-size, inherit);
|
|
64
64
|
}
|
|
65
65
|
</style>
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Snippet } from 'svelte';
|
|
2
|
+
import { type LoaderProps } from '../../../style/loader';
|
|
2
3
|
import { type LayoutProps } from '../../../style/layout';
|
|
3
4
|
import { type StyleProps } from '../../../style/surface';
|
|
4
5
|
type Props = {
|
|
@@ -8,7 +9,7 @@ type Props = {
|
|
|
8
9
|
columnSpan?: number;
|
|
9
10
|
rowSpan?: number;
|
|
10
11
|
area?: string;
|
|
11
|
-
} & LayoutProps & StyleProps;
|
|
12
|
+
} & LayoutProps & StyleProps & LoaderProps;
|
|
12
13
|
declare const GridItem: import("svelte").Component<Props, {}, "">;
|
|
13
14
|
type GridItem = ReturnType<typeof GridItem>;
|
|
14
15
|
export default GridItem;
|
|
@@ -1,26 +1,34 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { Snippet } from 'svelte';
|
|
3
|
+
import { loader as loaderAction } from '../../../actions/loader';
|
|
4
|
+
import { extractLoaderProps, resolveLoaderOptions, type LoaderProps } from '../../../style/loader';
|
|
3
5
|
import { extractLayoutProps, layoutStyle, type LayoutProps } from '../../../style/layout';
|
|
4
6
|
import { extractStyleProps, surfaceStyle, type StyleProps } from '../../../style/surface';
|
|
5
7
|
|
|
6
8
|
type Props = {
|
|
7
9
|
children?: Snippet;
|
|
8
10
|
} & LayoutProps &
|
|
9
|
-
StyleProps
|
|
11
|
+
StyleProps &
|
|
12
|
+
LoaderProps;
|
|
10
13
|
|
|
11
14
|
let { children, ...restProps }: Props = $props();
|
|
12
15
|
|
|
13
|
-
const
|
|
16
|
+
const extractedLoaderProps = $derived.by(() => extractLoaderProps(restProps));
|
|
17
|
+
const loaderProps = $derived(extractedLoaderProps.loaderProps);
|
|
18
|
+
const afterLoaderProps = $derived(extractedLoaderProps.restProps);
|
|
19
|
+
const loaderOptions = $derived.by(() => resolveLoaderOptions(loaderProps));
|
|
20
|
+
const extractedLayoutProps = $derived.by(() => extractLayoutProps(afterLoaderProps));
|
|
14
21
|
const layoutProps = $derived(extractedLayoutProps.layoutProps);
|
|
15
22
|
const afterLayoutProps = $derived(extractedLayoutProps.restProps);
|
|
16
23
|
const extractedStyleProps = $derived.by(() => extractStyleProps(afterLayoutProps));
|
|
17
24
|
const styleProps = $derived(extractedStyleProps.styleProps);
|
|
25
|
+
const props = $derived(extractedStyleProps.restProps);
|
|
18
26
|
const rootStyle = $derived.by(() =>
|
|
19
27
|
[layoutStyle(layoutProps), surfaceStyle(styleProps, 'stack')].filter(Boolean).join(' ')
|
|
20
28
|
);
|
|
21
29
|
</script>
|
|
22
30
|
|
|
23
|
-
<div class="hstack" style={rootStyle}>
|
|
31
|
+
<div class="hstack" style={rootStyle} {...props} use:loaderAction={loaderOptions}>
|
|
24
32
|
{#if children}
|
|
25
33
|
{@render children()}
|
|
26
34
|
{/if}
|
|
@@ -34,9 +42,7 @@
|
|
|
34
42
|
flex-direction: row;
|
|
35
43
|
gap: var(--stack-gap, 0px);
|
|
36
44
|
border-radius: var(--stack-border-radius, 0px);
|
|
37
|
-
padding:
|
|
38
|
-
var(--stack-padding-y, 0px)
|
|
39
|
-
var(--stack-padding-x, 0px);
|
|
45
|
+
padding: var(--stack-padding-y, 0px) var(--stack-padding-x, 0px);
|
|
40
46
|
font-size: var(--stack-font-size, inherit);
|
|
41
47
|
--divider-width: 1px;
|
|
42
48
|
--divider-height: auto;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import type { Snippet } from 'svelte';
|
|
2
|
+
import { type LoaderProps } from '../../../style/loader';
|
|
2
3
|
import { type LayoutProps } from '../../../style/layout';
|
|
3
4
|
import { type StyleProps } from '../../../style/surface';
|
|
4
5
|
type Props = {
|
|
5
6
|
children?: Snippet;
|
|
6
|
-
} & LayoutProps & StyleProps;
|
|
7
|
+
} & LayoutProps & StyleProps & LoaderProps;
|
|
7
8
|
declare const HStack: import("svelte").Component<Props, {}, "">;
|
|
8
9
|
type HStack = ReturnType<typeof HStack>;
|
|
9
10
|
export default HStack;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
<script module lang="ts">
|
|
2
|
+
export const demo = {
|
|
3
|
+
name: 'Loader',
|
|
4
|
+
description: 'Overlay loading state for any component.',
|
|
5
|
+
columnSpan: 1,
|
|
6
|
+
rowSpan: 2
|
|
7
|
+
};
|
|
8
|
+
</script>
|
|
9
|
+
|
|
10
|
+
<script lang="ts">
|
|
11
|
+
import Button from '../Button';
|
|
12
|
+
import ScrollView from '../ScrollView';
|
|
13
|
+
|
|
14
|
+
let pending = $state<Promise<void> | null>(null);
|
|
15
|
+
|
|
16
|
+
const startLoading = () => {
|
|
17
|
+
const next = new Promise<void>((resolve) => {
|
|
18
|
+
setTimeout(resolve, 1600);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
pending = next;
|
|
22
|
+
next.finally(() => {
|
|
23
|
+
if (pending === next) {
|
|
24
|
+
pending = null;
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
};
|
|
28
|
+
</script>
|
|
29
|
+
|
|
30
|
+
<ScrollView
|
|
31
|
+
background="color-mix(in oklab, var(--sveltely-background-color) 94%, var(--sveltely-primary-color))"
|
|
32
|
+
borderRadius="var(--sveltely-border-radius)"
|
|
33
|
+
scrollGradient={false}
|
|
34
|
+
loader={{ text: 'Loading preview...', promise: pending }}
|
|
35
|
+
>
|
|
36
|
+
<div class="loader-demo">
|
|
37
|
+
<div class="loader-demo-copy">
|
|
38
|
+
<strong>Preview panel</strong>
|
|
39
|
+
<span>Click the button to cover this ScrollView component with the loader overlay.</span>
|
|
40
|
+
</div>
|
|
41
|
+
<Button label="Show loader" onclick={startLoading} disabled={pending !== null} />
|
|
42
|
+
</div>
|
|
43
|
+
</ScrollView>
|
|
44
|
+
|
|
45
|
+
<style>
|
|
46
|
+
.loader-demo {
|
|
47
|
+
display: flex;
|
|
48
|
+
min-height: 8rem;
|
|
49
|
+
width: 100%;
|
|
50
|
+
flex-direction: column;
|
|
51
|
+
align-items: flex-start;
|
|
52
|
+
justify-content: space-between;
|
|
53
|
+
gap: var(--sveltely-gap);
|
|
54
|
+
padding: var(--sveltely-padding-y) var(--sveltely-padding-x);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.loader-demo-copy {
|
|
58
|
+
display: flex;
|
|
59
|
+
min-width: 0;
|
|
60
|
+
flex-direction: column;
|
|
61
|
+
gap: calc(var(--sveltely-gap) * 0.5);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.loader-demo-copy strong {
|
|
65
|
+
font-size: var(--sveltely-font-size);
|
|
66
|
+
line-height: 1.25;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.loader-demo-copy span {
|
|
70
|
+
color: var(--sveltely-secondary-color);
|
|
71
|
+
font-size: calc(var(--sveltely-font-size) * 0.875);
|
|
72
|
+
line-height: 1.3;
|
|
73
|
+
}
|
|
74
|
+
</style>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare const demo: {
|
|
2
|
+
name: string;
|
|
3
|
+
description: string;
|
|
4
|
+
columnSpan: number;
|
|
5
|
+
rowSpan: number;
|
|
6
|
+
};
|
|
7
|
+
declare const Loader: import("svelte").Component<Record<string, never>, {}, "">;
|
|
8
|
+
type Loader = ReturnType<typeof Loader>;
|
|
9
|
+
export default Loader;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { tick } from 'svelte';
|
|
3
3
|
import type { Snippet } from 'svelte';
|
|
4
|
+
import { loader as loaderAction } from '../../../actions/loader';
|
|
5
|
+
import { extractLoaderProps, resolveLoaderOptions, type LoaderProps } from '../../../style/loader';
|
|
4
6
|
import { extractLayoutProps, layoutStyle, type LayoutProps } from '../../../style/layout';
|
|
5
7
|
import { extractStyleProps, surfaceStyle, type StyleProps } from '../../../style/surface';
|
|
6
8
|
import type { ScrollAxis } from '../../../style/scroll';
|
|
@@ -40,7 +42,8 @@
|
|
|
40
42
|
scrollGradient?: boolean;
|
|
41
43
|
scrollGradientSize?: number | string;
|
|
42
44
|
} & LayoutProps &
|
|
43
|
-
StyleProps
|
|
45
|
+
StyleProps &
|
|
46
|
+
LoaderProps;
|
|
44
47
|
|
|
45
48
|
let {
|
|
46
49
|
children,
|
|
@@ -53,11 +56,16 @@
|
|
|
53
56
|
...restProps
|
|
54
57
|
}: Props = $props();
|
|
55
58
|
|
|
56
|
-
const
|
|
59
|
+
const extractedLoaderProps = $derived.by(() => extractLoaderProps(restProps));
|
|
60
|
+
const loaderProps = $derived(extractedLoaderProps.loaderProps);
|
|
61
|
+
const afterLoaderProps = $derived(extractedLoaderProps.restProps);
|
|
62
|
+
const loaderOptions = $derived.by(() => resolveLoaderOptions(loaderProps));
|
|
63
|
+
const extractedLayoutProps = $derived.by(() => extractLayoutProps(afterLoaderProps));
|
|
57
64
|
const layoutProps = $derived(extractedLayoutProps.layoutProps);
|
|
58
65
|
const afterLayoutProps = $derived(extractedLayoutProps.restProps);
|
|
59
66
|
const extractedStyleProps = $derived.by(() => extractStyleProps(afterLayoutProps));
|
|
60
67
|
const styleProps = $derived(extractedStyleProps.styleProps);
|
|
68
|
+
const props = $derived(extractedStyleProps.restProps);
|
|
61
69
|
const viewportStyle = $derived.by(() => surfaceStyle(styleProps, 'scroll-view'));
|
|
62
70
|
const contentStyle = $derived.by(() => surfaceStyle(contentStyles, 'scroll-view-content'));
|
|
63
71
|
const scrollGradientStyle = $derived(
|
|
@@ -141,6 +149,8 @@
|
|
|
141
149
|
class:scroll-view-can-scroll-up={canScrollToTop}
|
|
142
150
|
class:scroll-view-can-scroll-down={canScrollToBottom}
|
|
143
151
|
style={rootStyle}
|
|
152
|
+
{...props}
|
|
153
|
+
use:loaderAction={loaderOptions}
|
|
144
154
|
onscroll={handleScroll}
|
|
145
155
|
onwheel={handleWheel}
|
|
146
156
|
>
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Snippet } from 'svelte';
|
|
2
|
+
import { type LoaderProps } from '../../../style/loader';
|
|
2
3
|
import { type LayoutProps } from '../../../style/layout';
|
|
3
4
|
import { type StyleProps } from '../../../style/surface';
|
|
4
5
|
import type { ScrollAxis } from '../../../style/scroll';
|
|
@@ -35,7 +36,7 @@ type Props = {
|
|
|
35
36
|
onScroll?: (geometry: ScrollGeometry) => void;
|
|
36
37
|
scrollGradient?: boolean;
|
|
37
38
|
scrollGradientSize?: number | string;
|
|
38
|
-
} & LayoutProps & StyleProps;
|
|
39
|
+
} & LayoutProps & StyleProps & LoaderProps;
|
|
39
40
|
declare const ScrollView: import("svelte").Component<Props, {}, "viewport">;
|
|
40
41
|
type ScrollView = ReturnType<typeof ScrollView>;
|
|
41
42
|
export default ScrollView;
|
|
@@ -1,26 +1,34 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { Snippet } from 'svelte';
|
|
3
|
+
import { loader as loaderAction } from '../../../actions/loader';
|
|
4
|
+
import { extractLoaderProps, resolveLoaderOptions, type LoaderProps } from '../../../style/loader';
|
|
3
5
|
import { extractLayoutProps, layoutStyle, type LayoutProps } from '../../../style/layout';
|
|
4
6
|
import { extractStyleProps, surfaceStyle, type StyleProps } from '../../../style/surface';
|
|
5
7
|
|
|
6
8
|
type Props = {
|
|
7
9
|
children?: Snippet;
|
|
8
10
|
} & LayoutProps &
|
|
9
|
-
StyleProps
|
|
11
|
+
StyleProps &
|
|
12
|
+
LoaderProps;
|
|
10
13
|
|
|
11
14
|
let { children, ...restProps }: Props = $props();
|
|
12
15
|
|
|
13
|
-
const
|
|
16
|
+
const extractedLoaderProps = $derived.by(() => extractLoaderProps(restProps));
|
|
17
|
+
const loaderProps = $derived(extractedLoaderProps.loaderProps);
|
|
18
|
+
const afterLoaderProps = $derived(extractedLoaderProps.restProps);
|
|
19
|
+
const loaderOptions = $derived.by(() => resolveLoaderOptions(loaderProps));
|
|
20
|
+
const extractedLayoutProps = $derived.by(() => extractLayoutProps(afterLoaderProps));
|
|
14
21
|
const layoutProps = $derived(extractedLayoutProps.layoutProps);
|
|
15
22
|
const afterLayoutProps = $derived(extractedLayoutProps.restProps);
|
|
16
23
|
const extractedStyleProps = $derived.by(() => extractStyleProps(afterLayoutProps));
|
|
17
24
|
const styleProps = $derived(extractedStyleProps.styleProps);
|
|
25
|
+
const props = $derived(extractedStyleProps.restProps);
|
|
18
26
|
const rootStyle = $derived.by(() =>
|
|
19
27
|
[layoutStyle(layoutProps), surfaceStyle(styleProps, 'stack')].filter(Boolean).join(' ')
|
|
20
28
|
);
|
|
21
29
|
</script>
|
|
22
30
|
|
|
23
|
-
<div class="vstack" style={rootStyle}>
|
|
31
|
+
<div class="vstack" style={rootStyle} {...props} use:loaderAction={loaderOptions}>
|
|
24
32
|
{#if children}
|
|
25
33
|
{@render children()}
|
|
26
34
|
{/if}
|
|
@@ -34,9 +42,7 @@
|
|
|
34
42
|
flex-direction: column;
|
|
35
43
|
gap: var(--stack-gap, 0px);
|
|
36
44
|
border-radius: var(--stack-border-radius, 0px);
|
|
37
|
-
padding:
|
|
38
|
-
var(--stack-padding-y, 0px)
|
|
39
|
-
var(--stack-padding-x, 0px);
|
|
45
|
+
padding: var(--stack-padding-y, 0px) var(--stack-padding-x, 0px);
|
|
40
46
|
font-size: var(--stack-font-size, inherit);
|
|
41
47
|
--divider-width: 100%;
|
|
42
48
|
--divider-height: 1px;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import type { Snippet } from 'svelte';
|
|
2
|
+
import { type LoaderProps } from '../../../style/loader';
|
|
2
3
|
import { type LayoutProps } from '../../../style/layout';
|
|
3
4
|
import { type StyleProps } from '../../../style/surface';
|
|
4
5
|
type Props = {
|
|
5
6
|
children?: Snippet;
|
|
6
|
-
} & LayoutProps & StyleProps;
|
|
7
|
+
} & LayoutProps & StyleProps & LoaderProps;
|
|
7
8
|
declare const VStack: import("svelte").Component<Props, {}, "">;
|
|
8
9
|
type VStack = ReturnType<typeof VStack>;
|
|
9
10
|
export default VStack;
|
package/dist/index.d.ts
CHANGED
|
@@ -2,6 +2,9 @@ export { motion, hover } from './actions/motion';
|
|
|
2
2
|
export { portalHost, portalContent } from './actions/portal';
|
|
3
3
|
export { tooltip } from './actions/tooltip';
|
|
4
4
|
export type { TooltipOptions } from './actions/tooltip';
|
|
5
|
+
export { loader } from './actions/loader';
|
|
6
|
+
export type { LoaderOptions } from './actions/loader';
|
|
7
|
+
export type { LoaderProps } from './style/loader';
|
|
5
8
|
export { LayoutAlignment, LayoutJustification, LayoutSize } from './style/layout';
|
|
6
9
|
export type { LayoutAlignmentValue, LayoutJustificationValue, LayoutProps, LayoutSizeValue } from './style/layout';
|
|
7
10
|
export { LabelOrientation } from './style/label';
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { motion, hover } from './actions/motion';
|
|
2
2
|
export { portalHost, portalContent } from './actions/portal';
|
|
3
3
|
export { tooltip } from './actions/tooltip';
|
|
4
|
+
export { loader } from './actions/loader';
|
|
4
5
|
export { LayoutAlignment, LayoutJustification, LayoutSize } from './style/layout';
|
|
5
6
|
export { LabelOrientation } from './style/label';
|
|
6
7
|
export { ImageFit, ImageLoading } from './style/media';
|
package/dist/style/layout.d.ts
CHANGED
|
@@ -39,9 +39,9 @@ export type LayoutProps = {
|
|
|
39
39
|
align?: LayoutAlignment;
|
|
40
40
|
justify?: LayoutJustification;
|
|
41
41
|
};
|
|
42
|
-
export declare const extractLayoutProps: <T extends Record<
|
|
42
|
+
export declare const extractLayoutProps: <T extends Record<PropertyKey, unknown>>(props: T) => {
|
|
43
43
|
layoutProps: Partial<LayoutProps>;
|
|
44
|
-
restProps: Record<
|
|
44
|
+
restProps: Record<PropertyKey, unknown>;
|
|
45
45
|
};
|
|
46
46
|
export declare const layoutStyle: (styles?: LayoutProps) => string;
|
|
47
47
|
export {};
|
package/dist/style/layout.js
CHANGED
|
@@ -69,8 +69,9 @@ const justifyValues = {
|
|
|
69
69
|
export const extractLayoutProps = (props) => {
|
|
70
70
|
const layoutProps = {};
|
|
71
71
|
const restProps = {};
|
|
72
|
-
for (const
|
|
73
|
-
|
|
72
|
+
for (const key of Reflect.ownKeys(props)) {
|
|
73
|
+
const value = props[key];
|
|
74
|
+
if (typeof key === 'string' && LAYOUT_PROP_KEYS.has(key)) {
|
|
74
75
|
layoutProps[key] = value;
|
|
75
76
|
continue;
|
|
76
77
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { LoaderOptions } from '../actions/loader';
|
|
2
|
+
export type LoaderProps = {
|
|
3
|
+
loader?: LoaderOptions;
|
|
4
|
+
};
|
|
5
|
+
export declare const extractLoaderProps: <T extends Record<PropertyKey, unknown>>(props: T) => {
|
|
6
|
+
loaderProps: LoaderProps;
|
|
7
|
+
restProps: Record<PropertyKey, unknown>;
|
|
8
|
+
};
|
|
9
|
+
export declare const resolveLoaderOptions: (props?: LoaderProps) => LoaderOptions;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
const LOADER_PROP_KEYS = new Set(['loader']);
|
|
2
|
+
export const extractLoaderProps = (props) => {
|
|
3
|
+
const loaderProps = {};
|
|
4
|
+
const restProps = {};
|
|
5
|
+
for (const key of Reflect.ownKeys(props)) {
|
|
6
|
+
const value = props[key];
|
|
7
|
+
if (typeof key === 'string' && LOADER_PROP_KEYS.has(key)) {
|
|
8
|
+
loaderProps[key] = value;
|
|
9
|
+
continue;
|
|
10
|
+
}
|
|
11
|
+
restProps[key] = value;
|
|
12
|
+
}
|
|
13
|
+
return {
|
|
14
|
+
loaderProps,
|
|
15
|
+
restProps
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
export const resolveLoaderOptions = (props) => {
|
|
19
|
+
if (!props)
|
|
20
|
+
return false;
|
|
21
|
+
return props.loader ?? false;
|
|
22
|
+
};
|
package/dist/style/surface.d.ts
CHANGED
|
@@ -10,8 +10,8 @@ export type StyleProps = {
|
|
|
10
10
|
color?: string;
|
|
11
11
|
};
|
|
12
12
|
export type SurfaceStyles = StyleProps;
|
|
13
|
-
export declare const extractStyleProps: <T extends Record<
|
|
13
|
+
export declare const extractStyleProps: <T extends Record<PropertyKey, unknown>>(props: T) => {
|
|
14
14
|
styleProps: Partial<StyleProps>;
|
|
15
|
-
restProps: Record<
|
|
15
|
+
restProps: Record<PropertyKey, unknown>;
|
|
16
16
|
};
|
|
17
17
|
export declare const surfaceStyle: (styles?: SurfaceStyles, prefix?: string) => string;
|
package/dist/style/surface.js
CHANGED
|
@@ -19,8 +19,9 @@ const pushVar = (declarations, name, value) => {
|
|
|
19
19
|
export const extractStyleProps = (props) => {
|
|
20
20
|
const styleProps = {};
|
|
21
21
|
const restProps = {};
|
|
22
|
-
for (const
|
|
23
|
-
|
|
22
|
+
for (const key of Reflect.ownKeys(props)) {
|
|
23
|
+
const value = props[key];
|
|
24
|
+
if (typeof key === 'string' && STYLE_PROP_KEYS.has(key)) {
|
|
24
25
|
styleProps[key] = value;
|
|
25
26
|
continue;
|
|
26
27
|
}
|
package/dist/style.css
CHANGED