@edu-tosel/design 1.0.140 → 1.0.142

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.
package/layout/index.d.ts CHANGED
@@ -6,6 +6,7 @@ export { default as Home } from "./template/home";
6
6
  export * from "./template/dashboard";
7
7
  export { default as Event } from "./template/Event";
8
8
  export { default as Olympiad } from "./template/Olympiad";
9
+ export { default as Regexam } from "./template/Regexam";
9
10
  export { default as Sign } from "./template/Sign";
10
11
  export { default as DataField } from "./template/DataField";
11
12
  export { default as Gallery } from "./template/Gallery";
@@ -15,3 +16,4 @@ export { default as Tab } from "./template/Tab";
15
16
  export { default as TextBox } from "./template/TextBox";
16
17
  export { default as OlympiadLayout } from "./template/Olympiad/Olympiad.layout";
17
18
  export { default as Gomito } from "./template/Gomito";
19
+ export { default as RegexamLayout } from "./template/Regexam/Regexam.layout";
package/layout/index.js CHANGED
@@ -6,6 +6,7 @@ export { default as Home } from "./template/home";
6
6
  export * from "./template/dashboard";
7
7
  export { default as Event } from "./template/Event";
8
8
  export { default as Olympiad } from "./template/Olympiad";
9
+ export { default as Regexam } from "./template/Regexam";
9
10
  export { default as Sign } from "./template/Sign";
10
11
  export { default as DataField } from "./template/DataField";
11
12
  export { default as Gallery } from "./template/Gallery";
@@ -15,3 +16,4 @@ export { default as Tab } from "./template/Tab";
15
16
  export { default as TextBox } from "./template/TextBox";
16
17
  export { default as OlympiadLayout } from "./template/Olympiad/Olympiad.layout";
17
18
  export { default as Gomito } from "./template/Gomito";
19
+ export { default as RegexamLayout } from "./template/Regexam/Regexam.layout";
@@ -1,8 +1,8 @@
1
1
  import { Button as _Button } from "../../../interface";
