@uniai-fe/uds-templates 0.1.14 → 0.1.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/README.md +5 -0
- package/package.json +1 -1
- package/src/auth/index.tsx +8 -1
- package/src/modal/core/components/Container.tsx +3 -7
- package/src/modal/core/components/FooterButtons.tsx +2 -3
- package/src/modal/core/hooks/useModal.ts +1 -2
- package/src/modal/types/footer.ts +1 -3
- package/src/modal/types/index.ts +0 -1
- package/src/modal/types/options.ts +1 -3
- package/src/modal/types/state.ts +2 -4
- package/src/modal/types/templates.ts +2 -2
- package/src/page-frame/mobile/header/PageFrameMobileHeader.tsx +12 -9
package/README.md
CHANGED
|
@@ -125,6 +125,11 @@ export default function LoginPage() {
|
|
|
125
125
|
|
|
126
126
|
> modules 레포 내부(Storybook 등)에서는 개발 편의를 위해 `@uniai-fe/uds-templates/src/index.scss`를 직접 import하지만, 외부 서비스/패키지는 `@uniai-fe/uds-templates/css` 엔트리만 사용해야 한다.
|
|
127
127
|
|
|
128
|
+
### 최근 업데이트
|
|
129
|
+
|
|
130
|
+
- Modal CSS 변수 네임스페이스를 `--modal-*`, `--modal-alert-*`, `--modal-dialog-*` 세 축으로 통일했다. 기존 `--dialog-*` 이름을 사용하지 말고, Auth 템플릿이 Alert을 호출할 때에는 반드시 `Modal.Alert` 팩토리를 통해 렌더링한다.
|
|
131
|
+
- Auth(회원가입/아이디 찾기/비밀번호 찾기) 템플릿은 이메일 인증 타이머 5분, alert 문구, readonly 이메일 필드, 완료 단계 헤더 제거 등 최신 플로우를 반영했다. 모듈에서 `window.alert`/`window.confirm`을 호출하지 않고, 서비스 앱이 Modal helper를 주입하는 구조를 README와 `CONTEXT-AUTH*.md`에 명시했다.
|
|
132
|
+
|
|
128
133
|
### 토큰 스코프 & ThemeProvider
|
|
129
134
|
|
|
130
135
|
- templates SCSS는 모든 디자인 토큰을 `:root`에 선언하고, 빌드 시 `scripts/merge-theme-root.mjs`가 토큰 블록을 단일 `:root { ... }`로 합쳐 중복 선언을 제거합니다.
|
package/package.json
CHANGED
package/src/auth/index.tsx
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import "./login/index.scss";
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
AuthContainer,
|
|
5
|
+
AuthStageHeader,
|
|
6
|
+
type AuthContainerProps,
|
|
7
|
+
} from "./common/container";
|
|
4
8
|
import AuthCompleteTemplate from "./common/complete/Template";
|
|
5
9
|
import AuthPasswordSetField from "./common/password/markup/PasswordSetField";
|
|
6
10
|
import { AuthLogin } from "./login";
|
|
@@ -11,8 +15,10 @@ import { FindPassword } from "./find-password";
|
|
|
11
15
|
|
|
12
16
|
export const Auth = {
|
|
13
17
|
Container: AuthContainer,
|
|
18
|
+
StageHeader: AuthStageHeader,
|
|
14
19
|
Common: {
|
|
15
20
|
Container: AuthContainer,
|
|
21
|
+
StageHeader: AuthStageHeader,
|
|
16
22
|
Complete: AuthCompleteTemplate,
|
|
17
23
|
PasswordSetField: AuthPasswordSetField,
|
|
18
24
|
},
|
|
@@ -29,6 +35,7 @@ export {
|
|
|
29
35
|
useSignupAccountForm,
|
|
30
36
|
} from "./signup";
|
|
31
37
|
|
|
38
|
+
export type { AuthContainerProps };
|
|
32
39
|
export { useCheckPassword } from "./common/password/hooks/useCheckPassword";
|
|
33
40
|
export { DEFAULT_PASSWORD_RULES } from "./common/password/constants";
|
|
34
41
|
export { FindAccount, useFindAccountForm } from "./find-account";
|
|
@@ -1,16 +1,12 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
import type {
|
|
4
|
-
ModalFooterButton,
|
|
5
|
-
ModalSections,
|
|
6
|
-
ModalStackKey,
|
|
7
|
-
} from "../../types";
|
|
3
|
+
import type { ModalFooterButton, ModalSections } from "../../types";
|
|
8
4
|
import { ModalFooterButtons } from "./FooterButtons";
|
|
9
5
|
|
|
10
6
|
/**
|
|
11
7
|
* 모달 컨테이너; header/body/footer 슬롯만 담당한다.
|
|
12
8
|
* @component
|
|
13
|
-
* @param {ModalSections & {stackKey:
|
|
9
|
+
* @param {ModalSections & {stackKey: string; footerButtons?: ModalFooterButton[]}} props
|
|
14
10
|
* @param {React.ReactNode} [props.header] 헤더 슬롯
|
|
15
11
|
* @param {React.ReactNode} props.body 본문 슬롯
|
|
16
12
|
* @param {React.ReactNode} [props.footer] footer 슬롯
|
|
@@ -23,7 +19,7 @@ export function ModalContainer({
|
|
|
23
19
|
footer,
|
|
24
20
|
footerButtons,
|
|
25
21
|
}: ModalSections & {
|
|
26
|
-
stackKey:
|
|
22
|
+
stackKey: string;
|
|
27
23
|
footerButtons?: ModalFooterButton[];
|
|
28
24
|
}) {
|
|
29
25
|
return (
|
|
@@ -7,7 +7,6 @@ import { useModal } from "../hooks/useModal";
|
|
|
7
7
|
|
|
8
8
|
import type {
|
|
9
9
|
ModalFooterButton,
|
|
10
|
-
ModalStackKey,
|
|
11
10
|
ModalFooterButtonAppearance,
|
|
12
11
|
ModalFooterButtonLinkOptions,
|
|
13
12
|
} from "../../types";
|
|
@@ -38,13 +37,13 @@ const createAnchorProps = (
|
|
|
38
37
|
/**
|
|
39
38
|
* 모달 footer 버튼 리스트 렌더러.
|
|
40
39
|
* @component
|
|
41
|
-
* @param {{ stackKey:
|
|
40
|
+
* @param {{ stackKey: string; buttons: ModalFooterButton[] }} props 버튼 정의 목록
|
|
42
41
|
*/
|
|
43
42
|
export function ModalFooterButtons({
|
|
44
43
|
stackKey,
|
|
45
44
|
buttons,
|
|
46
45
|
}: {
|
|
47
|
-
stackKey:
|
|
46
|
+
stackKey: string;
|
|
48
47
|
buttons: ModalFooterButton[];
|
|
49
48
|
}) {
|
|
50
49
|
const { closeModal } = useModal();
|
|
@@ -9,13 +9,12 @@ import type {
|
|
|
9
9
|
ModalCloseRequest,
|
|
10
10
|
ModalState,
|
|
11
11
|
ModalStatePatch,
|
|
12
|
-
ModalStackKey,
|
|
13
12
|
} from "../../types";
|
|
14
13
|
|
|
15
14
|
const DEFAULT_CLOSE_DELAY = 400;
|
|
16
15
|
|
|
17
16
|
type CloseFlagState = {
|
|
18
|
-
stackKey:
|
|
17
|
+
stackKey: string;
|
|
19
18
|
showDelay: number;
|
|
20
19
|
callback?: () => void;
|
|
21
20
|
};
|
|
@@ -5,8 +5,6 @@ import type {
|
|
|
5
5
|
TextButtonSize,
|
|
6
6
|
} from "@uniai-fe/uds-primitives";
|
|
7
7
|
|
|
8
|
-
import type { ModalStackKey } from "./state";
|
|
9
|
-
|
|
10
8
|
export type ModalFooterButtonAppearance = "default" | "text";
|
|
11
9
|
|
|
12
10
|
export type ModalFooterButtonDefaultOptions = {
|
|
@@ -28,7 +26,7 @@ export type ModalFooterButtonLinkOptions = {
|
|
|
28
26
|
};
|
|
29
27
|
|
|
30
28
|
export type ModalFooterButton = {
|
|
31
|
-
stackKey:
|
|
29
|
+
stackKey: string;
|
|
32
30
|
role: "close" | string;
|
|
33
31
|
defaultOptions: ModalFooterButtonDefaultOptions;
|
|
34
32
|
linkOptions?: ModalFooterButtonLinkOptions;
|
package/src/modal/types/index.ts
CHANGED
package/src/modal/types/state.ts
CHANGED
|
@@ -4,8 +4,6 @@ import type { ModalFooterButton } from "./footer";
|
|
|
4
4
|
|
|
5
5
|
export type ModalShowState = "init" | boolean;
|
|
6
6
|
|
|
7
|
-
export type ModalStackKey = string;
|
|
8
|
-
|
|
9
7
|
export type ModalSections = {
|
|
10
8
|
header?: ReactNode;
|
|
11
9
|
body: ReactNode;
|
|
@@ -19,13 +17,13 @@ export type ModalProps = ModalSections & {
|
|
|
19
17
|
};
|
|
20
18
|
|
|
21
19
|
export type ModalState = {
|
|
22
|
-
stackKey:
|
|
20
|
+
stackKey: string;
|
|
23
21
|
modalProps: ModalProps;
|
|
24
22
|
className?: string;
|
|
25
23
|
};
|
|
26
24
|
|
|
27
25
|
export type ModalStatePatch = {
|
|
28
|
-
stackKey:
|
|
26
|
+
stackKey: string;
|
|
29
27
|
modalProps?: Partial<ModalProps>;
|
|
30
28
|
className?: string;
|
|
31
29
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ReactNode } from "react";
|
|
2
2
|
|
|
3
|
-
import type { ModalState
|
|
3
|
+
import type { ModalState } from "./state";
|
|
4
4
|
|
|
5
5
|
export type ModalTemplateButtonSpec = {
|
|
6
6
|
label?: ReactNode;
|
|
@@ -10,7 +10,7 @@ export type ModalTemplateButtonSpec = {
|
|
|
10
10
|
};
|
|
11
11
|
|
|
12
12
|
type ModalTemplateBase = {
|
|
13
|
-
stackKey:
|
|
13
|
+
stackKey: string;
|
|
14
14
|
showDelay?: number;
|
|
15
15
|
};
|
|
16
16
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import clsx from "clsx";
|
|
2
2
|
import type { ReactNode } from "react";
|
|
3
3
|
|
|
4
|
+
import IconBackword from "../img/chevron-backward.svg";
|
|
4
5
|
import "./page-frame-mobile-header.scss";
|
|
5
6
|
|
|
6
7
|
export interface PageFrameMobileHeaderProps {
|
|
@@ -25,8 +26,8 @@ export function PageFrameMobileHeader({
|
|
|
25
26
|
rightSlot,
|
|
26
27
|
}: PageFrameMobileHeaderProps) {
|
|
27
28
|
return (
|
|
28
|
-
<
|
|
29
|
-
<
|
|
29
|
+
<header className={clsx("page-frame-mobile-header", className)}>
|
|
30
|
+
<div className="page-frame-mobile-header__left">
|
|
30
31
|
{leftSlot ??
|
|
31
32
|
(onBack ? (
|
|
32
33
|
<button
|
|
@@ -36,17 +37,19 @@ export function PageFrameMobileHeader({
|
|
|
36
37
|
aria-label="뒤로가기"
|
|
37
38
|
>
|
|
38
39
|
<span className="page-frame-mobile-header__back-icon">
|
|
39
|
-
{backIcon ??
|
|
40
|
+
{backIcon ?? (
|
|
41
|
+
<IconBackword width={24} height={24} alt="뒤로가기" />
|
|
42
|
+
)}
|
|
40
43
|
</span>
|
|
41
44
|
</button>
|
|
42
45
|
) : (
|
|
43
46
|
<span className="page-frame-mobile-header__back-placeholder" />
|
|
44
47
|
))}
|
|
45
|
-
</
|
|
46
|
-
<
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
</
|
|
50
|
-
</
|
|
48
|
+
</div>
|
|
49
|
+
<h2 className="page-frame-mobile-header__title">
|
|
50
|
+
<span>{title}</span>
|
|
51
|
+
</h2>
|
|
52
|
+
<div className="page-frame-mobile-header__right">{rightSlot ?? null}</div>
|
|
53
|
+
</header>
|
|
51
54
|
);
|
|
52
55
|
}
|