@axel669/zephyr 0.3.8 → 0.4.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.
Files changed (76) hide show
  1. package/package.json +40 -33
  2. package/src/async/button.svelte +16 -8
  3. package/src/composed/data-table/th.svelte +2 -2
  4. package/src/composed/data-table.svelte +4 -3
  5. package/src/composed/form.svelte +60 -0
  6. package/src/composed/table-functions.js +3 -1
  7. package/src/composed/toast/message.svelte +15 -38
  8. package/src/control/input.svelte +21 -41
  9. package/src/control/label.svelte +1 -1
  10. package/src/control/link.svelte +1 -1
  11. package/src/control/radio-group.svelte +21 -0
  12. package/src/control/select.svelte +5 -5
  13. package/src/control/tabs.svelte +9 -21
  14. package/src/control/toggle.svelte +2 -2
  15. package/src/data-display/avatar.svelte +4 -1
  16. package/src/data-display/badge.svelte +1 -1
  17. package/src/data-display/chip.svelte +1 -1
  18. package/src/data-display/popover.svelte +1 -1
  19. package/src/data-display/progress.svelte +2 -2
  20. package/src/data-display/table.svelte +1 -1
  21. package/src/dialogs/confirm.svelte +3 -3
  22. package/src/hash.js +3 -3
  23. package/src/index.mjs +11 -1
  24. package/src/info/notification.svelte +13 -1
  25. package/src/info/titlebar.svelte +21 -5
  26. package/src/layout/dialog.svelte +1 -1
  27. package/src/layout/drawer.svelte +4 -4
  28. package/src/layout/flex.svelte +0 -4
  29. package/src/layout/grid.svelte +4 -4
  30. package/src/layout/paper.svelte +13 -4
  31. package/src/routing/route.svelte +48 -0
  32. package/src/routing/routing.js +62 -0
  33. package/src/routing/title.svelte +26 -0
  34. package/src/spinner/circle-spinner.svelte +2 -1
  35. package/src/spinner/hexagon-spinner.svelte +2 -1
  36. package/src/text.svelte +2 -4
  37. package/src/wsx.mjs +9 -8
  38. package/src/async/button.md +0 -27
  39. package/src/async/load-zone.md +0 -42
  40. package/src/composed/data-table/th.md +0 -21
  41. package/src/composed/data-table.md +0 -86
  42. package/src/composed/entry-button.md +0 -44
  43. package/src/composed/toast.md +0 -45
  44. package/src/control/button.md +0 -41
  45. package/src/control/input.md +0 -87
  46. package/src/control/label.md +0 -48
  47. package/src/control/link.md +0 -50
  48. package/src/control/radio.md +0 -58
  49. package/src/control/radio.svelte +0 -28
  50. package/src/control/select.md +0 -70
  51. package/src/control/tabs.md +0 -47
  52. package/src/control/toggle.md +0 -61
  53. package/src/data-display/avatar.md +0 -36
  54. package/src/data-display/badge.md +0 -30
  55. package/src/data-display/chip.md +0 -36
  56. package/src/data-display/details.md +0 -42
  57. package/src/data-display/popover.md +0 -32
  58. package/src/data-display/progress.md +0 -46
  59. package/src/data-display/table.md +0 -59
  60. package/src/data-display/tooltip.md +0 -29
  61. package/src/dialogs/alert.md +0 -42
  62. package/src/dialogs/confirm.md +0 -56
  63. package/src/functions.md +0 -108
  64. package/src/info/icon.md +0 -21
  65. package/src/info/notification.md +0 -36
  66. package/src/info/titlebar.md +0 -75
  67. package/src/info/toaster.md +0 -26
  68. package/src/layout/dialog.md +0 -43
  69. package/src/layout/drawer.md +0 -70
  70. package/src/layout/flex.md +0 -43
  71. package/src/layout/grid.md +0 -61
  72. package/src/layout/modal.md +0 -50
  73. package/src/layout/paper.md +0 -94
  74. package/src/layout/screen.md +0 -33
  75. package/src/spinner/spinners.md +0 -22
  76. package/src/text.md +0 -34
