@startsimpli/ui 0.4.21 → 0.4.23

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@startsimpli/ui",
3
- "version": "0.4.21",
3
+ "version": "0.4.23",
4
4
  "description": "Shared UI components package for StartSimpli applications",
5
5
  "main": "./src/index.ts",
6
6
  "types": "./src/index.ts",
@@ -32,7 +32,7 @@
32
32
  "next": "^14.0.0 || ^15.0.0 || ^16.0.0",
33
33
  "react": "^18.0.0 || ^19.0.0",
34
34
  "react-dom": "^18.0.0 || ^19.0.0",
35
- "@startsimpli/auth": "0.4.18"
35
+ "@startsimpli/auth": "0.4.20"
36
36
  },
37
37
  "peerDependenciesMeta": {
38
38
  "@startsimpli/auth": {
@@ -0,0 +1,256 @@
1
+ 'use client';
2
+
3
+ import { useState, useEffect } from 'react';
4
+ import { Button } from '../ui/button';
5
+ import {
6
+ Card,
7
+ CardHeader,
8
+ CardTitle,
9
+ CardDescription,
10
+ CardContent,
11
+ } from '../ui/card';
12
+ import { Checkbox } from '../ui/checkbox';
13
+ import { Label } from '../ui/label';
14
+ import { Sparkles, PlayCircle, HelpCircle, X } from 'lucide-react';
15
+
16
+ const STORAGE_KEY = 'workflow_guidance_dismissed';
17
+
18
+ export interface WorkflowEmptyStateProps {
19
+ onOpenTemplateGallery: () => void;
20
+ onStartFromScratch: () => void;
21
+ onOpenHelp?: () => void;
22
+ }
23
+
24
+ /**
25
+ * Empty State Component for Workflow Canvas
26
+ *
27
+ * Provides first-time user guidance with two paths:
28
+ * 1. Template Gallery - Pre-built workflows to learn from
29
+ * 2. Start From Scratch - Opens node palette with guidance
30
+ *
31
+ * Features:
32
+ * - localStorage-based dismissal (respects user preference)
33
+ * - Non-intrusive inline design (not a modal)
34
+ * - Action-oriented messaging (not "Welcome!")
35
+ * - Re-accessible via help button
36
+ */
37
+ export function WorkflowEmptyState({
38
+ onOpenTemplateGallery,
39
+ onStartFromScratch,
40
+ onOpenHelp,
41
+ }: WorkflowEmptyStateProps) {
42
+ const [isDismissed, setIsDismissed] = useState(true);
43
+ const [dontShowAgain, setDontShowAgain] = useState(false);
44
+
45
+ useEffect(() => {
46
+ // Check if user has dismissed guidance
47
+ const dismissed = localStorage.getItem(STORAGE_KEY) === 'true';
48
+ setIsDismissed(dismissed);
49
+ }, []);
50
+
51
+ const handleTemplateGalleryClick = () => {
52
+ if (dontShowAgain) {
53
+ localStorage.setItem(STORAGE_KEY, 'true');
54
+ }
55
+ setIsDismissed(true);
56
+ onOpenTemplateGallery();
57
+ };
58
+
59
+ const handleStartFromScratchClick = () => {
60
+ if (dontShowAgain) {
61
+ localStorage.setItem(STORAGE_KEY, 'true');
62
+ }
63
+ setIsDismissed(true);
64
+ onStartFromScratch();
65
+ };
66
+
67
+ const handleDismiss = () => {
68
+ if (dontShowAgain) {
69
+ localStorage.setItem(STORAGE_KEY, 'true');
70
+ }
71
+ setIsDismissed(true);
72
+ };
73
+
74
+ if (isDismissed) {
75
+ // Show persistent help button for returning users
76
+ return (
77
+ <div className="absolute bottom-6 right-6 z-10">
78
+ <Button
79
+ variant="outline"
80
+ size="icon"
81
+ onClick={onOpenHelp}
82
+ className="h-12 w-12 rounded-full shadow-lg hover:shadow-xl transition-all"
83
+ title="Need help? View templates and guidance"
84
+ >
85
+ <HelpCircle className="h-5 w-5" />
86
+ </Button>
87
+ </div>
88
+ );
89
+ }
90
+
91
+ return (
92
+ <div
93
+ className="flex items-center justify-center z-10"
94
+ role="dialog"
95
+ aria-labelledby="welcome-title"
96
+ aria-describedby="welcome-description"
97
+ aria-modal="false"
98
+ >
99
+ <Card className="w-full max-w-[720px] pointer-events-auto animate-in fade-in-0 zoom-in-95 duration-300 relative">
100
+ {/* Close button */}
101
+ <button
102
+ onClick={handleDismiss}
103
+ aria-label="Close welcome panel"
104
+ aria-keyshortcuts="Escape"
105
+ className="absolute right-4 top-4 rounded-full p-2 text-muted-foreground hover:bg-muted hover:text-foreground transition-colors"
106
+ >
107
+ <X className="w-5 h-5" aria-hidden="true" />
108
+ </button>
109
+
110
+ <CardHeader className="text-center pb-4 pt-10 px-10">
111
+ <CardTitle id="welcome-title" className="text-2xl font-semibold">
112
+ Welcome to Workflow Builder
113
+ </CardTitle>
114
+ <CardDescription
115
+ id="welcome-description"
116
+ className="text-sm text-muted-foreground leading-relaxed mt-2"
117
+ >
118
+ Create automated workflows with browser actions, logic, and AI
119
+ </CardDescription>
120
+ </CardHeader>
121
+
122
+ <CardContent className="flex flex-col gap-6 px-10 pb-10">
123
+ {/* Option 1: Template Gallery */}
124
+ <button
125
+ onClick={handleTemplateGalleryClick}
126
+ className="block w-full group text-left"
127
+ aria-label="Browse template gallery"
128
+ aria-describedby="template-gallery-desc"
129
+ >
130
+ <Card className="cursor-pointer transition-all duration-150 hover:shadow-md hover:border-primary/50 hover:scale-[1.02]">
131
+ <CardContent className="pt-6 pb-6">
132
+ <div className="flex items-start gap-4">
133
+ <div className="flex-shrink-0">
134
+ <div className="h-12 w-12 rounded-lg bg-primary/5 flex items-center justify-center group-hover:bg-primary/10 transition-colors">
135
+ <Sparkles className="h-6 w-6 text-primary/60" />
136
+ </div>
137
+ </div>
138
+ <div className="flex-1 text-left">
139
+ <h3 className="font-medium text-base mb-1">
140
+ Browse Template Gallery
141
+ </h3>
142
+ <p className="text-xs text-muted-foreground leading-relaxed">
143
+ Start with a pre-built workflow and customize it to your
144
+ needs. Perfect for learning common patterns.
145
+ </p>
146
+ <div className="mt-2 flex items-center gap-2 text-xs text-muted-foreground">
147
+ <span className="inline-flex items-center gap-1">
148
+ ⭐⭐⭐⭐⭐ Popular choice
149
+ </span>
150
+ <span>•</span>
151
+ <span>5 templates available</span>
152
+ </div>
153
+ </div>
154
+ </div>
155
+ </CardContent>
156
+ </Card>
157
+ <span id="template-gallery-desc" className="sr-only">
158
+ Choose from 5 pre-built workflow templates including login flows,
159
+ data extraction, API integration, multi-page navigation, and form
160
+ submission.
161
+ </span>
162
+ </button>
163
+
164
+ {/* Option 2: Start From Scratch */}
165
+ <button
166
+ onClick={handleStartFromScratchClick}
167
+ className="block w-full group text-left"
168
+ aria-label="Start from scratch"
169
+ aria-describedby="start-scratch-desc"
170
+ >
171
+ <Card className="cursor-pointer transition-all duration-150 hover:shadow-md hover:border-primary/50 hover:scale-[1.02]">
172
+ <CardContent className="pt-6 pb-6">
173
+ <div className="flex items-start gap-4">
174
+ <div className="flex-shrink-0">
175
+ <div className="h-12 w-12 rounded-lg bg-primary/5 flex items-center justify-center group-hover:bg-primary/10 transition-colors">
176
+ <PlayCircle className="h-6 w-6 text-primary/60" />
177
+ </div>
178
+ </div>
179
+ <div className="flex-1 text-left">
180
+ <h3 className="font-medium text-base mb-1">
181
+ Start From Scratch
182
+ </h3>
183
+ <p className="text-xs text-muted-foreground leading-relaxed">
184
+ Build your workflow from the ground up. We&apos;ll
185
+ highlight the node palette and show you how to get started.
186
+ </p>
187
+ <div className="mt-2 text-xs text-muted-foreground">
188
+ For experienced users
189
+ </div>
190
+ </div>
191
+ </div>
192
+ </CardContent>
193
+ </Card>
194
+ <span id="start-scratch-desc" className="sr-only">
195
+ Create a custom workflow by adding nodes from the node palette.
196
+ Ideal for users familiar with workflow automation.
197
+ </span>
198
+ </button>
199
+
200
+ {/* Don't show again checkbox */}
201
+ <div className="flex items-center justify-between pt-4 border-t">
202
+ <div className="flex items-center space-x-2">
203
+ <Checkbox
204
+ id="dontShowAgain"
205
+ checked={dontShowAgain}
206
+ onCheckedChange={(checked) => setDontShowAgain(checked === true)}
207
+ />
208
+ <Label
209
+ htmlFor="dontShowAgain"
210
+ className="text-sm text-muted-foreground cursor-pointer"
211
+ >
212
+ Don&apos;t show this again
213
+ </Label>
214
+ </div>
215
+ <Button
216
+ variant="ghost"
217
+ size="sm"
218
+ onClick={handleDismiss}
219
+ className="text-muted-foreground hover:text-foreground"
220
+ >
221
+ Close
222
+ </Button>
223
+ </div>
224
+ </CardContent>
225
+ </Card>
226
+ </div>
227
+ );
228
+ }
229
+
230
+ /**
231
+ * Hook to manage empty state visibility and reset.
232
+ */
233
+ export function useWorkflowEmptyState() {
234
+ const [isGuidanceDismissed, setIsGuidanceDismissed] = useState(true);
235
+
236
+ useEffect(() => {
237
+ const dismissed = localStorage.getItem(STORAGE_KEY) === 'true';
238
+ setIsGuidanceDismissed(dismissed);
239
+ }, []);
240
+
241
+ const resetGuidance = () => {
242
+ localStorage.removeItem(STORAGE_KEY);
243
+ setIsGuidanceDismissed(false);
244
+ };
245
+
246
+ const dismissGuidance = () => {
247
+ localStorage.setItem(STORAGE_KEY, 'true');
248
+ setIsGuidanceDismissed(true);
249
+ };
250
+
251
+ return {
252
+ isGuidanceDismissed,
253
+ resetGuidance,
254
+ dismissGuidance,
255
+ };
256
+ }