@team-monolith/cds 1.100.2 → 1.100.4

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.
@@ -1,6 +1,7 @@
1
1
  import React from "react";
2
+ import { SwitchProps as MuiSwitchProps } from "@mui/material";
2
3
  export type SwitchSize = "small" | "large";
3
- export interface SwitchProps {
4
+ export interface SwitchProps extends Omit<MuiSwitchProps, "size"> {
4
5
  className?: string;
5
6
  /** 스위치 체크 상태 여부 */
6
7
  checked: boolean;
@@ -15,4 +16,4 @@ export interface SwitchProps {
15
16
  /**
16
17
  * [피그마](https://www.figma.com/file/yhrRFizzmhPoHdw9FbYow2/Codle-PD-Kit---Components?type=design&node-id=36-1577&t=9sDLb4XIOdmF2VMc-0)
17
18
  */
18
- export declare const Switch: React.ForwardRefExoticComponent<SwitchProps & React.RefAttributes<HTMLButtonElement>>;
19
+ export declare const Switch: React.ForwardRefExoticComponent<Omit<SwitchProps, "ref"> & React.RefAttributes<HTMLButtonElement>>;
@@ -13,7 +13,7 @@ import { jsx as _jsx } from "@emotion/react/jsx-runtime";
13
13
  /** @jsxImportSource @emotion/react */
14
14
  import styled from "@emotion/styled";
15
15
  import React from "react";
16
- import { Switch as MuiSwitch } from "@mui/material";
16
+ import { Switch as MuiSwitch, } from "@mui/material";
17
17
  import { css } from "@emotion/react";
18
18
  /**
19
19
  * [피그마](https://www.figma.com/file/yhrRFizzmhPoHdw9FbYow2/Codle-PD-Kit---Components?type=design&node-id=36-1577&t=9sDLb4XIOdmF2VMc-0)
package/dist/index.d.ts CHANGED
@@ -30,6 +30,7 @@ export * from "./icons/custom/colored";
30
30
  export * from "./utils/hover";
31
31
  export * from "./utils/reset";
32
32
  export * from "./utils/zIndex";
33
+ export * from "./utils/visuallyHidden";
33
34
  export * from "./patterns/Dropdown";
34
35
  export * from "./patterns/SegmentedControl";
35
36
  export * from "./patterns/LexicalEditor";
package/dist/index.js CHANGED
@@ -30,6 +30,7 @@ export * from "./icons/custom/colored";
30
30
  export * from "./utils/hover";
31
31
  export * from "./utils/reset";
32
32
  export * from "./utils/zIndex";
33
+ export * from "./utils/visuallyHidden";
33
34
  export * from "./patterns/Dropdown";
34
35
  export * from "./patterns/SegmentedControl";
35
36
  export * from "./patterns/LexicalEditor";
@@ -3,6 +3,7 @@ import { jsxs as _jsxs, jsx as _jsx } from "@emotion/react/jsx-runtime";
3
3
  import { css } from "@emotion/react";
4
4
  import styled from "@emotion/styled";
5
5
  import { ArrowDownSLineIcon, ArrowUpSLineIcon } from "../icons";
6
+ import { RESET_BUTTON } from "../utils/reset";
6
7
  /** 배너같이 생겼으나 누를 때마다 하단내용이 접힘(보이지않음)/펼침(보임) 상태가 바뀌는 컴포넌트입니다. */
7
8
  export function Accordion(props) {
8
9
  const { className, icon, title, children, open = false, onClick, wrapperClassName, } = props;
@@ -10,7 +11,7 @@ export function Accordion(props) {
10
11
  display: flex;
11
12
  flex-direction: column;
12
13
  gap: 2px;
13
- `, className: wrapperClassName }, { children: [_jsxs(Container, Object.assign({ className: className, onClick: onClick }, { children: [_jsxs(Title, { children: [icon, title] }), open ? _jsx(ArrowUpSLineIcon, {}) : _jsx(ArrowDownSLineIcon, {})] })), open && children] })));
14
+ `, className: wrapperClassName }, { children: [_jsxs(Container, Object.assign({ type: "button", className: className, onClick: onClick, "aria-expanded": open }, { children: [_jsxs(Title, { children: [icon, title] }), open ? _jsx(ArrowUpSLineIcon, {}) : _jsx(ArrowDownSLineIcon, {})] })), open && children] })));
14
15
  }
