slim-select 2.13.1 → 3.0.0
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/README.md +184 -43
- package/dist/index.d.ts +304 -52
- package/dist/react/index.d.ts +304 -0
- package/dist/react/index.js +1549 -0
- package/dist/react/index.umd.js +22 -0
- package/dist/slimselect.cjs.js +1 -2030
- package/dist/slimselect.css +1 -1
- package/dist/slimselect.css.map +1 -1
- package/dist/slimselect.es.js +1224 -2012
- package/dist/slimselect.umd.js +1 -2036
- package/dist/vue/index.d.ts +304 -0
- package/dist/vue/index.js +1341 -0
- package/dist/vue/index.umd.js +1 -0
- package/index.html +1 -0
- package/package.json +58 -36
- package/release.js +0 -7
- package/src/slim-select/accessibility.test.ts +782 -0
- package/src/slim-select/classes.test.ts +7 -6
- package/src/slim-select/classes.ts +8 -6
- package/src/slim-select/helpers.test.ts +10 -8
- package/src/slim-select/index.test.ts +509 -14
- package/src/slim-select/index.ts +58 -31
- package/src/slim-select/react/index.tsx +9 -0
- package/src/slim-select/react/react.tsx +112 -0
- package/src/slim-select/render.test.ts +479 -119
- package/src/slim-select/render.ts +213 -91
- package/src/slim-select/select.test.ts +28 -10
- package/src/slim-select/select.ts +35 -12
- package/src/slim-select/settings.test.ts +19 -8
- package/src/slim-select/settings.ts +2 -4
- package/src/slim-select/slimselect.scss +30 -15
- package/src/slim-select/store.test.ts +13 -16
- package/src/slim-select/store.ts +97 -86
- package/src/slim-select/vue/index.ts +9 -0
- package/src/slim-select/vue/vue.test.ts +832 -0
- package/src/slim-select/{vue.vue → vue/vue.vue} +45 -23
- package/tsconfig.json +6 -4
- package/{vite.config.mts → vite.config.docs.mts} +10 -0
- package/vite.config.lib.mts +42 -0
- package/vite.config.react.mts +40 -0
- package/vite.config.vue.mts +39 -0
- package/vitest.config.ts +29 -0
- package/dist/classes.d.ts +0 -43
- package/dist/helpers.d.ts +0 -5
- package/dist/render.d.ts +0 -81
- package/dist/select.d.ts +0 -30
- package/dist/settings.d.ts +0 -35
- package/dist/slimselect.global.js +0 -2033
- package/dist/slimselect.js +0 -2036
- package/dist/slimselect.min.js +0 -1
- package/dist/slimselect.umd.min.js +0 -1
- package/dist/store.d.ts +0 -84
- package/jest.config.js +0 -14
- package/src/slim-select/rollup.config.mjs +0 -127
- package/src/slim-select/tsconfig.json +0 -14
package/src/slim-select/store.ts
CHANGED
|
@@ -1,64 +1,7 @@
|
|
|
1
1
|
import { generateID } from './helpers'
|
|
2
2
|
|
|
3
|
-
export type DataArray = DataObject[]
|
|
4
|
-
export type DataObject = Optgroup | Option
|
|
5
|
-
|
|
6
|
-
export type DataArrayPartial = DataObjectPartial[]
|
|
7
|
-
export type DataObjectPartial = OptgroupOptional | OptionOptional
|
|
8
|
-
|
|
9
3
|
type selectType = 'single' | 'multiple'
|
|
10
4
|
|
|
11
|
-
export interface OptgroupOptional {
|
|
12
|
-
id?: string
|
|
13
|
-
label: string // Required
|
|
14
|
-
selectAll?: boolean
|
|
15
|
-
selectAllText?: string
|
|
16
|
-
closable?: 'off' | 'open' | 'close'
|
|
17
|
-
options?: OptionOptional[]
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export class Optgroup {
|
|
21
|
-
public id: string
|
|
22
|
-
public label: string
|
|
23
|
-
public selectAll: boolean
|
|
24
|
-
public selectAllText: string
|
|
25
|
-
public closable: 'off' | 'open' | 'close'
|
|
26
|
-
public options: Option[]
|
|
27
|
-
|
|
28
|
-
constructor(optgroup: OptgroupOptional) {
|
|
29
|
-
this.id = !optgroup.id || optgroup.id === '' ? generateID() : optgroup.id
|
|
30
|
-
this.label = optgroup.label || ''
|
|
31
|
-
this.selectAll = optgroup.selectAll === undefined ? false : optgroup.selectAll
|
|
32
|
-
this.selectAllText = optgroup.selectAllText || 'Select All'
|
|
33
|
-
this.closable = optgroup.closable || 'off'
|
|
34
|
-
|
|
35
|
-
// If options exist, loop through options and create new option class
|
|
36
|
-
// and set the options to the optgroup options field
|
|
37
|
-
this.options = []
|
|
38
|
-
if (optgroup.options) {
|
|
39
|
-
for (const o of optgroup.options) {
|
|
40
|
-
this.options.push(new Option(o))
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export interface OptionOptional {
|
|
47
|
-
id?: string
|
|
48
|
-
value?: string
|
|
49
|
-
text: string // Required
|
|
50
|
-
html?: string
|
|
51
|
-
selected?: boolean
|
|
52
|
-
defaultSelected?: boolean
|
|
53
|
-
display?: boolean
|
|
54
|
-
disabled?: boolean
|
|
55
|
-
mandatory?: boolean
|
|
56
|
-
placeholder?: boolean
|
|
57
|
-
class?: string
|
|
58
|
-
style?: string
|
|
59
|
-
data?: { [key: string]: string }
|
|
60
|
-
}
|
|
61
|
-
|
|
62
5
|
export class Option {
|
|
63
6
|
id: string
|
|
64
7
|
value: string
|
|
@@ -74,9 +17,9 @@ export class Option {
|
|
|
74
17
|
data: { [key: string]: string }
|
|
75
18
|
mandatory: boolean
|
|
76
19
|
|
|
77
|
-
constructor(option:
|
|
20
|
+
constructor(option: Partial<Option>) {
|
|
78
21
|
this.id = !option.id || option.id === '' ? generateID() : option.id
|
|
79
|
-
this.value = option.value === undefined ? option.text : option.value
|
|
22
|
+
this.value = option.value === undefined ? option.text || '' : option.value || ''
|
|
80
23
|
this.text = option.text || ''
|
|
81
24
|
this.html = option.html || ''
|
|
82
25
|
this.defaultSelected = option.defaultSelected !== undefined ? option.defaultSelected : false
|
|
@@ -90,27 +33,54 @@ export class Option {
|
|
|
90
33
|
this.data = option.data || {}
|
|
91
34
|
}
|
|
92
35
|
}
|
|
36
|
+
export class Optgroup {
|
|
37
|
+
public id: string
|
|
38
|
+
public label: string
|
|
39
|
+
public selectAll: boolean
|
|
40
|
+
public selectAllText: string
|
|
41
|
+
public closable: 'off' | 'open' | 'close'
|
|
42
|
+
public options: Partial<Option>[]
|
|
43
|
+
|
|
44
|
+
constructor(optgroup: Partial<Optgroup>) {
|
|
45
|
+
this.id = !optgroup.id || optgroup.id === '' ? generateID() : optgroup.id
|
|
46
|
+
this.label = optgroup.label || ''
|
|
47
|
+
this.selectAll = optgroup.selectAll === undefined ? false : optgroup.selectAll
|
|
48
|
+
this.selectAllText = optgroup.selectAllText || 'Select All'
|
|
49
|
+
this.closable = optgroup.closable || 'off'
|
|
50
|
+
|
|
51
|
+
// If options exist, loop through options and create new option class
|
|
52
|
+
// and set the options to the optgroup options field
|
|
53
|
+
this.options = []
|
|
54
|
+
if (optgroup.options) {
|
|
55
|
+
for (const o of optgroup.options) {
|
|
56
|
+
this.options.push(new Option(o))
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
93
61
|
|
|
94
62
|
export default class Store {
|
|
95
63
|
private selectType: selectType = 'single'
|
|
96
64
|
|
|
97
65
|
// Main data set, never null
|
|
98
|
-
private data:
|
|
66
|
+
private data: (Option | Optgroup)[] = []
|
|
99
67
|
private selectedOrder: string[] = []
|
|
100
68
|
|
|
101
|
-
constructor(type: selectType, data:
|
|
69
|
+
constructor(type: selectType, data: (Partial<Option> | Partial<Optgroup>)[]) {
|
|
102
70
|
this.selectType = type
|
|
103
71
|
this.setData(data)
|
|
104
72
|
}
|
|
105
73
|
|
|
106
74
|
// Validate DataArrayPartial
|
|
107
|
-
public validateDataArray(data:
|
|
75
|
+
public validateDataArray(data: (Partial<Option> | Partial<Optgroup>)[]): Error | null {
|
|
108
76
|
if (!Array.isArray(data)) {
|
|
109
77
|
return new Error('Data must be an array')
|
|
110
78
|
}
|
|
111
79
|
|
|
112
80
|
// Loop through each data object
|
|
113
81
|
for (let dataObj of data) {
|
|
82
|
+
if (!dataObj) continue
|
|
83
|
+
|
|
114
84
|
// Optgroup
|
|
115
85
|
if (dataObj instanceof Optgroup || 'label' in dataObj) {
|
|
116
86
|
if (!('label' in dataObj)) {
|
|
@@ -139,7 +109,7 @@ export default class Store {
|
|
|
139
109
|
}
|
|
140
110
|
|
|
141
111
|
// Validate Option
|
|
142
|
-
public validateOption(option: Option
|
|
112
|
+
public validateOption(option: Partial<Option>): Error | null {
|
|
143
113
|
if (!('text' in option)) {
|
|
144
114
|
return new Error('Option must have a text')
|
|
145
115
|
}
|
|
@@ -147,34 +117,73 @@ export default class Store {
|
|
|
147
117
|
return null
|
|
148
118
|
}
|
|
149
119
|
|
|
150
|
-
public partialToFullData(data:
|
|
151
|
-
let dataFinal:
|
|
152
|
-
data.forEach((dataObj
|
|
120
|
+
public partialToFullData(data: (Partial<Option> | Partial<Optgroup>)[]): (Option | Optgroup)[] {
|
|
121
|
+
let dataFinal: (Option | Optgroup)[] = []
|
|
122
|
+
data.forEach((dataObj) => {
|
|
123
|
+
if (!dataObj) return
|
|
124
|
+
|
|
153
125
|
// Optgroup
|
|
154
126
|
if (dataObj instanceof Optgroup || 'label' in dataObj) {
|
|
155
127
|
let optOptions: Option[] = []
|
|
156
128
|
if ('options' in dataObj && dataObj.options) {
|
|
157
|
-
dataObj.options.forEach((option: Option
|
|
129
|
+
dataObj.options.forEach((option: Partial<Option>) => {
|
|
158
130
|
optOptions.push(new Option(option))
|
|
159
131
|
})
|
|
160
132
|
}
|
|
161
133
|
|
|
162
134
|
if (optOptions.length > 0) {
|
|
163
|
-
dataFinal.push(new Optgroup(dataObj))
|
|
135
|
+
dataFinal.push(new Optgroup(dataObj as Partial<Optgroup>))
|
|
164
136
|
}
|
|
165
137
|
}
|
|
166
138
|
|
|
167
139
|
// Option
|
|
168
140
|
if (dataObj instanceof Option || 'text' in dataObj) {
|
|
169
|
-
dataFinal.push(new Option(dataObj))
|
|
141
|
+
dataFinal.push(new Option(dataObj as Partial<Option>))
|
|
170
142
|
}
|
|
171
143
|
})
|
|
172
144
|
|
|
173
145
|
return dataFinal
|
|
174
146
|
}
|
|
175
147
|
|
|
176
|
-
public setData(data:
|
|
177
|
-
|
|
148
|
+
public setData(data: (Partial<Option> | Partial<Optgroup>)[], preserveSelected: boolean = false) {
|
|
149
|
+
// Convert new data to full data array
|
|
150
|
+
const newData = this.partialToFullData(data)
|
|
151
|
+
|
|
152
|
+
if (preserveSelected) {
|
|
153
|
+
// Get currently selected options before updating data
|
|
154
|
+
const selectedOptions = this.getSelectedOptions()
|
|
155
|
+
|
|
156
|
+
// Check which selected options are missing from new data
|
|
157
|
+
const missingSelected: (Option | Optgroup)[] = []
|
|
158
|
+
selectedOptions.forEach((selectedOption) => {
|
|
159
|
+
let found = false
|
|
160
|
+
|
|
161
|
+
// Check if this selected option exists in new data
|
|
162
|
+
for (const newItem of newData) {
|
|
163
|
+
if (newItem instanceof Option && newItem.id === selectedOption.id) {
|
|
164
|
+
found = true
|
|
165
|
+
break
|
|
166
|
+
}
|
|
167
|
+
if (newItem instanceof Optgroup) {
|
|
168
|
+
for (const opt of newItem.options) {
|
|
169
|
+
if (opt.id === selectedOption.id) {
|
|
170
|
+
found = true
|
|
171
|
+
break
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if (!found) {
|
|
178
|
+
missingSelected.push(selectedOption)
|
|
179
|
+
}
|
|
180
|
+
})
|
|
181
|
+
|
|
182
|
+
// Add missing selected options to the beginning of the data
|
|
183
|
+
this.data = [...missingSelected, ...newData]
|
|
184
|
+
} else {
|
|
185
|
+
this.data = newData
|
|
186
|
+
}
|
|
178
187
|
|
|
179
188
|
// Run this.data through setSelected by value
|
|
180
189
|
// to set the selected property and clean any wrong selected
|
|
@@ -184,8 +193,8 @@ export default class Store {
|
|
|
184
193
|
}
|
|
185
194
|
|
|
186
195
|
// Get data will return all the data
|
|
187
|
-
public getData():
|
|
188
|
-
return this.filter(null, true)
|
|
196
|
+
public getData(): Option[] | Optgroup[] {
|
|
197
|
+
return this.filter(null, true) as Option[] | Optgroup[]
|
|
189
198
|
}
|
|
190
199
|
|
|
191
200
|
// Get data options will return the data as a
|
|
@@ -194,9 +203,9 @@ export default class Store {
|
|
|
194
203
|
return this.filter(null, false) as Option[]
|
|
195
204
|
}
|
|
196
205
|
|
|
197
|
-
public addOption(option:
|
|
206
|
+
public addOption(option: Partial<Option>, addToStart: boolean = false) {
|
|
198
207
|
if (addToStart) {
|
|
199
|
-
let data = [new Option(option)] as
|
|
208
|
+
let data = [new Option(option)] as (Option | Optgroup)[]
|
|
200
209
|
this.setData(data.concat(this.getData()))
|
|
201
210
|
} else {
|
|
202
211
|
this.setData(this.getData().concat(new Option(option)))
|
|
@@ -207,19 +216,20 @@ export default class Store {
|
|
|
207
216
|
// each option and set the selected property to true
|
|
208
217
|
// but also clean selected by determining selectType
|
|
209
218
|
public setSelectedBy(selectedType: 'id' | 'value', selectedValues: string[]) {
|
|
210
|
-
let firstOption: Option | null = null
|
|
219
|
+
let firstOption: Partial<Option> | null = null
|
|
211
220
|
let hasSelected = false
|
|
212
|
-
const selectedObjects: Option[] = []
|
|
221
|
+
const selectedObjects: Partial<Option>[] = []
|
|
213
222
|
|
|
214
223
|
for (let dataObj of this.data) {
|
|
215
224
|
// Optgroup
|
|
216
225
|
if (dataObj instanceof Optgroup) {
|
|
217
|
-
for (let option of dataObj.options) {
|
|
226
|
+
for (let option of dataObj.options as Partial<Option>[]) {
|
|
218
227
|
if (!firstOption) {
|
|
219
228
|
firstOption = option
|
|
220
229
|
}
|
|
221
230
|
|
|
222
|
-
|
|
231
|
+
let optionValue = option[selectedType] || ''
|
|
232
|
+
option.selected = hasSelected ? false : selectedValues.includes(optionValue)
|
|
223
233
|
|
|
224
234
|
// If the option is selected, set hasSelected to true
|
|
225
235
|
// for single based selects
|
|
@@ -309,7 +319,7 @@ export default class Store {
|
|
|
309
319
|
let option: Option | null = null
|
|
310
320
|
for (let dataObj of this.data) {
|
|
311
321
|
if (dataObj instanceof Optgroup) {
|
|
312
|
-
option = dataObj.options[0]
|
|
322
|
+
option = dataObj.options[0] as Option
|
|
313
323
|
} else if (dataObj instanceof Option) {
|
|
314
324
|
option = dataObj
|
|
315
325
|
}
|
|
@@ -322,7 +332,7 @@ export default class Store {
|
|
|
322
332
|
}
|
|
323
333
|
|
|
324
334
|
// Take in search string and return filtered list of values
|
|
325
|
-
public search(search: string, searchFilter: (opt: Option, search: string) => boolean):
|
|
335
|
+
public search(search: string, searchFilter: (opt: Option, search: string) => boolean): (Option | Optgroup)[] {
|
|
326
336
|
search = search.trim()
|
|
327
337
|
|
|
328
338
|
// If search is empty, return all data
|
|
@@ -338,14 +348,15 @@ export default class Store {
|
|
|
338
348
|
|
|
339
349
|
// Filter takes in a function that will be used to filter the data
|
|
340
350
|
// This will also keep optgroups of sub options meet the filter requirements
|
|
341
|
-
public filter(filter: { (opt: Option): boolean } | null, includeOptgroup: boolean):
|
|
342
|
-
const dataSearch:
|
|
343
|
-
this.data.forEach((dataObj:
|
|
351
|
+
public filter(filter: { (opt: Option): boolean } | null, includeOptgroup: boolean): (Option | Optgroup)[] {
|
|
352
|
+
const dataSearch: (Option | Optgroup)[] = []
|
|
353
|
+
this.data.forEach((dataObj: Option | Optgroup) => {
|
|
344
354
|
// Optgroup
|
|
345
355
|
if (dataObj instanceof Optgroup) {
|
|
346
356
|
let optOptions: Option[] = []
|
|
347
|
-
dataObj.options
|
|
348
|
-
|
|
357
|
+
let options = dataObj.options as Option[]
|
|
358
|
+
options.forEach((option: Option) => {
|
|
359
|
+
if (!filter || filter(option as Option)) {
|
|
349
360
|
// If you dont want to include optgroups
|
|
350
361
|
// just push to the dataSearch array
|
|
351
362
|
if (!includeOptgroup) {
|