package/package.json CHANGED
@@ -1,33 +1,40 @@
1
- {
2
- "name": "@axel669/zephyr",
3
- "version": "0.3.8",
4
- "description": "",
5
- "main": "src/index.mjs",
6
- "type": "module",
7
- "scripts": {
8
- "test": "echo \"Error: no test specified\" && exit 1",
9
- "demo": "rollup -c test/rollup.config.mjs"
10
- },
11
- "keywords": [],
12
- "author": "",
13
- "license": "MIT",
14
- "dependencies": {
15
- "@axel669/windstorm": "0.3.8"
16
- },
17
- "devDependencies": {
18
- "@axel669/ipsen": "0.4.0-beta.7",
19
- "@axel669/rollup-html-input": "^0.1.2",
20
- "@rollup/plugin-node-resolve": "^15.0.2",
21
- "@rollup/plugin-terser": "^0.4.0",
22
- "prism-svelte": "^0.5.0",
23
- "rollup": "^3.20.2",
24
- "rollup-plugin-svelte": "^7.1.6",
25
- "svelte": "^4.2.7"
26
- },
27
- "files": [
28
- "src/"
29
- ],
30
- "imports": {
31
- "#lib": "./src/index.mjs"
32
- }
33
- }
1
+ {
2
+ "name": "@axel669/zephyr",
3
+ "version": "0.4.5",
4
+ "description": "",
5
+ "main": "src/index.mjs",
6
+ "type": "module",
7
+ "scripts": {
8
+ "site/start": "wrangler pages dev site --port 45067",
9
+ "site/build": "rollup -c docsite/rollup.config.mjs",
10
+ "site/watch": "rollup -c docsite/rollup.config.mjs --watch"
11
+ },
12
+ "keywords": [],
13
+ "author": "",
14
+ "license": "MIT",
15
+ "dependencies": {
16
+ "@axel669/rollup-copy-static": "^0.2.0",
17
+ "@axel669/windstorm": "0.4.5"
18
+ },
19
+ "devDependencies": {
20
+ "@axel669/asuid": "^0.2.1",
21
+ "@axel669/ipsen": "0.4.0-beta.7",
22
+ "@axel669/rollup-html-input": "^0.1.2",
23
+ "@rollup/plugin-node-resolve": "^15.0.2",
24
+ "@rollup/plugin-terser": "^0.4.0",
25
+ "marked": "^12.0.2",
26
+ "prism-svelte": "^0.5.0",
27
+ "prismjs": "^1.29.0",
28
+ "rollup": "^3.20.2",
29
+ "rollup-plugin-delete": "^2.0.0",
30
+ "rollup-plugin-svelte": "^7.1.6",
31
+ "svelte": "^4.2.7"
32
+ },
33
+ "files": [
34
+ "src/"
35
+ ],
36
+ "imports": {
37
+ "#lib": "./src/index.mjs",
38
+ "#comp/*": "./docsite/comp/*.svelte"
39
+ }
40
+ }
@@ -4,6 +4,7 @@
4
4
 
5
5
  export let handler = null
6
6
  export let disabled
7
+ export let spincolor = "@primary"
7
8
 
8
9
  let running = false
9
10
  const asyncHandler = async (evt) => {
@@ -19,11 +20,18 @@
19
20
  }
20
21
  </script>
21
22
 
