@team-monolith/cds 1.69.0 → 1.70.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 (19) hide show
  1. package/dist/components/AlertDialog/AlertDialogTitle.js +4 -1
  2. package/dist/components/Banner.js +4 -1
  3. package/dist/components/SquareButton.d.ts +4 -2
  4. package/dist/patterns/LexicalEditor/nodes/ImageNode/ImageComponent.js +2 -0
  5. package/dist/patterns/LexicalEditor/nodes/ProblemInputNode/InputComponent.js +2 -0
  6. package/dist/patterns/LexicalEditor/nodes/ProblemInputNode/SettingForm/FormSolution.d.ts +1 -1
  7. package/dist/patterns/LexicalEditor/nodes/ProblemInputNode/SettingForm/FormSolution.js +5 -1
  8. package/dist/patterns/LexicalEditor/nodes/ProblemSelectNode/ProblemSelectNode.js +0 -9
  9. package/dist/patterns/LexicalEditor/nodes/ProblemSelectNode/SelectComponent.js +2 -0
  10. package/dist/patterns/LexicalEditor/nodes/ProblemSelectNode/SettingForm/FormSelection.d.ts +1 -1
  11. package/dist/patterns/LexicalEditor/nodes/ProblemSelectNode/SettingForm/FormSelection.js +9 -3
  12. package/dist/patterns/LexicalEditor/nodes/SelfEvaluationNode/EvaluationComponent/Evaluation/SettingForm/FormQuestion.d.ts +1 -1
  13. package/dist/patterns/LexicalEditor/nodes/SelfEvaluationNode/EvaluationComponent/Evaluation/SettingForm/FormQuestion.js +3 -1
  14. package/dist/patterns/LexicalEditor/nodes/SelfEvaluationNode/EvaluationComponent/EvaluationComponent.js +2 -0
  15. package/dist/patterns/LexicalEditor/nodes/SheetInputNode/InputComponent.js +3 -1
  16. package/dist/patterns/LexicalEditor/nodes/SheetSelectNode/SelectComponent/SelectComponent.js +2 -0
  17. package/dist/patterns/LexicalEditor/nodes/SheetSelectNode/SelectComponent/SettingForm/FormSelection.d.ts +1 -1
  18. package/dist/patterns/LexicalEditor/nodes/SheetSelectNode/SelectComponent/SettingForm/FormSelection.js +8 -4
  19. package/package.json +1 -1
@@ -17,6 +17,7 @@ import SquareButton from "../SquareButton";
17
17
  import { CloseFillIcon } from "../../icons";
18
18
  import AlertDialogContext from "./AlertDialogContext";
19
19
  import { MOBILE } from "../../foundation/breakpoints";
20
+ // eslint-disable-next-line react/display-name, @typescript-eslint/no-explicit-any
20
21
  export const AlertDialogTitle = React.forwardRef((props, ref) => {
21
22
  const { className, component: Component = "div", onClose, children } = props, other = __rest(props, ["className", "component", "onClose", "children"]);
22
23
  const { icon } = React.useContext(AlertDialogContext);
@@ -51,5 +52,7 @@ export const AlertDialogTitle = React.forwardRef((props, ref) => {
51
52
  height: 32px;
52
53
  }
53
54
  `)}
54
- ` }, { children: icon }))), children] })), onClose && (_jsx(SquareButton, { color: "icon", size: "small", icon: _jsx(CloseFillIcon, {}), onClick: onClose }))] })) }));
55
+ ` }, { children: icon }))), children] })), onClose && (_jsx(SquareButton, { color: "icon", size: "small", icon: _jsx(CloseFillIcon, {}), onClick: onClose, buttonProps: {
56
+ "aria-label": "닫기",
57
+ } }))] })) }));
55
58
  });
@@ -47,6 +47,7 @@ const COLOR_PALETTE = (theme, color) => ({
47
47
  /**
48
48
  * [피그마](https://www.figma.com/file/yhrRFizzmhPoHdw9FbYow2/Codle-PD-Kit---Components?type=design&node-id=44-2847&t=bhnL1ombbddld3RQ-0)
49
49
  */
50
+ // eslint-disable-next-line react/display-name, @typescript-eslint/no-explicit-any
50
51
  const Banner = React.forwardRef((props, ref) => {
51
52
  const { className, component: Component = "div", headline, content, icon, color, buttonLabel, buttonClassName, onButtonClick, buttonProps, close, onClose, fullWidth } = props, other = __rest(props, ["className", "component", "headline", "content", "icon", "color", "buttonLabel", "buttonClassName", "onButtonClick", "buttonProps", "close", "onClose", "fullWidth"]);
52
53
  const theme = useTheme();
@@ -80,7 +81,9 @@ const Banner = React.forwardRef((props, ref) => {
80
81
  > button {
81
82
  color: ${COLOR_PALETTE(theme, color).content};
82
83
  }
83
- `, color: "icon", size: "small", icon: _jsx(CloseFillIcon, {}), onClick: onClose }))] })));
84
+ `, color: "icon", size: "small", icon: _jsx(CloseFillIcon, {}), onClick: onClose, buttonProps: {
85
+ "aria-label": "닫기",
86
+ } }))] })));
84
87
  });
85
88
  const IconDiv = styled.div `
