slim-select 3.4.3 → 3.5.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.
Files changed (73) hide show
  1. package/dist/classes.d.ts +46 -0
  2. package/dist/helpers.d.ts +5 -0
  3. package/dist/index.d.ts +53 -319
  4. package/dist/index.umd.d.ts +2 -0
  5. package/dist/react/index.d.ts +4 -319
  6. package/dist/react/index.js +1459 -1697
  7. package/dist/react/index.umd.js +2 -2
  8. package/dist/react/react.d.ts +17 -0
  9. package/dist/react/react.test.d.ts +1 -0
  10. package/dist/react/slim-select/react/index.d.ts +4 -0
  11. package/dist/render.d.ts +88 -0
  12. package/dist/select.d.ts +38 -0
  13. package/dist/settings.d.ts +39 -0
  14. package/dist/slimselect.cjs.js +2 -2
  15. package/dist/slimselect.cjs.js.map +1 -1
  16. package/dist/slimselect.css +1 -1
  17. package/dist/slimselect.css.map +1 -1
  18. package/dist/slimselect.es.js +1233 -1385
  19. package/dist/slimselect.es.js.map +1 -1
  20. package/dist/slimselect.iife.js +2 -2
  21. package/dist/slimselect.iife.js.map +1 -1
  22. package/dist/slimselect.js +2 -2
  23. package/dist/slimselect.js.map +1 -1
  24. package/dist/src/docs/main.d.ts +0 -0
  25. package/dist/src/docs/router.d.ts +2 -0
  26. package/dist/src/docs/store.d.ts +12 -0
  27. package/dist/store.d.ts +53 -0
  28. package/dist/vue/index.d.ts +4 -319
  29. package/dist/vue/index.js +1335 -1504
  30. package/dist/vue/index.umd.js +1 -1
  31. package/dist/vue/slim-select/vue/index.d.ts +4 -0
  32. package/package.json +30 -36
  33. package/src/slim-select/slimselect.scss +34 -5
  34. package/.nvmrc +0 -1
  35. package/.prettierignore +0 -1
  36. package/.prettierrc +0 -7
  37. package/CODE_OF_CONDUCT.md +0 -46
  38. package/CONTRIBUTING.md +0 -1
  39. package/cdn.html +0 -21
  40. package/docs.go +0 -12
  41. package/example.html +0 -25
  42. package/index.html +0 -76
  43. package/release.js +0 -191
  44. package/sitemap.js +0 -108
  45. package/src/slim-select/accessibility.test.ts +0 -782
  46. package/src/slim-select/classes.test.ts +0 -73
  47. package/src/slim-select/classes.ts +0 -117
  48. package/src/slim-select/helpers.test.ts +0 -162
  49. package/src/slim-select/helpers.ts +0 -61
  50. package/src/slim-select/index.test.ts +0 -1356
  51. package/src/slim-select/index.ts +0 -594
  52. package/src/slim-select/index.umd.ts +0 -8
  53. package/src/slim-select/react/index.tsx +0 -9
  54. package/src/slim-select/react/react.test.tsx +0 -498
  55. package/src/slim-select/react/react.tsx +0 -209
  56. package/src/slim-select/render.test.ts +0 -1927
  57. package/src/slim-select/render.ts +0 -1771
  58. package/src/slim-select/select.test.ts +0 -683
  59. package/src/slim-select/select.ts +0 -659
  60. package/src/slim-select/settings.test.ts +0 -285
  61. package/src/slim-select/settings.ts +0 -78
  62. package/src/slim-select/store.test.ts +0 -1007
  63. package/src/slim-select/store.ts +0 -433
  64. package/src/slim-select/vue/index.ts +0 -9
  65. package/src/slim-select/vue/vue.test.ts +0 -1091
  66. package/src/slim-select/vue/vue.vue +0 -224
  67. package/tsconfig.json +0 -26
  68. package/vite.config.docs.mts +0 -29
  69. package/vite.config.lib.es-cjs.ts +0 -40
  70. package/vite.config.lib.umd-iife.ts +0 -34
  71. package/vite.config.react.mts +0 -41
  72. package/vite.config.vue.mts +0 -40
  73. package/vitest.config.ts +0 -30
