@team-monolith/cds 1.51.1 → 1.52.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 (63) hide show
  1. package/dist/icons/Custom.js +2 -2
  2. package/dist/icons/custom/worksheet-color.svg +5 -5
  3. package/dist/icons/custom/worksheet.svg +4 -4
  4. package/dist/patterns/LexicalEditor/LexicalEditor.d.ts +2 -0
  5. package/dist/patterns/LexicalEditor/LexicalEditor.js +6 -2
  6. package/dist/patterns/LexicalEditor/Plugins.d.ts +1 -0
  7. package/dist/patterns/LexicalEditor/Plugins.js +4 -2
  8. package/dist/patterns/LexicalEditor/nodes/ProblemSelectNode/ProblemSelectNode.d.ts +1 -4
  9. package/dist/patterns/LexicalEditor/nodes/ProblemSelectNode/SelectBox/SelectBoxComponent.d.ts +1 -1
  10. package/dist/patterns/LexicalEditor/nodes/ProblemSelectNode/SelectBox/SelectBoxEdit.d.ts +1 -1
  11. package/dist/patterns/LexicalEditor/nodes/ProblemSelectNode/SelectBox/SelectBoxView.d.ts +1 -1
  12. package/dist/patterns/LexicalEditor/nodes/ProblemSelectNode/SettingForm/FormSelection.js +1 -1
  13. package/dist/patterns/LexicalEditor/nodes/SheetInputNode/InputComponent.d.ts +7 -0
  14. package/dist/patterns/LexicalEditor/nodes/SheetInputNode/InputComponent.js +79 -0
  15. package/dist/patterns/LexicalEditor/nodes/SheetInputNode/SettingForm.d.ts +11 -0
  16. package/dist/patterns/LexicalEditor/nodes/SheetInputNode/SettingForm.js +93 -0
  17. package/dist/patterns/LexicalEditor/nodes/SheetInputNode/SheetInputNode.d.ts +33 -0
  18. package/dist/patterns/LexicalEditor/nodes/SheetInputNode/SheetInputNode.js +77 -0
  19. package/dist/patterns/LexicalEditor/nodes/SheetInputNode/index.d.ts +2 -0
  20. package/dist/patterns/LexicalEditor/nodes/SheetInputNode/index.js +2 -0
  21. package/dist/patterns/LexicalEditor/nodes/SheetSelectNode/SelectBox/SelectBoxComponent.d.ts +18 -0
  22. package/dist/patterns/LexicalEditor/nodes/SheetSelectNode/SelectBox/SelectBoxComponent.js +80 -0
  23. package/dist/patterns/LexicalEditor/nodes/SheetSelectNode/SelectBox/SelectBoxEdit.d.ts +8 -0
  24. package/dist/patterns/LexicalEditor/nodes/SheetSelectNode/SelectBox/SelectBoxEdit.js +7 -0
  25. package/dist/patterns/LexicalEditor/nodes/SheetSelectNode/SelectBox/SelectBoxView.d.ts +9 -0
  26. package/dist/patterns/LexicalEditor/nodes/SheetSelectNode/SelectBox/SelectBoxView.js +22 -0
  27. package/dist/patterns/LexicalEditor/nodes/SheetSelectNode/SelectBox/index.d.ts +2 -0
  28. package/dist/patterns/LexicalEditor/nodes/SheetSelectNode/SelectBox/index.js +2 -0
  29. package/dist/patterns/LexicalEditor/nodes/SheetSelectNode/SelectComponent.d.ts +9 -0
  30. package/dist/patterns/LexicalEditor/nodes/SheetSelectNode/SelectComponent.js +81 -0
  31. package/dist/patterns/LexicalEditor/nodes/SheetSelectNode/SettingForm/FormAllowMultipleAnswers.d.ts +6 -0
  32. package/dist/patterns/LexicalEditor/nodes/SheetSelectNode/SettingForm/FormAllowMultipleAnswers.js +10 -0
  33. package/dist/patterns/LexicalEditor/nodes/SheetSelectNode/SettingForm/FormSelection.d.ts +11 -0
  34. package/dist/patterns/LexicalEditor/nodes/SheetSelectNode/SettingForm/FormSelection.js +86 -0
  35. package/dist/patterns/LexicalEditor/nodes/SheetSelectNode/SettingForm/SettingForm.d.ts +13 -0
  36. package/dist/patterns/LexicalEditor/nodes/SheetSelectNode/SettingForm/SettingForm.js +148 -0
  37. package/dist/patterns/LexicalEditor/nodes/SheetSelectNode/SettingForm/index.d.ts +1 -0
  38. package/dist/patterns/LexicalEditor/nodes/SheetSelectNode/SettingForm/index.js +1 -0
  39. package/dist/patterns/LexicalEditor/nodes/SheetSelectNode/SheetSelectNode.d.ts +43 -0
  40. package/dist/patterns/LexicalEditor/nodes/SheetSelectNode/SheetSelectNode.js +82 -0
  41. package/dist/patterns/LexicalEditor/nodes/SheetSelectNode/index.d.ts +2 -0
  42. package/dist/patterns/LexicalEditor/nodes/SheetSelectNode/index.js +2 -0
  43. package/dist/patterns/LexicalEditor/nodes/{ProblemSelectNode/SettingForm → insertImageDialog}/InsertImageDialog.d.ts +4 -1
  44. package/dist/patterns/LexicalEditor/nodes/{ProblemSelectNode/SettingForm → insertImageDialog}/InsertImageDialog.js +4 -4
  45. package/dist/patterns/LexicalEditor/nodes/{ProblemSelectNode/SettingForm → insertImageDialog}/InsertImageUploadedDialogBody.d.ts +1 -1
  46. package/dist/patterns/LexicalEditor/nodes/{ProblemSelectNode/SettingForm → insertImageDialog}/InsertImageUploadedDialogBody.js +5 -5
  47. package/dist/patterns/LexicalEditor/nodes/{ProblemSelectNode/SettingForm → insertImageDialog}/InsertImageUriDialogBody.d.ts +1 -1
  48. package/dist/patterns/LexicalEditor/nodes/{ProblemSelectNode/SettingForm → insertImageDialog}/InsertImageUriDialogBody.js +4 -4
  49. package/dist/patterns/LexicalEditor/nodes/insertImageDialog/index.d.ts +1 -0
  50. package/dist/patterns/LexicalEditor/nodes/insertImageDialog/index.js +1 -0
  51. package/dist/patterns/LexicalEditor/plugins/ComponentAdderPlugin/ComponentAdderPlugin.d.ts +1 -0
  52. package/dist/patterns/LexicalEditor/plugins/ComponentAdderPlugin/ComponentAdderPlugin.js +6 -2
  53. package/dist/patterns/LexicalEditor/plugins/ComponentAdderPlugin/useContextMenuOptions.d.ts +1 -0
  54. package/dist/patterns/LexicalEditor/plugins/ComponentAdderPlugin/useContextMenuOptions.js +8 -2
  55. package/dist/patterns/LexicalEditor/plugins/ComponentPickerMenuPlugin/ComponentPickerMenuPlugin.d.ts +2 -0
  56. package/dist/patterns/LexicalEditor/plugins/ComponentPickerMenuPlugin/ComponentPickerMenuPlugin.js +56 -4
  57. package/dist/patterns/LexicalEditor/plugins/SheetInputPlugin/index.d.ts +5 -0
  58. package/dist/patterns/LexicalEditor/plugins/SheetInputPlugin/index.js +20 -0
  59. package/dist/patterns/LexicalEditor/plugins/SheetSelectPlugin/index.d.ts +5 -0
  60. package/dist/patterns/LexicalEditor/plugins/SheetSelectPlugin/index.js +20 -0
  61. package/dist/patterns/LexicalEditor/theme.d.ts +2 -0
  62. package/dist/patterns/LexicalEditor/theme.js +14 -0
  63. package/package.json +1 -1
