@axel669/zephyr 0.5.4 → 0.5.5

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@axel669/zephyr",
3
- "version": "0.5.4",
3
+ "version": "0.5.5",
4
4
  "description": "",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
@@ -13,8 +13,8 @@
13
13
  "author": "",
14
14
  "license": "MIT",
15
15
  "dependencies": {
16
- "@axel669/windstorm": "0.5.4",
17
- "svelte": "^5.9.0"
16
+ "@axel669/windstorm": "0.5.5",
17
+ "svelte": "^5.30.1"
18
18
  },
19
19
  "devDependencies": {
20
20
  "@axel669/asuid": "^0.2.1",
@@ -2,27 +2,28 @@
2
2
  import Button from "../control/button.svelte"
3
3
  import Modal from "../layout/modal.svelte"
4
4
  import { handler$ } from "../handler$.js"
5
+ import { splitProps } from "../props.js"
5
6
 
6
7
  const {
7
- component,
8
- props,
9
- this:Wrapper = Modal,
10
- "w!props":wrapperProps = {},
11
8
  children,
9
+ modal,
12
10
  onentry,
11
+ onopen,
13
12
  ...rest
14
13
  } = $props()
15
14
 
15
+ const prop = splitProps(rest, "m!")
16
+
16
17
  let element = null
17
- const open = handler$(
18
- async (props) => {
19
- const elemProps = (typeof props === "function") ? props() : props
20
- const result = await element.show(elemProps)
21
- onentry?.(result)
22
- }
23
- )
18
+ const open = async (props) => {
19
+ onopen?.()
20
+ const result = await element.show()
21
+ onentry?.(result)
22
+ }
24
23
  </script>
25
24
 
26
- <Button {...rest} onclick={open(props)} {children} />
25
+ <Button {...prop.rest} onclick={open} {children} />
27
26
 
28
- <Wrapper bind:this={element} {...rest} {component} />
27
+ <Modal bind:this={element} {...prop["m!"]}>
28
+ {@render modal()}
29
+ </Modal>
@@ -4,15 +4,16 @@
4
4
  import Icon from "../info/icon.svelte"
5
5
  import Text from "../text.svelte"
6
6
  import Titlebar from "../info/titlebar.svelte"
7
+ import { modalContext } from "../layout/modal.svelte"
7
8
 
8
9
  const {
9
- close,
10
- color = "@primary",
10
+ color = "@default",
11
11
  icon,
12
12
  message,
13
13
  okText = "OK",
14
- titleText = "Alert",
14
+ title: titleText = "Alert",
15
15
  } = $props()
16
+ const { close } = modalContext()
16
17
  </script>
17
18
 
18
19
  <Dialog card {color}>
@@ -33,7 +34,7 @@
33
34
  </Text>
34
35
 
35
36
  {#snippet footer()}
36
- <Button onclick={close} {color} ground>
37
+ <Button onclick={() => close(true)} {color} ground>
37
38
  {okText}
38
39
  </Button>
39
40
  {/snippet}
@@ -5,19 +5,20 @@
5
5
  import Icon from "../info/icon.svelte"
6
6
  import Text from "../text.svelte"
7
7
  import Titlebar from "../info/titlebar.svelte"
8
+ import { modalContext } from "../layout/modal.svelte"
8
9
 
9
10
  import { handler$ } from "../handler$.js"
10
11
 
11
12
  const {
12
- close,
13
- titleText = "Confirm",
13
+ title: titleText = "Confirm",
14
14
  icon,
15
15
  message,
16
16
  okText = "OK",
17
17
  cancelText = "Cancel",
18
- color = "@primary",
18
+ color = "@default",
19
19
  } = $props()
20
20
 
21
+ const { close } = modalContext()
21
22
  const cls = handler$(close)
22
23
  </script>
23
24
 
@@ -0,0 +1,67 @@
1
+ <script>
2
+ import Button from "../control/button.svelte"
3
+ import Dialog from "../layout/dialog.svelte"
4
+ import Grid from "../layout/grid.svelte"
5
+ import Icon from "../info/icon.svelte"
6
+ import Input from "../control/input.svelte"
7
+ import Text from "../text.svelte"
8
+ import Titlebar from "../info/titlebar.svelte"
9
+ import { modalContext } from "../layout/modal.svelte"
10
+
11
+ import { handler$ } from "../handler$.js"
12
+ import { frameDelay } from "../internals.js"
13
+
14
+ let {
15
+ title: titleText = "Confirm",
16
+ icon,
17
+ message,
18
+ okText = "OK",
19
+ cancelText = "Cancel",
20
+ color = "@default",
21
+ value = $bindable(""),
22
+ initial = ""
23
+ } = $props()
24
+
25
+ const { close } = modalContext()
26
+ const cls = handler$(close)
27
+ let input = $state(null)
28
+
29
+ const done = (evt) => {
30
+ evt.preventDefault()
31
+ evt.stopPropagation()
32
+ close(true)
33
+ }
34
+
35
+ // the first 1-2 frames it's in the DOM it's not visible, focus didn't work
36
+ frameDelay(3, () => input.focus())
37
+ value = initial
38
+ </script>
39
+
40
+ <Dialog card {color}>
41
+ {#snippet header()}
42
+ <Titlebar {color}>
43
+ {#snippet title()}
44
+ <Text title>
45
+ <Icon name={icon}>
46
+ {titleText}
47
+ </Icon>
48
+ </Text>
49
+ {/snippet}
50
+ </Titlebar>
51
+ {/snippet}
52
+
53
+ <form onsubmit={done} ws-x="[grid]">
54
+ <Input bind:value {color} bind:this={input} label={message} />
55
+ </form>
56
+
57
+ {#snippet footer()}
58
+ <Grid cols="1fr 1fr" p="0px">
59
+ <Button onclick={cls(false)} color="@danger" ground>
60
+ {cancelText}
61
+ </Button>
62
+ <Button onclick={cls(true)} color="@secondary" ground>
63
+ {okText}
64
+ </Button>
65
+ </Grid>
66
+ {/snippet}
67
+ </Dialog>
@@ -1,14 +1,5 @@
1
1
  import { readable } from "svelte/store"
2
2
 
3
- // export const hash = $state(location.hash.slice(1))
4
- // window.addEventListener(
5
- // "popstate",
6
- // () => hashValue = location.hash.slice(1)
7
- // )
8
- // $effect(
9
- // () => location.hash = hash
10
- // )
11
-
12
3
  export const hash = readable(
13
4
  location.hash.slice(1),
14
5
  (set) => {
package/src/index.js CHANGED
@@ -27,7 +27,7 @@ export { default as Dialog } from "./layout/dialog.svelte"
27
27
  export { default as Drawer } from "./layout/drawer.svelte"
28
28
  export { default as Flex } from "./layout/flex.svelte"
29
29
  export { default as Grid } from "./layout/grid.svelte"
30
- export { default as Modal } from "./layout/modal.svelte"
30
+ export { default as Modal, modalAnimTime, modalContext } from "./layout/modal.svelte"
31
31
  export { default as Paper } from "./layout/paper.svelte"
32
32
  export { default as Screen } from "./layout/screen.svelte"
33
33
 
@@ -38,6 +38,7 @@ export { default as HexagonSpinner } from "./spinner/hexagon-spinner.svelte"
38
38
 
39
39
  export { default as Alert } from "./dialogs/alert.svelte"
40
40
  export { default as Confirm } from "./dialogs/confirm.svelte"
41
+ export { default as Prompt } from "./dialogs/prompt.svelte"
41
42
 
42
43
  export { default as DataTable } from "./composed/data-table.svelte"
43
44
  // export { default as TH } from "./composed/data-table/th.svelte"
@@ -52,7 +53,7 @@ export { default as Title } from "./routing/title.svelte"
52
53
 
53
54
  export { default as wsx } from "./wsx.js"
54
55
 
55
- export { hash } from "./hash.svelte.js"
56
+ export { hash } from "./hash.js"
56
57
 
57
58
  export {
58
59
  route,
@@ -0,0 +1,12 @@
1
+ export const frameDelay = (frames, action) => {
2
+ let frameCount = 0
3
+ const process = () => {
4
+ frameCount += 1
5
+ if (frameCount >= frames) {
6
+ action()
7
+ return
8
+ }
9
+ requestAnimationFrame(process)
10
+ }
11
+ requestAnimationFrame(process)
12
+ }
@@ -19,6 +19,7 @@
19
19
 
20
20
  <!-- svelte-ignore a11y_click_events_have_key_events -->
21
21
  <!-- svelte-ignore a11y_no_noninteractive_element_interactions -->
22
+ <!-- svelte-ignore a11y_interactive_supports_focus -->
22
23
  <wind-wrapper transition:trick ws-x="@@dialog [grid]" {onclick} role="dialog">
23
24
  <Paper {...props} />
24
25
  </wind-wrapper>
@@ -31,24 +31,18 @@
31
31
  </script>
32
32
 
33
33
  <script>
34
- import { getContext } from "svelte"
35
-
36
34
  import wsx from "../wsx.js"
37
35
 
38
36
  import Paper from "./paper.svelte"
39
- import { modalContext } from "./modal.svelte"
37
+ import { modalAnimTime } from "./modal.svelte"
40
38
 
41
39
  const {
42
40
  height,
43
41
  type = "menu",
44
- children,
45
- header,
46
- footer,
47
- content,
48
42
  ...rest
49
43
  } = $props()
50
44
 
51
- const animTime = getContext(modalContext)
45
+ const animTime = modalAnimTime()
52
46
 
53
47
  // When Svelte removes things from the DOM they are removed immediately
54
48
  // unless Svelte has a transition running. Adding this prevents the drawer
@@ -72,5 +66,5 @@
72
66
  <!-- svelte-ignore a11y_click_events_have_key_events -->
73
67
  <wind-drawer-container use:wsx={container} {onclick} role="menubar"
74
68
  transition:trick>
75
- <Paper r="0px" {...rest} {header} {footer} {content} {children} />
69
+ <Paper r="0px" {...rest} />
76
70
  </wind-drawer-container>
@@ -1,28 +1,34 @@
1
1
  <script module>
2
+ import { getContext } from "svelte"
3
+
2
4
  let topClose = null
3
- export const modalContext = Symbol("modal context")
5
+ const modalAnimTimeSymbol = Symbol("modal animation time")
6
+ const modalContextSymbol = Symbol("modal context")
7
+
8
+ export const modalAnimTime = () => getContext(modalAnimTimeSymbol)
9
+ export const modalContext = () => getContext(modalContextSymbol)
4
10
  </script>
5
11
 
6
12
  <script>
7
- import { tick, setContext } from "svelte"
13
+ import { setContext } from "svelte"
8
14
  import { writable } from "svelte/store"
9
15
 
10
16
  import wsx from "../wsx.js"
17
+ import { frameDelay } from "../internals.js"
11
18
 
12
19
  const {
13
- component,
20
+ children,
21
+ cancelable = false,
14
22
  animTime = "200ms"
15
23
  } = $props()
16
24
 
17
- let modalProps = $state(null)
18
25
  let resolver = $state(null)
19
- let displayed = $state(null)
26
+ let shown = $state(false)
20
27
 
21
28
  const close = (value) => {
22
29
  resolver(value)
23
30
  resolver = null
24
- modalProps = null
25
- Component = null
31
+ shown = false
26
32
  if (topClose !== close) {
27
33
  return
28
34
  }
@@ -31,38 +37,35 @@
31
37
  const closeToTop = (value) => {
32
38
  topClose(value)
33
39
  }
34
- const cancel = () => displayed.cancel?.()
40
+ const cancel = () => {
41
+ if (cancelable === false) {
42
+ return
43
+ }
44
+ close(null)
45
+ }
35
46
 
36
47
  export const show = (props) => new Promise(
37
- async (resolve) => {
38
- modalProps = props ?? {}
48
+ (resolve) => {
39
49
  topClose = topClose ?? close
40
- Component = component
41
- await tick()
42
- setTimeout(
43
- () => resolver = resolve,
44
- 0
45
- )
50
+ resolver = resolve
51
+ frameDelay(1, () => shown = true)
46
52
  }
47
53
  )
48
54
 
49
55
  const animationTime = writable(animTime)
50
56
  const wind = $derived({
51
57
  "@anim-time": $animationTime,
52
- $show: resolver !== null,
58
+ $show: shown === true,
53
59
  })
54
- let Component = $state(null)
55
- setContext(modalContext, animationTime)
60
+ setContext(modalAnimTimeSymbol, animationTime)
61
+ setContext(modalContextSymbol, { close, closeToTop })
56
62
  </script>
57
63
 
58
64
  <!-- svelte-ignore a11y_click_events_have_key_events -->
59
65
  <!-- svelte-ignore a11y_no_noninteractive_element_interactions -->
66
+ <!-- svelte-ignore a11y_interactive_supports_focus -->
60
67
  <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
+ {#if resolver !== null}
69
+ {@render children()}
70
+ {/if}
68
71
  </ws-modal>
@@ -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.svelte.js"
4
+ import { hash } from "../hash.js"
5
5
 
6
6
  export const route = derived(
7
7
  hash,
@@ -15,12 +15,6 @@ export const route = derived(
15
15
  route.set = (path) => {
16
16
  hash.set(path)
17
17
  }
18
- // export const route = $derived(
19
- // hash.startsWith("/") === false ? `/${hash}` : hash
20
- // )
21
- // $effect(
22
- // () => hash = route
23
- // )
24
18
 
25
19
  export const ctx = {
26
20
  router: Symbol("Router Context"),