86
89
  display: flex;
@@ -24,8 +24,10 @@ export interface SquareButtonOwnProps<RootComponentType extends React.ElementTyp
24
24
  loading?: boolean;
25
25
  /** 버튼 클릭 시 호출될 콜백 함수 */
26
26
  onClick?: React.MouseEventHandler<HTMLButtonElement>;
27
- /** 버튼에 전달될 Props */
28
- buttonProps?: Omit<ButtonProps, "disabled" | "color" | "type" | "size" | "icon" | "label" | "loading" | "fullWidth" | "onClick">;
27
+ /** 버튼에 전달될 Props. 접근성을 위해 aria-label이 필수로 들어가야 합니다. */
28
+ buttonProps: {
29
+ "aria-label": string;
30
+ } & Partial<Omit<ButtonProps, "disabled" | "color" | "type" | "size" | "icon" | "label" | "loading" | "fullWidth" | "onClick" | "aria-label">>;
29
31
  }
30
32
  export type SquareButtonProps<RootComponentType extends React.ElementType = SquareButtonTypeMap["defaultComponent"]> = PolymorphicProps<SquareButtonTypeMap<RootComponentType>, RootComponentType>;
31
33
  export interface SquareButtonTypeMap<RootComponentType extends React.ElementType = "span"> {
@@ -158,6 +158,8 @@ export default function ImageComponent({ src, altText, nodeKey, width, height, m
158
158
  ? `focused ${$isNodeSelection(selection) ? "draggable" : ""}`
159
159
  : null, src: src, altText: altText, imageRef: imageRef, width: width, height: height, maxWidth: maxWidth }) })) })), _jsx(SquareButton, { size: "small", color: "icon", icon: _jsx(Settings3FillIcon, {}), onClick: () => {
160
160
  setOpen(true);
161
+ }, buttonProps: {
162
+ "aria-label": "이미지 수정하기",
161
163
  } })] }), _jsx(InsertImageDialog, { open: open, title: "\uC774\uBBF8\uC9C0 \uC218\uC815\uD558\uAE30", onClose: () => setOpen(false), imageProps: {
162
164
  src,
163
165
  altText,
@@ -64,6 +64,8 @@ export function InputComponent(props) {
64
64
  gap: 4px;
65
65
  ` }, { children: [_jsx(VirtualInput, Object.assign({ onClick: () => setSettingOpen(true) }, { children: "\uC8FC\uAD00\uC2DD \uC785\uB825 \uCE78" })), _jsx(SquareButton, { size: "small", color: "icon", icon: _jsx(Settings3FillIcon, {}), onClick: () => {
66
66
  setSettingOpen(true);
67
+ }, buttonProps: {
68
+ "aria-label": "입력 칸 설정",
67
69
  } })] })), settingOpen && (_jsx(SettingForm, Object.assign({}, settingFormProps, { onClose: () => setSettingOpen(false) })))] }));
68
70
  }
69
71
  const VirtualInput = styled.div(({ theme }) => css `
@@ -2,7 +2,7 @@ import { Control } from "react-hook-form";
2
2
  import { ProblemInputPayload } from "../ProblemInputNode";
3
3
  export interface FormSolutionProps {
4
4
  index: number;
5
- control: Control<ProblemInputPayload, any>;
5
+ control: Control<ProblemInputPayload>;
6
6
  rules?: any;
7
7
  onDelete?: () => void;
8
8
  }
@@ -19,6 +19,10 @@ export function FormSolution(props) {
19
19
  `, startIcon: _jsx(TextTypeDropdown, { index: index, control: control, disabled: disabled }), endIcon: _jsxs("div", Object.assign({ css: css `
20
20
  display: flex;
21
21
  gap: 4px;
22
- ` }, { 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 }) })))] })) }));
22
+ ` }, { children: [onDelete && (_jsx(SquareButton, { color: "white", size: "xsmall", icon: _jsx(DeleteBinLineIcon, {}), onClick: onDelete, buttonProps: {
23
+ "aria-label": "삭제",
24
+ } })), 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, buttonProps: {
25
+ "aria-label": "정답 등록 불가",
26
+ } }) })))] })) }));
23
27
  } }));