2
- type EventType = "event" | "notice";
3
- interface Event {
2
+ type EventCategory = "event" | "notice";
3
+ export interface Event {
4
4
  id: number;
5
- type: EventType;
5
+ category: EventCategory;
6
6
  thumbnail: string;
7
7
  createdAt: string;
8
8
  startedAt?: string;
@@ -12,7 +12,4 @@ interface Event {
12
12
  content: string;
13
13
  button?: _Button;
14
14
  }
15
- export default function Container({ events }: {
16
- events: Event[];
17
- }): import("react/jsx-runtime").JSX.Element;
18
15
  export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,9 @@
1
+ import { Event } from "./Event";
2
+ import { OnClick } from "../../../interface";
3
+ interface EventProps {
4
+ events: (Event & {
5
+ onClick?: OnClick;
6
+ })[];
7
+ }
8
+ export default function Many({ events }: EventProps): import("react/jsx-runtime").JSX.Element;
9
+ export {};
@@ -0,0 +1,29 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { useState } from "react";
3
+ import { IoIosSearch } from "react-icons/io";
4
+ import dayjs from "dayjs";
5
+ import { LineBreaks } from "../../../text";
6
+ import { StatusText } from "./StatusText";
7
+ export default function Many({ events }) {
8
+ const [filter, setFilter] = useState("모두보기");
9
+ const [searchQuery, setSearchQuery] = useState("");
10
+ const filteredEvents = events
11
+ .filter((event) => {
12
+ const now = dayjs();
13
+ const startedAt = dayjs(event.startedAt);
14
+ const expiredAt = dayjs(event.expiredAt);
15
+ if (filter === "모두보기")
16
+ return true;
17
+ if (filter === "진행 중") {
18
+ return (event.startedAt && now.isAfter(startedAt) && now.isBefore(expiredAt));
19
+ }
20
+ if (filter === "예정된") {
21
+ return event.startedAt && now.isBefore(startedAt);
22
+ }
23
+ if (filter === "토셀소식")
24
+ return event.category === "notice";
25
+ return false;
26
+ })
27
+ .filter((event) => event.title.includes(searchQuery));
28
+ return (_jsx("div", { className: "min-h-screen w-full mx-auto", children: _jsx("div", { className: "mmd:max-w-300 h-full flex flex-col mx-auto px-10", children: _jsxs(_Fragment, { children: [_jsxs("div", { className: "flex flex-col sm:flex-row justify-between min-h-14.5 border-b-1", children: [_jsxs("div", { className: "w-full mb-5 h-9 sm:w-80 sm:h-9.5 flex items-center bg-[#f0f0f0]/10 rounded-xl", children: [_jsx(IoIosSearch, { className: "text-xl text-green-dark mr-3" }), _jsx("input", { type: "text", placeholder: "\uD0A4\uC6CC\uB4DC\uB97C \uC785\uB825\uD558\uC138\uC694.", value: searchQuery, onChange: (e) => setSearchQuery(e.target.value), className: "w-full h-full text-sm bg-[#f0f0f0]/10 placeholder:text-[#7f7f7f] placeholder:font-light outline-none" })] }), _jsx("div", { className: "flex h-9 pb-5 sm:pb-0 sm:h-9.5 items-center sm:justify-center ", children: ["모두보기", "진행 중", "예정된", "토셀소식"].map((item) => (_jsx("div", { className: `text-xs sm:text-2xs md:text-xs p-2 sm:p-3 flex items-center justify-center cursor-pointer rounded-lg ${filter === item ? "bg-green-dark/10 text-green-dark" : ""}`, onClick: () => setFilter(item), children: item }, item))) })] }), _jsx("div", { className: "pt-5 grid sm:grid-cols-2 mmd:grid-cols-3 gap-5 rounded-xl", children: filteredEvents.map((event) => (_jsxs("div", { onClick: event.onClick, className: "w-full max-h-84 shadow-md rounded-xl cursor-pointer box-shadow-green transition-all duration-500", children: [_jsx("div", { className: "w-full max-h-50 rounded-t-xl overflow-hidden relative", children: _jsx("img", { src: event.thumbnail, alt: "", className: "w-full" }) }), _jsxs("div", { className: "w-full min-h-34 p-8 gap-3 flex flex-col", children: [_jsx("div", { className: "flex items-center", children: _jsx(StatusText, { event: event }) }), _jsx(LineBreaks, { className: "text-sm font-bold text-gray-dark flex items-center", texts: event.title })] })] }, event.id))) })] }) }) }));
29
+ }
@@ -0,0 +1,6 @@
1
+ import { Event } from "./Event";
2
+ interface EventProps {
3
+ event: Event;
4
+ }
5
+ export default function One({ event }: EventProps): import("react/jsx-runtime").JSX.Element;
6
+ export {};
@@ -0,0 +1,10 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { cn, isHTMLString } from "../../../util";
3
+ import { StatusText } from "./StatusText";
4
+ export default function One({ event }) {
5
+ const button = () => ({
6
+ sizes: "w-full h-12 flex items-center justify-center rounded-md text-white cursor-pointer font-bold gap-3 text-sm xs:text-md",
7
+ backgrounds: "bg-gradient-to-l from-[#760023] to-[#105652]",
8
+ });
9
+ return (_jsxs("div", { className: "flex flex-col mmd:flex-row", children: [_jsx("div", { className: "min-w-[320px] h-auto p-5 mmd:sticky mmd:top-20 mmd:self-start", children: _jsxs("div", { className: "w-full h-auto rounded-xl sm:flex mmd:flex-col", children: [_jsx("div", { className: "w-full mmd:h-50 overflow-hidden", children: _jsx("img", { src: event.thumbnail, alt: "", className: "rounded-xl h-full object-cover w-full" }) }), _jsxs("div", { className: "w-full h-auto pt-5 sm:p-5 mmd:p-0 mmd:pt-5 gap-3 flex flex-col", children: [_jsx("div", { className: "flex items-center", children: _jsx(StatusText, { event: event }) }), _jsx("div", { className: "text-sm font-bold text-gray-dark flex items-center mb-2", children: event.title }), event.button && (_jsx("div", { onClick: event.button.onClick, className: cn(button()), children: event.button?.title }))] })] }, event.id) }), _jsxs("div", { className: "flex-grow p-5", children: [_jsx("div", { children: isHTMLString(event.content) ? (_jsx("div", { dangerouslySetInnerHTML: { __html: event.content }, className: "w-full rounded-xl object-cover overflow-hidden" })) : (_jsx("div", { children: event.content })) }), _jsx("button", { onClick: () => history.back(), className: "p-5 bg-green-dark/5 text-green-dark rounded-xl flex items-center justify-center hover:bg-green-dark/20 transition-all", children: "\uBAA9\uB85D\uC73C\uB85C \uB3CC\uC544\uAC00\uAE30" })] })] }));
10
+ }
@@ -0,0 +1,4 @@
1
+ import { Event } from "./Event";
2
+ export declare const StatusText: ({ event }: {
3
+ event: Event;
4
+ }) => React.ReactNode;
@@ -0,0 +1,38 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import dayjs from "dayjs";
3
+ export const StatusText = ({ event }) => {
4
+ const now = dayjs();
5
+ const startedAt = dayjs(event.startedAt);
6
+ const expiredAt = event.expiredAt
7
+ ? dayjs(event.expiredAt)
8
+ : dayjs(event.endData);
9
+ if (event.category === "event") {
10
+ if (event.expiredAt) {
11
+ if (now.isBefore(startedAt)) {
12
+ return (_jsx("span", { className: "px-2 py-1 text-2xs font-semibold rounded-md bg-green-dark text-white", children: "\uC624\uD508\uC608\uC815" }));
13
+ }
14
+ else if (now.isAfter(expiredAt)) {
15
+ return (_jsx("span", { className: "px-2 py-1 text-2xs font-semibold rounded-md bg-gray-light text-gray-mid", children: "\uB9C8\uAC10" }));
16
+ }
17
+ else {
18
+ const diff = expiredAt.diff(now, "day");
19
+ return (_jsxs("span", { className: "px-2 py-1 text-2xs font-semibold rounded-md bg-green-dark/10 text-green-dark", children: ["\uC9C4\uD589\uC911 | D-", diff] }));
20
+ }
21
+ }
22
+ else {
23
+ return (_jsx("div", { className: "w-[63px] h-[22px] rounded-md bg-black flex items-center justify-center", style: {
24
+ background: "linear-gradient(269deg, rgba(118, 0, 35, 0.10) 0%, rgba(16, 86, 82, 0.10) 100%)",
25
+ }, children: _jsx("div", { className: "px-2 py-1 text-2xs font-semibold rounded-md", style: {
26
+ background: "linear-gradient(269deg, rgba(118, 0, 35) 0%, rgba(16, 86, 82) 100%)",
27
+ WebkitBackgroundClip: "text",
28
+ WebkitTextFillColor: "transparent",
29
+ }, children: "\uC0C1\uC2DC \uC774\uBCA4\uD2B8" }) }));
30
+ }
31
+ }
32
+ else if (event.category === "notice") {
33
+ return (_jsx("span", { className: "px-2 py-1 text-2xs font-semibold rounded-md bg-blue-navy/10 text-blue-navy", children: "\uD1A0\uC140 \uC18C\uC2DD" }));
34
+ }
35
+ else {
36
+ return "";
37
+ }
38
+ };
@@ -1,7 +1,9 @@
1
- import Container from "./Container";
2
1
  import Layout from "./Layout";
2
+ import Many from "./Many";
3
+ import One from "./One";
3
4
  declare const Event: {
4
- Container: typeof Container;
5
5
  Layout: typeof Layout;
6
+ Many: typeof Many;
7
+ One: typeof One;
6
8
  };
7
9
  export default Event;
@@ -1,7 +1,9 @@
1
- import Container from "./Container";
2
1
  import Layout from "./Layout";
2
+ import Many from "./Many";
3
+ import One from "./One";
3
4
  const Event = {
4
- Container,
5
5
  Layout,
6
+ Many,
7
+ One,
6
8
  };
7
9
  export default Event;
@@ -1,47 +1,168 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useRef } from "react";
2
3
  import { cn } from "../../../util";
4
+ import { getMaxBday } from "../../../util/getMaxBday";
3
5
  export default function Conditions() {
6
+ const scrollContainerRef = useRef(null);
7
+ const cardWidth = 400; // card width
8
+ const handleScroll = (direction) => {
9
+ if (scrollContainerRef.current) {
10
+ const scrollAmount = cardWidth;
11
+ const currentScrollLeft = scrollContainerRef.current.scrollLeft;
12
+ const newScrollLeft = direction === "left"
13
+ ? Math.max(currentScrollLeft - scrollAmount, 0)
14
+ : currentScrollLeft + scrollAmount;
15
+ scrollContainerRef.current.scrollTo({
16
+ left: newScrollLeft,
17
+ behavior: "smooth",
18
+ });
19
+ }
20
+ };
4
21
  const container = {
5
- sizes: "w-full h-fit",
6
- spacings: "my-20 lg:my-40",
22
+ positions: "relative z-10 group mt-10 md:mt-20 mb-16 md:mb-40",
23
+ displays: "flex flex-col",
24
+ textstyles: "break-keep antialiased font-pretendard-var",
25
+ };
26
+ const deckTitlePositioning = {
7
27
  displays: "flex flex-col justify-center items-center",
8
- graphics: "antialiased",
9
- text: "break-keep",
28
+ sizes: "w-full",
29
+ };
30
+ const deckTitle = {
31
+ textstyles: "text-xl text-center text-green-dark font-pretendard-bold md:text-2xl",
32
+ animations: "duration-300",
33
+ };
34
+ const subTitle = {
35
+ textstyles: "text-xs sm:text-sm md:text-base font-pretendard-medium text-green-dark",
36
+ animations: "duration-300",
37
+ spacings: "mb-10",
10
38
  };
11
39
  const cardPositioning = {
12
40
  displays: "flex flex-nowrap",
13
- sizes: "w-screen",
41
+ sizes: "w-full",
14
42
  };
15
43
  const cardWrapper = {
16
- sizes: `w-full overflow-x-auto scroll-smooth scrollbar-hidden scroll-pl-4`,
44
+ sizes: "w-full overflow-x-auto scroll-smooth scrollbar-hidden scroll-px-4",
17
45
  display: "flex flex-nowrap vertical-top",
18
- spacings: "p-5",
46
+ spacings: "px-5 pt-4 md:pt-6 pb-12",
19
47
  snap: "snap-x snap-mandatory scroll-ms-0",
20
48
  };
49
+ //adjust the responsive right margin of scroller
21
50
  const cardDeck = {
22
51
  displays: "inline-flex",
23
52
  spacings: "gap-5 ml:mr-[calc(100vw-1200px)]",
24
53
  };
54
+ const buttonPositioning = {
55
+ displays: "hidden flex-row md:flex",
56
+ sizes: "w-full h-full",
57
+ spacings: "px-2",
58
+ positions: "absolute top-0 left-0 justify-between items-center opacity-0 group-hover:opacity-100 duration-300",
59
+ hovering: "group pointer-events-none",
60
+ };
61
+ const hoverButton = {
62
+ sizes: "rounded-full w-12 h-12 scale-50 group-hover:scale-100",
63
+ animation: "duration-300 ",
64
+ test: "bg-gray-medium/20 hover:bg-gray-medium/50 pointer-events-auto backdrop-blur-sm fill-red-500",
65
+ };
66
+ return (_jsxs("div", { className: cn(container), children: [_jsxs("div", { className: cn(deckTitlePositioning), children: [_jsx("div", { className: cn(deckTitle), children: "\uC5F0\uB839\uBCC4 \uCC38\uAC00\uAE30\uC900" }), _jsx("div", { className: cn(subTitle), children: "\uD559\uC0DD\uC774\uB77C\uBA74, \uB204\uAD6C\uB098 \uCC38\uAC00\uD560 \uC218 \uC788\uC5B4\uC694" }), _jsx("div", { className: "h-0.5 w-1/4 mb-8 bg-green-dark rounded-lg" })] }), _jsx("div", { className: cn(cardPositioning), children: _jsx("div", { className: cn(cardWrapper), ref: scrollContainerRef, children: _jsx("div", { className: cn(cardDeck), children: Object.entries(levelStyles).map(([key, { name, description, maxBday, majorColor, imgSrc }]) => (_jsx(LevelCard, { name: name, description: description, maxBday: maxBday, majorColor: majorColor, imgSrc: imgSrc }, key))) }) }) }), _jsxs("div", { className: cn(buttonPositioning), children: [_jsx("div", { className: cn(hoverButton), onClick: () => handleScroll("left"), children: _jsx("img", { src: "images/home/handle-left.svg", alt: "" }) }), _jsx("div", { className: cn(hoverButton), onClick: () => handleScroll("right"), children: _jsx("img", { src: "images/home/handle-right.svg", alt: "" }) })] })] }));
67
+ }
68
+ const levelStyles = {
69
+ PS: {
70
+ name: "Pre-Starter",
71
+ description: "초등학교 2학년까지 참가 가능",
72
+ maxBday: getMaxBday().PS,
73
+ majorColor: "text-ps-pink",
74
+ imgSrc: "/images/olympiad/img-oly-book-ps.png",
75
+ },
76
+ ST: {
77
+ name: "Starter",
78
+ description: "초등학교 4학년까지 참가 가능",
79
+ maxBday: getMaxBday().ST,
80
+ majorColor: "text-st-orange",
81
+ imgSrc: "/images/olympiad/img-oly-book-st.png",
82
+ },
83
+ BA: {
84
+ name: "Basic",
85
+ description: "초등학교 6학년까지 참가 가능",
86
+ maxBday: getMaxBday().BA,
87
+ majorColor: "text-ba-yellow",
88
+ imgSrc: "/images/olympiad/img-oly-book-ba.png",
89
+ },
90
+ JR: {
91
+ name: "Junior",
92
+ description: "중학교 3학년까지 참가 가능",
93
+ maxBday: getMaxBday().JR,
94
+ majorColor: "text-jr-blue",
95
+ imgSrc: "/images/olympiad/img-oly-book-jr.png",
96
+ },
97
+ HJ: {
98
+ name: "High Junior",
99
+ description: "고등학교 3학년까지 참가 가능",
100
+ maxBday: getMaxBday().HJ,
101
+ majorColor: "text-hj-blue",
102
+ imgSrc: "/images/olympiad/img-oly-book-hj.png",
103
+ },
104
+ };
105
+ const LevelCard = ({ name, description, maxBday, majorColor, imgSrc, }) => {
25
106
  const ghostCard = {
26
- sizes: "h-100 ",
27
107
  displays: "flex",
28
- spacings: "ms-0 ps-0 last:[calc(50vw-520px)]",
29
- animations: "duration-300",
30
- scroll: "snap-start last:snap-end",
108
+ spacings: "ms-0 ps-0 ",
109
+ scroll: "snap-start",
31
110
  };
32
- //control size of the card
111
+ //adjust the responsive left margin of scroller
112
+ //adjust the card size
33
113
  const card = {
34
- graphics: "shadow-main",
35
- sizes: "h-100 w-80 rounded-2xl",
36
- backgrounds: "bg-red",
37
- hover: "hover:shadow-main-hover",
114
+ graphics: "shadow-main group/book",
115
+ sizes: "h-100 w-65 xxxs:w-76 md:w-100 md:h-125 rounded-xl md:rounded-2xl",
116
+ hover: "hover:shadow-main-hover hover:scale-[1.03]",
38
117
  position: "ml:translate-x-[calc(50vw-600px)]",
39
- transition: "duration-200",
40
- displays: "display-block",
118
+ transition: "duration-300",
119
+ displays: "relative display-block overflow-hidden",
120
+ fonts: "font-pretendard-var",
121
+ // styling varies by level
122
+ // colors: majorColor ? "hover:bg-" + majorColor + "/10" : "hover:bg-white",
41
123
  };
42
- const sectiontitle = {
43
- textstyles: "text-xl text-center text-green-dark mb-10 font-pretendard-bold md:text-2xl",
44
- animations: "duration-300",
124
+ const imageWrapper = {
125
+ sizes: "w-full h-full p-10",
126
+ displays: "absolute flex justify-center items-center",
127
+ positions: "bottom-0 left-0",
128
+ background: "bg-[#f6f6f6]",
45
129
  };
46
- return (_jsxs("div", { className: cn(container), children: [_jsx("div", { className: cn(sectiontitle), children: "\uD559\uC0DD\uC774\uB77C\uBA74 \uB204\uAD6C\uB098 \uB3C4\uC804\uD560 \uC218 \uC788\uC5B4\uC694" }), _jsx("div", { className: "h-0.5 w-1/4 mb-8 bg-green-dark rounded-lg" }), _jsx("div", { className: cn(cardPositioning), children: _jsx("div", { className: cn(cardWrapper), children: _jsxs("div", { className: cn(cardDeck), children: [_jsx("div", { className: cn(ghostCard), children: _jsx("div", { className: cn(card), children: "1" }) }), _jsx("div", { className: cn(ghostCard), children: _jsx("div", { className: cn(card), children: "1" }) }), _jsx("div", { className: cn(ghostCard), children: _jsx("div", { className: cn(card), children: "1" }) }), _jsx("div", { className: cn(ghostCard), children: _jsx("div", { className: cn(card), children: "1" }) }), _jsx("div", { className: cn(ghostCard), children: _jsx("div", { className: cn(card), children: "1" }) }), _jsx("div", { className: cn(ghostCard), children: _jsx("div", { className: cn(card), children: "1" }) }), _jsx("div", { className: cn(ghostCard), children: _jsx("div", { className: cn(card), children: "1" }) }), _jsx("div", { className: cn(ghostCard), children: _jsx("div", { className: cn(card), children: "1" }) }), _jsx("div", { className: cn(ghostCard), children: _jsx("div", { className: cn(card), children: "1" }) })] }) }) })] }));
47
- }
130
+ // const bookTagWrapper = {
131
+ // sizes: "w-full h-full p-10",
132
+ // displays: "absolute flex justify-center items-center",
133
+ // positions: "bottom-0 left-0",
134
+ // clickEvent: "pointer-events-auto",
135
+ // };
136
+ // const bookTag = {
137
+ // sizes: "w-fit h-fit rounded-md",
138
+ // spacings: "py-1 px-2",
139
+ // textStyles: "font-medium text-white",
140
+ // background: "bg-green-dark",
141
+ // opacity: "opacity-0 group-hover/book:opacity-100",
142
+ // animation: "duration-300",
143
+ // };
144
+ const contentsWrapper = {
145
+ sizes: "w-full h-full",
146
+ displays: "relative flex flex-col gap-4 justify-between items-start",
147
+ spacings: "p-4 md:p-8",
148
+ };
149
+ const titleWrapper = {
150
+ displays: "flex flex-col justify-center items-center gap-0",
151
+ sizes: "w-full",
152
+ };
153
+ const title = {
154
+ textStyles: "text-lg font-bold",
155
+ textColor: majorColor ?? "text-gray-dark",
156
+ sizes: "w-fit h-fit rounded-md",
157
+ spacings: "py-1 px-2",
158
+ };
159
+ const subtitle = {
160
+ textStyles: "text-sm font-medium",
161
+ textColor: "text-gray-medium",
162
+ };
163
+ const dateText = {
164
+ textStyles: "text-sm font-medium md:text-base",
165
+ textColor: "text-gray-dark",
166
+ };
167
+ return (_jsx("div", { className: cn(ghostCard), children: _jsxs("div", { className: cn(card), children: [_jsx("div", { className: cn(imageWrapper), children: _jsx("div", { style: { backgroundImage: imgSrc ? `url(${imgSrc})` : undefined }, className: "w-full h-70 bg-cover bg-center" }) }), _jsxs("div", { className: cn(contentsWrapper), children: [_jsxs("div", { className: cn(titleWrapper), children: [_jsx("div", { className: cn(title), children: name }), _jsx("div", { className: cn(subtitle), children: description })] }), _jsxs("div", { className: cn(dateText), children: [maxBday, "\uC0DD \uC774\uC804\uBD80\uD130 ", _jsx("br", {}), " \uCC38\uC5EC\uD560 \uC218 \uC788\uC5B4\uC694"] })] })] }) }));
168
+ };
@@ -0,0 +1 @@
1
+ export default function Banner(): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,31 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { cn } from "../../../util";
3
+ export default function Banner() {
4
+ const container = {
5
+ sizes: "w-full h-screen",
6
+ displays: "flex justify-center items-center",
7
+ spacings: "px-5",
8
+ textstyles: "antialiased",
9
+ backgrounds: "bg-[url('/images/olympiad/img-oly-bg-a.png')] bg-cover bg-center",
10
+ };
11
+ const explainer = {
12
+ textstyles: "text-xl md:text-2xl font-pretendard-medium text-gray-light mix-blend-difference sm:text-green-dark sm:mix-blend-normal",
13
+ };
14
+ const brandTextCore = {
15
+ textstyles: "text-7xl md:text-8xl font-pretendard-bold text-green-dark leading-none mt-6 mix-blend-plus-darker",
16
+ animations: "duration-300",
17
+ };
18
+ const brandTextSub = {
19
+ textstyles: "text-2xl md:text-3xl font-pretendard-bold text-green-dark",
20
+ animations: "duration-300",
21
+ };
22
+ const AdvertButton = {
23
+ sizes: "h-fit w-full xxxs:w-fit rounded-lg",
24
+ backgrounds: "bg-green-light",
25
+ textstyles: "text-lg text-green-dark font-pretendard-medium text-center",
26
+ spacings: "px-3 py-2 mt-30 xxxs:mt-16",
27
+ hoveractions: "hover:bg-green-dark hover:text-white",
28
+ animations: "duration-300",
29
+ };
30
+ return (_jsx("div", { className: cn(container), children: _jsxs("div", { className: "flex flex-col w-full justify-start max-w-6xl", children: [_jsxs("div", { className: cn(explainer), children: ["\uD559\uC0DD\uC774\uB77C\uBA74, ", _jsx("br", {}), "\uC804\uAD6D \uC5B4\uB514\uC5D0\uC11C\uB098 \uCC38\uC5EC \uAC00\uB2A5\uD55C"] }), _jsx("div", { className: cn(brandTextCore), children: "VOCA" }), _jsx("div", { className: cn(brandTextSub), children: "\uC62C\uB9BC\uD53C\uC544\uB4DC" }), _jsx("a", { href: "https://olympiad.tosel.co.kr/dashboard", className: cn(AdvertButton), children: "\uC9C0\uAE08 \uC811\uC218\uD558\uAE30" })] }) }));
31
+ }
@@ -0,0 +1 @@
1
+ export default function RegexamLayout(): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,13 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useRef } from "react";
3
+ import { Regexam } from "../../../layout";
4
+ import { cn } from "../../../util";
5
+ export default function RegexamLayout() {
6
+ const ref = useRef(null);
7
+ const container = {
8
+ sizes: "min-h-screen w-full",
9
+ textoptions: "break-keep antialiased",
10
+ cursor: "cursor-default",
11
+ };
12
+ return (_jsx("div", { className: cn(container), children: _jsx(Regexam.Banner, {}) }));
13
+ }
@@ -0,0 +1,5 @@
1
+ import Banner from "./Banner";
2
+ declare const Regexam: {
3
+ Banner: typeof Banner;
4
+ };
5
+ export default Regexam;
@@ -0,0 +1,5 @@
1
+ import Banner from "./Banner";
2
+ const Regexam = {
3
+ Banner,
4
+ };
5
+ export default Regexam;
@@ -1,4 +1,5 @@
1
1
  import { OnClick } from "../../../interface";
