@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.
@@ -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
+ }
@@ -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
+ }