Compare commits
306 commits
Author | SHA1 | Date | |
---|---|---|---|
5dbea2825a | |||
312971acea | |||
a7ed4d880e | |||
ba27dbb533 | |||
9c6de739c7 | |||
2730d7aad4 | |||
5d17dd8531 | |||
d1f39c6cda | |||
bbdacdfe3b | |||
92eabcbd4a | |||
2a8107f379 | |||
ea45c47d43 | |||
d130beb4e9 | |||
6056cce4e9 | |||
ce590e3785 | |||
30e6dbadda | |||
4da6239a67 | |||
9ac71c4717 | |||
835ea12ac9 | |||
1b67baec25 | |||
624dd797a4 | |||
cbbdbda95b | |||
d796e90955 | |||
06d16cd857 | |||
d26b753f6b | |||
72da548a64 | |||
490e341db5 | |||
76780ccc34 | |||
beb07ebc2c | |||
20d3f5cd55 | |||
f63201d929 | |||
08d4f1fee7 | |||
09eeca0db0 | |||
e2aab31bc0 | |||
c01144ab23 | |||
86694c138e | |||
7c360b44b3 | |||
2099c3dc2e | |||
d25c065210 | |||
eb22895f00 | |||
ac8d27facf | |||
06d4435c82 | |||
bb76a572c0 | |||
6df44b1044 | |||
29097d5457 | |||
c21b998eaa | |||
96e4ac53d9 | |||
770342b7e8 | |||
eef836a037 | |||
8ab8157607 | |||
75caa0b1f3 | |||
3d42067bbd | |||
ce3d1111d8 | |||
7758226d64 | |||
25a7ed0318 | |||
23f0b7cb9d | |||
303d12504c | |||
3b4d7543e5 | |||
781c729e13 | |||
9605f367f9 | |||
1b4d3553ef | |||
f12c62c4b8 | |||
c7976b7acd | |||
4df199e0b9 | |||
0903934848 | |||
64b5df6874 | |||
824eca6f81 | |||
9c9aded8b2 | |||
7e200664c4 | |||
04571e36d3 | |||
11208fe62d | |||
b9acfa773d | |||
6e4903e852 | |||
a8862e78be | |||
bf94386cc5 | |||
0b6973b322 | |||
66c6864267 | |||
391c3e39cb | |||
3d402d4560 | |||
545a442f5c | |||
c989be1491 | |||
3633c4ac0f | |||
859f6262eb | |||
6b16e93977 | |||
7f727480e8 | |||
82b94228f9 | |||
b92823b70c | |||
22f9be0d93 | |||
2222f767a9 | |||
f0ec43fa20 | |||
c4f3a81d41 | |||
fb379408c1 | |||
c26596e9ec | |||
9835eb756a | |||
70397fd89a | |||
59ea75ef14 | |||
8647f36fbe | |||
046afbb614 | |||
de5307ce4d | |||
05a41c5c7d | |||
9e656397cd | |||
20579bad35 | |||
977221650a | |||
e09a342ac8 | |||
e64eface11 | |||
de6c46cdd0 | |||
a1ec9d0de6 | |||
3d921621b7 | |||
46deb9abe5 | |||
6b6fb17bca | |||
b4a6371cc8 | |||
60adc56bbf | |||
ebbea8c3b0 | |||
41f81d22ed | |||
cbaf43232c | |||
825efc6fd0 | |||
68313da412 | |||
3ed027229d | |||
44b4326a52 | |||
b3b7b3f14f | |||
3d099d85fc | |||
9676cff128 | |||
47aba515fb | |||
62e849d1b4 | |||
d116f95c54 | |||
6215ca5e59 | |||
67266a3aae | |||
85f0b5f9be | |||
592c326442 | |||
214b6e80df | |||
9f2661023d | |||
d2516e7de3 | |||
0e8e42e015 | |||
e7b4afd472 | |||
952b3fc146 | |||
760f39dbf3 | |||
573c840de4 | |||
44da784f29 | |||
6be462c80b | |||
e67b8a3e4c | |||
933ea6093f | |||
84b952e115 | |||
f745be449d | |||
8775bacdd9 | |||
fb2310cb56 | |||
68322d9528 | |||
d04031e02f | |||
7dcc155b8f | |||
b5b593a62f | |||
81c44ba8f2 | |||
f30b976424 | |||
ab22347d7b | |||
e6882f3e4b | |||
452c8fa666 | |||
a0fe05f926 | |||
939a73b762 | |||
68f6b8e398 | |||
dddba5b35b | |||
5afe8b5a7f | |||
9e11db8181 | |||
00e53f76ee | |||
5051bf1b10 | |||
034191c78a | |||
c03fcf5d03 | |||
eb17194ff3 | |||
0e44a916e3 | |||
88f63faa0b | |||
172366d6fa | |||
e3cc6eaf1b | |||
1f5192b4ad | |||
2e004015d5 | |||
b080bcda7d | |||
2a03d9be12 | |||
2b8acc5f37 | |||
9504cfcec5 | |||
1c751472b2 | |||
b48395ce36 | |||
a2485392a5 | |||
50fae125ed | |||
264a0cb486 | |||
92d5e49fb6 | |||
64407174e3 | |||
dbd15d7823 | |||
99f945bc03 | |||
312569a734 | |||
15d54c7d34 | |||
ef2c70fb7a | |||
69582349bb | |||
bef6743c3b | |||
472e0dff39 | |||
7887c05249 | |||
9bb0c628b2 | |||
a35c8b9009 | |||
1dbab0f29e | |||
e83f40956b | |||
dc7cf42e90 | |||
4c6acb5de2 | |||
7e38f83b9e | |||
71e64e0f52 | |||
4b9dd1efe3 | |||
4acd6d6ca8 | |||
6848970fd9 | |||
00bf028904 | |||
1285602b2f | |||
8782564ddf | |||
4de6e677d1 | |||
2fca709814 | |||
ffc32df462 | |||
f597bc9aff | |||
bc8a044ab1 | |||
31ef5bb065 | |||
7de0887e7d | |||
4e8842d013 | |||
b8074733c9 | |||
98206e899d | |||
659c3545fb | |||
97f91c240c | |||
7022c238fd | |||
bbeb556a48 | |||
bb0736e8fc | |||
b8f5bd1680 | |||
6c1e02fa82 | |||
f872caf1f8 | |||
585859f4cd | |||
e7d775e2ae | |||
5cf226f166 | |||
37db45e651 | |||
57807e88f6 | |||
589578f420 | |||
39b6eed395 | |||
061219cb00 | |||
62ccd923ff | |||
43e670d02d | |||
0829899284 | |||
7540d39f95 | |||
67382a3f31 | |||
899e4b16bb | |||
63e5b51683 | |||
3c05016920 | |||
0580a0433f | |||
fee575d6d9 | |||
b08a5412f9 | |||
f32995367b | |||
201b3c8ada | |||
9c021408fa | |||
aceb838988 | |||
03a45094b7 | |||
92680c0dc0 | |||
da87fa07cf | |||
2247eff08a | |||
5018e4a7d4 | |||
cc32284e8a | |||
b1005061ff | |||
6486bbbd6d | |||
f9f63e7aba | |||
5c17250e20 | |||
fc9bca2ece | |||
2fa92520ef | |||
bbbc31594c | |||
56845e3897 | |||
9bebf2e99e | |||
4d1c3cd2ae | |||
e8b96b0a6e | |||
879c97f64c | |||
5d4d3be1b5 | |||
a99547c2f4 | |||
a846534ffb | |||
efaf8f8aae | |||
c424ae2f3b | |||
22e1884ad4 | |||
0cf05f4eff | |||
31f9d33327 | |||
8540d5aabd | |||
55b356ec69 | |||
ba09fb00e6 | |||
23e5e7674f | |||
7091daa0d1 | |||
71a3131d3c | |||
caed692440 | |||
c36f76460c | |||
5c9dfdf2db | |||
2f873167f6 | |||
437651411f | |||
6c3bad777d | |||
d02cdffcdb | |||
dc9e7eb44d | |||
5c30a1f0de | |||
48b74a91bc | |||
9c001487ba | |||
826384b9d5 | |||
16e16a181c | |||
490a2bb37b | |||
35d8b6f603 | |||
24d6aea68f | |||
c3e46e55aa | |||
bded79386f | |||
367fee6885 | |||
3182c7f2c2 | |||
28f36bf6f5 | |||
3431d03ef0 | |||
cd4454201b | |||
496db95153 | |||
307881a068 | |||
f3c0abef95 | |||
90a92656be | |||
cd165deb3c |
16
.babelrc
|
@ -1,3 +1,17 @@
|
|||
{
|
||||
"presets": ["env", "stage-2"]
|
||||
"presets": [["@babel/preset-env", { "loose": true }]],
|
||||
"env": {
|
||||
"test": {
|
||||
"presets": [
|
||||
[
|
||||
"@babel/preset-env",
|
||||
{
|
||||
"targets": {
|
||||
"node": true
|
||||
}
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
1
.browserslistrc
Normal file
|
@ -0,0 +1 @@
|
|||
> 1%
|
4
.codecov.yml
Normal file
|
@ -0,0 +1,4 @@
|
|||
coverage:
|
||||
parsers:
|
||||
javascript:
|
||||
enable_partials: yes
|
|
@ -1 +1,3 @@
|
|||
node_modules/
|
||||
types/
|
||||
public/
|
53
.eslintrc
|
@ -1,53 +0,0 @@
|
|||
{
|
||||
"parser": "babel-eslint",
|
||||
"extends": [
|
||||
"airbnb",
|
||||
"prettier"
|
||||
],
|
||||
"plugins": [
|
||||
"prettier",
|
||||
"cypress"
|
||||
],
|
||||
"env": {
|
||||
"es6": true,
|
||||
"browser": true,
|
||||
"node": true,
|
||||
"mocha": true,
|
||||
"cypress/globals": true
|
||||
},
|
||||
"globals": {
|
||||
"describe": true,
|
||||
"it": true,
|
||||
"before": true,
|
||||
"after": true,
|
||||
"beforeEach": true,
|
||||
"afterEach": true
|
||||
},
|
||||
"rules": {
|
||||
"import/no-extraneous-dependencies": [
|
||||
"error",
|
||||
{
|
||||
"devDependencies": true
|
||||
}
|
||||
],
|
||||
"no-console": [
|
||||
"warn",
|
||||
{
|
||||
"allow": [
|
||||
"warn",
|
||||
"error"
|
||||
]
|
||||
}
|
||||
],
|
||||
"no-plusplus": "off",
|
||||
"no-unused-expressions": "off",
|
||||
"no-underscore-dangle": "off",
|
||||
"prettier/prettier": [
|
||||
"error",
|
||||
{
|
||||
"singleQuote": true,
|
||||
"trailingComma": "all"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
123
.eslintrc.json
Normal file
|
@ -0,0 +1,123 @@
|
|||
{
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"plugins": ["@typescript-eslint", "prettier", "sort-class-members"],
|
||||
"extends": [
|
||||
"airbnb-base",
|
||||
"airbnb-typescript",
|
||||
"plugin:prettier/recommended",
|
||||
"plugin:compat/recommended",
|
||||
"plugin:@typescript-eslint/recommended"
|
||||
],
|
||||
"env": {
|
||||
"es6": true,
|
||||
"browser": true,
|
||||
"mocha": true,
|
||||
"cypress/globals": true
|
||||
},
|
||||
"parserOptions": {
|
||||
"project": "./tsconfig.json",
|
||||
"ecmaVersion": 2020
|
||||
},
|
||||
"rules": {
|
||||
"import/prefer-default-export": "off",
|
||||
"import/no-extraneous-dependencies": [
|
||||
"error",
|
||||
{
|
||||
"devDependencies": true
|
||||
}
|
||||
],
|
||||
"no-console": [
|
||||
"warn",
|
||||
{
|
||||
"allow": ["warn", "error"]
|
||||
}
|
||||
],
|
||||
"no-plusplus": "off",
|
||||
"no-unused-expressions": "off",
|
||||
"no-underscore-dangle": "off",
|
||||
"consistent-return": "off",
|
||||
"import/no-useless-path-segments": "warn",
|
||||
"prefer-destructuring": [
|
||||
"warn",
|
||||
{
|
||||
"array": false,
|
||||
"object": true
|
||||
}
|
||||
],
|
||||
"curly": ["error", "all"],
|
||||
"newline-before-return": "error",
|
||||
"sort-class-members/sort-class-members": [
|
||||
2,
|
||||
{
|
||||
"order": [
|
||||
"[static-properties]",
|
||||
"[static-methods]",
|
||||
"[properties]",
|
||||
"[conventional-private-properties]",
|
||||
"constructor",
|
||||
"[methods]",
|
||||
"[conventional-private-methods]"
|
||||
],
|
||||
"accessorPairPositioning": "getThenSet"
|
||||
}
|
||||
],
|
||||
"lines-between-class-members": "off",
|
||||
"@typescript-eslint/no-namespace": "off",
|
||||
"react/jsx-filename-extension": [0]
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["*.test.ts"],
|
||||
"env": {
|
||||
"mocha": true
|
||||
},
|
||||
"rules": {
|
||||
"no-restricted-syntax": "off",
|
||||
"compat/compat": "off",
|
||||
"no-new": "off",
|
||||
"@typescript-eslint/no-empty-function": "off",
|
||||
"@typescript-eslint/no-explicit-any": "off",
|
||||
"@typescript-eslint/no-non-null-assertion": "off",
|
||||
"@typescript-eslint/no-unused-expressions": "off",
|
||||
"@typescript-eslint/naming-convention": [
|
||||
"error",
|
||||
{
|
||||
"selector": "default",
|
||||
"format": ["camelCase", "PascalCase", "UPPER_CASE"],
|
||||
"leadingUnderscore": "allow"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": ["cypress/**"],
|
||||
"plugins": ["cypress"],
|
||||
"rules": {
|
||||
"no-unused-vars": "warn"
|
||||
},
|
||||
"env": {
|
||||
"cypress/globals": true
|
||||
}
|
||||
}
|
||||
],
|
||||
"settings": {
|
||||
"polyfills": [
|
||||
"Array.from",
|
||||
"Array.prototype.find",
|
||||
"Array.prototype.includes",
|
||||
"Symbol",
|
||||
"Symbol.iterator",
|
||||
"DOMTokenList",
|
||||
"Object.assign",
|
||||
"CustomEvent",
|
||||
"Element.prototype.classList",
|
||||
"Element.prototype.closest",
|
||||
"Element.prototype.dataset"
|
||||
],
|
||||
"import/resolver": {
|
||||
"node": {
|
||||
"extensions": [".js", ".ts"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
64
.gitattributes
vendored
Normal file
|
@ -0,0 +1,64 @@
|
|||
## GITATTRIBUTES FOR WEB PROJECTS
|
||||
#
|
||||
# These settings are for any web project.
|
||||
#
|
||||
# Details per file setting:
|
||||
# text These files should be normalized (i.e. convert CRLF to LF).
|
||||
# binary These files are binary and should be left untouched.
|
||||
#
|
||||
# Note that binary is a macro for -text -diff.
|
||||
######################################################################
|
||||
|
||||
# Auto detect
|
||||
## Handle line endings automatically for files detected as
|
||||
## text and leave all files detected as binary untouched.
|
||||
## This will handle all files NOT defined below.
|
||||
* text eol=lf
|
||||
|
||||
# Source code
|
||||
*.css text eol=lf
|
||||
*.html text diff=html eol=lf
|
||||
*.js text eol=lf
|
||||
*.json text eol=lf
|
||||
*.scss text diff=css eol=lf
|
||||
*.ts text eol=lf
|
||||
|
||||
# Documentation
|
||||
*.md text eol=lf
|
||||
*.txt text eol=lf
|
||||
AUTHORS text eol=lf
|
||||
CHANGELOG text eol=lf
|
||||
CHANGES text eol=lf
|
||||
CONTRIBUTING text eol=lf
|
||||
COPYING text eol=lf
|
||||
copyright text eol=lf
|
||||
*COPYRIGHT* text eol=lf
|
||||
INSTALL text eol=lf
|
||||
license text eol=lf
|
||||
LICENSE text eol=lf
|
||||
NEWS text eol=lf
|
||||
readme text eol=lf
|
||||
*README* text eol=lf
|
||||
TODO text eol=lf
|
||||
|
||||
# Linters
|
||||
.eslintrc text eol=lf
|
||||
.stylelintrc text eol=lf
|
||||
|
||||
# Configs
|
||||
.babelrc text eol=lf
|
||||
.browserslistrc text eol=lf
|
||||
.editorconfig text eol=lf
|
||||
.env text eol=lf
|
||||
.gitattributes text eol=lf
|
||||
.gitconfig text eol=lf
|
||||
package-lock.json text -diff eol=lf
|
||||
*.npmignore text eol=lf
|
||||
*.yaml text eol=lf
|
||||
*.yml text eol=lf
|
||||
browserslist text eol=lf
|
||||
|
||||
# Graphics
|
||||
# SVG treated as an asset (binary) by default.
|
||||
*.svg text eol=lf
|
||||
*.png binary
|
38
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
|
@ -0,0 +1,38 @@
|
|||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: bug
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Desktop (please complete the following information):**
|
||||
- OS: [e.g. iOS]
|
||||
- Browser [e.g. chrome, safari]
|
||||
- Version [e.g. 22]
|
||||
|
||||
**Smartphone (please complete the following information):**
|
||||
- Device: [e.g. iPhone6]
|
||||
- OS: [e.g. iOS8.1]
|
||||
- Browser [e.g. stock browser, safari]
|
||||
- Version [e.g. 22]
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
|
@ -0,0 +1,20 @@
|
|||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: feature request
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
22
.github/PULL_REQUEST_TEMPLATE.md
vendored
|
@ -1,28 +1,28 @@
|
|||
<!--- Provide a general summary of your changes in the Title above -->
|
||||
|
||||
## Description
|
||||
<!--- Describe your changes in detail -->
|
||||
|
||||
## Motivation and Context
|
||||
<!--- Describe your changes in detail -->
|
||||
<!--- Why is this change required? What problem does it solve? -->
|
||||
<!--- If it fixes an open issue, please link to the issue here. -->
|
||||
|
||||
## How Has This Been Tested?
|
||||
<!--- Please describe in detail how you tested your changes. -->
|
||||
<!--- Include details of your testing environment, tests ran to see how -->
|
||||
<!--- your change affects other areas of the code, etc. -->
|
||||
|
||||
## Screenshots (if appropriate):
|
||||
## Screenshots (if appropriate)
|
||||
|
||||
## Types of changes
|
||||
|
||||
<!--- What types of changes does your code introduce? Put an `x` in all the boxes that apply: -->
|
||||
|
||||
- [ ] Chore (tooling change or documentation change)
|
||||
- [ ] Refactor (non-breaking change which maintains existing functionality)
|
||||
- [ ] Bug fix (non-breaking change which fixes an issue)
|
||||
- [ ] New feature (non-breaking change which adds functionality)
|
||||
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
|
||||
|
||||
## Checklist:
|
||||
## Checklist
|
||||
|
||||
<!--- Go over all the following points, and put an `x` in all the boxes that apply. -->
|
||||
<!--- If you're unsure about any of these, don't hesitate to ask. We're here to help! -->
|
||||
|
||||
- [ ] My code follows the code style of this project.
|
||||
- [ ] I have added new tests for the bug I fixed/the new feature I added.
|
||||
- [ ] I have modified existing tests for the bug I fixed/the new feature I added.
|
||||
- [ ] My change requires a change to the documentation.
|
||||
- [ ] I have updated the documentation accordingly.
|
BIN
.github/actions-scripts/__snapshots__/chrome-win32.png
vendored
Normal file
After Width: | Height: | Size: 24 KiB |
BIN
.github/actions-scripts/__snapshots__/edge-win32.png
vendored
Normal file
After Width: | Height: | Size: 24 KiB |
BIN
.github/actions-scripts/__snapshots__/firefox-darwin.png
vendored
Executable file
After Width: | Height: | Size: 47 KiB |
BIN
.github/actions-scripts/__snapshots__/firefox-win32.png
vendored
Normal file
After Width: | Height: | Size: 104 KiB |
BIN
.github/actions-scripts/__snapshots__/ie-win32.png
vendored
Normal file
After Width: | Height: | Size: 22 KiB |
BIN
.github/actions-scripts/__snapshots__/puppeteer-darwin.png
vendored
Executable file
After Width: | Height: | Size: 297 KiB |
BIN
.github/actions-scripts/__snapshots__/safari-darwin.png
vendored
Normal file
After Width: | Height: | Size: 284 KiB |
14
.github/actions-scripts/polyfills-sync.js
vendored
Normal file
|
@ -0,0 +1,14 @@
|
|||
const { readFileSync } = require('fs');
|
||||
const path = require('path');
|
||||
const assert = require('assert');
|
||||
|
||||
const readme = readFileSync(path.resolve(__dirname, '../../README.md'), 'utf8');
|
||||
|
||||
const polyfillsFromDocs = /^```polyfills\s*\n([^`]+)\n^```/m
|
||||
.exec(readme)[1]
|
||||
.split('\n')
|
||||
.map(v => v.trim())
|
||||
.sort();
|
||||
// @ts-ignore
|
||||
const polyfillsFromSettings = require('../../.eslintrc.json').settings.polyfills.sort();
|
||||
assert.deepStrictEqual(polyfillsFromDocs, polyfillsFromSettings);
|
92
.github/actions-scripts/puppeteer.js
vendored
Normal file
|
@ -0,0 +1,92 @@
|
|||
const { readFileSync, writeFileSync, mkdirSync } = require('fs');
|
||||
const path = require('path');
|
||||
const { once } = require('events');
|
||||
|
||||
const puppeteer = require('puppeteer');
|
||||
const pixelmatch = require('pixelmatch');
|
||||
const { PNG } = require('pngjs');
|
||||
|
||||
const server = require('../../server');
|
||||
|
||||
async function test() {
|
||||
const browser = await puppeteer.launch();
|
||||
const page = await browser.newPage();
|
||||
const artifactsPath = 'screenshot';
|
||||
const snapshotName = `puppeteer-${process.platform}.png`;
|
||||
let error;
|
||||
let pixelDifference;
|
||||
let diff;
|
||||
|
||||
if (!server.listening) await once(server, 'listening');
|
||||
|
||||
try {
|
||||
page.on('console', msg => {
|
||||
if (msg.type() === 'error') throw new Error(msg.text());
|
||||
});
|
||||
page.on('pageerror', err => {
|
||||
throw err;
|
||||
});
|
||||
|
||||
await page.goto(`http://127.0.0.1:${server.address().port}`, {
|
||||
waitUntil: 'networkidle2',
|
||||
});
|
||||
await page.setViewport({ width: 640, height: 1000 });
|
||||
await page.waitForTimeout(500); // Wait for resize to complete
|
||||
await page.click('label[for="choices-single-custom-templates"]');
|
||||
await page.keyboard.press('ArrowDown');
|
||||
await page.keyboard.press('ArrowDown');
|
||||
|
||||
mkdirSync(artifactsPath, { recursive: true });
|
||||
const imageBuffer = await page.screenshot({
|
||||
path: path.join(artifactsPath, snapshotName),
|
||||
fullPage: true,
|
||||
});
|
||||
|
||||
// compare with snapshot
|
||||
const screenshot = PNG.sync.read(imageBuffer);
|
||||
const snapshot = PNG.sync.read(
|
||||
readFileSync(path.resolve(__dirname, `./__snapshots__/${snapshotName}`)),
|
||||
);
|
||||
const { width, height } = screenshot;
|
||||
diff = new PNG({ width, height });
|
||||
pixelDifference = pixelmatch(
|
||||
screenshot.data,
|
||||
snapshot.data,
|
||||
diff.data,
|
||||
width,
|
||||
height,
|
||||
{
|
||||
threshold: 0.6,
|
||||
},
|
||||
);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
error = err;
|
||||
} finally {
|
||||
if (diff) {
|
||||
writeFileSync(path.join(artifactsPath, 'diff-' + snapshotName), PNG.sync.write(diff));
|
||||
}
|
||||
await Promise.all([
|
||||
browser.close(),
|
||||
new Promise(resolve => server.close(resolve)),
|
||||
]);
|
||||
}
|
||||
|
||||
if (pixelDifference > 200) {
|
||||
console.error(
|
||||
`Snapshot is different from screenshot by ${pixelDifference} pixels`,
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
if (error) process.exit(1);
|
||||
}
|
||||
|
||||
process.on('unhandledRejection', err => {
|
||||
console.error(err);
|
||||
process.exit(1);
|
||||
});
|
||||
process.once('uncaughtException', err => {
|
||||
console.error(err);
|
||||
process.exit(1);
|
||||
});
|
||||
setImmediate(test);
|
155
.github/actions-scripts/selenium.js
vendored
Normal file
|
@ -0,0 +1,155 @@
|
|||
const path = require('path');
|
||||
const { readFileSync, writeFileSync, mkdirSync } = require('fs');
|
||||
const { once } = require('events');
|
||||
|
||||
const pixelmatch = require('pixelmatch');
|
||||
const { PNG } = require('pngjs');
|
||||
const {
|
||||
Builder,
|
||||
By,
|
||||
Key,
|
||||
until,
|
||||
Capabilities,
|
||||
logging,
|
||||
} = require('selenium-webdriver');
|
||||
|
||||
const server = require('../../server');
|
||||
|
||||
async function test() {
|
||||
let pixelDifference;
|
||||
let error;
|
||||
|
||||
let capabilities;
|
||||
switch (process.env.BROWSER) {
|
||||
case 'ie':
|
||||
capabilities = Capabilities.ie();
|
||||
capabilities.set('ignoreProtectedModeSettings', true);
|
||||
capabilities.set('ignoreZoomSetting', true);
|
||||
capabilities.set('ie.options', {
|
||||
enableFullPageScreenshot: true,
|
||||
ensureCleanSession: true,
|
||||
});
|
||||
break;
|
||||
|
||||
case 'edge':
|
||||
capabilities = Capabilities.edge();
|
||||
break;
|
||||
|
||||
case 'safari':
|
||||
capabilities = Capabilities.safari();
|
||||
capabilities.set('safari.options', { technologyPreview: false });
|
||||
break;
|
||||
|
||||
case 'firefox': {
|
||||
capabilities = Capabilities.firefox().setLoggingPrefs({ browser: 'ALL' });
|
||||
break;
|
||||
}
|
||||
case 'chrome': {
|
||||
capabilities = Capabilities.chrome().setLoggingPrefs({ browser: 'ALL' });
|
||||
capabilities.set('chromeOptions', {
|
||||
args: ['--headless', '--no-sandbox', '--disable-gpu'],
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
let driver = await new Builder().withCapabilities(capabilities).build();
|
||||
|
||||
if (!server.listening) await once(server, 'listening');
|
||||
|
||||
try {
|
||||
await driver.get(`http://127.0.0.1:${server.address().port}`);
|
||||
|
||||
// wait for last choice to init
|
||||
await driver.wait(
|
||||
until.elementLocated(By.css('#reset-multiple ~ .choices__list')),
|
||||
10000,
|
||||
'waiting for all Choices instances to init',
|
||||
);
|
||||
|
||||
// Resize window
|
||||
await driver
|
||||
.manage()
|
||||
.window()
|
||||
.maximize();
|
||||
await driver
|
||||
.manage()
|
||||
.window()
|
||||
// magic numbers here to make sure all demo page are fit inside
|
||||
.setRect({ x: 0, y: 0, width: 630, height: 4000 });
|
||||
|
||||
// and click on press space on it, so it should open choices
|
||||
await driver
|
||||
.findElement(By.css('#reset-multiple ~ .choices__list button'))
|
||||
.sendKeys(Key.SPACE);
|
||||
await driver.sleep(1000);
|
||||
|
||||
// take screenshot
|
||||
const image = await driver.takeScreenshot();
|
||||
const imageBuffer = Buffer.from(image, 'base64');
|
||||
|
||||
const snapshotName = `${process.env.BROWSER}-${process.platform}.png`;
|
||||
const artifactsPath = 'screenshot';
|
||||
mkdirSync(artifactsPath, { recursive: true });
|
||||
|
||||
writeFileSync(path.join(artifactsPath, snapshotName), imageBuffer);
|
||||
|
||||
// compare with snapshot
|
||||
const screenshot = PNG.sync.read(imageBuffer);
|
||||
const snapshot = PNG.sync.read(
|
||||
readFileSync(path.resolve(__dirname, `./__snapshots__/${snapshotName}`)),
|
||||
);
|
||||
const { width, height } = screenshot;
|
||||
const diff = new PNG({ width, height });
|
||||
pixelDifference = pixelmatch(
|
||||
screenshot.data,
|
||||
snapshot.data,
|
||||
diff.data,
|
||||
width,
|
||||
height,
|
||||
{
|
||||
threshold: 1,
|
||||
},
|
||||
);
|
||||
writeFileSync(path.join(artifactsPath, 'diff.png'), PNG.sync.write(diff));
|
||||
|
||||
// getting console logs
|
||||
// ensure no errors in console (only supported in Chrome currently)
|
||||
if (process.env.BROWSER === 'chrome') {
|
||||
const entries = await driver
|
||||
.manage()
|
||||
.logs()
|
||||
.get(logging.Type.BROWSER);
|
||||
if (
|
||||
Array.isArray(entries) &&
|
||||
entries.some(entry => entry.level.name_ === 'SEVERE')
|
||||
)
|
||||
throw new Error(JSON.stringify(entries));
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
error = err;
|
||||
} finally {
|
||||
await Promise.all([
|
||||
driver.quit(),
|
||||
new Promise(resolve => server.close(resolve)),
|
||||
]);
|
||||
}
|
||||
if (pixelDifference > 200) {
|
||||
console.error(
|
||||
`Snapshot is different from screenshot by ${pixelDifference} pixels`,
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
if (error) process.exit(1);
|
||||
}
|
||||
|
||||
process.on('unhandledRejection', err => {
|
||||
console.error(err);
|
||||
process.exit(1);
|
||||
});
|
||||
process.once('uncaughtException', err => {
|
||||
console.error(err);
|
||||
process.exit(1);
|
||||
});
|
||||
setImmediate(test);
|
29
.github/release-drafter.yml
vendored
Normal file
|
@ -0,0 +1,29 @@
|
|||
name-template: 'Draft (next release)'
|
||||
tag-template: 'v$NEXT_PATCH_VERSION'
|
||||
sort-direction: descending
|
||||
exclude-labels:
|
||||
- 'skip-changelog'
|
||||
- 'release'
|
||||
categories:
|
||||
- title: '🚨 Breaking changes'
|
||||
labels:
|
||||
- 'breaking change'
|
||||
- title: '🚀 Features'
|
||||
labels:
|
||||
- 'feature'
|
||||
- 'enhancement'
|
||||
- title: '🐛 Bug Fixes'
|
||||
labels:
|
||||
- 'bugfix'
|
||||
- title: '🔧 Maintenance'
|
||||
labels:
|
||||
- 'chore'
|
||||
- 'housekeeping'
|
||||
- 'refactor'
|
||||
- 'documentation'
|
||||
change-template: '- $TITLE @$AUTHOR (#$NUMBER)'
|
||||
template: |
|
||||
# Changes
|
||||
$CHANGES
|
||||
# Contributors
|
||||
$CONTRIBUTORS
|
20
.github/stale.yml
vendored
|
@ -1,20 +0,0 @@
|
|||
# Number of days of inactivity before an issue becomes stale
|
||||
daysUntilStale: 60
|
||||
# Number of days of inactivity before a stale issue is closed
|
||||
daysUntilClose: 7
|
||||
# Issues with these labels will never be considered stale
|
||||
exemptLabels:
|
||||
- pinned
|
||||
- security
|
||||
- feature request
|
||||
# Label to use when marking an issue as stale
|
||||
staleLabel: stale
|
||||
# Comment to post when marking an issue as stale. Set to `false` to disable
|
||||
markComment: >
|
||||
Thanks for contributing to this issue. As it has been 60 days since the last
|
||||
activity, this issue is being automatically closed. This is often because the
|
||||
request was already solved in some way and it just wasn't updated or it's no
|
||||
longer applicable. If that's not the case, please do feel free to either
|
||||
reopen this issue or open a new one. We'll gladly take a look again!
|
||||
# Comment to post when closing a stale issue. Set to `false` to disable
|
||||
closeComment: false
|
131
.github/workflows/browsers.yml
vendored
Normal file
|
@ -0,0 +1,131 @@
|
|||
name: Browsers
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'src/**'
|
||||
- 'package-lock.json'
|
||||
- '.browserslistrc'
|
||||
- '.babelrc'
|
||||
- 'webpack.config.*'
|
||||
- 'public/index.html'
|
||||
- '.github/actions-scripts/__snapshots__/**'
|
||||
- '.github/workflows/browsers.yml'
|
||||
|
||||
jobs:
|
||||
selenium:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [windows-latest, macos-latest]
|
||||
browser: [edge, firefox, safari, chrome]
|
||||
exclude:
|
||||
- os: windows-latest
|
||||
browser: safari
|
||||
- os: macos-latest
|
||||
browser: edge
|
||||
- os: macos-latest
|
||||
browser: chrome
|
||||
# Safari workaround is not working in Catalina
|
||||
- browser: safari
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Dump GitHub context
|
||||
env:
|
||||
GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||
run: echo "$GITHUB_CONTEXT"
|
||||
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 1
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 18.x
|
||||
|
||||
- name: Cache node modules
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.npm
|
||||
key: ${{ runner.OS }}-build-${{ matrix.browser }}
|
||||
restore-keys: |
|
||||
${{ runner.OS }}-build-${{ env.cache-name }}-
|
||||
${{ runner.OS }}-build-
|
||||
${{ runner.OS }}-
|
||||
|
||||
- run: |
|
||||
npm ci
|
||||
npm run build
|
||||
env:
|
||||
CYPRESS_INSTALL_BINARY: 0
|
||||
HUSKY_SKIP_INSTALL: true
|
||||
|
||||
# install drivers
|
||||
- name: Enable Safari Driver
|
||||
run: |
|
||||
# Workaround for `sudo safardriver --enable` not working:
|
||||
# https://github.com/web-platform-tests/wpt/issues/19845
|
||||
# https://github.com/web-platform-tests/wpt/blob/master/tools/ci/azure/install_safari.yml
|
||||
mkdir -p ~/Library/WebDriver/
|
||||
curl https://raw.githubusercontent.com/web-platform-tests/wpt/master/tools/ci/azure/com.apple.Safari.plist -o ~/Library/WebDriver/com.apple.Safari.plist
|
||||
defaults write com.apple.Safari WebKitJavaScriptCanOpenWindowsAutomatically 1
|
||||
# sudo safaridriver --enable
|
||||
if: matrix.browser == 'safari'
|
||||
|
||||
- run: |
|
||||
brew install --cask firefox
|
||||
brew install geckodriver
|
||||
if: matrix.browser == 'firefox' && matrix.os == 'macos-latest'
|
||||
|
||||
- run: echo "$env:GeckoWebDriver" >> $GITHUB_PATH
|
||||
if: matrix.browser == 'firefox' && matrix.os == 'windows-latest'
|
||||
|
||||
- run: echo "$env:EdgeWebDriver" >> $GITHUB_PATH
|
||||
if: matrix.browser == 'edge' && matrix.os == 'windows-latest'
|
||||
|
||||
- run: echo "$env:ChromeWebDriver" >> $GITHUB_PATH
|
||||
if: matrix.browser == 'chrome' && matrix.os == 'windows-latest'
|
||||
|
||||
- run: npm i --no-optional --no-audit selenium-webdriver pixelmatch pngjs
|
||||
- run: node .github/actions-scripts/selenium.js
|
||||
env:
|
||||
BROWSER: ${{ matrix.browser }}
|
||||
PORT: 0
|
||||
NODE_ENV: production # prevent watching
|
||||
|
||||
- uses: actions/upload-artifact@v2
|
||||
if: failure()
|
||||
with:
|
||||
name: screenshot-${{ matrix.browser }}-${{ matrix.os }}
|
||||
path: screenshot
|
||||
|
||||
puppeteer:
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 1
|
||||
- name: Cache node modules
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.npm
|
||||
key: ${{ runner.OS }}-build-puppeteer
|
||||
restore-keys: |
|
||||
${{ runner.OS }}-build-puppeteer
|
||||
- run: |
|
||||
npm ci
|
||||
npm run build
|
||||
env:
|
||||
CYPRESS_INSTALL_BINARY: 0
|
||||
HUSKY_SKIP_INSTALL: true
|
||||
- run: npm i --no-optional --no-audit puppeteer pixelmatch pngjs
|
||||
- run: node .github/actions-scripts/puppeteer.js
|
||||
env:
|
||||
PORT: 0
|
||||
NODE_ENV: production # prevent watching
|
||||
|
||||
- uses: actions/upload-artifact@v2
|
||||
if: failure()
|
||||
with:
|
||||
name: screenshot-puppeteer-darwin
|
||||
path: screenshot
|
60
.github/workflows/build-and-test.yml
vendored
Normal file
|
@ -0,0 +1,60 @@
|
|||
name: Build and test
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
build-and-test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 1
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 18
|
||||
- name: Build and run all tests
|
||||
run: |
|
||||
npm ci
|
||||
npm run build
|
||||
npx bundlesize
|
||||
npm run test:unit:coverage
|
||||
npm run test:e2e
|
||||
env:
|
||||
CI: true
|
||||
CI_REPO_NAME: ${{ github.event.repository.name }}
|
||||
CI_REPO_OWNER: ${{ github.event.organization.login }}
|
||||
CI_COMMIT_SHA: ${{ github.sha }}
|
||||
GIT_COMMIT: ${{ github.sha }}
|
||||
CI_BRANCH: ${{ github.head_ref }}
|
||||
BUNDLESIZE_GITHUB_TOKEN: ${{secrets.BUNDLESIZE_GITHUB_TOKEN}}
|
||||
FORCE_COLOR: 2
|
||||
HUSKY_SKIP_INSTALL: true
|
||||
##
|
||||
## Disabling for now. There does not appear to be a secure way to do this
|
||||
## with protected branches. See discussion:
|
||||
## https://github.community/t/how-to-push-to-protected-branches-in-a-github-action/16101
|
||||
##
|
||||
# - name: Commit built files
|
||||
# run: |
|
||||
# git config --local user.email "action@github.com"
|
||||
# git config --local user.name "GitHub Action"
|
||||
# git commit -m "Update build files 🏗" -a || echo "No changes to commit" && exit 0
|
||||
# - name: Push changes
|
||||
# uses: ad-m/github-push-action@master
|
||||
# with:
|
||||
# github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Upload coverage to Codecov
|
||||
run: bash <(curl -s https://codecov.io/bash)
|
||||
-f ./coverage/lcov.info
|
||||
-B ${{ github.head_ref }}
|
||||
-C ${{ github.sha }}
|
||||
-Z || echo 'Codecov upload failed'
|
||||
env:
|
||||
CI: true
|
||||
GITLAB_CI: true # pretend we are GitLab CI, while Codecov adding support for Github Actions
|
||||
CODECOV_ENV: github-action
|
||||
CODECOV_TOKEN: ${{secrets.CODECOV_TOKEN}}
|
42
.github/workflows/bundlesize.yml
vendored
Normal file
|
@ -0,0 +1,42 @@
|
|||
name: Bundle size checks
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'src/scripts/**'
|
||||
- 'src/styles/**'
|
||||
- 'package-lock.json'
|
||||
- '.browserslistrc'
|
||||
|
||||
jobs:
|
||||
measure:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 1
|
||||
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 18
|
||||
|
||||
- name: Install dependencies and build
|
||||
run: |
|
||||
npm ci
|
||||
npm run build
|
||||
env:
|
||||
CYPRESS_INSTALL_BINARY: 0
|
||||
HUSKY_SKIP_INSTALL: true
|
||||
|
||||
# we don't need to build here, as even minized assets expected to be commited
|
||||
|
||||
- run: npx bundlesize
|
||||
env:
|
||||
CI: true
|
||||
BUNDLESIZE_GITHUB_TOKEN: ${{secrets.BUNDLESIZE_GITHUB_TOKEN}}
|
||||
CI_REPO_NAME: ${{ github.event.repository.name }}
|
||||
CI_REPO_OWNER: ${{ github.event.organization.login }}
|
||||
CI_COMMIT_SHA: ${{ github.event.after }}
|
||||
GIT_COMMIT: ${{ github.event.after }}
|
||||
CI_BRANCH: ${{ github.head_ref }}
|
||||
FORCE_COLOR: 2
|
32
.github/workflows/deploy-pages.yml
vendored
Normal file
|
@ -0,0 +1,32 @@
|
|||
name: Deploy Pages
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
deploy-gh-pages:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 1
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 18
|
||||
registry-url: https://registry.npmjs.org/
|
||||
- name: Build
|
||||
run: |
|
||||
npm ci
|
||||
npm run build
|
||||
rm -rf public/test
|
||||
env:
|
||||
CYPRESS_INSTALL_BINARY: 0
|
||||
HUSKY_SKIP_INSTALL: true
|
||||
- name: Deploy
|
||||
uses: peaceiris/actions-gh-pages@v3
|
||||
with:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
PUBLISH_BRANCH: gh-pages
|
||||
PUBLISH_DIR: ./public
|
24
.github/workflows/deployment.yml
vendored
Normal file
|
@ -0,0 +1,24 @@
|
|||
name: Publish to npm
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
jobs:
|
||||
publish-npm:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 1
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 18
|
||||
registry-url: https://registry.npmjs.org/
|
||||
- run: npm ci
|
||||
env:
|
||||
CYPRESS_INSTALL_BINARY: 0
|
||||
HUSKY_SKIP_INSTALL: true
|
||||
- run: npm publish
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
|
71
.github/workflows/e2e-tests.yml
vendored
Normal file
|
@ -0,0 +1,71 @@
|
|||
name: End-to-end tests
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'src/**'
|
||||
- 'package-lock.json'
|
||||
- '.browserslistrc'
|
||||
- '.babelrc'
|
||||
- 'webpack.config.*'
|
||||
- 'public/test/**'
|
||||
- 'cypress/**'
|
||||
- '.github/workflows/e2e-tests.yml'
|
||||
|
||||
jobs:
|
||||
test-e2e:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
CI: true
|
||||
TERM: xterm-256color
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 1
|
||||
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 18.x
|
||||
|
||||
- name: Cache node modules
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.npm
|
||||
key: ${{ runner.OS }}-build-${{ hashFiles('**/package-lock.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.OS }}-build-${{ env.cache-name }}-
|
||||
${{ runner.OS }}-build-
|
||||
${{ runner.OS }}-
|
||||
|
||||
- name: Get Cypress info
|
||||
id: cypress-info
|
||||
run: |
|
||||
echo ::set-output name=version::$(jq -r .devDependencies.cypress ./package.json)
|
||||
echo ::set-output name=cache::$(npx cypress cache path)
|
||||
env:
|
||||
CYPRESS_INSTALL_BINARY: 0
|
||||
- name: Cache Cypress cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ steps.cypress-info.outputs.cache }}
|
||||
key: ${{ runner.OS }}-cypress-${{ steps.cypress-info.outputs.version }}
|
||||
restore-keys: |
|
||||
${{ runner.OS }}-cypress-${{ steps.cypress-info.outputs.version }}
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
env:
|
||||
HUSKY_SKIP_INSTALL: true
|
||||
|
||||
- name: run Cypress (with or without recording)
|
||||
# if we have ran out of free Cypress recordings, run Cypress with recording switched off
|
||||
run: npm exec -- run-p --race start cypress:ci || npm exec -- run-p --race start cypress:run
|
||||
env:
|
||||
NODE_ENV: production # prevent watching
|
||||
CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
|
||||
DEBUG: commit-info,cypress:server:record
|
||||
# https://docs.cypress.io/guides/guides/continuous-integration.html#Environment-variables
|
||||
COMMIT_INFO_BRANCH: ${{ github.head_ref }}
|
||||
COMMIT_INFO_AUTHOR: ${{ github.event.sender.login }}
|
||||
COMMIT_INFO_SHA: ${{ github.event.after }}
|
41
.github/workflows/lint.yml
vendored
Normal file
|
@ -0,0 +1,41 @@
|
|||
name: Code linting
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'src/scripts/**'
|
||||
- 'src/styles/**'
|
||||
- package-lock.json
|
||||
- '.browserslistrc'
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 1
|
||||
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 18
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
env:
|
||||
CYPRESS_INSTALL_BINARY: 0
|
||||
HUSKY_SKIP_INSTALL: true
|
||||
|
||||
- name: run eslint
|
||||
run: npm run lint:js
|
||||
|
||||
## Can't use same eslint config for TypeScript and JavaScript
|
||||
## TypeScript rules cause rule definition not found errors
|
||||
## Can be re-enabled if this is resolved: https://github.com/eslint/eslint/issues/14851
|
||||
# - name: Lint JS bundle
|
||||
# run: |
|
||||
# npm run js:build
|
||||
# npx eslint --no-ignore ./public/assets/scripts/*.js
|
||||
|
||||
- name: run stylelint
|
||||
run: npm run lint:scss
|
23
.github/workflows/polyfills-sync.yml
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
name: Polyfills documentation
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'README.md'
|
||||
- '.browserslistrc'
|
||||
- '.eslintrc.json'
|
||||
|
||||
jobs:
|
||||
sync:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 1
|
||||
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 18
|
||||
|
||||
- name: Check Polyfills documentation and settings sync
|
||||
run: node .github/actions-scripts/polyfills-sync.js
|
14
.github/workflows/release-drafter.yml
vendored
Normal file
|
@ -0,0 +1,14 @@
|
|||
name: Release drafter
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
update-draft-release:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: release-drafter/release-drafter@v5
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
42
.github/workflows/unit-tests.yml
vendored
Normal file
|
@ -0,0 +1,42 @@
|
|||
name: Unit tests
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'src/scripts/**'
|
||||
- package-lock.json
|
||||
- '.browserslistrc'
|
||||
|
||||
jobs:
|
||||
test-unit:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 1
|
||||
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 18
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm install --no-optional --no-audit --ignore-scripts
|
||||
env:
|
||||
CYPRESS_INSTALL_BINARY: 0
|
||||
HUSKY_SKIP_INSTALL: true
|
||||
|
||||
- run: npm run test:unit:coverage
|
||||
env:
|
||||
FORCE_COLOR: 2
|
||||
|
||||
- name: Upload coverage to Codecov
|
||||
run: bash <(curl -s https://codecov.io/bash)
|
||||
-f ./coverage/lcov.info
|
||||
-B ${{ github.head_ref }}
|
||||
-C ${{ github.sha }}
|
||||
-Z || echo 'Codecov upload failed'
|
||||
env:
|
||||
CI: true
|
||||
GITLAB_CI: true # pretend we are GitLab CI, while Codecov adding support for Github Actions
|
||||
CODECOV_ENV: github-action
|
||||
CODECOV_TOKEN: ${{secrets.CODECOV_TOKEN}}
|
3
.gitignore
vendored
|
@ -1,10 +1,7 @@
|
|||
node_modules
|
||||
npm-debug.log
|
||||
.DS_Store
|
||||
.gitignore
|
||||
.idea
|
||||
.vscode
|
||||
package-lock.json
|
||||
|
||||
# Test
|
||||
tests/reports
|
||||
|
|
6
.huskyrc
Normal file
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"skipCI": true,
|
||||
"hooks": {
|
||||
"pre-commit": "lint-staged"
|
||||
}
|
||||
}
|
8
.mocharc.yml
Normal file
|
@ -0,0 +1,8 @@
|
|||
require:
|
||||
- 'ts-node/register'
|
||||
- './config/jsdom.js'
|
||||
exit: true
|
||||
spec: src/**/**/*.test.ts
|
||||
extension:
|
||||
- ts
|
||||
- js
|
20
.prettierrc.json
Normal file
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"singleQuote": true,
|
||||
"trailingComma": "all",
|
||||
"endOfLine": "lf",
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["*.svg"],
|
||||
"options": {
|
||||
"parser": "html",
|
||||
"htmlWhitespaceSensitivity": "ignore"
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": ["public/*.html"],
|
||||
"options": {
|
||||
"trailingComma": "es5"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
6
.stylelintrc.json
Normal file
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"extends": "stylelint-config-standard-scss",
|
||||
"rules": {
|
||||
"declaration-block-no-redundant-longhand-properties": null
|
||||
}
|
||||
}
|
12
.travis.yml
|
@ -1,12 +0,0 @@
|
|||
language: node_js
|
||||
node_js:
|
||||
- "8"
|
||||
before_install:
|
||||
- '[ "${TRAVIS_NODE_VERSION}" != "0.8" ] || npm install -g npm@1.4.28'
|
||||
- npm install -g npm@latest
|
||||
install:
|
||||
- npm install
|
||||
script:
|
||||
- npm run test:unit
|
||||
- npm run coverage
|
||||
- npm run test:e2e
|
17
.vscode/extensions.json
vendored
Normal file
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
// See http://go.microsoft.com/fwlink/?LinkId=827846
|
||||
// for the documentation about the extensions.json format
|
||||
"recommendations": [
|
||||
// we enforce ESLint rules, so, recommend extension
|
||||
"dbaeumer.vscode-eslint",
|
||||
// we use prettier, so, recommend extension
|
||||
"esbenp.prettier-vscode",
|
||||
// we are on GitHub, so, recommend extension
|
||||
"github.vscode-pull-request-github",
|
||||
// needed for our configured debug configuration with Chrome
|
||||
"msjsdiag.debugger-for-chrome"
|
||||
// Mocha recommended - https://mochajs.org/#mocha-sidebar-vs-code,
|
||||
// but it's buggy
|
||||
// "maty.vscode-mocha-sidebar"
|
||||
]
|
||||
}
|
70
.vscode/launch.json
vendored
Normal file
|
@ -0,0 +1,70 @@
|
|||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "chrome",
|
||||
"request": "launch",
|
||||
"name": "Launch Chrome",
|
||||
"preLaunchTask": "buildAndWatch",
|
||||
"url": "http://localhost:3001",
|
||||
"webRoot": "${workspaceFolder}",
|
||||
"sourceMapPathOverrides": {
|
||||
"webpack://Choices/*": "${workspaceFolder}/*"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"name": "Mocha Current File",
|
||||
"program": "${workspaceFolder}/node_modules/mocha/bin/mocha",
|
||||
"args": ["-u", "bdd", "--timeout", "999999", "--colors", "${file}"],
|
||||
"console": "integratedTerminal",
|
||||
"internalConsoleOptions": "neverOpen",
|
||||
"env": {
|
||||
"NODE_ENV": "test"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"name": "Mocha All",
|
||||
"program": "${workspaceFolder}/node_modules/mocha/bin/_mocha",
|
||||
"args": ["-u", "bdd", "--timeout", "999999", "--colors"],
|
||||
"console": "integratedTerminal",
|
||||
"internalConsoleOptions": "openOnSessionStart",
|
||||
"env": {
|
||||
"NODE_ENV": "test"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"name": "Cypress Current File",
|
||||
"runtimeExecutable": "${workspaceFolder}/node_modules/.bin/cypress",
|
||||
"windows": {
|
||||
"runtimeExecutable": "${workspaceFolder}\\node_modules\\.bin\\cypress.cmd"
|
||||
},
|
||||
"runtimeArgs": [
|
||||
"run",
|
||||
"--headed",
|
||||
"--no-exit",
|
||||
"--browser=electron",
|
||||
"--port",
|
||||
"9898",
|
||||
"--spec"
|
||||
],
|
||||
"protocol": "legacy",
|
||||
"port": 9898,
|
||||
"program": "${file}",
|
||||
"console": "integratedTerminal",
|
||||
"preLaunchTask": "buildAndWatch",
|
||||
"internalConsoleOptions": "openOnSessionStart",
|
||||
"timeout": 999999999999999,
|
||||
"autoAttachChildProcesses": false,
|
||||
"env": {
|
||||
"NODE_ENV": "test"
|
||||
// "DEBUG": "cypress:*"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
72
.vscode/settings.json
vendored
Normal file
|
@ -0,0 +1,72 @@
|
|||
{
|
||||
"eslint.enable": true,
|
||||
// prevent watch task failures on lint errors
|
||||
"eslint.autoFixOnSave": true,
|
||||
// switch off default VSCode formatting rules
|
||||
"javascript.format.enable": false,
|
||||
// Javascript prettier runs via ESLint
|
||||
"prettier.disableLanguages": ["javascript"],
|
||||
"[json]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[html]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[scss]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[javascript]": {
|
||||
"editor.formatOnSave": false
|
||||
},
|
||||
"search.exclude": {
|
||||
"**/node_modules": true,
|
||||
"public/assets": true,
|
||||
"**/coverage": true
|
||||
},
|
||||
// Mocha Sidebar settings
|
||||
"mocha.env": {
|
||||
"NODE_ENV": "test"
|
||||
},
|
||||
"mocha.files.glob": "src/scripts/**/*.test.js",
|
||||
"mocha.requires": ["@babel/register", "./config/jsdom.js"],
|
||||
// for Windows collaborators
|
||||
"files.eol": "\n",
|
||||
"files.encoding": "utf8",
|
||||
// associations for some files this project is using
|
||||
"files.associations": {
|
||||
".browserslistrc": "gitignore",
|
||||
".huskyrc": "jsonc",
|
||||
".npmrc": "ini"
|
||||
},
|
||||
// We use NPM as package manager
|
||||
"npm.packageManager": "npm",
|
||||
"npm.autoDetect": "on",
|
||||
"npm.fetchOnlinePackageInfo": true,
|
||||
"eslint.packageManager": "npm",
|
||||
"json.schemas": [
|
||||
// Cypress related settings - https://docs.cypress.io/guides/tooling/intelligent-code-completion.html#Features-1
|
||||
{
|
||||
"fileMatch": ["cypress.json"],
|
||||
"url": "https://on.cypress.io/cypress.schema.json"
|
||||
},
|
||||
// Husky config file
|
||||
{
|
||||
"fileMatch": [".huskyrc"],
|
||||
"url": "http://json.schemastore.org/huskyrc"
|
||||
},
|
||||
// Prettier config
|
||||
{
|
||||
"fileMatch": [".prettierrc.json"],
|
||||
"url": "http://json.schemastore.org/prettierrc"
|
||||
}
|
||||
],
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.eslint": true
|
||||
},
|
||||
"stylelint.validate": [
|
||||
"css",
|
||||
"less",
|
||||
"postcss",
|
||||
"scss"
|
||||
]
|
||||
}
|
87
.vscode/tasks.json
vendored
Normal file
|
@ -0,0 +1,87 @@
|
|||
{
|
||||
// See https://go.microsoft.com/fwlink/?LinkId=733558
|
||||
// for the documentation about the tasks.json format
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"type": "npm",
|
||||
"label": "buildAndWatch",
|
||||
"script": "js:watch",
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
},
|
||||
"isBackground": true,
|
||||
"presentation": {
|
||||
"echo": true,
|
||||
"reveal": "always",
|
||||
"focus": false,
|
||||
"panel": "dedicated",
|
||||
"showReuseMessage": true,
|
||||
"clear": false
|
||||
},
|
||||
"problemMatcher": [
|
||||
"$eslint-stylish",
|
||||
{
|
||||
"owner": "webpack",
|
||||
"fileLocation": "absolute",
|
||||
"pattern": [
|
||||
{
|
||||
"regexp": "^Module build failed \\(from (\\.+)\\)",
|
||||
"file": 1,
|
||||
"line": 2,
|
||||
"column": 3
|
||||
},
|
||||
{
|
||||
"regexp": "\\s*TS\\d+:\\s*(.*)",
|
||||
"message": 1
|
||||
}
|
||||
],
|
||||
"severity": "error",
|
||||
"source": "webpack",
|
||||
"background": {
|
||||
"activeOnStart": true,
|
||||
"beginsPattern": "^Listening at",
|
||||
"endsPattern": "Compiled successfully\\."
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "css:build",
|
||||
"group": "build",
|
||||
"problemMatcher": ["$node-sass"]
|
||||
},
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "lint",
|
||||
"problemMatcher": ["$eslint-stylish"]
|
||||
},
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "build",
|
||||
"group": "build"
|
||||
},
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "test",
|
||||
"group": "test"
|
||||
},
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "test:e2e",
|
||||
"group": "test"
|
||||
},
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "test:unit",
|
||||
"group": "test"
|
||||
},
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "cypress:open",
|
||||
"isBackground": true
|
||||
}
|
||||
]
|
||||
}
|
|
@ -5,7 +5,8 @@ In lieu of a formal styleguide, take care to maintain the existing coding style
|
|||
| Task | Usage |
|
||||
| -------------------- | ------------------------------------------------------------ |
|
||||
| `npm run start` | Fire up local server for development |
|
||||
| `npm run test` | Run sequence of tests once |
|
||||
| `npm run test:unit` | Run sequence of unit tests once |
|
||||
| `npm run test:e2e` | Run sequence of integration tests once |
|
||||
| `npm run test:watch` | Fire up test server and re-test on file change |
|
||||
| `npm run js:build` | Compile Choices to an uglified JavaScript file |
|
||||
| `npm run css:watch` | Watch SCSS files for changes. On a change, run build process |
|
||||
|
|
|
@ -1,54 +0,0 @@
|
|||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const config = {
|
||||
files: ['public/index.html'],
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert node arguments into an object
|
||||
* @return {Object} Arguments
|
||||
*/
|
||||
const argvToObject = () => {
|
||||
const args = {};
|
||||
let arg = null;
|
||||
process.argv.forEach((val, index) => {
|
||||
if (/^--/.test(val)) {
|
||||
arg = {
|
||||
index,
|
||||
name: val.replace(/^--/, ''),
|
||||
};
|
||||
return;
|
||||
}
|
||||
|
||||
if (arg && arg.index + 1 === index) {
|
||||
args[arg.name] = val;
|
||||
}
|
||||
});
|
||||
|
||||
return args;
|
||||
};
|
||||
|
||||
/**
|
||||
* Loop through files updating the current version
|
||||
* @param {Object} config
|
||||
*/
|
||||
const updateVersion = ({ files }) => {
|
||||
const args = argvToObject();
|
||||
const version = args.current;
|
||||
|
||||
console.log(`Updating version to ${version}`);
|
||||
|
||||
files.forEach(file => {
|
||||
const filePath = path.join(__dirname, file);
|
||||
const regex = new RegExp(/\?version=(.*?)\"/, 'g');
|
||||
|
||||
let contents = fs.readFileSync(filePath, 'utf-8');
|
||||
contents = contents.replace(regex, `?version=${version}"`);
|
||||
fs.writeFileSync(filePath, contents);
|
||||
});
|
||||
|
||||
console.log(`Updated version to ${version}`);
|
||||
};
|
||||
|
||||
updateVersion(config);
|
|
@ -1,6 +1,13 @@
|
|||
/* eslint-disable no-param-reassign */
|
||||
|
||||
const { JSDOM } = require('jsdom');
|
||||
|
||||
const jsdom = new JSDOM('<!doctype html><html><body></body></html>');
|
||||
const jsdom = new JSDOM(
|
||||
'<!doctype html><html><head><meta charset="utf-8"></head><body></body></html>',
|
||||
{
|
||||
pretendToBeVisual: true,
|
||||
},
|
||||
);
|
||||
const { window } = jsdom;
|
||||
|
||||
function copyProps(src, target) {
|
||||
|
@ -20,26 +27,6 @@ function ignoreExtensions(extensions = [], returnValue = {}) {
|
|||
});
|
||||
}
|
||||
|
||||
function mockRAF(global) {
|
||||
let callbacksQueue = [];
|
||||
|
||||
global.setInterval(() => {
|
||||
for (let i = 0; i < callbacksQueue.length; i++) {
|
||||
if (callbacksQueue[i] !== false) {
|
||||
callbacksQueue[i].call(null);
|
||||
}
|
||||
}
|
||||
|
||||
callbacksQueue = [];
|
||||
}, 1000 / 60);
|
||||
|
||||
global.requestAnimationFrame = callback => callbacksQueue.push(callback) - 1;
|
||||
|
||||
global.cancelAnimationFrame = id => {
|
||||
callbacksQueue[id] = false;
|
||||
};
|
||||
}
|
||||
|
||||
global.window = window;
|
||||
global.document = window.document;
|
||||
global.navigator = {
|
||||
|
@ -48,12 +35,16 @@ global.navigator = {
|
|||
global.CustomEvent = window.CustomEvent;
|
||||
global.Element = window.Element;
|
||||
global.HTMLElement = window.HTMLElement;
|
||||
global.Option = window.Option;
|
||||
global.HTMLOptionElement = window.HTMLOptionElement;
|
||||
global.HTMLOptGroupElement = window.HTMLOptGroupElement;
|
||||
global.HTMLSelectElement = window.HTMLSelectElement;
|
||||
global.HTMLInputElement = window.HTMLInputElement;
|
||||
global.DocumentFragment = window.DocumentFragment;
|
||||
global.requestAnimationFrame = window.requestAnimationFrame;
|
||||
window.matchMedia = () => true;
|
||||
|
||||
copyProps(window, global);
|
||||
mockRAF(global);
|
||||
|
||||
ignoreExtensions(['.scss', '.css']);
|
||||
ignoreExtensions(['.jpg', '.png', '.svg'], '');
|
||||
|
|
15
cypress.config.ts
Normal file
|
@ -0,0 +1,15 @@
|
|||
import { defineConfig } from 'cypress'
|
||||
|
||||
export default defineConfig({
|
||||
video: false,
|
||||
projectId: 'n7g5qp',
|
||||
e2e: {
|
||||
// We've imported your old cypress plugins here.
|
||||
// You may want to clean this up later by importing these.
|
||||
setupNodeEvents(on, config) {
|
||||
return require('./cypress/plugins/index.js')(on, config)
|
||||
},
|
||||
baseUrl: 'http://localhost:3001/test',
|
||||
specPattern: 'cypress/e2e/**/*.{js,jsx,ts,tsx}',
|
||||
},
|
||||
})
|
|
@ -1,4 +0,0 @@
|
|||
{
|
||||
"baseUrl": "http://localhost:3001/test",
|
||||
"video": false
|
||||
}
|
|
@ -1,6 +1,10 @@
|
|||
describe('Choices - select multiple', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('/select-multiple.html');
|
||||
cy.visit('/select-multiple', {
|
||||
onBeforeLoad(win) {
|
||||
cy.stub(win.console, 'warn').as('consoleWarn');
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
describe('scenarios', () => {
|
||||
|
@ -30,6 +34,7 @@ describe('Choices - select multiple', () => {
|
|||
beforeEach(() => {
|
||||
cy.get('[data-test-hook=basic]')
|
||||
.find('.choices__input--cloned')
|
||||
.wait(200) // Otherwise these tests are flaky
|
||||
.type('{esc}');
|
||||
});
|
||||
|
||||
|
@ -62,25 +67,25 @@ describe('Choices - select multiple', () => {
|
|||
.find('.choices__list--dropdown .choices__list')
|
||||
.children()
|
||||
.first()
|
||||
.then($choice => {
|
||||
.then(($choice) => {
|
||||
selectedChoiceText = $choice.text().trim();
|
||||
})
|
||||
.click();
|
||||
});
|
||||
|
||||
it('allows me select choices from a dropdown', () => {
|
||||
it('allows selecting choices from dropdown', () => {
|
||||
cy.get('[data-test-hook=basic]')
|
||||
.find('.choices__list--multiple .choices__item')
|
||||
.last()
|
||||
.should($item => {
|
||||
.should(($item) => {
|
||||
expect($item).to.contain(selectedChoiceText);
|
||||
});
|
||||
});
|
||||
|
||||
it('updates the value of the original input', () => {
|
||||
cy.get('[data-test-hook=basic]')
|
||||
.find('.choices__input.is-hidden')
|
||||
.should($select => {
|
||||
.find('.choices__input[hidden]')
|
||||
.should(($select) => {
|
||||
expect($select.val()).to.contain(selectedChoiceText);
|
||||
});
|
||||
});
|
||||
|
@ -89,7 +94,7 @@ describe('Choices - select multiple', () => {
|
|||
cy.get('[data-test-hook=basic]')
|
||||
.find('.choices__list--dropdown .choices__list')
|
||||
.children()
|
||||
.each($choice => {
|
||||
.each(($choice) => {
|
||||
expect($choice.text().trim()).to.not.equal(selectedChoiceText);
|
||||
});
|
||||
});
|
||||
|
@ -114,7 +119,7 @@ describe('Choices - select multiple', () => {
|
|||
cy.get('[data-test-hook=basic]')
|
||||
.find('.choices__list--dropdown')
|
||||
.should('be.visible')
|
||||
.should($dropdown => {
|
||||
.should(($dropdown) => {
|
||||
const dropdownText = $dropdown.text().trim();
|
||||
expect(dropdownText).to.equal('No choices to choose from');
|
||||
});
|
||||
|
@ -130,7 +135,7 @@ describe('Choices - select multiple', () => {
|
|||
.find('.choices__list--dropdown .choices__list')
|
||||
.children()
|
||||
.last()
|
||||
.then($choice => {
|
||||
.then(($choice) => {
|
||||
removedChoiceText = $choice.text().trim();
|
||||
})
|
||||
.click();
|
||||
|
@ -150,8 +155,8 @@ describe('Choices - select multiple', () => {
|
|||
|
||||
it('updates the value of the original input', () => {
|
||||
cy.get('[data-test-hook=basic]')
|
||||
.find('.choices__input.is-hidden')
|
||||
.should($select => {
|
||||
.find('.choices__input[hidden]')
|
||||
.should(($select) => {
|
||||
const val = $select.val() || [];
|
||||
expect(val).to.not.contain(removedChoiceText);
|
||||
});
|
||||
|
@ -171,7 +176,7 @@ describe('Choices - select multiple', () => {
|
|||
.find('.choices__list--dropdown .choices__list')
|
||||
.children()
|
||||
.first()
|
||||
.should($choice => {
|
||||
.should(($choice) => {
|
||||
expect($choice.text().trim()).to.equal('Choice 2');
|
||||
});
|
||||
});
|
||||
|
@ -187,7 +192,7 @@ describe('Choices - select multiple', () => {
|
|||
.find('.choices__list--dropdown .choices__list')
|
||||
.children()
|
||||
.first()
|
||||
.should($choice => {
|
||||
.should(($choice) => {
|
||||
expect($choice.text().trim()).to.equal('Choice 3');
|
||||
});
|
||||
});
|
||||
|
@ -202,7 +207,7 @@ describe('Choices - select multiple', () => {
|
|||
cy.get('[data-test-hook=basic]')
|
||||
.find('.choices__list--dropdown')
|
||||
.should('be.visible')
|
||||
.should($dropdown => {
|
||||
.should(($dropdown) => {
|
||||
const dropdownText = $dropdown.text().trim();
|
||||
expect(dropdownText).to.equal('No results found');
|
||||
});
|
||||
|
@ -210,6 +215,36 @@ describe('Choices - select multiple', () => {
|
|||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('disabling', () => {
|
||||
describe('on disable', () => {
|
||||
it('disables the search input', () => {
|
||||
cy.get('[data-test-hook=basic]')
|
||||
.find('button.disable')
|
||||
.focus()
|
||||
.click();
|
||||
|
||||
cy.get('[data-test-hook=basic]')
|
||||
.find('.choices__input--cloned')
|
||||
.should('be.disabled');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('enabling', () => {
|
||||
describe('on enable', () => {
|
||||
it('enables the search input', () => {
|
||||
cy.get('[data-test-hook=basic]')
|
||||
.find('button.enable')
|
||||
.focus()
|
||||
.click();
|
||||
|
||||
cy.get('[data-test-hook=basic]')
|
||||
.find('.choices__input--cloned')
|
||||
.should('not.be.disabled');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('remove button', () => {
|
||||
|
@ -304,7 +339,7 @@ describe('Choices - select multiple', () => {
|
|||
});
|
||||
|
||||
describe('on click', () => {
|
||||
it('does not opens choice dropdown', () => {
|
||||
it('does not open choice dropdown', () => {
|
||||
cy.get('[data-test-hook=disabled-via-attr]')
|
||||
.find('.choices')
|
||||
.click()
|
||||
|
@ -340,7 +375,7 @@ describe('Choices - select multiple', () => {
|
|||
cy.get('[data-test-hook=selection-limit]')
|
||||
.find('.choices__list--dropdown')
|
||||
.should('be.visible')
|
||||
.should($dropdown => {
|
||||
.should(($dropdown) => {
|
||||
const dropdownText = $dropdown.text().trim();
|
||||
expect(dropdownText).to.equal(
|
||||
`Only ${selectionLimit} values can be added`,
|
||||
|
@ -367,7 +402,7 @@ describe('Choices - select multiple', () => {
|
|||
.find('.choices__list--dropdown .choices__list')
|
||||
.children()
|
||||
.last()
|
||||
.then($choice => {
|
||||
.then(($choice) => {
|
||||
selectedChoiceText = $choice.text().trim();
|
||||
})
|
||||
.click();
|
||||
|
@ -377,7 +412,7 @@ describe('Choices - select multiple', () => {
|
|||
cy.get('[data-test-hook=prepend-append]')
|
||||
.find('.choices__list--multiple .choices__item')
|
||||
.last()
|
||||
.should($choice => {
|
||||
.should(($choice) => {
|
||||
expect($choice.data('value')).to.equal(
|
||||
`before-${selectedChoiceText}-after`,
|
||||
);
|
||||
|
@ -388,7 +423,7 @@ describe('Choices - select multiple', () => {
|
|||
cy.get('[data-test-hook=prepend-append]')
|
||||
.find('.choices__list--multiple .choices__item')
|
||||
.last()
|
||||
.should($choice => {
|
||||
.should(($choice) => {
|
||||
expect($choice.text()).to.not.contain(
|
||||
`before-${selectedChoiceText}-after`,
|
||||
);
|
||||
|
@ -430,7 +465,7 @@ describe('Choices - select multiple', () => {
|
|||
.find('.choices__list--dropdown .choices__list')
|
||||
.children()
|
||||
.first()
|
||||
.should($choice => {
|
||||
.should(($choice) => {
|
||||
expect($choice.text().trim()).to.not.contain(searchTerm);
|
||||
});
|
||||
});
|
||||
|
@ -448,7 +483,7 @@ describe('Choices - select multiple', () => {
|
|||
.find('.choices__list--dropdown .choices__list')
|
||||
.children()
|
||||
.first()
|
||||
.should($choice => {
|
||||
.should(($choice) => {
|
||||
expect($choice.text().trim()).to.contain(searchTerm);
|
||||
});
|
||||
});
|
||||
|
@ -456,20 +491,42 @@ describe('Choices - select multiple', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('placeholder', () => {
|
||||
/*
|
||||
{
|
||||
placeholder: true,
|
||||
placeholderValue: 'I am a placeholder',
|
||||
}
|
||||
*/
|
||||
describe('placeholder via empty option value', () => {
|
||||
describe('when no value has been inputted', () => {
|
||||
it('displays a placeholder', () => {
|
||||
cy.get('[data-test-hook=placeholder]')
|
||||
cy.get('[data-test-hook=placeholder-via-option-value]')
|
||||
.find('.choices__input--cloned')
|
||||
.should('have.attr', 'placeholder', 'I am a placeholder');
|
||||
});
|
||||
});
|
||||
|
||||
describe('when a value has been inputted', () => {
|
||||
it('does not display a placeholder', () => {
|
||||
cy.get('[data-test-hook=placeholder-via-option-value]')
|
||||
.find('.choices__input--cloned')
|
||||
.type('test')
|
||||
.should('not.have.value', 'I am a placeholder');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('placeholder via option attribute', () => {
|
||||
describe('when no value has been inputted', () => {
|
||||
it('displays a placeholder', () => {
|
||||
cy.get('[data-test-hook=placeholder-via-option-attr]')
|
||||
.find('.choices__input--cloned')
|
||||
.should('have.attr', 'placeholder', 'I am a placeholder');
|
||||
});
|
||||
});
|
||||
|
||||
describe('when a value has been inputted', () => {
|
||||
it('does not display a placeholder', () => {
|
||||
cy.get('[data-test-hook=placeholder-via-option-attr]')
|
||||
.find('.choices__input--cloned')
|
||||
.type('test')
|
||||
.should('not.have.value', 'I am a placeholder');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('remote data', () => {
|
||||
|
@ -484,16 +541,13 @@ describe('Choices - select multiple', () => {
|
|||
.should('have.attr', 'placeholder', 'Loading...');
|
||||
});
|
||||
|
||||
describe('opening the dropdown', () => {
|
||||
it('displays "no choices to choose" prompt', () => {
|
||||
cy.get('[data-test-hook=remote-data]').click();
|
||||
describe('on click', () => {
|
||||
it('does not open choice dropdown', () => {
|
||||
cy.get('[data-test-hook=remote-data]')
|
||||
.find('.choices')
|
||||
.click()
|
||||
.find('.choices__list--dropdown')
|
||||
.should('be.visible')
|
||||
.should($dropdown => {
|
||||
const dropdownText = $dropdown.text().trim();
|
||||
expect(dropdownText).to.equal('No choices to choose from');
|
||||
});
|
||||
.should('not.have.class', 'is-active');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -501,7 +555,7 @@ describe('Choices - select multiple', () => {
|
|||
describe('when data has loaded', () => {
|
||||
describe('opening the dropdown', () => {
|
||||
it('displays the loaded data', () => {
|
||||
cy.wait(2000);
|
||||
cy.wait(1000);
|
||||
cy.get('[data-test-hook=remote-data]')
|
||||
.find('.choices__list--dropdown .choices__list')
|
||||
.children()
|
||||
|
@ -521,7 +575,7 @@ describe('Choices - select multiple', () => {
|
|||
beforeEach(() => {
|
||||
cy.get('[data-test-hook=scrolling-dropdown]')
|
||||
.find('.choices__list--dropdown .choices__list .choices__item')
|
||||
.then($choices => {
|
||||
.then(($choices) => {
|
||||
choicesCount = $choices.length;
|
||||
});
|
||||
|
||||
|
@ -533,17 +587,20 @@ describe('Choices - select multiple', () => {
|
|||
it('highlights first choice on dropdown open', () => {
|
||||
cy.get('[data-test-hook=scrolling-dropdown]')
|
||||
.find('.choices__list--dropdown .choices__list .is-highlighted')
|
||||
.should($choice => {
|
||||
.should(($choice) => {
|
||||
expect($choice.text().trim()).to.equal('Choice 1');
|
||||
});
|
||||
});
|
||||
|
||||
it('scrolls to next choice on down arrow', () => {
|
||||
for (let index = 0; index < choicesCount; index++) {
|
||||
for (let index = 1; index <= choicesCount; index++) {
|
||||
cy.wait(100);
|
||||
|
||||
cy.get('[data-test-hook=scrolling-dropdown]')
|
||||
.find('.choices__list--dropdown .choices__list .is-highlighted')
|
||||
.should($choice => {
|
||||
expect($choice.text().trim()).to.equal(`Choice ${index + 1}`);
|
||||
.invoke('text')
|
||||
.then((text) => {
|
||||
expect(text.trim()).to.equal(`Choice ${index}`);
|
||||
});
|
||||
|
||||
cy.get('[data-test-hook=scrolling-dropdown]')
|
||||
|
@ -566,8 +623,9 @@ describe('Choices - select multiple', () => {
|
|||
|
||||
cy.get('[data-test-hook=scrolling-dropdown]')
|
||||
.find('.choices__list--dropdown .choices__list .is-highlighted')
|
||||
.should($choice => {
|
||||
expect($choice.text().trim()).to.equal(`Choice ${index}`);
|
||||
.invoke('text')
|
||||
.then((text) => {
|
||||
expect(text.trim()).to.equal(`Choice ${index}`);
|
||||
});
|
||||
|
||||
cy.get('[data-test-hook=scrolling-dropdown]')
|
||||
|
@ -585,7 +643,7 @@ describe('Choices - select multiple', () => {
|
|||
cy.get('[data-test-hook=groups]')
|
||||
.find('.choices__list--dropdown .choices__list .choices__group')
|
||||
.first()
|
||||
.then($group => {
|
||||
.then(($group) => {
|
||||
groupValue = $group.text().trim();
|
||||
});
|
||||
});
|
||||
|
@ -606,7 +664,7 @@ describe('Choices - select multiple', () => {
|
|||
cy.get('[data-test-hook=groups]')
|
||||
.find('.choices__list--dropdown .choices__list .choices__group')
|
||||
.first()
|
||||
.should($group => {
|
||||
.should(($group) => {
|
||||
expect($group.text().trim()).to.not.equal(groupValue);
|
||||
});
|
||||
});
|
||||
|
@ -637,11 +695,317 @@ describe('Choices - select multiple', () => {
|
|||
cy.get('[data-test-hook=groups]')
|
||||
.find('.choices__list--dropdown .choices__list .choices__group')
|
||||
.first()
|
||||
.should($group => {
|
||||
.should(($group) => {
|
||||
expect($group.text().trim()).to.equal(groupValue);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('custom properties', () => {
|
||||
beforeEach(() => {
|
||||
cy.get('[data-test-hook=custom-properties]')
|
||||
.find('.choices__input--cloned')
|
||||
.focus();
|
||||
});
|
||||
|
||||
describe('on input', () => {
|
||||
it('filters choices based on custom property', () => {
|
||||
const data = [
|
||||
{
|
||||
country: 'Germany',
|
||||
city: 'Berlin',
|
||||
},
|
||||
{
|
||||
country: 'United Kingdom',
|
||||
city: 'London',
|
||||
},
|
||||
{
|
||||
country: 'Portugal',
|
||||
city: 'Lisbon',
|
||||
},
|
||||
];
|
||||
|
||||
data.forEach(({ country, city }) => {
|
||||
cy.get('[data-test-hook=custom-properties]')
|
||||
.find('.choices__input--cloned')
|
||||
.type(country);
|
||||
|
||||
cy.get('[data-test-hook=custom-properties]')
|
||||
.find('.choices__list--dropdown .choices__list')
|
||||
.children()
|
||||
.first()
|
||||
.should(($choice) => {
|
||||
expect($choice.text().trim()).to.equal(city);
|
||||
});
|
||||
|
||||
cy.get('[data-test-hook=custom-properties]')
|
||||
.find('.choices__input--cloned')
|
||||
.type('{selectall}{del}');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('custom properties via HTML', () => {
|
||||
beforeEach(() => {
|
||||
cy.get('[data-test-hook=custom-properties-html]')
|
||||
.find('.choices')
|
||||
.click();
|
||||
});
|
||||
|
||||
describe('on input', () => {
|
||||
it('filters choices based on a string custom property', () => {
|
||||
const data = [
|
||||
{
|
||||
searchText: 'fantastic',
|
||||
label: 'Label Three',
|
||||
},
|
||||
];
|
||||
|
||||
data.forEach(({ searchText, label }) => {
|
||||
cy.get('[data-test-hook=custom-properties-html]')
|
||||
.find('.choices__input--cloned')
|
||||
.type(searchText);
|
||||
|
||||
cy.get('[data-test-hook=custom-properties-html]')
|
||||
.find('.choices__list--dropdown .choices__list')
|
||||
.children()
|
||||
.first()
|
||||
.should(($choice) => {
|
||||
expect($choice.text().trim()).to.equal(label);
|
||||
});
|
||||
|
||||
cy.get('[data-test-hook=custom-properties-html]')
|
||||
.find('.choices__input--cloned')
|
||||
.type('{selectall}{del}');
|
||||
});
|
||||
});
|
||||
|
||||
it('filters choices based on a JSON custom property', () => {
|
||||
const data = [
|
||||
{
|
||||
searchText: 'foo',
|
||||
label: 'Label Four',
|
||||
},
|
||||
];
|
||||
|
||||
data.forEach(({ searchText, label }) => {
|
||||
cy.get('[data-test-hook=custom-properties-html]')
|
||||
.find('.choices__input--cloned')
|
||||
.type(searchText);
|
||||
|
||||
cy.get('[data-test-hook=custom-properties-html]')
|
||||
.find('.choices__list--dropdown .choices__list')
|
||||
.children()
|
||||
.first()
|
||||
.should(($choice) => {
|
||||
expect($choice.text().trim()).to.equal(label);
|
||||
});
|
||||
|
||||
cy.get('[data-test-hook=custom-properties-html]')
|
||||
.find('.choices__input--cloned')
|
||||
.type('{selectall}{del}');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('non-string values', () => {
|
||||
beforeEach(() => {
|
||||
cy.get('[data-test-hook=non-string-values]').find('.choices').click();
|
||||
});
|
||||
|
||||
it('displays expected amount of choices in dropdown', () => {
|
||||
cy.get('[data-test-hook=non-string-values]')
|
||||
.find('.choices__list--dropdown .choices__list')
|
||||
.children()
|
||||
.should('have.length', 4);
|
||||
});
|
||||
|
||||
it('allows selecting choices from dropdown', () => {
|
||||
let $selectedChoice;
|
||||
cy.get('[data-test-hook=non-string-values]')
|
||||
.find('.choices__list--dropdown .choices__list')
|
||||
.children()
|
||||
.first()
|
||||
.then(($choice) => {
|
||||
$selectedChoice = $choice;
|
||||
})
|
||||
.click();
|
||||
|
||||
cy.get('[data-test-hook=non-string-values]')
|
||||
.find('.choices__list--single .choices__item')
|
||||
.last()
|
||||
.should(($item) => {
|
||||
expect($item.text().trim()).to.equal($selectedChoice.text().trim());
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('within form', () => {
|
||||
describe('selecting choice', () => {
|
||||
describe('on enter key', () => {
|
||||
it('selects choice', () => {
|
||||
cy.get('[data-test-hook=within-form] form').then(($form) => {
|
||||
$form.submit(() => {
|
||||
// this will fail the test if the form submits
|
||||
throw new Error('Form submitted');
|
||||
});
|
||||
});
|
||||
|
||||
cy.get('[data-test-hook=within-form]')
|
||||
.find('.choices__input--cloned')
|
||||
.click()
|
||||
.type('{enter}');
|
||||
|
||||
cy.get('[data-test-hook=within-form]')
|
||||
.find('.choices__list--multiple .choices__item')
|
||||
.last()
|
||||
.should(($item) => {
|
||||
expect($item).to.contain('Choice 1');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('dynamically setting choice by value', () => {
|
||||
const dynamicallySelectedChoiceValue = 'Choice 2';
|
||||
|
||||
it('selects choice', () => {
|
||||
cy.get('[data-test-hook=set-choice-by-value]')
|
||||
.find('.choices__list--multiple .choices__item')
|
||||
.last()
|
||||
.should(($choice) => {
|
||||
expect($choice.text().trim()).to.equal(
|
||||
dynamicallySelectedChoiceValue,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it('removes choice from dropdown list', () => {
|
||||
cy.get('[data-test-hook=set-choice-by-value]')
|
||||
.find('.choices__list--dropdown .choices__list')
|
||||
.children()
|
||||
.each(($choice) => {
|
||||
expect($choice.text().trim()).to.not.equal(
|
||||
dynamicallySelectedChoiceValue,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it('updates the value of the original input', () => {
|
||||
cy.get('[data-test-hook=set-choice-by-value]')
|
||||
.find('.choices__input[hidden]')
|
||||
.should(($select) => {
|
||||
const val = $select.val() || [];
|
||||
expect(val).to.contain(dynamicallySelectedChoiceValue);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('searching by label only', () => {
|
||||
it('gets zero results when searching by value', () => {
|
||||
cy.get('[data-test-hook=search-by-label]')
|
||||
.find('.choices__input--cloned')
|
||||
.type('value1');
|
||||
|
||||
cy.get('[data-test-hook=search-by-label]')
|
||||
.find('.choices__list--dropdown .choices__list')
|
||||
.children()
|
||||
.first()
|
||||
.should(($choice) => {
|
||||
expect($choice.text().trim()).to.equal('No results found');
|
||||
});
|
||||
});
|
||||
|
||||
it('gets a result when searching by label', () => {
|
||||
cy.get('[data-test-hook=search-by-label]')
|
||||
.find('.choices__input--cloned')
|
||||
.type('label1');
|
||||
|
||||
cy.get('[data-test-hook=search-by-label]')
|
||||
.find('.choices__list--dropdown .choices__list')
|
||||
.children()
|
||||
.first()
|
||||
.should(($choice) => {
|
||||
expect($choice.text().trim()).to.equal('label1');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('allow html', () => {
|
||||
describe('is undefined', () => {
|
||||
it('logs a deprecation warning', () => {
|
||||
cy.get('@consoleWarn').should(
|
||||
'be.calledOnceWithExactly',
|
||||
'Deprecation warning: allowHTML will default to false in a future release. To render HTML in Choices, you will need to set it to true. Setting allowHTML will suppress this message.',
|
||||
);
|
||||
});
|
||||
|
||||
it('does not show as text when selected', () => {
|
||||
cy.get('[data-test-hook=allowhtml-undefined]')
|
||||
.find('.choices__list--multiple .choices__item')
|
||||
.first()
|
||||
.should(($choice) => {
|
||||
expect($choice.text().trim()).to.equal('Choice 1');
|
||||
});
|
||||
});
|
||||
|
||||
it('does not show html as text in dropdown', () => {
|
||||
cy.get('[data-test-hook=allowhtml-undefined]')
|
||||
.find('.choices__list--dropdown .choices__list')
|
||||
.children()
|
||||
.first()
|
||||
.should(($choice) => {
|
||||
expect($choice.text().trim()).to.equal('Choice 2');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('set to true', () => {
|
||||
it('does not show as text when selected', () => {
|
||||
cy.get('[data-test-hook=allowhtml-true]')
|
||||
.find('.choices__list--multiple .choices__item')
|
||||
|
||||
.first()
|
||||
.should(($choice) => {
|
||||
expect($choice.text().trim()).to.equal('Choice 1');
|
||||
});
|
||||
});
|
||||
|
||||
it('does not show html as text in dropdown', () => {
|
||||
cy.get('[data-test-hook=allowhtml-true]')
|
||||
.find('.choices__list--dropdown .choices__list')
|
||||
.children()
|
||||
.first()
|
||||
.should(($choice) => {
|
||||
expect($choice.text().trim()).to.equal('Choice 2');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('set to false', () => {
|
||||
it('shows html as text when selected', () => {
|
||||
cy.get('[data-test-hook=allowhtml-false]')
|
||||
.find('.choices__list--multiple .choices__item')
|
||||
.first()
|
||||
.should(($choice) => {
|
||||
expect($choice.text().trim()).to.equal('<b>Choice 1</b>');
|
||||
});
|
||||
});
|
||||
|
||||
it('shows html as text', () => {
|
||||
cy.get('[data-test-hook=allowhtml-false]')
|
||||
.find('.choices__list--dropdown .choices__list')
|
||||
.children()
|
||||
.first()
|
||||
.should(($choice) => {
|
||||
expect($choice.text().trim()).to.equal('<b>Choice 2</b>');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
1149
cypress/e2e/select-one.spec.ts
Normal file
|
@ -1,6 +1,10 @@
|
|||
describe('Choices - text element', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('/text.html');
|
||||
cy.visit('/text', {
|
||||
onBeforeLoad(win) {
|
||||
cy.stub(win.console, 'warn').as('consoleWarn');
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
describe('scenarios', () => {
|
||||
|
@ -17,7 +21,7 @@ describe('Choices - text element', () => {
|
|||
cy.get('[data-test-hook=basic]')
|
||||
.find('.choices__list--multiple .choices__item')
|
||||
.last()
|
||||
.should($el => {
|
||||
.should(($el) => {
|
||||
expect($el).to.contain(textInput);
|
||||
});
|
||||
});
|
||||
|
@ -29,7 +33,7 @@ describe('Choices - text element', () => {
|
|||
.type('{enter}');
|
||||
|
||||
cy.get('[data-test-hook=basic]')
|
||||
.find('.choices__input.is-hidden')
|
||||
.find('.choices__input[hidden]')
|
||||
.should('have.value', textInput);
|
||||
});
|
||||
|
||||
|
@ -42,7 +46,7 @@ describe('Choices - text element', () => {
|
|||
cy.get('[data-test-hook=basic]')
|
||||
.find('.choices__list--dropdown')
|
||||
.should('be.visible')
|
||||
.should($dropdown => {
|
||||
.should(($dropdown) => {
|
||||
const dropdownText = $dropdown.text().trim();
|
||||
expect(dropdownText).to.equal(
|
||||
`Press Enter to add "${textInput}"`,
|
||||
|
@ -74,7 +78,7 @@ describe('Choices - text element', () => {
|
|||
cy.get('[data-test-hook=edit-items]')
|
||||
.find('.choices__list--multiple .choices__item')
|
||||
.last()
|
||||
.should($choice => {
|
||||
.should(($choice) => {
|
||||
expect($choice.data('value')).to.equal(`${textInput}-edited`);
|
||||
});
|
||||
});
|
||||
|
@ -90,7 +94,7 @@ describe('Choices - text element', () => {
|
|||
it('highlights all items', () => {
|
||||
cy.get('[data-test-hook=edit-items]')
|
||||
.find('.choices__list--multiple .choices__item')
|
||||
.each($choice => {
|
||||
.each(($choice) => {
|
||||
expect($choice.hasClass('is-highlighted')).to.equal(true);
|
||||
});
|
||||
});
|
||||
|
@ -124,7 +128,7 @@ describe('Choices - text element', () => {
|
|||
cy.get('[data-test-hook=remove-button]')
|
||||
.find('.choices__list--multiple')
|
||||
.children()
|
||||
.should($items => {
|
||||
.should(($items) => {
|
||||
expect($items.length).to.equal(1);
|
||||
});
|
||||
|
||||
|
@ -137,7 +141,7 @@ describe('Choices - text element', () => {
|
|||
|
||||
cy.get('[data-test-hook=remove-button]')
|
||||
.find('.choices__list--multiple .choices__item')
|
||||
.should($items => {
|
||||
.should(($items) => {
|
||||
expect($items.length).to.equal(0);
|
||||
});
|
||||
});
|
||||
|
@ -151,8 +155,8 @@ describe('Choices - text element', () => {
|
|||
.click();
|
||||
|
||||
cy.get('[data-test-hook=remove-button]')
|
||||
.find('.choices__input.is-hidden')
|
||||
.then($input => {
|
||||
.find('.choices__input[hidden]')
|
||||
.then(($input) => {
|
||||
expect($input.val()).to.not.contain(textInput);
|
||||
});
|
||||
});
|
||||
|
@ -175,7 +179,7 @@ describe('Choices - text element', () => {
|
|||
.find('.choices__list--multiple')
|
||||
.first()
|
||||
.children()
|
||||
.should($items => {
|
||||
.should(($items) => {
|
||||
expect($items.length).to.equal(1);
|
||||
});
|
||||
});
|
||||
|
@ -185,7 +189,7 @@ describe('Choices - text element', () => {
|
|||
cy.get('[data-test-hook=unique-values]')
|
||||
.find('.choices__list--dropdown')
|
||||
.should('be.visible')
|
||||
.should($dropdown => {
|
||||
.should(($dropdown) => {
|
||||
const dropdownText = $dropdown.text().trim();
|
||||
expect(dropdownText).to.equal(
|
||||
'Only unique values can be added',
|
||||
|
@ -197,8 +201,9 @@ describe('Choices - text element', () => {
|
|||
});
|
||||
|
||||
describe('input limit', () => {
|
||||
const inputLimit = 5;
|
||||
beforeEach(() => {
|
||||
for (let index = 0; index < 6; index++) {
|
||||
for (let index = 0; index < inputLimit + 1; index++) {
|
||||
cy.get('[data-test-hook=input-limit]')
|
||||
.find('.choices__input--cloned')
|
||||
.type(`${textInput} + ${index}`)
|
||||
|
@ -211,33 +216,40 @@ describe('Choices - text element', () => {
|
|||
.find('.choices__list--multiple')
|
||||
.first()
|
||||
.children()
|
||||
.should($items => {
|
||||
expect($items.length).to.equal(5);
|
||||
.should(($items) => {
|
||||
expect($items.length).to.equal(inputLimit);
|
||||
});
|
||||
});
|
||||
|
||||
it('hides dropdown prompt once limit has been reached', () => {
|
||||
cy.wait(500); // allow for animation frame
|
||||
describe('reaching input limit', () => {
|
||||
it('displays dropdown prompt', () => {
|
||||
cy.get('[data-test-hook=input-limit]')
|
||||
.find('.choices__list--dropdown')
|
||||
.should('not.be.visible');
|
||||
.should('be.visible')
|
||||
.should(($dropdown) => {
|
||||
const dropdownText = $dropdown.text().trim();
|
||||
expect(dropdownText).to.equal(
|
||||
`Only ${inputLimit} values can be added`,
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('regex filter', () => {
|
||||
describe('a valid that satisfies regex', () => {
|
||||
describe('add item filter', () => {
|
||||
describe('inputting a value that satisfies the filter', () => {
|
||||
const input = 'joe@bloggs.com';
|
||||
|
||||
it('allows me to add choice', () => {
|
||||
cy.get('[data-test-hook=regex-filter]')
|
||||
cy.get('[data-test-hook=add-item-filter]')
|
||||
.find('.choices__input--cloned')
|
||||
.type(input)
|
||||
.type('{enter}');
|
||||
|
||||
cy.get('[data-test-hook=regex-filter]')
|
||||
cy.get('[data-test-hook=add-item-filter]')
|
||||
.find('.choices__list--multiple .choices__item')
|
||||
.last()
|
||||
.should($choice => {
|
||||
.should(($choice) => {
|
||||
expect($choice.text().trim()).to.equal(input);
|
||||
});
|
||||
});
|
||||
|
@ -245,14 +257,20 @@ describe('Choices - text element', () => {
|
|||
|
||||
describe('inputting a value that does not satisfy the regex', () => {
|
||||
it('displays dropdown prompt', () => {
|
||||
cy.get('[data-test-hook=regex-filter]')
|
||||
cy.get('[data-test-hook=add-item-filter]')
|
||||
.find('.choices__input--cloned')
|
||||
.type(`this is not an email address`)
|
||||
.type('{enter}');
|
||||
|
||||
cy.get('[data-test-hook=regex-filter]')
|
||||
cy.get('[data-test-hook=add-item-filter]')
|
||||
.find('.choices__list--dropdown')
|
||||
.should('not.be.visible');
|
||||
.should('be.visible')
|
||||
.should(($dropdown) => {
|
||||
const dropdownText = $dropdown.text().trim();
|
||||
expect(dropdownText).to.equal(
|
||||
'Only values matching specific conditions can be added',
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -269,7 +287,7 @@ describe('Choices - text element', () => {
|
|||
cy.get('[data-test-hook=prepend-append]')
|
||||
.find('.choices__list--multiple .choices__item')
|
||||
.last()
|
||||
.should($choice => {
|
||||
.should(($choice) => {
|
||||
expect($choice.data('value')).to.equal(`before-${textInput}-after`);
|
||||
});
|
||||
});
|
||||
|
@ -278,7 +296,7 @@ describe('Choices - text element', () => {
|
|||
cy.get('[data-test-hook=prepend-append]')
|
||||
.find('.choices__list--multiple .choices__item')
|
||||
.last()
|
||||
.should($choice => {
|
||||
.should(($choice) => {
|
||||
expect($choice.text()).to.not.contain(`before-${textInput}-after`);
|
||||
expect($choice.text()).to.contain(textInput);
|
||||
});
|
||||
|
@ -305,21 +323,21 @@ describe('Choices - text element', () => {
|
|||
it('pre-populates choices', () => {
|
||||
cy.get('[data-test-hook=prepopulated]')
|
||||
.find('.choices__list--multiple .choices__item')
|
||||
.should($choices => {
|
||||
.should(($choices) => {
|
||||
expect($choices.length).to.equal(2);
|
||||
});
|
||||
|
||||
cy.get('[data-test-hook=prepopulated]')
|
||||
.find('.choices__list--multiple .choices__item')
|
||||
.first()
|
||||
.should($choice => {
|
||||
.should(($choice) => {
|
||||
expect($choice.text().trim()).to.equal('Josh Johnson');
|
||||
});
|
||||
|
||||
cy.get('[data-test-hook=prepopulated]')
|
||||
.find('.choices__list--multiple .choices__item')
|
||||
.last()
|
||||
.should($choice => {
|
||||
.should(($choice) => {
|
||||
expect($choice.text().trim()).to.equal('Joe Bloggs');
|
||||
});
|
||||
});
|
||||
|
@ -340,5 +358,74 @@ describe('Choices - text element', () => {
|
|||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('allow html', () => {
|
||||
describe('is undefined', () => {
|
||||
it('logs a deprecation warning', () => {
|
||||
cy.get('@consoleWarn').should(
|
||||
'be.calledOnceWithExactly',
|
||||
'Deprecation warning: allowHTML will default to false in a future release. To render HTML in Choices, you will need to set it to true. Setting allowHTML will suppress this message.',
|
||||
);
|
||||
});
|
||||
|
||||
it('does not show html as text', () => {
|
||||
cy.get('[data-test-hook=allowhtml-undefined]')
|
||||
.find('.choices__list--multiple .choices__item')
|
||||
.first()
|
||||
.should(($choice) => {
|
||||
expect($choice.text().trim()).to.equal('Mason Rogers');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('set to true', () => {
|
||||
it('does not show html as text', () => {
|
||||
cy.get('[data-test-hook=allowhtml-true]')
|
||||
.find('.choices__list--multiple .choices__item')
|
||||
.first()
|
||||
.should(($choice) => {
|
||||
expect($choice.text().trim()).to.equal('Mason Rogers');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('set to false', () => {
|
||||
it('shows html as text', () => {
|
||||
cy.get('[data-test-hook=allowhtml-false]')
|
||||
.find('.choices__list--multiple .choices__item')
|
||||
.first()
|
||||
.should(($choice) => {
|
||||
expect($choice.text().trim()).to.equal('<b>Mason Rogers</b>');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('within form', () => {
|
||||
describe('inputting item', () => {
|
||||
describe('on enter key', () => {
|
||||
it('does not submit form', () => {
|
||||
cy.get('[data-test-hook=within-form] form').then(($form) => {
|
||||
$form.submit(() => {
|
||||
// this will fail the test if the form submits
|
||||
throw new Error('Form submitted');
|
||||
});
|
||||
});
|
||||
|
||||
cy.get('[data-test-hook=within-form]')
|
||||
.find('.choices__input--cloned')
|
||||
.type(textInput)
|
||||
.type('{enter}');
|
||||
|
||||
cy.get('[data-test-hook=within-form]')
|
||||
.find('.choices__list--multiple .choices__item')
|
||||
.last()
|
||||
.should(($el) => {
|
||||
expect($el).to.contain(textInput);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,659 +0,0 @@
|
|||
describe('Choices - select one', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('/select-one.html');
|
||||
});
|
||||
|
||||
describe('scenarios', () => {
|
||||
describe('basic', () => {
|
||||
beforeEach(() => {
|
||||
// open dropdown
|
||||
cy.get('[data-test-hook=basic]')
|
||||
.find('.choices')
|
||||
.click();
|
||||
});
|
||||
|
||||
describe('focusing on text input', () => {
|
||||
it('displays a dropdown of choices', () => {
|
||||
cy.get('[data-test-hook=basic]')
|
||||
.find('.choices__list--dropdown')
|
||||
.should('be.visible');
|
||||
|
||||
cy.get('[data-test-hook=basic]')
|
||||
.find('.choices__list--dropdown .choices__list')
|
||||
.children()
|
||||
.should('have.length', 4)
|
||||
.each(($choice, index) => {
|
||||
expect($choice.text().trim()).to.equal(`Choice ${index + 1}`);
|
||||
});
|
||||
});
|
||||
|
||||
describe('pressing escape', () => {
|
||||
beforeEach(() => {
|
||||
cy.get('[data-test-hook=basic]')
|
||||
.find('.choices__input--cloned')
|
||||
.type('{esc}');
|
||||
});
|
||||
|
||||
it('closes the dropdown', () => {
|
||||
cy.get('[data-test-hook=basic]')
|
||||
.find('.choices__list--dropdown')
|
||||
.should('not.be.visible');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('selecting choices', () => {
|
||||
const selectedChoiceText = 'Choice 1';
|
||||
|
||||
it('allows me select choices from a dropdown', () => {
|
||||
cy.get('[data-test-hook=basic]')
|
||||
.find('.choices__list--dropdown .choices__list')
|
||||
.children()
|
||||
.first()
|
||||
.click();
|
||||
|
||||
cy.get('[data-test-hook=basic]')
|
||||
.find('.choices__list--single .choices__item')
|
||||
.last()
|
||||
.should($item => {
|
||||
expect($item).to.contain(selectedChoiceText);
|
||||
});
|
||||
});
|
||||
|
||||
it('does not remove selected choice from dropdown list', () => {
|
||||
cy.get('[data-test-hook=basic]')
|
||||
.find('.choices__list--dropdown .choices__list')
|
||||
.children()
|
||||
.first()
|
||||
.click();
|
||||
|
||||
cy.get('[data-test-hook=basic]')
|
||||
.find('.choices__list--dropdown .choices__list')
|
||||
.children()
|
||||
.first()
|
||||
.should($item => {
|
||||
expect($item).to.contain(selectedChoiceText);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('searching choices', () => {
|
||||
describe('on input', () => {
|
||||
describe('searching by label', () => {
|
||||
it('displays choices filtered by inputted value', () => {
|
||||
cy.get('[data-test-hook=basic]')
|
||||
.find('.choices__input--cloned')
|
||||
.type('item 2');
|
||||
|
||||
cy.get('[data-test-hook=basic]')
|
||||
.find('.choices__list--dropdown .choices__list')
|
||||
.children()
|
||||
.first()
|
||||
.should($choice => {
|
||||
expect($choice.text().trim()).to.equal('Choice 2');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('searching by value', () => {
|
||||
it('displays choices filtered by inputted value', () => {
|
||||
cy.get('[data-test-hook=basic]')
|
||||
.find('.choices__input--cloned')
|
||||
.type('find me');
|
||||
|
||||
cy.get('[data-test-hook=basic]')
|
||||
.find('.choices__list--dropdown .choices__list')
|
||||
.children()
|
||||
.first()
|
||||
.should($choice => {
|
||||
expect($choice.text().trim()).to.equal('Choice 3');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('no results found', () => {
|
||||
it('displays "no results found" prompt', () => {
|
||||
cy.get('[data-test-hook=basic]')
|
||||
.find('.choices__input--cloned')
|
||||
.type('faergge');
|
||||
|
||||
cy.get('[data-test-hook=basic]')
|
||||
.find('.choices__list--dropdown')
|
||||
.should('be.visible')
|
||||
.should($dropdown => {
|
||||
const dropdownText = $dropdown.text().trim();
|
||||
expect(dropdownText).to.equal('No results found');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('remove button', () => {
|
||||
/*
|
||||
{
|
||||
removeItemButton: true,
|
||||
}
|
||||
*/
|
||||
beforeEach(() => {
|
||||
cy.get('[data-test-hook=remove-button]')
|
||||
.find('.choices__input--cloned')
|
||||
.focus();
|
||||
|
||||
cy.get('[data-test-hook=remove-button]')
|
||||
.find('.choices__list--dropdown .choices__list')
|
||||
.children()
|
||||
.last()
|
||||
.click();
|
||||
});
|
||||
|
||||
describe('remove button', () => {
|
||||
describe('on click', () => {
|
||||
let removedChoiceText;
|
||||
|
||||
beforeEach(() => {
|
||||
cy.get('[data-test-hook=remove-button]')
|
||||
.find('.choices__list--single .choices__item')
|
||||
.last()
|
||||
.then($choice => {
|
||||
removedChoiceText = $choice.text().trim();
|
||||
})
|
||||
.click();
|
||||
|
||||
cy.get('[data-test-hook=remove-button]')
|
||||
.find('.choices__list--single .choices__item')
|
||||
.last()
|
||||
.find('.choices__button')
|
||||
.focus()
|
||||
.click();
|
||||
});
|
||||
|
||||
it('removes selected choice', () => {
|
||||
cy.get('[data-test-hook=remove-button]')
|
||||
.find('.choices__list--single')
|
||||
.children()
|
||||
.should('have.length', 0);
|
||||
});
|
||||
|
||||
it('updates the value of the original input', () => {
|
||||
cy.get('[data-test-hook=remove-button]')
|
||||
.find('.choices__input.is-hidden')
|
||||
.should($select => {
|
||||
const val = $select.val() || [];
|
||||
|
||||
expect(val).to.not.contain(removedChoiceText);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('disabled choice', () => {
|
||||
describe('selecting a disabled choice', () => {
|
||||
let selectedChoiceText;
|
||||
|
||||
beforeEach(() => {
|
||||
cy.get('[data-test-hook=disabled-choice]').click();
|
||||
|
||||
cy.get('[data-test-hook=disabled-choice]')
|
||||
.find('.choices__list--dropdown .choices__item--disabled')
|
||||
.then($choice => {
|
||||
selectedChoiceText = $choice.text().trim();
|
||||
})
|
||||
.click();
|
||||
});
|
||||
|
||||
it('does not change selected choice', () => {
|
||||
cy.get('[data-test-hook=prepend-append]')
|
||||
.find('.choices__list--single .choices__item')
|
||||
.last()
|
||||
.should($choice => {
|
||||
expect($choice.text()).to.not.contain(selectedChoiceText);
|
||||
});
|
||||
});
|
||||
|
||||
it('closes the dropdown list', () => {
|
||||
cy.get('[data-test-hook=disabled-choice]')
|
||||
.find('.choices__list--dropdown')
|
||||
.should('not.be.visible');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('adding items disabled', () => {
|
||||
/*
|
||||
{
|
||||
addItems: false,
|
||||
}
|
||||
*/
|
||||
it('disables the search input', () => {
|
||||
cy.get('[data-test-hook=add-items-disabled]')
|
||||
.find('.choices__input--cloned')
|
||||
.should('be.disabled');
|
||||
});
|
||||
|
||||
describe('on click', () => {
|
||||
it('does not open choice dropdown', () => {
|
||||
cy.get('[data-test-hook=add-items-disabled]')
|
||||
.find('.choices')
|
||||
.click();
|
||||
|
||||
cy.get('[data-test-hook=add-items-disabled]')
|
||||
.find('.choices__list--dropdown')
|
||||
.should('not.have.class', 'is-active');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('disabled via attribute', () => {
|
||||
it('disables the search input', () => {
|
||||
cy.get('[data-test-hook=disabled-via-attr]')
|
||||
.find('.choices__input--cloned')
|
||||
.should('be.disabled');
|
||||
});
|
||||
|
||||
describe('on click', () => {
|
||||
it('does not open choice dropdown', () => {
|
||||
cy.get('[data-test-hook=disabled-via-attr]')
|
||||
.find('.choices')
|
||||
.click();
|
||||
|
||||
cy.get('[data-test-hook=disabled-via-attr]')
|
||||
.find('.choices__list--dropdown')
|
||||
.should('not.have.class', 'is-active');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('prepend/append', () => {
|
||||
/*
|
||||
{
|
||||
prependValue: 'before-',
|
||||
appendValue: '-after',
|
||||
};
|
||||
*/
|
||||
|
||||
let selectedChoiceText;
|
||||
|
||||
beforeEach(() => {
|
||||
cy.get('[data-test-hook=prepend-append]')
|
||||
.find('.choices__input--cloned')
|
||||
.focus();
|
||||
|
||||
cy.get('[data-test-hook=prepend-append]')
|
||||
.find('.choices__list--dropdown .choices__list')
|
||||
.children()
|
||||
.last()
|
||||
.then($choice => {
|
||||
selectedChoiceText = $choice.text().trim();
|
||||
})
|
||||
.click();
|
||||
});
|
||||
|
||||
it('prepends and appends value to inputted value', () => {
|
||||
cy.get('[data-test-hook=prepend-append]')
|
||||
.find('.choices__list--single .choices__item')
|
||||
.last()
|
||||
.should($choice => {
|
||||
expect($choice.data('value')).to.equal(
|
||||
`before-${selectedChoiceText}-after`,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it('displays just the inputted value to the user', () => {
|
||||
cy.get('[data-test-hook=prepend-append]')
|
||||
.find('.choices__list--single .choices__item')
|
||||
.last()
|
||||
.should($choice => {
|
||||
expect($choice.text()).to.not.contain(
|
||||
`before-${selectedChoiceText}-after`,
|
||||
);
|
||||
expect($choice.text()).to.contain(selectedChoiceText);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('render choice limit', () => {
|
||||
/*
|
||||
{
|
||||
renderChoiceLimit: 1
|
||||
}
|
||||
*/
|
||||
|
||||
it('only displays given number of choices in the dropdown', () => {
|
||||
cy.get('[data-test-hook=render-choice-limit]')
|
||||
.find('.choices__list--dropdown .choices__list')
|
||||
.children()
|
||||
.should('have.length', 1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('search disabled', () => {
|
||||
/*
|
||||
{
|
||||
searchEnabled: false
|
||||
}
|
||||
*/
|
||||
const selectedChoiceText = 'Choice 3';
|
||||
|
||||
beforeEach(() => {
|
||||
cy.get('[data-test-hook=search-disabled]')
|
||||
.find('.choices')
|
||||
.click();
|
||||
});
|
||||
|
||||
it('does not display a search input', () => {
|
||||
cy.get('[data-test-hook=search-disabled]')
|
||||
.find('.choices__input--cloned')
|
||||
.should('not.exist');
|
||||
});
|
||||
|
||||
it('allows me select choices from a dropdown', () => {
|
||||
cy.get('[data-test-hook=search-disabled]')
|
||||
.find('.choices__list--dropdown .choices__list')
|
||||
.children()
|
||||
.last()
|
||||
.click();
|
||||
|
||||
cy.get('[data-test-hook=search-disabled]')
|
||||
.find('.choices__list--single .choices__item')
|
||||
.last()
|
||||
.should($item => {
|
||||
expect($item).to.contain(selectedChoiceText);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('search floor', () => {
|
||||
/*
|
||||
{
|
||||
searchFloor: 10,
|
||||
};
|
||||
*/
|
||||
|
||||
describe('on input', () => {
|
||||
beforeEach(() => {
|
||||
cy.get('[data-test-hook=search-floor]')
|
||||
.find('.choices__input--cloned')
|
||||
.focus();
|
||||
});
|
||||
|
||||
describe('search floor not reached', () => {
|
||||
it('displays choices not filtered by inputted value', () => {
|
||||
const searchTerm = 'item 2';
|
||||
|
||||
cy.get('[data-test-hook=search-floor]')
|
||||
.find('.choices__input--cloned')
|
||||
.type(searchTerm);
|
||||
|
||||
cy.get('[data-test-hook=search-floor]')
|
||||
.find('.choices__list--dropdown .choices__list')
|
||||
.children()
|
||||
.first()
|
||||
.should($choice => {
|
||||
expect($choice.text().trim()).to.not.contain(searchTerm);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('search floor reached', () => {
|
||||
it('displays choices filtered by inputted value', () => {
|
||||
const searchTerm = 'Choice 2';
|
||||
|
||||
cy.get('[data-test-hook=search-floor]')
|
||||
.find('.choices__input--cloned')
|
||||
.type(searchTerm);
|
||||
|
||||
cy.get('[data-test-hook=search-floor]')
|
||||
.find('.choices__list--dropdown .choices__list')
|
||||
.children()
|
||||
.first()
|
||||
.should($choice => {
|
||||
expect($choice.text().trim()).to.contain(searchTerm);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('remote data', () => {
|
||||
beforeEach(() => {
|
||||
cy.reload(true);
|
||||
});
|
||||
|
||||
describe('when loading data', () => {
|
||||
it('shows a loading message as a placeholder', () => {
|
||||
cy.get('[data-test-hook=remote-data]')
|
||||
.find('.choices__list--single')
|
||||
.children()
|
||||
.first()
|
||||
.should('have.class', 'choices__placeholder')
|
||||
.and($placeholder => {
|
||||
expect($placeholder).to.contain('Loading...');
|
||||
});
|
||||
});
|
||||
|
||||
describe('opening the dropdown', () => {
|
||||
it('displays "no choices to choose" prompt', () => {
|
||||
cy.get('[data-test-hook=remote-data]').click();
|
||||
cy.get('[data-test-hook=remote-data]')
|
||||
.find('.choices__list--dropdown')
|
||||
.should('be.visible')
|
||||
.should($dropdown => {
|
||||
const dropdownText = $dropdown.text().trim();
|
||||
expect(dropdownText).to.equal('No choices to choose from');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when data has loaded', () => {
|
||||
describe('opening the dropdown', () => {
|
||||
it('displays the loaded data', () => {
|
||||
cy.wait(2000);
|
||||
cy.get('[data-test-hook=remote-data]')
|
||||
.find('.choices__list--dropdown .choices__list')
|
||||
.children()
|
||||
.should('have.length', 50)
|
||||
.each(($choice, index) => {
|
||||
expect($choice.text().trim()).to.equal(`Label ${index + 1}`);
|
||||
expect($choice.data('value')).to.equal(`Value ${index + 1}`);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('scrolling dropdown', () => {
|
||||
let choicesCount;
|
||||
|
||||
beforeEach(() => {
|
||||
cy.get('[data-test-hook=scrolling-dropdown]')
|
||||
.find('.choices__list--dropdown .choices__list .choices__item')
|
||||
.then($choices => {
|
||||
choicesCount = $choices.length;
|
||||
});
|
||||
|
||||
cy.get('[data-test-hook=scrolling-dropdown]')
|
||||
.find('.choices')
|
||||
.click();
|
||||
});
|
||||
|
||||
it('highlights first choice on dropdown open', () => {
|
||||
cy.get('[data-test-hook=scrolling-dropdown]')
|
||||
.find('.choices__list--dropdown .choices__list .is-highlighted')
|
||||
.should($choice => {
|
||||
expect($choice.text().trim()).to.equal('Choice 1');
|
||||
});
|
||||
});
|
||||
|
||||
it('scrolls to next choice on down arrow', () => {
|
||||
for (let index = 0; index < choicesCount; index++) {
|
||||
cy.get('[data-test-hook=scrolling-dropdown]')
|
||||
.find('.choices__list--dropdown .choices__list .is-highlighted')
|
||||
.should($choice => {
|
||||
expect($choice.text().trim()).to.equal(`Choice ${index + 1}`);
|
||||
});
|
||||
|
||||
cy.get('[data-test-hook=scrolling-dropdown]')
|
||||
.find('.choices__input--cloned')
|
||||
.type('{downarrow}');
|
||||
}
|
||||
});
|
||||
|
||||
it('scrolls up to previous choice on up arrow', () => {
|
||||
// scroll to last choice
|
||||
for (let index = 0; index < choicesCount; index++) {
|
||||
cy.get('[data-test-hook=scrolling-dropdown]')
|
||||
.find('.choices__input--cloned')
|
||||
.type('{downarrow}');
|
||||
}
|
||||
|
||||
// scroll up to first choice
|
||||
for (let index = choicesCount; index > 0; index--) {
|
||||
cy.wait(100); // allow for dropdown animation to finish
|
||||
|
||||
cy.get('[data-test-hook=scrolling-dropdown]')
|
||||
.find('.choices__list--dropdown .choices__list .is-highlighted')
|
||||
.should($choice => {
|
||||
expect($choice.text().trim()).to.equal(`Choice ${index}`);
|
||||
});
|
||||
|
||||
cy.get('[data-test-hook=scrolling-dropdown]')
|
||||
.find('.choices__input--cloned')
|
||||
.type('{uparrow}');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('choice groups', () => {
|
||||
const choicesInGroup = 3;
|
||||
let groupValue;
|
||||
|
||||
beforeEach(() => {
|
||||
cy.get('[data-test-hook=groups]')
|
||||
.find('.choices__list--dropdown .choices__list .choices__group')
|
||||
.first()
|
||||
.then($group => {
|
||||
groupValue = $group.text().trim();
|
||||
});
|
||||
});
|
||||
|
||||
describe('selecting all choices in group', () => {
|
||||
it('removes group from dropdown', () => {
|
||||
for (let index = 0; index < choicesInGroup; index++) {
|
||||
cy.get('[data-test-hook=groups]')
|
||||
.find('.choices__input--cloned')
|
||||
.focus();
|
||||
|
||||
cy.get('[data-test-hook=groups]')
|
||||
.find('.choices__list--dropdown .choices__list .choices__item')
|
||||
.first()
|
||||
.click();
|
||||
}
|
||||
|
||||
cy.get('[data-test-hook=groups]')
|
||||
.find('.choices__list--dropdown .choices__list .choices__group')
|
||||
.first()
|
||||
.should($group => {
|
||||
expect($group.text().trim()).to.not.equal(groupValue);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('deselecting all choices in group', () => {
|
||||
beforeEach(() => {
|
||||
for (let index = 0; index < choicesInGroup; index++) {
|
||||
cy.get('[data-test-hook=groups]')
|
||||
.find('.choices__input--cloned')
|
||||
.focus();
|
||||
|
||||
cy.get('[data-test-hook=groups]')
|
||||
.find('.choices__list--dropdown .choices__list .choices__item')
|
||||
.first()
|
||||
.click();
|
||||
}
|
||||
});
|
||||
|
||||
it('shows group in dropdown', () => {
|
||||
for (let index = 0; index < choicesInGroup; index++) {
|
||||
cy.get('[data-test-hook=groups]')
|
||||
.find('.choices__input--cloned')
|
||||
.focus()
|
||||
.type('{backspace}');
|
||||
}
|
||||
|
||||
cy.get('[data-test-hook=groups]')
|
||||
.find('.choices__list--dropdown .choices__list .choices__group')
|
||||
.first()
|
||||
.should($group => {
|
||||
expect($group.text().trim()).to.equal(groupValue);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('parent/child', () => {
|
||||
describe('selecting "Parent choice 2"', () => {
|
||||
it('enables the child Choices instance', () => {
|
||||
cy.get('[data-test-hook=parent-child]')
|
||||
.find('.choices')
|
||||
.eq(1)
|
||||
.should('have.class', 'is-disabled');
|
||||
|
||||
cy.get('[data-test-hook=parent-child]')
|
||||
.find('.choices')
|
||||
.eq(0)
|
||||
.click();
|
||||
|
||||
cy.get('[data-test-hook=parent-child]')
|
||||
.find('.choices__list--dropdown .choices__list')
|
||||
.children()
|
||||
.eq(1)
|
||||
.click();
|
||||
|
||||
cy.get('[data-test-hook=parent-child]')
|
||||
.find('.choices')
|
||||
.eq(1)
|
||||
.should('not.have.class', 'is-disabled');
|
||||
});
|
||||
});
|
||||
|
||||
describe('changing selection from "Parent choice 2" to something else', () => {
|
||||
it('disables the child Choices instance', () => {
|
||||
// open parent instance and select second choice
|
||||
cy.get('[data-test-hook=parent-child]')
|
||||
.find('.choices')
|
||||
.eq(0)
|
||||
.click()
|
||||
.find('.choices__list--dropdown .choices__list')
|
||||
.children()
|
||||
.eq(1)
|
||||
.click();
|
||||
|
||||
cy.get('[data-test-hook=parent-child]')
|
||||
.find('.choices')
|
||||
.eq(1)
|
||||
.should('not.have.class', 'is-disabled');
|
||||
|
||||
// open parent instance and select third choice
|
||||
cy.get('[data-test-hook=parent-child]')
|
||||
.find('.choices')
|
||||
.eq(0)
|
||||
.click()
|
||||
.find('.choices__list--dropdown .choices__list')
|
||||
.children()
|
||||
.eq(2)
|
||||
.click();
|
||||
|
||||
cy.get('[data-test-hook=parent-child]')
|
||||
.find('.choices')
|
||||
.eq(1)
|
||||
.should('have.class', 'is-disabled');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -14,4 +14,4 @@
|
|||
module.exports = (on, config) => {
|
||||
// `on` is used to hook into various events Cypress emits
|
||||
// `config` is the resolved Cypress config
|
||||
}
|
||||
};
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
// ***********************************************************
|
||||
|
||||
// Import commands.js using ES2015 syntax:
|
||||
import './commands'
|
||||
import './commands';
|
||||
|
||||
// Alternatively you can use CommonJS syntax:
|
||||
// require('./commands')
|
17
jsconfig.json
Normal file
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"checkJs": true,
|
||||
"target": "es2020",
|
||||
"lib": ["esnext", "dom"],
|
||||
"types": ["cypress"],
|
||||
"strict": true,
|
||||
"moduleResolution": "node",
|
||||
/* Additional Checks */
|
||||
"noImplicitAny": false,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"noImplicitReturns": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"strictNullChecks": false
|
||||
}
|
||||
}
|
14
lint-staged.config.js
Normal file
|
@ -0,0 +1,14 @@
|
|||
module.exports = {
|
||||
'*.js': ['eslint --fix --quiet -f visualstudio', 'git add'],
|
||||
'*.{ts,scss,yaml,yml,md,html,json,babelrc,eslintrc}': [
|
||||
'prettier --write',
|
||||
'git add',
|
||||
],
|
||||
'src/icons/*.svg': [
|
||||
'prettier --write --parser=html --html-whitespace-sensitivity=ignore',
|
||||
'git add',
|
||||
],
|
||||
'.codecov.yml': () =>
|
||||
'curl -f --silent --data-binary @.codecov.yml https://codecov.io/validate',
|
||||
'src/scripts/**/*.js': () => 'npm run test:unit',
|
||||
};
|
23844
package-lock.json
generated
Normal file
156
package.json
|
@ -1,33 +1,33 @@
|
|||
{
|
||||
"name": "choices.js",
|
||||
"version": "4.0.6",
|
||||
"version": "10.2.0",
|
||||
"description": "A vanilla JS customisable text input/select box plugin",
|
||||
"main": "./public/assets/scripts/choices.min.js",
|
||||
"types": "./types/index.d.ts",
|
||||
"main": "./public/assets/scripts/choices.js",
|
||||
"types": "./public/types/src/index.d.ts",
|
||||
"scripts": {
|
||||
"start": "run-p js:watch css:watch",
|
||||
"build": "npm run js:build && npm run css:build",
|
||||
"lint": "eslint assets/**/*.js",
|
||||
"coverage": "nyc npm run test:unit",
|
||||
"cypress:run": "$(npm bin)/cypress run",
|
||||
"cypress:open": "$(npm bin)/cypress open",
|
||||
"test:unit": "mocha --require ./config/jsdom.js --compilers js:babel-core/register \"./src/**/**/**/**/*.test.js\" --exit",
|
||||
"build": "run-p js:build css:build",
|
||||
"lint": "run-p lint:js lint:scss",
|
||||
"lint:js": "eslint src/scripts/**/*.ts",
|
||||
"lint:scss": "stylelint src/**/*.scss",
|
||||
"bundlesize": "bundlesize",
|
||||
"cypress:run": "cypress run --browser chrome",
|
||||
"cypress:open": "cypress open",
|
||||
"cypress:ci": "cypress run --browser chrome --record --group $GITHUB_REF --ci-build-id $GITHUB_SHA",
|
||||
"test": "run-s test:unit test:e2e",
|
||||
"test:unit": "cross-env TS_NODE_TRANSPILE_ONLY=true NODE_ENV=test mocha",
|
||||
"test:unit:watch": "npm run test:unit -- --watch --inspect=5556",
|
||||
"test:unit:coverage": "NODE_ENV=test nyc --reporter=lcov --reporter=text --reporter=text-summary mocha",
|
||||
"test:e2e": "run-p --race start cypress:run",
|
||||
"test": "run-p test:unit test:e2e",
|
||||
"js:watch": "NODE_ENV=development node server.js",
|
||||
"js:build:minimised": "webpack --env.minimize --config webpack.config.prod.js",
|
||||
"js:build:unminimised": "webpack --config webpack.config.prod.js",
|
||||
"js:build": "run-p js:build:minimised js:build:unminimised",
|
||||
"js:watch": "cross-env NODE_ENV=development node server.js",
|
||||
"js:build": "webpack --config webpack.config.prod.js",
|
||||
"css:watch": "nodemon -e scss -x \"npm run css:build\"",
|
||||
"css:build": "run-p css:sass css:prefix css:min",
|
||||
"css:sass": "node-sass --output-style expanded --include-path scss src/styles/base.scss public/assets/styles/base.css && node-sass --output-style expanded --include-path scss src/styles/choices.scss public/assets/styles/choices.css",
|
||||
"css:prefix": "postcss --use autoprefixer -b 'last 2 versions' public/assets/styles/*.css -d public/assets/styles",
|
||||
"css:min": "csso public/assets/styles/base.css public/assets/styles/base.min.css && csso public/assets/styles/choices.css public/assets/styles/choices.min.css",
|
||||
"bump-version": "node bump-version.js --current $npm_package_version",
|
||||
"css:build": "run-s css:sass css:prefix css:min",
|
||||
"css:sass": "sass -I scss src/styles/base.scss public/assets/styles/base.css && sass -I scss src/styles/choices.scss public/assets/styles/choices.css",
|
||||
"css:prefix": "postcss public/assets/styles/*.css --use autoprefixer --no-map --env prod --dir public/assets/styles",
|
||||
"css:min": "csso public/assets/styles/base.css --output public/assets/styles/base.min.css && csso public/assets/styles/choices.css --output public/assets/styles/choices.min.css",
|
||||
"deploy": "git subtree push --prefix public origin gh-pages",
|
||||
"postversion": "npm run js:build",
|
||||
"prepush": "run-p lint test:unit"
|
||||
"prepublishOnly": "npm run build"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
@ -35,6 +35,14 @@
|
|||
},
|
||||
"author": "Josh Johnson",
|
||||
"license": "MIT",
|
||||
"files": [
|
||||
"public/assets/scripts",
|
||||
"public/assets/styles",
|
||||
"public/types",
|
||||
"src",
|
||||
"!src/**/*.test.js",
|
||||
"types"
|
||||
],
|
||||
"bugs": {
|
||||
"url": "https://github.com/jshjohnson/Choices/issues"
|
||||
},
|
||||
|
@ -48,57 +56,69 @@
|
|||
"js"
|
||||
],
|
||||
"devDependencies": {
|
||||
"autoprefixer": "^6.3.3",
|
||||
"babel-core": "^6.26.0",
|
||||
"babel-eslint": "^7.2.3",
|
||||
"babel-loader": "^7.1.2",
|
||||
"babel-preset-env": "^1.6.1",
|
||||
"babel-preset-stage-2": "^6.24.1",
|
||||
"chai": "^4.1.0",
|
||||
"csso": "^1.8.2",
|
||||
"cypress": "^3.1.0",
|
||||
"eslint": "^3.19.0",
|
||||
"eslint-config-airbnb": "^15.1.0",
|
||||
"eslint-config-prettier": "^2.9.0",
|
||||
"eslint-loader": "^1.5.0",
|
||||
"eslint-plugin-cypress": "^2.0.1",
|
||||
"eslint-plugin-import": "^2.7.0",
|
||||
"eslint-plugin-jsx-a11y": "^5.1.1",
|
||||
"eslint-plugin-prettier": "^2.6.0",
|
||||
"eslint-plugin-react": "^7.2.1",
|
||||
"express": "^4.16.3",
|
||||
"husky": "^0.14.3",
|
||||
"jsdom": "^11.5.1",
|
||||
"mocha": "^3.4.2",
|
||||
"node-sass": "^4.9.3",
|
||||
"nodemon": "^1.9.1",
|
||||
"npm-run-all": "^4.1.3",
|
||||
"nyc": "^11.0.3",
|
||||
"opn": "^5.1.0",
|
||||
"postcss-cli": "^2.5.1",
|
||||
"prettier": "^1.13.0",
|
||||
"sinon": "^2.4.0",
|
||||
"webpack": "^3.8.1",
|
||||
"webpack-dev-middleware": "^2.0.0",
|
||||
"webpack-hot-middleware": "^2.22.2",
|
||||
"whatwg-fetch": "^1.0.0",
|
||||
"wrapper-webpack-plugin": "^0.1.7"
|
||||
"@babel/core": "^7.20.5",
|
||||
"@babel/preset-env": "^7.20.2",
|
||||
"@babel/register": "^7.18.9",
|
||||
"@types/chai": "^4.3.4",
|
||||
"@types/mocha": "^10.0.1",
|
||||
"@types/sinon": "^10.0.13",
|
||||
"@types/sinon-chai": "^3.2.9",
|
||||
"@typescript-eslint/eslint-plugin": "^5.45.0",
|
||||
"@typescript-eslint/parser": "^5.45.0",
|
||||
"autoprefixer": "^10.4.13",
|
||||
"babel-loader": "^9.1.0",
|
||||
"bundlesize": "^0.18.1",
|
||||
"chai": "^4.3.7",
|
||||
"cross-env": "^7.0.3",
|
||||
"csso-cli": "^4.0.1",
|
||||
"cypress": "11.2.0",
|
||||
"eslint": "^8.28.0",
|
||||
"eslint-config-airbnb-base": "^15.0.0",
|
||||
"eslint-config-airbnb-typescript": "^17.0.0",
|
||||
"eslint-config-prettier": "^8.5.0",
|
||||
"eslint-plugin-compat": "4.0.2",
|
||||
"eslint-plugin-cypress": "^2.12.1",
|
||||
"eslint-plugin-import": "^2.26.0",
|
||||
"eslint-plugin-prettier": "^4.2.1",
|
||||
"eslint-plugin-sort-class-members": "^1.15.2",
|
||||
"eslint-webpack-plugin": "^3.2.0",
|
||||
"express": "^4.18.2",
|
||||
"husky": "^8.0.2",
|
||||
"jsdom": "^20.0.3",
|
||||
"lint-staged": "^13.0.4",
|
||||
"mocha": "^10.1.0",
|
||||
"nodemon": "^2.0.20",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"nyc": "^15.1.0",
|
||||
"postcss": "^8.4.19",
|
||||
"postcss-cli": "^10.0.0",
|
||||
"prettier": "^2.8.0",
|
||||
"sass": "^1.56.1",
|
||||
"sinon": "^15.0.0",
|
||||
"sinon-chai": "^3.7.0",
|
||||
"stylelint": "^14.15.0",
|
||||
"stylelint-config-standard": "^29.0.0",
|
||||
"stylelint-config-standard-scss": "^6.1.0",
|
||||
"ts-loader": "^9.4.1",
|
||||
"ts-node": "^10.9.1",
|
||||
"typescript": "^4.9.3",
|
||||
"webpack": "^5.75.0",
|
||||
"webpack-cli": "^5.0.0",
|
||||
"webpack-dev-middleware": "^6.0.1",
|
||||
"webpack-hot-middleware": "^2.25.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"classnames": "^2.2.5",
|
||||
"core-js": "^2.5.6",
|
||||
"custom-event-polyfill": "^0.3.0",
|
||||
"deepmerge": "^2.2.1",
|
||||
"fuse.js": "^3.1.0",
|
||||
"redux": "^3.3.1"
|
||||
"deepmerge": "^4.2.2",
|
||||
"fuse.js": "^6.6.2",
|
||||
"redux": "^4.2.0"
|
||||
},
|
||||
"npmName": "choices.js",
|
||||
"npmFileMap": [
|
||||
{
|
||||
"basePath": "src",
|
||||
"files": [
|
||||
"public/assets/scripts/*",
|
||||
"public/assets/styles/*",
|
||||
"public/types/*",
|
||||
"src/icons/*"
|
||||
]
|
||||
}
|
||||
|
@ -110,5 +130,15 @@
|
|||
"exclude": [
|
||||
"src/scripts/**/**/*.test.js"
|
||||
]
|
||||
},
|
||||
"bundlesize": [
|
||||
{
|
||||
"path": "public/assets/scripts/choices.min.js",
|
||||
"maxSize": "25 kB"
|
||||
},
|
||||
{
|
||||
"path": "public/assets/styles/choices.min.css",
|
||||
"maxSize": "2.5 kB"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
27
public/assets/scripts/.eslintrc.js
Normal file
|
@ -0,0 +1,27 @@
|
|||
// get polyfill settings from top level config
|
||||
// @ts-ignore
|
||||
const { settings } = require('../../../.eslintrc.json');
|
||||
|
||||
// Adding non-polyfilable Symbol-related functions as they are most probably
|
||||
// behind the flag
|
||||
|
||||
settings.polyfills.push(
|
||||
'Symbol.toStringTag',
|
||||
'Symbol.for',
|
||||
'Object.getOwnPropertySymbols',
|
||||
'Object.getOwnPropertyDescriptors',
|
||||
'Promise', // Promise is gate checked
|
||||
);
|
||||
|
||||
module.exports = /** @type {import('eslint').Linter.Config} */ ({
|
||||
root: true,
|
||||
extends: ['plugin:compat/recommended'],
|
||||
parserOptions: {
|
||||
// ensure that it's compatible with ES5 browsers, so, no `const`, etc
|
||||
ecmaVersion: 5,
|
||||
},
|
||||
env: {
|
||||
browser: true,
|
||||
},
|
||||
settings,
|
||||
});
|
4
public/assets/scripts/choices.min.js
vendored
1
public/assets/scripts/choices.min.js.LICENSE.txt
Normal file
|
@ -0,0 +1 @@
|
|||
/*! choices.js v10.2.0 | © 2022 Josh Johnson | https://github.com/jshjohnson/Choices#readme */
|
|
@ -1,14 +1,14 @@
|
|||
/*=============================================
|
||||
/* =============================================
|
||||
= Generic styling =
|
||||
=============================================*/
|
||||
============================================= */
|
||||
* {
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
*,
|
||||
*:before,
|
||||
*:after {
|
||||
*::before,
|
||||
*::after {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,7 @@ body {
|
|||
font-family: "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
|
||||
font-size: 16px;
|
||||
line-height: 1.4;
|
||||
color: #FFFFFF;
|
||||
color: #fff;
|
||||
background-color: #333;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
@ -39,6 +39,7 @@ label {
|
|||
|
||||
p {
|
||||
margin-top: 0;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
hr {
|
||||
|
@ -64,7 +65,7 @@ h6 {
|
|||
a,
|
||||
a:visited,
|
||||
a:focus {
|
||||
color: #FFFFFF;
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
@ -78,7 +79,6 @@ a:focus {
|
|||
border-radius: 2.5px;
|
||||
font-size: 14px;
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
@ -113,13 +113,16 @@ h6,
|
|||
font-size: 14px;
|
||||
}
|
||||
|
||||
label + p {
|
||||
margin-top: -4px;
|
||||
}
|
||||
|
||||
.container {
|
||||
display: block;
|
||||
margin: auto;
|
||||
max-width: 40em;
|
||||
padding: 48px;
|
||||
}
|
||||
|
||||
@media (max-width: 620px) {
|
||||
.container {
|
||||
padding: 0;
|
||||
|
@ -127,11 +130,10 @@ h6,
|
|||
}
|
||||
|
||||
.section {
|
||||
background-color: #FFFFFF;
|
||||
background-color: #fff;
|
||||
padding: 24px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.section a,
|
||||
.section a:visited,
|
||||
.section a:focus {
|
||||
|
@ -143,7 +145,7 @@ h6,
|
|||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.logo__img {
|
||||
.logo-img {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
display: inline-block;
|
||||
|
@ -156,6 +158,10 @@ h6,
|
|||
display: none;
|
||||
}
|
||||
|
||||
.push-bottom {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.zero-bottom {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
@ -168,12 +174,8 @@ h6,
|
|||
text-align: center;
|
||||
}
|
||||
|
||||
.is-hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
[data-test-hook] {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
/*===== End of Section comment block ======*/
|
||||
/* ===== End of Section comment block ====== */
|
||||
|
|
1
public/assets/styles/base.css.map
Normal file
|
@ -0,0 +1 @@
|
|||
{"version":3,"sourceRoot":"","sources":["../../../src/styles/base.scss"],"names":[],"mappings":"AAAA;AAAA;AAAA;AAYA;EACE;EACA;;;AAGF;AAAA;AAAA;EAGE;;;AAGF;AAAA;EAEE;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;;;AAGF;AAAA;AAAA;AAAA;AAAA;AAAA;EAME;EACA;EACA;EACA;;;AAGF;AAAA;AAAA;EAGE;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,eAtFiB;;;AAyFnB;AAAA;EAEE,WA1FoB;;;AA6FtB;AAAA;EAEE,WA9FoB;;;AAiGtB;AAAA;EAEE,WAlGoB;;;AAqGtB;AAAA;EAEE,WAtGoB;;;AAyGtB;AAAA;EAEE,WA1GoB;;;AA6GtB;AAAA;EAEE,WA9GoB;;;AAiHtB;EACE;;;AAGF;EACE;EACA;EACA;EACA;;AAEA;EANF;IAOI;;;;AAIJ;EACE;EACA,SAxIiB;EAyIjB;;AAEA;AAAA;AAAA;EAGE;;;AAIJ;EACE;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE,eArKiB;;;AAwKnB;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE,eArLiB;;;AAwLnB","file":"base.css"}
|
2
public/assets/styles/base.min.css
vendored
|
@ -1 +1 @@
|
|||
*{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}*,:after,:before{box-sizing:border-box}body,html{position:relative;margin:0;width:100%;height:100%}body{font-family:"Helvetica Neue",Helvetica,Arial,"Lucida Grande",sans-serif;font-size:16px;line-height:1.4;color:#fff;background-color:#333;overflow-x:hidden}hr,label{display:block}label{margin-bottom:8px;font-size:14px;font-weight:500;cursor:pointer}p{margin-top:0}hr{margin:30px 0;border:0;border-bottom:1px solid #eaeaea;height:1px}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:12px;font-weight:400;line-height:1.2}a,a:focus,a:visited{color:#fff;text-decoration:none;font-weight:600}.form-control{display:block;width:100%;background-color:#f9f9f9;padding:12px;border:1px solid #ddd;border-radius:2.5px;font-size:14px;-webkit-appearance:none;-moz-appearance:none;appearance:none;margin-bottom:24px}.h1,h1{font-size:32px}.h2,h2{font-size:24px}.h3,h3{font-size:20px}.h4,h4{font-size:18px}.h5,h5{font-size:16px}.h6,h6{font-size:14px}.container{display:block;margin:auto;max-width:40em;padding:48px}@media (max-width:620px){.container{padding:0}}.section{background-color:#fff;padding:24px;color:#333}.section a,.section a:focus,.section a:visited{color:#00bcd4}.logo{display:block;margin-bottom:12px}.logo__img{width:100%;height:auto;display:inline-block;max-width:100%;vertical-align:top;padding:6px 0}.visible-ie{display:none}.zero-bottom{margin-bottom:0}.zero-top{margin-top:0}.text-center{text-align:center}.is-hidden{display:none}[data-test-hook]{margin-bottom:24px}
|
||||
*{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}*,::after,::before{box-sizing:border-box}body,html{position:relative;margin:0;width:100%;height:100%}body{font-family:"Helvetica Neue",Helvetica,Arial,"Lucida Grande",sans-serif;font-size:16px;line-height:1.4;color:#fff;background-color:#333;overflow-x:hidden}hr,label{display:block}label,p{margin-bottom:8px}label{font-size:14px;font-weight:500;cursor:pointer}p{margin-top:0}hr{margin:30px 0;border:0;border-bottom:1px solid #eaeaea;height:1px}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:12px;font-weight:400;line-height:1.2}a,a:focus,a:visited{color:#fff;text-decoration:none;font-weight:600}.form-control{display:block;width:100%;background-color:#f9f9f9;padding:12px;border:1px solid #ddd;border-radius:2.5px;font-size:14px;-webkit-appearance:none;appearance:none;margin-bottom:24px}.h1,h1{font-size:32px}.h2,h2{font-size:24px}.h3,h3{font-size:20px}.h4,h4{font-size:18px}.h5,h5{font-size:16px}.h6,h6{font-size:14px}label+p{margin-top:-4px}.container{display:block;margin:auto;max-width:40em;padding:48px}@media (max-width:620px){.container{padding:0}}.section{background-color:#fff;padding:24px;color:#333}.section a,.section a:focus,.section a:visited{color:#00bcd4}.logo{display:block;margin-bottom:12px}.logo-img{width:100%;height:auto;display:inline-block;max-width:100%;vertical-align:top;padding:6px 0}.visible-ie{display:none}.push-bottom{margin-bottom:24px}.zero-bottom{margin-bottom:0}.zero-top{margin-top:0}.text-center{text-align:center}[data-test-hook]{margin-bottom:24px}
|
|
@ -1,50 +1,51 @@
|
|||
/*===============================
|
||||
/* ===============================
|
||||
= Choices =
|
||||
===============================*/
|
||||
=============================== */
|
||||
.choices {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
margin-bottom: 24px;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.choices:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.choices:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.choices.is-open {
|
||||
overflow: visible;
|
||||
}
|
||||
.choices.is-disabled .choices__inner,
|
||||
.choices.is-disabled .choices__input {
|
||||
background-color: #EAEAEA;
|
||||
background-color: #eaeaea;
|
||||
cursor: not-allowed;
|
||||
-webkit-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.choices.is-disabled .choices__item {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
.choices [hidden] {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.choices[data-type*="select-one"] {
|
||||
.choices[data-type*=select-one] {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.choices[data-type*="select-one"] .choices__inner {
|
||||
.choices[data-type*=select-one] .choices__inner {
|
||||
padding-bottom: 7.5px;
|
||||
}
|
||||
|
||||
.choices[data-type*="select-one"] .choices__input {
|
||||
.choices[data-type*=select-one] .choices__input {
|
||||
display: block;
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
border-bottom: 1px solid #DDDDDD;
|
||||
background-color: #FFFFFF;
|
||||
border-bottom: 1px solid #ddd;
|
||||
background-color: #fff;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.choices[data-type*="select-one"] .choices__button {
|
||||
background-image: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjEiIGhlaWdodD0iMjEiIHZpZXdCb3g9IjAgMCAyMSAyMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48ZyBmaWxsPSIjMDAwIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPjxwYXRoIGQ9Ik0yLjU5Mi4wNDRsMTguMzY0IDE4LjM2NC0yLjU0OCAyLjU0OEwuMDQ0IDIuNTkyeiIvPjxwYXRoIGQ9Ik0wIDE4LjM2NEwxOC4zNjQgMGwyLjU0OCAyLjU0OEwyLjU0OCAyMC45MTJ6Ii8+PC9nPjwvc3ZnPg==);
|
||||
.choices[data-type*=select-one] .choices__button {
|
||||
background-image: url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjEiIGhlaWdodD0iMjEiIHZpZXdCb3g9IjAgMCAyMSAyMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48ZyBmaWxsPSIjMDAwIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPjxwYXRoIGQ9Ik0yLjU5Mi4wNDRsMTguMzY0IDE4LjM2NC0yLjU0OCAyLjU0OEwuMDQ0IDIuNTkyeiIvPjxwYXRoIGQ9Ik0wIDE4LjM2NEwxOC4zNjQgMGwyLjU0OCAyLjU0OEwyLjU0OCAyMC45MTJ6Ii8+PC9nPjwvc3ZnPg==");
|
||||
padding: 0;
|
||||
background-size: 8px;
|
||||
position: absolute;
|
||||
|
@ -55,23 +56,23 @@
|
|||
height: 20px;
|
||||
width: 20px;
|
||||
border-radius: 10em;
|
||||
opacity: .5;
|
||||
opacity: 0.25;
|
||||
}
|
||||
|
||||
.choices[data-type*="select-one"] .choices__button:hover, .choices[data-type*="select-one"] .choices__button:focus {
|
||||
.choices[data-type*=select-one] .choices__button:hover, .choices[data-type*=select-one] .choices__button:focus {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.choices[data-type*="select-one"] .choices__button:focus {
|
||||
box-shadow: 0px 0px 0px 2px #00BCD4;
|
||||
.choices[data-type*=select-one] .choices__button:focus {
|
||||
box-shadow: 0 0 0 2px #00bcd4;
|
||||
}
|
||||
|
||||
.choices[data-type*="select-one"]:after {
|
||||
.choices[data-type*=select-one] .choices__item[data-value=""] .choices__button {
|
||||
display: none;
|
||||
}
|
||||
.choices[data-type*=select-one]::after {
|
||||
content: "";
|
||||
height: 0;
|
||||
width: 0;
|
||||
border-style: solid;
|
||||
border-color: #333333 transparent transparent transparent;
|
||||
border-color: #333 transparent transparent transparent;
|
||||
border-width: 5px;
|
||||
position: absolute;
|
||||
right: 11.5px;
|
||||
|
@ -79,31 +80,27 @@
|
|||
margin-top: -2.5px;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.choices[data-type*="select-one"].is-open:after {
|
||||
border-color: transparent transparent #333333 transparent;
|
||||
.choices[data-type*=select-one].is-open::after {
|
||||
border-color: transparent transparent #333 transparent;
|
||||
margin-top: -7.5px;
|
||||
}
|
||||
|
||||
.choices[data-type*="select-one"][dir="rtl"]:after {
|
||||
.choices[data-type*=select-one][dir=rtl]::after {
|
||||
left: 11.5px;
|
||||
right: auto;
|
||||
}
|
||||
|
||||
.choices[data-type*="select-one"][dir="rtl"] .choices__button {
|
||||
.choices[data-type*=select-one][dir=rtl] .choices__button {
|
||||
right: auto;
|
||||
left: 0;
|
||||
margin-left: 25px;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.choices[data-type*="select-multiple"] .choices__inner,
|
||||
.choices[data-type*="text"] .choices__inner {
|
||||
.choices[data-type*=select-multiple] .choices__inner,
|
||||
.choices[data-type*=text] .choices__inner {
|
||||
cursor: text;
|
||||
}
|
||||
|
||||
.choices[data-type*="select-multiple"] .choices__button,
|
||||
.choices[data-type*="text"] .choices__button {
|
||||
.choices[data-type*=select-multiple] .choices__button,
|
||||
.choices[data-type*=text] .choices__button {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
margin-top: 0;
|
||||
|
@ -112,17 +109,16 @@
|
|||
margin-left: 8px;
|
||||
padding-left: 16px;
|
||||
border-left: 1px solid #008fa1;
|
||||
background-image: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjEiIGhlaWdodD0iMjEiIHZpZXdCb3g9IjAgMCAyMSAyMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48ZyBmaWxsPSIjRkZGIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPjxwYXRoIGQ9Ik0yLjU5Mi4wNDRsMTguMzY0IDE4LjM2NC0yLjU0OCAyLjU0OEwuMDQ0IDIuNTkyeiIvPjxwYXRoIGQ9Ik0wIDE4LjM2NEwxOC4zNjQgMGwyLjU0OCAyLjU0OEwyLjU0OCAyMC45MTJ6Ii8+PC9nPjwvc3ZnPg==);
|
||||
background-image: url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjEiIGhlaWdodD0iMjEiIHZpZXdCb3g9IjAgMCAyMSAyMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48ZyBmaWxsPSIjRkZGIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPjxwYXRoIGQ9Ik0yLjU5Mi4wNDRsMTguMzY0IDE4LjM2NC0yLjU0OCAyLjU0OEwuMDQ0IDIuNTkyeiIvPjxwYXRoIGQ9Ik0wIDE4LjM2NEwxOC4zNjQgMGwyLjU0OCAyLjU0OEwyLjU0OCAyMC45MTJ6Ii8+PC9nPjwvc3ZnPg==");
|
||||
background-size: 8px;
|
||||
width: 8px;
|
||||
line-height: 1;
|
||||
opacity: .75;
|
||||
opacity: 0.75;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.choices[data-type*="select-multiple"] .choices__button:hover, .choices[data-type*="select-multiple"] .choices__button:focus,
|
||||
.choices[data-type*="text"] .choices__button:hover,
|
||||
.choices[data-type*="text"] .choices__button:focus {
|
||||
.choices[data-type*=select-multiple] .choices__button:hover, .choices[data-type*=select-multiple] .choices__button:focus,
|
||||
.choices[data-type*=text] .choices__button:hover,
|
||||
.choices[data-type*=text] .choices__button:focus {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
|
@ -132,22 +128,18 @@
|
|||
width: 100%;
|
||||
background-color: #f9f9f9;
|
||||
padding: 7.5px 7.5px 3.75px;
|
||||
border: 1px solid #DDDDDD;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 2.5px;
|
||||
font-size: 14px;
|
||||
min-height: 44px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.is-focused .choices__inner,
|
||||
.is-open .choices__inner {
|
||||
.is-focused .choices__inner, .is-open .choices__inner {
|
||||
border-color: #b7b7b7;
|
||||
}
|
||||
|
||||
.is-open .choices__inner {
|
||||
border-radius: 2.5px 2.5px 0 0;
|
||||
}
|
||||
|
||||
.is-flipped.is-open .choices__inner {
|
||||
border-radius: 0 0 2.5px 2.5px;
|
||||
}
|
||||
|
@ -157,18 +149,15 @@
|
|||
padding-left: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.choices__list--single {
|
||||
display: inline-block;
|
||||
padding: 4px 16px 4px 4px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
[dir="rtl"] .choices__list--single {
|
||||
[dir=rtl] .choices__list--single {
|
||||
padding-right: 4px;
|
||||
padding-left: 16px;
|
||||
}
|
||||
|
||||
.choices__list--single .choices__item {
|
||||
width: 100%;
|
||||
}
|
||||
|
@ -176,7 +165,6 @@
|
|||
.choices__list--multiple {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.choices__list--multiple .choices__item {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
|
@ -186,85 +174,76 @@
|
|||
font-weight: 500;
|
||||
margin-right: 3.75px;
|
||||
margin-bottom: 3.75px;
|
||||
background-color: #00BCD4;
|
||||
background-color: #00bcd4;
|
||||
border: 1px solid #00a5bb;
|
||||
color: #FFFFFF;
|
||||
color: #fff;
|
||||
word-break: break-all;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.choices__list--multiple .choices__item[data-deletable] {
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
[dir="rtl"] .choices__list--multiple .choices__item {
|
||||
[dir=rtl] .choices__list--multiple .choices__item {
|
||||
margin-right: 0;
|
||||
margin-left: 3.75px;
|
||||
}
|
||||
|
||||
.choices__list--multiple .choices__item.is-highlighted {
|
||||
background-color: #00a5bb;
|
||||
border: 1px solid #008fa1;
|
||||
}
|
||||
|
||||
.is-disabled .choices__list--multiple .choices__item {
|
||||
background-color: #aaaaaa;
|
||||
border: 1px solid #919191;
|
||||
}
|
||||
|
||||
.choices__list--dropdown {
|
||||
display: none;
|
||||
.choices__list--dropdown, .choices__list[aria-expanded] {
|
||||
visibility: hidden;
|
||||
z-index: 1;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
background-color: #FFFFFF;
|
||||
border: 1px solid #DDDDDD;
|
||||
background-color: #fff;
|
||||
border: 1px solid #ddd;
|
||||
top: 100%;
|
||||
margin-top: -1px;
|
||||
border-bottom-left-radius: 2.5px;
|
||||
border-bottom-right-radius: 2.5px;
|
||||
overflow: hidden;
|
||||
word-break: break-all;
|
||||
will-change: visibility;
|
||||
}
|
||||
|
||||
.choices__list--dropdown.is-active {
|
||||
display: block;
|
||||
.is-active.choices__list--dropdown, .is-active.choices__list[aria-expanded] {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.is-open .choices__list--dropdown {
|
||||
.is-open .choices__list--dropdown, .is-open .choices__list[aria-expanded] {
|
||||
border-color: #b7b7b7;
|
||||
}
|
||||
|
||||
.is-flipped .choices__list--dropdown {
|
||||
.is-flipped .choices__list--dropdown, .is-flipped .choices__list[aria-expanded] {
|
||||
top: auto;
|
||||
bottom: 100%;
|
||||
margin-top: 0;
|
||||
margin-bottom: -1px;
|
||||
border-radius: .25rem .25rem 0 0;
|
||||
border-radius: 0.25rem 0.25rem 0 0;
|
||||
}
|
||||
|
||||
.choices__list--dropdown .choices__list {
|
||||
.choices__list--dropdown .choices__list, .choices__list[aria-expanded] .choices__list {
|
||||
position: relative;
|
||||
max-height: 300px;
|
||||
overflow: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
will-change: scroll-position;
|
||||
}
|
||||
|
||||
.choices__list--dropdown .choices__item {
|
||||
.choices__list--dropdown .choices__item, .choices__list[aria-expanded] .choices__item {
|
||||
position: relative;
|
||||
padding: 10px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
[dir="rtl"] .choices__list--dropdown .choices__item {
|
||||
[dir=rtl] .choices__list--dropdown .choices__item, [dir=rtl] .choices__list[aria-expanded] .choices__item {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
@media (min-width: 640px) {
|
||||
.choices__list--dropdown .choices__item--selectable {
|
||||
.choices__list--dropdown .choices__item--selectable, .choices__list[aria-expanded] .choices__item--selectable {
|
||||
padding-right: 100px;
|
||||
}
|
||||
.choices__list--dropdown .choices__item--selectable:after {
|
||||
.choices__list--dropdown .choices__item--selectable::after, .choices__list[aria-expanded] .choices__item--selectable::after {
|
||||
content: attr(data-select-text);
|
||||
font-size: 12px;
|
||||
opacity: 0;
|
||||
|
@ -273,23 +252,21 @@
|
|||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
[dir="rtl"] .choices__list--dropdown .choices__item--selectable {
|
||||
[dir=rtl] .choices__list--dropdown .choices__item--selectable, [dir=rtl] .choices__list[aria-expanded] .choices__item--selectable {
|
||||
text-align: right;
|
||||
padding-left: 100px;
|
||||
padding-right: 10px;
|
||||
}
|
||||
[dir="rtl"] .choices__list--dropdown .choices__item--selectable:after {
|
||||
[dir=rtl] .choices__list--dropdown .choices__item--selectable::after, [dir=rtl] .choices__list[aria-expanded] .choices__item--selectable::after {
|
||||
right: auto;
|
||||
left: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.choices__list--dropdown .choices__item--selectable.is-highlighted {
|
||||
.choices__list--dropdown .choices__item--selectable.is-highlighted, .choices__list[aria-expanded] .choices__item--selectable.is-highlighted {
|
||||
background-color: #f2f2f2;
|
||||
}
|
||||
|
||||
.choices__list--dropdown .choices__item--selectable.is-highlighted:after {
|
||||
opacity: .5;
|
||||
.choices__list--dropdown .choices__item--selectable.is-highlighted::after, .choices__list[aria-expanded] .choices__item--selectable.is-highlighted::after {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.choices__item {
|
||||
|
@ -302,8 +279,9 @@
|
|||
|
||||
.choices__item--disabled {
|
||||
cursor: not-allowed;
|
||||
-webkit-user-select: none;
|
||||
user-select: none;
|
||||
opacity: .5;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.choices__heading {
|
||||
|
@ -324,7 +302,6 @@
|
|||
background-position: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.choices__button:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
@ -340,24 +317,24 @@
|
|||
max-width: 100%;
|
||||
padding: 4px 0 4px 2px;
|
||||
}
|
||||
|
||||
.choices__input:focus {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
[dir="rtl"] .choices__input {
|
||||
.choices__input::-webkit-search-decoration, .choices__input::-webkit-search-cancel-button, .choices__input::-webkit-search-results-button, .choices__input::-webkit-search-results-decoration {
|
||||
display: none;
|
||||
}
|
||||
.choices__input::-ms-clear, .choices__input::-ms-reveal {
|
||||
display: none;
|
||||
width: 0;
|
||||
height: 0;
|
||||
}
|
||||
[dir=rtl] .choices__input {
|
||||
padding-right: 2px;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.choices__placeholder {
|
||||
opacity: .5;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.choices__input.is-hidden,
|
||||
.choices[data-type*="select-one"] .choices__input.is-hidden,
|
||||
.choices[data-type*="select-multiple"] .choices__input.is-hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/*===== End of Choices ======*/
|
||||
/* ===== End of Choices ====== */
|
||||
|
|
1
public/assets/styles/choices.css.map
Normal file
|
@ -0,0 +1 @@
|
|||
{"version":3,"sourceRoot":"","sources":["../../../src/styles/choices.scss"],"names":[],"mappings":"AAAA;AAAA;AAAA;AA2BA;EACE;EACA;EACA,eApBkB;EAqBlB,WAxBqB;;AA0BrB;EACE;;AAGF;EACE;;AAGF;EACE;;AAIA;AAAA;EAEE,kBAlCsB;EAmCtB;EACA;;AAEF;EACE;;AAIJ;EACE;;;AAIJ;EACE;;AACA;EACE;;AAEF;EACE;EACA;EACA;EACA;EACA;EACA;;AAEF;EACE,kBApDyB;EAqDzB;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EAEE;;AAGF;EACE;;AAGJ;EACE;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;;AAIA;EACE;EACA;;AAEF;EACE;EACA;EACA;EACA;;;AAOJ;AAAA;EACE;;AAEF;AAAA;EACE;EACA;EACA;EACA;EACA;EACA,aA5HoB;EA6HpB;EACA;EACA,kBA9HiB;EA+HjB,iBAjIuB;EAkIvB,OAlIuB;EAmIvB;EACA;EACA;;AAEA;AAAA;AAAA;EAEE;;;AAKN;EACE;EACA;EACA;EACA,kBA1JiB;EA2JjB;EACA;EACA,eA/JsB;EAgKtB,WAnKqB;EAoKrB;EACA;;AAEA;EAEE;;AAGF;EACE;;AAGF;EACE;;;AAIJ;EACE;EACA;EACA;;AAOF;EACE;EACA;EACA;;AAEA;EACE;EACA;;AAEF;EACE;;;AAIJ;EACE;;AACA;EACE;EACA;EACA,eA9MyB;EA+MzB;EACA,WAnNmB;EAoNnB;EACA;EACA;EACA,kBA9MoB;EA+MpB;EACA;EACA;EACA;;AAEA;EACE;;AAGF;EACE;EACA;;AAGF;EACE;EACA;;AAGF;EACE;EACA;;;AAKN;EACE;EACA,SApOgB;EAqOhB;EACA;EACA,kBAjP0B;EAkP1B;EACA;EACA;EACA,2BAzPsB;EA0PtB,4BA1PsB;EA2PtB;EACA;EACA;;AAEA;EACE;;AAGF;EACE;;AAGF;EACE;EACA;EACA;EACA;EACA;;AAEF;EACE;EACA;EACA;EACA;EACA;;AAEF;EACE;EACA;EACA,WA3RmB;;AA6RnB;EACE;;AAIF;EADF;IAEI;;EAEA;IACE;IACA,WAtSe;IAuSf;IACA;IACA;IACA;IACA;;EAGF;IACE;IACA;IACA;;EAEA;IACE;IACA;;;AAKN;EACE;;AAEA;EACE;;;AAUR;EACE;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;EACA,WAxVqB;EAyVrB;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;;AAIJ;EACE;EACA;EACA,kBA3WiB;EA4WjB,WAjXqB;EAkXrB;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAGF;EAIE;;AAGF;EAEE;EACA;EACA;;AAGF;EACE;EACA;;;AAIJ;EACE;;;AAGF","file":"choices.css"}
|
2
public/assets/styles/choices.min.css
vendored
|
@ -1,231 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no">
|
||||
<title>Choices</title>
|
||||
<meta name=description itemprop=description content="A lightweight, configurable select box/text input plugin. Similar to Select2 and Selectize but without the jQuery dependency.">
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="../assets/images/apple-touch-icon.png">
|
||||
<link rel="icon" type="image/png" href="../assets/images/favicon-32x32.png" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="../assets/images/favicon-16x16.png" sizes="16x16">
|
||||
<link rel="manifest" href="../assets/images/manifest.json">
|
||||
<link rel="mask-icon" href="../assets/images/safari-pinned-tab.svg" color="#00bcd4">
|
||||
<link rel="shortcut icon" href="../assets/images/favicon.ico">
|
||||
<meta name="msapplication-config" content="../assets/images/browserconfig.xml">
|
||||
<meta name="theme-color" content="#ffffff">
|
||||
|
||||
<!-- Ignore these -->
|
||||
<link rel="stylesheet" href="../assets/styles/base.min.css?version=3.0.2">
|
||||
<!-- End ignore these -->
|
||||
|
||||
<!-- Choices includes -->
|
||||
<link rel="stylesheet" href="../assets/styles/choices.min.css?version=3.0.2">
|
||||
<script src="../assets/scripts/choices.min.js?version=2.8.8"></script>
|
||||
<!-- End Choices includes -->
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="section">
|
||||
<h2>Select multiple inputs</h2>
|
||||
<div data-test-hook="basic">
|
||||
<label for="choices-basic">Basic</label>
|
||||
<select class="form-control" name="choices-basic" id="choices-basic" multiple>
|
||||
<option value="Choice 1">Choice 1</option>
|
||||
<option value="Choice 2">Choice 2</option>
|
||||
<option value="Find me">Choice 3</option>
|
||||
<option value="Choice 4">Choice 4</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="remove-button">
|
||||
<label for="choices-remove-button">Remove button</label>
|
||||
<select class="form-control" name="choices-remove-button" id="choices-remove-button" multiple>
|
||||
<option value="Choice 1">Choice 1</option>
|
||||
<option value="Choice 2">Choice 2</option>
|
||||
<option value="Choice 3">Choice 3</option>
|
||||
<option value="Choice 4">Choice 4</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="disabled-choice">
|
||||
<label for="choices-disabled-choice">Disabled choice</label>
|
||||
<select class="form-control" name="choices-disabled-choice" id="choices-disabled-choice" multiple>
|
||||
<option value="Choice 1">Choice 1</option>
|
||||
<option value="Choice 2">Choice 2</option>
|
||||
<option value="Choice 3">Choice 3</option>
|
||||
<option value="Choice 4" disabled>Choice 4</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="add-items-disabled">
|
||||
<label for="choices-add-items-disabled">Add items disabled</label>
|
||||
<select class="form-control" name="choices-add-items-disabled" id="choices-add-items-disabled" multiple>
|
||||
<option value="Choice 1" selected>Choice 1</option>
|
||||
<option value="Choice 2">Choice 2</option>
|
||||
<option value="Choice 3">Choice 3</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="disabled-via-attr">
|
||||
<label for="choices-disabled-via-attr">Disabled via attribute</label>
|
||||
<select class="form-control" name="choices-disabled-via-attr" id="choices-disabled-via-attr" multiple disabled>
|
||||
<option value="Choice 1" selected>Choice 1</option>
|
||||
<option value="Choice 2">Choice 2</option>
|
||||
<option value="Choice 3">Choice 3</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="selection-limit">
|
||||
<label for="choices-selection-limit">Input limit</label>
|
||||
<select class="form-control" name="choices-selection-limit" id="choices-selection-limit" multiple>
|
||||
<option value="Choice 1">Choice 1</option>
|
||||
<option value="Choice 2">Choice 2</option>
|
||||
<option value="Choice 3">Choice 3</option>
|
||||
<option value="Choice 4">Choice 4</option>
|
||||
<option value="Choice 5">Choice 5</option>
|
||||
<option value="Choice 6">Choice 6</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="prepend-append">
|
||||
<label for="choices-prepend-append">Prepend/append</label>
|
||||
<select class="form-control" name="choices-prepend-append" id="choices-prepend-append" multiple>
|
||||
<option value="Choice 1">Choice 1</option>
|
||||
<option value="Choice 2">Choice 2</option>
|
||||
<option value="Choice 3">Choice 3</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="render-choice-limit">
|
||||
<label for="choices-render-choice-limit">Render choice limit</label>
|
||||
<select class="form-control" name="choices-render-choice-limit" id="choices-render-choice-limit" multiple>
|
||||
<option value="Choice 1">Choice 1</option>
|
||||
<option value="Choice 2">Choice 2</option>
|
||||
<option value="Choice 3">Choice 3</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="search-floor">
|
||||
<label for="choices-search-floor">Search floor</label>
|
||||
<select class="form-control" name="choices-search-floor" id="choices-search-floor" multiple>
|
||||
<option value="Choice 1">Choice 1</option>
|
||||
<option value="Choice 2">Choice 2</option>
|
||||
<option value="Choice 3">Choice 3</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="placeholder">
|
||||
<label for="choices-placeholder">Placeholder</label>
|
||||
<select class="form-control" name="choices-placeholder" id="choices-placeholder" multiple>
|
||||
<option value="Choice 1">Choice 1</option>
|
||||
<option value="Choice 2">Choice 2</option>
|
||||
<option value="Choice 3">Choice 3</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="remote-data">
|
||||
<label for="choices-remote-data">Remote data</label>
|
||||
<select class="form-control" name="choices-remote-data" id="choices-remote-data" multiple></select>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="scrolling-dropdown">
|
||||
<label for="choices-scrolling-dropdown">Scrolling dropdown</label>
|
||||
<select class="form-control" name="choices-scrolling-dropdown" id="choices-scrolling-dropdown" multiple>
|
||||
<option value="Choice 1">Choice 1</option>
|
||||
<option value="Choice 2">Choice 2</option>
|
||||
<option value="Choice 3">Choice 3</option>
|
||||
<option value="Choice 4">Choice 4</option>
|
||||
<option value="Choice 5">Choice 5</option>
|
||||
<option value="Choice 6">Choice 6</option>
|
||||
<option value="Choice 7">Choice 7</option>
|
||||
<option value="Choice 8">Choice 8</option>
|
||||
<option value="Choice 9">Choice 9</option>
|
||||
<option value="Choice 10">Choice 10</option>
|
||||
<option value="Choice 11">Choice 11</option>
|
||||
<option value="Choice 12">Choice 12</option>
|
||||
<option value="Choice 13">Choice 13</option>
|
||||
<option value="Choice 14">Choice 14</option>
|
||||
<option value="Choice 15">Choice 15</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="groups">
|
||||
<label for="choices-groups">Choice groups</label>
|
||||
<select class="form-control" name="choices-groups" id="choices-groups" multiple>
|
||||
<optgroup label="UK">
|
||||
<option value="London">London</option>
|
||||
<option value="Manchester">Manchester</option>
|
||||
<option value="Liverpool">Liverpool</option>
|
||||
</optgroup>
|
||||
<optgroup label="FR">
|
||||
<option value="Paris">Paris</option>
|
||||
<option value="Lyon">Lyon</option>
|
||||
<option value="Marseille">Marseille</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
new Choices('#choices-basic');
|
||||
|
||||
new Choices('#choices-remove-button', {
|
||||
removeItemButton: true,
|
||||
});
|
||||
|
||||
new Choices('#choices-disabled-choice');
|
||||
|
||||
new Choices('#choices-add-items-disabled', {
|
||||
addItems: false,
|
||||
});
|
||||
|
||||
new Choices('#choices-disabled-via-attr');
|
||||
|
||||
new Choices('#choices-selection-limit', {
|
||||
maxItemCount: 5,
|
||||
});
|
||||
|
||||
new Choices('#choices-prepend-append', {
|
||||
prependValue: 'before-',
|
||||
appendValue: '-after',
|
||||
});
|
||||
|
||||
new Choices('#choices-render-choice-limit', {
|
||||
renderChoiceLimit: 1,
|
||||
});
|
||||
|
||||
new Choices('#choices-search-floor', {
|
||||
searchFloor: 5,
|
||||
});
|
||||
|
||||
new Choices('#choices-placeholder', {
|
||||
placeholder: true,
|
||||
placeholderValue: 'I am a placeholder',
|
||||
});
|
||||
|
||||
new Choices('#choices-remote-data', {
|
||||
shouldSort: false,
|
||||
}).ajax((callback) => {
|
||||
fetch('/data')
|
||||
.then((response) => {
|
||||
response.json().then((data) => {
|
||||
callback(data, 'value', 'label');
|
||||
});
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
});
|
||||
});
|
||||
|
||||
new Choices('#choices-scrolling-dropdown', {
|
||||
shouldSort: false,
|
||||
});
|
||||
|
||||
new Choices('#choices-groups');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
628
public/test/select-multiple/index.html
Normal file
|
@ -0,0 +1,628 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width,initial-scale=1,user-scalable=no"
|
||||
/>
|
||||
<title>Choices</title>
|
||||
<meta
|
||||
name="description"
|
||||
itemprop="description"
|
||||
content="A lightweight, configurable select box/text input plugin. Similar to Select2 and Selectize but without the jQuery dependency."
|
||||
/>
|
||||
<link
|
||||
rel="apple-touch-icon"
|
||||
sizes="180x180"
|
||||
href="../../assets/images/apple-touch-icon.png"
|
||||
/>
|
||||
<link
|
||||
rel="icon"
|
||||
type="image/png"
|
||||
href="../../assets/images/favicon-32x32.png"
|
||||
sizes="32x32"
|
||||
/>
|
||||
<link
|
||||
rel="icon"
|
||||
type="image/png"
|
||||
href="../../assets/images/favicon-16x16.png"
|
||||
sizes="16x16"
|
||||
/>
|
||||
<link rel="manifest" href="../../assets/images/manifest.json" />
|
||||
<link
|
||||
rel="mask-icon"
|
||||
href="../../assets/images/safari-pinned-tab.svg"
|
||||
color="#00bcd4"
|
||||
/>
|
||||
<link rel="shortcut icon" href="../../assets/images/favicon.ico" />
|
||||
<meta
|
||||
name="msapplication-config"
|
||||
content="../../assets/images/browserconfig.xml"
|
||||
/>
|
||||
<meta name="theme-color" content="#ffffff" />
|
||||
|
||||
<!-- Ignore these -->
|
||||
<link rel="stylesheet" href="../../assets/styles/base.min.css" />
|
||||
<!-- End ignore these -->
|
||||
|
||||
<!-- Choices includes -->
|
||||
<link rel="stylesheet" href="../../assets/styles/choices.min.css" />
|
||||
<script src="../../assets/scripts/choices.min.js"></script>
|
||||
<!-- End Choices includes -->
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="section">
|
||||
<h2>Select multiple inputs</h2>
|
||||
<div data-test-hook="basic">
|
||||
<label for="choices-basic">Basic</label>
|
||||
<button class="disable push-bottom">Disable</button>
|
||||
<button class="enable push-bottom">Enable</button>
|
||||
<select
|
||||
class="form-control"
|
||||
name="choices-basic"
|
||||
id="choices-basic"
|
||||
multiple
|
||||
>
|
||||
<option value="Choice 1">Choice 1</option>
|
||||
<option value="Choice 2">Choice 2</option>
|
||||
<option value="Find me">Choice 3</option>
|
||||
<option value="Choice 4">Choice 4</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="remove-button">
|
||||
<label for="choices-remove-button">Remove button</label>
|
||||
<select
|
||||
class="form-control"
|
||||
name="choices-remove-button"
|
||||
id="choices-remove-button"
|
||||
multiple
|
||||
>
|
||||
<option value="Choice 1">Choice 1</option>
|
||||
<option value="Choice 2">Choice 2</option>
|
||||
<option value="Choice 3">Choice 3</option>
|
||||
<option value="Choice 4">Choice 4</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="disabled-choice">
|
||||
<label for="choices-disabled-choice">Disabled choice</label>
|
||||
<select
|
||||
class="form-control"
|
||||
name="choices-disabled-choice"
|
||||
id="choices-disabled-choice"
|
||||
multiple
|
||||
>
|
||||
<option value="Choice 1">Choice 1</option>
|
||||
<option value="Choice 2">Choice 2</option>
|
||||
<option value="Choice 3">Choice 3</option>
|
||||
<option value="Choice 4" disabled>Choice 4</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="add-items-disabled">
|
||||
<label for="choices-add-items-disabled">Add items disabled</label>
|
||||
<select
|
||||
class="form-control"
|
||||
name="choices-add-items-disabled"
|
||||
id="choices-add-items-disabled"
|
||||
multiple
|
||||
>
|
||||
<option value="Choice 1" selected>Choice 1</option>
|
||||
<option value="Choice 2">Choice 2</option>
|
||||
<option value="Choice 3">Choice 3</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="disabled-via-attr">
|
||||
<label for="choices-disabled-via-attr">Disabled via attribute</label>
|
||||
<select
|
||||
class="form-control"
|
||||
name="choices-disabled-via-attr"
|
||||
id="choices-disabled-via-attr"
|
||||
multiple
|
||||
disabled
|
||||
>
|
||||
<option value="Choice 1" selected>Choice 1</option>
|
||||
<option value="Choice 2">Choice 2</option>
|
||||
<option value="Choice 3">Choice 3</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="selection-limit">
|
||||
<label for="choices-selection-limit">Input limit</label>
|
||||
<select
|
||||
class="form-control"
|
||||
name="choices-selection-limit"
|
||||
id="choices-selection-limit"
|
||||
multiple
|
||||
>
|
||||
<option value="Choice 1">Choice 1</option>
|
||||
<option value="Choice 2">Choice 2</option>
|
||||
<option value="Choice 3">Choice 3</option>
|
||||
<option value="Choice 4">Choice 4</option>
|
||||
<option value="Choice 5">Choice 5</option>
|
||||
<option value="Choice 6">Choice 6</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="prepend-append">
|
||||
<label for="choices-prepend-append">Prepend/append</label>
|
||||
<select
|
||||
class="form-control"
|
||||
name="choices-prepend-append"
|
||||
id="choices-prepend-append"
|
||||
multiple
|
||||
>
|
||||
<option value="Choice 1">Choice 1</option>
|
||||
<option value="Choice 2">Choice 2</option>
|
||||
<option value="Choice 3">Choice 3</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="render-choice-limit">
|
||||
<label for="choices-render-choice-limit">Render choice limit</label>
|
||||
<select
|
||||
class="form-control"
|
||||
name="choices-render-choice-limit"
|
||||
id="choices-render-choice-limit"
|
||||
multiple
|
||||
>
|
||||
<option value="Choice 1">Choice 1</option>
|
||||
<option value="Choice 2">Choice 2</option>
|
||||
<option value="Choice 3">Choice 3</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="search-floor">
|
||||
<label for="choices-search-floor">Search floor</label>
|
||||
<select
|
||||
class="form-control"
|
||||
name="choices-search-floor"
|
||||
id="choices-search-floor"
|
||||
multiple
|
||||
>
|
||||
<option value="Choice 1">Choice 1</option>
|
||||
<option value="Choice 2">Choice 2</option>
|
||||
<option value="Choice 3">Choice 3</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="placeholder-via-option-value">
|
||||
<label for="choices-placeholder-via-option-value"
|
||||
>Placeholder via empty option value</label
|
||||
>
|
||||
<select
|
||||
class="form-control"
|
||||
name="choices-placeholder-via-option-value"
|
||||
id="choices-placeholder-via-option-value"
|
||||
multiple
|
||||
>
|
||||
<option value="">I am a placeholder</option>
|
||||
<option value="Choice 1">Choice 1</option>
|
||||
<option value="Choice 2">Choice 2</option>
|
||||
<option value="Choice 3">Choice 3</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="placeholder-via-option-attr">
|
||||
<label for="choices-placeholder-via-option-attr"
|
||||
>Placeholder via option attribute</label
|
||||
>
|
||||
<select
|
||||
class="form-control"
|
||||
name="choices-placeholder-via-option-attr"
|
||||
id="choices-placeholder-via-option-attr"
|
||||
multiple
|
||||
>
|
||||
<option placeholder>I am a placeholder</option>
|
||||
<option value="Choice 1">Choice 1</option>
|
||||
<option value="Choice 2">Choice 2</option>
|
||||
<option value="Choice 3">Choice 3</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="remote-data">
|
||||
<label for="choices-remote-data">Remote data</label>
|
||||
<select
|
||||
class="form-control"
|
||||
name="choices-remote-data"
|
||||
id="choices-remote-data"
|
||||
multiple
|
||||
>
|
||||
<option value="">I am a placeholder</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="scrolling-dropdown">
|
||||
<label for="choices-scrolling-dropdown">Scrolling dropdown</label>
|
||||
<select
|
||||
class="form-control"
|
||||
name="choices-scrolling-dropdown"
|
||||
id="choices-scrolling-dropdown"
|
||||
multiple
|
||||
>
|
||||
<option value="Choice 1">Choice 1</option>
|
||||
<option value="Choice 2">Choice 2</option>
|
||||
<option value="Choice 3">Choice 3</option>
|
||||
<option value="Choice 4">Choice 4</option>
|
||||
<option value="Choice 5">Choice 5</option>
|
||||
<option value="Choice 6">Choice 6</option>
|
||||
<option value="Choice 7">Choice 7</option>
|
||||
<option value="Choice 8">Choice 8</option>
|
||||
<option value="Choice 9">Choice 9</option>
|
||||
<option value="Choice 10">Choice 10</option>
|
||||
<option value="Choice 11">Choice 11</option>
|
||||
<option value="Choice 12">Choice 12</option>
|
||||
<option value="Choice 13">Choice 13</option>
|
||||
<option value="Choice 14">Choice 14</option>
|
||||
<option value="Choice 15">Choice 15</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="groups">
|
||||
<label for="choices-groups">Choice groups</label>
|
||||
<select
|
||||
class="form-control"
|
||||
name="choices-groups"
|
||||
id="choices-groups"
|
||||
multiple
|
||||
>
|
||||
<optgroup label="UK">
|
||||
<option value="London">London</option>
|
||||
<option value="Manchester">Manchester</option>
|
||||
<option value="Liverpool">Liverpool</option>
|
||||
</optgroup>
|
||||
<optgroup label="FR">
|
||||
<option value="Paris">Paris</option>
|
||||
<option value="Lyon">Lyon</option>
|
||||
<option value="Marseille">Marseille</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="custom-properties">
|
||||
<label for="choices-custom-properties">Custom properties</label>
|
||||
<select
|
||||
class="form-control"
|
||||
name="choices-custom-properties"
|
||||
id="choices-custom-properties"
|
||||
multiple
|
||||
></select>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="custom-properties-html">
|
||||
<label for="choices-custom-properties-html">Custom properties</label>
|
||||
<select
|
||||
class="form-control"
|
||||
name="choices-custom-properties-html"
|
||||
id="choices-custom-properties-html"
|
||||
>
|
||||
<option value="Dropdown item 1">Label One</option>
|
||||
<option value="Dropdown item 2">Label Two</option>
|
||||
<option
|
||||
value="Dropdown item 3"
|
||||
data-custom-properties="This option is fantastic"
|
||||
>Label Three</option
|
||||
>
|
||||
<option
|
||||
value="Dropdown item 4"
|
||||
data-custom-properties="{ 'description': 'foo' }"
|
||||
>Label Four</option
|
||||
>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="non-string-values">
|
||||
<label for="choices-non-string-values">Non-string values</label>
|
||||
<select
|
||||
class="form-control"
|
||||
name="choices-non-string-values"
|
||||
id="choices-non-string-values"
|
||||
></select>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="within-form">
|
||||
<form>
|
||||
<label for="choices-within-form">Within form</label>
|
||||
<select
|
||||
class="form-control"
|
||||
name="choices-within-form"
|
||||
id="choices-within-form"
|
||||
multiple
|
||||
>
|
||||
<option value="Choice 1">Choice 1</option>
|
||||
</select>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="set-choice-by-value">
|
||||
<label for="choices-set-choice-by-value"
|
||||
>Dynamically set choice by value</label
|
||||
>
|
||||
<select
|
||||
class="form-control"
|
||||
name="choices-set-choice-by-value"
|
||||
id="choices-set-choice-by-value"
|
||||
multiple
|
||||
>
|
||||
<option value="Choice 1">Choice 1</option>
|
||||
<option value="Choice 2">Choice 2</option>
|
||||
<option value="Choice 3">Choice 3</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="search-by-label">
|
||||
<label for="choices-search-by-label">Search by label</label>
|
||||
<select
|
||||
class="form-control"
|
||||
name="choices-search-by-label"
|
||||
id="choices-search-by-label"
|
||||
multiple
|
||||
>
|
||||
<option value="value1">label1</option>
|
||||
<option value="value2">label2</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="allowhtml-undefined">
|
||||
<label for="choices-allowhtml-undefined">HTML allowed by default</label>
|
||||
<select
|
||||
class="form-control"
|
||||
name="choices-allowhtml-undefined"
|
||||
id="choices-allowhtml-undefined"
|
||||
multiple
|
||||
></select>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="allowhtml-true">
|
||||
<label for="choices-allowhtml-true">HTML allowed</label>
|
||||
<select
|
||||
class="form-control"
|
||||
name="choices-allowhtml-true"
|
||||
id="choices-allowhtml-true"
|
||||
multiple
|
||||
></select>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="allowhtml-false">
|
||||
<label for="choices-allowhtml-false">HTML disabled</label>
|
||||
<select
|
||||
class="form-control"
|
||||
name="choices-allowhtml-false"
|
||||
id="choices-allowhtml-false"
|
||||
multiple
|
||||
></select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const choicesBasic = new Choices('#choices-basic', {
|
||||
allowHTML: true,
|
||||
});
|
||||
|
||||
document
|
||||
.querySelector('button.disable')
|
||||
.addEventListener('click', () => {
|
||||
choicesBasic.disable();
|
||||
});
|
||||
|
||||
document
|
||||
.querySelector('button.enable')
|
||||
.addEventListener('click', () => {
|
||||
choicesBasic.enable();
|
||||
});
|
||||
|
||||
new Choices('#choices-remove-button', {
|
||||
allowHTML: true,
|
||||
removeItemButton: true,
|
||||
});
|
||||
|
||||
new Choices('#choices-disabled-choice', {
|
||||
allowHTML: true,
|
||||
});
|
||||
|
||||
new Choices('#choices-add-items-disabled', {
|
||||
allowHTML: true,
|
||||
addItems: false,
|
||||
});
|
||||
|
||||
new Choices('#choices-disabled-via-attr', {
|
||||
allowHTML: true,
|
||||
});
|
||||
|
||||
new Choices('#choices-selection-limit', {
|
||||
allowHTML: true,
|
||||
maxItemCount: 5,
|
||||
});
|
||||
|
||||
new Choices('#choices-prepend-append', {
|
||||
allowHTML: true,
|
||||
prependValue: 'before-',
|
||||
appendValue: '-after',
|
||||
});
|
||||
|
||||
new Choices('#choices-render-choice-limit', {
|
||||
allowHTML: true,
|
||||
renderChoiceLimit: 1,
|
||||
});
|
||||
|
||||
new Choices('#choices-search-floor', {
|
||||
allowHTML: true,
|
||||
searchFloor: 5,
|
||||
});
|
||||
|
||||
new Choices('#choices-placeholder-via-option-value', {
|
||||
allowHTML: true,
|
||||
});
|
||||
|
||||
new Choices('#choices-placeholder-via-option-attr', {
|
||||
allowHTML: true,
|
||||
});
|
||||
|
||||
new Choices('#choices-remote-data', {
|
||||
allowHTML: true,
|
||||
shouldSort: false,
|
||||
}).setChoices(async () => {
|
||||
const data = await fetch('/data');
|
||||
return data.json();
|
||||
});
|
||||
|
||||
new Choices('#choices-scrolling-dropdown', {
|
||||
allowHTML: true,
|
||||
shouldSort: false,
|
||||
});
|
||||
|
||||
new Choices('#choices-groups', {
|
||||
allowHTML: true,
|
||||
});
|
||||
|
||||
new Choices('#choices-custom-properties', {
|
||||
allowHTML: true,
|
||||
searchFields: ['label', 'value', 'customProperties.country'],
|
||||
choices: [
|
||||
{
|
||||
id: 1,
|
||||
value: 'London',
|
||||
label: 'London',
|
||||
customProperties: {
|
||||
country: 'United Kingdom',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
value: 'Berlin',
|
||||
label: 'Berlin',
|
||||
customProperties: {
|
||||
country: 'Germany',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
value: 'Lisbon',
|
||||
label: 'Lisbon',
|
||||
customProperties: {
|
||||
country: 'Portugal',
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
new Choices('#choices-custom-properties-html', {
|
||||
allowHTML: true,
|
||||
searchFields: ['label', 'value', 'customProperties'],
|
||||
});
|
||||
|
||||
new Choices('#choices-non-string-values', {
|
||||
allowHTML: true,
|
||||
choices: [
|
||||
{
|
||||
id: 1,
|
||||
label: 'Number',
|
||||
value: 1,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
label: 'Boolean',
|
||||
value: true,
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
label: 'Object',
|
||||
value: {
|
||||
test: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
label: 'Array',
|
||||
value: ['test'],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
new Choices('#choices-within-form', {
|
||||
allowHTML: true,
|
||||
});
|
||||
|
||||
new Choices('#choices-set-choice-by-value', {
|
||||
allowHTML: true,
|
||||
}).setChoiceByValue('Choice 2');
|
||||
|
||||
new Choices('#choices-search-by-label', {
|
||||
allowHTML: true,
|
||||
searchFields: ['label']
|
||||
});
|
||||
|
||||
new Choices('#choices-allowhtml-undefined', {
|
||||
choices: [
|
||||
{
|
||||
id: 1,
|
||||
label: '<b>Choice 1</b>',
|
||||
value: 'Choice 1',
|
||||
selected: true
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
label: '<b>Choice 2</b>',
|
||||
value: 'Choice 2',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
label: 'Choice 3',
|
||||
value: 'Choice 3',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
new Choices('#choices-allowhtml-true', {
|
||||
allowHTML: true,
|
||||
choices: [
|
||||
{
|
||||
id: 1,
|
||||
label: '<b>Choice 1</b>',
|
||||
value: 'Choice 1',
|
||||
selected: true
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
label: '<b>Choice 2</b>',
|
||||
value: 'Choice 2',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
label: 'Choice 3',
|
||||
value: 'Choice 3',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
new Choices('#choices-allowhtml-false', {
|
||||
allowHTML: false,
|
||||
choices: [
|
||||
{
|
||||
id: 1,
|
||||
label: '<b>Choice 1</b>',
|
||||
value: 'Choice 1',
|
||||
selected: true
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
label: '<b>Choice 2</b>',
|
||||
value: 'Choice 2',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
label: 'Choice 3',
|
||||
value: 'Choice 3',
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,243 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no">
|
||||
<title>Choices</title>
|
||||
<meta name=description itemprop=description content="A lightweight, configurable select box/text input plugin. Similar to Select2 and Selectize but without the jQuery dependency.">
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="../assets/images/apple-touch-icon.png">
|
||||
<link rel="icon" type="image/png" href="../assets/images/favicon-32x32.png" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="../assets/images/favicon-16x16.png" sizes="16x16">
|
||||
<link rel="manifest" href="../assets/images/manifest.json">
|
||||
<link rel="mask-icon" href="../assets/images/safari-pinned-tab.svg" color="#00bcd4">
|
||||
<link rel="shortcut icon" href="../assets/images/favicon.ico">
|
||||
<meta name="msapplication-config" content="../assets/images/browserconfig.xml">
|
||||
<meta name="theme-color" content="#ffffff">
|
||||
|
||||
<!-- Ignore these -->
|
||||
<link rel="stylesheet" href="../assets/styles/base.min.css?version=3.0.2">
|
||||
<!-- End ignore these -->
|
||||
|
||||
<!-- Choices includes -->
|
||||
<link rel="stylesheet" href="../assets/styles/choices.min.css?version=3.0.2">
|
||||
<script src="../assets/scripts/choices.min.js?version=2.8.8"></script>
|
||||
<!-- End Choices includes -->
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="section">
|
||||
<h2>Select one inputs</h2>
|
||||
<div data-test-hook="basic">
|
||||
<label for="choices-basic">Basic</label>
|
||||
<select class="form-control" name="choices-basic" id="choices-basic">
|
||||
<option value="Choice 1">Choice 1</option>
|
||||
<option value="Choice 2">Choice 2</option>
|
||||
<option value="Find me">Choice 3</option>
|
||||
<option value="Choice 4">Choice 4</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="remove-button">
|
||||
<label for="choices-remove-button">Remove button</label>
|
||||
<select class="form-control" name="choices-remove-button" id="choices-remove-button">
|
||||
<option value="Choice 1">Choice 1</option>
|
||||
<option value="Choice 2">Choice 2</option>
|
||||
<option value="Choice 3">Choice 3</option>
|
||||
<option value="Choice 4">Choice 4</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="disabled-choice">
|
||||
<label for="choices-disabled-choice">Disabled choice</label>
|
||||
<select class="form-control" name="choices-disabled-choice" id="choices-disabled-choice">
|
||||
<option value="Choice 1">Choice 1</option>
|
||||
<option value="Choice 2">Choice 2</option>
|
||||
<option value="Choice 3">Choice 3</option>
|
||||
<option value="Choice 4" disabled>Choice 4</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="add-items-disabled">
|
||||
<label for="choices-add-items-disabled">Add items disabled</label>
|
||||
<select class="form-control" name="choices-add-items-disabled" id="choices-add-items-disabled">
|
||||
<option value="Choice 1" selected>Choice 1</option>
|
||||
<option value="Choice 2">Choice 2</option>
|
||||
<option value="Choice 3">Choice 3</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="disabled-via-attr">
|
||||
<label for="choices-disabled-via-attr">Disabled via attribute</label>
|
||||
<select class="form-control" name="choices-disabled-via-attr" id="choices-disabled-via-attr" disabled>
|
||||
<option value="Choice 1" selected>Choice 1</option>
|
||||
<option value="Choice 2">Choice 2</option>
|
||||
<option value="Choice 3">Choice 3</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="prepend-append">
|
||||
<label for="choices-prepend-append">Prepend/append</label>
|
||||
<select class="form-control" name="choices-prepend-append" id="choices-prepend-append">
|
||||
<option value="Choice 1">Choice 1</option>
|
||||
<option value="Choice 2">Choice 2</option>
|
||||
<option value="Choice 3">Choice 3</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="render-choice-limit">
|
||||
<label for="choices-render-choice-limit">Render choice limit</label>
|
||||
<select class="form-control" name="choices-render-choice-limit" id="choices-render-choice-limit">
|
||||
<option value="Choice 1">Choice 1</option>
|
||||
<option value="Choice 2">Choice 2</option>
|
||||
<option value="Choice 3">Choice 3</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="search-disabled">
|
||||
<label for="choices-search-disabled">Search disabled</label>
|
||||
<select class="form-control" name="choices-search-disabled" id="choices-search-disabled">
|
||||
<option value="Choice 1">Choice 1</option>
|
||||
<option value="Choice 2">Choice 2</option>
|
||||
<option value="Choice 3">Choice 3</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="search-floor">
|
||||
<label for="choices-search-floor">Search floor</label>
|
||||
<select class="form-control" name="choices-search-floor" id="choices-search-floor">
|
||||
<option value="Choice 1">Choice 1</option>
|
||||
<option value="Choice 2">Choice 2</option>
|
||||
<option value="Choice 3">Choice 3</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="remote-data">
|
||||
<label for="choices-remote-data">Remote data</label>
|
||||
<select class="form-control" name="choices-remote-data" id="choices-remote-data"></select>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="scrolling-dropdown">
|
||||
<label for="choices-scrolling-dropdown">Scrolling dropdown</label>
|
||||
<select class="form-control" name="choices-scrolling-dropdown" id="choices-scrolling-dropdown">
|
||||
<option value="Choice 1">Choice 1</option>
|
||||
<option value="Choice 2">Choice 2</option>
|
||||
<option value="Choice 3">Choice 3</option>
|
||||
<option value="Choice 4">Choice 4</option>
|
||||
<option value="Choice 5">Choice 5</option>
|
||||
<option value="Choice 6">Choice 6</option>
|
||||
<option value="Choice 7">Choice 7</option>
|
||||
<option value="Choice 8">Choice 8</option>
|
||||
<option value="Choice 9">Choice 9</option>
|
||||
<option value="Choice 10">Choice 10</option>
|
||||
<option value="Choice 11">Choice 11</option>
|
||||
<option value="Choice 12">Choice 12</option>
|
||||
<option value="Choice 13">Choice 13</option>
|
||||
<option value="Choice 14">Choice 14</option>
|
||||
<option value="Choice 15">Choice 15</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="groups">
|
||||
<label for="choices-groups">Choice groups</label>
|
||||
<select class="form-control" name="choices-groups" id="choices-groups" multiple>
|
||||
<optgroup label="UK">
|
||||
<option value="London">London</option>
|
||||
<option value="Manchester">Manchester</option>
|
||||
<option value="Liverpool">Liverpool</option>
|
||||
</optgroup>
|
||||
<optgroup label="FR">
|
||||
<option value="Paris">Paris</option>
|
||||
<option value="Lyon">Lyon</option>
|
||||
<option value="Marseille">Marseille</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="parent-child">
|
||||
<label for="choices-parent">Parent</label>
|
||||
<select class="form-control" name="choices-parent" id="choices-parent">
|
||||
<option value="Parent choice 1">Parent choice 1</option>
|
||||
<option value="Parent choice 2">Parent choice 2</option>
|
||||
<option value="Parent choice 3">Parent choice 3</option>
|
||||
</select>
|
||||
|
||||
<label for="choices-child">Child</label>
|
||||
<select class="form-control" name="choices-child" id="choices-child">
|
||||
<option value="Child choice 1">Child choice 1</option>
|
||||
<option value="Child choice 2">Child choice 2</option>
|
||||
<option value="Child choice 3">Child choice 3</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
new Choices('#choices-basic');
|
||||
|
||||
new Choices('#choices-remove-button', {
|
||||
removeItemButton: true,
|
||||
});
|
||||
|
||||
new Choices('#choices-disabled-choice', {
|
||||
removeItemButton: true,
|
||||
});
|
||||
|
||||
new Choices('#choices-add-items-disabled', {
|
||||
addItems: false,
|
||||
});
|
||||
|
||||
new Choices('#choices-disabled-via-attr');
|
||||
|
||||
new Choices('#choices-prepend-append', {
|
||||
prependValue: 'before-',
|
||||
appendValue: '-after',
|
||||
});
|
||||
|
||||
new Choices('#choices-render-choice-limit', {
|
||||
renderChoiceLimit: 1
|
||||
});
|
||||
|
||||
new Choices('#choices-search-disabled', {
|
||||
searchEnabled: false
|
||||
})
|
||||
|
||||
new Choices('#choices-search-floor', {
|
||||
searchFloor: 5,
|
||||
});
|
||||
|
||||
new Choices('#choices-remote-data', {
|
||||
shouldSort: false,
|
||||
}).ajax((callback) => {
|
||||
fetch('/data')
|
||||
.then((response) => {
|
||||
response.json().then((data) => {
|
||||
callback(data, 'value', 'label');
|
||||
});
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
});
|
||||
});
|
||||
|
||||
new Choices('#choices-scrolling-dropdown', {
|
||||
shouldSort: false,
|
||||
});
|
||||
|
||||
new Choices('#choices-groups');
|
||||
|
||||
const parent = new Choices('#choices-parent');
|
||||
const child = new Choices('#choices-child').disable();
|
||||
|
||||
parent.passedElement.element.addEventListener('change', (event) => {
|
||||
if (event.detail.value === 'Parent choice 2') {
|
||||
child.enable();
|
||||
} else {
|
||||
child.disable();
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
682
public/test/select-one/index.html
Normal file
|
@ -0,0 +1,682 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width,initial-scale=1,user-scalable=no"
|
||||
/>
|
||||
<title>Choices</title>
|
||||
<meta
|
||||
name="description"
|
||||
itemprop="description"
|
||||
content="A lightweight, configurable select box/text input plugin. Similar to Select2 and Selectize but without the jQuery dependency."
|
||||
/>
|
||||
<link
|
||||
rel="apple-touch-icon"
|
||||
sizes="180x180"
|
||||
href="../../assets/images/apple-touch-icon.png"
|
||||
/>
|
||||
<link
|
||||
rel="icon"
|
||||
type="image/png"
|
||||
href="../../assets/images/favicon-32x32.png"
|
||||
sizes="32x32"
|
||||
/>
|
||||
<link
|
||||
rel="icon"
|
||||
type="image/png"
|
||||
href="../../assets/images/favicon-16x16.png"
|
||||
sizes="16x16"
|
||||
/>
|
||||
<link rel="manifest" href="../../assets/images/manifest.json" />
|
||||
<link
|
||||
rel="mask-icon"
|
||||
href="../../assets/images/safari-pinned-tab.svg"
|
||||
color="#00bcd4"
|
||||
/>
|
||||
<link rel="shortcut icon" href="../../assets/images/favicon.ico" />
|
||||
<meta
|
||||
name="msapplication-config"
|
||||
content="../../assets/images/browserconfig.xml"
|
||||
/>
|
||||
<meta name="theme-color" content="#ffffff" />
|
||||
|
||||
<!-- Ignore these -->
|
||||
<link rel="stylesheet" href="../../assets/styles/base.min.css" />
|
||||
<!-- End ignore these -->
|
||||
|
||||
<!-- Choices includes -->
|
||||
<link rel="stylesheet" href="../../assets/styles/choices.min.css" />
|
||||
<script src="../../assets/scripts/choices.min.js"></script>
|
||||
<!-- End Choices includes -->
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="section">
|
||||
<h2>Select one inputs</h2>
|
||||
<div data-test-hook="basic">
|
||||
<label for="choices-basic">Basic</label>
|
||||
<button class="disable push-bottom">Disable</button>
|
||||
<button class="enable push-bottom">Enable</button>
|
||||
<select class="form-control" name="choices-basic" id="choices-basic">
|
||||
<option value="Choice 1">Choice 1</option>
|
||||
<option value="Choice 2">Choice 2</option>
|
||||
<option value="Find me">Choice 3</option>
|
||||
<option value="Choice 4">Choice 4</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="remove-button">
|
||||
<label for="choices-remove-button">Remove button</label>
|
||||
<select
|
||||
class="form-control"
|
||||
name="choices-remove-button"
|
||||
id="choices-remove-button"
|
||||
>
|
||||
<option value="Choice 1">Choice 1</option>
|
||||
<option value="Choice 2">Choice 2</option>
|
||||
<option value="Choice 3">Choice 3</option>
|
||||
<option value="Choice 4">Choice 4</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="disabled-choice">
|
||||
<label for="choices-disabled-choice">Disabled choice</label>
|
||||
<select
|
||||
class="form-control"
|
||||
name="choices-disabled-choice"
|
||||
id="choices-disabled-choice"
|
||||
>
|
||||
<option value="Choice 1">Choice 1</option>
|
||||
<option value="Choice 2">Choice 2</option>
|
||||
<option value="Choice 3">Choice 3</option>
|
||||
<option value="Choice 4" disabled>Choice 4</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="disabled-first-choice-via-options">
|
||||
<label for="choices-disabled-choice-via-options"
|
||||
>Disabled first choice by options</label
|
||||
>
|
||||
<select
|
||||
class="form-control"
|
||||
name="choices-disabled-choice-via-options"
|
||||
id="choices-disabled-choice-via-options"
|
||||
>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="add-items-disabled">
|
||||
<label for="choices-add-items-disabled">Add items disabled</label>
|
||||
<select
|
||||
class="form-control"
|
||||
name="choices-add-items-disabled"
|
||||
id="choices-add-items-disabled"
|
||||
>
|
||||
<option value="Choice 1" selected>Choice 1</option>
|
||||
<option value="Choice 2">Choice 2</option>
|
||||
<option value="Choice 3">Choice 3</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="disabled-via-attr">
|
||||
<label for="choices-disabled-via-attr">Disabled via attribute</label>
|
||||
<select
|
||||
class="form-control"
|
||||
name="choices-disabled-via-attr"
|
||||
id="choices-disabled-via-attr"
|
||||
disabled
|
||||
>
|
||||
<option value="Choice 1" selected>Choice 1</option>
|
||||
<option value="Choice 2">Choice 2</option>
|
||||
<option value="Choice 3">Choice 3</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="prepend-append">
|
||||
<label for="choices-prepend-append">Prepend/append</label>
|
||||
<select
|
||||
class="form-control"
|
||||
name="choices-prepend-append"
|
||||
id="choices-prepend-append"
|
||||
>
|
||||
<option value="Choice 1">Choice 1</option>
|
||||
<option value="Choice 2">Choice 2</option>
|
||||
<option value="Choice 3">Choice 3</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="render-choice-limit">
|
||||
<label for="choices-render-choice-limit">Render choice limit</label>
|
||||
<select
|
||||
class="form-control"
|
||||
name="choices-render-choice-limit"
|
||||
id="choices-render-choice-limit"
|
||||
>
|
||||
<option value="Choice 1">Choice 1</option>
|
||||
<option value="Choice 2">Choice 2</option>
|
||||
<option value="Choice 3">Choice 3</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="search-disabled">
|
||||
<label for="choices-search-disabled">Search disabled</label>
|
||||
<select
|
||||
class="form-control"
|
||||
name="choices-search-disabled"
|
||||
id="choices-search-disabled"
|
||||
>
|
||||
<option value="Choice 1">Choice 1</option>
|
||||
<option value="Choice 2">Choice 2</option>
|
||||
<option value="Choice 3">Choice 3</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="search-floor">
|
||||
<label for="choices-search-floor">Search floor</label>
|
||||
<select
|
||||
class="form-control"
|
||||
name="choices-search-floor"
|
||||
id="choices-search-floor"
|
||||
>
|
||||
<option value="Choice 1">Choice 1</option>
|
||||
<option value="Choice 2">Choice 2</option>
|
||||
<option value="Choice 3">Choice 3</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="placeholder-via-option-value">
|
||||
<label for="choices-placeholder-via-option-value"
|
||||
>Placeholder via empty option value</label
|
||||
>
|
||||
<select
|
||||
class="form-control"
|
||||
name="choices-placeholder-via-option-value"
|
||||
id="choices-placeholder-via-option-value"
|
||||
>
|
||||
<option value="">I am a placeholder</option>
|
||||
<option value="Choice 1">Choice 1</option>
|
||||
<option value="Choice 2">Choice 2</option>
|
||||
<option value="Choice 3">Choice 3</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="placeholder-via-option-attr">
|
||||
<label for="choices-placeholder-via-option-attr"
|
||||
>Placeholder via option attribute</label
|
||||
>
|
||||
<select
|
||||
class="form-control"
|
||||
name="choices-placeholder-via-option-attr"
|
||||
id="choices-placeholder-via-option-attr"
|
||||
>
|
||||
<option placeholder>I am a placeholder</option>
|
||||
<option value="Choice 1">Choice 1</option>
|
||||
<option value="Choice 2">Choice 2</option>
|
||||
<option value="Choice 3">Choice 3</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="remote-data">
|
||||
<label for="choices-remote-data">Remote data</label>
|
||||
<select
|
||||
class="form-control"
|
||||
name="choices-remote-data"
|
||||
id="choices-remote-data"
|
||||
>
|
||||
<option value="">I am a placeholder</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="scrolling-dropdown">
|
||||
<label for="choices-scrolling-dropdown">Scrolling dropdown</label>
|
||||
<select
|
||||
class="form-control"
|
||||
name="choices-scrolling-dropdown"
|
||||
id="choices-scrolling-dropdown"
|
||||
>
|
||||
<option value="Choice 1">Choice 1</option>
|
||||
<option value="Choice 2">Choice 2</option>
|
||||
<option value="Choice 3">Choice 3</option>
|
||||
<option value="Choice 4">Choice 4</option>
|
||||
<option value="Choice 5">Choice 5</option>
|
||||
<option value="Choice 6">Choice 6</option>
|
||||
<option value="Choice 7">Choice 7</option>
|
||||
<option value="Choice 8">Choice 8</option>
|
||||
<option value="Choice 9">Choice 9</option>
|
||||
<option value="Choice 10">Choice 10</option>
|
||||
<option value="Choice 11">Choice 11</option>
|
||||
<option value="Choice 12">Choice 12</option>
|
||||
<option value="Choice 13">Choice 13</option>
|
||||
<option value="Choice 14">Choice 14</option>
|
||||
<option value="Choice 15">Choice 15</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="groups">
|
||||
<label for="choices-groups">Choice groups</label>
|
||||
<select
|
||||
class="form-control"
|
||||
name="choices-groups"
|
||||
id="choices-groups"
|
||||
multiple
|
||||
>
|
||||
<optgroup label="UK">
|
||||
<option value="London">London</option>
|
||||
<option value="Manchester">Manchester</option>
|
||||
<option value="Liverpool">Liverpool</option>
|
||||
</optgroup>
|
||||
<optgroup label="FR">
|
||||
<option value="Paris">Paris</option>
|
||||
<option value="Lyon">Lyon</option>
|
||||
<option value="Marseille">Marseille</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="parent-child">
|
||||
<label for="choices-parent">Parent</label>
|
||||
<select
|
||||
class="form-control"
|
||||
name="choices-parent"
|
||||
id="choices-parent"
|
||||
>
|
||||
<option value="Parent choice 1">Parent choice 1</option>
|
||||
<option value="Parent choice 2">Parent choice 2</option>
|
||||
<option value="Parent choice 3">Parent choice 3</option>
|
||||
</select>
|
||||
|
||||
<label for="choices-child">Child</label>
|
||||
<select class="form-control" name="choices-child" id="choices-child">
|
||||
<option value="Child choice 1">Child choice 1</option>
|
||||
<option value="Child choice 2">Child choice 2</option>
|
||||
<option value="Child choice 3">Child choice 3</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="custom-properties">
|
||||
<label for="choices-custom-properties">Custom properties</label>
|
||||
<select
|
||||
class="form-control"
|
||||
name="choices-custom-properties"
|
||||
id="choices-custom-properties"
|
||||
></select>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="custom-properties-html">
|
||||
<label for="choices-custom-properties-html">Custom properties</label>
|
||||
<select
|
||||
class="form-control"
|
||||
name="choices-custom-properties-html"
|
||||
id="choices-custom-properties-html"
|
||||
>
|
||||
<option value="Dropdown item 1">Label One</option>
|
||||
<option value="Dropdown item 2">Label Two</option>
|
||||
<option
|
||||
value="Dropdown item 3"
|
||||
data-custom-properties="This option is fantastic"
|
||||
>Label Three</option
|
||||
>
|
||||
<option
|
||||
value="Dropdown item 4"
|
||||
data-custom-properties="{ 'description': 'foo' }"
|
||||
>Label Four</option
|
||||
>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="non-string-values">
|
||||
<label for="choices-non-string-values">Non-string values</label>
|
||||
<select
|
||||
class="form-control"
|
||||
name="choices-non-string-values"
|
||||
id="choices-non-string-values"
|
||||
></select>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="within-form">
|
||||
<form>
|
||||
<label for="choices-within-form">Within form</label>
|
||||
<select
|
||||
class="form-control"
|
||||
name="choices-within-form"
|
||||
id="choices-within-form"
|
||||
>
|
||||
<option value="Choice 1">Choice 1</option>
|
||||
</select>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="set-choice-by-value">
|
||||
<label for="choices-set-choice-by-value"
|
||||
>Dynamically set choice by value</label
|
||||
>
|
||||
<select
|
||||
class="form-control"
|
||||
name="choices-set-choice-by-value"
|
||||
id="choices-set-choice-by-value"
|
||||
>
|
||||
<option value="Choice 1">Choice 1</option>
|
||||
<option value="Choice 2">Choice 2</option>
|
||||
<option value="Choice 3">Choice 3</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="search-by-label">
|
||||
<label for="choices-search-by-label">Search by label</label>
|
||||
<select
|
||||
class="form-control"
|
||||
name="choices-search-by-label"
|
||||
id="choices-search-by-label"
|
||||
>
|
||||
<option value="value1">label1</option>
|
||||
<option value="value2">label2</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="allowhtml-undefined">
|
||||
<label for="choices-allowhtml-undefined">HTML allowed by default</label>
|
||||
<select
|
||||
class="form-control"
|
||||
name="choices-allowhtml-undefined"
|
||||
id="choices-allowhtml-undefined"
|
||||
></select>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="allowhtml-true">
|
||||
<label for="choices-allowhtml-true">HTML allowed</label>
|
||||
<select
|
||||
class="form-control"
|
||||
name="choices-allowhtml-true"
|
||||
id="choices-allowhtml-true"
|
||||
></select>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="allowhtml-false">
|
||||
<label for="choices-allowhtml-false">HTML disabled</label>
|
||||
<select
|
||||
class="form-control"
|
||||
name="choices-allowhtml-false"
|
||||
id="choices-allowhtml-false"
|
||||
></select>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="new-destroy-init">
|
||||
<label for="choices-new-destroy-init">New, Destroy, Init</label>
|
||||
<select
|
||||
class="form-control"
|
||||
name="choices-new-destroy-init"
|
||||
id="choices-new-destroy-init"
|
||||
>
|
||||
<option value="Choice 1">Choice 1</option>
|
||||
<option value="Choice 2">Choice 2</option>
|
||||
<option value="Choice 3">Choice 3</option>
|
||||
</select>
|
||||
<button class="destroy">Destroy</button>
|
||||
<button class="init">Init</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const choicesBasic = new Choices('#choices-basic', {
|
||||
allowHTML: true,
|
||||
});
|
||||
|
||||
document
|
||||
.querySelector('button.disable')
|
||||
.addEventListener('click', () => {
|
||||
choicesBasic.disable();
|
||||
});
|
||||
|
||||
document
|
||||
.querySelector('button.enable')
|
||||
.addEventListener('click', () => {
|
||||
choicesBasic.enable();
|
||||
});
|
||||
|
||||
new Choices('#choices-remove-button', {
|
||||
allowHTML: true,
|
||||
removeItemButton: true,
|
||||
});
|
||||
|
||||
new Choices('#choices-disabled-choice', {
|
||||
allowHTML: true,
|
||||
removeItemButton: true,
|
||||
});
|
||||
|
||||
new Choices('#choices-disabled-choice-via-options', {
|
||||
allowHTML: true,
|
||||
removeItemButton: true,
|
||||
choices: [
|
||||
{
|
||||
value: 'Choice 1',
|
||||
label: 'Choice 1',
|
||||
disabled: true,
|
||||
},
|
||||
{
|
||||
value: 'Choice 2',
|
||||
label: 'Choice 2',
|
||||
},
|
||||
{
|
||||
value: 'Choice 3',
|
||||
label: 'Choice 3',
|
||||
},
|
||||
{
|
||||
value: 'Choice 4',
|
||||
label: 'Choice 4',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
new Choices('#choices-add-items-disabled', {
|
||||
allowHTML: true,
|
||||
addItems: false,
|
||||
});
|
||||
|
||||
new Choices('#choices-disabled-via-attr', {
|
||||
allowHTML: true,
|
||||
});
|
||||
|
||||
new Choices('#choices-prepend-append', {
|
||||
allowHTML: true,
|
||||
prependValue: 'before-',
|
||||
appendValue: '-after',
|
||||
});
|
||||
|
||||
new Choices('#choices-render-choice-limit', {
|
||||
allowHTML: true,
|
||||
renderChoiceLimit: 1,
|
||||
});
|
||||
|
||||
new Choices('#choices-search-disabled', {
|
||||
allowHTML: true,
|
||||
searchEnabled: false,
|
||||
});
|
||||
|
||||
new Choices('#choices-search-floor', {
|
||||
allowHTML: true,
|
||||
searchFloor: 5,
|
||||
});
|
||||
|
||||
new Choices('#choices-placeholder-via-option-value', {
|
||||
allowHTML: true,
|
||||
});
|
||||
|
||||
new Choices('#choices-placeholder-via-option-attr', {
|
||||
allowHTML: true,
|
||||
});
|
||||
|
||||
new Choices('#choices-remote-data', {
|
||||
allowHTML: true,
|
||||
shouldSort: false,
|
||||
}).setChoices(async () => {
|
||||
const res = await fetch('/data');
|
||||
return res.json();
|
||||
});
|
||||
|
||||
new Choices('#choices-scrolling-dropdown', {
|
||||
allowHTML: true,
|
||||
shouldSort: false,
|
||||
});
|
||||
|
||||
new Choices('#choices-groups', {
|
||||
allowHTML: true,
|
||||
});
|
||||
|
||||
const parent = new Choices('#choices-parent', {
|
||||
allowHTML: true,
|
||||
});
|
||||
const child = new Choices('#choices-child', {
|
||||
allowHTML: true,
|
||||
}).disable();
|
||||
|
||||
parent.passedElement.element.addEventListener('change', event => {
|
||||
if (event.detail.value === 'Parent choice 2') {
|
||||
child.enable();
|
||||
} else {
|
||||
child.disable();
|
||||
}
|
||||
});
|
||||
|
||||
new Choices('#choices-custom-properties', {
|
||||
allowHTML: true,
|
||||
searchFields: ['label', 'value', 'customProperties.country'],
|
||||
choices: [
|
||||
{
|
||||
id: 1,
|
||||
value: 'London',
|
||||
label: 'London',
|
||||
customProperties: {
|
||||
country: 'United Kingdom',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
value: 'Berlin',
|
||||
label: 'Berlin',
|
||||
customProperties: {
|
||||
country: 'Germany',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
value: 'Lisbon',
|
||||
label: 'Lisbon',
|
||||
customProperties: {
|
||||
country: 'Portugal',
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
new Choices('#choices-custom-properties-html', {
|
||||
allowHTML: true,
|
||||
searchFields: ['label', 'value', 'customProperties'],
|
||||
});
|
||||
|
||||
new Choices('#choices-non-string-values', {
|
||||
allowHTML: true,
|
||||
choices: [
|
||||
{
|
||||
id: 1,
|
||||
label: 'Number',
|
||||
value: 1,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
label: 'Boolean',
|
||||
value: true,
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
label: 'Object',
|
||||
value: {
|
||||
test: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
label: 'Array',
|
||||
value: ['test'],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
new Choices('#choices-within-form', {
|
||||
allowHTML: true,
|
||||
});
|
||||
|
||||
new Choices('#choices-set-choice-by-value', {
|
||||
allowHTML: true,
|
||||
}).setChoiceByValue('Choice 2');
|
||||
|
||||
new Choices('#choices-search-by-label', {
|
||||
allowHTML: true,
|
||||
searchFields: ['label']
|
||||
});
|
||||
|
||||
new Choices('#choices-allowhtml-undefined', {
|
||||
choices: [
|
||||
{
|
||||
id: 1,
|
||||
label: '<b>Choice 1</b>',
|
||||
value: 'Choice 1',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
label: 'Choice 2',
|
||||
value: 'Choice 2',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
new Choices('#choices-allowhtml-true', {
|
||||
allowHTML: true,
|
||||
choices: [
|
||||
{
|
||||
id: 1,
|
||||
label: '<b>Choice 1</b>',
|
||||
value: 'Choice 1',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
label: 'Choice 2',
|
||||
value: 'Choice 2',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
new Choices('#choices-allowhtml-false', {
|
||||
allowHTML: false,
|
||||
choices: [
|
||||
{
|
||||
id: 1,
|
||||
label: '<b>Choice 1</b>',
|
||||
value: 'Choice 1',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
label: 'Choice 2',
|
||||
value: 'Choice 2',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const newDestroyInitChoices = new Choices('#choices-new-destroy-init', {
|
||||
allowHTML: true,
|
||||
});
|
||||
document
|
||||
.querySelector('button.destroy')
|
||||
.addEventListener('click', () => {
|
||||
newDestroyInitChoices.destroy();
|
||||
});
|
||||
document.querySelector('button.init').addEventListener('click', () => {
|
||||
newDestroyInitChoices.init();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,140 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no">
|
||||
<title>Choices</title>
|
||||
<meta name=description itemprop=description content="A lightweight, configurable select box/text input plugin. Similar to Select2 and Selectize but without the jQuery dependency.">
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="../assets/images/apple-touch-icon.png">
|
||||
<link rel="icon" type="image/png" href="../assets/images/favicon-32x32.png" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="../assets/images/favicon-16x16.png" sizes="16x16">
|
||||
<link rel="manifest" href="../assets/images/manifest.json">
|
||||
<link rel="mask-icon" href="../assets/images/safari-pinned-tab.svg" color="#00bcd4">
|
||||
<link rel="shortcut icon" href="../assets/images/favicon.ico">
|
||||
<meta name="msapplication-config" content="../assets/images/browserconfig.xml">
|
||||
<meta name="theme-color" content="#ffffff">
|
||||
|
||||
<!-- Ignore these -->
|
||||
<link rel="stylesheet" href="../assets/styles/base.min.css?version=3.0.2">
|
||||
<!-- End ignore these -->
|
||||
|
||||
<!-- Choices includes -->
|
||||
<link rel="stylesheet" href="../assets/styles/choices.min.css?version=3.0.2">
|
||||
<script src="../assets/scripts/choices.min.js?version=2.8.8"></script>
|
||||
<!-- End Choices includes -->
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="section">
|
||||
<h2>Text inputs</h2>
|
||||
<div data-test-hook="basic">
|
||||
<label for="choices-basic">Basic</label>
|
||||
<input class="form-control" id="choices-basic" type="text">
|
||||
</div>
|
||||
|
||||
<div data-test-hook="edit-items">
|
||||
<label for="choices-edit-items">Edit items</label>
|
||||
<input class="form-control" id="choices-edit-items" type="text">
|
||||
</div>
|
||||
|
||||
<div data-test-hook="remove-button">
|
||||
<label for="choices-remove-button">Remove button</label>
|
||||
<input class="form-control" id="choices-remove-button" type="text">
|
||||
</div>
|
||||
|
||||
<div data-test-hook="unique-values">
|
||||
<label for="choices-unique-values">Unique values</label>
|
||||
<input class="form-control" id="choices-unique-values" type="text">
|
||||
</div>
|
||||
|
||||
<div data-test-hook="input-limit">
|
||||
<label for="choices-input-limit">Input limit</label>
|
||||
<input class="form-control" id="choices-input-limit" type="text">
|
||||
</div>
|
||||
|
||||
<div data-test-hook="regex-filter">
|
||||
<label for="choices-regex-filter">Regex filter</label>
|
||||
<input class="form-control" id="choices-regex-filter" type="text">
|
||||
</div>
|
||||
|
||||
<div data-test-hook="adding-items-disabled">
|
||||
<label for="choices-adding-items-disabled">Add items disabled</label>
|
||||
<input class="form-control" id="choices-adding-items-disabled" type="text">
|
||||
</div>
|
||||
|
||||
<div data-test-hook="disabled-via-attr">
|
||||
<label for="choices-disabled-via-attr">Disabled via attribute</label>
|
||||
<input class="form-control" id="choices-disabled-via-attr" type="text" disabled>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="prepend-append">
|
||||
<label for="choices-prepend-append">Prepend/append</label>
|
||||
<input class="form-control" id="choices-prepend-append" type="text">
|
||||
</div>
|
||||
|
||||
<div data-test-hook="prepopulated">
|
||||
<label for="choices-prepopulated">Pre-populated choices</label>
|
||||
<input class="form-control" id="choices-prepopulated" type="text">
|
||||
</div>
|
||||
|
||||
<div data-test-hook="placeholder">
|
||||
<label for="choices-placeholder">Placeholder</label>
|
||||
<input class="form-control" id="choices-placeholder" type="text">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
new Choices('#choices-basic');
|
||||
|
||||
new Choices('#choices-edit-items', {
|
||||
editItems: true,
|
||||
});
|
||||
|
||||
new Choices('#choices-remove-button', {
|
||||
removeItemButton: true,
|
||||
});
|
||||
|
||||
new Choices('#choices-unique-values', {
|
||||
duplicateItemsAllowed: false,
|
||||
});
|
||||
|
||||
new Choices('#choices-input-limit', {
|
||||
maxItemCount: 5,
|
||||
});
|
||||
|
||||
new Choices('#choices-regex-filter', {
|
||||
regexFilter: /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/,
|
||||
});
|
||||
|
||||
new Choices('#choices-adding-items-disabled', {
|
||||
addItems: false,
|
||||
});
|
||||
|
||||
new Choices('#choices-disabled-via-attr');
|
||||
|
||||
new Choices('#choices-prepend-append', {
|
||||
prependValue: 'before-',
|
||||
appendValue: '-after',
|
||||
});
|
||||
|
||||
new Choices('#choices-prepopulated', {
|
||||
items: ['Josh Johnson', {
|
||||
value: 'joe@bloggs.co.uk',
|
||||
label: 'Joe Bloggs',
|
||||
customProperties: {
|
||||
description: 'Joe Blogg is such a generic name',
|
||||
}
|
||||
}],
|
||||
});
|
||||
|
||||
new Choices('#choices-placeholder', {
|
||||
placeholder: true,
|
||||
placeholderValue: 'I am a placeholder',
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
247
public/test/text/index.html
Normal file
|
@ -0,0 +1,247 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width,initial-scale=1,user-scalable=no"
|
||||
/>
|
||||
<title>Choices</title>
|
||||
<meta
|
||||
name="description"
|
||||
itemprop="description"
|
||||
content="A lightweight, configurable select box/text input plugin. Similar to Select2 and Selectize but without the jQuery dependency."
|
||||
/>
|
||||
<link
|
||||
rel="apple-touch-icon"
|
||||
sizes="180x180"
|
||||
href="../../assets/images/apple-touch-icon.png"
|
||||
/>
|
||||
<link
|
||||
rel="icon"
|
||||
type="image/png"
|
||||
href="../../assets/images/favicon-32x32.png"
|
||||
sizes="32x32"
|
||||
/>
|
||||
<link
|
||||
rel="icon"
|
||||
type="image/png"
|
||||
href="../../assets/images/favicon-16x16.png"
|
||||
sizes="16x16"
|
||||
/>
|
||||
<link rel="manifest" href="../../assets/images/manifest.json" />
|
||||
<link
|
||||
rel="mask-icon"
|
||||
href="../../assets/images/safari-pinned-tab.svg"
|
||||
color="#00bcd4"
|
||||
/>
|
||||
<link rel="shortcut icon" href="../../assets/images/favicon.ico" />
|
||||
<meta
|
||||
name="msapplication-config"
|
||||
content="../../assets/images/browserconfig.xml"
|
||||
/>
|
||||
<meta name="theme-color" content="#ffffff" />
|
||||
|
||||
<!-- Ignore these -->
|
||||
<link rel="stylesheet" href="../../assets/styles/base.min.css" />
|
||||
<!-- End ignore these -->
|
||||
|
||||
<!-- Choices includes -->
|
||||
<link rel="stylesheet" href="../../assets/styles/choices.min.css" />
|
||||
<script src="../../assets/scripts/choices.min.js"></script>
|
||||
<!-- End Choices includes -->
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="section">
|
||||
<h2>Text inputs</h2>
|
||||
<div data-test-hook="basic">
|
||||
<label for="choices-basic">Basic</label>
|
||||
<input class="form-control" id="choices-basic" type="text" />
|
||||
</div>
|
||||
|
||||
<div data-test-hook="edit-items">
|
||||
<label for="choices-edit-items">Edit items</label>
|
||||
<input class="form-control" id="choices-edit-items" type="text" />
|
||||
</div>
|
||||
|
||||
<div data-test-hook="remove-button">
|
||||
<label for="choices-remove-button">Remove button</label>
|
||||
<input class="form-control" id="choices-remove-button" type="text" />
|
||||
</div>
|
||||
|
||||
<div data-test-hook="unique-values">
|
||||
<label for="choices-unique-values">Unique values</label>
|
||||
<input class="form-control" id="choices-unique-values" type="text" />
|
||||
</div>
|
||||
|
||||
<div data-test-hook="allowhtml-undefined">
|
||||
<label for="allowhtml-undefined">HTML allowed by default</label>
|
||||
<input class="form-control" id="allowhtml-undefined" type="text" />
|
||||
</div>
|
||||
|
||||
<div data-test-hook="allowhtml-true">
|
||||
<label for="allowhtml-true">HTML allowed</label>
|
||||
<input class="form-control" id="allowhtml-true" type="text" />
|
||||
</div>
|
||||
|
||||
<div data-test-hook="allowhtml-false">
|
||||
<label for="allowhtml-false">HTML disabled</label>
|
||||
<input class="form-control" id="allowhtml-false" type="text" />
|
||||
</div>
|
||||
|
||||
<div data-test-hook="input-limit">
|
||||
<label for="choices-input-limit">Input limit</label>
|
||||
<input class="form-control" id="choices-input-limit" type="text" />
|
||||
</div>
|
||||
|
||||
<div data-test-hook="add-item-filter">
|
||||
<label for="choices-add-item-filter">Add item filter</label>
|
||||
<input
|
||||
class="form-control"
|
||||
id="choices-add-item-filter"
|
||||
type="text"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="adding-items-disabled">
|
||||
<label for="choices-adding-items-disabled">Add items disabled</label>
|
||||
<input
|
||||
class="form-control"
|
||||
id="choices-adding-items-disabled"
|
||||
type="text"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="disabled-via-attr">
|
||||
<label for="choices-disabled-via-attr">Disabled via attribute</label>
|
||||
<input
|
||||
class="form-control"
|
||||
id="choices-disabled-via-attr"
|
||||
type="text"
|
||||
disabled
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="prepend-append">
|
||||
<label for="choices-prepend-append">Prepend/append</label>
|
||||
<input class="form-control" id="choices-prepend-append" type="text" />
|
||||
</div>
|
||||
|
||||
<div data-test-hook="prepopulated">
|
||||
<label for="choices-prepopulated">Pre-populated choices</label>
|
||||
<input class="form-control" id="choices-prepopulated" type="text" />
|
||||
</div>
|
||||
|
||||
<div data-test-hook="placeholder">
|
||||
<label for="choices-placeholder">Placeholder</label>
|
||||
<input class="form-control" id="choices-placeholder" type="text" />
|
||||
</div>
|
||||
|
||||
<div data-test-hook="within-form">
|
||||
<form>
|
||||
<label for="choices-within-form">Within form</label>
|
||||
<input class="form-control" id="choices-within-form" type="text" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
new Choices('#choices-basic', {
|
||||
allowHTML: true,
|
||||
});
|
||||
|
||||
new Choices('#choices-edit-items', {
|
||||
allowHTML: true,
|
||||
editItems: true,
|
||||
});
|
||||
|
||||
new Choices('#choices-remove-button', {
|
||||
allowHTML: true,
|
||||
removeItemButton: true,
|
||||
});
|
||||
|
||||
new Choices('#choices-unique-values', {
|
||||
allowHTML: true,
|
||||
duplicateItemsAllowed: false,
|
||||
});
|
||||
|
||||
new Choices('#allowhtml-undefined', {
|
||||
items: [
|
||||
'<b>Mason Rogers</b>'
|
||||
],
|
||||
});
|
||||
|
||||
new Choices('#allowhtml-true', {
|
||||
allowHTML: true,
|
||||
items: [
|
||||
'<b>Mason Rogers</b>'
|
||||
],
|
||||
});
|
||||
|
||||
new Choices('#allowhtml-false', {
|
||||
allowHTML: false,
|
||||
items: [
|
||||
'<b>Mason Rogers</b>'
|
||||
],
|
||||
});
|
||||
|
||||
new Choices('#choices-input-limit', {
|
||||
allowHTML: true,
|
||||
maxItemCount: 5,
|
||||
});
|
||||
|
||||
new Choices('#choices-add-item-filter', {
|
||||
allowHTML: true,
|
||||
addItems: true,
|
||||
addItemFilter: value => {
|
||||
const regex = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
|
||||
const expression = new RegExp(regex.source, 'i');
|
||||
return expression.test(value);
|
||||
},
|
||||
});
|
||||
|
||||
new Choices('#choices-adding-items-disabled', {
|
||||
allowHTML: true,
|
||||
addItems: false,
|
||||
});
|
||||
|
||||
new Choices('#choices-disabled-via-attr', {
|
||||
allowHTML: true,
|
||||
});
|
||||
|
||||
new Choices('#choices-prepend-append', {
|
||||
allowHTML: true,
|
||||
prependValue: 'before-',
|
||||
appendValue: '-after',
|
||||
});
|
||||
|
||||
new Choices('#choices-prepopulated', {
|
||||
allowHTML: true,
|
||||
items: [
|
||||
'Josh Johnson',
|
||||
{
|
||||
value: 'joe@bloggs.co.uk',
|
||||
label: 'Joe Bloggs',
|
||||
customProperties: {
|
||||
description: 'Joe Blogg is such a generic name',
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
new Choices('#choices-placeholder', {
|
||||
allowHTML: true,
|
||||
placeholder: true,
|
||||
placeholderValue: 'I am a placeholder',
|
||||
});
|
||||
|
||||
new Choices('#choices-within-form', {
|
||||
allowHTML: true,
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
1
public/types/cypress/e2e/select-multiple.spec.d.ts
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
//# sourceMappingURL=select-multiple.spec.d.ts.map
|
1
public/types/cypress/e2e/select-multiple.spec.d.ts.map
Normal file
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"select-multiple.spec.d.ts","sourceRoot":"","sources":["../../../../cypress/e2e/select-multiple.spec.ts"],"names":[],"mappings":""}
|
1
public/types/cypress/e2e/select-one.spec.d.ts
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
//# sourceMappingURL=select-one.spec.d.ts.map
|
1
public/types/cypress/e2e/select-one.spec.d.ts.map
Normal file
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"select-one.spec.d.ts","sourceRoot":"","sources":["../../../../cypress/e2e/select-one.spec.ts"],"names":[],"mappings":""}
|
1
public/types/cypress/e2e/text.spec.d.ts
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
//# sourceMappingURL=text.spec.d.ts.map
|
1
public/types/cypress/e2e/text.spec.d.ts.map
Normal file
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"text.spec.d.ts","sourceRoot":"","sources":["../../../../cypress/e2e/text.spec.ts"],"names":[],"mappings":""}
|
1
public/types/cypress/integration/select-multiple.spec.d.ts
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
//# sourceMappingURL=select-multiple.spec.d.ts.map
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"select-multiple.spec.d.ts","sourceRoot":"","sources":["../../../../cypress/integration/select-multiple.spec.ts"],"names":[],"mappings":""}
|
1
public/types/cypress/integration/select-one.spec.d.ts
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
//# sourceMappingURL=select-one.spec.d.ts.map
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"select-one.spec.d.ts","sourceRoot":"","sources":["../../../../cypress/integration/select-one.spec.ts"],"names":[],"mappings":""}
|
1
public/types/cypress/integration/text.spec.d.ts
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
//# sourceMappingURL=text.spec.d.ts.map
|
1
public/types/cypress/integration/text.spec.d.ts.map
Normal file
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"text.spec.d.ts","sourceRoot":"","sources":["../../../../cypress/integration/text.spec.ts"],"names":[],"mappings":""}
|
3
public/types/cypress/plugins/index.d.ts
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
declare function _exports(on: any, config: any): void;
|
||||
export = _exports;
|
||||
//# sourceMappingURL=index.d.ts.map
|
1
public/types/cypress/plugins/index.d.ts.map
Normal file
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../cypress/plugins/index.js"],"names":[],"mappings":"AAaiB,sDAGhB"}
|
1
public/types/cypress/support/commands.d.ts
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
//# sourceMappingURL=commands.d.ts.map
|
1
public/types/cypress/support/commands.d.ts.map
Normal file
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../../../cypress/support/commands.js"],"names":[],"mappings":""}
|
2
public/types/cypress/support/e2e.d.ts
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
export {};
|
||||
//# sourceMappingURL=e2e.d.ts.map
|
1
public/types/cypress/support/e2e.d.ts.map
Normal file
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"e2e.d.ts","sourceRoot":"","sources":["../../../../cypress/support/e2e.js"],"names":[],"mappings":""}
|
2
public/types/cypress/support/index.d.ts
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
export {};
|
||||
//# sourceMappingURL=index.d.ts.map
|
1
public/types/cypress/support/index.d.ts.map
Normal file
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../cypress/support/index.js"],"names":[],"mappings":""}
|
7
public/types/src/index.d.ts
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
import Choices from './scripts/choices';
|
||||
export * from './scripts/interfaces';
|
||||
export * from './scripts/constants';
|
||||
export * from './scripts/defaults';
|
||||
export { default as templates } from './scripts/templates';
|
||||
export default Choices;
|
||||
//# sourceMappingURL=index.d.ts.map
|
1
public/types/src/index.d.ts.map
Normal file
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,mBAAmB,CAAC;AAExC,cAAc,sBAAsB,CAAC;AACrC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAE3D,eAAe,OAAO,CAAC"}
|