UNPKG

@jk-core/components

Version:
1 lines 168 kB
{"version":3,"file":"index.umd.cjs","sources":["../../../../../.yarn/berry/cache/react-npm-19.1.0-9804a7da5b-10c0.zip/node_modules/react/cjs/react-jsx-runtime.production.js","../../../../../.yarn/berry/cache/react-npm-19.1.0-9804a7da5b-10c0.zip/node_modules/react/cjs/react-jsx-runtime.development.js","../../../../../.yarn/berry/cache/react-npm-19.1.0-9804a7da5b-10c0.zip/node_modules/react/jsx-runtime.js","../src/common/Breadcrumbs/home.svg","../src/common/Breadcrumbs/index.tsx","../../utils/dist/index.js","../src/common/Button/index.tsx","../src/common/Pagination/arrow-left.svg","../src/common/Pagination/arrow-right.svg","../src/common/Pagination/index.tsx","../src/common/Skeleton/index.tsx","../src/common/SwitchButton/index.tsx","../src/common/Table/index.tsx","../src/assets/close.svg","../src/assets/arrow.svg","../src/assets/drop-arrow.svg","../src/Calendar/components/DateLabel/index.tsx","../src/Calendar/utils/isInRange.ts","../src/Calendar/utils/isSameDay.ts","../src/Calendar/components/DayTile/index.tsx","../src/Calendar/hooks/useCalendarNav.ts","../src/Calendar/utils/getWeeksInMonth.ts","../src/Calendar/RangeCalendar.tsx","../../hooks/dist/index.js","../src/Calendar/ScrollCalendar.tsx","../src/Calendar/components/MonthTile/index.tsx","../src/Calendar/components/ViewSelector/index.tsx","../src/Calendar/components/YearTile/index.tsx","../src/Calendar/hooks/useDateSelect.ts","../src/Calendar/SingleCalendar.tsx","../src/Calendar/index.tsx","../src/common/Accordion/arrow-down.svg","../src/common/Accordion/index.tsx","../src/common/Card/index.tsx","../../../.yarn/__virtual__/react-dom-virtual-473078bcc6/3/.yarn/berry/cache/react-dom-npm-19.1.0-773f826e46-10c0.zip/node_modules/react-dom/cjs/react-dom.production.js","../../../.yarn/__virtual__/react-dom-virtual-473078bcc6/3/.yarn/berry/cache/react-dom-npm-19.1.0-773f826e46-10c0.zip/node_modules/react-dom/cjs/react-dom.development.js","../../../.yarn/__virtual__/react-dom-virtual-473078bcc6/3/.yarn/berry/cache/react-dom-npm-19.1.0-773f826e46-10c0.zip/node_modules/react-dom/index.js","../src/common/DropDown/arrow-down.svg","../src/common/DropDown/search.svg","../src/common/DropDown/List.tsx","../src/common/DropDown/index.tsx","../src/common/SegmentButton/index.tsx"],"sourcesContent":["/**\n * @license React\n * react-jsx-runtime.production.js\n *\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n\"use strict\";\nvar REACT_ELEMENT_TYPE = Symbol.for(\"react.transitional.element\"),\n REACT_FRAGMENT_TYPE = Symbol.for(\"react.fragment\");\nfunction jsxProd(type, config, maybeKey) {\n var key = null;\n void 0 !== maybeKey && (key = \"\" + maybeKey);\n void 0 !== config.key && (key = \"\" + config.key);\n if (\"key\" in config) {\n maybeKey = {};\n for (var propName in config)\n \"key\" !== propName && (maybeKey[propName] = config[propName]);\n } else maybeKey = config;\n config = maybeKey.ref;\n return {\n $$typeof: REACT_ELEMENT_TYPE,\n type: type,\n key: key,\n ref: void 0 !== config ? config : null,\n props: maybeKey\n };\n}\nexports.Fragment = REACT_FRAGMENT_TYPE;\nexports.jsx = jsxProd;\nexports.jsxs = jsxProd;\n","/**\n * @license React\n * react-jsx-runtime.development.js\n *\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n\"use strict\";\n\"production\" !== process.env.NODE_ENV &&\n (function () {\n function getComponentNameFromType(type) {\n if (null == type) return null;\n if (\"function\" === typeof type)\n return type.$$typeof === REACT_CLIENT_REFERENCE\n ? null\n : type.displayName || type.name || null;\n if (\"string\" === typeof type) return type;\n switch (type) {\n case REACT_FRAGMENT_TYPE:\n return \"Fragment\";\n case REACT_PROFILER_TYPE:\n return \"Profiler\";\n case REACT_STRICT_MODE_TYPE:\n return \"StrictMode\";\n case REACT_SUSPENSE_TYPE:\n return \"Suspense\";\n case REACT_SUSPENSE_LIST_TYPE:\n return \"SuspenseList\";\n case REACT_ACTIVITY_TYPE:\n return \"Activity\";\n }\n if (\"object\" === typeof type)\n switch (\n (\"number\" === typeof type.tag &&\n console.error(\n \"Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue.\"\n ),\n type.$$typeof)\n ) {\n case REACT_PORTAL_TYPE:\n return \"Portal\";\n case REACT_CONTEXT_TYPE:\n return (type.displayName || \"Context\") + \".Provider\";\n case REACT_CONSUMER_TYPE:\n return (type._context.displayName || \"Context\") + \".Consumer\";\n case REACT_FORWARD_REF_TYPE:\n var innerType = type.render;\n type = type.displayName;\n type ||\n ((type = innerType.displayName || innerType.name || \"\"),\n (type = \"\" !== type ? \"ForwardRef(\" + type + \")\" : \"ForwardRef\"));\n return type;\n case REACT_MEMO_TYPE:\n return (\n (innerType = type.displayName || null),\n null !== innerType\n ? innerType\n : getComponentNameFromType(type.type) || \"Memo\"\n );\n case REACT_LAZY_TYPE:\n innerType = type._payload;\n type = type._init;\n try {\n return getComponentNameFromType(type(innerType));\n } catch (x) {}\n }\n return null;\n }\n function testStringCoercion(value) {\n return \"\" + value;\n }\n function checkKeyStringCoercion(value) {\n try {\n testStringCoercion(value);\n var JSCompiler_inline_result = !1;\n } catch (e) {\n JSCompiler_inline_result = !0;\n }\n if (JSCompiler_inline_result) {\n JSCompiler_inline_result = console;\n var JSCompiler_temp_const = JSCompiler_inline_result.error;\n var JSCompiler_inline_result$jscomp$0 =\n (\"function\" === typeof Symbol &&\n Symbol.toStringTag &&\n value[Symbol.toStringTag]) ||\n value.constructor.name ||\n \"Object\";\n JSCompiler_temp_const.call(\n JSCompiler_inline_result,\n \"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.\",\n JSCompiler_inline_result$jscomp$0\n );\n return testStringCoercion(value);\n }\n }\n function getTaskName(type) {\n if (type === REACT_FRAGMENT_TYPE) return \"<>\";\n if (\n \"object\" === typeof type &&\n null !== type &&\n type.$$typeof === REACT_LAZY_TYPE\n )\n return \"<...>\";\n try {\n var name = getComponentNameFromType(type);\n return name ? \"<\" + name + \">\" : \"<...>\";\n } catch (x) {\n return \"<...>\";\n }\n }\n function getOwner() {\n var dispatcher = ReactSharedInternals.A;\n return null === dispatcher ? null : dispatcher.getOwner();\n }\n function UnknownOwner() {\n return Error(\"react-stack-top-frame\");\n }\n function hasValidKey(config) {\n if (hasOwnProperty.call(config, \"key\")) {\n var getter = Object.getOwnPropertyDescriptor(config, \"key\").get;\n if (getter && getter.isReactWarning) return !1;\n }\n return void 0 !== config.key;\n }\n function defineKeyPropWarningGetter(props, displayName) {\n function warnAboutAccessingKey() {\n specialPropKeyWarningShown ||\n ((specialPropKeyWarningShown = !0),\n console.error(\n \"%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)\",\n displayName\n ));\n }\n warnAboutAccessingKey.isReactWarning = !0;\n Object.defineProperty(props, \"key\", {\n get: warnAboutAccessingKey,\n configurable: !0\n });\n }\n function elementRefGetterWithDeprecationWarning() {\n var componentName = getComponentNameFromType(this.type);\n didWarnAboutElementRef[componentName] ||\n ((didWarnAboutElementRef[componentName] = !0),\n console.error(\n \"Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release.\"\n ));\n componentName = this.props.ref;\n return void 0 !== componentName ? componentName : null;\n }\n function ReactElement(\n type,\n key,\n self,\n source,\n owner,\n props,\n debugStack,\n debugTask\n ) {\n self = props.ref;\n type = {\n $$typeof: REACT_ELEMENT_TYPE,\n type: type,\n key: key,\n props: props,\n _owner: owner\n };\n null !== (void 0 !== self ? self : null)\n ? Object.defineProperty(type, \"ref\", {\n enumerable: !1,\n get: elementRefGetterWithDeprecationWarning\n })\n : Object.defineProperty(type, \"ref\", { enumerable: !1, value: null });\n type._store = {};\n Object.defineProperty(type._store, \"validated\", {\n configurable: !1,\n enumerable: !1,\n writable: !0,\n value: 0\n });\n Object.defineProperty(type, \"_debugInfo\", {\n configurable: !1,\n enumerable: !1,\n writable: !0,\n value: null\n });\n Object.defineProperty(type, \"_debugStack\", {\n configurable: !1,\n enumerable: !1,\n writable: !0,\n value: debugStack\n });\n Object.defineProperty(type, \"_debugTask\", {\n configurable: !1,\n enumerable: !1,\n writable: !0,\n value: debugTask\n });\n Object.freeze && (Object.freeze(type.props), Object.freeze(type));\n return type;\n }\n function jsxDEVImpl(\n type,\n config,\n maybeKey,\n isStaticChildren,\n source,\n self,\n debugStack,\n debugTask\n ) {\n var children = config.children;\n if (void 0 !== children)\n if (isStaticChildren)\n if (isArrayImpl(children)) {\n for (\n isStaticChildren = 0;\n isStaticChildren < children.length;\n isStaticChildren++\n )\n validateChildKeys(children[isStaticChildren]);\n Object.freeze && Object.freeze(children);\n } else\n console.error(\n \"React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead.\"\n );\n else validateChildKeys(children);\n if (hasOwnProperty.call(config, \"key\")) {\n children = getComponentNameFromType(type);\n var keys = Object.keys(config).filter(function (k) {\n return \"key\" !== k;\n });\n isStaticChildren =\n 0 < keys.length\n ? \"{key: someKey, \" + keys.join(\": ..., \") + \": ...}\"\n : \"{key: someKey}\";\n didWarnAboutKeySpread[children + isStaticChildren] ||\n ((keys =\n 0 < keys.length ? \"{\" + keys.join(\": ..., \") + \": ...}\" : \"{}\"),\n console.error(\n 'A props object containing a \"key\" prop is being spread into JSX:\\n let props = %s;\\n <%s {...props} />\\nReact keys must be passed directly to JSX without using spread:\\n let props = %s;\\n <%s key={someKey} {...props} />',\n isStaticChildren,\n children,\n keys,\n children\n ),\n (didWarnAboutKeySpread[children + isStaticChildren] = !0));\n }\n children = null;\n void 0 !== maybeKey &&\n (checkKeyStringCoercion(maybeKey), (children = \"\" + maybeKey));\n hasValidKey(config) &&\n (checkKeyStringCoercion(config.key), (children = \"\" + config.key));\n if (\"key\" in config) {\n maybeKey = {};\n for (var propName in config)\n \"key\" !== propName && (maybeKey[propName] = config[propName]);\n } else maybeKey = config;\n children &&\n defineKeyPropWarningGetter(\n maybeKey,\n \"function\" === typeof type\n ? type.displayName || type.name || \"Unknown\"\n : type\n );\n return ReactElement(\n type,\n children,\n self,\n source,\n getOwner(),\n maybeKey,\n debugStack,\n debugTask\n );\n }\n function validateChildKeys(node) {\n \"object\" === typeof node &&\n null !== node &&\n node.$$typeof === REACT_ELEMENT_TYPE &&\n node._store &&\n (node._store.validated = 1);\n }\n var React = require(\"react\"),\n REACT_ELEMENT_TYPE = Symbol.for(\"react.transitional.element\"),\n REACT_PORTAL_TYPE = Symbol.for(\"react.portal\"),\n REACT_FRAGMENT_TYPE = Symbol.for(\"react.fragment\"),\n REACT_STRICT_MODE_TYPE = Symbol.for(\"react.strict_mode\"),\n REACT_PROFILER_TYPE = Symbol.for(\"react.profiler\");\n Symbol.for(\"react.provider\");\n var REACT_CONSUMER_TYPE = Symbol.for(\"react.consumer\"),\n REACT_CONTEXT_TYPE = Symbol.for(\"react.context\"),\n REACT_FORWARD_REF_TYPE = Symbol.for(\"react.forward_ref\"),\n REACT_SUSPENSE_TYPE = Symbol.for(\"react.suspense\"),\n REACT_SUSPENSE_LIST_TYPE = Symbol.for(\"react.suspense_list\"),\n REACT_MEMO_TYPE = Symbol.for(\"react.memo\"),\n REACT_LAZY_TYPE = Symbol.for(\"react.lazy\"),\n REACT_ACTIVITY_TYPE = Symbol.for(\"react.activity\"),\n REACT_CLIENT_REFERENCE = Symbol.for(\"react.client.reference\"),\n ReactSharedInternals =\n React.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,\n hasOwnProperty = Object.prototype.hasOwnProperty,\n isArrayImpl = Array.isArray,\n createTask = console.createTask\n ? console.createTask\n : function () {\n return null;\n };\n React = {\n \"react-stack-bottom-frame\": function (callStackForError) {\n return callStackForError();\n }\n };\n var specialPropKeyWarningShown;\n var didWarnAboutElementRef = {};\n var unknownOwnerDebugStack = React[\"react-stack-bottom-frame\"].bind(\n React,\n UnknownOwner\n )();\n var unknownOwnerDebugTask = createTask(getTaskName(UnknownOwner));\n var didWarnAboutKeySpread = {};\n exports.Fragment = REACT_FRAGMENT_TYPE;\n exports.jsx = function (type, config, maybeKey, source, self) {\n var trackActualOwner =\n 1e4 > ReactSharedInternals.recentlyCreatedOwnerStacks++;\n return jsxDEVImpl(\n type,\n config,\n maybeKey,\n !1,\n source,\n self,\n trackActualOwner\n ? Error(\"react-stack-top-frame\")\n : unknownOwnerDebugStack,\n trackActualOwner ? createTask(getTaskName(type)) : unknownOwnerDebugTask\n );\n };\n exports.jsxs = function (type, config, maybeKey, source, self) {\n var trackActualOwner =\n 1e4 > ReactSharedInternals.recentlyCreatedOwnerStacks++;\n return jsxDEVImpl(\n type,\n config,\n maybeKey,\n !0,\n source,\n self,\n trackActualOwner\n ? Error(\"react-stack-top-frame\")\n : unknownOwnerDebugStack,\n trackActualOwner ? createTask(getTaskName(type)) : unknownOwnerDebugTask\n );\n };\n })();\n","'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n module.exports = require('./cjs/react-jsx-runtime.production.js');\n} else {\n module.exports = require('./cjs/react-jsx-runtime.development.js');\n}\n","import * as React from \"react\";\nconst SvgHome = (props) => /* @__PURE__ */ React.createElement(\"svg\", { width: 18, height: 16, viewBox: \"0 0 18 16\", fill: \"none\", xmlns: \"http://www.w3.org/2000/svg\", stroke: \"black\", ...props }, /* @__PURE__ */ React.createElement(\"path\", { d: \"M4 5.5V14.5H14V5.5\", strokeWidth: 1.2 }), /* @__PURE__ */ React.createElement(\"path\", { d: \"M6.5 12H11.5\", strokeWidth: 1.2 }), /* @__PURE__ */ React.createElement(\"path\", { d: \"M1 8L9 1L17 8\", strokeWidth: 1.2 }));\nexport default SvgHome;\n","import { Fragment } from 'react/jsx-runtime';\nimport styles from './Breadcrumbs.module.scss';\nimport HomeIcon from './home.svg';\n\ninterface BreadcumbsProps {\n /**\n * 자식 요소로 BreadcrumbsItem 컴포넌트를 받습니다.\n * 각 BreadcrumbsItem은 경로를 나타내며, 클릭 시 해당 경로로 이동합니다.\n */\n children: React.ReactNode;\n}\n\n/**\n * Breadcrumbs 컴포넌트\n * 여러 개의 ```<BreadcrumbsItem />```을 자식으로 받아 경로를 표시합니다.\n * 각 ```BreadcrumbsItem```은 경로를 나타내며, 클릭 시 해당 경로로 이동합니다.\n */\nexport default function Breadcrumbs({ children }: BreadcumbsProps) {\n return (\n <div className={styles.breadcrumbs}>\n {Array.isArray(children)\n ? children.map((child, idx) => (\n <Fragment key={idx}>\n {idx > 0 && (\n <div className={styles.separator}>\n {'>'}\n </div>\n )}\n {child}\n </Fragment>\n ))\n : children}\n </div>\n );\n}\n\ninterface BreadcrumbsItemProps {\n /**\n * BreadcrumbsItem의 자식 요소로 표시될 텍스트입니다.\n * 경로를 나타내며, 클릭 시 해당 경로로 이동합니다.\n */\n children?: React.ReactNode;\n /**\n * BreadcrumbsItem이 클릭되었을 때 이동할 경로입니다.\n * 기본값은 '/'로 설정되어 있습니다.\n *\n */\n path: string;\n /**\n * BreadcrumbsItem이 홈 아이콘을 표시할지 여부입니다.\n * 기본값은 false로 설정되어 있습니다.\n * true로 설정하면 홈 아이콘이 표시됩니다.\n */\n root?: boolean;\n}\n\n/**\n * BreadcrumbsItem 컴포넌트\n * Breadcrumbs 컴포넌트의 자식으로 사용되며, 경로를 나타냅니다.\n * 클릭 시 해당 경로로 이동합니다.\n * 기본적으로 홈 아이콘과 함께 표시됩니다.\n */\nexport function BreadcrumbsItem({ children, path, root }: BreadcrumbsItemProps) {\n return (\n <button\n className={styles.item}\n type=\"button\"\n onClick={() => {\n window.location.assign(path);\n }}\n >\n {root\n ? (\n <>\n <HomeIcon className={styles.icon} />\n {children}\n </>\n )\n : children}\n </button>\n );\n}","const u = () => {\n const { userAgent: t } = navigator;\n return t.match(/Android/i) || t.match(/iPhone|iPad|iPod/i) ? !0 : !(t.match(/Windows/i) || t.match(/Macintosh/i));\n};\nfunction s(t) {\n return Object.entries(t).filter(([, r]) => r).map(([r]) => r).join(\" \");\n}\nconst c = (t = 0) => {\n const r = t ?? 0, i = Math.trunc(r) || 0, e = Math.floor((r - i) * 60) || 0;\n return {\n fullTime: `${i !== 0 ? `${i}시간` : \"\"}${e !== 0 ? ` ${e}분` : \"\"}` || \"0분\",\n hour: i,\n minute: e\n };\n}, a = (t) => t != null, o = (t, r = 2) => {\n if (t == null || Number.isNaN(Number(t)))\n return 0;\n const i = `${t}`;\n if (!i.includes(\"e\"))\n return +`${Math.round(parseFloat(`${t}e+${r}`))}e-${r}`;\n const e = i.split(\"e\");\n let n = \"\";\n return +e[1] + r > 0 && (n = \"+\"), +`${Math.round(parseFloat(`${+e[0]}e${n}${+e[1] + r}`))}e-${r}`;\n}, d = (t, r = 2) => t == null || Number.isNaN(t) ? \"-\" : o(t, r);\nexport {\n u as checkIsMobile,\n s as cn,\n d as displayRoundNum,\n c as formatTime,\n a as isDefined,\n o as roundNum\n};\n//# sourceMappingURL=index.js.map\n","import { ReactNode } from 'react';\nimport { cn } from '@jk-core/utils';\nimport styles from './Button.module.scss';\n\ninterface Props extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n /** 버튼 내용 */\n children: ReactNode;\n /** 버튼 등급 (Primary, Secondary, Tertiary, Cancel) */\n grade?: 'tertiary' | 'secondary' | 'primary' | 'cancel';\n /** 버튼 비활성화 여부 */\n disabled?: boolean;\n /** 버튼 클래스 */\n className?: string;\n /** 로딩 중 여부, 버튼 내부 스피너 표시 */\n isLoading?: boolean;\n /** 버튼 클릭 이벤트 핸들러 */\n onClick?: (e: React.MouseEvent<HTMLButtonElement>) => void;\n}\n\n/**\n * 공용 버튼 컴포넌트입니다.\n *\n * 다양한 등급(grade)과 상태(로딩, 비활성화 등)를 지원하며, 텍스트와 클릭 이벤트를 전달할 수 있습니다.\n *\n * - `grade` prop을 통해 버튼의 스타일(Primary, Secondary, Tertiary, Cancel)을 지정할 수 있습니다.\n * - `isLoading`이 true일 때 로딩 애니메이션이 표시됩니다.\n * - `disabled`가 true이면 버튼이 비활성화됩니다.\n * - `text` prop으로 버튼에 표시할 텍스트를 지정합니다.\n * - 추가적으로 button의 모든 기본 속성(React.)을 지원합니다.\n */\nexport default function Button({\n children, grade = 'primary', disabled = false, onClick, className = '', isLoading = false, ...props\n}: Props) {\n return (\n <button\n className={cn({\n [styles.button]: true,\n [styles.button__loading]: isLoading,\n [styles.button__disabled]: !!disabled,\n [styles.button__tertiary]: grade === 'tertiary',\n [styles.button__secondary]: grade === 'secondary',\n [styles.button__primary]: grade === 'primary',\n [styles.button__cancel]: grade === 'cancel',\n [className]: !!className,\n })}\n type=\"button\"\n disabled={disabled}\n onClick={onClick}\n {...props}\n >\n {children}\n {isLoading && (\n <div className={styles['loading-dot']}>\n <div />\n <div />\n <div />\n </div>\n )}\n </button>\n );\n}","import * as React from \"react\";\nconst SvgArrowLeft = (props) => /* @__PURE__ */ React.createElement(\"svg\", { width: \"30px\", height: \"30px\", viewBox: \"0 0 24 24\", fill: \"#000000\", xmlns: \"http://www.w3.org/2000/svg\", ...props }, /* @__PURE__ */ React.createElement(\"g\", { id: \"SVGRepo_bgCarrier\", strokeWidth: 0 }), /* @__PURE__ */ React.createElement(\"g\", { id: \"SVGRepo_tracerCarrier\", strokeLinecap: \"round\", strokeLinejoin: \"round\" }), /* @__PURE__ */ React.createElement(\"g\", { id: \"SVGRepo_iconCarrier\" }, /* @__PURE__ */ React.createElement(\"path\", { d: \"M16.1795 3.26875C15.7889 2.87823 15.1558 2.87823 14.7652 3.26875L8.12078 9.91322C6.94952 11.0845 6.94916 12.9833 8.11996 14.155L14.6903 20.7304C15.0808 21.121 15.714 21.121 16.1045 20.7304C16.495 20.3399 16.495 19.7067 16.1045 19.3162L9.53246 12.7442C9.14194 12.3536 9.14194 11.7205 9.53246 11.33L16.1795 4.68297C16.57 4.29244 16.57 3.65928 16.1795 3.26875Z\" })));\nexport default SvgArrowLeft;\n","import * as React from \"react\";\nconst SvgArrowRight = (props) => /* @__PURE__ */ React.createElement(\"svg\", { width: \"30px\", height: \"30px\", viewBox: \"0 0 24 24\", fill: \"#000000\", xmlns: \"http://www.w3.org/2000/svg\", ...props }, /* @__PURE__ */ React.createElement(\"g\", { id: \"SVGRepo_bgCarrier\" }), /* @__PURE__ */ React.createElement(\"g\", { id: \"SVGRepo_tracerCarrier\", strokeLinecap: \"round\", strokeLinejoin: \"round\" }), /* @__PURE__ */ React.createElement(\"g\", { id: \"SVGRepo_iconCarrier\" }, /* @__PURE__ */ React.createElement(\"path\", { d: \"M7.82054 20.7313C8.21107 21.1218 8.84423 21.1218 9.23476 20.7313L15.8792 14.0868C17.0505 12.9155 17.0508 11.0167 15.88 9.84497L9.3097 3.26958C8.91918 2.87905 8.28601 2.87905 7.89549 3.26958C7.50497 3.6601 7.50497 4.29327 7.89549 4.68379L14.4675 11.2558C14.8581 11.6464 14.8581 12.2795 14.4675 12.67L7.82054 19.317C7.43002 19.7076 7.43002 20.3407 7.82054 20.7313Z\" })));\nexport default SvgArrowRight;\n","\nimport { useMemo, useState } from 'react';\nimport LeftArrowIcon from './arrow-left.svg';\nimport RightArrowIcon from './arrow-right.svg';\nimport styles from './Pagination.module.scss';\n\ninterface PaginationProps {\n /**\n * 총 페이지 수\n */\n totalPage: number;\n /**\n * 현재 페이지\n */\n currentPage: number;\n\n /**\n * 페이지 크기 (기본값: false)\n * true로 설정하면 보여지는 페이지의 개수가 5개에서 7개로 늘어납니다.\n */\n large?: boolean;\n /**\n * 페이지 클릭 핸들러\n */\n onPageClick: (page: number) => void;\n}\n\nexport default function Pagination({ totalPage, currentPage, onPageClick, large = false }: PaginationProps) {\n const [animation, setAnimation] = useState<'left' | 'right' | 'doubleRight' | 'doubleLeft' | 'tripleRight' | 'tripleLeft' | ''>('');\n const [selectedPage, setSelectedPage] = useState(currentPage || 1);\n const weight = useMemo(() => (large ? 2 : 0), [large]);\n\n const pageArray = useMemo(() => {\n if (!totalPage) return Array.from({ length: 9 + weight }).map((_, i) => (i === 2 ? 1 : null));\n\n return Array.from({ length: 9 + weight }).map((_, i) => {\n const pageIndex = selectedPage + i - 2 - (weight / 2) ;\n\n if (pageIndex < 1 || pageIndex > totalPage) {\n return null;\n }\n return pageIndex;\n });\n }, [selectedPage, totalPage, weight]);\n\n const handlePageClick = (page: number) => {\n if (page > totalPage || page < 1) return;\n onPageClick(page);\n if (page === null) return;\n const diff = page - selectedPage;\n\n switch (diff) {\n case 1:\n setAnimation('right');\n break;\n case -1:\n setAnimation('left');\n break;\n case 2:\n setAnimation('doubleRight');\n break;\n case -2:\n setAnimation('doubleLeft');\n break;\n case 3:\n setAnimation('tripleRight');\n break;\n case -3:\n setAnimation('tripleLeft');\n break;\n default:\n setAnimation('');\n }\n\n setSelectedPage(page);\n\n setTimeout(() => {\n setAnimation('');\n }, 200);\n };\n\n return (\n <div className={styles.pagination}>\n <button\n className={`${styles.arrow} ${selectedPage <= 1 ? styles['arrow--disabled'] : '' }`}\n type=\"button\"\n onClick={() => handlePageClick(selectedPage - 1)}\n >\n <LeftArrowIcon />\n </button>\n <div\n className={styles.slider}\n style={{ width: `${(8 + weight) * 40}px` }}\n >\n <div\n className={styles.track}\n />\n <div className={styles.portal}>\n {selectedPage > (3 + weight / 2) && (\n < >\n <button\n className={styles.page}\n type=\"button\"\n onClick={() => handlePageClick(1)}\n >1\n </button>\n <span className={styles.portal__ellipsis}>•••</span>\n </>\n )}\n </div>\n <div\n className={styles.pages}\n style={{ width: `${(5 + weight) * 40}px` }}\n >\n <div className={`${styles.pageWrapper} ${animation === 'left' ? styles.left : ''} ${styles[animation]}`}>\n {pageArray.map((page, index) => (\n <button\n className={`${styles.page} ${selectedPage === page ? styles['page--selected'] : ''}`}\n key={index}\n type=\"button\"\n disabled={page === null}\n onClick={() => {\n if (page !== null) {\n handlePageClick(page);\n }\n }}\n >\n <span>{page}</span>\n </button>\n ))}\n </div>\n </div>\n <div className={styles.portal}>\n {selectedPage < totalPage - (2 + weight / 2) && (\n <>\n <span className={styles.portal__ellipsis}>•••</span>\n <button\n className={styles.page}\n type=\"button\"\n onClick={() => handlePageClick(totalPage)}\n >{totalPage}\n </button>\n </>\n )}\n </div>\n </div>\n <button\n className={`${styles.arrow} ${selectedPage >= totalPage ? styles['arrow--disabled'] : ''}`}\n type=\"button\"\n onClick={() => handlePageClick(selectedPage + 1)}\n >\n <RightArrowIcon />\n </button>\n </div>\n );\n}\n","import styles from './Skeleton.module.scss';\n\ninterface SkeletonProps {\n /**\n * 스켈레톤의 모양을 지정합니다. 'circle', 'rectangle', 'round' 중 하나를 선택할 수 있습니다.\n * 기본값은 'rectangle'입니다.\n */\n shape?: 'circle' | 'rectangle' | 'round';\n /**\n * 스켈레톤의 너비를 지정합니다. 기본값은 '100%'입니다.\n * 'auto'로 설정하면 콘텐츠에 맞게 자동으로 조정됩니다.\n */\n width?: string | number;\n /**\n * 스켈레톤의 높이를 지정합니다. 기본값은 '20px'입니다.\n * 'auto'로 설정하면 콘텐츠에 맞게 자동으로 조정됩니다.\n */\n height?: string | number;\n /**\n * 스켈레톤 애니메이션 효과를 지정합니다. 'glow' 또는 'blink' 중 하나를 선택할 수 있습니다.\n * 기본값은 'glow'입니다.\n */\n animation?: 'glow' | 'blink';\n}\n\n/**\n * 스켈레톤 컴포넌트는 로딩 상태를 나타내기 위해 사용됩니다.\n * 다양한 모양과 크기를 지원하며, 애니메이션 효과를 적용할 수 있습니다.\n */\nexport default function Skeleton({ shape, width, height, animation = 'glow' }: SkeletonProps) {\n const animationClass = animation === 'glow' ? styles['skeleton--glow'] : styles['skeleton--blink'];\n\n if (shape === 'circle') {\n return (\n <div className={`${styles['skeleton-circle']} ${animationClass}`} style={{ width, height }} />\n );\n }\n\n if (shape === 'round') {\n return (\n <div className={`${styles['skeleton-round']} ${animationClass}`} style={{ width, height }} />\n );\n }\n\n return (\n <div className={`${styles['skeleton-rectangle']} ${animationClass}`} style={{ width, height }} />\n );\n}","import { useState } from 'react';\nimport { cn } from '@jk-core/utils';\nimport styles from './SwitchButton.module.scss';\n\ninterface SwitchButtonProps {\n /**\n * 스위치 버튼의 상태를 나타냅니다.\n * true이면 스위치가 켜진 상태, false이면 꺼진 상태입니다.\n * 기본값은 false로 설정되어 있습니다.\n */\n checked?: boolean,\n /**\n * 스위치 버튼의 상태가 변경될 때 호출되는 함수입니다.\n */\n onChange?: (value: boolean) => void\n}\n\n/**\n * SwitchButton 컴포넌트\n * 스위치 버튼을 표시하며, 클릭 시 상태가 변경됩니다.\n * checked 속성으로 초기 상태를 설정할 수 있으며, onChange 함수를 통해 상태 변경을 처리할 수 있습니다.\n */\nexport default function SwitchButton({ checked = false, onChange = () => { } }: SwitchButtonProps) {\n const [isChecked, setIsChecked] = useState(checked);\n\n return (\n <button\n className={styles.button}\n type=\"button\"\n onClick={() => {\n setIsChecked(!isChecked);\n onChange(!isChecked);\n }}\n >\n <div\n className={cn({\n [styles.switch]: true,\n [styles.switch__off]: checked,\n })}\n >\n <div className={cn({\n [styles.switch__button]: true,\n [styles['switch__button--off']]: !checked,\n [styles['switch__button--on']]: checked,\n })}\n >\n <div className={cn({\n [styles['switch__button--circle']]: true,\n [styles['switch__button--circle-on']]: checked,\n })}\n />\n </div>\n </div>\n </button>\n );\n}\n","import { cn } from '@jk-core/utils';\nimport styles from './Table.module.scss';\n\ninterface TableLabelType{\n text: string | number;\n align?: 'left' | 'center' | 'right';\n}\ninterface TableHeaderType {\n label: TableLabelType;\n width?: string;\n subWidth?: string[];\n subLabel?:TableLabelType[];\n}\n\ninterface TableBodyType{\n head?: TableLabelType;\n labels: TableLabelType[];\n}\n\ninterface TableProps {\n /**\n * 테이블 헤더 설정\n * - `label`: 헤더의 라벨 텍스트, text와 align 속성을 포함한 객체\n * - `width`: 헤더의 너비, subWidth가 있을 경우 무시됨 (선택적)\n * - `subWidth`: 서브 헤더의 너비 배열 (선택적)\n * - `subLabel`: 서브 헤더의 라벨, text와 align 속성을 포함한 객체 배열 (선택적)\n */\n header: TableHeaderType[];\n /**\n * 테이블 바디 설정\n * - `head`: 바디의 헤더 텍스트, text와 align 속성을 포함한 객체 (선택적)\n * - `labels`: 각 행의 라벨 배열, text와 align 속성을 포함한 객체 배열\n */\n body: TableBodyType[];\n /**\n * 테이블의 모서리를 둥글게 처리할지 여부\n * - `rounded`: true일 경우 모서리가 둥글게 처리됨\n */\n rounded?: boolean;\n /**\n * 테이블의 테두리 표시 여부\n * - `border`: true일 경우 테이블에 테두리가 표시됨\n */\n border?: boolean;\n}\n\n/**\n * 테이블 컴포넌트\n * 헤더와 바디를 설정하여 테이블을 렌더링합니다.\n * - `header`: 테이블의 헤더 설정\n * - `body`: 테이블의 바디 설정\n * - `rounded`: 테이블의 모서리를 둥글게 처리할지 여부\n * - `border`: 테이블에 테두리를 표시할지 여부\n */\nexport default function Table({ header, body, rounded, border }: TableProps) {\n const subLabels = header.flatMap(col => col.subLabel || []);\n const isBodyWithHead = body.some(row => row.head);\n\n return (\n <div className={cn({\n [styles.wrapper]: true,\n [styles.wrapper__rounded]: !!rounded,\n [styles.wrapper__border]: !!border,\n })}\n >\n\n <table className={styles.table}>\n <colgroup>\n {isBodyWithHead && <col style={{ width: '100px' }} />}\n {header.map((col, colIndex) =>\n col.subLabel\n ? col.subLabel.map((_, subIndex) => (\n <col\n key={`col-${colIndex}-sub-${subIndex}`}\n style={{ width: col?.subWidth?.[subIndex] || 'auto' }}\n />\n ))\n : (\n <col\n key={`col-${colIndex}`}\n style={{ width: col.width || 'auto' }}\n />\n ),\n )}\n\n </colgroup>\n <thead>\n <tr>\n {body.some(row => row.head) && <th className={styles.fixed} rowSpan={2} />}\n {header.map((col, index) => (\n <th\n key={index}\n style={{ textAlign: col.label.align || 'left' }}\n rowSpan={col.subLabel ? 1 : 2}\n colSpan={col.subLabel ? col.subLabel.length : undefined}\n >\n {col.label.text}\n </th>\n ))}\n </tr>\n {subLabels.length > 0 && (\n <tr>\n {subLabels.map((subLabel, index) => (\n <th\n style={{ textAlign: subLabel.align || 'left' }}\n key={index}\n >{subLabel.text}\n </th>\n ))}\n </tr>\n )}\n </thead>\n <tbody>\n {body.map((row, rowIndex) => (\n <tr key={rowIndex}>\n {isBodyWithHead && <th style={{ textAlign: row?.head?.align || 'left' }}>{row?.head?.text || ''}</th>}\n {row.labels.map((col, colIndex) => (\n <td style={{ textAlign: col.align || 'left' }} key={colIndex}>\n {col.text}\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n );\n}\n","import * as React from \"react\";\nconst SvgClose = (props) => /* @__PURE__ */ React.createElement(\"svg\", { width: \"64px\", height: \"64px\", viewBox: \"0 0 24 24\", fill: \"#000000\", xmlns: \"http://www.w3.org/2000/svg\", stroke: \"#000000\", strokeWidth: 0.696, ...props }, /* @__PURE__ */ React.createElement(\"g\", { id: \"SVGRepo_bgCarrier\", strokeWidth: 0 }), /* @__PURE__ */ React.createElement(\"g\", { id: \"SVGRepo_tracerCarrier\", strokeLinecap: \"round\", strokeLinejoin: \"round\" }), /* @__PURE__ */ React.createElement(\"g\", { id: \"SVGRepo_iconCarrier\" }, /* @__PURE__ */ React.createElement(\"path\", { fillRule: \"evenodd\", clipRule: \"evenodd\", d: \"M19.207 6.207a1 1 0 0 0-1.414-1.414L12 10.586 6.207 4.793a1 1 0 0 0-1.414 1.414L10.586 12l-5.793 5.793a1 1 0 1 0 1.414 1.414L12 13.414l5.793 5.793a1 1 0 0 0 1.414-1.414L13.414 12l5.793-5.793z\" })));\nexport default SvgClose;\n","import * as React from \"react\";\nconst SvgArrow = (props) => /* @__PURE__ */ React.createElement(\"svg\", { width: \"64px\", height: \"64px\", viewBox: \"0 0 24 24\", fill: \"#0F0F0F\", xmlns: \"http://www.w3.org/2000/svg\", ...props }, /* @__PURE__ */ React.createElement(\"g\", { id: \"SVGRepo_bgCarrier\", strokeWidth: 0 }), /* @__PURE__ */ React.createElement(\"g\", { id: \"SVGRepo_tracerCarrier\", strokeLinecap: \"round\", strokeLinejoin: \"round\" }), /* @__PURE__ */ React.createElement(\"g\", { id: \"SVGRepo_iconCarrier\" }, /* @__PURE__ */ React.createElement(\"path\", { d: \"M16.1795 3.26875C15.7889 2.87823 15.1558 2.87823 14.7652 3.26875L8.12078 9.91322C6.94952 11.0845 6.94916 12.9833 8.11996 14.155L14.6903 20.7304C15.0808 21.121 15.714 21.121 16.1045 20.7304C16.495 20.3399 16.495 19.7067 16.1045 19.3162L9.53246 12.7442C9.14194 12.3536 9.14194 11.7205 9.53246 11.33L16.1795 4.68297C16.57 4.29244 16.57 3.65928 16.1795 3.26875Z\" })));\nexport default SvgArrow;\n","import * as React from \"react\";\nconst SvgDropArrow = (props) => /* @__PURE__ */ React.createElement(\"svg\", { width: 25, height: 25, viewBox: \"0 0 20 20\", fill: \"none\", stroke: \"#2D2D2D\", xmlns: \"http://www.w3.org/2000/svg\", ...props }, /* @__PURE__ */ React.createElement(\"path\", { d: \"M5 7.5L10 13L15 7.5\", strokeWidth: 1.4, strokeLinecap: \"round\" }));\nexport default SvgDropArrow;\n","import { cn } from '@jk-core/utils';\nimport ArrowIcon from '@/assets/arrow.svg';\nimport DropIcon from '@/assets/drop-arrow.svg';\nimport { CalendarView } from '@/Calendar/type';\nimport styles from './DateLabel.module.scss';\n\ninterface DateLabelProps {\n viewDate: Date;\n onArrowClick: (direction: 'prev' | 'next') => void;\n disabled: (direction: 'prev' | 'next') => boolean;\n method: CalendarView;\n selectMode?: CalendarView;\n setSelectMode?: (mode: CalendarView) => void;\n hideArrow?: 'prev' | 'next' | 'all' | null;\n range?: boolean;\n}\n\nexport default function DateLabel({\n viewDate, onArrowClick, disabled, method, selectMode = 'day', setSelectMode = () => { }, hideArrow = null, range = false,\n}: DateLabelProps) {\n return (\n <div className={cn({\n [styles.nav]: true,\n [styles['nav--range']]: range,\n [styles['nav--left']]: hideArrow === 'all',\n })}\n >\n {hideArrow !== 'all' && (\n <button\n className={styles.nav__button}\n type=\"button\"\n onClick={() => onArrowClick('prev')}\n disabled={disabled('prev') || hideArrow === 'prev'}\n >\n {hideArrow !== 'prev' && <ArrowIcon />}\n </button>\n )}\n {range ? (\n <div className={cn({\n [styles.nav__label]: true,\n [styles['nav__label--left']]: hideArrow === 'all',\n })}\n >\n {`${viewDate.getFullYear()}년 ${viewDate.getMonth() + 1}월`}\n </div>\n ) : (\n <div className={cn({\n [styles.nav__label]: true,\n [styles['nav__label--left']]: hideArrow === 'all',\n })}\n >\n {method === 'year' && '연도 선택'}\n {method !== 'year' && (\n <button\n className={cn({\n [styles['nav__label--date']]: true,\n [styles['nav__label--date-selected']]: selectMode === 'year',\n })}\n type=\"button\"\n onClick={() => setSelectMode('year')}\n >\n {`${viewDate.getFullYear()}년`}<DropIcon />\n </button>\n )}\n {method === 'day' && (\n <button\n className={cn({\n [styles['nav__label--date']]: true,\n [styles['nav__label--date-selected']]: selectMode === 'month',\n })}\n type=\"button\"\n onClick={() => setSelectMode('month')}\n >\n {`${viewDate.getMonth() + 1}월`}<DropIcon />\n </button>\n )}\n </div>\n )}\n {hideArrow !== 'all' && (\n <button\n className={styles.nav__button}\n type=\"button\"\n onClick={() => onArrowClick('next')}\n disabled={disabled('next') || hideArrow === 'next'}\n >\n {hideArrow !== 'next' && <ArrowIcon style={{ transform: 'rotate(180deg)' }} />}\n </button>\n )}\n </div>\n );\n}\n","import { CalendarRange } from '@/Calendar/type';\n\nconst isInRange = (day: Date, range?:CalendarRange) => {\n if (!range?.[0] || !range?.[1]) return false;\n return day >= range[0] && day < range[1];\n};\n\nexport default isInRange;\n","import { CalendarView } from '../type';\n\nconst isSameDay = (date1: Date | null, date2: Date | null, view: CalendarView = 'day'): boolean => {\n if (date1 === null || date2 === null) return false;\n\n switch (view) {\n case 'day':\n return date1.getFullYear() === date2.getFullYear()\n && date1.getMonth() === date2.getMonth()\n && date1.getDate() === date2.getDate();\n case 'month':\n return date1.getFullYear() === date2.getFullYear()\n && date1.getMonth() === date2.getMonth();\n case 'year':\n return date1.getFullYear() === date2.getFullYear();\n default:\n return false;\n }\n};\n\nexport default isSameDay;\n","\nimport { cn } from '@jk-core/utils';\nimport { CalendarRange } from '@/Calendar/type';\nimport isInRange from '@/Calendar/utils/isInRange';\nimport isSameDay from '@/Calendar/utils/isSameDay';\nimport styles from './DayTile.module.scss';\n\nconst WEEKS = ['일', '월', '화', '수', '목', '금', '토'];\n\ninterface Props {\n hoverDate?:Date | null,\n setHoverDate?:(date:Date | null)=>void,\n selectedDate?: CalendarRange;\n weeksInMonth: {\n thisMonth: string;\n date: Date;\n }[][];\n tileContent?: () => React.ReactNode;\n handleDayClick: (day: Date) => void;\n max?: Date;\n min?: Date;\n hideBefore?: boolean;\n hideAfter?: boolean;\n range?: boolean;\n scroll?: boolean;\n style?: React.CSSProperties;\n}\nexport default function DayTile({\n selectedDate, weeksInMonth, tileContent, handleDayClick, range = false,\n max, min, hideBefore = false, hideAfter = false, style, scroll,\n hoverDate, setHoverDate = () => { },\n}: Props) {\n const handleDisabled = (date: Date): boolean => {\n const compareDate = new Date(date.getFullYear(), date.getMonth(), date.getDate());\n const compareMin = min ? new Date(min.getFullYear(), min.getMonth(), min.getDate()) : null;\n const compareMax = max ? new Date(max.getFullYear(), max.getMonth(), max.getDate()) : null;\n\n return !!((compareMin && compareDate < compareMin) || (compareMax && compareDate > compareMax));\n };\n\n return (\n <div className={styles['day-tile']} style={style}>\n <div className={styles['day-tile__weeks']}>\n {WEEKS.map((week) => (<div className={styles['day-tile__weeks--date']} key={week}>{week}</div>))}\n </div>\n\n <div className={styles['day-tile__tile']}>\n {weeksInMonth.map((week, index) => (\n <div key={index} className={styles['day-tile__week']}>\n {week.map((day, idx) => (\n <button\n className={cn({\n [styles['day-tile__day']]: true,\n [styles['day-tile__day--today']]: isSameDay(day.date, new Date()),\n [styles['day-tile__day--selected-first']]: !!selectedDate && isSameDay(day.date, selectedDate[0] || null) && range\n && ((!!selectedDate[1]\n || ((!scroll && hoverDate != null && !!selectedDate[0])\n && hoverDate > selectedDate[0]))),\n [styles['day-tile__day--selected-last']]: (!!selectedDate && isSameDay(day.date, selectedDate[1] || null) && range)\n || (!scroll && !selectedDate?.[1] && isSameDay(day.date, hoverDate || null)),\n [styles['day-tile__day--before']]: day.thisMonth !== 'this',\n [styles['day-tile__day--hide-before']]: hideBefore && day.thisMonth === 'before',\n [styles['day-tile__day--hide-after']]: hideAfter && day.thisMonth === 'after',\n [styles['day-tile__day--tile']]: !!(tileContent && tileContent()),\n [styles['day-tile__day--range']]: isInRange(day.date, selectedDate) || (!!selectedDate?.[0] && (isInRange(day.date, [selectedDate[0], hoverDate]))),\n })}\n type=\"button\"\n disabled={handleDisabled(day.date)}\n key={idx}\n onMouseOver={() => {\n if (!selectedDate?.[1] && !((min && day.date < min) || (max && day.date > max))) {\n setHoverDate(new Date(\n day.date.getFullYear(),\n day.date.getMonth(),\n day.date.getDate(),\n ));\n }\n }}\n onFocus={() => {\n if (!selectedDate?.[1] && !((min && day.date < min) || (max && day.date > max))) {\n setHoverDate(new Date(\n day.date.getFullYear(),\n day.date.getMonth(),\n day.date.getDate(),\n ));\n }\n }}\n onMouseLeave={() => {\n if (hoverDate) setHoverDate(null);\n }}\n onClick={() => handleDayClick(day.date)}\n >\n <div className={cn({\n [styles['day-tile--content']]: true,\n [styles['day-tile--selected']]: !!selectedDate && (isSameDay(day.date, selectedDate[0] || null) || isSameDay(day.date, selectedDate[1] || null) || isSameDay(day.date, hoverDate || null)),\n })}\n >\n {day.date.getDate()}\n {tileContent && tileContent()}\n </div>\n </button>\n ))}\n </div>\n ))}\n </div>\n </div>\n );\n}\n","import { CalendarView } from '../type';\n\ninterface Props {\n method: CalendarView;\n selectMode: CalendarView;\n viewDate: Date;\n setDate:(date: Date) => void;\n min: Date;\n max: Date;\n}\nconst useCalendarNav = ({\n method, selectMode, viewDate, setDate, min, max,\n}:Props) => {\n const disabled = (direction: 'prev' | 'next') => {\n if (selectMode === 'year' || method !== selectMode) return true;\n\n if (method === 'day') {\n if (direction === 'prev') {\n const prevMonth = new Date(viewDate.getFullYear(), viewDate.getMonth() - 1, 1);\n const isPrevMonthBeforeMin = prevMonth.getFullYear() < min.getFullYear()\n || (prevMonth.getFullYear() === min.getFullYear()\n && prevMonth.getMonth() < min.getMonth());\n return isPrevMonthBeforeMin;\n }\n const nextMonth = new Date(viewDate.getFullYear(), viewDate.getMonth() + 1, 1);\n return nextMonth > max;\n }\n\n if (method === 'month') {\n if (direction === 'prev') {\n const prevYear = new Date(viewDate.getFullYear() - 1, viewDate.getMonth(), 1);\n return prevYear < min;\n }\n const nextYear = new Date(viewDate.getFullYear() + 1, viewDate.getMonth(), 1);\n return nextYear > max;\n }\n\n if (method === 'year') {\n if (direction === 'prev') {\n const prevDecade = new Date(viewDate.getFullYear() - 10, viewDate.getMonth(), 1);\n return prevDecade < min;\n }\n const nextDecade = new Date(viewDate.getFullYear() + 10, viewDate.getMonth(), 1);\n return nextDecade > max;\n }\n\n return false;\n };\n\n const onArrowClick = (direction: 'prev' | 'next') => {\n const offset = direction === 'prev' ? -1 : 1;\n const minDate = new Date(2000, 0, 1);\n const maxDate = new Date(2099, 11, 31);\n\n if (method === 'day') {\n const newDate = new Date(viewDate.getFullYear(), viewDate.getMonth() + offset, 1);\n\n if (newDate >= minDate && newDate <= maxDate) {\n setDate(newDate);\n }\n }\n\n if (method === 'month') {\n const newDate = new Date(viewDate.getFullYear() + offset, viewDate.getMonth(), 1);\n\n if (newDate >= minDate && newDate <= maxDate) {\n setDate(newDate);\n }\n }\n\n if (method === 'year') {\n const newDate = new Date(viewDate.getFullYear() + offset * 10, viewDate.getMonth(), 1);\n\n if (newDate >= minDate && newDate <= maxDate) {\n setDate(newDate);\n }\n }\n };\n\n return { disabled, onArrowClick };\n};\n\nexport default useCalendarNav;\n","const getWeeksInMonth = (viewDate:Date) => {\n const startOfMonth = new Date(viewDate.getFullYear(), viewDate.getMonth(), 1);\n const endOfMonth = new Date(viewDate.getFullYear(), viewDate.getMonth() + 1, 0);\n const weeks = [];\n let currentWeek = [];\n\n const startDayOfWeek = startOfMonth.getDay();\n if (startDayOfWeek !== 0) {\n const prevMonthEnd = new Date(startOfMonth);\n prevMonthEnd.setDate(0);\n for (let i = startDayOfWeek - 1; i >= 0; i -= 1) {\n const prevDate = new Date(prevMonthEnd);\n prevDate.setDate(prevMonthEnd.getDate() - i);\n currentWeek.push({ thisMonth: 'before', date: prevDate });\n }\n }\n\n const currentDate = new Date(startOfMonth);\n\n while (currentDate <= endOfMonth) {\n currentWeek.push({ thisMonth: 'this', date: new Date(currentDate) });\n if (currentDate.getDay() === 6) {\n weeks.push(currentWeek);\n currentWeek = [];\n }\n currentDate.setDate(currentDate.getDate() + 1);\n }\n\n const endDayOfWeek = endOfMonth.getDay();\n if (endDayOfWeek !== 6) {\n for (let i = 1; i <= 6 - endDayOfWeek; i += 1) {\n const nextDate = new Date(endOfMonth);\n nextDate.setDate(endOfMonth.getDate() + i);\n currentWeek.push({ thisMonth: 'after', date: nextDate });\n }\n }\n\n if (currentWeek.length > 0) {\n weeks.push(currentWeek);\n }\n\n return weeks;\n};\n\nexport default getWeeksInMonth;\n","\nimport { useEffect, useState } from 'react';\nimport { cn } from '@jk-core/utils';\nimport CloseIcon from '@/assets/close.svg';\nimport styles from './Calendar.module.scss';\nimport DateLabel from './components/DateLabel';\nimport DayTile from './components/DayTile';\nimport useCalendarNav from './hooks/useCalendarNav';\nimport { CalendarRange } from './type';\nimport getWeeksInMonth from './utils/getWeeksInMonth';\n\ninterface CalendarProps {\n clas