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