@contractspec/lib.example-shared-ui 0.0.0-canary-20260113170453
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/.turbo/turbo-build$colon$bundle.log +9 -0
- package/.turbo/turbo-build.log +11 -0
- package/CHANGELOG.md +34 -0
- package/dist/index.mjs +3121 -0
- package/package.json +43 -0
- package/src/EvolutionDashboard.tsx +480 -0
- package/src/EvolutionSidebar.tsx +282 -0
- package/src/LocalDataIndicator.tsx +39 -0
- package/src/MarkdownView.tsx +389 -0
- package/src/OverlayContextProvider.tsx +341 -0
- package/src/PersonalizationInsights.tsx +293 -0
- package/src/SaveToStudioButton.tsx +64 -0
- package/src/SpecEditorPanel.tsx +165 -0
- package/src/TemplateShell.tsx +63 -0
- package/src/hooks/index.ts +5 -0
- package/src/hooks/useBehaviorTracking.ts +327 -0
- package/src/hooks/useEvolution.ts +501 -0
- package/src/hooks/useRegistryTemplates.ts +49 -0
- package/src/hooks/useSpecContent.ts +243 -0
- package/src/hooks/useWorkflowComposer.ts +670 -0
- package/src/index.ts +15 -0
- package/src/lib/component-registry.tsx +64 -0
- package/src/lib/runtime-context.tsx +54 -0
- package/src/lib/types.ts +84 -0
- package/src/overlay-types.ts +25 -0
- package/src/utils/fetchPresentationData.ts +48 -0
- package/src/utils/generateSpecFromTemplate.ts +458 -0
- package/src/utils/index.ts +2 -0
- package/tsconfig.json +10 -0
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import React, { useState, useEffect } from 'react';
|
|
4
|
+
import type { TemplateId } from './types';
|
|
5
|
+
|
|
6
|
+
export interface TemplateComponentRegistration {
|
|
7
|
+
list: React.ComponentType<any>; // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
8
|
+
detail: React.ComponentType<any>; // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
9
|
+
form?: React.ComponentType<any>; // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export class TemplateComponentRegistry {
|
|
13
|
+
private readonly components = new Map<
|
|
14
|
+
TemplateId,
|
|
15
|
+
TemplateComponentRegistration
|
|
16
|
+
>();
|
|
17
|
+
private readonly listeners = new Set<(templateId: TemplateId) => void>();
|
|
18
|
+
|
|
19
|
+
register(
|
|
20
|
+
templateId: TemplateId,
|
|
21
|
+
registration: TemplateComponentRegistration
|
|
22
|
+
) {
|
|
23
|
+
this.components.set(templateId, registration);
|
|
24
|
+
this.listeners.forEach((l) => l(templateId));
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
get(templateId: TemplateId) {
|
|
28
|
+
return this.components.get(templateId);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
subscribe(listener: (templateId: TemplateId) => void) {
|
|
32
|
+
this.listeners.add(listener);
|
|
33
|
+
return () => {
|
|
34
|
+
this.listeners.delete(listener);
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export const templateComponentRegistry = new TemplateComponentRegistry();
|
|
40
|
+
|
|
41
|
+
export function registerTemplateComponents(
|
|
42
|
+
templateId: TemplateId,
|
|
43
|
+
components: TemplateComponentRegistration
|
|
44
|
+
) {
|
|
45
|
+
templateComponentRegistry.register(templateId, components);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function useTemplateComponents(
|
|
49
|
+
templateId: TemplateId
|
|
50
|
+
): TemplateComponentRegistration | undefined {
|
|
51
|
+
const [components, setComponents] = useState(() =>
|
|
52
|
+
templateComponentRegistry.get(templateId)
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
useEffect(() => {
|
|
56
|
+
return templateComponentRegistry.subscribe((updatedId) => {
|
|
57
|
+
if (updatedId === templateId) {
|
|
58
|
+
setComponents(templateComponentRegistry.get(templateId));
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
}, [templateId]);
|
|
62
|
+
|
|
63
|
+
return components;
|
|
64
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { createContext, useContext } from 'react';
|
|
4
|
+
import type { ApolloClient } from '@apollo/client';
|
|
5
|
+
import type { TransformEngine } from '@contractspec/lib.contracts';
|
|
6
|
+
import type {
|
|
7
|
+
TemplateDefinition,
|
|
8
|
+
TemplateId,
|
|
9
|
+
TemplateInstaller,
|
|
10
|
+
} from './types';
|
|
11
|
+
|
|
12
|
+
// Generic interface for handlers to avoid circular dependencies
|
|
13
|
+
// Real types are defined in @contractspec/module.examples or specific example packages
|
|
14
|
+
export type GenericTemplateHandlers = unknown;
|
|
15
|
+
|
|
16
|
+
export interface TemplateRuntimeContextValue<
|
|
17
|
+
THandlers = GenericTemplateHandlers,
|
|
18
|
+
> {
|
|
19
|
+
template: TemplateDefinition;
|
|
20
|
+
runtime: unknown; // LocalRuntimeServices
|
|
21
|
+
installer: TemplateInstaller;
|
|
22
|
+
client: ApolloClient;
|
|
23
|
+
components?: unknown; // TemplateComponentRegistration
|
|
24
|
+
/** @deprecated use template.id */
|
|
25
|
+
templateId: TemplateId;
|
|
26
|
+
projectId: string;
|
|
27
|
+
engine: TransformEngine;
|
|
28
|
+
fetchData: (
|
|
29
|
+
presentationName: string
|
|
30
|
+
) => Promise<{ data: unknown; metadata?: unknown }>;
|
|
31
|
+
handlers: THandlers;
|
|
32
|
+
resolvePresentation?: (presentationName: string) => unknown;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export const TemplateRuntimeContext =
|
|
36
|
+
createContext<TemplateRuntimeContextValue | null>(null);
|
|
37
|
+
|
|
38
|
+
export function useTemplateRuntime<
|
|
39
|
+
THandlers = GenericTemplateHandlers,
|
|
40
|
+
>(): TemplateRuntimeContextValue<THandlers> {
|
|
41
|
+
const context = useContext(TemplateRuntimeContext);
|
|
42
|
+
if (!context) {
|
|
43
|
+
throw new Error(
|
|
44
|
+
'useTemplateRuntime must be used within a TemplateRuntimeProvider'
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
return context as TemplateRuntimeContextValue<THandlers>;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export interface TemplateRuntimeProviderProps {
|
|
51
|
+
templateId: TemplateId;
|
|
52
|
+
projectId?: string;
|
|
53
|
+
lazy?: boolean;
|
|
54
|
+
}
|
package/src/lib/types.ts
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
export type TemplateId = string;
|
|
2
|
+
|
|
3
|
+
export type TemplateCategory =
|
|
4
|
+
| 'productivity'
|
|
5
|
+
| 'communication'
|
|
6
|
+
| 'content'
|
|
7
|
+
| 'business'
|
|
8
|
+
| 'ai';
|
|
9
|
+
|
|
10
|
+
export type TemplateComplexity = 'beginner' | 'intermediate' | 'advanced';
|
|
11
|
+
|
|
12
|
+
export interface TemplateDefinition {
|
|
13
|
+
id: TemplateId;
|
|
14
|
+
name: string;
|
|
15
|
+
description: string;
|
|
16
|
+
category: TemplateCategory;
|
|
17
|
+
complexity: TemplateComplexity;
|
|
18
|
+
icon: string;
|
|
19
|
+
features: string[];
|
|
20
|
+
tags: string[];
|
|
21
|
+
schema: {
|
|
22
|
+
models: string[];
|
|
23
|
+
contracts: string[];
|
|
24
|
+
};
|
|
25
|
+
components: {
|
|
26
|
+
list: string;
|
|
27
|
+
detail: string;
|
|
28
|
+
form?: string;
|
|
29
|
+
dashboard?: string;
|
|
30
|
+
};
|
|
31
|
+
preview?: {
|
|
32
|
+
demoUrl?: string;
|
|
33
|
+
videoUrl?: string;
|
|
34
|
+
};
|
|
35
|
+
docs?: {
|
|
36
|
+
quickstart?: string;
|
|
37
|
+
reference?: string;
|
|
38
|
+
};
|
|
39
|
+
/** Package name for external examples that can be cloned via Git */
|
|
40
|
+
package?: string;
|
|
41
|
+
/** Whether this template uses the new cross-cutting modules */
|
|
42
|
+
usesModules?: string[];
|
|
43
|
+
/** Feature spec key from the example package */
|
|
44
|
+
featureSpec?: string;
|
|
45
|
+
/** List of presentation names available for this template */
|
|
46
|
+
presentations?: string[];
|
|
47
|
+
/** List of render targets supported (default: ['react']) */
|
|
48
|
+
renderTargets?: ('react' | 'markdown' | 'json' | 'xml')[];
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export interface TemplateFilter {
|
|
52
|
+
category?: TemplateCategory;
|
|
53
|
+
complexity?: TemplateComplexity;
|
|
54
|
+
tag?: string;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export interface InstallTemplateOptions {
|
|
58
|
+
projectId?: string;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export interface SaveTemplateOptions {
|
|
62
|
+
endpoint?: string;
|
|
63
|
+
token?: string;
|
|
64
|
+
projectName: string;
|
|
65
|
+
organizationId: string;
|
|
66
|
+
templateId: TemplateId;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export interface SaveTemplateResult {
|
|
70
|
+
projectId: string;
|
|
71
|
+
status: string;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Interface for the TemplateInstaller class.
|
|
76
|
+
* Mirrors the public API of the implementation in @contractspec/module.examples
|
|
77
|
+
*/
|
|
78
|
+
export interface TemplateInstaller {
|
|
79
|
+
install(
|
|
80
|
+
templateId: TemplateId,
|
|
81
|
+
options?: InstallTemplateOptions
|
|
82
|
+
): Promise<void>;
|
|
83
|
+
saveToStudio(options: SaveTemplateOptions): Promise<SaveTemplateResult>;
|
|
84
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared Overlay Type Definitions
|
|
3
|
+
*
|
|
4
|
+
* These types are used across all template overlays to ensure consistency.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export interface OverlayDefinition {
|
|
8
|
+
overlayId: string;
|
|
9
|
+
version: string;
|
|
10
|
+
description: string;
|
|
11
|
+
appliesTo: {
|
|
12
|
+
presentation?: string;
|
|
13
|
+
role?: string;
|
|
14
|
+
feature?: string;
|
|
15
|
+
tier?: string;
|
|
16
|
+
};
|
|
17
|
+
modifications: OverlayModification[];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export type OverlayModification =
|
|
21
|
+
| { type: 'hideField'; field: string; reason?: string }
|
|
22
|
+
| { type: 'renameLabel'; field: string; newLabel: string }
|
|
23
|
+
| { type: 'addBadge'; position: string; label: string; variant?: string }
|
|
24
|
+
| { type: 'setDefault'; field: string; value: unknown }
|
|
25
|
+
| { type: 'setLimit'; field: string; max: number; message?: string };
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fetch Presentation Data Utility
|
|
3
|
+
*
|
|
4
|
+
* Types for presentation data fetching.
|
|
5
|
+
* Actual fetching logic is now handled via TemplateRuntimeContext and dependency injection.
|
|
6
|
+
*/
|
|
7
|
+
import type { TemplateId } from '../lib/types';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Data fetcher result type
|
|
11
|
+
*/
|
|
12
|
+
export interface PresentationDataResult {
|
|
13
|
+
data: unknown;
|
|
14
|
+
metadata?: {
|
|
15
|
+
total?: number;
|
|
16
|
+
timestamp?: Date;
|
|
17
|
+
source?: string;
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @deprecated Use fetchData from TemplateRuntimeContext instead.
|
|
23
|
+
*/
|
|
24
|
+
/**
|
|
25
|
+
* @deprecated Use fetchData from TemplateRuntimeContext instead.
|
|
26
|
+
*/
|
|
27
|
+
export async function fetchPresentationData(
|
|
28
|
+
_presentationName: string,
|
|
29
|
+
_templateId: TemplateId
|
|
30
|
+
): Promise<PresentationDataResult> {
|
|
31
|
+
throw new Error(
|
|
32
|
+
'fetchPresentationData is deprecated. Use fetchData from TemplateRuntimeContext.'
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* @deprecated
|
|
38
|
+
*/
|
|
39
|
+
export function hasPresentationDataFetcher(_presentationName: string): boolean {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* @deprecated
|
|
45
|
+
*/
|
|
46
|
+
export function getRegisteredPresentationFetchers(): string[] {
|
|
47
|
+
return [];
|
|
48
|
+
}
|