@axel669/zephyr 0.2.0-beta.3 → 0.3.4-beta.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 (47) hide show
  1. package/package.json +2 -2
  2. package/readme.md +4 -4
  3. package/src/async/button.md +27 -0
  4. package/src/async/button.svelte +2 -4
  5. package/src/async/load-zone.md +42 -0
  6. package/src/async/load-zone.svelte +3 -1
  7. package/src/composed/data-table/th.md +21 -0
  8. package/src/composed/data-table/th.svelte +2 -2
  9. package/src/composed/data-table.md +68 -67
  10. package/src/composed/data-table.svelte +66 -16
  11. package/src/composed/entry-button.md +23 -13
  12. package/src/composed/toast.md +30 -21
  13. package/src/composed/toast.svelte +1 -1
  14. package/src/control/input.md +87 -0
  15. package/src/control/input.svelte +3 -3
  16. package/src/control/label.md +0 -1
  17. package/src/control/label.svelte +1 -1
  18. package/src/control/link.svelte +4 -2
  19. package/src/control/radio.svelte +1 -1
  20. package/src/control/select.svelte +2 -2
  21. package/src/control/tabs.svelte +4 -2
  22. package/src/control/toggle.svelte +3 -3
  23. package/src/data-display/badge.svelte +1 -1
  24. package/src/data-display/chip.svelte +1 -1
  25. package/src/data-display/details.md +40 -1
  26. package/src/data-display/details.svelte +1 -1
  27. package/src/data-display/popover.svelte +1 -1
  28. package/src/data-display/progress.svelte +2 -2
  29. package/src/data-display/table.md +56 -4
  30. package/src/dialogs/alert.md +40 -1
  31. package/src/dialogs/alert.svelte +1 -1
  32. package/src/dialogs/confirm.md +54 -1
  33. package/src/dialogs/confirm.svelte +1 -1
  34. package/src/functions.md +25 -0
  35. package/src/hash.js +14 -0
  36. package/src/index.mjs +2 -1
  37. package/src/inline-dialog.svelte +1 -1
  38. package/src/layout/dialog.svelte +1 -1
  39. package/src/layout/drawer.svelte +3 -3
  40. package/src/layout/flex.svelte +2 -0
  41. package/src/layout/grid.svelte +2 -0
  42. package/src/layout/modal.svelte +1 -1
  43. package/src/layout/screen.svelte +2 -2
  44. package/src/spinner/circle-spinner.svelte +2 -2
  45. package/src/spinner/hexagon-spinner.svelte +2 -2
  46. package/src/spinner/spinners.md +20 -1
  47. package/src/wsx.mjs +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@axel669/zephyr",
3
- "version": "0.2.0-beta.3",
3
+ "version": "0.3.4-beta.0",
4
4
  "description": "",
5
5
  "main": "src/index.mjs",
6
6
  "type": "module",
@@ -12,7 +12,7 @@
12
12
  "author": "",
13
13
  "license": "MIT",
14
14
  "dependencies": {
15
- "@axel669/windstorm": "0.2.3"
15
+ "@axel669/windstorm": "0.3.4"
16
16
  },
