feat(icons): codex icons package is used instead of svg sprite (#2173)

* chore(icons): migrating to the coded icon pack

* conversion toolbar

* inline toolbar, part 1

* inline-link tool has the new icons

* added a test for creating a link by Enter keydown in link input

* rm last icons, svg sprite, loaders

* rollback .ce-settings styles

* Update CHANGELOG.md

* Update settings.json
This commit is contained in:
Peter Savchenko 2022-11-25 22:26:23 +04:00 committed by GitHub
parent f0f8f8fcb5
commit b1b582b150
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
39 changed files with 1860 additions and 3102 deletions

View file

@ -2,6 +2,7 @@
"cSpell.words": [ "cSpell.words": [
"Behaviour", "Behaviour",
"cacheable", "cacheable",
"childs",
"codexteam", "codexteam",
"colspan", "colspan",
"contenteditable", "contenteditable",
@ -11,6 +12,7 @@
"editorjs", "editorjs",
"entrypoints", "entrypoints",
"Flippable", "Flippable",
"GRAMMARLY",
"hsablonniere", "hsablonniere",
"intellij", "intellij",
"keydowns", "keydowns",

View file

@ -6,6 +6,7 @@
- `New`*UI* — Block Tunes became vertical just like the Toolbox 🤩 - `New`*UI* — Block Tunes became vertical just like the Toolbox 🤩
- `New`*Block Tunes API* — Now `render()` method of a Block Tune can return config with just icon, label and callback instead of custom HTML. This impovement is a key to the new straightforward way of configuring tune's appearance in Block Tunes menu. - `New`*Block Tunes API* — Now `render()` method of a Block Tune can return config with just icon, label and callback instead of custom HTML. This impovement is a key to the new straightforward way of configuring tune's appearance in Block Tunes menu.
- `New`*Tools API* — As well as `render()` in `Tunes API`, Tool's `renderSettings()` now also supports new configuration format. - `New`*Tools API* — As well as `render()` in `Tunes API`, Tool's `renderSettings()` now also supports new configuration format.
- `New`*UI* — Meet the new icons from [CodeX Icons](https://github.com/codex-team/icons) pack 🛍 💝
- `Deprecated`*Styles API* — CSS classes `.cdx-settings-button` and `.cdx-settings-button--active` are not recommended to use. Consider configuring your block settings with new JSON API instead. - `Deprecated`*Styles API* — CSS classes `.cdx-settings-button` and `.cdx-settings-button--active` are not recommended to use. Consider configuring your block settings with new JSON API instead.
- `Fix` — Wrong element not highlighted anymore when popover opened. - `Fix` — Wrong element not highlighted anymore when popover opened.
- `Fix` — When Tunes Menu open keydown events can not be handled inside plugins. - `Fix` — When Tunes Menu open keydown events can not be handled inside plugins.

View file

@ -13,15 +13,14 @@
], ],
"scripts": { "scripts": {
"clear": "rimraf dist && mkdirp dist", "clear": "rimraf dist && mkdirp dist",
"build": "yarn clear && yarn svg && yarn build:webpack:prod", "build": "yarn clear && yarn build:webpack:prod",
"build:dev": "yarn clear && yarn svg && yarn build:webpack:dev", "build:dev": "yarn clear && yarn build:webpack:dev",
"build:webpack:dev": "webpack --mode development --progress --display-error-details --display-entrypoints --watch", "build:webpack:dev": "webpack --mode development --progress --display-error-details --display-entrypoints --watch",
"build:webpack:prod": "webpack --mode production", "build:webpack:prod": "webpack --mode production",
"lint": "eslint src/ --ext .ts && yarn lint:tests", "lint": "eslint src/ --ext .ts && yarn lint:tests",
"lint:errors": "eslint src/ --ext .ts --quiet", "lint:errors": "eslint src/ --ext .ts --quiet",
"lint:fix": "eslint src/ --ext .ts --fix", "lint:fix": "eslint src/ --ext .ts --fix",
"lint:tests": "eslint test/ --ext .ts", "lint:tests": "eslint test/ --ext .ts",
"svg": "svg-sprite-generate -d src/assets/ -o dist/sprite.svg",
"ci:pull_paragraph": "git submodule update --init ./src/tools/paragraph", "ci:pull_paragraph": "git submodule update --init ./src/tools/paragraph",
"pull_tools": "git submodule update --init --recursive", "pull_tools": "git submodule update --init --recursive",
"_tools:checkout": "git submodule foreach \"git checkout master || git checkout main\"", "_tools:checkout": "git submodule foreach \"git checkout master || git checkout main\"",
@ -73,7 +72,6 @@
"eslint-plugin-chai-friendly": "^0.7.2", "eslint-plugin-chai-friendly": "^0.7.2",
"eslint-plugin-cypress": "^2.12.1", "eslint-plugin-cypress": "^2.12.1",
"extract-text-webpack-plugin": "^3.0.2", "extract-text-webpack-plugin": "^3.0.2",
"html-janitor": "^2.0.4",
"license-webpack-plugin": "^2.1.4", "license-webpack-plugin": "^2.1.4",
"mkdirp": "^1.0.4", "mkdirp": "^1.0.4",
"postcss-apply": "^0.12.0", "postcss-apply": "^0.12.0",
@ -82,10 +80,8 @@
"postcss-nested": "^4.1.2", "postcss-nested": "^4.1.2",
"postcss-nested-ancestors": "^2.0.0", "postcss-nested-ancestors": "^2.0.0",
"postcss-preset-env": "^6.6.0", "postcss-preset-env": "^6.6.0",
"raw-loader": "^4.0.1",
"rimraf": "^3.0.2", "rimraf": "^3.0.2",
"stylelint": "^13.3.3", "stylelint": "^13.3.3",
"svg-sprite-generator": "^0.0.7",
"terser-webpack-plugin": "^2.3.6", "terser-webpack-plugin": "^2.3.6",
"ts-loader": "^7.0.1", "ts-loader": "^7.0.1",
"tslint": "^6.1.1", "tslint": "^6.1.1",
@ -98,8 +94,10 @@
"url": "https://opencollective.com/editorjs" "url": "https://opencollective.com/editorjs"
}, },
"dependencies": { "dependencies": {
"@codexteam/icons": "^0.0.4",
"codex-notifier": "^1.1.2", "codex-notifier": "^1.1.2",
"codex-tooltip": "^1.0.5", "codex-tooltip": "^1.0.5",
"html-janitor": "^2.0.4",
"nanoid": "^3.1.22" "nanoid": "^3.1.22"
} }
} }

