@bigtablet/design-system 1.3.2 → 1.5.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.js CHANGED
@@ -13,21 +13,21 @@ var Card = ({
13
13
  heading,
14
14
  shadow = "sm",
15
15
  padding = "md",
16
- bordered,
16
+ bordered = false,
17
17
  className,
18
18
  children,
19
19
  ...props
20
20
  }) => {
21
21
  const cls = [
22
22
  "card",
23
- `card--shadow-${shadow}`,
24
- `card--p-${padding}`,
25
- bordered && "card--bordered",
26
- className
23
+ `card_shadow_${shadow}`,
24
+ `card_p_${padding}`,
25
+ bordered ? "card_bordered" : "",
26
+ className ?? ""
27
27
  ].filter(Boolean).join(" ");
28
28
  return /* @__PURE__ */ jsxs("div", { className: cls, ...props, children: [
29
- heading && /* @__PURE__ */ jsx("div", { className: "card__title", children: heading }),
30
- /* @__PURE__ */ jsx("div", { className: "card__body", children })
29
+ heading ? /* @__PURE__ */ jsx("div", { className: "card_title", children: heading }) : null,
30
+ /* @__PURE__ */ jsx("div", { className: "card_body", children })
31
31
  ] });
32
32
  };
33
33
  var AlertContext = createContext(null);
