slim-select 1.27.0 → 2.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.
Files changed (155) hide show
  1. package/.nvmrc +1 -0
  2. package/.prettierrc +6 -0
  3. package/.vscode/extensions.json +3 -0
  4. package/.vscode/settings.json +15 -5
  5. package/README.md +2 -1
  6. package/dist/helper.d.ts +1 -4
  7. package/dist/index.d.ts +38 -58
  8. package/dist/render.d.ts +109 -0
  9. package/dist/select.d.ts +31 -20
  10. package/dist/settings.d.ts +33 -0
  11. package/dist/slimselect.cjs.js +2 -0
  12. package/dist/slimselect.cjs.js.map +1 -0
  13. package/dist/slimselect.css +1 -2
  14. package/dist/slimselect.css.map +1 -0
  15. package/dist/slimselect.es.js +2 -0
  16. package/dist/slimselect.es.js.map +1 -0
  17. package/dist/slimselect.global.js +2 -0
  18. package/dist/slimselect.global.js.map +1 -0
  19. package/dist/slimselect.js +2 -1956
  20. package/dist/slimselect.js.map +1 -0
  21. package/dist/slimselect.umd.js +2 -0
  22. package/dist/slimselect.umd.js.map +1 -0
  23. package/dist/store.d.ts +71 -0
  24. package/docs/assets/check-mark.svg +6 -0
  25. package/docs/assets/data.js +59 -0
  26. package/docs/assets/home.css +1 -0
  27. package/docs/assets/home.js +1 -0
  28. package/docs/assets/index.css +1 -0
  29. package/docs/assets/index.js +16 -0
  30. package/docs/assets/index2.js +274 -0
  31. package/docs/assets/index3.js +126 -0
  32. package/docs/assets/index4.js +60 -0
  33. package/docs/assets/install.js +34 -0
  34. package/docs/assets/selects.js +55 -0
  35. package/docs/index.html +18 -5
  36. package/docs.go +3 -1
  37. package/index.html +16 -0
  38. package/jest.config.js +7 -0
  39. package/package.json +39 -39
  40. package/src/docs/app.vue +185 -76
  41. package/src/docs/assets/scss/_variables.scss +26 -10
  42. package/src/docs/assets/scss/alert.scss +12 -0
  43. package/src/docs/assets/scss/animations.scss +5 -3
  44. package/src/docs/assets/scss/button.scss +21 -0
  45. package/src/docs/assets/scss/index.scss +8 -6
  46. package/src/docs/assets/scss/input.scss +2 -2
  47. package/src/docs/assets/scss/layout.scss +195 -65
  48. package/src/docs/assets/scss/misc.scss +144 -34
  49. package/src/docs/assets/scss/prism.scss +155 -153
  50. package/src/docs/env.d.ts +12 -0
  51. package/src/docs/images/check-mark.svg +6 -0
  52. package/src/docs/images/chrome.svg +22 -0
  53. package/src/docs/images/firefox.svg +58 -0
  54. package/src/docs/images/github.png +0 -0
  55. package/src/docs/images/ie.svg +11 -0
  56. package/src/docs/images/npm.png +0 -0
  57. package/src/docs/images/opera.svg +15 -0
  58. package/src/docs/images/safari.svg +22 -0
  59. package/src/docs/main.ts +27 -0
  60. package/src/docs/pages/data.vue +130 -0
  61. package/src/docs/pages/events/addable.vue +79 -0
  62. package/src/docs/pages/events/before_after_change.vue +140 -0
  63. package/src/docs/pages/events/before_after_open_close.vue +122 -0
  64. package/src/docs/pages/events/error.vue +59 -0
  65. package/src/docs/pages/events/index.vue +33 -0
  66. package/src/docs/pages/events/search.vue +154 -0
  67. package/src/docs/pages/events/search_filter.vue +45 -0
  68. package/src/docs/pages/home.vue +96 -116
  69. package/src/docs/pages/install.vue +47 -74
  70. package/src/docs/pages/methods/destroy.vue +66 -0
  71. package/src/docs/pages/methods/enable_disable.vue +70 -0
  72. package/src/docs/pages/methods/get_data.vue +81 -0
  73. package/src/docs/pages/methods/get_selected.vue +78 -0
  74. package/src/docs/pages/methods/index.vue +36 -0
  75. package/src/docs/pages/methods/open_close.vue +63 -0
  76. package/src/docs/pages/methods/search.vue +62 -0
  77. package/src/docs/pages/methods/set_data.vue +106 -0
  78. package/src/docs/pages/methods/set_selected.vue +70 -0
  79. package/src/docs/pages/selects.vue +108 -114
  80. package/src/docs/pages/settings/always_open.vue +88 -0
  81. package/src/docs/pages/settings/close_on_select.vue +69 -0
  82. package/src/docs/pages/settings/content_location.vue +64 -0
  83. package/src/docs/pages/settings/content_position.vue +86 -0
  84. package/src/docs/pages/settings/css.vue +73 -0
  85. package/src/docs/pages/settings/data_attributes.vue +39 -0
  86. package/src/docs/pages/settings/deselect.vue +69 -0
  87. package/src/docs/pages/settings/display.vue +88 -0
  88. package/src/docs/pages/settings/hide_selected.vue +73 -0
  89. package/src/docs/pages/settings/html.vue +86 -0
  90. package/src/docs/pages/settings/index.vue +73 -0
  91. package/src/docs/pages/settings/mandatory.vue +91 -0
  92. package/src/docs/pages/settings/min_max.vue +61 -0
  93. package/src/docs/pages/settings/open_position.vue +60 -0
  94. package/src/docs/pages/settings/placeholder.vue +72 -0
  95. package/src/docs/pages/settings/search.vue +140 -0
  96. package/src/docs/pages/settings/select.vue +32 -0
  97. package/src/docs/pages/settings/select_by_group.vue +46 -0
  98. package/src/docs/pages/settings/show_tooltip.vue +44 -0
  99. package/src/docs/pages/settings/styles.vue +51 -0
  100. package/src/docs/router.ts +41 -13
  101. package/src/slim-select/helper.ts +25 -86
  102. package/src/slim-select/index.ts +318 -413
  103. package/src/slim-select/render.test.ts +39 -0
  104. package/src/slim-select/render.ts +1129 -0
  105. package/src/slim-select/rollup.config.mjs +39 -0
  106. package/src/slim-select/select.test.ts +155 -0
  107. package/src/slim-select/select.ts +280 -107
  108. package/src/slim-select/settings.ts +68 -0
  109. package/src/slim-select/slimselect.scss +263 -278
  110. package/src/slim-select/store.test.ts +220 -0
  111. package/src/slim-select/store.ts +320 -0
  112. package/src/slim-select/tsconfig.json +11 -5
  113. package/src/vue/slimselect.vue +61 -0
  114. package/tsconfig.json +10 -29
  115. package/vite.config.ts +18 -0
  116. package/.browserslistrc +0 -4
  117. package/.postcssrc.js +0 -5
  118. package/.travis.yml +0 -22
  119. package/babel.config.js +0 -5
  120. package/dist/config.d.ts +0 -83
  121. package/dist/data.d.ts +0 -50
  122. package/dist/slim.d.ts +0 -50
  123. package/dist/slimselect.min.css +0 -1
  124. package/dist/slimselect.min.js +0 -1
  125. package/dist/slimselect.min.mjs +0 -1
  126. package/docs/css/app.d5840d21.css +0 -1
  127. package/docs/css/chunk-vendors.4db6930d.css +0 -1
  128. package/docs/css/home.57020178.css +0 -1
  129. package/docs/css/install.baa5d3fb.css +0 -1
  130. package/docs/css/methods.728c742a.css +0 -1
  131. package/docs/css/options.b28a32ef.css +0 -1
  132. package/docs/css/selects.1a7e1e6a.css +0 -1
  133. package/docs/js/app.db13c724.js +0 -2
  134. package/docs/js/app.db13c724.js.map +0 -1
  135. package/docs/js/chunk-vendors.cc40aa28.js +0 -28
  136. package/docs/js/chunk-vendors.cc40aa28.js.map +0 -1
  137. package/docs/js/home.8bcb44fd.js +0 -2
  138. package/docs/js/home.8bcb44fd.js.map +0 -1
  139. package/docs/js/install.02f31028.js +0 -2
  140. package/docs/js/install.02f31028.js.map +0 -1
  141. package/docs/js/methods.1b31e988.js +0 -11
  142. package/docs/js/methods.1b31e988.js.map +0 -1
  143. package/docs/js/options.39fe1005.js +0 -2
  144. package/docs/js/options.39fe1005.js.map +0 -1
  145. package/docs/js/selects.f4d0b859.js +0 -2
  146. package/docs/js/selects.f4d0b859.js.map +0 -1
  147. package/src/docs/pages/methods.vue +0 -427
  148. package/src/docs/pages/options.vue +0 -1480
  149. package/src/main.ts +0 -29
  150. package/src/shims-vue.d.ts +0 -8
  151. package/src/slim-select/config.ts +0 -118
  152. package/src/slim-select/data.ts +0 -377
  153. package/src/slim-select/slim.ts +0 -770
  154. package/tslint.json +0 -26
  155. package/vue.config.js +0 -23
