@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,56 @@
1
+ /**
2
+ * @hua-labs/hua-ux/framework - useDelayedLoading
3
+ *
4
+ * 빠른 API 응답 시 로딩 UI 깜빡임을 방지하는 hook
5
+ * Prevents loading UI flicker for fast API responses
6
+ */
7
+ /**
8
+ * Delayed Loading 옵션
9
+ */
10
+ export interface DelayedLoadingOptions {
11
+ /**
12
+ * 로딩 UI를 표시하기 전 대기 시간 (밀리초)
13
+ * Delay before showing loading UI (milliseconds)
14
+ *
15
+ * @default 300
16
+ */
17
+ delay?: number;
18
+ /**
19
+ * 최소 표시 시간 (밀리초) - 로딩이 너무 빨리 끝나도 최소한 이 시간은 표시
20
+ * Minimum display time (milliseconds) - show loading for at least this duration
21
+ *
22
+ * @default 0
23
+ */
24
+ minDisplayTime?: number;
25
+ }
26
+ /**
27
+ * useDelayedLoading Hook
28
+ *
29
+ * 빠른 API 응답 시 로딩 UI가 깜빡거리는 것을 방지합니다.
30
+ * 300ms 이하로 끝나면 로딩 UI를 아예 표시하지 않습니다.
31
+ *
32
+ * Prevents loading UI flicker for fast API responses.
33
+ * If loading completes within 300ms, the loading UI is not shown at all.
34
+ *
35
+ * @example
36
+ * ```tsx
37
+ * function MyComponent() {
38
+ * const [isLoading, setIsLoading] = useState(false);
39
+ * const showLoading = useDelayedLoading(isLoading);
40
+ *
41
+ * const fetchData = async () => {
42
+ * setIsLoading(true);
43
+ * await api.getData(); // 빠르게 끝나면 로딩 UI 안보임
44
+ * setIsLoading(false);
45
+ * };
46
+ *
47
+ * return showLoading ? <Spinner /> : <Content />;
48
+ * }
49
+ * ```
50
+ *
51
+ * @param isLoading - 현재 로딩 상태
52
+ * @param options - 옵션
53
+ * @returns 실제로 로딩 UI를 표시할지 여부
54
+ */
55
+ export declare function useDelayedLoading(isLoading: boolean, options?: DelayedLoadingOptions): boolean;
56
+ //# sourceMappingURL=useDelayedLoading.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useDelayedLoading.d.ts","sourceRoot":"","sources":["../../../../src/framework/loading/hooks/useDelayedLoading.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC;;;;;OAKG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;;;;OAKG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,OAAO,EAClB,OAAO,GAAE,qBAA0B,GAClC,OAAO,CA8DT"}
@@ -0,0 +1,97 @@
1
+ /**
2
+ * @hua-labs/hua-ux/framework - useDelayedLoading
3
+ *
4
+ * 빠른 API 응답 시 로딩 UI 깜빡임을 방지하는 hook
5
+ * Prevents loading UI flicker for fast API responses
6
+ */
7
+ 'use client';
8
+ import { useEffect, useRef, useState } from 'react';
9
+ /**
10
+ * useDelayedLoading Hook
11
+ *
12
+ * 빠른 API 응답 시 로딩 UI가 깜빡거리는 것을 방지합니다.
13
+ * 300ms 이하로 끝나면 로딩 UI를 아예 표시하지 않습니다.
14
+ *
15
+ * Prevents loading UI flicker for fast API responses.
16
+ * If loading completes within 300ms, the loading UI is not shown at all.
17
+ *
18
+ * @example
19
+ * ```tsx
20
+ * function MyComponent() {
21
+ * const [isLoading, setIsLoading] = useState(false);
22
+ * const showLoading = useDelayedLoading(isLoading);
23
+ *
24
+ * const fetchData = async () => {
25
+ * setIsLoading(true);
26
+ * await api.getData(); // 빠르게 끝나면 로딩 UI 안보임
27
+ * setIsLoading(false);
28
+ * };
29
+ *
30
+ * return showLoading ? <Spinner /> : <Content />;
31
+ * }
32
+ * ```
33
+ *
34
+ * @param isLoading - 현재 로딩 상태
35
+ * @param options - 옵션
36
+ * @returns 실제로 로딩 UI를 표시할지 여부
37
+ */
38
+ export function useDelayedLoading(isLoading, options = {}) {
39
+ const { delay = 300, minDisplayTime = 0 } = options;
40
+ const [showLoading, setShowLoading] = useState(false);
41
+ const loadingStartTimeRef = useRef(null);
42
+ const timeoutRef = useRef(null);
43
+ useEffect(() => {
44
+ // 이전 timeout 정리 (race condition 방지)
45
+ if (timeoutRef.current) {
46
+ clearTimeout(timeoutRef.current);
47
+ timeoutRef.current = null;
48
+ }
49
+ if (isLoading) {
50
+ // 로딩 시작 시간 기록
51
+ const startTime = Date.now();
52
+ loadingStartTimeRef.current = startTime;
53
+ // delay 후에 로딩 UI 표시
54
+ timeoutRef.current = setTimeout(() => {
55
+ // timeout이 여전히 유효한지 확인 (race condition 방지)
56
+ if (timeoutRef.current) {
57
+ setShowLoading(true);
58
+ timeoutRef.current = null;
59
+ }
60
+ }, delay);
61
+ }
62
+ else {
63
+ // 로딩이 끝났을 때
64
+ if (loadingStartTimeRef.current !== null) {
65
+ const elapsedTime = Date.now() - loadingStartTimeRef.current;
66
+ const remainingTime = Math.max(0, minDisplayTime - elapsedTime);
67
+ if (remainingTime > 0) {
68
+ // 최소 표시 시간이 남아있으면 그 시간만큼 더 표시
69
+ timeoutRef.current = setTimeout(() => {
70
+ // timeout이 여전히 유효한지 확인 (race condition 방지)
71
+ if (timeoutRef.current) {
72
+ setShowLoading(false);
73
+ loadingStartTimeRef.current = null;
74
+ timeoutRef.current = null;
75
+ }
76
+ }, remainingTime);
77
+ }
78
+ else {
79
+ // 이미 최소 표시 시간을 넘었으면 즉시 숨김
80
+ setShowLoading(false);
81
+ loadingStartTimeRef.current = null;
82
+ }
83
+ }
84
+ else {
85
+ // 로딩이 시작되지 않았으면 즉시 숨김
86
+ setShowLoading(false);
87
+ }
88
+ }
89
+ return () => {
90
+ if (timeoutRef.current) {
91
+ clearTimeout(timeoutRef.current);
92
+ timeoutRef.current = null;
93
+ }
94
+ };
95
+ }, [isLoading, delay, minDisplayTime]);
96
+ return showLoading;
97
+ }
@@ -0,0 +1,69 @@
1
+ /**
2
+ * @hua-labs/hua-ux/framework - useLoadingState
3
+ *
4
+ * 로딩 상태를 관리하는 편의성 hook
5
+ * Convenience hook for managing loading state
6
+ */
7
+ import { type DelayedLoadingOptions } from './useDelayedLoading';
8
+ /**
9
+ * useLoadingState 반환 타입
10
+ */
11
+ export interface UseLoadingStateReturn {
12
+ /**
13
+ * 실제로 로딩 UI를 표시할지 여부 (useDelayedLoading 적용)
14
+ * Whether to actually show loading UI (with useDelayedLoading applied)
15
+ */
16
+ showLoading: boolean;
17
+ /**
18
+ * 로딩 시작
19
+ * Start loading
20
+ */
21
+ startLoading: () => void;
22
+ /**
23
+ * 로딩 종료
24
+ * Stop loading
25
+ */
26
+ stopLoading: () => void;
27
+ /**
28
+ * 로딩 상태 토글
29
+ * Toggle loading state
30
+ */
31
+ toggleLoading: () => void;
32
+ /**
33
+ * 현재 로딩 상태 (지연 없이)
34
+ * Current loading state (without delay)
35
+ */
36
+ isLoading: boolean;
37
+ }
38
+ /**
39
+ * useLoadingState Hook
40
+ *
41
+ * 로딩 상태를 쉽게 관리할 수 있는 편의성 hook입니다.
42
+ * useDelayedLoading이 자동으로 적용됩니다.
43
+ *
44
+ * Convenience hook for easily managing loading state.
45
+ * useDelayedLoading is automatically applied.
46
+ *
47
+ * @example
48
+ * ```tsx
49
+ * function MyComponent() {
50
+ * const { showLoading, startLoading, stopLoading } = useLoadingState();
51
+ *
52
+ * const fetchData = async () => {
53
+ * startLoading();
54
+ * try {
55
+ * await api.getData();
56
+ * } finally {
57
+ * stopLoading();
58
+ * }
59
+ * };
60
+ *
61
+ * return showLoading && <Spinner />;
62
+ * }
63
+ * ```
64
+ *
65
+ * @param options - useDelayedLoading 옵션
66
+ * @returns 로딩 상태 제어 함수
67
+ */
68
+ export declare function useLoadingState(options?: DelayedLoadingOptions): UseLoadingStateReturn;
69
+ //# sourceMappingURL=useLoadingState.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useLoadingState.d.ts","sourceRoot":"","sources":["../../../../src/framework/loading/hooks/useLoadingState.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,EAAqB,KAAK,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAEpF;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC;;;OAGG;IACH,WAAW,EAAE,OAAO,CAAC;IAErB;;;OAGG;IACH,YAAY,EAAE,MAAM,IAAI,CAAC;IAEzB;;;OAGG;IACH,WAAW,EAAE,MAAM,IAAI,CAAC;IAExB;;;OAGG;IACH,aAAa,EAAE,MAAM,IAAI,CAAC;IAE1B;;;OAGG;IACH,SAAS,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,eAAe,CAC7B,OAAO,GAAE,qBAA0B,GAClC,qBAAqB,CAuBvB"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * @hua-labs/hua-ux/framework - useLoadingState
3
+ *
4
+ * 로딩 상태를 관리하는 편의성 hook
5
+ * Convenience hook for managing loading state
6
+ */
7
+ 'use client';
8
+ import { useCallback, useState } from 'react';
9
+ import { useDelayedLoading } from './useDelayedLoading';
10
+ /**
11
+ * useLoadingState Hook
12
+ *
13
+ * 로딩 상태를 쉽게 관리할 수 있는 편의성 hook입니다.
14
+ * useDelayedLoading이 자동으로 적용됩니다.
15
+ *
16
+ * Convenience hook for easily managing loading state.
17
+ * useDelayedLoading is automatically applied.
18
+ *
19
+ * @example
20
+ * ```tsx
21
+ * function MyComponent() {
22
+ * const { showLoading, startLoading, stopLoading } = useLoadingState();
23
+ *
24
+ * const fetchData = async () => {
25
+ * startLoading();
26
+ * try {
27
+ * await api.getData();
28
+ * } finally {
29
+ * stopLoading();
30
+ * }
31
+ * };
32
+ *
33
+ * return showLoading && <Spinner />;
34
+ * }
35
+ * ```
36
+ *
37
+ * @param options - useDelayedLoading 옵션
38
+ * @returns 로딩 상태 제어 함수
39
+ */
40
+ export function useLoadingState(options = {}) {
41
+ const [isLoading, setIsLoading] = useState(false);
42
+ const showLoading = useDelayedLoading(isLoading, options);
43
+ const startLoading = useCallback(() => {
44
+ setIsLoading(true);
45
+ }, []);
46
+ const stopLoading = useCallback(() => {
47
+ setIsLoading(false);
48
+ }, []);
49
+ const toggleLoading = useCallback(() => {
50
+ setIsLoading((prev) => !prev);
51
+ }, []);
52
+ return {
53
+ showLoading,
54
+ startLoading,
55
+ stopLoading,
56
+ toggleLoading,
57
+ isLoading,
58
+ };
59
+ }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * @hua-labs/hua-ux/framework - Loading State
3
+ *
4
+ * 로딩 상태 최적화 도구 모음
5
+ * Loading state optimization tools
6
+ */
7
+ export { useDelayedLoading } from './hooks/useDelayedLoading';
8
+ export { useLoadingState } from './hooks/useLoadingState';
9
+ export { SkeletonGroup } from './components/SkeletonGroup';
10
+ export { SuspenseWrapper } from './components/SuspenseWrapper';
11
+ export { withSuspense } from './hoc/withSuspense';
12
+ export { Skeleton } from '@hua-labs/ui';
13
+ export type { DelayedLoadingOptions } from './hooks/useDelayedLoading';
14
+ export type { SkeletonGroupProps } from './components/SkeletonGroup';
15
+ export type { SuspenseWrapperProps } from './components/SuspenseWrapper';
16
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/framework/loading/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAGlD,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAExC,YAAY,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AACvE,YAAY,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AACrE,YAAY,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * @hua-labs/hua-ux/framework - Loading State
3
+ *
4
+ * 로딩 상태 최적화 도구 모음
5
+ * Loading state optimization tools
6
+ */
7
+ export { useDelayedLoading } from './hooks/useDelayedLoading';
8
+ export { useLoadingState } from './hooks/useLoadingState';
9
+ export { SkeletonGroup } from './components/SkeletonGroup';
10
+ export { SuspenseWrapper } from './components/SuspenseWrapper';
11
+ export { withSuspense } from './hoc/withSuspense';
12
+ // Skeleton은 @hua-labs/ui에서 re-export
13
+ export { Skeleton } from '@hua-labs/ui';
@@ -0,0 +1,90 @@
1
+ /**
2
+ * @hua-labs/hua-ux/framework - i18n Middleware
3
+ *
4
+ * i18n middleware for automatic language detection and routing
5
+ *
6
+ * **타입 안전성**: Next.js를 peerDependency로 사용하므로,
7
+ * Next.js 프로젝트에서는 자동으로 타입이 추론됩니다.
8
+ *
9
+ * **Type Safety**: Next.js is used as a peerDependency,
10
+ * so types are automatically inferred in Next.js projects.
11
+ */
12
+ /**
13
+ * Base interface for NextRequest (when Next.js is not available)
14
+ */
15
+ interface BaseNextRequest {
16
+ headers: {
17
+ get(name: string): string | null;
18
+ };
19
+ cookies: {
20
+ get(name: string): {
21
+ value: string;
22
+ } | undefined;
23
+ };
24
+ nextUrl: {
25
+ pathname: string;
26
+ searchParams: URLSearchParams;
27
+ };
28
+ }
29
+ /**
30
+ * NextRequest type - Next.js가 있으면 실제 타입, 없으면 기본 인터페이스
31
+ *
32
+ * Next.js가 optional peerDependency이므로, 타입 레벨에서만 처리합니다.
33
+ * 실제 Next.js 프로젝트에서는 Next.js의 NextRequest 타입이 자동으로 사용됩니다.
34
+ */
35
+ type NextRequest = BaseNextRequest;
36
+ /**
37
+ * Base interface for NextResponse (when Next.js is not available)
38
+ */
39
+ interface BaseNextResponse {
40
+ headers: Headers;
41
+ next?(): BaseNextResponse;
42
+ redirect?(url: string): BaseNextResponse;
43
+ }
44
+ /**
45
+ * i18n middleware configuration
46
+ */
47
+ export interface I18nMiddlewareConfig {
48
+ /**
49
+ * Default language
50
+ */
51
+ defaultLanguage: string;
52
+ /**
53
+ * Supported languages
54
+ */
55
+ supportedLanguages: string[];
56
+ /**
57
+ * Language detection strategy
58
+ */
59
+ detectionStrategy?: 'header' | 'cookie' | 'path' | 'query';
60
+ }
61
+ /**
62
+ * Create i18n middleware for Next.js
63
+ *
64
+ * **⚠️ Edge Runtime Note**: This middleware runs on Edge Runtime.
65
+ * Make sure your middleware.ts file exports the runtime config:
66
+ *
67
+ * ```ts
68
+ * export const runtime = 'edge';
69
+ * ```
70
+ *
71
+ * @example
72
+ * ```ts
73
+ * // middleware.ts
74
+ * import { createI18nMiddleware } from '@hua-labs/hua-ux/framework';
75
+ *
76
+ * // Edge Runtime 명시 (Vercel 자동 감지 방지)
77
+ * export const runtime = 'edge';
78
+ *
79
+ * export default createI18nMiddleware({
80
+ * defaultLanguage: 'ko',
81
+ * supportedLanguages: ['ko', 'en'],
82
+ * });
83
+ * ```
84
+ *
85
+ * **Alternative**: If you don't want to use Edge Runtime, you can handle
86
+ * language detection in your API routes or client components instead.
87
+ */
88
+ export declare function createI18nMiddleware(config: I18nMiddlewareConfig): (request: NextRequest) => BaseNextResponse;
89
+ export {};
90
+ //# sourceMappingURL=i18n.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"i18n.d.ts","sourceRoot":"","sources":["../../../src/framework/middleware/i18n.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAKH;;GAEG;AACH,UAAU,eAAe;IACvB,OAAO,EAAE;QACP,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;KAClC,CAAC;IACF,OAAO,EAAE;QACP,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG;YAAE,KAAK,EAAE,MAAM,CAAA;SAAE,GAAG,SAAS,CAAC;KAClD,CAAC;IACF,OAAO,EAAE;QACP,QAAQ,EAAE,MAAM,CAAC;QACjB,YAAY,EAAE,eAAe,CAAC;KAC/B,CAAC;CACH;AAED;;;;;GAKG;AACH,KAAK,WAAW,GAAG,eAAe,CAAC;AAEnC;;GAEG;AACH,UAAU,gBAAgB;IACxB,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,IAAI,gBAAgB,CAAC;IAC1B,QAAQ,CAAC,CAAC,GAAG,EAAE,MAAM,GAAG,gBAAgB,CAAC;CAC1C;AA4BD;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC;;OAEG;IACH,eAAe,EAAE,MAAM,CAAC;IAExB;;OAEG;IACH,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAE7B;;OAEG;IACH,iBAAiB,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;CAC5D;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,oBAAoB,IAChC,SAAS,WAAW,sBAsCpD"}
@@ -0,0 +1,99 @@
1
+ /**
2
+ * @hua-labs/hua-ux/framework - i18n Middleware
3
+ *
4
+ * i18n middleware for automatic language detection and routing
5
+ *
6
+ * **타입 안전성**: Next.js를 peerDependency로 사용하므로,
7
+ * Next.js 프로젝트에서는 자동으로 타입이 추론됩니다.
8
+ *
9
+ * **Type Safety**: Next.js is used as a peerDependency,
10
+ * so types are automatically inferred in Next.js projects.
11
+ */
12
+ /**
13
+ * NextResponse factory function
14
+ * Next.js가 설치되어 있으면 실제 NextResponse를 사용하고, 없으면 폴백 구현을 사용합니다.
15
+ */
16
+ let NextResponseFactory;
17
+ try {
18
+ // Next.js가 설치되어 있으면 실제 NextResponse 사용
19
+ const nextServer = require('next/server');
20
+ NextResponseFactory = nextServer.NextResponse;
21
+ }
22
+ catch {
23
+ // Next.js가 없으면 폴백 구현
24
+ // Fallback implementation if Next.js is not available
25
+ NextResponseFactory = {
26
+ next: () => ({
27
+ headers: new Headers(),
28
+ }),
29
+ redirect: (url) => ({
30
+ headers: new Headers(),
31
+ }),
32
+ };
33
+ }
34
+ /**
35
+ * Create i18n middleware for Next.js
36
+ *
37
+ * **⚠️ Edge Runtime Note**: This middleware runs on Edge Runtime.
38
+ * Make sure your middleware.ts file exports the runtime config:
39
+ *
40
+ * ```ts
41
+ * export const runtime = 'edge';
42
+ * ```
43
+ *
44
+ * @example
45
+ * ```ts
46
+ * // middleware.ts
47
+ * import { createI18nMiddleware } from '@hua-labs/hua-ux/framework';
48
+ *
49
+ * // Edge Runtime 명시 (Vercel 자동 감지 방지)
50
+ * export const runtime = 'edge';
51
+ *
52
+ * export default createI18nMiddleware({
53
+ * defaultLanguage: 'ko',
54
+ * supportedLanguages: ['ko', 'en'],
55
+ * });
56
+ * ```
57
+ *
58
+ * **Alternative**: If you don't want to use Edge Runtime, you can handle
59
+ * language detection in your API routes or client components instead.
60
+ */
61
+ export function createI18nMiddleware(config) {
62
+ return function i18nMiddleware(request) {
63
+ const { defaultLanguage, supportedLanguages, detectionStrategy = 'header' } = config;
64
+ // Get language from various sources
65
+ let language = defaultLanguage;
66
+ if (detectionStrategy === 'header') {
67
+ const acceptLanguage = request.headers.get('accept-language');
68
+ if (acceptLanguage) {
69
+ // Simple language detection from Accept-Language header
70
+ const preferredLang = acceptLanguage.split(',')[0].split('-')[0].toLowerCase();
71
+ if (supportedLanguages.includes(preferredLang)) {
72
+ language = preferredLang;
73
+ }
74
+ }
75
+ }
76
+ else if (detectionStrategy === 'cookie') {
77
+ const cookieLang = request.cookies.get('language')?.value;
78
+ if (cookieLang && supportedLanguages.includes(cookieLang)) {
79
+ language = cookieLang;
80
+ }
81
+ }
82
+ else if (detectionStrategy === 'path') {
83
+ const pathLang = request.nextUrl.pathname.split('/')[1];
84
+ if (pathLang && supportedLanguages.includes(pathLang)) {
85
+ language = pathLang;
86
+ }
87
+ }
88
+ else if (detectionStrategy === 'query') {
89
+ const queryLang = request.nextUrl.searchParams.get('lang');
90
+ if (queryLang && supportedLanguages.includes(queryLang)) {
91
+ language = queryLang;
92
+ }
93
+ }
94
+ // Add language to request headers for use in components
95
+ const response = NextResponseFactory.next();
96
+ response.headers.set('x-language', language);
97
+ return response;
98
+ };
99
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * @hua-labs/hua-ux/framework - Plugin System
3
+ *
4
+ * 플러그인 시스템 메인 export
5
+ */
6
+ export { pluginRegistry, registerPlugin, getPlugin, getAllPlugins } from './registry';
7
+ export type { HuaUxPlugin } from './types';
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/framework/plugins/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,cAAc,EACd,cAAc,EACd,SAAS,EACT,aAAa,EACd,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * @hua-labs/hua-ux/framework - Plugin System
3
+ *
4
+ * 플러그인 시스템 메인 export
5
+ */
6
+ export { pluginRegistry, registerPlugin, getPlugin, getAllPlugins } from './registry';
@@ -0,0 +1,95 @@
1
+ /**
2
+ * @hua-labs/hua-ux/framework - Plugin Registry
3
+ *
4
+ * 플러그인 등록 및 관리 시스템
5
+ */
6
+ import type { HuaUxPlugin } from './types';
7
+ /**
8
+ * 플러그인 레지스트리 / Plugin registry
9
+ *
10
+ * 모든 플러그인을 등록하고 관리하는 싱글톤 클래스
11
+ * Singleton class that registers and manages all plugins
12
+ */
13
+ declare class PluginRegistry {
14
+ private plugins;
15
+ private initialized;
16
+ /**
17
+ * 플러그인 등록 / Register plugin
18
+ *
19
+ * @param plugin - 등록할 플러그인
20
+ * @throws 라이선스가 없을 경우 에러
21
+ *
22
+ * @example
23
+ * ```ts
24
+ * import { registerPlugin } from '@hua-labs/hua-ux/framework';
25
+ * import { motionProPlugin } from '@hua-labs/motion-core/pro';
26
+ *
27
+ * registerPlugin(motionProPlugin);
28
+ * ```
29
+ */
30
+ register(plugin: HuaUxPlugin): void;
31
+ /**
32
+ * 플러그인 초기화 / Initialize plugin
33
+ *
34
+ * 등록된 플러그인의 init 함수를 호출합니다.
35
+ * Calls the init function of registered plugins.
36
+ *
37
+ * @param pluginName - 플러그인 이름
38
+ * @param config - 프레임워크 설정
39
+ */
40
+ initialize(pluginName: string, config: any): Promise<void>;
41
+ /**
42
+ * 모든 플러그인 초기화 / Initialize all plugins
43
+ *
44
+ * @param config - 프레임워크 설정
45
+ */
46
+ initializeAll(config: any): Promise<void>;
47
+ /**
48
+ * 플러그인 가져오기 / Get plugin
49
+ *
50
+ * @param name - 플러그인 이름
51
+ * @returns 플러그인 또는 undefined
52
+ */
53
+ get(name: string): HuaUxPlugin | undefined;
54
+ /**
55
+ * 모든 플러그인 가져오기 / Get all plugins
56
+ *
57
+ * @returns 플러그인 배열
58
+ */
59
+ getAll(): HuaUxPlugin[];
60
+ /**
61
+ * 플러그인 등록 해제 / Unregister plugin
62
+ *
63
+ * @param name - 플러그인 이름
64
+ */
65
+ unregister(name: string): void;
66
+ /**
67
+ * 레지스트리 초기화 (테스트용) / Reset registry (for testing)
68
+ */
69
+ reset(): void;
70
+ }
71
+ /**
72
+ * 전역 플러그인 레지스트리 인스턴스 / Global plugin registry instance
73
+ */
74
+ export declare const pluginRegistry: PluginRegistry;
75
+ /**
76
+ * 플러그인 등록 (편의 함수) / Register plugin (convenience function)
77
+ *
78
+ * @param plugin - 등록할 플러그인
79
+ */
80
+ export declare function registerPlugin(plugin: HuaUxPlugin): void;
81
+ /**
82
+ * 플러그인 가져오기 (편의 함수) / Get plugin (convenience function)
83
+ *
84
+ * @param name - 플러그인 이름
85
+ * @returns 플러그인 또는 undefined
86
+ */
87
+ export declare function getPlugin(name: string): HuaUxPlugin | undefined;
88
+ /**
89
+ * 모든 플러그인 가져오기 (편의 함수) / Get all plugins (convenience function)
90
+ *
91
+ * @returns 플러그인 배열
92
+ */
93
+ export declare function getAllPlugins(): HuaUxPlugin[];
94
+ export {};
95
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../src/framework/plugins/registry.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAG3C;;;;;GAKG;AACH,cAAM,cAAc;IAClB,OAAO,CAAC,OAAO,CAAuC;IACtD,OAAO,CAAC,WAAW,CAA0B;IAE7C;;;;;;;;;;;;;OAaG;IACH,QAAQ,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI;IA4CnC;;;;;;;;OAQG;IACG,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;IAkBhE;;;;OAIG;IACG,aAAa,CAAC,MAAM,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;IAO/C;;;;;OAKG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS;IAI1C;;;;OAIG;IACH,MAAM,IAAI,WAAW,EAAE;IAIvB;;;;OAIG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAK9B;;OAEG;IACH,KAAK,IAAI,IAAI;CAId;AAED;;GAEG;AACH,eAAO,MAAM,cAAc,gBAAuB,CAAC;AAEnD;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAExD;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAE/D;AAED;;;;GAIG;AACH,wBAAgB,aAAa,IAAI,WAAW,EAAE,CAE7C"}