View file

@ -1,3 +0,0 @@
<svg width="14" height="14" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<path transform="matrix(1 0 0 -1 0 14)" d="M8.024 4.1v8.6a1.125 1.125 0 0 1-2.25 0V4.1L2.18 7.695A1.125 1.125 0 1 1 .59 6.104L6.103.588c.44-.439 1.151-.439 1.59 0l5.516 5.516a1.125 1.125 0 0 1-1.59 1.59L8.023 4.1z"/>
</svg>

Before

Width:  |  Height:  |  Size: 353 B

View file

@ -1,3 +0,0 @@
<svg width="14" height="14" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<path d="M8.024 4.1v8.6a1.125 1.125 0 0 1-2.25 0V4.1L2.18 7.695A1.125 1.125 0 1 1 .59 6.104L6.103.588c.44-.439 1.151-.439 1.59 0l5.516 5.516a1.125 1.125 0 0 1-1.59 1.59L8.023 4.1z"/>
</svg>

Before

Width:  |  Height:  |  Size: 321 B

View file

@ -1 +0,0 @@
<svg width="12" height="14" viewBox="0 0 12 14" xmlns="http://www.w3.org/2000/svg"><path d="M5.997 14H1.72c-.618 0-1.058-.138-1.323-.415C.132 13.308 0 12.867 0 12.262V1.738C0 1.121.135.676.406.406.676.136 1.114 0 1.719 0h4.536c.669 0 1.248.041 1.738.124.49.083.93.242 1.318.478a3.458 3.458 0 0 1 1.461 1.752c.134.366.2.753.2 1.16 0 1.401-.7 2.426-2.1 3.075 1.84.586 2.76 1.726 2.76 3.42 0 .782-.2 1.487-.602 2.114a3.61 3.61 0 0 1-1.623 1.39 5.772 5.772 0 0 1-1.471.377c-.554.073-1.2.11-1.939.11zm-.21-6.217h-2.95v4.087h3.046c1.916 0 2.874-.69 2.874-2.072 0-.707-.248-1.22-.745-1.537-.496-.319-1.238-.478-2.225-.478zM2.837 2.13v3.619h2.597c.707 0 1.252-.067 1.638-.2.385-.134.68-.389.883-.765.16-.267.239-.566.239-.897 0-.707-.252-1.176-.755-1.409-.503-.232-1.27-.348-2.301-.348H2.836z"/></svg>

Before

Width:  |  Height:  |  Size: 794 B

View file

@ -1,3 +0,0 @@
<svg width="237" height="237" viewBox="0 0 237 237" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<path transform="rotate(45 280.675 51.325)" d="M191 191V73c0-5.523 4.477-10 10-10h25c5.523 0 10 4.477 10 10v118h118c5.523 0 10 4.477 10 10v25c0 5.523-4.477 10-10 10H236v118c0 5.523-4.477 10-10 10h-25c-5.523 0-10-4.477-10-10V236H73c-5.523 0-10-4.477-10-10v-25c0-5.523 4.477-10 10-10h118z"/>
</svg>

Before

Width:  |  Height:  |  Size: 430 B

View file

@ -1,10 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
<g transform="translate(4 1.5)" fill-rule="evenodd">
<circle cx="1.3" cy="1.3" r="1.3"/>
<circle cx="6.5" cy="1.3" r="1.3"/>
<circle cx="6.5" cy="6.5" r="1.3"/>
<circle cx="1.3" cy="6.5" r="1.3"/>
<circle cx="6.5" cy="11.7" r="1.3"/>
<circle cx="1.3" cy="11.7" r="1.3"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 372 B

