Merge pull request #37 from apuc/custom-themes

Update 0.2.4
This commit is contained in:
MaxOvs19 2023-02-20 14:28:10 +03:00 committed by GitHub
commit 3bd587b846
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 449 additions and 60 deletions

View File

@ -46,3 +46,10 @@ Tested in JS and React. Errors in work in React applications are revealed.
- Fixing bugs related to the cleanup of the select. - Fixing bugs related to the cleanup of the select.
- Documentation navigation update. - Documentation navigation update.
- Added icon for example page and documentation. - Added icon for example page and documentation.
### 20.02.2023 - update 0.2.4
- Added ability to create custom themes.
- Added style builder on homepage.
- Fixed documentation.
- Added a block describing how to create your own themes.

View File

@ -1,6 +1,6 @@
# CG-SELECT # CG-SELECT
## version ~ 0.2.33 ## version ~ 0.2.4
This component allows you to create a custom select. It offers more flexible customization and use of select. This component allows you to create a custom select. It offers more flexible customization and use of select.
Customization, multi-selection and live search by elements are available. Customization, multi-selection and live search by elements are available.

View File

@ -1,6 +1,6 @@
# CG-SELECT # CG-SELECT
## version ~ 0.2.33 ## version ~ 0.2.4
Этот компонент позволяет вам создать пользовательский Select. Он предлагает более гибкую настройку и использование select. Этот компонент позволяет вам создать пользовательский Select. Он предлагает более гибкую настройку и использование select.
Доступна кастомизация, multi-selection, живой поиск по элементам и многое другое. Доступна кастомизация, multi-selection, живой поиск по элементам и многое другое.

View File

@ -62,7 +62,7 @@
</a> </a>
<a href="#version--0231" id="version--0231" style="color: inherit; text-decoration: none"> <a href="#version--0231" id="version--0231" style="color: inherit; text-decoration: none">
<h2>version ~ 0.2.33</h2> <h2>version ~ 0.2.4</h2>
</a> </a>
<p> <p>
This component allows you to create a custom select. It offers more flexible This component allows you to create a custom select. It offers more flexible

View File

@ -1,8 +1,21 @@
@import '/src/main.scss'; @import '/src/main.scss';
@import './src/constructor/constructor.scss';
* { * {
font-size: 14px; font-size: 14px;
font-family: Arial, Helvetica, sans-serif; font-family: Arial, Helvetica, sans-serif;
text-align: justify;
}
.testClass {
background-color: #8297ff;
color: white;
}
.listTest {
background-color: #8297ff;
border: 1px solid black;
color: white;
} }
.body-example { .body-example {
@ -30,6 +43,7 @@
} }
.header { .header {
position: relative;
width: 100%; width: 100%;
border-radius: 5px; border-radius: 5px;
display: flex; display: flex;
@ -112,6 +126,7 @@
} }
&_submit { &_submit {
text-align: center;
width: 200px; width: 200px;
height: 35px; height: 35px;
border-radius: 10px; border-radius: 10px;
@ -140,6 +155,40 @@
} }
} }
.row {
display: flex;
justify-content: space-around;
}
.description-theme {
color: white;
.col {
width: 54%;
}
img {
border-radius: 15px;
}
.createTheme {
display: flex;
flex-direction: column;
}
h5 {
font-size: 18px;
margin: 0;
}
h6 {
font-size: 17px;
margin: 0;
}
p {
font-size: 16px;
}
}
code { code {
display: none; display: none;
} }
@ -180,6 +229,7 @@ pre {
} }
.check-code { .check-code {
text-align: center;
width: 200px; width: 200px;
height: 35px; height: 35px;
cursor: pointer; cursor: pointer;
@ -210,3 +260,11 @@ pre {
height: 40px; height: 40px;
} }
} }
.version {
position: absolute;
color: white;
font-size: 10px;
right: 20px;
bottom: 0px;
}

View File

