@axel669/zephyr 0.4.7 → 0.5.0-alpha.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.
Files changed (54) hide show
  1. package/package.json +41 -40
  2. package/src/async/button.svelte +17 -13
  3. package/src/async/suspend.svelte +38 -0
  4. package/src/changed.js +10 -0
  5. package/src/composed/data-table/th.svelte +2 -2
  6. package/src/composed/data-table.svelte +7 -7
  7. package/src/composed/entry-button.svelte +13 -16
  8. package/src/control/button.svelte +26 -22
  9. package/src/control/input.svelte +52 -50
  10. package/src/control/label.svelte +28 -24
  11. package/src/control/link.svelte +36 -30
  12. package/src/control/radio-group.svelte +13 -10
  13. package/src/control/select.svelte +21 -16
  14. package/src/control/tabs.svelte +18 -14
  15. package/src/control/toggle.svelte +33 -22
  16. package/src/data-display/avatar.svelte +12 -11
  17. package/src/data-display/badge.svelte +9 -7
  18. package/src/data-display/chip.svelte +27 -17
  19. package/src/data-display/details.svelte +22 -14
  20. package/src/data-display/popover.svelte +12 -9
  21. package/src/data-display/progress.svelte +17 -13
  22. package/src/data-display/table.svelte +24 -16
  23. package/src/data-display/tooltip.svelte +11 -9
  24. package/src/dialogs/alert.svelte +19 -12
  25. package/src/dialogs/confirm.svelte +22 -16
  26. package/src/{hash.js → hash.svelte.js} +9 -0
  27. package/src/{index.mjs → index.js} +12 -11
  28. package/src/{composed/element-toast.svelte → info/element-toaster.svelte} +41 -27
  29. package/src/info/icon.svelte +4 -4
  30. package/src/info/titlebar.svelte +20 -14
  31. package/src/info/toast.svelte +35 -0
  32. package/src/info/toaster/message.svelte +42 -0
  33. package/src/info/toaster.svelte +64 -6
  34. package/src/layout/dialog.svelte +10 -12
  35. package/src/layout/drawer.svelte +47 -18
  36. package/src/layout/flex.svelte +13 -11
  37. package/src/layout/grid.svelte +17 -15
  38. package/src/layout/modal.svelte +36 -26
  39. package/src/layout/paper.svelte +42 -33
  40. package/src/layout/screen.svelte +13 -9
  41. package/src/props.js +24 -0
  42. package/src/routing/route.svelte +31 -15
  43. package/src/routing/{routing.js → routing.svelte.js} +10 -1
  44. package/src/routing/title.svelte +8 -6
  45. package/src/spinner/circle-spinner.svelte +10 -8
  46. package/src/spinner/hexagon-spinner.svelte +10 -8
  47. package/src/text.svelte +6 -10
  48. package/src/composed/toast/message.svelte +0 -33
  49. package/src/composed/toast.svelte +0 -70
  50. package/src/info/notification.svelte +0 -28
  51. package/src/inline-dialog.svelte +0 -23
  52. /package/src/{handler$.mjs → handler$.js} +0 -0
  53. /package/src/{variant.mjs → variant.js} +0 -0
  54. /package/src/{wsx.mjs → wsx.js} +0 -0
@@ -1,18 +1,20 @@
1
- <svelte:options immutable />
2
-
3
1
  <script>
4
- import wsx from "../wsx.mjs"
2
+ import wsx from "../wsx.js"
5
3
 
6
- export let direction = false
7
- export let cols = null
8
- export let rows = null
9
- export let autoCol = false
10
- export let autoRow = false
11
- export let colsFit = false
12
- export let colsFill = false
13
- export let scrollable = false
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
- $: wind = {
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
- ...$$restProps
25
- }
26
+ ...rest
27
+ })
26
28
  </script>
27
29
 
28
30
  <ws-grid use:wsx={wind}>
29
- <slot />
31
+ {@render children?.()}
30
32
  </ws-grid>
@@ -1,23 +1,29 @@
1
- <svelte:options immutable />
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
- export let component
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
- visible.checked = false
25
+ Component = null
26
+ // visible.checked = false
21
27
  if (topClose !== close) {
22
28
  return
23
29
  }
@@ -31,30 +37,34 @@
31
37
  export const show = (props) => new Promise(
32
38
  async (resolve) => {
33
39
  modalProps = props ?? {}
34
- resolver = resolve
35
40
  topClose = topClose ?? close
41
+ Component = component
36
42
  await tick()
37
43
  setTimeout(
38
- () => visible.checked = true,
44
+ () => resolver = resolve,
39
45
  0
40
46
  )
41
47
  }
42
48
  )
