@contractspec/lib.example-shared-ui 3.4.2 → 4.0.0
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.log +36 -27
- package/CHANGELOG.md +30 -0
- package/dist/SpecDrivenTemplateShell.d.ts +19 -0
- package/dist/SpecDrivenTemplateShell.js +195 -0
- package/dist/browser/SpecDrivenTemplateShell.js +194 -0
- package/dist/browser/bundles/ExampleTemplateBundle.js +85 -0
- package/dist/browser/bundles/index.js +85 -0
- package/dist/browser/index.js +107 -33
- package/dist/bundles/ExampleTemplateBundle.d.ts +79 -0
- package/dist/bundles/ExampleTemplateBundle.js +86 -0
- package/dist/bundles/index.d.ts +1 -0
- package/dist/bundles/index.js +86 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +107 -33
- package/dist/node/SpecDrivenTemplateShell.js +194 -0
- package/dist/node/bundles/ExampleTemplateBundle.js +85 -0
- package/dist/node/bundles/index.js +85 -0
- package/dist/node/index.js +107 -33
- package/package.json +74 -7
- package/src/SpecDrivenTemplateShell.tsx +76 -0
- package/src/bundles/ExampleTemplateBundle.ts +91 -0
- package/src/bundles/index.ts +1 -0
- package/src/index.ts +1 -0
package/.turbo/turbo-build.log
CHANGED
|
@@ -2,85 +2,94 @@ $ contractspec-bun-build prebuild
|
|
|
2
2
|
$ bun run prebuild && bun run build:bundle && bun run build:types
|
|
3
3
|
$ contractspec-bun-build prebuild
|
|
4
4
|
$ contractspec-bun-build transpile
|
|
5
|
-
[contractspec-bun-build] transpile target=bun root=src entries=
|
|
6
|
-
Bundled
|
|
5
|
+
[contractspec-bun-build] transpile target=bun root=src entries=26
|
|
6
|
+
Bundled 26 modules in 37ms
|
|
7
7
|
|
|
8
8
|
./EvolutionDashboard.js 31.40 KB (entry point)
|
|
9
|
-
./index.js
|
|
9
|
+
./index.js 123.75 KB (entry point)
|
|
10
|
+
utils/index.js 10.1 KB (entry point)
|
|
10
11
|
lib/component-registry.js 1.23 KB (entry point)
|
|
11
12
|
lib/types.js 8 bytes (entry point)
|
|
12
13
|
./overlay-types.js 8 bytes (entry point)
|
|
13
|
-
utils/index.js 10.1 KB (entry point)
|
|
14
14
|
utils/fetchPresentationData.js 461 bytes (entry point)
|
|
15
|
+
./SpecEditorPanel.js 19.64 KB (entry point)
|
|
15
16
|
./TemplateShell.js 6.84 KB (entry point)
|
|
17
|
+
bundles/index.js 2.44 KB (entry point)
|
|
18
|
+
bundles/ExampleTemplateBundle.js 2.44 KB (entry point)
|
|
16
19
|
hooks/index.js 44.1 KB (entry point)
|
|
17
|
-
hooks/useRegistryTemplates.js 0.94 KB (entry point)
|
|
18
20
|
hooks/useWorkflowComposer.js 13.67 KB (entry point)
|
|
21
|
+
hooks/useSpecContent.js 14.30 KB (entry point)
|
|
22
|
+
utils/generateSpecFromTemplate.js 9.65 KB (entry point)
|
|
23
|
+
hooks/useRegistryTemplates.js 0.94 KB (entry point)
|
|
19
24
|
./EvolutionSidebar.js 21.24 KB (entry point)
|
|
20
25
|
hooks/useEvolution.js 9.50 KB (entry point)
|
|
21
|
-
./LocalDataIndicator.js 2.20 KB (entry point)
|
|
22
26
|
./MarkdownView.js 11.40 KB (entry point)
|
|
23
27
|
./OverlayContextProvider.js 5.89 KB (entry point)
|
|
24
28
|
./PersonalizationInsights.js 17.74 KB (entry point)
|
|
25
29
|
hooks/useBehaviorTracking.js 5.53 KB (entry point)
|
|
30
|
+
./SpecDrivenTemplateShell.js 6.90 KB (entry point)
|
|
31
|
+
./LocalDataIndicator.js 2.20 KB (entry point)
|
|
26
32
|
./SaveToStudioButton.js 2.33 KB (entry point)
|
|
27
|
-
./SpecEditorPanel.js 19.64 KB (entry point)
|
|
28
|
-
hooks/useSpecContent.js 14.30 KB (entry point)
|
|
29
|
-
utils/generateSpecFromTemplate.js 9.65 KB (entry point)
|
|
30
33
|
lib/runtime-context.js 430 bytes (entry point)
|
|
31
34
|
|
|
32
|
-
[contractspec-bun-build] transpile target=node root=src entries=
|
|
33
|
-
Bundled
|
|
35
|
+
[contractspec-bun-build] transpile target=node root=src entries=26
|
|
36
|
+
Bundled 26 modules in 46ms
|
|
34
37
|
|
|
35
38
|
./EvolutionDashboard.js 31.38 KB (entry point)
|
|
36
|
-
./index.js
|
|
39
|
+
./index.js 123.69 KB (entry point)
|
|
40
|
+
utils/index.js 10.1 KB (entry point)
|
|
37
41
|
lib/component-registry.js 1.22 KB (entry point)
|
|
38
42
|
lib/types.js 0 KB (entry point)
|
|
39
43
|
./overlay-types.js 0 KB (entry point)
|
|
40
|
-
utils/index.js 10.1 KB (entry point)
|
|
41
44
|
utils/fetchPresentationData.js 453 bytes (entry point)
|
|
45
|
+
./SpecEditorPanel.js 19.63 KB (entry point)
|
|
42
46
|
./TemplateShell.js 6.83 KB (entry point)
|
|
47
|
+
bundles/index.js 2.43 KB (entry point)
|
|
48
|
+
bundles/ExampleTemplateBundle.js 2.43 KB (entry point)
|
|
43
49
|
hooks/index.js 44.1 KB (entry point)
|
|
44
|
-
hooks/useRegistryTemplates.js 0.93 KB (entry point)
|
|
45
50
|
hooks/useWorkflowComposer.js 13.67 KB (entry point)
|
|
51
|
+
hooks/useSpecContent.js 14.29 KB (entry point)
|
|
52
|
+
utils/generateSpecFromTemplate.js 9.64 KB (entry point)
|
|
53
|
+
hooks/useRegistryTemplates.js 0.93 KB (entry point)
|
|
46
54
|
./EvolutionSidebar.js 21.23 KB (entry point)
|
|
47
55
|
hooks/useEvolution.js 9.50 KB (entry point)
|
|
48
|
-
./LocalDataIndicator.js 2.19 KB (entry point)
|
|
49
56
|
./MarkdownView.js 11.40 KB (entry point)
|
|
50
57
|
./OverlayContextProvider.js 5.88 KB (entry point)
|
|
51
58
|
./PersonalizationInsights.js 17.71 KB (entry point)
|
|
52
59
|
hooks/useBehaviorTracking.js 5.52 KB (entry point)
|
|
60
|
+
./SpecDrivenTemplateShell.js 6.88 KB (entry point)
|
|
61
|
+
./LocalDataIndicator.js 2.19 KB (entry point)
|
|
53
62
|
./SaveToStudioButton.js 2.32 KB (entry point)
|
|
54
|
-
./SpecEditorPanel.js 19.63 KB (entry point)
|
|
55
|
-
hooks/useSpecContent.js 14.29 KB (entry point)
|
|
56
|
-
utils/generateSpecFromTemplate.js 9.64 KB (entry point)
|
|
57
63
|
lib/runtime-context.js 422 bytes (entry point)
|
|
58
64
|
|
|
59
|
-
[contractspec-bun-build] transpile target=browser root=src entries=
|
|
60
|
-
Bundled
|
|
65
|
+
[contractspec-bun-build] transpile target=browser root=src entries=26
|
|
66
|
+
Bundled 26 modules in 111ms
|
|
61
67
|
|
|
62
68
|
./EvolutionDashboard.js 31.38 KB (entry point)
|
|
63
|
-
./index.js
|
|
69
|
+
./index.js 123.69 KB (entry point)
|
|
70
|
+
utils/index.js 10.1 KB (entry point)
|
|
64
71
|
lib/component-registry.js 1.22 KB (entry point)
|
|
65
72
|
lib/types.js 0 KB (entry point)
|
|
66
73
|
./overlay-types.js 0 KB (entry point)
|
|
67
|
-
utils/index.js 10.1 KB (entry point)
|
|
68
74
|
utils/fetchPresentationData.js 453 bytes (entry point)
|
|
75
|
+
./SpecEditorPanel.js 19.63 KB (entry point)
|
|
69
76
|
./TemplateShell.js 6.83 KB (entry point)
|
|
77
|
+
bundles/index.js 2.43 KB (entry point)
|
|
78
|
+
bundles/ExampleTemplateBundle.js 2.43 KB (entry point)
|
|
70
79
|
hooks/index.js 44.1 KB (entry point)
|
|
71
|
-
hooks/useRegistryTemplates.js 0.93 KB (entry point)
|
|
72
80
|
hooks/useWorkflowComposer.js 13.67 KB (entry point)
|
|
81
|
+
hooks/useSpecContent.js 14.29 KB (entry point)
|
|
82
|
+
utils/generateSpecFromTemplate.js 9.64 KB (entry point)
|
|
83
|
+
hooks/useRegistryTemplates.js 0.93 KB (entry point)
|
|
73
84
|
./EvolutionSidebar.js 21.23 KB (entry point)
|
|
74
85
|
hooks/useEvolution.js 9.50 KB (entry point)
|
|
75
|
-
./LocalDataIndicator.js 2.19 KB (entry point)
|
|
76
86
|
./MarkdownView.js 11.40 KB (entry point)
|
|
77
87
|
./OverlayContextProvider.js 5.88 KB (entry point)
|
|
78
88
|
./PersonalizationInsights.js 17.71 KB (entry point)
|
|
79
89
|
hooks/useBehaviorTracking.js 5.52 KB (entry point)
|
|
90
|
+
./SpecDrivenTemplateShell.js 6.88 KB (entry point)
|
|
91
|
+
./LocalDataIndicator.js 2.19 KB (entry point)
|
|
80
92
|
./SaveToStudioButton.js 2.32 KB (entry point)
|
|
81
|
-
./SpecEditorPanel.js 19.63 KB (entry point)
|
|
82
|
-
hooks/useSpecContent.js 14.29 KB (entry point)
|
|
83
|
-
utils/generateSpecFromTemplate.js 9.64 KB (entry point)
|
|
84
93
|
lib/runtime-context.js 422 bytes (entry point)
|
|
85
94
|
|
|
86
95
|
$ contractspec-bun-build types
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,35 @@
|
|
|
1
1
|
# @contractspec/lib.example-shared-ui
|
|
2
2
|
|
|
3
|
+
## 4.0.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 230bdf6: feat: ai-chat wireing
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- 66c51da: feat(example-shared-ui): add SpecDrivenTemplateShell, ExampleTemplateBundle, bundles export
|
|
12
|
+
- Add SpecDrivenTemplateShell component
|
|
13
|
+
- Add ExampleTemplateBundle and bundles/index
|
|
14
|
+
- Add optional peer @contractspec/lib.surface-runtime
|
|
15
|
+
|
|
16
|
+
- Updated dependencies [1fa29a0]
|
|
17
|
+
- Updated dependencies [230bdf6]
|
|
18
|
+
- @contractspec/lib.surface-runtime@0.3.0
|
|
19
|
+
- @contractspec/lib.contracts-spec@3.5.0
|
|
20
|
+
- @contractspec/lib.design-system@3.5.0
|
|
21
|
+
- @contractspec/lib.ui-kit-web@3.5.0
|
|
22
|
+
|
|
23
|
+
## 3.4.3
|
|
24
|
+
|
|
25
|
+
### Patch Changes
|
|
26
|
+
|
|
27
|
+
- 5f7c617: feat: improve ai docs
|
|
28
|
+
- Updated dependencies [5f7c617]
|
|
29
|
+
- @contractspec/lib.contracts-spec@3.4.3
|
|
30
|
+
- @contractspec/lib.design-system@3.4.3
|
|
31
|
+
- @contractspec/lib.ui-kit-web@3.4.3
|
|
32
|
+
|
|
3
33
|
## 3.4.2
|
|
4
34
|
|
|
5
35
|
### Patch Changes
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
import type { ResolvedSurfacePlan } from '@contractspec/lib.surface-runtime/runtime/resolve-bundle';
|
|
3
|
+
import { type SaveToStudioButtonProps } from './SaveToStudioButton';
|
|
4
|
+
export interface SpecDrivenTemplateShellProps {
|
|
5
|
+
plan: ResolvedSurfacePlan;
|
|
6
|
+
title: string;
|
|
7
|
+
description?: string;
|
|
8
|
+
sidebar?: ReactNode;
|
|
9
|
+
actions?: ReactNode;
|
|
10
|
+
children: ReactNode;
|
|
11
|
+
showSaveAction?: boolean;
|
|
12
|
+
saveProps?: SaveToStudioButtonProps;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Template shell driven by surface-runtime bundle spec.
|
|
16
|
+
* Uses BundleRenderer for adaptive, preference-driven layouts.
|
|
17
|
+
* Requires @contractspec/lib.surface-runtime as peer dependency.
|
|
18
|
+
*/
|
|
19
|
+
export declare function SpecDrivenTemplateShell({ plan, title, description, sidebar, actions, showSaveAction, saveProps, children, }: SpecDrivenTemplateShellProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// src/lib/runtime-context.tsx
|
|
3
|
+
import { createContext, useContext } from "react";
|
|
4
|
+
"use client";
|
|
5
|
+
var TemplateRuntimeContext = createContext(null);
|
|
6
|
+
function useTemplateRuntime() {
|
|
7
|
+
const context = useContext(TemplateRuntimeContext);
|
|
8
|
+
if (!context) {
|
|
9
|
+
throw new Error("useTemplateRuntime must be used within a TemplateRuntimeProvider");
|
|
10
|
+
}
|
|
11
|
+
return context;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// src/LocalDataIndicator.tsx
|
|
15
|
+
import { RefreshCw, Shield } from "lucide-react";
|
|
16
|
+
import { useState } from "react";
|
|
17
|
+
import { jsxDEV } from "react/jsx-dev-runtime";
|
|
18
|
+
"use client";
|
|
19
|
+
function LocalDataIndicator() {
|
|
20
|
+
const { projectId, templateId, template, installer } = useTemplateRuntime();
|
|
21
|
+
const [isResetting, setIsResetting] = useState(false);
|
|
22
|
+
const handleReset = async () => {
|
|
23
|
+
setIsResetting(true);
|
|
24
|
+
try {
|
|
25
|
+
await installer.install(templateId, { projectId });
|
|
26
|
+
} finally {
|
|
27
|
+
setIsResetting(false);
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
return /* @__PURE__ */ jsxDEV("div", {
|
|
31
|
+
className: "border-border bg-muted/40 text-muted-foreground inline-flex items-center gap-2 rounded-full border px-3 py-1 text-xs",
|
|
32
|
+
children: [
|
|
33
|
+
/* @__PURE__ */ jsxDEV(Shield, {
|
|
34
|
+
className: "h-3.5 w-3.5 text-violet-400"
|
|
35
|
+
}, undefined, false, undefined, this),
|
|
36
|
+
/* @__PURE__ */ jsxDEV("span", {
|
|
37
|
+
children: [
|
|
38
|
+
"Local runtime \xB7",
|
|
39
|
+
" ",
|
|
40
|
+
/* @__PURE__ */ jsxDEV("span", {
|
|
41
|
+
className: "text-foreground font-semibold",
|
|
42
|
+
children: template.name
|
|
43
|
+
}, undefined, false, undefined, this)
|
|
44
|
+
]
|
|
45
|
+
}, undefined, true, undefined, this),
|
|
46
|
+
/* @__PURE__ */ jsxDEV("button", {
|
|
47
|
+
type: "button",
|
|
48
|
+
className: "border-border text-muted-foreground hover:text-foreground inline-flex items-center gap-1 rounded-full border px-2 py-0.5 text-[11px] font-semibold",
|
|
49
|
+
onClick: handleReset,
|
|
50
|
+
disabled: isResetting,
|
|
51
|
+
children: [
|
|
52
|
+
/* @__PURE__ */ jsxDEV(RefreshCw, {
|
|
53
|
+
className: "h-3 w-3"
|
|
54
|
+
}, undefined, false, undefined, this),
|
|
55
|
+
isResetting ? "Resetting\u2026" : "Reset data"
|
|
56
|
+
]
|
|
57
|
+
}, undefined, true, undefined, this)
|
|
58
|
+
]
|
|
59
|
+
}, undefined, true, undefined, this);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// src/SaveToStudioButton.tsx
|
|
63
|
+
import { useState as useState2 } from "react";
|
|
64
|
+
import { Sparkles } from "lucide-react";
|
|
65
|
+
import { jsxDEV as jsxDEV2 } from "react/jsx-dev-runtime";
|
|
66
|
+
"use client";
|
|
67
|
+
function SaveToStudioButton({
|
|
68
|
+
organizationId = "demo-org",
|
|
69
|
+
projectName,
|
|
70
|
+
endpoint,
|
|
71
|
+
token
|
|
72
|
+
}) {
|
|
73
|
+
const { installer, templateId, template } = useTemplateRuntime();
|
|
74
|
+
const [status, setStatus] = useState2("idle");
|
|
75
|
+
const [error, setError] = useState2(null);
|
|
76
|
+
const handleSave = async () => {
|
|
77
|
+
setStatus("saving");
|
|
78
|
+
setError(null);
|
|
79
|
+
try {
|
|
80
|
+
await installer.saveToStudio({
|
|
81
|
+
templateId,
|
|
82
|
+
projectName: projectName ?? `${template.name} demo`,
|
|
83
|
+
organizationId,
|
|
84
|
+
endpoint,
|
|
85
|
+
token
|
|
86
|
+
});
|
|
87
|
+
setStatus("saved");
|
|
88
|
+
setTimeout(() => setStatus("idle"), 3000);
|
|
89
|
+
} catch (err) {
|
|
90
|
+
setStatus("error");
|
|
91
|
+
setError(err instanceof Error ? err.message : "Unknown error");
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
return /* @__PURE__ */ jsxDEV2("div", {
|
|
95
|
+
className: "flex flex-col items-end gap-1",
|
|
96
|
+
children: [
|
|
97
|
+
/* @__PURE__ */ jsxDEV2("button", {
|
|
98
|
+
type: "button",
|
|
99
|
+
className: "btn-primary inline-flex items-center gap-2 text-sm",
|
|
100
|
+
onClick: handleSave,
|
|
101
|
+
disabled: status === "saving",
|
|
102
|
+
children: [
|
|
103
|
+
/* @__PURE__ */ jsxDEV2(Sparkles, {
|
|
104
|
+
className: "h-4 w-4"
|
|
105
|
+
}, undefined, false, undefined, this),
|
|
106
|
+
status === "saving" ? "Publishing\u2026" : "Save to Studio"
|
|
107
|
+
]
|
|
108
|
+
}, undefined, true, undefined, this),
|
|
109
|
+
status === "error" && error ? /* @__PURE__ */ jsxDEV2("p", {
|
|
110
|
+
className: "text-destructive text-xs",
|
|
111
|
+
children: error
|
|
112
|
+
}, undefined, false, undefined, this) : null,
|
|
113
|
+
status === "saved" ? /* @__PURE__ */ jsxDEV2("p", {
|
|
114
|
+
className: "text-xs text-emerald-400",
|
|
115
|
+
children: "Template sent to Studio."
|
|
116
|
+
}, undefined, false, undefined, this) : null
|
|
117
|
+
]
|
|
118
|
+
}, undefined, true, undefined, this);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// src/SpecDrivenTemplateShell.tsx
|
|
122
|
+
import { BundleProvider, BundleRenderer } from "@contractspec/lib.surface-runtime/react";
|
|
123
|
+
import { jsxDEV as jsxDEV3 } from "react/jsx-dev-runtime";
|
|
124
|
+
function SpecDrivenTemplateShell({
|
|
125
|
+
plan,
|
|
126
|
+
title,
|
|
127
|
+
description,
|
|
128
|
+
sidebar,
|
|
129
|
+
actions,
|
|
130
|
+
showSaveAction = true,
|
|
131
|
+
saveProps,
|
|
132
|
+
children
|
|
133
|
+
}) {
|
|
134
|
+
const headerContent = /* @__PURE__ */ jsxDEV3("header", {
|
|
135
|
+
className: "border-border bg-card rounded-2xl border p-6 shadow-sm",
|
|
136
|
+
children: [
|
|
137
|
+
/* @__PURE__ */ jsxDEV3("div", {
|
|
138
|
+
className: "flex flex-wrap items-center justify-between gap-4",
|
|
139
|
+
children: [
|
|
140
|
+
/* @__PURE__ */ jsxDEV3("div", {
|
|
141
|
+
children: [
|
|
142
|
+
/* @__PURE__ */ jsxDEV3("p", {
|
|
143
|
+
className: "text-muted-foreground text-sm font-semibold tracking-wide uppercase",
|
|
144
|
+
children: "ContractSpec Templates"
|
|
145
|
+
}, undefined, false, undefined, this),
|
|
146
|
+
/* @__PURE__ */ jsxDEV3("h1", {
|
|
147
|
+
className: "text-3xl font-bold",
|
|
148
|
+
children: title
|
|
149
|
+
}, undefined, false, undefined, this),
|
|
150
|
+
description ? /* @__PURE__ */ jsxDEV3("p", {
|
|
151
|
+
className: "text-muted-foreground mt-2 max-w-2xl text-sm",
|
|
152
|
+
children: description
|
|
153
|
+
}, undefined, false, undefined, this) : null
|
|
154
|
+
]
|
|
155
|
+
}, undefined, true, undefined, this),
|
|
156
|
+
/* @__PURE__ */ jsxDEV3("div", {
|
|
157
|
+
className: "flex flex-col items-end gap-2",
|
|
158
|
+
children: [
|
|
159
|
+
/* @__PURE__ */ jsxDEV3(LocalDataIndicator, {}, undefined, false, undefined, this),
|
|
160
|
+
showSaveAction ? /* @__PURE__ */ jsxDEV3(SaveToStudioButton, {
|
|
161
|
+
...saveProps
|
|
162
|
+
}, undefined, false, undefined, this) : null
|
|
163
|
+
]
|
|
164
|
+
}, undefined, true, undefined, this)
|
|
165
|
+
]
|
|
166
|
+
}, undefined, true, undefined, this),
|
|
167
|
+
actions ? /* @__PURE__ */ jsxDEV3("div", {
|
|
168
|
+
className: "mt-4",
|
|
169
|
+
children: actions
|
|
170
|
+
}, undefined, false, undefined, this) : null
|
|
171
|
+
]
|
|
172
|
+
}, undefined, true, undefined, this);
|
|
173
|
+
const slotContent = {
|
|
174
|
+
header: headerContent,
|
|
175
|
+
primary: /* @__PURE__ */ jsxDEV3("main", {
|
|
176
|
+
className: "space-y-4 p-2",
|
|
177
|
+
children
|
|
178
|
+
}, undefined, false, undefined, this)
|
|
179
|
+
};
|
|
180
|
+
if (sidebar != null) {
|
|
181
|
+
slotContent.sidebar = /* @__PURE__ */ jsxDEV3("aside", {
|
|
182
|
+
className: "border-border bg-card rounded-2xl border p-4",
|
|
183
|
+
children: sidebar
|
|
184
|
+
}, undefined, false, undefined, this);
|
|
185
|
+
}
|
|
186
|
+
return /* @__PURE__ */ jsxDEV3(BundleProvider, {
|
|
187
|
+
plan,
|
|
188
|
+
children: /* @__PURE__ */ jsxDEV3(BundleRenderer, {
|
|
189
|
+
slotContent
|
|
190
|
+
}, undefined, false, undefined, this)
|
|
191
|
+
}, undefined, false, undefined, this);
|
|
192
|
+
}
|
|
193
|
+
export {
|
|
194
|
+
SpecDrivenTemplateShell
|
|
195
|
+
};
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
// src/lib/runtime-context.tsx
|
|
2
|
+
import { createContext, useContext } from "react";
|
|
3
|
+
"use client";
|
|
4
|
+
var TemplateRuntimeContext = createContext(null);
|
|
5
|
+
function useTemplateRuntime() {
|
|
6
|
+
const context = useContext(TemplateRuntimeContext);
|
|
7
|
+
if (!context) {
|
|
8
|
+
throw new Error("useTemplateRuntime must be used within a TemplateRuntimeProvider");
|
|
9
|
+
}
|
|
10
|
+
return context;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// src/LocalDataIndicator.tsx
|
|
14
|
+
import { RefreshCw, Shield } from "lucide-react";
|
|
15
|
+
import { useState } from "react";
|
|
16
|
+
import { jsxDEV } from "react/jsx-dev-runtime";
|
|
17
|
+
"use client";
|
|
18
|
+
function LocalDataIndicator() {
|
|
19
|
+
const { projectId, templateId, template, installer } = useTemplateRuntime();
|
|
20
|
+
const [isResetting, setIsResetting] = useState(false);
|
|
21
|
+
const handleReset = async () => {
|
|
22
|
+
setIsResetting(true);
|
|
23
|
+
try {
|
|
24
|
+
await installer.install(templateId, { projectId });
|
|
25
|
+
} finally {
|
|
26
|
+
setIsResetting(false);
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
return /* @__PURE__ */ jsxDEV("div", {
|
|
30
|
+
className: "border-border bg-muted/40 text-muted-foreground inline-flex items-center gap-2 rounded-full border px-3 py-1 text-xs",
|
|
31
|
+
children: [
|
|
32
|
+
/* @__PURE__ */ jsxDEV(Shield, {
|
|
33
|
+
className: "h-3.5 w-3.5 text-violet-400"
|
|
34
|
+
}, undefined, false, undefined, this),
|
|
35
|
+
/* @__PURE__ */ jsxDEV("span", {
|
|
36
|
+
children: [
|
|
37
|
+
"Local runtime ·",
|
|
38
|
+
" ",
|
|
39
|
+
/* @__PURE__ */ jsxDEV("span", {
|
|
40
|
+
className: "text-foreground font-semibold",
|
|
41
|
+
children: template.name
|
|
42
|
+
}, undefined, false, undefined, this)
|
|
43
|
+
]
|
|
44
|
+
}, undefined, true, undefined, this),
|
|
45
|
+
/* @__PURE__ */ jsxDEV("button", {
|
|
46
|
+
type: "button",
|
|
47
|
+
className: "border-border text-muted-foreground hover:text-foreground inline-flex items-center gap-1 rounded-full border px-2 py-0.5 text-[11px] font-semibold",
|
|
48
|
+
onClick: handleReset,
|
|
49
|
+
disabled: isResetting,
|
|
50
|
+
children: [
|
|
51
|
+
/* @__PURE__ */ jsxDEV(RefreshCw, {
|
|
52
|
+
className: "h-3 w-3"
|
|
53
|
+
}, undefined, false, undefined, this),
|
|
54
|
+
isResetting ? "Resetting…" : "Reset data"
|
|
55
|
+
]
|
|
56
|
+
}, undefined, true, undefined, this)
|
|
57
|
+
]
|
|
58
|
+
}, undefined, true, undefined, this);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// src/SaveToStudioButton.tsx
|
|
62
|
+
import { useState as useState2 } from "react";
|
|
63
|
+
import { Sparkles } from "lucide-react";
|
|
64
|
+
import { jsxDEV as jsxDEV2 } from "react/jsx-dev-runtime";
|
|
65
|
+
"use client";
|
|
66
|
+
function SaveToStudioButton({
|
|
67
|
+
organizationId = "demo-org",
|
|
68
|
+
projectName,
|
|
69
|
+
endpoint,
|
|
70
|
+
token
|
|
71
|
+
}) {
|
|
72
|
+
const { installer, templateId, template } = useTemplateRuntime();
|
|
73
|
+
const [status, setStatus] = useState2("idle");
|
|
74
|
+
const [error, setError] = useState2(null);
|
|
75
|
+
const handleSave = async () => {
|
|
76
|
+
setStatus("saving");
|
|
77
|
+
setError(null);
|
|
78
|
+
try {
|
|
79
|
+
await installer.saveToStudio({
|
|
80
|
+
templateId,
|
|
81
|
+
projectName: projectName ?? `${template.name} demo`,
|
|
82
|
+
organizationId,
|
|
83
|
+
endpoint,
|
|
84
|
+
token
|
|
85
|
+
});
|
|
86
|
+
setStatus("saved");
|
|
87
|
+
setTimeout(() => setStatus("idle"), 3000);
|
|
88
|
+
} catch (err) {
|
|
89
|
+
setStatus("error");
|
|
90
|
+
setError(err instanceof Error ? err.message : "Unknown error");
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
return /* @__PURE__ */ jsxDEV2("div", {
|
|
94
|
+
className: "flex flex-col items-end gap-1",
|
|
95
|
+
children: [
|
|
96
|
+
/* @__PURE__ */ jsxDEV2("button", {
|
|
97
|
+
type: "button",
|
|
98
|
+
className: "btn-primary inline-flex items-center gap-2 text-sm",
|
|
99
|
+
onClick: handleSave,
|
|
100
|
+
disabled: status === "saving",
|
|
101
|
+
children: [
|
|
102
|
+
/* @__PURE__ */ jsxDEV2(Sparkles, {
|
|
103
|
+
className: "h-4 w-4"
|
|
104
|
+
}, undefined, false, undefined, this),
|
|
105
|
+
status === "saving" ? "Publishing…" : "Save to Studio"
|
|
106
|
+
]
|
|
107
|
+
}, undefined, true, undefined, this),
|
|
108
|
+
status === "error" && error ? /* @__PURE__ */ jsxDEV2("p", {
|
|
109
|
+
className: "text-destructive text-xs",
|
|
110
|
+
children: error
|
|
111
|
+
}, undefined, false, undefined, this) : null,
|
|
112
|
+
status === "saved" ? /* @__PURE__ */ jsxDEV2("p", {
|
|
113
|
+
className: "text-xs text-emerald-400",
|
|
114
|
+
children: "Template sent to Studio."
|
|
115
|
+
}, undefined, false, undefined, this) : null
|
|
116
|
+
]
|
|
117
|
+
}, undefined, true, undefined, this);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// src/SpecDrivenTemplateShell.tsx
|
|
121
|
+
import { BundleProvider, BundleRenderer } from "@contractspec/lib.surface-runtime/react";
|
|
122
|
+
import { jsxDEV as jsxDEV3 } from "react/jsx-dev-runtime";
|
|
123
|
+
function SpecDrivenTemplateShell({
|
|
124
|
+
plan,
|
|
125
|
+
title,
|
|
126
|
+
description,
|
|
127
|
+
sidebar,
|
|
128
|
+
actions,
|
|
129
|
+
showSaveAction = true,
|
|
130
|
+
saveProps,
|
|
131
|
+
children
|
|
132
|
+
}) {
|
|
133
|
+
const headerContent = /* @__PURE__ */ jsxDEV3("header", {
|
|
134
|
+
className: "border-border bg-card rounded-2xl border p-6 shadow-sm",
|
|
135
|
+
children: [
|
|
136
|
+
/* @__PURE__ */ jsxDEV3("div", {
|
|
137
|
+
className: "flex flex-wrap items-center justify-between gap-4",
|
|
138
|
+
children: [
|
|
139
|
+
/* @__PURE__ */ jsxDEV3("div", {
|
|
140
|
+
children: [
|
|
141
|
+
/* @__PURE__ */ jsxDEV3("p", {
|
|
142
|
+
className: "text-muted-foreground text-sm font-semibold tracking-wide uppercase",
|
|
143
|
+
children: "ContractSpec Templates"
|
|
144
|
+
}, undefined, false, undefined, this),
|
|
145
|
+
/* @__PURE__ */ jsxDEV3("h1", {
|
|
146
|
+
className: "text-3xl font-bold",
|
|
147
|
+
children: title
|
|
148
|
+
}, undefined, false, undefined, this),
|
|
149
|
+
description ? /* @__PURE__ */ jsxDEV3("p", {
|
|
150
|
+
className: "text-muted-foreground mt-2 max-w-2xl text-sm",
|
|
151
|
+
children: description
|
|
152
|
+
}, undefined, false, undefined, this) : null
|
|
153
|
+
]
|
|
154
|
+
}, undefined, true, undefined, this),
|
|
155
|
+
/* @__PURE__ */ jsxDEV3("div", {
|
|
156
|
+
className: "flex flex-col items-end gap-2",
|
|
157
|
+
children: [
|
|
158
|
+
/* @__PURE__ */ jsxDEV3(LocalDataIndicator, {}, undefined, false, undefined, this),
|
|
159
|
+
showSaveAction ? /* @__PURE__ */ jsxDEV3(SaveToStudioButton, {
|
|
160
|
+
...saveProps
|
|
161
|
+
}, undefined, false, undefined, this) : null
|
|
162
|
+
]
|
|
163
|
+
}, undefined, true, undefined, this)
|
|
164
|
+
]
|
|
165
|
+
}, undefined, true, undefined, this),
|
|
166
|
+
actions ? /* @__PURE__ */ jsxDEV3("div", {
|
|
167
|
+
className: "mt-4",
|
|
168
|
+
children: actions
|
|
169
|
+
}, undefined, false, undefined, this) : null
|
|
170
|
+
]
|
|
171
|
+
}, undefined, true, undefined, this);
|
|
172
|
+
const slotContent = {
|
|
173
|
+
header: headerContent,
|
|
174
|
+
primary: /* @__PURE__ */ jsxDEV3("main", {
|
|
175
|
+
className: "space-y-4 p-2",
|
|
176
|
+
children
|
|
177
|
+
}, undefined, false, undefined, this)
|
|
178
|
+
};
|
|
179
|
+
if (sidebar != null) {
|
|
180
|
+
slotContent.sidebar = /* @__PURE__ */ jsxDEV3("aside", {
|
|
181
|
+
className: "border-border bg-card rounded-2xl border p-4",
|
|
182
|
+
children: sidebar
|
|
183
|
+
}, undefined, false, undefined, this);
|
|
184
|
+
}
|
|
185
|
+
return /* @__PURE__ */ jsxDEV3(BundleProvider, {
|
|
186
|
+
plan,
|
|
187
|
+
children: /* @__PURE__ */ jsxDEV3(BundleRenderer, {
|
|
188
|
+
slotContent
|
|
189
|
+
}, undefined, false, undefined, this)
|
|
190
|
+
}, undefined, false, undefined, this);
|
|
191
|
+
}
|
|
192
|
+
export {
|
|
193
|
+
SpecDrivenTemplateShell
|
|
194
|
+
};
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
// src/bundles/ExampleTemplateBundle.ts
|
|
2
|
+
import { defineModuleBundle } from "@contractspec/lib.surface-runtime/spec";
|
|
3
|
+
var ExampleTemplateBundle = defineModuleBundle({
|
|
4
|
+
meta: {
|
|
5
|
+
key: "example.template",
|
|
6
|
+
version: "0.1.0",
|
|
7
|
+
title: "Example Template",
|
|
8
|
+
description: "Adaptive template shell for ContractSpec examples",
|
|
9
|
+
owners: ["team-platform"],
|
|
10
|
+
tags: ["example", "template"],
|
|
11
|
+
stability: "experimental"
|
|
12
|
+
},
|
|
13
|
+
routes: [
|
|
14
|
+
{
|
|
15
|
+
routeId: "template",
|
|
16
|
+
path: "/sandbox",
|
|
17
|
+
defaultSurface: "template-shell"
|
|
18
|
+
}
|
|
19
|
+
],
|
|
20
|
+
surfaces: {
|
|
21
|
+
"template-shell": {
|
|
22
|
+
surfaceId: "template-shell",
|
|
23
|
+
kind: "workbench",
|
|
24
|
+
title: "Template Shell",
|
|
25
|
+
slots: [
|
|
26
|
+
{
|
|
27
|
+
slotId: "header",
|
|
28
|
+
role: "header",
|
|
29
|
+
accepts: ["action-bar"],
|
|
30
|
+
cardinality: "many"
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
slotId: "primary",
|
|
34
|
+
role: "primary",
|
|
35
|
+
accepts: ["entity-section", "rich-doc", "form", "custom-widget"],
|
|
36
|
+
cardinality: "many"
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
slotId: "sidebar",
|
|
40
|
+
role: "secondary",
|
|
41
|
+
accepts: ["entity-section", "custom-widget"],
|
|
42
|
+
cardinality: "one"
|
|
43
|
+
}
|
|
44
|
+
],
|
|
45
|
+
layouts: [
|
|
46
|
+
{
|
|
47
|
+
layoutId: "main-with-sidebar",
|
|
48
|
+
title: "Main with sidebar",
|
|
49
|
+
root: {
|
|
50
|
+
type: "panel-group",
|
|
51
|
+
direction: "horizontal",
|
|
52
|
+
persistKey: "example.template.main-sidebar",
|
|
53
|
+
children: [
|
|
54
|
+
{
|
|
55
|
+
type: "panel-group",
|
|
56
|
+
direction: "vertical",
|
|
57
|
+
persistKey: "example.template.content",
|
|
58
|
+
children: [
|
|
59
|
+
{ type: "slot", slotId: "header" },
|
|
60
|
+
{ type: "slot", slotId: "primary" }
|
|
61
|
+
]
|
|
62
|
+
},
|
|
63
|
+
{ type: "slot", slotId: "sidebar" }
|
|
64
|
+
]
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
],
|
|
68
|
+
data: [],
|
|
69
|
+
verification: {
|
|
70
|
+
dimensions: {
|
|
71
|
+
guidance: "Can reveal hints and walkthrough notes.",
|
|
72
|
+
density: "Can select compact or balanced layouts.",
|
|
73
|
+
dataDepth: "Controls content depth and expansion.",
|
|
74
|
+
control: "Shows advanced options when allowed.",
|
|
75
|
+
media: "Supports text-first and hybrid modes.",
|
|
76
|
+
pace: "Maps to motion tokens and transitions.",
|
|
77
|
+
narrative: "Can order summary before or after detail."
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
export {
|
|
84
|
+
ExampleTemplateBundle
|
|
85
|
+
};
|