@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,73 @@
1
+ /**
2
+ * @hua-labs/hua-ux/framework - BrandedCard
3
+ *
4
+ * Card 컴포넌트에 branding을 자동으로 적용하는 wrapper
5
+ * Wrapper that automatically applies branding to Card component
6
+ *
7
+ * CSS 변수를 사용하여 Tailwind의 최적화를 활용합니다.
8
+ * Uses CSS variables to leverage Tailwind's optimization.
9
+ */
10
+ 'use client';
11
+ import { jsx as _jsx } from "react/jsx-runtime";
12
+ import React from 'react';
13
+ import { Card, merge } from '@hua-labs/ui';
14
+ import { useBranding } from '../branding/context';
15
+ /**
16
+ * BrandedCard Component
17
+ *
18
+ * Card 컴포넌트에 branding 설정을 자동으로 적용합니다.
19
+ * Automatically applies branding configuration to Card component.
20
+ *
21
+ * **자동 적용되는 branding**:
22
+ * - Accent 색상: `variant="outline"`일 때 `border-[var(--color-accent)]` 사용
23
+ * - Primary 색상: `variant="default"`일 때 `bg-[var(--color-primary)]/5` 사용
24
+ *
25
+ * **Auto-applied branding**:
26
+ * - Accent color: Uses `border-[var(--color-accent)]` when `variant="outline"`
27
+ * - Primary color: Uses `bg-[var(--color-primary)]/5` when `variant="default"`
28
+ *
29
+ * **CSS 변수 방식의 장점**:
30
+ * - Tailwind의 JIT 컴파일러 최적화 활용
31
+ * - 인라인 스타일 없이 깔끔한 코드
32
+ * - 런타임에 동적으로 색상 변경 가능
33
+ *
34
+ * **Advantages of CSS variables**:
35
+ * - Leverages Tailwind's JIT compiler optimization
36
+ * - Clean code without inline styles
37
+ * - Dynamic color changes at runtime
38
+ *
39
+ * @example
40
+ * ```tsx
41
+ * // branding 설정이 있으면 자동으로 색상 적용
42
+ * // Automatically applies colors if branding is configured
43
+ * <BrandedCard variant="outline">
44
+ * <CardContent>내용</CardContent>
45
+ * </BrandedCard>
46
+ *
47
+ * // branding이 없으면 기본 Card와 동일하게 동작
48
+ * // Works same as default Card if branding is not configured
49
+ * <BrandedCard variant="elevated">
50
+ * <CardContent>내용</CardContent>
51
+ * </BrandedCard>
52
+ * ```
53
+ */
54
+ export const BrandedCard = React.forwardRef(({ variant = 'default', className, ...props }, ref) => {
55
+ const branding = useBranding();
56
+ // Branding 색상이 있으면 Tailwind arbitrary values 사용
57
+ // Use Tailwind arbitrary values if branding colors exist
58
+ let brandingClasses = '';
59
+ if (branding?.colors) {
60
+ if (variant === 'outline' && branding.colors.accent) {
61
+ // Accent 색상을 테두리로 사용
62
+ // Use accent color as border
63
+ brandingClasses = 'border-[var(--color-accent)]';
64
+ }
65
+ else if (variant === 'default' && branding.colors.primary) {
66
+ // Primary 색상의 약간의 tint를 배경에 적용
67
+ // Apply slight tint of primary color to background
68
+ brandingClasses = 'bg-[var(--color-primary)]/5';
69
+ }
70
+ }
71
+ return (_jsx(Card, { ref: ref, variant: variant, className: merge(brandingClasses, className), ...props }));
72
+ });
73
+ BrandedCard.displayName = 'BrandedCard';
@@ -0,0 +1,92 @@
1
+ /**
2
+ * @hua-labs/hua-ux/framework - ErrorBoundary
3
+ *
4
+ * React Error Boundary component for catching and handling errors
5
+ */
6
+ import { Component, ReactNode, ErrorInfo } from 'react';
7
+ /**
8
+ * Global error reporter interface
9
+ *
10
+ * 프로덕션 환경에서 에러 리포팅 서비스(Sentry, LogRocket 등)와 통합하기 위한 인터페이스
11
+ * Interface for integrating with error reporting services (Sentry, LogRocket, etc.) in production
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * // Sentry 통합 예시
16
+ * window.__ERROR_REPORTER__ = (error, errorInfo) => {
17
+ * Sentry.captureException(error, {
18
+ * contexts: { react: errorInfo },
19
+ * });
20
+ * };
21
+ * ```
22
+ */
23
+ declare global {
24
+ interface Window {
25
+ __ERROR_REPORTER__?: (error: Error, errorInfo: ErrorInfo) => void;
26
+ }
27
+ }
28
+ /**
29
+ * Error Boundary Props
30
+ */
31
+ export interface ErrorBoundaryProps {
32
+ /**
33
+ * Children to render
34
+ */
35
+ children: ReactNode;
36
+ /**
37
+ * Fallback UI to show when error occurs
38
+ * Can be a ReactNode or a function that receives error and reset callback
39
+ */
40
+ fallback?: ReactNode | ((error: Error, reset: () => void) => ReactNode);
41
+ /**
42
+ * Callback when error is caught
43
+ */
44
+ onError?: (error: Error, errorInfo: ErrorInfo) => void;
45
+ /**
46
+ * Custom error filter - return true to catch, false to rethrow
47
+ */
48
+ onReset?: () => void;
49
+ }
50
+ /**
51
+ * Error Boundary State
52
+ */
53
+ interface ErrorBoundaryState {
54
+ hasError: boolean;
55
+ error: Error | null;
56
+ }
57
+ /**
58
+ * Error Boundary Component
59
+ *
60
+ * Catches JavaScript errors anywhere in the child component tree,
61
+ * logs those errors, and displays a fallback UI.
62
+ *
63
+ * @example
64
+ * ```tsx
65
+ * <ErrorBoundary fallback={<div>Something went wrong</div>}>
66
+ * <MyComponent />
67
+ * </ErrorBoundary>
68
+ * ```
69
+ *
70
+ * @example
71
+ * ```tsx
72
+ * <ErrorBoundary
73
+ * fallback={(error, reset) => (
74
+ * <div>
75
+ * <h1>Error: {error.message}</h1>
76
+ * <button onClick={reset}>Try again</button>
77
+ * </div>
78
+ * )}
79
+ * >
80
+ * <MyComponent />
81
+ * </ErrorBoundary>
82
+ * ```
83
+ */
84
+ export declare class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {
85
+ constructor(props: ErrorBoundaryProps);
86
+ static getDerivedStateFromError(error: Error): ErrorBoundaryState;
87
+ componentDidCatch(error: Error, errorInfo: ErrorInfo): void;
88
+ reset: () => void;
89
+ render(): ReactNode;
90
+ }
91
+ export {};
92
+ //# sourceMappingURL=ErrorBoundary.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ErrorBoundary.d.ts","sourceRoot":"","sources":["../../../src/framework/components/ErrorBoundary.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAc,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAE/D;;;;;;;;;;;;;;;GAeG;AACH,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,kBAAkB,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,KAAK,IAAI,CAAC;KACnE;CACF;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC;;OAEG;IACH,QAAQ,EAAE,SAAS,CAAC;IAEpB;;;OAGG;IACH,QAAQ,CAAC,EAAE,SAAS,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,IAAI,KAAK,SAAS,CAAC,CAAC;IAExE;;OAEG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,KAAK,IAAI,CAAC;IAEvD;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAED;;GAEG;AACH,UAAU,kBAAkB;IAC1B,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;CACrB;AAyDD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,qBAAa,aAAc,SAAQ,SAAS,CAAC,kBAAkB,EAAE,kBAAkB,CAAC;gBACtE,KAAK,EAAE,kBAAkB;IAKrC,MAAM,CAAC,wBAAwB,CAAC,KAAK,EAAE,KAAK,GAAG,kBAAkB;IAKjE,iBAAiB,CAAC,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,GAAG,IAAI;IA4B3D,KAAK,QAAO,IAAI,CAMd;IAEF,MAAM,IAAI,SAAS;CAmBpB"}
@@ -0,0 +1,121 @@
1
+ /**
2
+ * @hua-labs/hua-ux/framework - ErrorBoundary
3
+ *
4
+ * React Error Boundary component for catching and handling errors
5
+ */
6
+ 'use client';
7
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
8
+ import { Component } from 'react';
9
+ /**
10
+ * Default fallback UI
11
+ */
12
+ function DefaultFallback({ error, reset }) {
13
+ return (_jsxs("div", { role: "alert", style: {
14
+ padding: '2rem',
15
+ margin: '2rem auto',
16
+ maxWidth: '600px',
17
+ border: '1px solid #ef4444',
18
+ borderRadius: '0.5rem',
19
+ backgroundColor: '#fef2f2',
20
+ color: '#991b1b',
21
+ }, children: [_jsx("h2", { style: { fontSize: '1.5rem', fontWeight: 'bold', marginBottom: '1rem' }, children: "\u26A0\uFE0F \uC624\uB958\uAC00 \uBC1C\uC0DD\uD588\uC2B5\uB2C8\uB2E4 / An error occurred" }), _jsxs("details", { style: { marginBottom: '1rem' }, children: [_jsx("summary", { style: { cursor: 'pointer', fontWeight: 500 }, children: "\uC5D0\uB7EC \uC0C1\uC138 \uC815\uBCF4 / Error details" }), _jsx("pre", { style: {
22
+ marginTop: '0.5rem',
23
+ padding: '1rem',
24
+ backgroundColor: '#fee2e2',
25
+ borderRadius: '0.25rem',
26
+ overflow: 'auto',
27
+ fontSize: '0.875rem',
28
+ }, children: error.message })] }), _jsx("button", { onClick: reset, style: {
29
+ padding: '0.5rem 1rem',
30
+ backgroundColor: '#dc2626',
31
+ color: 'white',
32
+ border: 'none',
33
+ borderRadius: '0.25rem',
34
+ cursor: 'pointer',
35
+ fontWeight: 500,
36
+ }, children: "\uD83D\uDD04 \uB2E4\uC2DC \uC2DC\uB3C4 / Try again" })] }));
37
+ }
38
+ /**
39
+ * Error Boundary Component
40
+ *
41
+ * Catches JavaScript errors anywhere in the child component tree,
42
+ * logs those errors, and displays a fallback UI.
43
+ *
44
+ * @example
45
+ * ```tsx
46
+ * <ErrorBoundary fallback={<div>Something went wrong</div>}>
47
+ * <MyComponent />
48
+ * </ErrorBoundary>
49
+ * ```
50
+ *
51
+ * @example
52
+ * ```tsx
53
+ * <ErrorBoundary
54
+ * fallback={(error, reset) => (
55
+ * <div>
56
+ * <h1>Error: {error.message}</h1>
57
+ * <button onClick={reset}>Try again</button>
58
+ * </div>
59
+ * )}
60
+ * >
61
+ * <MyComponent />
62
+ * </ErrorBoundary>
63
+ * ```
64
+ */
65
+ export class ErrorBoundary extends Component {
66
+ constructor(props) {
67
+ super(props);
68
+ this.reset = () => {
69
+ // Call onReset callback if provided
70
+ this.props.onReset?.();
71
+ // Reset error state
72
+ this.setState({ hasError: false, error: null });
73
+ };
74
+ this.state = { hasError: false, error: null };
75
+ }
76
+ static getDerivedStateFromError(error) {
77
+ // Update state so the next render will show the fallback UI
78
+ return { hasError: true, error };
79
+ }
80
+ componentDidCatch(error, errorInfo) {
81
+ // 개발 모드: 콘솔에 에러 로그
82
+ // Development mode: Log error to console
83
+ if (process.env.NODE_ENV === 'development') {
84
+ console.error('[ErrorBoundary] Caught error:', error);
85
+ console.error('[ErrorBoundary] Error info:', errorInfo);
86
+ }
87
+ // 프로덕션 모드: 에러 리포팅 서비스 통합 (선택적)
88
+ // Production mode: Integrate with error reporting service (optional)
89
+ if (process.env.NODE_ENV === 'production') {
90
+ // 전역 에러 리포터가 설정되어 있으면 사용
91
+ // Use global error reporter if configured
92
+ if (typeof window !== 'undefined' && window.__ERROR_REPORTER__) {
93
+ try {
94
+ window.__ERROR_REPORTER__(error, errorInfo);
95
+ }
96
+ catch (reportingError) {
97
+ // 에러 리포팅 자체가 실패해도 앱은 계속 동작해야 함
98
+ // App should continue working even if error reporting fails
99
+ console.error('[ErrorBoundary] Error reporting failed:', reportingError);
100
+ }
101
+ }
102
+ }
103
+ // Call onError callback if provided
104
+ this.props.onError?.(error, errorInfo);
105
+ }
106
+ render() {
107
+ if (this.state.hasError && this.state.error) {
108
+ // Render fallback UI
109
+ const { fallback } = this.props;
110
+ if (typeof fallback === 'function') {
111
+ return fallback(this.state.error, this.reset);
112
+ }
113
+ if (fallback) {
114
+ return fallback;
115
+ }
116
+ // Default fallback
117
+ return _jsx(DefaultFallback, { error: this.state.error, reset: this.reset });
118
+ }
119
+ return this.props.children;
120
+ }
121
+ }
@@ -0,0 +1,29 @@
1
+ /**
2
+ * @hua-labs/hua-ux/framework - HuaUxLayout
3
+ *
4
+ * Root layout wrapper that automatically sets up all providers
5
+ */
6
+ import type { HuaUxLayoutProps } from '../types';
7
+ /**
8
+ * HuaUxLayout Component
9
+ *
10
+ * Automatically configures i18n, motion, and state providers based on configuration.
11
+ *
12
+ * @example
13
+ * ```tsx
14
+ * // app/layout.tsx
15
+ * import { HuaUxLayout } from '@hua-labs/hua-ux/framework';
16
+ *
17
+ * export default function RootLayout({ children }) {
18
+ * return (
19
+ * <html lang="ko">
20
+ * <body>
21
+ * <HuaUxLayout>{children}</HuaUxLayout>
22
+ * </body>
23
+ * </html>
24
+ * );
25
+ * }
26
+ * ```
27
+ */
28
+ export declare function HuaUxLayout({ children, config }: HuaUxLayoutProps): import("react/jsx-runtime").JSX.Element;
29
+ //# sourceMappingURL=HuaUxLayout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HuaUxLayout.d.ts","sourceRoot":"","sources":["../../../src/framework/components/HuaUxLayout.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAGjD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,WAAW,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,gBAAgB,2CAEjE"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * @hua-labs/hua-ux/framework - HuaUxLayout
3
+ *
4
+ * Root layout wrapper that automatically sets up all providers
5
+ */
6
+ 'use client';
7
+ import { jsx as _jsx } from "react/jsx-runtime";
8
+ import { UnifiedProviders } from './Providers';
9
+ /**
10
+ * HuaUxLayout Component
11
+ *
12
+ * Automatically configures i18n, motion, and state providers based on configuration.
13
+ *
14
+ * @example
15
+ * ```tsx
16
+ * // app/layout.tsx
17
+ * import { HuaUxLayout } from '@hua-labs/hua-ux/framework';
18
+ *
19
+ * export default function RootLayout({ children }) {
20
+ * return (
21
+ * <html lang="ko">
22
+ * <body>
23
+ * <HuaUxLayout>{children}</HuaUxLayout>
24
+ * </body>
25
+ * </html>
26
+ * );
27
+ * }
28
+ * ```
29
+ */
30
+ export function HuaUxLayout({ children, config }) {
31
+ return _jsx(UnifiedProviders, { config: config, children: children });
32
+ }
@@ -0,0 +1,48 @@
1
+ /**
2
+ * @hua-labs/hua-ux/framework - HuaUxPage
3
+ *
4
+ * Page wrapper with automatic motion and i18n support
5
+ */
6
+ import type { HuaUxPageProps } from '../types';
7
+ /**
8
+ * HuaUxPage Component
9
+ *
10
+ * 페이지 콘텐츠를 자동 모션 애니메이션과 i18n 지원으로 감싸는 컴포넌트입니다.
11
+ * Wraps page content with automatic motion animations and i18n support.
12
+ *
13
+ * **바이브 코딩 친화적 / Vibe Coding Friendly**:
14
+ * - 한 파일에서 SEO, Motion, i18n을 모두 결정할 수 있습니다.
15
+ * - You can decide SEO, Motion, and i18n all in one file.
16
+ * - AI가 파일 하나만 보고도 완벽한 페이지를 생성할 수 있습니다.
17
+ * - AI can generate a perfect page by looking at just one file.
18
+ *
19
+ * @example
20
+ * ```tsx
21
+ * // app/page.tsx
22
+ * import { HuaUxPage } from '@hua-labs/hua-ux/framework';
23
+ *
24
+ * export default function HomePage() {
25
+ * return (
26
+ * <HuaUxPage
27
+ * vibe="clean"
28
+ * i18nKey="home"
29
+ * title="홈"
30
+ * description="환영합니다"
31
+ * >
32
+ * <h1>Welcome</h1>
33
+ * </HuaUxPage>
34
+ * );
35
+ * }
36
+ * ```
37
+ *
38
+ * @example
39
+ * ```tsx
40
+ * // 바이브 코더용: vibe만으로 스타일 결정
41
+ * // For vibe coders: decide style with just vibe
42
+ * <HuaUxPage vibe="fancy">
43
+ * <div>화려한 인터랙션이 자동 적용됩니다</div>
44
+ * </HuaUxPage>
45
+ * ```
46
+ */
47
+ export declare function HuaUxPage({ children, title, description, vibe, i18nKey, enableMotion, enableErrorBoundary, errorBoundaryFallback, seo, motion, }: HuaUxPageProps): import("react/jsx-runtime").JSX.Element;
48
+ //# sourceMappingURL=HuaUxPage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HuaUxPage.d.ts","sourceRoot":"","sources":["../../../src/framework/components/HuaUxPage.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAK/C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,wBAAgB,SAAS,CAAC,EACxB,QAAQ,EACR,KAAK,EACL,WAAW,EACX,IAAI,EACJ,OAAO,EACP,YAAmB,EACnB,mBAA0B,EAC1B,qBAAqB,EACrB,GAAG,EACH,MAAM,GACP,EAAE,cAAc,2CAwEhB"}
@@ -0,0 +1,105 @@
1
+ /**
2
+ * @hua-labs/hua-ux/framework - HuaUxPage
3
+ *
4
+ * Page wrapper with automatic motion and i18n support
5
+ */
6
+ 'use client';
7
+ import { jsx as _jsx } from "react/jsx-runtime";
8
+ import React from 'react';
9
+ import { getConfig } from '../config';
10
+ import { useMotion } from '../hooks/useMotion';
11
+ import { ErrorBoundary } from './ErrorBoundary';
12
+ /**
13
+ * HuaUxPage Component
14
+ *
15
+ * 페이지 콘텐츠를 자동 모션 애니메이션과 i18n 지원으로 감싸는 컴포넌트입니다.
16
+ * Wraps page content with automatic motion animations and i18n support.
17
+ *
18
+ * **바이브 코딩 친화적 / Vibe Coding Friendly**:
19
+ * - 한 파일에서 SEO, Motion, i18n을 모두 결정할 수 있습니다.
20
+ * - You can decide SEO, Motion, and i18n all in one file.
21
+ * - AI가 파일 하나만 보고도 완벽한 페이지를 생성할 수 있습니다.
22
+ * - AI can generate a perfect page by looking at just one file.
23
+ *
24
+ * @example
25
+ * ```tsx
26
+ * // app/page.tsx
27
+ * import { HuaUxPage } from '@hua-labs/hua-ux/framework';
28
+ *
29
+ * export default function HomePage() {
30
+ * return (
31
+ * <HuaUxPage
32
+ * vibe="clean"
33
+ * i18nKey="home"
34
+ * title="홈"
35
+ * description="환영합니다"
36
+ * >
37
+ * <h1>Welcome</h1>
38
+ * </HuaUxPage>
39
+ * );
40
+ * }
41
+ * ```
42
+ *
43
+ * @example
44
+ * ```tsx
45
+ * // 바이브 코더용: vibe만으로 스타일 결정
46
+ * // For vibe coders: decide style with just vibe
47
+ * <HuaUxPage vibe="fancy">
48
+ * <div>화려한 인터랙션이 자동 적용됩니다</div>
49
+ * </HuaUxPage>
50
+ * ```
51
+ */
52
+ export function HuaUxPage({ children, title, description, vibe, i18nKey, enableMotion = true, enableErrorBoundary = true, errorBoundaryFallback, seo, motion, }) {
53
+ const config = getConfig();
54
+ // vibe에 따라 모션 설정 조정
55
+ // Adjust motion settings based on vibe
56
+ const motionDuration = vibe === 'fancy' ? 800 : vibe === 'minimal' ? 300 : 600;
57
+ const shouldEnableMotion = enableMotion && config.motion?.enableAnimations !== false;
58
+ // motion prop 또는 vibe에 따라 모션 타입 결정
59
+ // Determine motion type based on motion prop or vibe
60
+ const motionType = motion || (vibe === 'fancy' ? 'slideUp' : vibe === 'minimal' ? 'fadeIn' : 'fadeIn');
61
+ // 통합 Motion Hook 사용 (성능 최적화)
62
+ // Use unified Motion Hook (performance optimization)
63
+ // Note: React Rules of Hooks를 준수하기 위해 내부적으로 모든 hook을 호출하지만,
64
+ // 실제로는 선택된 hook만 활성화되어 성능 오버헤드를 최소화합니다.
65
+ // Note: All hooks are called internally to respect React Rules of Hooks,
66
+ // but only the selected hook is actually activated to minimize performance overhead.
67
+ const motionResult = useMotion({
68
+ type: motionType,
69
+ duration: motionDuration,
70
+ autoStart: false, // 수동으로 start 호출
71
+ });
72
+ // Start the selected motion if enabled
73
+ // 모션이 활성화된 경우 선택된 모션 시작
74
+ React.useEffect(() => {
75
+ if (shouldEnableMotion) {
76
+ motionResult.start?.();
77
+ }
78
+ // eslint-disable-next-line react-hooks/exhaustive-deps
79
+ }, [shouldEnableMotion]); // motionResult.start는 안정적인 함수이므로 dependency에서 제외
80
+ const pageRef = motionResult.ref;
81
+ // SEO 메타데이터는 Next.js App Router에서 page.tsx의 export const metadata로 처리하는 것이 권장됩니다.
82
+ // 이 컴포넌트는 Client Component이므로 메타데이터를 직접 설정할 수 없습니다.
83
+ // SEO 설정이 있으면 개발자에게 경고 메시지 표시 (개발 모드에서만)
84
+ React.useEffect(() => {
85
+ if (process.env.NODE_ENV === 'development' && seo) {
86
+ console.warn('[HuaUxPage] SEO metadata should be set using `export const metadata` in page.tsx.\n' +
87
+ 'Use `generatePageMetadata()` helper function from @hua-labs/hua-ux/framework');
88
+ }
89
+ }, [seo]);
90
+ // i18nKey가 있으면 해당 네임스페이스를 자동으로 로드하도록 안내
91
+ // (실제 로드는 I18nProvider에서 자동 처리됨)
92
+ React.useEffect(() => {
93
+ if (process.env.NODE_ENV === 'development' && i18nKey) {
94
+ // i18nKey가 설정되어 있으면 해당 네임스페이스가 자동으로 로드됩니다.
95
+ // 번역 키는 `${i18nKey}:title`, `${i18nKey}:description` 형식으로 사용할 수 있습니다.
96
+ // Translation keys can be used in the format `${i18nKey}:title`, `${i18nKey}:description`
97
+ }
98
+ }, [i18nKey]);
99
+ const pageContent = (_jsx("div", { ref: pageRef, style: motionResult.style, children: children }));
100
+ // Wrap with ErrorBoundary if enabled
101
+ if (enableErrorBoundary) {
102
+ return (_jsx(ErrorBoundary, { fallback: errorBoundaryFallback, children: pageContent }));
103
+ }
104
+ return pageContent;
105
+ }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * @hua-labs/hua-ux/framework - Providers
3
+ *
4
+ * Unified providers for i18n, motion, and state
5
+ */
6
+ import type { ReactNode } from 'react';
7
+ import type { HuaUxConfig } from '../types';
8
+ /**
9
+ * UnifiedProviders component
10
+ *
11
+ * Automatically creates and wraps children with all necessary providers
12
+ */
13
+ export declare function UnifiedProviders({ children, config: overrideConfig, }: {
14
+ children: ReactNode;
15
+ config?: Partial<HuaUxConfig>;
16
+ }): import("react/jsx-runtime").JSX.Element;
17
+ //# sourceMappingURL=Providers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Providers.d.ts","sourceRoot":"","sources":["../../../src/framework/components/Providers.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAiE5C;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,EAC/B,QAAQ,EACR,MAAM,EAAE,cAAc,GACvB,EAAE;IACD,QAAQ,EAAE,SAAS,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;CAC/B,2CAWA"}
@@ -0,0 +1,72 @@
1
+ /**
2
+ * @hua-labs/hua-ux/framework - Providers
3
+ *
4
+ * Unified providers for i18n, motion, and state
5
+ */
6
+ 'use client';
7
+ import { jsx as _jsx } from "react/jsx-runtime";
8
+ import React from 'react';
9
+ import { getConfig } from '../config';
10
+ import { createZustandI18n } from '@hua-labs/i18n-core-zustand';
11
+ import { createI18nStore } from '@hua-labs/state';
12
+ import { BrandingProvider } from '../branding/context';
13
+ /**
14
+ * Create providers based on configuration
15
+ *
16
+ * Provider 체인을 생성합니다. Branding Provider는 가장 바깥쪽에 위치하여
17
+ * 다른 Provider들이 브랜딩 설정을 사용할 수 있도록 합니다.
18
+ *
19
+ * Creates a provider chain. Branding Provider is placed at the outermost level
20
+ * so other providers can use branding configuration.
21
+ */
22
+ function createProviders(config) {
23
+ const providers = [];
24
+ // Branding Provider를 먼저 추가 (다른 Provider들이 사용 가능하도록)
25
+ // Add Branding Provider first (so other providers can use it)
26
+ if (config.branding) {
27
+ providers.push(({ children }) => (_jsx(BrandingProvider, { branding: config.branding || null, children: children })));
28
+ }
29
+ // i18n Provider
30
+ if (config.i18n) {
31
+ const i18nStore = createI18nStore({
32
+ defaultLanguage: config.i18n.defaultLanguage,
33
+ supportedLanguages: config.i18n.supportedLanguages,
34
+ persist: config.state?.persist ?? true,
35
+ ssr: config.state?.ssr ?? true,
36
+ });
37
+ // Type assertion: I18nStoreState extends ZustandLanguageStore, so this is safe
38
+ const I18nProvider = createZustandI18n(i18nStore, // Type assertion needed due to Zustand's complex type system
39
+ {
40
+ fallbackLanguage: config.i18n.fallbackLanguage || 'en',
41
+ namespaces: config.i18n.namespaces || ['common'],
42
+ translationLoader: config.i18n.translationLoader || 'api',
43
+ translationApiPath: config.i18n.translationApiPath || '/api/translations',
44
+ defaultLanguage: config.i18n.defaultLanguage,
45
+ loadTranslations: config.i18n.loadTranslations,
46
+ debug: config.i18n.debug,
47
+ });
48
+ providers.push(I18nProvider);
49
+ }
50
+ // Return a combined provider
51
+ return function CombinedProvider({ children }) {
52
+ // Provider 체인 생성 (Branding Provider가 가장 바깥쪽)
53
+ // Create provider chain (Branding Provider is outermost)
54
+ const wrapped = providers.reduceRight((acc, Provider) => _jsx(Provider, { children: acc }), children);
55
+ return wrapped;
56
+ };
57
+ }
58
+ /**
59
+ * UnifiedProviders component
60
+ *
61
+ * Automatically creates and wraps children with all necessary providers
62
+ */
63
+ export function UnifiedProviders({ children, config: overrideConfig, }) {
64
+ const baseConfig = getConfig();
65
+ const config = overrideConfig
66
+ ? { ...baseConfig, ...overrideConfig }
67
+ : baseConfig;
68
+ const Provider = React.useMemo(() => createProviders(config), [config]);
69
+ // Provider 체인은 createProviders 내부에서 처리됨
70
+ // Provider chain is handled inside createProviders
71
+ return _jsx(Provider, { children: children });
72
+ }
@@ -0,0 +1,44 @@
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
+ import React from 'react';
8
+ import type { HuaUxPageProps } from '../types';
9
+ export interface WelcomePageProps extends Omit<HuaUxPageProps, 'children'> {
10
+ /**
11
+ * Project name to display
12
+ */
13
+ projectName?: string;
14
+ /**
15
+ * Show framework features
16
+ */
17
+ showFeatures?: boolean;
18
+ /**
19
+ * Show quick links
20
+ */
21
+ showQuickLinks?: boolean;
22
+ /**
23
+ * Custom content to display
24
+ */
25
+ children?: React.ReactNode;
26
+ }
27
+ /**
28
+ * WelcomePage Component
29
+ *
30
+ * Default welcome page for new hua-ux projects.
31
+ * Displays project information, framework features, and quick links.
32
+ *
33
+ * @example
34
+ * ```tsx
35
+ * // app/page.tsx
36
+ * import { WelcomePage } from '@hua-labs/hua-ux/framework';
37
+ *
38
+ * export default function HomePage() {
39
+ * return <WelcomePage projectName="My App" />;
40
+ * }
41
+ * ```
42
+ */
43
+ export declare function WelcomePage({ projectName, showFeatures, showQuickLinks, children, ...pageProps }: WelcomePageProps): import("react/jsx-runtime").JSX.Element;
44
+ //# sourceMappingURL=WelcomePage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WelcomePage.d.ts","sourceRoot":"","sources":["../../../src/framework/components/WelcomePage.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAE/C,MAAM,WAAW,gBAAiB,SAAQ,IAAI,CAAC,cAAc,EAAE,UAAU,CAAC;IACxE;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IAEvB;;OAEG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IAEzB;;OAEG;IACH,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,WAAW,CAAC,EAC1B,WAAsB,EACtB,YAAmB,EACnB,cAAqB,EACrB,QAAQ,EACR,GAAG,SAAS,EACb,EAAE,gBAAgB,2CAmJlB"}