add increase-decrease font size buttons

This commit is contained in:
Sergey Krylov 2022-07-11 15:06:52 +05:00
parent e1ad90fc6f
commit c92ae3a38d
7 changed files with 114 additions and 32 deletions

View File

@ -34,13 +34,14 @@ module.exports = {
"import/prefer-default-export": "off", "import/prefer-default-export": "off",
"linebreak-style": "off", "linebreak-style": "off",
"max-len": "off", "max-len": "off",
"no-console": "off",
"no-new": "off",
"no-continue": "off",
"no-plusplus": "off",
"object-curly-newline": "off",
"no-alert": "off", "no-alert": "off",
"no-console": "off",
"no-continue": "off",
"no-new": "off",
"no-plusplus": "off",
"no-restricted-globals": "off", "no-restricted-globals": "off",
"object-curly-newline": "off",
"prefer-destructuring": "off",
}, },
env: { env: {
browser: true, browser: true,

View File

@ -3,7 +3,7 @@ import { $, Dom } from 'core/Dom';
import { ExcelComponentState } from 'core/ExcelComponentState'; import { ExcelComponentState } from 'core/ExcelComponentState';
import { ComponentOptionsType } from 'core/ExcelComponent'; import { ComponentOptionsType } from 'core/ExcelComponent';
import { createToolbar } from 'components/toolbar/toolbar.template'; import { createToolbar } from 'components/toolbar/toolbar.template';
import { initialStyleState } from 'src/constants'; import { fontSizes, initialStyleState } from 'src/constants';
export class Toolbar extends ExcelComponentState { export class Toolbar extends ExcelComponentState {
static className = 'excel__toolbar'; static className = 'excel__toolbar';
@ -44,11 +44,41 @@ export class Toolbar extends ExcelComponentState {
onClick(event: MouseEvent) { onClick(event: MouseEvent) {
const target = $(event.target as HTMLElement); const target = $(event.target as HTMLElement);
const stringValue = target?.data?.value;
if (!stringValue) return;
const value = JSON.parse(stringValue); let stringValue;
const key = Object.keys(value)[0]; let value;
let key;
switch (true) {
case !!target.closest('[data-change-size]').$el: {
const el = target.closest('[data-change-size]');
if (el.hasClass('disable')) return;
const currentSize = this.store.getState().currentStyles.fontSize;
let idx = fontSizes.findIndex(font => font === currentSize);
let nextSize;
if (el.data.changeSize === 'increase') {
nextSize = fontSizes[++idx];
} else if (el.data.changeSize === 'decrease') {
nextSize = fontSizes[--idx];
}
value = { fontSize: nextSize };
key = 'fontSize';
break;
}
default: {
stringValue = target?.data?.value;
if (!stringValue) return;
value = JSON.parse(stringValue);
key = Object.keys(value)[0];
}
}
this.$emitEventToObserver('toolbar:applyStyle', value); this.$emitEventToObserver('toolbar:applyStyle', value);
this.setComponentState({ [key]: value[key] }); this.setComponentState({ [key]: value[key] });

View File

@ -1,5 +1,6 @@
import { ToolbarStateType } from 'components/toolbar/toolbar-types'; import { ToolbarStateType } from 'components/toolbar/toolbar-types';
import { initialStyleState } from 'src/constants'; import { isLargestFontSize, isSmallestFontSize } from 'core/utils';
import { fontFamilies, fontSizes, initialStyleState } from 'src/constants';
type ButtonConfigType = { type ButtonConfigType = {
icon: string; icon: string;
@ -80,21 +81,38 @@ export function createToolbar(state: ToolbarStateType): string {
], ],
]; ];
const buttons = btns.map(btn => (Array.isArray(btn) ? toButtonGroup(btn) : toButton(btn))); const buttons = btns.map(btn => (Array.isArray(btn) ? createButtonsFromConfigGroup(btn) : createButtonFromConfig(btn)));
const selectGroup = createGroup(createFontSizeButton(state.fontSize), createFontFamilyButton(state.fontFamily)); const selectGroup = createGroup(createFontSizeButton(state.fontSize), createFontFamilyButton(state.fontFamily));
const increaseDecreaseFontSize = createSizeUpDownButtons(state.fontSize);
buttons.push(increaseDecreaseFontSize);
buttons.push(selectGroup); buttons.push(selectGroup);
return buttons.join(' ');
return buttons.join('');
}
function createSizeUpDownButtons(currentSize = initialStyleState.fontSize) {
const buttons = ['increase', 'decrease'];
return buttons.map(btn => {
const disable = btn === 'increase' ? isLargestFontSize(currentSize) : isSmallestFontSize(currentSize);
return `
<div class="button${disable ? ' disable' : ''}" data-change-size="${btn}">
<i class="material-icons">text_${btn}</i>
</div>
`;
}).join('');
} }
function createFontSizeButton(currentSize = initialStyleState.fontSize) { function createFontSizeButton(currentSize = initialStyleState.fontSize) {
const fontSizeInPixels = +currentSize.slice(0, -2); const options = fontSizes.map(size => {
const options = []; // remove 'px' part
const sizeValue = size.slice(0, -2);
for (let i = 8; i <= 24; i += 2) { return size === currentSize
if (fontSizeInPixels === i) options.push(`<option value="${i}" selected>${i}</option>`); ? `<option value="${sizeValue}" selected>${sizeValue}</option>`
else options.push(`<option value="${i}">${i}</option>`); : `<option value="${sizeValue}">${sizeValue}</option>`;
} });
return ` return `
<div class="button"> <div class="button">
@ -106,12 +124,11 @@ function createFontSizeButton(currentSize = initialStyleState.fontSize) {
} }
function createFontFamilyButton(font = initialStyleState.fontFamily) { function createFontFamilyButton(font = initialStyleState.fontFamily) {
const fonts = ['Roboto', 'Cormorant SC', 'Kanit', 'Playfair Display']; const options = fontFamilies.map(fontName => createFontFamilyOption(fontName, fontName === font));
const options = fonts.map(fontName => createFontFamilyOption(fontName, fontName === font));
function createFontFamilyOption(name: string, selected: boolean) { function createFontFamilyOption(name: string, selected: boolean) {
return selected return selected
? `<option value="${name}" selected style="font-family: ${name}">${name}</option>` ? `<option value="${name}" style="font-family: ${name}" selected >${name}</option>`
: `<option value="${name}" style="font-family: ${name}">${name}</option>`; : `<option value="${name}" style="font-family: ${name}">${name}</option>`;
} }
@ -132,22 +149,22 @@ function createGroup(...btns: string[]) {
`; `;
} }
function toButtonGroup(buttons: ButtonConfigType[]) { function createButtonsFromConfigGroup(buttons: ButtonConfigType[]) {
if (buttons.length === 1) return toButton(buttons[0]); if (buttons.length === 1) return createButtonFromConfig(buttons[0]);
const btns = buttons.map(btn => toButton(btn)); const btns = buttons.map(btn => createButtonFromConfig(btn));
return createGroup(...btns); return createGroup(...btns);
} }
function toButton(button: ButtonConfigType) { function createButtonFromConfig(btnConfig: ButtonConfigType) {
const meta = ` const meta = `
data-type="button" data-type="button"
data-value='${JSON.stringify(button.value)}' data-value='${JSON.stringify(btnConfig.value)}'
`; `;
return ` return `
<div class="button ${button.isActive ? 'active' : ''}"${meta}> <div class="button ${btnConfig.isActive ? 'active' : ''}"${meta}>
<i class="material-icons" ${meta}>${button.icon}</i> <i class="material-icons" ${meta}>${btnConfig.icon}</i>
</div> </div>
`; `;
} }

View File

@ -4,13 +4,27 @@ import { storageName } from 'pages/ExcelPage';
import { StateType } from 'redux/types'; import { StateType } from 'redux/types';
import { storage } from 'core/utils'; import { storage } from 'core/utils';
export const fontSizes = [
'12px',
'14px',
'16px',
'18px',
'20px',
'22px',
'24px',
'26px',
'28px',
'30px',
];
export const fontFamilies = ['Roboto', 'Cormorant SC', 'Kanit', 'Playfair Display'];
export const initialStyleState: ToolbarStateType = { export const initialStyleState: ToolbarStateType = {
justifyContent: 'start', justifyContent: 'start',
fontWeight: 'normal', fontWeight: 'normal',
textDecoration: 'none', textDecoration: 'none',
fontStyle: 'normal', fontStyle: 'normal',
fontSize: '12px', fontSize: fontSizes[0],
fontFamily: 'Roboto', fontFamily: fontFamilies[0],
alignItems: 'start', alignItems: 'start',
}; };

View File

@ -105,6 +105,10 @@ export class Dom implements DomClass {
this.$el?.classList.add(className); this.$el?.classList.add(className);
} }
hasClass(className: string) {
return Array.from(this.$el.classList).includes(className);
}
removeClass(className: string) { removeClass(className: string) {
this.$el?.classList.remove(className); this.$el?.classList.remove(className);
} }

View File

@ -1,3 +1,5 @@
import { fontSizes } from 'src/constants';
export function capitalize(string: string): string { export function capitalize(string: string): string {
if (!string) return ''; if (!string) return '';
@ -49,3 +51,13 @@ export function parse(value: string) {
return value; return value;
} }
export function isLargestFontSize(fontSize?: string): number | boolean {
if (!fontSize) return false;
return fontSizes.length - 1 === fontSizes.findIndex(el => el === fontSize);
}
export function isSmallestFontSize(fontSize?: string): number | boolean {
if (!fontSize) return false;
return fontSizes.findIndex(el => el === fontSize) === 0;
}

View File

@ -16,6 +16,10 @@
@include button(green) @include button(green)
} }
.button.disable {
cursor: not-allowed;
}
.button__group { .button__group {
border-right: 1px solid #c0c0c0; border-right: 1px solid #c0c0c0;
&:last-child { &:last-child {