compote-ui 0.46.5 → 0.47.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 (23) hide show
  1. package/dist/components/combobox/combobox.svelte +99 -28
  2. package/dist/components/combobox/types.d.ts +1 -0
  3. package/dist/components/data-table-v8/index.d.ts +4 -4
  4. package/dist/components/data-table-v8/index.js +4 -4
  5. package/dist/components/data-table-v8/{data-table-column-filter.svelte → toolbar/data-table-column-filter.svelte} +6 -6
  6. package/dist/components/data-table-v8/{data-table-column-filter.svelte.d.ts → toolbar/data-table-column-filter.svelte.d.ts} +1 -1
  7. package/dist/components/data-table-v8/{data-table-column-visibility.svelte → toolbar/data-table-column-visibility.svelte} +4 -4
  8. package/dist/components/data-table-v8/{data-table-column-visibility.svelte.d.ts → toolbar/data-table-column-visibility.svelte.d.ts} +1 -1
  9. package/dist/components/data-table-v8/{data-table-search.svelte → toolbar/data-table-search.svelte} +3 -3
  10. package/dist/components/data-table-v8/{data-table-search.svelte.d.ts → toolbar/data-table-search.svelte.d.ts} +1 -1
  11. package/dist/components/data-table-v8/{data-table-virtual-rows.svelte → virtual/data-table-virtual-rows.svelte} +4 -4
  12. package/dist/components/data-table-v8/{data-table-virtual-rows.svelte.d.ts → virtual/data-table-virtual-rows.svelte.d.ts} +1 -1
  13. package/dist/components/data-table-v8/{data-table-virtualized.svelte → virtual/data-table-virtualized.svelte} +3 -3
  14. package/dist/components/data-table-v8/{data-table-virtualized.svelte.d.ts → virtual/data-table-virtualized.svelte.d.ts} +1 -1
  15. package/dist/components/data-table-v8/virtual/index.d.ts +1 -1
  16. package/dist/components/data-table-v8/virtual/index.js +1 -1
  17. package/dist/components/number-input/number-input.svelte +1 -1
  18. package/dist/components/toggle/toggle.svelte +5 -1
  19. package/dist/components/toggle-group/toggle-group-item.svelte +1 -4
  20. package/dist/components/toggle-group/toggle-group.svelte +5 -6
  21. package/package.json +1 -1
  22. /package/dist/components/data-table-v8/{data-table-toolbar.svelte → toolbar/data-table-toolbar.svelte} +0 -0
  23. /package/dist/components/data-table-v8/{data-table-toolbar.svelte.d.ts → toolbar/data-table-toolbar.svelte.d.ts} +0 -0
@@ -3,6 +3,8 @@
3
3
  import { Field } from '@ark-ui/svelte/field';
4
4
  import { useFilter } from '@ark-ui/svelte/locale';
5
5
  import { Portal } from '@ark-ui/svelte/portal';
6
+ import { createVirtualizer } from '@tanstack/svelte-virtual';
7
+ import { untrack } from 'svelte';
6
8
  import type { ComboboxProps } from './types';
7
9
  import { createListCollection, type ListItem } from '../../utils/collections';
8
10
  import { cn } from 'tailwind-variants';
@@ -18,26 +20,22 @@
18
20
  readOnly,
19
21
  multiple,
20
22
  loading = false,
23
+ virtualized = false,
21
24
  class: className,
22
25
  onValueChange,
23
26
  ...restProps
24
27
  }: ComboboxProps<T> = $props();
25
28
 
26
- // Client-side filtering state
27
29
  let filterText = $state('');
28
- const filters = useFilter({ sensitivity: 'base' });
29
30
 
30
- // Base collection only rebuilds when items prop changes
31
+ const filters = useFilter({ sensitivity: 'base' });
31
32
  const baseCollection = $derived(createListCollection(items));
32
-
33
- // Filtered view — lightweight .filter() on keystroke, full collection when empty
34
33
  const collection = $derived(
35
34
  filterText
36
35
  ? baseCollection.filter((itemString) => filters().contains(itemString, filterText))
37
36
  : baseCollection
38
37
  );
