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",
"linebreak-style": "off",
"max-len": "off",
"no-console": "off",
"no-new": "off",
"no-continue": "off",
"no-plusplus": "off",
"object-curly-newline": "off",
"no-alert": "off",
"no-console": "off",
"no-continue": "off",
"no-new": "off",
"no-plusplus": "off",
"no-restricted-globals": "off",
"object-curly-newline": "off",
"prefer-destructuring": "off",
},
env: {
browser: true,

View File

@ -3,7 +3,7 @@ import { $, Dom } from 'core/Dom';
import { ExcelComponentState } from 'core/ExcelComponentState';
import { ComponentOptionsType } from 'core/ExcelComponent';
import { createToolbar } from 'components/toolbar/toolbar.template';
import { initialStyleState } from 'src/constants';
import { fontSizes, initialStyleState } from 'src/constants';
export class Toolbar extends ExcelComponentState {
static className = 'excel__toolbar';
@ -44,11 +44,41 @@ export class Toolbar extends ExcelComponentState {
onClick(event: MouseEvent) {
const target = $(event.target as HTMLElement);
const stringValue = target?.data?.value;
let stringValue;
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;
const value = JSON.parse(stringValue);
const key = Object.keys(value)[0];
value = JSON.parse(stringValue);
key = Object.keys(value)[0];
}
}
this.$emitEventToObserver('toolbar:applyStyle', value);
this.setComponentState({ [key]: value[key] });

View File

@ -1,5 +1,6 @@
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 = {
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 increaseDecreaseFontSize = createSizeUpDownButtons(state.fontSize);
buttons.push(increaseDecreaseFontSize);
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) {
const fontSizeInPixels = +currentSize.slice(0, -2);
const options = [];
for (let i = 8; i <= 24; i += 2) {
if (fontSizeInPixels === i) options.push(`<option value="${i}" selected>${i}</option>`);
else options.push(`<option value="${i}">${i}</option>`);
}
const options = fontSizes.map(size => {
// remove 'px' part
const sizeValue = size.slice(0, -2);
return size === currentSize
? `<option value="${sizeValue}" selected>${sizeValue}</option>`
: `<option value="${sizeValue}">${sizeValue}</option>`;
});
return `
<div class="button">
@ -106,12 +124,11 @@ function createFontSizeButton(currentSize = initialStyleState.fontSize) {
}
function createFontFamilyButton(font = initialStyleState.fontFamily) {
const fonts = ['Roboto', 'Cormorant SC', 'Kanit', 'Playfair Display'];
const options = fonts.map(fontName => createFontFamilyOption(fontName, fontName === font));
const options = fontFamilies.map(fontName => createFontFamilyOption(fontName, fontName === font));
function createFontFamilyOption(name: string, selected: boolean) {
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>`;
}
@ -132,22 +149,22 @@ function createGroup(...btns: string[]) {
`;
}
function toButtonGroup(buttons: ButtonConfigType[]) {
if (buttons.length === 1) return toButton(buttons[0]);
const btns = buttons.map(btn => toButton(btn));
function createButtonsFromConfigGroup(buttons: ButtonConfigType[]) {
if (buttons.length === 1) return createButtonFromConfig(buttons[0]);
const btns = buttons.map(btn => createButtonFromConfig(btn));
return createGroup(...btns);
}
function toButton(button: ButtonConfigType) {
function createButtonFromConfig(btnConfig: ButtonConfigType) {
const meta = `
data-type="button"
data-value='${JSON.stringify(button.value)}'
data-value='${JSON.stringify(btnConfig.value)}'
`;
return `
<div class="button ${button.isActive ? 'active' : ''}"${meta}>
<i class="material-icons" ${meta}>${button.icon}</i>
<div class="button ${btnConfig.isActive ? 'active' : ''}"${meta}>
<i class="material-icons" ${meta}>${btnConfig.icon}</i>
</div>
`;
}

View File

@ -4,13 +4,27 @@ import { storageName } from 'pages/ExcelPage';
import { StateType } from 'redux/types';
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 = {
justifyContent: 'start',
fontWeight: 'normal',
textDecoration: 'none',
fontStyle: 'normal',
fontSize: '12px',
fontFamily: 'Roboto',
fontSize: fontSizes[0],
fontFamily: fontFamilies[0],
alignItems: 'start',
};

View File

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

View File

@ -1,3 +1,5 @@
import { fontSizes } from 'src/constants';
export function capitalize(string: string): string {
if (!string) return '';
@ -49,3 +51,13 @@ export function parse(value: string) {
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)
}
.button.disable {
cursor: not-allowed;
}
.button__group {
border-right: 1px solid #c0c0c0;
&:last-child {