@axel669/zephyr 0.2.0-beta.2 → 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.
- package/package.json +2 -2
- package/readme.md +4 -4
- package/src/async/button.md +27 -0
- package/src/async/button.svelte +2 -4
- package/src/async/load-zone.md +42 -0
- package/src/async/load-zone.svelte +7 -2
- package/src/composed/data-table/th.md +21 -0
- package/src/composed/data-table/th.svelte +4 -3
- package/src/composed/data-table.md +68 -67
- package/src/composed/data-table.svelte +98 -35
- package/src/composed/entry-button.md +23 -13
- package/src/composed/entry-button.svelte +2 -0
- package/src/composed/toast.md +30 -21
- package/src/composed/toast.svelte +3 -1
- package/src/control/button.svelte +2 -0
- package/src/control/input.md +87 -0
- package/src/control/input.svelte +5 -3
- package/src/control/label.md +0 -1
- package/src/control/label.svelte +3 -1
- package/src/control/link.svelte +6 -2
- package/src/control/radio.svelte +3 -1
- package/src/control/select.svelte +4 -2
- package/src/control/tabs.svelte +7 -3
- package/src/control/toggle.svelte +5 -3
- package/src/data-display/avatar.svelte +2 -0
- package/src/data-display/badge.svelte +3 -1
- package/src/data-display/chip.svelte +3 -1
- package/src/data-display/details.md +40 -1
- package/src/data-display/details.svelte +3 -1
- package/src/data-display/popover.svelte +3 -1
- package/src/data-display/progress.svelte +3 -1
- package/src/data-display/table.md +56 -4
- package/src/data-display/table.svelte +2 -0
- package/src/data-display/tooltip.svelte +2 -0
- package/src/dialogs/alert.md +40 -1
- package/src/dialogs/alert.svelte +3 -1
- package/src/dialogs/confirm.md +54 -1
- package/src/dialogs/confirm.svelte +3 -1
- package/src/functions.md +25 -0
- package/src/hash.js +14 -0
- package/src/index.mjs +2 -1
- package/src/inline-dialog.svelte +1 -1
- package/src/layout/dialog.svelte +3 -1
- package/src/layout/drawer.svelte +5 -3
- package/src/layout/flex.svelte +4 -0
- package/src/layout/grid.svelte +4 -0
- package/src/layout/modal.svelte +3 -1
- package/src/layout/paper.svelte +2 -0
- package/src/layout/screen.svelte +4 -2
- package/src/spinner/circle-spinner.svelte +4 -2
- package/src/spinner/hexagon-spinner.svelte +4 -2
- package/src/spinner/spinners.md +20 -1
- package/src/text.svelte +2 -0
- package/src/wsx.mjs +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@axel669/zephyr",
|
|
3
|
-
"version": "0.
|
|
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.
|
|
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
|
|
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
|
|
18
|
-
as the `wsx`
|
|
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={{"
|
|
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
|
+
```
|
package/src/async/button.svelte
CHANGED
|
@@ -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 =
|
|
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
|
|
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
|
+
```
|
|
@@ -1,17 +1,22 @@
|
|
|
1
|
+
<svelte:options immutable />
|
|
2
|
+
|
|
1
3
|
<script>
|
|
2
4
|
import Spinner from "../spinner/hexagon-spinner.svelte"
|
|
3
5
|
export let source = null
|
|
6
|
+
export let message = "Loading"
|
|
4
7
|
</script>
|
|
5
8
|
|
|
6
9
|
{#if source !== null}
|
|
7
10
|
{#await source}
|
|
8
11
|
<slot name="loading">
|
|
9
|
-
<ws-flex ws-x="
|
|
10
|
-
<span>
|
|
12
|
+
<ws-flex ws-x="[fl-center]">
|
|
13
|
+
<span>{message}</span>
|
|
11
14
|
<Spinner size="100px" />
|
|
12
15
|
</ws-flex>
|
|
13
16
|
</slot>
|
|
14
17
|
{:then result}
|
|
15
18
|
<slot {result} />
|
|
19
|
+
{:catch error}
|
|
20
|
+
<slot name="error" {error} />
|
|
16
21
|
{/await}
|
|
17
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.
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
<svelte:options immutable />
|
|
2
|
+
|
|
1
3
|
<script context="module">
|
|
2
4
|
const sortIcons = {
|
|
3
5
|
"asc": "arrow-narrow-up",
|
|
@@ -30,7 +32,6 @@
|
|
|
30
32
|
p: "0px",
|
|
31
33
|
sel: "none"
|
|
32
34
|
}
|
|
33
|
-
$: console.log($context.sorting)
|
|
34
35
|
$: sortIcon =
|
|
35
36
|
($context.sorting.base === sort)
|
|
36
37
|
? sortIcons[$context.sorting.direction]
|
|
@@ -40,7 +41,7 @@
|
|
|
40
41
|
<th use:wsx={wind} style="vertical-align: top;">
|
|
41
42
|
<Grid rows="40px min-content" p="0px" gap="0px">
|
|
42
43
|
{#if sort === null}
|
|
43
|
-
<div ws-x="flex fl.cross
|
|
44
|
+
<div ws-x="[flex] [fl.cross center] [fl.main center]">
|
|
44
45
|
<slot />
|
|
45
46
|
</div>
|
|
46
47
|
{:else}
|
|
@@ -53,7 +54,7 @@
|
|
|
53
54
|
{#if filter !== null}
|
|
54
55
|
<Grid gap="0px" p="0px" cols="min-content 1fr">
|
|
55
56
|
<Icon name="filter" />
|
|
56
|
-
<input type="text" ws-x="w.min
|
|
57
|
+
<input type="text" ws-x="[w.min 20px] [outline:focus none]" bind:value />
|
|
57
58
|
</Grid>
|
|
58
59
|
{/if}
|
|
59
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
|
|
7
|
-
|
|
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
|
-
|
|
18
|
-
|
|
12
|
+
### color
|
|
13
|
+
Sets `$color`
|
|
19
14
|
|
|
20
|
-
###
|
|
15
|
+
### data
|
|
21
16
|
`Array`
|
|
22
17
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
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
|
-
###
|
|
30
|
-
`
|
|
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
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
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
|
-
<
|
|
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
|
```
|
|
@@ -2,16 +2,31 @@
|
|
|
2
2
|
|
|
3
3
|
<script context="module">
|
|
4
4
|
// find the first filter in the list that returns false
|
|
5
|
-
const applyFilters = (data, filters) =>
|
|
6
|
-
(
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
const applyFilters = (data, filters) => {
|
|
6
|
+
if (Array.isArray(data) === false) {
|
|
7
|
+
return null
|
|
8
|
+
}
|
|
9
|
+
return data.filter(
|
|
10
|
+
(row) => {
|
|
11
|
+
for (const [filter, value] of filters) {
|
|
12
|
+
if (filter(row, value) === false) {
|
|
13
|
+
return false
|
|
14
|
+
}
|
|
10
15
|
}
|
|
16
|
+
return true
|
|
11
17
|
}
|
|
12
|
-
|
|
18
|
+
)
|
|
19
|
+
}
|
|
20
|
+
const sliceData = (data, page, pageSize, sortFunc) => {
|
|
21
|
+
if (data === null) {
|
|
22
|
+
return []
|
|
13
23
|
}
|
|
14
|
-
|
|
24
|
+
const sorted = data.sort(sortFunc)
|
|
25
|
+
return Array.from(
|
|
26
|
+
{ length: pageSize },
|
|
27
|
+
(_, i) => sorted[page * pageSize + i]
|
|
28
|
+
)
|
|
29
|
+
}
|
|
15
30
|
const noSort = {
|
|
16
31
|
direction: null,
|
|
17
32
|
func: (a, b) => 0,
|
|
@@ -38,26 +53,28 @@
|
|
|
38
53
|
|
|
39
54
|
export let color = false
|
|
40
55
|
export let fillHeader = true
|
|
41
|
-
export let data
|
|
56
|
+
export let data
|
|
42
57
|
export let pageSize = 10
|
|
43
58
|
export let page = 0
|
|
44
59
|
export let rowHeight = "40px"
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
{ length: pageSize },
|
|
48
|
-
(_, i) => filteredData[page * pageSize + i]
|
|
49
|
-
)
|
|
50
|
-
$: rowCount = filteredData.length
|
|
51
|
-
$: pageCount = Math.ceil(rowCount / pageSize)
|
|
52
|
-
$: maxPage = Math.max(pageCount - 1, 0)
|
|
60
|
+
export let scrollable = false
|
|
61
|
+
export let height = null
|
|
53
62
|
|
|
54
63
|
let sorting = noSort
|
|
55
64
|
let filters = new Map()
|
|
56
65
|
let filterFunctions = []
|
|
66
|
+
let jumpTarget = "1"
|
|
67
|
+
|
|
68
|
+
$: filteredData = applyFilters(data, filterFunctions)
|
|
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()
|
|
57
74
|
|
|
58
|
-
$: filteredData
|
|
59
|
-
|
|
60
|
-
|
|
75
|
+
$: if (filteredData === null) {
|
|
76
|
+
console.warn("DataTable: data is not an array")
|
|
77
|
+
}
|
|
61
78
|
|
|
62
79
|
const prev = () => page = Math.max(0, page - 1)
|
|
63
80
|
const next = () => page = Math.min(maxPage, page + 1)
|
|
@@ -104,23 +121,59 @@
|
|
|
104
121
|
const pass = handler$(
|
|
105
122
|
(row) => fire("row-click", row)
|
|
106
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
|
+
}
|
|
107
157
|
</script>
|
|
108
158
|
|
|
109
|
-
<Paper
|
|
110
|
-
<
|
|
111
|
-
<
|
|
112
|
-
<
|
|
113
|
-
<
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
<
|
|
118
|
-
<
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
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">
|
|
124
177
|
{#if pageCount > 0}
|
|
125
178
|
<Button on:click={prev} disabled={page === 0}>
|
|
126
179
|
<Icon name="arrow-big-left" />
|
|
@@ -129,8 +182,18 @@
|
|
|
129
182
|
<Icon name="arrow-big-right" />
|
|
130
183
|
</Button>
|
|
131
184
|
<Text adorn t.ws="nowrap">
|
|
132
|
-
Page
|
|
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}
|
|
133
191
|
</Text>
|
|
192
|
+
{:else}
|
|
193
|
+
<div ws-x="[col span 3] [p.l 4px]">
|
|
194
|
+
No data to show
|
|
195
|
+
</div>
|
|
134
196
|
{/if}
|
|
197
|
+
<slot name="action" />
|
|
135
198
|
</Grid>
|
|
136
199
|
</Paper>
|
|
@@ -6,29 +6,39 @@ addition to the buttons that show them.
|
|
|
6
6
|
|
|
7
7
|
## Props
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
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
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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
|
```
|