22
- <Button {...props} on:click={asyncHandler}>
23
- <div ws-x="[h 20px] [m.r:not(:empty) 4px]">
24
- {#if running === true}
25
- <Spinner size="20px" />
26
- {/if}
27
- </div>
28
- <slot />
29
- </Button>
23
+ <async-button ws-x="[disp inline-grid] [gr.cols 1fr] [pos relative]">
24
+ <Button {...props} on:click={asyncHandler}>
25
+ <slot />
26
+ </Button>
27
+ {#if running === true}
28
+ <Spinner
29
+ size="unset"
30
+ pos="absolute"
31
+ x="50%" y="0px"
32
+ tf="translateX(-50%)"
33
+ h="100%"
34
+ color={spincolor}
35
+ />
36
+ {/if}
37
+ </async-button>
@@ -45,8 +45,8 @@
45
45
  <slot />
46
46
  </div>
47
47
  {:else}
48
- <Button compact r="0px" color="primary" fill={$context.fillHeader}
49
- t.wt="inherit" on:click={setSort}>
48
+ <Button compact r="0px" fill={$context.fillHeader}
49
+ t.wt="inherit" on:click={setSort} color={$context.color}>
50
50
  <slot />
51
51
  <Icon name={sortIcon} m.l="4px" t.sz="16px" />
52
52
  </Button>
@@ -51,7 +51,7 @@
51
51
  import wsx from "../wsx.mjs"
52
52
  import { handler$, eventHandler$ } from "../handler$.mjs"
53
53
 
54
- export let color = false
54
+ export let color = "@primary"
55
55
  export let fillHeader = true
56
56
  export let data
57
57
  export let pageSize = 10
@@ -65,7 +65,7 @@
65
65
  let filterFunctions = []
66
66
  let jumpTarget = "1"
67
67
 
68
- $: filteredData = applyFilters(data, filterFunctions)
68
+ $: filteredData = applyFilters(data, filterFunctions, sorting.func)
69
69
  $: rows = sliceData(filteredData, page, pageSize, sorting.func)
70
70
  $: rowCount = filteredData?.length ?? 0
71
71
  $: pageCount = Math.ceil(rowCount / pageSize)
@@ -114,6 +114,7 @@
114
114
  fillHeader,
115
115
  sorting,
116
116
  updateFilter,
117
+ color,
117
118
  }
118
119
  setContext(dtContext, context)
119
120
 
@@ -156,7 +157,7 @@
156
157
  }
157
158
  </script>
158
159
 
159
- <Paper {color} h={height}>
160
+ <Paper {color} h={height} card>
160
161
  <ws-flex use:wsx={content} slot="content" bind:this={scroller}>
161
162
  <Table data={rows} {color} {fillHeader} {...$$restProps} b.t.w="0px">
162
163
  <tr use:wsx={header} slot="header">
@@ -0,0 +1,60 @@
1
+ <script context="module">
2
+ const identity = i => i
3
+ const alwaysGood = () => true
4
+ </script>
5
+
6
+ <script>
7
+ import Input from "../control/input.svelte"
8
+
9
+ export let fields
10
+ export let values
11
+ export let valid = {}
12
+
13
+ const refs = fields.reduce(
14
+ (refs, field) => {
15
+ refs[field.name] = {
16
+ vt: field.value.transform ?? identity,
17
+ t: field.value.out ?? identity,
18
+ v: field.value.validate ?? alwaysGood,
19
+ e: (value) => {
20
+ if (valid[field.name] !== false) {
21
+ return null
22
+ }
23
+ return field.value.error?.(value) ?? null
24
+ }
25
+ }
26
+ return refs
27
+ },
28
+ {}
29
+ )
30
+ let internal = fields.reduce(
31
+ (initial, field) => {
32
+ initial[field.name] = field.value.initial ?? ""
33
+ return initial
34
+ },
35
+ {}
36
+ )
37
+ let value = new Proxy(
38
+ {},
39
+ {
40
+ get(_, name) {
41
+ return internal[name]
42
+ },
43
+ set(_, name, value) {
44
+ const ref = refs[name]
45
+ internal[name] = ref.vt(value)
46
+ values = { ...values, [name]: ref.t(internal[name]) }
47
+ valid = { ...valid, [name]: ref.v(values[name]) }
48
+ return true
49
+ }
50
+ }
51
+ )
52
+ </script>
53
+
54
+ {#each fields as field}
55
+ <Input
56
+ {...field.props}
57
+ bind:value={value[field.name]}
58
+ error={refs[field.name].e(value[field.name])}
59
+ />
60
+ {/each}
@@ -9,5 +9,7 @@ export const sorts = {
9
9
  natural: (propName) => {
10
10
  const comparitor = new Intl.Collator(undefined, { numeric: true })
11
11
  return (a, b) => comparitor.compare(a[propName], b[propName])
12
- }
12
+ },
13
+ number: (propName) =>
14
+ (a, b) => a[propName] - b[propName]
13
15
  }
@@ -1,43 +1,13 @@
1
1
  <script>
2
- /*md
3
- [@] Components/ToastMessage
4
-
5
- # ToastMessage
6
-
7
- The default component for Toast to show messages with
8
-
9
- ## Props
10
-
11
- ### actionText
12
- `string`
13
-
14
- If given, the message will have a button that can be clicked and will
15
- use this text for the button text
16
-
17
- ### color
18
- `string`
19
-
20
- Sets `$color`
21
-
22
- ### icon
23
- `string`
24
-
25
- An icon to show with the message
26
-
27
- ### message
28
- `string`
29
-
30
- The message to show
31
- */
32
-
33
2
  import { createEventDispatcher } from "svelte"
