drab 2.2.1 → 2.3.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.
@@ -8,19 +8,24 @@ Displays a list of `details` elements.
|
|
8
8
|
@props
|
9
9
|
|
10
10
|
- `autoClose` - if `true`, other items close when a new one is opened
|
11
|
+
- `classContent` - class of all the `div`s that wrap the `content` slot
|
11
12
|
- `classDetails` - class of the `div` around each `details` element
|
12
|
-
- `
|
13
|
-
- `
|
14
|
-
- `classSummary` - class of all the `summary`
|
13
|
+
- `classHeader` - class of all the `summary` elements
|
14
|
+
- `classIcon` - class of the `div` that wrap the icon if displayed
|
15
|
+
- `classSummary` - class of all the `div`s that wrap the `summary` slot
|
15
16
|
- `class`
|
16
|
-
- `content` - array of `AccordionContent` elements
|
17
17
|
- `icon`
|
18
18
|
- `id`
|
19
|
+
- `items` - array of `AccordionItem` elements
|
19
20
|
- `transition` - rotates the icon, slides the content, defaults to empty object, set to false to remove
|
20
21
|
|
21
22
|
@slots
|
22
23
|
|
23
|
-
|
24
|
+
| name | purpose | default value |
|
25
|
+
| ---------- | ----------------------------- | -------------- |
|
26
|
+
| `summary` | summary element | `item.summary` |
|
27
|
+
| `icon` | icon element | `icon` prop |
|
28
|
+
| `content` | content of the accordion item | `item.content` |
|
24
29
|
|
25
30
|
@example
|
26
31
|
|
@@ -29,20 +34,51 @@ Pass components into the `content` prop if needed. `AccordionContent` has `summa
|
|
29
34
|
import { Accordion } from "drab";
|
30
35
|
</script>
|
31
36
|
|
32
|
-
<Accordion
|
33
|
-
|
34
|
-
{ summary: "Is it accessible?",
|
37
|
+
<Accordion
|
38
|
+
items={[
|
39
|
+
{ summary: "Is it accessible?", content: "Yes." },
|
35
40
|
{
|
36
41
|
summary: "Is it styled?",
|
37
|
-
|
42
|
+
content: "Nope, style with global styles.",
|
38
43
|
},
|
39
44
|
{
|
40
45
|
summary: "Is it animated?",
|
41
|
-
|
46
|
+
content: "Yes, with the transition prop.",
|
42
47
|
},
|
43
|
-
{ summary: "Does it work without Javascript?",
|
48
|
+
{ summary: "Does it work without Javascript?", content: "Yes." },
|
44
49
|
]}
|
45
|
-
|
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
|
+
{
|
68
|
+
summary: "A Component",
|
69
|
+
content: "Rendered only on this item.",
|
70
|
+
data: { component: FullscreenButton },
|
71
|
+
},
|
72
|
+
{ summary: "Summary", content: "Some other content" },
|
73
|
+
]}
|
74
|
+
>
|
75
|
+
<div slot="content" let:item>
|
76
|
+
{item.content}
|
77
|
+
{#if item.data?.component}
|
78
|
+
<svelte:component this={item.data.component} />
|
79
|
+
{/if}
|
80
|
+
</div>
|
81
|
+
</Accordion>
|
46
82
|
```
|
47
83
|
-->
|
48
84
|
|
@@ -54,28 +90,21 @@ import { prefersReducedMotion } from "../util/accessibility";
|
|
54
90
|
let className = "";
|
55
91
|
export { className as class };
|
56
92
|
export let id = "";
|
57
|
-
export let
|
93
|
+
export let items;
|
58
94
|
export let icon = "";
|
59
95
|
export let classDetails = "";
|
96
|
+
export let classHeader = "";
|
60
97
|
export let classSummary = "";
|
61
|
-
export let
|
98
|
+
export let classContent = "";
|
62
99
|
export let classIcon = "";
|
63
100
|
export let transition = {};
|
64
101
|
export let autoClose = true;
|
65
102
|
let clientJs = false;
|
66
|
-
for (const item of content) {
|
67
|
-
if (!item.classContentDetails)
|
68
|
-
item.classContentDetails = "";
|
69
|
-
if (!item.classContentSlot)
|
70
|
-
item.classContentSlot = "";
|
71
|
-
if (!item.classContentSummary)
|
72
|
-
item.classContentSummary = "";
|
73
|
-
}
|
74
103
|
const toggleOpen = (i) => {
|
75
|
-
|
104
|
+
items[i].open = !items[i].open;
|
76
105
|
if (autoClose) {
|
77
|
-
for (let j = 0; j <
|
78
|
-
const item =
|
106
|
+
for (let j = 0; j < items.length; j++) {
|
107
|
+
const item = items[j];
|
79
108
|
if (j !== i)
|
80
109
|
item.open = false;
|
81
110
|
}
|
@@ -88,64 +117,51 @@ onMount(() => {
|
|
88
117
|
});
|
89
118
|
</script>
|
90
119
|
|
91
|
-
<div class="transition"></div>
|
92
|
-
|
93
120
|
<div class={className} {id}>
|
94
|
-
{#each
|
95
|
-
<div class=
|
96
|
-
<details bind:open>
|
121
|
+
{#each items as item, index}
|
122
|
+
<div class={classDetails}>
|
123
|
+
<details bind:open={item.open}>
|
97
124
|
<!-- svelte-ignore a11y-no-redundant-roles -->
|
98
125
|
<summary
|
99
126
|
role="button"
|
100
127
|
tabindex="0"
|
101
|
-
class={
|
102
|
-
on:click={(
|
103
|
-
e.preventDefault();
|
104
|
-
toggleOpen(i);
|
105
|
-
}}
|
128
|
+
class={classHeader}
|
129
|
+
on:click|preventDefault={() => toggleOpen(index)}
|
106
130
|
on:keydown={(e) => {
|
107
131
|
if (e.key === "Enter") {
|
108
132
|
e.preventDefault();
|
109
|
-
toggleOpen(
|
133
|
+
toggleOpen(index);
|
110
134
|
}
|
111
135
|
}}
|
112
136
|
>
|
113
|
-
{
|
114
|
-
<
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
137
|
+
<div class={classSummary}>
|
138
|
+
<slot name="summary" {item} {index}>{item.summary}</slot>
|
139
|
+
</div>
|
140
|
+
<slot name="icon" {item} {index}>
|
141
|
+
{#if icon}
|
142
|
+
<div
|
143
|
+
class={classIcon}
|
144
|
+
class:d-rotate-180={item.open}
|
145
|
+
class:d-transition={transition}
|
146
|
+
>
|
147
|
+
{#if typeof icon !== "string"}
|
148
|
+
<svelte:component this={icon} />
|
149
|
+
{:else}
|
150
|
+
<span>{icon}</span>
|
151
|
+
{/if}
|
152
|
+
</div>
|
153
|
+
{/if}
|
154
|
+
</slot>
|
131
155
|
</summary>
|
132
156
|
{#if !clientJs || !transition}
|
133
|
-
<div class={
|
134
|
-
|
135
|
-
<svelte:component this={slot} class={classContentSlot} />
|
136
|
-
{:else}
|
137
|
-
<div class={classContentSlot}>{slot}</div>
|
138
|
-
{/if}
|
157
|
+
<div class={classContent}>
|
158
|
+
<slot name="content" {item} {index}>{item.content}</slot>
|
139
159
|
</div>
|
140
160
|
{/if}
|
141
161
|
</details>
|
142
|
-
{#if clientJs && open && transition}
|
143
|
-
<div transition:slide={transition}
|
144
|
-
|
145
|
-
<svelte:component this={slot} class={classContentSlot} />
|
146
|
-
{:else}
|
147
|
-
<div class={classContentSlot}>{slot}</div>
|
148
|
-
{/if}
|
162
|
+
{#if clientJs && item.open && transition}
|
163
|
+
<div class={classContent} transition:slide={transition}>
|
164
|
+
<slot name="content" {item} {index}>{item.content}</slot>
|
149
165
|
</div>
|
150
166
|
{/if}
|
151
167
|
</div>
|
@@ -159,10 +175,10 @@ onMount(() => {
|
|
159
175
|
summary::-webkit-details-marker {
|
160
176
|
display: none;
|
161
177
|
}
|
162
|
-
.
|
178
|
+
.d-rotate-180 {
|
163
179
|
transform: rotate(180deg);
|
164
180
|
}
|
165
|
-
.
|
181
|
+
.d-transition {
|
166
182
|
transition-property: transform;
|
167
183
|
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
168
184
|
transition-duration: 150ms;
|
@@ -1,37 +1,48 @@
|
|
1
1
|
import { SvelteComponent } from "svelte";
|
2
|
-
|
3
|
-
export interface
|
4
|
-
/**
|
5
|
-
|
6
|
-
/** content of the
|
7
|
-
|
8
|
-
/**
|
9
|
-
classContentSummary?: string;
|
10
|
-
/** content of the `slot` */
|
11
|
-
slot: string | ComponentType;
|
12
|
-
/** `slot` element class */
|
13
|
-
classContentSlot?: string;
|
14
|
-
/** controls whether the slotted content is displayed */
|
2
|
+
/** use `data` to pass anything back to the parent */
|
3
|
+
export interface AccordionItem<T = any> {
|
4
|
+
/** text summary of the item */
|
5
|
+
summary?: string;
|
6
|
+
/** text content of the item */
|
7
|
+
content?: string;
|
8
|
+
/** controls whether the content is displayed */
|
15
9
|
open?: boolean;
|
10
|
+
/** any data to pass back */
|
11
|
+
data?: T;
|
16
12
|
}
|
13
|
+
import { type ComponentType } from "svelte";
|
17
14
|
import { type SlideParams } from "svelte/transition";
|
18
15
|
declare const __propDef: {
|
19
16
|
props: {
|
20
17
|
class?: string | undefined;
|
21
18
|
id?: string | undefined;
|
22
|
-
/** array of `
|
19
|
+
/** array of `AccordionItem` elements */ items: AccordionItem[];
|
23
20
|
icon?: string | ComponentType | undefined;
|
24
21
|
/** class of the `div` around each `details` element */ classDetails?: string | undefined;
|
25
|
-
/** class of all the `summary` elements */
|
26
|
-
/** class of all the `
|
27
|
-
/** class of the `div`
|
22
|
+
/** class of all the `summary` elements */ classHeader?: string | undefined;
|
23
|
+
/** class of all the `div`s that wrap the `summary` slot */ classSummary?: string | undefined;
|
24
|
+
/** class of all the `div`s that wrap the `content` slot */ classContent?: string | undefined;
|
25
|
+
/** class of the `div` that wrap the icon if displayed */ classIcon?: string | undefined;
|
28
26
|
/** rotates the icon, slides the content, defaults to empty object, set to false to remove */ transition?: false | SlideParams | undefined;
|
29
27
|
/** if `true`, other items close when a new one is opened */ autoClose?: boolean | undefined;
|
30
28
|
};
|
31
29
|
events: {
|
32
30
|
[evt: string]: CustomEvent<any>;
|
33
31
|
};
|
34
|
-
slots: {
|
32
|
+
slots: {
|
33
|
+
summary: {
|
34
|
+
item: AccordionItem<any>;
|
35
|
+
index: any;
|
36
|
+
};
|
37
|
+
icon: {
|
38
|
+
item: AccordionItem<any>;
|
39
|
+
index: any;
|
40
|
+
};
|
41
|
+
content: {
|
42
|
+
item: AccordionItem<any>;
|
43
|
+
index: any;
|
44
|
+
};
|
45
|
+
};
|
35
46
|
};
|
36
47
|
export type AccordionProps = typeof __propDef.props;
|
37
48
|
export type AccordionEvents = typeof __propDef.events;
|
@@ -44,19 +55,24 @@ export type AccordionSlots = typeof __propDef.slots;
|
|
44
55
|
* @props
|
45
56
|
*
|
46
57
|
* - `autoClose` - if `true`, other items close when a new one is opened
|
58
|
+
* - `classContent` - class of all the `div`s that wrap the `content` slot
|
47
59
|
* - `classDetails` - class of the `div` around each `details` element
|
48
|
-
* - `
|
49
|
-
* - `
|
50
|
-
* - `classSummary` - class of all the `summary`
|
60
|
+
* - `classHeader` - class of all the `summary` elements
|
61
|
+
* - `classIcon` - class of the `div` that wrap the icon if displayed
|
62
|
+
* - `classSummary` - class of all the `div`s that wrap the `summary` slot
|
51
63
|
* - `class`
|
52
|
-
* - `content` - array of `AccordionContent` elements
|
53
64
|
* - `icon`
|
54
65
|
* - `id`
|
66
|
+
* - `items` - array of `AccordionItem` elements
|
55
67
|
* - `transition` - rotates the icon, slides the content, defaults to empty object, set to false to remove
|
56
68
|
*
|
57
69
|
* @slots
|
58
70
|
*
|
59
|
-
*
|
71
|
+
* | name | purpose | default value |
|
72
|
+
* | ---------- | ----------------------------- | -------------- |
|
73
|
+
* | `summary` | summary element | `item.summary` |
|
74
|
+
* | `icon` | icon element | `icon` prop |
|
75
|
+
* | `content` | content of the accordion item | `item.content` |
|
60
76
|
*
|
61
77
|
* @example
|
62
78
|
*
|
@@ -66,19 +82,50 @@ export type AccordionSlots = typeof __propDef.slots;
|
|
66
82
|
* </script>
|
67
83
|
*
|
68
84
|
* <Accordion
|
69
|
-
*
|
70
|
-
* { summary: "Is it accessible?",
|
85
|
+
* items={[
|
86
|
+
* { summary: "Is it accessible?", content: "Yes." },
|
71
87
|
* {
|
72
88
|
* summary: "Is it styled?",
|
73
|
-
*
|
89
|
+
* content: "Nope, style with global styles.",
|
74
90
|
* },
|
75
91
|
* {
|
76
92
|
* summary: "Is it animated?",
|
77
|
-
*
|
93
|
+
* content: "Yes, with the transition prop.",
|
94
|
+
* },
|
95
|
+
* { 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
|
+
* {
|
115
|
+
* summary: "A Component",
|
116
|
+
* content: "Rendered only on this item.",
|
117
|
+
* data: { component: FullscreenButton },
|
78
118
|
* },
|
79
|
-
* { summary: "
|
119
|
+
* { summary: "Summary", content: "Some other content" },
|
80
120
|
* ]}
|
81
|
-
*
|
121
|
+
* >
|
122
|
+
* <div slot="content" let:item>
|
123
|
+
* {item.content}
|
124
|
+
* {#if item.data?.component}
|
125
|
+
* <svelte:component this={item.data.component} />
|
126
|
+
* {/if}
|
127
|
+
* </div>
|
128
|
+
* </Accordion>
|
82
129
|
* ```
|
83
130
|
*/
|
84
131
|
export default class Accordion extends SvelteComponent<AccordionProps, AccordionEvents, AccordionSlots> {
|
package/dist/index.d.ts
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
import Accordion from "./components/Accordion.svelte";
|
2
|
-
import type {
|
2
|
+
import type { AccordionItem } from "./components/Accordion.svelte";
|
3
3
|
import Chord from "./components/Chord.svelte";
|
4
4
|
import type { ChordNote } from "./components/Chord.svelte";
|
5
5
|
import ContextMenu from "./components/ContextMenu.svelte";
|
@@ -12,4 +12,4 @@ import FullscreenButton from "./components/FullscreenButton.svelte";
|
|
12
12
|
import Popover from "./components/Popover.svelte";
|
13
13
|
import ShareButton from "./components/ShareButton.svelte";
|
14
14
|
import YouTube from "./components/YouTube.svelte";
|
15
|
-
export { Accordion, type
|
15
|
+
export { Accordion, type AccordionItem, Chord, type ChordNote, ContextMenu, CopyButton, DataTable, type DataTableRow, Editor, type EditorContentElement, FullscreenButton, Popover, ShareButton, YouTube, };
|