webcoreui 0.9.0 → 0.10.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.
Files changed (138) hide show
  1. package/README.md +22 -6
  2. package/components/Accordion/Accordion.astro +15 -10
  3. package/components/Accordion/Accordion.svelte +14 -12
  4. package/components/Accordion/Accordion.tsx +2 -2
  5. package/components/Alert/Alert.svelte +17 -12
  6. package/components/Alert/Alert.tsx +1 -1
  7. package/components/Alert/alert.ts +10 -3
  8. package/components/AspectRatio/AspectRatio.svelte +7 -4
  9. package/components/AspectRatio/aspectratio.ts +6 -0
  10. package/components/Avatar/Avatar.svelte +11 -9
  11. package/components/Badge/Badge.svelte +14 -10
  12. package/components/Badge/badge.ts +2 -1
  13. package/components/Banner/Banner.astro +10 -4
  14. package/components/Banner/Banner.svelte +14 -10
  15. package/components/Banner/Banner.tsx +1 -0
  16. package/components/Banner/banner.ts +6 -0
  17. package/components/BottomNavigation/BottomNavigation.svelte +7 -5
  18. package/components/Breadcrumb/Breadcrumb.astro +1 -1
  19. package/components/Breadcrumb/Breadcrumb.svelte +8 -6
  20. package/components/Breadcrumb/Breadcrumb.tsx +2 -2
  21. package/components/Button/Button.svelte +12 -8
  22. package/components/Button/Button.tsx +2 -2
  23. package/components/Button/button.ts +2 -3
  24. package/components/Card/Card.svelte +14 -10
  25. package/components/Card/card.ts +6 -0
  26. package/components/Carousel/Carousel.astro +46 -41
  27. package/components/Carousel/carousel.ts +3 -0
  28. package/components/Checkbox/Checkbox.svelte +12 -9
  29. package/components/Checkbox/checkbox.module.scss +4 -0
  30. package/components/Collapsible/Collapsible.astro +8 -5
  31. package/components/Collapsible/Collapsible.svelte +54 -49
  32. package/components/Collapsible/collapsible.ts +8 -0
  33. package/components/ConditionalWrapper/ConditionalWrapper.svelte +10 -6
  34. package/components/ConditionalWrapper/conditionalwrapper.ts +6 -0
  35. package/components/Copy/Copy.astro +17 -11
  36. package/components/Copy/Copy.svelte +68 -61
  37. package/components/Copy/Copy.tsx +1 -0
  38. package/components/Copy/copy.ts +8 -2
  39. package/components/DataTable/DataTable.astro +103 -93
  40. package/components/DataTable/DataTable.svelte +276 -272
  41. package/components/DataTable/datatable.ts +5 -2
  42. package/components/Flex/Flex.svelte +14 -10
  43. package/components/Flex/flex.ts +6 -0
  44. package/components/Footer/Footer.svelte +12 -9
  45. package/components/Footer/footer.ts +6 -0
  46. package/components/Grid/Grid.svelte +12 -8
  47. package/components/Grid/grid.ts +6 -0
  48. package/components/Group/Group.svelte +7 -4
  49. package/components/Group/group.ts +6 -0
  50. package/components/Icon/Icon.astro +19 -5
  51. package/components/Icon/Icon.svelte +23 -7
  52. package/components/Icon/Icon.tsx +19 -5
  53. package/components/Icon/icon.ts +9 -3
  54. package/components/Icon/map.ts +8 -10
  55. package/components/Input/Input.svelte +24 -20
  56. package/components/Input/input.ts +10 -3
  57. package/components/Kbd/Kbd.svelte +7 -4
  58. package/components/Kbd/kbd.ts +6 -0
  59. package/components/List/List.astro +65 -60
  60. package/components/List/List.svelte +149 -147
  61. package/components/List/List.tsx +1 -1
  62. package/components/Masonry/Masonry.svelte +12 -10
  63. package/components/Menu/Menu.astro +8 -3
  64. package/components/Menu/Menu.svelte +15 -10
  65. package/components/Menu/Menu.tsx +3 -1
  66. package/components/Menu/menu.ts +6 -0
  67. package/components/Modal/Modal.astro +1 -0
  68. package/components/Modal/Modal.svelte +18 -13
  69. package/components/Modal/Modal.tsx +2 -1
  70. package/components/Modal/modal.ts +6 -1
  71. package/components/Pagination/Pagination.astro +75 -69
  72. package/components/Pagination/Pagination.svelte +29 -26
  73. package/components/Pagination/Pagination.tsx +5 -4
  74. package/components/Pagination/pagination.module.scss +4 -0
  75. package/components/Popover/Popover.svelte +10 -6
  76. package/components/Popover/popover.ts +6 -0
  77. package/components/Progress/Progress.svelte +12 -10
  78. package/components/Progress/progress.ts +1 -1
  79. package/components/Radio/Radio.svelte +12 -9
  80. package/components/Radio/radio.ts +4 -2
  81. package/components/Rating/Rating.svelte +16 -14
  82. package/components/Ribbon/Ribbon.svelte +9 -6
  83. package/components/Ribbon/ribbon.ts +6 -0
  84. package/components/Select/Select.astro +73 -63
  85. package/components/Select/Select.svelte +27 -22
  86. package/components/Select/Select.tsx +8 -6
  87. package/components/Sheet/Sheet.svelte +9 -5
  88. package/components/Sheet/sheet.ts +6 -2
  89. package/components/Sidebar/Sidebar.svelte +7 -4
  90. package/components/Sidebar/sidebar.ts +6 -0
  91. package/components/Skeleton/Skeleton.svelte +9 -7
  92. package/components/Slider/Slider.svelte +15 -13
  93. package/components/Slider/slider.module.scss +4 -0
  94. package/components/Slider/slider.ts +4 -2
  95. package/components/Spinner/Spinner.svelte +7 -5
  96. package/components/Spoiler/Spoiler.astro +13 -8
  97. package/components/Spoiler/Spoiler.svelte +13 -10
  98. package/components/Spoiler/spoiler.ts +6 -0
  99. package/components/Stepper/Stepper.svelte +9 -7
  100. package/components/Switch/Switch.svelte +15 -12
  101. package/components/Table/Table.svelte +11 -9
  102. package/components/Table/table.ts +1 -1
  103. package/components/Tabs/Tabs.astro +8 -5
  104. package/components/Tabs/Tabs.svelte +14 -11
  105. package/components/Tabs/tabs.ts +7 -1
  106. package/components/Textarea/Textarea.svelte +14 -11
  107. package/components/Textarea/textarea.ts +9 -4
  108. package/components/ThemeSwitcher/ThemeSwitcher.astro +43 -37
  109. package/components/ThemeSwitcher/ThemeSwitcher.svelte +14 -10
  110. package/components/ThemeSwitcher/themeswitcher.ts +7 -0
  111. package/components/Timeline/Timeline.svelte +12 -9
  112. package/components/Timeline/timeline.ts +7 -2
  113. package/components/TimelineItem/TimelineItem.svelte +8 -5
  114. package/components/TimelineItem/timelineitem.ts +6 -0
  115. package/components/Toast/Toast.svelte +18 -10
  116. package/components/Toast/toast.ts +6 -1
  117. package/icons/alert.svg +2 -2
  118. package/icons/check.svg +2 -2
  119. package/icons/chevron-down.svg +3 -0
  120. package/icons/chevron-left.svg +3 -0
  121. package/icons/chevron-right.svg +3 -0
  122. package/icons/chevron-up.svg +3 -0
  123. package/icons/circle-check.svg +3 -3
  124. package/icons/info.svg +3 -3
  125. package/icons.d.ts +4 -5
  126. package/icons.js +4 -5
  127. package/index.d.ts +1 -0
  128. package/index.js +1 -0
  129. package/package.json +20 -20
  130. package/react.d.ts +3 -3
  131. package/svelte.d.ts +98 -98
  132. package/utils/bodyFreeze.ts +13 -0
  133. package/utils/modal.ts +12 -0
  134. package/icons/arrow-down.svg +0 -3
  135. package/icons/arrow-left.svg +0 -3
  136. package/icons/arrow-right.svg +0 -3
  137. package/icons/components.svg +0 -3
  138. package/icons/file.svg +0 -3
