drab 2.6.1 → 2.8.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.
@@ -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 py-4 font-bold hover:underline"
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
  {
@@ -49,14 +52,37 @@ Displays a list of `details` elements.
49
52
  summary: "Is it animated?",
50
53
  content: "Yes, with the transition prop.",
51
54
  },
52
- { summary: "Does it work without Javascript?", content: "Yes." },
55
+ { summary: "Does it work without JavaScript?", content: "Yes." },
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
+ },
53
73
  ]}
54
74
  >
55
- <svelte:fragment slot="content" let:item let:index>
56
- <div class="pb-4">
57
- <span>{index + 1}.</span>
58
- <span>{item.content}</span>
59
- </div>
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
  ```
@@ -86,9 +112,8 @@ const toggleOpen = (i) => {
86
112
  items[i].open = !items[i].open;
87
113
  if (autoClose) {
88
114
  for (let j = 0; j < items.length; j++) {
89
- const item = items[j];
90
115
  if (j !== i)
91
- item.open = false;
116
+ items[j].open = false;
92
117
  }
93
118
  }
94
119
  };
@@ -143,6 +168,7 @@ onMount(() => {
143
168
  {/if}
144
169
  </details>
145
170
  {#if clientJs && item.open && transition}
171
+ <!-- outside the details for the transition -->
146
172
  <div class={classContent} transition:slide={transition}>
147
173
  <slot name="content" {item} {index}>{item.content}</slot>
148
174
  </div>
@@ -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 py-4 font-bold hover:underline"
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
  * {
@@ -95,14 +98,37 @@ export type AccordionSlots = typeof __propDef.slots;
95
98
  * summary: "Is it animated?",
96
99
  * content: "Yes, with the transition prop.",
97
100
  * },
98
- * { summary: "Does it work without Javascript?", content: "Yes." },
101
+ * { summary: "Does it work without JavaScript?", content: "Yes." },
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
+ * },
99
119
  * ]}
100
120
  * >
101
- * <svelte:fragment slot="content" let:item let:index>
102
- * <div class="pb-4">
103
- * <span>{index + 1}.</span>
104
- * <span>{item.content}</span>
105
- * </div>
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
- ```svelte
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
- * ```svelte
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`
@@ -3,7 +3,7 @@
3
3
 
4
4
  ### CopyButton
5
5
 
