nextworks 0.2.0-alpha.11 → 0.2.0-alpha.13
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/README.md +283 -282
- package/dist/cli_manifests/blocks_manifest.json +198 -175
- package/dist/kits/blocks/.nextworks/docs/BLOCKS_QUICKSTART.md +101 -100
- package/dist/kits/blocks/.nextworks/docs/BLOCKS_README.md +105 -104
- package/dist/kits/blocks/.nextworks/docs/THEME_GUIDE.md +1 -1
- package/dist/kits/blocks/app/templates/aiworkflow/PresetThemeVars.tsx +58 -0
- package/dist/kits/blocks/app/templates/aiworkflow/README.md +46 -0
- package/dist/kits/blocks/app/templates/aiworkflow/components/CTA.tsx +44 -0
- package/dist/kits/blocks/app/templates/aiworkflow/components/Contact.tsx +105 -0
- package/dist/kits/blocks/app/templates/aiworkflow/components/FAQ.tsx +63 -0
- package/dist/kits/blocks/app/templates/aiworkflow/components/Features.tsx +65 -0
- package/dist/kits/blocks/app/templates/aiworkflow/components/Footer.tsx +109 -0
- package/dist/kits/blocks/app/templates/aiworkflow/components/Hero.tsx +636 -0
- package/dist/kits/blocks/app/templates/aiworkflow/components/Navbar.tsx +90 -0
- package/dist/kits/blocks/app/templates/aiworkflow/components/Pricing.tsx +86 -0
- package/dist/kits/blocks/app/templates/aiworkflow/components/ProcessTimeline.tsx +103 -0
- package/dist/kits/blocks/app/templates/aiworkflow/components/Testimonials.tsx +56 -0
- package/dist/kits/blocks/app/templates/aiworkflow/components/TrustBadges.tsx +59 -0
- package/dist/kits/blocks/app/templates/aiworkflow/page.tsx +43 -0
- package/dist/kits/blocks/app/templates/digitalagency/PresetThemeVars.tsx +80 -80
- package/dist/kits/blocks/app/templates/digitalagency/README.md +42 -42
- package/dist/kits/blocks/app/templates/digitalagency/components/Pricing.tsx +114 -114
- package/dist/kits/blocks/app/templates/digitalagency/components/Process.tsx +59 -59
- package/dist/kits/blocks/app/templates/digitalagency/components/Services.tsx +55 -55
- package/dist/kits/blocks/app/templates/digitalagency/components/Team.tsx +28 -28
- package/dist/kits/blocks/app/templates/digitalagency/components/Testimonials.tsx +65 -65
- package/dist/kits/blocks/app/templates/digitalagency/page.tsx +38 -38
- package/dist/kits/blocks/app/templates/gallery/PresetThemeVars.tsx +84 -84
- package/dist/kits/blocks/app/templates/productlaunch/PresetThemeVars.tsx +75 -75
- package/dist/kits/blocks/app/templates/productlaunch/README.md +62 -62
- package/dist/kits/blocks/app/templates/productlaunch/components/About.tsx +84 -84
- package/dist/kits/blocks/app/templates/productlaunch/components/CTA.tsx +50 -50
- package/dist/kits/blocks/app/templates/productlaunch/components/Contact.tsx +231 -231
- package/dist/kits/blocks/app/templates/productlaunch/components/FAQ.tsx +86 -86
- package/dist/kits/blocks/app/templates/productlaunch/components/Features.tsx +83 -83
- package/dist/kits/blocks/app/templates/productlaunch/components/Footer.tsx +132 -132
- package/dist/kits/blocks/app/templates/productlaunch/components/Hero.tsx +88 -88
- package/dist/kits/blocks/app/templates/productlaunch/components/Navbar.tsx +116 -116
- package/dist/kits/blocks/app/templates/productlaunch/components/Pricing.tsx +106 -106
- package/dist/kits/blocks/app/templates/productlaunch/components/ProcessTimeline.tsx +110 -110
- package/dist/kits/blocks/app/templates/productlaunch/components/ServicesGrid.tsx +68 -68
- package/dist/kits/blocks/app/templates/productlaunch/components/Team.tsx +104 -104
- package/dist/kits/blocks/app/templates/productlaunch/components/Testimonials.tsx +90 -90
- package/dist/kits/blocks/app/templates/productlaunch/components/TrustBadges.tsx +76 -76
- package/dist/kits/blocks/app/templates/productlaunch/page.tsx +43 -43
- package/dist/kits/blocks/app/templates/saasdashboard/PresetThemeVars.tsx +80 -80
- package/dist/kits/blocks/app/templates/saasdashboard/README.md +44 -44
- package/dist/kits/blocks/app/templates/saasdashboard/components/Contact.tsx +129 -129
- package/dist/kits/blocks/app/templates/saasdashboard/components/Dashboard.tsx +293 -293
- package/dist/kits/blocks/app/templates/saasdashboard/components/FAQ.tsx +55 -55
- package/dist/kits/blocks/app/templates/saasdashboard/components/Features.tsx +90 -90
- package/dist/kits/blocks/app/templates/saasdashboard/components/Footer.tsx +77 -77
- package/dist/kits/blocks/app/templates/saasdashboard/components/Hero.tsx +104 -104
- package/dist/kits/blocks/app/templates/saasdashboard/components/Hero_mask.tsx +126 -126
- package/dist/kits/blocks/app/templates/saasdashboard/components/Navbar.tsx +117 -117
- package/dist/kits/blocks/app/templates/saasdashboard/components/Pricing.tsx +90 -90
- package/dist/kits/blocks/app/templates/saasdashboard/components/SmoothScroll.tsx +96 -96
- package/dist/kits/blocks/app/templates/saasdashboard/components/Testimonials.tsx +72 -72
- package/dist/kits/blocks/app/templates/saasdashboard/components/TrustBadges.tsx +53 -53
- package/dist/kits/blocks/app/templates/saasdashboard/page.tsx +39 -39
- package/dist/kits/blocks/components/enhanced-theme-provider.tsx +195 -195
- package/dist/kits/blocks/components/providers/BlocksAppProviders.tsx +27 -27
- package/dist/kits/blocks/components/sections/About.tsx +291 -291
- package/dist/kits/blocks/components/sections/CTA.tsx +257 -257
- package/dist/kits/blocks/components/sections/Contact.tsx +267 -267
- package/dist/kits/blocks/components/sections/FAQ.tsx +214 -214
- package/dist/kits/blocks/components/sections/Features.tsx +268 -268
- package/dist/kits/blocks/components/sections/Footer.tsx +302 -302
- package/dist/kits/blocks/components/sections/HeroMotion.tsx +308 -308
- package/dist/kits/blocks/components/sections/HeroOverlay.tsx +358 -358
- package/dist/kits/blocks/components/sections/HeroProductDemo.tsx +236 -0
- package/dist/kits/blocks/components/sections/HeroSplit.tsx +352 -352
- package/dist/kits/blocks/components/sections/Navbar.tsx +350 -350
- package/dist/kits/blocks/components/sections/PortfolioSimple.tsx +549 -549
- package/dist/kits/blocks/components/sections/Pricing.tsx +264 -264
- package/dist/kits/blocks/components/sections/ProcessTimeline.tsx +325 -325
- package/dist/kits/blocks/components/sections/ServicesGrid.tsx +210 -210
- package/dist/kits/blocks/components/sections/Team.tsx +309 -309
- package/dist/kits/blocks/components/sections/Testimonials.tsx +158 -158
- package/dist/kits/blocks/components/sections/TrustBadges.tsx +162 -162
- package/dist/kits/blocks/components/sections/product-demo/ApprovalInboxPanel.tsx +125 -0
- package/dist/kits/blocks/components/sections/product-demo/DemoStage.tsx +397 -0
- package/dist/kits/blocks/components/sections/product-demo/DemoWindow.tsx +128 -0
- package/dist/kits/blocks/components/sections/product-demo/KnowledgePanel.tsx +127 -0
- package/dist/kits/blocks/components/sections/product-demo/RunConsolePanel.tsx +150 -0
- package/dist/kits/blocks/components/sections/product-demo/WorkflowStudioPanel.tsx +191 -0
- package/dist/kits/blocks/components/sections/product-demo/types.ts +193 -0
- package/dist/kits/blocks/components/theme-provider.tsx +1 -1
- package/dist/kits/blocks/components/ui/alert-dialog.tsx +134 -134
- package/dist/kits/blocks/components/ui/brand-node.tsx +121 -121
- package/dist/kits/blocks/components/ui/button.tsx +122 -122
- package/dist/kits/blocks/components/ui/card.tsx +95 -95
- package/dist/kits/blocks/components/ui/checkbox.tsx +30 -30
- package/dist/kits/blocks/components/ui/cta-button.tsx +125 -125
- package/dist/kits/blocks/components/ui/dropdown-menu.tsx +201 -201
- package/dist/kits/blocks/components/ui/feature-card.tsx +91 -91
- package/dist/kits/blocks/components/ui/input.tsx +27 -27
- package/dist/kits/blocks/components/ui/label.tsx +29 -29
- package/dist/kits/blocks/components/ui/pricing-card.tsx +120 -120
- package/dist/kits/blocks/components/ui/select.tsx +25 -25
- package/dist/kits/blocks/components/ui/skeleton.tsx +13 -13
- package/dist/kits/blocks/components/ui/table.tsx +98 -98
- package/dist/kits/blocks/components/ui/testimonial-card.tsx +108 -108
- package/dist/kits/blocks/components/ui/textarea.tsx +26 -26
- package/dist/kits/blocks/components/ui/theme-selector.tsx +243 -243
- package/dist/kits/blocks/components/ui/theme-toggle.tsx +74 -74
- package/dist/kits/blocks/components/ui/toaster.tsx +7 -7
- package/dist/kits/blocks/lib/themes.ts +400 -400
- package/dist/kits/blocks/lib/utils.ts +6 -6
- package/dist/kits/blocks/package-deps.json +3 -3
- package/package.json +1 -1
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { cn } from "@/lib/utils";
|
|
3
|
+
import type {
|
|
4
|
+
ProductDemoKnowledgePanelState,
|
|
5
|
+
ProductDemoStatusTone,
|
|
6
|
+
} from "./types";
|
|
7
|
+
|
|
8
|
+
export interface KnowledgePanelProps {
|
|
9
|
+
state: ProductDemoKnowledgePanelState;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const STATUS_TONE_CLASSES: Record<ProductDemoStatusTone, string> = {
|
|
13
|
+
neutral: "border-border/60 bg-muted/55 text-muted-foreground",
|
|
14
|
+
info: "border-sky-500/30 bg-sky-500/10 text-sky-600 dark:text-sky-300",
|
|
15
|
+
success:
|
|
16
|
+
"border-emerald-500/30 bg-emerald-500/10 text-emerald-600 dark:text-emerald-300",
|
|
17
|
+
warning:
|
|
18
|
+
"border-amber-500/30 bg-amber-500/10 text-amber-700 dark:text-amber-300",
|
|
19
|
+
danger: "border-rose-500/30 bg-rose-500/10 text-rose-600 dark:text-rose-300",
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
function getStatusClass(tone: ProductDemoStatusTone = "neutral") {
|
|
23
|
+
return STATUS_TONE_CLASSES[tone];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function KnowledgePanel({ state }: KnowledgePanelProps) {
|
|
27
|
+
return (
|
|
28
|
+
<div className="flex h-full flex-col gap-4">
|
|
29
|
+
<div className="space-y-1.5">
|
|
30
|
+
{state.title && (
|
|
31
|
+
<h4 className="text-sm font-semibold text-card-foreground">
|
|
32
|
+
{state.title}
|
|
33
|
+
</h4>
|
|
34
|
+
)}
|
|
35
|
+
{state.subtitle && (
|
|
36
|
+
<p className="text-xs leading-relaxed text-muted-foreground">
|
|
37
|
+
{state.subtitle}
|
|
38
|
+
</p>
|
|
39
|
+
)}
|
|
40
|
+
</div>
|
|
41
|
+
|
|
42
|
+
{state.query && (
|
|
43
|
+
<div className="rounded-xl border border-primary/25 bg-primary/8 px-3 py-2 text-xs text-primary">
|
|
44
|
+
{state.query}
|
|
45
|
+
</div>
|
|
46
|
+
)}
|
|
47
|
+
|
|
48
|
+
{state.summary && (
|
|
49
|
+
<p className="text-xs leading-relaxed text-muted-foreground">
|
|
50
|
+
{state.summary}
|
|
51
|
+
</p>
|
|
52
|
+
)}
|
|
53
|
+
|
|
54
|
+
{state.sources?.length ? (
|
|
55
|
+
<div className="flex flex-wrap gap-2">
|
|
56
|
+
{state.sources.map((source) => (
|
|
57
|
+
<span
|
|
58
|
+
key={source.id}
|
|
59
|
+
className={cn(
|
|
60
|
+
"rounded-full border px-2.5 py-1 text-[10px] font-medium uppercase tracking-[0.14em]",
|
|
61
|
+
getStatusClass(source.status),
|
|
62
|
+
)}
|
|
63
|
+
>
|
|
64
|
+
{source.label}
|
|
65
|
+
{source.kind ? ` • ${source.kind}` : ""}
|
|
66
|
+
</span>
|
|
67
|
+
))}
|
|
68
|
+
</div>
|
|
69
|
+
) : null}
|
|
70
|
+
|
|
71
|
+
<div className="space-y-3">
|
|
72
|
+
{state.snippets.map((snippet) => {
|
|
73
|
+
const isActive =
|
|
74
|
+
snippet.id === state.activeSnippetId || snippet.highlighted;
|
|
75
|
+
const source = state.sources?.find(
|
|
76
|
+
(item) => item.id === snippet.sourceId,
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
return (
|
|
80
|
+
<div
|
|
81
|
+
key={snippet.id}
|
|
82
|
+
className={cn(
|
|
83
|
+
"rounded-2xl border border-border/60 bg-background/80 p-3",
|
|
84
|
+
isActive && "border-primary/45 bg-primary/6 shadow-sm",
|
|
85
|
+
)}
|
|
86
|
+
>
|
|
87
|
+
<div className="flex items-start justify-between gap-3">
|
|
88
|
+
<div>
|
|
89
|
+
<div className="text-sm font-semibold text-card-foreground">
|
|
90
|
+
{snippet.title}
|
|
91
|
+
</div>
|
|
92
|
+
{(snippet.excerptLabel || source?.label) && (
|
|
93
|
+
<div className="mt-1 text-[11px] text-muted-foreground">
|
|
94
|
+
{[snippet.excerptLabel, source?.label]
|
|
95
|
+
.filter(Boolean)
|
|
96
|
+
.join(" • ")}
|
|
97
|
+
</div>
|
|
98
|
+
)}
|
|
99
|
+
</div>
|
|
100
|
+
{snippet.confidence && (
|
|
101
|
+
<span className="rounded-full border border-border/60 bg-muted/60 px-2 py-1 text-[10px] font-medium uppercase tracking-[0.14em] text-muted-foreground">
|
|
102
|
+
{snippet.confidence}
|
|
103
|
+
</span>
|
|
104
|
+
)}
|
|
105
|
+
</div>
|
|
106
|
+
<p className="mt-2 text-xs leading-relaxed text-muted-foreground">
|
|
107
|
+
{snippet.content}
|
|
108
|
+
</p>
|
|
109
|
+
{snippet.tags?.length ? (
|
|
110
|
+
<div className="mt-3 flex flex-wrap gap-2">
|
|
111
|
+
{snippet.tags.map((tag) => (
|
|
112
|
+
<span
|
|
113
|
+
key={tag}
|
|
114
|
+
className="rounded-full border border-border/60 bg-background/70 px-2 py-0.5 text-[10px] text-muted-foreground"
|
|
115
|
+
>
|
|
116
|
+
{tag}
|
|
117
|
+
</span>
|
|
118
|
+
))}
|
|
119
|
+
</div>
|
|
120
|
+
) : null}
|
|
121
|
+
</div>
|
|
122
|
+
);
|
|
123
|
+
})}
|
|
124
|
+
</div>
|
|
125
|
+
</div>
|
|
126
|
+
);
|
|
127
|
+
}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { cn } from "@/lib/utils";
|
|
3
|
+
import type {
|
|
4
|
+
ProductDemoRunConsoleState,
|
|
5
|
+
ProductDemoStatusTone,
|
|
6
|
+
} from "./types";
|
|
7
|
+
|
|
8
|
+
export interface RunConsolePanelProps {
|
|
9
|
+
state: ProductDemoRunConsoleState;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const STATUS_TONE_CLASSES: Record<ProductDemoStatusTone, string> = {
|
|
13
|
+
neutral: "border-border/60 bg-muted/55 text-muted-foreground",
|
|
14
|
+
info: "border-sky-500/30 bg-sky-500/10 text-sky-600 dark:text-sky-300",
|
|
15
|
+
success:
|
|
16
|
+
"border-emerald-500/30 bg-emerald-500/10 text-emerald-600 dark:text-emerald-300",
|
|
17
|
+
warning:
|
|
18
|
+
"border-amber-500/30 bg-amber-500/10 text-amber-700 dark:text-amber-300",
|
|
19
|
+
danger: "border-rose-500/30 bg-rose-500/10 text-rose-600 dark:text-rose-300",
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
function getStatusClass(tone: ProductDemoStatusTone = "neutral") {
|
|
23
|
+
return STATUS_TONE_CLASSES[tone];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function getProgressPercent(value: number | undefined) {
|
|
27
|
+
if (typeof value !== "number" || Number.isNaN(value)) {
|
|
28
|
+
return undefined;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return Math.min(100, Math.max(0, value));
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function RunConsolePanel({ state }: RunConsolePanelProps) {
|
|
35
|
+
const progressPercent = getProgressPercent(state.progressPercent);
|
|
36
|
+
|
|
37
|
+
return (
|
|
38
|
+
<div className="flex h-full flex-col gap-4">
|
|
39
|
+
<div className="flex flex-wrap items-start justify-between gap-3">
|
|
40
|
+
<div className="space-y-1.5">
|
|
41
|
+
{state.title && (
|
|
42
|
+
<h4 className="text-sm font-semibold text-card-foreground">
|
|
43
|
+
{state.title}
|
|
44
|
+
</h4>
|
|
45
|
+
)}
|
|
46
|
+
{state.subtitle && (
|
|
47
|
+
<p className="text-xs leading-relaxed text-muted-foreground">
|
|
48
|
+
{state.subtitle}
|
|
49
|
+
</p>
|
|
50
|
+
)}
|
|
51
|
+
</div>
|
|
52
|
+
|
|
53
|
+
{(state.statusLabel || state.progressLabel) && (
|
|
54
|
+
<div className="space-y-1 text-right">
|
|
55
|
+
{state.statusLabel && (
|
|
56
|
+
<div className="text-[11px] font-medium uppercase tracking-[0.16em] text-muted-foreground">
|
|
57
|
+
{state.statusLabel}
|
|
58
|
+
</div>
|
|
59
|
+
)}
|
|
60
|
+
{state.progressLabel && (
|
|
61
|
+
<div className="text-sm font-semibold text-card-foreground">
|
|
62
|
+
{state.progressLabel}
|
|
63
|
+
</div>
|
|
64
|
+
)}
|
|
65
|
+
</div>
|
|
66
|
+
)}
|
|
67
|
+
</div>
|
|
68
|
+
|
|
69
|
+
{typeof progressPercent === "number" ? (
|
|
70
|
+
<div className="space-y-2">
|
|
71
|
+
<div className="h-2 overflow-hidden rounded-full bg-muted/70">
|
|
72
|
+
<div
|
|
73
|
+
className="h-full rounded-full bg-primary transition-[width] duration-500"
|
|
74
|
+
style={{ width: `${progressPercent}%` }}
|
|
75
|
+
/>
|
|
76
|
+
</div>
|
|
77
|
+
<div className="text-[11px] text-muted-foreground">
|
|
78
|
+
{progressPercent}% complete
|
|
79
|
+
</div>
|
|
80
|
+
</div>
|
|
81
|
+
) : null}
|
|
82
|
+
|
|
83
|
+
{state.metrics?.length ? (
|
|
84
|
+
<div className="grid grid-cols-2 gap-2">
|
|
85
|
+
{state.metrics.map((metric) => (
|
|
86
|
+
<div
|
|
87
|
+
key={metric.id}
|
|
88
|
+
className={cn(
|
|
89
|
+
"rounded-xl border px-3 py-2",
|
|
90
|
+
getStatusClass(metric.tone),
|
|
91
|
+
)}
|
|
92
|
+
>
|
|
93
|
+
<div className="text-[10px] font-medium uppercase tracking-[0.14em] opacity-80">
|
|
94
|
+
{metric.label}
|
|
95
|
+
</div>
|
|
96
|
+
<div className="mt-1 text-sm font-semibold">{metric.value}</div>
|
|
97
|
+
</div>
|
|
98
|
+
))}
|
|
99
|
+
</div>
|
|
100
|
+
) : null}
|
|
101
|
+
|
|
102
|
+
<div className="space-y-2">
|
|
103
|
+
{state.entries.map((entry) => {
|
|
104
|
+
const isActive =
|
|
105
|
+
entry.id === state.activeEntryId || entry.highlighted;
|
|
106
|
+
|
|
107
|
+
return (
|
|
108
|
+
<div
|
|
109
|
+
key={entry.id}
|
|
110
|
+
className={cn(
|
|
111
|
+
"rounded-xl border border-border/60 bg-background/70 px-3 py-2.5",
|
|
112
|
+
isActive && "border-primary/40 bg-primary/6",
|
|
113
|
+
)}
|
|
114
|
+
>
|
|
115
|
+
<div className="flex items-start justify-between gap-3">
|
|
116
|
+
<div className="min-w-0 flex-1">
|
|
117
|
+
<div className="text-sm text-card-foreground">
|
|
118
|
+
{entry.message}
|
|
119
|
+
</div>
|
|
120
|
+
{(entry.source || entry.timestamp) && (
|
|
121
|
+
<div className="mt-1 text-[11px] text-muted-foreground">
|
|
122
|
+
{[entry.source, entry.timestamp]
|
|
123
|
+
.filter(Boolean)
|
|
124
|
+
.join(" • ")}
|
|
125
|
+
</div>
|
|
126
|
+
)}
|
|
127
|
+
{entry.detail && (
|
|
128
|
+
<p className="mt-2 text-xs leading-relaxed text-muted-foreground">
|
|
129
|
+
{entry.detail}
|
|
130
|
+
</p>
|
|
131
|
+
)}
|
|
132
|
+
</div>
|
|
133
|
+
{entry.status && (
|
|
134
|
+
<span
|
|
135
|
+
className={cn(
|
|
136
|
+
"rounded-full border px-2 py-1 text-[10px] font-medium uppercase tracking-[0.14em]",
|
|
137
|
+
getStatusClass(entry.status),
|
|
138
|
+
)}
|
|
139
|
+
>
|
|
140
|
+
{entry.status}
|
|
141
|
+
</span>
|
|
142
|
+
)}
|
|
143
|
+
</div>
|
|
144
|
+
</div>
|
|
145
|
+
);
|
|
146
|
+
})}
|
|
147
|
+
</div>
|
|
148
|
+
</div>
|
|
149
|
+
);
|
|
150
|
+
}
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { cn } from "@/lib/utils";
|
|
3
|
+
import type {
|
|
4
|
+
ProductDemoStatusTone,
|
|
5
|
+
ProductDemoWorkflowRegion,
|
|
6
|
+
ProductDemoWorkflowStudioState,
|
|
7
|
+
} from "./types";
|
|
8
|
+
|
|
9
|
+
export interface WorkflowStudioPanelProps {
|
|
10
|
+
state: ProductDemoWorkflowStudioState;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const STATUS_TONE_CLASSES: Record<ProductDemoStatusTone, string> = {
|
|
14
|
+
neutral: "border-border/60 bg-muted/55 text-muted-foreground",
|
|
15
|
+
info: "border-sky-500/30 bg-sky-500/10 text-sky-600 dark:text-sky-300",
|
|
16
|
+
success:
|
|
17
|
+
"border-emerald-500/30 bg-emerald-500/10 text-emerald-600 dark:text-emerald-300",
|
|
18
|
+
warning:
|
|
19
|
+
"border-amber-500/30 bg-amber-500/10 text-amber-700 dark:text-amber-300",
|
|
20
|
+
danger: "border-rose-500/30 bg-rose-500/10 text-rose-600 dark:text-rose-300",
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
function getStatusClass(tone: ProductDemoStatusTone = "neutral") {
|
|
24
|
+
return STATUS_TONE_CLASSES[tone];
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function getRegionState(
|
|
28
|
+
region: ProductDemoWorkflowRegion,
|
|
29
|
+
activeRegionId: string | undefined,
|
|
30
|
+
) {
|
|
31
|
+
const isActive = region.id === activeRegionId || region.active;
|
|
32
|
+
const isHighlighted = region.highlighted || isActive;
|
|
33
|
+
|
|
34
|
+
return { isActive, isHighlighted };
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function WorkflowStudioPanel({ state }: WorkflowStudioPanelProps) {
|
|
38
|
+
return (
|
|
39
|
+
<div className="flex h-full flex-col gap-4">
|
|
40
|
+
<div className="space-y-1.5">
|
|
41
|
+
{state.title && (
|
|
42
|
+
<h4 className="text-sm font-semibold text-card-foreground">
|
|
43
|
+
{state.title}
|
|
44
|
+
</h4>
|
|
45
|
+
)}
|
|
46
|
+
{state.subtitle && (
|
|
47
|
+
<p className="text-xs leading-relaxed text-muted-foreground">
|
|
48
|
+
{state.subtitle}
|
|
49
|
+
</p>
|
|
50
|
+
)}
|
|
51
|
+
</div>
|
|
52
|
+
|
|
53
|
+
{state.regions?.length ? (
|
|
54
|
+
<div className="grid gap-2 sm:grid-cols-2 xl:grid-cols-3">
|
|
55
|
+
{state.regions.map((region) => {
|
|
56
|
+
const { isActive, isHighlighted } = getRegionState(
|
|
57
|
+
region,
|
|
58
|
+
state.activeRegionId,
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
return (
|
|
62
|
+
<div
|
|
63
|
+
key={region.id}
|
|
64
|
+
className={cn(
|
|
65
|
+
"rounded-2xl border border-border/60 bg-background/75 p-3",
|
|
66
|
+
isActive && "border-primary/45 bg-primary/8 shadow-sm",
|
|
67
|
+
isHighlighted && "ring-1 ring-primary/20",
|
|
68
|
+
)}
|
|
69
|
+
>
|
|
70
|
+
<div className="flex items-start justify-between gap-3">
|
|
71
|
+
<div>
|
|
72
|
+
<div className="text-[10px] font-medium uppercase tracking-[0.16em] text-muted-foreground">
|
|
73
|
+
Region
|
|
74
|
+
</div>
|
|
75
|
+
<div className="mt-1 text-sm font-semibold text-card-foreground">
|
|
76
|
+
{region.label}
|
|
77
|
+
</div>
|
|
78
|
+
</div>
|
|
79
|
+
{region.status && (
|
|
80
|
+
<span
|
|
81
|
+
className={cn(
|
|
82
|
+
"rounded-full border px-2 py-1 text-[10px] font-medium uppercase tracking-[0.14em]",
|
|
83
|
+
getStatusClass(region.status),
|
|
84
|
+
)}
|
|
85
|
+
>
|
|
86
|
+
{region.status}
|
|
87
|
+
</span>
|
|
88
|
+
)}
|
|
89
|
+
</div>
|
|
90
|
+
{region.description && (
|
|
91
|
+
<p className="mt-2 text-xs leading-relaxed text-muted-foreground">
|
|
92
|
+
{region.description}
|
|
93
|
+
</p>
|
|
94
|
+
)}
|
|
95
|
+
{region.nodeIds?.length ? (
|
|
96
|
+
<div className="mt-3 flex flex-wrap gap-1.5">
|
|
97
|
+
{region.nodeIds.map((nodeId) => {
|
|
98
|
+
const node = state.nodes.find(
|
|
99
|
+
(item) => item.id === nodeId,
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
return (
|
|
103
|
+
<span
|
|
104
|
+
key={nodeId}
|
|
105
|
+
className="rounded-full border border-border/60 bg-background/80 px-2 py-0.5 text-[10px] text-muted-foreground"
|
|
106
|
+
>
|
|
107
|
+
{node?.label ?? nodeId}
|
|
108
|
+
</span>
|
|
109
|
+
);
|
|
110
|
+
})}
|
|
111
|
+
</div>
|
|
112
|
+
) : null}
|
|
113
|
+
</div>
|
|
114
|
+
);
|
|
115
|
+
})}
|
|
116
|
+
</div>
|
|
117
|
+
) : null}
|
|
118
|
+
|
|
119
|
+
<div className="grid gap-3 sm:grid-cols-2 xl:grid-cols-3">
|
|
120
|
+
{state.nodes.map((node) => {
|
|
121
|
+
const isActive = node.id === state.activeNodeId || node.active;
|
|
122
|
+
|
|
123
|
+
return (
|
|
124
|
+
<div
|
|
125
|
+
key={node.id}
|
|
126
|
+
className={cn(
|
|
127
|
+
"rounded-2xl border border-border/60 bg-background/80 p-3 shadow-sm",
|
|
128
|
+
isActive && "border-primary/45 bg-primary/6 shadow-md",
|
|
129
|
+
node.emphasized && "ring-1 ring-primary/30",
|
|
130
|
+
)}
|
|
131
|
+
>
|
|
132
|
+
<div className="flex items-start justify-between gap-3">
|
|
133
|
+
<div>
|
|
134
|
+
<div className="text-xs font-medium uppercase tracking-[0.16em] text-muted-foreground">
|
|
135
|
+
{node.type ?? "step"}
|
|
136
|
+
</div>
|
|
137
|
+
<div className="mt-1 text-sm font-semibold text-card-foreground">
|
|
138
|
+
{node.label}
|
|
139
|
+
</div>
|
|
140
|
+
</div>
|
|
141
|
+
{node.status && (
|
|
142
|
+
<span
|
|
143
|
+
className={cn(
|
|
144
|
+
"rounded-full border px-2 py-1 text-[10px] font-medium uppercase tracking-[0.14em]",
|
|
145
|
+
getStatusClass(node.status),
|
|
146
|
+
)}
|
|
147
|
+
>
|
|
148
|
+
{node.status}
|
|
149
|
+
</span>
|
|
150
|
+
)}
|
|
151
|
+
</div>
|
|
152
|
+
{node.description && (
|
|
153
|
+
<p className="mt-2 text-xs leading-relaxed text-muted-foreground">
|
|
154
|
+
{node.description}
|
|
155
|
+
</p>
|
|
156
|
+
)}
|
|
157
|
+
{node.metadata && (
|
|
158
|
+
<div className="mt-3 text-[11px] text-muted-foreground/90">
|
|
159
|
+
{node.metadata}
|
|
160
|
+
</div>
|
|
161
|
+
)}
|
|
162
|
+
</div>
|
|
163
|
+
);
|
|
164
|
+
})}
|
|
165
|
+
</div>
|
|
166
|
+
|
|
167
|
+
{state.branches?.length ? (
|
|
168
|
+
<div className="rounded-2xl border border-dashed border-border/60 bg-background/60 p-3">
|
|
169
|
+
<div className="text-[10px] font-medium uppercase tracking-[0.16em] text-muted-foreground">
|
|
170
|
+
Transitions
|
|
171
|
+
</div>
|
|
172
|
+
<div className="mt-3 flex flex-wrap gap-2">
|
|
173
|
+
{state.branches.map((branch) => (
|
|
174
|
+
<div
|
|
175
|
+
key={branch.id}
|
|
176
|
+
className={cn(
|
|
177
|
+
"rounded-full border px-2.5 py-1 text-[10px] font-medium uppercase tracking-[0.14em]",
|
|
178
|
+
getStatusClass(branch.status),
|
|
179
|
+
branch.active &&
|
|
180
|
+
"border-primary/45 bg-primary/10 text-primary",
|
|
181
|
+
)}
|
|
182
|
+
>
|
|
183
|
+
{branch.label ?? `${branch.fromNodeId} → ${branch.toNodeId}`}
|
|
184
|
+
</div>
|
|
185
|
+
))}
|
|
186
|
+
</div>
|
|
187
|
+
</div>
|
|
188
|
+
) : null}
|
|
189
|
+
</div>
|
|
190
|
+
);
|
|
191
|
+
}
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
export type ProductDemoStatusTone =
|
|
2
|
+
| "neutral"
|
|
3
|
+
| "info"
|
|
4
|
+
| "success"
|
|
5
|
+
| "warning"
|
|
6
|
+
| "danger";
|
|
7
|
+
|
|
8
|
+
export type ProductDemoHighlightTone =
|
|
9
|
+
| ProductDemoStatusTone
|
|
10
|
+
| "accent"
|
|
11
|
+
| "muted";
|
|
12
|
+
|
|
13
|
+
export type ProductDemoWindowKey =
|
|
14
|
+
| "workflowStudio"
|
|
15
|
+
| "runConsole"
|
|
16
|
+
| "approvalInbox"
|
|
17
|
+
| "knowledgePanel";
|
|
18
|
+
|
|
19
|
+
export interface ProductDemoWindowStatus {
|
|
20
|
+
label: string;
|
|
21
|
+
tone?: ProductDemoStatusTone;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface ProductDemoWindowLayoutHint {
|
|
25
|
+
x?: number;
|
|
26
|
+
y?: number;
|
|
27
|
+
width?: number;
|
|
28
|
+
height?: number;
|
|
29
|
+
zIndex?: number;
|
|
30
|
+
rotateDeg?: number;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface ProductDemoWindowMeta {
|
|
34
|
+
key: ProductDemoWindowKey;
|
|
35
|
+
title: string;
|
|
36
|
+
subtitle?: string;
|
|
37
|
+
status?: ProductDemoWindowStatus;
|
|
38
|
+
badge?: string;
|
|
39
|
+
layoutHint?: ProductDemoWindowLayoutHint;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export interface ProductDemoHighlightTarget {
|
|
43
|
+
id: string;
|
|
44
|
+
label?: string;
|
|
45
|
+
tone?: ProductDemoHighlightTone;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export interface ProductDemoWorkflowNode {
|
|
49
|
+
id: string;
|
|
50
|
+
label: string;
|
|
51
|
+
description?: string;
|
|
52
|
+
type?: string;
|
|
53
|
+
status?: ProductDemoStatusTone;
|
|
54
|
+
active?: boolean;
|
|
55
|
+
emphasized?: boolean;
|
|
56
|
+
metadata?: string;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export interface ProductDemoWorkflowBranch {
|
|
60
|
+
id: string;
|
|
61
|
+
fromNodeId: string;
|
|
62
|
+
toNodeId: string;
|
|
63
|
+
label?: string;
|
|
64
|
+
status?: ProductDemoStatusTone;
|
|
65
|
+
active?: boolean;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export interface ProductDemoWorkflowRegion {
|
|
69
|
+
id: string;
|
|
70
|
+
label: string;
|
|
71
|
+
description?: string;
|
|
72
|
+
status?: ProductDemoStatusTone;
|
|
73
|
+
nodeIds?: string[];
|
|
74
|
+
active?: boolean;
|
|
75
|
+
highlighted?: boolean;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export interface ProductDemoWorkflowStudioState {
|
|
79
|
+
window: ProductDemoWindowMeta;
|
|
80
|
+
title?: string;
|
|
81
|
+
subtitle?: string;
|
|
82
|
+
nodes: ProductDemoWorkflowNode[];
|
|
83
|
+
branches?: ProductDemoWorkflowBranch[];
|
|
84
|
+
regions?: ProductDemoWorkflowRegion[];
|
|
85
|
+
activeNodeId?: string;
|
|
86
|
+
activeRegionId?: string;
|
|
87
|
+
highlights?: ProductDemoHighlightTarget[];
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export interface ProductDemoRunConsoleEntry {
|
|
91
|
+
id: string;
|
|
92
|
+
message: string;
|
|
93
|
+
timestamp?: string;
|
|
94
|
+
source?: string;
|
|
95
|
+
status?: ProductDemoStatusTone;
|
|
96
|
+
detail?: string;
|
|
97
|
+
highlighted?: boolean;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export interface ProductDemoRunConsoleMetric {
|
|
101
|
+
id: string;
|
|
102
|
+
label: string;
|
|
103
|
+
value: string;
|
|
104
|
+
tone?: ProductDemoStatusTone;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export interface ProductDemoRunConsoleState {
|
|
108
|
+
window: ProductDemoWindowMeta;
|
|
109
|
+
title?: string;
|
|
110
|
+
subtitle?: string;
|
|
111
|
+
statusLabel?: string;
|
|
112
|
+
progressLabel?: string;
|
|
113
|
+
entries: ProductDemoRunConsoleEntry[];
|
|
114
|
+
metrics?: ProductDemoRunConsoleMetric[];
|
|
115
|
+
progressPercent?: number;
|
|
116
|
+
activeEntryId?: string;
|
|
117
|
+
highlights?: ProductDemoHighlightTarget[];
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export interface ProductDemoApprovalAction {
|
|
121
|
+
id: string;
|
|
122
|
+
label: string;
|
|
123
|
+
tone?: ProductDemoStatusTone;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export interface ProductDemoApprovalItem {
|
|
127
|
+
id: string;
|
|
128
|
+
title: string;
|
|
129
|
+
description?: string;
|
|
130
|
+
requester?: string;
|
|
131
|
+
status?: ProductDemoStatusTone;
|
|
132
|
+
priorityLabel?: string;
|
|
133
|
+
dueLabel?: string;
|
|
134
|
+
actions?: ProductDemoApprovalAction[];
|
|
135
|
+
highlighted?: boolean;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export interface ProductDemoApprovalInboxState {
|
|
139
|
+
window: ProductDemoWindowMeta;
|
|
140
|
+
title?: string;
|
|
141
|
+
subtitle?: string;
|
|
142
|
+
counts?: Array<{
|
|
143
|
+
id: string;
|
|
144
|
+
label: string;
|
|
145
|
+
value: string;
|
|
146
|
+
tone?: ProductDemoStatusTone;
|
|
147
|
+
}>;
|
|
148
|
+
items: ProductDemoApprovalItem[];
|
|
149
|
+
activeItemId?: string;
|
|
150
|
+
highlights?: ProductDemoHighlightTarget[];
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export interface ProductDemoKnowledgeSource {
|
|
154
|
+
id: string;
|
|
155
|
+
label: string;
|
|
156
|
+
kind?: string;
|
|
157
|
+
status?: ProductDemoStatusTone;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
export interface ProductDemoKnowledgeSnippet {
|
|
161
|
+
id: string;
|
|
162
|
+
title: string;
|
|
163
|
+
content: string;
|
|
164
|
+
sourceId?: string;
|
|
165
|
+
confidence?: string;
|
|
166
|
+
excerptLabel?: string;
|
|
167
|
+
tags?: string[];
|
|
168
|
+
highlighted?: boolean;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
export interface ProductDemoKnowledgePanelState {
|
|
172
|
+
window: ProductDemoWindowMeta;
|
|
173
|
+
title?: string;
|
|
174
|
+
subtitle?: string;
|
|
175
|
+
query?: string;
|
|
176
|
+
summary?: string;
|
|
177
|
+
sources?: ProductDemoKnowledgeSource[];
|
|
178
|
+
snippets: ProductDemoKnowledgeSnippet[];
|
|
179
|
+
activeSnippetId?: string;
|
|
180
|
+
highlights?: ProductDemoHighlightTarget[];
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
export interface ProductDemoScenario {
|
|
184
|
+
key: string;
|
|
185
|
+
label?: string;
|
|
186
|
+
description?: string;
|
|
187
|
+
workflowStudio: ProductDemoWorkflowStudioState;
|
|
188
|
+
runConsole: ProductDemoRunConsoleState;
|
|
189
|
+
approvalInbox: ProductDemoApprovalInboxState;
|
|
190
|
+
knowledgePanel: ProductDemoKnowledgePanelState;
|
|
191
|
+
activeWindow?: ProductDemoWindowKey;
|
|
192
|
+
highlights?: ProductDemoHighlightTarget[];
|
|
193
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { ThemeProvider } from "@nextworks/blocks-core";
|
|
1
|
+
export { ThemeProvider } from "@nextworks/blocks-core";
|