@uniai-fe/uds-primitives 0.0.15 → 0.0.16

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/styles.css CHANGED
@@ -2626,6 +2626,10 @@ figure.chip {
2626
2626
  --pagination-dot-size: 8px;
2627
2627
  --pagination-dot-bg: var(--color-cool-gray-85, #d2d3d7);
2628
2628
  --pagination-dot-active-bg: var(--color-primary-default, #0061ff);
2629
+ --pagination-dot-active-bg-secondary: var(
2630
+ --color-bg-surface-heavy,
2631
+ #313235
2632
+ );
2629
2633
  --pagination-carousel-height: 8px;
2630
2634
  --pagination-carousel-dot-width: 8px;
2631
2635
  --pagination-carousel-active-width: 20px;
@@ -2701,6 +2705,13 @@ figure.chip {
2701
2705
  align-items: center;
2702
2706
  }
2703
2707
 
2708
+ .pagination--variant-carousel[data-priority=secondary] {
2709
+ --pagination-dot-active-bg: var(
2710
+ --pagination-dot-active-bg-secondary,
2711
+ var(--color-secondary-strong, #ccdeff)
2712
+ );
2713
+ }
2714
+
2704
2715
  .pagination--variant-carousel .pagination-button {
2705
2716
  width: auto;
2706
2717
  height: var(--pagination-carousel-height);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uniai-fe/uds-primitives",
3
- "version": "0.0.15",
3
+ "version": "0.0.16",
4
4
  "description": "UNIAI Design System; Primitives Components Package",
5
5
  "type": "module",
6
6
  "private": false,
@@ -9,68 +9,86 @@ import {
9
9
  } from "../utils";
10
10
 
11
11
  /**
12
- * Carousel indicator Pagination. 점 형태로 현재 위치만 표시한다.
13
- * @component
14
- * @param {PaginationCarouselProps} props
15
- * @param {number} props.total 전체 step 수.
12
+ * @component PaginationCarousel
13
+ * @description
14
+ * Carousel(dot) indicator를 렌더한다. total/current는 normalizePaginationState로 보정하고,
15
+ * onPageChange가 없으면 버튼을 disabled 처리해 pointer/cursor를 제거한다.
16
+ * priority prop은 data attribute로 노출되어 SCSS에서 primary/secondary(active color) 토큰을 분기한다.
17
+ * @param {PaginationCarouselProps} props Carousel 구성 옵션.
18
+ * @param {number} props.total 전체 step 개수.
16
19
  * @param {number} [props.current=1] 현재 step index(1-indexed).
17
- * @param {(page: number) => void} [props.onPageChange]
18
- * 전달 dot를 클릭해 이동할 있고, 생략하면 모든 dot가 disabled 된다.
19
- * @param {string} [props.className] `.pagination` root className.
20
+ * @param {(page: number) => void} [props.onPageChange] dot를 클릭해 이동시키는 핸들러. 미제공 시 인터랙션이 비활성화된다.
21
+ * @param {string} [props.className] `.pagination` 루트 className merge 용도.
22
+ * @param {PaginationCarouselProps["priority"]} [props.priority=\"primary\"] active dot 색상 priority.
23
+ * @returns {JSX.Element} dot indicator `<ul>`.
20
24
  */
21
25
  const PaginationCarousel = forwardRef<
22
26
  HTMLUListElement,
23
27
  PaginationCarouselProps
24
- >(({ total, current = 1, onPageChange, className, ...restProps }, ref) => {
25
- const { total: normalizedTotal, current: normalizedCurrent } =
26
- normalizePaginationState({ total, current });
27
- const pages = createPaginationPages(normalizedTotal);
28
- const allowInteraction = typeof onPageChange === "function";
29
- const rootClassName = composePaginationClassName({
30
- variant: "carousel",
31
- className,
32
- });
28
+ >(
29
+ (
30
+ {
31
+ total,
32
+ current = 1,
33
+ onPageChange,
34
+ className,
35
+ priority = "primary",
36
+ ...restProps
37
+ },
38
+ ref,
39
+ ) => {
40
+ const { total: normalizedTotal, current: normalizedCurrent } =
41
+ normalizePaginationState({ total, current });
42
+ const pages = createPaginationPages(normalizedTotal);
43
+ const allowInteraction = typeof onPageChange === "function";
44
+ const rootClassName = composePaginationClassName({
45
+ variant: "carousel",
46
+ className,
47
+ });
33
48
 
34
- const handleClick = (page: number) => {
35
- if (!allowInteraction || page === normalizedCurrent) {
36
- return;
37
- }
38
- onPageChange?.(page);
39
- };
49
+ const handleClick = (page: number) => {
50
+ if (!allowInteraction || page === normalizedCurrent) {
51
+ return;
52
+ }
53
+ onPageChange?.(page);
54
+ };
40
55
 
41
- return (
42
- <ul
43
- {...restProps}
44
- ref={ref}
45
- className={rootClassName}
46
- data-variant="carousel"
47
- data-interactive={allowInteraction ? "true" : "false"}
48
- >
49
- {pages.map(page => {
50
- const isActive = page === normalizedCurrent;
51
- return (
52
- <li
53
- key={page}
54
- className={PAGINATION_ITEM_CLASSNAME}
55
- data-active={isActive ? "true" : undefined}
56
- >
57
- <button
58
- type="button"
59
- className={PAGINATION_BUTTON_CLASSNAME}
56
+ // priority data attr는 primary/secondary dot 색상을 분기한다.
57
+ return (
58
+ <ul
59
+ {...restProps}
60
+ ref={ref}
61
+ className={rootClassName}
62
+ data-variant="carousel"
63
+ data-interactive={allowInteraction ? "true" : "false"}
64
+ data-priority={priority}
65
+ >
66
+ {pages.map(page => {
67
+ const isActive = page === normalizedCurrent;
68
+ return (
69
+ <li
70
+ key={page}
71
+ className={PAGINATION_ITEM_CLASSNAME}
60
72
  data-active={isActive ? "true" : undefined}
61
- aria-label={`Step ${page}`}
62
- disabled={!allowInteraction}
63
- tabIndex={allowInteraction ? 0 : -1}
64
- onClick={allowInteraction ? () => handleClick(page) : undefined}
65
73
  >
66
- <span className="pagination-dot" aria-hidden="true" />
67
- </button>
68
- </li>
69
- );
70
- })}
71
- </ul>
72
- );
73
- });
74
+ <button
75
+ type="button"
76
+ className={PAGINATION_BUTTON_CLASSNAME}
77
+ data-active={isActive ? "true" : undefined}
78
+ aria-label={`Step ${page}`}
79
+ disabled={!allowInteraction}
80
+ tabIndex={allowInteraction ? 0 : -1}
81
+ onClick={allowInteraction ? () => handleClick(page) : undefined}
82
+ >
83
+ <span className="pagination-dot" aria-hidden="true" />
84
+ </button>
85
+ </li>
86
+ );
87
+ })}
88
+ </ul>
89
+ );
90
+ },
91
+ );
74
92
 
75
93
  PaginationCarousel.displayName = "PaginationCarousel";
76
94
 
@@ -7,13 +7,16 @@ import {
7
7
  } from "../utils";
8
8
 
9
9
  /**
10
- * Count(step) indicator; `1/5` 형태로 현재 위치만 표시한다.
11
- * @component
12
- * @param {PaginationCountProps} props
10
+ * @component PaginationCount
11
+ * @description
12
+ * Count(step) indicator를 `current/total` pill 형태로 렌더한다. 실제로는 disabled button을 사용해
13
+ * 시각적 일관성을 유지하고, normalizePaginationState로 total/current를 보정한다.
14
+ * @param {PaginationCountProps} props Count variant 구성 옵션.
13
15
  * @param {number} props.total 전체 step 수.
14
- * @param {number} [props.current=1] 현재 step position.
15
- * @param {"small" | "xsmall"} [props.size="small"] 높이/타이포 크기 옵션.
16
- * @param {string} [props.className] `.pagination` root className.
16
+ * @param {number} [props.current=1] 현재 위치(1-indexed).
17
+ * @param {PaginationCountProps["size"]} [props.size=\"small\"] 높이/타이포 크기.
18
+ * @param {string} [props.className] `.pagination` 루트 className merge 용도.
19
+ * @returns {JSX.Element} count indicator `<div>`.
17
20
  */
18
21
  const PaginationCount = forwardRef<HTMLDivElement, PaginationCountProps>(
19
22
  ({ total, current = 1, size = "small", className, ...restProps }, ref) => {
@@ -9,15 +9,17 @@ import {
9
9
  } from "../utils";
10
10
 
11
11
  /**
12
- * 숫자 페이지형 Pagination.
13
- * @component
14
- * @param {PaginationProps} props
15
- * @param {number} props.total 전체 페이지 개수(1 이상으로 자동 보정).
16
- * @param {number} [props.current=1] 현재 페이지. total 범위를 벗어나면 자동 조정된다.
17
- * @param {(page: number) => void} [props.onPageChange]
18
- * 페이지 버튼 클릭 핸들러. 전달되지 않으면 모든 버튼이 disabled 처리되어 cursor가 제거된다.
19
- * @param {string} [props.className] `.pagination` root className.
20
- * @param {React.AriaAttributes} [props.aria-*] ul element에 전달될 기타 속성.
12
+ * @component Pagination
13
+ * @description
14
+ * List variant pagination을 구현한다. total/current 값을 보정해 최소 1~total 범위의 페이지 버튼을 렌더하고,
15
+ * onPageChange가 없으면 data-interactive 값을 false로 지정해 전부 disabled 상태로 노출한다.
16
+ * @param {PaginationProps} props Pagination 구성 옵션.
17
+ * @param {number} props.total 전체 페이지 개수. 1 미만이면 자동으로 1로 보정된다.
18
+ * @param {number} [props.current=1] 현재 활성 페이지(1-indexed). total 범위를 벗어나면 자동 조정된다.
19
+ * @param {(page: number) => void} [props.onPageChange] 페이지 변경 핸들러. 미제공 시 버튼은 disabled 처리되고 tabIndex가 -1이 된다.
20
+ * @param {string} [props.className] `.pagination` 루트 className merge 용도.
21
+ * @param {React.AriaAttributes} [props.aria-*] ARIA 속성은 그대로 `<ul>`에 전달된다.
22
+ * @returns {JSX.Element} 페이지 네비게이터 `<ul>`.
21
23
  * @example
22
24
  * ```tsx
23
25
  * <Pagination total={10} current={3} onPageChange={setPage} />
@@ -13,6 +13,10 @@
13
13
  --pagination-dot-size: 8px;
14
14
  --pagination-dot-bg: var(--color-cool-gray-85, #d2d3d7);
15
15
  --pagination-dot-active-bg: var(--color-primary-default, #0061ff);
16
+ --pagination-dot-active-bg-secondary: var(
17
+ --color-bg-surface-heavy,
18
+ #313235
19
+ ); // semantic surface heavy
16
20
  --pagination-carousel-height: 8px;
17
21
  --pagination-carousel-dot-width: 8px;
18
22
  --pagination-carousel-active-width: 20px;
@@ -94,6 +98,14 @@
94
98
  align-items: center;
95
99
  }
96
100
 
101
+ // secondary priority일 때 active dot 컬러를 재정의한다.
102
+ .pagination--variant-carousel[data-priority="secondary"] {
103
+ --pagination-dot-active-bg: var(
104
+ --pagination-dot-active-bg-secondary,
105
+ var(--color-secondary-strong, #ccdeff)
106
+ );
107
+ }
108
+
97
109
  .pagination--variant-carousel .pagination-button {
98
110
  width: auto;
99
111
  height: var(--pagination-carousel-height);
@@ -2,9 +2,12 @@ import type { ComponentPropsWithoutRef } from "react";
2
2
 
3
3
  export const PAGINATION_VARIANTS = ["list", "carousel", "count"] as const;
4
4
  export const PAGINATION_COUNT_SIZES = ["small", "xsmall"] as const;
5
+ export const PAGINATION_CAROUSEL_PRIORITIES = ["primary", "secondary"] as const;
5
6
 
6
7
  export type PaginationVariant = (typeof PAGINATION_VARIANTS)[number];
7
8
  export type PaginationCountSize = (typeof PAGINATION_COUNT_SIZES)[number];
9
+ export type PaginationCarouselPriority =
10
+ (typeof PAGINATION_CAROUSEL_PRIORITIES)[number];
8
11
 
9
12
  type NativeListProps = ComponentPropsWithoutRef<"ul">;
10
13
  type NativeDivProps = ComponentPropsWithoutRef<"div">;
@@ -28,7 +31,9 @@ interface PaginationInteractiveProps {
28
31
  }
29
32
 
30
33
  /**
31
- * 숫자 페이지용 Pagination props
34
+ * 숫자 페이지용 Pagination props.
35
+ * native `<ul>` 속성과 state/interaction 옵션(total/current/onPageChange)을 함께 받는다.
36
+ * onPageChange가 전달되지 않으면 버튼이 disabled 상태가 되며 focus 방지를 위해 tabIndex가 -1로 설정된다.
32
37
  */
33
38
  export interface PaginationProps
34
39
  extends
@@ -37,16 +42,24 @@ export interface PaginationProps
37
42
  PaginationInteractiveProps {}
38
43
 
39
44
  /**
40
- * Carousel indicator props
45
+ * Carousel(dot) indicator props.
46
+ * native `<ul>` 속성과 total/current/onPageChange + priority 옵션을 함께 받아 dot 상태를 제어한다.
47
+ * priority는 SCSS data attribute 기반으로 semantic primary/secondary active 색상을 선택한다.
41
48
  */
42
49
  export interface PaginationCarouselProps
43
50
  extends
44
51
  Omit<NativeListProps, "children" | "onChange">,
45
52
  PaginationBaseProps,
46
- PaginationInteractiveProps {}
53
+ PaginationInteractiveProps {
54
+ /**
55
+ * dot active 색상 priority. primary(semantic primary standard) 또는 secondary(semantic surface heavy) 옵션을 제공한다.
56
+ */
57
+ priority?: PaginationCarouselPriority;
58
+ }
47
59
 
48
60
  /**
49
- * Count(step) indicator props
61
+ * Count(step) indicator props.
62
+ * `<div>` 래퍼에 disabled button을 내장해 `current/total` 텍스트만 출력하며 size로 높이/타이포를 전환한다.
50
63
  */
51
64
  export interface PaginationCountProps
52
65
  extends Omit<NativeDivProps, "children">, PaginationBaseProps {