slim-select 2.6.0 → 2.7.1
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/render.d.ts +1 -1
- package/dist/settings.d.ts +1 -0
- package/dist/slimselect.cjs.js +43 -9
- package/dist/slimselect.css +1 -1
- package/dist/slimselect.css.map +1 -1
- package/dist/slimselect.es.js +43 -9
- package/dist/slimselect.global.js +43 -9
- package/dist/slimselect.js +43 -9
- package/dist/slimselect.min.js +1 -1
- package/dist/slimselect.umd.js +43 -9
- package/dist/slimselect.umd.min.js +1 -1
- package/dist/store.d.ts +2 -1
- package/index.html +4 -0
- package/package.json +50 -26
- package/src/react/.eslintignore +2 -0
- package/src/react/.eslintrc.cjs +24 -0
- package/src/react/index.html +14 -0
- package/src/react/jestconfig.json +11 -0
- package/src/react/package.json +32 -0
- package/src/react/src/frameworkpage.tsx +133 -0
- package/src/react/src/index.ts +3 -0
- package/src/react/src/slimselect.tsx +148 -0
- package/src/react/tests/slimselect.test.tsx +52 -0
- package/src/react/tsconfig.json +37 -0
- package/src/react/tsconfig.node.json +10 -0
- package/src/react/vite.config.ts +55 -0
- package/src/slim-select/index.test.ts +2 -2
- package/src/slim-select/render.ts +39 -9
- package/src/slim-select/select.ts +3 -2
- package/src/slim-select/settings.ts +2 -0
- package/src/slim-select/slimselect.scss +3 -2
- package/src/slim-select/store.ts +20 -3
- package/src/vue/dist/slim-select/helpers.d.ts +5 -5
- package/src/vue/dist/slim-select/index.d.ts +46 -46
- package/src/vue/dist/slim-select/render.d.ts +120 -120
- package/src/vue/dist/slim-select/select.d.ts +28 -28
- package/src/vue/dist/slim-select/settings.d.ts +33 -32
- package/src/vue/dist/slim-select/store.d.ts +80 -79
- package/src/vue/dist/slimselectvue.es.js +1940 -1911
- package/src/vue/dist/slimselectvue.global.js +1940 -1911
- package/src/vue/dist/slimselectvue.ssr.js +1940 -1911
- package/src/vue/dist/vue/hello.d.ts +2 -2
- package/src/vue/dist/vue/slimselect.vue.d.ts +324 -317
- package/src/vue/slimselect.vue +2 -7
- package/tsconfig.json +1 -1
package/package.json
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "slim-select",
|
|
3
3
|
"description": "Slim advanced select dropdown",
|
|
4
|
-
"version": "2.
|
|
4
|
+
"version": "2.7.1",
|
|
5
5
|
"author": "Brian Voelker <brian@webiswhatido.com> (http://webiswhatido.com)",
|
|
6
6
|
"homepage": "https://slimselectjs.com",
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"bugs": {
|
|
9
9
|
"url": "https://github.com/brianvoe/slim-select/issues"
|
|
10
10
|
},
|
|
11
|
-
"type": "module",
|
|
12
11
|
"main": "dist/slimselect.umd.js",
|
|
13
12
|
"browser": "dist/slimselect.umd.js",
|
|
14
13
|
"module": "dist/slimselect.es.js",
|
|
@@ -18,8 +17,9 @@
|
|
|
18
17
|
"sass": "src/slim-select/slimselect.scss",
|
|
19
18
|
"exports": {
|
|
20
19
|
".": {
|
|
20
|
+
"import": "./dist/slimselect.js",
|
|
21
21
|
"require": "./dist/slimselect.umd.js",
|
|
22
|
-
"
|
|
22
|
+
"types": "./dist/*.d.ts"
|
|
23
23
|
},
|
|
24
24
|
"./styles": "./dist/slimselect.css"
|
|
25
25
|
},
|
|
@@ -49,34 +49,58 @@
|
|
|
49
49
|
"build:frameworks": "npm run build --workspaces",
|
|
50
50
|
"test": "jest"
|
|
51
51
|
},
|
|
52
|
+
"dependencies": {
|
|
53
|
+
"react": "^18.2.0",
|
|
54
|
+
"react-dom": "^18.2.0"
|
|
55
|
+
},
|
|
52
56
|
"devDependencies": {
|
|
53
|
-
"@jest/globals": "^29.
|
|
54
|
-
"@rollup/plugin-babel": "^6.0.
|
|
55
|
-
"@rollup/plugin-commonjs": "^25.0.
|
|
56
|
-
"@rollup/plugin-node-resolve": "^15.
|
|
57
|
-
"@rollup/plugin-terser": "^0.4.
|
|
58
|
-
"@rollup/plugin-typescript": "^11.1.
|
|
57
|
+
"@jest/globals": "^29.7.0",
|
|
58
|
+
"@rollup/plugin-babel": "^6.0.4",
|
|
59
|
+
"@rollup/plugin-commonjs": "^25.0.7",
|
|
60
|
+
"@rollup/plugin-node-resolve": "^15.2.3",
|
|
61
|
+
"@rollup/plugin-terser": "^0.4.4",
|
|
62
|
+
"@rollup/plugin-typescript": "^11.1.5",
|
|
59
63
|
"@slim-select/vue": "workspace:src/vue",
|
|
60
|
-
"@types/downloadjs": "^1.4.
|
|
61
|
-
"@vitejs/plugin-vue": "^4.
|
|
64
|
+
"@types/downloadjs": "^1.4.6",
|
|
65
|
+
"@vitejs/plugin-vue": "^4.5.0",
|
|
62
66
|
"clipboard": "^2.0.11",
|
|
63
67
|
"downloadjs": "^1.4.7",
|
|
64
|
-
"jest": "^29.
|
|
65
|
-
"jest-environment-jsdom": "^29.
|
|
66
|
-
"prettier": "^
|
|
68
|
+
"jest": "^29.7.0",
|
|
69
|
+
"jest-environment-jsdom": "^29.7.0",
|
|
70
|
+
"prettier": "^3.1.0",
|
|
67
71
|
"prismjs": "^1.29.0",
|
|
68
|
-
"rimraf": "^5.0.
|
|
69
|
-
"rollup": "^
|
|
70
|
-
"rollup-plugin-typescript2": "^0.
|
|
72
|
+
"rimraf": "^5.0.5",
|
|
73
|
+
"rollup": "^4.5.2",
|
|
74
|
+
"rollup-plugin-typescript2": "^0.36.0",
|
|
71
75
|
"rollup-plugin-vue": "^6.0.0",
|
|
72
|
-
"sass": "^1.
|
|
73
|
-
"ts-jest": "^29.
|
|
74
|
-
"tslib": "^2.
|
|
75
|
-
"typescript": "^
|
|
76
|
-
"vite": "^4.4
|
|
77
|
-
"vue": "^3.
|
|
78
|
-
"vue-router": "^4.
|
|
79
|
-
"vue-tsc": "^1.
|
|
80
|
-
"vuex": "^4.0.2"
|
|
76
|
+
"sass": "^1.59.2",
|
|
77
|
+
"ts-jest": "^29.0.5",
|
|
78
|
+
"tslib": "^2.5.0",
|
|
79
|
+
"typescript": "^4.9.5",
|
|
80
|
+
"vite": "^4.1.4",
|
|
81
|
+
"vue": "^3.2.47",
|
|
82
|
+
"vue-router": "^4.1.6",
|
|
83
|
+
"vue-tsc": "^1.2.0",
|
|
84
|
+
"vuex": "^4.0.2",
|
|
85
|
+
"@rollup/plugin-replace": "^5.0.2",
|
|
86
|
+
"@testing-library/jest-dom": "^5.16.5",
|
|
87
|
+
"@testing-library/react": "^14.0.0",
|
|
88
|
+
"@testing-library/user-event": "^14.4.3",
|
|
89
|
+
"@types/jest": "^29.5.1",
|
|
90
|
+
"@types/react": "^18.0.28",
|
|
91
|
+
"@types/react-dom": "^18.0.11",
|
|
92
|
+
"@typescript-eslint/eslint-plugin": "^5.59.2",
|
|
93
|
+
"@typescript-eslint/parser": "^5.59.2",
|
|
94
|
+
"@vitejs/plugin-react": "^4.0.0",
|
|
95
|
+
"eslint": "^8.39.0",
|
|
96
|
+
"eslint-config-prettier": "^8.8.0",
|
|
97
|
+
"eslint-plugin-prettier": "^4.2.1",
|
|
98
|
+
"eslint-plugin-react": "^7.32.2",
|
|
99
|
+
"eslint-plugin-react-hooks": "^4.6.0",
|
|
100
|
+
"eslint-plugin-react-refresh": "^0.3.4",
|
|
101
|
+
"identity-obj-proxy": "^3.0.0",
|
|
102
|
+
"jest-canvas-mock": "^2.5.0",
|
|
103
|
+
"rollup-plugin-peer-deps-external": "^2.2.4",
|
|
104
|
+
"vite-plugin-dts": "^2.3.0"
|
|
81
105
|
}
|
|
82
106
|
}
|
|
@@ -0,0 +1,24 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
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>
|
|
@@ -0,0 +1,11 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,133 @@
|
|
|
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
|
+
})()
|
|
@@ -0,0 +1,148 @@
|
|
|
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)
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
|
|
3
|
+
import { render } from '@testing-library/react'
|
|
4
|
+
import userEvent from '@testing-library/user-event'
|
|
5
|
+
import '@testing-library/jest-dom/extend-expect'
|
|
6
|
+
|
|
7
|
+
import 'jest-canvas-mock'
|
|
8
|
+
|
|
9
|
+
import SlimSelectComponent from '../src/slimselect'
|
|
10
|
+
|
|
11
|
+
describe('Slim Select', () => {
|
|
12
|
+
console.log(React.version)
|
|
13
|
+
it('renders successfully', () => {
|
|
14
|
+
const { queryByTestId, queryAllByText, getByText } = render(
|
|
15
|
+
<SlimSelectComponent id="slimselect" ref={null} multiple={true}>
|
|
16
|
+
<option value={'value1'}>Value 1</option>
|
|
17
|
+
<option value={'value2'}>Value 2</option>
|
|
18
|
+
<option value={'value3'}>Value 3</option>
|
|
19
|
+
</SlimSelectComponent>,
|
|
20
|
+
)
|
|
21
|
+
expect(queryByTestId('slimselect')).not.toEqual(null)
|
|
22
|
+
expect(queryByTestId('slimselect')).not.toBeVisible()
|
|
23
|
+
expect(getByText('Select Value')).not.toEqual(null)
|
|
24
|
+
expect(queryAllByText('Value 1')[1].getAttribute('aria-selected')).toEqual('false')
|
|
25
|
+
expect(queryAllByText('Value 2')[1].getAttribute('aria-selected')).toEqual('false')
|
|
26
|
+
expect(queryAllByText('Value 3')[1].getAttribute('aria-selected')).toEqual('false')
|
|
27
|
+
})
|
|
28
|
+
it('can be selected with onchange callback', async () => {
|
|
29
|
+
const { queryAllByText } = render(
|
|
30
|
+
<SlimSelectComponent id="slimselect" ref={null} multiple={true}>
|
|
31
|
+
<option value={'value1'}>Value 1</option>
|
|
32
|
+
<option value={'value2'}>Value 2</option>
|
|
33
|
+
<option value={'value3'}>Value 3</option>
|
|
34
|
+
</SlimSelectComponent>,
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
// First original html select element gets hidden, after comes slimselect div - that is why array index = 1
|
|
38
|
+
const firstSlimOption = queryAllByText('Value 1')[1]
|
|
39
|
+
const thirdSlimOpption = queryAllByText('Value 3')[1]
|
|
40
|
+
|
|
41
|
+
expect(firstSlimOption).not.toBeUndefined()
|
|
42
|
+
expect(thirdSlimOpption).not.toBeUndefined()
|
|
43
|
+
|
|
44
|
+
await userEvent.click(firstSlimOption as HTMLElement)
|
|
45
|
+
await userEvent.click(thirdSlimOpption as HTMLElement)
|
|
46
|
+
|
|
47
|
+
expect(queryAllByText('Select Value')).toHaveLength(0)
|
|
48
|
+
expect(queryAllByText('Value 1')[1].getAttribute('aria-selected')).toEqual('true')
|
|
49
|
+
expect(queryAllByText('Value 2')[1].getAttribute('aria-selected')).toEqual('false')
|
|
50
|
+
expect(queryAllByText('Value 3')[1].getAttribute('aria-selected')).toEqual('true')
|
|
51
|
+
})
|
|
52
|
+
})
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"exclude": ["dist", "node_modules"],
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"target": "ESNext",
|
|
5
|
+
"lib": ["DOM", "DOM.Iterable", "ESNext"],
|
|
6
|
+
"module": "ESNext",
|
|
7
|
+
"skipLibCheck": true,
|
|
8
|
+
"importHelpers": true,
|
|
9
|
+
"declaration": true,
|
|
10
|
+
"sourceMap": true,
|
|
11
|
+
//"rootDir": "./src",
|
|
12
|
+
"outDir": "./dist",
|
|
13
|
+
"esModuleInterop": true,
|
|
14
|
+
"forceConsistentCasingInFileNames": true,
|
|
15
|
+
|
|
16
|
+
/* Bundler mode */
|
|
17
|
+
"moduleResolution": "node",
|
|
18
|
+
"allowImportingTsExtensions": true,
|
|
19
|
+
"resolveJsonModule": true,
|
|
20
|
+
"isolatedModules": true,
|
|
21
|
+
"noEmit": true,
|
|
22
|
+
|
|
23
|
+
"jsx": "react-jsx",
|
|
24
|
+
|
|
25
|
+
/* Linting */
|
|
26
|
+
"strict": true,
|
|
27
|
+
"noFallthroughCasesInSwitch": true,
|
|
28
|
+
"noImplicitReturns": true,
|
|
29
|
+
"noUnusedLocals": false,
|
|
30
|
+
"noUnusedParameters": false,
|
|
31
|
+
"paths": {
|
|
32
|
+
"react": ["./node_modules/@types/react"]
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
"include": ["./src"],
|
|
36
|
+
"references": [{ "path": "./tsconfig.node.json" }]
|
|
37
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import react from '@vitejs/plugin-react'
|
|
2
|
+
import { defineConfig } from 'vite'
|
|
3
|
+
import { babel } from '@rollup/plugin-babel'
|
|
4
|
+
import commonjs from '@rollup/plugin-commonjs'
|
|
5
|
+
import peerDepsExternal from 'rollup-plugin-peer-deps-external'
|
|
6
|
+
import dts from 'vite-plugin-dts'
|
|
7
|
+
|
|
8
|
+
const formatNameMap = {
|
|
9
|
+
iife: 'global',
|
|
10
|
+
cjs: 'ssr',
|
|
11
|
+
es: 'es',
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// https://vitejs.dev/config/
|
|
15
|
+
export default defineConfig({
|
|
16
|
+
plugins: [
|
|
17
|
+
react(),
|
|
18
|
+
dts({
|
|
19
|
+
insertTypesEntry: true,
|
|
20
|
+
skipDiagnostics: true,
|
|
21
|
+
}),
|
|
22
|
+
],
|
|
23
|
+
build: {
|
|
24
|
+
target: 'modules',
|
|
25
|
+
lib: {
|
|
26
|
+
// Could also be a dictionary or array of multiple entry points
|
|
27
|
+
entry: 'src/index.ts',
|
|
28
|
+
formats: ['es', 'cjs', 'iife'],
|
|
29
|
+
name: 'SlimSelectReact',
|
|
30
|
+
// the proper extensions will be added
|
|
31
|
+
fileName: (format) => `slimselectreact.${formatNameMap[format]}.js`,
|
|
32
|
+
},
|
|
33
|
+
rollupOptions: {
|
|
34
|
+
// make sure to externalize deps that shouldn't be bundled
|
|
35
|
+
// into your library
|
|
36
|
+
// external: ['react', 'react-dom'],
|
|
37
|
+
plugins: [
|
|
38
|
+
peerDepsExternal(),
|
|
39
|
+
babel({
|
|
40
|
+
babelHelpers: 'bundled',
|
|
41
|
+
presets: ['@babel/preset-env', '@babel/preset-react'],
|
|
42
|
+
exclude: '../../node_modules/',
|
|
43
|
+
}),
|
|
44
|
+
commonjs(),
|
|
45
|
+
],
|
|
46
|
+
output: {
|
|
47
|
+
// for externalized deps
|
|
48
|
+
globals: {
|
|
49
|
+
react: 'React',
|
|
50
|
+
'react-dom': 'ReactDOM',
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
})
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
'use strict'
|
|
6
6
|
import { describe, expect, test } from '@jest/globals'
|
|
7
7
|
import SlimSelect from './'
|
|
8
|
-
import { OptionOptional } from '
|
|
9
|
-
import { Config } from '
|
|
8
|
+
import { OptionOptional } from './store'
|
|
9
|
+
import { Config } from './index'
|
|
10
10
|
|
|
11
11
|
describe('SlimSelect Module', () => {
|
|
12
12
|
test('constructor', () => {
|