feat(select): enhance select input with choices.js

- select fields come with a search field
- update language names by fixing missing caps in
LanguageSeeder
- add parent to categoryOptions
This commit is contained in:
Yassine Doghri 2021-07-26 17:33:34 +00:00
parent 9dd4c7741e
commit 910d457cf8
13 changed files with 467 additions and 239 deletions

View File

@ -17,6 +17,7 @@
"editor.defaultFormatter": "bmewburn.vscode-intelephense-client",
"editor.formatOnSave": false
},
"css.validate": false,
"color-highlight.markerType": "dot-before",
"files.associations": {
"*.xml.dist": "xml",

View File

@ -34,7 +34,7 @@ class LanguageSeeder extends Seeder
],
[
'code' => 'ae',
'native_name' => 'avesta',
'native_name' => 'Avesta',
],
[
'code' => 'af',
@ -50,7 +50,7 @@ class LanguageSeeder extends Seeder
],
[
'code' => 'an',
'native_name' => 'aragonés',
'native_name' => 'Aragonés',
],
[
'code' => 'ar',
@ -66,7 +66,7 @@ class LanguageSeeder extends Seeder
],
[
'code' => 'ay',
'native_name' => 'aymar aru',
'native_name' => 'Aymar aru',
],
[
'code' => 'az',
@ -94,7 +94,7 @@ class LanguageSeeder extends Seeder
],
[
'code' => 'bm',
'native_name' => 'bamanankan',
'native_name' => 'Bamanankan',
],
[
'code' => 'bn',
@ -106,15 +106,15 @@ class LanguageSeeder extends Seeder
],
[
'code' => 'br',
'native_name' => 'brezhoneg',
'native_name' => 'Brezhoneg',
],
[
'code' => 'bs',
'native_name' => 'bosanski jezik',
'native_name' => 'Bosanski jezik',
],
[
'code' => 'ca',
'native_name' => 'català, valencià',
'native_name' => 'Català, valencià',
],
[
'code' => 'ce',
@ -126,7 +126,7 @@ class LanguageSeeder extends Seeder
],
[
'code' => 'co',
'native_name' => 'corsu, lingua corsa',
'native_name' => 'Corsu, lingua corsa',
],
[
'code' => 'cr',
@ -150,7 +150,7 @@ class LanguageSeeder extends Seeder
],
[
'code' => 'da',
'native_name' => 'dansk',
'native_name' => 'Dansk',
],
[
'code' => 'de',
@ -190,7 +190,7 @@ class LanguageSeeder extends Seeder
],
[
'code' => 'eu',
'native_name' => 'euskara, euskera',
'native_name' => 'Euskara, euskera',
],
[
'code' => 'fa',
@ -202,19 +202,19 @@ class LanguageSeeder extends Seeder
],
[
'code' => 'fi',
'native_name' => 'suomi, suomen kieli',
'native_name' => 'Suomi, suomen kieli',
],
[
'code' => 'fj',
'native_name' => 'vosa Vakaviti',
'native_name' => 'Vosa Vakaviti',
],
[
'code' => 'fo',
'native_name' => 'føroyskt',
'native_name' => 'Føroyskt',
],
[
'code' => 'fr',
'native_name' => 'français, langue française',
'native_name' => 'Français, langue française',
],
[
'code' => 'fy',
@ -262,7 +262,7 @@ class LanguageSeeder extends Seeder
],
[
'code' => 'hr',
'native_name' => 'hrvatski jezik',
'native_name' => 'Hrvatski jezik',
],
[
'code' => 'ht',
@ -270,7 +270,7 @@ class LanguageSeeder extends Seeder
],
[
'code' => 'hu',
'native_name' => 'magyar',
'native_name' => 'Magyar',
],
[
'code' => 'hy',
@ -291,7 +291,7 @@ class LanguageSeeder extends Seeder
[
'code' => 'ie',
'native_name' =>
'(originally:) Occidental, (after WWII:) Interlingue',
'Interlingue, formerly Occidental',
],
[
'code' => 'ig',
@ -351,7 +351,7 @@ class LanguageSeeder extends Seeder
],
[
'code' => 'kl',
'native_name' => 'kalaallisut, kalaallit oqaasii',
'native_name' => 'Kalaallisut, kalaallit oqaasii',
],
[
'code' => 'km',
@ -391,7 +391,7 @@ class LanguageSeeder extends Seeder
],
[
'code' => 'la',
'native_name' => 'latine, lingua latina',
'native_name' => 'Latine, lingua latina',
],
[
'code' => 'lb',
@ -415,7 +415,7 @@ class LanguageSeeder extends Seeder
],
[
'code' => 'lt',
'native_name' => 'lietuvių kalba',
'native_name' => 'Lietuvių kalba',
],
[
'code' => 'lu',
@ -423,11 +423,11 @@ class LanguageSeeder extends Seeder
],
[
'code' => 'lv',
'native_name' => 'latviešu valoda',
'native_name' => 'Latviešu valoda',
],
[
'code' => 'mg',
'native_name' => 'fiteny malagasy',
'native_name' => 'Fiteny malagasy',
],
[
'code' => 'mh',
@ -435,7 +435,7 @@ class LanguageSeeder extends Seeder
],
[
'code' => 'mi',
'native_name' => 'te reo Māori',
'native_name' => 'Te reo Māori',
],
[
'code' => 'mk',
@ -507,11 +507,11 @@ class LanguageSeeder extends Seeder
],
[
'code' => 'ny',
'native_name' => 'chiCheŵa, chinyanja',
'native_name' => 'Chicheŵa, chinyanja',
],
[
'code' => 'oc',
'native_name' => 'occitan, lenga dòc',
'native_name' => 'Occitan, lenga dòc',
],
[
'code' => 'oj',
@ -567,7 +567,7 @@ class LanguageSeeder extends Seeder
],
[
'code' => 'ru',
'native_name' => 'русский',
'native_name' => 'Pусский',
],
[
'code' => 'rw',
@ -579,7 +579,7 @@ class LanguageSeeder extends Seeder
],
[
'code' => 'sc',
'native_name' => 'sardu',
'native_name' => 'Sardu',
],
[
'code' => 'sd',
@ -591,7 +591,7 @@ class LanguageSeeder extends Seeder
],
[
'code' => 'sg',
'native_name' => 'yângâ tî sängö',
'native_name' => 'Yângâ tî sängö',
],
[
'code' => 'si',
@ -607,7 +607,7 @@ class LanguageSeeder extends Seeder
],
[
'code' => 'sm',
'native_name' => "gagana fa'a Samoa",
'native_name' => "Gagana fa'a Samoa",
],
[
'code' => 'sn',

View File

@ -65,7 +65,11 @@ class CategoryModel extends Model
$options = array_reduce(
$categories,
function (array $result, Category $category): array {
$result[$category->id] = lang('Podcast.category_options.' . $category->code);
$result[$category->id] = '';
if ($category->parent !== null) {
$result[$category->id] = lang('Podcast.category_options.' . $category->parent->code) . ' ';
}
$result[$category->id] .= lang('Podcast.category_options.' . $category->code);
return $result;
},
[],

View File

@ -5,6 +5,7 @@ import Dropdown from "./modules/Dropdown";
import MarkdownEditor from "./modules/MarkdownEditor";
import MultiSelect from "./modules/MultiSelect";
import PublishMessageWarning from "./modules/PublishMessageWarning";
import Select from "./modules/Select";
import SidebarToggler from "./modules/SidebarToggler";
import Slugify from "./modules/Slugify";
import Soundbites from "./modules/Soundbites";
@ -15,6 +16,7 @@ import Tooltip from "./modules/Tooltip";
Dropdown();
Tooltip();
MarkdownEditor();
Select();
MultiSelect();
Slugify();
SidebarToggler();

View File

@ -14,24 +14,22 @@ const MultiSelect = (): void => {
maxItemText: multiSelect.dataset.maxItemText,
removeItemButton: true,
classNames: {
containerOuter:
"multiselect" +
(multiSelect.dataset.class ? ` ${multiSelect.dataset.class}` : ""),
containerInner: "multiselect__inner",
input: "multiselect__input",
inputCloned: "multiselect__input--cloned",
list: "multiselect__list",
listItems: "multiselect__list--multiple",
listSingle: "multiselect__list--single",
listDropdown: "multiselect__list--dropdown",
item: "multiselect__item",
itemSelectable: "multiselect__item--selectable",
itemDisabled: "multiselect__item--disabled",
itemChoice: "multiselect__item--choice",
placeholder: "multiselect__placeholder",
group: "multiselect__group",
groupHeading: "multiselect__heading",
button: "multiselect__button",
containerOuter: "choices",
containerInner: "choices__inner",
input: "choices__input",
inputCloned: "choices__input--cloned",
list: "choices__list",
listItems: "choices__list--multiple",
listSingle: "choices__list--single",
listDropdown: "choices__list--dropdown",
item: "choices__item",
itemSelectable: "choices__item--selectable",
itemDisabled: "choices__item--disabled",
itemChoice: "choices__item--choice",
placeholder: "choices__placeholder",
group: "choices__group",
groupHeading: "choices__heading",
button: "choices__button",
activeState: "is-active",
focusState: "is-focused",
openState: "is-open",

View File

@ -0,0 +1,45 @@
import Choices from "choices.js";
const Select = (): void => {
// Pass single element
const selects: NodeListOf<HTMLSelectElement> = document.querySelectorAll(
"select:not([multiple])"
);
for (let i = 0; i < selects.length; i++) {
const select = selects[i];
new Choices(select, {
classNames: {
containerOuter: "choices",
containerInner: "choices__inner",
input: "choices__input",
inputCloned: "choices__input--cloned",
list: "choices__list",
listItems: "choices__list--multiple",
listSingle: "choices__list--single",
listDropdown: "choices__list--dropdown",
item: "choices__item",
itemSelectable: "choices__item--selectable",
itemDisabled: "choices__item--disabled",
itemChoice: "choices__item--choice",
placeholder: "choices__placeholder",
group: "choices__group",
groupHeading: "choices__heading",
button: "choices__button",
activeState: "is-active",
focusState: "is-focused",
openState: "is-open",
disabledState: "is-disabled",
highlightedState: "is-highlighted",
selectedState: "is-selected",
flippedState: "is-flipped",
loadingState: "is-loading",
noResults: "has-no-results",
noChoices: "has-no-choices",
},
});
}
};
export default Select;

View File

@ -0,0 +1,364 @@
/*===============================
= Choices =
===============================*/
@layer components {
.choices {
position: relative;
margin-bottom: 24px;
font-size: 16px;
}
.choices:focus {
outline: none;
}
.choices:last-child {
margin-bottom: 0;
}
.choices.is-disabled .choices__inner,
.choices.is-disabled .choices__input {
background-color: #eaeaea;
cursor: not-allowed;
-webkit-user-select: none;
-ms-user-select: none;
user-select: none;
}
.choices.is-disabled .choices__item {
cursor: not-allowed;
}
.choices [hidden] {
display: none !important;
}
.choices[data-type*="select-one"] {
cursor: pointer;
}
.choices[data-type*="select-one"] .choices__inner {
padding-bottom: 7.5px;
}
.choices[data-type*="select-one"] .choices__input {
display: block;
width: 100%;
padding: 10px;
border-bottom: 1px solid #dddddd;
background-color: #ffffff;
margin: 0;
}
.choices[data-type*="select-one"] .choices__button {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%236B7280'%3E%3Cpath fill='none' d='M0 0h24v24H0z'/%3E%3Cpath d='M12 10.586l4.95-4.95 1.414 1.414-4.95 4.95 4.95 4.95-1.414 1.414-4.95-4.95-4.95 4.95-1.414-1.414 4.95-4.95-4.95-4.95L7.05 5.636z'/%3E%3C/svg%3E");
padding: 0;
background-size: 20px;
position: absolute;
top: 50%;
right: 0;
margin-top: -10px;
margin-right: 25px;
height: 20px;
width: 20px;
opacity: 0.5;
}
.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__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-width: 5px;
position: absolute;
right: 11.5px;
top: 50%;
margin-top: -2.5px;
pointer-events: none;
}
.choices[data-type*="select-one"].is-open:after {
border-color: transparent transparent #333333 transparent;
margin-top: -7.5px;
}
.choices[data-type*="select-one"][dir="rtl"]:after {
left: 11.5px;
right: auto;
}
.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 {
cursor: text;
}
.choices[data-type*="select-multiple"] .choices__button,
.choices[data-type*="text"] .choices__button {
position: relative;
display: inline-block;
margin-left: 8px;
padding-left: 16px;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23ffffff'%3E%3Cpath fill='none' d='M0 0h24v24H0z'/%3E%3Cpath d='M12 10.586l4.95-4.95 1.414 1.414-4.95 4.95 4.95 4.95-1.414 1.414-4.95-4.95-4.95 4.95-1.414-1.414 4.95-4.95-4.95-4.95L7.05 5.636z'/%3E%3C/svg%3E");
background-size: 16px;
width: 8px;
line-height: 1;
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 {
opacity: 1;
}
.choices__inner {
@apply p-2 bg-white border border-gray-700;
display: inline-block;
vertical-align: top;
width: 100%;
font-size: 16px;
min-height: 42px;
overflow: hidden;
}
.choices[data-type*="select-multiple"] .choices__inner {
@apply pb-1;
}
.is-focused .choices__inner,
.is-open .choices__inner {
@apply ring-inset ring-1 ring-blue-600;
}
.is-open .choices__inner {
border-radius: 0;
}
.is-flipped.is-open .choices__inner {
border-radius: 0;
}
.choices__list {
margin: 0;
padding-left: 0;
list-style: none;
}
.choices__list--single {
@apply pr-4;
display: inline-block;
width: 100%;
}
[dir="rtl"] .choices__list--single {
padding-right: 4px;
padding-left: 16px;
}
.choices__list--single .choices__item {
width: 100%;
}
.choices__list--multiple {
display: inline;
}
.choices__list--multiple .choices__item {
@apply inline-block px-2 py-1 mb-1 mr-1 text-sm text-white align-middle bg-pine-600;
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 {
margin-right: 0;
margin-left: 3.75px;
}
.choices__list--multiple .choices__item.is-highlighted {
@apply bg-pine-700;
}
.is-disabled .choices__list--multiple .choices__item {
background-color: #aaaaaa;
border: 1px solid #919191;
}
.choices__list--dropdown {
visibility: hidden;
z-index: 1;
position: absolute;
width: 100%;
background-color: #ffffff;
border: 1px solid #dddddd;
top: 100%;
margin-top: -1px;
overflow: hidden;
word-break: break-all;
will-change: visibility;
}
.choices__list--dropdown.is-active {
visibility: visible;
}
.is-open .choices__list--dropdown {
border-color: #b7b7b7;
}
.is-flipped .choices__list--dropdown {
top: auto;
bottom: 100%;
margin-top: 0;
margin-bottom: -1px;
}
.choices__list--dropdown .choices__list {
position: relative;
max-height: 300px;
overflow: auto;
-webkit-overflow-scrolling: touch;
will-change: scroll-position;
}
.choices__list--dropdown .choices__item {
position: relative;
padding: 10px;
font-size: 14px;
}
[dir="rtl"] .choices__list--dropdown .choices__item {
text-align: right;
}
@media (min-width: 640px) {
.choices__list--dropdown .choices__item--selectable {
padding-right: 100px;
}
.choices__list--dropdown .choices__item--selectable:after {
content: attr(data-select-text);
font-size: 12px;
opacity: 0;
position: absolute;
right: 10px;
top: 50%;
transform: translateY(-50%);
}
[dir="rtl"] .choices__list--dropdown .choices__item--selectable {
text-align: right;
padding-left: 100px;
padding-right: 10px;
}
[dir="rtl"] .choices__list--dropdown .choices__item--selectable:after {
right: auto;
left: 10px;
}
}
.choices__list--dropdown .choices__item--selectable.is-highlighted {
background-color: #f2f2f2;
}
.choices__list--dropdown .choices__item--selectable.is-highlighted:after {
opacity: 0.5;
}
.choices__item {
cursor: default;
}
.choices__item--selectable {
cursor: pointer;
}
.choices__item--disabled {
cursor: not-allowed;
-webkit-user-select: none;
-ms-user-select: none;
user-select: none;
opacity: 0.5;
}
.choices__heading {
font-weight: 600;
font-size: 12px;
padding: 10px;
border-bottom: 1px solid #f7f7f7;
color: gray;
}
.choices__button {
text-indent: -9999px;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
border: 0;
background-color: transparent;
background-repeat: no-repeat;
background-position: center;
cursor: pointer;
}
.choices__button:focus {
outline: none;
}
.choices__input {
@apply mb-1 align-middle bg-white;
display: inline-block;
font-size: 14px;
border: 0;
border-radius: 0;
max-width: 100%;
width: 1px;
padding: 0;
}
.choices__input:focus {
@apply outline-none;
box-shadow: none;
}
[dir="rtl"] .choices__input {
padding-right: 2px;
padding-left: 0;
}
.choices__placeholder {
opacity: 0.5;
}
}
/*===== End of Choices ======*/

View File

@ -3,7 +3,7 @@
@import "./layout.css";
@import "./breadcrumb.css";
@import "./dropdown.css";
@import "./multiSelect.css";
@import "./choices.css";
@import "./radioBtn.css";
@import "./switch.css";
@import "./charts.css";

View File

@ -1,183 +0,0 @@
/*===============================
= MultiSelect =
===============================*/
@layer components {
.multiselect {
@apply relative;
&:focus {
@apply outline-none ring;
}
&:last-child {
@apply mb-0;
}
&.is-disabled {
&.multiselect__inner,
&.multiselect__input {
@apply bg-gray-300 cursor-not-allowed select-none;
}
&.multiselect__item {
@apply cursor-not-allowed;
}
}
& [hidden] {
@apply hidden;
}
}
.multiselect[data-type*="select-multiple"],
.multiselect[data-type*="text"] {
& .multiselect__inner {
@apply cursor-text;
}
& .multiselect__button {
@apply relative inline-block w-2 pl-4 mt-0 mb-0 ml-1 opacity-75;
background-image: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjEiIGhlaWdodD0iMjEiIHZpZXdCb3g9IjAgMCAyMSAyMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48ZyBmaWxsPSIjRkZGIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPjxwYXRoIGQ9Ik0yLjU5Mi4wNDRsMTguMzY0IDE4LjM2NC0yLjU0OCAyLjU0OEwuMDQ0IDIuNTkyeiIvPjxwYXRoIGQ9Ik0wIDE4LjM2NEwxOC4zNjQgMGwyLjU0OCAyLjU0OEwyLjU0OCAyMC45MTJ6Ii8+PC9nPjwvc3ZnPg==);
background-size: 8px;
&:hover,
&:focus {
@apply opacity-100;
}
}
}
.multiselect__inner {
@apply inline-block w-full px-2 pt-2 pb-1 overflow-hidden align-top bg-white border rounded;
&.is-focused,
&.is-open {
@apply ring;
}
&.is-open {
@apply rounded-b-none;
}
&.is-flipped.is-open {
@apply rounded-t-none;
}
}
.multiselect__list {
@apply p-0 m-0 list-none;
}
.multiselect__list--multiple {
@apply inline;
& .multiselect__item {
@apply inline-flex px-2 py-1 mb-1 mr-2 text-sm text-white break-all rounded bg-pine-600;
&[data-deletable] {
@apply pr-1;
}
& [dir="rtl"] {
@apply ml-2 mr-0;
}
&.is-highlighted {
@apply bg-pine-600;
}
&.is-disabled {
@apply bg-gray-500;
}
}
}
.multiselect__list--dropdown {
@apply absolute z-10 invisible w-full overflow-hidden break-all bg-white border border-t-0 rounded-b shadow-lg;
top: 100%;
will-change: visibility;
&.is-active {
@apply visible;
}
&.is-open {
@apply ring;
}
&.is-flipped {
@apply top-auto mt-0 rounded-t;
bottom: 100%;
}
& .multiselect__list {
@apply relative overflow-auto;
max-height: 300px;
-webkit-overflow-scrolling: touch;
will-change: scroll-position;
}
& .multiselect__item {
@apply relative p-3;
& [dir="rtl"] {
@apply text-right;
}
}
& .multiselect__item--selectable {
@screen sm {
padding-right: 100px;
&:after {
@apply absolute text-sm transform -translate-y-1/2 opacity-0;
content: attr(data-select-text);
right: 10px;
top: 50%;
}
& [dir="rtl"] {
@apply text-right;
padding-left: 100px;
padding-right: 10px;
&:after {
@apply right-auto;
left: 10px;
}
}
}
&.is-highlighted {
@apply bg-gray-100;
&:after {
@apply opacity-50;
}
}
}
}
.multiselect__item {
@apply cursor-default;
}
.multiselect__item--selectable {
@apply cursor-pointer;
}
.multiselect__item--disabled {
@apply opacity-50 cursor-not-allowed select-none;
}
.multiselect__heading {
@apply p-3 font-semibold text-gray-600 border-b;
}
.multiselect__button {
@apply bg-transparent bg-center bg-no-repeat border-0 appearance-none cursor-pointer;
text-indent: -9999px;
&:focus {
@apply outline-none;
}
}
.multiselect__input {
@apply inline-block max-w-full py-1 pl-1 mb-1 align-baseline bg-transparent border-0 rounded-none;
&:focus {
@apply outline-none;
}
& [dir="rtl"] {
@apply pl-0 pr-1;
}
}
.multiselect__placeholder {
@apply opacity-50;
}
}
/*===== End of Multiselect ======*/

View File

@ -0,0 +1,2 @@
declare const Select: () => void;
export default Select;

View File

@ -1,5 +0,0 @@
import { LitElement } from "lit";
declare class MyElement extends LitElement {
render(): import("lit-html").TemplateResult<1>;
}
export default MyElement;

View File

@ -51,7 +51,7 @@
lang('Podcast.form.handle_hint'),
) ?>
<div class="relative mb-4">
<?= icon('at', 'absolute text-2xl h-full inset-0 text-gray-400 left-2') ?>
<?= icon('at', 'absolute text-xl h-full inset-0 text-gray-400 left-3') ?>
<?= form_input([
'id' => 'handle',
'name' => 'handle',

View File

@ -57,7 +57,7 @@
lang('Podcast.form.handle_hint'),
) ?>
<div class="relative mb-4">
<?= icon('at', 'absolute text-2xl h-full inset-0 text-gray-400 left-2') ?>
<?= icon('at', 'absolute text-xl h-full inset-0 text-gray-400 left-3') ?>
<?= form_input([
'id' => 'handle',
'name' => 'handle',