6
- Uses the navigator api to copy text to the clipboard.
6
+ Uses the [Clipboard API](https://developer.mozilla.org/en-US/docs/Web/API/Clipboard/writeText) to copy text to the clipboard.
7
7
 
8
8
  @props
9
9
 
@@ -21,7 +21,7 @@ export type CopyButtonSlots = typeof __propDef.slots;
21
21
  /**
22
22
  * ### CopyButton
23
23
  *
24
- * Uses the navigator api to copy text to the clipboard.
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,19 @@ 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
- - `paginate` - number of rows to show on each page, defaults to `0` - no pagination
32
- - `sortBy` - column to sort by--defaults to first column
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
+ - `transition` - fades the rows in, set to `false` to disable
33
34
 
34
35
  @slots
35
36
 
36
- | name | purpose | default value |
37
- | ---------- | ------------------------ | ------------- |
38
- | `previous` | previous button contents | `Previous` |
39
- | `next` | next button contents | `Next` |
37
+ | name | purpose | default value | slot props |
38
+ | ------------ | ------------------------ | -------------------------------- | ------------------------------ |
39
+ | `next` | next button contents | `Next` | `currentPage` |
40
+ | `pageNumber` | page numbers | `currentPage` / `numberOfPages` | `currentPage`, `numberOfPages` |
41
+ | `previous` | previous button contents | `Previous` | `currentPage` |
42
+ | `td` | td contents | `Previous` | `column`, `row` |
43
+ | `th` | th contents | `Previous` | `column` |
40
44
 
41
45
  @example
42
46
 
@@ -46,6 +50,7 @@ Data table to display an array of JS objects. Click a column header to sort.
46
50
  </script>
47
51
 
48
52
  <DataTable
53
+ class="mb-12"
49
54
  data={[
50
55
  { make: "Honda", model: "CR-V", year: 2011, awd: true },
51
56
  { make: "Volvo", model: "XC-40", year: 2024, awd: true },
@@ -57,22 +62,59 @@ Data table to display an array of JS objects. Click a column header to sort.
57
62
  { make: "GMC", model: "Acadia", year: 2008, awd: true },
58
63
  { make: "BMW", model: "X3", year: 2023, awd: true },
59
64
  ]}
60
- sortBy="make"
61
- paginate={4}
65
+ />
66
+
67
+ <DataTable
68
+ data={[
69
+ { make: "Honda", model: "CR-V", year: 2011, awd: true },
70
+ { make: "Volvo", model: "XC-40", year: 2024, awd: true },
71
+ { make: "Ferrari", model: "458 Italia", year: 2015, awd: false },
72
+ { make: "Chevrolet", model: "Silverado", year: 2022, awd: true },
73
+ { make: "Ford", model: "Model A", year: 1931, awd: false },
74
+ { make: "Subaru", model: "Outback", year: 2021, awd: true },
75
+ { make: "Ford", model: "Bronco", year: 1970, awd: true },
76
+ { make: "GMC", model: "Acadia", year: 2008, awd: true },
77
+ { make: "BMW", model: "X3", year: 2023, awd: true },
78
+ ]}
79
+ sortBy="year"
80
+ maxRows={4}
62
81
  class="tabular-nums"
63
- classTh="cursor-pointer uppercase"
82
+ classTh="cursor-pointer"
64
83
  classThSorted="underline"
65
84
  classTbodyTr="transition hover:bg-neutral-50"
66
85
  classFooter="flex justify-between items-center"
67
86
  classButton="btn"
68
- />
87
+ >
88
+ <svelte:fragment slot="th" let:column>
89
+ {#if column === "awd"}
90
+ <span class="uppercase">{column}</span>
91
+ {:else}
92
+ {column}
93
+ {/if}
94
+ </svelte:fragment>
95
+ <svelte:fragment slot="td" let:column let:row>
96
+ {@const item = row[column]}
97
+ {#if typeof item === "boolean"}
98
+ {#if item}
99
+ Yes
100
+ {:else}
101
+ No
102
+ {/if}
103
+ {:else}
104
+ {item}
105
+ {/if}
106
+ </svelte:fragment>
107
+ </DataTable>
69
108
  ```
70
109
  -->
71
110
 
72
111
  <script context="module"></script>
73
112
 
74
- <script>import { messageNoScript } from "../util/messages";
75
- import { onMount } from "svelte";
113
+ <script>import { onMount } from "svelte";
114
+ import { fade } from "svelte/transition";
115
+ import { duration } from "../util/transition";
116
+ import { prefersReducedMotion } from "../util/accessibility";
117
+ import { messageNoScript } from "../util/messages";
76
118
  let className = "";
77
119
  export { className as class };
78
120
  export let id = "";
@@ -97,12 +139,13 @@ export let classButton = "";
97
139
  export let classFooter = "";
98
140
  export let classPageNumber = "";
99
141
  export let classPageControls = "";
100
- export let paginate = 0;
142
+ export let maxRows = 0;
101
143
  export let currentPage = 1;
144
+ export let transition = { duration };
102
145
  export let classNoscript = "";
103
146
  let clientJs = false;
104
147
  $:
105
- numberOfPages = Math.floor(data.length / paginate) + 1;
148
+ numberOfPages = Math.floor(data.length / maxRows) + 1;
106
149
  const sort = (column, toggleAscending = true) => {
107
150
  if (column === sortBy && toggleAscending) {
108
151
  ascending = !ascending;
@@ -137,8 +180,21 @@ const sort = (column, toggleAscending = true) => {
137
180
  data = data;
138
181
  sortBy = column;
139
182
  };
183
+ const showRow = (i, currentPage2) => {
184
+ if (!maxRows)
185
+ return true;
186
+ const overMin = i >= maxRows * (currentPage2 - 1);
187
+ const underMax = i < maxRows * currentPage2;
188
+ return overMin && underMax;
189
+ };
140
190
  sort(sortBy, false);
141
- onMount(() => clientJs = true);
191
+ onMount(() => {
192
+ if (prefersReducedMotion()) {
193
+ if (transition)
194
+ transition.duration = 0;
195
+ }
196
+ clientJs = true;
197
+ });
142
198
  </script>
143
199
 
144
200
  <div class={className} {id}>
@@ -150,20 +206,21 @@ onMount(() => clientJs = true);
150
206
  class="{classTh} {sortBy === column ? classThSorted : ''}"
151
207
  on:click={() => sort(column)}
152
208
  >
153
- {column}
209
+ <slot name="th" {column}>{column}</slot>
154
210
  </th>
155
211
  {/each}
156
212
  </tr>
157
213
  </thead>
158
214
  <tbody class={classTbody}>
159
215
  {#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}>
216
+ {#if showRow(i, currentPage)}
217
+ <tr
218
+ in:fade={transition ? transition : { duration: 0 }}
219
+ class={classTbodyTr}
220
+ >
164
221
  {#each columns as column}
165
222
  <td class="{classTd} {sortBy === column ? classTdSorted : ''}">
166
- {row[column]}
223
+ <slot name="td" {row} {column}>{row[column]}</slot>
167
224
  </td>
168
225
  {/each}
169
226
  </tr>
@@ -172,31 +229,33 @@ onMount(() => clientJs = true);
172
229
  </tbody>
173
230
  </table>
174
231
 
175
- {#if paginate}
232
+ {#if maxRows}
176
233
  <div class={classFooter}>
177
- <div class={classPageNumber}>{currentPage} / {numberOfPages}</div>
234
+ <div class={classPageNumber}>
235
+ <slot name="pageNumber" {currentPage} {numberOfPages}>
236
+ {currentPage} / {numberOfPages}
237
+ </slot>
238
+ </div>
178
239
  <div class={classPageControls}>
179
240
  <button
241
+ type="button"
180
242
  class={classButton}
181
243
  disabled={!clientJs || currentPage < 2}
182
244
  on:click={() => currentPage--}
183
245
  >
184
- <slot name="previous">Previous</slot>
246
+ <slot name="previous" {currentPage}>Previous</slot>
185
247
  </button>
186
248
  <button
249
+ type="button"
187
250
  class={classButton}
188
251
  disabled={!clientJs || currentPage >= numberOfPages}
189
252
  on:click={() => currentPage++}
190
253
  >
191
- <slot name="next">Next</slot>
254
+ <slot name="next" {currentPage}>Next</slot>
192
255
  </button>
193
256
  </div>
194
257
  </div>
195
258
 
196
- <noscript>
197
- <div class={classNoscript}>
198
- {messageNoScript}
199
- </div>
200
- </noscript>
259
+ <noscript><div class={classNoscript}>{messageNoScript}</div></noscript>
201
260
  {/if}
202
261
  </div>
@@ -2,13 +2,14 @@ import { SvelteComponent } from "svelte";
2
2
  export type DataTableRow<T> = {
3
3
  [K in keyof T]: T[K];
4
4
  };
5
+ import { type FadeParams } from "svelte/transition";
5
6
  declare const __propDef: {
6
7
  props: {
7
8
  class?: string | undefined;
8
9
  id?: string | undefined;
9
10
  /** a list of objects to render in the table */ data: DataTableRow<any>[];
10
11
  /** table columns, in order */ columns?: string[] | undefined;
11
- /** column to sort by--defaults to first column */ sortBy?: string | undefined;
12
+ /** column to sort by, defaults to first column */ sortBy?: string | undefined;
12
13
  /** default sort order */ ascending?: boolean | undefined;
13
14
  /** `table` class */ classTable?: string | undefined;
14
15
  /** `table` id */ idTable?: string | undefined;
@@ -24,16 +25,32 @@ declare const __propDef: {
24
25
  /** `footer` class */ classFooter?: string | undefined;
25
26
  /** class of `div` wrapping page numbers */ classPageNumber?: string | undefined;
26
27
  /** 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 */ paginate?: number | undefined;
28
+ /** maximum number of rows to show on each page, defaults to `0` - no pagination */ maxRows?: number | undefined;
28
29
  /** current page, defaults to `1` */ currentPage?: number | undefined;
30
+ /** fades the rows in, set to `false` to disable */ transition?: false | FadeParams | undefined;
29
31
  /** `noscript` class */ classNoscript?: string | undefined;
30
32
  };
31
33
  events: {
32
34
  [evt: string]: CustomEvent<any>;
33
35
  };
34
36
  slots: {
35
- previous: {};
36
- next: {};
37
+ th: {
38
+ column: string;
39
+ };
40
+ td: {
41
+ row: DataTableRow<any>;
42
+ column: string;
43
+ };
44
+ pageNumber: {
45
+ currentPage: number;
46
+ numberOfPages: number;
47
+ };
48
+ previous: {
49
+ currentPage: number;
50
+ };
51
+ next: {
52
+ currentPage: number;
53
+ };
37
54
  };
38
55
  };
