Skip to content
This repository has been archived by the owner on Jun 26, 2020. It is now read-only.

Commit

Permalink
Merge pull request #474 from ckeditor/t/ckeditor5/1457
Browse files Browse the repository at this point in the history
t/ckeditor5/1457: Implemented `ColorGridView` and `ColorTileView` components
  • Loading branch information
mlewand authored Mar 29, 2019
2 parents 96ca937 + 09cf4cf commit 6be52b4
Show file tree
Hide file tree
Showing 6 changed files with 499 additions and 0 deletions.
195 changes: 195 additions & 0 deletions src/colorgrid/colorgridview.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
/**
* @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
* For licensing, see LICENSE.md.
*/

/**
* @module ui/colorgrid/colorgrid
*/

import View from '../view';
import ColorTileView from './colortileview';
import FocusTracker from '@ckeditor/ckeditor5-utils/src/focustracker';
import FocusCycler from '../focuscycler';
import KeystrokeHandler from '@ckeditor/ckeditor5-utils/src/keystrokehandler';
import '../../theme/components/colorgrid/colorgrid.css';

/**
* A grid of {@link module:ui/colorgrid/colortile~ColorTileView color tiles}.
*
* @extends module:ui/view~View
*/
export default class ColorGridView extends View {
/**
* Creates an instance of a color grid containing {@link module:ui/colorgrid/colortile~ColorTileView tiles}.
*
* @param {module:utils/locale~Locale} [locale] The localization services instance.
* @param {Object} options Component configuration
* @param {Array.<module:ui/colorgrid/colorgrid~ColorDefinition>} [options.colorDefinitions] Array with definitions
* required to create the {@link module:ui/colorgrid/colortile~ColorTileView tiles}.
* @param {Number} options.columns A number of columns to display the tiles.
*/
constructor( locale, options ) {
super( locale );

const colorDefinitions = options && options.colorDefinitions || [];
const viewStyleAttribute = {};

if ( options && options.columns ) {
viewStyleAttribute.gridTemplateColumns = `repeat( ${ options.columns }, 1fr)`;
}

/**
* The color of the currently selected color tile in {@link #items}.
*
* @type {String}
*/
this.set( 'selectedColor' );

/**
* Collection of the child tile views.
*
* @readonly
* @member {module:ui/viewcollection~ViewCollection}
*/
this.items = this.createCollection();

/**
* Tracks information about DOM focus in the grid.
*
* @readonly
* @member {module:utils/focustracker~FocusTracker}
*/
this.focusTracker = new FocusTracker();

/**
* Instance of the {@link module:utils/keystrokehandler~KeystrokeHandler}.
*
* @readonly
* @member {module:utils/keystrokehandler~KeystrokeHandler}
*/
this.keystrokes = new KeystrokeHandler();

/**
* Helps cycling over focusable {@link #items} in the grid.
*
* @readonly
* @protected
* @member {module:ui/focuscycler~FocusCycler}
*/
this._focusCycler = new FocusCycler( {
focusables: this.items,
focusTracker: this.focusTracker,
keystrokeHandler: this.keystrokes,
actions: {
// Navigate grid items backwards using the arrowup key.
focusPrevious: 'arrowleft',

// Navigate grid items forwards using the arrowdown key.
focusNext: 'arrowright',
}
} );

colorDefinitions.forEach( item => {
const colorTile = new ColorTileView();

colorTile.set( {
color: item.color,
label: item.label,
tooltip: true,
hasBorder: item.options.hasBorder
} );

colorTile.on( 'execute', () => {
this.fire( 'execute', {
value: item.color,
hasBorder: item.options.hasBorder,
label: item.label
} );
} );

this.items.add( colorTile );
} );

this.setTemplate( {
tag: 'div',
children: this.items,
attributes: {
class: [
'ck',
'ck-color-grid'
],
style: viewStyleAttribute
}
} );

this.on( 'change:selectedColor', ( evt, name, selectedColor ) => {
for ( const item of this.items ) {
item.isOn = item.color === selectedColor;
}
} );
}

/**
* Focuses the first focusable in {@link #items}.
*/
focus() {
if ( this.items.length ) {
this.items.first.focus();
}
}

/**
* Focuses the last focusable in {@link #items}.
*/
focusLast() {
if ( this.items.length ) {
this.items.last.focus();
}
}

/**
* @inheritDoc
*/
render() {
super.render();

// Items added before rendering should be known to the #focusTracker.
for ( const item of this.items ) {
this.focusTracker.add( item.element );
}

this.items.on( 'add', ( evt, item ) => {
this.focusTracker.add( item.element );
} );

this.items.on( 'remove', ( evt, item ) => {
this.focusTracker.remove( item.element );
} );

// Start listening for the keystrokes coming from #element.
this.keystrokes.listenTo( this.element );
}
}

/**
* A color definition used to create a {@link module:ui/colorgrid/colortile~ColorTileView}.
*
* {
* color: hsl(0, 0%, 75%),
* label: 'Light Grey',
* options: {
* hasBorder: true
* }
* }
*
* @typedef {Object} module:ui/colorgrid/colorgrid~ColorDefinition
* @type Object
*
* @property {String} color String representing a color.
* It is used as value of background-color style in {@link module:ui/colorgrid/colortile~ColorTileView}.
* @property {String} label String used as label for {@link module:ui/colorgrid/colortile~ColorTileView}.
* @property {Object} options Additional options passed to create a {@link module:ui/colorgrid/colortile~ColorTileView}.
* @property {Boolean} options.hasBorder A flag that indicates if special a CSS class should be added
* to {@link module:ui/colorgrid/colortile~ColorTileView}, which renders a border around it.
*/
54 changes: 54 additions & 0 deletions src/colorgrid/colortileview.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/**
* @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
* For licensing, see LICENSE.md.
*/

/**
* @module ui/colorgrid/colortile
*/

import ButtonView from '../button/buttonview';
import checkIcon from '../../theme/icons/color-tile-check.svg';

/**
* This class represents a single color tile in the {@link module:ui/colorgrid/colorgrid~ColorGridView}.
*
* @extends module:ui/button/buttonview~ButtonView
*/
export default class ColorTileView extends ButtonView {
constructor( locale ) {
super( locale );

const bind = this.bindTemplate;

/**
* String representing a color shown as tile's background.
*
* @type {String}
*/
this.set( 'color' );

/**
* A flag that toggles a special CSS class responsible for displaying
* a border around the button.
*
* @type {Boolean}
*/
this.set( 'hasBorder' );

this.icon = checkIcon;

this.extendTemplate( {
attributes: {
style: {
backgroundColor: bind.to( 'color' )
},
class: [
'ck',
'ck-color-grid__tile',
bind.if( 'hasBorder', 'ck-color-table__color-tile_bordered' )
]
}
} );
}
}
Loading

0 comments on commit 6be52b4

Please sign in to comment.