Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

852 color widget #4437

Merged
merged 7 commits into from
Oct 25, 2020
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions dev-test/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,14 @@ collections: # A list of collections the CMS should be able to edit
- { label: 'Markdown', name: 'markdown', widget: 'markdown' }
- { label: 'Datetime', name: 'datetime', widget: 'datetime' }
- { label: 'Date', name: 'date', widget: 'date' }
- { label: 'Color', name: 'color', widget: 'color' }
- {
label: 'Color string editable and alpha enabled',
name: 'colorEditable',
widget: 'color',
enableAlpha: true,
allowInput: true,
}
- { label: 'Image', name: 'image', widget: 'image' }
- { label: 'File', name: 'file', widget: 'file' }
- { label: 'Select', name: 'select', widget: 'select', options: ['a', 'b', 'c'] }
Expand Down
1 change: 1 addition & 0 deletions packages/netlify-cms-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
"netlify-cms-ui-default": "^2.11.6",
"netlify-cms-widget-boolean": "^2.3.4",
"netlify-cms-widget-code": "^1.2.4",
"netlify-cms-widget-color": "^1.0.0",
"netlify-cms-widget-date": "^2.5.5",
"netlify-cms-widget-datetime": "^2.6.5",
"netlify-cms-widget-file": "^2.7.4",
Expand Down
2 changes: 2 additions & 0 deletions packages/netlify-cms-app/src/extensions.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import NetlifyCmsWidgetMap from 'netlify-cms-widget-map';
import NetlifyCmsWidgetDate from 'netlify-cms-widget-date';
import NetlifyCmsWidgetDatetime from 'netlify-cms-widget-datetime';
import NetlifyCmsWidgetCode from 'netlify-cms-widget-code';
import NetlifyCmsWidgetColor from 'netlify-cms-widget-color';