15
16
  const Title = styled.div(({ theme }) => css `
16
17
  display: flex;
@@ -21,7 +22,8 @@ const Title = styled.div(({ theme }) => css `
21
22
  font-weight: 700;
22
23
  line-height: 16px; /* 133.333% */
23
24
  `);
24
- const Container = styled.div `
25
+ const Container = styled.button `
26
+ ${RESET_BUTTON}
25
27
  display: flex;
26
28
  padding: 8px 16px;
27
29
  align-items: center;
@@ -11,10 +11,9 @@ var __rest = (this && this.__rest) || function (s, e) {
11
11
  };
12
12
  import { jsx as _jsx, jsxs as _jsxs } from "@emotion/react/jsx-runtime";
13
13
  /** @jsxImportSource @emotion/react */
14
- import { forwardRef, useMemo, useRef, useState } from "react";
14
+ import { forwardRef, useId, useRef, useState } from "react";
15
15
  import { Button, ArrowDownSFillIcon, } from "../..";
16
16
  import { DropdownMenu } from "./DropdownMenu";
17
- import { uid } from "uid";
18
17
  /**
19
18
  * [피그마](https://www.figma.com/file/PnQp3tPxiCjgsPZfLUaUL1/Codle-PD-Kit---Patterns?type=design&node-id=203-95329&t=FwczLZ1IVvskUVbT-0)
20
19
  */
@@ -32,7 +31,7 @@ const Dropdown = forwardRef(function Dropdown(props, ref) {
32
31
  const isControlled = menuProps.open !== undefined;
33
32
  const [open, setOpen] = useState(false);
34
33
  const [itemState, setItemState] = useState(new Map());
35
- const dropdownMenuId = useMemo(() => `dropdown-menu-${uid()}`, []);
34
+ const dropdownMenuId = `dropdown-menu-${useId()}`;
36
35
  const handleClick = (e) => {
37
36
  onClick === null || onClick === void 0 ? void 0 : onClick(e);
38
37
  if (!isControlled)
@@ -14,12 +14,11 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "@emotion/reac
14
14
  import { css } from "@emotion/react";
15
15
  import * as React from "react";
16
16
  import styled from "@emotion/styled";
17
- import { CheckboxInput, ArrowRightSLineIcon, HOVER, } from "../../..";
18
- import { useContext, useMemo, useRef } from "react";
17
+ import { CheckboxInput, ArrowRightSLineIcon, HOVER, RESET_BUTTON, } from "../../..";
18
+ import { useContext, useId, useRef } from "react";
19
19
  import { DropdownMenu } from "../DropdownMenu";
20
20
  import { DropdownContext } from "../DropdownContext";
21
21
  import { getSelected, setSelected } from "./selected";
22
- import { uid } from "uid";
23
22
  const TYPE_TO_COLOR = (theme, type) => ({
24
23
  default: theme.color.foreground.neutralBase,
25
24
  danger: theme.color.foreground.danger,
@@ -28,10 +27,10 @@ const TYPE_TO_COLOR = (theme, type) => ({
28
27
  * [피그마](https://www.figma.com/file/PnQp3tPxiCjgsPZfLUaUL1/Codle-PD-Kit---Patterns?type=design&node-id=106-1900&t=FwczLZ1IVvskUVbT-0)
29
28
  */
30
29
  const DropdownItem = React.forwardRef(function DropdownItem(props, ref) {
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"]);
30
+ const { className, index, labelCss, component: Component = "button", 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
31
  const itemRef = useRef(null);
33
32
  const { open, onCloseOnItemClick, nestedIndex, itemState, setItemState } = useContext(DropdownContext);
34
- const dropdownMenuId = useMemo(() => `dropdown-menu-${uid()}`, []);
33
+ const dropdownMenuId = `dropdown-menu-${useId()}`;
35
34
  const absItemIndex = nestedIndex ? `${nestedIndex}-${index}` : `${index}`;
36
35
  // 서브메뉴가 존재하는지 여부
37
36
  const isSubMenuExist = Boolean(children);
@@ -51,7 +50,12 @@ const DropdownItem = React.forwardRef(function DropdownItem(props, ref) {
51
50
  setSelected(setItemState, absItemIndex);
52
51
  }
53
52
  };
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) => {
53
+ 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, disabled: disabled }, (Component === "button"
54
+ ? {
55
+ type: "button",
56
+ css: RESET_BUTTON,
57
+ }
58
+ : {}), { 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
59
  e.stopPropagation();
56
60
  } }))), 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
61
  open,
@@ -3,7 +3,7 @@ import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext
3
3
  import { useLexicalNodeSelection } from "@lexical/react/useLexicalNodeSelection";
4
4
  import { mergeRegister } from "@lexical/utils";
5
5
  import { $getNodeByKey, $getSelection, $isNodeSelection, $isRangeSelection, $setSelection, CLICK_COMMAND, COMMAND_PRIORITY_LOW, createCommand, DRAGSTART_COMMAND, KEY_BACKSPACE_COMMAND, KEY_DELETE_COMMAND, KEY_ENTER_COMMAND, KEY_ESCAPE_COMMAND, SELECTION_CHANGE_COMMAND, } from "lexical";
6
- import { Suspense, useCallback, useEffect, useRef, useState, } from "react";
6
+ import { Suspense, useCallback, useEffect, useRef, useState } from "react";
7
7
  import { $isImageNode } from "./ImageNode";
8
8
  import { SquareButton } from "../../../../components/SquareButton";
9
9
  import { Settings3FillIcon } from "../../../../icons";
@@ -13,6 +13,7 @@ import { useLexicalEditable } from "@lexical/react/useLexicalEditable";
13
13
  import { ImageNotAvailable } from "./ImageNotAvailable";
14
14
  import { ImageResizer } from "./ImageResizer";
15
15
  import { css } from "@emotion/react";
16
+ import { RESET_BUTTON } from "../../../../utils/reset";
16
17
  const imageCache = new Set();
17
18
  export const RIGHT_CLICK_IMAGE_COMMAND = createCommand("RIGHT_CLICK_IMAGE_COMMAND");
18
19
  function useSuspenseImage(src) {
@@ -32,6 +33,17 @@ function useSuspenseImage(src) {
32
33
  }
33
34
  function LazyImage({ altText, className, imageRef, src, width, height, maxWidth: _maxWidth, onError, title, onClick, }) {
34
35
  useSuspenseImage(src);
36
+ if (onClick) {
37
+ return (_jsx("button", Object.assign({ type: "button", css: RESET_BUTTON, onClick: onClick, "aria-label": "\uC774\uBBF8\uC9C0 (\uC0C8 \uD0ED)" }, { children: _jsx("img", { className: className || undefined, src: src, alt: altText, ref: imageRef, style: {
38
+ height,
39
+ // 이미지로 인해 좌우로 스크롤이 생기는 것을 방지
40
+ // maxWidth: `min(${maxWidth}px, 100%)`,
41
+ // 이미지가 maxWidth보다 클 경우 이미지를 줄이지 않기 위해 100%로 변경
42
+ // fixme: maxWidth를 수정할 수 있게 되면 원복합니다.
43
+ maxWidth: "100%",
44
+ width,
45
+ }, title: title, onError: onError, draggable: "false" }) })));
46
+ }
35
47
  return (_jsx("img", { className: className || undefined, src: src, alt: altText, ref: imageRef, style: {
36
48
  height,
37
49
  // 이미지로 인해 좌우로 스크롤이 생기는 것을 방지
@@ -40,7 +52,7 @@ function LazyImage({ altText, className, imageRef, src, width, height, maxWidth:
40
52
  // fixme: maxWidth를 수정할 수 있게 되면 원복합니다.
41
53
  maxWidth: "100%",
42
54
  width,
43
- }, title: title, onClick: onClick, onError: onError, draggable: "false" }));
55
+ }, title: title, onError: onError, draggable: "false" }));
44
56
  }
45
57
  export function ImageComponent({ src, altText, nodeKey, width, height, maxWidth, resizable, }) {
46
58
  const imageRef = useRef(null);
@@ -184,7 +196,7 @@ export function ImageComponent({ src, altText, nodeKey, width, height, maxWidth,
184
196
  ? `focused ${$isNodeSelection(selection) ? "draggable" : ""}`
185
197
  : null, css: css `
186
198
  cursor: pointer;
187
- `, src: src, altText: altText, imageRef: imageRef, width: width, height: height, maxWidth: maxWidth, onError: () => setIsLoadError(true), onClick: () => window.open(src, "_blank"), title: "\uD074\uB9AD\uD574\uC11C \uC6D0\uBCF8 \uC774\uBBF8\uC9C0 \uBCF4\uAE30" })) })) })));
199
+ `, src: src, altText: altText, imageRef: imageRef, width: width, height: height, maxWidth: maxWidth, onError: () => setIsLoadError(true), onClick: () => window.open(src, "_blank"), title: "\uD074\uB9AD\uD574\uC11C \uC6D0\uBCF8 \uC774\uBBF8\uC9C0 \uBCF4\uAE30." })) })) })));
188
200
  }
