Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
tiberiuichim committed Oct 3, 2020
1 parent a89d43d commit c01be5d
Show file tree
Hide file tree
Showing 14 changed files with 430 additions and 73 deletions.
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,8 @@
"scripts": {
"release": "release-it",
"bootstrap": "./bootstrap"
},
"dependencies": {
"react-color": "2.18.1"
}
}
75 changes: 18 additions & 57 deletions src/BlockStyleWrapper/Edit.jsx
Original file line number Diff line number Diff line change
@@ -1,63 +1,24 @@
import React from 'react';
import { Portal } from 'react-portal';
import themeSVG from '@plone/volto/icons/theme.svg';
import { Icon } from '@plone/volto/components';
import SidebarPopup from '../SidebarPopup/SidebarPopup';
import { doesNodeContainClick } from 'semantic-ui-react/dist/commonjs/lib';

import './styles.less';
import { StyleWrapperEdit, StyleWrapperView } from '../StyleWrapper';

export default (props) => {
const { children, selected } = props;
const [isOpen, setIsOpen] = React.useState(false);
const nodeRef = React.useRef();

const closeSidebar = React.useCallback(
(e) => {
if (isOpen && !doesNodeContainClick(nodeRef.current, e)) setIsOpen(false);
},
[isOpen],
);

React.useEffect(() => {
document.addEventListener('click', closeSidebar, false);
return () => {
document.removeEventListener('click', closeSidebar);
};
}, [closeSidebar]);

const { block, data, onChangeBlock } = props;
return (
<>
{selected ? (
<>
<Portal
node={
__CLIENT__ &&
document.querySelector(
'#sidebar > .sidebar-container > .tabs-wrapper > .formtabs',
)
}
>
<div id="open-styles-button">
<button
compact
onClick={() => {
setIsOpen(true);
}}
title="Style palette"
>
<Icon name={themeSVG} size="18px" />
</button>
</div>
</Portal>
<SidebarPopup open={isOpen} ref={nodeRef}>
<h1> Blabdsadsa</h1>
</SidebarPopup>
</>
) : (
''
)}
{children}
</>
<StyleWrapperEdit
{...props}
data={data?.styles || {}}
choices={[]}
onChangeValue={(id, value) =>
onChangeBlock(block, {
...data,
styles: {
...data?.styles,
[id]: value,
},
})
}
>
<StyleWrapperView {...props} data={data.styles || {}} />
</StyleWrapperEdit>
);
};
6 changes: 5 additions & 1 deletion src/BlockStyleWrapper/View.jsx
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
import React from 'react';
export default (props) => <div>Edit</div>;
import { StyleWrapperView } from '../StyleWrapper';

export default ({ data, children }) => (
<StyleWrapperView data={data.styles || {}}>{children}</StyleWrapperView>
);
15 changes: 0 additions & 15 deletions src/BlockStyleWrapper/styles.less

This file was deleted.

72 changes: 72 additions & 0 deletions src/StyleWrapper/StyleWrapperEdit.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import React from 'react';
import { Portal } from 'react-portal';
import { doesNodeContainClick } from 'semantic-ui-react/dist/commonjs/lib';
import { Icon } from '@plone/volto/components';
import themeSVG from '@plone/volto/icons/theme.svg';
import SidebarPopup from '../SidebarPopup/SidebarPopup';
import InlineForm from '@plone/volto/components/manage/Form/InlineForm';
import { StyleSchema } from './schema';

export default (props) => {
const { children, selected, onChangeValue, data } = props;
const [isOpen, setIsOpen] = React.useState(false);
const nodeRef = React.useRef();

const closeSidebar = React.useCallback(
(e) => {
if (isOpen && !doesNodeContainClick(nodeRef.current, e)) setIsOpen(false);
},
[isOpen],
);

React.useEffect(() => {
document.addEventListener('click', closeSidebar, false);
return () => {
document.removeEventListener('click', closeSidebar);
};
}, [closeSidebar]);

const schema = React.useMemo(() => StyleSchema(), []);

return (
<>
{selected ? (
<>
<Portal
node={
__CLIENT__ &&
document.querySelector(
'#sidebar > .sidebar-container > .tabs-wrapper > .formtabs',
)
}
>
<div id="open-styles-button">
<button
compact
onClick={() => {
setIsOpen(true);
}}
title="Style palette"
>
<Icon name={themeSVG} size="18px" />
</button>
</div>
</Portal>
<SidebarPopup open={isOpen} ref={nodeRef}>
<InlineForm
schema={schema}
title={schema.title}
onChangeField={(id, value) => {
onChangeValue(id, value);
}}
formData={data}
/>
</SidebarPopup>
</>
) : (
''
)}
{children}
</>
);
};
49 changes: 49 additions & 0 deletions src/StyleWrapper/StyleWrapperView.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import React from 'react';
import cx from 'classnames';
import { settings } from '~/config';