@@ -0,0 +1,9 @@
1
+ /** @jsxImportSource @emotion/react */
2
+ import { NodeKey } from "lexical";
3
+ import { Selection } from "./SheetSelectNode";
4
+ export declare function SelectComponent(props: {
5
+ selections: Selection[];
6
+ selected: string[];
7
+ allowMultipleAnswers: boolean;
8
+ nodeKey: NodeKey;
9
+ }): import("@emotion/react/jsx-runtime").JSX.Element;
@@ -0,0 +1,81 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "@emotion/react/jsx-runtime";
2
+ /** @jsxImportSource @emotion/react */
3
+ import { $getNodeByKey } from "lexical";
4
+ import { $isSheetSelectNode } from "./SheetSelectNode";
5
+ import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext";
6
+ import { useContext, useState } from "react";
7
+ import useLexicalEditable from "@lexical/react/useLexicalEditable";
8
+ import { LexicalCustomConfigContext } from "../../LexicalCustomConfigContext";
9
+ import styled from "@emotion/styled";
10
+ import { css } from "@emotion/react";
11
+ import { AlarmWarningFillIcon, Settings3FillIcon } from "../../../../icons";
12
+ import { SelectBoxEdit, SelectBoxView } from "./SelectBox";
13
+ import SquareButton from "../../../../components/SquareButton";
14
+ import { SettingForm } from "./SettingForm";
15
+ export function SelectComponent(props) {
16
+ const { selections, selected, allowMultipleAnswers, nodeKey } = props;
17
+ const [editor] = useLexicalComposerContext();
18
+ const [settingOpen, setSettingOpen] = useState(false);
19
+ const isEditable = useLexicalEditable();
20
+ const { freezeProblemNode } = useContext(LexicalCustomConfigContext);
21
+ // view
22
+ if (!isEditable) {
23
+ return (_jsxs(_Fragment, { children: [allowMultipleAnswers && (_jsxs(Alert, { children: [_jsx(AlarmWarningFillIcon, { css: css `
24
+ width: 14px;
25
+ height: 14px;
26
+ ` }), "\uC9C8\uBB38\uC5D0 \uD574\uB2F9\uD558\uB294 \uB2F5\uC744 \uBAA8\uB450 \uACE0\uB974\uB294 \uBB38\uD56D\uC785\uB2C8\uB2E4."] })), selections.map((selection, index) => (_jsx(SelectBoxView, { index: index + 1, isSelected: selected.includes(selection.value), image: selection.show.image, text: selection.show.text, onClick: freezeProblemNode
27
+ ? undefined
28
+ : () => {
29
+ const isSelected = selected.includes(selection.value);
30
+ if (isSelected) {
31
+ editor.update(() => {
32
+ const node = $getNodeByKey(nodeKey);
33
+ if (!$isSheetSelectNode(node)) {
34
+ return;
35
+ }
36
+ node.setSelected(selected.filter((v) => v !== selection.value));
37
+ });
38
+ }
39
+ else {
40
+ editor.update(() => {
41
+ const node = $getNodeByKey(nodeKey);
42
+ if (!$isSheetSelectNode(node)) {
43
+ return;
44
+ }
45
+ if (allowMultipleAnswers) {
46
+ node.setSelected([...selected, selection.value]);
47
+ }
48
+ else {
49
+ node.setSelected([selection.value]);
50
+ }
51
+ });
52
+ }
53
+ } }, index)))] }));
54
+ }
55
+ // edit
56
+ return (_jsxs(_Fragment, { children: [_jsxs("div", Object.assign({ css: css `
57
+ display: flex;
58
+ gap: 4px;
59
+ ` }, { children: [_jsx("div", Object.assign({ css: css `
60
+ display: flex;
61
+ flex-direction: column;
62
+ gap: 4px;
63
+ ` }, { children: selections.map((selection, index) => (_jsx(SelectBoxEdit, { index: index + 1, image: selection.show.image, text: selection.show.text || `${index + 1}번 선택지`, onClick: () => setSettingOpen((open) => !open) }, index))) })), _jsx(SquareButton, { size: "small", color: "icon", icon: _jsx(Settings3FillIcon, {}), onClick: () => {
64
+ setSettingOpen((open) => !open);
65
+ } })] })), settingOpen && (_jsx(SettingForm, { data: {
66
+ selections,
67
+ allowMultipleAnswers,
68
+ }, nodeKey: nodeKey, onClose: () => setSettingOpen(false) }))] }));
69
+ }
70
+ const Alert = styled.div(({ theme }) => css `
71
+ display: flex;
72
+ gap: 4px;
73
+ margin-bottom: 12px;
74
+ color: ${theme.color.foreground.neutralBaseDisabled};
75
+ /* Default/Label/12px-Md */
76
+ font-family: ${theme.fontFamily.ui};
77
+ font-size: 12px;
78
+ font-style: normal;
79
+ font-weight: 500;
80
+ line-height: 16px; /* 133.333% */
81
+ `);
@@ -0,0 +1,6 @@
1
+ import { Control } from "react-hook-form";
2
+ import { SettingFormData } from "./SettingForm";
3
+ /** SheetSelectNode SettingForm의 다중 선택 허용 여부 폼입니다. */
4
+ export declare function FormAllowMultipleAnswers(props: {
5
+ control: Control<SettingFormData, any>;
6
+ }): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,10 @@
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
+ /** SheetSelectNode SettingForm의 다중 선택 허용 여부 폼입니다. */
5
+ export function FormAllowMultipleAnswers(props) {
6
+ const { control } = props;
7
+ return (_jsx(Controller, { name: "allowMultipleAnswers", control: control, render: ({ field: { value, onChange } }) => {
8
+ return (_jsxs(SegmentedControlGroup, Object.assign({ size: "xsmall", value: value, onChange: onChange, fullWidth: true }, { children: [_jsx(SegmentedControlButton, { value: false, label: "\uD558\uB098\uB9CC \uC120\uD0DD" }), _jsx(SegmentedControlButton, { value: true, label: "\uC5EC\uB7EC \uAC1C \uC120\uD0DD" })] })));
9
+ } }));
10
+ }
@@ -0,0 +1,11 @@
1
+ /** @jsxImportSource @emotion/react */
2
+ import { Control, UseFormWatch } from "react-hook-form";
3
+ import { SettingFormData } from "./SettingForm";
4
+ /** SheetSelectNode SettingForm의 단일 선택지 폼입니다. */
5
+ export default function FormSelection(props: {
6
+ index: number;
7
+ control: Control<SettingFormData, any>;
8
+ watch: UseFormWatch<SettingFormData>;
9
+ rules?: any;
10
+ onDelete?: () => void;
11
+ }): import("@emotion/react/jsx-runtime").JSX.Element;
@@ -0,0 +1,86 @@
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "@emotion/react/jsx-runtime";
2
+ /** @jsxImportSource @emotion/react */
3
+ import { Controller } from "react-hook-form";
4
+ import styled from "@emotion/styled";
5
+ import { css } from "@emotion/react";
6
+ import { useState } from "react";
7
+ import { InsertImageDialog } from "../../insertImageDialog";
8
+ import { DeleteBinLineIcon, ErrorWarningFillIcon, ImageAddFillIcon, ImageEditFillIcon, Input, SquareButton, } from "../../../../..";
9
+ /** SheetSelectNode SettingForm의 단일 선택지 폼입니다. */
10
+ export default function FormSelection(props) {
11
+ const { index, control, watch, rules, onDelete } = props;
12
+ const [imageOpen, setImageOpen] = useState(false);
13
+ const [inputFocused, setInputFocused] = useState(false);
14
+ return (_jsxs(Container, { children: [_jsx(Index, { children: index + 1 }), _jsxs("div", Object.assign({ css: css `
15
+ display: flex;
16
+ flex: 1;
17
+ flex-direction: column;
18
+ gap: 4px;
19
+ ` }, { children: [_jsx(Controller, { name: `selections.${index}.show.image`, control: control, render: ({ field: { value, onChange } }) => (_jsxs(_Fragment, { children: [_jsx(InsertImageDialog, { title: value ? "이미지 바꾸기" : "이미지 삽입하기", open: imageOpen, onClose: () => setImageOpen(false), updateImg: (props) => onChange(props), deleteButton: Boolean(value) }), value && value.src && (_jsx("img", { src: value.src, alt: value.altText, css: css `
20
+ height: auto;
21
+ // 이미지로 인해 좌우로 스크롤이 생기는 것을 방지
22
+ max-width: min(400px, 100%);
23
+ width: fit-content;
24
+ border-radius: 6px;
25
+ `, draggable: "false" }))] })) }), _jsx(Controller, { name: `selections.${index}.show.text`, control: control, rules: rules, render: ({ field: { value, onChange }, fieldState: { invalid, error }, }) => (_jsx(Input, { size: "small", color: invalid
26
+ ? "activeDanger"
27
+ : inputFocused
28
+ ? "activePrimary"
29
+ : "default", value: value, onChange: onChange, inputProps: {
30
+ onFocus: (_e) => {
31
+ setInputFocused(true);
32
+ },
33
+ onBlur: (_e) => {
34
+ setInputFocused(false);
35
+ },
36
+ }, placeholder: `${index + 1}번 선택지`, hintIcon: invalid ? _jsx(ErrorWarningFillIcon, {}) : undefined, hintText: error === null || error === void 0 ? void 0 : error.message, multiline: true, fullWidth: true, css: css `
37
+ flex: 1;
38
+ ` })) })] })), _jsxs("div", Object.assign({ css: css `
39
+ display: flex;
40
+ // 이미지가 들어가서 container height가 커져도 높이가 유지되도록 설정
41
+ height: 36px;
42
+ gap: 8px;
43
+ align-items: center;
44
+ ` }, { children: [_jsx(SquareButton, { color: "icon", size: "xsmall", icon: watch(`selections.${index}.show.image`) ? (_jsx(ImageEditFillIcon, {})) : (_jsx(ImageAddFillIcon, {})), onClick: () => {
45
+ setImageOpen(true);
46
+ } }), onDelete && (_jsx(SquareButton, { color: "white", size: "xsmall", icon: _jsx(DeleteBinLineIcon, {}), onClick: onDelete }))] }))] }));
47
+ }
48
+ const Container = styled.div(({ theme }) => css `
49
+ display: flex;
50
+ padding: 4px 12px;
51
+ gap: 8px;
52
+ border-radius: 8px;
53
+ background: ${theme.color.background.neutralAlt};
54
+ `);
55
+ const Index = styled.div(({ theme }) => css `
56
+ display: flex;
57
+ box-sizing: border-box;
58
+ width: 20px;
59
+ height: 20px;
60
+ padding: 4px;
61
+ margin-top: 8px;
62
+ justify-content: center;
63
+ align-items: center;
64
+ border-radius: 4px;
65
+ border: 1px solid ${theme.color.background.neutralAltActive};
66
+ background: ${theme.color.background.neutralBase};
67
+ color: ${theme.color.foreground.neutralBaseDisabled};
68
+ font-family: ${theme.fontFamily.ui};
69
+ font-size: 14px;
70
+ font-weight: 800;
71
+ line-height: 16px;
72
+ `);
73
+ const Answer = styled.div(({ theme }) => css `
74
+ display: flex;
75
+ align-items: center;
76
+ padding-right: 4px;
77
+ gap: 8px;
78
+ color: ${theme.color.foreground.neutralBase};
79
+ cursor: pointer;
80
+ /* Default/Label/14px-Md */
81
+ font-family: ${theme.fontFamily.ui};
82
+ font-size: 14px;
83
+ font-style: normal;
84
+ font-weight: 500;
85
+ line-height: 16px; /* 114.286% */
86
+ `);
@@ -0,0 +1,13 @@
1
+ /** @jsxImportSource @emotion/react */
2
+ import { NodeKey } from "lexical";
3
+ import { Selection } from "../SheetSelectNode";
4
+ export interface SettingFormData {
5
+ selections: Selection[];
6
+ allowMultipleAnswers: boolean;
7
+ }
8
+ /** 활동지 활동의 선택형 입력칸 설정 컴포넌트입니다. */
9
+ export declare function SettingForm(props: {
10
+ data: SettingFormData;
11
+ nodeKey: NodeKey;
12
+ onClose: () => void;
13
+ }): import("@emotion/react/jsx-runtime").JSX.Element;
@@ -0,0 +1,148 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "@emotion/react/jsx-runtime";
2
+ /** @jsxImportSource @emotion/react */
3
+ import { $getNodeByKey } from "lexical";
4
+ import { $isSheetSelectNode } from "../SheetSelectNode";
5
+ import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext";
6
+ import { useFieldArray, useForm } from "react-hook-form";
7
+ import styled from "@emotion/styled";
8
+ import { css } from "@emotion/react";
9
+ import { AddFillIcon, AlarmWarningFillIcon, Button, ListRadioIcon, shadows, } from "../../../../..";
10
+ import { uid } from "uid";
11
+ import FormSelection from "./FormSelection";
12
+ import { FormAllowMultipleAnswers } from "./FormAllowMultipleAnswers";
13
+ /** 활동지 활동의 선택형 입력칸 설정 컴포넌트입니다. */
14
+ export function SettingForm(props) {
15
+ const { data, nodeKey, onClose } = props;
16
+ const { selections, allowMultipleAnswers } = data;
17
+ const [editor] = useLexicalComposerContext();
18
+ const { control, handleSubmit, watch } = useForm({
19
+ mode: "all",
20
+ defaultValues: {
21
+ selections,
22
+ allowMultipleAnswers,
23
+ },
24
+ });
25
+ const { fields, append, remove } = useFieldArray({
26
+ control,
27
+ name: "selections",
28
+ keyName: "uid",
29
+ });
30
+ const onSettingSubmit = (data) => {
31
+ editor.update(() => {
32
+ const node = $getNodeByKey(nodeKey);
33
+ if (!$isSheetSelectNode(node)) {
34
+ return;
35
+ }
36
+ node.setSelections(data.selections);
37
+ node.setAllowMultipleAnswers(data.allowMultipleAnswers);
38
+ });
39
+ onClose();
40
+ };
41
+ function validateDuplicatedSelection(index) {
42
+ const selections = watch("selections");
43
+ if (index === 0)
44
+ return true;
45
+ const duplicatedIndex = selections
46
+ .slice(0, index)
47
+ .findIndex((selection) => selection.show.text === selections[index].show.text);
48
+ if (duplicatedIndex < 0)
49
+ return true;
50
+ return `${duplicatedIndex + 1}번 선택지와 같은 내용입니다.`;
51
+ }
52
+ return (_jsxs(Form, Object.assign({ onSubmit: handleSubmit(onSettingSubmit) }, { children: [_jsxs(Title, { children: [_jsx(ListRadioIcon, { css: css `
53
+ width: 12px;
54
+ height: 12px;
55
+ ` }), "\uC120\uD0DD\uD615 \uC785\uB825 \uCE78"] }), _jsxs(Content, { children: [_jsxs(Left, { children: [_jsxs(FormArea, { children: [_jsx(Label, { children: "\uC120\uD0DD\uC9C0" }), fields.map((field, index) => (_jsx(FormSelection, { index: index, control: control, watch: watch, rules: {
56
+ required: "필수 입력 항목입니다.",
57
+ validate: () => validateDuplicatedSelection(index),
58
+ }, onDelete: index !== 0
59
+ ? () => {
60
+ remove(index);
61
+ }
62
+ : undefined }, field.uid)))] }), _jsx(Button, { color: "grey", size: "small", startIcon: _jsx(AddFillIcon, {}), label: "\uC120\uD0DD\uC9C0 \uCD94\uAC00", onClick: () => {
63
+ append({
64
+ show: {
65
+ image: null,
66
+ text: "",
67
+ },
68
+ value: uid(),
69
+ });
70
+ } })] }), _jsxs(Right, { children: [_jsxs(FormArea, { children: [_jsx(Label, { children: "\uB2E4\uC911 \uC120\uD0DD \uD5C8\uC6A9 \uC5EC\uBD80" }), _jsx(FormAllowMultipleAnswers, { control: control })] }), watch("allowMultipleAnswers") && (_jsxs(Alert, { children: [_jsx(AlarmWarningFillIcon, { css: css `
71
+ min-width: 14px;
72
+ width: 14px;
73
+ height: 14px;
74
+ ` }), "\uB2E4\uC911 \uC120\uD0DD\uC744 \uD5C8\uC6A9\uD55C \uBB38\uD56D\uC5D0\uB294 \uC5EC\uB7EC \uC120\uD0DD\uC9C0\uB97C \uACE0\uB97C \uC218 \uC788\uB2E4\uB294 \uC548\uB0B4\uAC00 \uC81C\uACF5\uB429\uB2C8\uB2E4."] }))] })] }), _jsxs(Buttons, { children: [_jsx(Button, { color: "grey", size: "xsmall", label: "\uB2EB\uAE30", onClick: onClose }), _jsx(Button, { color: "primary", size: "xsmall", label: "\uC774\uB300\uB85C \uB123\uAE30", bold: true, type: "submit" })] })] })));
75
+ }
76
+ const Form = styled.form(({ theme }) => css `
77
+ display: flex;
78
+ width: 620px;
79
+ flex-direction: column;
80
+ border-radius: 6px;
81
+ border: 1px solid ${theme.color.background.neutralAltActive};
82
+ background: ${theme.color.background.neutralBase};
83
+ box-shadow: ${shadows.shadow08};
84
+ `);
85
+ const Title = styled.div(({ theme }) => css `
86
+ display: flex;
87
+ padding: 8px 12px;
88
+ gap: 4px;
89
+ align-items: center;
90
+ color: ${theme.color.foreground.neutralBase};
91
+ /* Default/Label/12px-Md */
92
+ font-family: ${theme.fontFamily.ui};
93
+ font-size: 12px;
94
+ font-style: normal;
95
+ font-weight: 500;
96
+ line-height: 16px; /* 133.333% */
97
+ `);
98
+ const Content = styled.div(({ theme }) => css `
99
+ display: flex;
100
+ border-top: 1px solid ${theme.color.background.neutralAltActive};
101
+ border-bottom: 1px solid ${theme.color.background.neutralAltActive};
102
+ `);
103
+ const Left = styled.div `
104
+ flex: 1;
105
+ display: flex;
106
+ flex-direction: column;
107
+ gap: 12px;
108
+ padding: 12px;
109
+ `;
110
+ const Right = styled.div `
111
+ width: 240px;
112
+ display: flex;
113
+ flex-direction: column;
114
+ gap: 12px;
115
+ padding: 12px;
116
+ `;
117
+ const FormArea = styled.div `
118
+ display: flex;
119
+ flex-direction: column;
120
+ gap: 8px;
121
+ `;
122
+ const Label = styled.div(({ theme }) => css `
123
+ color: ${theme.color.foreground.neutralBaseDisabled};
124
+ /* Default/Label/12px-Md */
125
+ font-family: ${theme.fontFamily.ui};
126
+ font-size: 12px;
127
+ font-style: normal;
128
+ font-weight: 500;
129
+ line-height: 16px; /* 133.333% */
130
+ `);
131
+ const Buttons = styled.div `
132
+ display: flex;
133
+ padding: 12px;
134
+ justify-content: flex-end;
135
+ align-items: center;
136
+ gap: 8px;
137
+ `;
138
+ const Alert = styled.div(({ theme }) => css `
139
+ display: flex;
140
+ gap: 4px;
141
+ color: ${theme.color.foreground.neutralBaseDisabled};
142
+ /* Default/Label/12px-Md */
143
+ font-family: ${theme.fontFamily.ui};
144
+ font-size: 12px;
145
+ font-style: normal;
146
+ font-weight: 500;
147
+ line-height: 16px; /* 133.333% */
148
+ `);
@@ -0,0 +1 @@
1
+ export * from "./SettingForm";
@@ -0,0 +1 @@
1
+ export * from "./SettingForm";
@@ -0,0 +1,43 @@
1
+ import { DecoratorNode, EditorConfig, LexicalNode, NodeKey, SerializedLexicalNode, Spread } from "lexical";
2
+ import { ReactNode } from "react";
3
+ import { ImageProps } from "../insertImageDialog";
4
+ export interface Selection {
5
+ show: {
6
+ image: ImageProps | null;
7
+ text: string;
8
+ };
9
+ value: string;
10
+ }
11
+ export interface SheetSelectPayload {
12
+ selected: string[];
13
+ selections: Selection[];
14
+ allowMultipleAnswers: boolean;
15
+ key?: NodeKey;
16
+ }
17
+ export type SerializedSheetSelectNode = Spread<SheetSelectPayload, SerializedLexicalNode>;
18
+ /**
19
+ * selections는 Selection타입의 배열로서 객관식 정보를 담고 있습니다.
20
+ * selected는 선택한 답의 value를 담고 있습니다.(view mode에서만 노출)
21
+ */
22
+ export declare class SheetSelectNode extends DecoratorNode<ReactNode> {
23
+ __selections: Selection[];
24
+ __selected: string[];
25
+ __allowMultipleAnswers: boolean;
26
+ isInline(): boolean;
27
+ static getType(): string;
28
+ getSelections(): Selection[];
29
+ getSelected(): string[];
30
+ getAllowMultipleAnswers(): boolean;
31
+ setSelections(selections: Selection[]): void;
32
+ setSelected(selected: string[]): void;
33
+ setAllowMultipleAnswers(allowMultipleAnswers: boolean): void;
34
+ static clone(node: SheetSelectNode): SheetSelectNode;
35
+ constructor(selections: Selection[], selected: string[], allowMultipleAnswers: boolean, key?: NodeKey);
36
+ createDOM(config: EditorConfig): HTMLElement;
37
+ updateDOM(): boolean;
38
+ static importJSON(serializedNode: SerializedSheetSelectNode): SheetSelectNode;
39
+ exportJSON(): SerializedSheetSelectNode;
40
+ decorate(): ReactNode;
41
+ }
42
+ export declare function $createSheetSelectNode(payload: SheetSelectPayload): SheetSelectNode;
43
+ export declare function $isSheetSelectNode(node: LexicalNode | null | undefined): node is SheetSelectNode;
@@ -0,0 +1,82 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { $applyNodeReplacement, DecoratorNode, } from "lexical";
3
+ import { addClassNamesToElement } from "@lexical/utils";
4
+ import { SelectComponent } from "./SelectComponent";
5
+ /**
6
+ * selections는 Selection타입의 배열로서 객관식 정보를 담고 있습니다.
7
+ * selected는 선택한 답의 value를 담고 있습니다.(view mode에서만 노출)
8
+ */
9
+ export class SheetSelectNode extends DecoratorNode {
10
+ isInline() {
11
+ return false;
12
+ }
13
+ static getType() {
14
+ return "sheet-select";
15
+ }
16
+ getSelections() {
17
+ return this.__selections;
18
+ }
19
+ getSelected() {
20
+ return this.__selected;
21
+ }
22
+ getAllowMultipleAnswers() {
23
+ return this.__allowMultipleAnswers;
24
+ }
25
+ setSelections(selections) {
26
+ const self = this.getWritable();
27
+ self.__selections = selections;
28
+ }
29
+ setSelected(selected) {
30
+ const self = this.getWritable();
31
+ self.__selected = selected;
32
+ }
33
+ setAllowMultipleAnswers(allowMultipleAnswers) {
34
+ const self = this.getWritable();
35
+ self.__allowMultipleAnswers = allowMultipleAnswers;
36
+ }
37
+ static clone(node) {
38
+ return new SheetSelectNode(node.__selections, node.__selected, node.__allowMultipleAnswers, node.__key);
39
+ }
40
+ constructor(selections, selected, allowMultipleAnswers, key) {
41
+ super(key);
42
+ this.__selections = selections;
43
+ this.__selected = selected;
44
+ this.__allowMultipleAnswers = allowMultipleAnswers;
45
+ }
46
+ createDOM(config) {
47
+ // Define the DOM element here
48
+ const root = document.createElement("div");
49
+ addClassNamesToElement(root, config.theme.sheetSelect);
50
+ return root;
51
+ }
52
+ updateDOM() {
53
+ return false;
54
+ }
55
+ static importJSON(serializedNode) {
56
+ return $createSheetSelectNode({
57
+ key: serializedNode.key,
58
+ selections: serializedNode.selections,
59
+ selected: serializedNode.selected,
60
+ allowMultipleAnswers: serializedNode.allowMultipleAnswers,
61
+ });
62
+ }
63
+ exportJSON() {
64
+ return {
65
+ type: "sheet-select",
66
+ version: 1,
67
+ selections: this.__selections,
68
+ selected: this.__selected,
69
+ allowMultipleAnswers: this.__allowMultipleAnswers,
70
+ };
71
+ }
72
+ decorate() {
73
+ return (_jsx(SelectComponent, { selections: this.__selections, selected: this.__selected, allowMultipleAnswers: this.__allowMultipleAnswers, nodeKey: this.__key }));
74
+ }
75
+ }
76
+ export function $createSheetSelectNode(payload) {
77
+ const { selections, selected, key, allowMultipleAnswers } = payload;
78
+ return $applyNodeReplacement(new SheetSelectNode(selections, selected, allowMultipleAnswers, key));
79
+ }
80
+ export function $isSheetSelectNode(node) {
81
+ return node instanceof SheetSelectNode;
82
+ }
@@ -0,0 +1,2 @@
1
+ export * from "./SelectComponent";
2
+ export * from "./SheetSelectNode";
@@ -0,0 +1,2 @@
1
+ export * from "./SelectComponent";
2
+ export * from "./SheetSelectNode";
@@ -1,4 +1,7 @@
1
- import { ImageProps } from "../ProblemSelectNode";
1
+ export interface ImageProps {
2
+ src: string;
3
+ altText: string;
4
+ }
2
5
  export interface InsertImageDialogProps {
3
6
  title: string;
4
7
  open: boolean;
@@ -12,10 +12,10 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "@emotion/reac
12
12
  import { useContext, useRef, useState } from "react";
13
13
  import styled from "@emotion/styled";
14
14
  import { css, useTheme } from "@emotion/react";
15
- import { ImageFillIcon, LinkIcon, UploadLineIcon } from "../../../../../icons";
16
- import { AlertDialog, AlertDialogContent, AlertDialogTitle, } from "../../../../../components/AlertDialog";
17
- import Button from "../../../../../components/Button";
18
- import { CodleDesignSystemContext } from "../../../../../CodleDesignSystemProvider";
15
+ import { ImageFillIcon, LinkIcon, UploadLineIcon } from "../../../../icons";
16
+ import { AlertDialog, AlertDialogContent, AlertDialogTitle, } from "../../../../components/AlertDialog";
17
+ import Button from "../../../../components/Button";
18
+ import { CodleDesignSystemContext } from "../../../../CodleDesignSystemProvider";
19
19
  import { InsertImageUriDialogBody } from "./InsertImageUriDialogBody";
20
20
  import { InsertImageUploadedDialogBody } from "./InsertImageUploadedDialogBody";
21
21
  import { useForm } from "react-hook-form";
@@ -1,5 +1,5 @@
1
- import { ImageProps } from "../ProblemSelectNode";
2
1
  import { Control, UseFormSetValue, UseFormWatch } from "react-hook-form";
2
+ import { ImageProps } from "./InsertImageDialog";
3
3
  export interface InsertImageUploadedDialogBodyProps {
4
4
  control: Control<ImageProps, any>;
5
5
  watch: UseFormWatch<ImageProps>;
@@ -10,11 +10,11 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
11
11
  import { useContext, useRef } from "react";
12
12
  import styled from "@emotion/styled";
13
- import { CodleDesignSystemContext } from "../../../../../CodleDesignSystemProvider";
14
- import { AlertDialogActions, AlertDialogContent, } from "../../../../../components/AlertDialog";
15
- import Button from "../../../../../components/Button";
16
- import { RefreshLineIcon } from "../../../../../icons";
17
- import Input from "../../../../../components/Input";
13
+ import { CodleDesignSystemContext } from "../../../../CodleDesignSystemProvider";
14
+ import { AlertDialogActions, AlertDialogContent, } from "../../../../components/AlertDialog";
15
+ import Button from "../../../../components/Button";
16
+ import { RefreshLineIcon } from "../../../../icons";
17
+ import Input from "../../../../components/Input";
18
18
  import { Controller, } from "react-hook-form";
19
19
  export function InsertImageUploadedDialogBody(props) {
20
20
  const { control, watch, setValue } = props;
@@ -1,5 +1,5 @@
1
- import { ImageProps } from "../ProblemSelectNode";
2
1
  import { Control, UseFormWatch } from "react-hook-form";
2
+ import { ImageProps } from "./InsertImageDialog";
3
3
  export interface InsertImageUriDialogBodyProps {
4
4
  control: Control<ImageProps, any>;
5
5
  watch: UseFormWatch<ImageProps>;
@@ -1,9 +1,9 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import styled from "@emotion/styled";
3
- import { AlertDialogActions, AlertDialogContent, } from "../../../../../components/AlertDialog";
4
- import Input from "../../../../../components/Input";
5
- import { LinkIcon } from "../../../../../icons";
6
- import Button from "../../../../../components/Button";
3
+ import { AlertDialogActions, AlertDialogContent, } from "../../../../components/AlertDialog";
4
+ import Input from "../../../../components/Input";
5
+ import { LinkIcon } from "../../../../icons";
6
+ import Button from "../../../../components/Button";
7
7
  import { Controller } from "react-hook-form";
8
8
  export function InsertImageUriDialogBody(props) {
9
9
  const { control, watch } = props;
@@ -0,0 +1 @@
1
+ export * from "./InsertImageDialog";
@@ -0,0 +1 @@
1
+ export * from "./InsertImageDialog";
@@ -6,6 +6,7 @@
6
6
  /// <reference types="react" />
7
7
  export interface ComponentAdderPluginProps {
8
8
  anchorElem: HTMLElement;
9
+ isSheetEnabled: boolean;
9
10
  isQuizEnabled: boolean;
10
11
  }
11
12
  export declare const COMPONENT_ADDER_MENU_CLASSNAME = "component-adder-menu";
@@ -54,7 +54,7 @@ function getTextUpToAnchor(selection) {
54
54
  return anchorNode.getTextContent().slice(0, anchorOffset);
55
55
  }
56
56
  export function ComponentAdderPlugin(props) {
57
- const { anchorElem, isQuizEnabled } = props;
57
+ const { anchorElem, isSheetEnabled, isQuizEnabled } = props;
58
58
  const theme = useTheme();
59
59
  const [editor] = useLexicalComposerContext();
60
60
  const [nodeKey, setNodeKey] = useState(null);
@@ -137,7 +137,10 @@ export function ComponentAdderPlugin(props) {
137
137
  return newResolves.filter((newResolve) => resolves.indexOf(newResolve) === -1);
138
138
  });
139
139
  });
140
- const getContextMenuOptions = useContextMenuOptions({ isQuizEnabled });
140
+ const getContextMenuOptions = useContextMenuOptions({
141
+ isSheetEnabled,
142
+ isQuizEnabled,
143
+ });
141
144
  const filteredOptions = options.filter((option) => {
142
145
  if (!query) {
143
146
  return true;
@@ -197,6 +200,7 @@ export function ComponentAdderPlugin(props) {
197
200
  editor,
198
201
  theme,
199
202
  setImageOpen,
203
+ isSheetEnabled,
200
204
  isQuizEnabled,
201
205
  });
202
206
  setOptions(baseOptions);
@@ -4,5 +4,6 @@
4
4
  import { LexicalEditor, LexicalNode } from "lexical";
5
5
  import { ComponentDrawerOption, ComponentPickerOption } from "../ComponentPickerMenuPlugin";
6
6
  export declare function useContextMenuOptions(props: {
7
+ isSheetEnabled: boolean;
7
8
  isQuizEnabled: boolean;
8
9
  }): (editor: LexicalEditor, node: LexicalNode, setImageOpen: (open: boolean) => void) => (ComponentPickerOption | ComponentDrawerOption)[];