@kusitms/ui 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs ADDED
@@ -0,0 +1,1360 @@
1
+ 'use strict';
2
+
3
+ var icons = require('@kusitms/icons');
4
+ var RadixAccordion = require('@radix-ui/react-accordion');
5
+ var react = require('react');
6
+ var jsxRuntime = require('react/jsx-runtime');
7
+ var RadixSelect = require('@radix-ui/react-select');
8
+
9
+ function _interopNamespace(e) {
10
+ if (e && e.__esModule) return e;
11
+ var n = Object.create(null);
12
+ if (e) {
13
+ Object.keys(e).forEach(function (k) {
14
+ if (k !== 'default') {
15
+ var d = Object.getOwnPropertyDescriptor(e, k);
16
+ Object.defineProperty(n, k, d.get ? d : {
17
+ enumerable: true,
18
+ get: function () { return e[k]; }
19
+ });
20
+ }
21
+ });
22
+ }
23
+ n.default = e;
24
+ return Object.freeze(n);
25
+ }
26
+
27
+ var RadixAccordion__namespace = /*#__PURE__*/_interopNamespace(RadixAccordion);
28
+ var RadixSelect__namespace = /*#__PURE__*/_interopNamespace(RadixSelect);
29
+
30
+ // src/components/Accordion/Accordion.tsx
31
+
32
+ // src/utils/cn.ts
33
+ function cn(...values) {
34
+ return values.filter(Boolean).join(" ");
35
+ }
36
+ function AccordionRoot({ className, children, ...props }) {
37
+ return /* @__PURE__ */ jsxRuntime.jsx(
38
+ RadixAccordion__namespace.Root,
39
+ {
40
+ className: cn("flex w-full flex-col gap-2 lg:gap-3", className),
41
+ ...props,
42
+ children
43
+ }
44
+ );
45
+ }
46
+ function AccordionItem({
47
+ value,
48
+ question,
49
+ answer,
50
+ className
51
+ }) {
52
+ const itemRef = react.useRef(null);
53
+ const innerRef = react.useRef(null);
54
+ const [isOpen, setIsOpen] = react.useState(false);
55
+ const [height, setHeight] = react.useState(0);
56
+ react.useEffect(() => {
57
+ const item = itemRef.current;
58
+ if (!item) return;
59
+ const update = () => {
60
+ const open = item.getAttribute("data-state") === "open";
61
+ setIsOpen(open);
62
+ setHeight(open ? innerRef.current?.scrollHeight ?? 0 : 0);
63
+ };
64
+ update();
65
+ const observer = new MutationObserver(update);
66
+ observer.observe(item, {
67
+ attributes: true,
68
+ attributeFilter: ["data-state"]
69
+ });
70
+ return () => observer.disconnect();
71
+ }, []);
72
+ return /* @__PURE__ */ jsxRuntime.jsxs(
73
+ RadixAccordion__namespace.Item,
74
+ {
75
+ ref: itemRef,
76
+ value,
77
+ className: cn(
78
+ "w-full bg-fill-netural",
79
+ "rounded-2xl px-5 py-4",
80
+ "lg:rounded-5 lg:px-10 lg:py-8",
81
+ className
82
+ ),
83
+ children: [
84
+ /* @__PURE__ */ jsxRuntime.jsx(RadixAccordion__namespace.Header, { className: "flex", children: /* @__PURE__ */ jsxRuntime.jsxs(
85
+ RadixAccordion__namespace.Trigger,
86
+ {
87
+ className: cn(
88
+ "group flex w-full cursor-pointer items-center justify-between gap-2 text-left outline-none",
89
+ "focus-visible:rounded-md focus-visible:ring-2 focus-visible:ring-brand-primary/40"
90
+ ),
91
+ children: [
92
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex min-w-0 flex-1 items-start gap-1 lg:items-center lg:gap-2", children: [
93
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0 text-center text-body-18sb text-brand-primary lg:w-5.75 lg:pb-1 lg:text-headline-24sb", children: "Q." }),
94
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 flex-1 pt-0.5 text-body-16m text-label-normal lg:pt-0 lg:text-headline-24sb", children: question })
95
+ ] }),
96
+ /* @__PURE__ */ jsxRuntime.jsx(
97
+ icons.ToggleOpenSIcon,
98
+ {
99
+ "aria-hidden": true,
100
+ className: cn(
101
+ "shrink-0 text-label-normal transition-transform duration-200",
102
+ "size-5 lg:size-6",
103
+ "group-data-[state=open]:-rotate-180"
104
+ )
105
+ }
106
+ )
107
+ ]
108
+ }
109
+ ) }),
110
+ /* @__PURE__ */ jsxRuntime.jsx(RadixAccordion__namespace.Content, { forceMount: true, children: /* @__PURE__ */ jsxRuntime.jsx(
111
+ "div",
112
+ {
113
+ style: {
114
+ height,
115
+ overflow: "hidden",
116
+ opacity: isOpen ? 1 : 0,
117
+ transition: [
118
+ `height ${isOpen ? 300 : 500}ms cubic-bezier(0.4, 0, 0.2, 1)`,
119
+ `opacity ${isOpen ? 200 : 400}ms`
120
+ ].join(", ")
121
+ },
122
+ children: /* @__PURE__ */ jsxRuntime.jsx(
123
+ "div",
124
+ {
125
+ ref: innerRef,
126
+ className: "whitespace-pre-line pt-3 text-body-16r text-label-netural lg:text-headline-20r",
127
+ children: answer
128
+ }
129
+ )
130
+ }
131
+ ) })
132
+ ]
133
+ }
134
+ );
135
+ }
136
+ var Accordion = Object.assign(AccordionRoot, {
137
+ Item: AccordionItem
138
+ });
139
+ function getChipClasses(type) {
140
+ switch (type) {
141
+ case "brand":
142
+ return cn(
143
+ "inline-flex items-center justify-center rounded px-4 py-1",
144
+ "bg-fill-primary text-brand-primary text-label-14sb whitespace-nowrap lg:w-16 lg:h-8"
145
+ );
146
+ case "secondary":
147
+ return cn(
148
+ "inline-flex items-center justify-center rounded-md px-3 py-1",
149
+ "bg-fill-netural text-label-alternative",
150
+ "text-caption-12sb lg:text-label-14sb whitespace-nowrap"
151
+ );
152
+ }
153
+ }
154
+ function Label({
155
+ children,
156
+ className,
157
+ type = "brand",
158
+ description,
159
+ ...props
160
+ }) {
161
+ if (type === "default") {
162
+ return /* @__PURE__ */ jsxRuntime.jsxs(
163
+ "span",
164
+ {
165
+ className: cn("inline-flex self-start items-center gap-2.5", className),
166
+ ...props,
167
+ children: [
168
+ /* @__PURE__ */ jsxRuntime.jsx(
169
+ "span",
170
+ {
171
+ className: cn(
172
+ "inline-flex h-7.5 w-20 items-center justify-center rounded-sm bg-fill-netural",
173
+ "text-label-normal text-label-14sb whitespace-nowrap"
174
+ ),
175
+ children
176
+ }
177
+ ),
178
+ description != null && description !== "" && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-label-alternative text-label-14m whitespace-nowrap", children: description })
179
+ ]
180
+ }
181
+ );
182
+ }
183
+ return /* @__PURE__ */ jsxRuntime.jsx(
184
+ "span",
185
+ {
186
+ className: cn(getChipClasses(type), "self-start", className),
187
+ ...props,
188
+ children
189
+ }
190
+ );
191
+ }
192
+ function Blog({ imageUrl, title, content, labels }) {
193
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-full flex-row gap-3 lg:gap-7 pb-5 lg:pb-8 px-4 lg:pr-8 lg:pl-0", children: [
194
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "size-26 lg:w-60 lg:h-41 rounded-lg bg-fill-netural shrink-0 self-stretch overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
195
+ "img",
196
+ {
197
+ src: imageUrl,
198
+ alt: title,
199
+ className: "block h-full w-full object-cover"
200
+ }
201
+ ) }),
202
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-col gap-2 lg:gap-4 py-1", children: [
203
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-0.5 lg:gap-1", children: [
204
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-body-16b text-label-netural lg:text-headline-20b line-clamp-1", children: title }),
205
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "h-10 lg:h-13 text-label-14m text-label-alternative lg:text-body-16m line-clamp-2", children: content })
206
+ ] }),
207
+ labels.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-row flex-wrap gap-1 lg:gap-2", children: labels.map((label) => /* @__PURE__ */ jsxRuntime.jsx(Label, { type: "secondary", children: label }, label)) })
208
+ ] })
209
+ ] });
210
+ }
211
+ function BottomGradient({
212
+ height = 54,
213
+ className,
214
+ style,
215
+ ...props
216
+ }) {
217
+ return /* @__PURE__ */ jsxRuntime.jsx(
218
+ "div",
219
+ {
220
+ className: `absolute bottom-0 left-1/2 -translate-x-1/2 w-full pointer-events-none ${className ?? ""}`,
221
+ style: { height: `${height}px`, ...style },
222
+ ...props,
223
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 bg-linear-to-b from-transparent to-white rounded-b-2xl" })
224
+ }
225
+ );
226
+ }
227
+ function Button({
228
+ children,
229
+ className,
230
+ disabled,
231
+ showIcon = true,
232
+ ...props
233
+ }) {
234
+ return /* @__PURE__ */ jsxRuntime.jsxs(
235
+ "button",
236
+ {
237
+ type: "button",
238
+ disabled,
239
+ className: cn(
240
+ "group relative overflow-hidden inline-flex items-center justify-center rounded-full transition-colors",
241
+ "py-2 px-3 gap-1 lg:px-6 lg:gap-2",
242
+ disabled ? "text-label-14r lg:text-body-18m bg-fill-alternative text-label-light cursor-not-allowed" : "text-label-14m lg:text-body-18sb bg-brand-primary text-label-contrast cursor-pointer",
243
+ className
244
+ ),
245
+ ...props,
246
+ children: [
247
+ !disabled && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pointer-events-none absolute inset-0 bg-white/0 transition-colors group-hover:bg-white/25 group-active:bg-black/8" }),
248
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: showIcon ? "pl-2" : void 0, children }),
249
+ showIcon && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
250
+ /* @__PURE__ */ jsxRuntime.jsx(
251
+ icons.ArrowRightIcon,
252
+ {
253
+ className: cn(
254
+ "size-5 shrink-0 lg:hidden",
255
+ disabled ? "text-label-light" : "text-label-contrast"
256
+ )
257
+ }
258
+ ),
259
+ /* @__PURE__ */ jsxRuntime.jsx(
260
+ icons.ArrowRightMIcon,
261
+ {
262
+ className: cn(
263
+ "size-6 shrink-0 hidden lg:block",
264
+ disabled ? "text-label-light" : "text-label-contrast"
265
+ )
266
+ }
267
+ )
268
+ ] })
269
+ ]
270
+ }
271
+ );
272
+ }
273
+ function NavigationButton({
274
+ children,
275
+ className,
276
+ icon,
277
+ showArrow = true,
278
+ ...props
279
+ }) {
280
+ return /* @__PURE__ */ jsxRuntime.jsxs(
281
+ "button",
282
+ {
283
+ type: "button",
284
+ className: cn(
285
+ "group relative inline-flex items-center overflow-hidden rounded-lg bg-fill-netural pl-3 pr-2 py-2 gap-2 text-label-netural transition-colors cursor-pointer",
286
+ className
287
+ ),
288
+ ...props,
289
+ children: [
290
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pointer-events-none absolute inset-0 rounded-lg bg-transparent transition-colors group-hover:bg-interaction-hover-inverse" }),
291
+ icon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "relative z-10 inline-flex size-5 shrink-0 items-center justify-center overflow-hidden", children: icon }) : null,
292
+ /* @__PURE__ */ jsxRuntime.jsx(
293
+ "span",
294
+ {
295
+ className: cn(
296
+ "relative z-10 flex-1 text-left text-body-16m",
297
+ !showArrow && "pr-1"
298
+ ),
299
+ children
300
+ }
301
+ ),
302
+ showArrow ? /* @__PURE__ */ jsxRuntime.jsx(
303
+ icons.RightSIcon,
304
+ {
305
+ "aria-hidden": "true",
306
+ className: "relative z-10 size-5 shrink-0 text-label-alternative"
307
+ }
308
+ ) : null
309
+ ]
310
+ }
311
+ );
312
+ }
313
+ function PageNavButton({
314
+ className,
315
+ color = "light",
316
+ direction = "next",
317
+ ...props
318
+ }) {
319
+ return /* @__PURE__ */ jsxRuntime.jsxs(
320
+ "button",
321
+ {
322
+ type: "button",
323
+ "aria-label": direction === "next" ? "\uB2E4\uC74C \uD398\uC774\uC9C0\uB85C \uC774\uB3D9" : "\uC774\uC804 \uD398\uC774\uC9C0\uB85C \uC774\uB3D9",
324
+ className: cn(
325
+ "group relative inline-flex items-center justify-center overflow-hidden rounded-full transition-colors cursor-pointer",
326
+ "size-9 lg:size-13",
327
+ color === "light" ? "bg-fill-transparent-white text-static-white" : "bg-fill-transparent-black text-static-white",
328
+ direction === "prev" ? "rotate-180" : void 0,
329
+ className
330
+ ),
331
+ ...props,
332
+ children: [
333
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pointer-events-none absolute inset-0 rounded-full bg-transparent transition-colors group-active:bg-interaction-pressed" }),
334
+ /* @__PURE__ */ jsxRuntime.jsx(icons.RightSIcon, { className: "relative z-10 size-7 lg:size-10 translate-x-px" })
335
+ ]
336
+ }
337
+ );
338
+ }
339
+ function ScrollTopButton({ className, ...props }) {
340
+ return /* @__PURE__ */ jsxRuntime.jsx(
341
+ "button",
342
+ {
343
+ type: "button",
344
+ "aria-label": "\uB9E8 \uC704\uB85C \uC774\uB3D9",
345
+ className: cn(
346
+ "group relative inline-flex items-center justify-center overflow-hidden rounded-full border transition-colors cursor-pointer",
347
+ "size-10 lg:size-12",
348
+ "border-line-neutral bg-fill-normal text-static-black active:bg-interaction-pressed",
349
+ className
350
+ ),
351
+ ...props,
352
+ children: /* @__PURE__ */ jsxRuntime.jsx(icons.ArrowRightIcon, { "aria-hidden": true, className: "-rotate-90 size-5 lg:size-6" })
353
+ }
354
+ );
355
+ }
356
+ var variantStyles = {
357
+ default: {
358
+ container: "w-75 gap-5 px-4 pt-7 pb-9.5 pt-8.5 lg:pb-8.5 lg:pt-7.5",
359
+ content: ({ description }) => /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-label-14sb text-label-normal lg:text-body-16sb text-center whitespace-pre-line", children: description })
360
+ },
361
+ titled: {
362
+ container: "w-75 lg:w-55 gap-5 px-4 py-5 lg:pb-6.5",
363
+ content: ({ title, description }) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col items-center gap-5 text-center lg:gap-4.5", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3 lg:gap-2.5", children: [
364
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-brand-primary text-body-16b lg:text-body-18b", children: title }),
365
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-3.5 h-[1.5px] bg-line-normal rounded-full mx-auto" }),
366
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-label-normal text-label-14m whitespace-pre-line", children: description })
367
+ ] }) })
368
+ }
369
+ };
370
+ function RecruitmentCard({
371
+ type,
372
+ graphic: Graphic,
373
+ title,
374
+ description
375
+ }) {
376
+ const { container, content } = variantStyles[type];
377
+ return /* @__PURE__ */ jsxRuntime.jsxs(
378
+ "div",
379
+ {
380
+ className: `flex flex-col items-center rounded-2xl bg-fill-primary ${container}`,
381
+ children: [
382
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex size-20 shrink-0 items-center justify-center rounded-full bg-fill-normal", children: /* @__PURE__ */ jsxRuntime.jsx(Graphic, {}) }),
383
+ content({ title, description })
384
+ ]
385
+ }
386
+ );
387
+ }
388
+ function ReviewCard({ name, part, body }) {
389
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-72 lg:w-76 flex flex-col rounded-2xl bg-fill-primary p-5", children: [
390
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-body-16b text-label-normal pb-1 lg:text-body-18b", children: name }),
391
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-label-14sb text-brand-primary pb-3", children: part }),
392
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-label-14m text-label-netural", children: body })
393
+ ] });
394
+ }
395
+ function ShowcaseCard({
396
+ name,
397
+ description,
398
+ th,
399
+ isMeetup = false,
400
+ type,
401
+ imageUrl
402
+ }) {
403
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-85.75 lg:w-96 shrink-0 self-start flex-col rounded-2xl bg-fill-normal shadow-[0_1px_10px_0_rgba(179,179,188,0.25)]", children: [
404
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-47.5 lg:h-64 w-full shrink-0 overflow-hidden rounded-t-2xl bg-fill-alternative", children: /* @__PURE__ */ jsxRuntime.jsx(
405
+ "img",
406
+ {
407
+ src: imageUrl,
408
+ alt: name,
409
+ className: "block h-full w-full object-cover"
410
+ }
411
+ ) }),
412
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col px-4 pt-4 pb-4.5 lg:px-5 lg:pb-5", children: [
413
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5 mb-1", children: [
414
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-label-14b text-brand-primary lg:text-body-18b", children: [
415
+ th,
416
+ "\uAE30"
417
+ ] }),
418
+ isMeetup && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-row gap-1.25 text-label-assitive text-caption-12r", children: [
419
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "\xB7" }),
420
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "lg:text-body-16m", children: type })
421
+ ] })
422
+ ] }),
423
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-label-netural text-body-16b mb-0.5 lg:text-headline-20b", children: name }),
424
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-10 lg:h-13 overflow-hidden shrink-0", children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-label-14m text-label-alternative lg:text-body-18m line-clamp-2", children: description }) })
425
+ ] })
426
+ ] });
427
+ }
428
+ function Dropdown({
429
+ options,
430
+ value,
431
+ defaultValue,
432
+ onValueChange,
433
+ placeholder = "\uC120\uD0DD",
434
+ disabled = false,
435
+ className
436
+ }) {
437
+ return /* @__PURE__ */ jsxRuntime.jsxs(
438
+ RadixSelect__namespace.Root,
439
+ {
440
+ value,
441
+ defaultValue,
442
+ onValueChange,
443
+ disabled,
444
+ children: [
445
+ /* @__PURE__ */ jsxRuntime.jsxs(
446
+ RadixSelect__namespace.Trigger,
447
+ {
448
+ className: cn(
449
+ "group flex cursor-pointer items-center gap-x-2 bg-fill-normal outline-none",
450
+ "border border-line-neutral",
451
+ "rounded-md py-1.5 pl-3 pr-2",
452
+ "lg:rounded-lg lg:py-2.5 lg:pl-5 lg:pr-4",
453
+ "text-label-14sb lg:text-body-18sb text-label-light",
454
+ "disabled:cursor-not-allowed disabled:opacity-40",
455
+ className
456
+ ),
457
+ "aria-label": placeholder,
458
+ children: [
459
+ /* @__PURE__ */ jsxRuntime.jsx(RadixSelect__namespace.Value, { placeholder }),
460
+ /* @__PURE__ */ jsxRuntime.jsx(RadixSelect__namespace.Icon, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
461
+ icons.ToggleOpenSIcon,
462
+ {
463
+ className: cn(
464
+ "shrink-0 text-label-light transition-transform duration-200",
465
+ "size-4 lg:size-5",
466
+ "group-data-[state=open]:-rotate-180"
467
+ )
468
+ }
469
+ ) })
470
+ ]
471
+ }
472
+ ),
473
+ /* @__PURE__ */ jsxRuntime.jsx(RadixSelect__namespace.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
474
+ RadixSelect__namespace.Content,
475
+ {
476
+ position: "popper",
477
+ sideOffset: 4,
478
+ className: cn(
479
+ "z-50 min-w-[var(--radix-select-trigger-width)]",
480
+ "bg-fill-normal rounded-lg p-1",
481
+ "shadow-[0px_1px_10px_rgba(179,179,188,0.25)]",
482
+ "data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
483
+ "data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
484
+ "data-[side=bottom]:slide-in-from-top-2"
485
+ ),
486
+ children: /* @__PURE__ */ jsxRuntime.jsx(RadixSelect__namespace.Viewport, { children: options.map((option) => /* @__PURE__ */ jsxRuntime.jsx(
487
+ RadixSelect__namespace.Item,
488
+ {
489
+ value: option.value,
490
+ className: cn(
491
+ "flex cursor-pointer items-center rounded-md outline-none select-none",
492
+ "text-label-alternative text-label-14m lg:text-body-18m",
493
+ "p-2 lg:px-3 lg:py-2",
494
+ "data-[state=checked]:text-brand-primary data-[state=checked]:text-label-14sb lg:data-[state=checked]:text-body-18sb",
495
+ "data-[highlighted]:bg-fill-netural data-[highlighted]:outline-none"
496
+ ),
497
+ children: /* @__PURE__ */ jsxRuntime.jsx(RadixSelect__namespace.ItemText, { children: option.label })
498
+ },
499
+ option.value
500
+ )) })
501
+ }
502
+ ) })
503
+ ]
504
+ }
505
+ );
506
+ }
507
+ function EmailInput({
508
+ value,
509
+ onChange,
510
+ onSubmit,
511
+ validate,
512
+ buttonLabel = "\uC54C\uB9BC \uBC1B\uAE30",
513
+ buttonProps,
514
+ disabled,
515
+ className,
516
+ placeholder = "\uC774\uBA54\uC77C\uC744 \uC785\uB825\uD558\uC138\uC694",
517
+ ...inputProps
518
+ }) {
519
+ const canSubmit = !disabled && (validate ? validate(value) : value.length > 0);
520
+ const handleSubmit = () => {
521
+ if (!canSubmit) return;
522
+ onSubmit?.(value);
523
+ };
524
+ const handleKeyDown = (event) => {
525
+ if (event.key === "Enter") {
526
+ event.preventDefault();
527
+ handleSubmit();
528
+ }
529
+ };
530
+ return /* @__PURE__ */ jsxRuntime.jsxs(
531
+ "div",
532
+ {
533
+ className: cn(
534
+ "flex items-center rounded-full bg-fill-netural",
535
+ "w-full gap-1 py-2 pl-5 pr-2.5 min-w-72",
536
+ "lg:w-163 lg:gap-2 lg:py-3 lg:pl-7 lg:pr-5",
537
+ className
538
+ ),
539
+ children: [
540
+ /* @__PURE__ */ jsxRuntime.jsx(
541
+ "input",
542
+ {
543
+ type: "email",
544
+ value,
545
+ onChange: (event) => onChange(event.target.value),
546
+ onKeyDown: handleKeyDown,
547
+ disabled,
548
+ placeholder,
549
+ className: cn(
550
+ "min-w-0 flex-1 bg-transparent outline-none",
551
+ "text-label-strong placeholder:text-label-alternative",
552
+ "disabled:cursor-not-allowed",
553
+ "text-body-16m lg:text-headline-20m"
554
+ ),
555
+ ...inputProps
556
+ }
557
+ ),
558
+ /* @__PURE__ */ jsxRuntime.jsx(
559
+ Button,
560
+ {
561
+ showIcon: false,
562
+ disabled: !canSubmit,
563
+ onClick: handleSubmit,
564
+ className: "shrink-0",
565
+ ...buttonProps,
566
+ children: buttonLabel
567
+ }
568
+ )
569
+ ]
570
+ }
571
+ );
572
+ }
573
+ var defaultBylawsLink = (device, href, label = "\uD559\uD68C\uC815\uAD00") => {
574
+ const className = cn(
575
+ "font-sans not-italic text-label-normal",
576
+ device === "desktop" ? "text-body-16sb" : "text-caption-12r"
577
+ );
578
+ if (!href) {
579
+ return /* @__PURE__ */ jsxRuntime.jsx("span", { className, children: label });
580
+ }
581
+ return /* @__PURE__ */ jsxRuntime.jsx("a", { className: `${className} underline decoration-solid`, href, children: label });
582
+ };
583
+ function Footer({
584
+ logo,
585
+ mobileLogo,
586
+ links,
587
+ contactIcons,
588
+ copyright = "KUSITMS (\uD050\uC2DC\uC998, \uD55C\uAD6D\uB300\uD559\uC0DDIT\uACBD\uC601\uD559\uD68C)\n\xA9 2023.KUSITMS. ALL rights reserved.",
589
+ scrollTopButton,
590
+ bylawsHref,
591
+ bylawsLabel = "\uD559\uD68C\uC815\uAD00",
592
+ className,
593
+ ...props
594
+ }) {
595
+ return /* @__PURE__ */ jsxRuntime.jsxs("footer", { className: cn("w-full", "bg-fill-normal", className), ...props, children: [
596
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "hidden w-full flex-col items-center justify-center px-10 pb-15 lg:flex", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-full items-end justify-between", children: [
597
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-68.5 flex-col items-start", children: [
598
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col items-start pb-10 pt-15", children: logo }),
599
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex w-full pb-3", children: links ?? defaultBylawsLink("desktop", bylawsHref, bylawsLabel) }),
600
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "whitespace-pre-wrap font-sans text-body-16sb text-label-normal", children: copyright })
601
+ ] }),
602
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex shrink-0 flex-col items-start gap-5", children: [
603
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "w-full font-sans text-body-16sb text-label-normal", children: "Contact" }),
604
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-5", children: contactIcons })
605
+ ] })
606
+ ] }) }),
607
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex w-full flex-col items-center justify-center px-4 pb-15 lg:hidden", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-full flex-col items-start", children: [
608
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex w-full flex-col items-start", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-full items-start justify-between gap-4", children: [
609
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-1 flex-col items-start", children: [
610
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pb-4 pt-15", children: mobileLogo ?? logo }),
611
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pb-2", children: links ?? defaultBylawsLink("mobile", bylawsHref, bylawsLabel) }),
612
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "w-full whitespace-pre-wrap font-sans text-caption-12r text-label-normal", children: copyright })
613
+ ] }),
614
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "shrink-0 pt-13", children: scrollTopButton })
615
+ ] }) }),
616
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-full flex-col items-start gap-2 pt-7", children: [
617
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "w-full font-sans text-body-16sb text-label-normal", children: "Contact" }),
618
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex w-full flex-wrap items-center gap-1.5", children: contactIcons })
619
+ ] })
620
+ ] }) })
621
+ ] });
622
+ }
623
+ function HeaderMobileBar({
624
+ logo,
625
+ menuIcon,
626
+ closeIcon,
627
+ isOpen,
628
+ onToggle,
629
+ menuId
630
+ }) {
631
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-17.25 w-full items-center justify-between bg-fill-normal px-4 py-5", children: [
632
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "shrink-0", children: logo }),
633
+ /* @__PURE__ */ jsxRuntime.jsx(
634
+ "button",
635
+ {
636
+ type: "button",
637
+ className: cn(
638
+ "flex size-6 shrink-0 items-center justify-center transition-transform duration-200",
639
+ isOpen && "rotate-90"
640
+ ),
641
+ onClick: onToggle,
642
+ "aria-controls": menuId,
643
+ "aria-expanded": isOpen,
644
+ "aria-label": isOpen ? "Close navigation menu" : "Open navigation menu",
645
+ children: isOpen ? closeIcon : menuIcon
646
+ }
647
+ )
648
+ ] });
649
+ }
650
+ function HeaderMobileMenu({
651
+ children,
652
+ isOpen,
653
+ menuId
654
+ }) {
655
+ const contentRef = react.useRef(null);
656
+ const [height, setHeight] = react.useState(0);
657
+ const [isVisible, setIsVisible] = react.useState(false);
658
+ const updateHeight = react.useCallback(() => {
659
+ if (isOpen && contentRef.current) {
660
+ setHeight(contentRef.current.scrollHeight);
661
+ }
662
+ }, [isOpen]);
663
+ react.useEffect(() => {
664
+ updateHeight();
665
+ }, [updateHeight]);
666
+ react.useEffect(() => {
667
+ const content = contentRef.current;
668
+ if (!isOpen || !content || typeof ResizeObserver === "undefined") {
669
+ return;
670
+ }
671
+ const observer = new ResizeObserver(updateHeight);
672
+ observer.observe(content);
673
+ return () => observer.disconnect();
674
+ }, [isOpen, updateHeight]);
675
+ react.useEffect(() => {
676
+ if (isOpen) {
677
+ setIsVisible(true);
678
+ }
679
+ }, [isOpen]);
680
+ const handleTransitionEnd = (event) => {
681
+ if (event.target === event.currentTarget && !isOpen) {
682
+ setIsVisible(false);
683
+ }
684
+ };
685
+ return /* @__PURE__ */ jsxRuntime.jsx(
686
+ "div",
687
+ {
688
+ id: menuId,
689
+ className: "overflow-hidden transition-[max-height] duration-300 ease-in-out",
690
+ style: { maxHeight: isOpen ? height : 0 },
691
+ onTransitionEnd: handleTransitionEnd,
692
+ children: /* @__PURE__ */ jsxRuntime.jsx(
693
+ "nav",
694
+ {
695
+ ref: contentRef,
696
+ className: isVisible || isOpen ? "bg-fill-netural" : "hidden",
697
+ children
698
+ }
699
+ )
700
+ }
701
+ );
702
+ }
703
+ function HeaderMobileNavigationItem({
704
+ child
705
+ }) {
706
+ const className = cn(
707
+ "flex w-full flex-col items-center gap-3 bg-fill-netural px-4 py-5"
708
+ );
709
+ const content = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
710
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "w-full overflow-hidden text-ellipsis whitespace-nowrap text-center font-sans text-headline-20sb text-label-normal", children: child.props.children }),
711
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "h-px w-full bg-line-alternative" })
712
+ ] });
713
+ if (child.props.href) {
714
+ return /* @__PURE__ */ jsxRuntime.jsx("a", { className, href: child.props.href, children: content });
715
+ }
716
+ return /* @__PURE__ */ jsxRuntime.jsx("button", { className, type: "button", onClick: child.props.onClick, children: content });
717
+ }
718
+ function HeaderMobileNavigation({ children }) {
719
+ return react.Children.map(children, (child) => {
720
+ if (!react.isValidElement(child)) {
721
+ return child;
722
+ }
723
+ return /* @__PURE__ */ jsxRuntime.jsx(HeaderMobileNavigationItem, { child });
724
+ });
725
+ }
726
+ function Header2({
727
+ logo,
728
+ children,
729
+ mobileLogo,
730
+ menuIcon,
731
+ closeIcon,
732
+ isOpen,
733
+ defaultOpen = false,
734
+ onOpenChange,
735
+ menuId,
736
+ className,
737
+ ...props
738
+ }) {
739
+ const generatedMenuId = react.useId();
740
+ const [uncontrolledOpen, setUncontrolledOpen] = react.useState(defaultOpen);
741
+ const hasResponsiveHeader = Boolean(mobileLogo || menuIcon || closeIcon);
742
+ const isMenuOpen = isOpen ?? uncontrolledOpen;
743
+ const resolvedMenuId = menuId ?? generatedMenuId;
744
+ const handleToggle = () => {
745
+ const nextOpen = !isMenuOpen;
746
+ if (isOpen === void 0) {
747
+ setUncontrolledOpen(nextOpen);
748
+ }
749
+ onOpenChange?.(nextOpen);
750
+ };
751
+ if (hasResponsiveHeader) {
752
+ return /* @__PURE__ */ jsxRuntime.jsxs("header", { className: cn("w-full bg-fill-normal", className), ...props, children: [
753
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "hidden items-center justify-between px-10 py-6 lg:flex", children: [
754
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "shrink-0", children: logo }),
755
+ /* @__PURE__ */ jsxRuntime.jsx("nav", { className: "flex min-w-0 items-center justify-end gap-6 overflow-hidden", children })
756
+ ] }),
757
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "lg:hidden", children: [
758
+ /* @__PURE__ */ jsxRuntime.jsx(
759
+ HeaderMobileBar,
760
+ {
761
+ logo: mobileLogo ?? logo,
762
+ menuIcon,
763
+ closeIcon,
764
+ isOpen: isMenuOpen,
765
+ onToggle: handleToggle,
766
+ menuId: resolvedMenuId
767
+ }
768
+ ),
769
+ /* @__PURE__ */ jsxRuntime.jsx(HeaderMobileMenu, { menuId: resolvedMenuId, isOpen: isMenuOpen, children: /* @__PURE__ */ jsxRuntime.jsx(HeaderMobileNavigation, { children }) })
770
+ ] })
771
+ ] });
772
+ }
773
+ return /* @__PURE__ */ jsxRuntime.jsxs(
774
+ "header",
775
+ {
776
+ className: cn(
777
+ "flex items-center justify-between",
778
+ "w-full",
779
+ "bg-fill-normal px-10 py-6",
780
+ className
781
+ ),
782
+ ...props,
783
+ children: [
784
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "shrink-0", children: logo }),
785
+ /* @__PURE__ */ jsxRuntime.jsx("nav", { className: "flex min-w-0 items-center justify-end gap-6 overflow-hidden", children })
786
+ ]
787
+ }
788
+ );
789
+ }
790
+ var stateStyles = {
791
+ default: "text-body-16m text-label-light hover:text-body-16b hover:text-label-normal active:text-body-16b active:text-brand-primary",
792
+ hovered: "text-body-16b text-label-normal",
793
+ pressed: "text-body-16b text-brand-primary"
794
+ };
795
+ function isLinkProps(props) {
796
+ return "href" in props && typeof props.href === "string";
797
+ }
798
+ function HeaderNavigation({
799
+ children,
800
+ className,
801
+ state = "default",
802
+ ...props
803
+ }) {
804
+ const sharedClassName = cn(
805
+ "flex max-w-full items-center justify-center overflow-hidden text-ellipsis whitespace-nowrap px-4",
806
+ "font-sans transition-colors",
807
+ stateStyles[state],
808
+ className
809
+ );
810
+ if (isLinkProps(props)) {
811
+ const linkProps = props;
812
+ return /* @__PURE__ */ jsxRuntime.jsx("a", { className: sharedClassName, ...linkProps, children });
813
+ }
814
+ const buttonProps = props;
815
+ return /* @__PURE__ */ jsxRuntime.jsx("button", { className: sharedClassName, ...buttonProps, type: "button", children });
816
+ }
817
+ function List({ title, items }) {
818
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3", children: [
819
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 px-1", children: [
820
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-5.5 h-6 lg:w-7.5 lg:h-8 shrink-0", children: /* @__PURE__ */ jsxRuntime.jsx(icons.SnowGraphic, { className: "w-full h-full" }) }),
821
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-body-16b text-label-normal lg:text-headline-20b", children: title })
822
+ ] }),
823
+ /* @__PURE__ */ jsxRuntime.jsxs("ul", { className: "list-disc list-inside space-y-3 rounded-2xl bg-fill-netural px-4 py-6 lg:px-6 lg:py-7 w-236", children: [
824
+ /* @__PURE__ */ jsxRuntime.jsx("li", { className: "text-body-16m text-label-netural lg:text-body-18m truncate", children: items[0] }),
825
+ /* @__PURE__ */ jsxRuntime.jsx("li", { className: "text-body-16m text-label-netural lg:text-body-18m truncate", children: items[1] }),
826
+ /* @__PURE__ */ jsxRuntime.jsx("li", { className: "text-body-16m text-label-netural lg:text-body-18m truncate", children: items[2] })
827
+ ] })
828
+ ] });
829
+ }
830
+ var LINK_ICONS = {
831
+ behance: icons.BehanceIcon,
832
+ github: icons.GithubIcon,
833
+ service: icons.LinkIcon
834
+ };
835
+ function ModalLinkIcon({ type }) {
836
+ const Icon2 = LINK_ICONS[type];
837
+ return /* @__PURE__ */ jsxRuntime.jsx(Icon2, { className: "size-5 shrink-0" });
838
+ }
839
+ function Modal({
840
+ isOpen,
841
+ onClose,
842
+ onPrev,
843
+ onNext,
844
+ name,
845
+ th,
846
+ type,
847
+ imageUrl,
848
+ description,
849
+ teamRoles = [],
850
+ links = []
851
+ }) {
852
+ react.useEffect(() => {
853
+ if (!isOpen) return;
854
+ const prev = document.body.style.overflow;
855
+ document.body.style.overflow = "hidden";
856
+ return () => {
857
+ document.body.style.overflow = prev;
858
+ };
859
+ }, [isOpen]);
860
+ react.useEffect(() => {
861
+ if (!isOpen) return;
862
+ const handleKey = (e) => {
863
+ if (e.key === "Escape") onClose();
864
+ };
865
+ window.addEventListener("keydown", handleKey);
866
+ return () => window.removeEventListener("keydown", handleKey);
867
+ }, [isOpen, onClose]);
868
+ if (!isOpen) return null;
869
+ const hasNav = !!(onPrev || onNext);
870
+ return /* @__PURE__ */ jsxRuntime.jsxs(
871
+ "div",
872
+ {
873
+ className: "fixed inset-0 z-50 overflow-y-auto",
874
+ role: "dialog",
875
+ "aria-modal": "true",
876
+ "aria-label": name,
877
+ children: [
878
+ /* @__PURE__ */ jsxRuntime.jsx(
879
+ "div",
880
+ {
881
+ className: "fixed inset-0 bg-effect-dimmer",
882
+ onClick: onClose,
883
+ "aria-hidden": "true"
884
+ }
885
+ ),
886
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex min-h-full items-start lg:items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center", children: [
887
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center", children: [
888
+ hasNav && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "hidden lg:flex mr-5", children: /* @__PURE__ */ jsxRuntime.jsx(
889
+ PageNavButton,
890
+ {
891
+ direction: "prev",
892
+ color: "light",
893
+ onClick: onPrev,
894
+ className: !onPrev ? "invisible pointer-events-none" : ""
895
+ }
896
+ ) }),
897
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex w-83.75 lg:w-156 max-h-144 lg:max-h-231.5 flex-col rounded-2xl bg-fill-normal overflow-hidden", children: [
898
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "shrink-0 border-b-2 border-line-alternative p-4 lg:pl-7 lg:pr-8 lg:py-6", children: /* @__PURE__ */ jsxRuntime.jsx(
899
+ "button",
900
+ {
901
+ type: "button",
902
+ "aria-label": "\uB2EB\uAE30",
903
+ onClick: onClose,
904
+ className: "flex items-center justify-center text-label-alternative cursor-pointer",
905
+ children: /* @__PURE__ */ jsxRuntime.jsx(icons.CancelMIcon, { "aria-hidden": true, className: "size-5 lg:size-8" })
906
+ }
907
+ ) }),
908
+ /* @__PURE__ */ jsxRuntime.jsx(
909
+ "div",
910
+ {
911
+ className: cn(
912
+ "flex-1 min-h-0 overflow-y-auto pt-3 pb-4 lg:pt-5 lg:pb-8",
913
+ "[&::-webkit-scrollbar]:w-0.75",
914
+ "[&::-webkit-scrollbar-track]:bg-transparent [&::-webkit-scrollbar-track]:rounded-full",
915
+ "[&::-webkit-scrollbar-thumb]:rounded-full [&::-webkit-scrollbar-thumb]:bg-label-normal/75 [&::-webkit-scrollbar-thumb]:h-16"
916
+ ),
917
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-5 lg:px-8", children: [
918
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 flex-wrap", children: [
919
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-headline-20b lg:text-pc-30b text-label-normal", children: name }),
920
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-1.5 lg:gap-2", children: [
921
+ /* @__PURE__ */ jsxRuntime.jsxs(Label, { type: "brand", children: [
922
+ th,
923
+ "\uAE30"
924
+ ] }),
925
+ /* @__PURE__ */ jsxRuntime.jsx(Label, { type: "brand", children: type })
926
+ ] })
927
+ ] }),
928
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pt-4 lg:pt-5 pb-6 lg:pb-5", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full overflow-hidden rounded-xl border border-line-neutral bg-fill-alternative aspect-video", children: /* @__PURE__ */ jsxRuntime.jsx(
929
+ "img",
930
+ {
931
+ src: imageUrl,
932
+ alt: name,
933
+ className: "block h-full w-full object-cover"
934
+ }
935
+ ) }) }),
936
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-5 lg:gap-8", children: [
937
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1 lg:gap-2", children: [
938
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-body-16b lg:text-body-18b text-label-netural", children: "\uD504\uB85C\uC81D\uD2B8 \uC124\uBA85" }),
939
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-label-light text-body-16r lg:text-body-16m lg:text-label-alternative", children: description })
940
+ ] }),
941
+ (teamRoles.length > 0 || links.length > 0) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-5 lg:flex-row lg:gap-8", children: [
942
+ teamRoles.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2 lg:gap-3 lg:flex-1", children: [
943
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-body-16b lg:text-body-18b text-label-netural", children: "\uD504\uB85C\uC81D\uD2B8 \uD300\uC6D0" }),
944
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-1.5", children: teamRoles.map(({ role, members }) => /* @__PURE__ */ jsxRuntime.jsxs(
945
+ "div",
946
+ {
947
+ className: "flex items-center gap-2.5",
948
+ children: [
949
+ /* @__PURE__ */ jsxRuntime.jsx(Label, { type: "default", children: role }),
950
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-label-14m text-label-alternative", children: members.join(", ") })
951
+ ]
952
+ },
953
+ role
954
+ )) })
955
+ ] }),
956
+ links.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2 lg:flex-1", children: [
957
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-body-16b lg:text-body-18b text-label-netural", children: "\uB9C1\uD06C" }),
958
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-2 items-start", children: links.map(({ type: linkType, label, url }) => /* @__PURE__ */ jsxRuntime.jsx(
959
+ NavigationButton,
960
+ {
961
+ icon: /* @__PURE__ */ jsxRuntime.jsx(ModalLinkIcon, { type: linkType }),
962
+ onClick: () => window.open(url, "_blank", "noreferrer"),
963
+ children: label
964
+ },
965
+ url
966
+ )) })
967
+ ] })
968
+ ] })
969
+ ] })
970
+ ] })
971
+ }
972
+ ),
973
+ /* @__PURE__ */ jsxRuntime.jsx(
974
+ BottomGradient,
975
+ {
976
+ height: 48,
977
+ className: "lg:left-5! lg:right-5! lg:w-auto! lg:translate-x-0!"
978
+ }
979
+ )
980
+ ] }),
981
+ hasNav && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "hidden lg:flex ml-5", children: /* @__PURE__ */ jsxRuntime.jsx(
982
+ PageNavButton,
983
+ {
984
+ direction: "next",
985
+ color: "light",
986
+ onClick: onNext,
987
+ className: !onNext ? "invisible pointer-events-none" : ""
988
+ }
989
+ ) })
990
+ ] }),
991
+ hasNav && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-83.75 justify-between mt-4 lg:hidden", children: [
992
+ /* @__PURE__ */ jsxRuntime.jsx(
993
+ PageNavButton,
994
+ {
995
+ direction: "prev",
996
+ color: "light",
997
+ onClick: onPrev,
998
+ className: !onPrev ? "invisible pointer-events-none" : ""
999
+ }
1000
+ ),
1001
+ /* @__PURE__ */ jsxRuntime.jsx(
1002
+ PageNavButton,
1003
+ {
1004
+ direction: "next",
1005
+ color: "light",
1006
+ onClick: onNext,
1007
+ className: !onNext ? "invisible pointer-events-none" : ""
1008
+ }
1009
+ )
1010
+ ] })
1011
+ ] }) })
1012
+ ]
1013
+ }
1014
+ );
1015
+ }
1016
+ var filterStyles = {
1017
+ desktop: {
1018
+ container: "justify-center gap-5",
1019
+ item: "min-w-30 px-2.5 py-2.5",
1020
+ activeItem: "bg-fill-primary",
1021
+ text: "",
1022
+ activeText: "text-headline-20b text-brand-primary",
1023
+ inactiveText: "text-headline-20m text-label-netural"
1024
+ },
1025
+ mobile: {
1026
+ container: "justify-start gap-1 overflow-x-auto [scrollbar-width:none] [-ms-overflow-style:none]",
1027
+ item: "py-1",
1028
+ activeItem: "bg-fill-primary px-4",
1029
+ inactiveItem: "px-3",
1030
+ text: "",
1031
+ activeText: "text-body-16sb text-brand-primary",
1032
+ inactiveText: "text-body-16m text-label-netural"
1033
+ },
1034
+ responsive: {
1035
+ container: "justify-start gap-1 overflow-x-auto pb-10 [scrollbar-width:none] [-ms-overflow-style:none] lg:justify-center lg:gap-5 lg:overflow-visible lg:px-50 lg:pb-15",
1036
+ item: "py-1 lg:min-w-30 lg:px-2.5 lg:py-2.5",
1037
+ activeItem: "bg-fill-primary px-4 lg:px-2.5",
1038
+ inactiveItem: "px-3 lg:px-2.5",
1039
+ text: "",
1040
+ activeText: "text-body-16sb text-brand-primary lg:text-headline-20b",
1041
+ inactiveText: "text-body-16m text-label-netural lg:text-headline-20m"
1042
+ }
1043
+ };
1044
+ function FilterItem({
1045
+ children,
1046
+ active = false,
1047
+ device = "responsive",
1048
+ className,
1049
+ ...props
1050
+ }) {
1051
+ const styles = filterStyles[device];
1052
+ return /* @__PURE__ */ jsxRuntime.jsx(
1053
+ "button",
1054
+ {
1055
+ "aria-pressed": active,
1056
+ className: cn(
1057
+ "flex shrink-0 items-center justify-center rounded-full whitespace-nowrap",
1058
+ styles.item,
1059
+ active ? styles.activeItem : styles.inactiveItem,
1060
+ className
1061
+ ),
1062
+ type: "button",
1063
+ ...props,
1064
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1065
+ "span",
1066
+ {
1067
+ className: cn(
1068
+ "font-sans",
1069
+ styles.text,
1070
+ active ? styles.activeText : styles.inactiveText
1071
+ ),
1072
+ children
1073
+ }
1074
+ )
1075
+ }
1076
+ );
1077
+ }
1078
+ function NavigationFilter({
1079
+ children,
1080
+ device = "responsive",
1081
+ className,
1082
+ ...props
1083
+ }) {
1084
+ const styles = filterStyles[device];
1085
+ const childrenWithDevice = react.Children.map(children, (child) => {
1086
+ if (!react.isValidElement(child)) {
1087
+ return child;
1088
+ }
1089
+ return react.cloneElement(child, {
1090
+ device: child.props.device ?? device
1091
+ });
1092
+ });
1093
+ return /* @__PURE__ */ jsxRuntime.jsx(
1094
+ "div",
1095
+ {
1096
+ className: cn(
1097
+ "flex w-full items-center",
1098
+ device === "desktop" ? "flex-wrap" : void 0,
1099
+ device === "responsive" ? "lg:flex-wrap" : void 0,
1100
+ styles.container,
1101
+ className
1102
+ ),
1103
+ ...props,
1104
+ children: childrenWithDevice
1105
+ }
1106
+ );
1107
+ }
1108
+ var sizeStyles = {
1109
+ m: {
1110
+ container: "max-w-300",
1111
+ item: "h-31",
1112
+ text: "text-headline-24m",
1113
+ textOffset: "translate-y-4.75",
1114
+ activeText: "text-headline-24sb text-label-normal",
1115
+ inactiveText: "text-label-netural",
1116
+ underline: "after:h-0.75"
1117
+ },
1118
+ s: {
1119
+ container: "max-w-256",
1120
+ item: "h-26",
1121
+ text: "text-body-16m",
1122
+ textOffset: "translate-y-7",
1123
+ activeText: "text-body-16b text-label-normal",
1124
+ inactiveText: "text-label-netural",
1125
+ underline: "after:h-0.5"
1126
+ },
1127
+ responsive: {
1128
+ container: "max-w-256 lg:max-w-300",
1129
+ item: "h-26 lg:h-31",
1130
+ text: "text-body-16m lg:text-headline-24m",
1131
+ textOffset: "translate-y-7 lg:translate-y-4.75",
1132
+ activeText: "text-body-16b text-label-normal lg:text-headline-24sb lg:text-label-normal",
1133
+ inactiveText: "text-label-netural",
1134
+ underline: "after:h-0.5 lg:after:h-0.75"
1135
+ }
1136
+ };
1137
+ function NavigationTabItem({
1138
+ children,
1139
+ active = false,
1140
+ size = "responsive",
1141
+ className,
1142
+ ...props
1143
+ }) {
1144
+ const styles = sizeStyles[size];
1145
+ return /* @__PURE__ */ jsxRuntime.jsx(
1146
+ "button",
1147
+ {
1148
+ className: cn(
1149
+ "relative flex min-w-0 flex-1 basis-0 items-center justify-center border-b border-line-alternative px-4",
1150
+ styles.item,
1151
+ active ? "after:absolute after:bottom-0 after:left-0 after:w-full after:bg-brand-primary" : void 0,
1152
+ active ? styles.underline : void 0,
1153
+ className
1154
+ ),
1155
+ role: "tab",
1156
+ "aria-selected": active,
1157
+ type: "button",
1158
+ ...props,
1159
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1160
+ "span",
1161
+ {
1162
+ className: cn(
1163
+ "max-w-full overflow-hidden text-ellipsis whitespace-nowrap font-sans",
1164
+ styles.text,
1165
+ styles.textOffset,
1166
+ active ? styles.activeText : styles.inactiveText
1167
+ ),
1168
+ children
1169
+ }
1170
+ )
1171
+ }
1172
+ );
1173
+ }
1174
+ function NavigationTab({
1175
+ children,
1176
+ size = "responsive",
1177
+ className,
1178
+ ...props
1179
+ }) {
1180
+ const styles = sizeStyles[size];
1181
+ const childrenWithSize = react.Children.map(children, (child) => {
1182
+ if (!react.isValidElement(child)) {
1183
+ return child;
1184
+ }
1185
+ return react.cloneElement(child, {
1186
+ size: child.props.size ?? size
1187
+ });
1188
+ });
1189
+ return /* @__PURE__ */ jsxRuntime.jsx(
1190
+ "div",
1191
+ {
1192
+ className: cn(
1193
+ "mx-auto flex w-full items-stretch",
1194
+ styles.container,
1195
+ className
1196
+ ),
1197
+ role: "tablist",
1198
+ "aria-orientation": "horizontal",
1199
+ ...props,
1200
+ children: childrenWithSize
1201
+ }
1202
+ );
1203
+ }
1204
+ var paginationControlClassName = "flex size-6 items-center justify-center disabled:pointer-events-none [&_svg]:size-6 [&_svg]:shrink-0";
1205
+ var getPageItems = (currentPage, totalPages) => {
1206
+ if (totalPages <= 7) {
1207
+ return Array.from({ length: totalPages }, (_, i) => i + 1);
1208
+ }
1209
+ const middleStart = Math.max(2, currentPage - 1);
1210
+ const middleEnd = Math.min(totalPages - 1, currentPage + 1);
1211
+ const items = [1];
1212
+ if (middleStart > 2) {
1213
+ items.push("ellipsis-start");
1214
+ }
1215
+ for (let page = middleStart; page <= middleEnd; page += 1) {
1216
+ items.push(page);
1217
+ }
1218
+ if (middleEnd < totalPages - 1) {
1219
+ items.push("ellipsis-end");
1220
+ }
1221
+ items.push(totalPages);
1222
+ return items;
1223
+ };
1224
+ function Pagination({
1225
+ currentPage = 1,
1226
+ totalPages = 5,
1227
+ onPageChange,
1228
+ prevIcon = /* @__PURE__ */ jsxRuntime.jsx(icons.KeyboardArrowLeftIcon, { "aria-hidden": "true" }),
1229
+ nextIcon = /* @__PURE__ */ jsxRuntime.jsx(icons.KeyboardArrowRightIcon, { "aria-hidden": "true" }),
1230
+ firstIcon = /* @__PURE__ */ jsxRuntime.jsx(icons.KeyboardDoubleArrowLeftIcon, { "aria-hidden": "true" }),
1231
+ lastIcon = /* @__PURE__ */ jsxRuntime.jsx(icons.KeyboardDoubleArrowRightIcon, { "aria-hidden": "true" }),
1232
+ className,
1233
+ ...props
1234
+ }) {
1235
+ const safeTotalPages = Math.max(1, Math.floor(totalPages));
1236
+ const safeCurrentPage = Math.min(
1237
+ safeTotalPages,
1238
+ Math.max(1, Math.floor(currentPage))
1239
+ );
1240
+ const pageItems = getPageItems(safeCurrentPage, safeTotalPages);
1241
+ const handlePageChange = (page) => {
1242
+ onPageChange?.(Math.min(safeTotalPages, Math.max(1, page)));
1243
+ };
1244
+ const isFirstPage = safeCurrentPage === 1;
1245
+ const isLastPage = safeCurrentPage === safeTotalPages;
1246
+ const getControlClassName = (disabled) => cn(
1247
+ paginationControlClassName,
1248
+ disabled ? "text-label-disable" : "text-label-normal"
1249
+ );
1250
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1251
+ "div",
1252
+ {
1253
+ className: cn("inline-flex h-11 items-center gap-3 sm:gap-5", className),
1254
+ ...props,
1255
+ children: [
1256
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
1257
+ /* @__PURE__ */ jsxRuntime.jsx(
1258
+ "button",
1259
+ {
1260
+ type: "button",
1261
+ className: cn(getControlClassName(isFirstPage), "hidden sm:flex"),
1262
+ onClick: () => handlePageChange(1),
1263
+ disabled: isFirstPage,
1264
+ "aria-label": "First page",
1265
+ children: firstIcon
1266
+ }
1267
+ ),
1268
+ /* @__PURE__ */ jsxRuntime.jsx(
1269
+ "button",
1270
+ {
1271
+ type: "button",
1272
+ className: getControlClassName(isFirstPage),
1273
+ onClick: () => handlePageChange(safeCurrentPage - 1),
1274
+ disabled: isFirstPage,
1275
+ "aria-label": "Previous page",
1276
+ children: prevIcon
1277
+ }
1278
+ )
1279
+ ] }),
1280
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2 sm:gap-3", children: pageItems.map((pageItem) => {
1281
+ if (typeof pageItem !== "number") {
1282
+ return /* @__PURE__ */ jsxRuntime.jsx(
1283
+ "span",
1284
+ {
1285
+ "aria-hidden": "true",
1286
+ className: "font-sans text-body-16m text-label-disable",
1287
+ children: "..."
1288
+ },
1289
+ pageItem
1290
+ );
1291
+ }
1292
+ return /* @__PURE__ */ jsxRuntime.jsx(
1293
+ "button",
1294
+ {
1295
+ type: "button",
1296
+ className: cn(
1297
+ "whitespace-nowrap font-sans",
1298
+ pageItem === safeCurrentPage ? "text-body-16b text-label-normal" : "text-body-16m text-label-disable"
1299
+ ),
1300
+ onClick: () => handlePageChange(pageItem),
1301
+ "aria-current": pageItem === safeCurrentPage ? "page" : void 0,
1302
+ children: pageItem
1303
+ },
1304
+ pageItem
1305
+ );
1306
+ }) }),
1307
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
1308
+ /* @__PURE__ */ jsxRuntime.jsx(
1309
+ "button",
1310
+ {
1311
+ type: "button",
1312
+ className: getControlClassName(isLastPage),
1313
+ onClick: () => handlePageChange(safeCurrentPage + 1),
1314
+ disabled: isLastPage,
1315
+ "aria-label": "Next page",
1316
+ children: nextIcon
1317
+ }
1318
+ ),
1319
+ /* @__PURE__ */ jsxRuntime.jsx(
1320
+ "button",
1321
+ {
1322
+ type: "button",
1323
+ className: cn(getControlClassName(isLastPage), "hidden sm:flex"),
1324
+ onClick: () => handlePageChange(safeTotalPages),
1325
+ disabled: isLastPage,
1326
+ "aria-label": "Last page",
1327
+ children: lastIcon
1328
+ }
1329
+ )
1330
+ ] })
1331
+ ]
1332
+ }
1333
+ );
1334
+ }
1335
+
1336
+ exports.Accordion = Accordion;
1337
+ exports.Blog = Blog;
1338
+ exports.BottomGradient = BottomGradient;
1339
+ exports.Button = Button;
1340
+ exports.Dropdown = Dropdown;
1341
+ exports.EmailInput = EmailInput;
1342
+ exports.FilterItem = FilterItem;
1343
+ exports.Footer = Footer;
1344
+ exports.Header = Header2;
1345
+ exports.HeaderNavigation = HeaderNavigation;
1346
+ exports.Label = Label;
1347
+ exports.List = List;
1348
+ exports.Modal = Modal;
1349
+ exports.NavigationButton = NavigationButton;
1350
+ exports.NavigationFilter = NavigationFilter;
1351
+ exports.NavigationTab = NavigationTab;
1352
+ exports.NavigationTabItem = NavigationTabItem;
1353
+ exports.PageNavButton = PageNavButton;
1354
+ exports.Pagination = Pagination;
1355
+ exports.RecruitmentCard = RecruitmentCard;
1356
+ exports.ReviewCard = ReviewCard;
1357
+ exports.ScrollTopButton = ScrollTopButton;
1358
+ exports.ShowcaseCard = ShowcaseCard;
1359
+ //# sourceMappingURL=index.cjs.map
1360
+ //# sourceMappingURL=index.cjs.map