@@ -0,0 +1,220 @@
1
+ 'use strict'
2
+
3
+ import { describe, expect, test } from '@jest/globals'
4
+ import Store, { Optgroup, Option } from './store'
5
+
6
+ describe('store module', () => {
7
+ test('constructor', () => {
8
+ let store = new Store('single', [])
9
+ expect(store).toBeInstanceOf(Store)
10
+ })
11
+
12
+ test('set data', () => {
13
+ let store = new Store('single', [
14
+ {
15
+ text: 'test',
16
+ },
17
+ ])
18
+
19
+ let data = store.getData()
20
+
21
+ // Make sure data has one item and that it has the correct text
22
+ expect(data.length).toBe(1)
23
+ expect((data[0] as Option).text).toBe('test')
24
+
25
+ // Make sure the data has all the default fields
26
+ expect((data[0] as Option).id).toBeDefined()
27
+ expect((data[0] as Option).value).toBeDefined()
28
+ expect((data[0] as Option).text).toBeDefined()
29
+ expect((data[0] as Option).html).toBeDefined()
30
+ expect((data[0] as Option).selected).toBeDefined()
31
+ expect((data[0] as Option).display).toBeDefined()
32
+ expect((data[0] as Option).disabled).toBeDefined()
33
+ expect((data[0] as Option).placeholder).toBeDefined()
34
+ expect((data[0] as Option).class).toBeDefined()
35
+ expect((data[0] as Option).style).toBeDefined()
36
+ expect((data[0] as Option).data).toBeDefined()
37
+ expect((data[0] as Option).mandatory).toBeDefined()
38
+ })
39
+
40
+ test('set data with optgroup', () => {
41
+ let store = new Store('single', [
42
+ {
43
+ label: 'test',
44
+ options: [
45
+ {
46
+ text: 'test',
47
+ },
48
+ ],
49
+ },
50
+ ])
51
+
52
+ let data = store.getData()
53
+
54
+ // Make sure data has one item and that it has the correct text
55
+ expect(data.length).toBe(1)
56
+ expect((data[0] as Optgroup).label).toBe('test')
57
+ expect((data[0] as Optgroup).options?.length).toBe(1)
58
+ expect((data[0] as Optgroup).options?.[0].text).toBe('test')
59
+ })
60
+
61
+ test('set data with optgroup and option', () => {
62
+ let store = new Store('single', [
63
+ {
64
+ label: 'test',
65
+ options: [
66
+ {
67
+ text: 'test',
68
+ },
69
+ ],
70
+ },
71
+ {
72
+ text: 'test',
73
+ },
74
+ ])
75
+
76
+ let data = store.getData()
77
+
78
+ // Make sure data has one item and that it has the correct text
79
+ expect(data.length).toBe(2)
80
+ expect((data[0] as Optgroup).label).toBe('test')
81
+ expect((data[0] as Optgroup).options?.length).toBe(1)
82
+ expect((data[0] as Optgroup).options?.[0].text).toBe('test')
83
+ expect((data[1] as Option).text).toBe('test')
84
+ })
85
+
86
+ test('set data and set selected by ID', () => {
87
+ let store = new Store('single', [
88
+ {
89
+ id: '8675309',
90
+ text: 'test',
91
+ },
92
+ ])
93
+ store.setSelectedBy('id', ['8675309'])
94
+
95
+ let data = store.getData()
96
+
97
+ // Make sure data has one item and that it has the correct text
98
+ expect(data.length).toBe(1)
99
+ expect((data[0] as Option).text).toBe('test')
100
+ expect((data[0] as Option).selected).toBe(true)
101
+ })
102
+
103
+ test('set data and set selected by value', () => {
104
+ let store = new Store('single', [
105
+ {
106
+ text: 'test',
107
+ value: 'hello',
108
+ },
109
+ ])
110
+ store.setSelectedBy('value', ['hello'])
111
+
112
+ let data = store.getData()
113
+
114
+ // Make sure data has one item and that it has the correct text
115
+ expect(data.length).toBe(1)
116
+ expect((data[0] as Option).text).toBe('test')
117
+ expect((data[0] as Option).selected).toBe(true)
118
+ })
119
+
120
+ test('set data and set selected by value multiple for single element', () => {
121
+ let store = new Store('single', [
122
+ {
123
+ text: 'test1',
124
+ },
125
+ {
126
+ text: 'test2',
127
+ },
128
+ ])
129
+ store.setSelectedBy('value', ['test1', 'test2'])
130
+
131
+ let data = store.getData()
132
+
133
+ // Make sure data has one item and that it has the correct text
134
+ expect(data.length).toBe(2)
135
+ expect((data[0] as Option).text).toBe('test1')
136
+ expect((data[0] as Option).selected).toBe(true)
137
+ expect((data[1] as Option).text).toBe('test2')
138
+ expect((data[1] as Option).selected).toBe(false)
139
+ })
140
+
141
+ test('set data and search', () => {
142
+ let store = new Store('single', [
143
+ {
144
+ text: 'test1',
145
+ },
146
+ {
147
+ text: 'test2',
148
+ value: 'test2',
149
+ },
150
+ {
151
+ text: 'test3',
152
+ },
153
+ ])
154
+
155
+ let data = store.getData()
156
+
157
+ const searchFilter = (opt: Option, search: string): boolean => {
158
+ return opt.text.toLowerCase().indexOf(search.toLowerCase()) !== -1
159
+ }
160
+
161
+ // With searchFilter search against current store data set
162
+ let search = store.search('test2', searchFilter)
163
+ expect(search.length).toBe(1)
164
+ expect((search[0] as Option).value).toBe('test2')
165
+ })
166
+
167
+ test('set data with non selected on single select', () => {
168
+ let store = new Store('single', [
169
+ {
170
+ text: 'test1',
171
+ },
172
+ {
173
+ text: 'test2',
174
+ value: 'test2',
175
+ },
176
+ {
177
+ text: 'test3',
178
+ },
179
+ ])
180
+
181
+ let data = store.getData()
182
+
183
+ // Make sure data has one item and that it has the correct text
184
+ expect(data.length).toBe(3)
185
+ expect((data[0] as Option).text).toBe('test1')
186
+ expect((data[0] as Option).selected).toBe(true)
187
+ expect((data[1] as Option).text).toBe('test2')
188
+ expect((data[1] as Option).selected).toBe(false)
189
+ expect((data[2] as Option).text).toBe('test3')
190
+ expect((data[2] as Option).selected).toBe(false)
191
+ })
192
+
193
+ test('set data with multiple selected on single select', () => {
194
+ let store = new Store('single', [
195
+ {
196
+ text: 'test1',
197
+ },
198
+ {
199
+ text: 'test2',
200
+ value: 'test2',
201
+ selected: true,
202
+ },
203
+ {
204
+ text: 'test3',
205
+ selected: true,
206
+ },
207
+ ])
208
+
209
+ let data = store.getData()
210
+
211
+ // Make sure data has one item and that it has the correct text
212
+ expect(data.length).toBe(3)
213
+ expect((data[0] as Option).text).toBe('test1')
214
+ expect((data[0] as Option).selected).toBe(false)
215
+ expect((data[1] as Option).text).toBe('test2')
216
+ expect((data[1] as Option).selected).toBe(true)
217
+ expect((data[2] as Option).text).toBe('test3')
218
+ expect((data[2] as Option).selected).toBe(false)
219
+ })
220
+ })
@@ -0,0 +1,320 @@
1
+ import { generateID } from './helper'
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
+ type selectType = 'single' | 'multiple'
10
+
11
+ export interface OptgroupOptional {
12
+ id?: string
13
+ label: string // Required
14
+ options?: OptionOptional[]
15
+ }
16
+
17
+ export class Optgroup {
18
+ public id: string
19
+ public label: string
20
+ public options: Option[]
21
+
22
+ constructor(optgroup: OptgroupOptional) {
23
+ this.id = !optgroup.id || optgroup.id === '' ? generateID() : optgroup.id
24
+ this.label = optgroup.label || ''
25
+
26
+ // If options exist, loop through options and create new option class
27
+ // and set the options to the optgroup options field
28
+ this.options = []
29
+ if (optgroup.options) {
30
+ for (const o of optgroup.options) {
31
+ this.options.push(new Option(o))
32
+ }
33
+ }
34
+ }
35
+ }
36
+
37
+ export interface OptionOptional {
38
+ id?: string
39
+ value?: string
40
+ text: string // Required
41
+ html?: string
42
+ selected?: boolean
43
+ display?: boolean
44
+ disabled?: boolean
45
+ mandatory?: boolean
46
+ placeholder?: boolean
47
+ class?: string
48
+ style?: string
49
+ data?: { [key: string]: string }
50
+ }
51
+
52
+ export class Option {
53
+ id: string
54
+ value: string
55
+ text: string
56
+ html: string
57
+ selected: boolean
58
+ display: boolean
59
+ disabled: boolean
60
+ placeholder: boolean
61
+ class: string
62
+ style: string
63
+ data: { [key: string]: string }
64
+ mandatory: boolean
65
+
66
+ constructor(option: OptionOptional) {
67
+ this.id = !option.id || option.id === '' ? generateID() : option.id
68
+ this.value = option.value === undefined ? option.text : option.value
69
+ this.text = option.text || ''
70
+ this.html = option.html || ''
71
+ this.selected = option.selected !== undefined ? option.selected : false
72
+ this.display = option.display !== undefined ? option.display : true
73
+ this.disabled = option.disabled !== undefined ? option.disabled : false
74
+ this.mandatory = option.mandatory !== undefined ? option.mandatory : false
75
+ this.placeholder = option.placeholder !== undefined ? option.placeholder : false
76
+ this.class = option.class || ''
77
+ this.style = option.style || ''
78
+ this.data = option.data || {}
79
+ }
80
+ }
81
+
82
+ export default class Store {
83
+ private selectType: selectType = 'single'
84
+
85
+ // Main data set, never null
86
+ private data: DataArray = []
87
+
88
+ constructor(type: selectType, data: DataArrayPartial) {
89
+ this.selectType = type
90
+ this.setData(data)
91
+ }
92
+
93
+ // Validate DataArrayPartial
94
+ public validateDataArray(data: DataArray | DataArrayPartial): Error | null {
95
+ if (!Array.isArray(data)) {
96
+ return new Error('Data must be an array')
97
+ }
98
+
99
+ // Loop through each data object
100
+ for (let dataObj of data) {
101
+ // Optgroup
102
+ if (dataObj instanceof Optgroup || 'label' in dataObj) {
103
+ if (!('label' in dataObj)) {
104
+ return new Error('Optgroup must have a label')
105
+ }
106
+
107
+ if ('options' in dataObj && dataObj.options) {
108
+ for (let option of dataObj.options) {
109
+ return this.validateOption(option)
110
+ }
111
+ }
112
+ } else if (dataObj instanceof Option || 'text' in dataObj) {
113
+ return this.validateOption(dataObj)
114
+ } else {
115
+ return new Error('Data object must be a valid optgroup or option')
116
+ }
117
+ }
118
+
119
+ return null
120
+ }
121
+
122
+ // Validate Option
123
+ public validateOption(option: Option | OptionOptional): Error | null {
124
+ if (!('text' in option)) {
125
+ return new Error('Option must have a text')
126
+ }
127
+
128
+ return null
129
+ }
130
+
131
+ public partialToFullData(data: DataArrayPartial): DataArray {
132
+ let dataFinal: DataArray = []
133
+ data.forEach((dataObj: DataObject | DataObjectPartial) => {
134
+ // Optgroup
135
+ if (dataObj instanceof Optgroup || 'label' in dataObj) {
136
+ let optOptions: Option[] = []
137
+ if ('options' in dataObj && dataObj.options) {
138
+ dataObj.options.forEach((option: Option | OptionOptional) => {
139
+ optOptions.push(new Option(option))
140
+ })
141
+ }
142
+
143
+ if (optOptions.length > 0) {
144
+ dataFinal.push(new Optgroup(dataObj))
145
+ }
146
+ }
147
+
148
+ // Option
149
+ if (dataObj instanceof Option || 'text' in dataObj) {
150
+ dataFinal.push(new Option(dataObj))
151
+ }
152
+ })
153
+
154
+ return dataFinal
155
+ }
156
+
157
+ public setData(data: DataArray | DataArrayPartial) {
158
+ this.data = this.partialToFullData(data)
159
+
160
+ // Run this.data through setSelected by value
161
+ // to set the selected property and clean any wrong selected
162
+ if (this.selectType === 'single') {
163
+ this.setSelectedBy('value', this.getSelected())
164
+ }
165
+ }
166
+
167
+ // Get data will return all the data
168
+ public getData(): DataArray {
169
+ return this.filter(null, true)
170
+ }
171
+
172
+ // Get data options will return the data as a
173
+ // flat array of just options
174
+ public getDataOptions(): Option[] {
175
+ return this.filter(null, false) as Option[]
176
+ }
177
+
178
+ public addOption(option: OptionOptional) {
179
+ this.setData(this.getData().concat(new Option(option)))
180
+ }
181
+
182
+ // Pass in an array of id that will loop through
183
+ // each option and set the selected property to true
184
+ // but also clean selected by determining selectType
185
+ public setSelectedBy(selectedType: 'id' | 'value', selectedValues: string[]) {
186
+ let firstOption: Option | null = null
187
+ let hasSelected = false
188
+
189
+ for (let dataObj of this.data) {
190
+ // Optgroup
191
+ if (dataObj instanceof Optgroup) {
192
+ for (let option of dataObj.options) {
193
+ if (!firstOption) {
194
+ firstOption = option
195
+ }
196
+
197
+ option.selected = hasSelected ? false : selectedValues.includes(option[selectedType])
198
+
199
+ // If the option is selected, set hasSelected to true
200
+ // for single based selects
201
+ if (option.selected && this.selectType === 'single') {
202
+ hasSelected = true
203
+ }
204
+ }
205
+ }
206
+
207
+ // Option
208
+ if (dataObj instanceof Option) {
209
+ if (!firstOption) {
210
+ firstOption = dataObj
211
+ }
212
+
213
+ dataObj.selected = hasSelected ? false : selectedValues.includes(dataObj[selectedType])
214
+
215
+ // If the option is selected, set hasSelected to true
216
+ // for single based selects
217
+ if (dataObj.selected && this.selectType === 'single') {
218
+ hasSelected = true
219
+ }
220
+ }
221
+ }
222
+
223
+ // If no options are selected, select the first option
224
+ if (this.selectType === 'single' && firstOption && !hasSelected) {
225
+ firstOption.selected = true
226
+ }
227
+ }
228
+
229
+ public getSelected(): string[] {
230
+ let selectedOptions = this.getSelectedOptions()
231
+ let selectedValues: string[] = []
232
+
233
+ // Loop through each option and get the value
234
+ selectedOptions.forEach((option: Option) => {
235
+ selectedValues.push(option.value)
236
+ })
237
+
238
+ return selectedValues
239
+ }
240
+
241
+ public getSelectedOptions(): Option[] {
242
+ return this.filter((opt: Option) => {
243
+ return opt.selected
244
+ }, false) as Option[]
245
+ }
246
+
247
+ public getSelectedIDs(): string[] {
248
+ let selectedOptions = this.getSelectedOptions()
249
+
250
+ let selectedIDs: string[] = []
251
+ selectedOptions.forEach((op: Option) => {
252
+ selectedIDs.push(op.id)
253
+ })
254
+
255
+ return selectedIDs
256
+ }
257
+
258
+ public getOptionByID(id: string): Option | null {
259
+ let options = this.filter((opt: Option) => {
260
+ return opt.id === id
261
+ }, false) as Option[]
262
+
263
+ return options.length ? options[0] : null
264
+ }
265
+
266
+ // Take in search string and return filtered list of values
267
+ public search(search: string, searchFilter: (opt: Option, search: string) => boolean): DataArray {
268
+ search = search.trim()
269
+
270
+ // If search is empty, return all data
271
+ if (search === '') {
272
+ return this.getData()
273
+ }
274
+
275
+ // Run filter with search function
276
+ return this.filter((opt: Option): boolean => {
277
+ return searchFilter(opt, search)
278
+ }, true)
279
+ }
280
+
281
+ // Filter takes in a function that will be used to filter the data
282
+ // This will also keep optgroups of sub options meet the filter requirements
283
+ public filter(filter: { (opt: Option): boolean } | null, includeOptgroup: boolean): DataArray {
284
+ const dataSearch: DataArray = []
285
+ this.data.forEach((dataObj: DataObject) => {
286
+ // Optgroup
287
+ if (dataObj instanceof Optgroup) {
288
+ // If you dont want to include optgroups
289
+ if (!includeOptgroup) {
290
+ // Loop through each option and check if it meets the filter requirements
291
+ dataObj.options.forEach((option: Option) => {
292
+ if (filter && filter(option)) {
293
+ dataSearch.push(option)
294
+ }
295
+ })
296
+ } else {
297
+ let optOptions: Option[] = []
298
+ dataObj.options.forEach((option: Option) => {
299
+ if (!filter || filter(option)) {
300
+ optOptions.push(new Option(option))
301
+ }
302
+ })
303
+
304
+ if (optOptions.length > 0) {
305
+ dataSearch.push(new Optgroup({ id: dataObj.id, label: dataObj.label, options: optOptions }))
306
+ }
307
+ }
308
+ }
309
+
310
+ // Option
311
+ if (dataObj instanceof Option) {
312
+ if (!filter || filter(dataObj)) {
313
+ dataSearch.push(new Option(dataObj))
314
+ }
315
+ }
316
+ })
317
+
318
+ return dataSearch
319
+ }
320
+ }
@@ -1,8 +1,14 @@
1
1
  {
2
2
  "compilerOptions": {
3
- "strict": true, /* Enable all strict type-checking options. */
4
- "declaration": true, /* Generates corresponding '.d.ts' file. */
3
+ "target": "es2016",
4
+ "module": "esnext",
5
+ "moduleResolution": "node",
6
+ "strict": true /* Enable all strict type-checking options. */,
7
+ "declaration": true /* Generates corresponding '.d.ts' file. */,
5
8
  "outDir": "../../dist", // Output to dist folder
6
- "removeComments": true /* Do not emit comments to output. */
7
- }
8
- }
9
+ "removeComments": true /* Do not emit comments to output. */,
10
+ "importHelpers": true /* Import emit helpers from 'tslib'. */
11
+ },
12
+ "include": ["**/*.ts"],
13
+ "exclude": ["**/*.test.ts"]
14
+ }
@@ -0,0 +1,61 @@
1
+ <script lang="ts">
2
+ import { defineComponent, ref, watch, onMounted, onBeforeUnmount } from 'vue'
3
+ import SlimSelect from '../slim-select'
4
+
5
+ export default defineComponent({
6
+ name: 'SlimSelect',
7
+ props: {
8
+ options: {
9
+ type: Array,
10
+ required: true,
11
+ },
12
+ value: {
13
+ type: [String, Number, Array],
14
+ required: true,
15
+ },
16
+ config: {
17
+ type: Object,
18
+ required: false,
19
+ },
20
+ },
21
+ emits: ['update:value'],
22
+ setup(props, { emit }) {
23
+ const selectRef = ref(null)
24
+ let select: SlimSelect
25
+
26
+ const updateValue = (value: string | number | string[] | number[]) => {
27
+ emit('update:value', value)
28
+ }
29
+
30
+ const updateSelect = () => {
31
+ select.set(props.value)
32
+ }
33
+
34
+ const initSelect = () => {
35
+ select = new SlimSelect(selectRef.value, {
36
+ ...props.config,
37
+ onChange: updateValue,
38
+ })
39
+ }
40
+
41
+ onMounted(() => {
42
+ initSelect()
43
+ })
44
+
45
+ onBeforeUnmount(() => {
46
+ select.destroy()
47
+ })
48
+
49
+ watch(
50
+ () => props.value,
51
+ () => {
52
+ updateSelect()
53
+ },
54
+ )
55
+
56
+ return {
57
+ selectRef,
58
+ }
59
+ }
60
+ })
61
+ </script>
package/tsconfig.json CHANGED
@@ -1,37 +1,18 @@
1
1
  {
2
2
  "compilerOptions": {
3
+ "declaration": true,
3
4
  "target": "esnext",
5
+ "useDefineForClassFields": true,
4
6
  "module": "esnext",
5
- "strict": true,
6
- "importHelpers": true,
7
7
  "moduleResolution": "node",
8
- "esModuleInterop": true,
9
- "allowSyntheticDefaultImports": true,
8
+ "strict": true,
9
+ "jsx": "preserve",
10
+ "allowJs": false,
10
11
  "sourceMap": true,
11
- "baseUrl": ".",
12
- "types": [
13
- "webpack-env"
14
- ],
15
- "paths": {
16
- "@/*": [
17
- "src/*"
18
- ]
19
- },
20
- "lib": [
21
- "esnext",
22
- "dom",
23
- "dom.iterable",
24
- "scripthost"
25
- ]
12
+ "resolveJsonModule": true,
13
+ "esModuleInterop": true,
14
+ "importHelpers": true,
15
+ "lib": ["esnext", "dom"]
26
16
  },
27
- "include": [
28
- "src/**/*.ts",
29
- "src/**/*.tsx",
30
- "src/**/*.vue",
31
- "tests/**/*.ts",
32
- "tests/**/*.tsx"
33
- ],
34
- "exclude": [
35
- "node_modules"
36
- ]
17
+ "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"]
37
18
  }
package/vite.config.ts ADDED
@@ -0,0 +1,18 @@
1
+ import vue from '@vitejs/plugin-vue'
2
+ import { defineConfig } from 'vite'
3
+
4
+ // https://vitejs.dev/config/
5
+ export default defineConfig({
6
+ build: {
7
+ outDir: 'docs',
8
+ emptyOutDir: true,
9
+ rollupOptions: {
10
+ output: {
11
+ entryFileNames: `assets/[name].js`,
12
+ chunkFileNames: `assets/[name].js`,
13
+ assetFileNames: `assets/[name].[ext]`,
14
+ },
15
+ },
16
+ },
17
+ plugins: [vue()],
18
+ })
package/.browserslistrc DELETED
@@ -1,4 +0,0 @@
1
- > 1%
2
- last 2 versions
3
- not ie <= 8
4
- ie 11
package/.postcssrc.js DELETED
@@ -1,5 +0,0 @@
1
- module.exports = {
2
- plugins: {
3
- autoprefixer: {}
4
- }
5
- }