39
56
  export type DataTableProps = typeof __propDef.props;
@@ -67,15 +84,19 @@ export type DataTableSlots = typeof __propDef.slots;
67
84
  * - `data` - a list of objects to render in the table
68
85
  * - `idTable` - `table` id
69
86
  * - `id`
70
- * - `paginate` - number of rows to show on each page, defaults to `0` - no pagination
71
- * - `sortBy` - column to sort by--defaults to first column
87
+ * - `maxRows` - maximum number of rows to show on each page, defaults to `0` - no pagination
88
+ * - `sortBy` - column to sort by, defaults to first column
89
+ * - `transition` - fades the rows in, set to `false` to disable
72
90
  *
73
91
  * @slots
74
92
  *
75
- * | name | purpose | default value |
76
- * | ---------- | ------------------------ | ------------- |
77
- * | `previous` | previous button contents | `Previous` |
78
- * | `next` | next button contents | `Next` |
93
+ * | name | purpose | default value | slot props |
94
+ * | ------------ | ------------------------ | -------------------------------- | ------------------------------ |
95
+ * | `next` | next button contents | `Next` | `currentPage` |
96
+ * | `pageNumber` | page numbers | `currentPage` / `numberOfPages` | `currentPage`, `numberOfPages` |
97
+ * | `previous` | previous button contents | `Previous` | `currentPage` |
98
+ * | `td` | td contents | `Previous` | `column`, `row` |
99
+ * | `th` | th contents | `Previous` | `column` |
79
100
  *