39
38
 
40
- // Handle input change — only filter on actual user typing, not on selection/clear events
41
39
  function handleInputChange(details: Combobox.InputValueChangeDetails) {
42
40
  if (details.reason === 'input-change') {
43
41
  filterText = details.inputValue;
@@ -78,6 +76,29 @@
78
76
  }
79
77
  onValueChange?.(details);
80
78
  }
79
+
80
+ let contentRef = $state<HTMLDivElement | null>(null);
81
+
82
+ const virtualizer = createVirtualizer({
83
+ get count() {
84
+ return virtualized ? collection.size : 0;
85
+ },
86
+ getScrollElement: () => contentRef,
87
+ estimateSize: () => 36,
88
+ overscan: 10
89
+ });
90
+
91
+ $effect(() => {
92
+ const count = virtualized ? collection.size : 0;
93
+ const scrollElement = contentRef;
94
+
95
+ if (!scrollElement) return;
96
+
97
+ untrack(() => {
98
+ $virtualizer.setOptions({ ...$virtualizer.options, count });
99
+ $virtualizer.measure();
100
+ });
101
+ });
81
102
  </script>
82
103
 
83
104
  <Combobox.Root
@@ -86,6 +107,9 @@
86
107
  inputValue={controlledInputValue}
87
108
  onValueChange={handleValueChange}
88
109
  onInputValueChange={handleInputChange}
110
+ scrollToIndexFn={virtualized
111
+ ? (d) => $virtualizer.scrollToIndex(d.index, { align: 'center' })
112
+ : undefined}
89
113
  openOnClick
90
114
  {multiple}
91
115
  {readOnly}
@@ -140,31 +164,78 @@
140
164
  <Portal>
141
165
  <Combobox.Positioner class="data-[state=closed]:pointer-events-none">
142
166
  <Combobox.Content
143
- class="z-200 max-h-60 min-w-(--reference-width) overflow-auto rounded-md border bg-surface-document p-1 shadow-md data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95"
167
+ class={cn(
168
+ 'z-200 min-w-(--reference-width) rounded-md border bg-surface-document p-1 shadow-md',
169
+ 'data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95',
170
+ 'data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95',
171
+ virtualized ? 'overflow-hidden' : 'max-h-60 overflow-auto'
172
+ )}
144
173
  >