24
28
  }
@@ -63,15 +63,6 @@ export class ProblemSelectNode extends DecoratorNode {
63
63
  }
64
64
  }
65
65
  exportJSON() {
66
- // 서버에서 hasMultipleSolutions를 보내주지 않으면 없는 채로 내보냅니다.
67
- if (this.__hasMultipleSolutions === undefined) {
68
- return {
69
- type: "problem-select",
70
- version: 1,
71
- selections: this.__selections,
72
- selected: this.__selected,
73
- };
74
- }
75
66
  // 서버에서 hasMultipleSolutions를 보내주면 같이 내보냅니다.
76
67
  return {
77
68
  type: "problem-select",
@@ -69,6 +69,8 @@ export function SelectComponent(props) {
69
69
  ? `${index + 1}번 선택지`
70
70
  : selection.show.text, onClick: () => setSettingOpen(true) }, index))) })), _jsx(SquareButton, { size: "small", color: "icon", icon: _jsx(Settings3FillIcon, {}), onClick: () => {
71
71
  setSettingOpen(true);
72
+ }, buttonProps: {
73
+ "aria-label": "선택지 설정",
72
74
  } })] })), settingOpen && (_jsx(SettingForm, { selections: selections, nodeKey: nodeKey, onClose: () => setSettingOpen(false) }))] }));
73
75
  }
