slim-select 3.4.3 → 3.6.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/dist/classes.d.ts +47 -0
- package/dist/helpers.d.ts +5 -0
- package/dist/index.d.ts +53 -319
- package/dist/index.umd.d.ts +2 -0
- package/dist/react/index.d.ts +4 -319
- package/dist/react/index.js +1471 -1697
- package/dist/react/index.umd.js +2 -2
- package/dist/react/react.d.ts +17 -0
- package/dist/react/react.test.d.ts +1 -0
- package/dist/react/slim-select/react/index.d.ts +4 -0
- package/dist/render.d.ts +90 -0
- package/dist/select.d.ts +38 -0
- package/dist/settings.d.ts +40 -0
- package/dist/slimselect.cjs.js +2 -2
- package/dist/slimselect.cjs.js.map +1 -1
- package/dist/slimselect.css +1 -1
- package/dist/slimselect.css.map +1 -1
- package/dist/slimselect.es.js +1245 -1385
- package/dist/slimselect.es.js.map +1 -1
- package/dist/slimselect.iife.js +2 -2
- package/dist/slimselect.iife.js.map +1 -1
- package/dist/slimselect.js +2 -2
- package/dist/slimselect.js.map +1 -1
- package/dist/src/docs/main.d.ts +0 -0
- package/dist/src/docs/router.d.ts +2 -0
- package/dist/src/docs/store.d.ts +12 -0
- package/dist/store.d.ts +53 -0
- package/dist/vue/index.d.ts +4 -319
- package/dist/vue/index.js +1347 -1504
- package/dist/vue/index.umd.js +1 -1
- package/dist/vue/slim-select/vue/index.d.ts +4 -0
- package/package.json +30 -36
- package/src/slim-select/slimselect.scss +47 -5
- package/.nvmrc +0 -1
- package/.prettierignore +0 -1
- package/.prettierrc +0 -7
- package/CODE_OF_CONDUCT.md +0 -46
- package/CONTRIBUTING.md +0 -1
- package/cdn.html +0 -21
- package/docs.go +0 -12
- package/example.html +0 -25
- package/index.html +0 -76
- package/release.js +0 -191
- package/sitemap.js +0 -108
- package/src/slim-select/accessibility.test.ts +0 -782
- package/src/slim-select/classes.test.ts +0 -73
- package/src/slim-select/classes.ts +0 -117
- package/src/slim-select/helpers.test.ts +0 -162
- package/src/slim-select/helpers.ts +0 -61
- package/src/slim-select/index.test.ts +0 -1356
- package/src/slim-select/index.ts +0 -594
- package/src/slim-select/index.umd.ts +0 -8
- package/src/slim-select/react/index.tsx +0 -9
- package/src/slim-select/react/react.test.tsx +0 -498
- package/src/slim-select/react/react.tsx +0 -209
- package/src/slim-select/render.test.ts +0 -1927
- package/src/slim-select/render.ts +0 -1771
- package/src/slim-select/select.test.ts +0 -683
- package/src/slim-select/select.ts +0 -659
- package/src/slim-select/settings.test.ts +0 -285
- package/src/slim-select/settings.ts +0 -78
- package/src/slim-select/store.test.ts +0 -1007
- package/src/slim-select/store.ts +0 -433
- package/src/slim-select/vue/index.ts +0 -9
- package/src/slim-select/vue/vue.test.ts +0 -1091
- package/src/slim-select/vue/vue.vue +0 -224
- package/tsconfig.json +0 -26
- package/vite.config.docs.mts +0 -29
- package/vite.config.lib.es-cjs.ts +0 -40
- package/vite.config.lib.umd-iife.ts +0 -34
- package/vite.config.react.mts +0 -41
- package/vite.config.vue.mts +0 -40
- package/vitest.config.ts +0 -30
|
@@ -1,285 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
import { describe, expect, test, beforeEach } from 'vitest'
|
|
4
|
-
import Settings from './settings'
|
|
5
|
-
import Select from './select'
|
|
6
|
-
import { Option, Optgroup } from './store'
|
|
7
|
-
|
|
8
|
-
const defaultSettings: { [key: string]: any } = {
|
|
9
|
-
id: 'ss-qucyuytu',
|
|
10
|
-
style: '',
|
|
11
|
-
class: [],
|
|
12
|
-
isMultiple: false,
|
|
13
|
-
isOpen: false,
|
|
14
|
-
isFullOpen: false,
|
|
15
|
-
intervalMove: null,
|
|
16
|
-
disabled: false,
|
|
17
|
-
alwaysOpen: false,
|
|
18
|
-
showSearch: true,
|
|
19
|
-
focusSearch: true,
|
|
20
|
-
keepSearch: false,
|
|
21
|
-
ariaLabel: 'Combobox',
|
|
22
|
-
searchPlaceholder: 'Search...',
|
|
23
|
-
searchText: 'No Results',
|
|
24
|
-
searchingText: 'Searching...',
|
|
25
|
-
searchHighlight: false,
|
|
26
|
-
closeOnSelect: true,
|
|
27
|
-
contentLocation: HTMLBodyElement,
|
|
28
|
-
contentPosition: 'absolute',
|
|
29
|
-
openPosition: 'auto',
|
|
30
|
-
placeholderText: 'Select Value',
|
|
31
|
-
allowDeselect: false,
|
|
32
|
-
hideSelected: false,
|
|
33
|
-
keepOrder: false,
|
|
34
|
-
showOptionTooltips: false,
|
|
35
|
-
minSelected: 0,
|
|
36
|
-
maxSelected: 1000,
|
|
37
|
-
timeoutDelay: 200,
|
|
38
|
-
maxValuesShown: 20,
|
|
39
|
-
maxValuesMessage: '{number} selected',
|
|
40
|
-
contentWidth: ''
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
describe('Settings module', () => {
|
|
44
|
-
let select: Select
|
|
45
|
-
|
|
46
|
-
beforeEach(() => {
|
|
47
|
-
const selectElement = document.createElement('select')
|
|
48
|
-
select = new Select(selectElement)
|
|
49
|
-
})
|
|
50
|
-
|
|
51
|
-
test('empty constructor returns default settings', () => {
|
|
52
|
-
// Convert to unknown and then to custom object to prevent TS from throwing errors
|
|
53
|
-
const settings = new Settings() as unknown as { [key: string]: string }
|
|
54
|
-
Object.keys(defaultSettings).forEach((key) => {
|
|
55
|
-
if (key === 'id') {
|
|
56
|
-
expect(settings[key].substring(0, 3)).toBe('ss-')
|
|
57
|
-
} else if (key === 'contentLocation') {
|
|
58
|
-
expect(settings[key]).toBeInstanceOf(defaultSettings[key])
|
|
59
|
-
} else {
|
|
60
|
-
expect(settings[key]).toStrictEqual(defaultSettings[key])
|
|
61
|
-
}
|
|
62
|
-
})
|
|
63
|
-
})
|
|
64
|
-
|
|
65
|
-
test('settings can be overwritten via the constructor', () => {
|
|
66
|
-
const customSettings = {
|
|
67
|
-
disabled: true,
|
|
68
|
-
alwaysOpen: true,
|
|
69
|
-
showSearch: false,
|
|
70
|
-
focusSearch: true,
|
|
71
|
-
searchHighlight: true,
|
|
72
|
-
closeOnSelect: false,
|
|
73
|
-
placeholderText: 'new placeholder',
|
|
74
|
-
hideSelected: true,
|
|
75
|
-
keepOrder: true,
|
|
76
|
-
showOptionTooltips: true
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
const settingsWithOverride = {
|
|
80
|
-
...defaultSettings,
|
|
81
|
-
...customSettings
|
|
82
|
-
} as unknown as { [key: string]: any }
|
|
83
|
-
|
|
84
|
-
// Convert to unknown and then to custom object to prevent TS from throwing errors
|
|
85
|
-
const settings = new Settings(customSettings) as unknown as { [key: string]: any }
|
|
86
|
-
Object.keys(settingsWithOverride).forEach((key) => {
|
|
87
|
-
if (key === 'id') {
|
|
88
|
-
expect(settings[key].substring(0, 3)).toBe('ss-')
|
|
89
|
-
} else if (key === 'contentLocation') {
|
|
90
|
-
expect(settings[key]).toBeInstanceOf(defaultSettings[key])
|
|
91
|
-
} else {
|
|
92
|
-
expect(settings[key]).toStrictEqual(settingsWithOverride[key])
|
|
93
|
-
}
|
|
94
|
-
})
|
|
95
|
-
})
|
|
96
|
-
|
|
97
|
-
test('enable', () => {
|
|
98
|
-
select.select.disabled = true
|
|
99
|
-
|
|
100
|
-
select.enable()
|
|
101
|
-
expect(select.select.disabled).toBe(false)
|
|
102
|
-
})
|
|
103
|
-
|
|
104
|
-
test('disable', () => {
|
|
105
|
-
select.select.disabled = false
|
|
106
|
-
|
|
107
|
-
select.disable()
|
|
108
|
-
expect(select.select.disabled).toBe(true)
|
|
109
|
-
})
|
|
110
|
-
|
|
111
|
-
test('showUI', () => {
|
|
112
|
-
select.select.setAttribute('tabindex', '1')
|
|
113
|
-
select.select.setAttribute('aria-hidden', 'true')
|
|
114
|
-
select.select.style.position = 'absolute'
|
|
115
|
-
select.select.style.width = '0'
|
|
116
|
-
select.select.style.opacity = '0'
|
|
117
|
-
select.select.style.margin = '0'
|
|
118
|
-
select.select.style.padding = '0'
|
|
119
|
-
select.select.style.borderWidth = '0'
|
|
120
|
-
|
|
121
|
-
select.showUI()
|
|
122
|
-
expect(select.select.getAttribute('tabindex')).toBeFalsy()
|
|
123
|
-
expect(select.select.getAttribute('aria-hidden')).toBeFalsy()
|
|
124
|
-
expect(select.select.style.position).toBeFalsy()
|
|
125
|
-
expect(select.select.style.width).toBeFalsy()
|
|
126
|
-
expect(select.select.style.opacity).toBeFalsy()
|
|
127
|
-
expect(select.select.style.margin).toBeFalsy()
|
|
128
|
-
expect(select.select.style.padding).toBeFalsy()
|
|
129
|
-
// borderWidth gets reset
|
|
130
|
-
})
|
|
131
|
-
|
|
132
|
-
describe('createOptgroup', () => {
|
|
133
|
-
test('group gets created correctly', () => {
|
|
134
|
-
const optGroup = new Optgroup({
|
|
135
|
-
label: 'test',
|
|
136
|
-
options: [
|
|
137
|
-
{
|
|
138
|
-
text: 'opt 1'
|
|
139
|
-
},
|
|
140
|
-
{
|
|
141
|
-
text: 'opt 2'
|
|
142
|
-
}
|
|
143
|
-
]
|
|
144
|
-
})
|
|
145
|
-
|
|
146
|
-
const optGroupElement = select.createOptgroup(optGroup)
|
|
147
|
-
|
|
148
|
-
expect(optGroupElement).toBeInstanceOf(HTMLOptGroupElement)
|
|
149
|
-
expect(optGroupElement.children).toHaveLength(2)
|
|
150
|
-
})
|
|
151
|
-
|
|
152
|
-
test('selectAll get set correctly', () => {
|
|
153
|
-
const optGroup = new Optgroup({
|
|
154
|
-
label: 'test',
|
|
155
|
-
selectAll: true,
|
|
156
|
-
options: [
|
|
157
|
-
{
|
|
158
|
-
text: 'opt 1'
|
|
159
|
-
},
|
|
160
|
-
{
|
|
161
|
-
text: 'opt 2'
|
|
162
|
-
}
|
|
163
|
-
]
|
|
164
|
-
})
|
|
165
|
-
|
|
166
|
-
const optGroupElement = select.createOptgroup(optGroup)
|
|
167
|
-
|
|
168
|
-
expect(optGroupElement).toBeInstanceOf(HTMLOptGroupElement)
|
|
169
|
-
expect(optGroupElement.dataset.selectAll).toBe('true')
|
|
170
|
-
})
|
|
171
|
-
|
|
172
|
-
test('closable get set correctly', () => {
|
|
173
|
-
const optGroup = new Optgroup({
|
|
174
|
-
label: 'test',
|
|
175
|
-
closable: 'open',
|
|
176
|
-
options: [
|
|
177
|
-
{
|
|
178
|
-
text: 'opt 1'
|
|
179
|
-
},
|
|
180
|
-
{
|
|
181
|
-
text: 'opt 2'
|
|
182
|
-
}
|
|
183
|
-
]
|
|
184
|
-
})
|
|
185
|
-
|
|
186
|
-
const optGroupElement = select.createOptgroup(optGroup)
|
|
187
|
-
|
|
188
|
-
expect(optGroupElement).toBeInstanceOf(HTMLOptGroupElement)
|
|
189
|
-
expect(optGroupElement.dataset.closable).toBe(optGroup.closable)
|
|
190
|
-
})
|
|
191
|
-
})
|
|
192
|
-
|
|
193
|
-
describe('createOption', () => {
|
|
194
|
-
test('correct content is set', () => {
|
|
195
|
-
const option = new Option({ text: 'opt' })
|
|
196
|
-
const optionElement = select.createOption(option)
|
|
197
|
-
|
|
198
|
-
expect(optionElement).toBeInstanceOf(HTMLOptionElement)
|
|
199
|
-
expect(optionElement.id).toBe(option.id)
|
|
200
|
-
expect(optionElement.textContent).toBe(option.text)
|
|
201
|
-
})
|
|
202
|
-
|
|
203
|
-
test('HTML is set as data attribute', () => {
|
|
204
|
-
const option = new Option({ text: 'opt', html: '<h1>opt</h1>' })
|
|
205
|
-
const optionElement = select.createOption(option)
|
|
206
|
-
|
|
207
|
-
expect(optionElement.dataset.html).toBe(option.html)
|
|
208
|
-
})
|
|
209
|
-
|
|
210
|
-
test('malicious text is inserted with innerText', () => {
|
|
211
|
-
// decoded text: <img src=x onerror=alert(1)></img>
|
|
212
|
-
const str =
|
|
213
|
-
'<img src=x onerror=alert(1)></img>'
|
|
214
|
-
// const str = 'opt'
|
|
215
|
-
const decode = (string: string | null) => {
|
|
216
|
-
if (string === null) return ''
|
|
217
|
-
const doc = new DOMParser().parseFromString(string, 'text/html')
|
|
218
|
-
return doc.documentElement.textContent
|
|
219
|
-
}
|
|
220
|
-
const option = new Option({ text: str })
|
|
221
|
-
const optionElement = select.createOption(option)
|
|
222
|
-
// expect(decode(optionElement.textContent)).toBe('opt')
|
|
223
|
-
expect(optionElement.textContent).toBe(str)
|
|
224
|
-
})
|
|
225
|
-
|
|
226
|
-
test('disabled sets disabled property correctly', () => {
|
|
227
|
-
const option = new Option({ text: 'opt', disabled: true })
|
|
228
|
-
const optionElement = select.createOption(option)
|
|
229
|
-
|
|
230
|
-
expect(optionElement.disabled).toBe(true)
|
|
231
|
-
})
|
|
232
|
-
|
|
233
|
-
test('display false sets inline style correctly', () => {
|
|
234
|
-
const option = new Option({ text: 'opt', display: false })
|
|
235
|
-
const optionElement = select.createOption(option)
|
|
236
|
-
|
|
237
|
-
expect(optionElement.style.display).toBe('none')
|
|
238
|
-
})
|
|
239
|
-
|
|
240
|
-
test('placeholder and mandatory set data attributes correctly', () => {
|
|
241
|
-
const option = new Option({
|
|
242
|
-
text: 'opt',
|
|
243
|
-
placeholder: true,
|
|
244
|
-
mandatory: true
|
|
245
|
-
})
|
|
246
|
-
const optionElement = select.createOption(option)
|
|
247
|
-
|
|
248
|
-
expect(optionElement.dataset.placeholder).toBeTruthy()
|
|
249
|
-
expect(optionElement.dataset.mandatory).toBeTruthy()
|
|
250
|
-
})
|
|
251
|
-
|
|
252
|
-
test('class sets CSS classes correctly', () => {
|
|
253
|
-
const option = new Option({
|
|
254
|
-
text: 'opt',
|
|
255
|
-
class: 'class0 class1 class2'
|
|
256
|
-
})
|
|
257
|
-
const optionElement = select.createOption(option)
|
|
258
|
-
|
|
259
|
-
expect(optionElement.classList.contains('class0')).toBe(true)
|
|
260
|
-
expect(optionElement.classList.contains('class1')).toBe(true)
|
|
261
|
-
expect(optionElement.classList.contains('class2')).toBe(true)
|
|
262
|
-
})
|
|
263
|
-
|
|
264
|
-
test('custom data attributes are set correctly', () => {
|
|
265
|
-
const option = new Option({
|
|
266
|
-
text: 'opt',
|
|
267
|
-
data: {
|
|
268
|
-
test0: 'a',
|
|
269
|
-
test1: 'b'
|
|
270
|
-
}
|
|
271
|
-
})
|
|
272
|
-
const optionElement = select.createOption(option)
|
|
273
|
-
|
|
274
|
-
expect(optionElement.dataset.test0).toBe('a')
|
|
275
|
-
expect(optionElement.dataset.test1).toBe('b')
|
|
276
|
-
})
|
|
277
|
-
})
|
|
278
|
-
|
|
279
|
-
test('destroy', () => {
|
|
280
|
-
select.destroy()
|
|
281
|
-
|
|
282
|
-
expect((<any>select).observer).toBeFalsy()
|
|
283
|
-
expect('id' in select.select.dataset).toBeFalsy()
|
|
284
|
-
})
|
|
285
|
-
})
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
import { generateID } from './helpers'
|
|
2
|
-
|
|
3
|
-
export default class Settings {
|
|
4
|
-
public id: string = '' // Primary ID for the select
|
|
5
|
-
public style: string = '' // Style attribute from the select element
|
|
6
|
-
public class: string[] = [] // Class attribute from the select element
|
|
7
|
-
|
|
8
|
-
// Dynamic settings
|
|
9
|
-
public isMultiple: boolean = false
|
|
10
|
-
public isOpen: boolean = false
|
|
11
|
-
public isFullOpen: boolean = false
|
|
12
|
-
public intervalMove: ReturnType<typeof setInterval> | null = null
|
|
13
|
-
|
|
14
|
-
// Fields set from constructor
|
|
15
|
-
public disabled: boolean
|
|
16
|
-
public alwaysOpen: boolean
|
|
17
|
-
public showSearch: boolean
|
|
18
|
-
public focusSearch: boolean
|
|
19
|
-
public keepSearch: boolean
|
|
20
|
-
public ariaLabel: string
|
|
21
|
-
public searchPlaceholder: string
|
|
22
|
-
public searchText: string
|
|
23
|
-
public searchingText: string
|
|
24
|
-
public searchHighlight: boolean
|
|
25
|
-
public closeOnSelect: boolean
|
|
26
|
-
public contentLocation: HTMLElement | null
|
|
27
|
-
public contentPosition: 'relative' | 'absolute' | 'fixed'
|
|
28
|
-
public contentWidth: string
|
|
29
|
-
public openPosition: 'auto' | 'up' | 'down'
|
|
30
|
-
public placeholderText: string
|
|
31
|
-
public allowDeselect: boolean
|
|
32
|
-
public hideSelected: boolean
|
|
33
|
-
public keepOrder: boolean
|
|
34
|
-
public showOptionTooltips: boolean
|
|
35
|
-
public minSelected: number
|
|
36
|
-
public maxSelected: number
|
|
37
|
-
public timeoutDelay: number
|
|
38
|
-
public maxValuesShown: number
|
|
39
|
-
public maxValuesMessage: string
|
|
40
|
-
public addableText: string
|
|
41
|
-
|
|
42
|
-
constructor(settings?: Partial<Settings>) {
|
|
43
|
-
if (!settings) {
|
|
44
|
-
settings = {}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
this.id = 'ss-' + generateID()
|
|
48
|
-
this.style = settings.style || ''
|
|
49
|
-
this.class = settings.class || []
|
|
50
|
-
|
|
51
|
-
this.disabled = settings.disabled !== undefined ? settings.disabled : false
|
|
52
|
-
this.alwaysOpen = settings.alwaysOpen !== undefined ? settings.alwaysOpen : false
|
|
53
|
-
this.showSearch = settings.showSearch !== undefined ? settings.showSearch : true
|
|
54
|
-
this.focusSearch = settings.focusSearch !== undefined ? settings.focusSearch : true
|
|
55
|
-
this.keepSearch = settings.keepSearch !== undefined ? settings.keepSearch : false
|
|
56
|
-
this.ariaLabel = settings.ariaLabel || 'Combobox'
|
|
57
|
-
this.searchPlaceholder = settings.searchPlaceholder || 'Search...'
|
|
58
|
-
this.searchText = settings.searchText || 'No Results'
|
|
59
|
-
this.searchingText = settings.searchingText || 'Searching...'
|
|
60
|
-
this.searchHighlight = settings.searchHighlight !== undefined ? settings.searchHighlight : false
|
|
61
|
-
this.closeOnSelect = settings.closeOnSelect !== undefined ? settings.closeOnSelect : true
|
|
62
|
-
this.contentLocation = settings.contentLocation || document.body
|
|
63
|
-
this.contentPosition = settings.contentPosition || 'absolute'
|
|
64
|
-
this.contentWidth = settings.contentWidth || ''
|
|
65
|
-
this.openPosition = settings.openPosition || 'auto' // options: auto, up, down
|
|
66
|
-
this.placeholderText = settings.placeholderText !== undefined ? settings.placeholderText : 'Select Value'
|
|
67
|
-
this.allowDeselect = settings.allowDeselect !== undefined ? settings.allowDeselect : false
|
|
68
|
-
this.hideSelected = settings.hideSelected !== undefined ? settings.hideSelected : false
|
|
69
|
-
this.keepOrder = settings.keepOrder !== undefined ? settings.keepOrder : false
|
|
70
|
-
this.showOptionTooltips = settings.showOptionTooltips !== undefined ? settings.showOptionTooltips : false
|
|
71
|
-
this.minSelected = settings.minSelected || 0
|
|
72
|
-
this.maxSelected = settings.maxSelected || 1000
|
|
73
|
-
this.timeoutDelay = settings.timeoutDelay || 200
|
|
74
|
-
this.maxValuesShown = settings.maxValuesShown || 20
|
|
75
|
-
this.maxValuesMessage = settings.maxValuesMessage || '{number} selected'
|
|
76
|
-
this.addableText = settings.addableText || 'Press "Enter" to add {value}'
|
|
77
|
-
}
|
|
78
|
-
}
|