@hua-labs/hua-ux 0.1.0-alpha.0.1
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 +839 -0
- package/dist/framework/a11y/components/LiveRegion.d.ts +64 -0
- package/dist/framework/a11y/components/LiveRegion.d.ts.map +1 -0
- package/dist/framework/a11y/components/LiveRegion.js +43 -0
- package/dist/framework/a11y/components/SkipToContent.d.ts +62 -0
- package/dist/framework/a11y/components/SkipToContent.d.ts.map +1 -0
- package/dist/framework/a11y/components/SkipToContent.js +60 -0
- package/dist/framework/a11y/hooks/useFocusManagement.d.ts +60 -0
- package/dist/framework/a11y/hooks/useFocusManagement.d.ts.map +1 -0
- package/dist/framework/a11y/hooks/useFocusManagement.js +71 -0
- package/dist/framework/a11y/hooks/useFocusTrap.d.ts +64 -0
- package/dist/framework/a11y/hooks/useFocusTrap.d.ts.map +1 -0
- package/dist/framework/a11y/hooks/useFocusTrap.js +185 -0
- package/dist/framework/a11y/hooks/useLiveRegion.d.ts +56 -0
- package/dist/framework/a11y/hooks/useLiveRegion.d.ts.map +1 -0
- package/dist/framework/a11y/hooks/useLiveRegion.js +60 -0
- package/dist/framework/a11y/index.d.ts +16 -0
- package/dist/framework/a11y/index.d.ts.map +1 -0
- package/dist/framework/a11y/index.js +11 -0
- package/dist/framework/branding/context.d.ts +52 -0
- package/dist/framework/branding/context.d.ts.map +1 -0
- package/dist/framework/branding/context.js +96 -0
- package/dist/framework/branding/css-vars.d.ts +34 -0
- package/dist/framework/branding/css-vars.d.ts.map +1 -0
- package/dist/framework/branding/css-vars.js +95 -0
- package/dist/framework/branding/tailwind-config.d.ts +38 -0
- package/dist/framework/branding/tailwind-config.d.ts.map +1 -0
- package/dist/framework/branding/tailwind-config.js +66 -0
- package/dist/framework/components/BrandedButton.d.ts +53 -0
- package/dist/framework/components/BrandedButton.d.ts.map +1 -0
- package/dist/framework/components/BrandedButton.js +40 -0
- package/dist/framework/components/BrandedCard.d.ts +52 -0
- package/dist/framework/components/BrandedCard.d.ts.map +1 -0
- package/dist/framework/components/BrandedCard.js +73 -0
- package/dist/framework/components/ErrorBoundary.d.ts +92 -0
- package/dist/framework/components/ErrorBoundary.d.ts.map +1 -0
- package/dist/framework/components/ErrorBoundary.js +121 -0
- package/dist/framework/components/HuaUxLayout.d.ts +29 -0
- package/dist/framework/components/HuaUxLayout.d.ts.map +1 -0
- package/dist/framework/components/HuaUxLayout.js +32 -0
- package/dist/framework/components/HuaUxPage.d.ts +48 -0
- package/dist/framework/components/HuaUxPage.d.ts.map +1 -0
- package/dist/framework/components/HuaUxPage.js +105 -0
- package/dist/framework/components/Providers.d.ts +17 -0
- package/dist/framework/components/Providers.d.ts.map +1 -0
- package/dist/framework/components/Providers.js +72 -0
- package/dist/framework/components/WelcomePage.d.ts +44 -0
- package/dist/framework/components/WelcomePage.d.ts.map +1 -0
- package/dist/framework/components/WelcomePage.js +80 -0
- package/dist/framework/config/index.d.ts +182 -0
- package/dist/framework/config/index.d.ts.map +1 -0
- package/dist/framework/config/index.js +329 -0
- package/dist/framework/config/merge.d.ts +26 -0
- package/dist/framework/config/merge.d.ts.map +1 -0
- package/dist/framework/config/merge.js +160 -0
- package/dist/framework/config/schema.d.ts +25 -0
- package/dist/framework/config/schema.d.ts.map +1 -0
- package/dist/framework/config/schema.js +122 -0
- package/dist/framework/hooks/useMotion.d.ts +45 -0
- package/dist/framework/hooks/useMotion.d.ts.map +1 -0
- package/dist/framework/hooks/useMotion.js +40 -0
- package/dist/framework/index.d.ts +37 -0
- package/dist/framework/index.d.ts.map +1 -0
- package/dist/framework/index.js +42 -0
- package/dist/framework/license/errors.d.ts +15 -0
- package/dist/framework/license/errors.d.ts.map +1 -0
- package/dist/framework/license/errors.js +52 -0
- package/dist/framework/license/index.d.ts +70 -0
- package/dist/framework/license/index.d.ts.map +1 -0
- package/dist/framework/license/index.js +124 -0
- package/dist/framework/license/loader.d.ts +26 -0
- package/dist/framework/license/loader.d.ts.map +1 -0
- package/dist/framework/license/loader.js +137 -0
- package/dist/framework/license/types.d.ts +67 -0
- package/dist/framework/license/types.d.ts.map +1 -0
- package/dist/framework/license/types.js +18 -0
- package/dist/framework/loading/components/SkeletonGroup.d.ts +44 -0
- package/dist/framework/loading/components/SkeletonGroup.d.ts.map +1 -0
- package/dist/framework/loading/components/SkeletonGroup.js +34 -0
- package/dist/framework/loading/components/SuspenseWrapper.d.ts +58 -0
- package/dist/framework/loading/components/SuspenseWrapper.d.ts.map +1 -0
- package/dist/framework/loading/components/SuspenseWrapper.js +40 -0
- package/dist/framework/loading/hoc/withSuspense.d.ts +46 -0
- package/dist/framework/loading/hoc/withSuspense.d.ts.map +1 -0
- package/dist/framework/loading/hoc/withSuspense.js +54 -0
- package/dist/framework/loading/hooks/useDelayedLoading.d.ts +56 -0
- package/dist/framework/loading/hooks/useDelayedLoading.d.ts.map +1 -0
- package/dist/framework/loading/hooks/useDelayedLoading.js +97 -0
- package/dist/framework/loading/hooks/useLoadingState.d.ts +69 -0
- package/dist/framework/loading/hooks/useLoadingState.d.ts.map +1 -0
- package/dist/framework/loading/hooks/useLoadingState.js +59 -0
- package/dist/framework/loading/index.d.ts +16 -0
- package/dist/framework/loading/index.d.ts.map +1 -0
- package/dist/framework/loading/index.js +13 -0
- package/dist/framework/middleware/i18n.d.ts +90 -0
- package/dist/framework/middleware/i18n.d.ts.map +1 -0
- package/dist/framework/middleware/i18n.js +99 -0
- package/dist/framework/plugins/index.d.ts +8 -0
- package/dist/framework/plugins/index.d.ts.map +1 -0
- package/dist/framework/plugins/index.js +6 -0
- package/dist/framework/plugins/registry.d.ts +95 -0
- package/dist/framework/plugins/registry.d.ts.map +1 -0
- package/dist/framework/plugins/registry.js +160 -0
- package/dist/framework/plugins/types.d.ts +97 -0
- package/dist/framework/plugins/types.d.ts.map +1 -0
- package/dist/framework/plugins/types.js +6 -0
- package/dist/framework/seo/geo/examples.d.ts +87 -0
- package/dist/framework/seo/geo/examples.d.ts.map +1 -0
- package/dist/framework/seo/geo/examples.js +295 -0
- package/dist/framework/seo/geo/generateGEOMetadata.d.ts +107 -0
- package/dist/framework/seo/geo/generateGEOMetadata.d.ts.map +1 -0
- package/dist/framework/seo/geo/generateGEOMetadata.js +404 -0
- package/dist/framework/seo/geo/index.d.ts +19 -0
- package/dist/framework/seo/geo/index.d.ts.map +1 -0
- package/dist/framework/seo/geo/index.js +21 -0
- package/dist/framework/seo/geo/presets.d.ts +52 -0
- package/dist/framework/seo/geo/presets.d.ts.map +1 -0
- package/dist/framework/seo/geo/presets.js +47 -0
- package/dist/framework/seo/geo/structuredData.d.ts +187 -0
- package/dist/framework/seo/geo/structuredData.d.ts.map +1 -0
- package/dist/framework/seo/geo/structuredData.js +354 -0
- package/dist/framework/seo/geo/test-utils.d.ts +78 -0
- package/dist/framework/seo/geo/test-utils.d.ts.map +1 -0
- package/dist/framework/seo/geo/test-utils.js +139 -0
- package/dist/framework/seo/geo/types.d.ts +225 -0
- package/dist/framework/seo/geo/types.d.ts.map +1 -0
- package/dist/framework/seo/geo/types.js +51 -0
- package/dist/framework/types/index.d.ts +577 -0
- package/dist/framework/types/index.d.ts.map +1 -0
- package/dist/framework/types/index.js +6 -0
- package/dist/framework/utils/data-fetching.d.ts +45 -0
- package/dist/framework/utils/data-fetching.d.ts.map +1 -0
- package/dist/framework/utils/data-fetching.js +74 -0
- package/dist/framework/utils/file-structure.d.ts +29 -0
- package/dist/framework/utils/file-structure.d.ts.map +1 -0
- package/dist/framework/utils/file-structure.js +72 -0
- package/dist/framework/utils/metadata.d.ts +109 -0
- package/dist/framework/utils/metadata.d.ts.map +1 -0
- package/dist/framework/utils/metadata.js +105 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +21 -0
- package/dist/presets/index.d.ts +8 -0
- package/dist/presets/index.d.ts.map +1 -0
- package/dist/presets/index.js +7 -0
- package/dist/presets/marketing.d.ts +41 -0
- package/dist/presets/marketing.d.ts.map +1 -0
- package/dist/presets/marketing.js +81 -0
- package/dist/presets/product.d.ts +41 -0
- package/dist/presets/product.d.ts.map +1 -0
- package/dist/presets/product.js +74 -0
- package/package.json +91 -0
- package/src/framework/README.md +329 -0
- package/src/framework/__tests__/branding/css-vars.test.ts +147 -0
- package/src/framework/__tests__/components/ErrorBoundary.test.tsx +146 -0
- package/src/framework/__tests__/config/defineConfig.test.ts +138 -0
- package/src/framework/__tests__/hooks/useMotion.test.ts +105 -0
- package/src/framework/__tests__/seo/geo/generateGEOMetadata.test.ts +207 -0
- package/src/framework/__tests__/seo/geo/structuredData.test.ts +262 -0
- package/src/framework/a11y/components/LiveRegion.tsx +89 -0
- package/src/framework/a11y/components/SkipToContent.tsx +103 -0
- package/src/framework/a11y/hooks/useFocusManagement.ts +125 -0
- package/src/framework/a11y/hooks/useFocusTrap.ts +239 -0
- package/src/framework/a11y/hooks/useLiveRegion.ts +95 -0
- package/src/framework/a11y/index.ts +17 -0
- package/src/framework/branding/context.tsx +135 -0
- package/src/framework/branding/css-vars.ts +110 -0
- package/src/framework/branding/tailwind-config.ts +90 -0
- package/src/framework/components/BrandedButton.tsx +94 -0
- package/src/framework/components/BrandedCard.tsx +87 -0
- package/src/framework/components/ErrorBoundary.tsx +215 -0
- package/src/framework/components/HuaUxLayout.tsx +36 -0
- package/src/framework/components/HuaUxPage.tsx +138 -0
- package/src/framework/components/Providers.tsx +98 -0
- package/src/framework/components/WelcomePage.tsx +207 -0
- package/src/framework/config/index.ts +349 -0
- package/src/framework/config/merge.ts +190 -0
- package/src/framework/config/schema.ts +140 -0
- package/src/framework/hooks/useMotion.ts +57 -0
- package/src/framework/index.ts +122 -0
- package/src/framework/license/errors.ts +63 -0
- package/src/framework/license/index.ts +137 -0
- package/src/framework/license/loader.ts +158 -0
- package/src/framework/license/types.ts +95 -0
- package/src/framework/loading/components/SkeletonGroup.tsx +70 -0
- package/src/framework/loading/components/SuspenseWrapper.tsx +88 -0
- package/src/framework/loading/hoc/withSuspense.tsx +96 -0
- package/src/framework/loading/hooks/useDelayedLoading.ts +127 -0
- package/src/framework/loading/hooks/useLoadingState.ts +103 -0
- package/src/framework/loading/index.ts +19 -0
- package/src/framework/middleware/i18n.ts +161 -0
- package/src/framework/middleware/index.ts +7 -0
- package/src/framework/plugins/index.ts +13 -0
- package/src/framework/plugins/registry.ts +186 -0
- package/src/framework/plugins/types.ts +106 -0
- package/src/framework/seo/geo/examples.tsx +415 -0
- package/src/framework/seo/geo/generateGEOMetadata.ts +441 -0
- package/src/framework/seo/geo/index.ts +61 -0
- package/src/framework/seo/geo/presets.ts +58 -0
- package/src/framework/seo/geo/structuredData.ts +422 -0
- package/src/framework/seo/geo/test-utils.ts +179 -0
- package/src/framework/seo/geo/types.ts +315 -0
- package/src/framework/types/index.ts +623 -0
- package/src/framework/utils/data-fetching.ts +95 -0
- package/src/framework/utils/file-structure.ts +88 -0
- package/src/framework/utils/metadata.ts +152 -0
- package/src/index.ts +31 -0
- package/src/presets/index.ts +8 -0
- package/src/presets/marketing.ts +88 -0
- package/src/presets/product.ts +81 -0
|
@@ -0,0 +1,623 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @hua-labs/hua-ux/framework - Type Definitions
|
|
3
|
+
*
|
|
4
|
+
* Core types for the framework layer
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { ReactNode } from 'react';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Preset name
|
|
11
|
+
*/
|
|
12
|
+
export type PresetName = 'product' | 'marketing';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Preset configuration (개발자 모드 / Developer mode)
|
|
16
|
+
*
|
|
17
|
+
* 세부 설정을 포함한 Preset 객체 형태
|
|
18
|
+
* Preset object with detailed settings
|
|
19
|
+
*/
|
|
20
|
+
export interface PresetConfig {
|
|
21
|
+
/**
|
|
22
|
+
* Preset type / Preset 타입
|
|
23
|
+
*/
|
|
24
|
+
type: PresetName;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Motion overrides / 모션 설정 오버라이드
|
|
28
|
+
*
|
|
29
|
+
* Preset의 기본 모션 설정을 세부적으로 조정
|
|
30
|
+
* Fine-tune preset's default motion settings
|
|
31
|
+
*/
|
|
32
|
+
motion?: {
|
|
33
|
+
/**
|
|
34
|
+
* Animation duration in milliseconds / 애니메이션 지속 시간 (밀리초)
|
|
35
|
+
*/
|
|
36
|
+
duration?: number;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Animation easing function / 애니메이션 이징 함수
|
|
40
|
+
*/
|
|
41
|
+
easing?: string;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Spacing overrides / 간격 설정 오버라이드
|
|
46
|
+
*
|
|
47
|
+
* Preset의 기본 간격 설정을 세부적으로 조정
|
|
48
|
+
* Fine-tune preset's default spacing settings
|
|
49
|
+
*/
|
|
50
|
+
spacing?: {
|
|
51
|
+
/**
|
|
52
|
+
* Default spacing size / 기본 간격 크기
|
|
53
|
+
*/
|
|
54
|
+
default?: 'sm' | 'md' | 'lg' | 'xl';
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Preset (바이브 모드 또는 개발자 모드)
|
|
60
|
+
*
|
|
61
|
+
* - 문자열: 바이브 모드 (간단) / String: Vibe mode (simple)
|
|
62
|
+
* - 객체: 개발자 모드 (세부 설정) / Object: Developer mode (detailed)
|
|
63
|
+
*/
|
|
64
|
+
export type Preset = PresetName | PresetConfig;
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Framework configuration
|
|
68
|
+
*/
|
|
69
|
+
export interface HuaUxConfig {
|
|
70
|
+
/**
|
|
71
|
+
* Preset to use / 사용할 프리셋
|
|
72
|
+
*
|
|
73
|
+
* Preset을 선택하면 대부분의 설정이 자동으로 적용됩니다.
|
|
74
|
+
* Selecting a preset automatically applies most settings.
|
|
75
|
+
*
|
|
76
|
+
* **바이브 모드 (간단) / Vibe mode (simple)**:
|
|
77
|
+
* ```ts
|
|
78
|
+
* preset: 'product' // 이것만으로도 대부분 설정 완료
|
|
79
|
+
* ```
|
|
80
|
+
*
|
|
81
|
+
* **개발자 모드 (세부 설정) / Developer mode (detailed)**:
|
|
82
|
+
* ```ts
|
|
83
|
+
* preset: {
|
|
84
|
+
* type: 'product',
|
|
85
|
+
* motion: { duration: 300 },
|
|
86
|
+
* spacing: { default: 'md' },
|
|
87
|
+
* }
|
|
88
|
+
* ```
|
|
89
|
+
*
|
|
90
|
+
* - 'product': Professional, efficient (default) / 제품 페이지용 (전문적, 효율적, 기본값)
|
|
91
|
+
* - 'marketing': Dramatic, eye-catching / 마케팅 페이지용 (화려함, 눈에 띄는)
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* ```ts
|
|
95
|
+
* // 바이브 코더용 (간단)
|
|
96
|
+
* export default defineConfig({
|
|
97
|
+
* preset: 'product', // 끝!
|
|
98
|
+
* });
|
|
99
|
+
* ```
|
|
100
|
+
*
|
|
101
|
+
* @example
|
|
102
|
+
* ```ts
|
|
103
|
+
* // 전통 개발자용 (세부 설정)
|
|
104
|
+
* export default defineConfig({
|
|
105
|
+
* preset: {
|
|
106
|
+
* type: 'product',
|
|
107
|
+
* motion: { duration: 300 },
|
|
108
|
+
* },
|
|
109
|
+
* });
|
|
110
|
+
* ```
|
|
111
|
+
*/
|
|
112
|
+
preset?: Preset;
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* i18n configuration / 다국어 설정
|
|
116
|
+
*
|
|
117
|
+
* Internationalization settings for multi-language support.
|
|
118
|
+
* 다국어 지원을 위한 설정입니다.
|
|
119
|
+
*/
|
|
120
|
+
i18n?: {
|
|
121
|
+
/**
|
|
122
|
+
* Default language code / 기본 언어 코드
|
|
123
|
+
*
|
|
124
|
+
* 예: 'ko', 'en' / e.g., 'ko', 'en'
|
|
125
|
+
*/
|
|
126
|
+
defaultLanguage: string;
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Supported language codes / 지원하는 언어 코드 배열
|
|
130
|
+
*
|
|
131
|
+
* 예: ['ko', 'en', 'ja'] / e.g., ['ko', 'en', 'ja']
|
|
132
|
+
*/
|
|
133
|
+
supportedLanguages: string[];
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Fallback language / 대체 언어
|
|
137
|
+
*
|
|
138
|
+
* 번역이 없을 때 사용할 언어 / Language to use when translation is missing
|
|
139
|
+
*/
|
|
140
|
+
fallbackLanguage?: string;
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Translation namespaces / 번역 네임스페이스
|
|
144
|
+
*
|
|
145
|
+
* 로드할 번역 네임스페이스 목록 / List of translation namespaces to load
|
|
146
|
+
*/
|
|
147
|
+
namespaces?: string[];
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Translation loading strategy / 번역 로딩 전략
|
|
151
|
+
*
|
|
152
|
+
* - 'api': API Route에서 로드 / Load from API Route
|
|
153
|
+
* - 'static': 정적 파일에서 로드 / Load from static files
|
|
154
|
+
* - 'custom': 커스텀 로더 사용 / Use custom loader
|
|
155
|
+
*/
|
|
156
|
+
translationLoader?: 'api' | 'static' | 'custom';
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Translation API path / 번역 API 경로
|
|
160
|
+
*
|
|
161
|
+
* 'api' 로더 사용 시 API 경로 / API path when using 'api' loader
|
|
162
|
+
*/
|
|
163
|
+
translationApiPath?: string;
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Custom translation loader / 커스텀 번역 로더
|
|
167
|
+
*
|
|
168
|
+
* 'custom' 로더 사용 시 커스텀 로더 함수 / Custom loader function when using 'custom' loader
|
|
169
|
+
*
|
|
170
|
+
* @example
|
|
171
|
+
* ```ts
|
|
172
|
+
* loadTranslations: async (language, namespace) => {
|
|
173
|
+
* const response = await fetch(`/translations/${language}/${namespace}.json`);
|
|
174
|
+
* return response.json();
|
|
175
|
+
* }
|
|
176
|
+
* ```
|
|
177
|
+
*/
|
|
178
|
+
loadTranslations?: (language: string, namespace: string) => Promise<Record<string, string>>;
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Debug mode / 디버그 모드
|
|
182
|
+
*
|
|
183
|
+
* 디버그 모드를 활성화하면 Translator의 상세한 로그가 출력됩니다.
|
|
184
|
+
* Enable debug mode to see detailed Translator logs.
|
|
185
|
+
*/
|
|
186
|
+
debug?: boolean;
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Motion configuration / 모션/애니메이션 설정
|
|
191
|
+
*
|
|
192
|
+
* Animation and motion settings.
|
|
193
|
+
* 애니메이션 및 모션 설정입니다.
|
|
194
|
+
*/
|
|
195
|
+
motion?: {
|
|
196
|
+
/**
|
|
197
|
+
* Motion style (바이브 코더용) / 모션 스타일 (바이브 코더용)
|
|
198
|
+
*
|
|
199
|
+
* 명사 중심의 비즈니스 의도 표현
|
|
200
|
+
* Noun-centered business intent expression
|
|
201
|
+
*
|
|
202
|
+
* - 'smooth': 부드러운 전환 / Smooth transitions
|
|
203
|
+
* - 'dramatic': 드라마틱한 전환 / Dramatic transitions
|
|
204
|
+
* - 'minimal': 최소한의 전환 / Minimal transitions
|
|
205
|
+
*
|
|
206
|
+
* @example
|
|
207
|
+
* ```ts
|
|
208
|
+
* motion: {
|
|
209
|
+
* style: 'smooth', // 바이브 코더가 이해하기 쉬움
|
|
210
|
+
* }
|
|
211
|
+
* ```
|
|
212
|
+
*/
|
|
213
|
+
style?: 'smooth' | 'dramatic' | 'minimal';
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Default motion preset (개발자용) / 기본 모션 프리셋 (개발자용)
|
|
217
|
+
*
|
|
218
|
+
* - 'product': 빠른 전환, 최소 딜레이 / Fast transitions, minimal delay
|
|
219
|
+
* - 'marketing': 느린 전환, 긴 딜레이 / Slow transitions, long delay
|
|
220
|
+
*
|
|
221
|
+
* @note `style`이 설정되면 자동으로 매핑됩니다.
|
|
222
|
+
* @note Automatically mapped when `style` is set.
|
|
223
|
+
*/
|
|
224
|
+
defaultPreset?: 'product' | 'marketing';
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Enable animations globally / 전역 애니메이션 활성화 여부
|
|
228
|
+
*
|
|
229
|
+
* false로 설정하면 모든 애니메이션 비활성화 / Set to false to disable all animations
|
|
230
|
+
*/
|
|
231
|
+
enableAnimations?: boolean;
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Animation duration in milliseconds (개발자용) / 애니메이션 지속 시간 (밀리초, 개발자용)
|
|
235
|
+
*/
|
|
236
|
+
duration?: number;
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Animation easing function (개발자용) / 애니메이션 이징 함수 (개발자용)
|
|
240
|
+
*/
|
|
241
|
+
easing?: string;
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* State management configuration
|
|
246
|
+
*/
|
|
247
|
+
state?: {
|
|
248
|
+
persist?: boolean;
|
|
249
|
+
ssr?: boolean;
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* File structure configuration
|
|
254
|
+
*/
|
|
255
|
+
fileStructure?: {
|
|
256
|
+
enforce?: boolean;
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Plugins / 플러그인
|
|
261
|
+
*
|
|
262
|
+
* 프레임워크에 등록할 플러그인 목록
|
|
263
|
+
* List of plugins to register with the framework
|
|
264
|
+
*
|
|
265
|
+
* **플러그인 타입**:
|
|
266
|
+
* - 기능 플러그인: 고급 기능 추가 (예: motion-pro, i18n-pro)
|
|
267
|
+
* - 프리셋 플러그인: 새로운 프리셋 추가 (예: ecommerce, dashboard)
|
|
268
|
+
* - 브랜딩 플러그인: 화이트 라벨링 지원
|
|
269
|
+
*
|
|
270
|
+
* **Plugin types**:
|
|
271
|
+
* - Feature plugins: Add advanced features (e.g., motion-pro, i18n-pro)
|
|
272
|
+
* - Preset plugins: Add new presets (e.g., ecommerce, dashboard)
|
|
273
|
+
* - Branding plugins: White labeling support
|
|
274
|
+
*
|
|
275
|
+
* @example
|
|
276
|
+
* ```ts
|
|
277
|
+
* import { defineConfig } from '@hua-labs/hua-ux/framework';
|
|
278
|
+
* import { motionProPlugin } from '@hua-labs/motion-core/pro';
|
|
279
|
+
*
|
|
280
|
+
* export default defineConfig({
|
|
281
|
+
* preset: 'product',
|
|
282
|
+
* plugins: [motionProPlugin],
|
|
283
|
+
* });
|
|
284
|
+
* ```
|
|
285
|
+
*/
|
|
286
|
+
plugins?: import('../plugins/types').HuaUxPlugin[];
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* License configuration / 라이선스 설정
|
|
290
|
+
*
|
|
291
|
+
* Pro/Enterprise 기능을 사용하기 위한 라이선스 설정입니다.
|
|
292
|
+
* License settings for Pro/Enterprise features.
|
|
293
|
+
*
|
|
294
|
+
* **로드 순서**:
|
|
295
|
+
* 1. 환경 변수 (`HUA_UX_LICENSE_KEY`)
|
|
296
|
+
* 2. 설정 파일 (`license.apiKey` 또는 `license.type`)
|
|
297
|
+
* 3. 기본값 (Free)
|
|
298
|
+
*
|
|
299
|
+
* **Load order**:
|
|
300
|
+
* 1. Environment variable (`HUA_UX_LICENSE_KEY`)
|
|
301
|
+
* 2. Config file (`license.apiKey` or `license.type`)
|
|
302
|
+
* 3. Default (Free)
|
|
303
|
+
*
|
|
304
|
+
* @example
|
|
305
|
+
* ```ts
|
|
306
|
+
* // 환경 변수 사용 (권장)
|
|
307
|
+
* // HUA_UX_LICENSE_KEY=pro_xxx pnpm dev
|
|
308
|
+
*
|
|
309
|
+
* // 또는 설정 파일에서
|
|
310
|
+
* export default defineConfig({
|
|
311
|
+
* license: {
|
|
312
|
+
* apiKey: 'pro_xxx', // 실제 API 키
|
|
313
|
+
* },
|
|
314
|
+
* });
|
|
315
|
+
* ```
|
|
316
|
+
*
|
|
317
|
+
* @example
|
|
318
|
+
* ```ts
|
|
319
|
+
* // 개발용 (타입만 지정)
|
|
320
|
+
* export default defineConfig({
|
|
321
|
+
* license: {
|
|
322
|
+
* type: 'pro', // 개발 환경에서만 사용
|
|
323
|
+
* },
|
|
324
|
+
* });
|
|
325
|
+
* ```
|
|
326
|
+
*/
|
|
327
|
+
license?: {
|
|
328
|
+
/**
|
|
329
|
+
* API 키 / API key
|
|
330
|
+
*
|
|
331
|
+
* Pro/Enterprise 라이선스의 API 키
|
|
332
|
+
* API key for Pro/Enterprise license
|
|
333
|
+
*/
|
|
334
|
+
apiKey?: string;
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* 라이선스 타입 (개발용) / License type (for development)
|
|
338
|
+
*
|
|
339
|
+
* 개발 환경에서만 사용하세요. 프로덕션에서는 `apiKey`를 사용하세요.
|
|
340
|
+
* Use only in development. Use `apiKey` in production.
|
|
341
|
+
*/
|
|
342
|
+
type?: 'free' | 'pro' | 'enterprise';
|
|
343
|
+
};
|
|
344
|
+
|
|
345
|
+
/**
|
|
346
|
+
* Branding configuration (White Labeling) / 브랜딩 설정 (화이트 라벨링)
|
|
347
|
+
*
|
|
348
|
+
* 브랜드 커스터마이징을 위한 설정입니다.
|
|
349
|
+
* Brand customization settings.
|
|
350
|
+
*
|
|
351
|
+
* 색상, 타이포그래피, 로고 등을 설정하면 모든 컴포넌트에 자동 적용됩니다.
|
|
352
|
+
* Setting colors, typography, logo, etc. automatically applies to all components.
|
|
353
|
+
*
|
|
354
|
+
* @example
|
|
355
|
+
* ```ts
|
|
356
|
+
* export default defineConfig({
|
|
357
|
+
* preset: 'product',
|
|
358
|
+
* branding: {
|
|
359
|
+
* name: 'My Company',
|
|
360
|
+
* logo: '/logo.svg',
|
|
361
|
+
* colors: {
|
|
362
|
+
* primary: '#3B82F6',
|
|
363
|
+
* secondary: '#8B5CF6',
|
|
364
|
+
* },
|
|
365
|
+
* typography: {
|
|
366
|
+
* fontFamily: ['Inter', 'sans-serif'],
|
|
367
|
+
* },
|
|
368
|
+
* },
|
|
369
|
+
* });
|
|
370
|
+
* ```
|
|
371
|
+
*/
|
|
372
|
+
branding?: {
|
|
373
|
+
/**
|
|
374
|
+
* Company/Service name / 회사/서비스 이름
|
|
375
|
+
*/
|
|
376
|
+
name?: string;
|
|
377
|
+
|
|
378
|
+
/**
|
|
379
|
+
* Logo path / 로고 경로
|
|
380
|
+
*/
|
|
381
|
+
logo?: string;
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
* Color palette / 색상 팔레트
|
|
385
|
+
*
|
|
386
|
+
* Tailwind 색상 이름 또는 hex 코드를 사용할 수 있습니다.
|
|
387
|
+
* You can use Tailwind color names or hex codes.
|
|
388
|
+
*/
|
|
389
|
+
colors?: {
|
|
390
|
+
primary?: string;
|
|
391
|
+
secondary?: string;
|
|
392
|
+
accent?: string;
|
|
393
|
+
success?: string;
|
|
394
|
+
warning?: string;
|
|
395
|
+
error?: string;
|
|
396
|
+
info?: string;
|
|
397
|
+
};
|
|
398
|
+
|
|
399
|
+
/**
|
|
400
|
+
* Typography settings / 타이포그래피 설정
|
|
401
|
+
*/
|
|
402
|
+
typography?: {
|
|
403
|
+
/**
|
|
404
|
+
* Font family stack / 폰트 패밀리 스택
|
|
405
|
+
*/
|
|
406
|
+
fontFamily?: string[];
|
|
407
|
+
|
|
408
|
+
/**
|
|
409
|
+
* Font sizes / 폰트 크기
|
|
410
|
+
*/
|
|
411
|
+
fontSize?: {
|
|
412
|
+
h1?: string;
|
|
413
|
+
h2?: string;
|
|
414
|
+
h3?: string;
|
|
415
|
+
body?: string;
|
|
416
|
+
};
|
|
417
|
+
};
|
|
418
|
+
|
|
419
|
+
/**
|
|
420
|
+
* Custom CSS variables / 커스텀 CSS 변수
|
|
421
|
+
*
|
|
422
|
+
* 추가적인 CSS 변수를 정의할 수 있습니다.
|
|
423
|
+
* You can define additional CSS variables.
|
|
424
|
+
*/
|
|
425
|
+
customVariables?: Record<string, string>;
|
|
426
|
+
};
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
/**
|
|
430
|
+
* HuaUxLayout props
|
|
431
|
+
*/
|
|
432
|
+
export interface HuaUxLayoutProps {
|
|
433
|
+
children: ReactNode;
|
|
434
|
+
/**
|
|
435
|
+
* Override config (optional, uses hua-ux.config.ts by default)
|
|
436
|
+
*/
|
|
437
|
+
config?: Partial<HuaUxConfig>;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
/**
|
|
441
|
+
* HuaUxPage props
|
|
442
|
+
*/
|
|
443
|
+
export interface HuaUxPageProps {
|
|
444
|
+
children: ReactNode;
|
|
445
|
+
|
|
446
|
+
/**
|
|
447
|
+
* 페이지 제목 / Page title
|
|
448
|
+
*
|
|
449
|
+
* SEO 메타데이터에 사용됩니다.
|
|
450
|
+
* Used for SEO metadata.
|
|
451
|
+
*/
|
|
452
|
+
title?: string;
|
|
453
|
+
|
|
454
|
+
/**
|
|
455
|
+
* 페이지 설명 / Page description
|
|
456
|
+
*
|
|
457
|
+
* SEO 메타데이터에 사용됩니다.
|
|
458
|
+
* Used for SEO metadata.
|
|
459
|
+
*/
|
|
460
|
+
description?: string;
|
|
461
|
+
|
|
462
|
+
/**
|
|
463
|
+
* 페이지 감도 / Page vibe
|
|
464
|
+
*
|
|
465
|
+
* AI가 페이지의 스타일을 결정하는 핵심 키워드입니다.
|
|
466
|
+
* Core keyword for AI to determine page style.
|
|
467
|
+
*
|
|
468
|
+
* - 'clean': 여백 중심, 미니멀한 인터랙션 / Spacing-focused, minimal interactions
|
|
469
|
+
* - 'fancy': 화려한 인터랙션, 드라마틱한 모션 / Rich interactions, dramatic motion
|
|
470
|
+
* - 'minimal': 최소한의 모션, 빠른 전환 / Minimal motion, fast transitions
|
|
471
|
+
*
|
|
472
|
+
* @vibe AI가 페이지의 감도를 결정하는 핵심 키워드
|
|
473
|
+
*
|
|
474
|
+
* @example
|
|
475
|
+
* ```tsx
|
|
476
|
+
* <HuaUxPage vibe="clean">
|
|
477
|
+
* <div>여백 중심의 깔끔한 페이지</div>
|
|
478
|
+
* </HuaUxPage>
|
|
479
|
+
* ```
|
|
480
|
+
*/
|
|
481
|
+
vibe?: 'clean' | 'fancy' | 'minimal';
|
|
482
|
+
|
|
483
|
+
/**
|
|
484
|
+
* i18n 네임스페이스 키 / i18n namespace key
|
|
485
|
+
*
|
|
486
|
+
* 번역 파일의 네임스페이스를 지정합니다.
|
|
487
|
+
* 설정하면 해당 네임스페이스가 자동으로 로드되고,
|
|
488
|
+
* `title`과 `description`을 번역 키로 사용할 수 있습니다.
|
|
489
|
+
*
|
|
490
|
+
* Specifies the translation namespace.
|
|
491
|
+
* If specified, the namespace is automatically loaded,
|
|
492
|
+
* and `title` and `description` can be used as translation keys.
|
|
493
|
+
*
|
|
494
|
+
* **자동 번역 키 형식 / Auto translation key format**:
|
|
495
|
+
* - `title` → `${i18nKey}:title` 또는 `${i18nKey}.title`
|
|
496
|
+
* - `description` → `${i18nKey}:description` 또는 `${i18nKey}.description`
|
|
497
|
+
*
|
|
498
|
+
* @example
|
|
499
|
+
* ```tsx
|
|
500
|
+
* // translations/ko/home.json
|
|
501
|
+
* {
|
|
502
|
+
* "title": "홈",
|
|
503
|
+
* "description": "환영합니다"
|
|
504
|
+
* }
|
|
505
|
+
*
|
|
506
|
+
* // app/page.tsx
|
|
507
|
+
* <HuaUxPage i18nKey="home" title="home:title" description="home:description">
|
|
508
|
+
* <div>translations/ko/home.json, translations/en/home.json 사용</div>
|
|
509
|
+
* </HuaUxPage>
|
|
510
|
+
* ```
|
|
511
|
+
*/
|
|
512
|
+
i18nKey?: string;
|
|
513
|
+
|
|
514
|
+
/**
|
|
515
|
+
* 페이지 전환 애니메이션 활성화 / Enable page transition animations
|
|
516
|
+
*
|
|
517
|
+
* 기본값: true (설정에서 motion.enableAnimations가 true인 경우)
|
|
518
|
+
* Default: true (when motion.enableAnimations is true in config)
|
|
519
|
+
*/
|
|
520
|
+
enableMotion?: boolean;
|
|
521
|
+
|
|
522
|
+
/**
|
|
523
|
+
* 모션 타입 / Motion type
|
|
524
|
+
*
|
|
525
|
+
* 페이지 진입 시 사용할 모션 애니메이션 타입을 지정합니다.
|
|
526
|
+
* 지정하지 않으면 `vibe`에 따라 자동 선택됩니다.
|
|
527
|
+
*
|
|
528
|
+
* Specifies the motion animation type to use when the page enters.
|
|
529
|
+
* If not specified, automatically selected based on `vibe`.
|
|
530
|
+
*
|
|
531
|
+
* - 'fadeIn': 페이드 인 (기본값) / Fade in (default)
|
|
532
|
+
* - 'slideUp': 아래에서 위로 슬라이드 / Slide up from bottom
|
|
533
|
+
* - 'slideLeft': 오른쪽에서 왼쪽으로 슬라이드 / Slide from right to left
|
|
534
|
+
* - 'slideRight': 왼쪽에서 오른쪽으로 슬라이드 / Slide from left to right
|
|
535
|
+
* - 'scaleIn': 크기 확대 / Scale in
|
|
536
|
+
* - 'bounceIn': 바운스 효과 / Bounce in
|
|
537
|
+
*
|
|
538
|
+
* @example
|
|
539
|
+
* ```tsx
|
|
540
|
+
* <HuaUxPage motion="slideUp" vibe="fancy">
|
|
541
|
+
* <div>아래에서 위로 슬라이드되며 나타납니다</div>
|
|
542
|
+
* </HuaUxPage>
|
|
543
|
+
* ```
|
|
544
|
+
*/
|
|
545
|
+
motion?: 'fadeIn' | 'slideUp' | 'slideLeft' | 'slideRight' | 'scaleIn' | 'bounceIn';
|
|
546
|
+
|
|
547
|
+
/**
|
|
548
|
+
* SEO 메타데이터 설정 / SEO metadata settings
|
|
549
|
+
*
|
|
550
|
+
* Next.js App Router에서는 page.tsx에서 `export const metadata`를 사용하는 것이 권장됩니다.
|
|
551
|
+
* 이 prop은 문서화 및 타입 안전성을 위한 것입니다.
|
|
552
|
+
*
|
|
553
|
+
* In Next.js App Router, using `export const metadata` in page.tsx is recommended.
|
|
554
|
+
* This prop is for documentation and type safety.
|
|
555
|
+
*
|
|
556
|
+
* @example
|
|
557
|
+
* ```tsx
|
|
558
|
+
* // page.tsx
|
|
559
|
+
* import { generatePageMetadata } from '@hua-labs/hua-ux/framework';
|
|
560
|
+
*
|
|
561
|
+
* export const metadata = generatePageMetadata({
|
|
562
|
+
* title: '홈',
|
|
563
|
+
* description: '환영합니다',
|
|
564
|
+
* seo: {
|
|
565
|
+
* keywords: ['키워드1', '키워드2'],
|
|
566
|
+
* ogImage: '/og-image.png',
|
|
567
|
+
* },
|
|
568
|
+
* });
|
|
569
|
+
*
|
|
570
|
+
* export default function HomePage() {
|
|
571
|
+
* return <HuaUxPage title="홈" seo={{ keywords: ['키워드1'] }}>...</HuaUxPage>;
|
|
572
|
+
* }
|
|
573
|
+
* ```
|
|
574
|
+
*/
|
|
575
|
+
seo?: {
|
|
576
|
+
/**
|
|
577
|
+
* 검색 엔진 키워드 / Search engine keywords
|
|
578
|
+
*/
|
|
579
|
+
keywords?: string[];
|
|
580
|
+
|
|
581
|
+
/**
|
|
582
|
+
* Open Graph 이미지 / Open Graph image
|
|
583
|
+
*/
|
|
584
|
+
ogImage?: string;
|
|
585
|
+
|
|
586
|
+
/**
|
|
587
|
+
* Open Graph 제목 / Open Graph title
|
|
588
|
+
*
|
|
589
|
+
* 지정하지 않으면 `title` prop 사용
|
|
590
|
+
* If not specified, uses `title` prop
|
|
591
|
+
*/
|
|
592
|
+
ogTitle?: string;
|
|
593
|
+
|
|
594
|
+
/**
|
|
595
|
+
* Open Graph 설명 / Open Graph description
|
|
596
|
+
*
|
|
597
|
+
* 지정하지 않으면 `description` prop 사용
|
|
598
|
+
* If not specified, uses `description` prop
|
|
599
|
+
*/
|
|
600
|
+
ogDescription?: string;
|
|
601
|
+
|
|
602
|
+
/**
|
|
603
|
+
* Open Graph 타입 / Open Graph type
|
|
604
|
+
*/
|
|
605
|
+
ogType?: 'website' | 'article' | 'product';
|
|
606
|
+
};
|
|
607
|
+
|
|
608
|
+
/**
|
|
609
|
+
* ErrorBoundary 활성화 여부 / Enable ErrorBoundary
|
|
610
|
+
*
|
|
611
|
+
* 기본값: true
|
|
612
|
+
* Default: true
|
|
613
|
+
*/
|
|
614
|
+
enableErrorBoundary?: boolean;
|
|
615
|
+
|
|
616
|
+
/**
|
|
617
|
+
* ErrorBoundary fallback UI / ErrorBoundary fallback UI
|
|
618
|
+
*
|
|
619
|
+
* 에러 발생 시 표시할 커스텀 fallback UI
|
|
620
|
+
* Custom fallback UI to display when an error occurs
|
|
621
|
+
*/
|
|
622
|
+
errorBoundaryFallback?: ReactNode | ((error: Error, reset: () => void) => ReactNode);
|
|
623
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @hua-labs/hua-ux/framework - Data Fetching Utilities
|
|
3
|
+
*
|
|
4
|
+
* Type-safe data fetching utilities for server and client components
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
'use client';
|
|
8
|
+
|
|
9
|
+
import React, { useState, useEffect } from 'react';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Data fetching result
|
|
13
|
+
*/
|
|
14
|
+
export interface DataFetchResult<T> {
|
|
15
|
+
data: T | null;
|
|
16
|
+
isLoading: boolean;
|
|
17
|
+
error: Error | null;
|
|
18
|
+
refetch: () => Promise<void>;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Client-side data fetching hook
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```tsx
|
|
26
|
+
* function MyComponent() {
|
|
27
|
+
* const { data, isLoading, error } = useData<Post[]>('/api/posts');
|
|
28
|
+
*
|
|
29
|
+
* if (isLoading) return <Spinner />;
|
|
30
|
+
* if (error) return <Error message={error.message} />;
|
|
31
|
+
* return <PostList posts={data} />;
|
|
32
|
+
* }
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export function useData<T>(
|
|
36
|
+
url: string,
|
|
37
|
+
options?: RequestInit
|
|
38
|
+
): DataFetchResult<T> {
|
|
39
|
+
const [data, setData] = useState<T | null>(null);
|
|
40
|
+
const [isLoading, setIsLoading] = useState(true);
|
|
41
|
+
const [error, setError] = useState<Error | null>(null);
|
|
42
|
+
|
|
43
|
+
const fetchData = React.useCallback(async () => {
|
|
44
|
+
try {
|
|
45
|
+
setIsLoading(true);
|
|
46
|
+
setError(null);
|
|
47
|
+
const response = await fetch(url, options);
|
|
48
|
+
if (!response.ok) {
|
|
49
|
+
throw new Error(`HTTP error! status: ${response.status}`);
|
|
50
|
+
}
|
|
51
|
+
const json = await response.json();
|
|
52
|
+
setData(json);
|
|
53
|
+
} catch (err) {
|
|
54
|
+
setError(err instanceof Error ? err : new Error('Unknown error'));
|
|
55
|
+
} finally {
|
|
56
|
+
setIsLoading(false);
|
|
57
|
+
}
|
|
58
|
+
}, [url, options]);
|
|
59
|
+
|
|
60
|
+
useEffect(() => {
|
|
61
|
+
fetchData();
|
|
62
|
+
}, [fetchData]);
|
|
63
|
+
|
|
64
|
+
return {
|
|
65
|
+
data,
|
|
66
|
+
isLoading,
|
|
67
|
+
error,
|
|
68
|
+
refetch: fetchData,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Server-side data fetching utility
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
* ```tsx
|
|
77
|
+
* // app/page.tsx (Server Component)
|
|
78
|
+
* import { fetchData } from '@hua-labs/hua-ux/framework';
|
|
79
|
+
*
|
|
80
|
+
* export default async function HomePage() {
|
|
81
|
+
* const posts = await fetchData<Post[]>('/api/posts');
|
|
82
|
+
* return <PostList posts={posts} />;
|
|
83
|
+
* }
|
|
84
|
+
* ```
|
|
85
|
+
*/
|
|
86
|
+
export async function fetchData<T>(
|
|
87
|
+
url: string,
|
|
88
|
+
options?: RequestInit
|
|
89
|
+
): Promise<T> {
|
|
90
|
+
const response = await fetch(url, options);
|
|
91
|
+
if (!response.ok) {
|
|
92
|
+
throw new Error(`HTTP error! status: ${response.status}`);
|
|
93
|
+
}
|
|
94
|
+
return response.json();
|
|
95
|
+
}
|