74
76
  const Alert = styled.div(({ theme }) => css `
@@ -2,7 +2,7 @@ import { Control, RegisterOptions } from "react-hook-form";
2
2
  import { SettingFormData } from "./SettingForm";
3
3
  export interface FormSelectionProps {
4
4
  index: number;
5
- control: Control<SettingFormData, any>;
5
+ control: Control<SettingFormData>;
6
6
  rules?: Omit<RegisterOptions<SettingFormData, `selections.${number}`>, "disabled" | "valueAsNumber" | "valueAsDate" | "setValueAs">;
7
7
  onDelete?: () => void;
8
8
  }
@@ -39,10 +39,10 @@ export function FormSelection(props) {
39
39
  : inputFocused
40
40
  ? "activePrimary"
41
41
  : "default", value: value.show.text, onChange: (e) => onChange(Object.assign(Object.assign({}, value), { show: Object.assign(Object.assign({}, value.show), { text: e.target.value }) })), inputProps: {
42
- onFocus: (_e) => {
42
+ onFocus: () => {
43
43
  setInputFocused(true);
44
44
  },
45
- onBlur: (_e) => {
45
+ onBlur: () => {
46
46
  setInputFocused(false);
47
47
  },
48
48
  }, placeholder: `${index + 1}번 선택지`, hintIcon: invalid ? _jsx(ErrorWarningFillIcon, {}) : undefined, hintText: error === null || error === void 0 ? void 0 : error.message, multiline: true, fullWidth: true, css: css `
@@ -54,9 +54,15 @@ export function FormSelection(props) {
54
54
  align-items: center;
55
55
  ` }, { children: [_jsx(SquareButton, { color: "icon", size: "xsmall", icon: value.show.image ? _jsx(ImageEditFillIcon, {}) : _jsx(ImageAddFillIcon, {}), onClick: () => {
56
56
  setImageOpen(true);
57
+ }, buttonProps: {
58
+ "aria-label": value.show.image
59
+ ? "이미지 바꾸기"
60
+ : "이미지 삽입하기",
57
61
  } }), _jsxs(Answer, Object.assign({ onClick: () => {
58
62
  onChange(Object.assign(Object.assign({}, value), { isAnswer: !value.isAnswer }));
59
- } }, { children: ["\uC815\uB2F5", _jsx(Switch, { checked: Boolean(value.isAnswer), size: "small" })] })), onDelete && (_jsx(SquareButton, { color: "white", size: "xsmall", icon: _jsx(DeleteBinLineIcon, {}), onClick: onDelete }))] }))] }));
63
+ } }, { children: ["\uC815\uB2F5", _jsx(Switch, { checked: Boolean(value.isAnswer), size: "small" })] })), onDelete && (_jsx(SquareButton, { color: "white", size: "xsmall", icon: _jsx(DeleteBinLineIcon, {}), onClick: onDelete, buttonProps: {
64
+ "aria-label": "삭제",
65
+ } }))] }))] }));
60
66
  }
61
67
  const Container = styled.div(({ theme }) => css `
62
68
  display: flex;
@@ -4,6 +4,6 @@ import { SettingFormData } from "./SettingForm";
4
4
  /** 평가 항목을 설정하는 Form입니다. */
5
5
  export declare function FormQuestion(props: {
6
6
  index: number;
7
- control: Control<SettingFormData, any>;
7
+ control: Control<SettingFormData>;
8
8
  onDelete?: () => void;
9
9
  }): import("@emotion/react/jsx-runtime").JSX.Element;
@@ -8,7 +8,9 @@ export function FormQuestion(props) {
8
8
  const { control, index, onDelete } = props;
9
9
  return (_jsxs(Item, { children: [_jsx(Index, { children: index + 1 }), _jsx(FormInput, { control: control, name: `evaluations.${index}.question.text`, rules: {
10
10
  required: "필수 입력 항목입니다.",
11
- }, size: "small", placeholder: `${index + 1}번 평가 항목`, multiline: true, fullWidth: true }), onDelete && (_jsx(SquareButton, { color: "white", size: "xsmall", icon: _jsx(DeleteBinLineIcon, {}), onClick: onDelete }))] }));
11
+ }, size: "small", placeholder: `${index + 1}번 평가 항목`, multiline: true, fullWidth: true }), onDelete && (_jsx(SquareButton, { color: "white", size: "xsmall", icon: _jsx(DeleteBinLineIcon, {}), onClick: onDelete, buttonProps: {
12
+ "aria-label": "삭제",
13
+ } }))] }));
12
14
  }
13
15
  const Item = styled.div(({ theme }) => css `
14
16
  display: flex;
@@ -51,6 +51,8 @@ export function EvaluationComponent(props) {
51
51
  width: ${EVALUATION_EDIT_WIDTH}px;
52
52
  `, data: data, evaluations: evaluations, onClick: () => setSettingOpen((open) => !open) }), _jsx(SquareButton, { size: "small", color: "icon", icon: _jsx(Settings3FillIcon, {}), onClick: () => {
53
53
  setSettingOpen((open) => !open);
54
+ }, buttonProps: {
55
+ "aria-label": "평가 칸 설정",
54
56
  } })] })), settingOpen && (_jsx(SettingForm, { css: css `
55
57
  width: ${EVALUATION_EDIT_WIDTH}px;
56
58
  `, iconType: iconType, labels: labels, evaluations: evaluations, nodeKey: nodeKey, onClose: () => setSettingOpen(false) }))] }));
@@ -58,7 +58,9 @@ export function InputComponent(props) {
58
58
  ` }, { children: [_jsx(VirtualInput, Object.assign({ onClick: () => setSettingOpen((open) => !open), css: multiline &&
59
59
  css `
60
60
  height: ${TEXTAREA_HEIGHT + 2 * INPUT_VERTICAL_PADDING}px;
61
- ` }, { children: multiline ? "서술형 입력 칸" : "단답형 입력 칸" })), _jsx(SquareButton, { size: "small", color: "icon", icon: _jsx(Settings3FillIcon, {}), onClick: () => setSettingOpen((open) => !open) })] })), settingOpen && (_jsx(SettingForm, { multiline: multiline, placeholder: placeholder, nodeKey: nodeKey, onClose: () => setSettingOpen(false) }))] }));
61
+ ` }, { children: multiline ? "서술형 입력 칸" : "단답형 입력 칸" })), _jsx(SquareButton, { size: "small", color: "icon", icon: _jsx(Settings3FillIcon, {}), onClick: () => setSettingOpen((open) => !open), buttonProps: {
62
+ "aria-label": "입력 칸 설정",
63
+ } })] })), settingOpen && (_jsx(SettingForm, { multiline: multiline, placeholder: placeholder, nodeKey: nodeKey, onClose: () => setSettingOpen(false) }))] }));
62
64
  }
