@team-monolith/cds 1.7.0 → 1.8.0

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 (50) hide show
  1. package/dist/patterns/Dropdown/Dropdown.d.ts +36 -0
  2. package/dist/patterns/Dropdown/Dropdown.js +43 -0
  3. package/dist/patterns/Dropdown/DropdownContext.d.ts +11 -0
  4. package/dist/patterns/Dropdown/DropdownContext.js +9 -0
  5. package/dist/patterns/Dropdown/DropdownItem/DropdownItem.d.ts +50 -0
  6. package/dist/patterns/Dropdown/DropdownItem/DropdownItem.js +128 -0
  7. package/dist/patterns/Dropdown/DropdownItem/index.d.ts +2 -0
  8. package/dist/patterns/Dropdown/DropdownItem/index.js +2 -0
  9. package/dist/patterns/Dropdown/DropdownItem/selected.d.ts +8 -0
  10. package/dist/patterns/Dropdown/DropdownItem/selected.js +33 -0
  11. package/dist/patterns/Dropdown/DropdownMenu/DropdownMenu.d.ts +37 -0
  12. package/dist/patterns/Dropdown/DropdownMenu/DropdownMenu.js +92 -0
  13. package/dist/patterns/Dropdown/DropdownMenu/index.d.ts +2 -0
  14. package/dist/patterns/Dropdown/DropdownMenu/index.js +2 -0
  15. package/dist/patterns/Dropdown/DropdownMenu/style.d.ts +8 -0
  16. package/dist/patterns/Dropdown/DropdownMenu/style.js +103 -0
  17. package/dist/patterns/Dropdown/index.d.ts +2 -0
  18. package/dist/patterns/Dropdown/index.js +2 -0
  19. package/dist/patterns/LexicalEditor/LexicalEditor.js +2 -1
  20. package/dist/patterns/LexicalEditor/Plugins.js +2 -1
  21. package/dist/patterns/LexicalEditor/nodes/ProblemInputNode/Form/FormAnswer.d.ts +9 -0
  22. package/dist/patterns/LexicalEditor/nodes/ProblemInputNode/Form/FormAnswer.js +43 -0
  23. package/dist/patterns/LexicalEditor/nodes/ProblemInputNode/Form/FormCharacterCount.d.ts +8 -0
  24. package/dist/patterns/LexicalEditor/nodes/ProblemInputNode/Form/FormCharacterCount.js +12 -0
  25. package/dist/patterns/LexicalEditor/nodes/ProblemInputNode/Form/FormPlaceholder.d.ts +6 -0
  26. package/dist/patterns/LexicalEditor/nodes/ProblemInputNode/Form/FormPlaceholder.js +9 -0
  27. package/dist/patterns/LexicalEditor/nodes/ProblemInputNode/Form/index.d.ts +3 -0
  28. package/dist/patterns/LexicalEditor/nodes/ProblemInputNode/Form/index.js +3 -0
  29. package/dist/patterns/LexicalEditor/nodes/ProblemInputNode/InputComponent.d.ts +16 -0
  30. package/dist/patterns/LexicalEditor/nodes/ProblemInputNode/InputComponent.js +170 -0
  31. package/dist/patterns/LexicalEditor/nodes/ProblemInputNode/ProblemInputNode.d.ts +19 -0
  32. package/dist/patterns/LexicalEditor/nodes/ProblemInputNode/ProblemInputNode.js +68 -0
  33. package/dist/patterns/LexicalEditor/nodes/ProblemInputNode/index.d.ts +2 -0
  34. package/dist/patterns/LexicalEditor/nodes/ProblemInputNode/index.js +2 -0
  35. package/dist/patterns/LexicalEditor/nodes/index.d.ts +3 -0
  36. package/dist/patterns/LexicalEditor/nodes/index.js +3 -0
  37. package/dist/patterns/LexicalEditor/plugins/ComponentAdderPlugin/ComponentAdderPlugin.js +8 -5
  38. package/dist/patterns/LexicalEditor/plugins/ComponentAdderPlugin/useContextMenuOptions.d.ts +1 -1
  39. package/dist/patterns/LexicalEditor/plugins/ComponentAdderPlugin/useContextMenuOptions.js +140 -18
  40. package/dist/patterns/LexicalEditor/plugins/ComponentPickerMenuPlugin/ComponentPickerMenuList.js +12 -6
  41. package/dist/patterns/LexicalEditor/plugins/ComponentPickerMenuPlugin/ComponentPickerMenuPlugin.d.ts +5 -1
  42. package/dist/patterns/LexicalEditor/plugins/ComponentPickerMenuPlugin/ComponentPickerMenuPlugin.js +58 -4
  43. package/dist/patterns/LexicalEditor/plugins/ProblemInputPlugin/index.d.ts +5 -0
  44. package/dist/patterns/LexicalEditor/plugins/ProblemInputPlugin/index.js +21 -0
  45. package/dist/patterns/LexicalEditor/theme.d.ts +1 -0
  46. package/dist/patterns/LexicalEditor/theme.js +6 -0
  47. package/dist/patterns/SegmentedControl/SegmentedControlGroup.js +1 -1
  48. package/package.json +3 -2
  49. package/dist/patterns/LexicalEditor/plugins/ComponentAdderPlugin/getContextMenuOptions.d.ts +0 -6
  50. package/dist/patterns/LexicalEditor/plugins/ComponentAdderPlugin/getContextMenuOptions.js +0 -197
