@team-monolith/cds 1.4.7 → 1.4.9

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.
@@ -10,6 +10,22 @@ import { HorizontalRuleNode } from "@lexical/react/LexicalHorizontalRuleNode";
10
10
  import { getTheme } from "./theme";
11
11
  import { useTheme } from "@emotion/react";
12
12
  import Plugins from "./Plugins";
13
+ function validateValue(value) {
14
+ var _a, _b;
15
+ if (value && typeof value !== "object") {
16
+ return false;
17
+ }
18
+ // value = {
19
+ // root: {
20
+ // children: any[]
21
+ // }
22
+ // }
23
+ // value.root.children must be non-empty array
24
+ if (!((_b = (_a = value === null || value === void 0 ? void 0 : value.root) === null || _a === void 0 ? void 0 : _a.children) === null || _b === void 0 ? void 0 : _b.length)) {
25
+ return false;
26
+ }
27
+ return true;
28
+ }
13
29
  export function LexicalEditor(props) {
14
30
  const { className, value, onChange, editable = true, children } = props;
15
31
  const theme = useTheme();
@@ -32,7 +48,7 @@ export function LexicalEditor(props) {
32
48
  HorizontalRuleNode,
33
49
  ],
34
50
  theme: getTheme(theme),
35
- editorState: value ? JSON.stringify(value) : undefined,
51
+ editorState: validateValue(value) ? JSON.stringify(value) : undefined,
36
52
  editable: editable,
37
53
  };
38
54
  return (_jsxs(LexicalComposer, Object.assign({ initialConfig: initialConfig }, { children: [_jsx(Plugins, { className: className, onChange: onChange }), _jsx(_Fragment, { children: children })] })));
@@ -1,16 +1,32 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
1
10
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useEffect, useRef, useState } from "react";
11
+ import { useContext, useEffect, useRef, useState } from "react";
3
12
  import { INSERT_IMAGE_COMMAND } from ".";
4
13
  import { InsertImageUriDialogBody } from "./InsertImageUriDialogBody";
5
14
  import { InsertImageUploadedDialogBody } from "./InsertImageUploadedDialogBody";
6
15
  import styled from "@emotion/styled";
7
- import { AlertDialog, AlertDialogContent, AlertDialogTitle } from "../../../../components/AlertDialog";
8
- import { ImageFillIcon } from "../../../../icons";
16
+ import { AlertDialog, AlertDialogContent, AlertDialogTitle, } from "../../../../components/AlertDialog";
17
+ import { ImageFillIcon, LinkIcon, UploadLineIcon } from "../../../../icons";
9
18
  import Button from "../../../../components/Button";