export function getStyles(data) {
return {
backgroundColor: data.backgroundColor,
color: data.textColor,
textAlign: data.textAlign,
// fill in more
};
}

export function getStyle(name) {
const { pluggableStyles = [] } = settings;
return pluggableStyles.find(({ id }) => id === name);
}

export default (props) => {
const { data = {}, children } = props;
const { style_name, align, size } = data;
const style = getStyle(style_name);
const ViewWrapper = style?.viewComponent;

return (
<div
className={cx(
'align',
style?.cssClass,
{
center: !Boolean(align),
},
align,
)}
style={getStyles(data)}
>
<div
className={cx({
'full-width': align === 'full',
large: size === 'l',
medium: size === 'm',
small: size === 's',
})}
>
{ViewWrapper ? <ViewWrapper {...props} /> : children}
</div>
</div>
);
};
2 changes: 2 additions & 0 deletions src/StyleWrapper/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export StyleWrapperEdit from './StyleWrapperEdit';
export StyleWrapperView from './StyleWrapperView';
40 changes: 40 additions & 0 deletions src/StyleWrapper/schema.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
export const StyleSchema = () => ({
title: 'Styles',
fieldsets: [
{
id: 'default',
title: 'Default',
fields: ['style_name', 'align', 'size'],
},
{
id: 'advanced',
title: 'Advanced',
fields: ['backgroundColor', 'textColor'],
},
],
properties: {
style_name: {
title: 'Style',
widget: 'style_select',
},
align: {
title: 'Align',
widget: 'style_align',
},
size: {
title: 'Size',
widget: 'style_size',
},
backgroundColor: {
title: 'Background color',
type: 'color',
widget: 'style_simple_color',
},
textColor: {
title: 'Text color',
type: 'color',
widget: 'style_simple_color',
},
},
required: [],
});
29 changes: 29 additions & 0 deletions src/Widgets/Align.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/**
* AlignWidget component.
* To benefit from styling integration, use with a field named 'align'
* @module components/manage/Widgets/AlignWidget
*/

import React from 'react';
import { injectIntl } from 'react-intl';

import { FormFieldWrapper } from '@plone/volto/components';
import { AlignBlock } from '@plone/volto/helpers';

const AlignWidget = (props) => {
const { id, onChange, value } = props;
return (
<FormFieldWrapper {...props} className="align-widget">
<div className="align-tools">
<AlignBlock
align={value}
onChangeBlock={(block, { align }) => onChange(id, align)}
data={{ align: value }}
block={id}
/>
</div>
</FormFieldWrapper>
);
};

export default injectIntl(AlignWidget);
55 changes: 55 additions & 0 deletions src/Widgets/SimpleColorPicker.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import React from 'react';
import { GithubPicker } from 'react-color';
import { FormFieldWrapper, Icon } from '@plone/volto/components';
import { Button } from 'semantic-ui-react';
import clearSVG from '@plone/volto/icons/clear.svg';

export default (props) => {
const { id, value, onChange, available_colors } = props;
const [showPicker, setShowPicker] = React.useState(false);

return (
<FormFieldWrapper
{...props}
draggable={false}
className="simple-color-picker-widget"
>
<div>
<Button.Group>
<Button
color={value}
style={{ backgroundColor: value }}
onClick={() => setShowPicker(true)}
size="huge"
title="Pick color"
>
{''}
</Button>
<Button
compact
style={{ paddingLeft: '8px', paddingRight: '0px' }}
onClick={() => onChange(id, null)}
>
<Icon name={clearSVG} size="18px" color="red" />
</Button>
</Button.Group>

{showPicker ? (
<GithubPicker
width="220px"
triangle="top"
className="color-picker"
colors={available_colors}
color={value || '#000'}
onChangeComplete={(value) => {
setShowPicker(false);
onChange(id, value.hex);
}}
/>
) : (
''
)}
</div>
</FormFieldWrapper>
);
};
25 changes: 25 additions & 0 deletions src/Widgets/Size.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/**
* AlignWidget component.
* To benefit from styling integration, use with a field named 'align'
* @module components/manage/Widgets/AlignWidget
*/

import React from 'react';

import { FormFieldWrapper } from '@plone/volto/components';
import ImageSizeWidget from '@plone/volto/components/manage/Blocks/Image/ImageSizeWidget';

const SizeWidget = (props) => {
const { id, onChange, value } = props;
return (
<FormFieldWrapper {...props}>
<ImageSizeWidget
onChangeBlock={(id, { size }) => onChange(id, size)}
data={{ size: value }}
block={id}
/>
</FormFieldWrapper>
);
};

export default SizeWidget;
Loading

0 comments on commit c01be5d

Please sign in to comment.