@soul-refiner/design-system 0.1.26 → 0.1.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,46 +2,34 @@ import React from 'react';
2
2
  import styled from 'styled-components';
3
3
  import {
4
4
  createPluginFactory,
5
- ELEMENT_LINK,
6
- getAboveNode,
7
- insertLink,
5
+ getBlockAbove,
6
+ getPluginType,
8
7
  isEditorReadOnly,
9
8
  setNodes,
9
+ someNode,
10
+ PlateElement,
11
+ PlateElementProps,
10
12
  PlateRenderElementProps,
11
13
  } from '@udecode/plate';
12
- import { Button as UIButton, P } from 'components';
13
- import {
14
- BUTTON_COMMENT,
15
- BUTTON_GIFT_SUBSCRIPTION,
16
- BUTTON_LINK,
17
- BUTTON_SHARE,
18
- BUTTON_SHARE_PAGE,
19
- BUTTON_SPECIAL_OFFER,
20
- BUTTON_SUBSCRIBE,
21
- BUTTON_SIGNUP,
22
- COLORS,
23
- ELEMENT_BUTTON,
24
- ELEMENT_PARAGRAPH,
25
- } from '../constants';
14
+ import { Button as UIButton } from 'components';
15
+ import { COLORS, ELEMENT_BUTTON, ELEMENT_PARAGRAPH } from '../constants';
26
16
 
