@team-monolith/cds 1.99.7 → 1.99.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.
@@ -212,7 +212,7 @@ const SIZE_TO_LABEL_STYLE = {
212
212
  export const Button = React.forwardRef(function Button(props, ref) {
213
213
  const { className, component: Component = "button", disabled, color, size, startIcon, endIcon, label, fullWidth, bold = false, loading = false } = props, other = __rest(props, ["className", "component", "disabled", "color", "size", "startIcon", "endIcon", "label", "fullWidth", "bold", "loading"]);
214
214
  const theme = useTheme();
215
- return (_jsxs(Component, Object.assign({ type: Component === "a" ? undefined : "button" }, other, { className: className, ref: ref, css: [
215
+ return (_jsxs(Component, Object.assign({ type: Component === "button" || Component === "input" ? "button" : undefined }, other, { className: className, ref: ref, css: [
216
216
  css `
217
217
  display: inline-flex;
218
218
  align-items: center;
@@ -2,7 +2,7 @@
2
2
  /** @jsxImportSource @emotion/react */
3
3
  import { SerializedStyles } from "@emotion/react";
4
4
  import { TooltipProps } from "./Tooltip";
5
- interface OverflowTooltipProps extends Omit<TooltipProps, "open" | "onOpen" | "onClose" | "children"> {
5
+ interface OverflowTooltipProps extends Omit<TooltipProps, "open" | "onOpen" | "onClose" | "children" | "tooltipId"> {
6
6
  className?: string;
7
7
  childrenCss?: SerializedStyles;
8
8
  }
@@ -1,7 +1,8 @@
1
1
  import { jsx as _jsx } from "@emotion/react/jsx-runtime";
2
2
  import styled from "@emotion/styled";
3
- import { useRef, useState } from "react";
3
+ import { useRef, useState, useMemo } from "react";
4
4
  import { Tooltip } from "./Tooltip";
5
+ import { uid } from "uid";
5
6
  /**
6
7
  * 인자로 주어진 텍스트를 그립니다.
7
8
  * 공간이 부족하면 ...으로 표시하고 툴팁으로 전체 내용을 노출합니다.
@@ -9,6 +10,7 @@ import { Tooltip } from "./Tooltip";
9
10
  export function OverflowTooltip(props) {
10
11
  const tooltipRef = useRef(null);
11
12
  const [isTooltipOpen, setIsTooltipOpen] = useState(false);
13
+ const tooltipId = useMemo(() => `tooltip-${uid()}`, []);
12
14
  const getIsOverflow = () => {
13
15
  if (tooltipRef.current) {
14
16
  return tooltipRef.current.scrollWidth > tooltipRef.current.offsetWidth;
@@ -23,7 +25,7 @@ export function OverflowTooltip(props) {
23
25
  const handleClose = () => {
24
26
  setIsTooltipOpen(false);
25
27
  };
26
- return (_jsx(Tooltip, Object.assign({ open: isTooltipOpen, onOpen: handleOpen, onClose: handleClose }, props, { children: _jsx(OverflowDiv, Object.assign({ css: props.childrenCss, ref: tooltipRef, onMouseOver: handleOpen }, { children: props.text })) })));
28
+ return (_jsx(Tooltip, Object.assign({ tooltipId: tooltipId, open: isTooltipOpen, onOpen: handleOpen, onClose: handleClose }, props, { children: _jsx(OverflowDiv, Object.assign({ css: props.childrenCss, ref: tooltipRef, onMouseOver: handleOpen, "aria-labelledby": tooltipId }, { children: props.text })) })));
27
29
  }
28
30
  const OverflowDiv = styled.div `
29
31
  overflow: hidden;
@@ -184,7 +184,9 @@ export const SquareButton = React.forwardRef(function SquareButton(props, ref) {
184
184
  align-items: center;
185
185
  gap: 8px;
186
186
  width: ${fullWidth ? "100%" : "fit-content"};
187
- ` }, { children: [_jsx(Component, Object.assign({ type: Component === "a" ? undefined : "button" }, other, buttonProps, { ref: ref, css: [
187
+ ` }, { children: [_jsx(Component, Object.assign({ type: Component === "button" || Component === "input"
188
+ ? "button"
189
+ : undefined }, other, buttonProps, { ref: ref, css: [
188
190
  COLOR_TO_BUTTON_STYLE(theme, color, Boolean(disabled || loading)),
189
191
  SIZE_TO_BUTTON_STYLE[size],
190
192
  css `
@@ -21,6 +21,12 @@ export interface TooltipProps {
21
21
  placement?: "bottom-end" | "bottom-start" | "bottom" | "left-end" | "left-start" | "left" | "right-end" | "right-start" | "right" | "top-end" | "top-start" | "top";
22
22
  /** 툴팁을 표시할 객체입니다. ref를 props로 받을 수 있어야합니다. */
23
23
  children: React.ReactElement;
24
+ /**
25
+ * 툴팁의 고유 id입니다.
26
+ * 이 id는 툴팁을 띄우는 요소에 aria-labelledby 속성을 통해 연결되어,
27
+ * 스크린 리더 등의 보조 기술이 툴팁 내용을 올바르게 인식하도록 돕습니다.
28
+ */
29
+ tooltipId: string;
24
30
  }
25
31
  /**
26
32
  * [피그마](https://www.figma.com/file/yhrRFizzmhPoHdw9FbYow2/Codle-PD-Kit---Components?type=design&node-id=172-626&t=aFkKTFgWq2xFFGC5-0)
@@ -45,9 +45,9 @@ function addTabIndexIfNeeded(element) {
45
45
  * [피그마](https://www.figma.com/file/yhrRFizzmhPoHdw9FbYow2/Codle-PD-Kit---Components?type=design&node-id=172-626&t=aFkKTFgWq2xFFGC5-0)
46
46
  */
47
47
  export const Tooltip = React.forwardRef(function Tooltip(props, ref) {
48
- const { title, text, children } = props, restProps = __rest(props, ["title", "text", "children"]);
48
+ const { tooltipId, title, text, children } = props, restProps = __rest(props, ["tooltipId", "title", "text", "children"]);
49
49
  const focusableChildren = addTabIndexIfNeeded(children);
50
- return (_jsx(StyledTooltip, Object.assign({ ref: ref, title:
50
+ return (_jsx(StyledTooltip, Object.assign({ id: tooltipId, ref: ref, title:
51
51
  // title이 없고 text가 null인 경우 툴팁을 표시하지 않음
52
52
  !title && text === null ? null : (_jsxs(_Fragment, { children: [title && _jsx(TitleDiv, { children: title }), text] })), describeChild: true }, restProps, { children: focusableChildren })));
53
53
  });
@@ -32,7 +32,7 @@ const Dropdown = forwardRef(function Dropdown(props, ref) {
32
32
  const isControlled = menuProps.open !== undefined;
33
33
  const [open, setOpen] = useState(false);
34
34
  const [itemState, setItemState] = useState(new Map());
35
- const uniqueId = useMemo(uid, []);
35
+ const dropdownMenuId = useMemo(() => `dropdown-menu-${uid()}`, []);
36
36
  const handleClick = (e) => {
37
37
  onClick === null || onClick === void 0 ? void 0 : onClick(e);
38
38
  if (!isControlled)
@@ -55,6 +55,6 @@ const Dropdown = forwardRef(function Dropdown(props, ref) {
55
55
  });
56
56
  (_a = menuProps.onClose) === null || _a === void 0 ? void 0 : _a.call(menuProps, e);
57
57
  };
58
- return (_jsxs(Component, Object.assign({ className: className }, other, { ref: ref }, { children: [_jsx(Button, Object.assign({ css: buttonCss, ref: menuRef }, buttonProps, { onClick: handleClick, fullWidth: true, "aria-expanded": (_a = menuProps.open) !== null && _a !== void 0 ? _a : open, "aria-controls": uniqueId })), _jsx(DropdownMenu, Object.assign({ dropdownMenuId: uniqueId }, menuProps, { open: isControlled ? menuProps.open : open, onClose: handleClose, anchorEl: menuRef.current, closeOnItemClick: closeOnItemClick, itemState: itemState, setItemState: setItemState }, { children: children }))] })));
58
+ return (_jsxs(Component, Object.assign({ className: className }, other, { ref: ref }, { children: [_jsx(Button, Object.assign({ css: buttonCss, ref: menuRef }, buttonProps, { onClick: handleClick, fullWidth: true, "aria-expanded": (_a = menuProps.open) !== null && _a !== void 0 ? _a : open, "aria-controls": dropdownMenuId })), _jsx(DropdownMenu, Object.assign({ dropdownMenuId: dropdownMenuId }, menuProps, { open: isControlled ? menuProps.open : open, onClose: handleClose, anchorEl: menuRef.current, closeOnItemClick: closeOnItemClick, itemState: itemState, setItemState: setItemState }, { children: children }))] })));
59
59
  });
60
60
  export { Dropdown };
@@ -31,7 +31,7 @@ const DropdownItem = React.forwardRef(function DropdownItem(props, ref) {
31
31
  const { className, index, labelCss, component: Component = "div", type = "default", checkbox, checkboxProps = { checked: false }, startIcon, label, endIcon, preserveIconColor = false, disabled, active, onMouseEnter, onMouseLeave, onClick, subMenuProps, children } = props, other = __rest(props, ["className", "index", "labelCss", "component", "type", "checkbox", "checkboxProps", "startIcon", "label", "endIcon", "preserveIconColor", "disabled", "active", "onMouseEnter", "onMouseLeave", "onClick", "subMenuProps", "children"]);
32
32
  const itemRef = useRef(null);
33
33
  const { open, onCloseOnItemClick, nestedIndex, itemState, setItemState } = useContext(DropdownContext);
34
- const uniqueId = useMemo(uid, []);
34
+ const dropdownMenuId = useMemo(() => `dropdown-menu-${uid()}`, []);
35
35
  const absItemIndex = nestedIndex ? `${nestedIndex}-${index}` : `${index}`;
36
36
  // 서브메뉴가 존재하는지 여부
37
37
  const isSubMenuExist = Boolean(children);
@@ -51,7 +51,7 @@ const DropdownItem = React.forwardRef(function DropdownItem(props, ref) {
51
51
  setSelected(setItemState, absItemIndex);
52
52
  }
53
53
  };
54
- return (_jsxs(_Fragment, { children: [_jsx(Component, Object.assign({ className: className, ref: ref, tabIndex: disabled ? -1 : 0, onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, onClick: handleClick, "aria-disabled": disabled }, other, { "aria-expanded": isSubMenuExist ? isSubMenuShowed : undefined, "aria-controls": isSubMenuExist ? uniqueId : undefined }, { children: _jsxs(Item, Object.assign({ ref: itemRef, disabled: disabled, selected: isSubMenuShowed || Boolean(active) }, { children: [_jsxs(LeftWrapper, { children: [checkbox && (_jsx(StyledCheckboxInput, Object.assign({}, checkboxProps, { disabled: disabled, onClick: (e) => {
54
+ return (_jsxs(_Fragment, { children: [_jsx(Component, Object.assign({ className: className, ref: ref, tabIndex: disabled ? -1 : 0, onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, onClick: handleClick, "aria-disabled": disabled }, other, { "aria-expanded": isSubMenuExist ? isSubMenuShowed : undefined, "aria-controls": isSubMenuExist ? dropdownMenuId : undefined }, { children: _jsxs(Item, Object.assign({ ref: itemRef, disabled: disabled, selected: isSubMenuShowed || Boolean(active) }, { children: [_jsxs(LeftWrapper, { children: [checkbox && (_jsx(StyledCheckboxInput, Object.assign({}, checkboxProps, { disabled: disabled, onClick: (e) => {
55
55
  e.stopPropagation();
56
56
  } }))), startIcon && (_jsx(IconDiv, Object.assign({ type: type, preserveIconColor: preserveIconColor }, { children: startIcon }))), _jsx(LabelDiv, Object.assign({ css: labelCss, type: type }, { children: label }))] }), endIcon && (_jsx(IconDiv, Object.assign({ type: type, preserveIconColor: preserveIconColor }, { children: endIcon }))), !endIcon && isSubMenuExist && (_jsx(IconDiv, Object.assign({ type: type, preserveIconColor: preserveIconColor }, { children: _jsx(ArrowRightSLineIcon, {}) })))] })) })), isSubMenuExist && (_jsx(DropdownContext.Provider, Object.assign({ value: {
57
57
  open,
@@ -59,7 +59,7 @@ const DropdownItem = React.forwardRef(function DropdownItem(props, ref) {
59
59
  nestedIndex: absItemIndex,
60
60
  itemState,
61
61
  setItemState,
62
- } }, { children: _jsx(DropdownMenu, Object.assign({ dropdownMenuId: uniqueId }, subMenuProps, { open: isSubMenuShowed, anchorEl: itemRef.current, isNestedMenu: true, anchorOrigin: {
62
+ } }, { children: _jsx(DropdownMenu, Object.assign({ dropdownMenuId: dropdownMenuId }, subMenuProps, { open: isSubMenuShowed, anchorEl: itemRef.current, isNestedMenu: true, anchorOrigin: {
63
63
  vertical: "top",
64
64
  horizontal: "right",
65
65
  }, itemState: itemState, setItemState: setItemState }, { children: children })) })))] }));
@@ -7,9 +7,12 @@ import { AlertFillIcon, DeleteBinLineIcon, ErrorWarningFillIcon, } from "../../.
7
7
  import { SquareButton } from "../../../../../components/SquareButton";
8
8
  import { Tooltip } from "../../../../../components/Tooltip";
9
9
  import { TextTypeDropdown } from "./TextTypeDropdown";
10
+ import { uid } from "uid";
11
+ import { useMemo } from "react";
10
12
  export function FormSolution(props) {
11
13
  const { index, control, rules, onDelete } = props;
12
14
  const theme = useTheme();
15
+ const tooltipId = useMemo(() => `tooltip-${uid()}`, []);
13
16
  return (_jsx(Controller, { name: `solutions.${index}.value`, control: control, rules: rules, render: ({ field: { value, onChange }, fieldState: { invalid, error }, }) => {
14
17
  const disabled = (error === null || error === void 0 ? void 0 : error.type) === "enabled";
15
18
  return (_jsx(Input, { size: "small", color: invalid ? "activeDanger" : "default", onChange: onChange, disabled: disabled, value: value, hintIcon: !disabled && invalid ? _jsx(ErrorWarningFillIcon, {}) : undefined, hintText: !disabled ? error === null || error === void 0 ? void 0 : error.message : undefined, placeholder: "\uC548\uB155\uD558\uC138\uC694", fullWidth: true, css: css `
@@ -21,8 +24,8 @@ export function FormSolution(props) {
21
24
  gap: 4px;
22
25
  ` }, { children: [onDelete && (_jsx(SquareButton, { color: "white", size: "xsmall", icon: _jsx(DeleteBinLineIcon, {}), onClick: onDelete, buttonProps: {
23
26
  "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: {
27
+ } })), disabled && (_jsx(Tooltip, Object.assign({ tooltipId: tooltipId, 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
28
  "aria-label": "정답 등록 불가",
26
- } }) })))] })) }));
29
+ }, "aria-labelledby": tooltipId }) })))] })) }));
27
30
  } }));
28
31
  }
@@ -13,9 +13,13 @@ import { FormSegmentedControl } from "./FormSegmentedControl";
13
13
  import { FormPlaceholder } from "./FormPlaceholder";
14
14
  import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext";
15
15
  import { $getNodeByKey } from "lexical";
16
+ import { uid } from "uid";
17
+ import { useMemo } from "react";
16
18
  export function SettingForm(props) {
17
19
  const { solutions, showCharacterNumber, placeholder, nodeKey, onClose, caseSensitive, ignoreWhitespace, } = props;
18
20
  const [editor] = useLexicalComposerContext();
21
+ const inputTooltipId = useMemo(() => `tooltip-${uid()}`, []);
22
+ const placeholderTooltipId = useMemo(() => `tooltip-${uid()}`, []);
19
23
  const { control, handleSubmit, watch, trigger } = useForm({
20
24
  mode: "all",
21
25
  defaultValues: {
@@ -73,16 +77,16 @@ export function SettingForm(props) {
73
77
  ` }, { children: [_jsx(AlarmWarningFillIcon, { color: theme.color.foreground.neutralBaseDisabled, css: css `
74
78
  width: 14px;
75
79
  height: 14px;
76
- ` }), _jsx(Label, { children: "\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: [`예를 들어 정답이 '글자 수'이고`, _jsx("br", {}), _jsx("b", { children: "\uAE00\uC790 \uC218\uB300\uB85C" }), " \uC635\uC158\uC744 \uC120\uD0DD\uD588\uB2E4\uBA74", _jsx("br", {}), `입력 칸이 '☐☐ ☐' 처럼 표시됩니다.`] }), placement: "top" }, { children: _jsx(QuestionFillIcon, { css: css `
80
+ ` }), _jsx(Label, { children: "\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({ tooltipId: inputTooltipId, text: _jsxs("span", { children: [`예를 들어 정답이 '글자 수'이고`, _jsx("br", {}), _jsx("b", { children: "\uAE00\uC790 \uC218\uB300\uB85C" }), " \uC635\uC158\uC744 \uC120\uD0DD\uD588\uB2E4\uBA74", _jsx("br", {}), `입력 칸이 '☐☐ ☐' 처럼 표시됩니다.`] }), placement: "top" }, { children: _jsx(QuestionFillIcon, { css: css `
77
81
  width: 12px;
78
82
  height: 12px;
79
- ` }) }))] }), _jsx(FormSegmentedControl, { control: control, trigger: trigger, name: "showCharacterNumber", items: [
83
+ `, "aria-labelledby": inputTooltipId }) }))] }), _jsx(FormSegmentedControl, { control: control, trigger: trigger, name: "showCharacterNumber", items: [
80
84
  { value: false, label: "한 칸으로" },
81
85
  { value: true, label: "글자 수대로" },
82
- ] })] }), _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 `
86
+ ] })] }), _jsxs(FormArea, { children: [_jsxs(Label, { children: ["\uC790\uB9AC \uD45C\uC2DC\uC790", _jsx(Tooltip, Object.assign({ tooltipId: placeholderTooltipId, 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 `
83
87
  width: 12px;
84
88
  height: 12px;
85
- ` }) }))] }), _jsx(FormPlaceholder, { control: control })] }), _jsxs(FormArea, { children: [_jsx(Label, { children: "\uB744\uC5B4\uC4F0\uAE30" }), _jsx(FormSegmentedControl, { control: control, trigger: trigger, name: "ignoreWhitespace", items: [
89
+ `, "aria-labelledby": placeholderTooltipId }) }))] }), _jsx(FormPlaceholder, { control: control })] }), _jsxs(FormArea, { children: [_jsx(Label, { children: "\uB744\uC5B4\uC4F0\uAE30" }), _jsx(FormSegmentedControl, { control: control, trigger: trigger, name: "ignoreWhitespace", items: [
86
90
  { value: true, label: "무시하기" },
87
91
  { value: false, label: "포함하기" },
88
92
  ] })] }), _jsxs(FormArea, { children: [_jsx(Label, { children: "\uB300\uC18C\uBB38\uC790" }), _jsx(FormSegmentedControl, { control: control, trigger: trigger, name: "caseSensitive", items: [
@@ -11,12 +11,13 @@ import { AddFillIcon, AlarmWarningFillIcon, ListRadioIcon, } from "../../../../.
11
11
  import { Button } from "../../../../../components/Button";
12
12
  import { FormSelection } from "./FormSelection";
13
13
  import { Tooltip } from "../../../../../components/Tooltip";
14
- import { useState } from "react";
14
+ import { useState, useMemo } from "react";
15
15
  import { uid } from "uid";
16
16
  export function SettingForm(props) {
17
17
  const { selections, nodeKey, onClose } = props;
18
18
  const [editor] = useLexicalComposerContext();
19
19
  const [tooltipOpen, setTooltipOpen] = useState(false);
20
+ const tooltipId = useMemo(() => `tooltip-${uid()}`, []);
20
21
  const { control, handleSubmit, watch } = useForm({
21
22
  mode: "all",
22
23
  defaultValues: {
@@ -89,7 +90,7 @@ export function SettingForm(props) {
89
90
  }, disabled: fields.length >= 9 }), hasMultipleAnswers && (_jsxs(Alert, { children: [_jsx(AlarmWarningFillIcon, { css: css `
90
91
  width: 14px;
91
92
  height: 14px;
92
- ` }), "\uC815\uB2F5\uC774 \uC5EC\uB7EC \uAC1C\uC778 \uBB38\uC81C\uC5D0\uB294 \uC815\uB2F5\uC744 \uBAA8\uB450 \uC120\uD0DD\uD574\uC57C \uD55C\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(Tooltip, Object.assign({ open: !hasAnswer && tooltipOpen, text: "\uC120\uD0DD\uC9C0 \uC911 \uC815\uB2F5\uC744 \uD45C\uC2DC\uD574\uC8FC\uC138\uC694.", onOpen: () => setTooltipOpen(true), onClose: () => setTooltipOpen(false), placement: "top-end" }, { children: _jsx("span", { children: _jsx(Button, { color: "primary", size: "xsmall", label: "\uC774\uB300\uB85C \uB123\uAE30", type: "submit", disabled: !hasAnswer }) }) }))] })] })));
93
+ ` }), "\uC815\uB2F5\uC774 \uC5EC\uB7EC \uAC1C\uC778 \uBB38\uC81C\uC5D0\uB294 \uC815\uB2F5\uC744 \uBAA8\uB450 \uC120\uD0DD\uD574\uC57C \uD55C\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(Tooltip, Object.assign({ tooltipId: tooltipId, open: !hasAnswer && tooltipOpen, text: "\uC120\uD0DD\uC9C0 \uC911 \uC815\uB2F5\uC744 \uD45C\uC2DC\uD574\uC8FC\uC138\uC694.", onOpen: () => setTooltipOpen(true), onClose: () => setTooltipOpen(false), placement: "top-end" }, { children: _jsx("span", Object.assign({ "aria-labelledby": tooltipId }, { children: _jsx(Button, { color: "primary", size: "xsmall", label: "\uC774\uB300\uB85C \uB123\uAE30", type: "submit", disabled: !hasAnswer }) })) }))] })] })));
93
94
  }
94
95
  const Form = styled.form(({ theme }) => css `
95
96
  display: flex;
@@ -8,10 +8,13 @@ import { css } from "@emotion/react";
8
8
  import { InputMethodLineIcon, QuestionFillIcon } from "../../../../icons";
9
9
  import { Button, Input, shadows, Tooltip } from "../../../..";
10
10
  import { $isSheetInputNode } from "./SheetInputNode";
11
+ import { uid } from "uid";
12
+ import { useMemo } from "react";
11
13
  /** 활동지 활동의 입력칸 설정 컴포넌트입니다. */
12
14
  export function SettingForm(props) {
13
15
  const { multiline, placeholder, nodeKey, onClose } = props;
14
16
  const [editor] = useLexicalComposerContext();
17
+ const tooltipId = useMemo(() => `tooltip-${uid()}`, []);
15
18
  const { control, handleSubmit } = useForm({
16
19
  mode: "all",
17
20
  defaultValues: {
@@ -31,10 +34,10 @@ export function SettingForm(props) {
31
34
  return (_jsxs(Form, Object.assign({ onSubmit: handleSubmit(onSettingSubmit) }, { children: [_jsxs(Title, { children: [_jsx(InputMethodLineIcon, { css: css `
32
35
  width: 12px;
33
36
  height: 12px;
34
- ` }), multiline ? "서술형 입력 칸" : "단답형 입력 칸"] }), _jsx(Content, { children: _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 `
37
+ ` }), multiline ? "서술형 입력 칸" : "단답형 입력 칸"] }), _jsx(Content, { children: _jsxs(FormArea, { children: [_jsxs(Label, { children: ["\uC790\uB9AC \uD45C\uC2DC\uC790", _jsx(Tooltip, Object.assign({ tooltipId: tooltipId, 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 `
35
38
  width: 12px;
36
39
  height: 12px;
37
- ` }) }))] }), _jsx(Controller, { name: "placeholder", control: control, render: ({ field: { value, onChange } }) => (_jsx(Input, { size: "small", color: "default", value: value, onChange: onChange, placeholder: "\uC608) \uC5EC\uAE30\uC5D0 \uC785\uB825\uD558\uC138\uC694." })) })] }) }), _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" })] })] })));
40
+ `, "aria-labelledby": tooltipId }) }))] }), _jsx(Controller, { name: "placeholder", control: control, render: ({ field: { value, onChange } }) => (_jsx(Input, { size: "small", color: "default", value: value, onChange: onChange, placeholder: "\uC608) \uC5EC\uAE30\uC5D0 \uC785\uB825\uD558\uC138\uC694." })) })] }) }), _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" })] })] })));
38
41
  }
39
42
  const Form = styled.form(({ theme }) => css `
40
43
  display: flex;
@@ -3,14 +3,17 @@ import styled from "@emotion/styled";
3
3
  import { HOVER, RESET_BUTTON, Tooltip } from "../..";
4
4
  import { css } from "@emotion/react";
5
5
  import { toggleButtonGroupClasses, } from "./ToggleButtonGroup";
6
+ import { uid } from "uid";
7
+ import { useMemo } from "react";
6
8
  /** 하나의 ToggleButton을 그립니다. */
7
9
  export function ToggleButton(props) {
8
10
  const { datum, placement, isActive, onClick } = props;
9
11
  const { label, onIcon, offIcon } = datum;
12
+ const tooltipId = useMemo(() => `tooltip-${uid()}`, []);
10
13
  if (isActive) {
11
14
  return (_jsxs(Active, Object.assign({ "aria-label": `${label} 선택 해제하기`, className: toggleButtonGroupClasses.toggleButton.active, onClick: onClick }, { children: [onIcon, label] })));
12
15
  }
13
- return (_jsx(Tooltip, Object.assign({ placement: placement, text: label }, { children: _jsx(Inactive, Object.assign({ "aria-label": `${label} 선택하기`, className: toggleButtonGroupClasses.toggleButton.inactive, onClick: onClick }, { children: offIcon })) })));
16
+ return (_jsx(Tooltip, Object.assign({ tooltipId: tooltipId, placement: placement, text: label }, { children: _jsx(Inactive, Object.assign({ "aria-label": `${label} 선택하기`, className: toggleButtonGroupClasses.toggleButton.inactive, onClick: onClick, "aria-labelledby": tooltipId }, { children: offIcon })) })));
14
17
  }
15
18
  const Active = styled.button(({ theme }) => css `
16
19
  ${RESET_BUTTON};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@team-monolith/cds",
3
- "version": "1.99.7",
3
+ "version": "1.99.9",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "sideEffects": false,