View file

@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 4 11">
<path d="M3.289 4.17L2.164 9.713c-.078.384-.238.674-.48.87-.243.198-.52.296-.831.296-.312 0-.545-.1-.699-.302-.153-.202-.192-.49-.116-.864L1.15 4.225c.077-.38.232-.665.466-.857a1.25 1.25 0 01.818-.288c.312 0 .55.096.713.288.163.192.21.46.141.801zm-.667-2.09c-.295 0-.53-.09-.706-.273-.176-.181-.233-.439-.173-.77.055-.302.207-.55.457-.745C2.45.097 2.716 0 3 0c.273 0 .5.088.68.265.179.176.238.434.177.771-.06.327-.21.583-.45.767-.24.185-.502.277-.785.277z"/>
</svg>

Before

Width:  |  Height:  |  Size: 530 B

View file

@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 14 10">
<path d="M6 0v2H5a3 3 0 000 6h1v2H5A5 5 0 115 0h1zm2 0h1a5 5 0 110 10H8V8h1a3 3 0 000-6H8V0zM5 4h4a1 1 0 110 2H5a1 1 0 110-2z"/>
</svg>

Before

Width:  |  Height:  |  Size: 199 B

View file

@ -1,6 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
<g transform="translate(1 1.5)" fill-rule="evenodd">
<rect x="6" width="2" height="13" rx="1"/>
<rect x=".5" y="5.5" width="13" height="2" rx="1"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 233 B

View file

@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="52" height="52" viewBox="0 0 52 52">
<path fill="#D76B6B" fill-rule="nonzero" d="M26 52C11.64 52 0 40.36 0 26S11.64 0 26 0s26 11.64 26 26-11.64 26-26 26zm0-3.25c12.564 0 22.75-10.186 22.75-22.75S38.564 3.25 26 3.25 3.25 13.436 3.25 26 13.436 48.75 26 48.75zM15.708 33.042a2.167 2.167 0 1 1 0-4.334 2.167 2.167 0 0 1 0 4.334zm23.834 0a2.167 2.167 0 1 1 0-4.334 2.167 2.167 0 0 1 0 4.334zm-15.875 5.452a1.083 1.083 0 1 1-1.834-1.155c1.331-2.114 3.49-3.179 6.334-3.179 2.844 0 5.002 1.065 6.333 3.18a1.083 1.083 0 1 1-1.833 1.154c-.913-1.45-2.366-2.167-4.5-2.167s-3.587.717-4.5 2.167z"/>
</svg>

Before

Width:  |  Height:  |  Size: 643 B

View file

@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
<path d="M12.711 2.18a7.448 7.448 0 0 1 .79 9.603l2.143 2.144a1.214 1.214 0 1 1-1.717 1.717L11.783 13.5a7.446 7.446 0 1 1 .928-11.32ZM11.39 3.61a5.5 5.5 0 1 0-7.778 7.78 5.5 5.5 0 0 0 7.778-7.78Z" fill-rule="evenodd"/>
</svg>

Before

Width:  |  Height:  |  Size: 289 B

View file

@ -1,3 +0,0 @@
<svg width="13" height="13" xmlns="http://www.w3.org/2000/svg">
<path d="M6.5 9.294a.792.792 0 01-.562-.232L2.233 5.356a.794.794 0 011.123-1.123L6.5 7.377l3.144-3.144a.794.794 0 011.123 1.123L7.062 9.062a.792.792 0 01-.562.232z"/>
</svg>

Before

Width:  |  Height:  |  Size: 240 B

View file

@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 15 11">
<path d="M13.073 2.099l-1.448 1.448A3 3 0 009 2H8V0h1c1.68 0 3.166.828 4.073 2.099zM6.929 4l-.879.879L7.172 6H5a1 1 0 110-2h1.929zM6 0v2H5a3 3 0 100 6h1v2H5A5 5 0 115 0h1zm6.414 7l2.122 2.121-1.415 1.415L11 8.414l-2.121 2.122L7.464 9.12 9.586 7 7.464 4.879 8.88 3.464 11 5.586l2.121-2.122 1.415 1.415L12.414 7z"/>
</svg>

Before

Width:  |  Height:  |  Size: 384 B

View file