@@ -0,0 +1,43 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "@emotion/react/jsx-runtime";
2
+ /** @jsxImportSource @emotion/react */
3
+ import { css, useTheme } from "@emotion/react";
4
+ import { Controller } from "react-hook-form";
5
+ import Dropdown from "../../../../Dropdown";
6
+ import DropdownItem from "../../../../Dropdown/DropdownItem";
7
+ import Input from "../../../../../components/Input";
8
+ import { AlertFillIcon, DeleteBinLineIcon, ErrorWarningFillIcon, } from "../../../../../icons";
9
+ import SquareButton from "../../../../../components/SquareButton";
10
+ import Tooltip from "../../../../../components/Tooltip";
11
+ export function FormAnswer(props) {
12
+ const { index, control, onDelete, disabled } = props;
13
+ const theme = useTheme();
14
+ const TextTypeDropdown = (_jsx(Controller, { name: `answers.${index}.textType`, control: control, render: ({ field }) => (_jsx(Dropdown, Object.assign({ label: field.value === "normal" ? "일반 텍스트" : "코드 텍스트", size: "xsmall", color: "textNeutral", closeOnItemClick: true, disabled: disabled, buttonCss: css `
15
+ ${disabled && `color: ${theme.color.foreground.neutralAlt};`}
16
+ > span {
17
+ font-weight: 700;
18
+ }
19
+ `, menuProps: {
20
+ anchorOrigin: {
21
+ vertical: "bottom",
22
+ horizontal: "center",
23
+ },
24
+ transformOrigin: {
25
+ vertical: "top",
26
+ horizontal: "center",
27
+ },
28
+ } }, { children: field.value === "code" ? (_jsx(DropdownItem, { index: 0, label: "일반 텍스트", onClick: () => {
29
+ field.onChange("normal");
30
+ } })) : (_jsx(DropdownItem, { index: 0, label: "코드 텍스트", onClick: () => {
31
+ field.onChange("code");
32
+ } })) }))) }));
33
+ return (_jsx(Controller, { name: `answers.${index}.value`, control: control, rules: {
34
+ required: "정답을 입력해주세요.",
35
+ }, render: ({ field: { onChange, value }, fieldState: { invalid, error }, }) => (_jsx(Input, { size: "small", color: invalid ? "activeDanger" : "default", onChange: onChange, disabled: disabled, value: value, hintIcon: invalid ? _jsx(ErrorWarningFillIcon, {}) : undefined, hintText: error === null || error === void 0 ? void 0 : error.message, placeholder: "\uC548\uB155\uD558\uC138\uC694", fullWidth: true, css: css `
36
+ > div {
37
+ padding: 4px 12px;
38
+ }
39
+ `, startIcon: TextTypeDropdown, endIcon: _jsxs("div", Object.assign({ css: css `
40
+ display: flex;
41
+ gap: 4px;
42
+ ` }, { children: [onDelete && (_jsx(SquareButton, { color: "white", size: "xsmall", icon: _jsx(DeleteBinLineIcon, {}), onClick: onDelete })), disabled && (_jsx(Tooltip, Object.assign({ text: _jsxs("span", { children: ["\uC785\uB825 \uCE78 \uC124\uC815\uC774 '\uAE00\uC790 \uC218\uB300\uB85C'\uC778 \uACBD\uC6B0", _jsx("br", {}), "\uC815\uB2F5\uC744 \uD558\uB098\uB9CC \uB4F1\uB85D\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4."] }) }, { children: _jsx(SquareButton, { color: "danger", size: "xsmall", icon: _jsx(AlertFillIcon, { color: theme.color.foreground.neutralAlt }), disabled: true }) })))] })) })) }));
43
+ }
@@ -0,0 +1,8 @@
1
+ import { Control } from "react-hook-form";
2
+ import { ProblemInputPayload } from "../InputComponent";
3
+ import React from "react";
4
+ export interface FormCharacterCountProps {
5
+ control: Control<ProblemInputPayload, any>;
6
+ setMultiAnswerDisabled: React.Dispatch<React.SetStateAction<boolean>>;
7
+ }
8
+ export declare function FormCharacterCount(props: FormCharacterCountProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,12 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Controller } from "react-hook-form";
3
+ import { SegmentedControlButton, SegmentedControlGroup, } from "../../../../SegmentedControl";
4
+ export function FormCharacterCount(props) {
5
+ const { control, setMultiAnswerDisabled } = props;
6
+ return (_jsx(Controller, { name: "showCharacterCount", control: control, render: ({ field: { value, onChange } }) => {
7
+ return (_jsxs(SegmentedControlGroup, Object.assign({ size: "xsmall", value: value.toString(), onChange: (value) => {
8
+ onChange(value === "true");
9
+ setMultiAnswerDisabled(value === "true");
10
+ }, fullWidth: true }, { children: [_jsx(SegmentedControlButton, { value: "false", label: "\uD55C \uCE78\uC73C\uB85C" }), _jsx(SegmentedControlButton, { value: "true", label: "\uAE00\uC790 \uC218\uB300\uB85C" })] })));
11
+ } }));
12
+ }
@@ -0,0 +1,6 @@
1
+ import { Control } from "react-hook-form";
2
+ import { ProblemInputPayload } from "../InputComponent";
3
+ export interface FormPlaceholderProps {
4
+ control: Control<ProblemInputPayload, any>;
5
+ }
6
+ export declare function FormPlaceholder(props: FormPlaceholderProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,9 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Controller } from "react-hook-form";
3
+ import Input from "../../../../../components/Input";
4
+ export function FormPlaceholder(props) {
5
+ const { control } = props;
6
+ return (_jsx(Controller, { name: "placeholder", control: control, render: ({ field: { value, onChange } }) => {
7
+ return (_jsx(Input, { size: "small", color: "default", value: value, onChange: onChange, placeholder: "\uC608) \uC5EC\uAE30\uC5D0 \uC785\uB825\uD558\uC138\uC694." }));
8
+ } }));
9
+ }
@@ -0,0 +1,3 @@
1
+ export * from "./FormAnswer";
2
+ export * from "./FormCharacterCount";
3
+ export * from "./FormPlaceholder";
@@ -0,0 +1,3 @@
1
+ export * from "./FormAnswer";
2
+ export * from "./FormCharacterCount";
3
+ export * from "./FormPlaceholder";
@@ -0,0 +1,16 @@
1
+ import { NodeKey, SerializedLexicalNode } from "lexical";
2
+ export interface Answer {
3
+ textType: "normal" | "code";
4
+ value: string;
5
+ destroyed?: boolean;
6
+ }
7
+ export interface ProblemInputPayload {
8
+ key?: NodeKey;
9
+ answers: Answer[];
10
+ showCharacterCount: boolean;
11
+ placeholder: string;
12
+ }
13
+ export type SerializedProblemInputNode = SerializedLexicalNode & ProblemInputPayload;
14
+ export declare function InputComponent(props: {
15
+ data: ProblemInputPayload;
16
+ }): import("@emotion/react/jsx-runtime").JSX.Element;
@@ -0,0 +1,170 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "@emotion/react/jsx-runtime";
2
+ /** @jsxImportSource @emotion/react */
3
+ import { css, useTheme } from "@emotion/react";
4
+ import { $getSelection } from "lexical";
5
+ import { Suspense, useState } from "react";
6
+ import { useForm, useFieldArray } from "react-hook-form";
7
+ import Input from "../../../../components/Input";
8
+ import SquareButton from "../../../../components/SquareButton";
9
+ import { AddFillIcon, AlarmWarningFillIcon, InputMethodLineIcon, QuestionFillIcon, Settings3FillIcon, } from "../../../../icons";
10
+ import styled from "@emotion/styled";
11
+ import shadows from "../../../../foundation/shadows";
12
+ import Button from "../../../../components/Button";
13
+ import Tooltip from "../../../../components/Tooltip";
14
+ import { FormAnswer, FormCharacterCount, FormPlaceholder } from "./Form";
15
+ import useLexicalEditable from "@lexical/react/useLexicalEditable";
16
+ import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext";
17
+ import { $createProblemInputNode } from "./ProblemInputNode";
18
+ export function InputComponent(props) {
19
+ var _a;
20
+ const theme = useTheme();
21
+ const { data } = props;
22
+ const { answers, showCharacterCount, placeholder } = data;
23
+ const [settingOpen, setSettingOpen] = useState(false);
24
+ const [multiAnswerDisabled, setMultiAnswerDisabled] = useState(showCharacterCount);
25
+ const [editor] = useLexicalComposerContext();
26
+ const isEditable = useLexicalEditable();
27
+ const { control, handleSubmit, getValues } = useForm({
28
+ defaultValues: {
29
+ answers,
30
+ showCharacterCount,
31
+ placeholder,
32
+ },
33
+ });
34
+ // TODO: 읽기전용 모드(학생 view)에서 문제 제출 api를 추가해야 합니다.
35
+ const { fields, append, remove, update } = useFieldArray({
36
+ control,
37
+ name: "answers",
38
+ keyName: "uid",
39
+ });
40
+ const onSettingSubmit = (data) => {
41
+ editor.update(() => {
42
+ var _a;
43
+ const newNode = $createProblemInputNode(Object.assign({}, data));
44
+ const currentNode = (_a = $getSelection()) === null || _a === void 0 ? void 0 : _a.getNodes()[0];
45
+ currentNode === null || currentNode === void 0 ? void 0 : currentNode.replace(newNode);
46
+ });
47
+ setSettingOpen(false);
48
+ };
49
+ // TODO: 읽기전용 모드(학생 view)에서 문제 제출 api를 추가 후 수정해야 합니다.
50
+ const [answerInput, setAnswerInput] = useState("");
51
+ if (!isEditable) {
52
+ return (_jsx(Input, { size: "small", placeholder: (_a = getValues("placeholder")) !== null && _a !== void 0 ? _a : "주관식 입력 칸", value: answerInput, onChange: (e) => {
53
+ setAnswerInput(e.target.value);
54
+ }, color: "default", css: css `
55
+ width: 300px;
56
+ ` }));
57
+ }
58
+ return (_jsxs(Suspense, Object.assign({ fallback: null }, { children: [_jsxs("div", Object.assign({ css: css `
59
+ display: flex;
60
+ align-items: center;
61
+ gap: 4px;
62
+ ` }, { children: [_jsx(Input, { size: "small", placeholder: "주관식 입력 칸", defaultValue: "", color: "default", css: css `
63
+ width: 300px;
64
+ ` }), _jsx(SquareButton, { size: "small", color: "icon", icon: _jsx(Settings3FillIcon, {}), onClick: () => {
65
+ setSettingOpen(true);
66
+ } })] })), settingOpen && (_jsxs(SettingForm, Object.assign({ onSubmit: handleSubmit(onSettingSubmit) }, { children: [_jsxs(Title, { children: [_jsx(InputMethodLineIcon, { css: css `
67
+ width: 12px;
68
+ height: 12px;
69
+ ` }), "\uC8FC\uAD00\uC2DD \uC785\uB825 \uCE78"] }), _jsxs(Content, { children: [_jsxs(Left, { children: [_jsxs(FormArea, { children: [_jsx(Label, { children: "\uC815\uB2F5" }), fields
70
+ .map((field, index) => ({
71
+ field,
72
+ index,
73
+ }))
74
+ .filter(({ field }) => !field.destroyed)
75
+ .map(({ field, index }) => (_jsx(FormAnswer, { index: index, control: control, disabled: index !== 0 && multiAnswerDisabled, onDelete: index !== 0
76
+ ? () => {
77
+ if (field.value) {
78
+ update(index, Object.assign(Object.assign({}, field), { destroyed: true }));
79
+ }
80
+ else {
81
+ remove(index);
82
+ }
83
+ }
84
+ : undefined }, field.uid)))] }), _jsx(Button, { color: "grey", size: "small", startIcon: _jsx(AddFillIcon, {}), label: "\uBCF5\uC218 \uC815\uB2F5 \uCD94\uAC00", disabled: multiAnswerDisabled, onClick: () => {
85
+ append({
86
+ textType: "normal",
87
+ value: "",
88
+ });
89
+ } }), _jsxs("div", Object.assign({ css: css `
90
+ display: flex;
91
+ gap: 4px;
92
+ ` }, { children: [_jsx(AlarmWarningFillIcon, { color: theme.color.foreground.neutralBaseDisabled, css: css `
93
+ width: 14px;
94
+ height: 14px;
95
+ ` }), _jsxs(Label, { children: ["\uB744\uC5B4\uC4F0\uAE30, \uC54C\uD30C\uBCB3\uC758 \uB300\uC18C\uBB38\uC790 \uAD6C\uBD84\uAE4C\uC9C0 \uC77C\uCE58\uD574\uC57C \uC815\uB2F5\uC73C\uB85C \uCC98\uB9AC\uB429\uB2C8\uB2E4.", _jsx("br", {}), "\uAC00\uB2A5\uD55C \uC815\uB2F5\uC744 \uBAA8\uB450 \uCD94\uAC00\uD574\uC57C \uC6D0\uD65C\uD558\uAC8C \uC790\uB3D9 \uCC44\uC810\uD560 \uC218 \uC788\uC5B4\uC694."] })] }))] }), _jsxs(Right, { children: [_jsxs(FormArea, { children: [_jsxs(Label, { children: ["\uC785\uB825 \uCE78", _jsx(Tooltip, Object.assign({ text: _jsxs("span", { children: ["\uC608\uB97C \uB4E4\uC5B4 \uC815\uB2F5\uC774 '\uAE00\uC790 \uC218'\uC774\uACE0", _jsx("br", {}), _jsx("b", { children: "\uAE00\uC790 \uC218\uB300\uB85C" }), " \uC635\uC158\uC744 \uC120\uD0DD\uD588\uB2E4\uBA74", _jsx("br", {}), "\uC785\uB825 \uCE78\uC774 '\u2610\u2610 \u2610' \uCC98\uB7FC \uD45C\uC2DC\uB429\uB2C8\uB2E4."] }), placement: "top" }, { children: _jsx(QuestionFillIcon, { css: css `
96
+ width: 12px;
97
+ height: 12px;
98
+ ` }) }))] }), _jsx(FormCharacterCount, { control: control, setMultiAnswerDisabled: setMultiAnswerDisabled })] }), _jsxs(FormArea, { children: [_jsxs(Label, { children: ["\uC790\uB9AC \uD45C\uC2DC\uC790", _jsx(Tooltip, Object.assign({ text: _jsx("span", { children: "\uC785\uB825 \uCE78\uC5D0 \uAE30\uBCF8\uC73C\uB85C \uB178\uCD9C\uB418\uB294 \uD14D\uC2A4\uD2B8\uC785\uB2C8\uB2E4." }), placement: "top" }, { children: _jsx(QuestionFillIcon, { css: css `
99
+ width: 12px;
100
+ height: 12px;
101
+ ` }) }))] }), _jsx(FormPlaceholder, { control: control })] })] })] }), _jsxs(Buttons, { children: [_jsx(Button, { color: "grey", size: "xsmall", label: "\uB2EB\uAE30", onClick: () => {
102
+ setSettingOpen(false);
103
+ } }), _jsx(Button, { color: "primary", size: "xsmall", label: "\uC774\uB300\uB85C \uB123\uAE30", type: "submit" })] })] })))] })));
104
+ }
105
+ const SettingForm = styled.form(({ theme }) => css `
106
+ display: flex;
107
+ width: 620px;
108
+ flex-direction: column;
109
+ border-radius: 6px;
110
+ border: 1px solid ${theme.color.background.neutralAltActive};
111
+ background: ${theme.color.background.neutralBase};
112
+ box-shadow: ${shadows.shadow08};
113
+ `);
114
+ const Title = styled.div(({ theme }) => css `
115
+ display: flex;
116
+ padding: 8px 12px;
117
+ gap: 4px;
118
+ align-items: center;
119
+ color: ${theme.color.foreground.neutralBase};
120
+ /* Default/Label/12px-Md */
121
+ font-family: ${theme.fontFamily.ui};
122
+ font-size: 12px;
123
+ font-style: normal;
124
+ font-weight: 500;
125
+ line-height: 16px; /* 133.333% */
126
+ `);
127
+ const Content = styled.div(({ theme }) => css `
128
+ display: flex;
129
+ border-top: 1px solid ${theme.color.background.neutralAltActive};
130
+ border-bottom: 1px solid ${theme.color.background.neutralAltActive};
131
+ `);
132
+ const Left = styled.div `
133
+ display: flex;
134
+ flex-direction: column;
135
+ padding: 12px;
136
+ gap: 12px;
137
+ flex: 1;
138
+ `;
139
+ const FormArea = styled.div `
140
+ display: flex;
141
+ flex-direction: column;
142
+ gap: 8px;
143
+ `;
144
+ const Right = styled.div `
145
+ display: flex;
146
+ box-sizing: border-box;
147
+ width: 240px;
148
+ flex-direction: column;
149
+ padding: 12px;
150
+ gap: 12px;
151
+ `;
152
+ const Label = styled.div(({ theme }) => css `
153
+ display: flex;
154
+ gap: 4px;
155
+ align-items: center;
156
+ color: ${theme.color.foreground.neutralBaseDisabled};
157
+ /* Default/Label/12px-Md */
158
+ font-family: ${theme.fontFamily.ui};
159
+ font-size: 12px;
160
+ font-style: normal;
161
+ font-weight: 500;
162
+ line-height: 16px; /* 133.333% */
163
+ `);
164
+ const Buttons = styled.div `
165
+ display: flex;
166
+ padding: 12px;
167
+ justify-content: flex-end;
168
+ align-items: center;
169
+ gap: 8px;
170
+ `;
@@ -0,0 +1,19 @@
1
+ import { DecoratorNode, EditorConfig, LexicalNode, NodeKey } from "lexical";
2
+ import { ReactNode } from "react";
3
+ import { Answer, ProblemInputPayload, SerializedProblemInputNode } from "./InputComponent";
4
+ export declare class ProblemInputNode extends DecoratorNode<ReactNode> {
5
+ __answers: Answer[];
6
+ __showCharacterCount: boolean;
7
+ __placeholder: string;
8
+ static getType(): string;
9
+ get data(): ProblemInputPayload;
10
+ static clone(node: ProblemInputNode): ProblemInputNode;
11
+ constructor(answers: Answer[], showCharacterCount: boolean, placeholder: string, key?: NodeKey);
12
+ createDOM(config: EditorConfig): HTMLElement;
13
+ updateDOM(): boolean;
14
+ static importJSON(serializedNode: SerializedProblemInputNode): ProblemInputNode;
15
+ exportJSON(): SerializedProblemInputNode;
16
+ decorate(): ReactNode;
17
+ }
18
+ export declare function $createProblemInputNode({ key, answers, showCharacterCount, placeholder, }: ProblemInputPayload): ProblemInputNode;
19
+ export declare function $isProblemInputNode(node: LexicalNode | null | undefined): node is ProblemInputNode;
@@ -0,0 +1,68 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { $applyNodeReplacement, DecoratorNode, } from "lexical";
3
+ import { addClassNamesToElement } from "@lexical/utils";
4
+ import { InputComponent, } from "./InputComponent";
5
+ export class ProblemInputNode extends DecoratorNode {
6
+ static getType() {
7
+ return "problem-input";
8
+ }
9
+ get data() {
10
+ //fixme: 필요할 때 수정
11
+ //const self = this.getLatest();
12
+ return {
13
+ answers: this.__answers,
14
+ showCharacterCount: this.__showCharacterCount,
15
+ placeholder: this.__placeholder,
16
+ };
17
+ }
18
+ static clone(node) {
19
+ return $createProblemInputNode({
20
+ key: node.__key,
21
+ answers: node.__answers,
22
+ showCharacterCount: node.__showCharacterCount,
23
+ placeholder: node.__placeholder,
24
+ });
25
+ }
26
+ constructor(answers, showCharacterCount, placeholder, key) {
27
+ super(key);
28
+ this.__answers = answers;
29
+ this.__showCharacterCount = showCharacterCount;
30
+ this.__placeholder = placeholder;
31
+ }
32
+ createDOM(config) {
33
+ // Define the DOM element here
34
+ const root = document.createElement("div");
35
+ addClassNamesToElement(root, config.theme.problemInput);
36
+ return root;
37
+ }
38
+ updateDOM() {
39
+ return false;
40
+ }
41
+ static importJSON(serializedNode) {
42
+ const node = $createProblemInputNode({
43
+ key: serializedNode.key,
44
+ answers: serializedNode.answers,
45
+ showCharacterCount: serializedNode.showCharacterCount,
46
+ placeholder: serializedNode.placeholder,
47
+ });
48
+ return node;
49
+ }
50
+ exportJSON() {
51
+ return {
52
+ version: 1,
53
+ type: "problem-input",
54
+ answers: this.__answers,
55
+ showCharacterCount: this.__showCharacterCount,
56
+ placeholder: this.__placeholder,
57
+ };
58
+ }
59
+ decorate() {
60
+ return _jsx(InputComponent, { data: this.data });
61
+ }
62
+ }
63
+ export function $createProblemInputNode({ key, answers, showCharacterCount, placeholder, }) {
64
+ return $applyNodeReplacement(new ProblemInputNode(answers, showCharacterCount, placeholder, key));
65
+ }
66
+ export function $isProblemInputNode(node) {
67
+ return node instanceof ProblemInputNode;
68
+ }
@@ -0,0 +1,2 @@
1
+ export * from "./ProblemInputNode";
2
+ export * from "./InputComponent";
@@ -0,0 +1,2 @@
1
+ export * from "./ProblemInputNode";
2
+ export * from "./InputComponent";
@@ -0,0 +1,3 @@
1
+ export * from "./ColoredQuoteNode";
2
+ export * from "./ImageNode";
3
+ export * from "./ProblemInputNode";
@@ -0,0 +1,3 @@
1
+ export * from "./ColoredQuoteNode";
2
+ export * from "./ImageNode";
3
+ export * from "./ProblemInputNode";
@@ -29,6 +29,7 @@ import styled from "@emotion/styled";
29
29
  import { useContextMenuOptions } from "./useContextMenuOptions";