// Editor Components
import image from 'netlify-cms-editor-component-image';
Expand Down Expand Up @@ -55,6 +56,7 @@ CMS.registerWidget([
NetlifyCmsWidgetDate.Widget(),
NetlifyCmsWidgetDatetime.Widget(),
NetlifyCmsWidgetCode.Widget(),
NetlifyCmsWidgetColor.Widget(),
]);
CMS.registerEditorComponent(image);
CMS.registerEditorComponent({
Expand Down
4 changes: 4 additions & 0 deletions packages/netlify-cms-widget-color/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Change Log

All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
11 changes: 11 additions & 0 deletions packages/netlify-cms-widget-color/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Docs coming soon!

Netlify CMS was recently converted from a single npm package to a "monorepo" of over 20 packages.
That's over 20 Readme's! We haven't created one for this package yet, but we will soon.

In the meantime, you can:

1. Check out the [main readme](https://github.com/netlify/netlify-cms/#readme) or the [documentation
site](https://www.netlifycms.org) for more info.
2. Reach out to the [community chat](https://netlifycms.org/chat/) if you need help.
3. Help out and [write the readme yourself](https://github.com/netlify/netlify-cms/edit/master/packages/netlify-cms-widget-string/README.md)!
34 changes: 34 additions & 0 deletions packages/netlify-cms-widget-color/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"name": "netlify-cms-widget-color",
"description": "Widget for editing color strings in Netlify CMS.",
"version": "1.0.0",
"homepage": "https://www.netlifycms.org/docs/widgets/#color",
"repository": "https://github.com/netlify/netlify-cms/tree/master/packages/netlify-cms-widget-color",
"bugs": "https://github.com/netlify/netlify-cms/issues",
"module": "dist/esm/index.js",
"main": "dist/netlify-cms-widget-color.js",
"license": "MIT",
"keywords": [
"netlify",
"netlify-cms",
"widget",
"color"
],
"sideEffects": false,
"scripts": {
"develop": "yarn build:esm --watch",
"build": "cross-env NODE_ENV=production webpack",
"build:esm": "cross-env NODE_ENV=esm babel src --out-dir dist/esm --ignore \"**/__tests__\" --root-mode upward"
},
"dependencies": {
"react-color": "^2.18.1",
"validate-color": "^2.1.0"
},
"peerDependencies": {
"@emotion/core": "^10.0.35",
"@emotion/styled": "^10.0.27",
"netlify-cms-ui-default": "^2.6.0",
"prop-types": "^15.7.2",
"react": "^16.8.4"
}
}
176 changes: 176 additions & 0 deletions packages/netlify-cms-widget-color/src/ColorControl.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
import React from 'react';
import PropTypes from 'prop-types';
import styled from '@emotion/styled';
import ChromePicker from 'react-color';
import validateColor from 'validate-color';
import { zIndex } from 'netlify-cms-ui-default';

const ClearIcon = () => (
<svg height="20" width="20" viewBox="0 0 20 20" aria-hidden="true" focusable="false">
<path
fill="rgb(122, 130, 145)"
d="M14.348 14.849c-0.469 0.469-1.229 0.469-1.697 0l-2.651-3.030-2.651 3.029c-0.469 0.469-1.229 0.469-1.697 0-0.469-0.469-0.469-1.229 0-1.697l2.758-3.15-2.759-3.152c-0.469-0.469-0.469-1.228 0-1.697s1.228-0.469 1.697 0l2.652 3.031 2.651-3.031c0.469-0.469 1.228-0.469 1.697 0s0.469 1.229 0 1.697l-2.758 3.152 2.758 3.15c0.469 0.469 0.469 1.229 0 1.698z"
></path>
</svg>
);

const ClearButton = styled.div`
position: absolute;
right: 6px;
z-index: ${zIndex.zIndex1000};
padding: 8px;
margin-top: 11px;
`;

const ClearButtonWrapper = styled.div`
position: relative;
width: 100%;
`;

// color swatch background with checkerboard to display behind transparent colors
const ColorSwatchBackground = styled.div`
position: absolute;
z-index: ${zIndex.zIndex1};
background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAMUlEQVQ4T2NkYGAQYcAP3uCTZhw1gGGYhAGBZIA/nYDCgBDAm9BGDWAAJyRCgLaBCAAgXwixzAS0pgAAAABJRU5ErkJggg==');
height: 38px;
width: 48px;
margin-top: 10px;
margin-left: 10px;
border-radius: 5px;
`;

const ColorSwatch = styled.div`
position: absolute;
z-index: ${zIndex.zIndex2};
background: ${props => props.background};
cursor: pointer;
height: 38px;
width: 48px;
margin-top: 10px;
margin-left: 10px;
border-radius: 5px;
border: 2px solid rgb(223, 223, 227);
text-align: center;
font-size: 27px;
line-height: 1;
padding-top: 4px;
user-select: none;
color: ${props => props.color};
`;

const ColorPickerContainer = styled.div`
position: absolute;
z-index: ${zIndex.zIndex1000};
margin-top: 48px;
margin-left: 12px;
`;

// fullscreen div to close color picker when clicking outside of picker
const ClickOutsideDiv = styled.div`
position: fixed;
top: 0px;
right: 0px;
bottom: 0px;
left: 0px;
`;

export default class ColorControl extends React.Component {
static propTypes = {
onChange: PropTypes.func.isRequired,
forID: PropTypes.string,
value: PropTypes.node,
classNameWrapper: PropTypes.string.isRequired,
setActiveStyle: PropTypes.func.isRequired,
setInactiveStyle: PropTypes.func.isRequired,
};

static defaultProps = {
value: '',
};

state = {
showColorPicker: false,
};
// show/hide color picker
handleClick = () => {
this.setState({ showColorPicker: !this.state.showColorPicker });
};
handleClear = () => {
this.props.onChange('');
};
handleClose = () => {
this.setState({ showColorPicker: false });
};
handleChange = color => {
const formattedColor =
color.rgb.a < 1
? `rgba(${color.rgb.r}, ${color.rgb.g}, ${color.rgb.b}, ${color.rgb.a})`
: color.hex;
this.props.onChange(formattedColor);
};
render() {
const {
forID,
value,
field,
onChange,
classNameWrapper,
setActiveStyle,
setInactiveStyle,
} = this.props;

const allowInput = field.get('allowInput', false);

// clear button is not displayed if allowInput: true
const showClearButton = !allowInput && value;

return (
<>
{' '}
{showClearButton && (
<ClearButtonWrapper>
<ClearButton onClick={this.handleClear}>
<ClearIcon />
</ClearButton>
</ClearButtonWrapper>
)}
<ColorSwatchBackground />
<ColorSwatch
background={validateColor(this.props.value) ? this.props.value : '#fff'}
color={validateColor(this.props.value) ? 'rgba(255, 255, 255, 0)' : 'rgb(223, 223, 227)'}
onClick={this.handleClick}
>
?
</ColorSwatch>
{this.state.showColorPicker && (
<ColorPickerContainer>
<ClickOutsideDiv onClick={this.handleClose} />
<ChromePicker
color={value || ''}
onChange={this.handleChange}
disableAlpha={!field.get('enableAlpha', false)}
/>
</ColorPickerContainer>
)}
<input
// text input with padding left for the color swatch
type="text"
id={forID}
className={classNameWrapper}
value={value || ''}
onChange={e => onChange(e.target.value)}
onFocus={setActiveStyle}
onBlur={setInactiveStyle}
style={{
paddingLeft: '75px',
paddingRight: '70px',
color: !allowInput && '#bbb',
}}
// make readonly and open color picker on click if set to allowInput: false
onClick={!allowInput ? this.handleClick : undefined}
readOnly={!allowInput}
/>
</>
);
}
}
11 changes: 11 additions & 0 deletions packages/netlify-cms-widget-color/src/ColorPreview.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import React from 'react';
import PropTypes from 'prop-types';
import { WidgetPreviewContainer } from 'netlify-cms-ui-default';

const ColorPreview = ({ value }) => <WidgetPreviewContainer>{value}</WidgetPreviewContainer>;

ColorPreview.propTypes = {
value: PropTypes.node,
};

export default ColorPreview;
12 changes: 12 additions & 0 deletions packages/netlify-cms-widget-color/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import controlComponent from './ColorControl';
import previewComponent from './ColorPreview';

const Widget = (opts = {}) => ({
name: 'color',
controlComponent,
previewComponent,
...opts,
});

export const NetlifyCmsWidgetColor = { Widget, controlComponent, previewComponent };
export default NetlifyCmsWidgetColor;
3 changes: 3 additions & 0 deletions packages/netlify-cms-widget-color/webpack.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const { getConfig } = require('../../scripts/webpack.js');

module.exports = getConfig();
22 changes: 22 additions & 0 deletions website/content/docs/widgets/color.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
label: 'Color'
title: color
---

The color widget and saves it as a string.

- **Name:** `color`
- **UI:** color picker
- **Data type:** string
- **Options:**
- `default`: accepts a string; defaults to an empty string. Sets the default value
- `allowInput`: accepts a boolean, defaults to `false`. Allows manual editing of the color input value
- `enableAlpha`: accepts a boolean, defaults to `false`. Enables Alpha editing
- **Example:**
```yaml
- { label: 'Color', name: 'color', widget: 'color' }
```
- **Example:**
```yaml
- { label: 'Color', name: 'color', widget: 'color', enableAlpha: true, allowInput: true }
```
Loading