@ims360/svelte-ivory 0.0.49 → 0.0.51
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.
- package/dist/components/inputs/FullscreenDropzone.svelte +85 -0
- package/dist/components/inputs/FullscreenDropzone.svelte.d.ts +10 -0
- package/dist/components/inputs/FullscreenDropzone.svelte.d.ts.map +1 -0
- package/dist/components/inputs/index.d.ts +2 -0
- package/dist/components/inputs/index.d.ts.map +1 -0
- package/dist/components/inputs/index.js +1 -0
- package/dist/components/layout/tooltip/Tooltip.svelte +0 -1
- package/dist/components/layout/tooltip/Tooltip.svelte.d.ts.map +1 -1
- package/dist/components/table/Column.svelte +1 -1
- package/dist/components/table/Table.svelte +20 -10
- package/dist/components/table/Table.svelte.d.ts.map +1 -1
- package/dist/components/table/search.svelte.d.ts +2 -1
- package/dist/components/table/search.svelte.d.ts.map +1 -1
- package/dist/components/table/search.svelte.js +17 -6
- package/dist/utils/functions/debouncedValue.svelte.d.ts +5 -0
- package/dist/utils/functions/debouncedValue.svelte.d.ts.map +1 -0
- package/dist/utils/functions/debouncedValue.svelte.js +21 -0
- package/dist/utils/functions/index.d.ts +1 -0
- package/dist/utils/functions/index.d.ts.map +1 -1
- package/dist/utils/functions/index.js +1 -0
- package/package.json +5 -1
- package/src/lib/components/inputs/FullscreenDropzone.svelte +85 -0
- package/src/lib/components/inputs/index.ts +4 -0
- package/src/lib/components/layout/tooltip/Tooltip.svelte +0 -1
- package/src/lib/components/table/Column.svelte +1 -1
- package/src/lib/components/table/Table.svelte +20 -10
- package/src/lib/components/table/search.svelte.ts +20 -7
- package/src/lib/utils/functions/debouncedValue.svelte.ts +20 -0
- package/src/lib/utils/functions/index.ts +1 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
<script lang="ts" module>
|
|
2
|
+
import { FileUp } from '@lucide/svelte';
|
|
3
|
+
import type { Snippet } from 'svelte';
|
|
4
|
+
import { scale } from 'svelte/transition';
|
|
5
|
+
import { HiddenBackground, Portal } from '../layout';
|
|
6
|
+
|
|
7
|
+
export interface FullscreenDropzoneProps {
|
|
8
|
+
ondrop: (files: File[]) => void;
|
|
9
|
+
disabled: boolean;
|
|
10
|
+
children?: Snippet;
|
|
11
|
+
}
|
|
12
|
+
</script>
|
|
13
|
+
|
|
14
|
+
<script lang="ts">
|
|
15
|
+
let { ondrop, disabled, children = defaultChildren }: FullscreenDropzoneProps = $props();
|
|
16
|
+
|
|
17
|
+
let open = $state(false);
|
|
18
|
+
|
|
19
|
+
// This counter correctly handles dragenter/dragleave events as the
|
|
20
|
+
// cursor moves over different elements within the window.
|
|
21
|
+
let counter = $state(0);
|
|
22
|
+
|
|
23
|
+
function handleDragEnter(e: DragEvent) {
|
|
24
|
+
if (disabled) return;
|
|
25
|
+
e.preventDefault();
|
|
26
|
+
// We only want to react to file drags.
|
|
27
|
+
if (e.dataTransfer?.types.includes('Files')) {
|
|
28
|
+
counter++;
|
|
29
|
+
open = true;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function handleDragLeave(e: DragEvent) {
|
|
34
|
+
e.preventDefault();
|
|
35
|
+
counter = Math.max(counter - 1, 0);
|
|
36
|
+
// Only close the overlay when the counter is 0, meaning the cursor
|
|
37
|
+
// has truly left the window.
|
|
38
|
+
if (counter === 0) {
|
|
39
|
+
open = false;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function handleDrop(e: DragEvent) {
|
|
44
|
+
// Prevent the browser from opening the file.
|
|
45
|
+
e.preventDefault();
|
|
46
|
+
|
|
47
|
+
// Reset state and close the overlay.
|
|
48
|
+
open = false;
|
|
49
|
+
counter = 0;
|
|
50
|
+
|
|
51
|
+
const files = Array.from(e.dataTransfer?.files ?? []);
|
|
52
|
+
|
|
53
|
+
if (files.length > 0) {
|
|
54
|
+
ondrop(files);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
</script>
|
|
58
|
+
|
|
59
|
+
<svelte:window
|
|
60
|
+
ondragenter={handleDragEnter}
|
|
61
|
+
ondragleave={handleDragLeave}
|
|
62
|
+
ondrop={handleDrop}
|
|
63
|
+
ondragover={(e) => e.preventDefault()}
|
|
64
|
+
/>
|
|
65
|
+
|
|
66
|
+
{#if open}
|
|
67
|
+
<Portal>
|
|
68
|
+
<HiddenBackground>
|
|
69
|
+
{@render children()}
|
|
70
|
+
</HiddenBackground>
|
|
71
|
+
</Portal>
|
|
72
|
+
{/if}
|
|
73
|
+
|
|
74
|
+
{#snippet defaultChildren()}
|
|
75
|
+
<div
|
|
76
|
+
class="border-surface-400 text-surface-50 relative flex flex-col items-center gap-4 p-12 text-xl"
|
|
77
|
+
in:scale|global={{ duration: 100, delay: 100 }}
|
|
78
|
+
out:scale|global={{ duration: 100 }}
|
|
79
|
+
>
|
|
80
|
+
<div
|
|
81
|
+
class="absolute top-0 left-0 h-full w-full rounded-xl bg-black/75 opacity-50 blur-lg"
|
|
82
|
+
></div>
|
|
83
|
+
<FileUp size={40} />
|
|
84
|
+
</div>
|
|
85
|
+
{/snippet}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
export interface FullscreenDropzoneProps {
|
|
3
|
+
ondrop: (files: File[]) => void;
|
|
4
|
+
disabled: boolean;
|
|
5
|
+
children?: Snippet;
|
|
6
|
+
}
|
|
7
|
+
declare const FullscreenDropzone: import("svelte").Component<FullscreenDropzoneProps, {}, "">;
|
|
8
|
+
type FullscreenDropzone = ReturnType<typeof FullscreenDropzone>;
|
|
9
|
+
export default FullscreenDropzone;
|
|
10
|
+
//# sourceMappingURL=FullscreenDropzone.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FullscreenDropzone.svelte.d.ts","sourceRoot":"","sources":["../../../src/lib/components/inputs/FullscreenDropzone.svelte.ts"],"names":[],"mappings":"AAII,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAItC,MAAM,WAAW,uBAAuB;IACpC,MAAM,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,IAAI,CAAC;IAChC,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACtB;AAoEL,QAAA,MAAM,kBAAkB,6DAAwC,CAAC;AACjE,KAAK,kBAAkB,GAAG,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAChE,eAAe,kBAAkB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/components/inputs/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,OAAO,IAAI,kBAAkB,EAC7B,KAAK,uBAAuB,EAC/B,MAAM,6BAA6B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as FullscreenDropzone } from './FullscreenDropzone.svelte';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Tooltip.svelte.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/layout/tooltip/Tooltip.svelte.ts"],"names":[],"mappings":"AAII,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,KAAK,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAErE,OAAgB,EAAE,KAAK,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAG3E,MAAM,WAAW,YAAY;IACzB,OAAO,CAAC,EAAE,iBAAiB,CAAC,WAAW,CAAC,CAAC;IACzC,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,iCAAiC;IACjC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;IAC1B,sCAAsC;IACtC,YAAY,CAAC,EAAE,UAAU,CAAC;IAC1B,2EAA2E;IAC3E,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,SAAS,CAAC,EAAE,gBAAgB,CAAC;CAChC;
|
|
1
|
+
{"version":3,"file":"Tooltip.svelte.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/layout/tooltip/Tooltip.svelte.ts"],"names":[],"mappings":"AAII,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,KAAK,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAErE,OAAgB,EAAE,KAAK,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAG3E,MAAM,WAAW,YAAY;IACzB,OAAO,CAAC,EAAE,iBAAiB,CAAC,WAAW,CAAC,CAAC;IACzC,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,iCAAiC;IACjC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;IAC1B,sCAAsC;IACtC,YAAY,CAAC,EAAE,UAAU,CAAC;IAC1B,2EAA2E;IAC3E,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,SAAS,CAAC,EAAE,gBAAgB,CAAC;CAChC;AA4DL,kEAAkE;AAClE,QAAA,MAAM,OAAO,kDAAwC,CAAC;AACtD,KAAK,OAAO,GAAG,UAAU,CAAC,OAAO,OAAO,CAAC,CAAC;AAC1C,eAAe,OAAO,CAAC"}
|
|
@@ -75,7 +75,7 @@
|
|
|
75
75
|
class={twMerge(
|
|
76
76
|
clsx([
|
|
77
77
|
'box-border flex h-full shrink-0 flex-row items-center justify-start gap-1 truncate',
|
|
78
|
-
column.width !== 0 && '
|
|
78
|
+
column.width !== 0 && 'border-r-[calc(var(--spacing)_*_2)] border-transparent',
|
|
79
79
|
defaultClasses,
|
|
80
80
|
clazz
|
|
81
81
|
])
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
import ColumnHead from './ColumnHead.svelte';
|
|
11
11
|
import { treeWalker } from './controller';
|
|
12
12
|
import Row from './Row.svelte';
|
|
13
|
-
import {
|
|
13
|
+
import { applyHidden, searchTable } from './search.svelte';
|
|
14
14
|
import VirtualList from './VirtualList.svelte';
|
|
15
15
|
|
|
16
16
|
export interface TableProps<T extends TableRow<T>> {
|
|
@@ -88,25 +88,24 @@
|
|
|
88
88
|
else expanded.add(id);
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
-
let
|
|
92
|
-
let prevSearch = $state('');
|
|
93
|
-
|
|
91
|
+
let hidden = $state(new SvelteSet<string>());
|
|
94
92
|
const searchResult = $derived.by(() => {
|
|
95
93
|
if (!search)
|
|
96
94
|
return {
|
|
97
95
|
filteredData: data,
|
|
98
96
|
isSearching: false
|
|
99
97
|
};
|
|
100
|
-
const query = search.term.trim();
|
|
101
|
-
// Note: We only use the 'filteredData' part of the search result here.
|
|
102
|
-
const { hidden } = searchData(data, query, search.matches);
|
|
103
98
|
return {
|
|
104
|
-
filteredData:
|
|
99
|
+
filteredData: applyHidden(structuredClone(data), hidden),
|
|
105
100
|
isSearching: true
|
|
106
101
|
};
|
|
107
102
|
});
|
|
108
103
|
const results = $derived(treeWalker({ data: searchResult.filteredData, expanded }));
|
|
109
104
|
|
|
105
|
+
let expandedBeforeSearch = $state<SvelteSet<string> | null>(null);
|
|
106
|
+
let prevSearch = $state('');
|
|
107
|
+
|
|
108
|
+
// updates expanded and hidden states
|
|
110
109
|
$effect(() => {
|
|
111
110
|
if (!search) return;
|
|
112
111
|
const currentSearch = search.term.trim();
|
|
@@ -117,8 +116,13 @@
|
|
|
117
116
|
if (!wasSearching && isSearching) {
|
|
118
117
|
// Save the current expansion state before overwriting it.
|
|
119
118
|
expandedBeforeSearch = untrack(() => new SvelteSet(expanded));
|
|
120
|
-
const { expanded: searchExpanded } =
|
|
119
|
+
const { expanded: searchExpanded, hidden: searchHidden } = searchTable(
|
|
120
|
+
data,
|
|
121
|
+
currentSearch,
|
|
122
|
+
search.matches
|
|
123
|
+
);
|
|
121
124
|
expanded = searchExpanded; // Set the initial expansion for the search.
|
|
125
|
+
hidden = searchHidden;
|
|
122
126
|
}
|
|
123
127
|
|
|
124
128
|
// Transition: Searching -> Not Searching
|
|
@@ -127,13 +131,19 @@
|
|
|
127
131
|
if (expandedBeforeSearch) {
|
|
128
132
|
expanded = expandedBeforeSearch;
|
|
129
133
|
expandedBeforeSearch = null;
|
|
134
|
+
hidden = new SvelteSet<string>();
|
|
130
135
|
}
|
|
131
136
|
}
|
|
132
137
|
|
|
133
138
|
// Transition: Searching -> Searching (different query)
|
|
134
139
|
if (wasSearching && isSearching && currentSearch !== prevSearch) {
|
|
135
|
-
const { expanded: searchExpanded } =
|
|
140
|
+
const { expanded: searchExpanded, hidden: searchHidden } = searchTable(
|
|
141
|
+
data,
|
|
142
|
+
currentSearch,
|
|
143
|
+
search.matches
|
|
144
|
+
);
|
|
136
145
|
expanded = searchExpanded; // Update the expansion for the new search.
|
|
146
|
+
hidden = searchHidden;
|
|
137
147
|
}
|
|
138
148
|
|
|
139
149
|
prevSearch = currentSearch;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Table.svelte.d.ts","sourceRoot":"","sources":["../../../src/lib/components/table/Table.svelte.ts"],"names":[],"mappings":"AAKI,OAAO,EAAmC,KAAK,OAAO,EAAE,MAAM,QAAQ,CAAC;AACvE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAE9C,OAAO,EAA6B,KAAK,QAAQ,EAAE,MAAM,GAAG,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,KAAK,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAOhF,MAAM,WAAW,UAAU,CAAC,CAAC,SAAS,QAAQ,CAAC,CAAC,CAAC;IAC7C,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,IAAI,EAAE,CAAC,EAAE,CAAC;IACV,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,IAAI,CAAC;IAC3B,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,MAAM,GAAG,SAAS,CAAC;IACtC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uBAAuB;IACvB,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC;QAAE,GAAG,EAAE,CAAC,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAAC;IACvE,iDAAiD;IACjD,WAAW,CAAC,EAAE,OAAO,CAAC,CAAC;QAAE,GAAG,EAAE,CAAC,CAAA;KAAE,CAAC,CAAC,CAAC;IACpC,QAAQ,CAAC,EAAE,UAAU,CAAC;IACtB,WAAW,CAAC,EAAE,UAAU,CAAC;IACzB,MAAM,CAAC,EAAE;QACL,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,OAAO,CAAC;KAChC,CAAC;IACF;;OAEG;IACH,SAAS,CAAC,EAAE,gBAAgB,EAAE,CAAC;IAC/B,QAAQ,CAAC,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC;IAC7B;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,sEAAsE;IACtE,YAAY,CAAC,EAAE,MAAM,CAAC;CACzB;AAGD,MAAM,MAAM,YAAY,CAAC,CAAC,SAAS,QAAQ,CAAC,CAAC,CAAC,IAAI;IAC9C,QAAQ,CAAC,cAAc,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,gBAAgB,CAAC;IACpE,QAAQ,CAAC,eAAe,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/C,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC9B,CAAC;AAMF,wBAAgB,eAAe,CAAC,CAAC,SAAS,QAAQ,CAAC,CAAC,CAAC,KAAK,YAAY,CAAC,CAAC,CAAC,CAExE;AAIH,iBAAS,QAAQ,CAAC,CAAC,SAAS,QAAQ,CAAC,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"Table.svelte.d.ts","sourceRoot":"","sources":["../../../src/lib/components/table/Table.svelte.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { SvelteSet } from 'svelte/reactivity';
|
|
2
2
|
import type { TableRow } from '.';
|
|
3
3
|
/** collapses everything that doesnt match the searchString, expands direct search hit */
|
|
4
|
-
export declare const
|
|
4
|
+
export declare const searchTable: <T extends TableRow<T>>(nodes: T[], searchString: string, stringsMatch: (node: T, searchTerm: string) => boolean) => {
|
|
5
5
|
hidden: SvelteSet<string>;
|
|
6
6
|
expanded: SvelteSet<string>;
|
|
7
7
|
};
|
|
8
|
+
export declare function applyHidden<T extends TableRow<T>>(data: T[], hidden: SvelteSet<string>): T[];
|
|
8
9
|
//# sourceMappingURL=search.svelte.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search.svelte.d.ts","sourceRoot":"","sources":["../../../src/lib/components/table/search.svelte.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,GAAG,CAAC;AAElC,yFAAyF;AACzF,eAAO,MAAM,
|
|
1
|
+
{"version":3,"file":"search.svelte.d.ts","sourceRoot":"","sources":["../../../src/lib/components/table/search.svelte.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,GAAG,CAAC;AAElC,yFAAyF;AACzF,eAAO,MAAM,WAAW,GAAI,CAAC,SAAS,QAAQ,CAAC,CAAC,CAAC,EAC7C,OAAO,CAAC,EAAE,EACV,cAAc,MAAM,EACpB,cAAc,CAAC,IAAI,EAAE,CAAC,EAAE,UAAU,EAAE,MAAM,KAAK,OAAO;;;CA2BzD,CAAC;AAEF,wBAAgB,WAAW,CAAC,CAAC,SAAS,QAAQ,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAU5F"}
|
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
import { SvelteSet } from 'svelte/reactivity';
|
|
2
2
|
/** collapses everything that doesnt match the searchString, expands direct search hit */
|
|
3
|
-
export const
|
|
3
|
+
export const searchTable = (nodes, searchString, stringsMatch) => {
|
|
4
4
|
const search = searchString.trim().toLowerCase();
|
|
5
5
|
const hidden = new SvelteSet();
|
|
6
6
|
const expanded = new SvelteSet();
|
|
7
7
|
function nodeMatches(node, childOfMatch = false) {
|
|
8
8
|
const matches = stringsMatch(node, search);
|
|
9
|
-
let
|
|
9
|
+
let hasMatchingChild = false;
|
|
10
10
|
for (const child of node.children || []) {
|
|
11
11
|
const childMatches = nodeMatches(child, matches || childOfMatch);
|
|
12
12
|
if (childMatches)
|
|
13
|
-
|
|
13
|
+
hasMatchingChild = true;
|
|
14
14
|
}
|
|
15
|
-
if (
|
|
15
|
+
if (hasMatchingChild) {
|
|
16
16
|
expanded.add(node.id);
|
|
17
17
|
}
|
|
18
|
-
else if (!
|
|
18
|
+
else if (!matches) {
|
|
19
19
|
hidden.add(node.id);
|
|
20
20
|
}
|
|
21
|
-
return matches ||
|
|
21
|
+
return matches || hasMatchingChild;
|
|
22
22
|
}
|
|
23
23
|
nodes.forEach((n) => nodeMatches(n));
|
|
24
24
|
return {
|
|
@@ -26,3 +26,14 @@ export const searchData = (nodes, searchString, stringsMatch) => {
|
|
|
26
26
|
expanded
|
|
27
27
|
};
|
|
28
28
|
};
|
|
29
|
+
export function applyHidden(data, hidden) {
|
|
30
|
+
const results = [];
|
|
31
|
+
for (const node of data) {
|
|
32
|
+
if (hidden.has(node.id))
|
|
33
|
+
continue;
|
|
34
|
+
if (node.children)
|
|
35
|
+
node.children = applyHidden(node.children, hidden);
|
|
36
|
+
results.push(node);
|
|
37
|
+
}
|
|
38
|
+
return results;
|
|
39
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"debouncedValue.svelte.d.ts","sourceRoot":"","sources":["../../../src/lib/utils/functions/debouncedValue.svelte.ts"],"names":[],"mappings":"AAAA,wBAAgB,oBAAoB,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;aAKpC,CAAC;;EAc3B"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export function createDebouncedValue(delay, value) {
|
|
2
|
+
let current = $state(value);
|
|
3
|
+
let debounced = $state(value);
|
|
4
|
+
let timeout;
|
|
5
|
+
return {
|
|
6
|
+
set current(value) {
|
|
7
|
+
current = value;
|
|
8
|
+
if (timeout)
|
|
9
|
+
clearTimeout(timeout);
|
|
10
|
+
timeout = setTimeout(() => {
|
|
11
|
+
debounced = value;
|
|
12
|
+
}, delay);
|
|
13
|
+
},
|
|
14
|
+
get current() {
|
|
15
|
+
return current;
|
|
16
|
+
},
|
|
17
|
+
get debounced() {
|
|
18
|
+
return debounced;
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/utils/functions/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/utils/functions/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ims360/svelte-ivory",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.51",
|
|
4
4
|
"keywords": [
|
|
5
5
|
"svelte"
|
|
6
6
|
],
|
|
@@ -34,6 +34,10 @@
|
|
|
34
34
|
"types": "./dist/components/toast/index.d.ts",
|
|
35
35
|
"svelte": "./dist/components/toast/index.js"
|
|
36
36
|
},
|
|
37
|
+
"./components/inputs": {
|
|
38
|
+
"types": "./dist/components/inputs/index.d.ts",
|
|
39
|
+
"svelte": "./dist/components/inputs/index.js"
|
|
40
|
+
},
|
|
37
41
|
"./utils/actions": {
|
|
38
42
|
"types": "./dist/utils/actions/index.d.ts",
|
|
39
43
|
"svelte": "./dist/utils/actions/index.js"
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
<script lang="ts" module>
|
|
2
|
+
import { FileUp } from '@lucide/svelte';
|
|
3
|
+
import type { Snippet } from 'svelte';
|
|
4
|
+
import { scale } from 'svelte/transition';
|
|
5
|
+
import { HiddenBackground, Portal } from '../layout';
|
|
6
|
+
|
|
7
|
+
export interface FullscreenDropzoneProps {
|
|
8
|
+
ondrop: (files: File[]) => void;
|
|
9
|
+
disabled: boolean;
|
|
10
|
+
children?: Snippet;
|
|
11
|
+
}
|
|
12
|
+
</script>
|
|
13
|
+
|
|
14
|
+
<script lang="ts">
|
|
15
|
+
let { ondrop, disabled, children = defaultChildren }: FullscreenDropzoneProps = $props();
|
|
16
|
+
|
|
17
|
+
let open = $state(false);
|
|
18
|
+
|
|
19
|
+
// This counter correctly handles dragenter/dragleave events as the
|
|
20
|
+
// cursor moves over different elements within the window.
|
|
21
|
+
let counter = $state(0);
|
|
22
|
+
|
|
23
|
+
function handleDragEnter(e: DragEvent) {
|
|
24
|
+
if (disabled) return;
|
|
25
|
+
e.preventDefault();
|
|
26
|
+
// We only want to react to file drags.
|
|
27
|
+
if (e.dataTransfer?.types.includes('Files')) {
|
|
28
|
+
counter++;
|
|
29
|
+
open = true;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function handleDragLeave(e: DragEvent) {
|
|
34
|
+
e.preventDefault();
|
|
35
|
+
counter = Math.max(counter - 1, 0);
|
|
36
|
+
// Only close the overlay when the counter is 0, meaning the cursor
|
|
37
|
+
// has truly left the window.
|
|
38
|
+
if (counter === 0) {
|
|
39
|
+
open = false;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function handleDrop(e: DragEvent) {
|
|
44
|
+
// Prevent the browser from opening the file.
|
|
45
|
+
e.preventDefault();
|
|
46
|
+
|
|
47
|
+
// Reset state and close the overlay.
|
|
48
|
+
open = false;
|
|
49
|
+
counter = 0;
|
|
50
|
+
|
|
51
|
+
const files = Array.from(e.dataTransfer?.files ?? []);
|
|
52
|
+
|
|
53
|
+
if (files.length > 0) {
|
|
54
|
+
ondrop(files);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
</script>
|
|
58
|
+
|
|
59
|
+
<svelte:window
|
|
60
|
+
ondragenter={handleDragEnter}
|
|
61
|
+
ondragleave={handleDragLeave}
|
|
62
|
+
ondrop={handleDrop}
|
|
63
|
+
ondragover={(e) => e.preventDefault()}
|
|
64
|
+
/>
|
|
65
|
+
|
|
66
|
+
{#if open}
|
|
67
|
+
<Portal>
|
|
68
|
+
<HiddenBackground>
|
|
69
|
+
{@render children()}
|
|
70
|
+
</HiddenBackground>
|
|
71
|
+
</Portal>
|
|
72
|
+
{/if}
|
|
73
|
+
|
|
74
|
+
{#snippet defaultChildren()}
|
|
75
|
+
<div
|
|
76
|
+
class="border-surface-400 text-surface-50 relative flex flex-col items-center gap-4 p-12 text-xl"
|
|
77
|
+
in:scale|global={{ duration: 100, delay: 100 }}
|
|
78
|
+
out:scale|global={{ duration: 100 }}
|
|
79
|
+
>
|
|
80
|
+
<div
|
|
81
|
+
class="absolute top-0 left-0 h-full w-full rounded-xl bg-black/75 opacity-50 blur-lg"
|
|
82
|
+
></div>
|
|
83
|
+
<FileUp size={40} />
|
|
84
|
+
</div>
|
|
85
|
+
{/snippet}
|
|
@@ -75,7 +75,7 @@
|
|
|
75
75
|
class={twMerge(
|
|
76
76
|
clsx([
|
|
77
77
|
'box-border flex h-full shrink-0 flex-row items-center justify-start gap-1 truncate',
|
|
78
|
-
column.width !== 0 && '
|
|
78
|
+
column.width !== 0 && 'border-r-[calc(var(--spacing)_*_2)] border-transparent',
|
|
79
79
|
defaultClasses,
|
|
80
80
|
clazz
|
|
81
81
|
])
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
import ColumnHead from './ColumnHead.svelte';
|
|
11
11
|
import { treeWalker } from './controller';
|
|
12
12
|
import Row from './Row.svelte';
|
|
13
|
-
import {
|
|
13
|
+
import { applyHidden, searchTable } from './search.svelte';
|
|
14
14
|
import VirtualList from './VirtualList.svelte';
|
|
15
15
|
|
|
16
16
|
export interface TableProps<T extends TableRow<T>> {
|
|
@@ -88,25 +88,24 @@
|
|
|
88
88
|
else expanded.add(id);
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
-
let
|
|
92
|
-
let prevSearch = $state('');
|
|
93
|
-
|
|
91
|
+
let hidden = $state(new SvelteSet<string>());
|
|
94
92
|
const searchResult = $derived.by(() => {
|
|
95
93
|
if (!search)
|
|
96
94
|
return {
|
|
97
95
|
filteredData: data,
|
|
98
96
|
isSearching: false
|
|
99
97
|
};
|
|
100
|
-
const query = search.term.trim();
|
|
101
|
-
// Note: We only use the 'filteredData' part of the search result here.
|
|
102
|
-
const { hidden } = searchData(data, query, search.matches);
|
|
103
98
|
return {
|
|
104
|
-
filteredData:
|
|
99
|
+
filteredData: applyHidden(structuredClone(data), hidden),
|
|
105
100
|
isSearching: true
|
|
106
101
|
};
|
|
107
102
|
});
|
|
108
103
|
const results = $derived(treeWalker({ data: searchResult.filteredData, expanded }));
|
|
109
104
|
|
|
105
|
+
let expandedBeforeSearch = $state<SvelteSet<string> | null>(null);
|
|
106
|
+
let prevSearch = $state('');
|
|
107
|
+
|
|
108
|
+
// updates expanded and hidden states
|
|
110
109
|
$effect(() => {
|
|
111
110
|
if (!search) return;
|
|
112
111
|
const currentSearch = search.term.trim();
|
|
@@ -117,8 +116,13 @@
|
|
|
117
116
|
if (!wasSearching && isSearching) {
|
|
118
117
|
// Save the current expansion state before overwriting it.
|
|
119
118
|
expandedBeforeSearch = untrack(() => new SvelteSet(expanded));
|
|
120
|
-
const { expanded: searchExpanded } =
|
|
119
|
+
const { expanded: searchExpanded, hidden: searchHidden } = searchTable(
|
|
120
|
+
data,
|
|
121
|
+
currentSearch,
|
|
122
|
+
search.matches
|
|
123
|
+
);
|
|
121
124
|
expanded = searchExpanded; // Set the initial expansion for the search.
|
|
125
|
+
hidden = searchHidden;
|
|
122
126
|
}
|
|
123
127
|
|
|
124
128
|
// Transition: Searching -> Not Searching
|
|
@@ -127,13 +131,19 @@
|
|
|
127
131
|
if (expandedBeforeSearch) {
|
|
128
132
|
expanded = expandedBeforeSearch;
|
|
129
133
|
expandedBeforeSearch = null;
|
|
134
|
+
hidden = new SvelteSet<string>();
|
|
130
135
|
}
|
|
131
136
|
}
|
|
132
137
|
|
|
133
138
|
// Transition: Searching -> Searching (different query)
|
|
134
139
|
if (wasSearching && isSearching && currentSearch !== prevSearch) {
|
|
135
|
-
const { expanded: searchExpanded } =
|
|
140
|
+
const { expanded: searchExpanded, hidden: searchHidden } = searchTable(
|
|
141
|
+
data,
|
|
142
|
+
currentSearch,
|
|
143
|
+
search.matches
|
|
144
|
+
);
|
|
136
145
|
expanded = searchExpanded; // Update the expansion for the new search.
|
|
146
|
+
hidden = searchHidden;
|
|
137
147
|
}
|
|
138
148
|
|
|
139
149
|
prevSearch = currentSearch;
|
|
@@ -2,10 +2,10 @@ import { SvelteSet } from 'svelte/reactivity';
|
|
|
2
2
|
import type { TableRow } from '.';
|
|
3
3
|
|
|
4
4
|
/** collapses everything that doesnt match the searchString, expands direct search hit */
|
|
5
|
-
export const
|
|
5
|
+
export const searchTable = <T extends TableRow<T>>(
|
|
6
6
|
nodes: T[],
|
|
7
7
|
searchString: string,
|
|
8
|
-
stringsMatch: (
|
|
8
|
+
stringsMatch: (node: T, searchTerm: string) => boolean
|
|
9
9
|
) => {
|
|
10
10
|
const search = searchString.trim().toLowerCase();
|
|
11
11
|
const hidden = new SvelteSet<string>();
|
|
@@ -13,17 +13,18 @@ export const searchData = <T extends TableRow<T>>(
|
|
|
13
13
|
|
|
14
14
|
function nodeMatches(node: T, childOfMatch = false): boolean {
|
|
15
15
|
const matches = stringsMatch(node, search);
|
|
16
|
-
let
|
|
16
|
+
let hasMatchingChild = false;
|
|
17
17
|
for (const child of node.children || []) {
|
|
18
18
|
const childMatches = nodeMatches(child, matches || childOfMatch);
|
|
19
|
-
if (childMatches)
|
|
19
|
+
if (childMatches) hasMatchingChild = true;
|
|
20
20
|
}
|
|
21
|
-
|
|
21
|
+
|
|
22
|
+
if (hasMatchingChild) {
|
|
22
23
|
expanded.add(node.id);
|
|
23
|
-
} else if (!
|
|
24
|
+
} else if (!matches) {
|
|
24
25
|
hidden.add(node.id);
|
|
25
26
|
}
|
|
26
|
-
return matches ||
|
|
27
|
+
return matches || hasMatchingChild;
|
|
27
28
|
}
|
|
28
29
|
|
|
29
30
|
nodes.forEach((n) => nodeMatches(n));
|
|
@@ -32,3 +33,15 @@ export const searchData = <T extends TableRow<T>>(
|
|
|
32
33
|
expanded
|
|
33
34
|
};
|
|
34
35
|
};
|
|
36
|
+
|
|
37
|
+
export function applyHidden<T extends TableRow<T>>(data: T[], hidden: SvelteSet<string>): T[] {
|
|
38
|
+
const results: T[] = [];
|
|
39
|
+
|
|
40
|
+
for (const node of data) {
|
|
41
|
+
if (hidden.has(node.id)) continue;
|
|
42
|
+
if (node.children) node.children = applyHidden(node.children, hidden);
|
|
43
|
+
results.push(node);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return results;
|
|
47
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export function createDebouncedValue<T>(delay: number, value: T) {
|
|
2
|
+
let current = $state<T>(value);
|
|
3
|
+
let debounced = $state<T>(value);
|
|
4
|
+
let timeout: ReturnType<typeof setTimeout>;
|
|
5
|
+
return {
|
|
6
|
+
set current(value: T) {
|
|
7
|
+
current = value;
|
|
8
|
+
if (timeout) clearTimeout(timeout);
|
|
9
|
+
timeout = setTimeout(() => {
|
|
10
|
+
debounced = value;
|
|
11
|
+
}, delay);
|
|
12
|
+
},
|
|
13
|
+
get current() {
|
|
14
|
+
return current;
|
|
15
|
+
},
|
|
16
|
+
get debounced() {
|
|
17
|
+
return debounced;
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
}
|