189
201
  return (_jsxs(_Fragment, { children: [_jsxs(EditContainer, { children: [_jsx(Suspense, Object.assign({ fallback: null }, { children: _jsx("div", Object.assign({ draggable: draggable, css: css `
190
202
  // ImageResizer를 위한 relative 설정입니다.
@@ -9,6 +9,7 @@ import { SquareButton } from "../../../../../components/SquareButton";
9
9
  import { Switch } from "../../../../../components/Switch";
10
10
  import { useState } from "react";
11
11
  import { InsertImageDialog } from "../../../components/InsertImageDialog";
12
+ import { RESET_BUTTON } from "../../../../../utils/reset";
12
13
  export function FormSelection(props) {
13
14
  var _a;
14
15
  const { index, control, rules, onDelete } = props;
@@ -60,7 +61,7 @@ export function FormSelection(props) {
60
61
  : "이미지 삽입하기",
61
62
  } }), _jsxs(Answer, Object.assign({ onClick: () => {
62
63
  onChange(Object.assign(Object.assign({}, value), { isAnswer: !value.isAnswer }));
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
+ } }, { children: ["\uC815\uB2F5", _jsx(Switch, { checked: Boolean(value.isAnswer), size: "small", inputProps: { tabIndex: -1 } })] })), onDelete && (_jsx(SquareButton, { color: "white", size: "xsmall", icon: _jsx(DeleteBinLineIcon, {}), onClick: onDelete, buttonProps: {
64
65
  "aria-label": "삭제",
65
66
  } }))] }))] }));
66
67
  }
@@ -89,7 +90,8 @@ const Index = styled.div(({ theme }) => css `
89
90
  font-weight: 800;
90
91
  line-height: 16px;
91
92
  `);
92
- const Answer = styled.div(({ theme }) => css `
93
+ const Answer = styled.button(({ theme }) => css `
94
+ ${RESET_BUTTON}
93
95
  display: flex;
94
96
  align-items: center;
95
97
  padding-right: 4px;
@@ -1,3 +1,4 @@
1
+ /** @jsxImportSource @emotion/react */
1
2
  import { Dispatch } from "react";
2
3
  import { LexicalEditor } from "lexical";
3
4
  export interface FloatingLinkEditorProps {
@@ -1,5 +1,6 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { useCallback, useEffect, useRef, useState } from "react";
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "@emotion/react/jsx-runtime";
2
+ /** @jsxImportSource @emotion/react */
3
+ import { useCallback, useEffect, useId, useRef, useState, } from "react";
3
4
  import { sanitizeUrl } from "../../utils/url";
4
5
  import { $getSelection, $isRangeSelection, COMMAND_PRIORITY_HIGH, COMMAND_PRIORITY_LOW, KEY_ESCAPE_COMMAND, SELECTION_CHANGE_COMMAND, } from "lexical";
5
6
  import { getSelectedNode } from "../../utils/getSelectedNode";
@@ -9,6 +10,7 @@ import { $findMatchingParent, mergeRegister } from "@lexical/utils";
9
10
  import styled from "@emotion/styled";
10
11
  import { CloseFillIcon, CheckLineIcon, EditLineIcon, DeleteBinLineIcon, } from "../../../../icons";
11
12
  import { Input } from "../../../../components/Input";
13
+ import { VISUALLY_HIDDEN } from "../../../../utils/visuallyHidden";
12
14
  export function FloatingLinkEditor(props) {
13
15
  const { editor, isLink, setIsLink, anchorElem, isLinkEditMode, setIsLinkEditMode, } = props;
14
16
  const editorRef = useRef(null);
@@ -16,6 +18,7 @@ export function FloatingLinkEditor(props) {
16
18
  const [linkUrl, setLinkUrl] = useState("");
17
19
  const [editedLinkUrl, setEditedLinkUrl] = useState("https://");
18
20
  const [lastSelection, setLastSelection] = useState(null);
21
+ const newWindowInfoId = `new-window-info-${useId()}`;
19
22
  const $updateLinkEditor = useCallback(() => {
20
23
  var _a, _b;
21
24
  const selection = $getSelection();
@@ -151,7 +154,7 @@ export function FloatingLinkEditor(props) {
151
154
  } }, { children: _jsx(CloseFillIcon, {}) })), _jsx(Button, Object.assign({ tabIndex: 0, onClick: (event) => {
152
155
  event.preventDefault();
153
156
  handleLinkSubmission();
154
- } }, { children: _jsx(CheckLineIcon, {}) }))] })] })) : (_jsxs(_Fragment, { children: [_jsx(Link, Object.assign({ href: sanitizeUrl(linkUrl), target: "_blank", rel: "noopener noreferrer" }, { children: linkUrl })), _jsxs(Buttons, { children: [_jsx(Button, Object.assign({ tabIndex: 0, onClick: (event) => {
157
+ } }, { children: _jsx(CheckLineIcon, {}) }))] })] })) : (_jsxs(_Fragment, { children: [_jsx(Link, Object.assign({ href: sanitizeUrl(linkUrl), target: "_blank", rel: "noopener noreferrer", "aria-labelledby": newWindowInfoId }, { children: linkUrl })), _jsx("div", Object.assign({ id: newWindowInfoId, css: VISUALLY_HIDDEN }, { children: "\uC0C8 \uCC3D\uC5D0\uC11C \uC5F4\uB9BC" })), _jsxs(Buttons, { children: [_jsx(Button, Object.assign({ tabIndex: 0, onClick: (event) => {
155
158
  event.preventDefault();
156
159
  setEditedLinkUrl(linkUrl);
157
160
  setIsLinkEditMode(true);
@@ -30,10 +30,21 @@ export const SegmentedControlButton = React.forwardRef(function SegmentedControl
30
30
  const isActive = context.multiSelect
31
31
  ? context.value.includes(props.value)
32
32
  : context.value === props.value;
33
- const { label } = other;
34
- return (_jsx(StyledButton, Object.assign({}, other, { ref: ref, startIcon: typeof startIcon === "function" ? startIcon(isActive) : startIcon, endIcon: typeof endIcon === "function" ? endIcon(isActive) : endIcon, isActive: isActive, color: isActive ? "white" : "textNeutral", size: context.size, onClick: handleClick, disabled: context.disabled || props.disabled, title: isActive
35
- ? (typeof label === "string" ? `${label} 선택됨` : "선택됨")
36
- : undefined })));
33
+ // 화살표 키(좌, 우)로 인접 버튼으로 포커스 이동하는 로직
34
+ const handleKeyDown = (e) => {
35
+ let sibling = null;
36
+ if (e.key === "ArrowRight") {
37
+ sibling = e.currentTarget.nextElementSibling;
38
+ }
39
+ else if (e.key === "ArrowLeft") {
40
+ sibling = e.currentTarget.previousElementSibling;
41
+ }
42
+ if (sibling instanceof HTMLButtonElement) {
43
+ e.preventDefault();
44
+ sibling.focus();
45
+ }
46
+ };
47
+ return (_jsx(StyledButton, Object.assign({}, other, { ref: ref, startIcon: typeof startIcon === "function" ? startIcon(isActive) : startIcon, endIcon: typeof endIcon === "function" ? endIcon(isActive) : endIcon, isActive: isActive, color: isActive ? "white" : "textNeutral", size: context.size, onClick: handleClick, onKeyDown: handleKeyDown, disabled: context.disabled || props.disabled, "aria-selected": isActive, role: "tab", tabIndex: isActive ? 0 : -1 })));
37
48
  });
38
49
  const StyledButton = styled(Button, {
39
50
  shouldForwardProp: (prop) => prop !== "isActive",
@@ -29,7 +29,7 @@ export const SegmentedControlGroup = React.forwardRef(function SegmentedControlG
29
29
  background-color: ${theme.color.background.neutralAlt};
30
30
  border-radius: 8px;
31
31
  border: 1px solid ${theme.color.background.neutralAltActive};
32
- ` }, { children: _jsx(Context.Provider, Object.assign({ value: Object.assign(Object.assign({}, props), { onClick: (newValue) => {
32
+ `, role: "tablist", "aria-orientation": "horizontal" }, { children: _jsx(Context.Provider, Object.assign({ value: Object.assign(Object.assign({}, props), { onClick: (newValue) => {
33
33
  var _a, _b, _c;
34
34
  if (multiSelect) {
35
35
  if (props.value.includes(newValue)) {
@@ -20,7 +20,7 @@ import { SegmentedControlGroupPropsContext, } from "./SegmentedControlGroupProps
20
20
  * [피그마](https://www.figma.com/file/PnQp3tPxiCjgsPZfLUaUL1/Codle-PD-Kit---Patterns?node-id=181%3A89883)
21
21
  */
22
22
  export const SegmentedControlSquareButton = React.forwardRef(function SegmentedControlSquareButton(props, ref) {
23
- const { onClick, icon } = props, other = __rest(props, ["onClick", "icon"]);
23
+ const { onClick, icon, buttonProps } = props, other = __rest(props, ["onClick", "icon", "buttonProps"]);
24
24
  const context = useContext(SegmentedControlGroupPropsContext);
25
25
  const handleClick = (e) => {
26
26
  var _a;
@@ -30,7 +30,25 @@ export const SegmentedControlSquareButton = React.forwardRef(function SegmentedC
30
30
  const isActive = context.multiSelect
31
31
  ? context.value.includes(props.value)
32
32
  : context.value === props.value;
33
- return (_jsx(StyledSquareButton, Object.assign({}, other, { ref: ref, isActive: isActive, icon: typeof icon === "function" ? icon(isActive) : icon, color: isActive ? "white" : "icon", size: context.size, fullWidth: context.fullWidth, onClick: handleClick, disabled: context.disabled || props.disabled })));
33
+ // 화살표 (좌, ) 인접 버튼으로 포커스 이동하는 로직
34
+ const handleKeyDown = (e) => {
35
+ var _a, _b, _c, _d;
36
+ let siblingButton = null;
37
+ if (e.key === "ArrowRight") {
38
+ // sibling 요소의 첫 번째 자식인 버튼에 포커스 이동 처리
39
+ siblingButton =
40
+ (_b = (_a = e.currentTarget.nextElementSibling) === null || _a === void 0 ? void 0 : _a.firstElementChild) !== null && _b !== void 0 ? _b : null;
41
+ }
42
+ else if (e.key === "ArrowLeft") {
43
+ siblingButton =
44
+ (_d = (_c = e.currentTarget.previousElementSibling) === null || _c === void 0 ? void 0 : _c.firstElementChild) !== null && _d !== void 0 ? _d : null;
45
+ }
46
+ if (siblingButton instanceof HTMLButtonElement) {
47
+ e.preventDefault();
48
+ siblingButton.focus();
49
+ }
50
+ };
51
+ return (_jsx(StyledSquareButton, Object.assign({}, other, { ref: ref, isActive: isActive, icon: typeof icon === "function" ? icon(isActive) : icon, color: isActive ? "white" : "icon", size: context.size, fullWidth: context.fullWidth, onClick: handleClick, onKeyDown: handleKeyDown, disabled: context.disabled || props.disabled, buttonProps: Object.assign(Object.assign({}, buttonProps), { "aria-selected": isActive, role: "tab", tabIndex: isActive ? 0 : -1 }) })));
34
52
  });
35
53
  const StyledSquareButton = styled(SquareButton, {
36
54
  shouldForwardProp: (prop) => prop !== "isActive",
@@ -0,0 +1 @@
1
+ export declare const VISUALLY_HIDDEN: import("@emotion/utils").SerializedStyles;
@@ -0,0 +1,12 @@
1
+ import { css } from "@emotion/react";
2
+ export const VISUALLY_HIDDEN = css `
3
+ position: absolute;
4
+ width: 1px;
5
+ height: 1px;
6
+ margin: -1px;
7
+ padding: 0;
8
+ border: 0;
9
+ overflow: hidden;
10
+ clip: rect(0, 0, 0, 0);
11
+ white-space: nowrap; /* 텍스트가 줄 바뀜 없이 한 줄로 유지되도록 */
12
+ `;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@team-monolith/cds",
3
- "version": "1.100.2",
3
+ "version": "1.100.4",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "sideEffects": false,