145
- {#if loading}
146
- <div class="flex items-center justify-center py-4">
147
- <span
148
- class="size-5 animate-spin rounded-full border-2 border-surface-3 border-t-ink-dim"
149
- ></span>
150
- </div>
174
+ {#if virtualized}
175
+ {#if loading}
176
+ <div class="flex items-center justify-center py-4">
177
+ <span
178
+ class="size-5 animate-spin rounded-full border-2 border-surface-3 border-t-ink-dim"
179
+ ></span>
180
+ </div>
181
+ {:else if collection.size === 0}
182
+ <Combobox.Empty class="py-2 text-center text-sm text-ink-dim">
183
+ No results found
184
+ </Combobox.Empty>
185
+ {:else}
186
+ <div
187
+ bind:this={contentRef}
188
+ class="overflow-auto overscroll-contain"
189
+ style="height: min(15rem, {$virtualizer.getTotalSize()}px);"
190
+ >
191
+ <div
192
+ style="height: {$virtualizer.getTotalSize()}px; width: 100%; position: relative;"
193
+ >
194
+ {#each $virtualizer.getVirtualItems() as vItem (vItem.key)}
195
+ {@const item = collection.items[vItem.index]}
196
+ {#if item}
197
+ <Combobox.Item
198
+ {item}
199
+ aria-setsize={collection.size}
200
+ aria-posinset={vItem.index + 1}
201
+ style="position:absolute;top:0;left:0;width:100%;height:{vItem.size}px;transform:translateY({vItem.start}px)"
202
+ class="relative flex cursor-default items-center rounded-sm py-1.5 pr-8 pl-2 text-sm select-none data-disabled:pointer-events-none data-disabled:opacity-50 data-highlighted:bg-surface-1 data-[state=checked]:bg-surface-1"
203
+ >
204
+ <Combobox.ItemText>{item.label}</Combobox.ItemText>
205
+ <Combobox.ItemIndicator class="absolute right-2 items-center justify-center">
206
+ <PhCheck class="size-3.5" />
207
+ </Combobox.ItemIndicator>
208
+ </Combobox.Item>
209
+ {/if}
210
+ {/each}
211
+ </div>
212
+ </div>
213
+ {/if}
151
214
  {:else}
152
- <Combobox.Empty class="py-2 text-center text-sm text-ink-dim">
153
- No results found
154
- </Combobox.Empty>
155
- {/if}
215
+ {#if loading}
216
+ <div class="flex items-center justify-center py-4">
217
+ <span
218
+ class="size-5 animate-spin rounded-full border-2 border-surface-3 border-t-ink-dim"
219
+ ></span>
220
+ </div>
221
+ {:else}
222
+ <Combobox.Empty class="py-2 text-center text-sm text-ink-dim">
223
+ No results found
224
+ </Combobox.Empty>
225
+ {/if}
156
226
 
157
- {#each loading ? [] : collection.items as item (item.value)}
158
- <Combobox.Item
159
- {item}
160
- class="relative flex cursor-default items-center rounded-sm py-1.5 pr-8 pl-2 text-sm select-none data-disabled:pointer-events-none data-disabled:opacity-50 data-highlighted:bg-surface-1 data-[state=checked]:bg-surface-1"
161
- >
162
- <Combobox.ItemText>{item.label}</Combobox.ItemText>
163
- <Combobox.ItemIndicator class="absolute right-2 items-center justify-center">
164
- <PhCheck class="size-3.5" />
165
- </Combobox.ItemIndicator>
166
- </Combobox.Item>
167
- {/each}
227
+ {#each loading ? [] : collection.items as item (item.value)}
228
+ <Combobox.Item
229
+ {item}
230
+ class="relative flex cursor-default items-center rounded-sm py-1.5 pr-8 pl-2 text-sm select-none data-disabled:pointer-events-none data-disabled:opacity-50 data-highlighted:bg-surface-1 data-[state=checked]:bg-surface-1"
231
+ >
232
+ <Combobox.ItemText>{item.label}</Combobox.ItemText>
233
+ <Combobox.ItemIndicator class="absolute right-2 items-center justify-center">
234
+ <PhCheck class="size-3.5" />
235
+ </Combobox.ItemIndicator>
236
+ </Combobox.Item>
237
+ {/each}
238
+ {/if}
168
239
  </Combobox.Content>
169
240
  </Combobox.Positioner>
170
241
  </Portal>
@@ -9,5 +9,6 @@ export interface ComboboxProps<T extends ListItem> extends Omit<ComboboxRootBase
9
9
  multiple?: boolean;
10
10
  layout?: 'vertical' | 'horizontal';
11
11
  loading?: boolean;
12
+ virtualized?: boolean;
12
13
  class?: string;
13
14
  }
@@ -3,10 +3,10 @@ export { createTable } from './create-table.svelte';
3
3
  export { renderComponent, renderSnippet } from './render-helpers';
4
4
  export { default as FlexRender } from './flex-render.svelte';
5
5
  export { default as Root } from './data-table.svelte';
6
- export { default as Toolbar } from './data-table-toolbar.svelte';
7
6
  export { default as Title } from './data-table-title.svelte';
8
- export { default as ColumnVisibility } from './data-table-column-visibility.svelte';
9
- export { default as ColumnFilter } from './data-table-column-filter.svelte';
10
- export { default as Search } from './data-table-search.svelte';
7
+ export { default as Toolbar } from './toolbar/data-table-toolbar.svelte';
8
+ export { default as ColumnFilter } from './toolbar/data-table-column-filter.svelte';
9
+ export { default as ColumnVisibility } from './toolbar/data-table-column-visibility.svelte';
10
+ export { default as Search } from './toolbar/data-table-search.svelte';
11
11
  export type { CreateDataTableOptions, DataTableInstance } from './create-table.svelte';
12
12
  export type { DataTableAlign, DataTableAccessorFnColumn, DataTableAccessorKeyColumn, DataTableColumn, DataTableColumnBase, DataTableColumnOptions, DataTableColumnType, DataTableCellPropsResolver, DataTableCellRenderProps, DataTableGroupColumn, DataTableLeafColumnBase, DataTableLeafColumn } from './types';
@@ -3,8 +3,8 @@ export { createTable } from './create-table.svelte';
3
3
  export { renderComponent, renderSnippet } from './render-helpers';
4
4
  export { default as FlexRender } from './flex-render.svelte';
5
5
  export { default as Root } from './data-table.svelte';
6
- export { default as Toolbar } from './data-table-toolbar.svelte';
7
6
  export { default as Title } from './data-table-title.svelte';
8
- export { default as ColumnVisibility } from './data-table-column-visibility.svelte';
9
- export { default as ColumnFilter } from './data-table-column-filter.svelte';
10
- export { default as Search } from './data-table-search.svelte';
7
+ export { default as Toolbar } from './toolbar/data-table-toolbar.svelte';
8
+ export { default as ColumnFilter } from './toolbar/data-table-column-filter.svelte';
9
+ export { default as ColumnVisibility } from './toolbar/data-table-column-visibility.svelte';
10
+ export { default as Search } from './toolbar/data-table-search.svelte';
@@ -1,13 +1,13 @@
1
1
  <script lang="ts" generics="T extends RowData">
2
2
  import { onDestroy } from 'svelte';
3
3
  import type { Column, RowData } from '@tanstack/table-core';
4
- import * as Popover from '../popover';
5
- import * as ScrollArea from '../scroll-area';
6
- import Checkbox from '../checkbox/checkbox.svelte';
4
+ import * as Popover from '../../popover';
5
+ import * as ScrollArea from '../../scroll-area';
6
+ import Checkbox from '../../checkbox/checkbox.svelte';
7
7
  import { cn } from 'tailwind-variants';
8
- import { getReactiveTableState, type DataTableInstance } from './data-table-utils';
9
- import NumberInput from '../number-input/number-input.svelte';
10
- import * as Field from '../field';
8
+ import { getReactiveTableState, type DataTableInstance } from '../data-table-utils';
9
+ import NumberInput from '../../number-input/number-input.svelte';
10
+ import * as Field from '../../field';
11
11
 
12
12
  type Props = {
13
13
  table: DataTableInstance<T>;
@@ -1,5 +1,5 @@
1
1
  import type { RowData } from '@tanstack/table-core';
2
- import { type DataTableInstance } from './data-table-utils';
2
+ import { type DataTableInstance } from '../data-table-utils';
3
3
  declare function $$render<T extends RowData>(): {
4
4
  props: {
5
5
  table: DataTableInstance<T>;
@@ -1,9 +1,9 @@
1
1
  <script lang="ts" generics="T extends RowData">
2
2
  import type { RowData } from '@tanstack/table-core';
3
- import * as Popover from '../popover';
4
- import * as ScrollArea from '../scroll-area';
5
- import Checkbox from '../checkbox/checkbox.svelte';
6
- import { getReactiveTableState, type DataTableInstance } from './data-table-utils';
3
+ import * as Popover from '../../popover';
4
+ import * as ScrollArea from '../../scroll-area';
5
+ import Checkbox from '../../checkbox/checkbox.svelte';
6
+ import { getReactiveTableState, type DataTableInstance } from '../data-table-utils';
7
7
 
8
8
  type Props = {
9
9
  table: DataTableInstance<T>;
@@ -1,5 +1,5 @@
1
1
  import type { RowData } from '@tanstack/table-core';
2
- import { type DataTableInstance } from './data-table-utils';
2
+ import { type DataTableInstance } from '../data-table-utils';
3
3
  declare function $$render<T extends RowData>(): {
4
4
  props: {
5
5
  table: DataTableInstance<T>;
@@ -2,9 +2,9 @@
2
2
  import { onDestroy } from 'svelte';
3
3
  import type { RowData } from '@tanstack/table-core';
4
4
  import { cn, type ClassValue } from 'tailwind-variants';
5
- import { PhMagnifyingGlass, PhX } from '../../icons';
6
- import * as Field from '../field';
7
- import { getReactiveTableState, type DataTableInstance } from './data-table-utils';
5
+ import { PhMagnifyingGlass, PhX } from '../../../icons';
6
+ import * as Field from '../../field';
7
+ import { getReactiveTableState, type DataTableInstance } from '../data-table-utils';
8
8
 
9
9
  type Props = {
10
10
  table: DataTableInstance<T>;
@@ -1,6 +1,6 @@
1
1
  import type { RowData } from '@tanstack/table-core';
2
2
  import { type ClassValue } from 'tailwind-variants';
3
- import { type DataTableInstance } from './data-table-utils';
3
+ import { type DataTableInstance } from '../data-table-utils';
4
4
  declare function $$render<T extends RowData>(): {
5
5
  props: {
6
6
  table: DataTableInstance<T>;
@@ -3,9 +3,9 @@
3
3
  import { createVirtualizer } from '@tanstack/svelte-virtual';
4
4
  import { untrack } from 'svelte';
5
5
  import { cn } from 'tailwind-variants';
6
- import { PhArrowSquareOut, PhCheck, PhX } from '../../icons';
7
- import type { DataTableInstance } from './data-table-utils';
8
- import FlexRender from './flex-render.svelte';
6
+ import { PhArrowSquareOut, PhCheck, PhX } from '../../../icons';
7
+ import type { DataTableInstance } from '../data-table-utils';
8
+ import FlexRender from '../flex-render.svelte';
9
9
  import {
10
10
  alignClass,
11
11
  getBooleanCellValue,
@@ -20,7 +20,7 @@
20
20
  virtualColumnSizeStyle,
21
21
  virtualGrowColumnSizeStyle,
22
22
  virtualSelectionColumnSizeStyle
23
- } from './data-table-utils';
23
+ } from '../data-table-utils';
24
24
 
25
25
  type Props = {
26
26
  rows: Row<T>[];
@@ -1,5 +1,5 @@
1
1
  import type { Row, RowData } from '@tanstack/table-core';
2
- import type { DataTableInstance } from './data-table-utils';
2
+ import type { DataTableInstance } from '../data-table-utils';
3
3
  declare function $$render<T extends RowData>(): {
4
4
  props: {
5
5
  rows: Row<T>[];
@@ -2,15 +2,15 @@
2
2
  import type { RowData } from '@tanstack/table-core';
3
3
  import type { HTMLAttributes } from 'svelte/elements';
4
4
  import { cn, type ClassValue } from 'tailwind-variants';
5
- import type { DataTableInstance } from './data-table-utils';
6
- import DataTableHead from './data-table-head.svelte';
5
+ import type { DataTableInstance } from '../data-table-utils';
6
+ import DataTableHead from '../data-table-head.svelte';
7
7
  import DataTableVirtualRows from './data-table-virtual-rows.svelte';
8
8
  import {
9
9
  getAllRowsSelectionState,
10
10
  getReactiveTableState,
11
11
  getSelectedRowCount,
12
12
  tableSizeStyle
13
- } from './data-table-utils';
13
+ } from '../data-table-utils';
14
14
 
15
15
  type Props = Omit<HTMLAttributes<HTMLDivElement>, 'class'> & {
16
16
  table: DataTableInstance<T>;
@@ -1,7 +1,7 @@
1
1
  import type { RowData } from '@tanstack/table-core';
2
2
  import type { HTMLAttributes } from 'svelte/elements';
3
3
  import { type ClassValue } from 'tailwind-variants';
4
- import type { DataTableInstance } from './data-table-utils';
4
+ import type { DataTableInstance } from '../data-table-utils';
5
5
  declare function $$render<T extends RowData>(): {
6
6
  props: Omit<HTMLAttributes<HTMLDivElement>, "class"> & {
7
7
  table: DataTableInstance<T>;
@@ -1,3 +1,3 @@
1
- export { default as Root } from '../data-table-virtualized.svelte';
1
+ export { default as Root } from './data-table-virtualized.svelte';
2
2
  export { ColumnFilter, ColumnVisibility, FlexRender, Search, Title, Toolbar, createDataTableColumnHelper, createTable, renderComponent, renderSnippet } from '../index';
3
3
  export type { CreateDataTableOptions, DataTableAccessorFnColumn, DataTableAccessorKeyColumn, DataTableAlign, DataTableCellPropsResolver, DataTableCellRenderProps, DataTableColumn, DataTableColumnBase, DataTableColumnOptions, DataTableColumnType, DataTableGroupColumn, DataTableInstance, DataTableLeafColumn, DataTableLeafColumnBase } from '../index';
@@ -1,2 +1,2 @@
1
- export { default as Root } from '../data-table-virtualized.svelte';
1
+ export { default as Root } from './data-table-virtualized.svelte';
2
2
  export { ColumnFilter, ColumnVisibility, FlexRender, Search, Title, Toolbar, createDataTableColumnHelper, createTable, renderComponent, renderSnippet } from '../index';
@@ -28,7 +28,7 @@
28
28
  {...restProps}
29
29
  allowMouseWheel
30
30
  locale={locale().locale}
31
- value={value?.toString()}
31
+ value={value != null ? new Intl.NumberFormat(locale().locale, { useGrouping: false, maximumFractionDigits: 20 }).format(value) : undefined}
32
32
  readOnly={readonly}
33
33
  onValueChange={(valueChangeDetails) => {
34
34
  onValueChange?.(valueChangeDetails);
@@ -13,6 +13,10 @@
13
13
  }: ToggleProps = $props();
14
14
  </script>
15
15
 
16
- <ArkToggle.Root {...rootProps} bind:pressed class={toggle({ size, icon, class: className as never })}>
16
+ <ArkToggle.Root
17
+ {...rootProps}
18
+ bind:pressed
19
+ class={toggle({ size, icon, class: className as never })}
20
+ >
17
21
  {@render children?.()}
18
22
  </ArkToggle.Root>
@@ -22,9 +22,6 @@
22
22
  );
23
23
  </script>
24
24
 
25
- <ToggleGroup.Item
26
- {...rest}
27
- class={itemClass}
28
- >
25
+ <ToggleGroup.Item {...rest} class={itemClass}>
29
26
  {@render children?.()}
30
27
  </ToggleGroup.Item>
@@ -36,7 +36,10 @@
36
36
 
37
37
  const rootClass = $derived(
38
38
  variant === 'ghost'
39
- ? cn('inline-flex w-fit gap-1 data-[orientation=vertical]:flex-col data-[orientation=vertical]:gap-1', className)
39
+ ? cn(
40
+ 'inline-flex w-fit gap-1 data-[orientation=vertical]:flex-col data-[orientation=vertical]:gap-1',
41
+ className
42
+ )
40
43
  : cn(
41
44
  'inline-flex w-fit rounded border border-border data-[orientation=vertical]:flex-col [&>:not([hidden])~:not([hidden])]:border-border data-[orientation=horizontal]:[&>:not([hidden])~:not([hidden])]:border-s data-[orientation=horizontal]:[&>:not([hidden])~:not([hidden])]:border-e-0 data-[orientation=vertical]:[&>:not([hidden])~:not([hidden])]:border-t data-[orientation=vertical]:[&>:not([hidden])~:not([hidden])]:border-b-0',
42
45
  className
@@ -44,10 +47,6 @@
44
47
  );
45
48
  </script>
46
49
 
47
- <ToggleGroup.Root
48
- {...rootProps}
49
- bind:value
50
- class={rootClass}
51
- >
50
+ <ToggleGroup.Root {...rootProps} bind:value class={rootClass}>
52
51
  {@render children?.()}
53
52
  </ToggleGroup.Root>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "compote-ui",
3
- "version": "0.46.5",
3
+ "version": "0.47.1",
4
4
  "license": "MIT",
5
5
  "scripts": {
6
6
  "dev": "vite dev --open",