@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.
Files changed (58) hide show
  1. package/package.json +12 -10
  2. package/readme.md +8 -1
  3. package/src/async/button.svelte +17 -13
  4. package/src/async/suspend.svelte +38 -0
  5. package/src/changed.js +10 -0
  6. package/src/composed/data-table/th.svelte +2 -2
  7. package/src/composed/data-table.svelte +154 -180
  8. package/src/composed/entry-button.svelte +13 -16
  9. package/src/control/button.svelte +26 -22
  10. package/src/control/input.svelte +52 -50
  11. package/src/control/label.svelte +28 -24
  12. package/src/control/link.svelte +36 -30
  13. package/src/control/radio-group.svelte +13 -10
  14. package/src/control/select.svelte +21 -16
  15. package/src/control/tabs.svelte +18 -14
  16. package/src/control/toggle.svelte +33 -22
  17. package/src/custom-macros.js +9 -0
  18. package/src/data-display/avatar.svelte +12 -11
  19. package/src/data-display/badge.svelte +9 -7
  20. package/src/data-display/chip.svelte +27 -17
  21. package/src/data-display/details.svelte +22 -14
  22. package/src/data-display/popover.svelte +12 -9
  23. package/src/data-display/progress.svelte +17 -13
  24. package/src/data-display/table.svelte +29 -17
  25. package/src/data-display/tooltip.svelte +11 -9
  26. package/src/dialogs/alert.svelte +18 -12
  27. package/src/dialogs/confirm.svelte +22 -16
  28. package/src/{hash.js → hash.svelte.js} +9 -0
  29. package/src/{index.mjs → index.js} +10 -10
  30. package/src/{composed/element-toast.svelte → info/element-toaster.svelte} +41 -27
  31. package/src/info/icon.svelte +4 -4
  32. package/src/info/titlebar.svelte +20 -14
  33. package/src/info/toast.svelte +35 -0
  34. package/src/info/toaster/message.svelte +42 -0
  35. package/src/info/toaster.svelte +64 -6
  36. package/src/layout/dialog.svelte +10 -12
  37. package/src/layout/drawer.svelte +45 -18
  38. package/src/layout/flex.svelte +13 -11
  39. package/src/layout/grid.svelte +17 -15
  40. package/src/layout/modal.svelte +34 -26
  41. package/src/layout/paper.svelte +31 -33
  42. package/src/layout/screen.svelte +13 -9
  43. package/src/props.js +24 -0
  44. package/src/routing/route.svelte +29 -16
  45. package/src/routing/{routing.js → routing.svelte.js} +10 -1
  46. package/src/routing/title.svelte +8 -6
  47. package/src/spinner/circle-spinner.svelte +10 -8
  48. package/src/spinner/hexagon-spinner.svelte +10 -8
  49. package/src/text.svelte +6 -10
  50. package/src/wind.js +4 -0
  51. package/src/{wsx.mjs → wsx.js} +1 -1
  52. package/src/async/load-zone.svelte +0 -22
  53. package/src/composed/toast/message.svelte +0 -33
  54. package/src/composed/toast.svelte +0 -70
  55. package/src/info/notification.svelte +0 -28
  56. package/src/inline-dialog.svelte +0 -23
  57. /package/src/{handler$.mjs → handler$.js} +0 -0
  58. /package/src/{variant.mjs → variant.js} +0 -0