2
- export default function Navigation({ clickBrowser, }: {
2
+ export default function Navigation({ clickBrowser, elements, }: {
3
3
  clickBrowser: OnClick;
4
+ elements: React.ReactNode[];
4
5
  }): import("react/jsx-runtime").JSX.Element;
@@ -1,9 +1,8 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { useEffect, useState } from "react";
3
3
  import { animated, useTransition } from "react-spring";
4
- import SVG from "../../../asset/SVG";
5
4
  import { cn } from "../../../util";
6
- export default function Navigation({ clickBrowser, }) {
5
+ export default function Navigation({ clickBrowser, elements, }) {
7
6
  const [flag, setFlag] = useState(false);
8
7
  const container = {
9
8
  displays: "flex flex-col justify-between items-center",
@@ -29,5 +28,5 @@ export default function Navigation({ clickBrowser, }) {
29
28
  return () => clearTimeout(timer);
30
29
  }
31
30
  }, [flag]);
32
- return (_jsxs(_Fragment, { children: [_jsx("div", { className: "h-screen fixed top-0 left-0 flex justify-center items-center z-45", children: transition((styles, item) => item && (_jsx(animated.div, { style: styles, className: cn(container), children: _jsx(SVG.Icon.Browser, { onClick: () => setFlag(!flag) }) }))) }), overlayTransition((styles, item) => item && (_jsxs(animated.div, { style: styles, className: "bg-white h-screen fixed top-0 left-0 z-40 flex flex-col justify-center items-center overflow-hidden gap-y-14", children: [_jsx("img", { src: "/images/logos/tosel.png", alt: "tosel", width: 368.56, height: 80.07 }), _jsx("div", { children: "dashboard loading..." })] })))] }));
31
+ return (_jsxs(_Fragment, { children: [_jsx("div", { className: "h-screen fixed top-0 left-0 flex justify-center items-center z-45", children: transition((styles, item) => item && (_jsx(animated.div, { style: styles, className: cn(container), children: elements.map((element) => element) }))) }), overlayTransition((styles, item) => item && (_jsxs(animated.div, { style: styles, className: "bg-white h-screen fixed top-0 left-0 z-40 flex flex-col justify-center items-center overflow-hidden gap-y-14", children: [_jsx("img", { src: "/images/logos/tosel.png", alt: "tosel", width: 368.56, height: 80.07 }), _jsx("div", { children: "dashboard loading..." })] })))] }));
33
32
  }
@@ -35,21 +35,23 @@ export default function Footer() {
35
35
  sizes: "w-9 h-9 rounded-md",
36
36
  displays: "flex justify-center items-center",
37
37
  backgrounds: "bg-gray-medium/30 hover:bg-gray-medium",
38
- animation: "duration-200"
38
+ animation: "duration-200",
39
39
  };
40
40
  const socialIconControl = {
41
41
  siezes: "h-6",
42
42
  };
43
- return (_jsx("div", { className: cn(container), children: _jsxs("div", { className: cn(body), children: [_jsxs("div", { className: cn(logoWrapper), children: [_jsx("img", { className: cn(svgController), src: "/images/logos/logo-tosel-main.svg", alt: "" }), _jsx("img", { className: cn(svgController), src: "/images/logos/logo-itc-main.svg", alt: "" })] }), _jsxs("div", { className: "flex flex-wrap justify-between items-center border-b-1 border-gray-dark pb-4 mt-5 font-medium gap-y-1", children: [_jsx("div", { children: "Copyright TOSEL. \u24D2 All Rights Reserved." }), _jsx("div", { className: "flex gap-5", children: buttons.map((button, index) => (_jsx("div", { children: button.title }, index))) })] }), _jsxs("div", { className: cn(infoSet), children: [_jsx("div", { className: cn(infoTitle), children: "\uACE0\uAC1D\uBB38\uC758" }), _jsxs("div", { className: cn(info), children: ["\uB300\uD45C\uBC88\uD638 | 02-923-0505", _jsx("br", {}), " \uAC1C\uC778\uBB38\uC758 | tosel_cs@tosel.co.kr ", _jsx("br", {}), "\uB2E8\uCCB4\uBB38\uC758 | tosel_academy@tosel.co.kr"] })] }), _jsxs("div", { className: cn(infoSet), children: [_jsx("div", { className: cn(infoTitle), children: "\uAD6D\uC81C\uD1A0\uC140\uC704\uC6D0\uD68C" }), _jsxs("div", { className: cn(info), children: ["\uC6F9\uC11C\uBE44\uC2A4: \uC8FC\uC2DD\uD68C\uC0AC \uC5D0\uB4C0\uD1A0\uC140 | \uD1B5\uC2E0\uD310\uB9E4\uC5C5\uC2E0\uACE0\uBC88\uD638: \uC81C 2012-\uC11C\uC6B8\uC131\uBD81-0083\uD638", _jsx("br", {}), " \uC11C\uC6B8\uC2DC \uC131\uBD81\uAD6C \uC548\uC554\uB85C 145 \uACE0\uB824\uB300\uD559\uAD50 \uB77C\uC774\uC2DC\uC6C0 4\uCE35", _jsx("br", {}), " Lyceum Korea University, 145 Anam Ro, Seongbuk-Gu, Seoul, Korea 02841"] })] }), _jsxs("div", { className: cn(iconWrapper), children: [_jsx("a", { onClick: () => location.href = 'https://blog.naver.com/ebs1503', children: _jsx("div", { className: cn(iconBox), children: _jsx("img", { className: cn(socialIconControl), src: "/images/logos/naver.svg", alt: "" }) }) }), _jsx("a", { onClick: () => location.href = 'https://www.instagram.com/tosel_official/', children: _jsx("div", { className: cn(iconBox), children: _jsx("img", { className: cn(socialIconControl), src: "/images/logos/instagram.svg", alt: "" }) }) }), _jsx("a", { onClick: () => location.href = 'https://www.youtube.com/@tosel_official', children: _jsx("div", { className: cn(iconBox), children: _jsx("img", { className: cn(socialIconControl), src: "/images/logos/youtube.svg", alt: "" }) }) })] })] }) }));
43
+ return (_jsx("div", { className: cn(container), children: _jsxs("div", { className: cn(body), children: [_jsxs("div", { className: cn(logoWrapper), children: [_jsx("img", { className: cn(svgController), src: "/images/logos/logo-tosel-main.svg", alt: "" }), _jsx("img", { className: cn(svgController), src: "/images/logos/logo-itc-main.svg", alt: "" })] }), _jsxs("div", { className: "flex flex-wrap justify-between items-center border-b-1 border-gray-dark pb-4 mt-5 font-medium gap-y-1", children: [_jsx("div", { children: "Copyright TOSEL. \u24D2 All Rights Reserved." }), _jsx("div", { className: "flex gap-5", children: buttons.map((button, index) => (_jsxs("div", { onClick: button.onClick, className: "cursor-default", children: [button.title, " "] }, index))) })] }), _jsxs("div", { className: cn(infoSet), children: [_jsx("div", { className: cn(infoTitle), children: "\uACE0\uAC1D\uBB38\uC758" }), _jsxs("div", { className: cn(info), children: ["\uB300\uD45C\uBC88\uD638 | 02-923-0505", _jsx("br", {}), " \uAC1C\uC778\uBB38\uC758 | tosel_cs@tosel.co.kr ", _jsx("br", {}), "\uB2E8\uCCB4\uBB38\uC758 | tosel_academy@tosel.co.kr"] })] }), _jsxs("div", { className: cn(infoSet), children: [_jsx("div", { className: cn(infoTitle), children: "\uAD6D\uC81C\uD1A0\uC140\uC704\uC6D0\uD68C" }), _jsxs("div", { className: cn(info), children: ["\uC6F9\uC11C\uBE44\uC2A4: \uC8FC\uC2DD\uD68C\uC0AC \uC5D0\uB4C0\uD1A0\uC140 | \uD1B5\uC2E0\uD310\uB9E4\uC5C5\uC2E0\uACE0\uBC88\uD638: \uC81C 2012-\uC11C\uC6B8\uC131\uBD81-0083\uD638", _jsx("br", {}), " \uC11C\uC6B8\uC2DC \uC131\uBD81\uAD6C \uC548\uC554\uB85C 145 \uACE0\uB824\uB300\uD559\uAD50 \uB77C\uC774\uC2DC\uC6C0 4\uCE35", _jsx("br", {}), " Lyceum Korea University, 145 Anam Ro, Seongbuk-Gu, Seoul, Korea 02841"] })] }), _jsxs("div", { className: cn(iconWrapper), children: [_jsx("a", { onClick: () => (location.href = "https://blog.naver.com/ebs1503"), children: _jsx("div", { className: cn(iconBox), children: _jsx("img", { className: cn(socialIconControl), src: "/images/logos/naver.svg", alt: "" }) }) }), _jsx("a", { onClick: () => (location.href = "https://www.instagram.com/tosel_official/"), children: _jsx("div", { className: cn(iconBox), children: _jsx("img", { className: cn(socialIconControl), src: "/images/logos/instagram.svg", alt: "" }) }) }), _jsx("a", { onClick: () => (location.href = "https://www.youtube.com/@tosel_official"), children: _jsx("div", { className: cn(iconBox), children: _jsx("img", { className: cn(socialIconControl), src: "/images/logos/youtube.svg", alt: "" }) }) })] })] }) }));
44
44
  }
45
45
  const buttons = [
46
- // {
47
- // title: "이용약관",
48
- // },
49
- // {
50
- // title: "개인정보 처리방침",
51
- // },
52
- // {
53
- // title: "FAQ",
54
- // },
46
+ // {
47
+ // title: "이용약관",
48
+ // },
49
+ // {
50
+ // title: "개인정보 처리방침",
51
+ // },
52
+ {
53
+ title: "FAQ",
54
+ onClick: () => (window.location.href =
55
+ "https://dull-marmoset-39f.notion.site/TOSEL-FAQ-4054b35db6fc421c9495039e769992a3"),
56
+ },
55
57
  ];
@@ -11,9 +11,9 @@ export default function Confirm(props) {
11
11
  styles: className ?? "mt-2.5",
12
12
  };
13
13
  return (_jsx(ConfirmModalDesign, { ...props, children: _jsx("div", { className: cn(container), children: props.widgets?.map((widget, index) => (_createElement(ConfirmModalWidget, { ...widget, key: index }))) }), option: {
14
- ...props.option,
15
14
  width: "md",
16
15
  height: "lg",
16
+ ...props.option,
17
17
  } }));
18
18
  }