80
101
  * @example
81
102
  *
@@ -85,6 +106,7 @@ export type DataTableSlots = typeof __propDef.slots;
85
106
  * </script>
86
107
  *
87
108
  * <DataTable
109
+ * class="mb-12"
88
110
  * data={[
89
111
  * { make: "Honda", model: "CR-V", year: 2011, awd: true },
90
112
  * { make: "Volvo", model: "XC-40", year: 2024, awd: true },
@@ -96,15 +118,49 @@ export type DataTableSlots = typeof __propDef.slots;
96
118
  * { make: "GMC", model: "Acadia", year: 2008, awd: true },
97
119
  * { make: "BMW", model: "X3", year: 2023, awd: true },
98
120
  * ]}
99
- * sortBy="make"
100
- * paginate={4}
121
+ * />
122
+ *
123
+ * <DataTable
124
+ * data={[
125
+ * { make: "Honda", model: "CR-V", year: 2011, awd: true },
126
+ * { make: "Volvo", model: "XC-40", year: 2024, awd: true },
127
+ * { make: "Ferrari", model: "458 Italia", year: 2015, awd: false },
128
+ * { make: "Chevrolet", model: "Silverado", year: 2022, awd: true },
129
+ * { make: "Ford", model: "Model A", year: 1931, awd: false },
130
+ * { make: "Subaru", model: "Outback", year: 2021, awd: true },
131
+ * { make: "Ford", model: "Bronco", year: 1970, awd: true },
132
+ * { make: "GMC", model: "Acadia", year: 2008, awd: true },
133
+ * { make: "BMW", model: "X3", year: 2023, awd: true },
134
+ * ]}
135
+ * sortBy="year"
136
+ * maxRows={4}
101
137
  * class="tabular-nums"
102
- * classTh="cursor-pointer uppercase"
138
+ * classTh="cursor-pointer"
103
139
  * classThSorted="underline"
104
140
  * classTbodyTr="transition hover:bg-neutral-50"
105
141
  * classFooter="flex justify-between items-center"
106
142
  * classButton="btn"
107
- * />
143
+ * >
144
+ * <svelte:fragment slot="th" let:column>
145
+ * {#if column === "awd"}
146
+ * <span class="uppercase">{column}</span>
147
+ * {:else}
148
+ * {column}
149
+ * {/if}
150
+ * </svelte:fragment>
151
+ * <svelte:fragment slot="td" let:column let:row>
152
+ * {@const item = row[column]}
153
+ * {#if typeof item === "boolean"}
154
+ * {#if item}
155
+ * Yes
156
+ * {:else}
157
+ * No
158
+ * {/if}
159
+ * {:else}
160
+ * {item}
161
+ * {/if}
162
+ * </svelte:fragment>
163
+ * </DataTable>
108
164
  * ```
109
165
  */
110
166
  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 fullscreen</div>
41
+ <div class="mb-2">Target element</div>
42
42
  <FullscreenButton target={fullscreenDiv} class="btn btn-s bg-neutral-50">
43
- <span>Enable Element Fullscreen</span>
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 fullscreen</div>
60
+ * <div class="mb-2">Target element</div>
61
61
  * <FullscreenButton target={fullscreenDiv} class="btn btn-s bg-neutral-50">
62
- * <span>Enable Element Fullscreen</span>
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
  ### Popover
5
5
 
6
- Displays a popover relatively positioned to the button.
6
+ Displays a popover relatively positioned to the target.
7
7
 
8
8
  @props
9
9
 
@@ -83,8 +83,8 @@ const setPosition = async () => {
83
83
  }
84
84
  }
85
85
  const targetRect = target.getBoundingClientRect();
86
- coordinates.x += targetRect.x;
87
- coordinates.y += targetRect.y;
86
+ coordinates.x += targetRect.x + window.scrollX;
87
+ coordinates.y += targetRect.y + window.scrollY;
88
88
  await tick();
89
89
  const popoverRect = popover.getBoundingClientRect();
90
90
  if (popoverRect.x < 0) {
@@ -22,7 +22,7 @@ export type PopoverSlots = typeof __propDef.slots;
22
22
  /**
23
23
  * ### Popover
24
24
  *
25
- * Displays a popover relatively positioned to the button.
25
+ * Displays a popover relatively positioned to the target.
26
26
  *
27
27
  * @props
28
28
  *