@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,74 @@
1
+ /**
2
+ * @hua-labs/hua-ux/framework - Data Fetching Utilities
3
+ *
4
+ * Type-safe data fetching utilities for server and client components
5
+ */
6
+ 'use client';
7
+ import React, { useState, useEffect } from 'react';
8
+ /**
9
+ * Client-side data fetching hook
10
+ *
11
+ * @example
12
+ * ```tsx
13
+ * function MyComponent() {
14
+ * const { data, isLoading, error } = useData<Post[]>('/api/posts');
15
+ *
16
+ * if (isLoading) return <Spinner />;
17
+ * if (error) return <Error message={error.message} />;
18
+ * return <PostList posts={data} />;
19
+ * }
20
+ * ```
21
+ */
22
+ export function useData(url, options) {
23
+ const [data, setData] = useState(null);
24
+ const [isLoading, setIsLoading] = useState(true);
25
+ const [error, setError] = useState(null);
26
+ const fetchData = React.useCallback(async () => {
27
+ try {
28
+ setIsLoading(true);
29
+ setError(null);
30
+ const response = await fetch(url, options);
31
+ if (!response.ok) {
32
+ throw new Error(`HTTP error! status: ${response.status}`);
33
+ }
34
+ const json = await response.json();
35
+ setData(json);
36
+ }
37
+ catch (err) {
38
+ setError(err instanceof Error ? err : new Error('Unknown error'));
39
+ }
40
+ finally {
41
+ setIsLoading(false);
42
+ }
43
+ }, [url, options]);
44
+ useEffect(() => {
45
+ fetchData();
46
+ }, [fetchData]);
47
+ return {
48
+ data,
49
+ isLoading,
50
+ error,
51
+ refetch: fetchData,
52
+ };
53
+ }
54
+ /**
55
+ * Server-side data fetching utility
56
+ *
57
+ * @example
58
+ * ```tsx
59
+ * // app/page.tsx (Server Component)
60
+ * import { fetchData } from '@hua-labs/hua-ux/framework';
61
+ *
62
+ * export default async function HomePage() {
63
+ * const posts = await fetchData<Post[]>('/api/posts');
64
+ * return <PostList posts={posts} />;
65
+ * }
66
+ * ```
67
+ */
68
+ export async function fetchData(url, options) {
69
+ const response = await fetch(url, options);
70
+ if (!response.ok) {
71
+ throw new Error(`HTTP error! status: ${response.status}`);
72
+ }
73
+ return response.json();
74
+ }
@@ -0,0 +1,29 @@
1
+ /**
2
+ * @hua-labs/hua-ux/framework - File Structure Validation
3
+ *
4
+ * Validates project file structure according to framework conventions
5
+ *
6
+ * **서버 전용**: 이 모듈은 Node.js 환경에서만 사용 가능합니다.
7
+ * **Server Only**: This module is only available in Node.js environment.
8
+ */
9
+ /**
10
+ * File structure validation result
11
+ */
12
+ export interface FileStructureResult {
13
+ valid: boolean;
14
+ missing: string[];
15
+ warnings: string[];
16
+ }
17
+ /**
18
+ * Validate project file structure
19
+ *
20
+ * @example
21
+ * ```ts
22
+ * const result = validateFileStructure(process.cwd());
23
+ * if (!result.valid) {
24
+ * console.error('Missing directories:', result.missing);
25
+ * }
26
+ * ```
27
+ */
28
+ export declare function validateFileStructure(projectRoot: string): FileStructureResult;
29
+ //# sourceMappingURL=file-structure.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-structure.d.ts","sourceRoot":"","sources":["../../../src/framework/utils/file-structure.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAmCH;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,mBAAmB,CAyB9E"}
@@ -0,0 +1,72 @@
1
+ /**
2
+ * @hua-labs/hua-ux/framework - File Structure Validation
3
+ *
4
+ * Validates project file structure according to framework conventions
5
+ *
6
+ * **서버 전용**: 이 모듈은 Node.js 환경에서만 사용 가능합니다.
7
+ * **Server Only**: This module is only available in Node.js environment.
8
+ */
9
+ // 서버 환경에서만 fs 사용
10
+ let existsSync;
11
+ let join;
12
+ if (typeof window === 'undefined' && typeof require !== 'undefined') {
13
+ // Node.js 환경
14
+ const fs = require('fs');
15
+ const path = require('path');
16
+ existsSync = fs.existsSync;
17
+ join = path.join;
18
+ }
19
+ else {
20
+ // 클라이언트 환경: 더미 함수 (사용 시 에러)
21
+ existsSync = () => {
22
+ throw new Error('validateFileStructure is only available in Node.js environment');
23
+ };
24
+ join = (...args) => args.join('/');
25
+ }
26
+ /**
27
+ * Expected directory structure
28
+ */
29
+ const REQUIRED_DIRS = [
30
+ 'app',
31
+ 'components',
32
+ 'lib',
33
+ ];
34
+ const OPTIONAL_DIRS = [
35
+ 'hooks',
36
+ 'store',
37
+ 'translations',
38
+ ];
39
+ /**
40
+ * Validate project file structure
41
+ *
42
+ * @example
43
+ * ```ts
44
+ * const result = validateFileStructure(process.cwd());
45
+ * if (!result.valid) {
46
+ * console.error('Missing directories:', result.missing);
47
+ * }
48
+ * ```
49
+ */
50
+ export function validateFileStructure(projectRoot) {
51
+ const missing = [];
52
+ const warnings = [];
53
+ // Check required directories
54
+ for (const dir of REQUIRED_DIRS) {
55
+ const dirPath = join(projectRoot, dir);
56
+ if (!existsSync(dirPath)) {
57
+ missing.push(dir);
58
+ }
59
+ }
60
+ // Check optional directories (warnings only)
61
+ for (const dir of OPTIONAL_DIRS) {
62
+ const dirPath = join(projectRoot, dir);
63
+ if (!existsSync(dirPath)) {
64
+ warnings.push(`Optional directory "${dir}" not found`);
65
+ }
66
+ }
67
+ return {
68
+ valid: missing.length === 0,
69
+ missing,
70
+ warnings,
71
+ };
72
+ }
@@ -0,0 +1,109 @@
1
+ /**
2
+ * @hua-labs/hua-ux/framework - Metadata Utilities
3
+ *
4
+ * Next.js Metadata 생성 유틸리티 (Next.js 없이도 사용 가능)
5
+ *
6
+ * Next.js가 설치되어 있으면 Next.js Metadata 타입을 사용하고,
7
+ * 없으면 일반 메타데이터 객체 타입을 사용합니다.
8
+ *
9
+ * Works with or without Next.js:
10
+ * - With Next.js: Returns Next.js Metadata type
11
+ * - Without Next.js: Returns generic metadata object type
12
+ */
13
+ type MetadataType = typeof import('next') extends {
14
+ Metadata: infer T;
15
+ } ? T : {
16
+ title?: string;
17
+ description?: string;
18
+ keywords?: string[];
19
+ openGraph?: {
20
+ title?: string;
21
+ description?: string;
22
+ type?: 'website' | 'article' | 'product';
23
+ images?: Array<{
24
+ url: string;
25
+ }>;
26
+ };
27
+ twitter?: {
28
+ card?: 'summary' | 'summary_large_image';
29
+ title?: string;
30
+ description?: string;
31
+ images?: string[];
32
+ };
33
+ };
34
+ /**
35
+ * SEO 설정 타입
36
+ */
37
+ export interface SEOConfig {
38
+ keywords?: string[];
39
+ ogImage?: string;
40
+ ogTitle?: string;
41
+ ogDescription?: string;
42
+ ogType?: 'website' | 'article' | 'product';
43
+ }
44
+ /**
45
+ * 페이지 메타데이터 생성
46
+ *
47
+ * Next.js App Router의 `export const metadata`에서 사용할 수 있는 메타데이터를 생성합니다.
48
+ * CRA/Vite 등 일반 React 앱에서도 사용 가능합니다 (React Helmet 등과 함께).
49
+ *
50
+ * Generates metadata that can be used in Next.js App Router's `export const metadata`.
51
+ * Also works in plain React apps (CRA/Vite) with React Helmet, etc.
52
+ *
53
+ * @param options - 메타데이터 옵션
54
+ * @param options.title - 페이지 제목
55
+ * @param options.description - 페이지 설명
56
+ * @param options.seo - SEO 설정 (선택적)
57
+ * @returns Next.js Metadata 객체 (Next.js가 있으면) 또는 일반 메타데이터 객체 (없으면)
58
+ *
59
+ * @example
60
+ * ```tsx
61
+ * // Next.js App Router
62
+ * // app/page.tsx
63
+ * import { generatePageMetadata } from '@hua-labs/hua-ux/framework';
64
+ *
65
+ * export const metadata = generatePageMetadata({
66
+ * title: '홈',
67
+ * description: '환영합니다',
68
+ * seo: {
69
+ * keywords: ['키워드1', '키워드2'],
70
+ * ogImage: '/og-image.png',
71
+ * },
72
+ * });
73
+ *
74
+ * export default function HomePage() {
75
+ * return <div>...</div>;
76
+ * }
77
+ * ```
78
+ *
79
+ * @example
80
+ * ```tsx
81
+ * // CRA/Vite (React Helmet 사용)
82
+ * import { Helmet } from 'react-helmet-async';
83
+ * import { generatePageMetadata } from '@hua-labs/hua-ux/framework';
84
+ *
85
+ * export default function HomePage() {
86
+ * const metadata = generatePageMetadata({
87
+ * title: 'Home',
88
+ * description: 'Welcome',
89
+ * });
90
+ *
91
+ * return (
92
+ * <>
93
+ * <Helmet>
94
+ * <title>{metadata.title}</title>
95
+ * <meta name="description" content={metadata.description} />
96
+ * </Helmet>
97
+ * <div>...</div>
98
+ * </>
99
+ * );
100
+ * }
101
+ * ```
102
+ */
103
+ export declare function generatePageMetadata(options: {
104
+ title: string;
105
+ description?: string;
106
+ seo?: SEOConfig;
107
+ }): MetadataType;
108
+ export {};
109
+ //# sourceMappingURL=metadata.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metadata.d.ts","sourceRoot":"","sources":["../../../src/framework/utils/metadata.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,KAAK,YAAY,GAGf,cAAc,MAAM,CAAC,SAAS;IAAE,QAAQ,EAAE,MAAM,CAAC,CAAA;CAAE,GAAG,CAAC,GAGrD;IACE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,SAAS,CAAC,EAAE;QACV,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,IAAI,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;QACzC,MAAM,CAAC,EAAE,KAAK,CAAC;YAAE,GAAG,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;KACjC,CAAC;IACF,OAAO,CAAC,EAAE;QACR,IAAI,CAAC,EAAE,SAAS,GAAG,qBAAqB,CAAC;QACzC,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;KACnB,CAAC;CACH,CAAC;AAEN;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;CAC5C;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0DG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE;IAC5C,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,GAAG,CAAC,EAAE,SAAS,CAAC;CACjB,GAAG,YAAY,CAsCf"}
@@ -0,0 +1,105 @@
1
+ /**
2
+ * @hua-labs/hua-ux/framework - Metadata Utilities
3
+ *
4
+ * Next.js Metadata 생성 유틸리티 (Next.js 없이도 사용 가능)
5
+ *
6
+ * Next.js가 설치되어 있으면 Next.js Metadata 타입을 사용하고,
7
+ * 없으면 일반 메타데이터 객체 타입을 사용합니다.
8
+ *
9
+ * Works with or without Next.js:
10
+ * - With Next.js: Returns Next.js Metadata type
11
+ * - Without Next.js: Returns generic metadata object type
12
+ */
13
+ /**
14
+ * 페이지 메타데이터 생성
15
+ *
16
+ * Next.js App Router의 `export const metadata`에서 사용할 수 있는 메타데이터를 생성합니다.
17
+ * CRA/Vite 등 일반 React 앱에서도 사용 가능합니다 (React Helmet 등과 함께).
18
+ *
19
+ * Generates metadata that can be used in Next.js App Router's `export const metadata`.
20
+ * Also works in plain React apps (CRA/Vite) with React Helmet, etc.
21
+ *
22
+ * @param options - 메타데이터 옵션
23
+ * @param options.title - 페이지 제목
24
+ * @param options.description - 페이지 설명
25
+ * @param options.seo - SEO 설정 (선택적)
26
+ * @returns Next.js Metadata 객체 (Next.js가 있으면) 또는 일반 메타데이터 객체 (없으면)
27
+ *
28
+ * @example
29
+ * ```tsx
30
+ * // Next.js App Router
31
+ * // app/page.tsx
32
+ * import { generatePageMetadata } from '@hua-labs/hua-ux/framework';
33
+ *
34
+ * export const metadata = generatePageMetadata({
35
+ * title: '홈',
36
+ * description: '환영합니다',
37
+ * seo: {
38
+ * keywords: ['키워드1', '키워드2'],
39
+ * ogImage: '/og-image.png',
40
+ * },
41
+ * });
42
+ *
43
+ * export default function HomePage() {
44
+ * return <div>...</div>;
45
+ * }
46
+ * ```
47
+ *
48
+ * @example
49
+ * ```tsx
50
+ * // CRA/Vite (React Helmet 사용)
51
+ * import { Helmet } from 'react-helmet-async';
52
+ * import { generatePageMetadata } from '@hua-labs/hua-ux/framework';
53
+ *
54
+ * export default function HomePage() {
55
+ * const metadata = generatePageMetadata({
56
+ * title: 'Home',
57
+ * description: 'Welcome',
58
+ * });
59
+ *
60
+ * return (
61
+ * <>
62
+ * <Helmet>
63
+ * <title>{metadata.title}</title>
64
+ * <meta name="description" content={metadata.description} />
65
+ * </Helmet>
66
+ * <div>...</div>
67
+ * </>
68
+ * );
69
+ * }
70
+ * ```
71
+ */
72
+ export function generatePageMetadata(options) {
73
+ const { title, description, seo } = options;
74
+ // 메타데이터 객체 직접 구성 (타입 안전하게)
75
+ // Build metadata object directly (type-safe)
76
+ const metadata = {
77
+ title,
78
+ description,
79
+ };
80
+ // Keywords 추가
81
+ if (seo?.keywords && seo.keywords.length > 0) {
82
+ metadata.keywords = seo.keywords;
83
+ }
84
+ // Open Graph 메타데이터
85
+ if (seo?.ogImage || seo?.ogTitle || seo?.ogDescription || seo?.ogType) {
86
+ metadata.openGraph = {
87
+ title: seo.ogTitle || title,
88
+ description: seo.ogDescription || description,
89
+ type: seo.ogType || 'website',
90
+ ...(seo.ogImage && { images: [{ url: seo.ogImage }] }),
91
+ };
92
+ }
93
+ // Twitter Card 메타데이터 (Open Graph가 있으면 자동으로 사용)
94
+ if (seo?.ogImage) {
95
+ metadata.twitter = {
96
+ card: 'summary_large_image',
97
+ ...(seo.ogTitle && { title: seo.ogTitle }),
98
+ ...(seo.ogDescription && { description: seo.ogDescription }),
99
+ ...(seo.ogImage && { images: [seo.ogImage] }),
100
+ };
101
+ }
102
+ // MetadataType으로 타입 단언 (조건부 타입이 컴파일 타임에 올바르게 추론됨)
103
+ // Type assertion to MetadataType (conditional type is correctly inferred at compile time)
104
+ return metadata;
105
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * @hua-labs/hua-ux
3
+ *
4
+ * Ship UX faster: UI + motion + i18n, pre-wired.
5
+ * A framework for React product teams.
6
+ */
7
+ export * from '@hua-labs/ui';
8
+ export { BrandedButton as Button, BrandedCard as Card } from './framework';
9
+ export type { ButtonProps } from '@hua-labs/ui';
10
+ export type { CardProps, CardHeaderProps, CardTitleProps, CardDescriptionProps, CardContentProps, CardFooterProps } from '@hua-labs/ui';
11
+ export * from '@hua-labs/motion-core';
12
+ export * from '@hua-labs/i18n-core';
13
+ export * from '@hua-labs/i18n-core-zustand';
14
+ export * from '@hua-labs/state';
15
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,cAAc,cAAc,CAAA;AAK5B,OAAO,EAAE,aAAa,IAAI,MAAM,EAAE,WAAW,IAAI,IAAI,EAAE,MAAM,aAAa,CAAA;AAG1E,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAC/C,YAAY,EAAE,SAAS,EAAE,eAAe,EAAE,cAAc,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAGvI,cAAc,uBAAuB,CAAA;AAGrC,cAAc,qBAAqB,CAAA;AAGnC,cAAc,6BAA6B,CAAA;AAG3C,cAAc,iBAAiB,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,21 @@
1
+ /**
2
+ * @hua-labs/hua-ux
3
+ *
4
+ * Ship UX faster: UI + motion + i18n, pre-wired.
5
+ * A framework for React product teams.
6
+ */
7
+ // Re-export UI components
8
+ // Note: Button and Card are overridden below with branded versions
9
+ export * from '@hua-labs/ui';
10
+ // Override Button and Card with branded versions for automatic branding
11
+ // When branding is configured, these components automatically use branding colors
12
+ // When branding is not configured, they work exactly like the original components
13
+ export { BrandedButton as Button, BrandedCard as Card } from './framework';
14
+ // Re-export Motion hooks
15
+ export * from '@hua-labs/motion-core';
16
+ // Re-export i18n core
17
+ export * from '@hua-labs/i18n-core';
18
+ // Re-export i18n Zustand adapter
19
+ export * from '@hua-labs/i18n-core-zustand';
20
+ // Re-export state management
21
+ export * from '@hua-labs/state';
@@ -0,0 +1,8 @@
1
+ /**
2
+ * HUA UX Presets
3
+ *
4
+ * Pre-configured settings for common use cases
5
+ */
6
+ export * from './product';
7
+ export * from './marketing';
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/presets/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,WAAW,CAAA;AACzB,cAAc,aAAa,CAAA"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * HUA UX Presets
3
+ *
4
+ * Pre-configured settings for common use cases
5
+ */
6
+ export * from './product';
7
+ export * from './marketing';
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Marketing Preset
3
+ *
4
+ * 랜딩 페이지 모션 중심 설정
5
+ * 마케팅 페이지, 랜딩 페이지에 적합
6
+ */
7
+ import type { PresetConfig } from '@hua-labs/motion-core';
8
+ /**
9
+ * Marketing Preset Configuration
10
+ *
11
+ * - 드라마틱한 모션 (느린 전환, 긴 딜레이)
12
+ * - 넓은 스페이싱 (xl 기본값)
13
+ * - 호버/클릭 인터랙션 강조
14
+ */
15
+ export declare const marketingPreset: {
16
+ /**
17
+ * Motion Presets for Marketing UI
18
+ */
19
+ readonly motion: PresetConfig;
20
+ /**
21
+ * Spacing Guidelines
22
+ *
23
+ * - 기본 스페이싱: xl (24px)
24
+ * - 섹션 간격: xl (32px+)
25
+ * - 컴포넌트 내부: md (8px)
26
+ */
27
+ readonly spacing: {
28
+ readonly default: "xl";
29
+ readonly section: "xl";
30
+ readonly component: "md";
31
+ };
32
+ /**
33
+ * i18n Configuration
34
+ */
35
+ readonly i18n: {
36
+ readonly defaultLanguage: "ko";
37
+ readonly supportedLanguages: readonly ["ko", "en"];
38
+ };
39
+ };
40
+ export type MarketingPreset = typeof marketingPreset;
41
+ //# sourceMappingURL=marketing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"marketing.d.ts","sourceRoot":"","sources":["../../src/presets/marketing.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAgB,YAAY,EAAE,MAAM,uBAAuB,CAAA;AAEvE;;;;;;GAMG;AACH,eAAO,MAAM,eAAe;IAC1B;;OAEG;qBA4CE,YAAY;IAEjB;;;;;;OAMG;;;;;;IAOH;;OAEG;;;;;CAKK,CAAA;AAEV,MAAM,MAAM,eAAe,GAAG,OAAO,eAAe,CAAA"}
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Marketing Preset
3
+ *
4
+ * 랜딩 페이지 모션 중심 설정
5
+ * 마케팅 페이지, 랜딩 페이지에 적합
6
+ */
7
+ /**
8
+ * Marketing Preset Configuration
9
+ *
10
+ * - 드라마틱한 모션 (느린 전환, 긴 딜레이)
11
+ * - 넓은 스페이싱 (xl 기본값)
12
+ * - 호버/클릭 인터랙션 강조
13
+ */
14
+ export const marketingPreset = {
15
+ /**
16
+ * Motion Presets for Marketing UI
17
+ */
18
+ motion: {
19
+ hero: {
20
+ entrance: 'fadeIn',
21
+ delay: 300,
22
+ duration: 1000,
23
+ hover: false,
24
+ click: false
25
+ },
26
+ title: {
27
+ entrance: 'slideUp',
28
+ delay: 500,
29
+ duration: 800,
30
+ hover: false,
31
+ click: false
32
+ },
33
+ button: {
34
+ entrance: 'scaleIn',
35
+ delay: 700,
36
+ duration: 400,
37
+ hover: true,
38
+ click: true
39
+ },
40
+ card: {
41
+ entrance: 'slideUp',
42
+ delay: 600,
43
+ duration: 600,
44
+ hover: true,
45
+ click: false
46
+ },
47
+ text: {
48
+ entrance: 'fadeIn',
49
+ delay: 400,
50
+ duration: 700,
51
+ hover: false,
52
+ click: false
53
+ },
54
+ image: {
55
+ entrance: 'scaleIn',
56
+ delay: 500,
57
+ duration: 800,
58
+ hover: true,
59
+ click: false
60
+ }
61
+ },
62
+ /**
63
+ * Spacing Guidelines
64
+ *
65
+ * - 기본 스페이싱: xl (24px)
66
+ * - 섹션 간격: xl (32px+)
67
+ * - 컴포넌트 내부: md (8px)
68
+ */
69
+ spacing: {
70
+ default: 'xl',
71
+ section: 'xl',
72
+ component: 'md'
73
+ },
74
+ /**
75
+ * i18n Configuration
76
+ */
77
+ i18n: {
78
+ defaultLanguage: 'ko',
79
+ supportedLanguages: ['ko', 'en']
80
+ }
81
+ };
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Product Preset
3
+ *
4
+ * 기본 여백 + 기본 모션 설정
5
+ * 제품 페이지, 대시보드 등 일반적인 제품 UI에 적합
6
+ */
7
+ import type { PresetConfig } from '@hua-labs/motion-core';
8
+ /**
9
+ * Product Preset Configuration
10
+ *
11
+ * - 보수적인 모션 (빠른 전환, 최소한의 딜레이)
12
+ * - 일관된 스페이싱 (md 기본값)
13
+ * - 호버/클릭 인터랙션 최소화
14
+ */
15
+ export declare const productPreset: {
16
+ /**
17
+ * Motion Presets for Product UI
18
+ */
19
+ readonly motion: PresetConfig;
20
+ /**
21
+ * Spacing Guidelines
22
+ *
23
+ * - 기본 스페이싱: md (8px)
24
+ * - 섹션 간격: lg (16px)
25
+ * - 컴포넌트 내부: sm (4px)
26
+ */
27
+ readonly spacing: {
28
+ readonly default: "md";
29
+ readonly section: "lg";
30
+ readonly component: "sm";
31
+ };
32
+ /**
33
+ * i18n Configuration
34
+ */
35
+ readonly i18n: {
36
+ readonly defaultLanguage: "ko";
37
+ readonly supportedLanguages: readonly ["ko", "en"];
38
+ };
39
+ };
40
+ export type ProductPreset = typeof productPreset;
41
+ //# sourceMappingURL=product.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"product.d.ts","sourceRoot":"","sources":["../../src/presets/product.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAgB,YAAY,EAAE,MAAM,uBAAuB,CAAA;AAEvE;;;;;;GAMG;AACH,eAAO,MAAM,aAAa;IACxB;;OAEG;qBAqCE,YAAY;IAEjB;;;;;;OAMG;;;;;;IAOH;;OAEG;;;;;CAKK,CAAA;AAEV,MAAM,MAAM,aAAa,GAAG,OAAO,aAAa,CAAA"}