63
65
  const VirtualInput = styled.div(({ theme }) => css `
64
66
  box-sizing: border-box;
@@ -64,6 +64,8 @@ export function SelectComponent(props) {
64
64
  ? `${index + 1}번 선택지`
65
65
  : selection.show.text, onClick: () => setSettingOpen((open) => !open) }, index))) })), _jsx(SquareButton, { size: "small", color: "icon", icon: _jsx(Settings3FillIcon, {}), onClick: () => {
66
66
  setSettingOpen((open) => !open);
67
+ }, buttonProps: {
68
+ "aria-label": "선택지 설정",
67
69
  } })] })), settingOpen && (_jsx(SettingForm, { data: {
68
70
  selections,
69
71
  allowMultipleAnswers,
@@ -4,7 +4,7 @@ import { SettingFormData } from "./SettingForm";
4
4
  /** SheetSelectNode SettingForm의 단일 선택지 폼입니다. */
5
5
  export default function FormSelection(props: {
6
6
  index: number;
7
- control: Control<SettingFormData, any>;
7
+ control: Control<SettingFormData>;
8
8
  rules?: Omit<RegisterOptions<SettingFormData, `selections.${number}.show`>, "disabled" | "valueAsNumber" | "valueAsDate" | "setValueAs">;
9
9
  onDelete?: () => void;
10
10
  }): import("@emotion/react/jsx-runtime").JSX.Element;
@@ -5,7 +5,7 @@ import styled from "@emotion/styled";
5
5
  import { css } from "@emotion/react";
6
6
  import { useState } from "react";
7
7
  import { DeleteBinLineIcon, ErrorWarningFillIcon, ImageAddFillIcon, ImageEditFillIcon, Input, SquareButton, } from "../../../../../..";
8
- import { InsertImageDialog, } from "../../../../components/InsertImageDialog";
8
+ import { InsertImageDialog } from "../../../../components/InsertImageDialog";
9
9
  /** SheetSelectNode SettingForm의 단일 선택지 폼입니다. */
10
10
  export default function FormSelection(props) {
11
11
  var _a;
@@ -37,10 +37,10 @@ export default function FormSelection(props) {
37
37
  : inputFocused
38
38
  ? "activePrimary"
39
39
  : "default", value: value.text, onChange: (e) => onChange(Object.assign(Object.assign({}, value), { text: e.target.value })), inputProps: {
40
- onFocus: (_e) => {
40
+ onFocus: () => {
41
41
  setInputFocused(true);
42
42
  },
43
- onBlur: (_e) => {
43
+ onBlur: () => {
44
44
  setInputFocused(false);
45
45
  },
46
46
  }, placeholder: `${index + 1}번 선택지`, hintIcon: invalid ? _jsx(ErrorWarningFillIcon, {}) : undefined, hintText: error === null || error === void 0 ? void 0 : error.message, multiline: true, fullWidth: true, css: css `
@@ -53,7 +53,11 @@ export default function FormSelection(props) {
53
53
  align-items: center;
54
54
  ` }, { children: [_jsx(SquareButton, { color: "icon", size: "xsmall", icon: value.image ? _jsx(ImageEditFillIcon, {}) : _jsx(ImageAddFillIcon, {}), onClick: () => {
55
55
  setImageOpen(true);
56
- } }), onDelete && (_jsx(SquareButton, { color: "white", size: "xsmall", icon: _jsx(DeleteBinLineIcon, {}), onClick: onDelete }))] }))] }));
56
+ }, buttonProps: {
57
+ "aria-label": value.image ? "이미지 바꾸기" : "이미지 삽입하기",
58
+ } }), onDelete && (_jsx(SquareButton, { color: "white", size: "xsmall", icon: _jsx(DeleteBinLineIcon, {}), onClick: onDelete, buttonProps: {
59
+ "aria-label": "삭제",
60
+ } }))] }))] }));
57
61
  }
58
62
  const Container = styled.div(({ theme }) => css `
59
63
  display: flex;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@team-monolith/cds",
3
- "version": "1.69.0",
3
+ "version": "1.70.0",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "sideEffects": false,