@@ -1,433 +0,0 @@
1
- import { generateID } from './helpers'
2
-
3
- export class Option {
4
- id: string
5
- value: string
6
- text: string
7
- html: string
8
- defaultSelected: boolean
9
- selected: boolean
10
- display: boolean
11
- disabled: boolean
12
- placeholder: boolean
13
- class: string
14
- style: string
15
- data: { [key: string]: string }
16
- mandatory: boolean
17
-
18
- constructor(option: Partial<Option>) {
19
- this.id = !option.id || option.id === '' ? generateID() : option.id
20
- this.value = option.value === undefined ? option.text || '' : option.value || ''
21
- this.text = option.text || ''
22
- this.html = option.html || ''
23
- this.defaultSelected = option.defaultSelected !== undefined ? option.defaultSelected : false
24
- this.selected = option.selected !== undefined ? option.selected : false
25
- this.display = option.display !== undefined ? option.display : true
26
- this.disabled = option.disabled !== undefined ? option.disabled : false
27
- this.mandatory = option.mandatory !== undefined ? option.mandatory : false
28
- this.placeholder = option.placeholder !== undefined ? option.placeholder : false
29
- this.class = option.class || ''
30
- this.style = option.style || ''
31
- this.data = option.data || {}
32
- }
33
- }
34
- export class Optgroup {
35
- public id: string
36
- public label: string
37
- public selectAll: boolean
38
- public selectAllText: string
39
- public closable: 'off' | 'open' | 'close'
40
- public options: Partial<Option>[]
41
-
42
- constructor(optgroup: Partial<Optgroup>) {
43
- this.id = !optgroup.id || optgroup.id === '' ? generateID() : optgroup.id
44
- this.label = optgroup.label || ''
45
- this.selectAll = optgroup.selectAll === undefined ? false : optgroup.selectAll
46
- this.selectAllText = optgroup.selectAllText || 'Select All'
47
- this.closable = optgroup.closable || 'off'
48
-
49
- // If options exist, loop through options and create new option class
50
- // and set the options to the optgroup options field
51
- this.options = []
52
- if (optgroup.options) {
53
- for (const o of optgroup.options) {
54
- this.options.push(new Option(o))
55
- }
56
- }
57
- }
58
- }
59
-
60
- export default class Store {
61
- private selectType: 'single' | 'multiple' = 'single'
62
-
63
- // Main data set, never null
64
- private data: (Option | Optgroup)[] = []
65
- private selectedOrder: string[] = []
66
-
67
- constructor(type: 'single' | 'multiple', data: (Partial<Option> | Partial<Optgroup>)[]) {
68
- this.selectType = type
69
- this.setData(data)
70
- }
71
-
72
- // Validate DataArrayPartial
73
- public validateDataArray(data: (Partial<Option> | Partial<Optgroup>)[]): Error | null {
74
- if (!Array.isArray(data)) {
75
- return new Error('Data must be an array')
76
- }
77
-
78
- // Loop through each data object
79
- for (let dataObj of data) {
80
- if (!dataObj) continue
81
-
82
- // Optgroup
83
- if (dataObj instanceof Optgroup || 'label' in dataObj) {
84
- if (!('label' in dataObj)) {
85
- return new Error('Optgroup must have a label')
86
- }
87
-
88
- if ('options' in dataObj && dataObj.options) {
89
- for (let option of dataObj.options) {
90
- const validationError = this.validateOption(option)
91
- if (validationError) {
92
- return validationError
93
- }
94
- }
95
- }
96
- } else if (dataObj instanceof Option || 'text' in dataObj) {
97
- const validationError = this.validateOption(dataObj)
98
- if (validationError) {
99
- return validationError
100
- }
101
- } else {
102
- return new Error('Data object must be a valid optgroup or option')
103
- }
104
- }
105
-
106
- return null
107
- }
108
-
109
- // Validate Option
110
- public validateOption(option: Partial<Option>): Error | null {
111
- if (!('text' in option)) {
112
- return new Error('Option must have a text')
113
- }
114
-
115
- return null
116
- }
117
-
118
- public partialToFullData(data: (Partial<Option> | Partial<Optgroup>)[]): (Option | Optgroup)[] {
119
- let dataFinal: (Option | Optgroup)[] = []
120
- data.forEach((dataObj) => {
121
- if (!dataObj) return
122
-
123
- // Optgroup
124
- if (dataObj instanceof Optgroup || 'label' in dataObj) {
125
- let optOptions: Option[] = []
126
- if ('options' in dataObj && dataObj.options) {
127
- dataObj.options.forEach((option: Partial<Option>) => {
128
- optOptions.push(new Option(option))
129
- })
130
- }
131
-
132
- if (optOptions.length > 0) {
133
- dataFinal.push(new Optgroup(dataObj as Partial<Optgroup>))
134
- }
135
- }
136
-
137
- // Option
138
- if (dataObj instanceof Option || 'text' in dataObj) {
139
- dataFinal.push(new Option(dataObj as Partial<Option>))
140
- }
141
- })
142
-
143
- return dataFinal
144
- }
145
-
146
- public setData(data: (Partial<Option> | Partial<Optgroup>)[], preserveSelected: boolean = false) {
147
- // Convert new data to full data array
148
- const newData = this.partialToFullData(data)
149
-
150
- let selectedOptionsBeforeUpdate: Option[] = []
151
-
152
- if (preserveSelected) {
153
- // Get currently selected options before updating data
154
- selectedOptionsBeforeUpdate = this.getSelectedOptions()
155
-
156
- // Check which selected options are missing from new data
157
- const missingSelected: (Option | Optgroup)[] = []
158
- selectedOptionsBeforeUpdate.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
- }
187
-
188
- // Run this.data through setSelected by value
189
- // to set the selected property and clean any wrong selected
190
- if (this.selectType === 'single') {
191
- // When search returns new data and user had nothing selected, don't auto-select first option
192
- const allowEmptySelection = preserveSelected && selectedOptionsBeforeUpdate.length === 0
193
- this.setSelectedBy('id', this.getSelected(), allowEmptySelection)
194
- }
195
- }
196
-
197
- // Get data will return all the data
198
- public getData(): Option[] | Optgroup[] {
199
- return this.filter(null, true) as Option[] | Optgroup[]
200
- }
201
-
202
- // Get data options will return the data as a
203
- // flat array of just options
204
- public getDataOptions(): Option[] {
205
- return this.filter(null, false) as Option[]
206
- }
207
-
208
- public addOption(option: Partial<Option>, addToStart: boolean = false) {
209
- if (addToStart) {
210
- let data = [new Option(option)] as (Option | Optgroup)[]
211
- this.setData(data.concat(this.getData()))
212
- } else {
213
- this.setData(this.getData().concat(new Option(option)))
214
- }
215
- }
216
-
217
- // Pass in an array of id that will loop through
218
- // each option and set the selected property to true
219
- // but also clean selected by determining selectType
220
- // When allowEmptySelection is true (e.g. after search with no prior selection), single select will not auto-select the first option
221
- public setSelectedBy(
222
- selectedType: 'id' | 'value',
223
- selectedValues: string[],
224
- allowEmptySelection: boolean = false
225
- ) {
226
- let firstOption: Partial<Option> | null = null
227
- let hasSelected = false
228
- const selectedObjects: Partial<Option>[] = []
229
-
230
- for (let dataObj of this.data) {
231
- // Optgroup
232
- if (dataObj instanceof Optgroup) {
233
- for (let option of dataObj.options as Partial<Option>[]) {
234
- if (!firstOption) {
235
- firstOption = option
236
- }
237
-
238
- let optionValue = option[selectedType] || ''
239
- option.selected = hasSelected ? false : selectedValues.includes(optionValue)
240
-
241
- // If the option is selected, set hasSelected to true
242
- // for single based selects
243
- if (option.selected) {
244
- selectedObjects.push(option)
245
-
246
- if (this.selectType === 'single') {
247
- hasSelected = true
248
- }
249
- }
250
- }
251
- }
252
-
253
- // Option
254
- if (dataObj instanceof Option) {
255
- if (!firstOption) {
256
- firstOption = dataObj
257
- }
258
-
259
- dataObj.selected = hasSelected ? false : selectedValues.includes(dataObj[selectedType])
260
-
261
- // If the option is selected, set hasSelected to true
262
- // for single based selects
263
- if (dataObj.selected) {
264
- selectedObjects.push(dataObj)
265
-
266
- if (this.selectType === 'single') {
267
- hasSelected = true
268
- }
269
- }
270
- }
271
- }
272
-
273
- // If no options are selected, select the first option (unless allowEmptySelection, e.g. after search with no selection)
274
- if (
275
- this.selectType === 'single' &&
276
- firstOption &&
277
- !hasSelected &&
278
- !allowEmptySelection
279
- ) {
280
- firstOption.selected = true
281
- selectedObjects.push(firstOption)
282
- }
283
-
284
- // Put together a list of selected ids in the order of the selected values
285
- const selectedIds = selectedValues.map((value) => {
286
- return selectedObjects.find((option) => option[selectedType] === value)?.id || ''
287
- })
288
-
289
- this.selectedOrder = selectedIds
290
- }
291
-
292
- public getSelected(): string[] {
293
- return this.getSelectedOptions().map((option) => option.id)
294
- }
295
-
296
- public getSelectedValues(): string[] {
297
- return this.getSelectedOptions().map((option) => option.value)
298
- }
299
-
300
- public getSelectedOptions(): Option[] {
301
- return this.filter((opt: Option) => {
302
- return opt.selected
303
- }, false) as Option[]
304
- }
305
-
306
- public getOptgroupByID(id: string): Optgroup | null {
307
- // Loop through each data object
308
- // and if optgroup is found, return it
309
- for (let dataObj of this.data) {
310
- if (dataObj instanceof Optgroup && dataObj.id === id) {
311
- return dataObj
312
- }
313
- }
314
-
315
- return null
316
- }
317
-
318
- public getOptionByID(id: string): Option | null {
319
- let options = this.filter((opt: Option) => {
320
- return opt.id === id
321
- }, false) as Option[]
322
-
323
- return options.length ? options[0] : null
324
- }
325
-
326
- public getSelectType(): string {
327
- return this.selectType
328
- }
329
-
330
- public getFirstOption(): Option | null {
331
- let option: Option | null = null
332
- for (let dataObj of this.data) {
333
- if (dataObj instanceof Optgroup) {
334
- option = dataObj.options[0] as Option
335
- } else if (dataObj instanceof Option) {
336
- option = dataObj
337
- }
338
-
339
- if (option) {
340
- break
341
- }
342
- }
343
- return option
344
- }
345
-
346
- // Take in search string and return filtered list of values
347
- public search(search: string, searchFilter: (opt: Option, search: string) => boolean): (Option | Optgroup)[] {
348
- search = search.trim()
349
-
350
- // If search is empty, return all data
351
- if (search === '') {
352
- return this.getData()
353
- }
354
-
355
- // Run filter with search function
356
- return this.filter((opt: Option): boolean => {
357
- return searchFilter(opt, search)
358
- }, true)
359
- }
360
-
361
- // Filter takes in a function that will be used to filter the data
362
- // This will also keep optgroups of sub options meet the filter requirements
363
- public filter(filter: { (opt: Option): boolean } | null, includeOptgroup: boolean): (Option | Optgroup)[] {
364
- const dataSearch: (Option | Optgroup)[] = []
365
- this.data.forEach((dataObj: Option | Optgroup) => {
366
- // Optgroup
367
- if (dataObj instanceof Optgroup) {
368
- let optOptions: Option[] = []
369
- let options = dataObj.options as Option[]
370
- options.forEach((option: Option) => {
371
- if (!filter || filter(option as Option)) {
372
- // If you dont want to include optgroups
373
- // just push to the dataSearch array
374
- if (!includeOptgroup) {
375
- dataSearch.push(new Option(option))
376
- } else {
377
- optOptions.push(new Option(option))
378
- }
379
- }
380
- })
381
-
382
- // If we pushed any options to the optOptions array
383
- // push the optgroup to the dataSearch array
384
- if (optOptions.length > 0) {
385
- // Create new optgroup with the new options
386
- let optgroup = new Optgroup(dataObj)
387
- optgroup.options = optOptions
388
-
389
- // Push optgroup to dataSearch
390
- dataSearch.push(optgroup)
391
- }
392
- }
393
-
394
- // Option
395
- if (dataObj instanceof Option) {
396
- if (!filter || filter(dataObj)) {
397
- dataSearch.push(new Option(dataObj))
398
- }
399
- }
400
- })
401
-
402
- return dataSearch
403
- }
404
-
405
- // Take in an array of options and reoder them based upon the selected order
406
- public selectedOrderOptions(options: Option[]): Option[] {
407
- const newOrder: Option[] = []
408
- this.selectedOrder.forEach((id) => {
409
- const option = options.find((opt) => opt.id === id)
410
- if (option) {
411
- newOrder.push(option)
412
- }
413
- })
414
-
415
- // add any remaining options that were not in the selected order
416
- options.forEach((option) => {
417
- let isIn = false
418
- newOrder.forEach((selectedOption) => {
419
- if (option.id === selectedOption.id) {
420
- isIn = true
421
-
422
- return
423
- }
424
- })
425
-
426
- if (!isIn) {
427
- newOrder.push(option)
428
- }
429
- })
430
-
431
- return newOrder
432
- }
433
- }
@@ -1,9 +0,0 @@
1
- import SlimSelect from './vue.vue'
2
-
3
- export default SlimSelect
4
-
5
- // Re-export classes
6
- export { Settings, Option, Optgroup } from '../index'
7
-
8
- // Re-export types
9
- export type { Config, Events } from '../index'