@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.
Files changed (210) hide show
  1. package/README.md +839 -0
  2. package/dist/framework/a11y/components/LiveRegion.d.ts +64 -0
  3. package/dist/framework/a11y/components/LiveRegion.d.ts.map +1 -0
  4. package/dist/framework/a11y/components/LiveRegion.js +43 -0
  5. package/dist/framework/a11y/components/SkipToContent.d.ts +62 -0
  6. package/dist/framework/a11y/components/SkipToContent.d.ts.map +1 -0
  7. package/dist/framework/a11y/components/SkipToContent.js +60 -0
  8. package/dist/framework/a11y/hooks/useFocusManagement.d.ts +60 -0
  9. package/dist/framework/a11y/hooks/useFocusManagement.d.ts.map +1 -0
  10. package/dist/framework/a11y/hooks/useFocusManagement.js +71 -0
  11. package/dist/framework/a11y/hooks/useFocusTrap.d.ts +64 -0
  12. package/dist/framework/a11y/hooks/useFocusTrap.d.ts.map +1 -0
  13. package/dist/framework/a11y/hooks/useFocusTrap.js +185 -0
  14. package/dist/framework/a11y/hooks/useLiveRegion.d.ts +56 -0
  15. package/dist/framework/a11y/hooks/useLiveRegion.d.ts.map +1 -0
  16. package/dist/framework/a11y/hooks/useLiveRegion.js +60 -0
  17. package/dist/framework/a11y/index.d.ts +16 -0
  18. package/dist/framework/a11y/index.d.ts.map +1 -0
  19. package/dist/framework/a11y/index.js +11 -0
  20. package/dist/framework/branding/context.d.ts +52 -0
  21. package/dist/framework/branding/context.d.ts.map +1 -0
  22. package/dist/framework/branding/context.js +96 -0
  23. package/dist/framework/branding/css-vars.d.ts +34 -0
  24. package/dist/framework/branding/css-vars.d.ts.map +1 -0
  25. package/dist/framework/branding/css-vars.js +95 -0
  26. package/dist/framework/branding/tailwind-config.d.ts +38 -0
  27. package/dist/framework/branding/tailwind-config.d.ts.map +1 -0
  28. package/dist/framework/branding/tailwind-config.js +66 -0
  29. package/dist/framework/components/BrandedButton.d.ts +53 -0
  30. package/dist/framework/components/BrandedButton.d.ts.map +1 -0
  31. package/dist/framework/components/BrandedButton.js +40 -0
  32. package/dist/framework/components/BrandedCard.d.ts +52 -0
  33. package/dist/framework/components/BrandedCard.d.ts.map +1 -0
  34. package/dist/framework/components/BrandedCard.js +73 -0
  35. package/dist/framework/components/ErrorBoundary.d.ts +92 -0
  36. package/dist/framework/components/ErrorBoundary.d.ts.map +1 -0
  37. package/dist/framework/components/ErrorBoundary.js +121 -0
  38. package/dist/framework/components/HuaUxLayout.d.ts +29 -0
  39. package/dist/framework/components/HuaUxLayout.d.ts.map +1 -0
  40. package/dist/framework/components/HuaUxLayout.js +32 -0
  41. package/dist/framework/components/HuaUxPage.d.ts +48 -0
  42. package/dist/framework/components/HuaUxPage.d.ts.map +1 -0
  43. package/dist/framework/components/HuaUxPage.js +105 -0
  44. package/dist/framework/components/Providers.d.ts +17 -0
  45. package/dist/framework/components/Providers.d.ts.map +1 -0
  46. package/dist/framework/components/Providers.js +72 -0
  47. package/dist/framework/components/WelcomePage.d.ts +44 -0
  48. package/dist/framework/components/WelcomePage.d.ts.map +1 -0
  49. package/dist/framework/components/WelcomePage.js +80 -0
  50. package/dist/framework/config/index.d.ts +182 -0
  51. package/dist/framework/config/index.d.ts.map +1 -0
  52. package/dist/framework/config/index.js +329 -0
  53. package/dist/framework/config/merge.d.ts +26 -0
  54. package/dist/framework/config/merge.d.ts.map +1 -0
  55. package/dist/framework/config/merge.js +160 -0
  56. package/dist/framework/config/schema.d.ts +25 -0
  57. package/dist/framework/config/schema.d.ts.map +1 -0
  58. package/dist/framework/config/schema.js +122 -0
  59. package/dist/framework/hooks/useMotion.d.ts +45 -0
  60. package/dist/framework/hooks/useMotion.d.ts.map +1 -0
  61. package/dist/framework/hooks/useMotion.js +40 -0
  62. package/dist/framework/index.d.ts +37 -0
  63. package/dist/framework/index.d.ts.map +1 -0
  64. package/dist/framework/index.js +42 -0
  65. package/dist/framework/license/errors.d.ts +15 -0
  66. package/dist/framework/license/errors.d.ts.map +1 -0
  67. package/dist/framework/license/errors.js +52 -0
  68. package/dist/framework/license/index.d.ts +70 -0
  69. package/dist/framework/license/index.d.ts.map +1 -0
  70. package/dist/framework/license/index.js +124 -0
  71. package/dist/framework/license/loader.d.ts +26 -0
  72. package/dist/framework/license/loader.d.ts.map +1 -0
  73. package/dist/framework/license/loader.js +137 -0
  74. package/dist/framework/license/types.d.ts +67 -0
  75. package/dist/framework/license/types.d.ts.map +1 -0
  76. package/dist/framework/license/types.js +18 -0
  77. package/dist/framework/loading/components/SkeletonGroup.d.ts +44 -0
  78. package/dist/framework/loading/components/SkeletonGroup.d.ts.map +1 -0
  79. package/dist/framework/loading/components/SkeletonGroup.js +34 -0
  80. package/dist/framework/loading/components/SuspenseWrapper.d.ts +58 -0
  81. package/dist/framework/loading/components/SuspenseWrapper.d.ts.map +1 -0
  82. package/dist/framework/loading/components/SuspenseWrapper.js +40 -0
  83. package/dist/framework/loading/hoc/withSuspense.d.ts +46 -0
  84. package/dist/framework/loading/hoc/withSuspense.d.ts.map +1 -0
  85. package/dist/framework/loading/hoc/withSuspense.js +54 -0
  86. package/dist/framework/loading/hooks/useDelayedLoading.d.ts +56 -0
  87. package/dist/framework/loading/hooks/useDelayedLoading.d.ts.map +1 -0
  88. package/dist/framework/loading/hooks/useDelayedLoading.js +97 -0
  89. package/dist/framework/loading/hooks/useLoadingState.d.ts +69 -0
  90. package/dist/framework/loading/hooks/useLoadingState.d.ts.map +1 -0
  91. package/dist/framework/loading/hooks/useLoadingState.js +59 -0
  92. package/dist/framework/loading/index.d.ts +16 -0
  93. package/dist/framework/loading/index.d.ts.map +1 -0
  94. package/dist/framework/loading/index.js +13 -0
  95. package/dist/framework/middleware/i18n.d.ts +90 -0
  96. package/dist/framework/middleware/i18n.d.ts.map +1 -0
  97. package/dist/framework/middleware/i18n.js +99 -0
  98. package/dist/framework/plugins/index.d.ts +8 -0
  99. package/dist/framework/plugins/index.d.ts.map +1 -0
  100. package/dist/framework/plugins/index.js +6 -0
  101. package/dist/framework/plugins/registry.d.ts +95 -0
  102. package/dist/framework/plugins/registry.d.ts.map +1 -0
  103. package/dist/framework/plugins/registry.js +160 -0
  104. package/dist/framework/plugins/types.d.ts +97 -0
  105. package/dist/framework/plugins/types.d.ts.map +1 -0
  106. package/dist/framework/plugins/types.js +6 -0
  107. package/dist/framework/seo/geo/examples.d.ts +87 -0
  108. package/dist/framework/seo/geo/examples.d.ts.map +1 -0
  109. package/dist/framework/seo/geo/examples.js +295 -0
  110. package/dist/framework/seo/geo/generateGEOMetadata.d.ts +107 -0
  111. package/dist/framework/seo/geo/generateGEOMetadata.d.ts.map +1 -0
  112. package/dist/framework/seo/geo/generateGEOMetadata.js +404 -0
  113. package/dist/framework/seo/geo/index.d.ts +19 -0
  114. package/dist/framework/seo/geo/index.d.ts.map +1 -0
  115. package/dist/framework/seo/geo/index.js +21 -0
  116. package/dist/framework/seo/geo/presets.d.ts +52 -0
  117. package/dist/framework/seo/geo/presets.d.ts.map +1 -0
  118. package/dist/framework/seo/geo/presets.js +47 -0
  119. package/dist/framework/seo/geo/structuredData.d.ts +187 -0
  120. package/dist/framework/seo/geo/structuredData.d.ts.map +1 -0
  121. package/dist/framework/seo/geo/structuredData.js +354 -0
  122. package/dist/framework/seo/geo/test-utils.d.ts +78 -0
  123. package/dist/framework/seo/geo/test-utils.d.ts.map +1 -0
  124. package/dist/framework/seo/geo/test-utils.js +139 -0
  125. package/dist/framework/seo/geo/types.d.ts +225 -0
  126. package/dist/framework/seo/geo/types.d.ts.map +1 -0
  127. package/dist/framework/seo/geo/types.js +51 -0
  128. package/dist/framework/types/index.d.ts +577 -0
  129. package/dist/framework/types/index.d.ts.map +1 -0
  130. package/dist/framework/types/index.js +6 -0
  131. package/dist/framework/utils/data-fetching.d.ts +45 -0
  132. package/dist/framework/utils/data-fetching.d.ts.map +1 -0
  133. package/dist/framework/utils/data-fetching.js +74 -0
  134. package/dist/framework/utils/file-structure.d.ts +29 -0
  135. package/dist/framework/utils/file-structure.d.ts.map +1 -0
  136. package/dist/framework/utils/file-structure.js +72 -0
  137. package/dist/framework/utils/metadata.d.ts +109 -0
  138. package/dist/framework/utils/metadata.d.ts.map +1 -0
  139. package/dist/framework/utils/metadata.js +105 -0
  140. package/dist/index.d.ts +15 -0
  141. package/dist/index.d.ts.map +1 -0
  142. package/dist/index.js +21 -0
  143. package/dist/presets/index.d.ts +8 -0
  144. package/dist/presets/index.d.ts.map +1 -0
  145. package/dist/presets/index.js +7 -0
  146. package/dist/presets/marketing.d.ts +41 -0
  147. package/dist/presets/marketing.d.ts.map +1 -0
  148. package/dist/presets/marketing.js +81 -0
  149. package/dist/presets/product.d.ts +41 -0
  150. package/dist/presets/product.d.ts.map +1 -0
  151. package/dist/presets/product.js +74 -0
  152. package/package.json +91 -0
  153. package/src/framework/README.md +329 -0
  154. package/src/framework/__tests__/branding/css-vars.test.ts +147 -0
  155. package/src/framework/__tests__/components/ErrorBoundary.test.tsx +146 -0
  156. package/src/framework/__tests__/config/defineConfig.test.ts +138 -0
  157. package/src/framework/__tests__/hooks/useMotion.test.ts +105 -0
  158. package/src/framework/__tests__/seo/geo/generateGEOMetadata.test.ts +207 -0
  159. package/src/framework/__tests__/seo/geo/structuredData.test.ts +262 -0
  160. package/src/framework/a11y/components/LiveRegion.tsx +89 -0
  161. package/src/framework/a11y/components/SkipToContent.tsx +103 -0
  162. package/src/framework/a11y/hooks/useFocusManagement.ts +125 -0
  163. package/src/framework/a11y/hooks/useFocusTrap.ts +239 -0
  164. package/src/framework/a11y/hooks/useLiveRegion.ts +95 -0
  165. package/src/framework/a11y/index.ts +17 -0
  166. package/src/framework/branding/context.tsx +135 -0
  167. package/src/framework/branding/css-vars.ts +110 -0
  168. package/src/framework/branding/tailwind-config.ts +90 -0
  169. package/src/framework/components/BrandedButton.tsx +94 -0
  170. package/src/framework/components/BrandedCard.tsx +87 -0
  171. package/src/framework/components/ErrorBoundary.tsx +215 -0
  172. package/src/framework/components/HuaUxLayout.tsx +36 -0
  173. package/src/framework/components/HuaUxPage.tsx +138 -0
  174. package/src/framework/components/Providers.tsx +98 -0
  175. package/src/framework/components/WelcomePage.tsx +207 -0
  176. package/src/framework/config/index.ts +349 -0
  177. package/src/framework/config/merge.ts +190 -0
  178. package/src/framework/config/schema.ts +140 -0
  179. package/src/framework/hooks/useMotion.ts +57 -0
  180. package/src/framework/index.ts +122 -0
  181. package/src/framework/license/errors.ts +63 -0
  182. package/src/framework/license/index.ts +137 -0
  183. package/src/framework/license/loader.ts +158 -0
  184. package/src/framework/license/types.ts +95 -0
  185. package/src/framework/loading/components/SkeletonGroup.tsx +70 -0
  186. package/src/framework/loading/components/SuspenseWrapper.tsx +88 -0
  187. package/src/framework/loading/hoc/withSuspense.tsx +96 -0
  188. package/src/framework/loading/hooks/useDelayedLoading.ts +127 -0
  189. package/src/framework/loading/hooks/useLoadingState.ts +103 -0
  190. package/src/framework/loading/index.ts +19 -0
  191. package/src/framework/middleware/i18n.ts +161 -0
  192. package/src/framework/middleware/index.ts +7 -0
  193. package/src/framework/plugins/index.ts +13 -0
  194. package/src/framework/plugins/registry.ts +186 -0
  195. package/src/framework/plugins/types.ts +106 -0
  196. package/src/framework/seo/geo/examples.tsx +415 -0
  197. package/src/framework/seo/geo/generateGEOMetadata.ts +441 -0
  198. package/src/framework/seo/geo/index.ts +61 -0
  199. package/src/framework/seo/geo/presets.ts +58 -0
  200. package/src/framework/seo/geo/structuredData.ts +422 -0
  201. package/src/framework/seo/geo/test-utils.ts +179 -0
  202. package/src/framework/seo/geo/types.ts +315 -0
  203. package/src/framework/types/index.ts +623 -0
  204. package/src/framework/utils/data-fetching.ts +95 -0
  205. package/src/framework/utils/file-structure.ts +88 -0
  206. package/src/framework/utils/metadata.ts +152 -0
  207. package/src/index.ts +31 -0
  208. package/src/presets/index.ts +8 -0
  209. package/src/presets/marketing.ts +88 -0
  210. package/src/presets/product.ts +81 -0
