drab 2.3.0 → 2.4.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.
@@ -21,11 +21,11 @@ Displays a list of `details` elements.
21
21
 
22
22
  @slots
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
+ | 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
 
@@ -53,14 +53,6 @@ Displays a list of `details` elements.
53
53
  <span>{item.content}</span>
54
54
  </div>
55
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
56
 
65
57
  <Accordion
66
58
  items={[
@@ -72,12 +64,12 @@ To render a component on unique items, pass it into the `data` prop and utilize
72
64
  { summary: "Summary", content: "Some other content" },
73
65
  ]}
74
66
  >
75
- <div slot="content" let:item>
67
+ <svelte:fragment slot="content" let:item>
76
68
  {item.content}
77
69
  {#if item.data?.component}
78
70
  <svelte:component this={item.data.component} />
79
71
  {/if}
80
- </div>
72
+ </svelte:fragment>
81
73
  </Accordion>
82
74
  ```
83
75
  -->
@@ -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,11 +67,11 @@ export type AccordionSlots = typeof __propDef.slots;
68
67
  *
69
68
  * @slots
70
69
  *
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` |
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
  *
@@ -100,14 +99,6 @@ export type AccordionSlots = typeof __propDef.slots;
100
99
  * <span>{item.content}</span>
101
100
  * </div>
102
101
  * </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
102
  *
112
103
  * <Accordion
113
104
  * items={[
@@ -119,12 +110,12 @@ export type AccordionSlots = typeof __propDef.slots;
119
110
  * { summary: "Summary", content: "Some other content" },
120
111
  * ]}
121
112
  * >
122
- * <div slot="content" let:item>
113
+ * <svelte:fragment slot="content" let:item>
123
114
  * {item.content}
124
115
  * {#if item.data?.component}
125
116
  * <svelte:component this={item.data.component} />
126
117
  * {/if}
127
- * </div>
118
+ * </svelte:fragment>
128
119
  * </Accordion>
129
120
  * ```
130
121
  */
@@ -3,100 +3,104 @@
3
3
 
4
4
  ### Tabs
5
5
 
6
- Displays tabs and slotted content.
6
+ Displays tabs and the active tab's content.
7
7
 
8
8
  @props
9
9
 
10
- - `classButtonActive` - class of the active tab's `button`
11
- - `classButtonInactive` - class of all the inactive tabs' `button`s
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
- - `classSlot` - class of `div` that wraps the slotted content
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
- - `transition` - fades the content in, defaults to empty object, set to false to remove
19
+ - `tabs` - array of tabs
20
20
 
21
21
  @slots
22
22
 
23
- Pass components into the `content` prop if needed. `TabsContent` has a `slot` attribute of type `string | ComponentType`.
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 { FullscreenButton } from "drab";
31
33
  </script>
32
34
 
33
- <Tabs content={[
34
- { name: "String", slot: "Slot" },
35
- { name: "Component", slot: FullscreenButton },
35
+ <Tabs
36
+ items={[
37
+ { name: "Tab 1", content: "Content 1" },
38
+ { name: "Tab 2", content: "Content 2" },
36
39
  ]}
37
40
  />
41
+
42
+ <Tabs
43
+ tabs={[
44
+ { title: "Tab", content: "Content 1" },
45
+ {
46
+ title: "Tab",
47
+ content: "A tab with a component",
48
+ data: { component: FullscreenButton },
49
+ },
50
+ ]}
51
+ let:activeTab
52
+ >
53
+ <svelte:fragment slot="title" let:item let:index>
54
+ {item.title}
55
+ {index + 1}
56
+ </svelte:fragment>
57
+ <div>{activeTab.content}</div>
58
+ {#if activeTab.data?.component}
59
+ <svelte:component this={activeTab.data.component} />
60
+ {/if}
61
+ </Tabs>
38
62
  ```
39
63
  -->
40
64
 
41
65
  <script context="module"></script>
42
66
 
43
67
  <script>import { onMount } from "svelte";
44
- import { fade } from "svelte/transition";
45
68
  import { messageNoScript } from "../util/messages";
46
69
  let className = "";
47
70
  export { className as class };
48
71
  export let id = "";
49
72
  export let classHeader = "";
50
- export let classButton = "";
51
- export let classButtonActive = "";
52
- export let classButtonInactive = "";
73
+ export let classTitle = "";
74
+ export let classTitleActive = "";
75
+ export let classTitleInactive = "";
53
76
  export let classNoscript = "";
54
- export let classSlot = "";
55
- export let content;
56
- export let transition = {};
57
- const fadeTransition = transition ? transition : { duration: 0 };
77
+ export let classContent = "";
78
+ export let tabs;
79
+ export let activeIndex = 0;
58
80
  let clientJs = false;
59
- let activeIndex = 0;
60
- for (const item of content) {
61
- if (!item.classContentSlot)
62
- item.classContentSlot = "";
63
- }
64
81
  $:
65
- activeTab = content[activeIndex];
82
+ activeTab = tabs[activeIndex];
66
83
  onMount(() => clientJs = true);
67
84
  </script>
68
85
 
69
86
  <div class={className} {id}>
70
87
  <div class={classHeader}>
71
- {#each content as { name }, i}
88
+ {#each tabs as item, index}
72
89
  <button
73
90
  disabled={!clientJs}
74
- class="{classButton} {activeIndex === i
75
- ? classButtonActive
76
- : ''} {activeIndex !== i ? classButtonInactive : ''}"
77
- on:click={() => (activeIndex = i)}
91
+ class="{classTitle} {activeIndex === index
92
+ ? classTitleActive
93
+ : ''} {activeIndex !== index ? classTitleInactive : ''}"
94
+ on:click={() => (activeIndex = index)}
78
95
  >
79
- {name}
96
+ <slot name="title" {item} {index}>{item.title}</slot>
80
97
  </button>
81
98
  {/each}
82
99
  </div>
83
- <div class={classSlot}>
84
- {#if typeof activeTab.slot !== "string"}
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}
100
+ <div class={classContent}>
101
+ <slot {activeTab}>{activeTab.content}</slot>
96
102
  </div>
97
103
  <noscript>
98
- <div class={classNoscript}>
99
- {messageNoScript}
100
- </div>
104
+ <div class={classNoscript}>{messageNoScript}</div>
101
105
  </noscript>
102
106
  </div>
@@ -1,31 +1,37 @@
1
1
  import { SvelteComponent } from "svelte";
2
- import type { ComponentType } from "svelte";
3
- export interface TabsContent {
4
- /** tab name, displayed in `button` element */
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
- slot: string | ComponentType;
8
- /** class of the slotted content */
9
- classContentSlot?: string;
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` class */ classButton?: string | undefined;
18
- /** class of the active tab's `button` */ classButtonActive?: string | undefined;
19
- /** class of all the inactive tabs' `button`s */ classButtonInactive?: string | undefined;
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 */ classSlot?: string | undefined;
22
- /** array of `TabContent` elements */ content: TabsContent[];
23
- /** fades the content in, defaults to empty object, set to false to remove */ transition?: false | FadeParams | undefined;
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,62 @@ export type TabsSlots = typeof __propDef.slots;
33
39
  /**
34
40
  * ### Tabs
35
41
  *
36
- * Displays tabs and slotted content.
42
+ * Displays tabs and the active tab's content.
37
43
  *
38
44
  * @props
39
45
  *
40
- * - `classButtonActive` - class of the active tab's `button`
41
- * - `classButtonInactive` - class of all the inactive tabs' `button`s
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
- * - `classSlot` - class of `div` that wraps the slotted content
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
- * - `transition` - fades the content in, defaults to empty object, set to false to remove
55
+ * - `tabs` - array of tabs
50
56
  *
51
57
  * @slots
52
58
  *
53
- * Pass components into the `content` prop if needed. `TabsContent` has a `slot` attribute of type `string | ComponentType`.
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 { FullscreenButton } from "drab";
61
69
  * </script>
62
70
  *
63
- * <Tabs content={[
64
- * { name: "String", slot: "Slot" },
65
- * { name: "Component", slot: FullscreenButton },
71
+ * <Tabs
72
+ * items={[
73
+ * { name: "Tab 1", content: "Content 1" },
74
+ * { name: "Tab 2", content: "Content 2" },
66
75
  * ]}
67
76
  * />
77
+ *
78
+ * <Tabs
79
+ * tabs={[
80
+ * { title: "Tab", content: "Content 1" },
81
+ * {
82
+ * title: "Tab",
83
+ * content: "A tab with a component",
84
+ * data: { component: FullscreenButton },
85
+ * },
86
+ * ]}
87
+ * let:activeTab
88
+ * >
89
+ * <svelte:fragment slot="title" let:item let:index>
90
+ * {item.title}
91
+ * {index + 1}
92
+ * </svelte:fragment>
93
+ * <div>{activeTab.content}</div>
94
+ * {#if activeTab.data?.component}
95
+ * <svelte:component this={activeTab.data.component} />
96
+ * {/if}
97
+ * </Tabs>
68
98
  * ```
69
99
  */
70
100
  export default class Tabs extends SvelteComponent<TabsProps, TabsEvents, TabsSlots> {
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.0",
3
+ "version": "2.4.0",
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",