@@ -89,24 +89,24 @@ var AlertModal = ({
89
89
  onCancel,
90
90
  onClose
91
91
  }) => {
92
- return /* @__PURE__ */ jsx("div", { className: "alert-overlay", onClick: onClose, children: /* @__PURE__ */ jsxs(
92
+ return /* @__PURE__ */ jsx("div", { className: "alert_overlay", onClick: onClose, children: /* @__PURE__ */ jsxs(
93
93
  "div",
94
94
  {
95
- className: `alert-modal alert-modal--${variant}`,
95
+ className: `alert_modal alert_modal_${variant}`,
96
96
  onClick: (e) => e.stopPropagation(),
97
97
  role: "alertdialog",
98
98
  "aria-modal": "true",
99
- "aria-labelledby": "alert-title",
100
- "aria-describedby": "alert-message",
99
+ "aria-labelledby": "alert_title",
100
+ "aria-describedby": "alert_message",
101
101
  children: [
102
- title && /* @__PURE__ */ jsx("div", { className: "alert-modal__title", id: "alert-title", children: title }),
103
- message && /* @__PURE__ */ jsx("div", { className: "alert-modal__message", id: "alert-message", children: message }),
104
- /* @__PURE__ */ jsxs("div", { className: `alert-modal__actions alert-modal__actions--${actionsAlign}`, children: [
102
+ title && /* @__PURE__ */ jsx("div", { className: "alert_modal_title", id: "alert_title", children: title }),
103
+ message && /* @__PURE__ */ jsx("div", { className: "alert_modal_message", id: "alert_message", children: message }),
104
+ /* @__PURE__ */ jsxs("div", { className: `alert_modal_actions alert_modal_actions_${actionsAlign}`, children: [
105
105
  showCancel && /* @__PURE__ */ jsx(
106
106
  "button",
107
107
  {
108
108
  type: "button",
109
- className: "alert-modal__button alert-modal__button--cancel",
109
+ className: "alert_modal_button alert_modal_button_cancel",
110
110
  onClick: onCancel,
111
111
  children: cancelText
112
112
  }
@@ -115,7 +115,7 @@ var AlertModal = ({
115
115
  "button",
116
116
  {
117
117
  type: "button",
118
- className: "alert-modal__button alert-modal__button--confirm",
118
+ className: "alert_modal_button alert_modal_button_confirm",
119
119
  onClick: onConfirm,
120
120
  children: confirmText
121
121
  }
@@ -210,44 +210,53 @@ var Loading = ({ size = 24 }) => {
210
210
  {
211
211
  className: "loading",
212
212
  style: { width: size, height: size },
213
- "aria-label": "Loading"
213
+ role: "status",
214
+ "aria-label": "\uB85C\uB529 \uC911"
214
215
  }
215
216
  );
216
217
  };
217
- var ToastProvider = () => /* @__PURE__ */ jsx(
218
- ToastContainer,
219
- {
220
- position: "top-right",
221
- autoClose: 2e3,
222
- hideProgressBar: false,
223
- newestOnTop: false,
224
- closeOnClick: true,
225
- rtl: false,
226
- pauseOnFocusLoss: true,
227
- draggable: true,
228
- pauseOnHover: true,
229
- theme: "light",
230
- transition: Slide
231
- }
232
- );
233
- var useToast = () => {
218
+ var ToastProvider = ({ containerId = "default" }) => {
219
+ return /* @__PURE__ */ jsx(
220
+ ToastContainer,
221
+ {
222
+ containerId,
223
+ position: "top-right",
224
+ autoClose: 2e3,
225
+ hideProgressBar: false,
226
+ newestOnTop: false,
227
+ closeOnClick: true,
228
+ rtl: false,
229
+ pauseOnFocusLoss: true,
230
+ draggable: true,
231
+ pauseOnHover: true,
232
+ theme: "light",
233
+ transition: Slide
234
+ }
235
+ );
236
+ };
237
+ var useToast = (containerId = "default") => {
238
+ const base = { containerId };
234
239
  return {
235
- success: (msg) => toast.success(msg),
236
- error: (msg) => toast.error(msg),
237
- warning: (msg) => toast.warning(msg),
238
- info: (msg) => toast.info(msg),
239
- message: (msg) => toast(msg)
240
+ success: (msg) => toast.success(msg, base),
241
+ error: (msg) => toast.error(msg, base),
242
+ warning: (msg) => toast.warning(msg, base),
243
+ info: (msg) => toast.info(msg, base),
244
+ message: (msg) => toast(msg, base)
240
245
  };
241
246
  };
242
247
  var Button = ({
243
248
  variant = "primary",
244
249
  size = "md",
245
250
  className,
246
- style,
247
251
  ...props
248
252
  }) => {
249
- const classes = ["btn", `btn--${variant}`, `btn--${size}`, className].filter(Boolean).join(" ");
250
- return /* @__PURE__ */ jsx("button", { className: classes, ...props });
253
+ const buttonClassName = [
254
+ "button",
255
+ `button_variant_${variant}`,
256
+ `button_size_${size}`,
257
+ className ?? ""
258
+ ].filter(Boolean).join(" ");
259
+ return /* @__PURE__ */ jsx("button", { className: buttonClassName, ...props });
251
260
  };
252
261
  var Checkbox = ({
253
262
  label,
@@ -256,62 +265,63 @@ var Checkbox = ({
256
265
  className,
257
266
  ...props
258
267
  }) => {
259
- const ref = React3.useRef(null);
268
+ const inputRef = React3.useRef(null);
260
269
  React3.useEffect(() => {
261
- if (ref.current) ref.current.indeterminate = !!indeterminate;
270
+ if (!inputRef.current) return;
271
+ inputRef.current.indeterminate = Boolean(indeterminate);
262
272
  }, [indeterminate]);
263
- return /* @__PURE__ */ jsxs(
264
- "label",
265
- {
266
- className: ["checkbox", `checkbox--${size}`, className].filter(Boolean).join(" "),
267
- children: [
268
- /* @__PURE__ */ jsx("input", { ref, type: "checkbox", className: "checkbox__input", ...props }),
269
- /* @__PURE__ */ jsx("span", { className: "checkbox__box", "aria-hidden": true }),
270
- label && /* @__PURE__ */ jsx("span", { className: "checkbox__label", children: label })
271
- ]
272
- }
273
- );
273
+ const rootClassName = [
274
+ "checkbox",
275
+ `checkbox_size_${size}`,
276
+ className ?? ""
277
+ ].filter(Boolean).join(" ");
278
+ return /* @__PURE__ */ jsxs("label", { className: rootClassName, children: [
279
+ /* @__PURE__ */ jsx(
280
+ "input",
281
+ {
282
+ ref: inputRef,
283
+ type: "checkbox",
284
+ className: "checkbox_input",
285
+ ...props
286
+ }
287
+ ),
288
+ /* @__PURE__ */ jsx("span", { className: "checkbox_box", "aria-hidden": "true" }),
289
+ label ? /* @__PURE__ */ jsx("span", { className: "checkbox_label", children: label }) : null
290
+ ] });
274
291
  };
275
292
  var FileInput = ({
276
- label = "Choose file",
293
+ label = "\uD30C\uC77C \uC120\uD0DD",
277
294
  onFiles,
278
295
  className,
296
+ disabled,
279
297
  ...props
280
298
  }) => {
281
- const id = React3.useId();
282
- return /* @__PURE__ */ jsxs("div", { className: ["file", className].filter(Boolean).join(" "), children: [
299
+ const inputId = React3.useId();
300
+ const rootClassName = ["file_input", disabled ? "file_input_disabled" : "", className ?? ""].filter(Boolean).join(" ");
301
+ return /* @__PURE__ */ jsxs("div", { className: rootClassName, children: [
283
302
  /* @__PURE__ */ jsx(
284
303
  "input",
285
304
  {
286
- id,
305
+ id: inputId,
287
306
  type: "file",
288
- className: "file__input",
307
+ className: "file_input_control",
308
+ disabled,
289
309
  onChange: (e) => onFiles?.(e.currentTarget.files),
290
310
  ...props
291
311
  }
292
312
  ),
293
- /* @__PURE__ */ jsx("label", { htmlFor: id, className: "file__label", children: label })
313
+ /* @__PURE__ */ jsx("label", { htmlFor: inputId, className: "file_input_label", children: label })
294
314
  ] });
295
315
  };
296
- var Radio = ({
297
- label,
298
- size = "md",
299
- className,
300
- ...props
301
- }) => {
302
- return /* @__PURE__ */ jsxs(
303
- "label",
304
- {
305
- className: ["radio", `radio--${size}`, className].filter(Boolean).join(" "),
306
- children: [
307
- /* @__PURE__ */ jsx("input", { type: "radio", className: "radio__input", ...props }),
308
- /* @__PURE__ */ jsx("span", { className: "radio__dot", "aria-hidden": true }),
309
- label && /* @__PURE__ */ jsx("span", { className: "radio__label", children: label })
310
- ]
311
- }
312
- );
316
+ var Radio = ({ label, size = "md", className, ...props }) => {
317
+ const rootClassName = ["radio", `radio_size_${size}`, className ?? ""].filter(Boolean).join(" ");
318
+ return /* @__PURE__ */ jsxs("label", { className: rootClassName, children: [
319
+ /* @__PURE__ */ jsx("input", { type: "radio", className: "radio_input", ...props }),
320
+ /* @__PURE__ */ jsx("span", { className: "radio_dot", "aria-hidden": "true" }),
321
+ label ? /* @__PURE__ */ jsx("span", { className: "radio_label", children: label }) : null
322
+ ] });
313
323
  };
314
- function Select({
324
+ var Select = ({
315
325
  id,
316
326
  label,
317
327
  placeholder = "Select\u2026",
@@ -324,39 +334,38 @@ function Select({
324
334
  variant = "outline",
325
335
  fullWidth,
326
336
  className
327
- }) {
337
+ }) => {
328
338
  const internalId = React3.useId();
329
339
  const selectId = id ?? internalId;
330
340
  const isControlled = value !== void 0;
331
- const [internal, setInternal] = React3.useState(defaultValue);
332
- const currentValue = isControlled ? value ?? null : internal;
333
- const [open, setOpen] = React3.useState(false);
341
+ const [internalValue, setInternalValue] = React3.useState(defaultValue);
342
+ const currentValue = isControlled ? value ?? null : internalValue;
343
+ const [isOpen, setIsOpen] = React3.useState(false);
334
344
  const [activeIndex, setActiveIndex] = React3.useState(-1);
335
345
  const wrapperRef = React3.useRef(null);
336
- const listRef = React3.useRef(null);
337
346
  const currentOption = React3.useMemo(
338
347
  () => options.find((o) => o.value === currentValue) ?? null,
339
348
  [options, currentValue]
340
349
  );
341
350
  const setValue = React3.useCallback(
342
351
  (next) => {
343
- const opt = options.find((o) => o.value === next) ?? null;
344
- if (!isControlled) setInternal(next);
345
- onChange?.(next, opt);
352
+ const option = options.find((o) => o.value === next) ?? null;
353
+ if (!isControlled) setInternalValue(next);
354
+ onChange?.(next, option);
346
355
  },
347
356
  [isControlled, onChange, options]
348
357
  );
349
358
  React3.useEffect(() => {
350
359
  const onDocClick = (e) => {
351
360
  if (!wrapperRef.current) return;
352
- if (!wrapperRef.current.contains(e.target)) setOpen(false);
361
+ if (!wrapperRef.current.contains(e.target)) setIsOpen(false);
353
362
  };
354
363
  document.addEventListener("mousedown", onDocClick);
355
364
  return () => document.removeEventListener("mousedown", onDocClick);
356
365
  }, []);
357
366
  const moveActive = (dir) => {
358
- if (!open) {
359
- setOpen(true);
367
+ if (!isOpen) {
368
+ setIsOpen(true);
360
369
  return;
361
370
  }
362
371
  let i = activeIndex;
@@ -374,7 +383,7 @@ function Select({
374
383
  const opt = options[activeIndex];
375
384
  if (!opt.disabled) {
376
385
  setValue(opt.value);
377
- setOpen(false);
386
+ setIsOpen(false);
378
387
  }
379
388
  };
380
389
  const onKeyDown = (e) => {
@@ -383,7 +392,7 @@ function Select({
383
392
  case " ":
384
393
  case "Enter":
385
394
  e.preventDefault();
386
- if (!open) setOpen(true);
395
+ if (!isOpen) setIsOpen(true);
387
396
  else commitActive();
388
397
  break;
389
398
  case "ArrowDown":
@@ -396,12 +405,12 @@ function Select({
396
405
  break;
397
406
  case "Home":
398
407
  e.preventDefault();
399
- setOpen(true);
408
+ setIsOpen(true);
400
409
  setActiveIndex(options.findIndex((o) => !o.disabled));
401
410
  break;
402
411
  case "End":
403
412
  e.preventDefault();
404
- setOpen(true);
413
+ setIsOpen(true);
405
414
  for (let i = options.length - 1; i >= 0; i--) {
406
415
  if (!options[i].disabled) {
407
416
  setActiveIndex(i);
@@ -411,98 +420,90 @@ function Select({
411
420
  break;
412
421
  case "Escape":
413
422
  e.preventDefault();
414
- setOpen(false);
423
+ setIsOpen(false);
415
424
  break;
416
425
  }
417
426
  };
418
427
  React3.useEffect(() => {
419
- if (open) {
420
- const idx = Math.max(
421
- 0,
422
- options.findIndex((o) => o.value === currentValue && !o.disabled)
423
- );
424
- setActiveIndex(idx === -1 ? 0 : idx);
425
- }
426
- }, [open, options, currentValue]);
428
+ if (!isOpen) return;
429
+ const idx = options.findIndex((o) => o.value === currentValue && !o.disabled);
430
+ setActiveIndex(idx >= 0 ? idx : Math.max(0, options.findIndex((o) => !o.disabled)));
431
+ }, [isOpen, options, currentValue]);
432
+ const rootClassName = ["select", className ?? ""].filter(Boolean).join(" ");
433
+ const controlClassName = [
434
+ "select_control",
435
+ `select_control_variant_${variant}`,
436
+ `select_control_size_${size}`,
437
+ isOpen && "is_open",
438
+ disabled && "is_disabled"
439
+ ].filter(Boolean).join(" ");
427
440
  return /* @__PURE__ */ jsxs(
428
441
  "div",
429
442
  {
430
443
  ref: wrapperRef,
431
- className: `select${className ? ` ${className}` : ""}`,
444
+ className: rootClassName,
432
445
  style: fullWidth ? { width: "100%" } : void 0,
433
446
  children: [
434
- label && /* @__PURE__ */ jsx("label", { htmlFor: selectId, className: "select__label", children: label }),
447
+ label ? /* @__PURE__ */ jsx("label", { htmlFor: selectId, className: "select_label", children: label }) : null,
435
448
  /* @__PURE__ */ jsxs(
436
449
  "button",
437
450
  {
438
451
  id: selectId,
439
452
  type: "button",
440
- className: [
441
- "select__control",
442
- `select__control--${variant}`,
443
- `select__control--${size}`,
444
- open && "is-open",
445
- disabled && "is-disabled"
446
- ].filter(Boolean).join(" "),
453
+ className: controlClassName,
447
454
  "aria-haspopup": "listbox",
448
- "aria-expanded": open,
449
- "aria-controls": `${selectId}-listbox`,
450
- onClick: () => !disabled && setOpen((o) => !o),
455
+ "aria-expanded": isOpen,
456
+ "aria-controls": `${selectId}_listbox`,
457
+ onClick: () => !disabled && setIsOpen((o) => !o),
451
458
  onKeyDown,
452
459
  disabled,
453
460
  children: [
454
- /* @__PURE__ */ jsx(
455
- "span",
456
- {
457
- className: currentOption ? "select__value" : "select__placeholder",
458
- children: currentOption ? currentOption.label : placeholder
459
- }
460
- ),
461
- /* @__PURE__ */ jsx("span", { className: "select__icon", "aria-hidden": true, children: /* @__PURE__ */ jsx(ChevronDown, { size: 16 }) })
461
+ /* @__PURE__ */ jsx("span", { className: currentOption ? "select_value" : "select_placeholder", children: currentOption ? currentOption.label : placeholder }),
462
+ /* @__PURE__ */ jsx("span", { className: "select_icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx(ChevronDown, { size: 16 }) })
462
463
  ]
463
464
  }
464
465
  ),
465
- open && /* @__PURE__ */ jsx(
466
+ isOpen ? /* @__PURE__ */ jsx(
466
467
  "ul",
467
468
  {
468
- ref: listRef,
469
- id: `${selectId}-listbox`,
469
+ id: `${selectId}_listbox`,
470
470
  role: "listbox",
471
- className: "select__list",
471
+ className: "select_list",
472
472
  children: options.map((opt, i) => {
473
473
  const selected = currentValue === opt.value;
474
474
  const active = i === activeIndex;
475
+ const optionClassName = [
476
+ "select_option",
477
+ selected && "is_selected",
478
+ active && "is_active",
479
+ opt.disabled && "is_disabled"
480
+ ].filter(Boolean).join(" ");
475
481
  return /* @__PURE__ */ jsxs(
476
482
  "li",
477
483
  {
478
484
  role: "option",
479
485
  "aria-selected": selected,
480
- className: [
481
- "select__option",
482
- selected && "is-selected",
483
- active && "is-active",
484
- opt.disabled && "is-disabled"
485
- ].filter(Boolean).join(" "),
486
+ className: optionClassName,
486
487
  onMouseEnter: () => !opt.disabled && setActiveIndex(i),
487
488
  onClick: () => {
488
489
  if (opt.disabled) return;
489
490
  setValue(opt.value);
490
- setOpen(false);
491
+ setIsOpen(false);
491
492
  },
492
493
  children: [
493
494
  /* @__PURE__ */ jsx("span", { children: opt.label }),
494
- selected && /* @__PURE__ */ jsx(Check, { size: 16, "aria-hidden": true })
495
+ selected ? /* @__PURE__ */ jsx(Check, { size: 16, "aria-hidden": "true" }) : null
495
496
  ]
496
497
  },
497
498
  opt.value
498
499
  );
499
500
  })
500
501
  }
501
- )
502
+ ) : null
502
503
  ]
503
504
  }
504
505
  );
505
- }
506
+ };
506
507
  var Switch = ({
507
508
  checked,
508
509
  defaultChecked,
@@ -512,32 +513,33 @@ var Switch = ({
512
513
  className,
513
514
  ...props
514
515
  }) => {
515
- const controlled = checked !== void 0;
516
- const [inner, setInner] = React3.useState(!!defaultChecked);
517
- const on = controlled ? !!checked : inner;
518
- const toggle = () => {
516
+ const isControlled = checked !== void 0;
517
+ const [innerChecked, setInnerChecked] = React3.useState(!!defaultChecked);
518
+ const isOn = isControlled ? !!checked : innerChecked;
519
+ const handleToggle = () => {
519
520
  if (disabled) return;
520
- const next = !on;
521
- if (!controlled) setInner(next);
521
+ const next = !isOn;
522
+ if (!isControlled) setInnerChecked(next);
522
523
  onChange?.(next);
523
524
  };
525
+ const rootClassName = [
526
+ "switch",
527
+ `switch_size_${size}`,
528
+ isOn && "switch_on",
529
+ disabled && "switch_disabled",
530
+ className ?? ""
531
+ ].filter(Boolean).join(" ");
524
532
  return /* @__PURE__ */ jsx(
525
533
  "button",
526
534
  {
527
535
  type: "button",
528
536
  role: "switch",
529
- "aria-checked": on,
537
+ "aria-checked": isOn,
530
538
  disabled,
531
- onClick: toggle,
532
- className: [
533
- "switch",
534
- `switch--${size}`,
535
- on && "is-on",
536
- disabled && "is-disabled",
537
- className
538
- ].filter(Boolean).join(" "),
539
+ onClick: handleToggle,
540
+ className: rootClassName,
539
541
  ...props,
540
- children: /* @__PURE__ */ jsx("span", { className: "switch__thumb" })
542
+ children: /* @__PURE__ */ jsx("span", { className: "switch_thumb" })
541
543
  }
542
544
  );
543
545
  };
@@ -559,67 +561,109 @@ var TextField = React3.forwardRef(
559
561
  }, ref) => {
560
562
  const inputId = id ?? React3.useId();
561
563
  const helperId = helperText ? `${inputId}-help` : void 0;
562
- const classNames = [
563
- "tf__input",
564
- `tf__input--${variant}`,
565
- `tf__input--${size}`,
566
- leftIcon && "tf__input--with-left",
567
- rightIcon && "tf__input--with-right",
568
- error && "tf__input--error",
569
- success && "tf__input--success",
570
- className
564
+ const rootClassName = [
565
+ "text_field",
566
+ fullWidth && "text_field_full_width",
567
+ className ?? ""
571
568
  ].filter(Boolean).join(" ");
572
- return /* @__PURE__ */ jsxs("div", { className: "tf", style: fullWidth ? { width: "100%" } : void 0, children: [
573
- label && /* @__PURE__ */ jsx("label", { className: "tf__label", htmlFor: inputId, children: label }),
574
- /* @__PURE__ */ jsxs("div", { className: "tf__wrapper", children: [
575
- leftIcon && /* @__PURE__ */ jsx("span", { className: "tf__icon tf__icon--left", children: leftIcon }),
569
+ const inputClassName = [
570
+ "text_field_input",
571
+ `text_field_variant_${variant}`,
572
+ `text_field_size_${size}`,
573
+ leftIcon && "text_field_with_left",
574
+ rightIcon && "text_field_with_right",
575
+ error && "text_field_error",
576
+ success && "text_field_success"
577
+ ].filter(Boolean).join(" ");
578
+ const helperClassName = [
579
+ "text_field_helper",
580
+ error && "text_field_helper_error",
581
+ success && "text_field_helper_success"
582
+ ].filter(Boolean).join(" ");
583
+ return /* @__PURE__ */ jsxs("div", { className: rootClassName, children: [
584
+ label ? /* @__PURE__ */ jsx("label", { className: "text_field_label", htmlFor: inputId, children: label }) : null,
585
+ /* @__PURE__ */ jsxs("div", { className: "text_field_wrap", children: [
586
+ leftIcon ? /* @__PURE__ */ jsx("span", { className: "text_field_icon text_field_icon_left", children: leftIcon }) : null,
576
587
  /* @__PURE__ */ jsx(
577
588
  "input",
578
589
  {
579
590
  id: inputId,
580
591
  ref,
581
- className: classNames,
592
+ className: inputClassName,
582
593
  "aria-invalid": !!error,
583
594
  "aria-describedby": helperId,
584
595
  ...props,
585
596
  onChange: onChangeAction
586
597
  }
587
598
  ),
588
- rightIcon && /* @__PURE__ */ jsx("span", { className: "tf__icon tf__icon--right", children: rightIcon })
599
+ rightIcon ? /* @__PURE__ */ jsx("span", { className: "text_field_icon text_field_icon_right", children: rightIcon }) : null
589
600
  ] }),
590
- helperText && /* @__PURE__ */ jsx(
591
- "div",
592
- {
593
- id: helperId,
594
- className: `tf__helper ${error ? "tf__helper--error" : ""}`,
595
- children: helperText
596
- }
597
- )
601
+ helperText ? /* @__PURE__ */ jsx("div", { id: helperId, className: helperClassName, children: helperText }) : null
598
602
  ] });
599
603
  }
600
604
  );
601
605
  TextField.displayName = "TextField";
602
- var Pagination = ({ page, hasNext, onChange }) => {
606
+ var range = (start, end) => {
607
+ const out = [];
608
+ for (let i = start; i <= end; i += 1) out.push(i);
609
+ return out;
610
+ };
611
+ var getPaginationItems = (page, totalPages) => {
612
+ if (totalPages <= 7) return range(1, totalPages);
613
+ const items = [];
614
+ const last = totalPages;
615
+ const start = Math.max(2, page - 1);
616
+ const end = Math.min(last - 1, page + 1);
617
+ items.push(1);
618
+ if (start > 2) items.push("ellipsis");
619
+ for (const p of range(start, end)) items.push(p);
620
+ if (end < last - 1) items.push("ellipsis");
621
+ items.push(last);
622
+ return items;
623
+ };
624
+ var Pagination = ({ page, totalPages, onChange }) => {
603
625
  const prevDisabled = page <= 1;
604
- const nextDisabled = !hasNext;
626
+ const nextDisabled = page >= totalPages;
627
+ const items = React3.useMemo(
628
+ () => getPaginationItems(page, totalPages),
629
+ [page, totalPages]
630
+ );
605
631
  return /* @__PURE__ */ jsxs("nav", { className: "pagination", "aria-label": "Pagination", children: [
606
632
  /* @__PURE__ */ jsx(
607
633
  "button",
608
634
  {
609
- className: "pagination__item",
610
- onClick: () => !prevDisabled && onChange(page - 1),
635
+ className: "pagination_item",
636
+ onClick: () => onChange(page - 1),
611
637
  disabled: prevDisabled,
612
- children: "Prev"
638
+ "aria-label": "Previous page",
639
+ children: "\u2039"
613
640
  }
614
641
  ),
615
- /* @__PURE__ */ jsx("span", { className: "pagination__page", children: page }),
642
+ /* @__PURE__ */ jsx("div", { className: "pagination_pages", role: "list", children: items.map((it, idx) => {
643
+ if (it === "ellipsis") {
644
+ return /* @__PURE__ */ jsx("span", { className: "pagination_ellipsis", "aria-hidden": "true", children: "\u2026" }, `e-${idx}`);
645
+ }
646
+ const isActive = it === page;
647
+ return /* @__PURE__ */ jsx(
648
+ "button",
649
+ {
650
+ type: "button",
651
+ className: `pagination_pageButton ${isActive ? "is-active" : ""}`,
652
+ onClick: () => onChange(it),
653
+ "aria-current": isActive ? "page" : void 0,
654
+ children: it
655
+ },
656
+ it
657
+ );
658
+ }) }),
616
659
  /* @__PURE__ */ jsx(
617
660
  "button",
618
661
  {
619
- className: "pagination__item",
620
- onClick: () => !nextDisabled && onChange(page + 1),
662
+ className: "pagination_item",
663
+ onClick: () => onChange(page + 1),
621
664
  disabled: nextDisabled,
622
- children: "Next"
665
+ "aria-label": "Next page",
666
+ children: "\u203A"
623
667
  }
624
668
  )
625
669
  ] });
@@ -631,12 +675,16 @@ var Modal = ({
631
675
  width = 520,
632
676
  title,
633
677
  children,
678
+ className,
634
679
  ...props
635
680
  }) => {
636
681
  React3.useEffect(() => {
637
- const onKey = (e) => e.key === "Escape" && onClose?.();
638
- if (open) document.addEventListener("keydown", onKey);
639
- return () => document.removeEventListener("keydown", onKey);
682
+ if (!open) return;
683
+ const onKeyDown = (e) => {
684
+ if (e.key === "Escape") onClose?.();
685
+ };
686
+ document.addEventListener("keydown", onKeyDown);
687
+ return () => document.removeEventListener("keydown", onKeyDown);
640
688
  }, [open, onClose]);
641
689
  if (!open) return null;
642
690
  return /* @__PURE__ */ jsx(
@@ -649,37 +697,18 @@ var Modal = ({
649
697
  children: /* @__PURE__ */ jsxs(
650
698
  "div",
651
699
  {
652
- className: "modal__panel",
700
+ className: ["modal_panel", className].filter(Boolean).join(" "),
653
701
  style: { width },
654
702
  onClick: (e) => e.stopPropagation(),
655
703
  ...props,
656
704
  children: [
657
- title && /* @__PURE__ */ jsx("div", { className: "modal__header", children: title }),
658
- /* @__PURE__ */ jsx("div", { className: "modal__body", children })
705
+ title && /* @__PURE__ */ jsx("div", { className: "modal_header", children: title }),
706
+ /* @__PURE__ */ jsx("div", { className: "modal_body", children })
659
707
  ]
660
708
  }
661
709
  )
662
710
  }
663
711
  );
664
712
  };
665
- var SkeletonCard = () => /* @__PURE__ */ jsxs("div", { className: "card-skeleton", children: [
666
- /* @__PURE__ */ jsx("div", { className: "card-skeleton__thumb" }),
667
- /* @__PURE__ */ jsxs("div", { className: "card-skeleton__text", children: [
668
- /* @__PURE__ */ jsx("div", { className: "card-skeleton__line short" }),
669
- /* @__PURE__ */ jsx("div", { className: "card-skeleton__line" })
670
- ] })
671
- ] });
672
- var card_default = SkeletonCard;
673
- var SkeletonList = () => /* @__PURE__ */ jsxs("div", { className: "request-item skeleton", children: [
674
- /* @__PURE__ */ jsxs("div", { className: "request-item__left", children: [
675
- /* @__PURE__ */ jsx("div", { className: "skeleton__title" }),
676
- /* @__PURE__ */ jsxs("div", { className: "request-item__tags", children: [
677
- /* @__PURE__ */ jsx("span", { className: "skeleton__tag" }),
678
- /* @__PURE__ */ jsx("span", { className: "skeleton__tag" }),
679
- /* @__PURE__ */ jsx("span", { className: "skeleton__tag" })
680
- ] })
681
- ] }),
682
- /* @__PURE__ */ jsx("div", { className: "request-item__dday", children: /* @__PURE__ */ jsx("span", { className: "skeleton__dday" }) })
683
- ] });
684
713
 
685
- export { Alert, AlertProvider, Button, Card, Checkbox, FileInput, Loading, Modal, Pagination, Radio, Select, card_default as SkeletonCard, SkeletonList, Switch, TextField, ToastProvider, useAlert, useToast };
714
+ export { Alert, AlertProvider, Button, Card, Checkbox, FileInput, Loading, Modal, Pagination, Radio, Select, Switch, TextField, ToastProvider, useAlert, useToast };