drab 2.6.1 → 2.7.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/dist/components/Accordion.svelte +34 -8
- package/dist/components/Accordion.svelte.d.ts +34 -8
- package/dist/components/Breakpoint.svelte +1 -11
- package/dist/components/Breakpoint.svelte.d.ts +1 -11
- package/dist/components/ContextMenu.svelte +0 -4
- package/dist/components/ContextMenu.svelte.d.ts +0 -2
- package/dist/components/CopyButton.svelte +1 -1
- package/dist/components/CopyButton.svelte.d.ts +1 -1
- package/dist/components/DataTable.svelte +64 -20
- package/dist/components/DataTable.svelte.d.ts +67 -14
- package/dist/components/FullscreenButton.svelte +2 -3
- package/dist/components/FullscreenButton.svelte.d.ts +2 -3
- package/dist/components/Popover.svelte +1 -1
- package/dist/components/Popover.svelte.d.ts +1 -1
- package/dist/components/ShareButton.svelte +1 -1
- package/dist/components/ShareButton.svelte.d.ts +1 -1
- package/dist/components/Sheet.svelte +35 -37
- package/dist/components/Sheet.svelte.d.ts +4 -12
- package/dist/components/Tabs.svelte +41 -22
- package/dist/components/Tabs.svelte.d.ts +23 -18
- package/package.json +1 -1
@@ -3,7 +3,7 @@
|
|
3
3
|
|
4
4
|
### Accordion
|
5
5
|
|
6
|
-
Displays a list of `details` elements.
|
6
|
+
Displays a list of `details` elements with helpful defaults and transitions.
|
7
7
|
|
8
8
|
@props
|
9
9
|
|
@@ -30,15 +30,18 @@ Displays a list of `details` elements.
|
|
30
30
|
@example
|
31
31
|
|
32
32
|
```svelte
|
33
|
-
<script>
|
33
|
+
<script lang="ts">
|
34
34
|
import { Accordion } from "drab";
|
35
|
+
import { FullscreenButton } from "drab";
|
35
36
|
import { Chevron } from "../../site/svg/Chevron.svelte";
|
36
37
|
</script>
|
37
38
|
|
38
39
|
<Accordion
|
39
40
|
icon={Chevron}
|
41
|
+
class="mb-12"
|
40
42
|
classDetails="border-b"
|
41
|
-
classHeader="flex gap-8 cursor-pointer items-center justify-between
|
43
|
+
classHeader="flex gap-8 cursor-pointer items-center justify-between p-4 font-bold underline hover:decoration-dotted"
|
44
|
+
classContent="pb-4 px-4"
|
42
45
|
items={[
|
43
46
|
{ summary: "Is it accessible?", content: "Yes." },
|
44
47
|
{
|
@@ -51,12 +54,35 @@ Displays a list of `details` elements.
|
|
51
54
|
},
|
52
55
|
{ summary: "Does it work without Javascript?", content: "Yes." },
|
53
56
|
]}
|
57
|
+
/>
|
58
|
+
|
59
|
+
<Accordion
|
60
|
+
icon={Chevron}
|
61
|
+
classDetails="border-b"
|
62
|
+
classHeader="flex gap-8 cursor-pointer items-center justify-between p-4 font-bold underline hover:decoration-dotted"
|
63
|
+
classContent="pb-4 px-4"
|
64
|
+
autoClose={false}
|
65
|
+
items={[
|
66
|
+
{ summary: "Summary", content: "Content" },
|
67
|
+
{ summary: "Summary", content: "Content", data: { uppercase: true } },
|
68
|
+
{
|
69
|
+
summary: "Summary",
|
70
|
+
content: "Content",
|
71
|
+
data: { component: FullscreenButton },
|
72
|
+
},
|
73
|
+
]}
|
54
74
|
>
|
55
|
-
<svelte:fragment slot="
|
56
|
-
<
|
57
|
-
|
58
|
-
|
59
|
-
</
|
75
|
+
<svelte:fragment slot="summary" let:item let:index>
|
76
|
+
<span class:uppercase={item.data?.uppercase}>
|
77
|
+
{item.summary}
|
78
|
+
{index + 1}
|
79
|
+
</span>
|
80
|
+
</svelte:fragment>
|
81
|
+
<svelte:fragment slot="content" let:item>
|
82
|
+
<span>{item.content}</span>
|
83
|
+
{#if item.data?.component === FullscreenButton}
|
84
|
+
<div><svelte:component this={FullscreenButton} class="btn mt-4" /></div>
|
85
|
+
{/if}
|
60
86
|
</svelte:fragment>
|
61
87
|
</Accordion>
|
62
88
|
```
|
@@ -49,7 +49,7 @@ export type AccordionSlots = typeof __propDef.slots;
|
|
49
49
|
/**
|
50
50
|
* ### Accordion
|
51
51
|
*
|
52
|
-
* Displays a list of `details` elements.
|
52
|
+
* Displays a list of `details` elements with helpful defaults and transitions.
|
53
53
|
*
|
54
54
|
* @props
|
55
55
|
*
|
@@ -76,15 +76,18 @@ export type AccordionSlots = typeof __propDef.slots;
|
|
76
76
|
* @example
|
77
77
|
*
|
78
78
|
* ```svelte
|
79
|
-
* <script>
|
79
|
+
* <script lang="ts">
|
80
80
|
* import { Accordion } from "drab";
|
81
|
+
* import { FullscreenButton } from "drab";
|
81
82
|
* import { Chevron } from "../../site/svg/Chevron.svelte";
|
82
83
|
* </script>
|
83
84
|
*
|
84
85
|
* <Accordion
|
85
86
|
* icon={Chevron}
|
87
|
+
* class="mb-12"
|
86
88
|
* classDetails="border-b"
|
87
|
-
* classHeader="flex gap-8 cursor-pointer items-center justify-between
|
89
|
+
* classHeader="flex gap-8 cursor-pointer items-center justify-between p-4 font-bold underline hover:decoration-dotted"
|
90
|
+
* classContent="pb-4 px-4"
|
88
91
|
* items={[
|
89
92
|
* { summary: "Is it accessible?", content: "Yes." },
|
90
93
|
* {
|
@@ -97,12 +100,35 @@ export type AccordionSlots = typeof __propDef.slots;
|
|
97
100
|
* },
|
98
101
|
* { summary: "Does it work without Javascript?", content: "Yes." },
|
99
102
|
* ]}
|
103
|
+
* />
|
104
|
+
*
|
105
|
+
* <Accordion
|
106
|
+
* icon={Chevron}
|
107
|
+
* classDetails="border-b"
|
108
|
+
* classHeader="flex gap-8 cursor-pointer items-center justify-between p-4 font-bold underline hover:decoration-dotted"
|
109
|
+
* classContent="pb-4 px-4"
|
110
|
+
* autoClose={false}
|
111
|
+
* items={[
|
112
|
+
* { summary: "Summary", content: "Content" },
|
113
|
+
* { summary: "Summary", content: "Content", data: { uppercase: true } },
|
114
|
+
* {
|
115
|
+
* summary: "Summary",
|
116
|
+
* content: "Content",
|
117
|
+
* data: { component: FullscreenButton },
|
118
|
+
* },
|
119
|
+
* ]}
|
100
120
|
* >
|
101
|
-
* <svelte:fragment slot="
|
102
|
-
* <
|
103
|
-
*
|
104
|
-
*
|
105
|
-
* </
|
121
|
+
* <svelte:fragment slot="summary" let:item let:index>
|
122
|
+
* <span class:uppercase={item.data?.uppercase}>
|
123
|
+
* {item.summary}
|
124
|
+
* {index + 1}
|
125
|
+
* </span>
|
126
|
+
* </svelte:fragment>
|
127
|
+
* <svelte:fragment slot="content" let:item>
|
128
|
+
* <span>{item.content}</span>
|
129
|
+
* {#if item.data?.component === FullscreenButton}
|
130
|
+
* <div><svelte:component this={FullscreenButton} class="btn mt-4" /></div>
|
131
|
+
* {/if}
|
106
132
|
* </svelte:fragment>
|
107
133
|
* </Accordion>
|
108
134
|
* ```
|
@@ -5,17 +5,7 @@
|
|
5
5
|
|
6
6
|
Displays the current breakpoint and `window.innerWidth`, based on the `breakpoints` provided. Defaults to [TailwindCSS breakpoint sizes](https://tailwindcss.com/docs/responsive-design).
|
7
7
|
|
8
|
-
|
9
|
-
<script lang="ts">
|
10
|
-
import { dev } from "$app/environment"; // SvelteKit Example
|
11
|
-
</script>
|
12
|
-
|
13
|
-
{#if dev}
|
14
|
-
<Breakpoint
|
15
|
-
class="fixed bottom-4 right-4 rounded border bg-white px-2 py-1 font-mono tabular-nums shadow"
|
16
|
-
/>
|
17
|
-
{/if}
|
18
|
-
```
|
8
|
+
With SvelteKit, this component can be wrapped in an `{#if dev}` block that checks for the [dev module](https://kit.svelte.dev/docs/modules#$app-environment-dev), to show only during development.
|
19
9
|
|
20
10
|
@props
|
21
11
|
|
@@ -21,17 +21,7 @@ export type BreakpointSlots = typeof __propDef.slots;
|
|
21
21
|
*
|
22
22
|
* Displays the current breakpoint and `window.innerWidth`, based on the `breakpoints` provided. Defaults to [TailwindCSS breakpoint sizes](https://tailwindcss.com/docs/responsive-design).
|
23
23
|
*
|
24
|
-
*
|
25
|
-
* <script lang="ts">
|
26
|
-
* import { dev } from "$app/environment"; // SvelteKit Example
|
27
|
-
* </script>
|
28
|
-
*
|
29
|
-
* {#if dev}
|
30
|
-
* <Breakpoint
|
31
|
-
* class="fixed bottom-4 right-4 rounded border bg-white px-2 py-1 font-mono tabular-nums shadow"
|
32
|
-
* />
|
33
|
-
* {/if}
|
34
|
-
* ```
|
24
|
+
* With SvelteKit, this component can be wrapped in an `{#if dev}` block that checks for the [dev module](https://kit.svelte.dev/docs/modules#$app-environment-dev), to show only during development.
|
35
25
|
*
|
36
26
|
* @props
|
37
27
|
*
|
@@ -7,7 +7,6 @@ Displays when the parent element is right clicked, or long pressed on mobile.
|
|
7
7
|
|
8
8
|
@props
|
9
9
|
|
10
|
-
- `classNoscript` - `noscript` class
|
11
10
|
- `class`
|
12
11
|
- `display` - controls `display` css property
|
13
12
|
- `id`
|
@@ -50,7 +49,6 @@ let className = "";
|
|
50
49
|
export { className as class };
|
51
50
|
export let id = "";
|
52
51
|
export let display = false;
|
53
|
-
export let classNoscript = "";
|
54
52
|
export let transition = { duration };
|
55
53
|
let contextMenu;
|
56
54
|
let base;
|
@@ -124,8 +122,6 @@ onMount(() => {
|
|
124
122
|
</div>
|
125
123
|
{/if}
|
126
124
|
|
127
|
-
<noscript><div class={classNoscript}>{messageNoScript}</div></noscript>
|
128
|
-
|
129
125
|
<style>
|
130
126
|
span {
|
131
127
|
width: 0;
|
@@ -5,7 +5,6 @@ declare const __propDef: {
|
|
5
5
|
class?: string | undefined;
|
6
6
|
id?: string | undefined;
|
7
7
|
/** controls `display` css property */ display?: boolean | undefined;
|
8
|
-
/** `noscript` class */ classNoscript?: string | undefined;
|
9
8
|
/** fades the content, set to `false` to remove */ transition?: false | FadeParams | undefined;
|
10
9
|
};
|
11
10
|
events: {
|
@@ -25,7 +24,6 @@ export type ContextMenuSlots = typeof __propDef.slots;
|
|
25
24
|
*
|
26
25
|
* @props
|
27
26
|
*
|
28
|
-
* - `classNoscript` - `noscript` class
|
29
27
|
* - `class`
|
30
28
|
* - `display` - controls `display` css property
|
31
29
|
* - `id`
|
@@ -21,7 +21,7 @@ export type CopyButtonSlots = typeof __propDef.slots;
|
|
21
21
|
/**
|
22
22
|
* ### CopyButton
|
23
23
|
*
|
24
|
-
* Uses the
|
24
|
+
* Uses the [Clipboard API](https://developer.mozilla.org/en-US/docs/Web/API/Clipboard/writeText) to copy text to the clipboard.
|
25
25
|
*
|
26
26
|
* @props
|
27
27
|
*
|
@@ -28,15 +28,18 @@ Data table to display an array of JS objects. Click a column header to sort.
|
|
28
28
|
- `data` - a list of objects to render in the table
|
29
29
|
- `idTable` - `table` id
|
30
30
|
- `id`
|
31
|
-
- `
|
32
|
-
- `sortBy` - column to sort by
|
31
|
+
- `maxRows` - maximum number of rows to show on each page, defaults to `0` - no pagination
|
32
|
+
- `sortBy` - column to sort by, defaults to first column
|
33
33
|
|
34
34
|
@slots
|
35
35
|
|
36
|
-
| name
|
37
|
-
|
|
38
|
-
| `
|
39
|
-
| `
|
36
|
+
| name | purpose | default value | slot props |
|
37
|
+
| ------------ | ------------------------ | -------------------------------- | ------------------------------ |
|
38
|
+
| `next` | next button contents | `Next` | `currentPage` |
|
39
|
+
| `pageNumber` | page numbers | `currentPage` / `numberOfPages` | `currentPage`, `numberOfPages` |
|
40
|
+
| `previous` | previous button contents | `Previous` | `currentPage` |
|
41
|
+
| `td` | td contents | `Previous` | `column`, `row` |
|
42
|
+
| `th` | th contents | `Previous` | `column` |
|
40
43
|
|
41
44
|
@example
|
42
45
|
|
@@ -46,6 +49,7 @@ Data table to display an array of JS objects. Click a column header to sort.
|
|
46
49
|
</script>
|
47
50
|
|
48
51
|
<DataTable
|
52
|
+
class="mb-12"
|
49
53
|
data={[
|
50
54
|
{ make: "Honda", model: "CR-V", year: 2011, awd: true },
|
51
55
|
{ make: "Volvo", model: "XC-40", year: 2024, awd: true },
|
@@ -57,15 +61,49 @@ Data table to display an array of JS objects. Click a column header to sort.
|
|
57
61
|
{ make: "GMC", model: "Acadia", year: 2008, awd: true },
|
58
62
|
{ make: "BMW", model: "X3", year: 2023, awd: true },
|
59
63
|
]}
|
60
|
-
|
61
|
-
|
64
|
+
/>
|
65
|
+
|
66
|
+
<DataTable
|
67
|
+
data={[
|
68
|
+
{ make: "Honda", model: "CR-V", year: 2011, awd: true },
|
69
|
+
{ make: "Volvo", model: "XC-40", year: 2024, awd: true },
|
70
|
+
{ make: "Ferrari", model: "458 Italia", year: 2015, awd: false },
|
71
|
+
{ make: "Chevrolet", model: "Silverado", year: 2022, awd: true },
|
72
|
+
{ make: "Ford", model: "Model A", year: 1931, awd: false },
|
73
|
+
{ make: "Subaru", model: "Outback", year: 2021, awd: true },
|
74
|
+
{ make: "Ford", model: "Bronco", year: 1970, awd: true },
|
75
|
+
{ make: "GMC", model: "Acadia", year: 2008, awd: true },
|
76
|
+
{ make: "BMW", model: "X3", year: 2023, awd: true },
|
77
|
+
]}
|
78
|
+
sortBy="year"
|
79
|
+
maxRows={4}
|
62
80
|
class="tabular-nums"
|
63
|
-
classTh="cursor-pointer
|
81
|
+
classTh="cursor-pointer"
|
64
82
|
classThSorted="underline"
|
65
83
|
classTbodyTr="transition hover:bg-neutral-50"
|
66
84
|
classFooter="flex justify-between items-center"
|
67
85
|
classButton="btn"
|
68
|
-
|
86
|
+
>
|
87
|
+
<svelte:fragment slot="th" let:column>
|
88
|
+
{#if column === "awd"}
|
89
|
+
<span class="uppercase">{column}</span>
|
90
|
+
{:else}
|
91
|
+
{column}
|
92
|
+
{/if}
|
93
|
+
</svelte:fragment>
|
94
|
+
<svelte:fragment slot="td" let:column let:row>
|
95
|
+
{@const item = row[column]}
|
96
|
+
{#if typeof item === "boolean"}
|
97
|
+
{#if item}
|
98
|
+
Yes
|
99
|
+
{:else}
|
100
|
+
No
|
101
|
+
{/if}
|
102
|
+
{:else}
|
103
|
+
{item}
|
104
|
+
{/if}
|
105
|
+
</svelte:fragment>
|
106
|
+
</DataTable>
|
69
107
|
```
|
70
108
|
-->
|
71
109
|
|
@@ -97,12 +135,12 @@ export let classButton = "";
|
|
97
135
|
export let classFooter = "";
|
98
136
|
export let classPageNumber = "";
|
99
137
|
export let classPageControls = "";
|
100
|
-
export let
|
138
|
+
export let maxRows = 0;
|
101
139
|
export let currentPage = 1;
|
102
140
|
export let classNoscript = "";
|
103
141
|
let clientJs = false;
|
104
142
|
$:
|
105
|
-
numberOfPages = Math.floor(data.length /
|
143
|
+
numberOfPages = Math.floor(data.length / maxRows) + 1;
|
106
144
|
const sort = (column, toggleAscending = true) => {
|
107
145
|
if (column === sortBy && toggleAscending) {
|
108
146
|
ascending = !ascending;
|
@@ -150,7 +188,7 @@ onMount(() => clientJs = true);
|
|
150
188
|
class="{classTh} {sortBy === column ? classThSorted : ''}"
|
151
189
|
on:click={() => sort(column)}
|
152
190
|
>
|
153
|
-
{column}
|
191
|
+
<slot name="th" {column}>{column}</slot>
|
154
192
|
</th>
|
155
193
|
{/each}
|
156
194
|
</tr>
|
@@ -158,12 +196,12 @@ onMount(() => clientJs = true);
|
|
158
196
|
<tbody class={classTbody}>
|
159
197
|
{#each data as row, i}
|
160
198
|
{@const showRow =
|
161
|
-
i <
|
162
|
-
{#if
|
199
|
+
i < maxRows * currentPage && i >= maxRows * (currentPage - 1)}
|
200
|
+
{#if maxRows ? showRow : true}
|
163
201
|
<tr class={classTbodyTr}>
|
164
202
|
{#each columns as column}
|
165
203
|
<td class="{classTd} {sortBy === column ? classTdSorted : ''}">
|
166
|
-
{row[column]}
|
204
|
+
<slot name="td" {row} {column}>{row[column]}</slot>
|
167
205
|
</td>
|
168
206
|
{/each}
|
169
207
|
</tr>
|
@@ -172,23 +210,29 @@ onMount(() => clientJs = true);
|
|
172
210
|
</tbody>
|
173
211
|
</table>
|
174
212
|
|
175
|
-
{#if
|
213
|
+
{#if maxRows}
|
176
214
|
<div class={classFooter}>
|
177
|
-
<div class={classPageNumber}>
|
215
|
+
<div class={classPageNumber}>
|
216
|
+
<slot name="pageNumber" {currentPage} {numberOfPages}>
|
217
|
+
{currentPage} / {numberOfPages}
|
218
|
+
</slot>
|
219
|
+
</div>
|
178
220
|
<div class={classPageControls}>
|
179
221
|
<button
|
222
|
+
type="button"
|
180
223
|
class={classButton}
|
181
224
|
disabled={!clientJs || currentPage < 2}
|
182
225
|
on:click={() => currentPage--}
|
183
226
|
>
|
184
|
-
<slot name="previous">Previous</slot>
|
227
|
+
<slot name="previous" {currentPage}>Previous</slot>
|
185
228
|
</button>
|
186
229
|
<button
|
230
|
+
type="button"
|
187
231
|
class={classButton}
|
188
232
|
disabled={!clientJs || currentPage >= numberOfPages}
|
189
233
|
on:click={() => currentPage++}
|
190
234
|
>
|
191
|
-
<slot name="next">Next</slot>
|
235
|
+
<slot name="next" {currentPage}>Next</slot>
|
192
236
|
</button>
|
193
237
|
</div>
|
194
238
|
</div>
|
@@ -8,7 +8,7 @@ declare const __propDef: {
|
|
8
8
|
id?: string | undefined;
|
9
9
|
/** a list of objects to render in the table */ data: DataTableRow<any>[];
|
10
10
|
/** table columns, in order */ columns?: string[] | undefined;
|
11
|
-
/** column to sort by
|
11
|
+
/** column to sort by, defaults to first column */ sortBy?: string | undefined;
|
12
12
|
/** default sort order */ ascending?: boolean | undefined;
|
13
13
|
/** `table` class */ classTable?: string | undefined;
|
14
14
|
/** `table` id */ idTable?: string | undefined;
|
@@ -24,7 +24,7 @@ declare const __propDef: {
|
|
24
24
|
/** `footer` class */ classFooter?: string | undefined;
|
25
25
|
/** class of `div` wrapping page numbers */ classPageNumber?: string | undefined;
|
26
26
|
/** class of `div` that wraps the "Previous" and "Next" buttons */ classPageControls?: string | undefined;
|
27
|
-
/** number of rows to show on each page, defaults to `0` - no pagination */
|
27
|
+
/** maximum number of rows to show on each page, defaults to `0` - no pagination */ maxRows?: number | undefined;
|
28
28
|
/** current page, defaults to `1` */ currentPage?: number | undefined;
|
29
29
|
/** `noscript` class */ classNoscript?: string | undefined;
|
30
30
|
};
|
@@ -32,8 +32,23 @@ declare const __propDef: {
|
|
32
32
|
[evt: string]: CustomEvent<any>;
|
33
33
|
};
|
34
34
|
slots: {
|
35
|
-
|
36
|
-
|
35
|
+
th: {
|
36
|
+
column: string;
|
37
|
+
};
|
38
|
+
td: {
|
39
|
+
row: DataTableRow<any>;
|
40
|
+
column: string;
|
41
|
+
};
|
42
|
+
pageNumber: {
|
43
|
+
currentPage: number;
|
44
|
+
numberOfPages: number;
|
45
|
+
};
|
46
|
+
previous: {
|
47
|
+
currentPage: number;
|
48
|
+
};
|
49
|
+
next: {
|
50
|
+
currentPage: number;
|
51
|
+
};
|
37
52
|
};
|
38
53
|
};
|
39
54
|
export type DataTableProps = typeof __propDef.props;
|
@@ -67,15 +82,18 @@ export type DataTableSlots = typeof __propDef.slots;
|
|
67
82
|
* - `data` - a list of objects to render in the table
|
68
83
|
* - `idTable` - `table` id
|
69
84
|
* - `id`
|
70
|
-
* - `
|
71
|
-
* - `sortBy` - column to sort by
|
85
|
+
* - `maxRows` - maximum number of rows to show on each page, defaults to `0` - no pagination
|
86
|
+
* - `sortBy` - column to sort by, defaults to first column
|
72
87
|
*
|
73
88
|
* @slots
|
74
89
|
*
|
75
|
-
* | name
|
76
|
-
* |
|
77
|
-
* | `
|
78
|
-
* | `
|
90
|
+
* | name | purpose | default value | slot props |
|
91
|
+
* | ------------ | ------------------------ | -------------------------------- | ------------------------------ |
|
92
|
+
* | `next` | next button contents | `Next` | `currentPage` |
|
93
|
+
* | `pageNumber` | page numbers | `currentPage` / `numberOfPages` | `currentPage`, `numberOfPages` |
|
94
|
+
* | `previous` | previous button contents | `Previous` | `currentPage` |
|
95
|
+
* | `td` | td contents | `Previous` | `column`, `row` |
|
96
|
+
* | `th` | th contents | `Previous` | `column` |
|
79
97
|
*
|
80
98
|
* @example
|
81
99
|
*
|
@@ -85,6 +103,7 @@ export type DataTableSlots = typeof __propDef.slots;
|
|
85
103
|
* </script>
|
86
104
|
*
|
87
105
|
* <DataTable
|
106
|
+
* class="mb-12"
|
88
107
|
* data={[
|
89
108
|
* { make: "Honda", model: "CR-V", year: 2011, awd: true },
|
90
109
|
* { make: "Volvo", model: "XC-40", year: 2024, awd: true },
|
@@ -96,15 +115,49 @@ export type DataTableSlots = typeof __propDef.slots;
|
|
96
115
|
* { make: "GMC", model: "Acadia", year: 2008, awd: true },
|
97
116
|
* { make: "BMW", model: "X3", year: 2023, awd: true },
|
98
117
|
* ]}
|
99
|
-
*
|
100
|
-
*
|
118
|
+
* />
|
119
|
+
*
|
120
|
+
* <DataTable
|
121
|
+
* data={[
|
122
|
+
* { make: "Honda", model: "CR-V", year: 2011, awd: true },
|
123
|
+
* { make: "Volvo", model: "XC-40", year: 2024, awd: true },
|
124
|
+
* { make: "Ferrari", model: "458 Italia", year: 2015, awd: false },
|
125
|
+
* { make: "Chevrolet", model: "Silverado", year: 2022, awd: true },
|
126
|
+
* { make: "Ford", model: "Model A", year: 1931, awd: false },
|
127
|
+
* { make: "Subaru", model: "Outback", year: 2021, awd: true },
|
128
|
+
* { make: "Ford", model: "Bronco", year: 1970, awd: true },
|
129
|
+
* { make: "GMC", model: "Acadia", year: 2008, awd: true },
|
130
|
+
* { make: "BMW", model: "X3", year: 2023, awd: true },
|
131
|
+
* ]}
|
132
|
+
* sortBy="year"
|
133
|
+
* maxRows={4}
|
101
134
|
* class="tabular-nums"
|
102
|
-
* classTh="cursor-pointer
|
135
|
+
* classTh="cursor-pointer"
|
103
136
|
* classThSorted="underline"
|
104
137
|
* classTbodyTr="transition hover:bg-neutral-50"
|
105
138
|
* classFooter="flex justify-between items-center"
|
106
139
|
* classButton="btn"
|
107
|
-
*
|
140
|
+
* >
|
141
|
+
* <svelte:fragment slot="th" let:column>
|
142
|
+
* {#if column === "awd"}
|
143
|
+
* <span class="uppercase">{column}</span>
|
144
|
+
* {:else}
|
145
|
+
* {column}
|
146
|
+
* {/if}
|
147
|
+
* </svelte:fragment>
|
148
|
+
* <svelte:fragment slot="td" let:column let:row>
|
149
|
+
* {@const item = row[column]}
|
150
|
+
* {#if typeof item === "boolean"}
|
151
|
+
* {#if item}
|
152
|
+
* Yes
|
153
|
+
* {:else}
|
154
|
+
* No
|
155
|
+
* {/if}
|
156
|
+
* {:else}
|
157
|
+
* {item}
|
158
|
+
* {/if}
|
159
|
+
* </svelte:fragment>
|
160
|
+
* </DataTable>
|
108
161
|
* ```
|
109
162
|
*/
|
110
163
|
export default class DataTable extends SvelteComponent<DataTableProps, DataTableEvents, DataTableSlots> {
|
@@ -38,10 +38,9 @@ Make the document or a specific element fullscreen.
|
|
38
38
|
bind:this={fullscreenDiv}
|
39
39
|
class="mt-4 rounded bg-neutral-800 p-4 text-neutral-50"
|
40
40
|
>
|
41
|
-
<div class="mb-2">Target element
|
41
|
+
<div class="mb-2">Target element</div>
|
42
42
|
<FullscreenButton target={fullscreenDiv} class="btn btn-s bg-neutral-50">
|
43
|
-
|
44
|
-
<span slot="enabled">Exit Element Fullscreen</span>
|
43
|
+
Enable Element Fullscreen
|
45
44
|
</FullscreenButton>
|
46
45
|
</div>
|
47
46
|
```
|
@@ -57,10 +57,9 @@ export type FullscreenButtonSlots = typeof __propDef.slots;
|
|
57
57
|
* bind:this={fullscreenDiv}
|
58
58
|
* class="mt-4 rounded bg-neutral-800 p-4 text-neutral-50"
|
59
59
|
* >
|
60
|
-
* <div class="mb-2">Target element
|
60
|
+
* <div class="mb-2">Target element</div>
|
61
61
|
* <FullscreenButton target={fullscreenDiv} class="btn btn-s bg-neutral-50">
|
62
|
-
*
|
63
|
-
* <span slot="enabled">Exit Element Fullscreen</span>
|
62
|
+
* Enable Element Fullscreen
|
64
63
|
* </FullscreenButton>
|
65
64
|
* </div>
|
66
65
|
* ```
|
@@ -3,7 +3,7 @@
|
|
3
3
|
|
4
4
|
### ShareButton
|
5
5
|
|
6
|
-
Uses the
|
6
|
+
Uses the [Navigator API](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/share) or the [Clipboard API](https://developer.mozilla.org/en-US/docs/Web/API/Clipboard/writeText) to share or copy a url link depending on browser support.
|
7
7
|
|
8
8
|
@props
|
9
9
|
|
@@ -22,7 +22,7 @@ export type ShareButtonSlots = typeof __propDef.slots;
|
|
22
22
|
/**
|
23
23
|
* ### ShareButton
|
24
24
|
*
|
25
|
-
* Uses the
|
25
|
+
* Uses the [Navigator API](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/share) or the [Clipboard API](https://developer.mozilla.org/en-US/docs/Web/API/Clipboard/writeText) to share or copy a url link depending on browser support.
|
26
26
|
*
|
27
27
|
* @props
|
28
28
|
*
|
@@ -11,9 +11,8 @@ Creates a sheet element based on the `position` provided.
|
|
11
11
|
- `class`
|
12
12
|
- `display` - controls whether the sheet is displayed
|
13
13
|
- `id`
|
14
|
-
- `
|
14
|
+
- `maxSize` - max width/height of sheet based on the `side` - can also use css instead
|
15
15
|
- `position` - determines the position of sheet
|
16
|
-
- `size` - width/height of sheet based on the `side` - can also use css instead
|
17
16
|
- `transitionSheet` - slides the sheet, set to `false` to remove
|
18
17
|
- `transition` - fades the entire component, set to `false` to remove
|
19
18
|
|
@@ -28,7 +27,6 @@ Creates a sheet element based on the `position` provided.
|
|
28
27
|
```svelte
|
29
28
|
<script lang="ts">
|
30
29
|
import { Sheet } from "drab";
|
31
|
-
import { X } from "../../site/svg/X.svelte";
|
32
30
|
|
33
31
|
let display = false;
|
34
32
|
</script>
|
@@ -46,13 +44,8 @@ Creates a sheet element based on the `position` provided.
|
|
46
44
|
>
|
47
45
|
<div class="mb-4 flex items-center justify-between">
|
48
46
|
<h2 class="my-0">Sheet</h2>
|
49
|
-
<button
|
50
|
-
|
51
|
-
title="Close"
|
52
|
-
class="btn btn-s"
|
53
|
-
on:click={() => (display = false)}
|
54
|
-
>
|
55
|
-
<X />
|
47
|
+
<button type="button" class="btn btn-s" on:click={() => (display = false)}>
|
48
|
+
Close
|
56
49
|
</button>
|
57
50
|
</div>
|
58
51
|
<div>
|
@@ -80,15 +73,9 @@ export let classSheet = "";
|
|
80
73
|
export let display = false;
|
81
74
|
export let transition = { duration };
|
82
75
|
export let position = "right";
|
83
|
-
export let
|
76
|
+
export let maxSize = 488;
|
84
77
|
export let transitionSheet = { duration };
|
85
|
-
export let onClickClose = false;
|
86
78
|
let sheet;
|
87
|
-
const clickOutside = (e) => {
|
88
|
-
if (e.target instanceof Node && !sheet.contains(e.target) || onClickClose) {
|
89
|
-
display = false;
|
90
|
-
}
|
91
|
-
};
|
92
79
|
const onKeyDown = (e) => {
|
93
80
|
if (e.key === "Escape") {
|
94
81
|
display = false;
|
@@ -96,13 +83,13 @@ const onKeyDown = (e) => {
|
|
96
83
|
};
|
97
84
|
if (transitionSheet && !transitionSheet.x && !transitionSheet.y) {
|
98
85
|
if (position === "bottom") {
|
99
|
-
transitionSheet.y =
|
86
|
+
transitionSheet.y = maxSize;
|
100
87
|
} else if (position === "top") {
|
101
|
-
transitionSheet.y = -
|
88
|
+
transitionSheet.y = -maxSize;
|
102
89
|
} else if (position === "right") {
|
103
|
-
transitionSheet.x =
|
90
|
+
transitionSheet.x = maxSize;
|
104
91
|
} else {
|
105
|
-
transitionSheet.x = -
|
92
|
+
transitionSheet.x = -maxSize;
|
106
93
|
}
|
107
94
|
}
|
108
95
|
onMount(() => {
|
@@ -119,12 +106,11 @@ onMount(() => {
|
|
119
106
|
|
120
107
|
{#if display}
|
121
108
|
<div
|
122
|
-
role="button"
|
123
|
-
tabindex="0"
|
124
|
-
on:click={clickOutside}
|
125
|
-
on:keydown={onKeyDown}
|
126
109
|
transition:fade={transition ? transition : { duration: 0 }}
|
127
110
|
class="d-backdrop {className}"
|
111
|
+
class:d-backdrop-bottom={position === "bottom"}
|
112
|
+
class:d-backdrop-top={position === "top"}
|
113
|
+
class:d-backdrop-right={position === "right"}
|
128
114
|
{id}
|
129
115
|
>
|
130
116
|
<div
|
@@ -132,47 +118,59 @@ onMount(() => {
|
|
132
118
|
bind:this={sheet}
|
133
119
|
transition:fly={transitionSheet ? transitionSheet : { duration: 0 }}
|
134
120
|
style={position === "top" || position === "bottom"
|
135
|
-
? `max-height: ${
|
136
|
-
: `max-width: ${
|
121
|
+
? `max-height: ${maxSize}px;`
|
122
|
+
: `max-width: ${maxSize}px`}
|
137
123
|
class="d-sheet {classSheet}"
|
138
|
-
class:d-bottom={position === "bottom"}
|
139
|
-
class:d-top={position === "top"}
|
140
|
-
class:d-left={position === "left"}
|
141
|
-
class:d-right={position === "right"}
|
124
|
+
class:d-sheet-bottom={position === "bottom"}
|
125
|
+
class:d-sheet-top={position === "top"}
|
126
|
+
class:d-sheet-left={position === "left"}
|
127
|
+
class:d-sheet-right={position === "right"}
|
142
128
|
>
|
143
129
|
<slot>Content</slot>
|
144
130
|
</div>
|
131
|
+
<button title="Close" on:click={() => (display = false)}></button>
|
145
132
|
</div>
|
146
133
|
{/if}
|
147
134
|
|
148
135
|
<style>
|
136
|
+
button {
|
137
|
+
flex-grow: 1;
|
138
|
+
}
|
149
139
|
.d-backdrop {
|
150
140
|
position: fixed;
|
151
|
-
display:
|
141
|
+
display: flex;
|
152
142
|
z-index: 40;
|
153
143
|
top: 0;
|
154
144
|
bottom: 0;
|
155
145
|
left: 0;
|
156
146
|
right: 0;
|
157
147
|
overflow: hidden;
|
158
|
-
|
148
|
+
}
|
149
|
+
.d-backdrop-bottom {
|
150
|
+
flex-direction: column-reverse;
|
151
|
+
}
|
152
|
+
.d-backdrop-top {
|
153
|
+
flex-direction: column;
|
154
|
+
}
|
155
|
+
.d-backdrop-right {
|
156
|
+
flex-direction: row-reverse;
|
159
157
|
}
|
160
158
|
.d-sheet {
|
161
159
|
margin: auto;
|
162
160
|
}
|
163
|
-
.d-bottom {
|
161
|
+
.d-sheet-bottom {
|
164
162
|
margin-bottom: 0;
|
165
163
|
width: 100%;
|
166
164
|
}
|
167
|
-
.d-top {
|
165
|
+
.d-sheet-top {
|
168
166
|
margin-top: 0;
|
169
167
|
width: 100%;
|
170
168
|
}
|
171
|
-
.d-right {
|
169
|
+
.d-sheet-right {
|
172
170
|
margin-right: 0;
|
173
171
|
height: 100%;
|
174
172
|
}
|
175
|
-
.d-left {
|
173
|
+
.d-sheet-left {
|
176
174
|
margin-left: 0;
|
177
175
|
height: 100%;
|
178
176
|
}
|
@@ -8,9 +8,8 @@ declare const __propDef: {
|
|
8
8
|
/** controls whether the sheet is displayed*/ display?: boolean | undefined;
|
9
9
|
/** fades the entire component, set to `false` to remove */ transition?: false | FadeParams | undefined;
|
10
10
|
/** determines the position of sheet */ position?: "top" | "bottom" | "left" | "right" | undefined;
|
11
|
-
/** width/height of sheet based on the `side` - can also use css instead */
|
11
|
+
/** max width/height of sheet based on the `side` - can also use css instead */ maxSize?: number | undefined;
|
12
12
|
/** slides the sheet, set to `false` to remove */ transitionSheet?: false | FlyParams | undefined;
|
13
|
-
/** close on click, defaults to `false` - only closes if clicked outside */ onClickClose?: boolean | undefined;
|
14
13
|
};
|
15
14
|
events: {
|
16
15
|
[evt: string]: CustomEvent<any>;
|
@@ -33,9 +32,8 @@ export type SheetSlots = typeof __propDef.slots;
|
|
33
32
|
* - `class`
|
34
33
|
* - `display` - controls whether the sheet is displayed
|
35
34
|
* - `id`
|
36
|
-
* - `
|
35
|
+
* - `maxSize` - max width/height of sheet based on the `side` - can also use css instead
|
37
36
|
* - `position` - determines the position of sheet
|
38
|
-
* - `size` - width/height of sheet based on the `side` - can also use css instead
|
39
37
|
* - `transitionSheet` - slides the sheet, set to `false` to remove
|
40
38
|
* - `transition` - fades the entire component, set to `false` to remove
|
41
39
|
*
|
@@ -50,7 +48,6 @@ export type SheetSlots = typeof __propDef.slots;
|
|
50
48
|
* ```svelte
|
51
49
|
* <script lang="ts">
|
52
50
|
* import { Sheet } from "drab";
|
53
|
-
* import { X } from "../../site/svg/X.svelte";
|
54
51
|
*
|
55
52
|
* let display = false;
|
56
53
|
* </script>
|
@@ -68,13 +65,8 @@ export type SheetSlots = typeof __propDef.slots;
|
|
68
65
|
* >
|
69
66
|
* <div class="mb-4 flex items-center justify-between">
|
70
67
|
* <h2 class="my-0">Sheet</h2>
|
71
|
-
* <button
|
72
|
-
*
|
73
|
-
* title="Close"
|
74
|
-
* class="btn btn-s"
|
75
|
-
* on:click={() => (display = false)}
|
76
|
-
* >
|
77
|
-
* <X />
|
68
|
+
* <button type="button" class="btn btn-s" on:click={() => (display = false)}>
|
69
|
+
* Close
|
78
70
|
* </button>
|
79
71
|
* </div>
|
80
72
|
* <div>
|
@@ -3,7 +3,7 @@
|
|
3
3
|
|
4
4
|
### Tabs
|
5
5
|
|
6
|
-
Displays tabs and the
|
6
|
+
Displays tabs and the selected tab's content.
|
7
7
|
|
8
8
|
@props
|
9
9
|
|
@@ -15,15 +15,16 @@ Displays tabs and the active tab's content.
|
|
15
15
|
- `classTab` - class of all title `button`s
|
16
16
|
- `class`
|
17
17
|
- `id`
|
18
|
-
- `selectedIndex` - index of selected tab, defaults to 0
|
19
|
-
- `tabs` - array of
|
18
|
+
- `selectedIndex` - index of selected tab, defaults to `0`
|
19
|
+
- `tabs` - array of `TabsTab` objects
|
20
|
+
- `transition` - fades the panel content, set to `false` to remove
|
20
21
|
|
21
22
|
@slots
|
22
23
|
|
23
|
-
| name
|
24
|
-
|
|
25
|
-
| `
|
26
|
-
| `tab`
|
24
|
+
| name | purpose | default value | slot props |
|
25
|
+
| ------- | ------------------ | ------------------- | ---------------------- |
|
26
|
+
| `panel` | active tab's panel | `selectedTab.panel` | `selectedTab`, `index` |
|
27
|
+
| `tab` | title of each tab | `tab.tab` | `tab`, `index` |
|
27
28
|
|
28
29
|
@example
|
29
30
|
|
@@ -60,16 +61,17 @@ Displays tabs and the active tab's content.
|
|
60
61
|
data: { component: FullscreenButton },
|
61
62
|
},
|
62
63
|
]}
|
63
|
-
let:selectedTab
|
64
64
|
>
|
65
|
-
<svelte:fragment slot="tab" let:
|
66
|
-
{
|
65
|
+
<svelte:fragment slot="tab" let:tab let:index>
|
66
|
+
{tab.tab}
|
67
67
|
{index + 1}
|
68
68
|
</svelte:fragment>
|
69
|
-
<
|
70
|
-
|
71
|
-
|
72
|
-
|
69
|
+
<svelte:fragment slot="panel" let:selectedTab>
|
70
|
+
<div class="mb-2">{selectedTab.panel}</div>
|
71
|
+
{#if selectedTab.data?.component}
|
72
|
+
<svelte:component this={selectedTab.data.component} class="btn" />
|
73
|
+
{/if}
|
74
|
+
</svelte:fragment>
|
73
75
|
</Tabs>
|
74
76
|
```
|
75
77
|
-->
|
@@ -78,6 +80,9 @@ Displays tabs and the active tab's content.
|
|
78
80
|
|
79
81
|
<script>import { onMount } from "svelte";
|
80
82
|
import { messageNoScript } from "../util/messages";
|
83
|
+
import { fade } from "svelte/transition";
|
84
|
+
import { duration } from "../util/transition";
|
85
|
+
import { prefersReducedMotion } from "../util/accessibility";
|
81
86
|
let className = "";
|
82
87
|
export { className as class };
|
83
88
|
export let id = "";
|
@@ -89,15 +94,20 @@ export let classNoscript = "";
|
|
89
94
|
export let classTabPanel = "";
|
90
95
|
export let tabs;
|
91
96
|
export let selectedIndex = 0;
|
97
|
+
export let transition = { duration };
|
92
98
|
let clientJs = false;
|
93
|
-
|
94
|
-
|
95
|
-
|
99
|
+
onMount(() => {
|
100
|
+
if (prefersReducedMotion()) {
|
101
|
+
if (transition)
|
102
|
+
transition.duration = 0;
|
103
|
+
}
|
104
|
+
clientJs = true;
|
105
|
+
});
|
96
106
|
</script>
|
97
107
|
|
98
108
|
<div class={className} {id}>
|
99
109
|
<div class={classTabList} role="tablist">
|
100
|
-
{#each tabs as
|
110
|
+
{#each tabs as tab, index}
|
101
111
|
<button
|
102
112
|
role="tab"
|
103
113
|
tabindex={index === selectedIndex ? 0 : -1}
|
@@ -109,13 +119,22 @@ onMount(() => clientJs = true);
|
|
109
119
|
: ''} {selectedIndex !== index ? classTabInactive : ''}"
|
110
120
|
on:click={() => (selectedIndex = index)}
|
111
121
|
>
|
112
|
-
<slot name="tab" {
|
122
|
+
<slot name="tab" {tab} {index}>{tab.tab}</slot>
|
113
123
|
</button>
|
114
124
|
{/each}
|
115
125
|
</div>
|
116
|
-
|
117
|
-
|
118
|
-
|
126
|
+
{#each tabs as tab, index}
|
127
|
+
{#if index === selectedIndex}
|
128
|
+
<div
|
129
|
+
class={classTabPanel}
|
130
|
+
role="tabpanel"
|
131
|
+
id="tabpanel"
|
132
|
+
in:fade={transition ? transition : { duration: 0 }}
|
133
|
+
>
|
134
|
+
<slot name="panel" selectedTab={tab} {index}>{tab.panel}</slot>
|
135
|
+
</div>
|
136
|
+
{/if}
|
137
|
+
{/each}
|
119
138
|
<noscript>
|
120
139
|
<div class={classNoscript}>{messageNoScript}</div>
|
121
140
|
</noscript>
|
@@ -7,6 +7,7 @@ export interface TabsTab<T = any> {
|
|
7
7
|
/** any data to pass back to the parent */
|
8
8
|
data?: T;
|
9
9
|
}
|
10
|
+
import { type FadeParams } from "svelte/transition";
|
10
11
|
declare const __propDef: {
|
11
12
|
props: {
|
12
13
|
class?: string | undefined;
|
@@ -17,19 +18,21 @@ declare const __propDef: {
|
|
17
18
|
/** class of all the inactive tabs' `button`s */ classTabInactive?: string | undefined;
|
18
19
|
/** `noscript` class */ classNoscript?: string | undefined;
|
19
20
|
/** class of `div` that wraps the slotted content */ classTabPanel?: string | undefined;
|
20
|
-
/** array of
|
21
|
-
/** index of selected tab, defaults to 0 */ selectedIndex?: number | undefined;
|
21
|
+
/** array of `TabsTab` objects */ tabs: TabsTab[];
|
22
|
+
/** index of selected tab, defaults to `0` */ selectedIndex?: number | undefined;
|
23
|
+
/** fades the panel content, set to `false` to remove */ transition?: false | FadeParams | undefined;
|
22
24
|
};
|
23
25
|
events: {
|
24
26
|
[evt: string]: CustomEvent<any>;
|
25
27
|
};
|
26
28
|
slots: {
|
27
29
|
tab: {
|
28
|
-
|
30
|
+
tab: TabsTab<any>;
|
29
31
|
index: any;
|
30
32
|
};
|
31
|
-
|
33
|
+
panel: {
|
32
34
|
selectedTab: TabsTab<any>;
|
35
|
+
index: any;
|
33
36
|
};
|
34
37
|
};
|
35
38
|
};
|
@@ -39,7 +42,7 @@ export type TabsSlots = typeof __propDef.slots;
|
|
39
42
|
/**
|
40
43
|
* ### Tabs
|
41
44
|
*
|
42
|
-
* Displays tabs and the
|
45
|
+
* Displays tabs and the selected tab's content.
|
43
46
|
*
|
44
47
|
* @props
|
45
48
|
*
|
@@ -51,15 +54,16 @@ export type TabsSlots = typeof __propDef.slots;
|
|
51
54
|
* - `classTab` - class of all title `button`s
|
52
55
|
* - `class`
|
53
56
|
* - `id`
|
54
|
-
* - `selectedIndex` - index of selected tab, defaults to 0
|
55
|
-
* - `tabs` - array of
|
57
|
+
* - `selectedIndex` - index of selected tab, defaults to `0`
|
58
|
+
* - `tabs` - array of `TabsTab` objects
|
59
|
+
* - `transition` - fades the panel content, set to `false` to remove
|
56
60
|
*
|
57
61
|
* @slots
|
58
62
|
*
|
59
|
-
* | name
|
60
|
-
* |
|
61
|
-
* | `
|
62
|
-
* | `tab`
|
63
|
+
* | name | purpose | default value | slot props |
|
64
|
+
* | ------- | ------------------ | ------------------- | ---------------------- |
|
65
|
+
* | `panel` | active tab's panel | `selectedTab.panel` | `selectedTab`, `index` |
|
66
|
+
* | `tab` | title of each tab | `tab.tab` | `tab`, `index` |
|
63
67
|
*
|
64
68
|
* @example
|
65
69
|
*
|
@@ -96,16 +100,17 @@ export type TabsSlots = typeof __propDef.slots;
|
|
96
100
|
* data: { component: FullscreenButton },
|
97
101
|
* },
|
98
102
|
* ]}
|
99
|
-
* let:selectedTab
|
100
103
|
* >
|
101
|
-
* <svelte:fragment slot="tab" let:
|
102
|
-
* {
|
104
|
+
* <svelte:fragment slot="tab" let:tab let:index>
|
105
|
+
* {tab.tab}
|
103
106
|
* {index + 1}
|
104
107
|
* </svelte:fragment>
|
105
|
-
* <
|
106
|
-
* {
|
107
|
-
*
|
108
|
-
* {
|
108
|
+
* <svelte:fragment slot="panel" let:selectedTab>
|
109
|
+
* <div class="mb-2">{selectedTab.panel}</div>
|
110
|
+
* {#if selectedTab.data?.component}
|
111
|
+
* <svelte:component this={selectedTab.data.component} class="btn" />
|
112
|
+
* {/if}
|
113
|
+
* </svelte:fragment>
|
109
114
|
* </Tabs>
|
110
115
|
* ```
|
111
116
|
*/
|