drab 2.3.0 → 2.4.1
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 +21 -31
- package/dist/components/Accordion.svelte.d.ts +21 -32
- package/dist/components/Chord.svelte +4 -1
- package/dist/components/Chord.svelte.d.ts +4 -1
- package/dist/components/ContextMenu.svelte +7 -7
- package/dist/components/ContextMenu.svelte.d.ts +7 -7
- package/dist/components/CopyButton.svelte +3 -1
- package/dist/components/CopyButton.svelte.d.ts +4 -2
- package/dist/components/DataTable.svelte +72 -54
- package/dist/components/DataTable.svelte.d.ts +15 -0
- package/dist/components/Editor.svelte +6 -1
- package/dist/components/Editor.svelte.d.ts +6 -1
- package/dist/components/FullscreenButton.svelte +10 -5
- package/dist/components/FullscreenButton.svelte.d.ts +10 -5
- package/dist/components/Popover.svelte +20 -6
- package/dist/components/Popover.svelte.d.ts +20 -6
- package/dist/components/ShareButton.svelte +8 -5
- package/dist/components/ShareButton.svelte.d.ts +6 -3
- package/dist/components/Tabs.svelte +63 -48
- package/dist/components/Tabs.svelte.d.ts +68 -27
- package/dist/components/YouTube.svelte +5 -1
- package/dist/components/YouTube.svelte.d.ts +5 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +2 -1
- package/package.json +3 -2
@@ -21,20 +21,26 @@ Displays a list of `details` elements.
|
|
21
21
|
|
22
22
|
@slots
|
23
23
|
|
24
|
-
| name
|
25
|
-
|
|
26
|
-
| `summary`
|
27
|
-
| `icon`
|
28
|
-
| `content`
|
24
|
+
| name | purpose | default value | slot props |
|
25
|
+
| --------- | ----------------------------- | -------------- | --------------- |
|
26
|
+
| `summary` | summary element | `item.summary` | `item`, `index` |
|
27
|
+
| `icon` | icon element | `icon` prop | `item`, `index` |
|
28
|
+
| `content` | content of the accordion item | `item.content` | `item`, `index` |
|
29
29
|
|
30
30
|
@example
|
31
31
|
|
32
32
|
```svelte
|
33
33
|
<script>
|
34
|
-
import
|
34
|
+
import Accordion from "./Accordion.svelte";
|
35
|
+
import FullscreenButton from "./FullscreenButton.svelte";
|
36
|
+
import Chevron from "../../site/svg/Chevron.svelte";
|
35
37
|
</script>
|
36
38
|
|
37
|
-
<Accordion
|
39
|
+
<Accordion
|
40
|
+
icon={Chevron}
|
41
|
+
classDetails="border-b"
|
42
|
+
classHeader="flex gap-8 cursor-pointer items-center justify-between py-4 font-bold hover:underline"
|
43
|
+
classContent="pb-4"
|
38
44
|
items={[
|
39
45
|
{ summary: "Is it accessible?", content: "Yes." },
|
40
46
|
{
|
@@ -46,38 +52,22 @@ Displays a list of `details` elements.
|
|
46
52
|
content: "Yes, with the transition prop.",
|
47
53
|
},
|
48
54
|
{ summary: "Does it work without Javascript?", content: "Yes." },
|
49
|
-
]}
|
50
|
-
>
|
51
|
-
<div slot="content" let:item let:index>
|
52
|
-
<span>{index + 1}.</span>
|
53
|
-
<span>{item.content}</span>
|
54
|
-
</div>
|
55
|
-
</Accordion>
|
56
|
-
```
|
57
|
-
|
58
|
-
To render a component on unique items, pass it into the `data` prop and utilize `<svelte:component this={item.data.component}>` inside of the slot.
|
59
|
-
|
60
|
-
```svelte
|
61
|
-
<script>
|
62
|
-
import { Accordion, FullScreenButton } from "drab";
|
63
|
-
</script>
|
64
|
-
|
65
|
-
<Accordion
|
66
|
-
items={[
|
67
55
|
{
|
68
|
-
summary: "
|
56
|
+
summary: "Component",
|
69
57
|
content: "Rendered only on this item.",
|
70
58
|
data: { component: FullscreenButton },
|
71
59
|
},
|
72
|
-
{ summary: "Summary", content: "Some other content" },
|
73
60
|
]}
|
74
61
|
>
|
75
|
-
<
|
76
|
-
|
62
|
+
<svelte:fragment slot="content" let:item let:index>
|
63
|
+
<div class="mb-4">
|
64
|
+
<span>{index + 1}.</span>
|
65
|
+
<span>{item.content}</span>
|
66
|
+
</div>
|
77
67
|
{#if item.data?.component}
|
78
|
-
<svelte:component this={item.data.component} />
|
68
|
+
<svelte:component class="btn" this={item.data.component} />
|
79
69
|
{/if}
|
80
|
-
</
|
70
|
+
</svelte:fragment>
|
81
71
|
</Accordion>
|
82
72
|
```
|
83
73
|
-->
|
@@ -1,5 +1,4 @@
|
|
1
1
|
import { SvelteComponent } from "svelte";
|
2
|
-
/** use `data` to pass anything back to the parent */
|
3
2
|
export interface AccordionItem<T = any> {
|
4
3
|
/** text summary of the item */
|
5
4
|
summary?: string;
|
@@ -7,7 +6,7 @@ export interface AccordionItem<T = any> {
|
|
7
6
|
content?: string;
|
8
7
|
/** controls whether the content is displayed */
|
9
8
|
open?: boolean;
|
10
|
-
/** any data to pass back */
|
9
|
+
/** any data to pass back to the parent */
|
11
10
|
data?: T;
|
12
11
|
}
|
13
12
|
import { type ComponentType } from "svelte";
|
@@ -68,20 +67,26 @@ export type AccordionSlots = typeof __propDef.slots;
|
|
68
67
|
*
|
69
68
|
* @slots
|
70
69
|
*
|
71
|
-
* | name
|
72
|
-
* |
|
73
|
-
* | `summary`
|
74
|
-
* | `icon`
|
75
|
-
* | `content`
|
70
|
+
* | name | purpose | default value | slot props |
|
71
|
+
* | --------- | ----------------------------- | -------------- | --------------- |
|
72
|
+
* | `summary` | summary element | `item.summary` | `item`, `index` |
|
73
|
+
* | `icon` | icon element | `icon` prop | `item`, `index` |
|
74
|
+
* | `content` | content of the accordion item | `item.content` | `item`, `index` |
|
76
75
|
*
|
77
76
|
* @example
|
78
77
|
*
|
79
78
|
* ```svelte
|
80
79
|
* <script>
|
81
|
-
* import
|
80
|
+
* import Accordion from "./Accordion.svelte";
|
81
|
+
* import FullscreenButton from "./FullscreenButton.svelte";
|
82
|
+
* import Chevron from "../../site/svg/Chevron.svelte";
|
82
83
|
* </script>
|
83
84
|
*
|
84
85
|
* <Accordion
|
86
|
+
* icon={Chevron}
|
87
|
+
* classDetails="border-b"
|
88
|
+
* classHeader="flex gap-8 cursor-pointer items-center justify-between py-4 font-bold hover:underline"
|
89
|
+
* classContent="pb-4"
|
85
90
|
* items={[
|
86
91
|
* { summary: "Is it accessible?", content: "Yes." },
|
87
92
|
* {
|
@@ -93,38 +98,22 @@ export type AccordionSlots = typeof __propDef.slots;
|
|
93
98
|
* content: "Yes, with the transition prop.",
|
94
99
|
* },
|
95
100
|
* { summary: "Does it work without Javascript?", content: "Yes." },
|
96
|
-
* ]}
|
97
|
-
* >
|
98
|
-
* <div slot="content" let:item let:index>
|
99
|
-
* <span>{index + 1}.</span>
|
100
|
-
* <span>{item.content}</span>
|
101
|
-
* </div>
|
102
|
-
* </Accordion>
|
103
|
-
* ```
|
104
|
-
*
|
105
|
-
* To render a component on unique items, pass it into the `data` prop and utilize `<svelte:component this={item.data.component}>` inside of the slot.
|
106
|
-
*
|
107
|
-
* ```svelte
|
108
|
-
* <script>
|
109
|
-
* import { Accordion, FullScreenButton } from "drab";
|
110
|
-
* </script>
|
111
|
-
*
|
112
|
-
* <Accordion
|
113
|
-
* items={[
|
114
101
|
* {
|
115
|
-
* summary: "
|
102
|
+
* summary: "Component",
|
116
103
|
* content: "Rendered only on this item.",
|
117
104
|
* data: { component: FullscreenButton },
|
118
105
|
* },
|
119
|
-
* { summary: "Summary", content: "Some other content" },
|
120
106
|
* ]}
|
121
107
|
* >
|
122
|
-
* <
|
123
|
-
*
|
108
|
+
* <svelte:fragment slot="content" let:item let:index>
|
109
|
+
* <div class="mb-4">
|
110
|
+
* <span>{index + 1}.</span>
|
111
|
+
* <span>{item.content}</span>
|
112
|
+
* </div>
|
124
113
|
* {#if item.data?.component}
|
125
|
-
* <svelte:component this={item.data.component} />
|
114
|
+
* <svelte:component class="btn" this={item.data.component} />
|
126
115
|
* {/if}
|
127
|
-
* </
|
116
|
+
* </svelte:fragment>
|
128
117
|
* </Accordion>
|
129
118
|
* ```
|
130
119
|
*/
|
@@ -25,14 +25,14 @@ Displays when the parent element is right clicked.
|
|
25
25
|
import { ContextMenu } from "drab";
|
26
26
|
</script>
|
27
27
|
|
28
|
-
<div>
|
28
|
+
<div class="flex justify-center rounded border border-dashed p-12">
|
29
29
|
<div>Right click here</div>
|
30
|
-
<ContextMenu>
|
31
|
-
<div>
|
32
|
-
<div>Context Menu</div>
|
33
|
-
<button>Button</button>
|
34
|
-
<button>Button</button>
|
35
|
-
<button>Button</button>
|
30
|
+
<ContextMenu class="transition">
|
31
|
+
<div class="card flex w-48 flex-col gap-2">
|
32
|
+
<div class="font-bold">Context Menu</div>
|
33
|
+
<button class="btn">Button</button>
|
34
|
+
<button class="btn">Button</button>
|
35
|
+
<button class="btn">Button</button>
|
36
36
|
</div>
|
37
37
|
</ContextMenu>
|
38
38
|
</div>
|
@@ -41,14 +41,14 @@ export type ContextMenuSlots = typeof __propDef.slots;
|
|
41
41
|
* import { ContextMenu } from "drab";
|
42
42
|
* </script>
|
43
43
|
*
|
44
|
-
* <div>
|
44
|
+
* <div class="flex justify-center rounded border border-dashed p-12">
|
45
45
|
* <div>Right click here</div>
|
46
|
-
* <ContextMenu>
|
47
|
-
* <div>
|
48
|
-
* <div>Context Menu</div>
|
49
|
-
* <button>Button</button>
|
50
|
-
* <button>Button</button>
|
51
|
-
* <button>Button</button>
|
46
|
+
* <ContextMenu class="transition">
|
47
|
+
* <div class="card flex w-48 flex-col gap-2">
|
48
|
+
* <div class="font-bold">Context Menu</div>
|
49
|
+
* <button class="btn">Button</button>
|
50
|
+
* <button class="btn">Button</button>
|
51
|
+
* <button class="btn">Button</button>
|
52
52
|
* </div>
|
53
53
|
* </ContextMenu>
|
54
54
|
* </div>
|
@@ -42,10 +42,12 @@ export type CopyButtonSlots = typeof __propDef.slots;
|
|
42
42
|
*
|
43
43
|
* ```svelte
|
44
44
|
* <script>
|
45
|
-
*
|
45
|
+
* import { CopyButton } from "drab";
|
46
46
|
* </script>
|
47
47
|
*
|
48
|
-
* <
|
48
|
+
* <div>
|
49
|
+
* <CopyButton class="btn" text="Text to copy" />
|
50
|
+
* </div>
|
49
51
|
* ```
|
50
52
|
*/
|
51
53
|
export default class CopyButton extends SvelteComponent<CopyButtonProps, CopyButtonEvents, CopyButtonSlots> {
|
@@ -22,10 +22,12 @@ Data table to display an array of JS objects. Click a column header to sort.
|
|
22
22
|
- `classTh` - `th` class
|
23
23
|
- `classTheadTr` - `thead tr` class
|
24
24
|
- `classThead` - `thead` class
|
25
|
+
- `class`
|
25
26
|
- `columns` - table columns, in order
|
26
27
|
- `currentPage` - current page, defaults to `1`
|
27
28
|
- `data` - a list of objects to render in the table
|
28
29
|
- `idTable` - `table` id
|
30
|
+
- `id`
|
29
31
|
- `paginate` - number of rows to show on each page, defaults to `0` - no pagination
|
30
32
|
- `sortBy` - column to sort by--defaults to first column
|
31
33
|
|
@@ -43,15 +45,26 @@ Data table to display an array of JS objects. Click a column header to sort.
|
|
43
45
|
import { DataTable } from "drab";
|
44
46
|
</script>
|
45
47
|
|
46
|
-
<DataTable
|
48
|
+
<DataTable
|
47
49
|
data={[
|
48
50
|
{ make: "Honda", model: "CR-V", year: 2011, awd: true },
|
49
51
|
{ make: "Volvo", model: "XC-40", year: 2024, awd: true },
|
50
52
|
{ make: "Ferrari", model: "458 Italia", year: 2015, awd: false },
|
51
53
|
{ make: "Chevrolet", model: "Silverado", year: 2022, awd: true },
|
52
54
|
{ make: "Ford", model: "Model A", year: 1931, awd: false },
|
55
|
+
{ make: "Subaru", model: "Outback", year: 2021, awd: true },
|
56
|
+
{ make: "Ford", model: "Bronco", year: 1970, awd: true },
|
57
|
+
{ make: "GMC", model: "Acadia", year: 2008, awd: true },
|
58
|
+
{ make: "BMW", model: "X3", year: 2023, awd: true },
|
53
59
|
]}
|
54
60
|
sortBy="make"
|
61
|
+
paginate={4}
|
62
|
+
class="tabular-nums"
|
63
|
+
classTh="cursor-pointer uppercase"
|
64
|
+
classThSorted="underline"
|
65
|
+
classTbodyTr="transition hover:bg-gray-50"
|
66
|
+
classFooter="flex justify-between items-center"
|
67
|
+
classButton="btn"
|
55
68
|
/>
|
56
69
|
```
|
57
70
|
-->
|
@@ -60,6 +73,9 @@ Data table to display an array of JS objects. Click a column header to sort.
|
|
60
73
|
|
61
74
|
<script>import { messageNoScript } from "../util/messages";
|
62
75
|
import { onMount } from "svelte";
|
76
|
+
let className = "";
|
77
|
+
export { className as class };
|
78
|
+
export let id = "";
|
63
79
|
export let data;
|
64
80
|
export let columns = [];
|
65
81
|
if (!columns.length && data[0]) {
|
@@ -125,60 +141,62 @@ sort(sortBy, false);
|
|
125
141
|
onMount(() => clientJs = true);
|
126
142
|
</script>
|
127
143
|
|
128
|
-
<
|
129
|
-
<
|
130
|
-
<
|
131
|
-
{
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
144
|
+
<div class={className} {id}>
|
145
|
+
<table class={classTable} id={idTable}>
|
146
|
+
<thead class={classThead}>
|
147
|
+
<tr class={classTheadTr}>
|
148
|
+
{#each columns as column}
|
149
|
+
<th
|
150
|
+
class="{classTh} {sortBy === column ? classThSorted : ''}"
|
151
|
+
on:click={() => sort(column)}
|
152
|
+
>
|
153
|
+
{column}
|
154
|
+
</th>
|
155
|
+
{/each}
|
156
|
+
</tr>
|
157
|
+
</thead>
|
158
|
+
<tbody class={classTbody}>
|
159
|
+
{#each data as row, i}
|
160
|
+
{@const showRow =
|
161
|
+
i < paginate * currentPage && i >= paginate * (currentPage - 1)}
|
162
|
+
{#if paginate ? showRow : true}
|
163
|
+
<tr class={classTbodyTr}>
|
164
|
+
{#each columns as column}
|
165
|
+
<td class="{classTd} {sortBy === column ? classTdSorted : ''}">
|
166
|
+
{row[column]}
|
167
|
+
</td>
|
168
|
+
{/each}
|
169
|
+
</tr>
|
170
|
+
{/if}
|
138
171
|
{/each}
|
139
|
-
</
|
140
|
-
</
|
141
|
-
<tbody class={classTbody}>
|
142
|
-
{#each data as row, i}
|
143
|
-
{@const showRow =
|
144
|
-
i < paginate * currentPage && i >= paginate * (currentPage - 1)}
|
145
|
-
{#if paginate ? showRow : true}
|
146
|
-
<tr class={classTbodyTr}>
|
147
|
-
{#each columns as column}
|
148
|
-
<td class="{classTd} {sortBy === column ? classTdSorted : ''}">
|
149
|
-
{row[column]}
|
150
|
-
</td>
|
151
|
-
{/each}
|
152
|
-
</tr>
|
153
|
-
{/if}
|
154
|
-
{/each}
|
155
|
-
</tbody>
|
156
|
-
</table>
|
172
|
+
</tbody>
|
173
|
+
</table>
|
157
174
|
|
158
|
-
{#if paginate}
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
175
|
+
{#if paginate}
|
176
|
+
<div class={classFooter}>
|
177
|
+
<div class={classPageNumber}>{currentPage} / {numberOfPages}</div>
|
178
|
+
<div class={classPageControls}>
|
179
|
+
<button
|
180
|
+
class={classButton}
|
181
|
+
disabled={!clientJs || currentPage < 2}
|
182
|
+
on:click={() => currentPage--}
|
183
|
+
>
|
184
|
+
<slot name="previous">Previous</slot>
|
185
|
+
</button>
|
186
|
+
<button
|
187
|
+
class={classButton}
|
188
|
+
disabled={!clientJs || currentPage >= numberOfPages}
|
189
|
+
on:click={() => currentPage++}
|
190
|
+
>
|
191
|
+
<slot name="next">Next</slot>
|
192
|
+
</button>
|
193
|
+
</div>
|
176
194
|
</div>
|
177
|
-
</div>
|
178
195
|
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
{/if}
|
196
|
+
<noscript>
|
197
|
+
<div class={classNoscript}>
|
198
|
+
{messageNoScript}
|
199
|
+
</div>
|
200
|
+
</noscript>
|
201
|
+
{/if}
|
202
|
+
</div>
|
@@ -4,6 +4,8 @@ export type DataTableRow<T> = {
|
|
4
4
|
};
|
5
5
|
declare const __propDef: {
|
6
6
|
props: {
|
7
|
+
class?: string | undefined;
|
8
|
+
id?: string | undefined;
|
7
9
|
/** a list of objects to render in the table */ data: DataTableRow<any>[];
|
8
10
|
/** table columns, in order */ columns?: string[] | undefined;
|
9
11
|
/** column to sort by--defaults to first column */ sortBy?: string | undefined;
|
@@ -59,10 +61,12 @@ export type DataTableSlots = typeof __propDef.slots;
|
|
59
61
|
* - `classTh` - `th` class
|
60
62
|
* - `classTheadTr` - `thead tr` class
|
61
63
|
* - `classThead` - `thead` class
|
64
|
+
* - `class`
|
62
65
|
* - `columns` - table columns, in order
|
63
66
|
* - `currentPage` - current page, defaults to `1`
|
64
67
|
* - `data` - a list of objects to render in the table
|
65
68
|
* - `idTable` - `table` id
|
69
|
+
* - `id`
|
66
70
|
* - `paginate` - number of rows to show on each page, defaults to `0` - no pagination
|
67
71
|
* - `sortBy` - column to sort by--defaults to first column
|
68
72
|
*
|
@@ -87,8 +91,19 @@ export type DataTableSlots = typeof __propDef.slots;
|
|
87
91
|
* { make: "Ferrari", model: "458 Italia", year: 2015, awd: false },
|
88
92
|
* { make: "Chevrolet", model: "Silverado", year: 2022, awd: true },
|
89
93
|
* { make: "Ford", model: "Model A", year: 1931, awd: false },
|
94
|
+
* { make: "Subaru", model: "Outback", year: 2021, awd: true },
|
95
|
+
* { make: "Ford", model: "Bronco", year: 1970, awd: true },
|
96
|
+
* { make: "GMC", model: "Acadia", year: 2008, awd: true },
|
97
|
+
* { make: "BMW", model: "X3", year: 2023, awd: true },
|
90
98
|
* ]}
|
91
99
|
* sortBy="make"
|
100
|
+
* paginate={4}
|
101
|
+
* class="tabular-nums"
|
102
|
+
* classTh="cursor-pointer uppercase"
|
103
|
+
* classThSorted="underline"
|
104
|
+
* classTbodyTr="transition hover:bg-gray-50"
|
105
|
+
* classFooter="flex justify-between items-center"
|
106
|
+
* classButton="btn"
|
92
107
|
* />
|
93
108
|
* ```
|
94
109
|
*/
|
@@ -27,7 +27,12 @@ Text editor with controls to add elements and keyboard shortcuts.
|
|
27
27
|
import { Editor } from "drab";
|
28
28
|
</script>
|
29
29
|
|
30
|
-
<Editor
|
30
|
+
<Editor
|
31
|
+
classButton="btn"
|
32
|
+
classControls="flex gap-2"
|
33
|
+
classTextarea="border w-full h-36 p-2 rounded"
|
34
|
+
placeholderTextarea="asterisk: ctrl+i, anchor: ctrl+["
|
35
|
+
contentElements={[
|
31
36
|
{
|
32
37
|
name: "Bullet",
|
33
38
|
text: "- ",
|
@@ -73,7 +73,12 @@ export type EditorSlots = typeof __propDef.slots;
|
|
73
73
|
* import { Editor } from "drab";
|
74
74
|
* </script>
|
75
75
|
*
|
76
|
-
* <Editor
|
76
|
+
* <Editor
|
77
|
+
* classButton="btn"
|
78
|
+
* classControls="flex gap-2"
|
79
|
+
* classTextarea="border w-full h-36 p-2 rounded"
|
80
|
+
* placeholderTextarea="asterisk: ctrl+i, anchor: ctrl+["
|
81
|
+
* contentElements={[
|
77
82
|
* {
|
78
83
|
* name: "Bullet",
|
79
84
|
* text: "- ",
|
@@ -30,13 +30,18 @@ Make the document or a specific element fullscreen.
|
|
30
30
|
let fullscreenDiv;
|
31
31
|
</script>
|
32
32
|
|
33
|
-
<
|
33
|
+
<div>
|
34
|
+
<FullscreenButton class="btn" />
|
35
|
+
</div>
|
34
36
|
|
35
|
-
<div
|
36
|
-
|
37
|
-
|
37
|
+
<div
|
38
|
+
bind:this={fullscreenDiv}
|
39
|
+
class="mt-4 rounded bg-gray-800 p-4 text-gray-50"
|
40
|
+
>
|
41
|
+
<div class="mb-2">Target element fullscreen</div>
|
42
|
+
<FullscreenButton targetElement={fullscreenDiv} class="btn">
|
43
|
+
<span>Enable Element Fullscreen</span>
|
38
44
|
<span slot="enabled">Exit Element Fullscreen</span>
|
39
|
-
<span slot="disabled">Enable Element Fullscreen</span>
|
40
45
|
</FullscreenButton>
|
41
46
|
</div>
|
42
47
|
```
|
@@ -49,13 +49,18 @@ export type FullscreenButtonSlots = typeof __propDef.slots;
|
|
49
49
|
* let fullscreenDiv;
|
50
50
|
* </script>
|
51
51
|
*
|
52
|
-
* <
|
52
|
+
* <div>
|
53
|
+
* <FullscreenButton class="btn" />
|
54
|
+
* </div>
|
53
55
|
*
|
54
|
-
* <div
|
55
|
-
*
|
56
|
-
*
|
56
|
+
* <div
|
57
|
+
* bind:this={fullscreenDiv}
|
58
|
+
* class="mt-4 rounded bg-gray-800 p-4 text-gray-50"
|
59
|
+
* >
|
60
|
+
* <div class="mb-2">Target element fullscreen</div>
|
61
|
+
* <FullscreenButton targetElement={fullscreenDiv} class="btn">
|
62
|
+
* <span>Enable Element Fullscreen</span>
|
57
63
|
* <span slot="enabled">Exit Element Fullscreen</span>
|
58
|
-
* <span slot="disabled">Enable Element Fullscreen</span>
|
59
64
|
* </FullscreenButton>
|
60
65
|
* </div>
|
61
66
|
* ```
|
@@ -31,13 +31,27 @@ Displays a popover relatively positioned to the button.
|
|
31
31
|
import { Popover } from "drab";
|
32
32
|
</script>
|
33
33
|
|
34
|
-
<Popover>
|
34
|
+
<Popover classButton="btn" classPopover="p-2 transition">
|
35
35
|
<span slot="button">Hover</span>
|
36
|
-
<div>
|
37
|
-
<div>
|
38
|
-
<button>Button</button>
|
39
|
-
<button>Button</button>
|
40
|
-
<button>Button</button>
|
36
|
+
<div class="card flex w-48 flex-col gap-2">
|
37
|
+
<div class="font-bold">Bottom</div>
|
38
|
+
<button class="btn">Button</button>
|
39
|
+
<button class="btn">Button</button>
|
40
|
+
<button class="btn">Button</button>
|
41
|
+
</div>
|
42
|
+
</Popover>
|
43
|
+
<Popover
|
44
|
+
classButton="btn"
|
45
|
+
classPopover="p-2 transition"
|
46
|
+
eventType="click"
|
47
|
+
position="right"
|
48
|
+
>
|
49
|
+
<span slot="button">Click</span>
|
50
|
+
<div class="card flex w-48 flex-col gap-2">
|
51
|
+
<div class="font-bold">Right</div>
|
52
|
+
<button class="btn">Button</button>
|
53
|
+
<button class="btn">Button</button>
|
54
|
+
<button class="btn">Button</button>
|
41
55
|
</div>
|
42
56
|
</Popover>
|
43
57
|
```
|
@@ -53,13 +53,27 @@ export type PopoverSlots = typeof __propDef.slots;
|
|
53
53
|
* import { Popover } from "drab";
|
54
54
|
* </script>
|
55
55
|
*
|
56
|
-
* <Popover>
|
56
|
+
* <Popover classButton="btn" classPopover="p-2 transition">
|
57
57
|
* <span slot="button">Hover</span>
|
58
|
-
* <div>
|
59
|
-
* <div>
|
60
|
-
* <button>Button</button>
|
61
|
-
* <button>Button</button>
|
62
|
-
* <button>Button</button>
|
58
|
+
* <div class="card flex w-48 flex-col gap-2">
|
59
|
+
* <div class="font-bold">Bottom</div>
|
60
|
+
* <button class="btn">Button</button>
|
61
|
+
* <button class="btn">Button</button>
|
62
|
+
* <button class="btn">Button</button>
|
63
|
+
* </div>
|
64
|
+
* </Popover>
|
65
|
+
* <Popover
|
66
|
+
* classButton="btn"
|
67
|
+
* classPopover="p-2 transition"
|
68
|
+
* eventType="click"
|
69
|
+
* position="right"
|
70
|
+
* >
|
71
|
+
* <span slot="button">Click</span>
|
72
|
+
* <div class="card flex w-48 flex-col gap-2">
|
73
|
+
* <div class="font-bold">Right</div>
|
74
|
+
* <button class="btn">Button</button>
|
75
|
+
* <button class="btn">Button</button>
|
76
|
+
* <button class="btn">Button</button>
|
63
77
|
* </div>
|
64
78
|
* </Popover>
|
65
79
|
* ```
|
@@ -28,11 +28,14 @@ Uses the navigator api to share or copy a url link depending on browser support.
|
|
28
28
|
import { ShareButton } from "drab";
|
29
29
|
</script>
|
30
30
|
|
31
|
-
<
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
31
|
+
<div>
|
32
|
+
<ShareButton
|
33
|
+
class="btn"
|
34
|
+
text="Check out this page: "
|
35
|
+
title="drab"
|
36
|
+
url="https://drab.robino.dev"
|
37
|
+
/>
|
38
|
+
</div>
|
36
39
|
```
|
37
40
|
-->
|
38
41
|
|
@@ -47,11 +47,14 @@ export type ShareButtonSlots = typeof __propDef.slots;
|
|
47
47
|
* import { ShareButton } from "drab";
|
48
48
|
* </script>
|
49
49
|
*
|
50
|
+
* <div>
|
50
51
|
* <ShareButton
|
51
|
-
*
|
52
|
-
*
|
53
|
-
*
|
52
|
+
* class="btn"
|
53
|
+
* text="Check out this page: "
|
54
|
+
* title="drab"
|
55
|
+
* url="https://drab.robino.dev"
|
54
56
|
* />
|
57
|
+
* </div>
|
55
58
|
* ```
|
56
59
|
*/
|
57
60
|
export default class ShareButton extends SvelteComponent<ShareButtonProps, ShareButtonEvents, ShareButtonSlots> {
|
@@ -3,100 +3,115 @@
|
|
3
3
|
|
4
4
|
### Tabs
|
5
5
|
|
6
|
-
Displays tabs and
|
6
|
+
Displays tabs and the active tab's content.
|
7
7
|
|
8
8
|
@props
|
9
9
|
|
10
|
-
- `
|
11
|
-
- `
|
12
|
-
- `classButton` - `button` class
|
10
|
+
- `activeIndex` - index of active tab, defaults to 0
|
11
|
+
- `classContent` - class of `div` that wraps the slotted content
|
13
12
|
- `classHeader` - class of the `div` that wraps the `button`s
|
14
13
|
- `classNoscript` - `noscript` class
|
15
|
-
- `
|
14
|
+
- `classTitleActive` - class of the active tab's `button`
|
15
|
+
- `classTitleInactive` - class of all the inactive tabs' `button`s
|
16
|
+
- `classTitle` - class of all title `button`s
|
16
17
|
- `class`
|
17
|
-
- `content` - array of `TabContent` elements
|
18
18
|
- `id`
|
19
|
-
- `
|
19
|
+
- `tabs` - array of tabs
|
20
20
|
|
21
21
|
@slots
|
22
22
|
|
23
|
-
|
23
|
+
| name | purpose | default value | slot props |
|
24
|
+
| --------- | --------------------- | -------------------- | --------------- |
|
25
|
+
| `default` | active item's content | `activeItem.content` | `activeItem` |
|
26
|
+
| `title` | title of each tab | `item.title` | `item`, `index` |
|
24
27
|
|
25
28
|
@example
|
26
29
|
|
27
30
|
```svelte
|
28
31
|
<script>
|
29
32
|
import { Tabs } from "drab";
|
30
|
-
import
|
33
|
+
import FullscreenButton from "./FullscreenButton.svelte";
|
31
34
|
</script>
|
32
35
|
|
33
|
-
<Tabs
|
34
|
-
|
35
|
-
|
36
|
+
<Tabs
|
37
|
+
classHeader="grid grid-flow-col grid-rows-1 gap-1 rounded bg-gray-200 p-1"
|
38
|
+
classTitle="btn rounded-sm p-0.5"
|
39
|
+
classTitleActive="bg-white text-gray-950"
|
40
|
+
classTitleInactive="bg-gray-200 text-gray-500"
|
41
|
+
classContent="py-2"
|
42
|
+
tabs={[
|
43
|
+
{ title: "Tab 1", content: "Content 1" },
|
44
|
+
{ title: "Tab 2", content: "Content 2" },
|
36
45
|
]}
|
37
46
|
/>
|
47
|
+
|
48
|
+
<Tabs
|
49
|
+
classHeader="grid grid-flow-col grid-rows-1 gap-1 rounded bg-gray-200 p-1"
|
50
|
+
classTitle="btn rounded-sm p-0.5"
|
51
|
+
classTitleActive="bg-white text-gray-950"
|
52
|
+
classTitleInactive="bg-gray-200 text-gray-500"
|
53
|
+
classContent="py-2"
|
54
|
+
tabs={[
|
55
|
+
{ title: "Tab", content: "Generated indexes" },
|
56
|
+
{
|
57
|
+
title: "Tab",
|
58
|
+
content: "A tab with a component",
|
59
|
+
data: { component: FullscreenButton },
|
60
|
+
},
|
61
|
+
]}
|
62
|
+
let:activeTab
|
63
|
+
>
|
64
|
+
<svelte:fragment slot="title" let:item let:index>
|
65
|
+
{item.title}
|
66
|
+
{index + 1}
|
67
|
+
</svelte:fragment>
|
68
|
+
<div>{activeTab.content}</div>
|
69
|
+
{#if activeTab.data?.component}
|
70
|
+
<svelte:component class="btn" this={activeTab.data.component} />
|
71
|
+
{/if}
|
72
|
+
</Tabs>
|
38
73
|
```
|
39
74
|
-->
|
40
75
|
|
41
76
|
<script context="module"></script>
|
42
77
|
|
43
78
|
<script>import { onMount } from "svelte";
|
44
|
-
import { fade } from "svelte/transition";
|
45
79
|
import { messageNoScript } from "../util/messages";
|
46
80
|
let className = "";
|
47
81
|
export { className as class };
|
48
82
|
export let id = "";
|
49
83
|
export let classHeader = "";
|
50
|
-
export let
|
51
|
-
export let
|
52
|
-
export let
|
84
|
+
export let classTitle = "";
|
85
|
+
export let classTitleActive = "";
|
86
|
+
export let classTitleInactive = "";
|
53
87
|
export let classNoscript = "";
|
54
|
-
export let
|
55
|
-
export let
|
56
|
-
export let
|
57
|
-
const fadeTransition = transition ? transition : { duration: 0 };
|
88
|
+
export let classContent = "";
|
89
|
+
export let tabs;
|
90
|
+
export let activeIndex = 0;
|
58
91
|
let clientJs = false;
|
59
|
-
let activeIndex = 0;
|
60
|
-
for (const item of content) {
|
61
|
-
if (!item.classContentSlot)
|
62
|
-
item.classContentSlot = "";
|
63
|
-
}
|
64
92
|
$:
|
65
|
-
activeTab =
|
93
|
+
activeTab = tabs[activeIndex];
|
66
94
|
onMount(() => clientJs = true);
|
67
95
|
</script>
|
68
96
|
|
69
97
|
<div class={className} {id}>
|
70
98
|
<div class={classHeader}>
|
71
|
-
{#each
|
99
|
+
{#each tabs as item, index}
|
72
100
|
<button
|
73
101
|
disabled={!clientJs}
|
74
|
-
class="{
|
75
|
-
?
|
76
|
-
: ''} {activeIndex !==
|
77
|
-
on:click={() => (activeIndex =
|
102
|
+
class="{classTitle} {activeIndex === index
|
103
|
+
? classTitleActive
|
104
|
+
: ''} {activeIndex !== index ? classTitleInactive : ''}"
|
105
|
+
on:click={() => (activeIndex = index)}
|
78
106
|
>
|
79
|
-
{
|
107
|
+
<slot name="title" {item} {index}>{item.title}</slot>
|
80
108
|
</button>
|
81
109
|
{/each}
|
82
110
|
</div>
|
83
|
-
<div class={
|
84
|
-
{
|
85
|
-
<div in:fade={fadeTransition}>
|
86
|
-
<svelte:component
|
87
|
-
this={activeTab.slot}
|
88
|
-
class={activeTab.classContentSlot}
|
89
|
-
/>
|
90
|
-
</div>
|
91
|
-
{:else}
|
92
|
-
<div in:fade={fadeTransition} class={activeTab.classContentSlot}>
|
93
|
-
{activeTab.slot}
|
94
|
-
</div>
|
95
|
-
{/if}
|
111
|
+
<div class={classContent}>
|
112
|
+
<slot {activeTab}>{activeTab.content}</slot>
|
96
113
|
</div>
|
97
114
|
<noscript>
|
98
|
-
<div class={classNoscript}>
|
99
|
-
{messageNoScript}
|
100
|
-
</div>
|
115
|
+
<div class={classNoscript}>{messageNoScript}</div>
|
101
116
|
</noscript>
|
102
117
|
</div>
|
@@ -1,31 +1,37 @@
|
|
1
1
|
import { SvelteComponent } from "svelte";
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
name: string;
|
2
|
+
export interface TabsTab<T = any> {
|
3
|
+
/** tab title, displayed in `button` element */
|
4
|
+
title?: string;
|
6
5
|
/** slotted content, displayed once tab is clicked */
|
7
|
-
|
8
|
-
/**
|
9
|
-
|
6
|
+
content?: string;
|
7
|
+
/** any data to pass back to the parent */
|
8
|
+
data?: T;
|
10
9
|
}
|
11
|
-
import { type FadeParams } from "svelte/transition";
|
12
10
|
declare const __propDef: {
|
13
11
|
props: {
|
14
12
|
class?: string | undefined;
|
15
13
|
id?: string | undefined;
|
16
14
|
/** class of the `div` that wraps the `button`s */ classHeader?: string | undefined;
|
17
|
-
/** `button`
|
18
|
-
/** class of the active tab's `button` */
|
19
|
-
/** class of all the inactive tabs' `button`s */
|
15
|
+
/** class of all title `button`s */ classTitle?: string | undefined;
|
16
|
+
/** class of the active tab's `button` */ classTitleActive?: string | undefined;
|
17
|
+
/** class of all the inactive tabs' `button`s */ classTitleInactive?: string | undefined;
|
20
18
|
/** `noscript` class */ classNoscript?: string | undefined;
|
21
|
-
/** class of `div` that wraps the slotted content */
|
22
|
-
/** array of
|
23
|
-
/**
|
19
|
+
/** class of `div` that wraps the slotted content */ classContent?: string | undefined;
|
20
|
+
/** array of tabs */ tabs: TabsTab[];
|
21
|
+
/** index of active tab, defaults to 0 */ activeIndex?: number | undefined;
|
24
22
|
};
|
25
23
|
events: {
|
26
24
|
[evt: string]: CustomEvent<any>;
|
27
25
|
};
|
28
|
-
slots: {
|
26
|
+
slots: {
|
27
|
+
title: {
|
28
|
+
item: TabsTab<any>;
|
29
|
+
index: any;
|
30
|
+
};
|
31
|
+
default: {
|
32
|
+
activeTab: TabsTab<any>;
|
33
|
+
};
|
34
|
+
};
|
29
35
|
};
|
30
36
|
export type TabsProps = typeof __propDef.props;
|
31
37
|
export type TabsEvents = typeof __propDef.events;
|
@@ -33,38 +39,73 @@ export type TabsSlots = typeof __propDef.slots;
|
|
33
39
|
/**
|
34
40
|
* ### Tabs
|
35
41
|
*
|
36
|
-
* Displays tabs and
|
42
|
+
* Displays tabs and the active tab's content.
|
37
43
|
*
|
38
44
|
* @props
|
39
45
|
*
|
40
|
-
* - `
|
41
|
-
* - `
|
42
|
-
* - `classButton` - `button` class
|
46
|
+
* - `activeIndex` - index of active tab, defaults to 0
|
47
|
+
* - `classContent` - class of `div` that wraps the slotted content
|
43
48
|
* - `classHeader` - class of the `div` that wraps the `button`s
|
44
49
|
* - `classNoscript` - `noscript` class
|
45
|
-
* - `
|
50
|
+
* - `classTitleActive` - class of the active tab's `button`
|
51
|
+
* - `classTitleInactive` - class of all the inactive tabs' `button`s
|
52
|
+
* - `classTitle` - class of all title `button`s
|
46
53
|
* - `class`
|
47
|
-
* - `content` - array of `TabContent` elements
|
48
54
|
* - `id`
|
49
|
-
* - `
|
55
|
+
* - `tabs` - array of tabs
|
50
56
|
*
|
51
57
|
* @slots
|
52
58
|
*
|
53
|
-
*
|
59
|
+
* | name | purpose | default value | slot props |
|
60
|
+
* | --------- | --------------------- | -------------------- | --------------- |
|
61
|
+
* | `default` | active item's content | `activeItem.content` | `activeItem` |
|
62
|
+
* | `title` | title of each tab | `item.title` | `item`, `index` |
|
54
63
|
*
|
55
64
|
* @example
|
56
65
|
*
|
57
66
|
* ```svelte
|
58
67
|
* <script>
|
59
68
|
* import { Tabs } from "drab";
|
60
|
-
* import
|
69
|
+
* import FullscreenButton from "./FullscreenButton.svelte";
|
61
70
|
* </script>
|
62
71
|
*
|
63
|
-
* <Tabs
|
64
|
-
*
|
65
|
-
*
|
72
|
+
* <Tabs
|
73
|
+
* classHeader="grid grid-flow-col grid-rows-1 gap-1 rounded bg-gray-200 p-1"
|
74
|
+
* classTitle="btn rounded-sm p-0.5"
|
75
|
+
* classTitleActive="bg-white text-gray-950"
|
76
|
+
* classTitleInactive="bg-gray-200 text-gray-500"
|
77
|
+
* classContent="py-2"
|
78
|
+
* tabs={[
|
79
|
+
* { title: "Tab 1", content: "Content 1" },
|
80
|
+
* { title: "Tab 2", content: "Content 2" },
|
66
81
|
* ]}
|
67
82
|
* />
|
83
|
+
*
|
84
|
+
* <Tabs
|
85
|
+
* classHeader="grid grid-flow-col grid-rows-1 gap-1 rounded bg-gray-200 p-1"
|
86
|
+
* classTitle="btn rounded-sm p-0.5"
|
87
|
+
* classTitleActive="bg-white text-gray-950"
|
88
|
+
* classTitleInactive="bg-gray-200 text-gray-500"
|
89
|
+
* classContent="py-2"
|
90
|
+
* tabs={[
|
91
|
+
* { title: "Tab", content: "Generated indexes" },
|
92
|
+
* {
|
93
|
+
* title: "Tab",
|
94
|
+
* content: "A tab with a component",
|
95
|
+
* data: { component: FullscreenButton },
|
96
|
+
* },
|
97
|
+
* ]}
|
98
|
+
* let:activeTab
|
99
|
+
* >
|
100
|
+
* <svelte:fragment slot="title" let:item let:index>
|
101
|
+
* {item.title}
|
102
|
+
* {index + 1}
|
103
|
+
* </svelte:fragment>
|
104
|
+
* <div>{activeTab.content}</div>
|
105
|
+
* {#if activeTab.data?.component}
|
106
|
+
* <svelte:component class="btn" this={activeTab.data.component} />
|
107
|
+
* {/if}
|
108
|
+
* </Tabs>
|
68
109
|
* ```
|
69
110
|
*/
|
70
111
|
export default class Tabs extends SvelteComponent<TabsProps, TabsEvents, TabsSlots> {
|
@@ -21,7 +21,11 @@ Embeds a YouTube video into a website with the video `uid`, using [www.youtube-n
|
|
21
21
|
import { YouTube } from "drab";
|
22
22
|
</script>
|
23
23
|
|
24
|
-
<YouTube
|
24
|
+
<YouTube
|
25
|
+
class="aspect-video w-full rounded"
|
26
|
+
title="Renegade - Kevin Olusola"
|
27
|
+
uid="gouiY85kD2o"
|
28
|
+
/>
|
25
29
|
```
|
26
30
|
-->
|
27
31
|
|
@@ -37,7 +37,11 @@ export type YouTubeSlots = typeof __propDef.slots;
|
|
37
37
|
* import { YouTube } from "drab";
|
38
38
|
* </script>
|
39
39
|
*
|
40
|
-
* <YouTube
|
40
|
+
* <YouTube
|
41
|
+
* class="aspect-video w-full rounded"
|
42
|
+
* title="Renegade - Kevin Olusola"
|
43
|
+
* uid="gouiY85kD2o"
|
44
|
+
* />
|
41
45
|
* ```
|
42
46
|
*/
|
43
47
|
export default class YouTube extends SvelteComponent<YouTubeProps, YouTubeEvents, YouTubeSlots> {
|
package/dist/index.d.ts
CHANGED
@@ -11,5 +11,7 @@ import type { EditorContentElement } from "./components/Editor.svelte";
|
|
11
11
|
import FullscreenButton from "./components/FullscreenButton.svelte";
|
12
12
|
import Popover from "./components/Popover.svelte";
|
13
13
|
import ShareButton from "./components/ShareButton.svelte";
|
14
|
+
import Tabs from "./components/Tabs.svelte";
|
15
|
+
import type { TabsTab } from "./components/Tabs.svelte";
|
14
16
|
import YouTube from "./components/YouTube.svelte";
|
15
|
-
export { Accordion, type AccordionItem, Chord, type ChordNote, ContextMenu, CopyButton, DataTable, type DataTableRow, Editor, type EditorContentElement, FullscreenButton, Popover, ShareButton, YouTube, };
|
17
|
+
export { Accordion, type AccordionItem, Chord, type ChordNote, ContextMenu, CopyButton, DataTable, type DataTableRow, Editor, type EditorContentElement, FullscreenButton, Popover, ShareButton, Tabs, type TabsTab, YouTube, };
|
package/dist/index.js
CHANGED
@@ -7,5 +7,6 @@ import Editor from "./components/Editor.svelte";
|
|
7
7
|
import FullscreenButton from "./components/FullscreenButton.svelte";
|
8
8
|
import Popover from "./components/Popover.svelte";
|
9
9
|
import ShareButton from "./components/ShareButton.svelte";
|
10
|
+
import Tabs from "./components/Tabs.svelte";
|
10
11
|
import YouTube from "./components/YouTube.svelte";
|
11
|
-
export { Accordion, Chord, ContextMenu, CopyButton, DataTable, Editor, FullscreenButton, Popover, ShareButton, YouTube, };
|
12
|
+
export { Accordion, Chord, ContextMenu, CopyButton, DataTable, Editor, FullscreenButton, Popover, ShareButton, Tabs, YouTube, };
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "drab",
|
3
|
-
"version": "2.
|
3
|
+
"version": "2.4.1",
|
4
4
|
"description": "An unstyled Svelte component library",
|
5
5
|
"keywords": [
|
6
6
|
"components",
|
@@ -15,6 +15,7 @@
|
|
15
15
|
"Fullscreen",
|
16
16
|
"Popover",
|
17
17
|
"Share",
|
18
|
+
"Tabs",
|
18
19
|
"YouTube"
|
19
20
|
],
|
20
21
|
"homepage": "https://drab.robino.dev",
|
@@ -35,7 +36,7 @@
|
|
35
36
|
"lint": "prettier --check . && eslint .",
|
36
37
|
"format": "prettier --write . --plugin=prettier-plugin-svelte --plugin=prettier-plugin-tailwindcss",
|
37
38
|
"pub": "npm publish --access public",
|
38
|
-
"doc": "node scripts/buildDocs.js"
|
39
|
+
"doc": "node src/scripts/buildDocs.js"
|
39
40
|
},
|
40
41
|
"exports": {
|
41
42
|
".": {
|