19
+ import { useTheme } from "@emotion/react";
20
+ import { CodleDesignSystemContext } from "../../../../CodleDesignSystemProvider";
10
21
  export function InsertImageDialog(props) {
11
22
  const { open, activeEditor, onClose } = props;
23
+ const theme = useTheme();
12
24
  const [mode, setMode] = useState(null);
13
25
  const hasModifier = useRef(false);
26
+ const inputRef = useRef(null);
27
+ const cdsContext = useContext(CodleDesignSystemContext);
28
+ const [src, setSrc] = useState("");
29
+ const [altText, setAltText] = useState("");
14
30
  useEffect(() => {
15
31
  hasModifier.current = false;
16
32
  const handler = (e) => {
@@ -23,17 +39,70 @@ export function InsertImageDialog(props) {
23
39
  }, [activeEditor]);
24
40
  const onClick = (payload) => {
25
41
  activeEditor.dispatchCommand(INSERT_IMAGE_COMMAND, payload);
26
- onClose();
42
+ handleOnClose();
27
43
  };
28
44
  const handleOnClose = () => {
29
45
  setMode(null);
46
+ setSrc("");
47
+ setAltText("");
30
48
  onClose();
31
49
  };
32
- return (_jsxs(AlertDialog, Object.assign({ icon: _jsx(ImageFillIcon, {}), open: open, onClose: handleOnClose, disableIconPadding: true }, { children: [_jsx(AlertDialogTitle, Object.assign({ onClose: handleOnClose }, { children: "\uC774\uBBF8\uC9C0 \uC785\uB825\uD558\uAE30" })), !mode && (_jsx(AlertDialogContent, { children: _jsxs(Buttons, { children: [_jsx(Button, { color: "grey", size: "medium", fullWidth: true, label: "URL \uC785\uB825\uD558\uAE30", onClick: () => setMode("url") }), _jsx(Button, { color: "grey", size: "medium", fullWidth: true, label: "\uD30C\uC77C \uC62C\uB9AC\uAE30", onClick: () => setMode("file") })] }) })), mode === "url" && _jsx(InsertImageUriDialogBody, { onClick: onClick }), mode === "file" && _jsx(InsertImageUploadedDialogBody, { onClick: onClick })] })));
50
+ return (_jsxs(StyledAlertDialog, Object.assign({ icon: _jsx(ImageFillIcon, { color: theme.color.background.primary }), open: open, onClose: handleOnClose, disableIconPadding: true }, { children: [_jsx(StyledAlertDialogTitle, Object.assign({ onClose: handleOnClose }, { children: "\uC774\uBBF8\uC9C0 \uC0BD\uC785\uD558\uAE30" })), !mode && (_jsx(AlertDialogContent, { children: _jsxs(Buttons, { children: [_jsxs(ButtonAndDescription, { children: [_jsx(Description, { children: "\uC774\uBBF8\uC9C0 URL\uC744 \uC54C\uACE0 \uC788\uB2E4\uBA74" }), _jsx(Button, { color: "grey", size: "medium", fullWidth: true, label: "URL\uB85C \uC0BD\uC785\uD558\uAE30", startIcon: _jsx(LinkIcon, {}), onClick: () => setMode("url") })] }), _jsxs(ButtonAndDescription, { children: [_jsx(Description, { children: "\uAC16\uACE0 \uC788\uB294 \uC774\uBBF8\uC9C0\uB97C \uC0BD\uC785\uD558\uACE0 \uC2F6\uB2E4\uBA74" }), _jsx(Button, { color: "grey", size: "medium", fullWidth: true, label: "\uD30C\uC77C \uC120\uD0DD\uD558\uAE30", startIcon: _jsx(UploadLineIcon, {}), onClick: () => {
51
+ var _a;
52
+ (_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.click();
53
+ } }), _jsx(HiddenInput, { ref: inputRef, type: "file", accept: "image/*", onChange: (event) => __awaiter(this, void 0, void 0, function* () {
54
+ var _a, _b;
55
+ const file = (_a = event.target.files) === null || _a === void 0 ? void 0 : _a[0];
56
+ if (!file)
57
+ return;
58
+ const uploadByFile = (_b = cdsContext.lexical) === null || _b === void 0 ? void 0 : _b.uploadByFile;
59
+ if (uploadByFile) {
60
+ setSrc(yield uploadByFile(file));
61
+ setMode("file");
62
+ }
63
+ }) })] })] }) })), mode === "url" && (_jsx(InsertImageUriDialogBody, { src: src, setSrc: setSrc, altText: altText, setAltText: setAltText, onClick: onClick })), mode === "file" && (_jsx(InsertImageUploadedDialogBody, { src: src, setSrc: setSrc, altText: altText, setAltText: setAltText, onClick: onClick }))] })));
33
64
  }
65
+ const StyledAlertDialog = styled(AlertDialog) `
66
+ gap: 16px;
67
+ `;
68
+ const StyledAlertDialogTitle = styled(AlertDialogTitle) `
69
+ color: ${({ theme }) => theme.color.foreground.neutralBase};
70
+ text-align: center;
71
+
72
+ /* Default/Heading/20px-Bd */
73
+ font-family: ${({ theme }) => theme.fontFamily.ui};
74
+ font-size: 20px;
75
+ font-style: normal;
76
+ font-weight: 700;
77
+ line-height: 28px; /* 140% */
78
+ letter-spacing: 0.25px;
79
+ `;
34
80
  const Buttons = styled.div `
81
+ display: flex;
82
+ align-items: flex-start;
83
+ gap: 8px;
84
+
85
+ // Actions가 없는 경우 하단이 디자인과 맞지 않는다
86
+ margin-bottom: -16px;
87
+ `;
88
+ const ButtonAndDescription = styled.div `
35
89
  display: flex;
36
90
  flex-direction: column;
37
- margin-top: 20px;
38
- gap: 20px;
91
+ align-items: center;
92
+ gap: 8px;
93
+ flex: 1 0 0;
94
+ `;
95
+ const Description = styled.div `
96
+ color: ${({ theme }) => theme.color.foreground.neutralBaseDisabled};
97
+ text-align: center;
98
+
99
+ /* Default/Label/12px-Md */
100
+ font-family: ${({ theme }) => theme.fontFamily.ui};
101
+ font-size: 12px;
102
+ font-style: normal;
103
+ font-weight: 500;
104
+ line-height: 16px; /* 133.333% */
105
+ `;
106
+ const HiddenInput = styled.input `
107
+ display: none;
39
108
  `;
@@ -1,5 +1,9 @@
1
1
  import { InsertImagePayload } from ".";
2
2
  export interface InsertImageUploadedDialogBodyProps {
3
+ src: string;
4
+ setSrc: (src: string) => void;
5
+ altText: string;
6
+ setAltText: (altText: string) => void;
3
7
  onClick: (payload: InsertImagePayload) => void;
4
8
  }
5
9
  export declare function InsertImageUploadedDialogBody(props: InsertImageUploadedDialogBodyProps): import("react/jsx-runtime").JSX.Element;
@@ -8,23 +8,22 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  });
9
9
  };