@ -31,6 +31,7 @@
<li><a href="/docs/index.html">Documentation</a></li> <li><a href="/docs/index.html">Documentation</a></li>
</ul> </ul>
</nav> </nav>
<p class="version">v. 0.2.4</p>
</header> </header>
</div> </div>
@ -192,6 +193,172 @@
</code> </code>
</div> </div>
<div class="example-select description-theme">
<h1 class="example-select_title">Setting up and adding a theme</h1>
<div class="layout-select">
<div class="row">
<div class="col">
<h5>Default theme:</h5>
<p style="margin-right: 50px">
To change the theme of the select, you need to specify this parameter in the select
settings. The default theme is the classic theme, you can choose a white or dark
theme.
</p>
<code style="display: block; margin-top: 32px">
<pre>
<span class="code__keyword">const</span> <span class="code__var">dropdown</span> = <span class="code__keyword">new</span> <span class="code__class">CGSelect</span>({
selector: <span class="code__string">'.cg-dropdown_one',</span>
placeholder: <span class="code__string">'Choose a car',</span>
lable: <span class="code__string">'EXAMPLE',</span>
items: [
...
],
<span class="code__keyword">theme</span>: <span class="code__string">'dark / white'</span>
});
</pre>
</code>
</div>
<div class="col">
<h5>Create custom theme:</h5>
<div class="createTheme">
<p style="margin-right: 25px">
To create your own theme, you need to create an object with the following fields.
In these fields you need to insert the previously created css class. After
creating the object, just pass it to the select settings.
</p>
<code style="display: block">
<pre>
<span class="code__keyword">interface</span> <span class="code__var">CustomTheme</span> {
name: <span class="code__class">'string',</span>
styles: {
head?: <span class="code__class">'string',</span>
list?: <span class="code__class">'testClass',</span> ,
placeholder?: <span class="code__class">'string',</span> ,
caret?: <span class="code__class">'string',</span> ,
search?: <span class="code__class">'string',</span> ,
chips?: <span class="code__class">'string',</span> ,
lable?: <span class="code__class">'string',</span> ,
},
});
</pre>
</code>
</div>
</div>
</div>
<h5 style="margin: 20px 0 5px; text-align: center">Example:</h5>
<div class="row">
<h6>For JS</h6>
<h6>For TS</h6>
</div>
<div class="row">
<code style="display: block">
<pre>
<span class="code__keyword">const</span> <span class="code__var">newTheme</span> = {
name: <span class="code__string">'test',</span>
styles: {
head: <span class="code__string">'headTestClass',</span>
list: <span class="code__string">'listTestClass',</span> ,
placeholder: <span class="code__string">'placeholderTestClass',</span> ,
caret: <span class="code__string">'caretTestClass',</span> ,
search: <span class="code__string">'searchTestClass',</span> ,
chips: <span class="code__string">'chipsTestClass',</span> ,
lable: <span class="code__string">'lableTestClass',</span> ,
},
});
</pre>
</code>
<code style="display: block">
<pre>
<span class="code__keyword">const</span> <span class="code__var">newCustomTheme</span>:<span class="code__class"> CustomTheme</span> = {
name: <span class="code__string">'test',</span>
styles: {
head: <span class="code__string">'headTestClass',</span>
list: <span class="code__string">'listTestClass',</span> ,
placeholder: <span class="code__string">'placeholderTestClass',</span> ,
caret: <span class="code__string">'caretTestClass',</span> ,
search: <span class="code__string">'searchTestClass',</span> ,
chips: <span class="code__string">'chipsTestClass',</span> ,
lable: <span class="code__string">'lableTestClass',</span> ,
},
});
</pre>
</code>
</div>
<h6>CSS</h6>
<code style="display: block; width: 44%">
<pre>
.headTestClass {
background-color: #8297ff;
color: white;
}
.listTestClass {
background-color: #8297ff;
border: 1px solid black;
color: white;
}
</pre>
</code>
<h6>Example custom theme in CG-Select</h6>
<p>
See an example of a select on
<a
href="https://codesandbox.io/p/sandbox/cg-select-example-eq9rle?file=%2Fsrc%2Findex.js"
style="font-size: 16px; color: #88d0f7"
>codesandbox.io</a
>
</p>
<div class="layout-select" style="margin-bottom: 60px">
<button class="cg-dropdown cg-dropdown_theme"></button>
</div>
</div>
</div>
<div class="example-select">
<h1 class="example-select_title">Select constructor</h1>
<div class="row" style="margin: 20px; color: white">
<div class="col">
<h5 style="font-size: 18px; margin: 0;">Select Style Builder:</h5>
<p style="margin-right: 50px; font-size: 17px">
This is a constructor for styling a select online without downloading. For it to work,
you need to:
<ol style="font-size: 15px;">
<li class="liList">Select a part of the select for customization. </li>
<li class="liList">Enter styles in the text field in the form "color: red;".</li>
<li class="liList">Click on the render button.</li>
</ol>
</p>
</div>
<div class="col">
<div class="layout-select constructor">
<button class="cg-dropdown body"></button>
<textarea
name="styles"
id="styles"
cols="30"
rows="5"
class="textareaStyle"
placeholder="Enter CSS properties"
disabled="disabled"
></textarea>
<button type="button" class="check-code render">Render</button>
</div>
</div>
</div>
<div class="layout-select constructor" style="margin-bottom: 60px;">
<button class="cg-dropdown select"></button>
</div>
</div>
<div class="example-select"> <div class="example-select">
<h1 class="example-select_title">Categories</h1> <h1 class="example-select_title">Categories</h1>

