@axel669/zephyr 0.5.4 → 1.0.0-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 (91) hide show
  1. package/package.json +48 -42
  2. package/readme.md +0 -44
  3. package/src/changed.svelte.js +23 -0
  4. package/src/component/adorn.svelte +9 -0
  5. package/src/component/alert.svelte +32 -0
  6. package/src/component/application.svelte +17 -0
  7. package/src/component/async-button.svelte +53 -0
  8. package/src/component/avatar.svelte +15 -0
  9. package/src/component/badge.svelte +7 -0
  10. package/src/component/button.svelte +7 -0
  11. package/src/component/chip.svelte +10 -0
  12. package/src/component/circle-spinner.svelte +6 -0
  13. package/src/component/confirm.svelte +40 -0
  14. package/src/component/control-label.svelte +41 -0
  15. package/src/component/data-table.svelte +227 -0
  16. package/src/component/details.svelte +22 -0
  17. package/src/component/dialog-element.svelte +35 -0
  18. package/src/component/dialog.svelte +43 -0
  19. package/src/component/drawer.svelte +20 -0
  20. package/src/component/flex.svelte +7 -0
  21. package/src/component/grid.svelte +7 -0
  22. package/src/component/hexagon-spinner.svelte +6 -0
  23. package/src/component/icon.svelte +7 -0
  24. package/src/component/link.svelte +11 -0
  25. package/src/component/modal.svelte +32 -0
  26. package/src/component/paper.svelte +33 -0
  27. package/src/component/popover.svelte +19 -0
  28. package/src/component/progress.svelte +6 -0
  29. package/src/component/prompt.svelte +58 -0
  30. package/src/{routing → component}/routing.svelte.js +5 -13
  31. package/src/component/screen.svelte +30 -0
  32. package/src/component/select.svelte +40 -0
  33. package/src/{async → component}/suspend.svelte +14 -8
  34. package/src/component/table.svelte +49 -0
  35. package/src/component/tabs.svelte +2 -0
  36. package/src/component/text.svelte +26 -0
  37. package/src/component/titlebar.svelte +23 -0
  38. package/src/component/toast.svelte +7 -0
  39. package/src/component/toaster.svelte +60 -0
  40. package/src/component/toggle-label.svelte +11 -0
  41. package/src/component/tooltip.svelte +11 -0
  42. package/src/custom-macros.js +11 -9
  43. package/src/{hash.svelte.js → hash.js} +0 -9
  44. package/src/index.js +3 -2
  45. package/src/internals.js +12 -0
  46. package/src/main.js +47 -0
  47. package/src/ws.js +10 -0
  48. package/src/async/button.svelte +0 -41
  49. package/src/changed.js +0 -10
  50. package/src/composed/data-table/th.svelte +0 -61
  51. package/src/composed/data-table.svelte +0 -174
  52. package/src/composed/entry-button.svelte +0 -28
  53. package/src/composed/form.svelte +0 -60
  54. package/src/composed/table-functions.js +0 -15
  55. package/src/control/button.svelte +0 -39
  56. package/src/control/input.svelte +0 -103
  57. package/src/control/label.svelte +0 -49
  58. package/src/control/link.svelte +0 -47
  59. package/src/control/radio-group.svelte +0 -24
  60. package/src/control/select.svelte +0 -69
  61. package/src/control/tabs.svelte +0 -35
  62. package/src/control/toggle.svelte +0 -60
  63. package/src/data-display/avatar.svelte +0 -29
  64. package/src/data-display/badge.svelte +0 -16
  65. package/src/data-display/chip.svelte +0 -38
  66. package/src/data-display/details.svelte +0 -33
  67. package/src/data-display/popover.svelte +0 -28
  68. package/src/data-display/progress.svelte +0 -25
  69. package/src/data-display/table.svelte +0 -50
  70. package/src/data-display/tooltip.svelte +0 -19
  71. package/src/dialogs/alert.svelte +0 -40
  72. package/src/dialogs/confirm.svelte +0 -51
  73. package/src/info/element-toaster.svelte +0 -110
  74. package/src/info/icon.svelte +0 -9
  75. package/src/info/titlebar.svelte +0 -40
  76. package/src/info/toast.svelte +0 -35
  77. package/src/info/toaster/message.svelte +0 -42
  78. package/src/info/toaster.svelte +0 -72
  79. package/src/layout/dialog.svelte +0 -24
  80. package/src/layout/drawer.svelte +0 -76
  81. package/src/layout/flex.svelte +0 -24
  82. package/src/layout/grid.svelte +0 -32
  83. package/src/layout/modal.svelte +0 -68
  84. package/src/layout/paper.svelte +0 -54
  85. package/src/layout/screen.svelte +0 -38
  86. package/src/spinner/circle-spinner.svelte +0 -18
  87. package/src/spinner/hexagon-spinner.svelte +0 -18
  88. package/src/text.svelte +0 -16
  89. package/src/wsx.js +0 -29
  90. /package/src/{routing → component}/route.svelte +0 -0
  91. /package/src/{routing → component}/title.svelte +0 -0