19
19
  function ConfirmModalWidget({ type, data }) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@edu-tosel/design",
3
- "version": "1.0.140",
3
+ "version": "1.0.142",
4
4
  "description": "UI components for International TOSEL Committee",
5
5
  "keywords": [
6
6
  "jsx",
@@ -0,0 +1 @@
1
+ export declare const getMaxBday: () => Record<string, string>;
@@ -0,0 +1,23 @@
1
+ // utils/getMaxBday.ts
2
+ export const getMaxBday = () => {
3
+ const maxBday = {};
4
+ const today = new Date();
5
+ const currentYear = today.getFullYear();
6
+ const levelAges = {
7
+ PS: 5,
8
+ ST: 10,
9
+ BA: 15,
10
+ JR: 20,
11
+ HJ: 18,
12
+ };
13
+ for (const [level, maxAge] of Object.entries(levelAges)) {
14
+ const maxBirthYear = currentYear - maxAge;
15
+ const maxBirthDate = new Date(maxBirthYear, 11, 31);
16
+ const year = maxBirthDate.getFullYear();
17
+ const month = String(maxBirthDate.getMonth() + 1).padStart(2, "0");
18
+ const day = String(maxBirthDate.getDate()).padStart(2, "0");
19
+ const formattedDate = `${year}년 ${month}월 ${day}일`;
20
+ maxBday[level] = formattedDate;
21
+ }
22
+ return maxBday;
23
+ };
package/version.txt CHANGED
@@ -1 +1 @@
1
- 1.0.140
1
+ 1.0.142
@@ -1,75 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { useState } from "react";
3
- import { IoIosSearch } from "react-icons/io";
4
- import dayjs from "dayjs";
5
- import { cn, isHTMLString } from "../../../util";
6
- export default function Container({ events }) {
7
- const [selectedEvent, setSelectedEvent] = useState(null);
8
- const [filter, setFilter] = useState("모두보기");
9
- const [searchQuery, setSearchQuery] = useState("");
10
- const handleCardClick = (event) => {
11
- setSelectedEvent(event);
12
- };
13
- const handleBackToList = () => {
14
- setSelectedEvent(null);
15
- };
16
- const getStatusText = (event) => {
17
- const now = dayjs();
18
- const startedAt = dayjs(event.startedAt);
19
- const expiredAt = event.expiredAt
20
- ? dayjs(event.expiredAt)
21
- : dayjs(event.endData);
22
- if (event.type === "event") {
23
- if (event.expiredAt) {
24
- if (now.isBefore(startedAt)) {
25
- return (_jsx("span", { className: "px-2 py-1 text-2xs font-semibold rounded-md bg-green-dark text-white", children: "\uC624\uD508\uC608\uC815" }));
26
- }
27
- else if (now.isAfter(expiredAt)) {
28
- return (_jsx("span", { className: "px-2 py-1 text-2xs font-semibold rounded-md bg-gray-light text-gray-mid", children: "\uB9C8\uAC10" }));
29
- }
30
- else {
31
- const diff = expiredAt.diff(now, "day");
32
- return (_jsxs("span", { className: "px-2 py-1 text-2xs font-semibold rounded-md bg-green-dark/10 text-green-dark", children: ["\uC9C4\uD589\uC911 | D-", diff] }));
33
- }
34
- }
35
- else {
36
- return (_jsx("div", { className: "w-[63px] h-[22px] rounded-md bg-black flex items-center justify-center", style: {
37
- background: "linear-gradient(269deg, rgba(118, 0, 35, 0.10) 0%, rgba(16, 86, 82, 0.10) 100%)",
38
- }, children: _jsx("div", { className: "px-2 py-1 text-2xs font-semibold rounded-md", style: {
39
- background: "linear-gradient(269deg, rgba(118, 0, 35) 0%, rgba(16, 86, 82) 100%)",
40
- WebkitBackgroundClip: "text",
41
- WebkitTextFillColor: "transparent",
42
- }, children: "\uC0C1\uC2DC \uC774\uBCA4\uD2B8" }) }));
43
- }
44
- }
45
- else if (event.type === "notice") {
46
- return (_jsx("span", { className: "px-2 py-1 text-2xs font-semibold rounded-md bg-blue-navy/10 text-blue-navy", children: "\uD1A0\uC140 \uC18C\uC2DD" }));
47
- }
48
- else {
49
- return "";
50
- }
51
- };
52
- const filteredEvents = events
53
- .filter((event) => {
54
- const now = dayjs();
55
- const startedAt = dayjs(event.startedAt);
56
- const expiredAt = dayjs(event.expiredAt);
57
- if (filter === "모두보기")
58
- return true;
59
- if (filter === "진행 중") {
60
- return (event.startedAt && now.isAfter(startedAt) && now.isBefore(expiredAt));
61
- }
62
- if (filter === "예정된") {
63
- return event.startedAt && now.isBefore(startedAt);
64
- }
65
- if (filter === "토셀소식")
66
- return event.type === "notice";
67
- return false;
68
- })
69
- .filter((event) => event.title.includes(searchQuery));
70
- const button = () => ({
71
- sizes: "w-full h-12 flex items-center justify-center rounded-md text-white cursor-pointer font-bold gap-3 text-sm xs:text-md",
72
- backgrounds: "bg-gradient-to-l from-[#760023] to-[#105652]",
73
- });
74
- return (_jsx("div", { className: "min-h-screen w-full mx-auto", children: _jsx("div", { className: "mmd:max-w-300 h-full flex flex-col mx-auto px-10", children: selectedEvent ? (_jsxs("div", { className: "flex flex-col mmd:flex-row", children: [_jsx("div", { className: "min-w-[320px] h-auto p-5 mmd:sticky mmd:top-20 mmd:self-start", children: _jsxs("div", { className: "w-full h-auto rounded-xl sm:flex mmd:flex-col", children: [_jsx("div", { className: "w-full mmd:h-50 overflow-hidden", children: _jsx("img", { src: selectedEvent.thumbnail, alt: "", className: "rounded-xl h-full object-cover w-full" }) }), _jsxs("div", { className: "w-full h-auto pt-5 sm:p-5 mmd:p-0 mmd:pt-5 gap-3 flex flex-col", children: [_jsx("div", { className: "flex items-center", children: getStatusText(selectedEvent) }), _jsx("div", { className: "text-sm font-bold text-gray-dark flex items-center mb-2", children: selectedEvent.title }), selectedEvent.button && (_jsx("div", { onClick: selectedEvent.button.onClick, className: cn(button()), children: selectedEvent.button?.title }))] })] }, selectedEvent.id) }), _jsxs("div", { className: "flex-grow p-5", children: [_jsx("div", { children: isHTMLString(selectedEvent.content) ? (_jsx("div", { dangerouslySetInnerHTML: { __html: selectedEvent.content }, className: "w-full rounded-xl object-cover overflow-hidden" })) : (_jsx("div", { children: selectedEvent.content })) }), _jsx("button", { onClick: handleBackToList, className: "p-5 bg-green-dark/5 text-green-dark rounded-xl flex items-center justify-center hover:bg-green-dark/20 transition-all", children: "\uBAA9\uB85D\uC73C\uB85C \uB3CC\uC544\uAC00\uAE30" })] })] })) : (_jsxs(_Fragment, { children: [_jsxs("div", { className: "flex flex-col sm:flex-row justify-between min-h-14.5 border-b-1", children: [_jsxs("div", { className: "w-full mb-5 h-9 sm:w-80 sm:h-9.5 flex items-center bg-[#f0f0f0]/10 rounded-xl", children: [_jsx(IoIosSearch, { className: "text-xl text-green-dark mr-3" }), _jsx("input", { type: "text", placeholder: "\uD0A4\uC6CC\uB4DC\uB97C \uC785\uB825\uD558\uC138\uC694.", value: searchQuery, onChange: (e) => setSearchQuery(e.target.value), className: "w-full h-full text-sm bg-[#f0f0f0]/10 placeholder:text-[#7f7f7f] placeholder:font-light outline-none" })] }), _jsx("div", { className: "flex h-9 pb-5 sm:pb-0 sm:h-9.5 items-center sm:justify-center ", children: ["모두보기", "진행 중", "예정된", "토셀소식"].map((item) => (_jsx("div", { className: `text-xs sm:text-2xs md:text-xs p-2 sm:p-3 flex items-center justify-center cursor-pointer rounded-lg ${filter === item ? "bg-green-dark/10 text-green-dark" : ""}`, onClick: () => setFilter(item), children: item }, item))) })] }), _jsx("div", { className: "pt-5 flex grid sm:grid-cols-2 mmd:grid-cols-3 gap-5 rounded-xl", children: filteredEvents.map((event) => (_jsxs("div", { onClick: () => handleCardClick(event), className: "w-full max-h-84 shadow-md rounded-xl cursor-pointer box-shadow-green transition-all duration-500", children: [_jsx("div", { className: "w-full max-h-50 rounded-t-xl overflow-hidden relative", children: _jsx("img", { src: event.thumbnail, alt: "", className: "w-full" }) }), _jsxs("div", { className: "w-full min-h-34 p-8 gap-3 flex flex-col", children: [_jsx("div", { className: "flex items-center", children: getStatusText(event) }), _jsx("div", { className: "text-sm font-bold text-gray-dark flex items-center", children: event.title })] })] }, event.id))) })] })) }) }));
75
- }