17
17
  "devDependencies": {
18
18
  "@axel669/ipsen": "0.4.0-beta.7",
package/readme.md CHANGED
@@ -8,14 +8,14 @@ library, with some additional parts to make it look nice in the markup.
8
8
  Zephyr can be installed through npm (or the variants like yarn, pnpm, etc).
9
9
 
10
10
  ```bash
11
- npm install @axel669/zephyr@0.2.0-beta.1
11
+ npm install @axel669/zephyr
12
12
  ```
13
13
 
14
14
  ## Components
15
15
  Components can be imported individually from the library for tree-shaking, or
16
16
  the entire lib can imported at once, but I dunno how big that bundle will be.
17
- Components can also take any windstorm function as a prop, using the same rules
18
- as the `wsx` action.
17
+ Components can also take any windstorm macro as a prop, including custom macros,
18
+ using the same rules as the `wsx` covered in [Functions](./src/functions.md).
19
19
 
20
20
  ### Theming
21
21
  Windstorm expects a theme to be defined on an ancestor of the html elements
@@ -43,7 +43,7 @@ Windstorm theme is usable, including custom ones.
43
43
  </script>
44
44
 
45
45
  <!-- the wsx action can be used to setup the ws-x needed for the body -->
46
- <svelte:body use:wsx={{"$theme": theme, "$app": true}} />
46
+ <svelte:body use:wsx={{"@theme": theme, "@app": true}} />
47
47
 
48
48
  <Button on:click={handler}>
49
49
  I'm a button!
@@ -0,0 +1,27 @@
1
+ # AsyncButton
2
+ A button that makes it simpler to fire off async functions in response to button
3
+ clicks. In addition to calling the function, the button will disable itself
4
+ during the function duration and show a load spinner inside the button.
5
+
6
+ ## Props
7
+ The AsyncButton supports all of the [Button](../control/button.md) props.
8
+
9
+ ### handler
10
+ The async function to call when the button is clicked.
11
+
12
+ ## Example
13
+
14
+ ```svelte
15
+ <script>
16
+ import { AsyncButton } from "@axel669/zephyr"
17
+
18
+ const load = async () => {
19
+ const res = await fetch(someURL)
20
+ console.log(await res.text())
21
+ }
22
+ </script>
23
+
24
+ <AsyncButton handler={load} color="@primary">
25
+ Load Things
26
+ </AsyncButton>
27
+ ```
@@ -4,7 +4,6 @@
4
4
 
5
5
  export let handler = null
6
6
  export let disabled
7
- export let inactiveProps = null
8
7
 
9
8
  let running = false
10
9
  const asyncHandler = async (evt) => {
@@ -13,16 +12,15 @@
13
12
  running = false
14
13
  }
15
14
 
16
- $: inactive = (typeof disabled === "boolean") ? disabled : running
15
+ $: inactive = disabled || running
17
16
  $: props = {
18
17
  ...$$restProps,
19
- ...(running === false ? null : inactiveProps),
20
18
  disabled: inactive,
21
19
  }
22
20
  </script>
23
21
 
24
22
  <Button {...props} on:click={asyncHandler}>
25
- <div ws-x="h[20px] m.r:not(:empty)[4px]">
23
+ <div ws-x="[h 20px] [m.r:not(:empty) 4px]">
26
24
  {#if running === true}
27
25
  <Spinner size="20px" />
28
26
  {/if}
@@ -0,0 +1,42 @@
1
+ # LoadZone
2
+ A component for putting content that is behind an async function.
3
+
4
+ ## Props
5
+
6
+ ### message
7
+ The text to show while the promise is pending.
8
+
9
+ ### source
10
+ `Promise`
11
+
12
+ The promise that will resolve into some kind of content-related information.
13
+
14
+ ## Slots
15
+
16
+ ### default
17
+ The default slot will be shown when the promise resolves.
18
+
19
+ ### loading
20
+ The content to show while the promise is pending. Overrides the default of a
21
+ load spinner with some text.
22
+
23
+ ### error
24
+ The content to show when the promise rejects. Use `let:error` to get the error
25
+ that was thrown.
26
+
27
+ ## Example
28
+
29
+ ```svelte
30
+ <LoadZone source={asyncThing} let:result>
31
+ <div>
32
+ content
33
+ </div>
34
+ <div>
35
+ {JSON.stringify(result)}
36
+ </div>
37
+
38
+ <div slot="error">
39
+ :(
40
+ </div>
41
+ </LoadZone>
42
+ ```
@@ -9,12 +9,14 @@
9
9
  {#if source !== null}
10
10
  {#await source}
11
11
  <slot name="loading">
12
- <ws-flex ws-x="fl.cross[center] fl.main[center]">
12
+ <ws-flex ws-x="[fl-center]">
13
13
  <span>{message}</span>
14
14
  <Spinner size="100px" />
15
15
  </ws-flex>
16
16
  </slot>
17
17
  {:then result}
18
18
  <slot {result} />
19
+ {:catch error}
20
+ <slot name="error" {error} />
19
21
  {/await}
20
22
  {/if}
@@ -0,0 +1,21 @@
1
+ # TH
2
+
3
+ The TH component has no use outside fo the DataTable, but is used to support
4
+ the filter and sorting functionality for that component.
5
+
6
+ ## Props
7
+
8
+ ### sort
9
+ `Function`
10
+
11
+ The sorting function to use for the column defined. Should return values that
12
+ match the expected values for `Array.sort`.
13
+
14
+ ### filter
15
+ `Function`
16
+
17
+ The function to use for filtering based on the column. The function is given
18
+ 2 arguments: a row of data and the text from the filter input field. The
19
+ function should return `true` if the item should be shown. A filter function on
20
+ a specific column does not need to only look at the specified column, but not
21
+ doing could cause confusion for users without proper context.
@@ -41,7 +41,7 @@
41
41
  <th use:wsx={wind} style="vertical-align: top;">
42
42
  <Grid rows="40px min-content" p="0px" gap="0px">
43
43
  {#if sort === null}
44
- <div ws-x="flex fl.cross[center] fl.main[center]">
44
+ <div ws-x="[flex] [fl.cross center] [fl.main center]">
45
45
  <slot />
46
46
  </div>
47
47
  {:else}
@@ -54,7 +54,7 @@
54
54
  {#if filter !== null}
55
55
  <Grid gap="0px" p="0px" cols="min-content 1fr">
56
56
  <Icon name="filter" />
57
- <input type="text" ws-x="w.min[20px] outline:focus[none]" bind:value />
57
+ <input type="text" ws-x="[w.min 20px] [outline:focus none]" bind:value />
58
58
  </Grid>
59
59
  {/if}
60
60
  </Grid>
@@ -1,85 +1,86 @@
1
- NOTE: include Th as its own component
2
-
3
1
  # DataTable
4
2
 
5
3
  The DataTable is a more advanced way to show data on screen. Underneath is
6
- a table element like the Table component, but the DataTable supports
7
- more fine-grained control over how data is passed, how rows are displayed,
8
- and pagination.
4
+ a [Table](../data-display/table.md) component, but with additional functionality
5
+ for pagination, sorting, and fitering.
9
6
 
10
7
  > If pagination is not needed, the DataTable may not be necessary as it will
11
8
  > only be shortcutting data formatting at that point.
12
9
 
13
10
  ## Props
14
- All [windstorm functions](https://axel669.github.io/lib.windstorm/#css-shorthands)
15
- are supported.
16
11
 
17
- - ### color
18
- Sets `$color`
12
+ ### color
13
+ Sets `$color`
19
14
 
20
- ### cols
15
+ ### data
21
16
  `Array`
22
17
 
23
- The columns that should be displayed. Should be in the format of
24
- `{ label, width?, format?, prop? }`. If a format function is provided,
25
- it is called on each cell to determine a cells value as
26
- `format(rowItem)`, otherwise the property defined in prop will be used
27
- as the cell value.
18
+ The data to display. Each item in the array can be in either the same
19
+ format as the Table, or any kind of object if column format functions
20
+ are used.
28
21
 
29
- ### data
30
- `Array`
22
+ ### page
23
+ `Number`
24
+
25
+ The current page of data being viewed. Can be bound, or set to control
26
+ which page is displayed
27
+
28
+ ### pageSize
29
+ `Number`
30
+
31
+ The number of items to show on each page. Default is 10.
31
32
 
32
- The data to display. Each item in the array can be in either the same
33
- format as the Table, or any kind of object if column format functions
34
- are used.
35
-
36
- ### cellWSX
37
- `function`
38
-
39
- If given, this function will be called for each cell, and should return
40
- an object that will be passed to the `wsx` action for each <td>
41
- generated. The function is passed `(rowvalue, rowNum, col)`.
42
-
43
- ### rowWSX
44
- `function`
45
-
46
- If given, this function will be called for each row, and should return
47
- an object that will be passed to the `wsx` action for each <tr>
48
- generated. The function is passed `(rowValue, rowNum)`.
49
- - ### page
50
- The current page of data being viewed. Can be bound, or set to control
51
- which page is displayed
52
- - ### pageSize
53
- The number of items to show on each page. Default is 10
54
- - ### rowHeight
55
- The height of each row. Can be set individually through rowWSX, but
56
- that may lead to a degraded user experience if the rows change size
57
- while paging through the data
33
+ ### rowHeight
34
+ The height of each row. The component uses this to make empty rows the same
35
+ height as rows with data so that the pagination doesnt randomly resize the
36
+ visual area of the table.
37
+
38
+ ## Slots
39
+
40
+ ### header
41
+ A fragment that should contain the header cells for the table header. A standard
42
+ `th` can be used, but the [TH](./data-table/th.md) element from zephyr has
43
+ additional configuration to handle more complex header-related actions.
44
+
45
+ ### row
46
+ A fragment that should use regular `td` elements to define how a row should be
47
+ layed out. The fragment will need `let:row` to access each row's data for
48
+ displaying it.
58
49
 
59
50
  ## Example
60
- ```js
61
- let page
62
- const cols = [
63
- { label: "N", prop: "a" },
64
- { label: "Squared", prop: "b" },
65
- { label: "Cubed", format: row => `^3 = ${row.c}` },
66
- ]
67
- const data = [
68
- { a: 1, b: 1 ** 2, c: 1 ** 3 },
69
- { a: 2, b: 2 ** 2, c: 2 ** 3 },
70
- { a: 3, b: 3 ** 2, c: 3 ** 3 },
71
- { a: 4, b: 4 ** 2, c: 4 ** 3 },
72
- { a: 5, b: 5 ** 2, c: 5 ** 3 },
73
- { a: 6, b: 6 ** 2, c: 6 ** 3 },
74
- { a: 7, b: 7 ** 2, c: 7 ** 3 },
75
- { a: 8, b: 8 ** 2, c: 8 ** 3 },
76
- { a: 9, b: 9 ** 2, c: 9 ** 3 },
77
- { a: 10, b: 10 ** 2, c: 10 ** 3 },
78
- { a: 11, b: 11 ** 2, c: 11 ** 3 },
79
- { a: 12, b: 12 ** 2, c: 12 ** 3 },
80
- { a: 13, b: 13 ** 2, c: 13 ** 3 },
81
- ]
82
- ```
83
51
  ```svelte
84
- <DataTable {cols} {data} color="warning" pageSize={3} bind:page />
52
+ <script>
53
+ import { DataTable, TH, sorts } from "@axel669/zephyr"
54
+
55
+ let page
56
+ const data = [
57
+ { a: 1, b: 1 ** 2, c: 1 ** 3 },
58
+ { a: 2, b: 2 ** 2, c: 2 ** 3 },
59
+ { a: 3, b: 3 ** 2, c: 3 ** 3 },
60
+ { a: 4, b: 4 ** 2, c: 4 ** 3 },
61
+ { a: 5, b: 5 ** 2, c: 5 ** 3 },
62
+ { a: 6, b: 6 ** 2, c: 6 ** 3 },
63
+ { a: 7, b: 7 ** 2, c: 7 ** 3 },
64
+ { a: 8, b: 8 ** 2, c: 8 ** 3 },
65
+ { a: 9, b: 9 ** 2, c: 9 ** 3 },
66
+ { a: 10, b: 10 ** 2, c: 10 ** 3 },
67
+ { a: 11, b: 11 ** 2, c: 11 ** 3 },
68
+ { a: 12, b: 12 ** 2, c: 12 ** 3 },
69
+ { a: 13, b: 13 ** 2, c: 13 ** 3 },
70
+ ]
71
+ </script>
72
+
73
+ <DataTable {cols} {data} color="warning" pageSize={3} bind:page>
74
+ <svelte:fragment slot="header">
75
+ <TH sort={sorts.natural}>N</TH>
76
+ <th>Squared</th>
77
+ <th>Cubed</th>
78
+ </svelte:fragment>
79
+
80
+ <svelte:fragment slot="row" let:row>
81
+ <td>{row.a}</td>
82
+ <td>{row.b}</td>
83
+ <td>^3 = {row.c}</td>
84
+ </svelte:fragment>
85
+ </DataTable>
85
86
  ```
@@ -57,16 +57,20 @@
57
57
  export let pageSize = 10
58
58
  export let page = 0
59
59
  export let rowHeight = "40px"
60
+ export let scrollable = false
61
+ export let height = null
60
62
 
61
63
  let sorting = noSort
62
64
  let filters = new Map()
63
65
  let filterFunctions = []
66
+ let jumpTarget = "1"
64
67
 
65
68
  $: filteredData = applyFilters(data, filterFunctions)
66
69
  $: rows = sliceData(filteredData, page, pageSize, sorting.func)
67
70
  $: rowCount = filteredData?.length ?? 0
68
71
  $: pageCount = Math.ceil(rowCount / pageSize)
69
72
  $: maxPage = Math.max(pageCount - 1, 0)
73
+ $: jumpTarget = (page + 1).toString()
70
74
 
71
75
  $: if (filteredData === null) {
72
76
  console.warn("DataTable: data is not an array")
@@ -117,23 +121,59 @@
117
121
  const pass = handler$(
118
122
  (row) => fire("row-click", row)
119
123
  )
124
+
125
+ let scroller = null
126
+ $: if (scroller !== null && isNaN(page) === false) {
127
+ scroller.scrollTop = 0
128
+ }
129
+ const jump = (evt) => {
130
+ if (evt.type === "keypress" && evt.key !== "Enter") {
131
+ return
132
+ }
133
+ const target = parseInt(evt.target.value)
134
+ if (isNaN(target) === true) {
135
+ jumpTarget = (page + 1).toString()
136
+ return
137
+ }
138
+ page = Math.max(
139
+ Math.min(jumpTarget - 1, maxPage),
140
+ 0
141
+ )
142
+ jumpTarget = (page + 1).toString()
143
+ }
144
+
145
+ $: content = {
146
+ "fl.cross": "stretch",
147
+ p: "0px",
148
+ gap: "0px",
149
+ over: (scrollable === true) ? "auto" : null,
150
+ }
151
+ $: header = {
152
+ "h.min": rowHeight,
153
+ y: "0px",
154
+ z: "+10",
155
+ pos: (scrollable === true) ? "sticky" : null,
156
+ }
120
157
  </script>
121
158
 
122
- <Paper card {color} l-fl.cross="stretch" l-p="0px">
123
- <Table data={rows} {color} {fillHeader} {...$$restProps}>
124
- <tr ws-x="h.min[{rowHeight}]" slot="header">
125
- <slot name="header">
126
- <th>No Header Defined</th>
127
- </slot>
128
- </tr>
129
- <tr ws-x="h[{rowHeight}]" slot="row" let:row>
130
- <slot name="row" {row}>
131
- <th>No Row Defined</th>
132
- </slot>
133
- </tr>
134
- <tr ws-x="h[{rowHeight}]" slot="empty-row" />
135
- </Table>
136
- <Grid slot="footer" gr.cols="min-content min-content min-content 1fr">
159
+ <Paper {color} h={height}>
160
+ <ws-flex use:wsx={content} slot="content" bind:this={scroller}>
161
+ <Table data={rows} {color} {fillHeader} {...$$restProps} b.t.w="0px">
162
+ <tr use:wsx={header} slot="header">
163
+ <slot name="header">
164
+ <th>No Header Defined</th>
165
+ </slot>
166
+ </tr>
167
+ <tr ws-x="[h {rowHeight}]" slot="row" let:row>
168
+ <slot name="row" {row}>
169
+ <th>No Row Defined</th>
170
+ </slot>
171
+ </tr>
172
+ <tr ws-x="[h {rowHeight}]" slot="empty-row" />
173
+ </Table>
174
+ </ws-flex>
175
+ <Grid slot="footer" gr.cols="min-content min-content min-content 1fr"
176
+ rows="32px" b="1px solid @color" b.b.w="4px">
137
177
  {#if pageCount > 0}
138
178
  <Button on:click={prev} disabled={page === 0}>
139
179
  <Icon name="arrow-big-left" />
@@ -142,8 +182,18 @@
142
182
  <Icon name="arrow-big-right" />
143
183
  </Button>
144
184
  <Text adorn t.ws="nowrap">
145
- Page {page + 1} / {pageCount}
185
+ Page
186
+ <input ws-x="[b 1px solid @text-color-normal] [w 36px] [r 4px]
187
+ [h 24px] [bg.c transaprent] [t.a center] [m.l 4px] [m.r 4px]"
188
+ type="text" bind:value={jumpTarget}
189
+ on:keypress={jump} on:blur={jump} />
190
+ / {pageCount}
146
191
  </Text>
192
+ {:else}
193
+ <div ws-x="[col span 3] [p.l 4px]">
194
+ No data to show
195
+ </div>
147
196
  {/if}
197
+ <slot name="action" />
148
198
  </Grid>
149
199
  </Paper>
@@ -6,29 +6,39 @@ addition to the buttons that show them.
6
6
 
7
7
  ## Props
8
8
 
9
- - ### component
10
- The component to show when clicked
11
- - ### props
12
- The props to pass to the component when it is shown, or a function that
13
- generates the props when called
14
- - ### this
15
- The wrapper for the component. Default is Modal but any component that
16
- has the same interface as Modal will work
9
+ ### component
10
+ The component to show when clicked
11
+
12
+ ### props
13
+ The props to pass to the component when it is shown, or a function that
14
+ generates the props when called.
15
+
16
+ ### this
17
+ The wrapper for the component. Default is [Modal](../layout/modal.md) but any
18
+ component that has the same interface as Modal will work.
17
19
 
18
20
  ## Events
19
- - ### entry
20
- When the component is close the entry event is fired. The detail
21
- property of the event will have the value from closing it
21
+
22
+ ### entry
23
+ When the component is closed the entry event is fired. The detail
24
+ property of the event will have the value from closing it.
22
25
 
23
26
  ## Example
24
27
  ```svelte
28
+ <script>
29
+ const propsFunc = () => ({
30
+ now: Date.now(),
31
+ rand: Math.random(),
32
+ })
33
+ </script>
34
+
25
35
  <EntryButton component={Subscreen} on:entry={console.log}>
26
36
  Open Subscreen
27
37
  </EntryButton>
28
- <EntryButton component={CoolDialog} on:entry={console.log}>
38
+ <EntryButton component={CoolDialog} props={{ thing: true }} on:entry={console.log}>
29
39
  Open Subscreen
30
40
  </EntryButton>
31
- <EntryButton this={CoolModal} component={CustomThing} on:entry={console.log}>
41
+ <EntryButton this={CoolModal} component={CustomThing} on:entry={console.log} props={propsFunc}>
32
42
  Open Subscreen
33
43
  </EntryButton>
34
44
  ```
@@ -1,36 +1,45 @@
1
1
  # Toast
2
-
3
- Displays toast notifications along the edge of the screen.
2
+ Displays toast notifications along the edge of the screen. Unlike the Toaster
3
+ component, this has functions for interacting with and generating toast
4
+ messages, where the Toaster component has the programmer manage the content.
4
5
 
5
6
  ## Props
6
7
  See the Toaster component. The Toast component is wrapper around it that
7
8
  also controls the children being shown for convenience.
8
9
 
9
- - ### component
10
- The component to use as a wrapper for the messages. Defaults to the
11
- ToastMessage component.
10
+ ### component
11
+ The component to use as a wrapper for the messages. Defaults to the
12
+ ToastMessage component.
13
+
14
+ ### position
15
+ The position to show modals in. Uses the same positions as the Windstorm
16
+ toaster.
12
17
 
13
18
  ## Functions
14
- - ### show(duration, props)
15
- Shows a toast notification that will disappear after the specified
16
- duration (time in milliseconds). The props provided are passed to an
17
- instance of the component specified in the props.
19
+
20
+ ### show(duration, props)
21
+ Shows a toast notification that will disappear after the specified
22
+ duration (time in milliseconds). The props provided are passed to an
23
+ instance of the component specified in the props.
18
24
 
19
25
  ## Events
20
- - ### action(info)
21
- Fired when a toast message is clicked. The info argument contains a
22
- value property that is provided by the message component, and a copy
23
- of the props passed to that instace.\\
24
- For the default messages, the value will be `null` if no button was
25
- clicked, and `true` if the action button was clicked. This allows
26
- actions to be taken against interactions in the message without having
27
- to bind all kinds of events or callbacks.
26
+
27
+ ### action
28
+ Fired when a toast message is clicked. The info argument contains a
29
+ value property that is provided by the message component, and a copy
30
+ of the props passed to that instace.
31
+
32
+ For the default messages, the value will be `null` if no button was
33
+ clicked, and `true` if the action button was clicked. This allows
34
+ actions to be taken against interactions in the message without having
35
+ to bind all kinds of events or callbacks.
28
36
 
29
37
  ## Example
30
- ```js
31
- let toast = null
32
- const notify = () => toast.show(5000, { message: "hi" })
33
- ```
34
38
  ```svelte
39
+ <script>
40
+ let toast = null
41
+ const notify = () => toast.show(5000, { message: "hi" })
42
+ </script>
43
+
35
44
  <Toast bind:this={toast} position="bc" />
36
45
  ```
@@ -59,7 +59,7 @@
59
59
 
60
60
  <Toaster {position} {...$$restProps}>
61
61
  {#each items as {props, id} (id)}
62
- <zephyr-toast-wrapper ws-x="grid" transition:fade={{duration: 200}}>
62
+ <zephyr-toast-wrapper ws-x="[grid]" transition:fade={{duration: 200}}>
63
63
  <svelte:component
64
64
  this={component}
65
65
  {...props}