@contractspec/lib.example-shared-ui 1.10.1 → 1.12.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 +86 -11
- package/.turbo/turbo-prebuild.log +1 -0
- package/CHANGELOG.md +32 -0
- package/dist/EvolutionDashboard.d.ts +11 -0
- package/dist/EvolutionDashboard.d.ts.map +1 -0
- package/dist/EvolutionDashboard.js +804 -0
- package/dist/EvolutionSidebar.d.ts +19 -0
- package/dist/EvolutionSidebar.d.ts.map +1 -0
- package/dist/EvolutionSidebar.js +532 -0
- package/dist/LocalDataIndicator.d.ts +2 -0
- package/dist/LocalDataIndicator.d.ts.map +1 -0
- package/dist/LocalDataIndicator.js +63 -0
- package/dist/MarkdownView.d.ts +20 -0
- package/dist/MarkdownView.d.ts.map +1 -0
- package/dist/MarkdownView.js +304 -0
- package/dist/OverlayContextProvider.d.ts +79 -0
- package/dist/OverlayContextProvider.d.ts.map +1 -0
- package/dist/OverlayContextProvider.js +203 -0
- package/dist/PersonalizationInsights.d.ts +14 -0
- package/dist/PersonalizationInsights.d.ts.map +1 -0
- package/dist/PersonalizationInsights.js +456 -0
- package/dist/SaveToStudioButton.d.ts +8 -0
- package/dist/SaveToStudioButton.d.ts.map +1 -0
- package/dist/SaveToStudioButton.js +74 -0
- package/dist/SpecEditorPanel.d.ts +23 -0
- package/dist/SpecEditorPanel.d.ts.map +1 -0
- package/dist/SpecEditorPanel.js +720 -0
- package/dist/TemplateShell.d.ts +13 -0
- package/dist/TemplateShell.d.ts.map +1 -0
- package/dist/TemplateShell.js +190 -0
- package/dist/browser/EvolutionDashboard.js +803 -0
- package/dist/browser/EvolutionSidebar.js +531 -0
- package/dist/browser/LocalDataIndicator.js +62 -0
- package/dist/browser/MarkdownView.js +303 -0
- package/dist/browser/OverlayContextProvider.js +202 -0
- package/dist/browser/PersonalizationInsights.js +455 -0
- package/dist/browser/SaveToStudioButton.js +73 -0
- package/dist/browser/SpecEditorPanel.js +719 -0
- package/dist/browser/TemplateShell.js +189 -0
- package/dist/browser/hooks/index.js +1516 -0
- package/dist/browser/hooks/useBehaviorTracking.js +157 -0
- package/dist/browser/hooks/useEvolution.js +260 -0
- package/dist/browser/hooks/useRegistryTemplates.js +31 -0
- package/dist/browser/hooks/useSpecContent.js +579 -0
- package/dist/browser/hooks/useWorkflowComposer.js +493 -0
- package/dist/browser/index.js +3497 -0
- package/dist/browser/lib/component-registry.js +42 -0
- package/dist/browser/lib/runtime-context.js +15 -0
- package/dist/browser/lib/types.js +0 -0
- package/dist/browser/overlay-types.js +0 -0
- package/dist/browser/utils/fetchPresentationData.js +15 -0
- package/dist/browser/utils/generateSpecFromTemplate.js +423 -0
- package/dist/browser/utils/index.js +437 -0
- package/dist/hooks/index.d.ts +6 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/index.js +1517 -0
- package/dist/hooks/useBehaviorTracking.d.ts +56 -0
- package/dist/hooks/useBehaviorTracking.d.ts.map +1 -0
- package/dist/hooks/useBehaviorTracking.js +158 -0
- package/dist/hooks/useEvolution.d.ts +111 -0
- package/dist/hooks/useEvolution.d.ts.map +1 -0
- package/dist/hooks/useEvolution.js +261 -0
- package/dist/hooks/useRegistryTemplates.d.ts +10 -0
- package/dist/hooks/useRegistryTemplates.d.ts.map +1 -0
- package/dist/hooks/useRegistryTemplates.js +32 -0
- package/dist/hooks/useSpecContent.d.ts +41 -0
- package/dist/hooks/useSpecContent.d.ts.map +1 -0
- package/dist/hooks/useSpecContent.js +580 -0
- package/dist/hooks/useWorkflowComposer.d.ts +94 -0
- package/dist/hooks/useWorkflowComposer.d.ts.map +1 -0
- package/dist/hooks/useWorkflowComposer.js +494 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3498 -0
- package/dist/lib/component-registry.d.ts +18 -0
- package/dist/lib/component-registry.d.ts.map +1 -0
- package/dist/lib/component-registry.js +43 -0
- package/dist/lib/runtime-context.d.ts +29 -0
- package/dist/lib/runtime-context.d.ts.map +1 -0
- package/dist/lib/runtime-context.js +16 -0
- package/dist/lib/types.d.ts +69 -0
- package/dist/lib/types.d.ts.map +1 -0
- package/dist/lib/types.js +1 -0
- package/dist/node/EvolutionDashboard.js +803 -0
- package/dist/node/EvolutionSidebar.js +531 -0
- package/dist/node/LocalDataIndicator.js +62 -0
- package/dist/node/MarkdownView.js +303 -0
- package/dist/node/OverlayContextProvider.js +202 -0
- package/dist/node/PersonalizationInsights.js +455 -0
- package/dist/node/SaveToStudioButton.js +73 -0
- package/dist/node/SpecEditorPanel.js +719 -0
- package/dist/node/TemplateShell.js +189 -0
- package/dist/node/hooks/index.js +1516 -0
- package/dist/node/hooks/useBehaviorTracking.js +157 -0
- package/dist/node/hooks/useEvolution.js +260 -0
- package/dist/node/hooks/useRegistryTemplates.js +31 -0
- package/dist/node/hooks/useSpecContent.js +579 -0
- package/dist/node/hooks/useWorkflowComposer.js +493 -0
- package/dist/node/index.js +3497 -0
- package/dist/node/lib/component-registry.js +42 -0
- package/dist/node/lib/runtime-context.js +15 -0
- package/dist/node/lib/types.js +0 -0
- package/dist/node/overlay-types.js +0 -0
- package/dist/node/utils/fetchPresentationData.js +15 -0
- package/dist/node/utils/generateSpecFromTemplate.js +423 -0
- package/dist/node/utils/index.js +437 -0
- package/dist/overlay-types.d.ts +41 -0
- package/dist/overlay-types.d.ts.map +1 -0
- package/dist/overlay-types.js +1 -0
- package/dist/utils/fetchPresentationData.d.ts +34 -0
- package/dist/utils/fetchPresentationData.d.ts.map +1 -0
- package/dist/utils/fetchPresentationData.js +16 -0
- package/dist/utils/generateSpecFromTemplate.d.ts +7 -0
- package/dist/utils/generateSpecFromTemplate.d.ts.map +1 -0
- package/dist/utils/generateSpecFromTemplate.js +424 -0
- package/dist/utils/index.d.ts +3 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +438 -0
- package/package.json +222 -17
- package/.turbo/turbo-build$colon$bundle.log +0 -9
- package/dist/index.mjs +0 -3121
|
@@ -0,0 +1,304 @@
|
|
|
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/MarkdownView.tsx
|
|
15
|
+
import { useCallback, useEffect, useState } from "react";
|
|
16
|
+
import {
|
|
17
|
+
Button,
|
|
18
|
+
ErrorState,
|
|
19
|
+
LoaderBlock
|
|
20
|
+
} from "@contractspec/lib.design-system";
|
|
21
|
+
import { Card } from "@contractspec/lib.ui-kit-web/ui/card";
|
|
22
|
+
import { Badge } from "@contractspec/lib.ui-kit-web/ui/badge";
|
|
23
|
+
import { jsxDEV } from "react/jsx-dev-runtime";
|
|
24
|
+
"use client";
|
|
25
|
+
function MarkdownView({
|
|
26
|
+
templateId: propTemplateId,
|
|
27
|
+
presentationId,
|
|
28
|
+
className
|
|
29
|
+
}) {
|
|
30
|
+
const {
|
|
31
|
+
engine,
|
|
32
|
+
template,
|
|
33
|
+
templateId: contextTemplateId,
|
|
34
|
+
resolvePresentation,
|
|
35
|
+
fetchData
|
|
36
|
+
} = useTemplateRuntime();
|
|
37
|
+
const templateId = propTemplateId ?? contextTemplateId;
|
|
38
|
+
const presentations = template?.presentations ?? [];
|
|
39
|
+
const [selectedPresentation, setSelectedPresentation] = useState("");
|
|
40
|
+
const [markdownContent, setMarkdownContent] = useState("");
|
|
41
|
+
const [loading, setLoading] = useState(false);
|
|
42
|
+
const [error, setError] = useState(null);
|
|
43
|
+
useEffect(() => {
|
|
44
|
+
if (presentationId && presentations.includes(presentationId)) {
|
|
45
|
+
setSelectedPresentation(presentationId);
|
|
46
|
+
} else if (presentations.length > 0 && !selectedPresentation) {
|
|
47
|
+
setSelectedPresentation(presentations[0] ?? "");
|
|
48
|
+
}
|
|
49
|
+
}, [presentationId, presentations, selectedPresentation]);
|
|
50
|
+
const renderMarkdown = useCallback(async () => {
|
|
51
|
+
if (!selectedPresentation || !engine)
|
|
52
|
+
return;
|
|
53
|
+
setLoading(true);
|
|
54
|
+
setError(null);
|
|
55
|
+
try {
|
|
56
|
+
if (!resolvePresentation) {
|
|
57
|
+
throw new Error("resolvePresentation not available in runtime context");
|
|
58
|
+
}
|
|
59
|
+
const descriptor = resolvePresentation(selectedPresentation);
|
|
60
|
+
if (!descriptor) {
|
|
61
|
+
throw new Error(`Presentation descriptor not found: ${selectedPresentation}`);
|
|
62
|
+
}
|
|
63
|
+
const dataResult = await fetchData(selectedPresentation);
|
|
64
|
+
const result = await engine.render("markdown", descriptor, { data: dataResult.data });
|
|
65
|
+
setMarkdownContent(result.body);
|
|
66
|
+
} catch (err) {
|
|
67
|
+
setError(err instanceof Error ? err : new Error("Failed to render markdown"));
|
|
68
|
+
} finally {
|
|
69
|
+
setLoading(false);
|
|
70
|
+
}
|
|
71
|
+
}, [
|
|
72
|
+
selectedPresentation,
|
|
73
|
+
templateId,
|
|
74
|
+
engine,
|
|
75
|
+
resolvePresentation,
|
|
76
|
+
fetchData
|
|
77
|
+
]);
|
|
78
|
+
useEffect(() => {
|
|
79
|
+
renderMarkdown();
|
|
80
|
+
}, [renderMarkdown]);
|
|
81
|
+
if (!presentations.length) {
|
|
82
|
+
return /* @__PURE__ */ jsxDEV(Card, {
|
|
83
|
+
className,
|
|
84
|
+
children: /* @__PURE__ */ jsxDEV("div", {
|
|
85
|
+
className: "p-6 text-center",
|
|
86
|
+
children: /* @__PURE__ */ jsxDEV("p", {
|
|
87
|
+
className: "text-muted-foreground",
|
|
88
|
+
children: "No presentations available for this template."
|
|
89
|
+
}, undefined, false, undefined, this)
|
|
90
|
+
}, undefined, false, undefined, this)
|
|
91
|
+
}, undefined, false, undefined, this);
|
|
92
|
+
}
|
|
93
|
+
const handleCopy = useCallback(() => {
|
|
94
|
+
if (markdownContent) {
|
|
95
|
+
navigator.clipboard.writeText(markdownContent);
|
|
96
|
+
}
|
|
97
|
+
}, [markdownContent]);
|
|
98
|
+
return /* @__PURE__ */ jsxDEV("div", {
|
|
99
|
+
className,
|
|
100
|
+
children: [
|
|
101
|
+
/* @__PURE__ */ jsxDEV("div", {
|
|
102
|
+
className: "mb-4 flex flex-wrap items-center gap-2",
|
|
103
|
+
children: [
|
|
104
|
+
/* @__PURE__ */ jsxDEV("span", {
|
|
105
|
+
className: "text-muted-foreground text-sm font-medium",
|
|
106
|
+
children: "Presentation:"
|
|
107
|
+
}, undefined, false, undefined, this),
|
|
108
|
+
presentations.map((name) => /* @__PURE__ */ jsxDEV(Button, {
|
|
109
|
+
variant: selectedPresentation === name ? "default" : "outline",
|
|
110
|
+
size: "sm",
|
|
111
|
+
onPress: () => setSelectedPresentation(name),
|
|
112
|
+
children: formatPresentationName(name)
|
|
113
|
+
}, name, false, undefined, this)),
|
|
114
|
+
/* @__PURE__ */ jsxDEV("div", {
|
|
115
|
+
className: "ml-auto flex items-center gap-2",
|
|
116
|
+
children: [
|
|
117
|
+
/* @__PURE__ */ jsxDEV(Badge, {
|
|
118
|
+
variant: "secondary",
|
|
119
|
+
children: "LLM-friendly"
|
|
120
|
+
}, undefined, false, undefined, this),
|
|
121
|
+
/* @__PURE__ */ jsxDEV(Button, {
|
|
122
|
+
variant: "outline",
|
|
123
|
+
size: "sm",
|
|
124
|
+
onPress: handleCopy,
|
|
125
|
+
disabled: !markdownContent || loading,
|
|
126
|
+
children: "Copy"
|
|
127
|
+
}, undefined, false, undefined, this)
|
|
128
|
+
]
|
|
129
|
+
}, undefined, true, undefined, this)
|
|
130
|
+
]
|
|
131
|
+
}, undefined, true, undefined, this),
|
|
132
|
+
/* @__PURE__ */ jsxDEV(Card, {
|
|
133
|
+
className: "overflow-hidden",
|
|
134
|
+
children: [
|
|
135
|
+
loading && /* @__PURE__ */ jsxDEV(LoaderBlock, {
|
|
136
|
+
label: "Rendering markdown..."
|
|
137
|
+
}, undefined, false, undefined, this),
|
|
138
|
+
error && /* @__PURE__ */ jsxDEV(ErrorState, {
|
|
139
|
+
title: "Render failed",
|
|
140
|
+
description: error.message,
|
|
141
|
+
onRetry: renderMarkdown,
|
|
142
|
+
retryLabel: "Retry"
|
|
143
|
+
}, undefined, false, undefined, this),
|
|
144
|
+
!loading && !error && markdownContent && /* @__PURE__ */ jsxDEV("div", {
|
|
145
|
+
className: "p-6",
|
|
146
|
+
children: /* @__PURE__ */ jsxDEV(MarkdownRenderer, {
|
|
147
|
+
content: markdownContent
|
|
148
|
+
}, undefined, false, undefined, this)
|
|
149
|
+
}, undefined, false, undefined, this),
|
|
150
|
+
!loading && !error && !markdownContent && /* @__PURE__ */ jsxDEV("div", {
|
|
151
|
+
className: "p-6 text-center",
|
|
152
|
+
children: /* @__PURE__ */ jsxDEV("p", {
|
|
153
|
+
className: "text-muted-foreground",
|
|
154
|
+
children: "Select a presentation to view its markdown output."
|
|
155
|
+
}, undefined, false, undefined, this)
|
|
156
|
+
}, undefined, false, undefined, this)
|
|
157
|
+
]
|
|
158
|
+
}, undefined, true, undefined, this)
|
|
159
|
+
]
|
|
160
|
+
}, undefined, true, undefined, this);
|
|
161
|
+
}
|
|
162
|
+
function MarkdownRenderer({ content }) {
|
|
163
|
+
const lines = content.split(`
|
|
164
|
+
`);
|
|
165
|
+
const rendered = [];
|
|
166
|
+
let i = 0;
|
|
167
|
+
while (i < lines.length) {
|
|
168
|
+
const line = lines[i] ?? "";
|
|
169
|
+
if (line.startsWith("|") && lines[i + 1]?.match(/^\|[\s-|]+\|$/)) {
|
|
170
|
+
const tableLines = [line];
|
|
171
|
+
i++;
|
|
172
|
+
while (i < lines.length && (lines[i]?.startsWith("|") ?? false)) {
|
|
173
|
+
tableLines.push(lines[i] ?? "");
|
|
174
|
+
i++;
|
|
175
|
+
}
|
|
176
|
+
rendered.push(renderTable(tableLines, rendered.length));
|
|
177
|
+
continue;
|
|
178
|
+
}
|
|
179
|
+
if (line.startsWith("# ")) {
|
|
180
|
+
rendered.push(/* @__PURE__ */ jsxDEV("h1", {
|
|
181
|
+
className: "mb-4 text-2xl font-bold",
|
|
182
|
+
children: line.slice(2)
|
|
183
|
+
}, i, false, undefined, this));
|
|
184
|
+
} else if (line.startsWith("## ")) {
|
|
185
|
+
rendered.push(/* @__PURE__ */ jsxDEV("h2", {
|
|
186
|
+
className: "mt-6 mb-3 text-xl font-semibold",
|
|
187
|
+
children: line.slice(3)
|
|
188
|
+
}, i, false, undefined, this));
|
|
189
|
+
} else if (line.startsWith("### ")) {
|
|
190
|
+
rendered.push(/* @__PURE__ */ jsxDEV("h3", {
|
|
191
|
+
className: "mt-4 mb-2 text-lg font-medium",
|
|
192
|
+
children: line.slice(4)
|
|
193
|
+
}, i, false, undefined, this));
|
|
194
|
+
} else if (line.startsWith("> ")) {
|
|
195
|
+
rendered.push(/* @__PURE__ */ jsxDEV("blockquote", {
|
|
196
|
+
className: "text-muted-foreground my-2 border-l-4 border-violet-500/50 pl-4 italic",
|
|
197
|
+
children: line.slice(2)
|
|
198
|
+
}, i, false, undefined, this));
|
|
199
|
+
} else if (line.startsWith("- ")) {
|
|
200
|
+
rendered.push(/* @__PURE__ */ jsxDEV("li", {
|
|
201
|
+
className: "ml-4 list-disc",
|
|
202
|
+
children: formatInlineMarkdown(line.slice(2))
|
|
203
|
+
}, i, false, undefined, this));
|
|
204
|
+
} else if (line.startsWith("**") && line.includes(":**")) {
|
|
205
|
+
const [label, ...rest] = line.split(":**");
|
|
206
|
+
rendered.push(/* @__PURE__ */ jsxDEV("p", {
|
|
207
|
+
className: "my-1",
|
|
208
|
+
children: [
|
|
209
|
+
/* @__PURE__ */ jsxDEV("strong", {
|
|
210
|
+
children: [
|
|
211
|
+
label?.slice(2),
|
|
212
|
+
":"
|
|
213
|
+
]
|
|
214
|
+
}, undefined, true, undefined, this),
|
|
215
|
+
rest.join(":**")
|
|
216
|
+
]
|
|
217
|
+
}, i, true, undefined, this));
|
|
218
|
+
} else if (line.startsWith("_") && line.endsWith("_")) {
|
|
219
|
+
rendered.push(/* @__PURE__ */ jsxDEV("p", {
|
|
220
|
+
className: "text-muted-foreground my-1 italic",
|
|
221
|
+
children: line.slice(1, -1)
|
|
222
|
+
}, i, false, undefined, this));
|
|
223
|
+
} else if (!line.trim()) {
|
|
224
|
+
rendered.push(/* @__PURE__ */ jsxDEV("div", {
|
|
225
|
+
className: "h-2"
|
|
226
|
+
}, i, false, undefined, this));
|
|
227
|
+
} else {
|
|
228
|
+
rendered.push(/* @__PURE__ */ jsxDEV("p", {
|
|
229
|
+
className: "my-1",
|
|
230
|
+
children: formatInlineMarkdown(line)
|
|
231
|
+
}, i, false, undefined, this));
|
|
232
|
+
}
|
|
233
|
+
i++;
|
|
234
|
+
}
|
|
235
|
+
return /* @__PURE__ */ jsxDEV("div", {
|
|
236
|
+
className: "prose prose-sm dark:prose-invert max-w-none",
|
|
237
|
+
children: rendered
|
|
238
|
+
}, undefined, false, undefined, this);
|
|
239
|
+
}
|
|
240
|
+
function renderTable(lines, keyPrefix) {
|
|
241
|
+
if (lines.length < 2)
|
|
242
|
+
return null;
|
|
243
|
+
const parseRow = (row) => row.split("|").slice(1, -1).map((cell) => cell.trim());
|
|
244
|
+
const headers = parseRow(lines[0] ?? "");
|
|
245
|
+
const dataRows = lines.slice(2).map(parseRow);
|
|
246
|
+
return /* @__PURE__ */ jsxDEV("div", {
|
|
247
|
+
className: "my-4 overflow-x-auto",
|
|
248
|
+
children: /* @__PURE__ */ jsxDEV("table", {
|
|
249
|
+
className: "border-border min-w-full border-collapse border text-sm",
|
|
250
|
+
children: [
|
|
251
|
+
/* @__PURE__ */ jsxDEV("thead", {
|
|
252
|
+
children: /* @__PURE__ */ jsxDEV("tr", {
|
|
253
|
+
className: "bg-muted/50",
|
|
254
|
+
children: headers.map((header, idx) => /* @__PURE__ */ jsxDEV("th", {
|
|
255
|
+
className: "border-border border px-3 py-2 text-left font-semibold",
|
|
256
|
+
children: header
|
|
257
|
+
}, idx, false, undefined, this))
|
|
258
|
+
}, undefined, false, undefined, this)
|
|
259
|
+
}, undefined, false, undefined, this),
|
|
260
|
+
/* @__PURE__ */ jsxDEV("tbody", {
|
|
261
|
+
children: dataRows.map((row, rowIdx) => /* @__PURE__ */ jsxDEV("tr", {
|
|
262
|
+
className: "hover:bg-muted/30",
|
|
263
|
+
children: row.map((cell, cellIdx) => /* @__PURE__ */ jsxDEV("td", {
|
|
264
|
+
className: "border-border border px-3 py-2",
|
|
265
|
+
children: formatInlineMarkdown(cell)
|
|
266
|
+
}, cellIdx, false, undefined, this))
|
|
267
|
+
}, rowIdx, false, undefined, this))
|
|
268
|
+
}, undefined, false, undefined, this)
|
|
269
|
+
]
|
|
270
|
+
}, undefined, true, undefined, this)
|
|
271
|
+
}, `table-${keyPrefix}`, false, undefined, this);
|
|
272
|
+
}
|
|
273
|
+
function formatInlineMarkdown(text) {
|
|
274
|
+
const parts = text.split(/(\*\*[^*]+\*\*)/g);
|
|
275
|
+
return parts.map((part, i) => {
|
|
276
|
+
if (part.startsWith("**") && part.endsWith("**")) {
|
|
277
|
+
return /* @__PURE__ */ jsxDEV("strong", {
|
|
278
|
+
children: part.slice(2, -2)
|
|
279
|
+
}, i, false, undefined, this);
|
|
280
|
+
}
|
|
281
|
+
if (part.includes("`")) {
|
|
282
|
+
const codeParts = part.split(/(`[^`]+`)/g);
|
|
283
|
+
return codeParts.map((cp, j) => {
|
|
284
|
+
if (cp.startsWith("`") && cp.endsWith("`")) {
|
|
285
|
+
return /* @__PURE__ */ jsxDEV("code", {
|
|
286
|
+
className: "rounded bg-violet-500/10 px-1.5 py-0.5 font-mono text-sm",
|
|
287
|
+
children: cp.slice(1, -1)
|
|
288
|
+
}, `${i}-${j}`, false, undefined, this);
|
|
289
|
+
}
|
|
290
|
+
return cp;
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
return part;
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
function formatPresentationName(name) {
|
|
297
|
+
const parts = name.split(".");
|
|
298
|
+
const lastPart = parts[parts.length - 1] ?? name;
|
|
299
|
+
return lastPart.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
300
|
+
}
|
|
301
|
+
export {
|
|
302
|
+
MarkdownView,
|
|
303
|
+
MarkdownRenderer
|
|
304
|
+
};
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { TemplateId } from './lib/types';
|
|
3
|
+
/**
|
|
4
|
+
* Overlay modification operation types (for OverlayContextProvider)
|
|
5
|
+
*/
|
|
6
|
+
export type OverlayModificationOp = {
|
|
7
|
+
op: 'hide';
|
|
8
|
+
} | {
|
|
9
|
+
op: 'relabel';
|
|
10
|
+
label: string;
|
|
11
|
+
} | {
|
|
12
|
+
op: 'reorder';
|
|
13
|
+
position: number;
|
|
14
|
+
} | {
|
|
15
|
+
op: 'restyle';
|
|
16
|
+
className?: string;
|
|
17
|
+
variant?: string;
|
|
18
|
+
} | {
|
|
19
|
+
op: 'set-default';
|
|
20
|
+
value: unknown;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Overlay spec for a field or component
|
|
24
|
+
*/
|
|
25
|
+
export interface OverlaySpec {
|
|
26
|
+
id: string;
|
|
27
|
+
target: string;
|
|
28
|
+
modifications: OverlayModificationOp[];
|
|
29
|
+
conditions?: {
|
|
30
|
+
role?: string[];
|
|
31
|
+
device?: 'mobile' | 'desktop' | 'any';
|
|
32
|
+
featureFlags?: string[];
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Context value for overlay engine
|
|
37
|
+
*/
|
|
38
|
+
export interface OverlayContextValue {
|
|
39
|
+
/** Current overlays */
|
|
40
|
+
overlays: OverlaySpec[];
|
|
41
|
+
/** Apply overlays to a component */
|
|
42
|
+
applyOverlay: <T extends Record<string, unknown>>(path: string, target: T) => T;
|
|
43
|
+
/** Check if a field should be hidden */
|
|
44
|
+
isHidden: (path: string) => boolean;
|
|
45
|
+
/** Get relabeled text */
|
|
46
|
+
getLabel: (path: string, defaultLabel: string) => string;
|
|
47
|
+
/** Get position for reordering */
|
|
48
|
+
getPosition: (path: string, defaultPosition: number) => number;
|
|
49
|
+
/** Get style modifications */
|
|
50
|
+
getStyle: (path: string) => {
|
|
51
|
+
className?: string;
|
|
52
|
+
variant?: string;
|
|
53
|
+
};
|
|
54
|
+
/** Get default value */
|
|
55
|
+
getDefault: <T>(path: string, defaultValue: T) => T;
|
|
56
|
+
/** Current user role */
|
|
57
|
+
role: string;
|
|
58
|
+
/** Current device type */
|
|
59
|
+
device: 'mobile' | 'desktop';
|
|
60
|
+
}
|
|
61
|
+
export interface OverlayContextProviderProps extends React.PropsWithChildren {
|
|
62
|
+
templateId: TemplateId;
|
|
63
|
+
role?: string;
|
|
64
|
+
device?: 'mobile' | 'desktop';
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Provider for overlay engine context.
|
|
68
|
+
* Loads template-specific overlays and provides helper functions.
|
|
69
|
+
*/
|
|
70
|
+
export declare function OverlayContextProvider({ templateId, role, device, children, }: OverlayContextProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
71
|
+
/**
|
|
72
|
+
* Hook to access overlay context
|
|
73
|
+
*/
|
|
74
|
+
export declare function useOverlayContext(): OverlayContextValue;
|
|
75
|
+
/**
|
|
76
|
+
* Hook to check if within overlay context
|
|
77
|
+
*/
|
|
78
|
+
export declare function useIsInOverlayContext(): boolean;
|
|
79
|
+
//# sourceMappingURL=OverlayContextProvider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OverlayContextProvider.d.ts","sourceRoot":"","sources":["../src/OverlayContextProvider.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAC7B;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,GACd;IAAE,EAAE,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAChC;IAAE,EAAE,EAAE,SAAS,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GACnC;IAAE,EAAE,EAAE,SAAS,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GACvD;IAAE,EAAE,EAAE,aAAa,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAAC;AAE1C;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,qBAAqB,EAAE,CAAC;IACvC,UAAU,CAAC,EAAE;QACX,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;QAChB,MAAM,CAAC,EAAE,QAAQ,GAAG,SAAS,GAAG,KAAK,CAAC;QACtC,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;KACzB,CAAC;CACH;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,uBAAuB;IACvB,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,oCAAoC;IACpC,YAAY,EAAE,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9C,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,CAAC,KACN,CAAC,CAAC;IACP,wCAAwC;IACxC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;IACpC,yBAAyB;IACzB,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,KAAK,MAAM,CAAC;IACzD,kCAAkC;IAClC,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,KAAK,MAAM,CAAC;IAC/D,8BAA8B;IAC9B,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK;QAAE,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACrE,wBAAwB;IACxB,UAAU,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC,KAAK,CAAC,CAAC;IACpD,wBAAwB;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,0BAA0B;IAC1B,MAAM,EAAE,QAAQ,GAAG,SAAS,CAAC;CAC9B;AAID,MAAM,WAAW,2BAA4B,SAAQ,KAAK,CAAC,iBAAiB;IAC1E,UAAU,EAAE,UAAU,CAAC;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;CAC/B;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,EACrC,UAAU,EACV,IAAa,EACb,MAAkB,EAClB,QAAQ,GACT,EAAE,2BAA2B,2CA0K7B;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,mBAAmB,CAQvD;AAED;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,OAAO,CAE/C"}
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// src/OverlayContextProvider.tsx
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { useContext, useMemo } from "react";
|
|
5
|
+
import { jsxDEV } from "react/jsx-dev-runtime";
|
|
6
|
+
"use client";
|
|
7
|
+
var OverlayContext = React.createContext(null);
|
|
8
|
+
function OverlayContextProvider({
|
|
9
|
+
templateId,
|
|
10
|
+
role = "user",
|
|
11
|
+
device = "desktop",
|
|
12
|
+
children
|
|
13
|
+
}) {
|
|
14
|
+
const overlays = useMemo(() => getTemplateOverlays(templateId, role), [templateId, role]);
|
|
15
|
+
const activeOverlays = useMemo(() => {
|
|
16
|
+
return overlays.filter((overlay) => {
|
|
17
|
+
const conditions = overlay.conditions;
|
|
18
|
+
if (!conditions)
|
|
19
|
+
return true;
|
|
20
|
+
if (conditions.role && !conditions.role.includes(role)) {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
if (conditions.device && conditions.device !== "any" && conditions.device !== device) {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
return true;
|
|
27
|
+
});
|
|
28
|
+
}, [overlays, role, device]);
|
|
29
|
+
const overlayMap = useMemo(() => {
|
|
30
|
+
const map = new Map;
|
|
31
|
+
for (const overlay of activeOverlays) {
|
|
32
|
+
map.set(overlay.target, overlay);
|
|
33
|
+
}
|
|
34
|
+
return map;
|
|
35
|
+
}, [activeOverlays]);
|
|
36
|
+
const applyOverlay = useMemo(() => (path, target) => {
|
|
37
|
+
const overlay = overlayMap.get(path);
|
|
38
|
+
if (!overlay)
|
|
39
|
+
return target;
|
|
40
|
+
let result = { ...target };
|
|
41
|
+
for (const mod of overlay.modifications) {
|
|
42
|
+
switch (mod.op) {
|
|
43
|
+
case "hide":
|
|
44
|
+
result = { ...result, hidden: true };
|
|
45
|
+
break;
|
|
46
|
+
case "relabel":
|
|
47
|
+
result = { ...result, label: mod.label };
|
|
48
|
+
break;
|
|
49
|
+
case "reorder":
|
|
50
|
+
result = { ...result, position: mod.position };
|
|
51
|
+
break;
|
|
52
|
+
case "restyle":
|
|
53
|
+
result = {
|
|
54
|
+
...result,
|
|
55
|
+
className: mod.className,
|
|
56
|
+
variant: mod.variant
|
|
57
|
+
};
|
|
58
|
+
break;
|
|
59
|
+
case "set-default":
|
|
60
|
+
result = { ...result, defaultValue: mod.value };
|
|
61
|
+
break;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return result;
|
|
65
|
+
}, [overlayMap]);
|
|
66
|
+
const isHidden = useMemo(() => (path) => {
|
|
67
|
+
const overlay = overlayMap.get(path);
|
|
68
|
+
return overlay?.modifications.some((m) => m.op === "hide") ?? false;
|
|
69
|
+
}, [overlayMap]);
|
|
70
|
+
const getLabel = useMemo(() => (path, defaultLabel) => {
|
|
71
|
+
const overlay = overlayMap.get(path);
|
|
72
|
+
const relabel = overlay?.modifications.find((m) => m.op === "relabel");
|
|
73
|
+
return relabel && relabel.op === "relabel" ? relabel.label : defaultLabel;
|
|
74
|
+
}, [overlayMap]);
|
|
75
|
+
const getPosition = useMemo(() => (path, defaultPosition) => {
|
|
76
|
+
const overlay = overlayMap.get(path);
|
|
77
|
+
const reorder = overlay?.modifications.find((m) => m.op === "reorder");
|
|
78
|
+
return reorder && reorder.op === "reorder" ? reorder.position : defaultPosition;
|
|
79
|
+
}, [overlayMap]);
|
|
80
|
+
const getStyle = useMemo(() => (path) => {
|
|
81
|
+
const overlay = overlayMap.get(path);
|
|
82
|
+
const restyle = overlay?.modifications.find((m) => m.op === "restyle");
|
|
83
|
+
if (restyle && restyle.op === "restyle") {
|
|
84
|
+
return {
|
|
85
|
+
className: restyle.className,
|
|
86
|
+
variant: restyle.variant
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
return {};
|
|
90
|
+
}, [overlayMap]);
|
|
91
|
+
const getDefault = useMemo(() => (path, defaultValue) => {
|
|
92
|
+
const overlay = overlayMap.get(path);
|
|
93
|
+
const setDefault = overlay?.modifications.find((m) => m.op === "set-default");
|
|
94
|
+
return setDefault && setDefault.op === "set-default" ? setDefault.value : defaultValue;
|
|
95
|
+
}, [overlayMap]);
|
|
96
|
+
const value = useMemo(() => ({
|
|
97
|
+
overlays: activeOverlays,
|
|
98
|
+
applyOverlay,
|
|
99
|
+
isHidden,
|
|
100
|
+
getLabel,
|
|
101
|
+
getPosition,
|
|
102
|
+
getStyle,
|
|
103
|
+
getDefault,
|
|
104
|
+
role,
|
|
105
|
+
device
|
|
106
|
+
}), [
|
|
107
|
+
activeOverlays,
|
|
108
|
+
applyOverlay,
|
|
109
|
+
isHidden,
|
|
110
|
+
getLabel,
|
|
111
|
+
getPosition,
|
|
112
|
+
getStyle,
|
|
113
|
+
getDefault,
|
|
114
|
+
role,
|
|
115
|
+
device
|
|
116
|
+
]);
|
|
117
|
+
return /* @__PURE__ */ jsxDEV(OverlayContext.Provider, {
|
|
118
|
+
value,
|
|
119
|
+
children
|
|
120
|
+
}, undefined, false, undefined, this);
|
|
121
|
+
}
|
|
122
|
+
function useOverlayContext() {
|
|
123
|
+
const context = useContext(OverlayContext);
|
|
124
|
+
if (!context) {
|
|
125
|
+
throw new Error("useOverlayContext must be used within an OverlayContextProvider");
|
|
126
|
+
}
|
|
127
|
+
return context;
|
|
128
|
+
}
|
|
129
|
+
function useIsInOverlayContext() {
|
|
130
|
+
return useContext(OverlayContext) !== null;
|
|
131
|
+
}
|
|
132
|
+
function getTemplateOverlays(templateId, _role) {
|
|
133
|
+
const templateOverlays = {
|
|
134
|
+
"crm-pipeline": [
|
|
135
|
+
{
|
|
136
|
+
id: "crm-hide-internal-fields",
|
|
137
|
+
target: "deal.internalNotes",
|
|
138
|
+
modifications: [{ op: "hide" }],
|
|
139
|
+
conditions: { role: ["viewer", "user"] }
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
id: "crm-relabel-value",
|
|
143
|
+
target: "deal.value",
|
|
144
|
+
modifications: [{ op: "relabel", label: "Deal Amount" }]
|
|
145
|
+
}
|
|
146
|
+
],
|
|
147
|
+
"saas-boilerplate": [
|
|
148
|
+
{
|
|
149
|
+
id: "saas-hide-billing",
|
|
150
|
+
target: "settings.billing",
|
|
151
|
+
modifications: [{ op: "hide" }],
|
|
152
|
+
conditions: { role: ["viewer"] }
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
id: "saas-restyle-plan",
|
|
156
|
+
target: "settings.plan",
|
|
157
|
+
modifications: [{ op: "restyle", variant: "premium" }],
|
|
158
|
+
conditions: { role: ["admin"] }
|
|
159
|
+
}
|
|
160
|
+
],
|
|
161
|
+
"agent-console": [
|
|
162
|
+
{
|
|
163
|
+
id: "agent-hide-cost",
|
|
164
|
+
target: "run.cost",
|
|
165
|
+
modifications: [{ op: "hide" }],
|
|
166
|
+
conditions: { role: ["viewer"] }
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
id: "agent-relabel-tokens",
|
|
170
|
+
target: "run.tokens",
|
|
171
|
+
modifications: [{ op: "relabel", label: "Token Usage" }]
|
|
172
|
+
}
|
|
173
|
+
],
|
|
174
|
+
"todos-app": [
|
|
175
|
+
{
|
|
176
|
+
id: "todos-hide-assignee",
|
|
177
|
+
target: "task.assignee",
|
|
178
|
+
modifications: [{ op: "hide" }],
|
|
179
|
+
conditions: { device: "mobile" }
|
|
180
|
+
}
|
|
181
|
+
],
|
|
182
|
+
"messaging-app": [
|
|
183
|
+
{
|
|
184
|
+
id: "messaging-reorder-timestamp",
|
|
185
|
+
target: "message.timestamp",
|
|
186
|
+
modifications: [{ op: "reorder", position: 0 }]
|
|
187
|
+
}
|
|
188
|
+
],
|
|
189
|
+
"recipe-app-i18n": [
|
|
190
|
+
{
|
|
191
|
+
id: "recipe-relabel-servings",
|
|
192
|
+
target: "recipe.servings",
|
|
193
|
+
modifications: [{ op: "relabel", label: "Portions" }]
|
|
194
|
+
}
|
|
195
|
+
]
|
|
196
|
+
};
|
|
197
|
+
return templateOverlays[templateId] ?? [];
|
|
198
|
+
}
|
|
199
|
+
export {
|
|
200
|
+
useOverlayContext,
|
|
201
|
+
useIsInOverlayContext,
|
|
202
|
+
OverlayContextProvider
|
|
203
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { TemplateId } from './lib/types';
|
|
2
|
+
export interface PersonalizationInsightsProps {
|
|
3
|
+
templateId: TemplateId;
|
|
4
|
+
/** Whether to show in collapsed mode */
|
|
5
|
+
collapsed?: boolean;
|
|
6
|
+
/** Toggle collapsed state */
|
|
7
|
+
onToggle?: () => void;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Component showing personalization insights based on user behavior.
|
|
11
|
+
* Displays usage patterns, recommendations, and feature adoption.
|
|
12
|
+
*/
|
|
13
|
+
export declare function PersonalizationInsights({ templateId, collapsed, onToggle, }: PersonalizationInsightsProps): import("react/jsx-runtime").JSX.Element;
|
|
14
|
+
//# sourceMappingURL=PersonalizationInsights.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PersonalizationInsights.d.ts","sourceRoot":"","sources":["../src/PersonalizationInsights.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAM9C,MAAM,WAAW,4BAA4B;IAC3C,UAAU,EAAE,UAAU,CAAC;IACvB,wCAAwC;IACxC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,6BAA6B;IAC7B,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;CACvB;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,EACtC,UAAU,EACV,SAAiB,EACjB,QAAQ,GACT,EAAE,4BAA4B,2CA+I9B"}
|