package/package.json CHANGED
@@ -1,24 +1,25 @@
1
1
  {
2
2
  "name": "@axel669/zephyr",
3
- "version": "0.4.7",
3
+ "version": "0.5.4",
4
4
  "description": "",
5
- "main": "src/index.mjs",
5
+ "main": "src/index.js",
6
6
  "type": "module",
7
7
  "scripts": {
8
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"
9
+ "site/build": "rollup -c docsite/rollup.config.js",
10
+ "site/watch": "rollup -c docsite/rollup.config.js --watch"
11
11
  },
12
12
  "keywords": [],
13
13
  "author": "",
14
14
  "license": "MIT",
15
15
  "dependencies": {
16
- "@axel669/rollup-copy-static": "^0.2.0",
17
- "@axel669/windstorm": "0.4.6"
16
+ "@axel669/windstorm": "0.5.4",
17
+ "svelte": "^5.9.0"
18
18
  },
19
19
  "devDependencies": {
20
20
  "@axel669/asuid": "^0.2.1",
21
21
  "@axel669/ipsen": "0.4.0-beta.7",
22
+ "@axel669/rollup-copy-static": "^0.2.0",
22
23
  "@axel669/rollup-html-input": "^0.1.2",
23
24
  "@rollup/plugin-node-resolve": "^15.0.2",
24
25
  "@rollup/plugin-terser": "^0.4.0",
@@ -27,14 +28,15 @@
27
28
  "prismjs": "^1.29.0",
28
29
  "rollup": "^3.20.2",
29
30
  "rollup-plugin-delete": "^2.0.0",
30
- "rollup-plugin-svelte": "^7.1.6",
31
- "svelte": "^4.2.7"
31
+ "rollup-plugin-svelte": "^7.2.2"
32
32
  },
33
33
  "files": [
34
34
  "src/"
35
35
  ],
36
36
  "imports": {
37
- "#lib": "./src/index.mjs",
38
- "#comp/*": "./docsite/comp/*.svelte"
37
+ "#lib": "./src/index.js",
38
+ "#comp/*": "./docsite/comp/*.svelte",
39
+ "#state/*": "./docsite/state/*.js",
40
+ "#README": "./readme.md"
39
41
  }
40
42
  }
package/readme.md CHANGED
@@ -4,6 +4,12 @@ library, with some additional parts to make it look nice in the markup.
4
4
 
5
5
  [Docs Here](https://zephyr.axel669.net)
6
6
 
7
+ ## Todo
8
+ These are things that I plan to do, but didn't want to hold up the 0.5.x major
9
+ changes for svelte 5/runes/improvements.
10
+ - Add filter/sort back into data table
11
+ - Form element
12
+
7
13
  ## Installation
8
14
  Zephyr can be installed through npm (or the variants like yarn, pnpm, etc).
9
15
 
@@ -15,7 +21,8 @@ npm install @axel669/zephyr
15
21
  Components can be imported individually from the library for tree-shaking, or
16
22
  the entire lib can imported at once, but I dunno how big that bundle will be.
17
23
  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).
24
+ using the same rules as the `wsx` covered in
25
+ [Functions](./docsite/docs/functions.md).
19
26
 
20
27
  ### Theming
21
28
  Windstorm expects a theme to be defined on an ancestor of the html elements
@@ -1,29 +1,33 @@
1
1
  <script>
2
2
  import Button from "../control/button.svelte"
3
3
  import Spinner from "../spinner/circle-spinner.svelte"
4
+ import { splitProps } from "../props.js"
4
5
 
5
- export let handler = null
6
- export let disabled
7
- export let spincolor = "@primary"
6
+ const {
7
+ handler = null,
8
+ disabled,
9
+ ...rest
10
+ } = $props()
8
11
 
