@springmicro/rte 0.1.3 → 0.1.11

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.
Files changed (87) hide show
  1. package/README.md +57 -4
  2. package/dist/index.js +7361 -7279
  3. package/package.json +7 -3
  4. package/.eslintrc.cjs +0 -18
  5. package/dist/index.d.ts +0 -10
  6. package/dist/index.umd.cjs +0 -469
  7. package/index.html +0 -13
  8. package/src/App.css +0 -42
  9. package/src/App.tsx +0 -10
  10. package/src/contexts/color-context.tsx +0 -53
  11. package/src/hooks/useSimpleFormik.tsx +0 -74
  12. package/src/index.css +0 -68
  13. package/src/index.tsx +0 -3
  14. package/src/main.tsx +0 -10
  15. package/src/slate/base-editor.stories.tsx +0 -16
  16. package/src/slate/base-editor.tsx +0 -116
  17. package/src/slate/blog-rte.stories.tsx +0 -16
  18. package/src/slate/blog-rte.tsx +0 -126
  19. package/src/slate/common/button.tsx +0 -35
  20. package/src/slate/common/element.tsx +0 -13
  21. package/src/slate/common/icon.jsx +0 -97
  22. package/src/slate/components/code-to-text/CodeToTextButton.jsx +0 -19
  23. package/src/slate/components/code-to-text/HtmlCode.jsx +0 -64
  24. package/src/slate/components/code-to-text/HtmlContextMenu.jsx +0 -39
  25. package/src/slate/components/code-to-text/index.jsx +0 -111
  26. package/src/slate/components/color-picker/color-cursor.stories.tsx +0 -16
  27. package/src/slate/components/color-picker/color-cursor.tsx +0 -34
  28. package/src/slate/components/color-picker/color-formats-view.stories.tsx +0 -25
  29. package/src/slate/components/color-picker/color-formats-view.tsx +0 -115
  30. package/src/slate/components/color-picker/color-gradient.stories.tsx +0 -48
  31. package/src/slate/components/color-picker/color-gradient.tsx +0 -128
  32. package/src/slate/components/color-picker/color-hue.stories.tsx +0 -41
  33. package/src/slate/components/color-picker/color-hue.tsx +0 -110
  34. package/src/slate/components/color-picker/color-picker.stories.tsx +0 -25
  35. package/src/slate/components/color-picker/color-picker.tsx +0 -41
  36. package/src/slate/components/color-picker/color-popover.stories.tsx +0 -26
  37. package/src/slate/components/color-picker/color-popover.tsx +0 -58
  38. package/src/slate/components/color-picker/color-swatch.stories.tsx +0 -16
  39. package/src/slate/components/color-picker/color-swatch.tsx +0 -76
  40. package/src/slate/components/color-picker/default-colors.ts +0 -38
  41. package/src/slate/components/color-picker/slate-color-button.tsx +0 -128
  42. package/src/slate/components/embed/Embed.jsx +0 -96
  43. package/src/slate/components/embed/Image.jsx +0 -45
  44. package/src/slate/components/embed/Video.jsx +0 -65
  45. package/src/slate/components/equation/Equation.jsx +0 -19
  46. package/src/slate/components/equation/EquationButton.jsx +0 -68
  47. package/src/slate/components/id/Id.jsx +0 -57
  48. package/src/slate/components/image/image.stories.tsx +0 -17
  49. package/src/slate/components/image/image.tsx +0 -62
  50. package/src/slate/components/image/insert-image-button.stories.tsx +0 -83
  51. package/src/slate/components/image/insert-image-button.tsx +0 -132
  52. package/src/slate/components/image/types.ts +0 -9
  53. package/src/slate/components/link/Link.jsx +0 -56
  54. package/src/slate/components/link/LinkButton.tsx +0 -106
  55. package/src/slate/components/table/Table.jsx +0 -11
  56. package/src/slate/components/table/TableSelector.jsx +0 -97
  57. package/src/slate/components/table-context-menu/TableContextMenu.tsx +0 -106
  58. package/src/slate/custom-types.d.ts +0 -152
  59. package/src/slate/editor.module.css +0 -226
  60. package/src/slate/paper-rte.stories.tsx +0 -16
  61. package/src/slate/paper-rte.tsx +0 -47
  62. package/src/slate/plugins/withEmbeds.js +0 -33
  63. package/src/slate/plugins/withEquation.js +0 -8
  64. package/src/slate/plugins/withImages.ts +0 -69
  65. package/src/slate/plugins/withLinks.js +0 -9
  66. package/src/slate/plugins/withTable.js +0 -74
  67. package/src/slate/serializers/generic.ts +0 -44
  68. package/src/slate/serializers/types.ts +0 -20
  69. package/src/slate/toolbar/index.tsx +0 -186
  70. package/src/slate/toolbar/paper-toolbar.tsx +0 -494
  71. package/src/slate/toolbar/shortcuts.tsx +0 -77
  72. package/src/slate/toolbar/toolbar-groups.ts +0 -213
  73. package/src/slate/types/index.ts +0 -0
  74. package/src/slate/utils/customHooks/useContextMenu.js +0 -42
  75. package/src/slate/utils/customHooks/useFormat.js +0 -26
  76. package/src/slate/utils/customHooks/usePopup.jsx +0 -26
  77. package/src/slate/utils/customHooks/useResize.js +0 -27
  78. package/src/slate/utils/embed.js +0 -18
  79. package/src/slate/utils/equation.js +0 -22
  80. package/src/slate/utils/index.jsx +0 -267
  81. package/src/slate/utils/link.js +0 -44
  82. package/src/slate/utils/p.js +0 -4
  83. package/src/slate/utils/table.js +0 -131
  84. package/src/vite-env.d.ts +0 -1
  85. package/tsconfig.json +0 -32
  86. package/tsconfig.node.json +0 -10
  87. package/vite.config.ts +0 -41
