@marianmeres/stuic 1.2.0 → 1.4.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.
- package/dist/components/HoverExpandableWidth/HoverExpandableWidth.svelte +102 -0
- package/dist/components/HoverExpandableWidth/HoverExpandableWidth.svelte.d.ts +27 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +3 -1
- package/dist/utils/window-size.d.ts +23 -0
- package/dist/utils/window-size.js +34 -0
- package/package.json +1 -1
- package/dist/components/Expandable/Expandable.svelte +0 -54
- package/dist/components/Expandable/Expandable.svelte.d.ts +0 -27
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
<script>import { createClog } from "@marianmeres/clog";
|
|
2
|
+
import { createEventDispatcher } from "svelte";
|
|
3
|
+
import { get } from "svelte/store";
|
|
4
|
+
import { prefersReducedMotionStore } from "../../utils/prefers-reduced-motion.js";
|
|
5
|
+
import { windowSize } from "../../utils/window-size.js";
|
|
6
|
+
import { twMerge } from "tailwind-merge";
|
|
7
|
+
const clog = createClog("HoverExpandableWidth");
|
|
8
|
+
const dispatch = createEventDispatcher();
|
|
9
|
+
export let shadowOpacity = 0.8;
|
|
10
|
+
export let transitionDuration = 150;
|
|
11
|
+
export let targetWidth = 300;
|
|
12
|
+
let _class = "";
|
|
13
|
+
export { _class as class };
|
|
14
|
+
$:
|
|
15
|
+
_isExpanded = false;
|
|
16
|
+
let _isShrinking = false;
|
|
17
|
+
let _isExpanding = false;
|
|
18
|
+
let _todo;
|
|
19
|
+
let el;
|
|
20
|
+
const _maybeTodo = () => {
|
|
21
|
+
if (typeof _todo === "function")
|
|
22
|
+
_todo();
|
|
23
|
+
_todo = null;
|
|
24
|
+
};
|
|
25
|
+
const _expand = () => {
|
|
26
|
+
_todo = _expand;
|
|
27
|
+
if (_isExpanding || _isShrinking || _isExpanded)
|
|
28
|
+
return;
|
|
29
|
+
_isExpanded = true;
|
|
30
|
+
_isExpanding = true;
|
|
31
|
+
const box = el.getBoundingClientRect();
|
|
32
|
+
const w = get(windowSize);
|
|
33
|
+
const pos = {
|
|
34
|
+
top: box.top,
|
|
35
|
+
bottom: w.height - box.bottom,
|
|
36
|
+
left: box.left,
|
|
37
|
+
right: w.width - box.right
|
|
38
|
+
};
|
|
39
|
+
el.style.boxShadow = `8px 0 16px -8px rgb(0 0 0 / ${shadowOpacity})`;
|
|
40
|
+
el.style.zIndex = `1`;
|
|
41
|
+
el.style.top = `${pos.top}px`;
|
|
42
|
+
el.style.right = `${pos.right}px`;
|
|
43
|
+
el.style.bottom = `${pos.bottom}px`;
|
|
44
|
+
el.style.left = `${pos.left}px`;
|
|
45
|
+
el.style.width = "auto";
|
|
46
|
+
el.style.height = "auto";
|
|
47
|
+
setTimeout(
|
|
48
|
+
() => {
|
|
49
|
+
_isExpanding = false;
|
|
50
|
+
_maybeTodo();
|
|
51
|
+
},
|
|
52
|
+
transitionDuration + 1e3 / 60 * 3
|
|
53
|
+
// 3 x raf
|
|
54
|
+
);
|
|
55
|
+
requestAnimationFrame(() => {
|
|
56
|
+
el.style.position = `fixed`;
|
|
57
|
+
requestAnimationFrame(() => {
|
|
58
|
+
el.style.width = `${box.width}px`;
|
|
59
|
+
requestAnimationFrame(() => {
|
|
60
|
+
!$prefersReducedMotionStore && (el.style.transitionProperty = "all");
|
|
61
|
+
el.style.width = `${targetWidth}px`;
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
};
|
|
66
|
+
const _shrink = () => {
|
|
67
|
+
_todo = _shrink;
|
|
68
|
+
if (_isExpanding || _isShrinking || !_isExpanded)
|
|
69
|
+
return;
|
|
70
|
+
_isExpanded = false;
|
|
71
|
+
_isShrinking = true;
|
|
72
|
+
el.style.position = `static`;
|
|
73
|
+
el.style.zIndex = `auto`;
|
|
74
|
+
el.style.top = "auto";
|
|
75
|
+
el.style.right = "auto";
|
|
76
|
+
el.style.bottom = "auto";
|
|
77
|
+
el.style.left = "auto";
|
|
78
|
+
el.style.width = "100%";
|
|
79
|
+
el.style.height = "100%";
|
|
80
|
+
el.style.boxShadow = "none";
|
|
81
|
+
setTimeout(() => {
|
|
82
|
+
_isShrinking = false;
|
|
83
|
+
el.style.transitionProperty = "none";
|
|
84
|
+
_maybeTodo();
|
|
85
|
+
}, transitionDuration);
|
|
86
|
+
};
|
|
87
|
+
$:
|
|
88
|
+
dispatch("change", _isExpanded);
|
|
89
|
+
</script>
|
|
90
|
+
|
|
91
|
+
<!-- svelte-ignore a11y-click-events-have-key-events a11y-no-static-element-interactions -->
|
|
92
|
+
<div
|
|
93
|
+
bind:this={el}
|
|
94
|
+
on:mouseenter={_expand}
|
|
95
|
+
on:mouseleave={_shrink}
|
|
96
|
+
on:click
|
|
97
|
+
aria-expanded={_isExpanded}
|
|
98
|
+
class={twMerge(`${_class}`)}
|
|
99
|
+
style="width: 100%; height: 100%; transition-duration: {transitionDuration}ms;"
|
|
100
|
+
>
|
|
101
|
+
<slot isExpanded={_isExpanded} inTransition={_isExpanding || _isShrinking} />
|
|
102
|
+
</div>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { SvelteComponent } from "svelte";
|
|
2
|
+
declare const __propDef: {
|
|
3
|
+
props: {
|
|
4
|
+
shadowOpacity?: number | undefined;
|
|
5
|
+
transitionDuration?: number | undefined;
|
|
6
|
+
targetWidth?: number | undefined;
|
|
7
|
+
class?: string | undefined;
|
|
8
|
+
};
|
|
9
|
+
events: {
|
|
10
|
+
click: MouseEvent;
|
|
11
|
+
change: CustomEvent<any>;
|
|
12
|
+
} & {
|
|
13
|
+
[evt: string]: CustomEvent<any>;
|
|
14
|
+
};
|
|
15
|
+
slots: {
|
|
16
|
+
default: {
|
|
17
|
+
isExpanded: boolean;
|
|
18
|
+
inTransition: boolean;
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
export type HoverExpandableWidthProps = typeof __propDef.props;
|
|
23
|
+
export type HoverExpandableWidthEvents = typeof __propDef.events;
|
|
24
|
+
export type HoverExpandableWidthSlots = typeof __propDef.slots;
|
|
25
|
+
export default class HoverExpandableWidth extends SvelteComponent<HoverExpandableWidthProps, HoverExpandableWidthEvents, HoverExpandableWidthSlots> {
|
|
26
|
+
}
|
|
27
|
+
export {};
|
package/dist/index.d.ts
CHANGED
|
@@ -5,5 +5,6 @@ export { default as SystemAwareColorScheme } from './components/ColorScheme/Syst
|
|
|
5
5
|
export { default as LocalColorScheme } from './components/ColorScheme/LocalColorScheme.svelte';
|
|
6
6
|
export { ColorScheme } from './components/ColorScheme/color-scheme.js';
|
|
7
7
|
export { default as Drawer, createDrawerStore } from './components/Drawer/Drawer.svelte';
|
|
8
|
-
export { default as
|
|
8
|
+
export { default as HoverExpandableWidth } from './components/HoverExpandableWidth/HoverExpandableWidth.svelte';
|
|
9
9
|
export { default as X } from './components/X/X.svelte';
|
|
10
|
+
export { windowSize, breakpoint } from './utils/window-size.js';
|
package/dist/index.js
CHANGED
|
@@ -12,6 +12,8 @@ export { ColorScheme } from './components/ColorScheme/color-scheme.js';
|
|
|
12
12
|
//
|
|
13
13
|
export { default as Drawer, createDrawerStore } from './components/Drawer/Drawer.svelte';
|
|
14
14
|
//
|
|
15
|
-
export { default as
|
|
15
|
+
export { default as HoverExpandableWidth } from './components/HoverExpandableWidth/HoverExpandableWidth.svelte';
|
|
16
16
|
//
|
|
17
17
|
export { default as X } from './components/X/X.svelte';
|
|
18
|
+
//
|
|
19
|
+
export { windowSize, breakpoint } from './utils/window-size.js';
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/// <reference types="svelte" />
|
|
2
|
+
export declare const windowSize: {
|
|
3
|
+
touch: () => void;
|
|
4
|
+
subscribe(this: void, run: import("svelte/store").Subscriber<{
|
|
5
|
+
width: number;
|
|
6
|
+
height: number;
|
|
7
|
+
scale: number;
|
|
8
|
+
}>, invalidate?: import("svelte/store").Invalidator<{
|
|
9
|
+
width: number;
|
|
10
|
+
height: number;
|
|
11
|
+
scale: number;
|
|
12
|
+
}> | undefined): import("svelte/store").Unsubscriber;
|
|
13
|
+
};
|
|
14
|
+
interface Breakpoint {
|
|
15
|
+
__current__: null | string;
|
|
16
|
+
sm: boolean;
|
|
17
|
+
md: boolean;
|
|
18
|
+
lg: boolean;
|
|
19
|
+
xl: boolean;
|
|
20
|
+
'2xl': boolean;
|
|
21
|
+
}
|
|
22
|
+
export declare const breakpoint: import("svelte/store").Readable<Breakpoint>;
|
|
23
|
+
export {};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { derived, writable } from 'svelte/store';
|
|
2
|
+
const getWindowSize = () => {
|
|
3
|
+
const { width, height, scale } = window?.visualViewport || {
|
|
4
|
+
width: 0,
|
|
5
|
+
height: 0,
|
|
6
|
+
scale: 1,
|
|
7
|
+
};
|
|
8
|
+
return { width, height, scale };
|
|
9
|
+
};
|
|
10
|
+
let _trigger = writable(0);
|
|
11
|
+
export const windowSize = {
|
|
12
|
+
...derived([_trigger], ([_]) => getWindowSize()),
|
|
13
|
+
touch: () => _trigger.set(Date.now()),
|
|
14
|
+
};
|
|
15
|
+
// init now!
|
|
16
|
+
windowSize.touch();
|
|
17
|
+
// intentionally not debounced
|
|
18
|
+
window?.visualViewport?.addEventListener('resize', windowSize.touch);
|
|
19
|
+
window?.visualViewport?.addEventListener('scroll', windowSize.touch);
|
|
20
|
+
export const breakpoint = derived([windowSize], ([{ width: w }]) => {
|
|
21
|
+
const list = [
|
|
22
|
+
['sm', 640],
|
|
23
|
+
['md', 768],
|
|
24
|
+
['lg', 1024],
|
|
25
|
+
['xl', 1280],
|
|
26
|
+
['2xl', 1536],
|
|
27
|
+
];
|
|
28
|
+
// return list.reduce<string | null>((m, [k, v]) => (w && w >= v ? k : m), null);
|
|
29
|
+
return list.reduce((m, [k, v]) => {
|
|
30
|
+
const flag = w && w >= v;
|
|
31
|
+
m = { ...m, [k]: flag, __current__: flag ? k : m.__current__ };
|
|
32
|
+
return m;
|
|
33
|
+
}, { __current__: null, sm: false, md: false, lg: false, xl: false, '2xl': false });
|
|
34
|
+
});
|
package/package.json
CHANGED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
<script>import { createEventDispatcher } from "svelte";
|
|
2
|
-
import { twMerge } from "tailwind-merge";
|
|
3
|
-
import { prefersReducedMotionStore } from "../../utils/prefers-reduced-motion.js";
|
|
4
|
-
const dispatch = createEventDispatcher();
|
|
5
|
-
export let position = "left";
|
|
6
|
-
export let expandsOn = "hover";
|
|
7
|
-
export let force = false;
|
|
8
|
-
let _class = "";
|
|
9
|
-
export { _class as class };
|
|
10
|
-
export let expandedClass = "";
|
|
11
|
-
const _presetsCls = {
|
|
12
|
-
left: `left-0`,
|
|
13
|
-
right: `right-0`,
|
|
14
|
-
top: `top-0`,
|
|
15
|
-
bottom: `bottom-0`
|
|
16
|
-
};
|
|
17
|
-
$:
|
|
18
|
-
_isExpanded = !!force;
|
|
19
|
-
const click = "click";
|
|
20
|
-
const hover = "hover";
|
|
21
|
-
const both = "both";
|
|
22
|
-
const _onHover = (flag) => {
|
|
23
|
-
if (force)
|
|
24
|
-
return _isExpanded = true;
|
|
25
|
-
if ([hover, both].includes(expandsOn))
|
|
26
|
-
_isExpanded = !!flag;
|
|
27
|
-
};
|
|
28
|
-
const _onClick = (e) => {
|
|
29
|
-
if (force)
|
|
30
|
-
return _isExpanded = true;
|
|
31
|
-
if ([click, both].includes(expandsOn))
|
|
32
|
-
_isExpanded = !_isExpanded;
|
|
33
|
-
};
|
|
34
|
-
$:
|
|
35
|
-
dispatch("expanded", _isExpanded);
|
|
36
|
-
</script>
|
|
37
|
-
|
|
38
|
-
<!-- svelte-ignore a11y-click-events-have-key-events a11y-no-static-element-interactions -->
|
|
39
|
-
<div
|
|
40
|
-
on:mouseenter={() => _onHover(true)}
|
|
41
|
-
on:mouseleave={() => _onHover(false)}
|
|
42
|
-
on:click={_onClick}
|
|
43
|
-
on:click
|
|
44
|
-
aria-expanded={_isExpanded}
|
|
45
|
-
class={twMerge(`
|
|
46
|
-
absolute w-full h-full flex flex-col
|
|
47
|
-
${$prefersReducedMotionStore ? '' : 'transition-all'}
|
|
48
|
-
${_presetsCls[position] || ''}
|
|
49
|
-
${_class}
|
|
50
|
-
${_isExpanded ? expandedClass : ''}
|
|
51
|
-
`)}
|
|
52
|
-
>
|
|
53
|
-
<slot isExpanded={_isExpanded} />
|
|
54
|
-
</div>
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { SvelteComponent } from "svelte";
|
|
2
|
-
declare const __propDef: {
|
|
3
|
-
props: {
|
|
4
|
-
position?: "left" | "top" | "right" | "bottom" | undefined;
|
|
5
|
-
expandsOn?: "click" | "hover" | "both" | undefined;
|
|
6
|
-
force?: boolean | undefined;
|
|
7
|
-
class?: string | undefined;
|
|
8
|
-
expandedClass?: string | undefined;
|
|
9
|
-
};
|
|
10
|
-
events: {
|
|
11
|
-
click: MouseEvent;
|
|
12
|
-
expanded: CustomEvent<any>;
|
|
13
|
-
} & {
|
|
14
|
-
[evt: string]: CustomEvent<any>;
|
|
15
|
-
};
|
|
16
|
-
slots: {
|
|
17
|
-
default: {
|
|
18
|
-
isExpanded: boolean;
|
|
19
|
-
};
|
|
20
|
-
};
|
|
21
|
-
};
|
|
22
|
-
export type ExpandableProps = typeof __propDef.props;
|
|
23
|
-
export type ExpandableEvents = typeof __propDef.events;
|
|
24
|
-
export type ExpandableSlots = typeof __propDef.slots;
|
|
25
|
-
export default class Expandable extends SvelteComponent<ExpandableProps, ExpandableEvents, ExpandableSlots> {
|
|
26
|
-
}
|
|
27
|
-
export {};
|