slim-select 2.8.2 → 2.9.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/.prettierignore +1 -0
- package/.prettierrc +4 -3
- package/README.md +2 -0
- package/dist/classes.d.ts +43 -0
- package/dist/helpers.d.ts +1 -1
- package/dist/index.d.ts +5 -2
- package/dist/render.d.ts +4 -44
- package/dist/select.d.ts +4 -2
- package/dist/settings.d.ts +2 -1
- package/dist/slimselect.cjs.js +248 -120
- package/dist/slimselect.css +1 -1
- package/dist/slimselect.css.map +1 -1
- package/dist/slimselect.es.js +248 -120
- package/dist/slimselect.global.js +248 -120
- package/dist/slimselect.js +248 -120
- package/dist/slimselect.min.js +1 -1
- package/dist/slimselect.umd.js +248 -120
- package/dist/slimselect.umd.min.js +1 -1
- package/dist/store.d.ts +4 -2
- package/index.html +1 -4
- package/jest.config.js +6 -0
- package/package.json +30 -39
- package/src/slim-select/classes.test.ts +72 -0
- package/src/slim-select/classes.ts +109 -0
- package/src/slim-select/helpers.test.ts +160 -0
- package/src/slim-select/helpers.ts +3 -12
- package/src/slim-select/index.test.ts +109 -16
- package/src/slim-select/index.ts +41 -12
- package/src/slim-select/render.test.ts +1169 -18
- package/src/slim-select/render.ts +75 -96
- package/src/slim-select/rollup.config.mjs +28 -28
- package/src/slim-select/select.test.ts +306 -156
- package/src/slim-select/select.ts +69 -20
- package/src/slim-select/settings.test.ts +257 -0
- package/src/slim-select/settings.ts +4 -0
- package/src/slim-select/slimselect.scss +7 -3
- package/src/slim-select/store.test.ts +986 -235
- package/src/slim-select/store.ts +70 -28
- package/src/{vue/slimselect.vue → slim-select/vue.vue} +19 -17
- package/tsconfig.json +2 -3
- package/src/react/.eslintignore +0 -2
- package/src/react/.eslintrc.cjs +0 -24
- package/src/react/index.html +0 -14
- package/src/react/jestconfig.json +0 -11
- package/src/react/package.json +0 -32
- package/src/react/src/frameworkpage.tsx +0 -133
- package/src/react/src/index.ts +0 -3
- package/src/react/src/slimselect.tsx +0 -148
- package/src/react/tests/slimselect.test.tsx +0 -52
- package/src/react/tsconfig.json +0 -37
- package/src/react/tsconfig.node.json +0 -10
- package/src/react/vite.config.ts +0 -55
- package/src/vue/README.md +0 -48
- package/src/vue/dist/slim-select/helpers.d.ts +0 -5
- package/src/vue/dist/slim-select/index.d.ts +0 -46
- package/src/vue/dist/slim-select/render.d.ts +0 -120
- package/src/vue/dist/slim-select/select.d.ts +0 -28
- package/src/vue/dist/slim-select/settings.d.ts +0 -34
- package/src/vue/dist/slim-select/store.d.ts +0 -80
- package/src/vue/dist/slimselectvue.es.js +0 -1978
- package/src/vue/dist/slimselectvue.global.js +0 -1981
- package/src/vue/dist/slimselectvue.ssr.js +0 -1980
- package/src/vue/dist/vue/hello.d.ts +0 -2
- package/src/vue/dist/vue/slimselect.vue.d.ts +0 -326
- package/src/vue/hello.ts +0 -5
- package/src/vue/package.json +0 -28
- package/src/vue/rollup.config.mjs +0 -44
- package/src/vue/tsconfig.json +0 -14
- /package/{vite.config.ts → vite.config.mts} +0 -0
package/src/slim-select/store.ts
CHANGED
|
@@ -93,6 +93,7 @@ export default class Store {
|
|
|
93
93
|
|
|
94
94
|
// Main data set, never null
|
|
95
95
|
private data: DataArray = []
|
|
96
|
+
private selectedOrder: string[] = []
|
|
96
97
|
|
|
97
98
|
constructor(type: selectType, data: DataArrayPartial) {
|
|
98
99
|
this.selectType = type
|
|
@@ -115,11 +116,17 @@ export default class Store {
|
|
|
115
116
|
|
|
116
117
|
if ('options' in dataObj && dataObj.options) {
|
|
117
118
|
for (let option of dataObj.options) {
|
|
118
|
-
|
|
119
|
+
const validationError = this.validateOption(option)
|
|
120
|
+
if (validationError) {
|
|
121
|
+
return validationError
|
|
122
|
+
}
|
|
119
123
|
}
|
|
120
124
|
}
|
|
121
125
|
} else if (dataObj instanceof Option || 'text' in dataObj) {
|
|
122
|
-
|
|
126
|
+
const validationError = this.validateOption(dataObj)
|
|
127
|
+
if (validationError) {
|
|
128
|
+
return validationError
|
|
129
|
+
}
|
|
123
130
|
} else {
|
|
124
131
|
return new Error('Data object must be a valid optgroup or option')
|
|
125
132
|
}
|
|
@@ -169,7 +176,7 @@ export default class Store {
|
|
|
169
176
|
// Run this.data through setSelected by value
|
|
170
177
|
// to set the selected property and clean any wrong selected
|
|
171
178
|
if (this.selectType === 'single') {
|
|
172
|
-
this.setSelectedBy('
|
|
179
|
+
this.setSelectedBy('id', this.getSelected())
|
|
173
180
|
}
|
|
174
181
|
}
|
|
175
182
|
|
|
@@ -184,8 +191,13 @@ export default class Store {
|
|
|
184
191
|
return this.filter(null, false) as Option[]
|
|
185
192
|
}
|
|
186
193
|
|
|
187
|
-
public addOption(option: OptionOptional) {
|
|
188
|
-
|
|
194
|
+
public addOption(option: OptionOptional, addToStart: boolean = false) {
|
|
195
|
+
if (addToStart) {
|
|
196
|
+
let data = [new Option(option)] as DataArray
|
|
197
|
+
this.setData(data.concat(this.getData()))
|
|
198
|
+
} else {
|
|
199
|
+
this.setData(this.getData().concat(new Option(option)))
|
|
200
|
+
}
|
|
189
201
|
}
|
|
190
202
|
|
|
191
203
|
// Pass in an array of id that will loop through
|
|
@@ -194,6 +206,7 @@ export default class Store {
|
|
|
194
206
|
public setSelectedBy(selectedType: 'id' | 'value', selectedValues: string[]) {
|
|
195
207
|
let firstOption: Option | null = null
|
|
196
208
|
let hasSelected = false
|
|
209
|
+
const selectedObjects: Option[] = []
|
|
197
210
|
|
|
198
211
|
for (let dataObj of this.data) {
|
|
199
212
|
// Optgroup
|
|
@@ -207,8 +220,12 @@ export default class Store {
|
|
|
207
220
|
|
|
208
221
|
// If the option is selected, set hasSelected to true
|
|
209
222
|
// for single based selects
|
|
210
|
-
if (option.selected
|
|
211
|
-
|
|
223
|
+
if (option.selected) {
|
|
224
|
+
selectedObjects.push(option)
|
|
225
|
+
|
|
226
|
+
if (this.selectType === 'single') {
|
|
227
|
+
hasSelected = true
|
|
228
|
+
}
|
|
212
229
|
}
|
|
213
230
|
}
|
|
214
231
|
}
|
|
@@ -223,8 +240,12 @@ export default class Store {
|
|
|
223
240
|
|
|
224
241
|
// If the option is selected, set hasSelected to true
|
|
225
242
|
// for single based selects
|
|
226
|
-
if (dataObj.selected
|
|
227
|
-
|
|
243
|
+
if (dataObj.selected) {
|
|
244
|
+
selectedObjects.push(dataObj)
|
|
245
|
+
|
|
246
|
+
if (this.selectType === 'single') {
|
|
247
|
+
hasSelected = true
|
|
248
|
+
}
|
|
228
249
|
}
|
|
229
250
|
}
|
|
230
251
|
}
|
|
@@ -232,19 +253,23 @@ export default class Store {
|
|
|
232
253
|
// If no options are selected, select the first option
|
|
233
254
|
if (this.selectType === 'single' && firstOption && !hasSelected) {
|
|
234
255
|
firstOption.selected = true
|
|
256
|
+
selectedObjects.push(firstOption)
|
|
235
257
|
}
|
|
258
|
+
|
|
259
|
+
// Put together a list of selected ids in the order of the selected values
|
|
260
|
+
const selectedIds = selectedValues.map((value) => {
|
|
261
|
+
return selectedObjects.find((option) => option[selectedType] === value)?.id || ''
|
|
262
|
+
})
|
|
263
|
+
|
|
264
|
+
this.selectedOrder = selectedIds
|
|
236
265
|
}
|
|
237
266
|
|
|
238
267
|
public getSelected(): string[] {
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
// Loop through each option and get the value
|
|
243
|
-
selectedOptions.forEach((option: Option) => {
|
|
244
|
-
selectedValues.push(option.value)
|
|
245
|
-
})
|
|
268
|
+
return this.getSelectedOptions().map((option) => option.id)
|
|
269
|
+
}
|
|
246
270
|
|
|
247
|
-
|
|
271
|
+
public getSelectedValues(): string[] {
|
|
272
|
+
return this.getSelectedOptions().map((option) => option.value)
|
|
248
273
|
}
|
|
249
274
|
|
|
250
275
|
public getSelectedOptions(): Option[] {
|
|
@@ -253,17 +278,6 @@ export default class Store {
|
|
|
253
278
|
}, false) as Option[]
|
|
254
279
|
}
|
|
255
280
|
|
|
256
|
-
public getSelectedIDs(): string[] {
|
|
257
|
-
let selectedOptions = this.getSelectedOptions()
|
|
258
|
-
|
|
259
|
-
let selectedIDs: string[] = []
|
|
260
|
-
selectedOptions.forEach((op: Option) => {
|
|
261
|
-
selectedIDs.push(op.id)
|
|
262
|
-
})
|
|
263
|
-
|
|
264
|
-
return selectedIDs
|
|
265
|
-
}
|
|
266
|
-
|
|
267
281
|
public getOptgroupByID(id: string): Optgroup | null {
|
|
268
282
|
// Loop through each data object
|
|
269
283
|
// and if optgroup is found, return it
|
|
@@ -362,4 +376,32 @@ export default class Store {
|
|
|
362
376
|
return dataSearch
|
|
363
377
|
}
|
|
364
378
|
|
|
379
|
+
// Take in an array of options and reoder them based upon the selected order
|
|
380
|
+
public selectedOrderOptions(options: Option[]): Option[] {
|
|
381
|
+
const newOrder: Option[] = []
|
|
382
|
+
this.selectedOrder.forEach((id) => {
|
|
383
|
+
const option = options.find((opt) => opt.id === id)
|
|
384
|
+
if (option) {
|
|
385
|
+
newOrder.push(option)
|
|
386
|
+
}
|
|
387
|
+
})
|
|
388
|
+
|
|
389
|
+
// add any remaining options that were not in the selected order
|
|
390
|
+
options.forEach((option) => {
|
|
391
|
+
let isIn = false
|
|
392
|
+
newOrder.forEach((selectedOption) => {
|
|
393
|
+
if (option.id === selectedOption.id) {
|
|
394
|
+
isIn = true
|
|
395
|
+
|
|
396
|
+
return
|
|
397
|
+
}
|
|
398
|
+
})
|
|
399
|
+
|
|
400
|
+
if (!isIn) {
|
|
401
|
+
newOrder.push(option)
|
|
402
|
+
}
|
|
403
|
+
})
|
|
404
|
+
|
|
405
|
+
return newOrder
|
|
406
|
+
}
|
|
365
407
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { defineComponent, PropType } from 'vue'
|
|
3
|
-
|
|
4
3
|
import SlimSelect, { Config, Events } from '../slim-select'
|
|
5
4
|
import { SettingsPartial } from '../slim-select/settings'
|
|
6
5
|
import { DataArrayPartial, Option } from '../slim-select/store'
|
|
@@ -9,31 +8,34 @@ export default defineComponent({
|
|
|
9
8
|
name: 'SlimSelect',
|
|
10
9
|
props: {
|
|
11
10
|
modelValue: {
|
|
12
|
-
type: [String, Array, undefined] as PropType<string | string[] | undefined
|
|
11
|
+
type: [String, Array, undefined] as PropType<string | string[] | undefined>
|
|
13
12
|
},
|
|
14
13
|
multiple: {
|
|
15
14
|
type: Boolean,
|
|
16
|
-
default: false
|
|
15
|
+
default: false
|
|
17
16
|
},
|
|
18
17
|
data: {
|
|
19
|
-
type: Array as PropType<DataArrayPartial
|
|
18
|
+
type: Array as PropType<DataArrayPartial>
|
|
20
19
|
},
|
|
21
20
|
settings: {
|
|
22
|
-
type: Object as PropType<SettingsPartial
|
|
21
|
+
type: Object as PropType<SettingsPartial>
|
|
23
22
|
},
|
|
24
23
|
events: {
|
|
25
24
|
type: Object as PropType<Events>,
|
|
26
|
-
|
|
25
|
+
default: () => {
|
|
26
|
+
return {}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
27
29
|
},
|
|
28
30
|
emits: ['update:modelValue'],
|
|
29
31
|
data() {
|
|
30
32
|
return {
|
|
31
|
-
slim: null as SlimSelect | null
|
|
33
|
+
slim: null as SlimSelect | null
|
|
32
34
|
}
|
|
33
35
|
},
|
|
34
36
|
mounted() {
|
|
35
37
|
let config = {
|
|
36
|
-
select: this.$refs.slim
|
|
38
|
+
select: this.$refs.slim
|
|
37
39
|
} as Config
|
|
38
40
|
|
|
39
41
|
// If data is passed in, use it
|
|
@@ -47,12 +49,12 @@ export default defineComponent({
|
|
|
47
49
|
}
|
|
48
50
|
|
|
49
51
|
// If events are passed in, use it
|
|
50
|
-
config.events = this.events || {}
|
|
52
|
+
config.events = (this.events || {}) as Events
|
|
51
53
|
|
|
52
54
|
// Wrap config.events.afterChange to run value update
|
|
53
55
|
const ogAfterChange = config.events.afterChange
|
|
54
56
|
config.events.afterChange = (newVal: Option[]) => {
|
|
55
|
-
const value = this.multiple ? newVal.map((option) => option.value) : newVal.length > 0 ? newVal[0].value : ''
|
|
57
|
+
const value = this.multiple ? newVal.map((option) => option.value) : newVal.length > 0 ? newVal[0].value : ''
|
|
56
58
|
|
|
57
59
|
// Check if value is different from modelValue
|
|
58
60
|
if (this.value !== value) {
|
|
@@ -88,7 +90,7 @@ export default defineComponent({
|
|
|
88
90
|
// Set the value of the select to the newVal
|
|
89
91
|
this.slim?.setSelected(this.getCleanValue(newVal))
|
|
90
92
|
},
|
|
91
|
-
immediate: true
|
|
93
|
+
immediate: true
|
|
92
94
|
},
|
|
93
95
|
data: {
|
|
94
96
|
handler: function (newData) {
|
|
@@ -96,8 +98,8 @@ export default defineComponent({
|
|
|
96
98
|
this.slim.setData(newData)
|
|
97
99
|
}
|
|
98
100
|
},
|
|
99
|
-
deep: true
|
|
100
|
-
}
|
|
101
|
+
deep: true
|
|
102
|
+
}
|
|
101
103
|
},
|
|
102
104
|
computed: {
|
|
103
105
|
value: {
|
|
@@ -106,8 +108,8 @@ export default defineComponent({
|
|
|
106
108
|
},
|
|
107
109
|
set(value: string | string[]) {
|
|
108
110
|
this.$emit('update:modelValue', value)
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
111
113
|
},
|
|
112
114
|
methods: {
|
|
113
115
|
// This allows via a ref to call the SlimSelect methods
|
|
@@ -128,8 +130,8 @@ export default defineComponent({
|
|
|
128
130
|
}
|
|
129
131
|
|
|
130
132
|
return multi ? [] : ''
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
133
135
|
})
|
|
134
136
|
</script>
|
|
135
137
|
|
package/tsconfig.json
CHANGED
|
@@ -17,9 +17,8 @@
|
|
|
17
17
|
"importHelpers": true,
|
|
18
18
|
"lib": ["esnext", "dom"],
|
|
19
19
|
"paths": {
|
|
20
|
-
"slim-select": ["src/slim-select"]
|
|
21
|
-
"@slim-select/vue": ["src/vue"]
|
|
20
|
+
"slim-select": ["src/slim-select"]
|
|
22
21
|
}
|
|
23
22
|
},
|
|
24
|
-
"include": ["dist/", "src/**/*.ts", "src/**/*.d.ts"
|
|
23
|
+
"include": ["dist/", "src/**/*.ts", "src/**/*.d.ts"]
|
|
25
24
|
}
|
package/src/react/.eslintignore
DELETED
package/src/react/.eslintrc.cjs
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
module.exports = {
|
|
2
|
-
root: true,
|
|
3
|
-
env: { browser: true, es2020: true, node: true },
|
|
4
|
-
extends: [
|
|
5
|
-
'eslint:recommended',
|
|
6
|
-
'plugin:@typescript-eslint/recommended',
|
|
7
|
-
'plugin:react-hooks/recommended',
|
|
8
|
-
'plugin:react/recommended',
|
|
9
|
-
'plugin:@typescript-eslint/eslint-recommended',
|
|
10
|
-
],
|
|
11
|
-
parser: '@typescript-eslint/parser',
|
|
12
|
-
parserOptions: { ecmaVersion: 'latest', sourceType: 'module' },
|
|
13
|
-
plugins: ['prettier', 'react-refresh'],
|
|
14
|
-
rules: {
|
|
15
|
-
'react-hooks/rules-of-hooks': 'error',
|
|
16
|
-
'react-hooks/exhaustive-deps': 'warn',
|
|
17
|
-
'@typescript-eslint/no-non-null-assertion': 'off',
|
|
18
|
-
'@typescript-eslint/ban-ts-comment': 'off',
|
|
19
|
-
'@typescript-eslint/no-explicit-any': 'off',
|
|
20
|
-
'@typescript-eslint/no-extra-semi': 'off',
|
|
21
|
-
'@typescript-eslint/no-unused-vars': 'off',
|
|
22
|
-
'@typescript-eslint/no-invalid-void-type': 'off',
|
|
23
|
-
},
|
|
24
|
-
}
|
package/src/react/index.html
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="UTF-8" />
|
|
5
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
-
<title>Slim Select React</title>
|
|
7
|
-
</head>
|
|
8
|
-
<body>
|
|
9
|
-
<div id="react-root">
|
|
10
|
-
<div id="react-hide"></div>
|
|
11
|
-
</div>
|
|
12
|
-
<script type="module" src="/src/frameworkpage.tsx"></script>
|
|
13
|
-
</body>
|
|
14
|
-
</html>
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"transform": {
|
|
3
|
-
"^.+\\.(t|j)sx?$": "ts-jest"
|
|
4
|
-
},
|
|
5
|
-
"testRegex": "(/tests/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$",
|
|
6
|
-
"moduleFileExtensions": ["ts", "tsx", "js", "jsx", "json", "node"],
|
|
7
|
-
"testEnvironment": "jsdom",
|
|
8
|
-
"moduleNameMapper": {
|
|
9
|
-
"\\.(css|scss)$": "identity-obj-proxy"
|
|
10
|
-
}
|
|
11
|
-
}
|
package/src/react/package.json
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@slim-select/react",
|
|
3
|
-
"private": false,
|
|
4
|
-
"description": "React integration",
|
|
5
|
-
"version": "1.0.0",
|
|
6
|
-
"keywords": [
|
|
7
|
-
"react"
|
|
8
|
-
],
|
|
9
|
-
"repository": {
|
|
10
|
-
"type": "git",
|
|
11
|
-
"url": "git+https://github.com/brianvoe/slim-select.git"
|
|
12
|
-
},
|
|
13
|
-
"author": "Brian Voelker <brian@webiswhatido.com> (http://webiswhatido.com)",
|
|
14
|
-
"homepage": "https://slimselectjs.com/frameworks#vue",
|
|
15
|
-
"license": "MIT",
|
|
16
|
-
"type": "module",
|
|
17
|
-
"scripts": {
|
|
18
|
-
"dev": "vite",
|
|
19
|
-
"build": "tsc && vite build",
|
|
20
|
-
"lint": "eslint src --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
|
|
21
|
-
"preview": "vite preview",
|
|
22
|
-
"test": "jest --config jestconfig.json",
|
|
23
|
-
"build:cjs": "tsc --module commonjs --outDir dist/cjs"
|
|
24
|
-
},
|
|
25
|
-
"main": "dist/slimselectreact.ssr.js",
|
|
26
|
-
"browser": "dist/slimselect.global.js",
|
|
27
|
-
"module": "dist/slimselectreact.es.js",
|
|
28
|
-
"types": "dist/slimselect.react.d.ts",
|
|
29
|
-
"files": [
|
|
30
|
-
"dist"
|
|
31
|
-
]
|
|
32
|
-
}
|
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
import React from 'react'
|
|
2
|
-
import ReactDOM from 'react-dom/client'
|
|
3
|
-
import { SlimSelect } from '.'
|
|
4
|
-
import { useState } from 'react'
|
|
5
|
-
|
|
6
|
-
const ShowComponent = () => {
|
|
7
|
-
const [simpleSingle, setSimpleSingle] = useState('2')
|
|
8
|
-
const [simpleMultiple, setSimpleMultiple] = useState(['2', '3'])
|
|
9
|
-
|
|
10
|
-
return (
|
|
11
|
-
<div id="react" className="content">
|
|
12
|
-
<h2 className="header">React</h2>
|
|
13
|
-
<h3>Install</h3>
|
|
14
|
-
<p>
|
|
15
|
-
The react component is in a sub package under SlimSelect. All functionality still work in the implementation.
|
|
16
|
-
</p>
|
|
17
|
-
<div className="code-toolbar">
|
|
18
|
-
<pre className="language-bash">
|
|
19
|
-
<code>npm install @slim-select/react</code>
|
|
20
|
-
</pre>
|
|
21
|
-
</div>
|
|
22
|
-
<br />
|
|
23
|
-
<h3>Simple example</h3>
|
|
24
|
-
<div style={{ display: 'flex', flexDirection: 'row', width: '100%' }}>
|
|
25
|
-
<div style={{ flex: 0.5 }}>
|
|
26
|
-
<strong>Value</strong> {simpleSingle}
|
|
27
|
-
<SlimSelect
|
|
28
|
-
modelValue={simpleSingle}
|
|
29
|
-
events={{ afterChange: (values) => setSimpleSingle(values[0].value as unknown as string) }}
|
|
30
|
-
style={{ marginLeft: '5px' }}
|
|
31
|
-
ref={null}
|
|
32
|
-
>
|
|
33
|
-
<option value="all">All</option>
|
|
34
|
-
<option value={'1'}>Option 1</option>
|
|
35
|
-
<option value={'2'}>Option 2</option>
|
|
36
|
-
<option value={'3'}>Option 3</option>
|
|
37
|
-
</SlimSelect>
|
|
38
|
-
</div>
|
|
39
|
-
<div style={{ flex: 0.6, marginLeft: 15 }}>
|
|
40
|
-
<div>
|
|
41
|
-
<strong>Value</strong> {JSON.stringify(simpleMultiple)}
|
|
42
|
-
</div>
|
|
43
|
-
<SlimSelect
|
|
44
|
-
modelValue={simpleMultiple}
|
|
45
|
-
ref={null}
|
|
46
|
-
multiple={true}
|
|
47
|
-
events={{ afterChange: (values) => setSimpleMultiple(values.map((v) => v.value) as unknown as string[]) }}
|
|
48
|
-
>
|
|
49
|
-
<option value={'1'}>Option 1</option>
|
|
50
|
-
<option value={'2'}>Option 2</option>
|
|
51
|
-
<option value={'3'}>Value 3</option>
|
|
52
|
-
</SlimSelect>
|
|
53
|
-
</div>
|
|
54
|
-
</div>
|
|
55
|
-
<div className="code-toolbar">
|
|
56
|
-
<pre className="language-javascript">
|
|
57
|
-
<code className="language-javascript">
|
|
58
|
-
import React from "react" <br />
|
|
59
|
-
import SlimSelect from "@slim-select/react" <br />
|
|
60
|
-
import {`{`} useState {`}`} from "react"
|
|
61
|
-
<br />
|
|
62
|
-
<br />
|
|
63
|
-
export default MySelect = () {`=>`} {`{`}
|
|
64
|
-
<br />
|
|
65
|
-
const [simpleSingle, setSimpleSingle] = useState("2") <br />
|
|
66
|
-
return ( <br />
|
|
67
|
-
<SlimSelect <br />
|
|
68
|
-
modelValue= {`{`}simpleSingle{`}`}
|
|
69
|
-
<br />
|
|
70
|
-
events={`{{ afterChange: (values) => setSimpleSingle(values[0].value as unknown as string) }}`}
|
|
71
|
-
> <br />
|
|
72
|
-
<option value="all">All</option> <br />
|
|
73
|
-
<option value="1">Option 1</option> <br />
|
|
74
|
-
<option value="2">Option 2</option> <br />
|
|
75
|
-
<option value="3">Option 3</option> <br />
|
|
76
|
-
</SlimSelect> <br /> ){`}`}
|
|
77
|
-
</code>
|
|
78
|
-
</pre>
|
|
79
|
-
</div>
|
|
80
|
-
|
|
81
|
-
<br />
|
|
82
|
-
<div className="separator"></div>
|
|
83
|
-
<br />
|
|
84
|
-
|
|
85
|
-
<h3>Attributes</h3>
|
|
86
|
-
<p>There are certain attributes that are reactive to changes</p>
|
|
87
|
-
|
|
88
|
-
<h4>disabled</h4>
|
|
89
|
-
<SlimSelect settings={{ disabled: true }}>
|
|
90
|
-
<option value={'1'}>Option 1</option>
|
|
91
|
-
<option value={'2'}>Option 2</option>
|
|
92
|
-
<option value={'3'}>Value 3</option>
|
|
93
|
-
</SlimSelect>
|
|
94
|
-
<div className="code-toolbar">
|
|
95
|
-
<pre className="language-javascript">
|
|
96
|
-
<code className="language-javascript">
|
|
97
|
-
import React from "react" <br />
|
|
98
|
-
import SlimSelect from "@slim-select/react" <br />
|
|
99
|
-
import {`{`} useState {`}`} from "react"
|
|
100
|
-
<br />
|
|
101
|
-
<br />
|
|
102
|
-
export default MySelect = () {`=>`} {`{`}
|
|
103
|
-
<br />
|
|
104
|
-
const [simpleSingle, setSimpleSingle] = useState("2") <br />
|
|
105
|
-
return ( <br />
|
|
106
|
-
<SlimSelect <br />
|
|
107
|
-
settings={`{`}
|
|
108
|
-
{`{`}disabled: true {`}`}
|
|
109
|
-
{`}`}>
|
|
110
|
-
<br />
|
|
111
|
-
<option value="all">All</option> <br />
|
|
112
|
-
<option value="1">Option 1</option> <br />
|
|
113
|
-
<option value="2">Option 2</option> <br />
|
|
114
|
-
<option value="3">Option 3</option> <br />
|
|
115
|
-
</SlimSelect> <br /> ){`}`}
|
|
116
|
-
</code>
|
|
117
|
-
</pre>
|
|
118
|
-
</div>
|
|
119
|
-
</div>
|
|
120
|
-
)
|
|
121
|
-
}
|
|
122
|
-
const timeout = document.getElementById('app') ? 100 : 0
|
|
123
|
-
;(function () {
|
|
124
|
-
const interval = window.setInterval(() => {
|
|
125
|
-
if (document.getElementById('react-root') != null && document.getElementById('react-hide') != null) {
|
|
126
|
-
ReactDOM.createRoot(document.getElementById('react-root') as HTMLElement).render(
|
|
127
|
-
<React.StrictMode>
|
|
128
|
-
<ShowComponent />
|
|
129
|
-
</React.StrictMode>,
|
|
130
|
-
)
|
|
131
|
-
}
|
|
132
|
-
}, timeout)
|
|
133
|
-
})()
|
package/src/react/src/index.ts
DELETED
|
@@ -1,148 +0,0 @@
|
|
|
1
|
-
import React, { forwardRef, useCallback, useImperativeHandle, useRef } from 'react'
|
|
2
|
-
import { useEffect } from 'react'
|
|
3
|
-
|
|
4
|
-
import SlimSelect, { Events, Config } from '../../slim-select'
|
|
5
|
-
import { SettingsPartial } from '../../slim-select/settings'
|
|
6
|
-
import { DataArrayPartial, Option } from '../../slim-select/store'
|
|
7
|
-
import '../../slim-select/slimselect.scss'
|
|
8
|
-
|
|
9
|
-
export type SlimSelectProps = {
|
|
10
|
-
style?: React.CSSProperties
|
|
11
|
-
id?: string | undefined
|
|
12
|
-
modelValue?: string | string[] | undefined
|
|
13
|
-
multiple?: boolean
|
|
14
|
-
data?: DataArrayPartial
|
|
15
|
-
settings?: SettingsPartial
|
|
16
|
-
events?: Events
|
|
17
|
-
children?: React.ReactNode
|
|
18
|
-
}
|
|
19
|
-
export interface SlimSelectRef {
|
|
20
|
-
set: (newValue: string | string[]) => void
|
|
21
|
-
// Potentially call other functions on SlimSelect that have not been exposed via Ref yet
|
|
22
|
-
getSlimSelectInstance: () => SlimSelect
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
const SlimSelectComponent = (props: SlimSelectProps, ref: React.Ref<any>): JSX.Element => {
|
|
26
|
-
const { id = undefined, modelValue, style = {}, multiple = false, data, settings, events, children } = props
|
|
27
|
-
|
|
28
|
-
const slimHTMLElement = useRef(null)
|
|
29
|
-
const slimSelect = useRef<SlimSelect>()
|
|
30
|
-
const value = useRef<any>()
|
|
31
|
-
|
|
32
|
-
useEffect(() => {
|
|
33
|
-
const config = {
|
|
34
|
-
select: slimHTMLElement.current as unknown as Element,
|
|
35
|
-
events: {},
|
|
36
|
-
} as Config
|
|
37
|
-
|
|
38
|
-
// If data is passed in, use it
|
|
39
|
-
if (data) {
|
|
40
|
-
config.data = data
|
|
41
|
-
}
|
|
42
|
-
// If settings are passed in, use it
|
|
43
|
-
if (settings) {
|
|
44
|
-
config.settings = settings
|
|
45
|
-
}
|
|
46
|
-
// If events are passed in, use it
|
|
47
|
-
if (events) {
|
|
48
|
-
config.events = events
|
|
49
|
-
}
|
|
50
|
-
// Satisfy tsc
|
|
51
|
-
if (config.events == undefined) {
|
|
52
|
-
config.events = {}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// Wrap config.events.afterChange to run value update
|
|
56
|
-
const originalPropAfterChange = config.events.afterChange
|
|
57
|
-
|
|
58
|
-
config.events.afterChange = function (newSelectedOption: Option[]): void {
|
|
59
|
-
if (Array.isArray(newSelectedOption) && newSelectedOption.length > 0) {
|
|
60
|
-
const stringValue = multiple ? newSelectedOption.map((option) => option.value) : newSelectedOption[0].value
|
|
61
|
-
if (value.current !== stringValue) {
|
|
62
|
-
value.current = stringValue
|
|
63
|
-
}
|
|
64
|
-
// If they had an original afterChange, run it
|
|
65
|
-
if (config.events && originalPropAfterChange && typeof originalPropAfterChange === 'function') {
|
|
66
|
-
originalPropAfterChange(newSelectedOption)
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// Initialize SlimSelect
|
|
72
|
-
slimSelect.current = new SlimSelect(config)
|
|
73
|
-
|
|
74
|
-
// Get SlimSelect selected values
|
|
75
|
-
const selected = multiple
|
|
76
|
-
? (slimSelect.current as SlimSelect).getSelected()
|
|
77
|
-
: (slimSelect.current as SlimSelect).getSelected()[0]
|
|
78
|
-
|
|
79
|
-
// Check if modelValue is the same as the value of the select
|
|
80
|
-
if (selected !== modelValue && modelValue) {
|
|
81
|
-
// If not, set the value of the select to the modelValue
|
|
82
|
-
;(slimSelect.current as SlimSelect).setSelected(modelValue)
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// Destroy SlimSelect on unmount
|
|
86
|
-
return () => {
|
|
87
|
-
if (slimSelect.current) {
|
|
88
|
-
;(slimSelect.current as SlimSelect)?.destroy()
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
}, [modelValue, multiple, data, settings, events, children])
|
|
92
|
-
|
|
93
|
-
const getCleanValue = useCallback(
|
|
94
|
-
(val: string | string[] | undefined): string | string[] => {
|
|
95
|
-
const multi = multiple
|
|
96
|
-
|
|
97
|
-
// If its multiple and the modelValue is a string, return an array with the string
|
|
98
|
-
if (typeof val === 'string') {
|
|
99
|
-
return multi ? [val] : val
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// If its not multiple and the modelValue is an array, return the first item
|
|
103
|
-
if (Array.isArray(val)) {
|
|
104
|
-
return multi ? val : val[0]
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
return multi ? [] : ''
|
|
108
|
-
},
|
|
109
|
-
[multiple],
|
|
110
|
-
)
|
|
111
|
-
|
|
112
|
-
useEffect(() => {
|
|
113
|
-
if (modelValue) {
|
|
114
|
-
;(slimSelect.current as SlimSelect)?.setSelected(getCleanValue(modelValue))
|
|
115
|
-
}
|
|
116
|
-
}, [modelValue, getCleanValue])
|
|
117
|
-
|
|
118
|
-
useEffect(() => {
|
|
119
|
-
if (data) {
|
|
120
|
-
;(slimSelect.current as SlimSelect)?.setData(data)
|
|
121
|
-
}
|
|
122
|
-
}, [data])
|
|
123
|
-
|
|
124
|
-
useImperativeHandle(
|
|
125
|
-
ref,
|
|
126
|
-
() => {
|
|
127
|
-
return {
|
|
128
|
-
set(newValue: string | string[]): void {
|
|
129
|
-
;(slimSelect.current as SlimSelect)?.setSelected(newValue)
|
|
130
|
-
},
|
|
131
|
-
getSlimSelectInstance(): SlimSelect {
|
|
132
|
-
return slimSelect.current as SlimSelect
|
|
133
|
-
},
|
|
134
|
-
} as SlimSelectRef
|
|
135
|
-
},
|
|
136
|
-
[],
|
|
137
|
-
)
|
|
138
|
-
|
|
139
|
-
return (
|
|
140
|
-
<>
|
|
141
|
-
<select style={style} id={id} data-testid={id} multiple={multiple} ref={slimHTMLElement}>
|
|
142
|
-
{children}
|
|
143
|
-
</select>
|
|
144
|
-
</>
|
|
145
|
-
)
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
export default forwardRef(SlimSelectComponent)
|