@axel669/zephyr 0.4.7 → 0.5.4
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/package.json +12 -10
- package/readme.md +8 -1
- package/src/async/button.svelte +17 -13
- package/src/async/suspend.svelte +38 -0
- package/src/changed.js +10 -0
- package/src/composed/data-table/th.svelte +2 -2
- package/src/composed/data-table.svelte +154 -180
- package/src/composed/entry-button.svelte +13 -16
- package/src/control/button.svelte +26 -22
- package/src/control/input.svelte +52 -50
- package/src/control/label.svelte +28 -24
- package/src/control/link.svelte +36 -30
- package/src/control/radio-group.svelte +13 -10
- package/src/control/select.svelte +21 -16
- package/src/control/tabs.svelte +18 -14
- package/src/control/toggle.svelte +33 -22
- package/src/custom-macros.js +9 -0
- package/src/data-display/avatar.svelte +12 -11
- package/src/data-display/badge.svelte +9 -7
- package/src/data-display/chip.svelte +27 -17
- package/src/data-display/details.svelte +22 -14
- package/src/data-display/popover.svelte +12 -9
- package/src/data-display/progress.svelte +17 -13
- package/src/data-display/table.svelte +29 -17
- package/src/data-display/tooltip.svelte +11 -9
- package/src/dialogs/alert.svelte +18 -12
- package/src/dialogs/confirm.svelte +22 -16
- package/src/{hash.js → hash.svelte.js} +9 -0
- package/src/{index.mjs → index.js} +10 -10
- package/src/{composed/element-toast.svelte → info/element-toaster.svelte} +41 -27
- package/src/info/icon.svelte +4 -4
- package/src/info/titlebar.svelte +20 -14
- package/src/info/toast.svelte +35 -0
- package/src/info/toaster/message.svelte +42 -0
- package/src/info/toaster.svelte +64 -6
- package/src/layout/dialog.svelte +10 -12
- package/src/layout/drawer.svelte +45 -18
- package/src/layout/flex.svelte +13 -11
- package/src/layout/grid.svelte +17 -15
- package/src/layout/modal.svelte +34 -26
- package/src/layout/paper.svelte +31 -33
- package/src/layout/screen.svelte +13 -9
- package/src/props.js +24 -0
- package/src/routing/route.svelte +29 -16
- package/src/routing/{routing.js → routing.svelte.js} +10 -1
- package/src/routing/title.svelte +8 -6
- package/src/spinner/circle-spinner.svelte +10 -8
- package/src/spinner/hexagon-spinner.svelte +10 -8
- package/src/text.svelte +6 -10
- package/src/wind.js +4 -0
- package/src/{wsx.mjs → wsx.js} +1 -1
- package/src/async/load-zone.svelte +0 -22
- package/src/composed/toast/message.svelte +0 -33
- package/src/composed/toast.svelte +0 -70
- package/src/info/notification.svelte +0 -28
- package/src/inline-dialog.svelte +0 -23
- /package/src/{handler$.mjs → handler$.js} +0 -0
- /package/src/{variant.mjs → variant.js} +0 -0
package/src/info/toaster.svelte
CHANGED
|
@@ -1,14 +1,72 @@
|
|
|
1
|
+
<script module>
|
|
2
|
+
const genID = () => `${Date.now()}:${Math.random().toString(16)}`
|
|
3
|
+
|
|
4
|
+
const delays = {}
|
|
5
|
+
const delay = ({time, action, id}) => {
|
|
6
|
+
const trigger = () => {
|
|
7
|
+
const info = delays[id]
|
|
8
|
+
clearTimeout(info.id)
|
|
9
|
+
action()
|
|
10
|
+
delete delays[id]
|
|
11
|
+
}
|
|
12
|
+
const timeoutID = setTimeout(trigger, time)
|
|
13
|
+
delays[id] = { trigger, id: timeoutID }
|
|
14
|
+
}
|
|
15
|
+
delay.trigger = (id) => delays[id].trigger()
|
|
16
|
+
</script>
|
|
17
|
+
|
|
1
18
|
<script>
|
|
2
|
-
import
|
|
19
|
+
import { fade } from "svelte/transition"
|
|
3
20
|
|
|
4
|
-
|
|
21
|
+
import { eventHandler$ } from "../handler$.js"
|
|
22
|
+
import wsx from "../wsx.js"
|
|
5
23
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
24
|
+
import ToastMessage from "./toaster/message.svelte"
|
|
25
|
+
|
|
26
|
+
const {
|
|
27
|
+
message = ToastMessage,
|
|
28
|
+
position = "tc",
|
|
29
|
+
onaction,
|
|
30
|
+
...rest
|
|
31
|
+
} = $props()
|
|
32
|
+
|
|
33
|
+
let items = $state([])
|
|
34
|
+
|
|
35
|
+
const act = eventHandler$(
|
|
36
|
+
(evt, id, props) => {
|
|
37
|
+
delay.trigger(id)
|
|
38
|
+
evt.props = props
|
|
39
|
+
onaction?.(evt)
|
|
40
|
+
}
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
export const show = (duration, props) => {
|
|
44
|
+
const id = genID()
|
|
45
|
+
items = [...items, { id, props }]
|
|
46
|
+
delay({
|
|
47
|
+
action: () => items = items.filter(
|
|
48
|
+
item => item.id !== id
|
|
49
|
+
),
|
|
50
|
+
time: duration,
|
|
51
|
+
id,
|
|
52
|
+
})
|
|
9
53
|
}
|
|
54
|
+
export const clear = () => items = []
|
|
55
|
+
|
|
56
|
+
const wind = $derived({
|
|
57
|
+
[`$${position}`]: true,
|
|
58
|
+
...rest,
|
|
59
|
+
})
|
|
60
|
+
const Message = $derived(message)
|
|
10
61
|
</script>
|
|
11
62
|
|
|
12
63
|
<ws-toaster use:wsx={wind}>
|
|
13
|
-
|
|
64
|
+
{#each items as {props, id} (id)}
|
|
65
|
+
<zephyr-toast-wrapper ws-x="[grid]" transition:fade={{duration: 200}}>
|
|
66
|
+
<Message
|
|
67
|
+
{...props}
|
|
68
|
+
onaction={act(id, {...props})}
|
|
69
|
+
/>
|
|
70
|
+
</zephyr-toast-wrapper>
|
|
71
|
+
{/each}
|
|
14
72
|
</ws-toaster>
|
package/src/layout/dialog.svelte
CHANGED
|
@@ -1,26 +1,24 @@
|
|
|
1
|
-
<svelte:options immutable />
|
|
2
|
-
|
|
3
1
|
<script>
|
|
4
2
|
import { fade } from "svelte/transition"
|
|
5
3
|
|
|
6
|
-
import wsx from "../wsx.
|
|
4
|
+
import wsx from "../wsx.js"
|
|
7
5
|
|
|
8
6
|
import Paper from "./paper.svelte"
|
|
9
7
|
|
|
8
|
+
const props = $props()
|
|
9
|
+
|
|
10
10
|
const trick = (node, options) => ({
|
|
11
11
|
delay: 0,
|
|
12
12
|
duration: 250,
|
|
13
13
|
css: () => "",
|
|
14
14
|
})
|
|
15
|
+
const onclick = (evt) => {
|
|
16
|
+
evt.stopPropagation()
|
|
17
|
+
}
|
|
15
18
|
</script>
|
|
16
19
|
|
|
17
|
-
<!-- svelte-ignore
|
|
18
|
-
<!-- svelte-ignore
|
|
19
|
-
<wind-wrapper transition:trick ws-x="@@dialog [grid]"
|
|
20
|
-
|
|
21
|
-
<Paper {...$$props}>
|
|
22
|
-
<slot name="header" slot="header" />
|
|
23
|
-
<slot />
|
|
24
|
-
<slot name="footer" slot="footer" />
|
|
25
|
-
</Paper>
|
|
20
|
+
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
|
21
|
+
<!-- svelte-ignore a11y_no_noninteractive_element_interactions -->
|
|
22
|
+
<wind-wrapper transition:trick ws-x="@@dialog [grid]" {onclick} role="dialog">
|
|
23
|
+
<Paper {...props} />
|
|
26
24
|
</wind-wrapper>
|
package/src/layout/drawer.svelte
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
<
|
|
2
|
-
|
|
3
|
-
<script context="module">
|
|
1
|
+
<script module>
|
|
4
2
|
const defs = {
|
|
5
3
|
select: {
|
|
6
4
|
"@@select": true,
|
|
@@ -15,35 +13,64 @@
|
|
|
15
13
|
"@@action": true,
|
|
16
14
|
}
|
|
17
15
|
}
|
|
16
|
+
const parseTime = (timestring) => {
|
|
17
|
+
if (!timestring) {
|
|
18
|
+
return 200
|
|
19
|
+
}
|
|
20
|
+
const { base, scale } =
|
|
21
|
+
timestring.match(/(?<base>\d+)(?<scale>s|ms)/)?.groups ?? {}
|
|
22
|
+
if (base === undefined) {
|
|
23
|
+
return 200
|
|
24
|
+
}
|
|
25
|
+
const numeric = parseInt(base)
|
|
26
|
+
if (scale === "ms") {
|
|
27
|
+
return numeric
|
|
28
|
+
}
|
|
29
|
+
return numeric * 1000
|
|
30
|
+
}
|
|
18
31
|
</script>
|
|
19
32
|
|
|
20
33
|
<script>
|
|
21
|
-
import
|
|
34
|
+
import { getContext } from "svelte"
|
|
35
|
+
|
|
36
|
+
import wsx from "../wsx.js"
|
|
22
37
|
|
|
23
38
|
import Paper from "./paper.svelte"
|
|
39
|
+
import { modalContext } from "./modal.svelte"
|
|
40
|
+
|
|
41
|
+
const {
|
|
42
|
+
height,
|
|
43
|
+
type = "menu",
|
|
44
|
+
children,
|
|
45
|
+
header,
|
|
46
|
+
footer,
|
|
47
|
+
content,
|
|
48
|
+
...rest
|
|
49
|
+
} = $props()
|
|
24
50
|
|
|
25
|
-
|
|
26
|
-
export let type = "menu"
|
|
51
|
+
const animTime = getContext(modalContext)
|
|
27
52
|
|
|
53
|
+
// When Svelte removes things from the DOM they are removed immediately
|
|
54
|
+
// unless Svelte has a transition running. Adding this prevents the drawer
|
|
55
|
+
// from disappearing without first letting the built in animations run.
|
|
28
56
|
const trick = (node, options) => ({
|
|
29
57
|
delay: 0,
|
|
30
|
-
duration:
|
|
58
|
+
duration: parseTime($animTime),
|
|
31
59
|
css: () => "",
|
|
32
60
|
})
|
|
33
61
|
|
|
34
|
-
|
|
62
|
+
const container = $derived({
|
|
35
63
|
...defs[type],
|
|
64
|
+
$show: true,
|
|
36
65
|
h: (type === "select") ? height : "100%",
|
|
37
66
|
grid: true,
|
|
38
|
-
}
|
|
67
|
+
})
|
|
68
|
+
const onclick = (evt) => evt.stopPropagation()
|
|
39
69
|
</script>
|
|
40
|
-
|
|
41
|
-
<!-- svelte-ignore
|
|
42
|
-
|
|
43
|
-
role="menubar"
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
<slot />
|
|
47
|
-
<slot name="footer" slot="footer" />
|
|
48
|
-
</Paper>
|
|
70
|
+
|
|
71
|
+
<!-- svelte-ignore a11y_interactive_supports_focus -->
|
|
72
|
+
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
|
73
|
+
<wind-drawer-container use:wsx={container} {onclick} role="menubar"
|
|
74
|
+
transition:trick>
|
|
75
|
+
<Paper r="0px" {...rest} {header} {footer} {content} {children} />
|
|
49
76
|
</wind-drawer-container>
|
package/src/layout/flex.svelte
CHANGED
|
@@ -1,22 +1,24 @@
|
|
|
1
|
-
<svelte:options immutable />
|
|
2
|
-
|
|
3
1
|
<script>
|
|
4
|
-
import wsx from "../wsx.
|
|
2
|
+
import wsx from "../wsx.js"
|
|
5
3
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
4
|
+
const {
|
|
5
|
+
direction = false,
|
|
6
|
+
cross = "stretch",
|
|
7
|
+
main = "start",
|
|
8
|
+
scrollable = false,
|
|
9
|
+
children,
|
|
10
|
+
...rest
|
|
11
|
+
} = $props()
|
|
10
12
|
|
|
11
|
-
|
|
13
|
+
const wind = $derived({
|
|
12
14
|
"fl.dir": direction,
|
|
13
15
|
"fl.cross": cross,
|
|
14
16
|
"fl.main": main,
|
|
15
17
|
over: (scrollable === true) ? "auto" : null,
|
|
16
|
-
|
|
17
|
-
}
|
|
18
|
+
...rest
|
|
19
|
+
})
|
|
18
20
|
</script>
|
|
19
21
|
|
|
20
22
|
<ws-flex use:wsx={wind}>
|
|
21
|
-
|
|
23
|
+
{@render children?.()}
|
|
22
24
|
</ws-flex>
|
package/src/layout/grid.svelte
CHANGED
|
@@ -1,18 +1,20 @@
|
|
|
1
|
-
<svelte:options immutable />
|
|
2
|
-
|
|
3
1
|
<script>
|
|
4
|
-
import wsx from "../wsx.
|
|
2
|
+
import wsx from "../wsx.js"
|
|
5
3
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
4
|
+
const {
|
|
5
|
+
direction = false,
|
|
6
|
+
cols = null,
|
|
7
|
+
rows = null,
|
|
8
|
+
autoCol = false,
|
|
9
|
+
autoRow = false,
|
|
10
|
+
colsFit = false,
|
|
11
|
+
colsFill = false,
|
|
12
|
+
scrollable = false,
|
|
13
|
+
children,
|
|
14
|
+
...rest
|
|
15
|
+
} = $props()
|
|
14
16
|
|
|
15
|
-
|
|
17
|
+
const wind = $derived({
|
|
16
18
|
"gr.flow": direction,
|
|
17
19
|
"gr.cols": cols?.join?.(" ") ?? cols ?? false,
|
|
18
20
|
"gr.rows": rows?.join?.(" ") ?? rows ?? false,
|
|
@@ -21,10 +23,10 @@
|
|
|
21
23
|
"gr.cols-fit": colsFit,
|
|
22
24
|
"gr.cols-fill": colsFill,
|
|
23
25
|
over: (scrollable === true) ? "auto" : null,
|
|
24
|
-
|
|
25
|
-
}
|
|
26
|
+
...rest
|
|
27
|
+
})
|
|
26
28
|
</script>
|
|
27
29
|
|
|
28
30
|
<ws-grid use:wsx={wind}>
|
|
29
|
-
|
|
31
|
+
{@render children?.()}
|
|
30
32
|
</ws-grid>
|
package/src/layout/modal.svelte
CHANGED
|
@@ -1,23 +1,28 @@
|
|
|
1
|
-
<
|
|
2
|
-
|
|
3
|
-
<script context="module">
|
|
1
|
+
<script module>
|
|
4
2
|
let topClose = null
|
|
3
|
+
export const modalContext = Symbol("modal context")
|
|
5
4
|
</script>
|
|
6
5
|
|
|
7
6
|
<script>
|
|
8
|
-
import { tick } from "svelte"
|
|
7
|
+
import { tick, setContext } from "svelte"
|
|
8
|
+
import { writable } from "svelte/store"
|
|
9
|
+
|
|
10
|
+
import wsx from "../wsx.js"
|
|
9
11
|
|
|
10
|
-
|
|
12
|
+
const {
|
|
13
|
+
component,
|
|
14
|
+
animTime = "200ms"
|
|
15
|
+
} = $props()
|
|
11
16
|
|
|
12
|
-
let modalProps = null
|
|
13
|
-
let resolver = null
|
|
14
|
-
let displayed = null
|
|
17
|
+
let modalProps = $state(null)
|
|
18
|
+
let resolver = $state(null)
|
|
19
|
+
let displayed = $state(null)
|
|
15
20
|
|
|
16
21
|
const close = (value) => {
|
|
17
22
|
resolver(value)
|
|
18
23
|
resolver = null
|
|
19
24
|
modalProps = null
|
|
20
|
-
|
|
25
|
+
Component = null
|
|
21
26
|
if (topClose !== close) {
|
|
22
27
|
return
|
|
23
28
|
}
|
|
@@ -31,30 +36,33 @@
|
|
|
31
36
|
export const show = (props) => new Promise(
|
|
32
37
|
async (resolve) => {
|
|
33
38
|
modalProps = props ?? {}
|
|
34
|
-
resolver = resolve
|
|
35
39
|
topClose = topClose ?? close
|
|
40
|
+
Component = component
|
|
36
41
|
await tick()
|
|
37
42
|
setTimeout(
|
|
38
|
-
() =>
|
|
43
|
+
() => resolver = resolve,
|
|
39
44
|
0
|
|
40
45
|
)
|
|
41
46
|
}
|
|
42
47
|
)
|
|
43
48
|
|
|
44
|
-
|
|
49
|
+
const animationTime = writable(animTime)
|
|
50
|
+
const wind = $derived({
|
|
51
|
+
"@anim-time": $animationTime,
|
|
52
|
+
$show: resolver !== null,
|
|
53
|
+
})
|
|
54
|
+
let Component = $state(null)
|
|
55
|
+
setContext(modalContext, animationTime)
|
|
45
56
|
</script>
|
|
46
57
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
/>
|
|
59
|
-
</ws-modal>
|
|
60
|
-
{/if}
|
|
58
|
+
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
|
59
|
+
<!-- svelte-ignore a11y_no_noninteractive_element_interactions -->
|
|
60
|
+
<ws-modal onclick={cancel} role="dialog" use:wsx={wind}>
|
|
61
|
+
<Component
|
|
62
|
+
bind:this={displayed}
|
|
63
|
+
this={component}
|
|
64
|
+
{...modalProps}
|
|
65
|
+
{close}
|
|
66
|
+
{closeToTop}
|
|
67
|
+
/>
|
|
68
|
+
</ws-modal>
|
package/src/layout/paper.svelte
CHANGED
|
@@ -1,56 +1,54 @@
|
|
|
1
|
-
<svelte:options immutable />
|
|
2
|
-
|
|
3
1
|
<script>
|
|
4
2
|
import Flex from "./flex.svelte"
|
|
5
|
-
import wsx from "../wsx.
|
|
3
|
+
import wsx from "../wsx.js"
|
|
4
|
+
import { splitProps } from "../props.js"
|
|
6
5
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
6
|
+
const {
|
|
7
|
+
color,
|
|
8
|
+
card = false,
|
|
9
|
+
square = false,
|
|
10
|
+
layout = Flex,
|
|
11
|
+
scrollable = true,
|
|
12
|
+
children,
|
|
13
|
+
content,
|
|
14
|
+
header,
|
|
15
|
+
footer,
|
|
16
|
+
...rest
|
|
17
|
+
} = $props()
|
|
12
18
|
|
|
13
|
-
|
|
14
|
-
(
|
|
15
|
-
const [target, name] =
|
|
16
|
-
(key.startsWith("l-") === true)
|
|
17
|
-
? [ p.layout, key.slice(2) ]
|
|
18
|
-
: [ p.paper, key ]
|
|
19
|
-
target[name] = value
|
|
20
|
-
return p
|
|
21
|
-
},
|
|
22
|
-
{ layout: {}, paper: {} }
|
|
19
|
+
const props = $derived(
|
|
20
|
+
splitProps(rest, "l!")
|
|
23
21
|
)
|
|
24
22
|
|
|
25
|
-
|
|
23
|
+
const layoutProps = $derived({
|
|
26
24
|
over: scrollable ? "auto" : false,
|
|
27
25
|
$content: true,
|
|
28
|
-
...props
|
|
29
|
-
}
|
|
30
|
-
|
|
26
|
+
...props["l!"],
|
|
27
|
+
})
|
|
28
|
+
const wind = $derived({
|
|
31
29
|
"$color": color,
|
|
32
30
|
"$outline": card,
|
|
33
31
|
r: square && "0px",
|
|
34
|
-
...props.
|
|
35
|
-
}
|
|
32
|
+
...props.rest,
|
|
33
|
+
})
|
|
36
34
|
</script>
|
|
37
35
|
|
|
38
36
|
<ws-paper use:wsx={wind}>
|
|
39
|
-
{#if
|
|
37
|
+
{#if header}
|
|
40
38
|
<div ws-x="[$header] [grid] [p 0px]">
|
|
41
|
-
|
|
39
|
+
{@render header()}
|
|
42
40
|
</div>
|
|
43
41
|
{/if}
|
|
44
|
-
{#if
|
|
45
|
-
|
|
42
|
+
{#if content}
|
|
43
|
+
{@render content()}
|
|
46
44
|
{:else}
|
|
47
|
-
<
|
|
48
|
-
|
|
49
|
-
</
|
|
45
|
+
<Flex {...layoutProps}>
|
|
46
|
+
{@render children?.()}
|
|
47
|
+
</Flex>
|
|
50
48
|
{/if}
|
|
51
|
-
{#if
|
|
49
|
+
{#if footer}
|
|
52
50
|
<div ws-x="[$footer] [grid] [p 0px]">
|
|
53
|
-
|
|
51
|
+
{@render footer()}
|
|
54
52
|
</div>
|
|
55
53
|
{/if}
|
|
56
54
|
</ws-paper>
|
package/src/layout/screen.svelte
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
<
|
|
2
|
-
|
|
3
|
-
<script context="module">
|
|
1
|
+
<script module>
|
|
4
2
|
const ctxStack = Symbol("stack context")
|
|
5
3
|
const ctxClose = Symbol("close context")
|
|
6
4
|
</script>
|
|
@@ -9,9 +7,14 @@
|
|
|
9
7
|
import { getContext, setContext } from "svelte"
|
|
10
8
|
import { fly } from "svelte/transition"
|
|
11
9
|
|
|
12
|
-
import wsx from "../wsx.
|
|
10
|
+
import wsx from "../wsx.js"
|
|
13
11
|
|
|
14
|
-
|
|
12
|
+
const {
|
|
13
|
+
alignLeft = false,
|
|
14
|
+
width = false,
|
|
15
|
+
children,
|
|
16
|
+
...rest
|
|
17
|
+
} = $props()
|
|
15
18
|
|
|
16
19
|
const stack = getContext(ctxStack) ?? 0
|
|
17
20
|
const animation = {
|
|
@@ -21,14 +24,15 @@
|
|
|
21
24
|
|
|
22
25
|
setContext(ctxStack, stack + 1)
|
|
23
26
|
|
|
24
|
-
|
|
27
|
+
const wind = $derived({
|
|
25
28
|
"@stack": stack.toString(),
|
|
26
29
|
"@screen-width": width,
|
|
27
30
|
"bg.c": "transparent",
|
|
28
|
-
|
|
29
|
-
|
|
31
|
+
$left: alignLeft,
|
|
32
|
+
...rest
|
|
33
|
+
})
|
|
30
34
|
</script>
|
|
31
35
|
|
|
32
36
|
<ws-screen use:wsx={wind} transition:fly={animation}>
|
|
33
|
-
|
|
37
|
+
{@render children?.()}
|
|
34
38
|
</ws-screen>
|
package/src/props.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export const filterProps = (props, filter) => Object.entries(props).reduce(
|
|
2
|
+
(p, [name, value]) => {
|
|
3
|
+
if (name.startsWith(filter) === true) {
|
|
4
|
+
p[name.slice(filter.length)] = value
|
|
5
|
+
}
|
|
6
|
+
return p
|
|
7
|
+
},
|
|
8
|
+
{}
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
export const splitProps = (props, ...splits) => Object.entries(props).reduce(
|
|
12
|
+
(groups, [name, value]) => {
|
|
13
|
+
for (const split of splits) {
|
|
14
|
+
if (name.startsWith(split) === true) {
|
|
15
|
+
groups[split] = groups[split] ?? {}
|
|
16
|
+
groups[split][name.slice(split.length)] = value
|
|
17
|
+
return groups
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
groups.rest[name] = value
|
|
21
|
+
return groups
|
|
22
|
+
},
|
|
23
|
+
{ rest: {} }
|
|
24
|
+
)
|
package/src/routing/route.svelte
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<script
|
|
1
|
+
<script module>
|
|
2
2
|
const urlChars = "[\\w\\-\\%\\(\\)\\.@!\\*\\^\\$]"
|
|
3
3
|
const urlPattern = (path, exact) => {
|
|
4
4
|
const regexSource = path.replace(
|
|
@@ -15,35 +15,48 @@
|
|
|
15
15
|
<script>
|
|
16
16
|
import { getContext, setContext } from "svelte"
|
|
17
17
|
|
|
18
|
-
import { ctx, resolve, route } from "./routing.js"
|
|
18
|
+
import { ctx, resolve, route } from "./routing.svelte.js"
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
const {
|
|
21
|
+
path = "",
|
|
22
|
+
component = null,
|
|
23
|
+
props = {},
|
|
24
|
+
exact = false,
|
|
25
|
+
content,
|
|
26
|
+
children,
|
|
27
|
+
} = $props()
|
|
24
28
|
|
|
25
29
|
const parent = getContext(ctx.parent) ?? "/"
|
|
26
30
|
const fullPath = resolve(parent, path)
|
|
27
31
|
|
|
28
32
|
setContext(ctx.parent, fullPath)
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
33
|
+
const pattern = $derived(
|
|
34
|
+
urlPattern(fullPath, exact)
|
|
35
|
+
)
|
|
36
|
+
const match = $derived(
|
|
37
|
+
$route.match(pattern)
|
|
38
|
+
)
|
|
39
|
+
const routeParams = $derived(
|
|
40
|
+
Object.fromEntries(
|
|
41
|
+
Object.entries({ ...match?.groups }).map(
|
|
42
|
+
([key, value]) => [key, decodeURIComponent(value)]
|
|
43
|
+
)
|
|
34
44
|
)
|
|
35
45
|
)
|
|
36
|
-
|
|
46
|
+
const routeInfo = $derived({
|
|
37
47
|
params: routeParams,
|
|
38
48
|
match: routeParams._path,
|
|
39
49
|
route: $route,
|
|
40
|
-
}
|
|
50
|
+
})
|
|
51
|
+
const Content = $derived(component)
|
|
41
52
|
</script>
|
|
42
53
|
|
|
43
54
|
{#if match !== null}
|
|
44
55
|
{#key routeParams._path}
|
|
45
|
-
|
|
46
|
-
<
|
|
47
|
-
|
|
56
|
+
{#if Content !== null}
|
|
57
|
+
<Content {...props} {routeInfo} />
|
|
58
|
+
{:else}
|
|
59
|
+
{@render (content ?? children)?.(routeInfo, props)}
|
|
60
|
+
{/if}
|
|
48
61
|
{/key}
|
|
49
62
|
{/if}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { onMount, getContext } from "svelte"
|
|
2
2
|
import { writable, derived } from "svelte/store"
|
|
3
3
|
|
|
4
|
-
import { hash } from "../hash.js"
|
|
4
|
+
import { hash } from "../hash.svelte.js"
|
|
5
5
|
|
|
6
6
|
export const route = derived(
|
|
7
7
|
hash,
|
|
@@ -12,6 +12,15 @@ export const route = derived(
|
|
|
12
12
|
return hash
|
|
13
13
|
}
|
|
14
14
|
)
|
|
15
|
+
route.set = (path) => {
|
|
16
|
+
hash.set(path)
|
|
17
|
+
}
|
|
18
|
+
// export const route = $derived(
|
|
19
|
+
// hash.startsWith("/") === false ? `/${hash}` : hash
|
|
20
|
+
// )
|
|
21
|
+
// $effect(
|
|
22
|
+
// () => hash = route
|
|
23
|
+
// )
|
|
15
24
|
|
|
16
25
|
export const ctx = {
|
|
17
26
|
router: Symbol("Router Context"),
|
package/src/routing/title.svelte
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
<script
|
|
1
|
+
<script module>
|
|
2
2
|
import { writable } from "svelte/store"
|
|
3
3
|
|
|
4
|
-
import { stackStore } from "./routing.js"
|
|
4
|
+
import { stackStore } from "./routing.svelte.js"
|
|
5
5
|
|
|
6
|
-
// const stack = writable([])
|
|
7
6
|
const stack = stackStore()
|
|
8
7
|
|
|
9
8
|
const updateTitle = (format, data) => {
|
|
@@ -17,10 +16,13 @@
|
|
|
17
16
|
|
|
18
17
|
<script>
|
|
19
18
|
import { onMount } from "svelte"
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
|
|
20
|
+
const {
|
|
21
|
+
data = "",
|
|
22
|
+
format = null,
|
|
23
|
+
} = $props()
|
|
22
24
|
|
|
23
25
|
stack.push(data)
|
|
24
26
|
|
|
25
|
-
|
|
27
|
+
$effect(() => updateTitle(format, $stack))
|
|
26
28
|
</script>
|