@contractspec/example.learning-journey-ui-onboarding 3.7.6 → 3.7.10
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 +3 -3
- package/AGENTS.md +50 -24
- package/CHANGELOG.md +34 -0
- package/README.md +66 -26
- package/dist/OnboardingMiniApp.js +280 -280
- package/dist/browser/OnboardingMiniApp.js +280 -280
- package/dist/browser/components/CodeSnippet.js +4 -4
- package/dist/browser/components/JourneyMap.js +1 -1
- package/dist/browser/components/StepChecklist.js +6 -6
- package/dist/browser/components/index.js +11 -11
- package/dist/browser/index.js +285 -284
- package/dist/browser/views/Overview.js +14 -14
- package/dist/browser/views/Progress.js +9 -9
- package/dist/browser/views/Steps.js +8 -8
- package/dist/browser/views/Timeline.js +6 -6
- package/dist/browser/views/index.js +276 -276
- package/dist/components/CodeSnippet.js +4 -4
- package/dist/components/JourneyMap.js +1 -1
- package/dist/components/StepChecklist.js +6 -6
- package/dist/components/index.d.ts +1 -1
- package/dist/components/index.js +11 -11
- package/dist/index.d.ts +4 -4
- package/dist/index.js +285 -284
- package/dist/node/OnboardingMiniApp.js +280 -280
- package/dist/node/components/CodeSnippet.js +4 -4
- package/dist/node/components/JourneyMap.js +1 -1
- package/dist/node/components/StepChecklist.js +6 -6
- package/dist/node/components/index.js +11 -11
- package/dist/node/index.js +285 -284
- package/dist/node/views/Overview.js +14 -14
- package/dist/node/views/Progress.js +9 -9
- package/dist/node/views/Steps.js +8 -8
- package/dist/node/views/Timeline.js +6 -6
- package/dist/node/views/index.js +276 -276
- package/dist/views/Overview.js +14 -14
- package/dist/views/Progress.js +9 -9
- package/dist/views/Steps.js +8 -8
- package/dist/views/Timeline.js +6 -6
- package/dist/views/index.d.ts +1 -1
- package/dist/views/index.js +276 -276
- package/package.json +13 -13
- package/src/OnboardingMiniApp.tsx +70 -70
- package/src/components/CodeSnippet.tsx +43 -43
- package/src/components/JourneyMap.tsx +70 -70
- package/src/components/StepChecklist.tsx +118 -118
- package/src/components/index.ts +1 -1
- package/src/docs/learning-journey-ui-onboarding.docblock.ts +11 -11
- package/src/example.ts +25 -25
- package/src/index.ts +5 -6
- package/src/learning-journey-ui-onboarding.feature.ts +12 -12
- package/src/views/Overview.tsx +182 -182
- package/src/views/Progress.tsx +167 -167
- package/src/views/Steps.tsx +79 -79
- package/src/views/Timeline.tsx +126 -126
- package/src/views/index.ts +1 -1
- package/tsconfig.json +7 -8
- package/tsdown.config.js +7 -13
package/src/views/Overview.tsx
CHANGED
|
@@ -1,204 +1,204 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
+
import type { LearningViewProps } from '@contractspec/example.learning-journey-ui-shared';
|
|
4
|
+
import { XpBar } from '@contractspec/example.learning-journey-ui-shared';
|
|
3
5
|
import { Button } from '@contractspec/lib.design-system';
|
|
4
6
|
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
Card,
|
|
8
|
+
CardContent,
|
|
9
|
+
CardHeader,
|
|
10
|
+
CardTitle,
|
|
9
11
|
} from '@contractspec/lib.ui-kit-web/ui/card';
|
|
10
12
|
import { Progress } from '@contractspec/lib.ui-kit-web/ui/progress';
|
|
11
|
-
import { XpBar } from '@contractspec/example.learning-journey-ui-shared';
|
|
12
|
-
import type { LearningViewProps } from '@contractspec/example.learning-journey-ui-shared';
|
|
13
13
|
|
|
14
14
|
interface OnboardingOverviewProps extends LearningViewProps {
|
|
15
|
-
|
|
15
|
+
onStart?: () => void;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
export function Overview({
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
track,
|
|
20
|
+
progress,
|
|
21
|
+
onStart,
|
|
22
22
|
}: OnboardingOverviewProps) {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
23
|
+
const totalSteps = track.steps.length;
|
|
24
|
+
const completedSteps = progress.completedStepIds.length;
|
|
25
|
+
const percentComplete =
|
|
26
|
+
totalSteps > 0 ? (completedSteps / totalSteps) * 100 : 0;
|
|
27
|
+
const isComplete = completedSteps === totalSteps;
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
// Estimate time remaining (rough: 5 min per step)
|
|
30
|
+
const remainingSteps = totalSteps - completedSteps;
|
|
31
|
+
const estimatedMinutes = remainingSteps * 5;
|
|
32
32
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
33
|
+
const totalXp =
|
|
34
|
+
track.totalXp ??
|
|
35
|
+
track.steps.reduce((sum, s) => sum + (s.xpReward ?? 0), 0) +
|
|
36
|
+
(track.completionRewards?.xpBonus ?? 0);
|
|
37
37
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
38
|
+
return (
|
|
39
|
+
<div className="space-y-6">
|
|
40
|
+
{/* Welcome Banner */}
|
|
41
|
+
<Card className="overflow-hidden bg-gradient-to-r from-blue-500/10 via-violet-500/10 to-purple-500/10">
|
|
42
|
+
<CardContent className="p-8">
|
|
43
|
+
<div className="flex flex-col items-center gap-6 text-center md:flex-row md:text-left">
|
|
44
|
+
<div className="flex h-20 w-20 items-center justify-center rounded-2xl bg-gradient-to-br from-blue-500 to-violet-600 text-4xl shadow-lg">
|
|
45
|
+
{isComplete ? '🎉' : '🚀'}
|
|
46
|
+
</div>
|
|
47
|
+
<div className="flex-1">
|
|
48
|
+
<h1 className="font-bold text-2xl">{track.name}</h1>
|
|
49
|
+
<p className="mt-1 max-w-2xl text-muted-foreground">
|
|
50
|
+
{track.description}
|
|
51
|
+
</p>
|
|
52
|
+
{!isComplete && (
|
|
53
|
+
<p className="mt-3 text-muted-foreground text-sm">
|
|
54
|
+
⏱️ Estimated time:{' '}
|
|
55
|
+
{estimatedMinutes > 0
|
|
56
|
+
? `~${estimatedMinutes} minutes`
|
|
57
|
+
: 'Less than a minute'}
|
|
58
|
+
</p>
|
|
59
|
+
)}
|
|
60
|
+
</div>
|
|
61
|
+
{!isComplete && (
|
|
62
|
+
<Button size="lg" onClick={onStart}>
|
|
63
|
+
{completedSteps > 0 ? 'Continue' : 'Get Started'}
|
|
64
|
+
</Button>
|
|
65
|
+
)}
|
|
66
|
+
</div>
|
|
67
|
+
</CardContent>
|
|
68
|
+
</Card>
|
|
69
69
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
70
|
+
{/* Progress Overview */}
|
|
71
|
+
<div className="grid gap-4 md:grid-cols-3">
|
|
72
|
+
<Card>
|
|
73
|
+
<CardHeader className="pb-2">
|
|
74
|
+
<CardTitle className="font-medium text-muted-foreground text-sm">
|
|
75
|
+
Progress
|
|
76
|
+
</CardTitle>
|
|
77
|
+
</CardHeader>
|
|
78
|
+
<CardContent>
|
|
79
|
+
<div className="font-bold text-3xl">
|
|
80
|
+
{Math.round(percentComplete)}%
|
|
81
|
+
</div>
|
|
82
|
+
<Progress value={percentComplete} className="mt-2 h-2" />
|
|
83
|
+
<p className="mt-2 text-muted-foreground text-sm">
|
|
84
|
+
{completedSteps} of {totalSteps} steps completed
|
|
85
|
+
</p>
|
|
86
|
+
</CardContent>
|
|
87
|
+
</Card>
|
|
88
88
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
89
|
+
<Card>
|
|
90
|
+
<CardHeader className="pb-2">
|
|
91
|
+
<CardTitle className="font-medium text-muted-foreground text-sm">
|
|
92
|
+
XP Earned
|
|
93
|
+
</CardTitle>
|
|
94
|
+
</CardHeader>
|
|
95
|
+
<CardContent>
|
|
96
|
+
<div className="font-bold text-3xl text-blue-500">
|
|
97
|
+
{progress.xpEarned}
|
|
98
|
+
</div>
|
|
99
|
+
<XpBar
|
|
100
|
+
current={progress.xpEarned}
|
|
101
|
+
max={totalXp}
|
|
102
|
+
showLabel={false}
|
|
103
|
+
size="sm"
|
|
104
|
+
/>
|
|
105
|
+
</CardContent>
|
|
106
|
+
</Card>
|
|
107
107
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
108
|
+
<Card>
|
|
109
|
+
<CardHeader className="pb-2">
|
|
110
|
+
<CardTitle className="font-medium text-muted-foreground text-sm">
|
|
111
|
+
Time Remaining
|
|
112
|
+
</CardTitle>
|
|
113
|
+
</CardHeader>
|
|
114
|
+
<CardContent>
|
|
115
|
+
<div className="font-bold text-3xl">
|
|
116
|
+
{isComplete ? '✓' : `~${estimatedMinutes}m`}
|
|
117
|
+
</div>
|
|
118
|
+
<p className="mt-2 text-muted-foreground text-sm">
|
|
119
|
+
{isComplete ? 'All done!' : `${remainingSteps} steps to go`}
|
|
120
|
+
</p>
|
|
121
|
+
</CardContent>
|
|
122
|
+
</Card>
|
|
123
|
+
</div>
|
|
124
124
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
125
|
+
{/* Step Preview */}
|
|
126
|
+
<Card>
|
|
127
|
+
<CardHeader>
|
|
128
|
+
<CardTitle className="flex items-center gap-2">
|
|
129
|
+
<span>📋</span>
|
|
130
|
+
<span>Your Journey</span>
|
|
131
|
+
</CardTitle>
|
|
132
|
+
</CardHeader>
|
|
133
|
+
<CardContent>
|
|
134
|
+
<div className="space-y-3">
|
|
135
|
+
{track.steps.map((step, index) => {
|
|
136
|
+
const isStepCompleted = progress.completedStepIds.includes(
|
|
137
|
+
step.id
|
|
138
|
+
);
|
|
139
|
+
const isCurrent =
|
|
140
|
+
!isStepCompleted &&
|
|
141
|
+
track.steps
|
|
142
|
+
.slice(0, index)
|
|
143
|
+
.every((s) => progress.completedStepIds.includes(s.id));
|
|
144
144
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
145
|
+
return (
|
|
146
|
+
<div
|
|
147
|
+
key={step.id}
|
|
148
|
+
className="flex items-center gap-4 rounded-lg border p-3"
|
|
149
|
+
>
|
|
150
|
+
<div
|
|
151
|
+
className={`flex h-8 w-8 shrink-0 items-center justify-center rounded-full font-semibold text-sm ${
|
|
152
|
+
isStepCompleted
|
|
153
|
+
? 'bg-green-500 text-white'
|
|
154
|
+
: isCurrent
|
|
155
|
+
? 'bg-blue-500 text-white'
|
|
156
|
+
: 'bg-muted text-muted-foreground'
|
|
157
|
+
}`}
|
|
158
|
+
>
|
|
159
|
+
{isStepCompleted ? '✓' : index + 1}
|
|
160
|
+
</div>
|
|
161
|
+
<div className="min-w-0 flex-1">
|
|
162
|
+
<p
|
|
163
|
+
className={`font-medium ${
|
|
164
|
+
isStepCompleted
|
|
165
|
+
? 'text-green-500'
|
|
166
|
+
: isCurrent
|
|
167
|
+
? 'text-foreground'
|
|
168
|
+
: 'text-muted-foreground'
|
|
169
|
+
}`}
|
|
170
|
+
>
|
|
171
|
+
{step.title}
|
|
172
|
+
</p>
|
|
173
|
+
</div>
|
|
174
|
+
{step.xpReward && (
|
|
175
|
+
<span className="text-muted-foreground text-sm">
|
|
176
|
+
+{step.xpReward} XP
|
|
177
|
+
</span>
|
|
178
|
+
)}
|
|
179
|
+
</div>
|
|
180
|
+
);
|
|
181
|
+
})}
|
|
182
|
+
</div>
|
|
183
|
+
</CardContent>
|
|
184
|
+
</Card>
|
|
185
185
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
186
|
+
{/* Completion Message */}
|
|
187
|
+
{isComplete && (
|
|
188
|
+
<Card className="border-green-500/50 bg-green-500/5">
|
|
189
|
+
<CardContent className="flex items-center gap-4 p-6">
|
|
190
|
+
<div className="text-4xl">🎉</div>
|
|
191
|
+
<div>
|
|
192
|
+
<h3 className="font-semibold text-green-500 text-lg">
|
|
193
|
+
Onboarding Complete!
|
|
194
|
+
</h3>
|
|
195
|
+
<p className="text-muted-foreground">
|
|
196
|
+
You've completed all {totalSteps} steps. Welcome aboard!
|
|
197
|
+
</p>
|
|
198
|
+
</div>
|
|
199
|
+
</CardContent>
|
|
200
|
+
</Card>
|
|
201
|
+
)}
|
|
202
|
+
</div>
|
|
203
|
+
);
|
|
204
204
|
}
|