43
49
 
44
- let visible = null
50
+ // let visible = null
51
+ const animationTime = writable(animTime)
52
+ const wind = $derived({
53
+ "@anim-time": $animationTime,
54
+ $show: resolver !== null,
55
+ })
56
+ let Component = $state(null)
57
+ setContext(modalContext, animationTime)
45
58
  </script>
46
59
 
47
- <input type="checkbox" bind:this={visible} ws-x="[disp none]" />
48
- {#if resolver !== null}
49
- <!-- svelte-ignore a11y-click-events-have-key-events -->
50
- <!-- svelte-ignore a11y-no-noninteractive-element-interactions -->
51
- <ws-modal on:click={cancel} role="dialog">
52
- <svelte:component
53
- bind:this={displayed}
54
- this={component}
55
- {...modalProps}
56
- {close}
57
- {closeToTop}
58
- />
59
- </ws-modal>
60
- {/if}
60
+ <!-- svelte-ignore a11y_click_events_have_key_events -->
61
+ <!-- svelte-ignore a11y_no_noninteractive_element_interactions -->
62
+ <ws-modal onclick={cancel} role="dialog" use:wsx={wind}>
63
+ <Component
64
+ bind:this={displayed}
65
+ this={component}
66
+ {...modalProps}
67
+ {close}
68
+ {closeToTop}
69
+ />
70
+ </ws-modal>
@@ -1,56 +1,65 @@
1
- <svelte:options immutable />
2
-
3
1
  <script>
4
2
  import Flex from "./flex.svelte"
5
- import wsx from "../wsx.mjs"
3
+ import wsx from "../wsx.js"
4
+ import { splitProps } from "../props.js"
6
5
 
7
- export let color
8
- export let card = false
9
- export let square = false
10
- export let layout = Flex
11
- export let scrollable = true
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
- $: props = Object.entries($$restProps).reduce(
14
- (p, [key, value]) => {
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
+ // $: props = Object.entries($$restProps).reduce(
20
+ // (p, [key, value]) => {
21
+ // const [target, name] =
22
+ // (key.startsWith("l!") === true)
23
+ // ? [ p.layout, key.slice(2) ]
24
+ // : [ p.paper, key ]
25
+ // target[name] = value
26
+ // return p
27
+ // },
28
+ // { layout: {}, paper: {} }
29
+ // )
30
+ const props = $derived(
31
+ splitProps(rest, "l!")
23
32
  )
24
33
 
25
- $: layoutProps = {
34
+ const layoutProps = $derived({
26
35
  over: scrollable ? "auto" : false,
27
36
  $content: true,
28
- ...props.layout,
29
- }
30
- $: wind = {
37
+ ...props["l!"],
38
+ })
39
+ const wind = $derived({
31
40
  "$color": color,
32
41
  "$outline": card,
33
42
  r: square && "0px",
34
- ...props.paper,
35
- }
43
+ ...props.rest,
44
+ })
36
45
  </script>
37
46
 
38
47
  <ws-paper use:wsx={wind}>
39
- {#if $$slots.header}
48
+ {#if header}
40
49
  <div ws-x="[$header] [grid] [p 0px]">
41
- <slot name="header" />
50
+ {@render header()}
42
51
  </div>
43
52
  {/if}
44
- {#if $$slots.content}
45
- <slot name="content" />
53
+ {#if content}
54
+ {@render content()}
46
55
  {:else}
47
- <svelte:component this={layout} {...layoutProps}>
48
- <slot />
49
- </svelte:component>
56
+ <Flex {...layoutProps}>
57
+ {@render children?.()}
58
+ </Flex>
50
59
  {/if}
51
- {#if $$slots.footer}
60
+ {#if footer}
52
61
  <div ws-x="[$footer] [grid] [p 0px]">
53
- <slot name="footer" />
62
+ {@render footer()}
54
63
  </div>
55
64
  {/if}
56
65
  </ws-paper>
@@ -1,6 +1,4 @@
1
- <svelte:options immutable />
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.mjs"
10
+ import wsx from "../wsx.js"
13
11
 
14
- export let width = false
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
- $: wind = {
27
+ const wind = $derived({
25
28
  "@stack": stack.toString(),
26
29
  "@screen-width": width,
27
30
  "bg.c": "transparent",
28
- ...$$restProps
29
- }
31
+ $left: alignLeft,
32
+ ...rest
33
+ })
30
34
  </script>
31
35
 
32
36
  <ws-screen use:wsx={wind} transition:fly={animation}>
33
- <slot />
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
+ )
@@ -1,4 +1,4 @@
1
- <script context="module">
1
+ <script module>
2
2
  const urlChars = "[\\w\\-\\%\\(\\)\\.@!\\*\\^\\$]"
3
3
  const urlPattern = (path, exact) => {
4
4
  const regexSource = path.replace(
@@ -15,35 +15,51 @@
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
- export let path = ""
21
- export let component = null
22
- export let props = {}
23
- export let exact = false
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
- $: pattern = urlPattern(fullPath, exact)
30
- $: match = $route.match(pattern)
31
- $: routeParams = Object.fromEntries(
32
- Object.entries({ ...match?.groups }).map(
33
- ([key, value]) => [key, decodeURIComponent(value)]
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
- $: routeInfo = {
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
- <slot {routeInfo}>
56
+ {#if Content !== null}
57
+ <Content {...props} {routeInfo} />
58
+ {:else}
59
+ {@render (content ?? children)?.(routeInfo, props)}
60
+ {/if}
61
+ <!-- <slot {routeInfo}>
46
62
  <svelte:component this={component} {...props} {routeInfo} />
47
- </slot>
63
+ </slot> -->
48
64
  {/key}
49
65
  {/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"),
@@ -1,9 +1,8 @@
1
- <script context="module">
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
- export let data = ""
21
- export let format = null
19
+
20
+ const {
21
+ data = "",
22
+ format = null,
23
+ } = $props()
22
24
 
23
25
  stack.push(data)
24
26
 
25
- $: updateTitle(format, $stack)
27
+ $effect(() => updateTitle(format, $stack))
26
28
  </script>
@@ -1,16 +1,18 @@
1
- <svelte:options immutable />
2
-
3
1
  <script>
4
- import wsx from "../wsx.mjs"
2
+ import wsx from "../wsx.js"
5
3
 
6
- export let size = "100px"
7
- export let color = "@primary"
4
+ const {
5
+ size = "100px",
6
+ color = "@primary",
7
+ ...rest
8
+ } = $props()
8
9
 
9
- $: wind = {
10
- ...$$restProps,
10
+ const wind = $derived({
11
+ ...rest,
11
12
  "@size": size,
12
13
  "$color": color,
13
- }
14
+ })
14
15
  </script>
15
16
 
17
+ <!-- svelte-ignore element_invalid_self_closing_tag -->
16
18
  <ws-circle-spinner use:wsx={wind} style="aspect-ratio: 1 / 1;" />
@@ -1,16 +1,18 @@
1
- <svelte:options immutable />
2
-
3
1
  <script>
4
- import wsx from "../wsx.mjs"
2
+ import wsx from "../wsx.js"
5
3
 
6
- export let size = "100px"
7
- export let color = "@primary"
4
+ const {
5
+ size = "100px",
6
+ color = "@primary",
7
+ ...rest
8
+ } = $props()
8
9
 
9
- $: wind = {
10
- ...$$restProps,
10
+ const wind = $derived({
11
+ ...rest,
11
12
  "@size": size,
12
13
  "$color": color,
13
- }
14
+ })
14
15
  </script>
15
16
 
17
+ <!-- svelte-ignore element_invalid_self_closing_tag -->
16
18
  <ws-hexagon-spinner use:wsx={wind} style="aspect-ratio: 1 / 1;" />
package/src/text.svelte CHANGED
@@ -1,20 +1,16 @@
1
- <svelte:options immutable />
2
-
3
1
  <script>
4
- import wsx from "./wsx.mjs"
2
+ import wsx from "./wsx.js"
5
3
 
6
- export let title = false
7
- export let subtitle = false
8
- export let adorn = false
4
+ const { adorn, subtitle, title, children, ...rest } = $props()
9
5
 
10
- $: wind = {
6
+ const wind = $derived({
11
7
  "$title-text": title,
12
8
  "$subtitle-text": subtitle,
13
9
  "$adorn": adorn,
14
- ...$$restProps
15
- }
10
+ ...rest
11
+ })
16
12
  </script>
17
13
 
18
14
  <span use:wsx={wind}>
19
- <slot />
15
+ {@render children?.()}
20
16
  </span>
@@ -1,33 +0,0 @@
1
- <script>
2
- import { createEventDispatcher } from "svelte"
3
-
4
- import Button from "../../control/button.svelte"
5
- import Icon from "../../info/icon.svelte"
6
- import Notification from "../../info/notification.svelte"
7
- import Text from "../../text.svelte"
8
-
9
- export let message = ""
10
- export let icon = false
11
- export let color = false
12
- export let actionText = null
13
-
14
- const dispatch = createEventDispatcher()
15
- const dismiss = () => dispatch("action", null)
16
- const respond = () => dispatch("action", true)
17
- </script>
18
-
19
- <Notification {color} on:click={dismiss}>
20
- <Text slot="start" -adorn>
21
- {#if icon !== false}
22
- <Icon name={icon} />
23
- {/if}
24
- </Text>
25
- <span>{message}</span>
26
- <div slot="end" ws-x="[grid]">
27
- {#if actionText}
28
- <Button on:click={respond} r.l="0px">
29
- {actionText}
30
- </Button>
31
- {/if}
32
- </div>
33
- </Notification>
@@ -1,70 +0,0 @@
1
- <svelte:options immutable />
2
-
3
- <script context="module">
4
- const genID = () => `${Date.now()}:${Math.random().toString(16)}`
5
-
6
- const delays = {}
7
- const delay = ({time, action, id}) => {
8
- const trigger = () => {
9
- const info = delays[id]
10
- clearTimeout(info.id)
11
- action()
12
- delete delays[id]
13
- }
14
- const timeoutID = setTimeout(trigger, time)
15
- delays[id] = { trigger, id: timeoutID }
16
- }
17
- delay.trigger = (id) => delays[id].trigger()
18
- </script>
19
-
20
- <script>
21
- import { createEventDispatcher } from "svelte"
22
- import { fade } from "svelte/transition"
23
-
24
- import { eventHandler$ } from "../handler$.mjs"
25
-
26
- import Toaster from "../info/toaster.svelte"
27
-
28
- import ToastMessage from "./toast/message.svelte"
29
-
30
- export let component = ToastMessage
31
- export let position = "tc"
32
-
33
- let items = []
34
-
35
- const dispatch = createEventDispatcher()
36
- const act = eventHandler$(
37
- (evt, id, props) => {
38
- delay.trigger(id)
39
- dispatch(
40
- "action",
41
- { value: evt.detail, props }
42
- )
43
- }
44
- )
45
-
46
- export const show = (duration, props) => {
47
- const id = genID()
48
- items = [...items, { id, props }]
49
- delay({
50
- action: () => items = items.filter(
51
- item => item.id !== id
52
- ),
53
- time: duration,
54
- id,
55
- })
56
- }
57
- export const clear = () => items = []
58
- </script>
59
-
60
- <Toaster {position} {...$$restProps}>
61
- {#each items as {props, id} (id)}
62
- <zephyr-toast-wrapper ws-x="[grid]" transition:fade={{duration: 200}}>
63
- <svelte:component
64
- this={component}
65
- {...props}
66
- on:action={act(id, props)}
67
- />
68
- </zephyr-toast-wrapper>
69
- {/each}
70
- </Toaster>
@@ -1,28 +0,0 @@
1
- <script>
2
- import wsx from "../wsx.mjs"
3
-
4
- export let color = false
5
-
6
- $: wind = {
7
- "$color": color,
8
- ...$$restProps,
9
- }
10
- </script>
11
-
12
- <!-- svelte-ignore a11y-click-events-have-key-events -->
13
- <!-- svelte-ignore a11y-interactive-supports-focus -->
14
- <ws-notification use:wsx={wind} on:click role="button">
15
- {#if $$slots.start}
16
- <div ws-x="[$start] [grid]">
17
- <slot name="start" />
18
- </div>
19
- {/if}
20
- <div ws-x="[$notif-text]">
21
- <slot />
22
- </div>
23
- {#if $$slots.end}
24
- <div ws-x="[$end] [grid]">
25
- <slot name="end" />
26
- </div>
27
- {/if}
28
- </ws-notification>
@@ -1,23 +0,0 @@
1
- <script>
2
- import wsx from "../wsx.mjs"
3
-
4
- import Paper from "./paper.svelte"
5
-
6
- const id = Math.random().toString(16)
7
-
8
- $: paper = {
9
- "@dialog": true,
10
- "$outline": true,
11
- ...$$restProps
12
- }
13
- </script>
14
-
15
- <slot name="toggle" {id} />
16
- <input type="checkbox" ws-x="hide" {id} />
17
- <ws-modal>
18
- <ws-paper use:wsx={paper}>
19
- <slot name="header" {id} />
20
- <slot name="content" {id} />
21
- <slot name="footer" {id} />
22
- </ws-paper>
23
- </ws-modal>
File without changes
File without changes