svelte-select-5 6.0.2 → 6.1.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.
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,
@@ -122,6 +161,7 @@
122
161
  let isScrolling = $state(false);
123
162
  let prefloat = $state(true);
124
163
  let _inputAttributes = $state({});
164
+ let prevJustValue = $state(undefined);
125
165
  let isScrollingTimer;
126
166
 
127
167
  // Floating UI config - using closure for listOffset to capture current value
@@ -719,6 +759,32 @@
719
759
  justValue = computeJustValue();
720
760
  });
721
761
 
762
+ // Handle external changes to justValue (allows setting value via justValue)
763
+ $effect(() => {
764
+ const computed = computeJustValue();
765
+ const isExternalChange = justValue !== prevJustValue &&
766
+ JSON.stringify(justValue) !== JSON.stringify(computed);
767
+
768
+ if (isExternalChange && items) {
769
+ if (multiple) {
770
+ value = justValue
771
+ ? items.filter(item => justValue.includes(item[itemId]))
772
+ : null;
773
+ } else {
774
+ value = justValue != null
775
+ ? items.find(item => item[itemId] === justValue) ?? null
776
+ : null;
777
+ }
778
+ }
779
+ prevJustValue = justValue;
780
+ });
781
+
782
+ // Read-only props - always reflect current state, external changes are ignored
783
+ $effect(() => {
784
+ readonlyValue = value;
785
+ readonlyId = computeJustValue();
786
+ });
787
+
722
788
  $effect(() => {
723
789
  if (!multiple && prev_value && !value) oninput?.(value);
724
790
  });
@@ -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: () => any;
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: () => any;
127
+ getFilteredItems: () => import("./filter").SelectItem[];
83
128
  handleClear: () => void;
84
- }, "loading" | "filterText" | "items" | "value" | "justValue" | "container" | "input" | "focused" | "listOpen" | "hoverItemIndex">;
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
- export default function filter({ loadOptions, filterText, items, multiple, value, itemId, groupBy, filterSelectedItems, itemFilter, convertStringItemsToObjects, filterGroupedItems, label, }: {
2
- loadOptions: any;
3
- filterText: any;
4
- items: any;
5
- multiple: any;
6
- value: any;
7
- itemId: any;
8
- groupBy: any;
9
- filterSelectedItems: any;
10
- itemFilter: any;
11
- convertStringItemsToObjects: any;
12
- filterGroupedItems: any;
13
- label: any;
14
- }): any;
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
- export default function getItems({ dispatch, loadOptions, convertStringItemsToObjects, filterText }: {
2
- dispatch: any;
3
- loadOptions: any;
4
- convertStringItemsToObjects: any;
5
- filterText: any;
6
- }): Promise<{
7
- filteredItems: any;
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);
@@ -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,
@@ -122,6 +161,7 @@
122
161
  let isScrolling = $state(false);
123
162
  let prefloat = $state(true);
124
163
  let _inputAttributes = $state({});
164
+ let prevJustValue = $state(undefined);
125
165
  let isScrollingTimer;
126
166
 
127
167
  // Floating UI config - using closure for listOffset to capture current value
@@ -719,6 +759,32 @@
719
759
  justValue = computeJustValue();
720
760
  });
721
761
 
762
+ // Handle external changes to justValue (allows setting value via justValue)
763
+ $effect(() => {
764
+ const computed = computeJustValue();
765
+ const isExternalChange = justValue !== prevJustValue &&
766
+ JSON.stringify(justValue) !== JSON.stringify(computed);
767
+
768
+ if (isExternalChange && items) {
769
+ if (multiple) {
770
+ value = justValue
771
+ ? items.filter(item => justValue.includes(item[itemId]))
772
+ : null;
773
+ } else {
774
+ value = justValue != null
775
+ ? items.find(item => item[itemId] === justValue) ?? null
776
+ : null;
777
+ }
778
+ }
779
+ prevJustValue = justValue;
780
+ });
781
+
782
+ // Read-only props - always reflect current state, external changes are ignored
783
+ $effect(() => {
784
+ readonlyValue = value;
785
+ readonlyId = computeJustValue();
786
+ });
787
+
722
788
  $effect(() => {
723
789
  if (!multiple && prev_value && !value) oninput?.(value);
724
790
  });
@@ -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: () => any;
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: () => any;
127
+ getFilteredItems: () => import("../filter").SelectItem[];
83
128
  handleClear: () => void;
84
- }, "loading" | "filterText" | "items" | "value" | "justValue" | "container" | "input" | "focused" | "listOpen" | "hoverItemIndex">;
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.0.2",
3
+ "version": "6.1.1",
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)",