@hua-labs/hua-ux 0.1.0-alpha.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +839 -0
- package/dist/framework/a11y/components/LiveRegion.d.ts +64 -0
- package/dist/framework/a11y/components/LiveRegion.d.ts.map +1 -0
- package/dist/framework/a11y/components/LiveRegion.js +43 -0
- package/dist/framework/a11y/components/SkipToContent.d.ts +62 -0
- package/dist/framework/a11y/components/SkipToContent.d.ts.map +1 -0
- package/dist/framework/a11y/components/SkipToContent.js +60 -0
- package/dist/framework/a11y/hooks/useFocusManagement.d.ts +60 -0
- package/dist/framework/a11y/hooks/useFocusManagement.d.ts.map +1 -0
- package/dist/framework/a11y/hooks/useFocusManagement.js +71 -0
- package/dist/framework/a11y/hooks/useFocusTrap.d.ts +64 -0
- package/dist/framework/a11y/hooks/useFocusTrap.d.ts.map +1 -0
- package/dist/framework/a11y/hooks/useFocusTrap.js +185 -0
- package/dist/framework/a11y/hooks/useLiveRegion.d.ts +56 -0
- package/dist/framework/a11y/hooks/useLiveRegion.d.ts.map +1 -0
- package/dist/framework/a11y/hooks/useLiveRegion.js +60 -0
- package/dist/framework/a11y/index.d.ts +16 -0
- package/dist/framework/a11y/index.d.ts.map +1 -0
- package/dist/framework/a11y/index.js +11 -0
- package/dist/framework/branding/context.d.ts +52 -0
- package/dist/framework/branding/context.d.ts.map +1 -0
- package/dist/framework/branding/context.js +96 -0
- package/dist/framework/branding/css-vars.d.ts +34 -0
- package/dist/framework/branding/css-vars.d.ts.map +1 -0
- package/dist/framework/branding/css-vars.js +95 -0
- package/dist/framework/branding/tailwind-config.d.ts +38 -0
- package/dist/framework/branding/tailwind-config.d.ts.map +1 -0
- package/dist/framework/branding/tailwind-config.js +66 -0
- package/dist/framework/components/BrandedButton.d.ts +53 -0
- package/dist/framework/components/BrandedButton.d.ts.map +1 -0
- package/dist/framework/components/BrandedButton.js +40 -0
- package/dist/framework/components/BrandedCard.d.ts +52 -0
- package/dist/framework/components/BrandedCard.d.ts.map +1 -0
- package/dist/framework/components/BrandedCard.js +73 -0
- package/dist/framework/components/ErrorBoundary.d.ts +92 -0
- package/dist/framework/components/ErrorBoundary.d.ts.map +1 -0
- package/dist/framework/components/ErrorBoundary.js +121 -0
- package/dist/framework/components/HuaUxLayout.d.ts +29 -0
- package/dist/framework/components/HuaUxLayout.d.ts.map +1 -0
- package/dist/framework/components/HuaUxLayout.js +32 -0
- package/dist/framework/components/HuaUxPage.d.ts +48 -0
- package/dist/framework/components/HuaUxPage.d.ts.map +1 -0
- package/dist/framework/components/HuaUxPage.js +105 -0
- package/dist/framework/components/Providers.d.ts +17 -0
- package/dist/framework/components/Providers.d.ts.map +1 -0
- package/dist/framework/components/Providers.js +72 -0
- package/dist/framework/components/WelcomePage.d.ts +44 -0
- package/dist/framework/components/WelcomePage.d.ts.map +1 -0
- package/dist/framework/components/WelcomePage.js +80 -0
- package/dist/framework/config/index.d.ts +182 -0
- package/dist/framework/config/index.d.ts.map +1 -0
- package/dist/framework/config/index.js +329 -0
- package/dist/framework/config/merge.d.ts +26 -0
- package/dist/framework/config/merge.d.ts.map +1 -0
- package/dist/framework/config/merge.js +160 -0
- package/dist/framework/config/schema.d.ts +25 -0
- package/dist/framework/config/schema.d.ts.map +1 -0
- package/dist/framework/config/schema.js +122 -0
- package/dist/framework/hooks/useMotion.d.ts +45 -0
- package/dist/framework/hooks/useMotion.d.ts.map +1 -0
- package/dist/framework/hooks/useMotion.js +40 -0
- package/dist/framework/index.d.ts +37 -0
- package/dist/framework/index.d.ts.map +1 -0
- package/dist/framework/index.js +42 -0
- package/dist/framework/license/errors.d.ts +15 -0
- package/dist/framework/license/errors.d.ts.map +1 -0
- package/dist/framework/license/errors.js +52 -0
- package/dist/framework/license/index.d.ts +70 -0
- package/dist/framework/license/index.d.ts.map +1 -0
- package/dist/framework/license/index.js +124 -0
- package/dist/framework/license/loader.d.ts +26 -0
- package/dist/framework/license/loader.d.ts.map +1 -0
- package/dist/framework/license/loader.js +137 -0
- package/dist/framework/license/types.d.ts +67 -0
- package/dist/framework/license/types.d.ts.map +1 -0
- package/dist/framework/license/types.js +18 -0
- package/dist/framework/loading/components/SkeletonGroup.d.ts +44 -0
- package/dist/framework/loading/components/SkeletonGroup.d.ts.map +1 -0
- package/dist/framework/loading/components/SkeletonGroup.js +34 -0
- package/dist/framework/loading/components/SuspenseWrapper.d.ts +58 -0
- package/dist/framework/loading/components/SuspenseWrapper.d.ts.map +1 -0
- package/dist/framework/loading/components/SuspenseWrapper.js +40 -0
- package/dist/framework/loading/hoc/withSuspense.d.ts +46 -0
- package/dist/framework/loading/hoc/withSuspense.d.ts.map +1 -0
- package/dist/framework/loading/hoc/withSuspense.js +54 -0
- package/dist/framework/loading/hooks/useDelayedLoading.d.ts +56 -0
- package/dist/framework/loading/hooks/useDelayedLoading.d.ts.map +1 -0
- package/dist/framework/loading/hooks/useDelayedLoading.js +97 -0
- package/dist/framework/loading/hooks/useLoadingState.d.ts +69 -0
- package/dist/framework/loading/hooks/useLoadingState.d.ts.map +1 -0
- package/dist/framework/loading/hooks/useLoadingState.js +59 -0
- package/dist/framework/loading/index.d.ts +16 -0
- package/dist/framework/loading/index.d.ts.map +1 -0
- package/dist/framework/loading/index.js +13 -0
- package/dist/framework/middleware/i18n.d.ts +90 -0
- package/dist/framework/middleware/i18n.d.ts.map +1 -0
- package/dist/framework/middleware/i18n.js +99 -0
- package/dist/framework/plugins/index.d.ts +8 -0
- package/dist/framework/plugins/index.d.ts.map +1 -0
- package/dist/framework/plugins/index.js +6 -0
- package/dist/framework/plugins/registry.d.ts +95 -0
- package/dist/framework/plugins/registry.d.ts.map +1 -0
- package/dist/framework/plugins/registry.js +160 -0
- package/dist/framework/plugins/types.d.ts +97 -0
- package/dist/framework/plugins/types.d.ts.map +1 -0
- package/dist/framework/plugins/types.js +6 -0
- package/dist/framework/seo/geo/examples.d.ts +87 -0
- package/dist/framework/seo/geo/examples.d.ts.map +1 -0
- package/dist/framework/seo/geo/examples.js +295 -0
- package/dist/framework/seo/geo/generateGEOMetadata.d.ts +107 -0
- package/dist/framework/seo/geo/generateGEOMetadata.d.ts.map +1 -0
- package/dist/framework/seo/geo/generateGEOMetadata.js +404 -0
- package/dist/framework/seo/geo/index.d.ts +19 -0
- package/dist/framework/seo/geo/index.d.ts.map +1 -0
- package/dist/framework/seo/geo/index.js +21 -0
- package/dist/framework/seo/geo/presets.d.ts +52 -0
- package/dist/framework/seo/geo/presets.d.ts.map +1 -0
- package/dist/framework/seo/geo/presets.js +47 -0
- package/dist/framework/seo/geo/structuredData.d.ts +187 -0
- package/dist/framework/seo/geo/structuredData.d.ts.map +1 -0
- package/dist/framework/seo/geo/structuredData.js +354 -0
- package/dist/framework/seo/geo/test-utils.d.ts +78 -0
- package/dist/framework/seo/geo/test-utils.d.ts.map +1 -0
- package/dist/framework/seo/geo/test-utils.js +139 -0
- package/dist/framework/seo/geo/types.d.ts +225 -0
- package/dist/framework/seo/geo/types.d.ts.map +1 -0
- package/dist/framework/seo/geo/types.js +51 -0
- package/dist/framework/types/index.d.ts +577 -0
- package/dist/framework/types/index.d.ts.map +1 -0
- package/dist/framework/types/index.js +6 -0
- package/dist/framework/utils/data-fetching.d.ts +45 -0
- package/dist/framework/utils/data-fetching.d.ts.map +1 -0
- package/dist/framework/utils/data-fetching.js +74 -0
- package/dist/framework/utils/file-structure.d.ts +29 -0
- package/dist/framework/utils/file-structure.d.ts.map +1 -0
- package/dist/framework/utils/file-structure.js +72 -0
- package/dist/framework/utils/metadata.d.ts +109 -0
- package/dist/framework/utils/metadata.d.ts.map +1 -0
- package/dist/framework/utils/metadata.js +105 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +21 -0
- package/dist/presets/index.d.ts +8 -0
- package/dist/presets/index.d.ts.map +1 -0
- package/dist/presets/index.js +7 -0
- package/dist/presets/marketing.d.ts +41 -0
- package/dist/presets/marketing.d.ts.map +1 -0
- package/dist/presets/marketing.js +81 -0
- package/dist/presets/product.d.ts +41 -0
- package/dist/presets/product.d.ts.map +1 -0
- package/dist/presets/product.js +74 -0
- package/package.json +91 -0
- package/src/framework/README.md +329 -0
- package/src/framework/__tests__/branding/css-vars.test.ts +147 -0
- package/src/framework/__tests__/components/ErrorBoundary.test.tsx +146 -0
- package/src/framework/__tests__/config/defineConfig.test.ts +138 -0
- package/src/framework/__tests__/hooks/useMotion.test.ts +105 -0
- package/src/framework/__tests__/seo/geo/generateGEOMetadata.test.ts +207 -0
- package/src/framework/__tests__/seo/geo/structuredData.test.ts +262 -0
- package/src/framework/a11y/components/LiveRegion.tsx +89 -0
- package/src/framework/a11y/components/SkipToContent.tsx +103 -0
- package/src/framework/a11y/hooks/useFocusManagement.ts +125 -0
- package/src/framework/a11y/hooks/useFocusTrap.ts +239 -0
- package/src/framework/a11y/hooks/useLiveRegion.ts +95 -0
- package/src/framework/a11y/index.ts +17 -0
- package/src/framework/branding/context.tsx +135 -0
- package/src/framework/branding/css-vars.ts +110 -0
- package/src/framework/branding/tailwind-config.ts +90 -0
- package/src/framework/components/BrandedButton.tsx +94 -0
- package/src/framework/components/BrandedCard.tsx +87 -0
- package/src/framework/components/ErrorBoundary.tsx +215 -0
- package/src/framework/components/HuaUxLayout.tsx +36 -0
- package/src/framework/components/HuaUxPage.tsx +138 -0
- package/src/framework/components/Providers.tsx +98 -0
- package/src/framework/components/WelcomePage.tsx +207 -0
- package/src/framework/config/index.ts +349 -0
- package/src/framework/config/merge.ts +190 -0
- package/src/framework/config/schema.ts +140 -0
- package/src/framework/hooks/useMotion.ts +57 -0
- package/src/framework/index.ts +122 -0
- package/src/framework/license/errors.ts +63 -0
- package/src/framework/license/index.ts +137 -0
- package/src/framework/license/loader.ts +158 -0
- package/src/framework/license/types.ts +95 -0
- package/src/framework/loading/components/SkeletonGroup.tsx +70 -0
- package/src/framework/loading/components/SuspenseWrapper.tsx +88 -0
- package/src/framework/loading/hoc/withSuspense.tsx +96 -0
- package/src/framework/loading/hooks/useDelayedLoading.ts +127 -0
- package/src/framework/loading/hooks/useLoadingState.ts +103 -0
- package/src/framework/loading/index.ts +19 -0
- package/src/framework/middleware/i18n.ts +161 -0
- package/src/framework/middleware/index.ts +7 -0
- package/src/framework/plugins/index.ts +13 -0
- package/src/framework/plugins/registry.ts +186 -0
- package/src/framework/plugins/types.ts +106 -0
- package/src/framework/seo/geo/examples.tsx +415 -0
- package/src/framework/seo/geo/generateGEOMetadata.ts +441 -0
- package/src/framework/seo/geo/index.ts +61 -0
- package/src/framework/seo/geo/presets.ts +58 -0
- package/src/framework/seo/geo/structuredData.ts +422 -0
- package/src/framework/seo/geo/test-utils.ts +179 -0
- package/src/framework/seo/geo/types.ts +315 -0
- package/src/framework/types/index.ts +623 -0
- package/src/framework/utils/data-fetching.ts +95 -0
- package/src/framework/utils/file-structure.ts +88 -0
- package/src/framework/utils/metadata.ts +152 -0
- package/src/index.ts +31 -0
- package/src/presets/index.ts +8 -0
- package/src/presets/marketing.ts +88 -0
- package/src/presets/product.ts +81 -0
|
@@ -0,0 +1,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
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -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 @@
|
|
|
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,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"}
|