@@ -1,272 +1,276 @@
1
- <script lang="ts">
2
- import type { HeadingObject, SvelteDataTableProps } from './datatable'
3
-
4
- import Button from '../Button/Button.svelte'
5
- import Input from '../Input/Input.svelte'
6
- import Pagination from '../Pagination/Pagination.svelte'
7
- import Select from '../Select/Select.svelte'
8
-
9
- import { classNames } from '../../utils/classNames'
10
- import { debounce } from '../../utils/debounce'
11
-
12
- import checkIcon from '../../icons/check.svg?raw'
13
- import orderIcon from '../../icons/order.svg?raw'
14
- import searchIcon from '../../icons/search.svg?raw'
15
-
16
- import styles from './datatable.module.scss'
17
-
18
- import type { ListEventType } from '../List/list'
19
-
20
- export let headings: SvelteDataTableProps['headings'] = []
21
- export let filterPlaceholder: SvelteDataTableProps['filterPlaceholder'] = 'Filter entries'
22
- export let showFilterIcon: SvelteDataTableProps['showFilterIcon'] = false
23
- export let noResultsLabel: SvelteDataTableProps['noResultsLabel'] = 'No results.'
24
- export let itemsPerPage: SvelteDataTableProps['itemsPerPage'] = null
25
- export let subText: SvelteDataTableProps['subText'] = ''
26
- export let columnToggleLabel: SvelteDataTableProps['columnToggleLabel'] = 'Columns'
27
- export let pagination: SvelteDataTableProps['pagination'] = {}
28
- export let data: SvelteDataTableProps['data'] = []
29
- export let hover: SvelteDataTableProps['hover'] = false
30
- export let striped: SvelteDataTableProps['striped'] = null
31
- export let offsetStripe: SvelteDataTableProps['offsetStripe'] = false
32
- export let compact: SvelteDataTableProps['compact'] = false
33
- export let maxHeight: SvelteDataTableProps['maxHeight'] = ''
34
- export let className: SvelteDataTableProps['className'] = ''
35
- export let id: SvelteDataTableProps['id'] = ''
36
- export let onFilter: SvelteDataTableProps['onFilter'] = () => {}
37
-
38
- let filteredData: any = data
39
- let toggledData: any = filteredData
40
- let filteredHeadings: any = headings
41
- let page: number = 1
42
- let hasActiveFilter: boolean = false
43
- let sortOrder = 1
44
-
45
- const classes = classNames([
46
- styles.table,
47
- hover && styles.hover,
48
- striped && styles[`striped-${striped}s`],
49
- offsetStripe && styles.offset,
50
- compact && styles.compact,
51
- maxHeight && styles.scroll
52
- ])
53
-
54
- const footerClasses = classNames([
55
- styles.footer,
56
- subText && styles.between
57
- ])
58
-
59
- const showColumnToggle = headings?.some(heading => {
60
- return typeof heading === 'string' ? false : heading.toggleable
61
- })
62
-
63
- const columnToggleItems = [{
64
- items: headings?.length ? headings
65
- .filter(heading => typeof heading !== 'string' && heading.toggleable)
66
- .map(heading => ({
67
- icon: checkIcon,
68
- name: (heading as HeadingObject).name,
69
- value: String(headings.findIndex(h => {
70
- return (h as HeadingObject).name === (heading as HeadingObject).name
71
- }))
72
- })) : []
73
- }]
74
-
75
- const columnFilterIndexes = headings?.map(heading => (heading as HeadingObject).filterable)
76
- .map((heading, index) => heading ? index : null)
77
- .filter(heading => heading !== null) || []
78
-
79
- const hasPagination = data?.length && itemsPerPage
80
- ? data.length > itemsPerPage
81
- : false
82
-
83
- const filter = debounce((event: Event) => {
84
- const target = event.target as HTMLInputElement
85
-
86
- hasActiveFilter = !!target.value
87
-
88
- filteredData = toggledData?.filter((row: string[]) => {
89
- const rowValue = row.filter((_, index) => columnFilterIndexes.includes(index))
90
- .join('')
91
- .toLowerCase()
92
-
93
- return rowValue.includes(target.value.toLowerCase())
94
- })
95
-
96
- onFilter?.({
97
- results: filteredData,
98
- numberOfResults: filteredData.length
99
- })
100
- }, 400)
101
-
102
- const toggleColumns = (event: ListEventType) => {
103
- const columnToggleListElement = Array.from(event.list.children)
104
- .find(child => (child as HTMLLIElement).dataset.name === event.name) as HTMLLIElement
105
- const svgIcon = columnToggleListElement.children[0] as HTMLElement
106
-
107
- svgIcon.style.opacity = svgIcon.style.opacity === '0'
108
- ? '1'
109
- : '0'
110
-
111
- if (svgIcon.style.opacity === '0') {
112
- filteredData = (hasActiveFilter ? data : filteredData)?.map((row: string[]) => {
113
- return row.map((column, index) => index === Number(event.value) ? null : column)
114
- })
115
-
116
- filteredHeadings = filteredHeadings.map((heading: HeadingObject | string) => {
117
- return ((heading as HeadingObject)?.name || heading) === event.name ? null : heading
118
- })
119
- } else {
120
- filteredData = (hasActiveFilter ? data : filteredData)?.map((row: string[], x: number) => {
121
- return row.map((column, y) => y === Number(event.value) ? data?.[x][y] : column)
122
- })
123
-
124
- filteredHeadings = filteredHeadings.map((heading: HeadingObject | string, index: number) => {
125
- return ((headings?.[index] as HeadingObject)?.name || headings?.[index]) === event.name
126
- ? headings?.[index]
127
- : heading
128
- })
129
- }
130
-
131
- hasActiveFilter = false
132
- toggledData = filteredData
133
- }
134
-
135
- const sort = (index: number) => {
136
- filteredData = filteredData.sort((a: string[], b: string[]) => {
137
- let aValue: string | number = a[index]
138
- let bValue: string | number = b[index]
139
-
140
- if (!isNaN(aValue as any)) {
141
- aValue = Number(aValue)
142
- }
143
-
144
- if (!isNaN(bValue as any)) {
145
- bValue = Number(bValue)
146
- }
147
-
148
- return aValue > bValue
149
- ? sortOrder * -1
150
- : sortOrder
151
- })
152
-
153
- sortOrder = sortOrder === 1 ? -1 : 1
154
- }
155
-
156
- $: isNextPage = (index: number) => {
157
- if (hasPagination && itemsPerPage && !hasActiveFilter) {
158
- const currentPage = Math.ceil((index + 1) / itemsPerPage)
159
-
160
- return currentPage !== page ? 'true' : undefined
161
- }
162
-
163
- if (hasActiveFilter && itemsPerPage) {
164
- return index >= itemsPerPage ? 'true' : undefined
165
- }
166
-
167
- return undefined
168
- }
169
- </script>
170
-
171
- <section class={className || null} id={id || null}>
172
- {#if columnFilterIndexes?.length || showColumnToggle}
173
- <div class={styles.filters}>
174
- {#if columnFilterIndexes?.length}
175
- {#if showFilterIcon}
176
- <Input
177
- type="search"
178
- placeholder={filterPlaceholder}
179
- onInput={filter}
180
- >
181
- {@html searchIcon}
182
- </Input>
183
- {:else}
184
- <Input
185
- type="search"
186
- placeholder={filterPlaceholder}
187
- onInput={filter}
188
- />
189
- {/if}
190
- {/if}
191
- {#if showColumnToggle}
192
- <Select
193
- name={`data-table-${id || crypto.randomUUID()}`}
194
- itemGroups={columnToggleItems}
195
- position="bottom-end"
196
- value={columnToggleLabel}
197
- onChange={toggleColumns}
198
- updateValue={false}
199
- />
200
- {/if}
201
- </div>
202
- {/if}
203
-
204
- <div
205
- class={classes}
206
- style={maxHeight ? `max-height:${maxHeight}` : undefined}
207
- >
208
- <table>
209
- {#if filteredHeadings?.length}
210
- <thead>
211
- <tr>
212
- {#each filteredHeadings as heading, index}
213
- {#if heading}
214
- <th>
215
- {#if heading.sortable}
216
- <Button theme="flat" slot="wrapper" onClick={() => sort(index)}>
217
- {heading.name || heading}
218
- {@html orderIcon}
219
- </Button>
220
- {:else}
221
- {heading.name || heading}
222
- {/if}
223
- </th>
224
- {/if}
225
- {/each}
226
- </tr>
227
- </thead>
228
- {/if}
229
-
230
- <tbody>
231
- {#if filteredData?.length}
232
- {#each filteredData as row, index}
233
- <tr data-hidden={isNextPage(index)}>
234
- {#each row as column}
235
- {#if column}
236
- <td>
237
- {@html column}
238
- </td>
239
- {/if}
240
- {/each}
241
- </tr>
242
- {/each}
243
- {/if}
244
- <slot />
245
- </tbody>
246
- {#if columnFilterIndexes?.length && !filteredData.length}
247
- <tfoot>
248
- <tr>
249
- <td colspan={data?.[0].length} class={styles['no-results']}>
250
- {noResultsLabel}
251
- </td>
252
- </tr>
253
- </tfoot>
254
- {/if}
255
- </table>
256
- </div>
257
- {#if subText || hasPagination}
258
- <div class={footerClasses}>
259
- {#if subText}
260
- <span class={styles.subtext}>{subText}</span>
261
- {/if}
262
- {#if hasPagination && itemsPerPage && !hasActiveFilter}
263
- <Pagination
264
- {...pagination}
265
- totalPages={Math.ceil((data?.length || 0) / itemsPerPage)}
266
- currentPage={page}
267
- onChange={event => page = event.page}
268
- />
269
- {/if}
270
- </div>
271
- {/if}
272
- </section>
1
+ <script lang="ts">
2
+ import type { HeadingObject, SvelteDataTableProps } from './datatable'
3
+
4
+ import Button from '../Button/Button.svelte'
5
+ import Input from '../Input/Input.svelte'
6
+ import Pagination from '../Pagination/Pagination.svelte'
7
+ import Select from '../Select/Select.svelte'
8
+
9
+ import { classNames } from '../../utils/classNames'
10
+ import { debounce } from '../../utils/debounce'
11
+
12
+ import checkIcon from '../../icons/check.svg?raw'
13
+ import orderIcon from '../../icons/order.svg?raw'
14
+ import searchIcon from '../../icons/search.svg?raw'
15
+
16
+ import styles from './datatable.module.scss'
17
+
18
+ import type { ListEventType } from '../List/list'
19
+
20
+ const {
21
+ headings,
22
+ filterPlaceholder = 'Filter entries',
23
+ showFilterIcon,
24
+ noResultsLabel = 'No results.',
25
+ itemsPerPage,
26
+ subText,
27
+ columnToggleLabel = 'Columns',
28
+ pagination,
29
+ data,
30
+ hover,
31
+ striped,
32
+ offsetStripe,
33
+ compact,
34
+ maxHeight,
35
+ className,
36
+ id,
37
+ onFilter,
38
+ children
39
+ }: SvelteDataTableProps = $props()
40
+
41
+ let filteredData: any = $state(data)
42
+ let toggledData: any = $state(data)
43
+ let filteredHeadings: any = $state(headings)
44
+ let page: number = $state(1)
45
+ let hasActiveFilter: boolean = $state(false)
46
+ let sortOrder = 1
47
+
48
+ const classes = classNames([
49
+ styles.table,
50
+ hover && styles.hover,
51
+ striped && styles[`striped-${striped}s`],
52
+ offsetStripe && styles.offset,
53
+ compact && styles.compact,
54
+ maxHeight && styles.scroll
55
+ ])
56
+
57
+ const footerClasses = classNames([
58
+ styles.footer,
59
+ subText && styles.between
60
+ ])
61
+
62
+ const showColumnToggle = headings?.some(heading => {
63
+ return typeof heading === 'string' ? false : heading.toggleable
64
+ })
65
+
66
+ const columnToggleItems = [{
67
+ items: headings?.length ? headings
68
+ .filter(heading => typeof heading !== 'string' && heading.toggleable)
69
+ .map(heading => ({
70
+ icon: checkIcon,
71
+ name: (heading as HeadingObject).name,
72
+ value: String(headings.findIndex(h => {
73
+ return (h as HeadingObject).name === (heading as HeadingObject).name
74
+ }))
75
+ })) : []
76
+ }]
77
+
78
+ const columnFilterIndexes = headings?.map(heading => (heading as HeadingObject).filterable)
79
+ .map((heading, index) => heading ? index : null)
80
+ .filter(heading => heading !== null) || []
81
+
82
+ const hasPagination = data?.length && itemsPerPage
83
+ ? data.length > itemsPerPage
84
+ : false
85
+
86
+ const filter = debounce((event: Event) => {
87
+ const target = event.target as HTMLInputElement
88
+
89
+ hasActiveFilter = !!target.value
90
+
91
+ filteredData = toggledData?.filter((row: string[]) => {
92
+ const rowValue = row.filter((_, index) => columnFilterIndexes.includes(index))
93
+ .join('')
94
+ .toLowerCase()
95
+
96
+ return rowValue.includes(target.value.toLowerCase())
97
+ })
98
+
99
+ onFilter?.({
100
+ results: $state.snapshot(filteredData),
101
+ numberOfResults: filteredData.length
102
+ })
103
+ }, 400)
104
+
105
+ const toggleColumns = (event: ListEventType) => {
106
+ const columnToggleListElement = Array.from(event.list.children)
107
+ .find(child => (child as HTMLLIElement).dataset.name === event.name) as HTMLLIElement
108
+ const svgIcon = columnToggleListElement.children[0] as HTMLElement
109
+
110
+ svgIcon.style.opacity = svgIcon.style.opacity === '0'
111
+ ? '1'
112
+ : '0'
113
+
114
+ if (svgIcon.style.opacity === '0') {
115
+ filteredData = (hasActiveFilter ? data : filteredData)?.map((row: string[]) => {
116
+ return row.map((column, index) => index === Number(event.value) ? null : column)
117
+ })
118
+
119
+ filteredHeadings = filteredHeadings.map((heading: HeadingObject | string) => {
120
+ return ((heading as HeadingObject)?.name || heading) === event.name ? null : heading
121
+ })
122
+ } else {
123
+ filteredData = (hasActiveFilter ? data : filteredData)?.map((row: string[], x: number) => {
124
+ return row.map((column, y) => y === Number(event.value) ? data?.[x][y] : column)
125
+ })
126
+
127
+ filteredHeadings = filteredHeadings.map((heading: HeadingObject | string, index: number) => {
128
+ return ((headings?.[index] as HeadingObject)?.name || headings?.[index]) === event.name
129
+ ? headings?.[index]
130
+ : heading
131
+ })
132
+ }
133
+
134
+ hasActiveFilter = false
135
+ toggledData = filteredData
136
+ }
137
+
138
+ const sort = (index: number) => {
139
+ filteredData = filteredData.sort((a: string[], b: string[]) => {
140
+ let aValue: string | number = a[index]
141
+ let bValue: string | number = b[index]
142
+
143
+ if (!isNaN(aValue as any)) {
144
+ aValue = Number(aValue)
145
+ }
146
+
147
+ if (!isNaN(bValue as any)) {
148
+ bValue = Number(bValue)
149
+ }
150
+
151
+ return aValue > bValue
152
+ ? sortOrder * -1
153
+ : sortOrder
154
+ })
155
+
156
+ sortOrder = sortOrder === 1 ? -1 : 1
157
+ }
158
+
159
+ // eslint-disable-next-line prefer-const
160
+ let isNextPage = $derived((index: number) => {
161
+ if (hasPagination && itemsPerPage && !hasActiveFilter) {
162
+ const currentPage = Math.ceil((index + 1) / itemsPerPage)
163
+
164
+ return currentPage !== page ? 'true' : undefined
165
+ }
166
+
167
+ if (hasActiveFilter && itemsPerPage) {
168
+ return index >= itemsPerPage ? 'true' : undefined
169
+ }
170
+
171
+ return undefined
172
+ })
173
+ </script>
174
+
175
+ <section class={className} id={id}>
176
+ {#if columnFilterIndexes?.length || showColumnToggle}
177
+ <div class={styles.filters}>
178
+ {#if columnFilterIndexes?.length}
179
+ {#if showFilterIcon}
180
+ <Input
181
+ type="search"
182
+ placeholder={filterPlaceholder}
183
+ onInput={filter}
184
+ >
185
+ {@html searchIcon}
186
+ </Input>
187
+ {:else}
188
+ <Input
189
+ type="search"
190
+ placeholder={filterPlaceholder}
191
+ onInput={filter}
192
+ />
193
+ {/if}
194
+ {/if}
195
+ {#if showColumnToggle}
196
+ <Select
197
+ name={`data-table-${id || crypto.randomUUID()}`}
198
+ itemGroups={columnToggleItems}
199
+ position="bottom-end"
200
+ value={columnToggleLabel}
201
+ onChange={toggleColumns}
202
+ updateValue={false}
203
+ />
204
+ {/if}
205
+ </div>
206
+ {/if}
207
+
208
+ <div
209
+ class={classes}
210
+ style={maxHeight ? `max-height:${maxHeight}` : undefined}
211
+ >
212
+ <table>
213
+ {#if filteredHeadings?.length}
214
+ <thead>
215
+ <tr>
216
+ {#each filteredHeadings as heading, index}
217
+ {#if heading}
218
+ <th>
219
+ {#if heading.sortable}
220
+ <Button theme="flat" onClick={() => sort(index)}>
221
+ {heading.name || heading}
222
+ {@html orderIcon}
223
+ </Button>
224
+ {:else}
225
+ {heading.name || heading}
226
+ {/if}
227
+ </th>
228
+ {/if}
229
+ {/each}
230
+ </tr>
231
+ </thead>
232
+ {/if}
233
+
234
+ <tbody>
235
+ {#if filteredData?.length}
236
+ {#each filteredData as row, index}
237
+ <tr data-hidden={isNextPage(index)}>
238
+ {#each row as column}
239
+ {#if column}
240
+ <td>
241
+ {@html column}
242
+ </td>
243
+ {/if}
244
+ {/each}
245
+ </tr>
246
+ {/each}
247
+ {/if}
248
+ {@render children?.()}
249
+ </tbody>
250
+ {#if columnFilterIndexes?.length && !filteredData.length}
251
+ <tfoot>
252
+ <tr>
253
+ <td colspan={data?.[0].length} class={styles['no-results']}>
254
+ {noResultsLabel}
255
+ </td>
256
+ </tr>
257
+ </tfoot>
258
+ {/if}
259
+ </table>
260
+ </div>
261
+ {#if subText || hasPagination}
262
+ <div class={footerClasses}>
263
+ {#if subText}
264
+ <span class={styles.subtext}>{subText}</span>
265
+ {/if}
266
+ {#if hasPagination && itemsPerPage && !hasActiveFilter}
267
+ <Pagination
268
+ {...pagination}
269
+ totalPages={Math.ceil((data?.length || 0) / itemsPerPage)}
270
+ currentPage={page}
271
+ onChange={event => page = event.page}
272
+ />
273
+ {/if}
274
+ </div>
275
+ {/if}
276
+ </section>
@@ -1,3 +1,5 @@
1
+ import type { Snippet } from 'svelte'
2
+
1
3
  import type { PaginationProps } from '../Pagination/pagination'
2
4
 
3
5
  export type DataTableEventType = {
@@ -17,13 +19,13 @@ export type DataTableProps = {
17
19
  filterPlaceholder?: string
18
20
  showFilterIcon?: boolean
19
21
  noResultsLabel?: string
20
- itemsPerPage?: number | null
22
+ itemsPerPage?: number
21
23
  subText?: string
22
24
  columnToggleLabel?: string
23
25
  pagination?: PaginationProps
24
26
  data: string[][]
25
27
  hover?: boolean
26
- striped?: 'column' | 'row' | null
28
+ striped?: 'column' | 'row'
27
29
  offsetStripe?: boolean
28
30
  compact?: boolean
29
31
  maxHeight?: string
@@ -33,6 +35,7 @@ export type DataTableProps = {
33
35
 
34
36
  export type SvelteDataTableProps = {
35
37
  onFilter?: (event: DataTableEventType) => void
38
+ children?: Snippet
36
39
  } & DataTableProps
37
40
 
38
41
  export type ReactDataTableProps = {
@@ -1,15 +1,19 @@
1
1
  <script lang="ts">
2
- import type { FlexProps } from './flex'
2
+ import type { SvelteFlexProps } from './flex'
3
3
 
4
4
  import { classNames } from '../../utils/classNames'
5
5
  import { getLayoutClasses } from '../../utils/getLayoutClasses'
6
6
 
7
- export let element: FlexProps['className'] = 'div'
8
- export let gap: FlexProps['gap'] = ''
9
- export let alignment: FlexProps['alignment'] = {}
10
- export let direction: FlexProps['direction'] = ''
11
- export let wrap: FlexProps['wrap'] = ''
12
- export let className: FlexProps['className'] = ''
7
+ const {
8
+ element = 'div',
9
+ gap,
10
+ alignment,
11
+ direction,
12
+ wrap,
13
+ className,
14
+ children,
15
+ ...rest
16
+ }: SvelteFlexProps = $props()
13
17
 
14
18
  const classes = classNames([
15
19
  'flex',
@@ -17,11 +21,11 @@
17
21
  className
18
22
  ])
19
23
 
20
- const props = {
24
+ const componentProps = {
21
25
  class: classes
22
26
  }
23
27
  </script>
24
28
 
25
- <svelte:element this={element} {...props} {...$$restProps}>
26
- <slot />
29
+ <svelte:element this={element} {...componentProps} {...rest}>
30
+ {@render children?.()}
27
31
  </svelte:element>
@@ -1,3 +1,5 @@
1
+ import type { Snippet } from 'svelte'
2
+
1
3
  import type {
2
4
  Alignment,
3
5
  Direction,
@@ -16,6 +18,10 @@ export type FlexProps = {
16
18
  [key: string]: any
17
19
  }
18
20
 
21
+ export type SvelteFlexProps = {
22
+ children: Snippet
23
+ } & FlexProps
24
+
19
25
  export type ReactFlexProps = {
20
26
  Element?: keyof JSX.IntrinsicElements
21
27
  children: React.ReactNode