9
- let running = false
10
- const asyncHandler = async (evt) => {
12
+ let running = $state(false)
13
+ const onclick = async (evt) => {
11
14
  running = true
12
15
  await handler(evt)
13
16
  running = false
14
17
  }
15
18
 
16
- $: inactive = disabled || running
17
- $: props = {
18
- ...$$restProps,
19
+ const inactive = $derived(disabled || running)
20
+ const prop = $derived(
21
+ splitProps(rest, "sp!")
22
+ )
23
+ const buttonProps = $derived({
24
+ ...prop.rest,
19
25
  disabled: inactive,
20
- }
26
+ })
21
27
  </script>
22
28
 
23
29
  <async-button ws-x="[disp inline-grid] [gr.cols 1fr] [pos relative]">
24
- <Button {...props} on:click={asyncHandler}>
25
- <slot />
26
- </Button>
30
+ <Button {...buttonProps} {onclick} />
27
31
  {#if running === true}
28
32
  <Spinner
29
33
  size="unset"
@@ -31,7 +35,7 @@
31
35
  x="50%" y="0px"
32
36
  tf="translateX(-50%)"
33
37
  h="100%"
34
- color={spincolor}
38
+ {...prop["sp!"]}
35
39
  />
36
40
  {/if}
37
41
  </async-button>
@@ -0,0 +1,38 @@
1
+ <script>
2
+ import CircleSpinner from "../spinner/circle-spinner.svelte"
3
+
4
+ const {
5
+ "!component": Component,
6
+ loading,
7
+ error,
8
+ ...rest
9
+ } = $props()
10
+ const wait = $derived(
11
+ Promise.all(
12
+ Object.entries(rest).map(
13
+ async (pair) => [pair[0], await pair[1]]
14
+ )
15
+ )
16
+ )
17
+ </script>
18
+
19
+ {#await wait}
20
+ {#if loading}
21
+ {@render loading()}
22
+ {:else}
23
+ <div ws-x="[flex] [fl-center] [p 4px]">
24
+ <CircleSpinner size="56px" />
25
+ <span>Loading</span>
26
+ </div>
27
+ {/if}
28
+ {:then entries}
29
+ <Component {...Object.fromEntries(entries)} />
30
+ {:catch loadError}
31
+ {#if error}
32
+ {@render error(loadError)}
33
+ {:else}
34
+ <div ws-x="[b 1px solid red] [p 8px]">
35
+ {loadError}
36
+ </div>
37
+ {/if}
38
+ {/await}
package/src/changed.js ADDED
@@ -0,0 +1,10 @@
1
+ export const trackChanges = (initial) => {
2
+ let current = initial
3
+ return (next) => {
4
+ if (next !== current) {
5
+ current = next
6
+ return true
7
+ }
8
+ return false
9
+ }
10
+ }
@@ -14,7 +14,7 @@
14
14
  import Grid from "../../layout/grid.svelte"
15
15
  import Icon from "../../info/icon.svelte"
16
16
 
17
- import wsx from "../../wsx.mjs"
17
+ import wsx from "../../wsx.js"
18
18
  import { dtContext } from "../data-table.svelte"
19
19
 
20
20
  export let sort = null
@@ -46,7 +46,7 @@
46
46
  </div>
47
47
  {:else}
48
48
  <Button compact r="0px" fill={$context.fillHeader}
49
- t.wt="inherit" on:click={setSort} color={$context.color}>
49
+ t.wt="inherit" on:click={setSort} color={$context.color} ground>
50
50
  <slot />
51
51
  <Icon name={sortIcon} m.l="4px" t.sz="16px" />
52
52
  </Button>
@@ -1,200 +1,174 @@
1
- <svelte:options immutable />
2
-
3
- <script context="module">
4
- // find the first filter in the list that returns false
5
- const applyFilters = (data, filters) => {
6
- if (Array.isArray(data) === false) {
7
- return null
1
+ <script module>
2
+ const itemRange = (info) => {
3
+ const {
4
+ scrollPos,
5
+ scrollMax,
6
+ rowSize,
7
+ length,
8
+ containerHeight,
9
+ } = info
10
+ if (scrollMax === null) {
11
+ return [0, 0]
8
12
  }
9
- return data.filter(
10
- (row) => {
11
- for (const [filter, value] of filters) {
12
- if (filter(row, value) === false) {
13
- return false
14
- }
15
- }
16
- return true
17
- }
13
+ const displayed = Math.ceil(containerHeight / rowSize) - 1
14
+ const itemPos = Math.floor(
15
+ (scrollPos / scrollMax) * (length - displayed)
18
16
  )
17
+ return [
18
+ itemPos - 1,
19
+ itemPos + displayed + 1,
20
+ displayed + 2,
21
+ ]
19
22
  }
20
- const sliceData = (data, page, pageSize, sortFunc) => {
21
- if (data === null) {
22
- return []
23
- }
24
- const sorted = data.sort(sortFunc)
25
- return Array.from(
26
- { length: pageSize },
27
- (_, i) => sorted[page * pageSize + i]
23
+ const emptyRow = Symbol("empty row")
24
+ const nullRow = Symbol("null row")
25
+
26
+ const sliceData = (data, range) => {
27
+ const displayed = data.slice(
28
+ Math.max(range[0], 0),
29
+ range[1]
28
30
  )
31
+ if (range[0] === -1) {
32
+ return [emptyRow, ...displayed]
33
+ }
34
+ if (displayed.length < range[2]) {
35
+ return [
36
+ ...displayed,
37
+ ...Array.from(
38
+ { length: range[2] - displayed.length },
39
+ () => nullRow
40
+ )
41
+ ]
42
+ }
43
+ return displayed
29
44
  }
30
- const noSort = {
31
- direction: null,
32
- func: (a, b) => 0,
33
- base: null,
34
- }
35
-
36
- export const dtContext = Symbol("table key")
37
45
  </script>
38
46
 
39
47
  <script>
40
- import { createEventDispatcher, setContext } from "svelte"
41
- import { writable } from "svelte/store"
42
-
43
- import Button from "../control/button.svelte"
44
- import Icon from "../info/icon.svelte"
45
- import Paper from "../layout/paper.svelte"
46
- import Table from "../data-display/table.svelte"
47
- import Text from "../text.svelte"
48
+ import { on } from "svelte/events"
48
49
 
49
50
  import Grid from "../layout/grid.svelte"
50
51
 
51
- import wsx from "../wsx.mjs"
52
- import { handler$, eventHandler$ } from "../handler$.mjs"
53
-
54
- export let color = "@primary"
55
- export let fillHeader = true
56
- export let data
57
- export let pageSize = 10
58
- export let page = 0
59
- export let rowHeight = "40px"
60
- export let scrollable = false
61
- export let height = null
62
-
63
- let sorting = noSort
64
- let filters = new Map()
65
- let filterFunctions = []
66
- let jumpTarget = "1"
67
-
68
- $: filteredData = applyFilters(data, filterFunctions, sorting.func)
69
- $: rows = sliceData(filteredData, page, pageSize, sorting.func)
70
- $: rowCount = filteredData?.length ?? 0
71
- $: pageCount = Math.ceil(rowCount / pageSize)
72
- $: maxPage = Math.max(pageCount - 1, 0)
73
- $: jumpTarget = (page + 1).toString()
74
-
75
- $: if (filteredData === null) {
76
- console.warn("DataTable: data is not an array")
77
- }
78
-
79
- const prev = () => page = Math.max(0, page - 1)
80
- const next = () => page = Math.min(maxPage, page + 1)
81
-
82
- const updateSort = (func) => {
83
- if (sorting.base === func) {
84
- if (sorting.direction === "desc") {
85
- sorting = noSort
86
- return
87
- }
88
- sorting = {
89
- func: (a, b) => -func(a, b),
90
- base: func,
91
- direction: "desc"
92
- }
93
- return
94
- }
95
- sorting = {
96
- func,
97
- base: func,
98
- direction: "asc",
99
- }
100
- }
101
- const updateFilter = (func, value) => {
102
- if (func === null) {
103
- return
104
- }
105
- filters.set(func, value)
106
- filterFunctions = [
107
- ...filters.entries()
108
- ]
109
- }
110
-
111
- const context = writable({})
112
- $: $context = {
113
- updateSort,
114
- fillHeader,
115
- sorting,
116
- updateFilter,
52
+ import wsx from "../wsx.js"
53
+
54
+ const {
55
+ data,
56
+ rowSize = 40,
57
+ headerSize = rowSize,
58
+ cols = "1fr",
59
+ gap = 2,
60
+ colGap = gap,
61
+ rowGap = gap,
62
+ header,
63
+ row,
117
64
  color,
118
- }
119
- setContext(dtContext, context)
65
+ fillHeader = false,
66
+ ...rest
67
+ } = $props()
120
68
 
121
- const fire = createEventDispatcher()
122
- const pass = handler$(
123
- (row) => fire("row-click", row)
69
+ const rowPx = rowSize + rowGap
70
+ const height = $derived(
71
+ rowPx * data.length - rowGap
124
72
  )
73
+ const tableHeight = $derived(height + rowPx)
125
74
 
126
- let scroller = null
127
- $: if (scroller !== null && isNaN(page) === false) {
128
- scroller.scrollTop = 0
75
+ let scrollPos = $state(0)
76
+ let scrollMax = $state(null)
77
+ let containerHeight = $state(null)
78
+ const scrollHandler = (evt) => {
79
+ scrollPos = container.scrollTop
129
80
  }
130
- const jump = (evt) => {
131
- if (evt.type === "keypress" && evt.key !== "Enter") {
132
- return
133
- }
134
- const target = parseInt(evt.target.value)
135
- if (isNaN(target) === true) {
136
- jumpTarget = (page + 1).toString()
137
- return
138
- }
139
- page = Math.max(
140
- Math.min(jumpTarget - 1, maxPage),
141
- 0
81
+ const range = $derived(
82
+ itemRange({
83
+ scrollPos,
84
+ scrollMax,
85
+ containerHeight,
86
+ rowSize: rowSize + rowGap,
87
+ length: data.length,
88
+ })
89
+ )
90
+ let container = $state(null)
91
+
92
+ $effect(() => {
93
+ containerHeight = container.clientHeight
94
+ scrollMax = container.scrollHeight - containerHeight
95
+ on(container, "scroll", scrollHandler, { passive: true })
96
+ const observer = new ResizeObserver(
97
+ () => {
98
+ containerHeight = container.clientHeight
99
+ scrollMax = container.scrollHeight - containerHeight
100
+ }
142
101
  )
143
- jumpTarget = (page + 1).toString()
144
- }
102
+ observer.observe(container)
103
+ return () => observer.unobserve(container)
104
+ })
145
105
 
146
- $: content = {
147
- "fl.cross": "stretch",
148
- p: "0px",
149
- gap: "0px",
150
- over: (scrollable === true) ? "auto" : null,
151
- }
152
- $: header = {
153
- "h.min": rowHeight,
154
- y: "0px",
155
- z: "+10",
156
- pos: (scrollable === true) ? "sticky" : null,
157
- }
106
+ const displayed = $derived(range[2])
107
+ const displayedRows = $derived(
108
+ sliceData(data, range)
109
+ )
110
+ const tbodyHeight = $derived(displayRows.length * rowSize)
111
+
112
+ const tableWSX = $derived({
113
+ "$fill-header": fillHeader,
114
+ $color: color,
115
+ "gr.cols": cols,
116
+ "gap.col": `${colGap}px`,
117
+ "gap.row": `${rowGap}px`,
118
+ "@header-size": `${headerSize}px`,
119
+ "@row-size": `${rowSize}px`,
120
+ "$sticky-header": true,
121
+ w: "100%",
122
+ h: `${tableHeight}px`,
123
+ over: "visible",
124
+ con: "paint",
125
+ })
126
+ const tbodyWSX = $derived({
127
+ disp: "grid",
128
+ "gr.rows": "subgrid",
129
+ "gr.cols": "subgrid",
130
+ row: `span ${displayed}`,
131
+ tf: `translateY(${range[0] * rowPx}px)`,
132
+ })
133
+ const footerWSX = $derived({
134
+ h: "40px",
135
+ bg: "@background-element",
136
+ $color: color,
137
+ "b.y": "2px solid @ripple-base-color",
138
+ disp: "flex",
139
+ "fl-center": true,
140
+ })
141
+
142
+ const show = $derived({
143
+ start: Math.max(1, range[0] + 2),
144
+ end: Math.min(data.length, range[1] - 1),
145
+ total: data.length,
146
+ })
158
147
  </script>
159
148
 
160
- <Paper {color} h={height} card>
161
- <ws-flex use:wsx={content} slot="content" bind:this={scroller}>
162
- <Table data={rows} {color} {fillHeader} {...$$restProps} b.t.w="0px">
163
- <tr use:wsx={header} slot="header">
164
- <slot name="header">
165
- <th>No Header Defined</th>
166
- </slot>
167
- </tr>
168
- <tr ws-x="[h {rowHeight}]" slot="row" let:row>
169
- <slot name="row" {row}>
170
- <th>No Row Defined</th>
171
- </slot>
172
- </tr>
173
- <tr ws-x="[h {rowHeight}]" slot="empty-row" />
174
- </Table>
175
- </ws-flex>
176
- <Grid slot="footer" gr.cols="min-content min-content min-content 1fr"
177
- rows="32px" b="1px solid @color" b.b.w="4px">
178
- {#if pageCount > 0}
179
- <Button on:click={prev} disabled={page === 0}>
180
- <Icon name="caret-left" />
181
- </Button>
182
- <Button on:click={next} disabled={page === maxPage}>
183
- <Icon name="caret-right" />
184
- </Button>
185
- <Text adorn t.ws="nowrap">
186
- Page
187
- <input ws-x="[b 1px solid @text-color-normal] [w 36px] [r 4px]
188
- [h 24px] [bg.c transaprent] [t.a center] [m.l 4px] [m.r 4px]"
189
- type="text" bind:value={jumpTarget}
190
- on:keypress={jump} on:blur={jump} />
191
- / {pageCount}
192
- </Text>
193
- {:else}
194
- <div ws-x="[col span 3] [p.l 4px]">
195
- No data to show
196
- </div>
197
- {/if}
198
- <slot name="action" />
199
- </Grid>
200
- </Paper>
149
+ <Grid cols="1fr" rows="1fr min-content" pos="relative" {...rest} gap="0px">
150
+ <div ws-x="[over auto]" bind:this={container}>
151
+ <table use:wsx={tableWSX}>
152
+ <thead>
153
+ {@render header()}
154
+ </thead>
155
+ <tbody use:wsx={tbodyWSX}>
156
+ {#each displayedRows as dataRow}
157
+ {#if dataRow === nullRow}
158
+ <tr>
159
+ <td ws-x="[col 1 / -1]"></td>
160
+ </tr>
161
+ {:else if dataRow === emptyRow}
162
+ <tr></tr>
163
+ {:else}
164
+ {@render row(dataRow)}
165
+ {/if}
166
+ {/each}
167
+ </tbody>
168
+ </table>
169
+ </div>
170
+
171
+ <div use:wsx={footerWSX}>
172
+ Showing: {show.start} - {show.end} of {show.total}
173
+ </div>
174
+ </Grid>
@@ -1,31 +1,28 @@
1
- <svelte:options immutable />
2
-
3
1
  <script>
4
- import { createEventDispatcher } from "svelte"
5
-
6
2
  import Button from "../control/button.svelte"
7
3
  import Modal from "../layout/modal.svelte"
8
- import { handler$ } from "../handler$.mjs"
9
-
10
- export let component
11
- export let props
12
- let wrapper = Modal
13
- export { wrapper as this }
4
+ import { handler$ } from "../handler$.js"
14
5
 
15
- const send = createEventDispatcher()
6
+ const {
7
+ component,
8
+ props,
9
+ this:Wrapper = Modal,
10
+ "w!props":wrapperProps = {},
11
+ children,
12
+ onentry,
13
+ ...rest
14
+ } = $props()
16
15
 
17
16
  let element = null
18
17
  const open = handler$(
19
18
  async (props) => {
20
19
  const elemProps = (typeof props === "function") ? props() : props
21
20
  const result = await element.show(elemProps)
22
- send("entry", result)
21
+ onentry?.(result)
23
22
  }
24
23
  )
25
24
  </script>
26
25
 
27
- <Button {...$$restProps} on:click={open(props)}>
28
- <slot />
29
- </Button>
26
+ <Button {...rest} onclick={open(props)} {children} />
30
27
 
31
- <svelte:component this={wrapper} {component} bind:this={element} />
28
+ <Wrapper bind:this={element} {...rest} {component} />
@@ -1,35 +1,39 @@
1
- <svelte:options immutable />
2
-
3
1
  <script>
4
- import wsx from "../wsx.mjs"
5
- import variant from "../variant.mjs"
2
+ import wsx from "../wsx.js"
3
+ import variant from "../variant.js"
6
4
 
7
- export let color = false
8
- export let compact = false
9
- export let ground = false
10
- export let disabled
5
+ const {
6
+ color = false,
7
+ compact = false,
8
+ ground = false,
9
+ disabled,
11
10
 
12
- export let fill = false
13
- export let outline = false
14
- export let flat = false
11
+ fill = false,
12
+ outline = false,
13
+ flat = false,
14
+ children,
15
+ onclick,
16
+ ...rest
17
+ } = $props()
15
18
 
16
- // $: type = variant({ fill, outline, flat })
17
- $: type = variant(
18
- "$flat",
19
- { fill },
20
- { outline },
21
- { flat }
19
+ const type = $derived(
20
+ variant(
21
+ "$flat",
22
+ { fill },
23
+ { outline },
24
+ { flat }
25
+ )
22
26
  )
23
27
 
24
- $: wind = {
28
+ const wind = $derived({
25
29
  [type]: true,
26
30
  "$color": color,
27
31
  $compact: compact,
28
32
  $ground: ground,
29
- ...$$restProps
30
- }
33
+ ...rest
34
+ })
31
35
  </script>
32
36
 
33
- <button use:wsx={wind} {disabled} on:click|stopPropagation>
34
- <slot />
37
+ <button use:wsx={wind} {disabled} {onclick}>
38
+ {@render children?.()}
35
39
  </button>