svelte-select-5 6.0.3 → 6.1.2
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/Select.svelte +56 -1
- package/Select.svelte.d.ts +50 -3
- package/filter.d.ts +85 -14
- package/filter.js +28 -0
- package/get-items.d.ts +67 -8
- package/get-items.js +28 -0
- package/no-styles/Select.svelte +56 -1
- package/no-styles/Select.svelte.d.ts +50 -3
- package/package.json +1 -1
package/Select.svelte
CHANGED
|
@@ -1,4 +1,39 @@
|
|
|
1
1
|
<script>
|
|
2
|
+
/**
|
|
3
|
+
* @typedef {Object} SelectItem
|
|
4
|
+
* @property {string|number} [value] - The value identifier for the item
|
|
5
|
+
* @property {string} [label] - Display label (or use custom label prop)
|
|
6
|
+
* @property {boolean} [selectable] - Whether the item can be selected
|
|
7
|
+
* @property {boolean} [isCreator] - Whether this is a "create new" item
|
|
8
|
+
* @property {string} [groupValue] - Group identifier for grouped items
|
|
9
|
+
* @property {string} [groupHeader] - Group header display text
|
|
10
|
+
* @property {*} [key: string] - Additional custom properties
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @typedef {SelectItem|SelectItem[]|null|undefined} SelectValue
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* @typedef {Object} FloatingConfig
|
|
19
|
+
* @property {'absolute'|'fixed'} [strategy] - Positioning strategy
|
|
20
|
+
* @property {'bottom-start'|'bottom-end'|'top-start'|'top-end'} [placement] - Dropdown placement
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* @callback ItemFilterFn
|
|
25
|
+
* @param {string} label - The item's label value
|
|
26
|
+
* @param {string} filterText - Current filter text
|
|
27
|
+
* @param {SelectItem} item - The item being filtered
|
|
28
|
+
* @returns {boolean} - Whether the item matches the filter
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* @callback LoadOptionsFn
|
|
33
|
+
* @param {string} filterText - Current filter text
|
|
34
|
+
* @returns {Promise<SelectItem[]>} - Promise resolving to items
|
|
35
|
+
*/
|
|
36
|
+
|
|
2
37
|
import { onDestroy, onMount } from 'svelte';
|
|
3
38
|
import { offset, flip, shift } from 'svelte-floating-ui/dom';
|
|
4
39
|
import { createFloatingActions } from 'svelte-floating-ui';
|
|
@@ -26,6 +61,10 @@
|
|
|
26
61
|
listOpen = $bindable(false),
|
|
27
62
|
hoverItemIndex = $bindable(0),
|
|
28
63
|
|
|
64
|
+
// Read-only bindable props (output only - external changes are ignored)
|
|
65
|
+
readonlyValue = $bindable(),
|
|
66
|
+
readonlyId = $bindable(),
|
|
67
|
+
|
|
29
68
|
// Function props
|
|
30
69
|
filter = _filter,
|
|
31
70
|
getItems = _getItems,
|
|
@@ -721,12 +760,17 @@
|
|
|
721
760
|
});
|
|
722
761
|
|
|
723
762
|
// Handle external changes to justValue (allows setting value via justValue)
|
|
763
|
+
// Also handles case where justValue is set before items are loaded
|
|
724
764
|
$effect(() => {
|
|
725
765
|
const computed = computeJustValue();
|
|
726
766
|
const isExternalChange = justValue !== prevJustValue &&
|
|
727
767
|
JSON.stringify(justValue) !== JSON.stringify(computed);
|
|
728
768
|
|
|
729
|
-
if
|
|
769
|
+
// Update value if: external justValue change, OR items loaded while justValue is set but value is empty
|
|
770
|
+
const needsValueUpdate = isExternalChange ||
|
|
771
|
+
(items && justValue != null && !value && JSON.stringify(justValue) !== JSON.stringify(computed));
|
|
772
|
+
|
|
773
|
+
if (needsValueUpdate && items) {
|
|
730
774
|
if (multiple) {
|
|
731
775
|
value = justValue
|
|
732
776
|
? items.filter(item => justValue.includes(item[itemId]))
|
|
@@ -740,6 +784,15 @@
|
|
|
740
784
|
prevJustValue = justValue;
|
|
741
785
|
});
|
|
742
786
|
|
|
787
|
+
// Read-only props - always reflect current state, external changes are ignored
|
|
788
|
+
$effect(() => {
|
|
789
|
+
readonlyValue = value;
|
|
790
|
+
});
|
|
791
|
+
|
|
792
|
+
$effect(() => {
|
|
793
|
+
readonlyId = computeJustValue();
|
|
794
|
+
});
|
|
795
|
+
|
|
743
796
|
$effect(() => {
|
|
744
797
|
if (!multiple && prev_value && !value) oninput?.(value);
|
|
745
798
|
});
|
|
@@ -789,6 +842,8 @@
|
|
|
789
842
|
});
|
|
790
843
|
|
|
791
844
|
onDestroy(() => {
|
|
845
|
+
clearTimeout(timeout);
|
|
846
|
+
clearTimeout(isScrollingTimer);
|
|
792
847
|
list?.remove();
|
|
793
848
|
});
|
|
794
849
|
</script>
|
package/Select.svelte.d.ts
CHANGED
|
@@ -1,9 +1,52 @@
|
|
|
1
1
|
export default Select;
|
|
2
|
+
export type SelectItem = {
|
|
3
|
+
/**
|
|
4
|
+
* - The value identifier for the item
|
|
5
|
+
*/
|
|
6
|
+
value?: string | number;
|
|
7
|
+
/**
|
|
8
|
+
* - Display label (or use custom label prop)
|
|
9
|
+
*/
|
|
10
|
+
label?: string;
|
|
11
|
+
/**
|
|
12
|
+
* - Whether the item can be selected
|
|
13
|
+
*/
|
|
14
|
+
selectable?: boolean;
|
|
15
|
+
/**
|
|
16
|
+
* - Whether this is a "create new" item
|
|
17
|
+
*/
|
|
18
|
+
isCreator?: boolean;
|
|
19
|
+
/**
|
|
20
|
+
* - Group identifier for grouped items
|
|
21
|
+
*/
|
|
22
|
+
groupValue?: string;
|
|
23
|
+
/**
|
|
24
|
+
* - Group header display text
|
|
25
|
+
*/
|
|
26
|
+
groupHeader?: string;
|
|
27
|
+
/**
|
|
28
|
+
* : string] - Additional custom properties
|
|
29
|
+
*/
|
|
30
|
+
key?: any;
|
|
31
|
+
};
|
|
32
|
+
export type SelectValue = SelectItem | SelectItem[] | null | undefined;
|
|
33
|
+
export type FloatingConfig = {
|
|
34
|
+
/**
|
|
35
|
+
* - Positioning strategy
|
|
36
|
+
*/
|
|
37
|
+
strategy?: "absolute" | "fixed";
|
|
38
|
+
/**
|
|
39
|
+
* - Dropdown placement
|
|
40
|
+
*/
|
|
41
|
+
placement?: "bottom-start" | "bottom-end" | "top-start" | "top-end";
|
|
42
|
+
};
|
|
43
|
+
export type ItemFilterFn = (label: string, filterText: string, item: SelectItem) => boolean;
|
|
44
|
+
export type LoadOptionsFn = (filterText: string) => Promise<SelectItem[]>;
|
|
2
45
|
type Select = {
|
|
3
46
|
$on?(type: string, callback: (e: any) => void): () => void;
|
|
4
47
|
$set?(props: Partial<$$ComponentProps>): void;
|
|
5
48
|
} & {
|
|
6
|
-
getFilteredItems: () =>
|
|
49
|
+
getFilteredItems: () => SelectItem[];
|
|
7
50
|
handleClear: () => void;
|
|
8
51
|
};
|
|
9
52
|
declare const Select: import("svelte").Component<{
|
|
@@ -17,6 +60,8 @@ declare const Select: import("svelte").Component<{
|
|
|
17
60
|
loading?: boolean;
|
|
18
61
|
listOpen?: boolean;
|
|
19
62
|
hoverItemIndex?: number;
|
|
63
|
+
readonlyValue?: any;
|
|
64
|
+
readonlyId?: any;
|
|
20
65
|
filter?: typeof _filter;
|
|
21
66
|
getItems?: typeof _getItems;
|
|
22
67
|
id?: any;
|
|
@@ -79,9 +124,9 @@ declare const Select: import("svelte").Component<{
|
|
|
79
124
|
inputHidden?: any;
|
|
80
125
|
requiredSlot?: any;
|
|
81
126
|
}, {
|
|
82
|
-
getFilteredItems: () =>
|
|
127
|
+
getFilteredItems: () => import("./filter").SelectItem[];
|
|
83
128
|
handleClear: () => void;
|
|
84
|
-
}, "loading" | "filterText" | "items" | "value" | "justValue" | "container" | "input" | "
|
|
129
|
+
}, "loading" | "filterText" | "items" | "value" | "focused" | "listOpen" | "justValue" | "container" | "input" | "hoverItemIndex" | "readonlyValue" | "readonlyId">;
|
|
85
130
|
type $$ComponentProps = {
|
|
86
131
|
justValue?: any;
|
|
87
132
|
container?: any;
|
|
@@ -93,6 +138,8 @@ type $$ComponentProps = {
|
|
|
93
138
|
loading?: boolean;
|
|
94
139
|
listOpen?: boolean;
|
|
95
140
|
hoverItemIndex?: number;
|
|
141
|
+
readonlyValue?: any;
|
|
142
|
+
readonlyId?: any;
|
|
96
143
|
filter?: typeof _filter;
|
|
97
144
|
getItems?: typeof _getItems;
|
|
98
145
|
id?: any;
|
package/filter.d.ts
CHANGED
|
@@ -1,14 +1,85 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {Object} SelectItem
|
|
3
|
+
* @property {string|number} [value]
|
|
4
|
+
* @property {string} [label]
|
|
5
|
+
* @property {*} [key: string]
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* @typedef {Object} FilterOptions
|
|
9
|
+
* @property {Function|undefined} loadOptions - Async load function
|
|
10
|
+
* @property {string} filterText - Current filter text
|
|
11
|
+
* @property {(SelectItem|string)[]} items - Items to filter
|
|
12
|
+
* @property {boolean} multiple - Multi-select mode
|
|
13
|
+
* @property {SelectItem|SelectItem[]|null} value - Current value
|
|
14
|
+
* @property {string} itemId - Property name for item ID
|
|
15
|
+
* @property {string|undefined} groupBy - Property name for grouping
|
|
16
|
+
* @property {boolean} filterSelectedItems - Whether to filter out selected items
|
|
17
|
+
* @property {(label: string, filterText: string, item: SelectItem) => boolean} itemFilter - Filter function
|
|
18
|
+
* @property {(items: (string|SelectItem)[]) => SelectItem[]} convertStringItemsToObjects - Converter function
|
|
19
|
+
* @property {(items: SelectItem[]) => SelectItem[]} filterGroupedItems - Group filter function
|
|
20
|
+
* @property {string} label - Property name for label
|
|
21
|
+
*/
|
|
22
|
+
/**
|
|
23
|
+
* Filters items based on filter text and selection state
|
|
24
|
+
* @param {FilterOptions} options - Filter options
|
|
25
|
+
* @returns {SelectItem[]} Filtered items
|
|
26
|
+
*/
|
|
27
|
+
export default function filter({ loadOptions, filterText, items, multiple, value, itemId, groupBy, filterSelectedItems, itemFilter, convertStringItemsToObjects, filterGroupedItems, label, }: FilterOptions): SelectItem[];
|
|
28
|
+
export type SelectItem = {
|
|
29
|
+
value?: string | number;
|
|
30
|
+
label?: string;
|
|
31
|
+
/**
|
|
32
|
+
* : string]
|
|
33
|
+
*/
|
|
34
|
+
key?: any;
|
|
35
|
+
};
|
|
36
|
+
export type FilterOptions = {
|
|
37
|
+
/**
|
|
38
|
+
* - Async load function
|
|
39
|
+
*/
|
|
40
|
+
loadOptions: Function | undefined;
|
|
41
|
+
/**
|
|
42
|
+
* - Current filter text
|
|
43
|
+
*/
|
|
44
|
+
filterText: string;
|
|
45
|
+
/**
|
|
46
|
+
* - Items to filter
|
|
47
|
+
*/
|
|
48
|
+
items: (SelectItem | string)[];
|
|
49
|
+
/**
|
|
50
|
+
* - Multi-select mode
|
|
51
|
+
*/
|
|
52
|
+
multiple: boolean;
|
|
53
|
+
/**
|
|
54
|
+
* - Current value
|
|
55
|
+
*/
|
|
56
|
+
value: SelectItem | SelectItem[] | null;
|
|
57
|
+
/**
|
|
58
|
+
* - Property name for item ID
|
|
59
|
+
*/
|
|
60
|
+
itemId: string;
|
|
61
|
+
/**
|
|
62
|
+
* - Property name for grouping
|
|
63
|
+
*/
|
|
64
|
+
groupBy: string | undefined;
|
|
65
|
+
/**
|
|
66
|
+
* - Whether to filter out selected items
|
|
67
|
+
*/
|
|
68
|
+
filterSelectedItems: boolean;
|
|
69
|
+
/**
|
|
70
|
+
* - Filter function
|
|
71
|
+
*/
|
|
72
|
+
itemFilter: (label: string, filterText: string, item: SelectItem) => boolean;
|
|
73
|
+
/**
|
|
74
|
+
* - Converter function
|
|
75
|
+
*/
|
|
76
|
+
convertStringItemsToObjects: (items: (string | SelectItem)[]) => SelectItem[];
|
|
77
|
+
/**
|
|
78
|
+
* - Group filter function
|
|
79
|
+
*/
|
|
80
|
+
filterGroupedItems: (items: SelectItem[]) => SelectItem[];
|
|
81
|
+
/**
|
|
82
|
+
* - Property name for label
|
|
83
|
+
*/
|
|
84
|
+
label: string;
|
|
85
|
+
};
|
package/filter.js
CHANGED
|
@@ -1,3 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {Object} SelectItem
|
|
3
|
+
* @property {string|number} [value]
|
|
4
|
+
* @property {string} [label]
|
|
5
|
+
* @property {*} [key: string]
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @typedef {Object} FilterOptions
|
|
10
|
+
* @property {Function|undefined} loadOptions - Async load function
|
|
11
|
+
* @property {string} filterText - Current filter text
|
|
12
|
+
* @property {(SelectItem|string)[]} items - Items to filter
|
|
13
|
+
* @property {boolean} multiple - Multi-select mode
|
|
14
|
+
* @property {SelectItem|SelectItem[]|null} value - Current value
|
|
15
|
+
* @property {string} itemId - Property name for item ID
|
|
16
|
+
* @property {string|undefined} groupBy - Property name for grouping
|
|
17
|
+
* @property {boolean} filterSelectedItems - Whether to filter out selected items
|
|
18
|
+
* @property {(label: string, filterText: string, item: SelectItem) => boolean} itemFilter - Filter function
|
|
19
|
+
* @property {(items: (string|SelectItem)[]) => SelectItem[]} convertStringItemsToObjects - Converter function
|
|
20
|
+
* @property {(items: SelectItem[]) => SelectItem[]} filterGroupedItems - Group filter function
|
|
21
|
+
* @property {string} label - Property name for label
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Filters items based on filter text and selection state
|
|
26
|
+
* @param {FilterOptions} options - Filter options
|
|
27
|
+
* @returns {SelectItem[]} Filtered items
|
|
28
|
+
*/
|
|
1
29
|
export default function filter({
|
|
2
30
|
loadOptions,
|
|
3
31
|
filterText,
|
package/get-items.d.ts
CHANGED
|
@@ -1,11 +1,70 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {Object} SelectItem
|
|
3
|
+
* @property {string|number} [value]
|
|
4
|
+
* @property {string} [label]
|
|
5
|
+
* @property {*} [key: string]
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* @typedef {Object} GetItemsOptions
|
|
9
|
+
* @property {(event: string, detail: Object) => void} dispatch - Event dispatcher function
|
|
10
|
+
* @property {(filterText: string) => Promise<SelectItem[]|string[]>} loadOptions - Async load function
|
|
11
|
+
* @property {(items: string[]) => SelectItem[]} convertStringItemsToObjects - String to object converter
|
|
12
|
+
* @property {string} filterText - Current filter text
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* @typedef {Object} GetItemsResult
|
|
16
|
+
* @property {SelectItem[]} filteredItems - Loaded items
|
|
17
|
+
* @property {boolean} loading - Loading state
|
|
18
|
+
* @property {boolean} focused - Focus state
|
|
19
|
+
* @property {boolean} listOpen - List open state
|
|
20
|
+
*/
|
|
21
|
+
/**
|
|
22
|
+
* Asynchronously loads items using loadOptions function
|
|
23
|
+
* @param {GetItemsOptions} options - Options for loading items
|
|
24
|
+
* @returns {Promise<GetItemsResult|undefined>} Result object or undefined if cancelled
|
|
25
|
+
*/
|
|
26
|
+
export default function getItems({ dispatch, loadOptions, convertStringItemsToObjects, filterText }: GetItemsOptions): Promise<GetItemsResult | undefined>;
|
|
27
|
+
export type SelectItem = {
|
|
28
|
+
value?: string | number;
|
|
29
|
+
label?: string;
|
|
30
|
+
/**
|
|
31
|
+
* : string]
|
|
32
|
+
*/
|
|
33
|
+
key?: any;
|
|
34
|
+
};
|
|
35
|
+
export type GetItemsOptions = {
|
|
36
|
+
/**
|
|
37
|
+
* - Event dispatcher function
|
|
38
|
+
*/
|
|
39
|
+
dispatch: (event: string, detail: any) => void;
|
|
40
|
+
/**
|
|
41
|
+
* - Async load function
|
|
42
|
+
*/
|
|
43
|
+
loadOptions: (filterText: string) => Promise<SelectItem[] | string[]>;
|
|
44
|
+
/**
|
|
45
|
+
* - String to object converter
|
|
46
|
+
*/
|
|
47
|
+
convertStringItemsToObjects: (items: string[]) => SelectItem[];
|
|
48
|
+
/**
|
|
49
|
+
* - Current filter text
|
|
50
|
+
*/
|
|
51
|
+
filterText: string;
|
|
52
|
+
};
|
|
53
|
+
export type GetItemsResult = {
|
|
54
|
+
/**
|
|
55
|
+
* - Loaded items
|
|
56
|
+
*/
|
|
57
|
+
filteredItems: SelectItem[];
|
|
58
|
+
/**
|
|
59
|
+
* - Loading state
|
|
60
|
+
*/
|
|
8
61
|
loading: boolean;
|
|
62
|
+
/**
|
|
63
|
+
* - Focus state
|
|
64
|
+
*/
|
|
9
65
|
focused: boolean;
|
|
66
|
+
/**
|
|
67
|
+
* - List open state
|
|
68
|
+
*/
|
|
10
69
|
listOpen: boolean;
|
|
11
|
-
}
|
|
70
|
+
};
|
package/get-items.js
CHANGED
|
@@ -1,3 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {Object} SelectItem
|
|
3
|
+
* @property {string|number} [value]
|
|
4
|
+
* @property {string} [label]
|
|
5
|
+
* @property {*} [key: string]
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @typedef {Object} GetItemsOptions
|
|
10
|
+
* @property {(event: string, detail: Object) => void} dispatch - Event dispatcher function
|
|
11
|
+
* @property {(filterText: string) => Promise<SelectItem[]|string[]>} loadOptions - Async load function
|
|
12
|
+
* @property {(items: string[]) => SelectItem[]} convertStringItemsToObjects - String to object converter
|
|
13
|
+
* @property {string} filterText - Current filter text
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @typedef {Object} GetItemsResult
|
|
18
|
+
* @property {SelectItem[]} filteredItems - Loaded items
|
|
19
|
+
* @property {boolean} loading - Loading state
|
|
20
|
+
* @property {boolean} focused - Focus state
|
|
21
|
+
* @property {boolean} listOpen - List open state
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Asynchronously loads items using loadOptions function
|
|
26
|
+
* @param {GetItemsOptions} options - Options for loading items
|
|
27
|
+
* @returns {Promise<GetItemsResult|undefined>} Result object or undefined if cancelled
|
|
28
|
+
*/
|
|
1
29
|
export default async function getItems({ dispatch, loadOptions, convertStringItemsToObjects, filterText }) {
|
|
2
30
|
let res = await loadOptions(filterText).catch((err) => {
|
|
3
31
|
console.warn('svelte-select loadOptions error :>> ', err);
|
package/no-styles/Select.svelte
CHANGED
|
@@ -1,4 +1,39 @@
|
|
|
1
1
|
<script>
|
|
2
|
+
/**
|
|
3
|
+
* @typedef {Object} SelectItem
|
|
4
|
+
* @property {string|number} [value] - The value identifier for the item
|
|
5
|
+
* @property {string} [label] - Display label (or use custom label prop)
|
|
6
|
+
* @property {boolean} [selectable] - Whether the item can be selected
|
|
7
|
+
* @property {boolean} [isCreator] - Whether this is a "create new" item
|
|
8
|
+
* @property {string} [groupValue] - Group identifier for grouped items
|
|
9
|
+
* @property {string} [groupHeader] - Group header display text
|
|
10
|
+
* @property {*} [key: string] - Additional custom properties
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @typedef {SelectItem|SelectItem[]|null|undefined} SelectValue
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* @typedef {Object} FloatingConfig
|
|
19
|
+
* @property {'absolute'|'fixed'} [strategy] - Positioning strategy
|
|
20
|
+
* @property {'bottom-start'|'bottom-end'|'top-start'|'top-end'} [placement] - Dropdown placement
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* @callback ItemFilterFn
|
|
25
|
+
* @param {string} label - The item's label value
|
|
26
|
+
* @param {string} filterText - Current filter text
|
|
27
|
+
* @param {SelectItem} item - The item being filtered
|
|
28
|
+
* @returns {boolean} - Whether the item matches the filter
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* @callback LoadOptionsFn
|
|
33
|
+
* @param {string} filterText - Current filter text
|
|
34
|
+
* @returns {Promise<SelectItem[]>} - Promise resolving to items
|
|
35
|
+
*/
|
|
36
|
+
|
|
2
37
|
import { onDestroy, onMount } from 'svelte';
|
|
3
38
|
import { offset, flip, shift } from 'svelte-floating-ui/dom';
|
|
4
39
|
import { createFloatingActions } from 'svelte-floating-ui';
|
|
@@ -26,6 +61,10 @@
|
|
|
26
61
|
listOpen = $bindable(false),
|
|
27
62
|
hoverItemIndex = $bindable(0),
|
|
28
63
|
|
|
64
|
+
// Read-only bindable props (output only - external changes are ignored)
|
|
65
|
+
readonlyValue = $bindable(),
|
|
66
|
+
readonlyId = $bindable(),
|
|
67
|
+
|
|
29
68
|
// Function props
|
|
30
69
|
filter = _filter,
|
|
31
70
|
getItems = _getItems,
|
|
@@ -721,12 +760,17 @@
|
|
|
721
760
|
});
|
|
722
761
|
|
|
723
762
|
// Handle external changes to justValue (allows setting value via justValue)
|
|
763
|
+
// Also handles case where justValue is set before items are loaded
|
|
724
764
|
$effect(() => {
|
|
725
765
|
const computed = computeJustValue();
|
|
726
766
|
const isExternalChange = justValue !== prevJustValue &&
|
|
727
767
|
JSON.stringify(justValue) !== JSON.stringify(computed);
|
|
728
768
|
|
|
729
|
-
if
|
|
769
|
+
// Update value if: external justValue change, OR items loaded while justValue is set but value is empty
|
|
770
|
+
const needsValueUpdate = isExternalChange ||
|
|
771
|
+
(items && justValue != null && !value && JSON.stringify(justValue) !== JSON.stringify(computed));
|
|
772
|
+
|
|
773
|
+
if (needsValueUpdate && items) {
|
|
730
774
|
if (multiple) {
|
|
731
775
|
value = justValue
|
|
732
776
|
? items.filter(item => justValue.includes(item[itemId]))
|
|
@@ -740,6 +784,15 @@
|
|
|
740
784
|
prevJustValue = justValue;
|
|
741
785
|
});
|
|
742
786
|
|
|
787
|
+
// Read-only props - always reflect current state, external changes are ignored
|
|
788
|
+
$effect(() => {
|
|
789
|
+
readonlyValue = value;
|
|
790
|
+
});
|
|
791
|
+
|
|
792
|
+
$effect(() => {
|
|
793
|
+
readonlyId = computeJustValue();
|
|
794
|
+
});
|
|
795
|
+
|
|
743
796
|
$effect(() => {
|
|
744
797
|
if (!multiple && prev_value && !value) oninput?.(value);
|
|
745
798
|
});
|
|
@@ -789,6 +842,8 @@
|
|
|
789
842
|
});
|
|
790
843
|
|
|
791
844
|
onDestroy(() => {
|
|
845
|
+
clearTimeout(timeout);
|
|
846
|
+
clearTimeout(isScrollingTimer);
|
|
792
847
|
list?.remove();
|
|
793
848
|
});
|
|
794
849
|
</script>
|
|
@@ -1,9 +1,52 @@
|
|
|
1
1
|
export default Select;
|
|
2
|
+
export type SelectItem = {
|
|
3
|
+
/**
|
|
4
|
+
* - The value identifier for the item
|
|
5
|
+
*/
|
|
6
|
+
value?: string | number;
|
|
7
|
+
/**
|
|
8
|
+
* - Display label (or use custom label prop)
|
|
9
|
+
*/
|
|
10
|
+
label?: string;
|
|
11
|
+
/**
|
|
12
|
+
* - Whether the item can be selected
|
|
13
|
+
*/
|
|
14
|
+
selectable?: boolean;
|
|
15
|
+
/**
|
|
16
|
+
* - Whether this is a "create new" item
|
|
17
|
+
*/
|
|
18
|
+
isCreator?: boolean;
|
|
19
|
+
/**
|
|
20
|
+
* - Group identifier for grouped items
|
|
21
|
+
*/
|
|
22
|
+
groupValue?: string;
|
|
23
|
+
/**
|
|
24
|
+
* - Group header display text
|
|
25
|
+
*/
|
|
26
|
+
groupHeader?: string;
|
|
27
|
+
/**
|
|
28
|
+
* : string] - Additional custom properties
|
|
29
|
+
*/
|
|
30
|
+
key?: any;
|
|
31
|
+
};
|
|
32
|
+
export type SelectValue = SelectItem | SelectItem[] | null | undefined;
|
|
33
|
+
export type FloatingConfig = {
|
|
34
|
+
/**
|
|
35
|
+
* - Positioning strategy
|
|
36
|
+
*/
|
|
37
|
+
strategy?: "absolute" | "fixed";
|
|
38
|
+
/**
|
|
39
|
+
* - Dropdown placement
|
|
40
|
+
*/
|
|
41
|
+
placement?: "bottom-start" | "bottom-end" | "top-start" | "top-end";
|
|
42
|
+
};
|
|
43
|
+
export type ItemFilterFn = (label: string, filterText: string, item: SelectItem) => boolean;
|
|
44
|
+
export type LoadOptionsFn = (filterText: string) => Promise<SelectItem[]>;
|
|
2
45
|
type Select = {
|
|
3
46
|
$on?(type: string, callback: (e: any) => void): () => void;
|
|
4
47
|
$set?(props: Partial<$$ComponentProps>): void;
|
|
5
48
|
} & {
|
|
6
|
-
getFilteredItems: () =>
|
|
49
|
+
getFilteredItems: () => SelectItem[];
|
|
7
50
|
handleClear: () => void;
|
|
8
51
|
};
|
|
9
52
|
declare const Select: import("svelte").Component<{
|
|
@@ -17,6 +60,8 @@ declare const Select: import("svelte").Component<{
|
|
|
17
60
|
loading?: boolean;
|
|
18
61
|
listOpen?: boolean;
|
|
19
62
|
hoverItemIndex?: number;
|
|
63
|
+
readonlyValue?: any;
|
|
64
|
+
readonlyId?: any;
|
|
20
65
|
filter?: typeof _filter;
|
|
21
66
|
getItems?: typeof _getItems;
|
|
22
67
|
id?: any;
|
|
@@ -79,9 +124,9 @@ declare const Select: import("svelte").Component<{
|
|
|
79
124
|
inputHidden?: any;
|
|
80
125
|
requiredSlot?: any;
|
|
81
126
|
}, {
|
|
82
|
-
getFilteredItems: () =>
|
|
127
|
+
getFilteredItems: () => import("../filter").SelectItem[];
|
|
83
128
|
handleClear: () => void;
|
|
84
|
-
}, "loading" | "filterText" | "items" | "value" | "justValue" | "container" | "input" | "
|
|
129
|
+
}, "loading" | "filterText" | "items" | "value" | "focused" | "listOpen" | "justValue" | "container" | "input" | "hoverItemIndex" | "readonlyValue" | "readonlyId">;
|
|
85
130
|
type $$ComponentProps = {
|
|
86
131
|
justValue?: any;
|
|
87
132
|
container?: any;
|
|
@@ -93,6 +138,8 @@ type $$ComponentProps = {
|
|
|
93
138
|
loading?: boolean;
|
|
94
139
|
listOpen?: boolean;
|
|
95
140
|
hoverItemIndex?: number;
|
|
141
|
+
readonlyValue?: any;
|
|
142
|
+
readonlyId?: any;
|
|
96
143
|
filter?: typeof _filter;
|
|
97
144
|
getItems?: typeof _getItems;
|
|
98
145
|
id?: any;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "svelte-select-5",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.1.2",
|
|
4
4
|
"description": "A <Select> component for Svelte 5 apps (fork of svelte-select)",
|
|
5
5
|
"repository": "https://github.com/Dbone29/svelte-select-5.git",
|
|
6
6
|
"author": "Robert Balfré <rob.balfre@gmail.com> (https://github.com/rob-balfre)",
|