10
10
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
11
- import { useContext, useRef, useState } from "react";
11
+ import { useContext, useRef } from "react";
12
12
  import styled from "@emotion/styled";
13
13
  import { CodleDesignSystemContext } from "../../../../CodleDesignSystemProvider";
14
- import { AlertDialogContent, AlertDialogActions } from "../../../../components/AlertDialog";
14
+ import { AlertDialogContent, AlertDialogActions, } from "../../../../components/AlertDialog";
15
15
  import Button from "../../../../components/Button";
16
16
  import Input from "../../../../components/Input";
17
+ import { RefreshLineIcon } from "../../../../icons";
17
18
  export function InsertImageUploadedDialogBody(props) {
18
- const { onClick } = props;
19
- const [src, setSrc] = useState("");
20
- const [altText, setAltText] = useState("");
19
+ const { src, setSrc, altText, setAltText, onClick } = props;
21
20
  const inputRef = useRef(null);
22
21
  const cdsContext = useContext(CodleDesignSystemContext);
23
22
  const isDisabled = src === "";
24
- return (_jsxs(_Fragment, { children: [_jsx(AlertDialogContent, { children: _jsxs(Inputs, { children: [_jsx(Button, { fullWidth: true, color: "grey", size: "medium", label: "\uD30C\uC77C \uC62C\uB9AC\uAE30", onClick: () => {
23
+ return (_jsxs(_Fragment, { children: [_jsx(AlertDialogContent, { children: _jsxs(Inputs, { children: [_jsx(Button, { fullWidth: true, color: "grey", size: "medium", label: "\uD30C\uC77C \uBC14\uAFB8\uAE30", onClick: () => {
25
24
  var _a;
26
25
  (_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.click();
27
- } }), _jsx(HiddenInput, { ref: inputRef, type: "file", accept: "image/*", onChange: (event) => __awaiter(this, void 0, void 0, function* () {
26
+ }, startIcon: _jsx(RefreshLineIcon, {}) }), _jsx(HiddenInput, { ref: inputRef, type: "file", accept: "image/*", onChange: (event) => __awaiter(this, void 0, void 0, function* () {
28
27
  var _a, _b;
29
28
  const file = (_a = event.target.files) === null || _a === void 0 ? void 0 : _a[0];
30
29
  if (!file)
@@ -33,17 +32,20 @@ export function InsertImageUploadedDialogBody(props) {
33
32
  if (uploadByFile) {
34
33
  setSrc(yield uploadByFile(file));
35
34
  }
36
- }) }), _jsx(Input, { fullWidth: true, label: "\uC124\uBA85", placeholder: "\uC774\uBBF8\uC9C0\uC5D0 \uB300\uD55C \uC124\uBA85", color: "default", size: "medium", onChange: (e) => {
35
+ }) }), _jsxs(ImagePreview, { children: ["\uC774\uBBF8\uC9C0 \uBBF8\uB9AC\uBCF4\uAE30", _jsx("img", { src: src, alt: altText })] }), _jsx(Input, { fullWidth: true, label: "\uB300\uCCB4 \uD14D\uC2A4\uD2B8", placeholder: "\uC0BD\uC785\uD558\uB294 \uC774\uBBF8\uC9C0\uC5D0 \uAD00\uD55C \uC124\uBA85", color: "default", size: "medium", onChange: (e) => {
37
36
  setAltText(e.target.value);
38
- }, value: altText })] }) }), _jsx(AlertDialogActions, { children: _jsx(Button, { label: "\uD655\uC778", size: "large", color: "primary", disabled: isDisabled, onClick: () => onClick({ altText, src }) }) })] }));
37
+ }, value: altText })] }) }), _jsx(AlertDialogActions, { children: _jsx(Button, { fullWidth: true, label: "\uC0BD\uC785\uD558\uAE30", size: "medium", color: "primary", disabled: isDisabled, onClick: () => onClick({ altText, src }) }) })] }));
39
38
  }
40
39
  const Inputs = styled.div `
41
40
  display: flex;
42
41
  flex-direction: column;
43
- gap: 20px;
44
- margin-top: 20px;
45
- margin-bottom: 10px;
42
+ gap: 16px;
46
43
  `;
47
44
  const HiddenInput = styled.input `
48
45
  display: none;
49
46
  `;
47
+ const ImagePreview = styled.div `
48
+ display: flex;
49
+ flex-direction: column;
50
+ gap: 8px;
51
+ `;
@@ -1,5 +1,9 @@
1
1
  import { InsertImagePayload } from ".";
2
2
  export interface InsertImageUriDialogBodyProps {
3
+ src: string;
4
+ setSrc: (src: string) => void;
5
+ altText: string;
6
+ setAltText: (altText: string) => void;
3
7
  onClick: (payload: InsertImagePayload) => void;
4
8
  }
5
9
  export declare function InsertImageUriDialogBody(props: InsertImageUriDialogBodyProps): import("react/jsx-runtime").JSX.Element;
@@ -1,24 +1,20 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { useState } from "react";
3
2
  import styled from "@emotion/styled";
4
- import { AlertDialogContent, AlertDialogActions } from "../../../../components/AlertDialog";
3
+ import { AlertDialogActions, AlertDialogContent, } from "../../../../components/AlertDialog";
5
4
  import Input from "../../../../components/Input";
5
+ import { LinkIcon } from "../../../../icons";
6
6
  import Button from "../../../../components/Button";
7
7
  export function InsertImageUriDialogBody(props) {
8
- const { onClick } = props;
9
- const [src, setSrc] = useState("");
10
- const [altText, setAltText] = useState("");
8
+ const { src, setSrc, altText, setAltText, onClick } = props;
11
9
  const isDisabled = src === "";
12
- return (_jsxs(_Fragment, { children: [_jsx(AlertDialogContent, { children: _jsxs(Inputs, { children: [_jsx(Input, { fullWidth: true, label: "URL", placeholder: "https://source.unsplash.com/random", color: "default", size: "medium", onChange: (e) => {
10
+ return (_jsxs(_Fragment, { children: [" ", _jsx(AlertDialogContent, { children: _jsxs(Inputs, { children: [_jsx(Input, { fullWidth: true, label: "URL", placeholder: "https://www.pexels.com/photo/n-2848492/", color: "default", size: "medium", onChange: (e) => {
13
11
  setSrc(e.target.value);
14
- }, value: src }), _jsx(Input, { fullWidth: true, label: "\uC124\uBA85", placeholder: "\uC774\uBBF8\uC9C0\uC5D0 \uB300\uD55C \uC124\uBA85", color: "default", size: "medium", onChange: (e) => {
12
+ }, value: src, startIcon: _jsx(LinkIcon, {}) }), _jsx(Input, { fullWidth: true, label: "\uB300\uCCB4 \uD14D\uC2A4\uD2B8", placeholder: "\uC0BD\uC785\uD558\uB294 \uC774\uBBF8\uC9C0\uC5D0 \uAD00\uD55C \uC124\uBA85", color: "default", size: "medium", onChange: (e) => {
15
13
  setAltText(e.target.value);
16
- }, value: altText })] }) }), _jsx(AlertDialogActions, { children: _jsx(Button, { label: "\uD655\uC778", size: "large", color: "primary", disabled: isDisabled, onClick: () => onClick({ altText, src }) }) })] }));
14
+ }, value: altText })] }) }), _jsx(AlertDialogActions, { children: _jsx(Button, { fullWidth: true, label: "\uC0BD\uC785\uD558\uAE30", size: "medium", color: "primary", disabled: isDisabled, onClick: () => onClick({ altText, src }) }) })] }));
17
15
  }
18
16
  const Inputs = styled.div `
19
17
  display: flex;
20
18
  flex-direction: column;
21
- gap: 20px;
22
- margin-top: 20px;
23
- margin-bottom: 10px;
19
+ gap: 16px;
24
20
  `;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@team-monolith/cds",
3
- "version": "1.4.7",
3
+ "version": "1.4.9",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "sideEffects": false,