@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,160 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @hua-labs/hua-ux/framework - Plugin Registry
|
|
3
|
+
*
|
|
4
|
+
* 플러그인 등록 및 관리 시스템
|
|
5
|
+
*/
|
|
6
|
+
import { hasLicense } from '../license';
|
|
7
|
+
/**
|
|
8
|
+
* 플러그인 레지스트리 / Plugin registry
|
|
9
|
+
*
|
|
10
|
+
* 모든 플러그인을 등록하고 관리하는 싱글톤 클래스
|
|
11
|
+
* Singleton class that registers and manages all plugins
|
|
12
|
+
*/
|
|
13
|
+
class PluginRegistry {
|
|
14
|
+
constructor() {
|
|
15
|
+
this.plugins = new Map();
|
|
16
|
+
this.initialized = new Set();
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* 플러그인 등록 / Register plugin
|
|
20
|
+
*
|
|
21
|
+
* @param plugin - 등록할 플러그인
|
|
22
|
+
* @throws 라이선스가 없을 경우 에러
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```ts
|
|
26
|
+
* import { registerPlugin } from '@hua-labs/hua-ux/framework';
|
|
27
|
+
* import { motionProPlugin } from '@hua-labs/motion-core/pro';
|
|
28
|
+
*
|
|
29
|
+
* registerPlugin(motionProPlugin);
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
register(plugin) {
|
|
33
|
+
// 중복 등록 확인
|
|
34
|
+
if (this.plugins.has(plugin.name)) {
|
|
35
|
+
console.warn(`[hua-ux] Plugin "${plugin.name}" is already registered. Overwriting...`);
|
|
36
|
+
}
|
|
37
|
+
// 라이선스 검증
|
|
38
|
+
if (plugin.license !== 'free') {
|
|
39
|
+
// 플러그인의 checkLicense 함수가 있으면 사용
|
|
40
|
+
if (plugin.checkLicense) {
|
|
41
|
+
if (!plugin.checkLicense()) {
|
|
42
|
+
throw new Error(`[hua-ux] ❌ Plugin "${plugin.name}" requires a valid ${plugin.license} license.\n` +
|
|
43
|
+
`[hua-ux] ❌ Please purchase a ${plugin.license} license.\n\n` +
|
|
44
|
+
`💡 Purchase link: https://hua-labs.com/pricing`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
// 기본 라이선스 검증 (license feature 기반)
|
|
49
|
+
const feature = `plugin-${plugin.name}`;
|
|
50
|
+
if (!hasLicense(feature)) {
|
|
51
|
+
// 라이선스가 없어도 경고만 표시 (개발 환경)
|
|
52
|
+
if (process.env.NODE_ENV === 'development') {
|
|
53
|
+
console.warn(`[hua-ux] ⚠️ Plugin "${plugin.name}" may require a ${plugin.license} license.\n` +
|
|
54
|
+
`[hua-ux] ⚠️ Some features may not work without a valid license.`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
// 플러그인 등록
|
|
60
|
+
this.plugins.set(plugin.name, plugin);
|
|
61
|
+
if (process.env.NODE_ENV === 'development') {
|
|
62
|
+
console.log(`[hua-ux] ✅ Plugin "${plugin.name}" v${plugin.version} registered successfully`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* 플러그인 초기화 / Initialize plugin
|
|
67
|
+
*
|
|
68
|
+
* 등록된 플러그인의 init 함수를 호출합니다.
|
|
69
|
+
* Calls the init function of registered plugins.
|
|
70
|
+
*
|
|
71
|
+
* @param pluginName - 플러그인 이름
|
|
72
|
+
* @param config - 프레임워크 설정
|
|
73
|
+
*/
|
|
74
|
+
async initialize(pluginName, config) {
|
|
75
|
+
const plugin = this.plugins.get(pluginName);
|
|
76
|
+
if (!plugin) {
|
|
77
|
+
throw new Error(`[hua-ux] Plugin "${pluginName}" not found`);
|
|
78
|
+
}
|
|
79
|
+
// 이미 초기화된 경우 스킵
|
|
80
|
+
if (this.initialized.has(pluginName)) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
// init 함수 호출
|
|
84
|
+
if (plugin.init) {
|
|
85
|
+
await plugin.init(config);
|
|
86
|
+
this.initialized.add(pluginName);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* 모든 플러그인 초기화 / Initialize all plugins
|
|
91
|
+
*
|
|
92
|
+
* @param config - 프레임워크 설정
|
|
93
|
+
*/
|
|
94
|
+
async initializeAll(config) {
|
|
95
|
+
const promises = Array.from(this.plugins.keys()).map(name => this.initialize(name, config));
|
|
96
|
+
await Promise.all(promises);
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* 플러그인 가져오기 / Get plugin
|
|
100
|
+
*
|
|
101
|
+
* @param name - 플러그인 이름
|
|
102
|
+
* @returns 플러그인 또는 undefined
|
|
103
|
+
*/
|
|
104
|
+
get(name) {
|
|
105
|
+
return this.plugins.get(name);
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* 모든 플러그인 가져오기 / Get all plugins
|
|
109
|
+
*
|
|
110
|
+
* @returns 플러그인 배열
|
|
111
|
+
*/
|
|
112
|
+
getAll() {
|
|
113
|
+
return Array.from(this.plugins.values());
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* 플러그인 등록 해제 / Unregister plugin
|
|
117
|
+
*
|
|
118
|
+
* @param name - 플러그인 이름
|
|
119
|
+
*/
|
|
120
|
+
unregister(name) {
|
|
121
|
+
this.plugins.delete(name);
|
|
122
|
+
this.initialized.delete(name);
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* 레지스트리 초기화 (테스트용) / Reset registry (for testing)
|
|
126
|
+
*/
|
|
127
|
+
reset() {
|
|
128
|
+
this.plugins.clear();
|
|
129
|
+
this.initialized.clear();
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* 전역 플러그인 레지스트리 인스턴스 / Global plugin registry instance
|
|
134
|
+
*/
|
|
135
|
+
export const pluginRegistry = new PluginRegistry();
|
|
136
|
+
/**
|
|
137
|
+
* 플러그인 등록 (편의 함수) / Register plugin (convenience function)
|
|
138
|
+
*
|
|
139
|
+
* @param plugin - 등록할 플러그인
|
|
140
|
+
*/
|
|
141
|
+
export function registerPlugin(plugin) {
|
|
142
|
+
pluginRegistry.register(plugin);
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* 플러그인 가져오기 (편의 함수) / Get plugin (convenience function)
|
|
146
|
+
*
|
|
147
|
+
* @param name - 플러그인 이름
|
|
148
|
+
* @returns 플러그인 또는 undefined
|
|
149
|
+
*/
|
|
150
|
+
export function getPlugin(name) {
|
|
151
|
+
return pluginRegistry.get(name);
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* 모든 플러그인 가져오기 (편의 함수) / Get all plugins (convenience function)
|
|
155
|
+
*
|
|
156
|
+
* @returns 플러그인 배열
|
|
157
|
+
*/
|
|
158
|
+
export function getAllPlugins() {
|
|
159
|
+
return pluginRegistry.getAll();
|
|
160
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @hua-labs/hua-ux/framework - Plugin Types
|
|
3
|
+
*
|
|
4
|
+
* 플러그인 타입 정의
|
|
5
|
+
*/
|
|
6
|
+
import type { ComponentType } from 'react';
|
|
7
|
+
import type { HuaUxConfig } from '../types';
|
|
8
|
+
import type { LicenseType } from '../license/types';
|
|
9
|
+
/**
|
|
10
|
+
* 플러그인 인터페이스 / Plugin interface
|
|
11
|
+
*/
|
|
12
|
+
export interface HuaUxPlugin {
|
|
13
|
+
/**
|
|
14
|
+
* 플러그인 이름 / Plugin name
|
|
15
|
+
*
|
|
16
|
+
* 고유한 식별자로 사용됩니다.
|
|
17
|
+
* Used as a unique identifier.
|
|
18
|
+
*/
|
|
19
|
+
name: string;
|
|
20
|
+
/**
|
|
21
|
+
* 플러그인 버전 / Plugin version
|
|
22
|
+
*
|
|
23
|
+
* Semantic versioning 형식 (예: '1.0.0')
|
|
24
|
+
* Semantic versioning format (e.g., '1.0.0')
|
|
25
|
+
*/
|
|
26
|
+
version: string;
|
|
27
|
+
/**
|
|
28
|
+
* 라이선스 타입 / License type
|
|
29
|
+
*
|
|
30
|
+
* 이 플러그인이 필요한 라이선스 타입
|
|
31
|
+
* Required license type for this plugin
|
|
32
|
+
*/
|
|
33
|
+
license: LicenseType;
|
|
34
|
+
/**
|
|
35
|
+
* 플러그인 초기화 / Plugin initialization
|
|
36
|
+
*
|
|
37
|
+
* 플러그인이 등록될 때 호출됩니다.
|
|
38
|
+
* Called when the plugin is registered.
|
|
39
|
+
*
|
|
40
|
+
* @param config - 프레임워크 설정
|
|
41
|
+
*/
|
|
42
|
+
init?(config: HuaUxConfig): void | Promise<void>;
|
|
43
|
+
/**
|
|
44
|
+
* 컴포넌트 확장 / Component extensions
|
|
45
|
+
*
|
|
46
|
+
* 플러그인이 제공하는 컴포넌트들
|
|
47
|
+
* Components provided by the plugin
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* ```ts
|
|
51
|
+
* components: {
|
|
52
|
+
* ParallaxScroll: ParallaxScrollComponent,
|
|
53
|
+
* Motion3D: Motion3DComponent,
|
|
54
|
+
* }
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
components?: Record<string, ComponentType<any>>;
|
|
58
|
+
/**
|
|
59
|
+
* 훅 확장 / Hook extensions
|
|
60
|
+
*
|
|
61
|
+
* 플러그인이 제공하는 커스텀 훅들
|
|
62
|
+
* Custom hooks provided by the plugin
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* ```ts
|
|
66
|
+
* hooks: {
|
|
67
|
+
* useParallax: useParallaxHook,
|
|
68
|
+
* useMotion3D: useMotion3DHook,
|
|
69
|
+
* }
|
|
70
|
+
* ```
|
|
71
|
+
*/
|
|
72
|
+
hooks?: Record<string, Function>;
|
|
73
|
+
/**
|
|
74
|
+
* 설정 스키마 확장 / Config schema extension
|
|
75
|
+
*
|
|
76
|
+
* 플러그인이 추가하는 설정 스키마 (향후 Zod 스키마 지원)
|
|
77
|
+
* Additional config schema added by the plugin (future Zod schema support)
|
|
78
|
+
*/
|
|
79
|
+
configSchema?: any;
|
|
80
|
+
/**
|
|
81
|
+
* 라이선스 검증 / License validation
|
|
82
|
+
*
|
|
83
|
+
* 플러그인 등록 시 라이선스를 검증하는 함수
|
|
84
|
+
* Function to validate license when plugin is registered
|
|
85
|
+
*
|
|
86
|
+
* @returns 라이선스 유효 여부
|
|
87
|
+
*/
|
|
88
|
+
checkLicense?(): boolean;
|
|
89
|
+
/**
|
|
90
|
+
* 플러그인 설명 / Plugin description
|
|
91
|
+
*
|
|
92
|
+
* 플러그인의 기능 설명
|
|
93
|
+
* Description of plugin features
|
|
94
|
+
*/
|
|
95
|
+
description?: string;
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/framework/plugins/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAC3C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEpD;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B;;;;;OAKG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;;;;OAKG;IACH,OAAO,EAAE,MAAM,CAAC;IAEhB;;;;;OAKG;IACH,OAAO,EAAE,WAAW,CAAC;IAErB;;;;;;;OAOG;IACH,IAAI,CAAC,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjD;;;;;;;;;;;;;OAaG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC;IAEhD;;;;;;;;;;;;;OAaG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAEjC;;;;;OAKG;IACH,YAAY,CAAC,EAAE,GAAG,CAAC;IAEnB;;;;;;;OAOG;IACH,YAAY,CAAC,IAAI,OAAO,CAAC;IAEzB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @hua-labs/hua-ux/framework - GEO Usage Examples
|
|
3
|
+
*
|
|
4
|
+
* Examples of using GEO (Generative Engine Optimization) to make your
|
|
5
|
+
* application discoverable by AI search engines
|
|
6
|
+
*
|
|
7
|
+
* AI 검색 엔진이 애플리케이션을 잘 찾고 추천하도록 GEO 사용 예시
|
|
8
|
+
*
|
|
9
|
+
* These examples demonstrate various use cases including:
|
|
10
|
+
* - Basic GEO configuration
|
|
11
|
+
* - Using presets
|
|
12
|
+
* - Error handling
|
|
13
|
+
* - Dynamic content
|
|
14
|
+
* - Minimal configuration
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* Example 1: Basic GEO for a software project
|
|
18
|
+
*
|
|
19
|
+
* AI 검색 엔진이 소프트웨어 프로젝트를 정확하게 이해하도록 기본 GEO 메타데이터 생성
|
|
20
|
+
*/
|
|
21
|
+
export declare function Example1_BasicGEO(): import("react/jsx-runtime").JSX.Element;
|
|
22
|
+
/**
|
|
23
|
+
* Example 2: Next.js App Router metadata
|
|
24
|
+
*
|
|
25
|
+
* Next.js App Router의 generateMetadata()와 함께 사용
|
|
26
|
+
*/
|
|
27
|
+
export declare function Example2_NextjsMetadata(): Promise<{
|
|
28
|
+
title: string;
|
|
29
|
+
description: string | undefined;
|
|
30
|
+
keywords: string | undefined;
|
|
31
|
+
openGraph: {
|
|
32
|
+
title: string | undefined;
|
|
33
|
+
description: string | undefined;
|
|
34
|
+
};
|
|
35
|
+
other: {
|
|
36
|
+
'script:ld+json': string;
|
|
37
|
+
};
|
|
38
|
+
}>;
|
|
39
|
+
/**
|
|
40
|
+
* Example 3: FAQ Page with structured data
|
|
41
|
+
*
|
|
42
|
+
* AI가 자주 묻는 질문에 답변할 수 있도록 FAQ 구조화된 데이터 추가
|
|
43
|
+
*/
|
|
44
|
+
export declare function Example3_FAQPage(): import("react/jsx-runtime").JSX.Element;
|
|
45
|
+
/**
|
|
46
|
+
* Example 4: HowTo Guide with structured data
|
|
47
|
+
*
|
|
48
|
+
* AI가 튜토리얼을 이해하고 추천할 수 있도록 HowTo 구조화된 데이터 추가
|
|
49
|
+
*/
|
|
50
|
+
export declare function Example4_HowToGuide(): import("react/jsx-runtime").JSX.Element;
|
|
51
|
+
/**
|
|
52
|
+
* Example 5: AI Context for Chatbots
|
|
53
|
+
*
|
|
54
|
+
* ChatGPT, Claude 같은 AI 챗봇이 맥락을 이해하기 쉬운 설명 생성
|
|
55
|
+
*/
|
|
56
|
+
export declare function Example5_AIContext(): import("react/jsx-runtime").JSX.Element;
|
|
57
|
+
/**
|
|
58
|
+
* Example 6: Complete landing page with full GEO
|
|
59
|
+
*
|
|
60
|
+
* 모든 GEO 기능을 사용한 완전한 랜딩 페이지 예시
|
|
61
|
+
*/
|
|
62
|
+
export declare function Example6_CompleteLandingPage(): import("react/jsx-runtime").JSX.Element;
|
|
63
|
+
/**
|
|
64
|
+
* Example 7: Minimal Configuration
|
|
65
|
+
*
|
|
66
|
+
* 최소한의 설정으로 GEO 메타데이터 생성
|
|
67
|
+
* Shows minimum required fields
|
|
68
|
+
*/
|
|
69
|
+
export declare function Example7_MinimalConfig(): import("react/jsx-runtime").JSX.Element;
|
|
70
|
+
/**
|
|
71
|
+
* Example 8: Error Handling
|
|
72
|
+
*
|
|
73
|
+
* 에러 처리 예제
|
|
74
|
+
* Shows how to handle validation errors
|
|
75
|
+
*/
|
|
76
|
+
export declare function Example8_ErrorHandling(): import("react/jsx-runtime").JSX.Element;
|
|
77
|
+
/**
|
|
78
|
+
* Example 9: Dynamic Content
|
|
79
|
+
*
|
|
80
|
+
* 동적 콘텐츠를 사용한 GEO 메타데이터 생성
|
|
81
|
+
* Shows how to use dynamic data
|
|
82
|
+
*/
|
|
83
|
+
export declare function Example9_DynamicContent({ title, features, }: {
|
|
84
|
+
title: string;
|
|
85
|
+
features: string[];
|
|
86
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
87
|
+
//# sourceMappingURL=examples.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"examples.d.ts","sourceRoot":"","sources":["../../../../src/framework/seo/geo/examples.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAMH;;;;GAIG;AACH,wBAAgB,iBAAiB,4CAmFhC;AAED;;;;GAIG;AACH,wBAAsB,uBAAuB;;;;;;;;;;;GAuB5C;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,4CAkC/B;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,4CAmClC;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,4CAgCjC;AAED;;;;GAIG;AACH,wBAAgB,4BAA4B,4CAkE3C;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,4CAerC;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,4CAgBrC;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,EACtC,KAAK,EACL,QAAQ,GACT,EAAE;IACD,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB,2CAoBA"}
|
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* @hua-labs/hua-ux/framework - GEO Usage Examples
|
|
4
|
+
*
|
|
5
|
+
* Examples of using GEO (Generative Engine Optimization) to make your
|
|
6
|
+
* application discoverable by AI search engines
|
|
7
|
+
*
|
|
8
|
+
* AI 검색 엔진이 애플리케이션을 잘 찾고 추천하도록 GEO 사용 예시
|
|
9
|
+
*
|
|
10
|
+
* These examples demonstrate various use cases including:
|
|
11
|
+
* - Basic GEO configuration
|
|
12
|
+
* - Using presets
|
|
13
|
+
* - Error handling
|
|
14
|
+
* - Dynamic content
|
|
15
|
+
* - Minimal configuration
|
|
16
|
+
*/
|
|
17
|
+
import Script from 'next/script';
|
|
18
|
+
import { generateGEOMetadata, renderJSONLD, createAIContext } from './generateGEOMetadata';
|
|
19
|
+
import { generateFAQPageLD, generateHowToLD } from './structuredData';
|
|
20
|
+
/**
|
|
21
|
+
* Example 1: Basic GEO for a software project
|
|
22
|
+
*
|
|
23
|
+
* AI 검색 엔진이 소프트웨어 프로젝트를 정확하게 이해하도록 기본 GEO 메타데이터 생성
|
|
24
|
+
*/
|
|
25
|
+
export function Example1_BasicGEO() {
|
|
26
|
+
const geoMetadata = generateGEOMetadata({
|
|
27
|
+
name: 'hua-ux',
|
|
28
|
+
alternateName: ['@hua-labs/hua-ux', 'hua UX framework'],
|
|
29
|
+
description: 'Privacy-first UX framework for Next.js with built-in i18n, motion, and accessibility',
|
|
30
|
+
version: '1.0.0',
|
|
31
|
+
applicationCategory: ['UX Framework', 'Developer Tool'],
|
|
32
|
+
programmingLanguage: ['TypeScript', 'React', 'Next.js'],
|
|
33
|
+
applicationType: 'DeveloperApplication',
|
|
34
|
+
url: 'https://hua-labs.dev',
|
|
35
|
+
documentationUrl: 'https://hua-labs.dev/docs/hua-ux',
|
|
36
|
+
codeRepository: 'https://github.com/hua-labs/hua',
|
|
37
|
+
license: 'MIT',
|
|
38
|
+
author: {
|
|
39
|
+
name: 'hua-labs',
|
|
40
|
+
url: 'https://hua-labs.dev',
|
|
41
|
+
},
|
|
42
|
+
features: [
|
|
43
|
+
'Privacy-first architecture (no tracking, no analytics by default)',
|
|
44
|
+
'Built-in internationalization (i18n) with hua-i18n',
|
|
45
|
+
'Smooth motion animations with hua-motion',
|
|
46
|
+
'WCAG 2.1 compliant accessibility features',
|
|
47
|
+
'Automatic error handling with ErrorBoundary',
|
|
48
|
+
'Loading state optimization (300ms flicker prevention)',
|
|
49
|
+
'AI-friendly documentation (Korean/English bilingual)',
|
|
50
|
+
],
|
|
51
|
+
useCases: [
|
|
52
|
+
'Building multilingual Next.js applications',
|
|
53
|
+
'Creating accessible web applications',
|
|
54
|
+
'Rapid prototyping with privacy-first defaults',
|
|
55
|
+
'Enterprise applications requiring WCAG compliance',
|
|
56
|
+
],
|
|
57
|
+
keywords: [
|
|
58
|
+
'nextjs',
|
|
59
|
+
'react',
|
|
60
|
+
'ux framework',
|
|
61
|
+
'i18n',
|
|
62
|
+
'internationalization',
|
|
63
|
+
'accessibility',
|
|
64
|
+
'a11y',
|
|
65
|
+
'wcag',
|
|
66
|
+
'motion',
|
|
67
|
+
'animation',
|
|
68
|
+
'privacy',
|
|
69
|
+
'gdpr',
|
|
70
|
+
'typescript',
|
|
71
|
+
],
|
|
72
|
+
softwareRequirements: ['Next.js 14+', 'React 18+', 'TypeScript 5+'],
|
|
73
|
+
operatingSystem: ['Windows', 'macOS', 'Linux'],
|
|
74
|
+
relatedTo: [
|
|
75
|
+
'Next.js',
|
|
76
|
+
'React',
|
|
77
|
+
'hua-i18n',
|
|
78
|
+
'hua-motion',
|
|
79
|
+
'hua-state',
|
|
80
|
+
'Tailwind CSS',
|
|
81
|
+
],
|
|
82
|
+
});
|
|
83
|
+
return (_jsxs("head", { children: [geoMetadata.meta.map((meta) => (_jsx("meta", { name: meta.name, content: meta.content }, meta.name))), geoMetadata.openGraph?.map((og) => (_jsx("meta", { property: og.property, content: og.content }, og.property))), geoMetadata.twitter?.map((tw) => (_jsx("meta", { name: tw.name, content: tw.content }, tw.name))), geoMetadata.jsonLd.map((ld, index) => (_jsx(Script, { ...renderJSONLD(ld) }, index)))] }));
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Example 2: Next.js App Router metadata
|
|
87
|
+
*
|
|
88
|
+
* Next.js App Router의 generateMetadata()와 함께 사용
|
|
89
|
+
*/
|
|
90
|
+
export async function Example2_NextjsMetadata() {
|
|
91
|
+
const geoMeta = generateGEOMetadata({
|
|
92
|
+
name: 'My App',
|
|
93
|
+
description: 'Built with hua-ux for privacy-first UX',
|
|
94
|
+
features: ['i18n', 'Dark mode', 'Responsive design'],
|
|
95
|
+
keywords: ['nextjs', 'react', 'privacy', 'accessibility'],
|
|
96
|
+
});
|
|
97
|
+
// Next.js Metadata 객체로 변환
|
|
98
|
+
return {
|
|
99
|
+
title: 'My App',
|
|
100
|
+
description: geoMeta.meta.find((m) => m.name === 'description')?.content,
|
|
101
|
+
keywords: geoMeta.meta.find((m) => m.name === 'keywords')?.content,
|
|
102
|
+
openGraph: {
|
|
103
|
+
title: geoMeta.openGraph?.find((og) => og.property === 'og:title')?.content,
|
|
104
|
+
description: geoMeta.openGraph?.find((og) => og.property === 'og:description')
|
|
105
|
+
?.content,
|
|
106
|
+
},
|
|
107
|
+
// JSON-LD는 layout.tsx나 page.tsx에서 Script 컴포넌트로 추가
|
|
108
|
+
other: {
|
|
109
|
+
'script:ld+json': JSON.stringify(geoMeta.jsonLd),
|
|
110
|
+
},
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Example 3: FAQ Page with structured data
|
|
115
|
+
*
|
|
116
|
+
* AI가 자주 묻는 질문에 답변할 수 있도록 FAQ 구조화된 데이터 추가
|
|
117
|
+
*/
|
|
118
|
+
export function Example3_FAQPage() {
|
|
119
|
+
const faqLd = generateFAQPageLD([
|
|
120
|
+
{
|
|
121
|
+
question: 'What is hua-ux?',
|
|
122
|
+
answer: 'hua-ux is a privacy-first UX framework for Next.js applications. It provides built-in internationalization (i18n), motion animations, accessibility features (WCAG 2.1 compliant), automatic error handling, and loading state optimization.',
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
question: 'How do I install hua-ux?',
|
|
126
|
+
answer: 'You can create a new hua-ux project using the CLI: npx create-hua-ux my-app. Or install it in an existing Next.js project: pnpm add @hua-labs/hua-ux',
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
question: 'Is hua-ux free to use?',
|
|
130
|
+
answer: 'Yes, hua-ux is open-source and available under the MIT license. You can use it freely in both personal and commercial projects.',
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
question: 'What makes hua-ux privacy-first?',
|
|
134
|
+
answer: 'hua-ux has no tracking, no analytics, and no data collection by default. It respects user privacy and follows GDPR/CCPA principles. You have full control over what data your application collects.',
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
question: 'Does hua-ux support TypeScript?',
|
|
138
|
+
answer: 'Yes, hua-ux is written in TypeScript and provides full type safety. All components, hooks, and utilities come with TypeScript definitions.',
|
|
139
|
+
},
|
|
140
|
+
]);
|
|
141
|
+
return (_jsx("head", { children: _jsx(Script, { ...renderJSONLD(faqLd) }) }));
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Example 4: HowTo Guide with structured data
|
|
145
|
+
*
|
|
146
|
+
* AI가 튜토리얼을 이해하고 추천할 수 있도록 HowTo 구조화된 데이터 추가
|
|
147
|
+
*/
|
|
148
|
+
export function Example4_HowToGuide() {
|
|
149
|
+
const howToLd = generateHowToLD({
|
|
150
|
+
name: 'How to add internationalization (i18n) to your Next.js app with hua-ux',
|
|
151
|
+
description: 'Step-by-step guide to implementing multilingual support in your Next.js application using hua-ux',
|
|
152
|
+
totalTime: 'PT10M', // 10 minutes
|
|
153
|
+
steps: [
|
|
154
|
+
{
|
|
155
|
+
name: 'Create a new hua-ux project',
|
|
156
|
+
text: 'Run the CLI command: npx create-hua-ux my-app. This creates a new Next.js project with hua-ux pre-configured.',
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
name: 'Configure supported locales',
|
|
160
|
+
text: 'Edit hua.config.ts and add your locales to the i18n.locales array. For example: locales: ["en", "ko", "ja"]',
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
name: 'Create translation files',
|
|
164
|
+
text: 'Add JSON translation files in the messages/ directory. Create one file per locale: messages/en.json, messages/ko.json, etc.',
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
name: 'Use translations in components',
|
|
168
|
+
text: 'Import useI18n hook and use the t() function to translate text: const { t } = useI18n(); return <h1>{t("welcome")}</h1>',
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
name: 'Add language switcher',
|
|
172
|
+
text: 'Use the LocaleSwitcher component to let users change languages: <LocaleSwitcher />',
|
|
173
|
+
},
|
|
174
|
+
],
|
|
175
|
+
});
|
|
176
|
+
return (_jsx("head", { children: _jsx(Script, { ...renderJSONLD(howToLd) }) }));
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Example 5: AI Context for Chatbots
|
|
180
|
+
*
|
|
181
|
+
* ChatGPT, Claude 같은 AI 챗봇이 맥락을 이해하기 쉬운 설명 생성
|
|
182
|
+
*/
|
|
183
|
+
export function Example5_AIContext() {
|
|
184
|
+
const context = createAIContext({
|
|
185
|
+
name: 'hua-ux',
|
|
186
|
+
description: 'Privacy-first UX framework for Next.js',
|
|
187
|
+
features: [
|
|
188
|
+
'Internationalization (i18n)',
|
|
189
|
+
'Motion animations',
|
|
190
|
+
'WCAG 2.1 accessibility',
|
|
191
|
+
'Error boundaries',
|
|
192
|
+
'Loading state optimization',
|
|
193
|
+
],
|
|
194
|
+
useCases: [
|
|
195
|
+
'Multilingual web applications',
|
|
196
|
+
'Accessible enterprise applications',
|
|
197
|
+
'Privacy-compliant consumer apps',
|
|
198
|
+
],
|
|
199
|
+
programmingLanguage: ['TypeScript', 'React', 'Next.js'],
|
|
200
|
+
softwareRequirements: ['Next.js 14+', 'React 18+'],
|
|
201
|
+
});
|
|
202
|
+
// Returns:
|
|
203
|
+
// "hua-ux is a Privacy-first UX framework for Next.js. Key features include:
|
|
204
|
+
// Internationalization (i18n), Motion animations, WCAG 2.1 accessibility, Error
|
|
205
|
+
// boundaries, Loading state optimization. Common use cases: Multilingual web
|
|
206
|
+
// applications, Accessible enterprise applications, Privacy-compliant consumer
|
|
207
|
+
// apps. Built with: TypeScript, React, Next.js. Requires: Next.js 14+, React 18+."
|
|
208
|
+
return (_jsx("head", { children: _jsx("meta", { name: "ai:context", content: context }) }));
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Example 6: Complete landing page with full GEO
|
|
212
|
+
*
|
|
213
|
+
* 모든 GEO 기능을 사용한 완전한 랜딩 페이지 예시
|
|
214
|
+
*/
|
|
215
|
+
export function Example6_CompleteLandingPage() {
|
|
216
|
+
// Software metadata
|
|
217
|
+
const geoMeta = generateGEOMetadata({
|
|
218
|
+
name: 'hua-ux',
|
|
219
|
+
description: 'Privacy-first UX framework for Next.js',
|
|
220
|
+
version: '1.0.0',
|
|
221
|
+
applicationCategory: 'UX Framework',
|
|
222
|
+
programmingLanguage: 'TypeScript',
|
|
223
|
+
features: ['i18n', 'Motion', 'Accessibility', 'Error handling', 'Loading optimization'],
|
|
224
|
+
keywords: ['nextjs', 'react', 'ux', 'i18n', 'accessibility', 'privacy'],
|
|
225
|
+
codeRepository: 'https://github.com/hua-labs/hua',
|
|
226
|
+
license: 'MIT',
|
|
227
|
+
});
|
|
228
|
+
// FAQ structured data
|
|
229
|
+
const faqLd = generateFAQPageLD([
|
|
230
|
+
{ question: 'What is hua-ux?', answer: 'Privacy-first UX framework for Next.js' },
|
|
231
|
+
{ question: 'How to install?', answer: 'npx create-hua-ux my-app' },
|
|
232
|
+
]);
|
|
233
|
+
// HowTo guide
|
|
234
|
+
const howToLd = generateHowToLD({
|
|
235
|
+
name: 'Getting started with hua-ux',
|
|
236
|
+
steps: [
|
|
237
|
+
{ name: 'Install', text: 'npx create-hua-ux my-app' },
|
|
238
|
+
{ name: 'Configure', text: 'Edit hua.config.ts' },
|
|
239
|
+
{ name: 'Build', text: 'pnpm dev' },
|
|
240
|
+
],
|
|
241
|
+
});
|
|
242
|
+
// AI context
|
|
243
|
+
const aiContext = createAIContext({
|
|
244
|
+
name: 'hua-ux',
|
|
245
|
+
description: 'Privacy-first UX framework',
|
|
246
|
+
features: ['i18n', 'Motion', 'Accessibility'],
|
|
247
|
+
});
|
|
248
|
+
return (_jsxs("html", { children: [_jsxs("head", { children: [geoMeta.meta.map((meta) => (_jsx("meta", { name: meta.name, content: meta.content }, meta.name))), geoMeta.openGraph?.map((og) => (_jsx("meta", { property: og.property, content: og.content }, og.property))), geoMeta.twitter?.map((tw) => (_jsx("meta", { name: tw.name, content: tw.content }, tw.name))), _jsx("meta", { name: "ai:context", content: aiContext }), _jsx(Script, { ...renderJSONLD(geoMeta.jsonLd[0]) }), _jsx(Script, { ...renderJSONLD(faqLd) }), _jsx(Script, { ...renderJSONLD(howToLd) })] }), _jsx("body", {})] }));
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Example 7: Minimal Configuration
|
|
252
|
+
*
|
|
253
|
+
* 최소한의 설정으로 GEO 메타데이터 생성
|
|
254
|
+
* Shows minimum required fields
|
|
255
|
+
*/
|
|
256
|
+
export function Example7_MinimalConfig() {
|
|
257
|
+
const geoMeta = generateGEOMetadata({
|
|
258
|
+
name: 'My App',
|
|
259
|
+
description: 'A simple app',
|
|
260
|
+
});
|
|
261
|
+
return (_jsxs(_Fragment, { children: [_jsx(Script, { ...renderJSONLD(geoMeta.jsonLd[0]) }), _jsxs("main", { children: [_jsx("h1", { children: "Minimal GEO Configuration" }), _jsx("p", { children: "Only name and description are required." })] })] }));
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Example 8: Error Handling
|
|
265
|
+
*
|
|
266
|
+
* 에러 처리 예제
|
|
267
|
+
* Shows how to handle validation errors
|
|
268
|
+
*/
|
|
269
|
+
export function Example8_ErrorHandling() {
|
|
270
|
+
try {
|
|
271
|
+
const geoMeta = generateGEOMetadata({
|
|
272
|
+
name: '', // Invalid!
|
|
273
|
+
description: 'Test',
|
|
274
|
+
});
|
|
275
|
+
return _jsx("div", { children: "Success" });
|
|
276
|
+
}
|
|
277
|
+
catch (error) {
|
|
278
|
+
console.error('GEO metadata generation failed:', error);
|
|
279
|
+
return (_jsxs("div", { children: [_jsx("h1", { children: "Error" }), _jsx("p", { children: error.message })] }));
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Example 9: Dynamic Content
|
|
284
|
+
*
|
|
285
|
+
* 동적 콘텐츠를 사용한 GEO 메타데이터 생성
|
|
286
|
+
* Shows how to use dynamic data
|
|
287
|
+
*/
|
|
288
|
+
export function Example9_DynamicContent({ title, features, }) {
|
|
289
|
+
const geoMeta = generateGEOMetadata({
|
|
290
|
+
name: title,
|
|
291
|
+
description: `App with ${features.length} features`,
|
|
292
|
+
features,
|
|
293
|
+
});
|
|
294
|
+
return (_jsxs(_Fragment, { children: [_jsx(Script, { ...renderJSONLD(geoMeta.jsonLd[0]) }), _jsxs("main", { children: [_jsx("h1", { children: title }), _jsx("ul", { children: features.map((feature, i) => (_jsx("li", { children: feature }, i))) })] })] }));
|
|
295
|
+
}
|