diff --git a/CHANGELOG.md b/CHANGELOG.md index 6675a8f..b7cb891 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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. - Documentation navigation update. - 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. diff --git a/README.md b/README.md index 0886619..7b9e6c0 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # 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. Customization, multi-selection and live search by elements are available. diff --git a/READMERU.md b/READMERU.md index a361de9..96a7874 100644 --- a/READMERU.md +++ b/READMERU.md @@ -1,6 +1,6 @@ # CG-SELECT -## version ~ 0.2.33 +## version ~ 0.2.4 Этот компонент позволяет вам создать пользовательский Select. Он предлагает более гибкую настройку и использование select. Доступна кастомизация, multi-selection, живой поиск по элементам и многое другое. diff --git a/docs/index.html b/docs/index.html index 99b1f79..5a8e523 100644 --- a/docs/index.html +++ b/docs/index.html @@ -62,7 +62,7 @@ -

version ~ 0.2.33

+

version ~ 0.2.4

This component allows you to create a custom select. It offers more flexible diff --git a/example/example.scss b/example/example.scss index b1bd873..a4e07c5 100644 --- a/example/example.scss +++ b/example/example.scss @@ -1,8 +1,21 @@ @import '/src/main.scss'; +@import './src/constructor/constructor.scss'; * { font-size: 14px; 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 { @@ -30,6 +43,7 @@ } .header { + position: relative; width: 100%; border-radius: 5px; display: flex; @@ -112,6 +126,7 @@ } &_submit { + text-align: center; width: 200px; height: 35px; 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 { display: none; } @@ -180,6 +229,7 @@ pre { } .check-code { + text-align: center; width: 200px; height: 35px; cursor: pointer; @@ -210,3 +260,11 @@ pre { height: 40px; } } + +.version { + position: absolute; + color: white; + font-size: 10px; + right: 20px; + bottom: 0px; +} diff --git a/example/index.html b/example/index.html index b316ee7..8863a25 100644 --- a/example/index.html +++ b/example/index.html @@ -31,6 +31,7 @@

  • Documentation
  • +

    v. 0.2.4

    @@ -192,6 +193,172 @@ +
    +

    Setting up and adding a theme

    + +
    +
    +
    +
    Default theme:
    +

    + 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. +

    + +
    +                  const dropdown = new CGSelect({
    +                    selector: '.cg-dropdown_one', 
    +                    placeholder: 'Choose a car', 
    +                    lable: 'EXAMPLE', 
    +                    items: [
    +                      ...
    +                    ],
    +                    theme:  'dark / white'
    +                  });
    +                
    +
    +
    + +
    +
    Create custom theme:
    +
    +

    + 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. +

    + +
    +            interface CustomTheme {
    +              name: 'string', 
    +              styles: {
    +                head?:  'string', 
    +                list?: 'testClass', ,
    +                placeholder?: 'string', ,
    +                caret?: 'string', ,
    +                search?: 'string', ,
    +                chips?: 'string', ,
    +                lable?: 'string', ,
    +              },
    +            });
    +                  
    +
    +
    +
    +
    + +
    Example:
    + +
    +
    For JS
    +
    For TS
    +
    + +
    + +
    +        const newTheme = {
    +          name: 'test', 
    +          styles: {
    +            head:  'headTestClass', 
    +            list: 'listTestClass', ,
    +            placeholder: 'placeholderTestClass', ,
    +            caret: 'caretTestClass', ,
    +            search: 'searchTestClass', ,
    +            chips: 'chipsTestClass', ,
    +            lable: 'lableTestClass', ,
    +          },
    +        });
    +              
    +
    + + +
    +        const newCustomTheme: CustomTheme  = {
    +          name: 'test', 
    +          styles: {
    +            head:  'headTestClass', 
    +            list: 'listTestClass', ,
    +            placeholder: 'placeholderTestClass', ,
    +            caret: 'caretTestClass', ,
    +            search: 'searchTestClass', ,
    +            chips: 'chipsTestClass', ,
    +            lable: 'lableTestClass', ,
    +          },
    +        });
    +              
    +
    +
    +
    CSS
    + +
    +              .headTestClass {
    +                background-color: #8297ff;
    +                color: white;
    +              }
    +
    +              .listTestClass {
    +                background-color: #8297ff;
    +                border: 1px solid black;
    +                color: white;
    +              }
    +            
    +
    + +
    Example custom theme in CG-Select
    +

    + See an example of a select on + codesandbox.io +

    +
    + +
    +
    +
    + +
    +

    Select constructor

    +
    +
    +
    Select Style Builder:
    +

    + This is a constructor for styling a select online without downloading. For it to work, + you need to: +

      +
    1. Select a part of the select for customization.
    2. +
    3. Enter styles in the text field in the form "color: red;".
    4. +
    5. Click on the render button.
    6. +
    +

    +
    +
    +
    + + + +
    + +
    + +
    +
    + +
    +
    +

    Categories

    diff --git a/example/index.js b/example/index.js index c4a86d0..7ace743 100644 --- a/example/index.js +++ b/example/index.js @@ -1,5 +1,8 @@ import { CGSelect } from '../src/cg-select'; -import './example'; +import { newCustomTheme } from './src/themeTest'; + +import './src/example'; +import './src/constructor/constructor'; // ------------------------------Обычный селект-------------------- const dropdown = new CGSelect({ @@ -27,10 +30,34 @@ const dropdown = new CGSelect({ }, }); -dropdown.on('clear', function (e) { - console.log(`this state: ${e}`); -}); +// dropdown.on('clear', function (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----------------------- const dropdownNativeSelect = new CGSelect({ selector: '.cg-dropdown_selectNative', diff --git a/example/src/constructor/constructor.js b/example/src/constructor/constructor.js new file mode 100644 index 0000000..4df819e --- /dev/null +++ b/example/src/constructor/constructor.js @@ -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); +}); diff --git a/example/src/constructor/constructor.scss b/example/src/constructor/constructor.scss new file mode 100644 index 0000000..0739c16 --- /dev/null +++ b/example/src/constructor/constructor.scss @@ -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; +} diff --git a/example/example.js b/example/src/example.js similarity index 66% rename from example/example.js rename to example/src/example.js index f807677..2238b38 100644 --- a/example/example.js +++ b/example/src/example.js @@ -13,38 +13,36 @@ const codeFourth = document.getElementById('codeFourth'); const fifthBtn = document.getElementById('fifth'); const codeFifth = document.getElementById('codeFifth'); -const six = document.getElementById('six') +const six = document.getElementById('six'); const codeSix = document.getElementById('codeSix'); - -const Native = document.getElementById('Native') -const codeNative = document.getElementById('codeNative') - +const Native = document.getElementById('Native'); +const codeNative = document.getElementById('codeNative'); firstBtn.addEventListener('click', () => { - codeFirst.classList.toggle("active") -}) + codeFirst.classList.toggle('active'); +}); secondBtn.addEventListener('click', () => { - codeSecond.classList.toggle("active") -}) + codeSecond.classList.toggle('active'); +}); thirdBtn.addEventListener('click', () => { - codeThird.classList.toggle("active") -}) + codeThird.classList.toggle('active'); +}); fourthBtn.addEventListener('click', () => { - codeFourth.classList.toggle("active") -}) + codeFourth.classList.toggle('active'); +}); fifthBtn.addEventListener('click', () => { - codeFifth.classList.toggle("active") -}) + codeFifth.classList.toggle('active'); +}); six.addEventListener('click', () => { - codeSix.classList.toggle("active") -}) + codeSix.classList.toggle('active'); +}); Native.addEventListener('click', () => { - codeNative.classList.toggle("active") -}) \ No newline at end of file + codeNative.classList.toggle('active'); +}); diff --git a/example/src/themeTest.ts b/example/src/themeTest.ts new file mode 100644 index 0000000..ae66df1 --- /dev/null +++ b/example/src/themeTest.ts @@ -0,0 +1,9 @@ +import { CustomTheme } from 'components/theme/theme.interface'; + +export const newCustomTheme: CustomTheme = { + name: 'test', + styles: { + head: 'testClass', + list: 'listTest', + }, +}; diff --git a/package-lock.json b/package-lock.json index 0399bd1..0807227 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "cg-select", - "version": "0.2.33", + "version": "0.2.4", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "cg-select", - "version": "0.2.33", + "version": "0.2.4", "license": "ISC", "dependencies": { "@parcel/optimizer-css": "^2.8.0", diff --git a/package.json b/package.json index 09cdfdd..d7e3434 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cg-select", - "version": "0.2.33", + "version": "0.2.4", "description": "Feature rich Select control for React/JS with multiselect, autocomplete and styling", "author": { "name": "CraftGroup", diff --git a/src/cg-select.ts b/src/cg-select.ts index d760654..40a94e0 100644 --- a/src/cg-select.ts +++ b/src/cg-select.ts @@ -25,6 +25,7 @@ import { ILanguage } from './interfaces/language.interface'; import './main.scss'; import { changeTheme } from './components/theme/theme'; +import { CustomTheme } from 'components/theme/theme.interface'; /** * @class Class Description ICgSelect @@ -36,7 +37,7 @@ export class CGSelect implements ICgSelect { selected?: string; placeholder?: string; items?: IItems[] | string[] | any; - theme?: string; + theme?: string | CustomTheme; searchMode?: boolean; closeOnSelect?: boolean; nativeSelectMode?: boolean; @@ -916,17 +917,19 @@ export class CGSelect implements ICgSelect { * @param callback * @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'); + let value = ''; switch (state) { case 'select': options?.forEach((option: Element) => { option.addEventListener('click', () => { console.log('option:select', option.textContent); + value = option.textContent!; + callback(state, value); }); }); - callback(state); break; case 'close': this.element!.addEventListener('click', () => { diff --git a/src/components/theme/theme.interface.ts b/src/components/theme/theme.interface.ts new file mode 100644 index 0000000..af4420d --- /dev/null +++ b/src/components/theme/theme.interface.ts @@ -0,0 +1,12 @@ +export interface CustomTheme { + name: string; + styles: { + head?: string; + list?: string; + placeholder?: string; + caret?: string; + search?: string; + chips?: string; + lable?: string; + }; +} diff --git a/src/components/theme/theme.ts b/src/components/theme/theme.ts index cf2e58b..571c70d 100644 --- a/src/components/theme/theme.ts +++ b/src/components/theme/theme.ts @@ -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 caret = element!.querySelector('.caret'); const list = element!.querySelector('ul.list'); @@ -13,32 +15,37 @@ export function changeTheme(element: Element, theme: string) { elem.classList.remove('pathWhite'); }); - switch (theme.toLowerCase()) { - case 'dark': - select!.classList.add('selectDark'); - list!.classList.add('listDark'); - nativeSelect?.classList.add('listDark'); - path.forEach((elem) => { - elem.classList.add('pathWhite'); - }); - break; - case 'white': - select!.classList.add('selectWhite'); - caret!.classList.add('caretWhite'); - list!.classList.add('listWhite'); - nativeSelect?.classList.add('listWhite'); - path.forEach((elem) => { - elem.classList.add('pathBlack'); - }); + if (typeof theme === 'string') { + switch (theme) { + case 'dark': + select!.classList.add('selectDark'); + list!.classList.add('listDark'); + nativeSelect?.classList.add('listDark'); + path.forEach((elem) => { + elem.classList.add('pathWhite'); + }); + break; + case 'white': + select!.classList.add('selectWhite'); + caret!.classList.add('caretWhite'); + list!.classList.add('listWhite'); + nativeSelect?.classList.add('listWhite'); + path.forEach((elem) => { + elem.classList.add('pathBlack'); + }); - if (search!) { - search!.classList.add('inputWhite'); - } - break; + if (search!) { + search!.classList.add('inputWhite'); + } + break; - default: - select!.classList.add('classicSelect'); - list!.classList.add('classicList'); - break; + default: + select!.classList.add('classicSelect'); + list!.classList.add('classicList'); + break; + } + } else { + select!.classList.add(`${theme.styles.head}`); + list!.classList.add(`${theme.styles.list}`); } } diff --git a/src/components/utils/utils.interface.ts b/src/components/utils/utils.interface.ts index 31ca536..d139979 100644 --- a/src/components/utils/utils.interface.ts +++ b/src/components/utils/utils.interface.ts @@ -1,3 +1,4 @@ +import { CustomTheme } from 'components/theme/theme.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. * @type {boolean} */ - theme?: string; + theme?: string | CustomTheme; } diff --git a/src/interfaces/cg-select.interface.ts b/src/interfaces/cg-select.interface.ts index 403b1a6..39a0f07 100644 --- a/src/interfaces/cg-select.interface.ts +++ b/src/interfaces/cg-select.interface.ts @@ -1,3 +1,4 @@ +import { CustomTheme } from 'components/theme/theme.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. * @type {string} values: dark, white */ - theme?: string; + theme?: string | CustomTheme; /** * An optional parameter that adds a live search on the select elements. * @type {boolean}