@@ -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
+ }
package/src/main.js ADDED
@@ -0,0 +1,47 @@
1
+ export { ws, wsAttr } from "./ws.js"
2
+ export { hash } from "./hash.js"
3
+ export { resolve, relpath, stackStore } from "./component/routing.svelte.js"
4
+
5
+ window.fdebug = ([name]) =>
6
+ (func) =>
7
+ (...args) => {
8
+ console.log(name)
9
+ func(...args)
10
+ }
11
+
12
+ export { default as Adorn } from "./component/adorn.svelte"
13
+ export { default as Alert } from "./component/alert.svelte"
14
+ export { default as Application } from "./component/application.svelte"
15
+ export { default as AsyncButton } from "./component/async-button.svelte"
16
+ export { default as Avatar } from "./component/avatar.svelte"
17
+ export { default as Badge } from "./component/badge.svelte"
18
+ export { default as Button } from "./component/button.svelte"
19
+ export { default as Chip } from "./component/chip.svelte"
20
+ export { default as CircleSpinner } from "./component/circle-spinner.svelte"
21
+ export { default as Confirm } from "./component/confirm.svelte"
22
+ export { default as ControlLabel } from "./component/control-label.svelte"
23
+ export { default as DataTable } from "./component/data-table.svelte"
24
+ export { default as Details } from "./component/details.svelte"
25
+ export { default as Dialog, showDialog } from "./component/dialog.svelte"
26
+ export { default as Drawer } from "./component/drawer.svelte"
27
+ export { default as Flex } from "./component/flex.svelte"
28
+ export { default as Grid } from "./component/grid.svelte"
29
+ export { default as HexagonSpinner } from "./component/hexagon-spinner.svelte"
30
+ export { default as Icon } from "./component/icon.svelte"
31
+ export { default as Link } from "./component/link.svelte"
32
+ export { default as Modal } from "./component/modal.svelte"
33
+ export { default as Paper } from "./component/paper.svelte"
34
+ export { default as Popover } from "./component/popover.svelte"
35
+ export { default as Progress } from "./component/progress.svelte"
36
+ export { default as Prompt } from "./component/prompt.svelte"
37
+ export { default as Route } from "./component/route.svelte"
38
+ export { default as Screen } from "./component/screen.svelte"
39
+ export { default as Select } from "./component/select.svelte"
40
+ export { default as Suspend } from "./component/suspend.svelte"
41
+ export { default as Table } from "./component/table.svelte"
42
+ export { default as Text } from "./component/text.svelte"
43
+ export { default as Titlebar } from "./component/titlebar.svelte"
44
+ export { default as Toast } from "./component/toast.svelte"
45
+ export { default as Toaster, showToast } from "./component/toaster.svelte"
46
+ export { default as ToggleLabel } from "./component/toggle-label.svelte"
47
+ export { default as Tooltip } from "./component/tooltip.svelte"
package/src/ws.js ADDED
@@ -0,0 +1,10 @@
1
+ import * as ws from "@axel669/windstorm"
2
+
3
+ export { ws }
4
+ export const wsAttr = (node, value) => {
5
+ const update = (value) => {
6
+ node.setAttribute("data-ws", value)
7
+ }
8
+ update(value)
9
+ return { update }
10
+ }
@@ -1,41 +0,0 @@
1
- <script>
2
- import Button from "../control/button.svelte"
3
- import Spinner from "../spinner/circle-spinner.svelte"
4
- import { splitProps } from "../props.js"
5
-
6
- const {
7
- handler = null,
8
- disabled,
9
- ...rest
10
- } = $props()
11
-
12
- let running = $state(false)
13
- const onclick = async (evt) => {
14
- running = true
15
- await handler(evt)
16
- running = false
17
- }
18
-
19
- const inactive = $derived(disabled || running)
20
- const prop = $derived(
21
- splitProps(rest, "sp!")
22
- )
23
- const buttonProps = $derived({
24
- ...prop.rest,
25
- disabled: inactive,
26
- })
27
- </script>
28
-
29
- <async-button ws-x="[disp inline-grid] [gr.cols 1fr] [pos relative]">
30
- <Button {...buttonProps} {onclick} />
31
- {#if running === true}
32
- <Spinner
33
- size="unset"
34
- pos="absolute"
35
- x="50%" y="0px"
36
- tf="translateX(-50%)"
37
- h="100%"
38
- {...prop["sp!"]}
39
- />
40
- {/if}
41
- </async-button>
package/src/changed.js DELETED
@@ -1,10 +0,0 @@
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
- }
@@ -1,61 +0,0 @@
1
- <svelte:options immutable />
2
-
3
- <script context="module">
4
- const sortIcons = {
5
- "asc": "arrow-up",
6
- "desc": "arrow-down",
7
- }
8
- </script>
9
-
10
- <script>
11
- import { getContext } from "svelte"
12
-
13
- import Button from "../../control/button.svelte"
14
- import Grid from "../../layout/grid.svelte"
15
- import Icon from "../../info/icon.svelte"
16
-
17
- import wsx from "../../wsx.js"
18
- import { dtContext } from "../data-table.svelte"
19
-
20
- export let sort = null
21
- export let filter = null
22
-
23
- const context = getContext(dtContext)
24
-
25
- const setSort = () => $context.updateSort(sort)
26
-
27
- let value = ""
28
- $: $context.updateFilter(filter, value)
29
-
30
- $: wind = {
31
- ...$$restProps,
32
- p: "0px",
33
- sel: "none"
34
- }
35
- $: sortIcon =
36
- ($context.sorting.base === sort)
37
- ? sortIcons[$context.sorting.direction]
38
- : "arrow-down-up"
39
- </script>
40
-
41
- <th use:wsx={wind} style="vertical-align: top;">
42
- <Grid rows="40px min-content" p="0px" gap="0px">
43
- {#if sort === null}
44
- <div ws-x="[flex] [fl.cross center] [fl.main center]">
45
- <slot />
46
- </div>
47
- {:else}
48
- <Button compact r="0px" fill={$context.fillHeader}
49
- t.wt="inherit" on:click={setSort} color={$context.color} ground>
50
- <slot />
51
- <Icon name={sortIcon} m.l="4px" t.sz="16px" />
52
- </Button>
53
- {/if}
54
- {#if filter !== null}
55
- <Grid gap="0px" p="0px" cols="min-content 1fr">
56
- <Icon name="filter" />
57
- <input type="text" ws-x="[w.min 20px] [outln:focus none]" bind:value />
58
- </Grid>
59
- {/if}
60
- </Grid>
61
- </th>
@@ -1,174 +0,0 @@
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]
12
- }
13
- const displayed = Math.ceil(containerHeight / rowSize) - 1
14
- const itemPos = Math.floor(
15
- (scrollPos / scrollMax) * (length - displayed)
16
- )
17
- return [
18
- itemPos - 1,
19
- itemPos + displayed + 1,
20
- displayed + 2,
21
- ]
22
- }
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]
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
44
- }
45
- </script>
46
-
47
- <script>
48
- import { on } from "svelte/events"
49
-
50
- import Grid from "../layout/grid.svelte"
51
-
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,
64
- color,
65
- fillHeader = false,
66
- ...rest
67
- } = $props()
68
-
69
- const rowPx = rowSize + rowGap
70
- const height = $derived(
71
- rowPx * data.length - rowGap
72
- )
73
- const tableHeight = $derived(height + rowPx)
74
-
75
- let scrollPos = $state(0)
76
- let scrollMax = $state(null)
77
- let containerHeight = $state(null)
78
- const scrollHandler = (evt) => {
79
- scrollPos = container.scrollTop
80
- }
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
- }
101
- )
102
- observer.observe(container)
103
- return () => observer.unobserve(container)
104
- })
105
-
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
- })
147
- </script>
148
-
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,28 +0,0 @@
1
- <script>
2
- import Button from "../control/button.svelte"
3
- import Modal from "../layout/modal.svelte"
4
- import { handler$ } from "../handler$.js"
5
-
6
- const {
7
- component,
8
- props,
9
- this:Wrapper = Modal,
10
- "w!props":wrapperProps = {},
11
- children,
12
- onentry,
13
- ...rest
14
- } = $props()
15
-
16
- 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
- )
24
- </script>
25
-
26
- <Button {...rest} onclick={open(props)} {children} />
27
-
28
- <Wrapper bind:this={element} {...rest} {component} />
@@ -1,60 +0,0 @@
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}
@@ -1,15 +0,0 @@
1
- export const filters = {
2
- text: (propName) =>
3
- (row, text) =>
4
- row[propName]
5
- .toLowerCase()
6
- .includes(text.toLowerCase())
7
- }
8
- export const sorts = {
9
- natural: (propName) => {
10
- const comparitor = new Intl.Collator(undefined, { numeric: true })
11
- return (a, b) => comparitor.compare(a[propName], b[propName])
12
- },
13
- number: (propName) =>
14
- (a, b) => a[propName] - b[propName]
15
- }
@@ -1,39 +0,0 @@
1
- <script>
2
- import wsx from "../wsx.js"
3
- import variant from "../variant.js"
4
-
5
- const {
6
- color = false,
7
- compact = false,
8
- ground = false,
9
- disabled,
10
-
11
- fill = false,
12
- outline = false,
13
- flat = false,
14
- children,
15
- onclick,
16
- ...rest
17
- } = $props()
18
-
19
- const type = $derived(
20
- variant(
21
- "$flat",
22
- { fill },
23
- { outline },
24
- { flat }
25
- )
26
- )
27
-
28
- const wind = $derived({
29
- [type]: true,
30
- "$color": color,
31
- $compact: compact,
32
- $ground: ground,
33
- ...rest
34
- })
35
- </script>
36
-
37
- <button use:wsx={wind} {disabled} {onclick}>
38
- {@render children?.()}
39
- </button>
@@ -1,103 +0,0 @@
1
- <script>
2
- import wsx, { none } from "../wsx.js"
3
- import variant from "../variant.js"
4
- import { splitProps } from "../props.js"
5
-
6
- let {
7
- type = "text",
8
-
9
- flat = false,
10
- lined = false,
11
- linedFill = false,
12
- outline = false,
13
- label,
14
- color = "@default",
15
- disabled,
16
-
17
- value = $bindable(""),
18
- autocompleteOptions = null,
19
-
20
- start,
21
- end,
22
- extra,
23
-
24
- oninput,
25
- ...rest
26
- } = $props()
27
-
28
- let input = $state(null)
29
- export const focus = () => input.focus()
30
-
31
- const id =
32
- (autocompleteOptions === null)
33
- ? null
34
- : `${Math.random().toString(16)}_${Date.now()}`
35
-
36
- const prop = splitProps(rest, "i!")
37
-
38
- const variantStyle = $derived(
39
- variant(
40
- none,
41
- { outline },
42
- { linedFill },
43
- { lined },
44
- { flat }
45
- )
46
- )
47
-
48
- const wind = $derived({
49
- [variantStyle]: true,
50
- "@@control": true,
51
- "$color": color,
52
- ...prop.rest,
53
- })
54
-
55
- const tag = $derived(
56
- (type === "area") ? "textarea" : "input"
57
- )
58
-
59
- const update = (evt) => {
60
- value = evt.target.value
61
- oninput?.(evt)
62
- }
63
- </script>
64
-
65
- <label use:wsx={wind}>
66
- {#if label}
67
- <span use:wsx={{ "$label": true }}>{label}</span>
68
- {/if}
69
- <svelte:element
70
- this={tag}
71
- {...prop.input}
72
- {disabled}
73
- {type}
74
- {value}
75
- oninput={update}
76
- list={id}
77
- bind:this={input}
78
- />
79
-
80
- {#if start}
81
- <span use:wsx={{ "$start": true }}>
82
- {@render start()}
83
- </span>
84
- {/if}
85
- {#if end}
86
- <span use:wsx={{ "$end": true }}>
87
- {@render end()}
88
- </span>
89
- {/if}
90
- {#if extra}
91
- <span use:wsx={{ "$extra": true }}>
92
- {@render extra()}
93
- </span>
94
- {/if}
95
-
96
- {#if autocompleteOptions !== null}
97
- <datalist {id}>
98
- {#each autocompleteOptions as value}
99
- <option {value}>{value}</option>
100
- {/each}
101
- </datalist>
102
- {/if}
103
- </label>