@@ -1,41 +0,0 @@
1
- import React from "react";
2
- import { StoryFn, Meta } from "@storybook/react";
3
- import { ColorHue, ColorHueProps } from "./color-hue";
4
- import { colorStringToColorFormats } from "@springmicro/utils/editor";
5
-
6
- type ColorHueWrapperProps = {
7
- initialColor: string;
8
- width: number;
9
- };
10
-
11
- function ColorHueWrapper({ initialColor, width }: ColorHueWrapperProps) {
12
- const [colorFormats, setColorFormats] = React.useState(
13
- colorStringToColorFormats(initialColor)
14
- );
15
- React.useEffect(() => {
16
- setColorFormats(colorStringToColorFormats(initialColor));
17
- }, [initialColor]);
18
- return (
19
- <ColorHue
20
- width={width}
21
- colorFormats={colorFormats}
22
- setColorFormats={setColorFormats}
23
- />
24
- );
25
- }
26
-
27
- export default {
28
- /* 👇 The title prop is optional.
29
- * See https://storybook.js.org/docs/react/configure/overview#configure-story-loading
30
- * to learn how to generate automatic titles
31
- */
32
- title: "Slate Color Picker/Color Hue",
33
- component: ColorHueWrapper,
34
- } as Meta<typeof ColorHueWrapper>;
35
-
36
- export const Primary = {
37
- args: {
38
- initialColor: "#00ff00",
39
- width: 360,
40
- } as ColorHueWrapperProps,
41
- };
@@ -1,110 +0,0 @@
1
- import { useState, useRef, Dispatch, SetStateAction, useEffect } from "react";
2
- import { Box } from "@mui/material";
3
- import {
4
- hueFromColorFormats,
5
- newColorFormatsFromHue,
6
- } from "@springmicro/utils/editor";
7
- import { ColorFormats } from "@springmicro/utils/types";
8
- import { ColorCursor } from "./color-cursor";
9
-
10
- const hueMax = 360;
11
-
12
- const calcPosFromHue = (hue: number, width: number) => {
13
- return (width * hue) / hueMax;
14
- };
15
-
16
- const calcHueFromPos = (x: number, w: number) => {
17
- return Math.round(Math.min(hueMax, Math.max(0, (hueMax * x) / w)));
18
- };
19
-
20
- export type ColorHueProps = {
21
- width: number;
22
- colorFormats: ColorFormats;
23
- setColorFormats: Dispatch<SetStateAction<ColorFormats>>;
24
- };
25
-
26
- export function ColorHue({
27
- width,
28
- colorFormats,
29
- setColorFormats,
30
- }: ColorHueProps) {
31
- const height = 15;
32
- const ref = useRef();
33
- const [mouseIsDown, setMouseIsDown] = useState(false);
34
- const [cursorPosition, setCursorPosition] = useState({
35
- x: calcPosFromHue(hueFromColorFormats(colorFormats), width),
36
- y: (height * 2) / 3,
37
- });
38
- const [rect, setRect] = useState<DOMRect>();
39
-
40
- const updateHue = (x: number, y: number, w: number, h: number) => {
41
- const newHue = calcHueFromPos(x, w);
42
- setColorFormats(newColorFormatsFromHue(colorFormats, newHue));
43
- };
44
-
45
- useEffect(() => {
46
- setCursorPosition({
47
- x: calcPosFromHue(hueFromColorFormats(colorFormats), width),
48
- y: cursorPosition.y,
49
- });
50
- }, [colorFormats]);
51
-
52
- return (
53
- <Box
54
- ref={ref}
55
- onMouseDown={(e) => {
56
- if (!ref.current) return;
57
- setMouseIsDown(true);
58
- const rect = (ref.current as HTMLElement).getBoundingClientRect();
59
- setRect(rect);
60
- // e.clientX was not giving the right position within the element
61
- // calculate instead
62
- const x = e.pageX - rect.x;
63
- const y = e.pageY - rect.y;
64
- updateHue(x, y, rect.width, rect.height);
65
- }}
66
- onMouseUp={(e) => {
67
- setMouseIsDown(false);
68
- }}
69
- onMouseMove={(e) => {
70
- if (mouseIsDown && rect) {
71
- const x = e.pageX - rect.x;
72
- const y = e.pageY - rect.y;
73
- if (x <= width && y <= height && x >= 0 && y >= 0) {
74
- // console.log(x, y, rect.x, rect.y)
75
- updateHue(x, y, rect.width, rect.height);
76
- }
77
- }
78
- }}
79
- sx={{
80
- position: "relative",
81
- height,
82
- width,
83
- background: `linear-gradient(
84
- to right,
85
- rgba(255, 0, 0, 1) 0%,
86
- rgba(255, 255, 0, 1) 17%,
87
- rgba(0, 255, 0, 1) 34%,
88
- rgba(0, 255, 255, 1) 51%,
89
- rgba(0, 0, 255, 1) 68%,
90
- rgba(255, 0, 255, 1) 85%,
91
- rgba(255, 0, 0, 1) 100%
92
- )`,
93
- borderRadius: 1,
94
- }}
95
- >
96
- <Box
97
- sx={{
98
- position: "absolute",
99
- top: cursorPosition.y + "px",
100
- left: cursorPosition.x + "px",
101
- transform: "translate(-50%, -50%)",
102
- }}
103
- >
104
- <ColorCursor
105
- color={`hsl(${hueFromColorFormats(colorFormats)}, 100%, 50%)`}
106
- />
107
- </Box>
108
- </Box>
109
- );
110
- }
@@ -1,25 +0,0 @@
1
- import React from "react";
2
- import { StoryFn, Meta } from "@storybook/react";
3
- import { ColorPicker, ColorPickerProps } from "./color-picker";
4
- import { ColorProvider } from "../../../contexts/color-context";
5
-
6
- function ColorPickerWrapper(props: ColorPickerProps) {
7
- return (
8
- <ColorProvider initialColor={props.color}>
9
- <ColorPicker />
10
- </ColorProvider>
11
- );
12
- }
13
-
14
- export default {
15
- /* 👇 The title prop is optional.
16
- * See https://storybook.js.org/docs/react/configure/overview#configure-story-loading
17
- * to learn how to generate automatic titles
18
- */
19
- title: "Slate Color Picker/Color Picker",
20
- component: ColorPickerWrapper,
21
- } as Meta<typeof ColorPickerWrapper>;
22
-
23
- export const Primary = {
24
- args: { color: "green" } as ColorPickerProps,
25
- };
@@ -1,41 +0,0 @@
1
- import * as React from "react";
2
- import { Box } from "@mui/material";
3
- import { ColorGradient } from "./color-gradient";
4
- import { ColorHue } from "./color-hue";
5
- import { ColorFormatsView } from "./color-formats-view";
6
- import { ColorContext } from "../../../contexts/color-context";
7
-
8
- export type ColorPickerProps = {
9
- color: string;
10
- };
11
-
12
- export function ColorPicker() {
13
- const { colorFormats, setColorFormats } = React.useContext(ColorContext);
14
- const width = 360;
15
- const height = 250;
16
-
17
- return (
18
- <Box sx={{ display: "flex", flexDirection: "row", gap: 2 }}>
19
- <Box sx={{ display: "flex", flexDirection: "column", gap: 2 }}>
20
- <ColorGradient
21
- width={width}
22
- height={height}
23
- colorFormats={colorFormats}
24
- setColorFormats={setColorFormats}
25
- />
26
- <ColorHue
27
- width={width}
28
- colorFormats={colorFormats}
29
- setColorFormats={setColorFormats}
30
- />
31
- </Box>
32
- <Box>
33
- <ColorFormatsView
34
- height={height}
35
- colorFormats={colorFormats}
36
- setColorFormats={setColorFormats}
37
- />
38
- </Box>
39
- </Box>
40
- );
41
- }
@@ -1,26 +0,0 @@
1
- import { ColorPopover, ColorPopoverProps } from "./color-popover";
2
- import React from "react";
3
- import { StoryFn, Meta } from "@storybook/react";
4
- import { Button } from "@mui/material";
5
- import { ColorProvider } from "../../../contexts/color-context";
6
-
7
- function ColorPopoverWrapper(props: ColorPopoverProps) {
8
- return (
9
- <ColorProvider initialColor="blue">
10
- <ColorPopover {...props} />
11
- </ColorProvider>
12
- );
13
- }
14
-
15
- export default {
16
- /* 👇 The title prop is optional.
17
- * See https://storybook.js.org/docs/react/configure/overview#configure-story-loading
18
- * to learn how to generate automatic titles
19
- */
20
- title: "Slate Color Picker/Color Popover",
21
- component: ColorPopoverWrapper,
22
- } as Meta<typeof ColorPopoverWrapper>;
23
-
24
- export const Primary = {
25
- args: { children: <Button>Pick Color</Button> } as ColorPopoverProps,
26
- };
@@ -1,58 +0,0 @@
1
- import * as React from "react";
2
- import { Popover, Box, BoxProps } from "@mui/material";
3
- import { ColorPicker } from "./color-picker";
4
-
5
- export type ColorPopoverProps = {
6
- boxProps?: BoxProps;
7
- };
8
-
9
- export function ColorPopover({
10
- children,
11
- boxProps,
12
- }: React.PropsWithChildren<ColorPopoverProps>) {
13
- const [anchorEl, setAnchorEl] = React.useState<HTMLDivElement | null>(null);
14
-
15
- const handleClick = (event: React.MouseEvent<HTMLDivElement>) => {
16
- setAnchorEl(event.currentTarget);
17
- };
18
-
19
- const handleClose = () => {
20
- setAnchorEl(null);
21
- };
22
-
23
- const open = Boolean(anchorEl);
24
- const id = open ? "simple-popover" : undefined;
25
-
26
- return (
27
- <>
28
- <Box
29
- {...boxProps}
30
- sx={{
31
- ...boxProps?.sx,
32
- // "-webkit-appearance": "button",
33
- cursor: "pointer",
34
- // backgroundColor: "transparent",
35
- // backgroundImage: "none",
36
- }}
37
- role="button"
38
- // component="button"
39
- aria-describedby={id}
40
- onClick={handleClick}
41
- >
42
- {children}
43
- </Box>
44
- <Popover
45
- id={id}
46
- open={open}
47
- anchorEl={anchorEl}
48
- onClose={handleClose}
49
- anchorOrigin={{
50
- vertical: "top",
51
- horizontal: "right",
52
- }}
53
- >
54
- <ColorPicker />
55
- </Popover>
56
- </>
57
- );
58
- }
@@ -1,16 +0,0 @@
1
- import { ColorSwatch, ColorSwatchProps } from "./color-swatch";
2
- import React from "react";
3
- import { StoryFn, Meta } from "@storybook/react";
4
-
5
- export default {
6
- /* 👇 The title prop is optional.
7
- * See https://storybook.js.org/docs/react/configure/overview#configure-story-loading
8
- * to learn how to generate automatic titles
9
- */
10
- title: "Slate Color Picker/Color Swatch",
11
- component: ColorSwatch,
12
- } as Meta<typeof ColorSwatch>;
13
-
14
- export const Primary = {
15
- args: { color: "blue" } as ColorSwatchProps,
16
- };
@@ -1,76 +0,0 @@
1
- import { Button, Popover, Typography, useTheme } from "@mui/material";
2
- import * as React from "react";
3
- import { colorConvert, isColor } from "@springmicro/utils/editor";
4
-
5
- export type ColorSwatchProps = {
6
- color: string;
7
- onClick?: React.MouseEventHandler<HTMLButtonElement>;
8
- };
9
-
10
- export function ColorSwatch(props: ColorSwatchProps) {
11
- const theme = useTheme();
12
- const { color, onClick } = props;
13
- const [anchorEl, setAnchorEl] = React.useState<HTMLElement | null>(null);
14
-
15
- if (!isColor(color)) {
16
- throw new Error(`Could not render color ${color}.`);
17
- }
18
-
19
- const handlePopoverOpen = (event: React.MouseEvent<HTMLElement>) => {
20
- setAnchorEl(event.currentTarget);
21
- };
22
-
23
- const handlePopoverClose = () => {
24
- setAnchorEl(null);
25
- };
26
-
27
- const open = Boolean(anchorEl);
28
-
29
- return (
30
- <>
31
- <Button
32
- aria-owns={open ? "mouse-over-popover" : undefined}
33
- aria-haspopup="true"
34
- onMouseEnter={handlePopoverOpen}
35
- onMouseLeave={handlePopoverClose}
36
- aria-label={`selected color: ${colorConvert(color, "hex")}`}
37
- sx={{
38
- backgroundColor: color,
39
- width: 24,
40
- height: 24,
41
- minWidth: "unset",
42
- padding: "unset",
43
- borderRadius: 0.5,
44
- "&:hover": {
45
- backgroundColor: color,
46
- // @ts-ignore
47
- outline: `4px solid ${theme.palette.neutral["200"]}`,
48
- },
49
- }}
50
- onClick={onClick}
51
- ></Button>
52
- <Popover
53
- id="mouse-over-popover"
54
- sx={{
55
- pointerEvents: "none",
56
- }}
57
- open={open}
58
- anchorEl={anchorEl}
59
- anchorOrigin={{
60
- vertical: "bottom",
61
- horizontal: "left",
62
- }}
63
- transformOrigin={{
64
- vertical: "top",
65
- horizontal: "left",
66
- }}
67
- onClose={handlePopoverClose}
68
- disableRestoreFocus
69
- >
70
- <Typography sx={{ p: 1 }} fontSize={12}>
71
- {colorConvert(color, "hex")}
72
- </Typography>
73
- </Popover>
74
- </>
75
- );
76
- }
@@ -1,38 +0,0 @@
1
- export const defaultColors = [
2
- "#000000",
3
- "#e60000",
4
- "#ff9900",
5
- "#ffff00",
6
- "#008a00",
7
- "#0066cc",
8
- "#9933ff",
9
- "#ffffff",
10
- "#f9fafc", // This is the color of the slate editor background, without this color it's hard to set the background color back to the paper color without using a tool to tell you the color of the element. I would rather offer a transparent option to solve this problem.
11
- "#facccc",
12
- "#ffebcc",
13
- "#ffffcc",
14
- "#cce8cc",
15
- "#cce0f5",
16
- "#ebd6ff",
17
- "#bbbbbb",
18
- "#f06666",
19
- "#ffc266",
20
- "#ffff66",
21
- "#66b966",
22
- "#66a3e0",
23
- "#c285ff",
24
- "#888888",
25
- "#a10000",
26
- "#b26b00",
27
- "#b2b200",
28
- "#006100",
29
- "#0047b2",
30
- "#6b24b2",
31
- "#444444",
32
- "#5c0000",
33
- "#663d00",
34
- "#666600",
35
- "#003700",
36
- "#002966",
37
- "#3d1466",
38
- ];
@@ -1,128 +0,0 @@
1
- import * as React from "react";
2
- import { BaseEditor, BaseSelection, Location, Transforms } from "slate";
3
- import { ColorProvider } from "../../../contexts/color-context";
4
- import { ColorPopover } from "./color-popover";
5
- import { activeMark, addMarkData, defaultMarkData } from "../../utils";
6
- import Icon from "../../common/icon";
7
- import Button from "../../common/button";
8
- import { ColorSwatch } from "./color-swatch";
9
- import { Box, Menu } from "@mui/material";
10
- import { defaultColors } from "./default-colors";
11
- import { CustomEditor } from "../../custom-types";
12
-
13
- export type SlateColorButtonProps = {
14
- format: "bgcolor" | "color";
15
- editor: CustomEditor;
16
- };
17
-
18
- export function SlateColorButton({ format, editor }: SlateColorButtonProps) {
19
- const [anchorEl, setAnchorEl] = React.useState<null | Element>(null);
20
- const open = Boolean(anchorEl);
21
- const id = `${format}-menu-button`;
22
- const [selection, setSelection] = React.useState<BaseSelection | Location>();
23
- const initialColor =
24
- format === "bgcolor"
25
- ? defaultMarkData["bgColor"]
26
- : defaultMarkData["color"];
27
-
28
- React.useEffect(() => {
29
- if (editor.selection) {
30
- setSelection(editor.selection);
31
- }
32
- }, [editor.selection]);
33
-
34
- const getCurrentColor = () => {
35
- if (!selection) return initialColor;
36
- Transforms.select(editor, selection!);
37
- return activeMark(editor, format)[format] ?? initialColor;
38
- };
39
-
40
- const handleClick = (event?: React.MouseEvent<HTMLButtonElement>) => {
41
- const el = event?.currentTarget
42
- ? event.currentTarget
43
- : document.querySelector(`#${id}`);
44
- setSelection(editor.selection);
45
- if (anchorEl) setAnchorEl(null);
46
- else if (el) setAnchorEl(el);
47
- };
48
-
49
- const handleSwatchClick = (value: string) => {
50
- if (selection === undefined) return;
51
- Transforms.select(editor, selection!);
52
- console.log(editor.selection, format, value);
53
- addMarkData(editor, {
54
- format: format,
55
- value: value,
56
- });
57
- if (anchorEl) setAnchorEl(null);
58
- };
59
-
60
- return (
61
- <>
62
- <Button
63
- id={id}
64
- aria-controls={open ? "basic-menu" : undefined}
65
- aria-haspopup="true"
66
- aria-expanded={open ? "true" : undefined}
67
- onClick={handleClick}
68
- format="link"
69
- style={{ backgroundColor: "#f9fafc" }}
70
- >
71
- <Icon icon={format} />
72
- </Button>
73
- <Menu
74
- id="basic-menu"
75
- anchorEl={anchorEl}
76
- open={open}
77
- onClose={() => handleClick()}
78
- MenuListProps={{
79
- "aria-labelledby": id,
80
- }}
81
- >
82
- <Box
83
- sx={{
84
- display: "grid",
85
- gap: 1,
86
- gridTemplateColumns: "repeat(6, 1fr)",
87
- gridTemplateRows: "repeat(6, 1fr)",
88
- p: 1,
89
- }}
90
- >
91
- {defaultColors.map((c) => (
92
- <ColorSwatch
93
- onClick={(e) => handleSwatchClick(c)}
94
- color={c}
95
- key={c}
96
- />
97
- ))}
98
- </Box>
99
- <ColorProvider
100
- initialColor={initialColor}
101
- colorChangeCallback={(color) => {
102
- if (color !== getCurrentColor()) {
103
- addMarkData(editor, {
104
- format: format,
105
- value: color,
106
- });
107
- }
108
- }}
109
- >
110
- <ColorPopover>
111
- <Box sx={{ px: 1 }}>
112
- <Icon icon="colorize" /> Custom Color{" "}
113
- <Box
114
- component="span"
115
- sx={{
116
- // background: getCurrentColor(),
117
- height: 8,
118
- width: 8,
119
- display: "inline-block",
120
- }}
121
- ></Box>
122
- </Box>
123
- </ColorPopover>
124
- </ColorProvider>
125
- </Menu>{" "}
126
- </>
127
- );
128
- }
@@ -1,96 +0,0 @@
1
- import React, { useRef, useState } from "react";
2
- import Button from "../../common/button";
3
- import Icon from "../../common/icon";
4
- import { isBlockActive } from "../../utils";
5
- import usePopup from "../../utils/customHooks/usePopup";
6
- import { insertEmbed } from "../../utils/embed";
7
- import { Transforms } from "slate";
8
- import { ReactEditor } from "slate-react";
9
-
10
- const Embed = ({ editor, format }) => {
11
- const urlInputRef = useRef();
12
- const [showInput, setShowInput] = usePopup(urlInputRef);
13
- const [formData, setFormData] = useState({
14
- url: "",
15
- alt: "",
16
- });
17
- const [selection, setSelection] = useState();
18
- const handleButtonClick = (e) => {
19
- e.preventDefault();
20
- setSelection(editor.selection);
21
- selection && ReactEditor.focus(editor);
22
-
23
- setShowInput((prev) => !prev);
24
- };
25
- const handleFormSubmit = (e) => {
26
- e.preventDefault();
27
-
28
- selection && Transforms.select(editor, selection);
29
- selection && ReactEditor.focus(editor);
30
-
31
- insertEmbed(editor, { ...formData }, format);
32
- setShowInput(false);
33
- setFormData({
34
- url: "",
35
- alt: "",
36
- });
37
- };
38
- const handleImageUpload = () => {
39
- setShowInput(false);
40
- };
41
- return (
42
- <div ref={urlInputRef} className="popup-wrapper">
43
- <Button
44
- active={isBlockActive(editor, format)}
45
- style={{
46
- border: showInput ? "1px solid lightgray" : "",
47
- borderBottom: "none",
48
- }}
49
- format={format}
50
- onClick={handleButtonClick}
51
- >
52
- <Icon icon={format} />
53
- </Button>
54
- {showInput && (
55
- <div className="popup">
56
- {format === "image" && (
57
- <div>
58
- <div
59
- style={{ display: "flex", gap: "10px" }}
60
- onClick={handleImageUpload}
61
- >
62
- <Icon icon="upload" />
63
- <span>Upload</span>
64
- </div>
65
- <p style={{ textAlign: "center", opacity: "0.7", width: "100%" }}>
66
- OR
67
- </p>
68
- </div>
69
- )}
70
- <form onSubmit={handleFormSubmit}>
71
- <input
72
- type="text"
73
- placeholder="Enter url"
74
- value={formData.url}
75
- onChange={(e) =>
76
- setFormData((prev) => ({ ...prev, url: e.target.value }))
77
- }
78
- />
79
- <input
80
- type="text"
81
- placeholder="Enter alt"
82
- value={formData.alt}
83
- onChange={(e) =>
84
- setFormData((prev) => ({ ...prev, alt: e.target.value }))
85
- }
86
- />
87
-
88
- <Button type="submit">Save</Button>
89
- </form>
90
- </div>
91
- )}
92
- </div>
93
- );
94
- };
95
-
96
- export default Embed;