Closed favoyang closed 3 years ago
Hey @favoyang, have you tried building this with a custom inline style? I think you could create one that sets color
quite easily.
The Draftail examples has a "Redacted" inline style in the "Custom formats" editor that's quite similar – it sets the background-color
, not color
, but otherwise it's the same: https://www.draftail.org/examples/
Thanks for the help. It seems combined with a color picker popup, it can be very useful colored text feature. A nice built-in feature to have.
@favoyang is there a specific reason you think it would work better built-in instead of as an extension?
Extension works for me as well. I just assume that a large part of audiences of draftail is editor rather than end user. So I prefer give them more feature than control. And text color is quite trivial, you probably won't use it often, but there's always one or two time you'll need it.
đź‘Ťif you or anyone else wants to work on this I think it would be a good start to add it on the examples page, I'm happy to help where I can.
As part of Hacktoberfest, I think it would be pretty cool if this could be built as an example of an extension inside examples/
.
Could use something like https://github.com/Simonwep/pickr (or another color picker dependency).
Here are related Draft.js projects that already have a color picker:
I'm working on this, but stuck on how to commit the editor state. I have managed to show the color picker.
Basically I'm using react-color
, in the examples, using the controls
attribute. I have received the getEditorState
but I don't know how to continue. And due to the structure of the examples, I don't know how to add new inline styles, and then commit the editor state.
Does inlineStyles
takes a function? Advice needed to proceed.
Hey @alvinthen, nice to hear!
The controls
API has getEditorState
to get the whole editor state, and also onChange
to update it. That's most likely what should be used to apply the changes to the editor state.
For example, using the Draft.js RichUtils.toggleInlineStyle()
:
const { getEditorState, onChange } = this.props;
let state = getEditorState();
state = RichUtils.toggleInlineStyle(state, 'COLOR_FF0000');
onChange(state);
Alternatively this could be built using an entity that has a color
attribute in its data. I'm not entirely sure which would be the most appropriate.
Hey! Thanks for the reply!
Correct me if I'm wrong, in order to have new inline styles, I would have to add the new styles into inlineStyles
of EditorWrapper
, right? I'm not quite sure how to pass the new styles from the plugin to example.js
without changing too much of the current structure. Some insights would help.
@alvinthen oops, yes indeed. I just realised inlineStyles
relies on the style types (COLOR_FF0000
) to be provided upfront. Draftail doesn't provide a way to implement the Draft.js customStyleFn
.
I think it would be easier to do this with the entity type API instead of controls
– then you can define a COLOR
entity.
Could you share what you've done so far so I can help further?
This is what I have done using controls
, stuck at handling onChange
of the color picker.
handleChange(color) {
const { getEditorState, onChange } = this.props;
const editorState = getEditorState();
let nextEditorState = editorState;
// What goes here...
onChange(nextEditorState);
}
I guess it's as what you said that we can't utilise customStyleFn
in Draftail, I'm trying out with the entity API now.
I’ve finally merged #165, converting @alvinthen’s initial work from using entities to inline styles ( see https://github.com/springload/draftail/pull/165#issuecomment-817197525 for reasoning). I think there’s definitely a place for an entity-based implementation though, so here is the entity-based implementation for reference:
// @flow
import React from "react";
import type { Node } from "react";
import { ContentState } from "draft-js";
export const COLOR_ICON =
"M322.018 832l57.6-192h264.764l57.6 192h113.632l-191.996-640h-223.236l-192 640h113.636zM475.618 320h72.764l57.6 192h-187.964l57.6-192z";
type Props = {|
entityKey: string,
contentState: ContentState,
children: Node,
|};
const Color = (props: Props) => {
const { entityKey, contentState, children } = props;
const { color } = contentState.getEntity(entityKey).getData();
return <span style={{ color }}>{children}</span>;
};
export default Color;
import React, { Component } from "react";
import { RichUtils, EditorState } from "draft-js";
import type { EntityInstance } from "draft-js";
// $FlowFixMe
import { ChromePicker } from "react-color";
import Modal from "../components/Modal";
type Props = {|
editorState: EditorState,
onComplete: (EditorState) => void,
onClose: () => void,
entityType: {
type: string,
},
entity: ?EntityInstance,
|};
type State = {|
color: string,
|};
class ColorSource extends Component<Props, State> {
constructor(props: Props) {
super(props);
const { entity } = this.props;
const state = {
color: "#fff",
};
if (entity) {
const data = entity.getData();
state.color = data.color;
}
this.state = state;
this.onRequestClose = this.onRequestClose.bind(this);
this.onChangeColor = this.onChangeColor.bind(this);
this.onConfirm = this.onConfirm.bind(this);
}
/* :: onConfirm: () => void; */
onConfirm() {
const { color } = this.state;
const { editorState, entityType, onComplete } = this.props;
const contentState = editorState.getCurrentContent();
const data = { color };
const contentStateWithEntity = contentState.createEntity(
// Fixed in https://github.com/facebook/draft-js/commit/6ba124cf663b78c41afd6c361a67bd29724fa617, to be released.
// $FlowFixMe
entityType.type,
"MUTABLE",
data,
);
const entityKey = contentStateWithEntity.getLastCreatedEntityKey();
const nextState = RichUtils.toggleLink(
editorState,
editorState.getSelection(),
entityKey,
);
onComplete(nextState);
}
/* :: onRequestClose: (e: SyntheticEvent<>) => void; */
onRequestClose(e: SyntheticEvent<>) {
const { onClose } = this.props;
e.preventDefault();
onClose();
}
/* :: onChangeColor: (color: {| hex: string |}) => void; */
onChangeColor(color: {| hex: string |}) {
this.setState({ color: color.hex });
}
render() {
const { color } = this.state;
return (
<Modal
onRequestClose={this.onRequestClose}
onAfterOpen={() => {}}
isOpen
contentLabel="Pick a color"
>
<div className="ColorSource">
<ChromePicker onChangeComplete={this.onChangeColor} color={color} />
<button type="button" onClick={this.onConfirm}>
Save
</button>
</div>
</Modal>
);
}
}
export default ColorSource;
It would be appreciated if draftail can modify font color for text selection.