30
30
  import { InsertImageDialog } from "../ImagesPlugin/InsertImageDialog";
31
31
  import { ZINDEX } from "../../../../utils/zIndex";
32
+ import { useTheme } from "@emotion/react";
32
33
  export const COMPONENT_ADDER_MENU_CLASSNAME = "component-adder-menu";
33
34
  function isOnMenu(element) {
34
35
  return !!element.closest(`.${COMPONENT_ADDER_MENU_CLASSNAME}`);
@@ -48,6 +49,7 @@ function getTextUpToAnchor(selection) {
48
49
  }
49
50
  export function ComponentAdderPlugin(props) {
50
51
  const { anchorElem } = props;
52
+ const theme = useTheme();
51
53
  const [editor] = useLexicalComposerContext();
52
54
  const [nodeKey, setNodeKey] = useState(null);
53
55
  const menuRef = useRef(null);
@@ -58,7 +60,7 @@ export function ComponentAdderPlugin(props) {
58
60
  });
59
61
  const [plusOrMenu, setPlusOrMenu] = useState("plus");
60
62
  const [options, setOptions] = useState([]);
61
- const [open, setOpen] = useState(false);
63
+ const [imageOpen, setImageOpen] = useState(false);
62
64
  const [query, setQuery] = useState("");
63
65
  // EditorState의 Selection 을 추적하여
64
66
  // Plus 및 Menu 버튼을 누르고 다른 곳을 클릭하면 메뉴를 닫습니다.
@@ -129,11 +131,12 @@ export function ComponentAdderPlugin(props) {
129
131
  const getContextMenuOptions = useContextMenuOptions();
130
132
  const filteredOptions = options.filter((option) => {
131
133
  const regex = new RegExp(query, "i");
132
- return (regex.test(option.title) ||
134
+ return (option.component ||
135
+ regex.test(option.title) ||
133
136
  option.keywords.some((keyword) => regex.test(keyword)));
134
137
  });
135
138
  const { onDragStart, onDragEnd, targetLineRef } = useDraggableBlockMenu(editor, anchorElem, blockElem, setBlockElem);
136
- return (_jsxs(_Fragment, { children: [_jsx(InsertImageDialog, { open: open, activeEditor: editor, onClose: () => setOpen(false) }), _jsx(LexicalNodeMenuPlugin, { nodeKey: nodeKey, anchorClassName: cssToClassName `
139
+ return (_jsxs(_Fragment, { children: [_jsx(InsertImageDialog, { open: imageOpen, activeEditor: editor, onClose: () => setImageOpen(false) }), _jsx(LexicalNodeMenuPlugin, { nodeKey: nodeKey, anchorClassName: cssToClassName `
137
140
  z-index: ${ZINDEX.DIALOG + 1};
138
141
  `, options: filteredOptions, menuRenderFn: (anchorElementRef, { selectedIndex, selectOptionAndCleanUp, setHighlightedIndex }) => anchorElementRef.current && filteredOptions.length
139
142
  ? ReactDOM.createPortal(_jsx(ComponentPickerMenuList, { options: filteredOptions, selectedIndex: selectedIndex, selectOptionAndCleanUp: selectOptionAndCleanUp, setHighlightedIndex: setHighlightedIndex }), anchorElementRef.current)
@@ -178,7 +181,7 @@ export function ComponentAdderPlugin(props) {
178
181
  yield promise;
179
182
  setNodeKey(newNodeKey);
180
183
  }
181
- const baseOptions = getBaseOptions(editor, setOpen);
184
+ const baseOptions = getBaseOptions(editor, theme, setImageOpen);
182
185
  setOptions(baseOptions);
183
186
  setPlusOrMenu("plus");
184
187
  }), onMenuClick: () => __awaiter(this, void 0, void 0, function* () {
@@ -196,7 +199,7 @@ export function ComponentAdderPlugin(props) {
196
199
  // Add a node key to the selection.
197
200
  nodeSelection.add(newNode.getKey());
198
201
  $setSelection(nodeSelection);
199
- const contextMenuOptions = getContextMenuOptions(editor, newNode, setOpen);
202
+ const contextMenuOptions = getContextMenuOptions(editor, newNode, setImageOpen);
200
203
  setOptions(contextMenuOptions);
201
204
  if (nodeKey === null) {
202
205
  setNodeKey(newNode.getKey());
@@ -3,4 +3,4 @@
3
3
  */
4
4
  import { LexicalEditor, LexicalNode } from "lexical";
5
5
  import { ComponentPickerOption } from "../ComponentPickerMenuPlugin";
6
- export declare function useContextMenuOptions(): (editor: LexicalEditor, node: LexicalNode, setOpen: (open: boolean) => void) => ComponentPickerOption[];
6
+ export declare function useContextMenuOptions(): (editor: LexicalEditor, node: LexicalNode, setImageOpen: (open: boolean) => void) => ComponentPickerOption[];