34
3
 
35
4
  import Button from "../../control/button.svelte"
36
5
  import Icon from "../../info/icon.svelte"
37
6
  import Notification from "../../info/notification.svelte"
7
+ import Text from "../../text.svelte"
38
8
 
39
9
  export let message = ""
40
- export let icon = ""
10
+ export let icon = false
41
11
  export let color = false
42
12
  export let actionText = null
43
13
 
@@ -47,10 +17,17 @@
47
17
  </script>
48
18
 
49
19
  <Notification {color} on:click={dismiss}>
50
- <Icon name={icon}>{message}</Icon>
51
- {#if actionText}
52
- <Button {color} variant="fill" on:click={respond}>
53
- {actionText}
54
- </Button>
55
- {/if}
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>
56
33
  </Notification>
@@ -1,21 +1,5 @@
1
1
  <svelte:options immutable />
2
2
 
3
- <script context="module">
4
- const parseNumeric = (value) => {
5
- if (value === "") {
6
- return null
7
- }
8
- return parseFloat(value)
9
- }
10
-
11
- const diff = (type, value, internal) => {
12
- if ((type !== "number" && type !== "range") || typeof value === "string") {
13
- return value !== internal
14
- }
15
- return parseFloat(internal) !== value
16
- }
17
- </script>
18
-
19
3
  <script>
20
4
  import wsx from "../wsx.mjs"
21
5
 
@@ -24,20 +8,12 @@
24
8
  export let flat = false
25
9
  export let label
26
10
  export let color = "@default"
27
- export let error = null
28
- export let hint = null
29
11
  export let disabled
30
12
 
31
13
  export let value = ""
32
14
  export let autocompleteOptions = null
33
15
 
34
- export let transform = i => i
35
- export let tvalue
36
- export let validate = () => true
37
- export let valid
38
-
39
16
  let input = null
40
- let internalValue = value
41
17
  export const focus = () => input.focus()
42
18
 
43
19
  const id =
@@ -45,17 +21,7 @@
45
21
  ? null
46
22
  : `${Math.random().toString(16)}_${Date.now()}`
47
23
 
48
- $: isNumeric = (type === "number" || type === "range")
49
- $: if (diff(type, value, internalValue) === true) {
50
- internalValue = value
51
- }
52
-
53
- const update = (evt) => {
54
- internalValue = evt.target.value
55
- value = (isNumeric === true) ? parseNumeric(internalValue) : internalValue
56
- tvalue = transform(value)
57
- valid = validate(tvalue)
58
- }
24
+ const update = (evt) => value = evt.target.value
59
25
 
60
26
  $: restKeys = Object.keys($$restProps)
61
27
  $: props = restKeys.reduce(
@@ -72,7 +38,7 @@
72
38
 
73
39
  $: wind = {
74
40
  "$flat": flat,
75
- "@control": true,
41
+ "@@control": true,
76
42
  "$color": color,
77
43
  ...props.wind,
78
44
  }
@@ -80,16 +46,16 @@
80
46
  $: tag = (type === "area") ? "textarea" : "input"
81
47
  </script>
82
48
 
83
- <label use:wsx={wind} ws-error={error}>
49
+ <label use:wsx={wind}>
84
50
  {#if label}
85
- <span use:wsx={{ slot: "label-text" }} ws-hint={hint}>{label}</span>
51
+ <span use:wsx={{ "$label": true }}>{label}</span>
86
52
  {/if}
87
53
  <svelte:element
88
54
  this={tag}
89
55
  {...props.input}
90
56
  {disabled}
91
57
  {type}
92
- value={internalValue}
58
+ {value}
93
59
  list={id}
94
60
  on:focus
95
61
  on:blur
@@ -97,8 +63,22 @@
97
63
  bind:this={input}
98
64
  />
99
65
 
100
- <slot name="start" />
101
- <slot name="end" />
66
+ {#if $$slots.start}
67
+ <span use:wsx={{ "$start": true }}>
68
+ <slot name="start" />
69
+ </span>
70
+ {/if}
71
+ {#if $$slots.end}
72
+ <span use:wsx={{ "$end": true }}>
73
+ <slot name="end" />
74
+ </span>
75
+ {/if}
76
+ {#if $$slots.extra}
77
+ <span use:wsx={{ "$extra": true }}>
78
+ <slot name="extra" />
79
+ </span>
80
+ {/if}
81
+
102
82
  {#if autocompleteOptions !== null}
103
83
  <datalist {id}>
104
84
  {#each autocompleteOptions as value}
@@ -20,7 +20,7 @@
20
20
  $: baseStyles =
21
21
  (button === true)
22
22
  ? {
23
- "@button": true,
23
+ "@@button": true,
24
24
  [type]: true,
25
25
  "$color": color,
26
26
  $compact: compact,
@@ -20,7 +20,7 @@
20
20
  $: type = variant({ fill, outline, flat })
21
21
 
22
22
  $: wind = {
23
- "@button": button,
23
+ "@@button": button,
24
24
  [type]: true,
25
25
  "$color": color,
26
26
  ...$$restProps
@@ -0,0 +1,21 @@
1
+ <svelte:options immutable />
2
+
3
+ <script>
4
+ import wsx from "../wsx.mjs"
5
+ import { handler$ } from "../handler$.mjs"
6
+
7
+ import Flex from "../layout/flex.svelte"
8
+
9
+ export let options = []
10
+ export let layout = Flex
11
+ export let value
12
+ </script>
13
+
14
+ <svelte:component this={layout} {...$$restProps}>
15
+ {#each options as {value: itemValue, label, disabled, ...wind}, index (value)}
16
+ <label use:wsx={{"@@toggle": true, ...wind}} {disabled}>
17
+ <span>{label}</span>
18
+ <input type="radio" value={itemValue} bind:group={value} />
19
+ </label>
20
+ {/each}
21
+ </svelte:component>
@@ -21,8 +21,8 @@
21
21
 
22
22
  export let options = []
23
23
  export let value
24
- export let color = "default"
25
- export let outline = false
24
+ export let color = "@default"
25
+ export let flat = false
26
26
  export let label = null
27
27
  export let disabled = false
28
28
 
@@ -33,8 +33,8 @@
33
33
  $: grouped = groupOptions(options)
34
34
 
35
35
  $: wind = {
36
- "@control": true,
37
- "$outline": outline,
36
+ "@@control": true,
37
+ "$flat": flat,
38
38
  "$color": color,
39
39
  ...$$restProps,
40
40
  }
@@ -42,7 +42,7 @@
42
42
 
43
43
  <label use:wsx={wind}>
44
44
  {#if label}
45
- <span ws-x="[$label-text]">{label}</span>
45
+ <span ws-x="[$label]">{label}</span>
46
46
  {/if}
47
47
  <select value={indexValue} on:input={update} {disabled}>
48
48
  {#each grouped as item, index}
@@ -1,28 +1,19 @@
1
1
  <svelte:options immutable />
2
2
 
3
3
  <script>
4
+ import { writable } from "svelte/store"
5
+
4
6
  import wsx from "../wsx.mjs"
5
7
  import { handler$ } from "../handler$.mjs"
6
8
 
7
- export let color = "@primary"
9
+ export let color = "@default"
8
10
  export let options = []
9
11
  export let vertical = false
10
- export let solid = false
12
+ export let fill = false
11
13
  export let value
12
14
 
13
- $: index = options.findIndex(item => item.value === value)
14
-
15
- const set = handler$(
16
- (next) => {
17
- if (value === next) {
18
- return
19
- }
20
- value = next
21
- }
22
- )
23
-
24
15
  $: wind = {
25
- "$solid": solid,
16
+ "$fill": fill,
26
17
  "$color": color,
27
18
  $vert: vertical,
28
19
  ...$$restProps,
@@ -32,12 +23,9 @@
32
23
  <!-- svelte-ignore a11y-click-events-have-key-events -->
33
24
  <ws-tabs use:wsx={wind} role="tablist">
34
25
  {#each options as tab, i}
35
- <!-- svelte-ignore a11y-interactive-supports-focus -->
36
- <ws-tab use:wsx={{"$tab-selected": index === i}}
37
- on:click={set(tab.value)} role="tab">
38
- <slot {tab} selected={index === i}>
39
- {tab.label}
40
- </slot>
41
- </ws-tab>
26
+ <label>
27
+ <input type="radio" value={tab.value} bind:group={value} />
28
+ <ws-tab>{tab.label}</ws-tab>
29
+ </label>
42
30
  {/each}
43
31
  </ws-tabs>
@@ -13,14 +13,14 @@
13
13
  export let reverse = false
14
14
 
15
15
  $: container = {
16
- "@toggle": true,
16
+ "@@toggle": true,
17
17
  "$flat": flat,
18
18
  "$color": color,
19
19
  "fl.dir": reverse ? "row-reverse" : false,
20
20
  ...$$restProps,
21
21
  }
22
22
  $: input = {
23
- "@switch": checkbox === false
23
+ "@@switch": checkbox === false
24
24
  }
25
25
 
26
26
  const updateGroup = (checked) => {
@@ -18,7 +18,10 @@
18
18
 
19
19
  <ws-avatar use:wsx={wind}>
20
20
  {#if image !== null}
21
- <img src={image} {alt} />
21
+ <!-- svelte-ignore a11y-missing-attribute -->
22
+ <object data={image} type="image/png">
23
+ {alt}
24
+ </object>
22
25
  {:else}
23
26
  {text}
24
27
  {/if}
@@ -3,7 +3,7 @@
3
3
  <script>
4
4
  import wsx from "../wsx.mjs"
5
5
 
6
- export let color = "@default"
6
+ export let color = null
7
7
  export let text = ""
8
8
 
9
9
  $: wind = { "$color": color, ...$$restProps }
@@ -16,7 +16,7 @@
16
16
  $: wind = {
17
17
  [type]: true,
18
18
  "$color": color,
19
- $click: clickable,
19
+ "@@click": clickable,
20
20
  ...$$restProps
21
21
  }
22
22
  </script>
@@ -18,7 +18,7 @@
18
18
  <ws-popover use:wsx={wind}>
19
19
  <slot {show} />
20
20
  {#if visible}
21
- <wind-content slot="content" ws-x="[inset 0px]" transition:fade={anim}>
21
+ <wind-content ws-x="[$content] [inset 0px]" transition:fade={anim}>
22
22
  <slot name="content" {hide} />
23
23
  </wind-content>
24
24
  {/if}
@@ -11,7 +11,7 @@
11
11
  export let label = null
12
12
 
13
13
  $: wind = {
14
- "@progress": true,
14
+ "@@progress": true,
15
15
  "$outline": outline,
16
16
  "$color": color,
17
17
  $row: row,
@@ -21,7 +21,7 @@
21
21
 
22
22
  <label use:wsx={wind}>
23
23
  {#if label}
24
- <span ws-x="[$progress-label] [t-ws nowrap]">{label}</span>
24
+ <span ws-x="[$progress-label] [t.ws nowrap]">{label}</span>
25
25
  {/if}
26
26
  <progress {value} {max} />
27
27
  </label>
@@ -3,7 +3,7 @@
3
3
  <script>
4
4
  import wsx from "../wsx.mjs"
5
5
 
6
- export let color = false
6
+ export let color = "@default"
7
7
  export let fillHeader = false
8
8
  export let data = []
9
9
 
@@ -34,11 +34,11 @@
34
34
  {message}
35
35
  </Text>
36
36
 
37
- <Grid cols="1fr 1fr" slot="footer" pad="0px">
38
- <Button on:click={cls(false)} color="danger">
37
+ <Grid cols="1fr 1fr" slot="footer" p="0px">
38
+ <Button on:click={cls(false)} color="@danger">
39
39
  {cancelText}
40
40
  </Button>
41
- <Button on:click={cls(true)} color="secondary">
41
+ <Button on:click={cls(true)} color="@secondary">
42
42
  {okText}
43
43
  </Button>
44
44
  </Grid>
package/src/hash.js CHANGED
@@ -3,9 +3,9 @@ import { readable } from "svelte/store"
3
3
  export const hash = readable(
4
4
  location.hash.slice(1),
5
5
  (set) => {
6
- setInterval(
7
- () => set(location.hash.slice(1)),
8
- 50
6
+ window.addEventListener(
7
+ "popstate",
8
+ () => set(location.hash.slice(1))
9
9
  )
10
10
  }
11
11
  )