27
- export const Button = ({
28
- attributes,
29
- className,
30
- children,
31
- editor,
32
- element,
33
- }: PlateRenderElementProps) => {
34
- const [state, setState] = React.useState('');
35
- const { ref: _, ...htmlAttributes } = attributes;
17
+ export const Button = React.forwardRef<
18
+ React.ElementRef<typeof PlateElement>,
19
+ PlateElementProps
20
+ >(({ children, editor, element, ...props }: PlateRenderElementProps, ref) => {
36
21
  const { buttonType, color } = element;
37
22
 
38
- const currAboveNode = getAboveNode(editor, {
39
- /**
40
- * @todo possibly wrong
41
- */
42
- at: editor.prevSelection?.focus,
23
+ const pressed =
24
+ !!editor?.selection &&
25
+ someNode(editor, {
26
+ match: { type: getPluginType(editor, ELEMENT_BUTTON) },
27
+ });
28
+
29
+ const currBlock = getBlockAbove(editor, {
30
+ at: editor.selection?.focus,
43
31
  match: {
44
- type: ELEMENT_BUTTON,
32
+ type: getPluginType(editor, ELEMENT_BUTTON),
45
33
  buttonType: buttonType,
46
34
  },
47
35
  });
@@ -49,21 +37,21 @@ export const Button = ({
49
37
  const editable = !isEditorReadOnly(editor);
50
38
 
51
39
  const handleColorChange = (color: string) => {
52
- if (currAboveNode) {
40
+ if (currBlock) {
53
41
  setNodes(
54
42
  editor,
55
43
  {
56
44
  color,
57
45
  },
58
46
  {
59
- at: currAboveNode ? currAboveNode[1] : undefined,
47
+ at: currBlock ? currBlock[1] : undefined,
60
48
  }
61
49
  );
62
50
  }
63
51
  };
64
52
 
65
53
  const ColorMenu = () =>
66
- !currAboveNode?.[1] || !editable ? null : (
54
+ !pressed || !editable ? null : (
67
55
  <ColorMenuComponent contentEditable={false}>
68
56
  {COLORS.map((color) => (
69
57
  <ColorItem
@@ -80,12 +68,38 @@ export const Button = ({
80
68
  );
81
69
 
82
70
  return (
83
- <ButtonWrapper>
84
- <ColorMenu />
85
- <UIButton>{children}</UIButton>
86
- </ButtonWrapper>
71
+ <PlateElement
72
+ asChild
73
+ editor={editor}
74
+ element={element}
75
+ ref={ref}
76
+ {...props}
77
+ >
78
+ <>
79
+ <ColorMenu />
80
+ <UIButton
81
+ size="small"
82
+ sx={`
83
+ margin-left: auto !important;
84
+ margin-right: auto !important;
85
+ background-color: ${
86
+ color ? color : 'var(--color-blue-5)'
87
+ } !important;
88
+ border-color: ${color ? color : 'var(--color-blue-5)'} !important;
89
+ &:hover {
90
+ background-color: ${
91
+ color ? color : 'var(--color-blue-5)'
92
+ } !important;
93
+ filter: brightness(85%);
94
+ }
95
+ `}
96
+ >
97
+ {children}
98
+ </UIButton>
99
+ </>
100
+ </PlateElement>
87
101
  );
88
- };
102
+ });
89
103
 
90
104
  const ColorMenuComponent = styled.div`
91
105
  display: flex;
@@ -94,6 +108,7 @@ const ColorMenuComponent = styled.div`
94
108
  gap: 16px;
95
109
  z-index: 5;
96
110
  position: absolute;
111
+ transform: translateY(24px);
97
112
  left: calc(50% - 148px);
98
113
  border-radius: 16px;
99
114
  padding: 8px 16px;
@@ -109,14 +124,12 @@ const ColorItem = styled.div<{ $color: string }>`
109
124
  cursor: pointer;
110
125
  `;
111
126
 
112
- const ButtonWrapper = styled.div``;
113
-
114
127
  export const createButtonsPlugin = createPluginFactory({
115
128
  key: ELEMENT_BUTTON,
116
129
  type: ELEMENT_BUTTON,
117
130
  isElement: true,
118
131
  component: Button,
119
- then: (editor) => ({
132
+ then: () => ({
120
133
  inject: {
121
134
  props: {
122
135
  classNames: undefined,
@@ -2,7 +2,6 @@ import { KEYS_HEADING } from '@udecode/plate';
2
2
  import {
3
3
  ELEMENT_BLOCKQUOTE,
4
4
  ELEMENT_BUTTON,
5
- ELEMENT_CODE_BLOCK,
6
5
  ELEMENT_MEDIA,
7
6
  ELEMENT_MEDIA_EMBED,
8
7
  ELEMENT_OL,
@@ -27,7 +26,6 @@ export const exitBreakPlugin = {
27
26
  allow: [
28
27
  ELEMENT_BLOCKQUOTE,
29
28
  ELEMENT_BUTTON,
30
- ELEMENT_CODE_BLOCK,
31
29
  ELEMENT_MEDIA,
32
30
  ELEMENT_MEDIA_EMBED,
33
31
  ELEMENT_OL,
@@ -0,0 +1,80 @@
1
+ import React from 'react';
2
+ import styled from 'styled-components';
3
+ import {
4
+ Box,
5
+ Caption,
6
+ CaptionTextarea,
7
+ Image,
8
+ PlateElement,
9
+ PlateElementProps,
10
+ Resizable,
11
+ TImageElement,
12
+ useMediaState,
13
+ Value,
14
+ } from '@udecode/plate';
15
+ import { useReadOnly } from 'slate-react';
16
+
17
+ const align = 'center';
18
+
19
+ export const ImageElement = ({
20
+ ...props
21
+ }: PlateElementProps<Value, TImageElement>) => {
22
+ const { children, nodeProps } = props;
23
+
24
+ const readOnly = useReadOnly();
25
+
26
+ useMediaState();
27
+
28
+ return (
29
+ <PlateElement {...props}>
30
+ <Figure className="group" contentEditable={false}>
31
+ <Resizable
32
+ style={{
33
+ alignItems: 'center',
34
+ width: '100%',
35
+ maxWidth: '100%',
36
+ marginLeft: 'auto',
37
+ marginRight: 'auto',
38
+ }}
39
+ options={{
40
+ renderHandleLeft: (htmlProps) => <Box {...htmlProps} />,
41
+ renderHandleRight: (htmlProps) => <Box {...htmlProps} />,
42
+ align,
43
+ readOnly,
44
+ }}
45
+ >
46
+ <Image {...nodeProps} />
47
+ </Resizable>
48
+ <Caption className="HERE">
49
+ <Textarea
50
+ $readOnly={readOnly}
51
+ placeholder="Write a caption..."
52
+ readOnly={readOnly}
53
+ />
54
+ </Caption>
55
+ </Figure>
56
+ {children}
57
+ </PlateElement>
58
+ );
59
+ };
60
+
61
+ const Figure = styled.figure`
62
+ position: relative;
63
+ margin: 0px;
64
+ width: 100%;
65
+
66
+ img {
67
+ width: 100%;
68
+ }
69
+ `;
70
+
71
+ const Textarea = styled(CaptionTextarea)<{ $readOnly: boolean }>`
72
+ width: 100%;
73
+ padding: 8px 16px;
74
+ box-sizing: border-box;
75
+ text-align: center;
76
+ resize: none;
77
+ outline: none;
78
+ border: 1px solid
79
+ ${({ $readOnly }) => ($readOnly ? 'transparent' : 'var(--color-grey-9)')};
80
+ `;
@@ -1,3 +1,6 @@
1
+ /**
2
+ * PLUGINS
3
+ */
1
4
  import {
2
5
  createBlockquotePlugin,
3
6
  createCodeBlockPlugin,
@@ -5,6 +8,8 @@ import {
5
8
  createHorizontalRulePlugin,
6
9
  createIndentListPlugin,
7
10
  createImagePlugin,
11
+ createTextIndentPlugin,
12
+ createListPlugin,
8
13
  createMediaEmbedPlugin,
9
14
  createResetNodePlugin,
10
15
  createTablePlugin,
@@ -22,24 +27,11 @@ import {
22
27
  createIndentPlugin,
23
28
  createLineHeightPlugin,
24
29
  createLinkPlugin,
25
- PlateFloatingLink,
26
30
  createExitBreakPlugin,
27
31
  createHistoryPlugin,
28
32
  createSelectOnBackspacePlugin,
29
33
  createSoftBreakPlugin,
30
34
  } from '@udecode/plate';
31
-
32
- import {
33
- ELEMENT_PARAGRAPH,
34
- ELEMENT_H1,
35
- ELEMENT_H2,
36
- ELEMENT_H3,
37
- ELEMENT_H4,
38
- ELEMENT_H5,
39
- ELEMENT_H6,
40
- ELEMENT_CODE_BLOCK,
41
- } from '../constants';
42
-
43
35
  import { createButtonsPlugin } from './buttons';
44
36
  import { exitBreakPlugin } from './exitBreak';
45
37
  import { resetBlockTypePlugin } from './resetBlockType';
@@ -55,6 +47,26 @@ import {
55
47
  createHSixPlugin,
56
48
  } from './text';
57
49
 
50
+ import { LinkFloatingMenu } from './link';
51
+
52
+ /**
53
+ * ELEMENT TYPES
54
+ */
55
+ import {
56
+ ELEMENT_PARAGRAPH,
57
+ ELEMENT_H1,
58
+ ELEMENT_H2,
59
+ ELEMENT_H3,
60
+ ELEMENT_H4,
61
+ ELEMENT_H5,
62
+ ELEMENT_H6,
63
+ ELEMENT_OL,
64
+ ELEMENT_UL,
65
+ } from '../constants';
66
+
67
+ /**
68
+ * ELEMENT TYPES
69
+ */
58
70
  export const blocks = [
59
71
  createButtonsPlugin(),
60
72
  createBlockquotePlugin(),
@@ -68,6 +80,7 @@ export const blocks = [
68
80
  disableEmbedInsert: true,
69
81
  },
70
82
  }),
83
+ createTextIndentPlugin(),
71
84
  createIndentListPlugin({
72
85
  inject: {
73
86
  props: {
@@ -79,12 +92,13 @@ export const blocks = [
79
92
  ELEMENT_H4,
80
93
  ELEMENT_H5,
81
94
  ELEMENT_H6,
82
- ELEMENT_CODE_BLOCK,
95
+ ELEMENT_OL,
96
+ ELEMENT_UL,
83
97
  ],
84
98
  },
85
99
  },
86
100
  }),
87
- // createFootnotePlugin(),
101
+ createListPlugin(),
88
102
  createMediaEmbedPlugin(),
89
103
  createParagraphPlugin(),
90
104
  createHOnePlugin(),
@@ -138,7 +152,7 @@ export const inline = [
138
152
  }),
139
153
  createLineHeightPlugin(),
140
154
  createLinkPlugin({
141
- renderAfterEditable: PlateFloatingLink,
155
+ renderAfterEditable: LinkFloatingMenu,
142
156
  }),
143
157
  ];
144
158
 
@@ -0,0 +1,144 @@
1
+ import React from 'react';
2
+ import styled from 'styled-components';
3
+ import {
4
+ FloatingLinkUrlInput,
5
+ LinkOpenButton,
6
+ PlateElement,
7
+ PlateElementProps,
8
+ TEditableProps,
9
+ TLinkElement,
10
+ useFloatingLinkEdit,
11
+ useFloatingLinkEditState,
12
+ useFloatingLinkInsert,
13
+ useFloatingLinkInsertState,
14
+ useFloatingLinkSelectors,
15
+ useLink,
16
+ Value,
17
+ } from '@udecode/plate';
18
+ import { Box } from 'components';
19
+ import { AASansSerif, Link, Upload } from 'icons';
20
+
21
+ export const LinkElement = React.forwardRef<
22
+ React.ElementRef<typeof PlateElement>,
23
+ PlateElementProps<Value, TLinkElement>
24
+ >(({ children, ...props }, ref) => {
25
+ const { props: linkProps } = useLink({ element: props.element });
26
+
27
+ return (
28
+ <PlateElement asChild ref={ref} {...linkProps} {...(props as any)}>
29
+ <a>{children}</a>
30
+ </PlateElement>
31
+ );
32
+ });
33
+
34
+ export const LinkFloatingMenu = ({ readOnly }: TEditableProps) => {
35
+ const isEditing = useFloatingLinkSelectors().isEditing();
36
+
37
+ const state = useFloatingLinkInsertState();
38
+ const {
39
+ props: insertProps,
40
+ ref: insertRef,
41
+ textInputProps,
42
+ } = useFloatingLinkInsert(state);
43
+
44
+ const editState = useFloatingLinkEditState();
45
+ const {
46
+ props: editProps,
47
+ ref: editRef,
48
+ editButtonProps,
49
+ } = useFloatingLinkEdit(editState);
50
+
51
+ if (readOnly) return null;
52
+
53
+ const input = (
54
+ <Box
55
+ $dir="column"
56
+ sx={`
57
+ background-color: var(--color-white);
58
+ gap: 16px;
59
+ padding: 16px;
60
+ border-radius: 16px;
61
+ box-shadow: var(--elevation-2);
62
+ `}
63
+ >
64
+ <Box $align="center" $justify="center" $gap={8}>
65
+ <Box $align="center" $justify="center">
66
+ <Link />
67
+ </Box>
68
+ <FloatingLinkUrlInput
69
+ style={{
70
+ border: 'none',
71
+ outline: 'none',
72
+ padding: '8px 12px',
73
+ }}
74
+ placeholder="Paste link"
75
+ />
76
+ </Box>
77
+ <Box $align="center" $justify="center" $gap={8}>
78
+ <Box $align="center" $justify="center">
79
+ <AASansSerif />
80
+ </Box>
81
+ <Input placeholder="Text to display" {...textInputProps} />
82
+ </Box>
83
+ </Box>
84
+ );
85
+
86
+ const editContent = isEditing ? (
87
+ input
88
+ ) : (
89
+ <Box
90
+ $align="center"
91
+ $justify="center"
92
+ sx={`
93
+ box-sizing: box-content;
94
+ background-color: var(--color-white);
95
+ gap: 8px;
96
+ padding: 16px;
97
+ border-radius: 16px;
98
+ box-shadow: var(--elevation-2);
99
+
100
+ a,
101
+ button {
102
+ padding: 8px 12px;
103
+ background-color: transparent;
104
+ outline: none;
105
+ border: none;
106
+ border-radius: 8px;
107
+ cursor: pointer;
108
+ width: max-content;
109
+ font-size: 16px;
110
+ line-height: 16px;
111
+
112
+ &:hover {
113
+ background-color: var(--color-grey-9);
114
+ }
115
+ }
116
+ `}
117
+ $gap={8}
118
+ >
119
+ <button type="button" {...editButtonProps}>
120
+ Edit link
121
+ </button>
122
+ <LinkOpenButton>
123
+ <Upload />
124
+ </LinkOpenButton>
125
+ </Box>
126
+ );
127
+
128
+ return (
129
+ <>
130
+ <div ref={insertRef} {...insertProps}>
131
+ {input}
132
+ </div>
133
+ <div ref={editRef} {...editProps}>
134
+ {editContent}
135
+ </div>
136
+ </>
137
+ );
138
+ };
139
+
140
+ const Input = styled.input`
141
+ border: none;
142
+ outline: none;
143
+ padding: 8px 12px;
144
+ `;
@@ -0,0 +1,34 @@
1
+ import React from 'react';
2
+ import { PlateElement, PlateElementProps } from '@udecode/plate';
3
+ import { styled } from 'styled-components';
4
+
5
+ export const ListElement = ({
6
+ children,
7
+ variant = 'ul',
8
+ ...props
9
+ }: PlateElementProps & {
10
+ variant: 'ul' | 'ol';
11
+ }) => {
12
+ const Element = variant;
13
+
14
+ return (
15
+ <PlateElement asChild {...props}>
16
+ <>
17
+ <Element>
18
+ {React.Children.map(children, (child) => (
19
+ <Li>{child}</Li>
20
+ ))}
21
+ </Element>
22
+ </>
23
+ </PlateElement>
24
+ );
25
+ };
26
+
27
+ const Li = styled.li`
28
+ margin: 16px 0px;
29
+ padding-left: 8px;
30
+
31
+ &::marker {
32
+ color: var(--color-grey-4);
33
+ }
34
+ `;