@contractspec/lib.example-shared-ui 3.4.3 → 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 +20 -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/dist/index.js
CHANGED
|
@@ -2129,6 +2129,79 @@ function SaveToStudioButton({
|
|
|
2129
2129
|
}, undefined, true, undefined, this);
|
|
2130
2130
|
}
|
|
2131
2131
|
|
|
2132
|
+
// src/SpecDrivenTemplateShell.tsx
|
|
2133
|
+
import { BundleProvider, BundleRenderer } from "@contractspec/lib.surface-runtime/react";
|
|
2134
|
+
import { jsxDEV as jsxDEV8 } from "react/jsx-dev-runtime";
|
|
2135
|
+
function SpecDrivenTemplateShell({
|
|
2136
|
+
plan,
|
|
2137
|
+
title,
|
|
2138
|
+
description,
|
|
2139
|
+
sidebar,
|
|
2140
|
+
actions,
|
|
2141
|
+
showSaveAction = true,
|
|
2142
|
+
saveProps,
|
|
2143
|
+
children
|
|
2144
|
+
}) {
|
|
2145
|
+
const headerContent = /* @__PURE__ */ jsxDEV8("header", {
|
|
2146
|
+
className: "border-border bg-card rounded-2xl border p-6 shadow-sm",
|
|
2147
|
+
children: [
|
|
2148
|
+
/* @__PURE__ */ jsxDEV8("div", {
|
|
2149
|
+
className: "flex flex-wrap items-center justify-between gap-4",
|
|
2150
|
+
children: [
|
|
2151
|
+
/* @__PURE__ */ jsxDEV8("div", {
|
|
2152
|
+
children: [
|
|
2153
|
+
/* @__PURE__ */ jsxDEV8("p", {
|
|
2154
|
+
className: "text-muted-foreground text-sm font-semibold tracking-wide uppercase",
|
|
2155
|
+
children: "ContractSpec Templates"
|
|
2156
|
+
}, undefined, false, undefined, this),
|
|
2157
|
+
/* @__PURE__ */ jsxDEV8("h1", {
|
|
2158
|
+
className: "text-3xl font-bold",
|
|
2159
|
+
children: title
|
|
2160
|
+
}, undefined, false, undefined, this),
|
|
2161
|
+
description ? /* @__PURE__ */ jsxDEV8("p", {
|
|
2162
|
+
className: "text-muted-foreground mt-2 max-w-2xl text-sm",
|
|
2163
|
+
children: description
|
|
2164
|
+
}, undefined, false, undefined, this) : null
|
|
2165
|
+
]
|
|
2166
|
+
}, undefined, true, undefined, this),
|
|
2167
|
+
/* @__PURE__ */ jsxDEV8("div", {
|
|
2168
|
+
className: "flex flex-col items-end gap-2",
|
|
2169
|
+
children: [
|
|
2170
|
+
/* @__PURE__ */ jsxDEV8(LocalDataIndicator, {}, undefined, false, undefined, this),
|
|
2171
|
+
showSaveAction ? /* @__PURE__ */ jsxDEV8(SaveToStudioButton, {
|
|
2172
|
+
...saveProps
|
|
2173
|
+
}, undefined, false, undefined, this) : null
|
|
2174
|
+
]
|
|
2175
|
+
}, undefined, true, undefined, this)
|
|
2176
|
+
]
|
|
2177
|
+
}, undefined, true, undefined, this),
|
|
2178
|
+
actions ? /* @__PURE__ */ jsxDEV8("div", {
|
|
2179
|
+
className: "mt-4",
|
|
2180
|
+
children: actions
|
|
2181
|
+
}, undefined, false, undefined, this) : null
|
|
2182
|
+
]
|
|
2183
|
+
}, undefined, true, undefined, this);
|
|
2184
|
+
const slotContent = {
|
|
2185
|
+
header: headerContent,
|
|
2186
|
+
primary: /* @__PURE__ */ jsxDEV8("main", {
|
|
2187
|
+
className: "space-y-4 p-2",
|
|
2188
|
+
children
|
|
2189
|
+
}, undefined, false, undefined, this)
|
|
2190
|
+
};
|
|
2191
|
+
if (sidebar != null) {
|
|
2192
|
+
slotContent.sidebar = /* @__PURE__ */ jsxDEV8("aside", {
|
|
2193
|
+
className: "border-border bg-card rounded-2xl border p-4",
|
|
2194
|
+
children: sidebar
|
|
2195
|
+
}, undefined, false, undefined, this);
|
|
2196
|
+
}
|
|
2197
|
+
return /* @__PURE__ */ jsxDEV8(BundleProvider, {
|
|
2198
|
+
plan,
|
|
2199
|
+
children: /* @__PURE__ */ jsxDEV8(BundleRenderer, {
|
|
2200
|
+
slotContent
|
|
2201
|
+
}, undefined, false, undefined, this)
|
|
2202
|
+
}, undefined, false, undefined, this);
|
|
2203
|
+
}
|
|
2204
|
+
|
|
2132
2205
|
// src/utils/generateSpecFromTemplate.ts
|
|
2133
2206
|
function generateSpecFromTemplate(template) {
|
|
2134
2207
|
const templateId = template?.id ?? "unknown";
|
|
@@ -2698,7 +2771,7 @@ function useSpecContent(templateId) {
|
|
|
2698
2771
|
import { useCallback as useCallback8, useEffect as useEffect5 } from "react";
|
|
2699
2772
|
import { Button as Button5, LoaderBlock as LoaderBlock3 } from "@contractspec/lib.design-system";
|
|
2700
2773
|
import { Badge as Badge5 } from "@contractspec/lib.ui-kit-web/ui/badge";
|
|
2701
|
-
import { jsxDEV as
|
|
2774
|
+
import { jsxDEV as jsxDEV9 } from "react/jsx-dev-runtime";
|
|
2702
2775
|
"use client";
|
|
2703
2776
|
function SpecEditorPanel({
|
|
2704
2777
|
templateId,
|
|
@@ -2740,54 +2813,54 @@ function SpecEditorPanel({
|
|
|
2740
2813
|
onLog?.("Spec reset to template defaults");
|
|
2741
2814
|
}, [reset, onLog]);
|
|
2742
2815
|
if (loading) {
|
|
2743
|
-
return /* @__PURE__ */
|
|
2816
|
+
return /* @__PURE__ */ jsxDEV9(LoaderBlock3, {
|
|
2744
2817
|
label: "Loading spec..."
|
|
2745
2818
|
}, undefined, false, undefined, this);
|
|
2746
2819
|
}
|
|
2747
|
-
return /* @__PURE__ */
|
|
2820
|
+
return /* @__PURE__ */ jsxDEV9("div", {
|
|
2748
2821
|
className: "space-y-4",
|
|
2749
2822
|
children: [
|
|
2750
|
-
/* @__PURE__ */
|
|
2823
|
+
/* @__PURE__ */ jsxDEV9("div", {
|
|
2751
2824
|
className: "flex items-center justify-between",
|
|
2752
2825
|
children: [
|
|
2753
|
-
/* @__PURE__ */
|
|
2826
|
+
/* @__PURE__ */ jsxDEV9("div", {
|
|
2754
2827
|
className: "flex items-center gap-2",
|
|
2755
2828
|
children: [
|
|
2756
|
-
/* @__PURE__ */
|
|
2829
|
+
/* @__PURE__ */ jsxDEV9(Button5, {
|
|
2757
2830
|
variant: "default",
|
|
2758
2831
|
size: "sm",
|
|
2759
2832
|
onClick: handleSave,
|
|
2760
2833
|
children: "Save"
|
|
2761
2834
|
}, undefined, false, undefined, this),
|
|
2762
|
-
/* @__PURE__ */
|
|
2835
|
+
/* @__PURE__ */ jsxDEV9(Button5, {
|
|
2763
2836
|
variant: "outline",
|
|
2764
2837
|
size: "sm",
|
|
2765
2838
|
onClick: handleValidate,
|
|
2766
2839
|
children: "Validate"
|
|
2767
2840
|
}, undefined, false, undefined, this),
|
|
2768
|
-
isDirty && /* @__PURE__ */
|
|
2841
|
+
isDirty && /* @__PURE__ */ jsxDEV9(Badge5, {
|
|
2769
2842
|
variant: "secondary",
|
|
2770
2843
|
className: "border-amber-500/30 bg-amber-500/20 text-amber-400",
|
|
2771
2844
|
children: "Unsaved changes"
|
|
2772
2845
|
}, undefined, false, undefined, this),
|
|
2773
|
-
validation && /* @__PURE__ */
|
|
2846
|
+
validation && /* @__PURE__ */ jsxDEV9(Badge5, {
|
|
2774
2847
|
variant: validation.valid ? "default" : "destructive",
|
|
2775
2848
|
className: validation.valid ? "border-green-500/30 bg-green-500/20 text-green-400" : "",
|
|
2776
2849
|
children: validation.valid ? "Valid" : `${validation.errors.filter((e) => e.severity === "error").length} errors`
|
|
2777
2850
|
}, undefined, false, undefined, this)
|
|
2778
2851
|
]
|
|
2779
2852
|
}, undefined, true, undefined, this),
|
|
2780
|
-
/* @__PURE__ */
|
|
2853
|
+
/* @__PURE__ */ jsxDEV9("div", {
|
|
2781
2854
|
className: "flex items-center gap-2",
|
|
2782
2855
|
children: [
|
|
2783
|
-
lastSaved && /* @__PURE__ */
|
|
2856
|
+
lastSaved && /* @__PURE__ */ jsxDEV9("span", {
|
|
2784
2857
|
className: "text-muted-foreground text-xs",
|
|
2785
2858
|
children: [
|
|
2786
2859
|
"Last saved: ",
|
|
2787
2860
|
new Date(lastSaved).toLocaleTimeString()
|
|
2788
2861
|
]
|
|
2789
2862
|
}, undefined, true, undefined, this),
|
|
2790
|
-
/* @__PURE__ */
|
|
2863
|
+
/* @__PURE__ */ jsxDEV9(Button5, {
|
|
2791
2864
|
variant: "ghost",
|
|
2792
2865
|
size: "sm",
|
|
2793
2866
|
onPress: handleReset,
|
|
@@ -2797,16 +2870,16 @@ function SpecEditorPanel({
|
|
|
2797
2870
|
}, undefined, true, undefined, this)
|
|
2798
2871
|
]
|
|
2799
2872
|
}, undefined, true, undefined, this),
|
|
2800
|
-
validation && validation.errors.length > 0 && /* @__PURE__ */
|
|
2873
|
+
validation && validation.errors.length > 0 && /* @__PURE__ */ jsxDEV9("div", {
|
|
2801
2874
|
className: "rounded-lg border border-amber-500/50 bg-amber-500/10 p-3",
|
|
2802
2875
|
children: [
|
|
2803
|
-
/* @__PURE__ */
|
|
2876
|
+
/* @__PURE__ */ jsxDEV9("p", {
|
|
2804
2877
|
className: "mb-2 text-xs font-semibold text-amber-400 uppercase",
|
|
2805
2878
|
children: "Validation Issues"
|
|
2806
2879
|
}, undefined, false, undefined, this),
|
|
2807
|
-
/* @__PURE__ */
|
|
2880
|
+
/* @__PURE__ */ jsxDEV9("ul", {
|
|
2808
2881
|
className: "space-y-1",
|
|
2809
|
-
children: validation.errors.map((error, index) => /* @__PURE__ */
|
|
2882
|
+
children: validation.errors.map((error, index) => /* @__PURE__ */ jsxDEV9("li", {
|
|
2810
2883
|
className: `text-xs ${error.severity === "error" ? "text-red-400" : "text-amber-400"}`,
|
|
2811
2884
|
children: [
|
|
2812
2885
|
"Line ",
|
|
@@ -2818,9 +2891,9 @@ function SpecEditorPanel({
|
|
|
2818
2891
|
}, undefined, false, undefined, this)
|
|
2819
2892
|
]
|
|
2820
2893
|
}, undefined, true, undefined, this),
|
|
2821
|
-
/* @__PURE__ */
|
|
2894
|
+
/* @__PURE__ */ jsxDEV9("div", {
|
|
2822
2895
|
className: "border-border bg-card rounded-2xl border p-4",
|
|
2823
|
-
children: /* @__PURE__ */
|
|
2896
|
+
children: /* @__PURE__ */ jsxDEV9(SpecEditor, {
|
|
2824
2897
|
projectId: "sandbox",
|
|
2825
2898
|
type: "CAPABILITY",
|
|
2826
2899
|
content,
|
|
@@ -2835,7 +2908,7 @@ function SpecEditorPanel({
|
|
|
2835
2908
|
}
|
|
2836
2909
|
|
|
2837
2910
|
// src/TemplateShell.tsx
|
|
2838
|
-
import { jsxDEV as
|
|
2911
|
+
import { jsxDEV as jsxDEV10 } from "react/jsx-dev-runtime";
|
|
2839
2912
|
var TemplateShell = ({
|
|
2840
2913
|
title,
|
|
2841
2914
|
description,
|
|
@@ -2844,56 +2917,56 @@ var TemplateShell = ({
|
|
|
2844
2917
|
showSaveAction = true,
|
|
2845
2918
|
saveProps,
|
|
2846
2919
|
children
|
|
2847
|
-
}) => /* @__PURE__ */
|
|
2920
|
+
}) => /* @__PURE__ */ jsxDEV10("div", {
|
|
2848
2921
|
className: "space-y-6",
|
|
2849
2922
|
children: [
|
|
2850
|
-
/* @__PURE__ */
|
|
2923
|
+
/* @__PURE__ */ jsxDEV10("header", {
|
|
2851
2924
|
className: "border-border bg-card rounded-2xl border p-6 shadow-sm",
|
|
2852
2925
|
children: [
|
|
2853
|
-
/* @__PURE__ */
|
|
2926
|
+
/* @__PURE__ */ jsxDEV10("div", {
|
|
2854
2927
|
className: "flex flex-wrap items-center justify-between gap-4",
|
|
2855
2928
|
children: [
|
|
2856
|
-
/* @__PURE__ */
|
|
2929
|
+
/* @__PURE__ */ jsxDEV10("div", {
|
|
2857
2930
|
children: [
|
|
2858
|
-
/* @__PURE__ */
|
|
2931
|
+
/* @__PURE__ */ jsxDEV10("p", {
|
|
2859
2932
|
className: "text-muted-foreground text-sm font-semibold tracking-wide uppercase",
|
|
2860
2933
|
children: "ContractSpec Templates"
|
|
2861
2934
|
}, undefined, false, undefined, this),
|
|
2862
|
-
/* @__PURE__ */
|
|
2935
|
+
/* @__PURE__ */ jsxDEV10("h1", {
|
|
2863
2936
|
className: "text-3xl font-bold",
|
|
2864
2937
|
children: title
|
|
2865
2938
|
}, undefined, false, undefined, this),
|
|
2866
|
-
description ? /* @__PURE__ */
|
|
2939
|
+
description ? /* @__PURE__ */ jsxDEV10("p", {
|
|
2867
2940
|
className: "text-muted-foreground mt-2 max-w-2xl text-sm",
|
|
2868
2941
|
children: description
|
|
2869
2942
|
}, undefined, false, undefined, this) : null
|
|
2870
2943
|
]
|
|
2871
2944
|
}, undefined, true, undefined, this),
|
|
2872
|
-
/* @__PURE__ */
|
|
2945
|
+
/* @__PURE__ */ jsxDEV10("div", {
|
|
2873
2946
|
className: "flex flex-col items-end gap-2",
|
|
2874
2947
|
children: [
|
|
2875
|
-
/* @__PURE__ */
|
|
2876
|
-
showSaveAction ? /* @__PURE__ */
|
|
2948
|
+
/* @__PURE__ */ jsxDEV10(LocalDataIndicator, {}, undefined, false, undefined, this),
|
|
2949
|
+
showSaveAction ? /* @__PURE__ */ jsxDEV10(SaveToStudioButton, {
|
|
2877
2950
|
...saveProps
|
|
2878
2951
|
}, undefined, false, undefined, this) : null
|
|
2879
2952
|
]
|
|
2880
2953
|
}, undefined, true, undefined, this)
|
|
2881
2954
|
]
|
|
2882
2955
|
}, undefined, true, undefined, this),
|
|
2883
|
-
actions ? /* @__PURE__ */
|
|
2956
|
+
actions ? /* @__PURE__ */ jsxDEV10("div", {
|
|
2884
2957
|
className: "mt-4",
|
|
2885
2958
|
children: actions
|
|
2886
2959
|
}, undefined, false, undefined, this) : null
|
|
2887
2960
|
]
|
|
2888
2961
|
}, undefined, true, undefined, this),
|
|
2889
|
-
/* @__PURE__ */
|
|
2962
|
+
/* @__PURE__ */ jsxDEV10("div", {
|
|
2890
2963
|
className: sidebar ? "grid gap-6 lg:grid-cols-[minmax(0,1fr)_320px]" : "w-full",
|
|
2891
2964
|
children: [
|
|
2892
|
-
/* @__PURE__ */
|
|
2965
|
+
/* @__PURE__ */ jsxDEV10("main", {
|
|
2893
2966
|
className: "space-y-4 p-2",
|
|
2894
2967
|
children
|
|
2895
2968
|
}, undefined, false, undefined, this),
|
|
2896
|
-
sidebar ? /* @__PURE__ */
|
|
2969
|
+
sidebar ? /* @__PURE__ */ jsxDEV10("aside", {
|
|
2897
2970
|
className: "border-border bg-card rounded-2xl border p-4",
|
|
2898
2971
|
children: sidebar
|
|
2899
2972
|
}, undefined, false, undefined, this) : null
|
|
@@ -3487,6 +3560,7 @@ export {
|
|
|
3487
3560
|
TemplateRuntimeContext,
|
|
3488
3561
|
TemplateComponentRegistry,
|
|
3489
3562
|
SpecEditorPanel,
|
|
3563
|
+
SpecDrivenTemplateShell,
|
|
3490
3564
|
SaveToStudioButton,
|
|
3491
3565
|
PersonalizationInsights,
|
|
3492
3566
|
OverlayContextProvider,
|
|
@@ -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
|
+
};
|
|
@@ -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
|
+
};
|