@ -4,7 +4,7 @@
* @copyright <CodeX Team> 2018 * @copyright <CodeX Team> 2018
*/ */
import { API, BlockTune, PopoverItem } from '../../../types'; import { API, BlockTune, PopoverItem } from '../../../types';
import $ from '../dom'; import { IconCross } from '@codexteam/icons';
/** /**
* *
@ -36,8 +36,7 @@ export default class DeleteTune implements BlockTune {
*/ */
public render(): PopoverItem { public render(): PopoverItem {
return { return {
// eslint-disable-next-line @typescript-eslint/no-magic-numbers icon: IconCross,
icon: $.svg('cross', 14, 14).outerHTML,
label: this.api.i18n.t('Delete'), label: this.api.i18n.t('Delete'),
name: 'delete', name: 'delete',
confirmation: { confirmation: {

View file

@ -4,9 +4,10 @@
* @copyright <CodeX Team> 2018 * @copyright <CodeX Team> 2018
*/ */
import $ from '../dom';
import { API, BlockTune, PopoverItem } from '../../../types'; import { API, BlockTune, PopoverItem } from '../../../types';
import Popover from '../utils/popover'; import Popover from '../utils/popover';
import { IconChevronDown } from '@codexteam/icons';
/** /**
* *
@ -45,8 +46,7 @@ export default class MoveDownTune implements BlockTune {
*/ */
public render(): PopoverItem { public render(): PopoverItem {
return { return {
// eslint-disable-next-line @typescript-eslint/no-magic-numbers icon: IconChevronDown,
icon: $.svg('arrow-down', 14, 14).outerHTML,
label: this.api.i18n.t('Move down'), label: this.api.i18n.t('Move down'),
onActivate: (item, event): void => this.handleClick(event), onActivate: (item, event): void => this.handleClick(event),
name: 'move-down', name: 'move-down',

View file

@ -3,9 +3,9 @@
* @classdesc Editor's default tune that moves up selected block * @classdesc Editor's default tune that moves up selected block
* @copyright <CodeX Team> 2018 * @copyright <CodeX Team> 2018
*/ */
import $ from '../dom';
import { API, BlockTune, PopoverItem } from '../../../types'; import { API, BlockTune, PopoverItem } from '../../../types';
import Popover from '../../components/utils/popover'; import Popover from '../../components/utils/popover';
import { IconChevronUp } from '@codexteam/icons';
/** /**
* *
@ -44,8 +44,7 @@ export default class MoveUpTune implements BlockTune {
*/ */
public render(): PopoverItem { public render(): PopoverItem {
return { return {
// eslint-disable-next-line @typescript-eslint/no-magic-numbers icon: IconChevronUp,
icon: $.svg('arrow-up', 14, 14).outerHTML,
label: this.api.i18n.t('Move up'), label: this.api.i18n.t('Move up'),
onActivate: (item, e): void => this.handleClick(e), onActivate: (item, e): void => this.handleClick(e),
name: 'move-up', name: 'move-up',

View file

@ -45,10 +45,10 @@ export default class Dom {
} }
/** /**
* Helper for making Elements with classname and attributes * Helper for making Elements with class name and attributes
* *
* @param {string} tagName - new Element tag name * @param {string} tagName - new Element tag name
* @param {string[]|string} [classNames] - list or name of CSS classname(s) * @param {string[]|string} [classNames] - list or name of CSS class name(s)
* @param {object} [attributes] - any attributes * @param {object} [attributes] - any attributes
* @returns {HTMLElement} * @returns {HTMLElement}
*/ */
@ -80,25 +80,6 @@ export default class Dom {
return document.createTextNode(content); return document.createTextNode(content);
} }
/**
* Creates SVG icon linked to the sprite
*
* @param {string} name - name (id) of icon from sprite
* @param {number} [width] - icon width
* @param {number} [height] - icon height
* @returns {SVGElement}
*/
public static svg(name: string, width = 14, height = 14): SVGElement {
const icon = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
icon.classList.add('icon', 'icon--' + name);
icon.setAttribute('width', width + 'px');
icon.setAttribute('height', height + 'px');
icon.innerHTML = `<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#${name}"></use>`;
return icon;
}
/** /**
* Append one or several elements to the parent * Append one or several elements to the parent
* *
@ -202,7 +183,7 @@ export default class Dom {
} }
/** /**
* Find all contendeditable, textarea and editable input elements passed holder contains * Find all contenteditable, textarea and editable input elements passed holder contains
* *
* @param holder - element where to find inputs * @param holder - element where to find inputs
*/ */

View file

@ -1,5 +1,5 @@
import $ from '../dom';
import { InlineTool, SanitizerConfig } from '../../../types'; import { InlineTool, SanitizerConfig } from '../../../types';
import { IconBold } from '@codexteam/icons';
/** /**
* Bold Tool * Bold Tool
@ -61,8 +61,7 @@ export default class BoldInlineTool implements InlineTool {
this.nodes.button = document.createElement('button') as HTMLButtonElement; this.nodes.button = document.createElement('button') as HTMLButtonElement;
this.nodes.button.type = 'button'; this.nodes.button.type = 'button';
this.nodes.button.classList.add(this.CSS.button, this.CSS.buttonModifier); this.nodes.button.classList.add(this.CSS.button, this.CSS.buttonModifier);
// eslint-disable-next-line @typescript-eslint/no-magic-numbers this.nodes.button.innerHTML = IconBold;
this.nodes.button.appendChild($.svg('bold', 12, 14));
return this.nodes.button; return this.nodes.button;
} }

View file

@ -1,5 +1,5 @@
import $ from '../dom';
import { InlineTool, SanitizerConfig } from '../../../types'; import { InlineTool, SanitizerConfig } from '../../../types';
import { IconItalic } from '@codexteam/icons';
/** /**
* Italic Tool * Italic Tool
@ -61,8 +61,7 @@ export default class ItalicInlineTool implements InlineTool {
this.nodes.button = document.createElement('button') as HTMLButtonElement; this.nodes.button = document.createElement('button') as HTMLButtonElement;
this.nodes.button.type = 'button'; this.nodes.button.type = 'button';
this.nodes.button.classList.add(this.CSS.button, this.CSS.buttonModifier); this.nodes.button.classList.add(this.CSS.button, this.CSS.buttonModifier);
// eslint-disable-next-line @typescript-eslint/no-magic-numbers this.nodes.button.innerHTML = IconItalic;
this.nodes.button.appendChild($.svg('italic', 4, 11));
return this.nodes.button; return this.nodes.button;
} }

View file

@ -1,9 +1,8 @@
import SelectionUtils from '../selection'; import SelectionUtils from '../selection';
import $ from '../dom';
import * as _ from '../utils'; import * as _ from '../utils';
import { API, InlineTool, SanitizerConfig } from '../../../types'; import { InlineTool, SanitizerConfig, API } from '../../../types';
import { Notifier, Toolbar, I18n, InlineToolbar } from '../../../types/api'; import { Notifier, Toolbar, I18n, InlineToolbar } from '../../../types/api';
import { IconLink, IconUnlink } from '@codexteam/icons';
/** /**
* Link Tool * Link Tool
@ -123,10 +122,8 @@ export default class LinkInlineTool implements InlineTool {
this.nodes.button = document.createElement('button') as HTMLButtonElement; this.nodes.button = document.createElement('button') as HTMLButtonElement;
this.nodes.button.type = 'button'; this.nodes.button.type = 'button';
this.nodes.button.classList.add(this.CSS.button, this.CSS.buttonModifier); this.nodes.button.classList.add(this.CSS.button, this.CSS.buttonModifier);
// eslint-disable-next-line @typescript-eslint/no-magic-numbers
this.nodes.button.appendChild($.svg('link', 14, 10)); this.nodes.button.innerHTML = IconLink;
// eslint-disable-next-line @typescript-eslint/no-magic-numbers
this.nodes.button.appendChild($.svg('unlink', 15, 11));
return this.nodes.button; return this.nodes.button;
} }
@ -194,6 +191,7 @@ export default class LinkInlineTool implements InlineTool {
const anchorTag = this.selection.findParentTag('A'); const anchorTag = this.selection.findParentTag('A');
if (anchorTag) { if (anchorTag) {
this.nodes.button.innerHTML = IconUnlink;
this.nodes.button.classList.add(this.CSS.buttonUnlink); this.nodes.button.classList.add(this.CSS.buttonUnlink);
this.nodes.button.classList.add(this.CSS.buttonActive); this.nodes.button.classList.add(this.CSS.buttonActive);
this.openActions(); this.openActions();
@ -207,6 +205,7 @@ export default class LinkInlineTool implements InlineTool {
this.selection.save(); this.selection.save();
} else { } else {
this.nodes.button.innerHTML = IconLink;
this.nodes.button.classList.remove(this.CSS.buttonUnlink); this.nodes.button.classList.remove(this.CSS.buttonUnlink);
this.nodes.button.classList.remove(this.CSS.buttonActive); this.nodes.button.classList.remove(this.CSS.buttonActive);
} }

View file

@ -8,6 +8,7 @@ import { ModuleConfig } from '../../../types-internal/module-config';
import { BlockAPI } from '../../../../types'; import { BlockAPI } from '../../../../types';
import Block from '../../block'; import Block from '../../block';
import Toolbox, { ToolboxEvent } from '../../ui/toolbox'; import Toolbox, { ToolboxEvent } from '../../ui/toolbox';
import { IconMenu, IconPlus } from '@codexteam/icons';
/** /**
* @todo Tab on non-empty block should open Block Settings of the hoveredBlock (not where caret is set) * @todo Tab on non-empty block should open Block Settings of the hoveredBlock (not where caret is set)
@ -335,9 +336,9 @@ export default class Toolbar extends Module<ToolbarNodes> {
* - Plus Button * - Plus Button
* - Toolbox * - Toolbox
*/ */
this.nodes.plusButton = $.make('div', this.CSS.plusButton); this.nodes.plusButton = $.make('div', this.CSS.plusButton, {
// eslint-disable-next-line @typescript-eslint/no-magic-numbers innerHTML: IconPlus,
$.append(this.nodes.plusButton, $.svg('plus', 16, 16)); });
$.append(this.nodes.actions, this.nodes.plusButton); $.append(this.nodes.actions, this.nodes.plusButton);
this.readOnlyMutableListeners.on(this.nodes.plusButton, 'click', () => { this.readOnlyMutableListeners.on(this.nodes.plusButton, 'click', () => {
@ -365,11 +366,10 @@ export default class Toolbar extends Module<ToolbarNodes> {
* - Remove Block Button * - Remove Block Button
* - Settings Panel * - Settings Panel
*/ */
this.nodes.settingsToggler = $.make('span', this.CSS.settingsToggler); this.nodes.settingsToggler = $.make('span', this.CSS.settingsToggler, {
// eslint-disable-next-line @typescript-eslint/no-magic-numbers innerHTML: IconMenu,
const settingsIcon = $.svg('dots', 16, 16); });
$.append(this.nodes.settingsToggler, settingsIcon);
$.append(this.nodes.actions, this.nodes.settingsToggler); $.append(this.nodes.actions, this.nodes.settingsToggler);
this.tooltip.onHover( this.tooltip.onHover(

View file

@ -11,6 +11,7 @@ import Tooltip from '../../utils/tooltip';
import { ModuleConfig } from '../../../types-internal/module-config'; import { ModuleConfig } from '../../../types-internal/module-config';
import InlineTool from '../../tools/inline'; import InlineTool from '../../tools/inline';
import { CommonInternalSettings } from '../../tools/base'; import { CommonInternalSettings } from '../../tools/base';
import { IconChevronDown } from '@codexteam/icons';
/** /**
* Inline Toolbar elements * Inline Toolbar elements
@ -51,6 +52,7 @@ export default class InlineToolbar extends Module<InlineToolbarNodes> {
inputField: 'cdx-input', inputField: 'cdx-input',
focusedButton: 'ce-inline-tool--focused', focusedButton: 'ce-inline-tool--focused',
conversionToggler: 'ce-inline-toolbar__dropdown', conversionToggler: 'ce-inline-toolbar__dropdown',
conversionTogglerArrow: 'ce-inline-toolbar__dropdown-arrow',
conversionTogglerHidden: 'ce-inline-toolbar__dropdown--hidden', conversionTogglerHidden: 'ce-inline-toolbar__dropdown--hidden',
conversionTogglerContent: 'ce-inline-toolbar__dropdown-content', conversionTogglerContent: 'ce-inline-toolbar__dropdown-content',
togglerAndButtonsWrapper: 'ce-inline-toolbar__toggler-and-button-wrapper', togglerAndButtonsWrapper: 'ce-inline-toolbar__toggler-and-button-wrapper',
@ -428,11 +430,12 @@ export default class InlineToolbar extends Module<InlineToolbarNodes> {
this.nodes.conversionToggler = $.make('div', this.CSS.conversionToggler); this.nodes.conversionToggler = $.make('div', this.CSS.conversionToggler);
this.nodes.conversionTogglerContent = $.make('div', this.CSS.conversionTogglerContent); this.nodes.conversionTogglerContent = $.make('div', this.CSS.conversionTogglerContent);
// eslint-disable-next-line @typescript-eslint/no-magic-numbers const iconWrapper = $.make('div', this.CSS.conversionTogglerArrow, {
const icon = $.svg('toggler-down', 13, 13); innerHTML: IconChevronDown,
});
this.nodes.conversionToggler.appendChild(this.nodes.conversionTogglerContent); this.nodes.conversionToggler.appendChild(this.nodes.conversionTogglerContent);
this.nodes.conversionToggler.appendChild(icon); this.nodes.conversionToggler.appendChild(iconWrapper);
this.nodes.togglerAndButtonsWrapper.appendChild(this.nodes.conversionToggler); this.nodes.togglerAndButtonsWrapper.appendChild(this.nodes.conversionToggler);
@ -665,6 +668,15 @@ export default class InlineToolbar extends Module<InlineToolbarNodes> {
tool.surround(range); tool.surround(range);
this.checkToolsState(); this.checkToolsState();
/**
* If tool has "actions", so after click it will probably toggle them on.
* For example, the Inline Link Tool will show the URL-input.
* So we disable the Flipper for that case to allow Tool bind own Enter listener
*/
if (tool.renderActions !== undefined) {
this.flipper.deactivate();
}
} }
/** /**

View file

@ -1,9 +1,4 @@
/* eslint-disable jsdoc/no-undefined-types */ /* eslint-disable jsdoc/no-undefined-types */
/**
* Prebuilded sprite of SVG icons
*/
import sprite from '../../../dist/sprite.svg';
/** /**
* Module UI * Module UI
* *
@ -163,11 +158,6 @@ export default class UI extends Module<UINodes> {
*/ */
this.addLoader(); this.addLoader();
/**
* Append SVG sprite
*/
this.appendSVGSprite();
/** /**
* Load and append CSS * Load and append CSS
*/ */
@ -875,17 +865,4 @@ export default class UI extends Module<UINodes> {
*/ */
this.Editor.InlineToolbar.tryToShow(true, isNeedToShowConversionToolbar); this.Editor.InlineToolbar.tryToShow(true, isNeedToShowConversionToolbar);
} }
/**
* Append prebuilt sprite with SVG icons
*/
private appendSVGSprite(): void {
const spriteHolder = $.make('div');
spriteHolder.hidden = true;
spriteHolder.style.display = 'none';
spriteHolder.innerHTML = sprite;
$.append(this.nodes.wrapper, spriteHolder);
}
} }

View file

@ -1,5 +1,6 @@
import Dom from '../dom'; import Dom from '../dom';
import Listeners from './listeners'; import Listeners from './listeners';
import { IconSearch } from '@codexteam/icons';
/** /**
* Item that could be searched * Item that could be searched
@ -113,15 +114,14 @@ export default class SearchInput {
private render(placeholder: string): void { private render(placeholder: string): void {
this.wrapper = Dom.make('div', SearchInput.CSS.wrapper); this.wrapper = Dom.make('div', SearchInput.CSS.wrapper);
const iconWrapper = Dom.make('div', SearchInput.CSS.icon); const iconWrapper = Dom.make('div', SearchInput.CSS.icon, {
// eslint-disable-next-line @typescript-eslint/no-magic-numbers innerHTML: IconSearch,
const icon = Dom.svg('search', 16, 16); });
this.input = Dom.make('input', SearchInput.CSS.input, { this.input = Dom.make('input', SearchInput.CSS.input, {
placeholder, placeholder,
}) as HTMLInputElement; }) as HTMLInputElement;
iconWrapper.appendChild(icon);
this.wrapper.appendChild(iconWrapper); this.wrapper.appendChild(iconWrapper);
this.wrapper.appendChild(this.input); this.wrapper.appendChild(this.input);

View file

@ -63,20 +63,7 @@
} }
&__icon { &__icon {
display: inline-flex; @apply --tool-icon;
width: 20px;
height: 20px;
border: 1px solid var(--color-gray-border);
border-radius: 3px;
align-items: center;
justify-content: center;
margin-right: 10px;
background: #fff;
svg {
width: 11px;
height: 11px;
}
} }
&--last { &--last {

View file

@ -40,6 +40,8 @@
*/ */
.cdx-settings-button { .cdx-settings-button {
@apply --toolbar-button; @apply --toolbar-button;
min-width: var(--toolbox-buttons-size);
min-height: var(--toolbox-buttons-size);
&--active { &--active {
color: var(--color-active-icon); color: var(--color-active-icon);

View file

@ -50,13 +50,13 @@
} }
&__dropdown { &__dropdown {
display: inline-flex; display: flex;
height: var(--toolbar-buttons-size); padding: 6px;
padding: 0 9px 0 10px;
margin: 0 6px 0 -6px; margin: 0 6px 0 -6px;
align-items: center; align-items: center;
cursor: pointer; cursor: pointer;
border-right: 1px solid var(--color-gray-border); border-right: 1px solid var(--color-gray-border);
box-sizing: border-box;
&:hover { &:hover {
background: var(--bg-light); background: var(--bg-light);
@ -66,19 +66,14 @@
display: none; display: none;
} }
&-content{ &-content,
&-arrow {
display: flex; display: flex;
font-weight: 500;
font-size: 14px;
svg { svg {
height: 12px; width: var(--icon-size);
height: var(--icon-size);
} }
} }
.icon--toggler-down {
margin-left: 4px;
}
} }
&__shortcut { &__shortcut {
@ -90,19 +85,11 @@
.ce-inline-tool { .ce-inline-tool {
@apply --toolbar-button; @apply --toolbar-button;
border-radius: 0; border-radius: 0;
line-height: normal; line-height: normal;
width: auto; padding: 0 1px !important;
padding: 0 5px !important;
min-width: 24px;
&:not(:last-of-type) {
margin-right: 2px;
}
.icon {
height: 12px;
}
&--link { &--link {
.icon--unlink { .icon--unlink {

View file

@ -17,11 +17,10 @@
justify-content: center; justify-content: center;
margin-right: var(--icon-margin-right); margin-right: var(--icon-margin-right);
.icon { svg {
width: 14px; width: var(--icon-size);
height: 14px; height: var(--icon-size);
color: var(--grayText); color: var(--grayText);
flex-shrink: 0;
} }
} }

View file

@ -34,28 +34,5 @@
&--selected { &--selected {
color: var(--color-active-icon); color: var(--color-active-icon);
} }
&--delete {
transition: background-color 300ms ease;
will-change: background-color;
.icon {
transition: transform 200ms ease-out;
will-change: transform;
}
}
&--confirm {
background-color: var(--color-confirm) !important;
color: #fff;
&:hover {
background-color: color-mod(var(--color-confirm) blackness(+5%)) !important;
}
.icon {
transform: rotate(90deg);
}
}
} }
} }

View file

@ -57,12 +57,12 @@
&__settings-btn { &__settings-btn {
@apply --toolbox-button; @apply --toolbox-button;
margin-left: 5px; margin-left: 3px;
cursor: pointer; cursor: pointer;
user-select: none; user-select: none;
@media (--not-mobile){ @media (--not-mobile){
width: 18px; width: 24px;
} }
&--hidden { &--hidden {
@ -74,6 +74,14 @@
position: static; position: static;
} }
} }
&__plus,
&__settings-btn {
svg {
width: 24px;
height: 24px;
}
}
} }
/** /**

View file

@ -101,10 +101,12 @@
} }
svg { svg {
fill: currentColor;
vertical-align: middle;
max-height: 100%; max-height: 100%;
} }
path {
stroke: currentColor;
}
} }
/** /**
@ -137,4 +139,4 @@
top: calc(-1 * var(--window-scroll-offset)); top: calc(-1 * var(--window-scroll-offset));
position: fixed; position: fixed;
width: 100%; width: 100%;
} }

View file

@ -49,17 +49,17 @@
*/ */
--narrow-mode-right-padding: 50px; --narrow-mode-right-padding: 50px;
/**
* Toolbar buttons height and width
*/
--toolbar-buttons-size: 34px;
/** /**
* Toolbar Plus Button and Toolbox buttons height and width * Toolbar Plus Button and Toolbox buttons height and width
*/ */
--toolbox-buttons-size: 26px; --toolbox-buttons-size: 26px;
--toolbox-buttons-size--mobile: 36px; --toolbox-buttons-size--mobile: 36px;
/**
* Size of svg icons got from the CodeX Icons pack
*/
--icon-size: 20px;
/** /**
* The main `.cdx-block` wrapper has such vertical paddings * The main `.cdx-block` wrapper has such vertical paddings
* And the Block Actions toggler too * And the Block Actions toggler too
@ -159,20 +159,22 @@
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
width: var(--toolbar-buttons-size);
height: var(--toolbar-buttons-size); padding: 0;
line-height: var(--toolbar-buttons-size);
padding: 0 !important;
text-align: center;
border-radius: 3px; border-radius: 3px;
cursor: pointer; cursor: pointer;
border: 0; border: 0;
outline: none; outline: none;
background-color: transparent; background-color: transparent;
vertical-align: bottom; vertical-align: bottom;
color: #000; color: inherit;
margin: 0; margin: 0;
svg {
width: var(--icon-size);
height: var(--icon-size);
}
&:hover { &:hover {
background-color: var(--bg-light); background-color: var(--bg-light);
} }
@ -241,8 +243,8 @@
} }
svg { svg {
width: 12px; width: var(--icon-size);
height: 12px; height: var(--icon-size);
} }
} }
} }

View file

@ -92,8 +92,7 @@ export default class Stub implements BlockTool {
*/ */
private make(): HTMLElement { private make(): HTMLElement {
const wrapper = $.make('div', this.CSS.wrapper); const wrapper = $.make('div', this.CSS.wrapper);
// eslint-disable-next-line @typescript-eslint/no-magic-numbers const icon = `<svg xmlns="http://www.w3.org/2000/svg" width="52" height="52" viewBox="0 0 52 52"><path fill="#D76B6B" fill-rule="nonzero" d="M26 52C11.64 52 0 40.36 0 26S11.64 0 26 0s26 11.64 26 26-11.64 26-26 26zm0-3.25c12.564 0 22.75-10.186 22.75-22.75S38.564 3.25 26 3.25 3.25 13.436 3.25 26 13.436 48.75 26 48.75zM15.708 33.042a2.167 2.167 0 1 1 0-4.334 2.167 2.167 0 0 1 0 4.334zm23.834 0a2.167 2.167 0 1 1 0-4.334 2.167 2.167 0 0 1 0 4.334zm-15.875 5.452a1.083 1.083 0 1 1-1.834-1.155c1.331-2.114 3.49-3.179 6.334-3.179 2.844 0 5.002 1.065 6.333 3.18a1.083 1.083 0 1 1-1.833 1.154c-.913-1.45-2.366-2.167-4.5-2.167s-3.587.717-4.5 2.167z"/></svg>`;
const icon = $.svg('sad-face', 52, 52);
const infoContainer = $.make('div', this.CSS.info); const infoContainer = $.make('div', this.CSS.info);
const title = $.make('div', this.CSS.title, { const title = $.make('div', this.CSS.title, {
textContent: this.title, textContent: this.title,
@ -102,7 +101,7 @@ export default class Stub implements BlockTool {
textContent: this.subtitle, textContent: this.subtitle,
}); });
wrapper.appendChild(icon); wrapper.innerHTML = icon;
infoContainer.appendChild(title); infoContainer.appendChild(title);
infoContainer.appendChild(subtitle); infoContainer.appendChild(subtitle);

View file

@ -1,7 +0,0 @@
/**
* Allow to import .svg from components/modules/ui from TypeScript file
*/
declare module '*.svg' {
const content: string;
export default content;
}

View file

@ -0,0 +1,33 @@
describe('Inline Tool Link', () => {
it('should create a link by Enter keydown in input', () => {
cy.createEditor({
data: {
blocks: [
{
type: 'paragraph',
data: {
text: 'First block text',
},
},
],
},
});
cy.get('[data-cy=editorjs]')
.find('div.ce-block')
.click()
.type('{selectall}')
.type('{ctrl}K');
cy.get('[data-cy=editorjs]')
.find('.ce-inline-tool-input')
.click()
.type('https://codex.so')
.type('{enter}');
cy.get('[data-cy=editorjs]')
.find('div.ce-block')
.find('a')
.should('have.attr', 'href', 'https://codex.so');
});
});

View file

@ -91,15 +91,7 @@ module.exports = (env, argv) => {
use: [ use: [
'postcss-loader', 'postcss-loader',
], ],
}, }
{
test: /\.(svg)$/,
use: [
{
loader: 'raw-loader',
},
],
},
], ],
}, },

4597
yarn.lock

File diff suppressed because it is too large Load diff