@@ -0,0 +1,207 @@
1
+ /**
2
+ * @hua-labs/hua-ux/framework - WelcomePage
3
+ *
4
+ * Default welcome page component for new projects
5
+ * Similar to Next.js default welcome page
6
+ */
7
+
8
+ 'use client';
9
+
10
+ import React from 'react';
11
+ import { HuaUxPage } from './HuaUxPage';
12
+ import { Button, Card, Badge } from '@hua-labs/ui';
13
+ import { useTranslation } from '@hua-labs/i18n-core';
14
+ import type { HuaUxPageProps } from '../types';
15
+
16
+ export interface WelcomePageProps extends Omit<HuaUxPageProps, 'children'> {
17
+ /**
18
+ * Project name to display
19
+ */
20
+ projectName?: string;
21
+
22
+ /**
23
+ * Show framework features
24
+ */
25
+ showFeatures?: boolean;
26
+
27
+ /**
28
+ * Show quick links
29
+ */
30
+ showQuickLinks?: boolean;
31
+
32
+ /**
33
+ * Custom content to display
34
+ */
35
+ children?: React.ReactNode;
36
+ }
37
+
38
+ /**
39
+ * WelcomePage Component
40
+ *
41
+ * Default welcome page for new hua-ux projects.
42
+ * Displays project information, framework features, and quick links.
43
+ *
44
+ * @example
45
+ * ```tsx
46
+ * // app/page.tsx
47
+ * import { WelcomePage } from '@hua-labs/hua-ux/framework';
48
+ *
49
+ * export default function HomePage() {
50
+ * return <WelcomePage projectName="My App" />;
51
+ * }
52
+ * ```
53
+ */
54
+ export function WelcomePage({
55
+ projectName = 'My App',
56
+ showFeatures = true,
57
+ showQuickLinks = true,
58
+ children,
59
+ ...pageProps
60
+ }: WelcomePageProps) {
61
+ const { t, currentLanguage } = useTranslation();
62
+
63
+ const features = [
64
+ {
65
+ title: t('features.ui.title', 'UI Components'),
66
+ description: t('features.ui.description', 'Pre-built, accessible components'),
67
+ icon: '🎨',
68
+ },
69
+ {
70
+ title: t('features.i18n.title', 'i18n Support'),
71
+ description: t('features.i18n.description', 'Multi-language support out of the box'),
72
+ icon: '🌐',
73
+ },
74
+ {
75
+ title: t('features.motion.title', 'Motion'),
76
+ description: t('features.motion.description', 'Smooth animations and transitions'),
77
+ icon: '✨',
78
+ },
79
+ {
80
+ title: t('features.ai.title', 'AI-First'),
81
+ description: t('features.ai.description', 'Built for vibe coding with AI'),
82
+ icon: '🤖',
83
+ },
84
+ ];
85
+
86
+ const quickLinks = [
87
+ {
88
+ title: t('links.docs.title', 'Documentation'),
89
+ description: t('links.docs.description', 'Learn more about hua-ux'),
90
+ href: 'https://github.com/HUA-Labs/HUA-Labs-public',
91
+ external: true,
92
+ },
93
+ {
94
+ title: t('links.examples.title', 'Examples'),
95
+ description: t('links.examples.description', 'See examples and patterns'),
96
+ href: '/examples',
97
+ external: false,
98
+ },
99
+ {
100
+ title: t('links.github.title', 'GitHub'),
101
+ description: t('links.github.description', 'View source code'),
102
+ href: 'https://github.com/HUA-Labs/HUA-Labs-public',
103
+ external: true,
104
+ },
105
+ ];
106
+
107
+ return (
108
+ <HuaUxPage
109
+ title={t('welcome.title', 'Welcome')}
110
+ description={t('welcome.description', `Get started by editing app/page.tsx`)}
111
+ vibe="clean"
112
+ {...pageProps}
113
+ >
114
+ <div className="min-h-screen flex flex-col items-center justify-center p-8 bg-gradient-to-br from-gray-50 to-gray-100 dark:from-gray-900 dark:to-gray-800">
115
+ <div className="max-w-4xl w-full space-y-8">
116
+ {/* Header */}
117
+ <div className="text-center space-y-4">
118
+ <div className="flex items-center justify-center gap-3">
119
+ <h1 className="text-5xl font-bold bg-gradient-to-r from-blue-600 to-purple-600 bg-clip-text text-transparent">
120
+ {projectName}
121
+ </h1>
122
+ <Badge variant="secondary" className="text-sm">
123
+ {t('badge.alpha', 'Alpha')}
124
+ </Badge>
125
+ </div>
126
+ <p className="text-xl text-gray-600 dark:text-gray-400">
127
+ {t('welcome.subtitle', 'Built with @hua-labs/hua-ux')}
128
+ </p>
129
+ <p className="text-gray-500 dark:text-gray-500">
130
+ {t('welcome.description', 'Get started by editing app/page.tsx')}
131
+ </p>
132
+ </div>
133
+
134
+ {/* Custom Content */}
135
+ {children && (
136
+ <div className="flex justify-center">
137
+ {children}
138
+ </div>
139
+ )}
140
+
141
+ {/* Features Grid */}
142
+ {showFeatures && (
143
+ <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
144
+ {features.map((feature, index) => (
145
+ <Card
146
+ key={index}
147
+ className="p-6 hover:shadow-lg transition-shadow cursor-pointer"
148
+ >
149
+ <div className="space-y-2">
150
+ <div className="text-3xl mb-2">{feature.icon}</div>
151
+ <h3 className="font-semibold text-lg">{feature.title}</h3>
152
+ <p className="text-sm text-gray-600 dark:text-gray-400">
153
+ {feature.description}
154
+ </p>
155
+ </div>
156
+ </Card>
157
+ ))}
158
+ </div>
159
+ )}
160
+
161
+ {/* Quick Links */}
162
+ {showQuickLinks && (
163
+ <div className="grid grid-cols-1 md:grid-cols-3 gap-4">
164
+ {quickLinks.map((link, index) => (
165
+ <Card
166
+ key={index}
167
+ className="p-6 hover:shadow-lg transition-shadow"
168
+ >
169
+ <div className="space-y-2">
170
+ <h3 className="font-semibold text-lg">{link.title}</h3>
171
+ <p className="text-sm text-gray-600 dark:text-gray-400">
172
+ {link.description}
173
+ </p>
174
+ <Button
175
+ variant="outline"
176
+ size="sm"
177
+ className="mt-4"
178
+ onClick={() => {
179
+ if (link.external) {
180
+ window.open(link.href, '_blank', 'noopener,noreferrer');
181
+ } else {
182
+ window.location.href = link.href;
183
+ }
184
+ }}
185
+ >
186
+ {t('links.visit', 'Visit')} →
187
+ </Button>
188
+ </div>
189
+ </Card>
190
+ ))}
191
+ </div>
192
+ )}
193
+
194
+ {/* Footer Info */}
195
+ <div className="text-center text-sm text-gray-500 dark:text-gray-400 space-y-2">
196
+ <p>
197
+ {t('footer.language', 'Language')}: <strong>{currentLanguage}</strong>
198
+ </p>
199
+ <p>
200
+ {t('footer.framework', 'Framework')}: <strong>@hua-labs/hua-ux</strong>
201
+ </p>
202
+ </div>
203
+ </div>
204
+ </div>
205
+ </HuaUxPage>
206
+ );
207
+ }
@@ -0,0 +1,349 @@
1
+ /**
2
+ * @hua-labs/hua-ux/framework - Config System
3
+ *
4
+ * Configuration loading and management
5
+ */
6
+
7
+ import type { HuaUxConfig, Preset } from '../types';
8
+ import { defaultConfig, validateConfig } from './schema';
9
+ import { mergePresetWithConfig, createConfigFromUserConfig } from './merge';
10
+ import { initLicense } from '../license';
11
+ import { pluginRegistry } from '../plugins';
12
+
13
+ /**
14
+ * Global config cache
15
+ */
16
+ let cachedConfig: HuaUxConfig | null = null;
17
+
18
+ /**
19
+ * 프레임워크 설정 정의 / Define framework configuration
20
+ *
21
+ * IntelliSense를 완벽히 지원하는 설정 함수입니다.
22
+ * Provides full IntelliSense support for configuration options.
23
+ *
24
+ * 모든 옵션은 선택사항이며 기본값 또는 Preset과 병합됩니다.
25
+ * All options are optional and will be merged with defaults or Preset.
26
+ *
27
+ * **Zero-Config**: 설정 파일이 없어도 기본값으로 동작합니다.
28
+ * **Zero-Config**: Works with defaults even without a config file.
29
+ *
30
+ * **Preset 우선**: `preset: 'product'`만 지정해도 대부분의 설정이 자동 적용됩니다.
31
+ * **Preset First**: Just specify `preset: 'product'` and most settings are auto-applied.
32
+ *
33
+ * **바이브 코딩 친화적**: AI가 이해하기 쉬운 한글 주석과 명사 중심 설정
34
+ * **Vibe Coding Friendly**: Korean comments and noun-centered settings for AI understanding
35
+ *
36
+ * @param config - 설정 객체 / Configuration object
37
+ * @param config.preset - 사용할 프리셋 / Preset to use
38
+ * - **바이브 모드 (간단) / Vibe mode (simple)**: `'product' | 'marketing'`
39
+ * - 'product': 제품 페이지용 (전문적, 효율적, 기본값) / Product pages (professional, efficient, default)
40
+ * - 'marketing': 마케팅 페이지용 (화려함, 눈에 띄는) / Marketing pages (dramatic, eye-catching)
41
+ * - **개발자 모드 (세부 설정) / Developer mode (detailed)**: `{ type: 'product' | 'marketing', motion?: {...}, spacing?: {...} }`
42
+ * - 세부 설정을 포함한 Preset 객체 / Preset object with detailed settings
43
+ * - Preset을 선택하면 motion, spacing, i18n 등이 자동 설정됩니다.
44
+ * - Selecting a preset automatically configures motion, spacing, i18n, etc.
45
+ * @param config.i18n - 다국어 설정 / Internationalization settings
46
+ * @param config.i18n.defaultLanguage - 기본 언어 코드 (예: 'ko', 'en') / Default language code (e.g., 'ko', 'en')
47
+ * @param config.i18n.supportedLanguages - 지원하는 언어 코드 배열 / Array of supported language codes
48
+ * @param config.i18n.namespaces - 로드할 번역 네임스페이스 / Translation namespaces to load
49
+ * @param config.i18n.translationLoader - 번역 로딩 전략 ('static' | 'api') / Translation loading strategy
50
+ * @param config.i18n.translationApiPath - 번역 API 경로 ('api' 로더 사용 시) / API path for translations
51
+ * @param config.motion - 모션/애니메이션 설정 / Motion/animation settings
52
+ * @param config.motion.style - 모션 스타일 (바이브 코더용) / Motion style (for vibe coders)
53
+ * - 'smooth': 부드러운 전환 / Smooth transitions
54
+ * - 'dramatic': 드라마틱한 전환 / Dramatic transitions
55
+ * - 'minimal': 최소한의 전환 / Minimal transitions
56
+ * @param config.motion.defaultPreset - 기본 모션 프리셋 (개발자용) / Default motion preset (for developers)
57
+ * - 'product': 빠른 전환, 최소 딜레이 / Fast transitions, minimal delay
58
+ * - 'marketing': 느린 전환, 긴 딜레이 / Slow transitions, long delay
59
+ * @param config.motion.enableAnimations - 전역 애니메이션 활성화 여부 / Enable animations globally
60
+ * @param config.motion.duration - 애니메이션 지속 시간 (밀리초, 개발자용) / Animation duration in milliseconds (for developers)
61
+ * @param config.motion.easing - 애니메이션 이징 함수 (개발자용) / Animation easing function (for developers)
62
+ * @param config.state - 상태 관리 설정 / State management settings
63
+ * @param config.state.persist - localStorage 영속성 활성화 여부 / Enable localStorage persistence
64
+ * @param config.state.ssr - SSR 지원 활성화 여부 / Enable SSR support
65
+ * @param config.branding - 브랜딩 설정 (화이트 라벨링) / Branding settings (white labeling)
66
+ * @param config.branding.name - 회사/서비스 이름 / Company/service name
67
+ * @param config.branding.logo - 로고 경로 / Logo path
68
+ * @param config.branding.colors - 색상 팔레트 (primary, secondary, accent 등) / Color palette
69
+ * @param config.branding.typography - 타이포그래피 설정 (fontFamily, fontSize 등) / Typography settings
70
+ *
71
+ * @returns 검증된 설정 객체 / Validated configuration object
72
+ *
73
+ * @example
74
+ * ```ts
75
+ * // 최소 설정 (Preset만) - 바이브 코더용
76
+ * // hua-ux.config.ts
77
+ * import { defineConfig } from '@hua-labs/hua-ux/framework';
78
+ *
79
+ * export default defineConfig({
80
+ * preset: 'product', // 끝! 나머지는 자동 설정
81
+ * });
82
+ * ```
83
+ *
84
+ * @example
85
+ * ```ts
86
+ * // Preset + 일부 커스터마이징
87
+ * export default defineConfig({
88
+ * preset: 'product',
89
+ * i18n: {
90
+ * supportedLanguages: ['ko', 'en', 'ja'], // 언어만 추가
91
+ * },
92
+ * });
93
+ * ```
94
+ *
95
+ * @example
96
+ * ```ts
97
+ * // 개발자 모드: Preset 객체 형태 (세부 설정)
98
+ * export default defineConfig({
99
+ * preset: {
100
+ * type: 'product',
101
+ * motion: { duration: 300 },
102
+ * spacing: { default: 'md' },
103
+ * },
104
+ * });
105
+ * ```
106
+ *
107
+ * @example
108
+ * ```ts
109
+ * // 바이브 코더용: motion.style 사용
110
+ * export default defineConfig({
111
+ * preset: 'product',
112
+ * motion: {
113
+ * style: 'smooth', // 명사 중심, 이해하기 쉬움
114
+ * },
115
+ * });
116
+ * ```
117
+ *
118
+ * @example
119
+ * ```ts
120
+ * // 완전 커스터마이징 (Preset 없이) - 전통 개발자용
121
+ * export default defineConfig({
122
+ * i18n: {
123
+ * defaultLanguage: 'ko',
124
+ * supportedLanguages: ['ko', 'en'],
125
+ * namespaces: ['common'],
126
+ * translationLoader: 'api',
127
+ * translationApiPath: '/api/translations',
128
+ * },
129
+ * motion: {
130
+ * defaultPreset: 'product',
131
+ * enableAnimations: true,
132
+ * },
133
+ * state: {
134
+ * persist: true,
135
+ * ssr: true,
136
+ * },
137
+ * });
138
+ * ```
139
+ */
140
+ export function defineConfig(config: Partial<HuaUxConfig>): HuaUxConfig {
141
+ // 라이선스 초기화
142
+ if (config.license) {
143
+ initLicense(config.license);
144
+ }
145
+
146
+ // 플러그인 등록 및 초기화
147
+ if (config.plugins && config.plugins.length > 0) {
148
+ config.plugins.forEach(plugin => {
149
+ pluginRegistry.register(plugin);
150
+ });
151
+ }
152
+
153
+ // Preset이 지정된 경우 Preset과 병합
154
+ if (config.preset) {
155
+ const { preset, ...userConfig } = config;
156
+ const merged = mergePresetWithConfig(preset, userConfig);
157
+ const validated = validateConfig(merged);
158
+
159
+ // 플러그인 초기화 (설정이 완료된 후)
160
+ if (config.plugins && config.plugins.length > 0) {
161
+ pluginRegistry.initializeAll(validated).catch((error: Error) => {
162
+ console.error('[hua-ux] Plugin initialization error:', error);
163
+ });
164
+ }
165
+
166
+ return validated;
167
+ }
168
+
169
+ // Preset이 없는 경우 사용자 설정만 사용
170
+ const merged = createConfigFromUserConfig(config);
171
+ const validated = validateConfig(merged);
172
+
173
+ // 플러그인 초기화 (설정이 완료된 후)
174
+ if (config.plugins && config.plugins.length > 0) {
175
+ pluginRegistry.initializeAll(validated).catch((error: Error) => {
176
+ console.error('[hua-ux] Plugin initialization error:', error);
177
+ });
178
+ }
179
+
180
+ return validated;
181
+ }
182
+
183
+ /**
184
+ * Load configuration from file
185
+ *
186
+ * 동적으로 설정 파일을 로드합니다.
187
+ *
188
+ * **로드 순서**:
189
+ * 1. `hua-ux.config.ts` 시도 (TypeScript)
190
+ * 2. `hua-ux.config.js` 시도 (JavaScript)
191
+ * 3. 없으면 기본값 (product preset)
192
+ *
193
+ * **Zero-Config**: 설정 파일이 없어도 기본값으로 동작합니다.
194
+ *
195
+ * **주의사항**:
196
+ * - 이 함수는 Node.js 환경(빌드 타임)에서만 동작합니다.
197
+ * - 런타임에서는 캐시된 설정을 사용합니다.
198
+ * - **권장**: 설정 파일을 명시적으로 import하여 타입 안전성을 보장하세요.
199
+ * ```ts
200
+ * // hua-ux.config.ts
201
+ * import { defineConfig } from '@hua-labs/hua-ux/framework';
202
+ * export default defineConfig({ preset: 'product' });
203
+ *
204
+ * // app/layout.tsx 또는 다른 서버 컴포넌트에서
205
+ * import config from '../hua-ux.config';
206
+ * import { setConfig } from '@hua-labs/hua-ux/framework';
207
+ * setConfig(config);
208
+ * ```
209
+ *
210
+ * **Fallback 용도**: 이 함수는 설정 파일이 명시적으로 import되지 않은 경우에만 사용됩니다.
211
+ * 프로덕션 환경에서는 설정 파일을 명시적으로 import하는 것을 권장합니다.
212
+ */
213
+ export function loadConfig(): HuaUxConfig {
214
+ if (cachedConfig) {
215
+ return cachedConfig;
216
+ }
217
+
218
+ // Node.js 환경에서만 동적 로드 시도 (서버 사이드에서만)
219
+ // 클라이언트에서는 기본 설정 반환
220
+ if (typeof window !== 'undefined') {
221
+ // 브라우저 환경: 기본 설정 반환
222
+ cachedConfig = mergePresetWithConfig('product', {});
223
+ return cachedConfig;
224
+ }
225
+
226
+ // Node.js 환경에서만 동적 로드 시도
227
+ if (typeof process !== 'undefined' && process.cwd && typeof require !== 'undefined') {
228
+ try {
229
+ const fs = require('fs');
230
+ const path = require('path');
231
+ const projectRoot = process.cwd();
232
+
233
+ // 설정 파일 경로 후보
234
+ const configPaths = [
235
+ path.join(projectRoot, 'hua-ux.config.ts'),
236
+ path.join(projectRoot, 'hua-ux.config.js'),
237
+ path.join(projectRoot, 'hua-ux.config.mjs'),
238
+ ];
239
+
240
+ // 첫 번째로 발견된 설정 파일 사용
241
+ //
242
+ // ⚠️ 주의: 이 코드는 Fallback 용도입니다.
243
+ // 권장 방법: 설정 파일을 명시적으로 import하여 타입 안전성을 보장하세요.
244
+ //
245
+ // Next.js 빌드 시 동적 require는 경고를 발생시킬 수 있지만,
246
+ // 런타임에서는 정상 작동합니다. 설정 파일은 보통 빌드 타임에 처리되므로
247
+ // 이 코드는 주로 개발 환경에서 사용됩니다.
248
+ //
249
+ // 실제 프로덕션에서는 설정 파일을 명시적으로 import하는 것을 권장합니다:
250
+ // ```ts
251
+ // import config from './hua-ux.config';
252
+ // import { setConfig } from '@hua-labs/hua-ux/framework';
253
+ // setConfig(config);
254
+ // ```
255
+ for (const configPath of configPaths) {
256
+ if (fs.existsSync(configPath)) {
257
+ try {
258
+ // 동적 require는 Next.js 빌드 시 경고를 발생시킬 수 있지만
259
+ // 런타임에서는 정상 작동합니다.
260
+ // 실제 프로덕션에서는 설정 파일이 이미 import되어 있으므로
261
+ // 이 경로는 거의 사용되지 않습니다.
262
+ if (typeof require !== 'undefined' && typeof require.resolve === 'function') {
263
+ try {
264
+ // webpackIgnore 주석으로 Next.js 빌드 시 무시하도록 시도
265
+ // @ts-ignore - 동적 require는 타입 체크를 통과하지 못함
266
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
267
+ // ⚠️ Fallback 용도: 명시적 import를 권장합니다.
268
+ const configModule = require(/* webpackIgnore: true */ configPath);
269
+ const userConfig = configModule.default || configModule;
270
+
271
+ // Preset 병합 처리
272
+ if (userConfig && typeof userConfig === 'object') {
273
+ if (userConfig.preset) {
274
+ const { preset, ...rest } = userConfig;
275
+ cachedConfig = mergePresetWithConfig(preset, rest);
276
+ } else {
277
+ cachedConfig = createConfigFromUserConfig(userConfig);
278
+ }
279
+
280
+ cachedConfig = validateConfig(cachedConfig);
281
+ return cachedConfig;
282
+ }
283
+ } catch (requireError) {
284
+ // require 실패 (TypeScript 파일 등)
285
+ // 기본값 사용
286
+ break;
287
+ }
288
+ }
289
+ } catch (fileError) {
290
+ // 파일 읽기 실패
291
+ continue;
292
+ }
293
+ }
294
+ }
295
+ } catch (error) {
296
+ // fs, path 등이 없는 환경 (브라우저, Edge Runtime 등)
297
+ // 기본값 사용
298
+ }
299
+ }
300
+
301
+ // 기본값 (product preset)
302
+ // 설정 파일이 없거나 로드 실패 시
303
+ cachedConfig = mergePresetWithConfig('product', {});
304
+ return cachedConfig;
305
+ }
306
+
307
+ /**
308
+ * Get current configuration
309
+ *
310
+ * 캐시된 설정을 반환하거나, 없으면 로드합니다.
311
+ *
312
+ * **클라이언트 안전**: 클라이언트에서는 항상 기본값을 반환합니다.
313
+ * **Client Safe**: Always returns default config on client side.
314
+ */
315
+ export function getConfig(): HuaUxConfig {
316
+ // 캐시된 설정이 있으면 반환
317
+ if (cachedConfig) {
318
+ return cachedConfig;
319
+ }
320
+
321
+ // 클라이언트 환경에서는 loadConfig를 호출하지 않고 기본값 반환
322
+ // (loadConfig는 서버 전용이며 fs 모듈을 사용함)
323
+ // 단, setConfig로 설정된 경우는 캐시를 우선 사용
324
+ if (typeof window !== 'undefined') {
325
+ cachedConfig = mergePresetWithConfig('product', {});
326
+ return cachedConfig;
327
+ }
328
+
329
+ // 서버 환경에서만 loadConfig 호출
330
+ return loadConfig();
331
+ }
332
+
333
+ /**
334
+ * Set configuration (for testing or manual override)
335
+ *
336
+ * 테스트나 수동 오버라이드를 위한 설정 설정 함수
337
+ */
338
+ export function setConfig(config: HuaUxConfig): void {
339
+ cachedConfig = validateConfig(config);
340
+ }
341
+
342
+ /**
343
+ * Reset configuration cache
344
+ *
345
+ * 설정 캐시를 초기화합니다. (주로 테스트용)
346
+ */
347
+ export function resetConfig(): void {
348
+ cachedConfig = null;
349
+ }