View File

@ -1,5 +1,8 @@
import { CGSelect } from '../src/cg-select'; import { CGSelect } from '../src/cg-select';
import './example'; import { newCustomTheme } from './src/themeTest';
import './src/example';
import './src/constructor/constructor';
// ------------------------------Обычный селект-------------------- // ------------------------------Обычный селект--------------------
const dropdown = new CGSelect({ const dropdown = new CGSelect({
@ -27,10 +30,34 @@ const dropdown = new CGSelect({
}, },
}); });
dropdown.on('clear', function (e) { // dropdown.on('clear', function (e) {
console.log(`this state: ${e}`); // console.log(`this state: ${e}`);
}); // });
const droptheme = new CGSelect({
selector: '.cg-dropdown_theme',
placeholder: 'Choose a car',
items: [
'BMW',
{
id: '213sade',
title: 'Opel',
value: 1,
},
'Mersedes',
'MAN',
'Ferari',
],
styles: {
head: {
width: '830px',
},
list: {
width: '824px',
},
},
theme: newCustomTheme,
});
// ------------------------------NativeSelect----------------------- // ------------------------------NativeSelect-----------------------
const dropdownNativeSelect = new CGSelect({ const dropdownNativeSelect = new CGSelect({
selector: '.cg-dropdown_selectNative', selector: '.cg-dropdown_selectNative',

View File

@ -0,0 +1,83 @@
import { CGSelect } from '../../../src/cg-select';
const body = new CGSelect({
selector: '.body',
placeholder: 'Select element to style',
items: ['head', 'list', 'placeholder', 'caret', 'search'],
});
let head = '';
let list = '';
let placeholder = '';
let caret = '';
let valueSelect = '';
const textarea = document.querySelector('#styles');
const renderBtn = document.querySelector('.render');
body.on('select', (e, value) => {
valueSelect = value;
textarea.value = '';
textarea.removeAttribute('disabled');
getValueSelect(valueSelect);
});
function getValueSelect(value) {
textarea.onkeyup = function () {
switch (value) {
case 'head':
// ввод стилей
head = textarea.value;
break;
case 'list':
list = textarea.value;
break;
case 'placeholder':
placeholder = textarea.value;
break;
case 'caret':
caret = textarea.value;
break;
case 'search':
search = textarea.value;
break;
default:
break;
}
};
}
renderBtn.addEventListener('click', () => {
const select = new CGSelect({
selector: '.select',
placeholder: 'Choose a car',
label: 'Exemple select',
items: [
'BMW',
{
id: '213sade',
title: 'Opel',
value: 1,
},
'Mersedes',
'MAN',
'Ferari',
],
searchMode: true,
multiselect: true,
multiselectTag: true,
});
const drop = document.querySelector('.select');
let headSelect = drop.querySelector('.cg-select');
let listSelect = drop.querySelector('.list');
let placeholderSelect = drop.querySelector('.selected');
let caretSelect = drop.querySelector('.caret');
let searchSelect = drop.querySelector('.inputSearch');
headSelect.setAttribute('style', head);
listSelect.setAttribute('style', list);
placeholderSelect.setAttribute('style', placeholder);
caretSelect.setAttribute('style', caret);
searchSelect.setAttribute('style', search);
});

View File

@ -0,0 +1,16 @@
.textareaStyle {
resize: none;
border-radius: 5px;
margin: 15px;
}
.constructor {
display: flex;
align-items: center;
flex-direction: column;
}
.liList {
margin-bottom: 5px;
font-size: 17px;
}

View File

@ -13,38 +13,36 @@ const codeFourth = document.getElementById('codeFourth');
const fifthBtn = document.getElementById('fifth'); const fifthBtn = document.getElementById('fifth');
const codeFifth = document.getElementById('codeFifth'); const codeFifth = document.getElementById('codeFifth');
const six = document.getElementById('six') const six = document.getElementById('six');
const codeSix = document.getElementById('codeSix'); const codeSix = document.getElementById('codeSix');
const Native = document.getElementById('Native');
const Native = document.getElementById('Native') const codeNative = document.getElementById('codeNative');
const codeNative = document.getElementById('codeNative')
firstBtn.addEventListener('click', () => { firstBtn.addEventListener('click', () => {
codeFirst.classList.toggle("active") codeFirst.classList.toggle('active');
}) });
secondBtn.addEventListener('click', () => { secondBtn.addEventListener('click', () => {
codeSecond.classList.toggle("active") codeSecond.classList.toggle('active');
}) });
thirdBtn.addEventListener('click', () => { thirdBtn.addEventListener('click', () => {
codeThird.classList.toggle("active") codeThird.classList.toggle('active');
}) });
fourthBtn.addEventListener('click', () => { fourthBtn.addEventListener('click', () => {
codeFourth.classList.toggle("active") codeFourth.classList.toggle('active');
}) });
fifthBtn.addEventListener('click', () => { fifthBtn.addEventListener('click', () => {
codeFifth.classList.toggle("active") codeFifth.classList.toggle('active');
}) });
six.addEventListener('click', () => { six.addEventListener('click', () => {
codeSix.classList.toggle("active") codeSix.classList.toggle('active');
}) });
Native.addEventListener('click', () => { Native.addEventListener('click', () => {
codeNative.classList.toggle("active") codeNative.classList.toggle('active');
}) });

9
example/src/themeTest.ts Normal file
View File

@ -0,0 +1,9 @@
import { CustomTheme } from 'components/theme/theme.interface';
export const newCustomTheme: CustomTheme = {
name: 'test',
styles: {
head: 'testClass',
list: 'listTest',
},
};

4
package-lock.json generated
View File

@ -1,12 +1,12 @@
{ {
"name": "cg-select", "name": "cg-select",
"version": "0.2.33", "version": "0.2.4",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "cg-select", "name": "cg-select",
"version": "0.2.33", "version": "0.2.4",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"@parcel/optimizer-css": "^2.8.0", "@parcel/optimizer-css": "^2.8.0",

View File

@ -1,6 +1,6 @@
{ {
"name": "cg-select", "name": "cg-select",
"version": "0.2.33", "version": "0.2.4",
"description": "Feature rich Select control for React/JS with multiselect, autocomplete and styling", "description": "Feature rich Select control for React/JS with multiselect, autocomplete and styling",
"author": { "author": {
"name": "CraftGroup", "name": "CraftGroup",

View File

@ -25,6 +25,7 @@ import { ILanguage } from './interfaces/language.interface';
import './main.scss'; import './main.scss';
import { changeTheme } from './components/theme/theme'; import { changeTheme } from './components/theme/theme';
import { CustomTheme } from 'components/theme/theme.interface';
/** /**
* @class Class Description ICgSelect * @class Class Description ICgSelect
@ -36,7 +37,7 @@ export class CGSelect implements ICgSelect {
selected?: string; selected?: string;
placeholder?: string; placeholder?: string;
items?: IItems[] | string[] | any; items?: IItems[] | string[] | any;
theme?: string; theme?: string | CustomTheme;
searchMode?: boolean; searchMode?: boolean;
closeOnSelect?: boolean; closeOnSelect?: boolean;
nativeSelectMode?: boolean; nativeSelectMode?: boolean;
@ -916,17 +917,19 @@ export class CGSelect implements ICgSelect {
* @param callback * @param callback
* @method on * @method on
*/ */
public on(state: string, callback: (state: any) => any) { public on(state: string, callback: (state: any, value?: string) => any) {
const options = this.element?.querySelectorAll('.list__item'); const options = this.element?.querySelectorAll('.list__item');
let value = '';
switch (state) { switch (state) {
case 'select': case 'select':
options?.forEach((option: Element) => { options?.forEach((option: Element) => {
option.addEventListener('click', () => { option.addEventListener('click', () => {
console.log('option:select', option.textContent); console.log('option:select', option.textContent);
value = option.textContent!;
callback(state, value);
}); });
}); });
callback(state);
break; break;
case 'close': case 'close':
this.element!.addEventListener('click', () => { this.element!.addEventListener('click', () => {

View File

@ -0,0 +1,12 @@
export interface CustomTheme {
name: string;
styles: {
head?: string;
list?: string;
placeholder?: string;
caret?: string;
search?: string;
chips?: string;
lable?: string;
};
}

View File

@ -1,4 +1,6 @@
export function changeTheme(element: Element, theme: string) { import { CustomTheme } from './theme.interface';
export function changeTheme(element: Element, theme: string | CustomTheme) {
const select = element!.querySelector('.cg-select'); const select = element!.querySelector('.cg-select');
const caret = element!.querySelector('.caret'); const caret = element!.querySelector('.caret');
const list = element!.querySelector('ul.list'); const list = element!.querySelector('ul.list');
@ -13,32 +15,37 @@ export function changeTheme(element: Element, theme: string) {
elem.classList.remove('pathWhite'); elem.classList.remove('pathWhite');
}); });
switch (theme.toLowerCase()) { if (typeof theme === 'string') {
case 'dark': switch (theme) {
select!.classList.add('selectDark'); case 'dark':
list!.classList.add('listDark'); select!.classList.add('selectDark');
nativeSelect?.classList.add('listDark'); list!.classList.add('listDark');
path.forEach((elem) => { nativeSelect?.classList.add('listDark');
elem.classList.add('pathWhite'); path.forEach((elem) => {
}); elem.classList.add('pathWhite');
break; });
case 'white': break;
select!.classList.add('selectWhite'); case 'white':
caret!.classList.add('caretWhite'); select!.classList.add('selectWhite');
list!.classList.add('listWhite'); caret!.classList.add('caretWhite');
nativeSelect?.classList.add('listWhite'); list!.classList.add('listWhite');
path.forEach((elem) => { nativeSelect?.classList.add('listWhite');
elem.classList.add('pathBlack'); path.forEach((elem) => {
}); elem.classList.add('pathBlack');
});
if (search!) { if (search!) {
search!.classList.add('inputWhite'); search!.classList.add('inputWhite');
} }
break; break;
default: default:
select!.classList.add('classicSelect'); select!.classList.add('classicSelect');
list!.classList.add('classicList'); list!.classList.add('classicList');
break; break;
}
} else {
select!.classList.add(`${theme.styles.head}`);
list!.classList.add(`${theme.styles.list}`);
} }
} }

View File

@ -1,3 +1,4 @@
import { CustomTheme } from 'components/theme/theme.interface';
import { IItems } from 'interfaces/items.interface'; import { IItems } from 'interfaces/items.interface';
/** /**
@ -55,5 +56,5 @@ export interface ISelectedItems {
* An optional parameter that is responsible for enabling a light/dark theme by default, the dark theme is set. * An optional parameter that is responsible for enabling a light/dark theme by default, the dark theme is set.
* @type {boolean} * @type {boolean}
*/ */
theme?: string; theme?: string | CustomTheme;
} }

View File

@ -1,3 +1,4 @@
import { CustomTheme } from 'components/theme/theme.interface';
import { IItems } from './items.interface'; import { IItems } from './items.interface';
/** /**
@ -29,7 +30,7 @@ export interface ICgSelect {
* An optional parameter responsible for switching between different themes, the classic theme is set by default. * An optional parameter responsible for switching between different themes, the classic theme is set by default.
* @type {string} values: dark, white * @type {string} values: dark, white
*/ */
theme?: string; theme?: string | CustomTheme;
/** /**
* An optional parameter that adds a live search on the select elements. * An optional parameter that adds a live search on the select elements.
* @type {boolean} * @type {boolean}