@contractspec/example.learning-journey-ui-onboarding 3.7.6 → 3.7.7

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.
Files changed (56) hide show
  1. package/.turbo/turbo-build.log +3 -3
  2. package/AGENTS.md +50 -24
  3. package/README.md +66 -26
  4. package/dist/OnboardingMiniApp.js +280 -280
  5. package/dist/browser/OnboardingMiniApp.js +280 -280
  6. package/dist/browser/components/CodeSnippet.js +4 -4
  7. package/dist/browser/components/JourneyMap.js +1 -1
  8. package/dist/browser/components/StepChecklist.js +6 -6
  9. package/dist/browser/components/index.js +11 -11
  10. package/dist/browser/index.js +285 -284
  11. package/dist/browser/views/Overview.js +14 -14
  12. package/dist/browser/views/Progress.js +9 -9
  13. package/dist/browser/views/Steps.js +8 -8
  14. package/dist/browser/views/Timeline.js +6 -6
  15. package/dist/browser/views/index.js +276 -276
  16. package/dist/components/CodeSnippet.js +4 -4
  17. package/dist/components/JourneyMap.js +1 -1
  18. package/dist/components/StepChecklist.js +6 -6
  19. package/dist/components/index.d.ts +1 -1
  20. package/dist/components/index.js +11 -11
  21. package/dist/index.d.ts +4 -4
  22. package/dist/index.js +285 -284
  23. package/dist/node/OnboardingMiniApp.js +280 -280
  24. package/dist/node/components/CodeSnippet.js +4 -4
  25. package/dist/node/components/JourneyMap.js +1 -1
  26. package/dist/node/components/StepChecklist.js +6 -6
  27. package/dist/node/components/index.js +11 -11
  28. package/dist/node/index.js +285 -284
  29. package/dist/node/views/Overview.js +14 -14
  30. package/dist/node/views/Progress.js +9 -9
  31. package/dist/node/views/Steps.js +8 -8
  32. package/dist/node/views/Timeline.js +6 -6
  33. package/dist/node/views/index.js +276 -276
  34. package/dist/views/Overview.js +14 -14
  35. package/dist/views/Progress.js +9 -9
  36. package/dist/views/Steps.js +8 -8
  37. package/dist/views/Timeline.js +6 -6
  38. package/dist/views/index.d.ts +1 -1
  39. package/dist/views/index.js +276 -276
  40. package/package.json +10 -10
  41. package/src/OnboardingMiniApp.tsx +70 -70
  42. package/src/components/CodeSnippet.tsx +43 -43
  43. package/src/components/JourneyMap.tsx +70 -70
  44. package/src/components/StepChecklist.tsx +118 -118
  45. package/src/components/index.ts +1 -1
  46. package/src/docs/learning-journey-ui-onboarding.docblock.ts +11 -11
  47. package/src/example.ts +25 -25
  48. package/src/index.ts +5 -6
  49. package/src/learning-journey-ui-onboarding.feature.ts +12 -12
  50. package/src/views/Overview.tsx +182 -182
  51. package/src/views/Progress.tsx +167 -167
  52. package/src/views/Steps.tsx +79 -79
  53. package/src/views/Timeline.tsx +126 -126
  54. package/src/views/index.ts +1 -1
  55. package/tsconfig.json +7 -8
  56. package/tsdown.config.js +7 -13
@@ -1,185 +1,185 @@
1
1
  'use client';
2
2
 
3
+ import type { LearningViewProps } from '@contractspec/example.learning-journey-ui-shared';
4
+ import {
5
+ BadgeDisplay,
6
+ XpBar,
7
+ } from '@contractspec/example.learning-journey-ui-shared';
3
8
  import {
4
- Card,
5
- CardContent,
6
- CardHeader,
7
- CardTitle,
9
+ Card,
10
+ CardContent,
11
+ CardHeader,
12
+ CardTitle,
8
13
  } from '@contractspec/lib.ui-kit-web/ui/card';
9
14
  import { Progress } from '@contractspec/lib.ui-kit-web/ui/progress';
10
- import {
11
- XpBar,
12
- BadgeDisplay,
13
- } from '@contractspec/example.learning-journey-ui-shared';
14
- import type { LearningViewProps } from '@contractspec/example.learning-journey-ui-shared';
15
15
 
16
16
  export function ProgressView({ track, progress }: LearningViewProps) {
17
- const totalSteps = track.steps.length;
18
- const completedSteps = progress.completedStepIds.length;
19
- const percentComplete =
20
- totalSteps > 0 ? (completedSteps / totalSteps) * 100 : 0;
17
+ const totalSteps = track.steps.length;
18
+ const completedSteps = progress.completedStepIds.length;
19
+ const percentComplete =
20
+ totalSteps > 0 ? (completedSteps / totalSteps) * 100 : 0;
21
21
 
22
- const totalXp =
23
- track.totalXp ??
24
- track.steps.reduce((sum, s) => sum + (s.xpReward ?? 0), 0) +
25
- (track.completionRewards?.xpBonus ?? 0);
22
+ const totalXp =
23
+ track.totalXp ??
24
+ track.steps.reduce((sum, s) => sum + (s.xpReward ?? 0), 0) +
25
+ (track.completionRewards?.xpBonus ?? 0);
26
26
 
27
- const remainingSteps = totalSteps - completedSteps;
28
- const estimatedMinutes = remainingSteps * 5;
27
+ const remainingSteps = totalSteps - completedSteps;
28
+ const estimatedMinutes = remainingSteps * 5;
29
29
 
30
- return (
31
- <div className="space-y-6">
32
- {/* Main Progress */}
33
- <Card>
34
- <CardHeader>
35
- <CardTitle className="flex items-center gap-2">
36
- <span>📈</span>
37
- <span>Your Progress</span>
38
- </CardTitle>
39
- </CardHeader>
40
- <CardContent className="space-y-6">
41
- {/* Circular progress indicator */}
42
- <div className="flex items-center justify-center">
43
- <div className="relative flex h-40 w-40 items-center justify-center">
44
- <svg
45
- className="absolute h-full w-full -rotate-90"
46
- viewBox="0 0 100 100"
47
- >
48
- <circle
49
- cx="50"
50
- cy="50"
51
- r="45"
52
- fill="none"
53
- strokeWidth="8"
54
- className="stroke-muted"
55
- />
56
- <circle
57
- cx="50"
58
- cy="50"
59
- r="45"
60
- fill="none"
61
- strokeWidth="8"
62
- strokeLinecap="round"
63
- strokeDasharray={`${percentComplete * 2.83} 283`}
64
- className="stroke-blue-500 transition-all duration-500"
65
- />
66
- </svg>
67
- <div className="text-center">
68
- <div className="text-3xl font-bold">
69
- {Math.round(percentComplete)}%
70
- </div>
71
- <div className="text-muted-foreground text-sm">Complete</div>
72
- </div>
73
- </div>
74
- </div>
30
+ return (
31
+ <div className="space-y-6">
32
+ {/* Main Progress */}
33
+ <Card>
34
+ <CardHeader>
35
+ <CardTitle className="flex items-center gap-2">
36
+ <span>📈</span>
37
+ <span>Your Progress</span>
38
+ </CardTitle>
39
+ </CardHeader>
40
+ <CardContent className="space-y-6">
41
+ {/* Circular progress indicator */}
42
+ <div className="flex items-center justify-center">
43
+ <div className="relative flex h-40 w-40 items-center justify-center">
44
+ <svg
45
+ className="absolute h-full w-full -rotate-90"
46
+ viewBox="0 0 100 100"
47
+ >
48
+ <circle
49
+ cx="50"
50
+ cy="50"
51
+ r="45"
52
+ fill="none"
53
+ strokeWidth="8"
54
+ className="stroke-muted"
55
+ />
56
+ <circle
57
+ cx="50"
58
+ cy="50"
59
+ r="45"
60
+ fill="none"
61
+ strokeWidth="8"
62
+ strokeLinecap="round"
63
+ strokeDasharray={`${percentComplete * 2.83} 283`}
64
+ className="stroke-blue-500 transition-all duration-500"
65
+ />
66
+ </svg>
67
+ <div className="text-center">
68
+ <div className="font-bold text-3xl">
69
+ {Math.round(percentComplete)}%
70
+ </div>
71
+ <div className="text-muted-foreground text-sm">Complete</div>
72
+ </div>
73
+ </div>
74
+ </div>
75
75
 
76
- {/* Stats row */}
77
- <div className="grid grid-cols-3 gap-4 text-center">
78
- <div>
79
- <div className="text-2xl font-bold text-green-500">
80
- {completedSteps}
81
- </div>
82
- <div className="text-muted-foreground text-sm">Completed</div>
83
- </div>
84
- <div>
85
- <div className="text-2xl font-bold text-orange-500">
86
- {remainingSteps}
87
- </div>
88
- <div className="text-muted-foreground text-sm">Remaining</div>
89
- </div>
90
- <div>
91
- <div className="text-2xl font-bold">{estimatedMinutes}m</div>
92
- <div className="text-muted-foreground text-sm">Est. Time</div>
93
- </div>
94
- </div>
95
- </CardContent>
96
- </Card>
76
+ {/* Stats row */}
77
+ <div className="grid grid-cols-3 gap-4 text-center">
78
+ <div>
79
+ <div className="font-bold text-2xl text-green-500">
80
+ {completedSteps}
81
+ </div>
82
+ <div className="text-muted-foreground text-sm">Completed</div>
83
+ </div>
84
+ <div>
85
+ <div className="font-bold text-2xl text-orange-500">
86
+ {remainingSteps}
87
+ </div>
88
+ <div className="text-muted-foreground text-sm">Remaining</div>
89
+ </div>
90
+ <div>
91
+ <div className="font-bold text-2xl">{estimatedMinutes}m</div>
92
+ <div className="text-muted-foreground text-sm">Est. Time</div>
93
+ </div>
94
+ </div>
95
+ </CardContent>
96
+ </Card>
97
97
 
98
- {/* XP Progress */}
99
- <Card>
100
- <CardHeader>
101
- <CardTitle className="flex items-center gap-2">
102
- <span>⚡</span>
103
- <span>Experience Points</span>
104
- </CardTitle>
105
- </CardHeader>
106
- <CardContent className="space-y-4">
107
- <div className="flex items-baseline gap-2">
108
- <span className="text-3xl font-bold text-blue-500">
109
- {progress.xpEarned}
110
- </span>
111
- <span className="text-muted-foreground">/ {totalXp} XP</span>
112
- </div>
113
- <XpBar
114
- current={progress.xpEarned}
115
- max={totalXp}
116
- showLabel={false}
117
- size="lg"
118
- />
119
- </CardContent>
120
- </Card>
98
+ {/* XP Progress */}
99
+ <Card>
100
+ <CardHeader>
101
+ <CardTitle className="flex items-center gap-2">
102
+ <span>⚡</span>
103
+ <span>Experience Points</span>
104
+ </CardTitle>
105
+ </CardHeader>
106
+ <CardContent className="space-y-4">
107
+ <div className="flex items-baseline gap-2">
108
+ <span className="font-bold text-3xl text-blue-500">
109
+ {progress.xpEarned}
110
+ </span>
111
+ <span className="text-muted-foreground">/ {totalXp} XP</span>
112
+ </div>
113
+ <XpBar
114
+ current={progress.xpEarned}
115
+ max={totalXp}
116
+ showLabel={false}
117
+ size="lg"
118
+ />
119
+ </CardContent>
120
+ </Card>
121
121
 
122
- {/* Badges */}
123
- <Card>
124
- <CardHeader>
125
- <CardTitle className="flex items-center gap-2">
126
- <span>🏅</span>
127
- <span>Achievements</span>
128
- </CardTitle>
129
- </CardHeader>
130
- <CardContent>
131
- <BadgeDisplay badges={progress.badges} size="lg" />
132
- {progress.badges.length === 0 &&
133
- track.completionRewards?.badgeKey && (
134
- <p className="text-muted-foreground text-sm">
135
- Complete all steps to earn the "
136
- {track.completionRewards.badgeKey}" badge!
137
- </p>
138
- )}
139
- </CardContent>
140
- </Card>
122
+ {/* Badges */}
123
+ <Card>
124
+ <CardHeader>
125
+ <CardTitle className="flex items-center gap-2">
126
+ <span>🏅</span>
127
+ <span>Achievements</span>
128
+ </CardTitle>
129
+ </CardHeader>
130
+ <CardContent>
131
+ <BadgeDisplay badges={progress.badges} size="lg" />
132
+ {progress.badges.length === 0 &&
133
+ track.completionRewards?.badgeKey && (
134
+ <p className="text-muted-foreground text-sm">
135
+ Complete all steps to earn the "
136
+ {track.completionRewards.badgeKey}" badge!
137
+ </p>
138
+ )}
139
+ </CardContent>
140
+ </Card>
141
141
 
142
- {/* Step-by-step breakdown */}
143
- <Card>
144
- <CardHeader>
145
- <CardTitle className="flex items-center gap-2">
146
- <span>📋</span>
147
- <span>Step Details</span>
148
- </CardTitle>
149
- </CardHeader>
150
- <CardContent>
151
- <div className="space-y-3">
152
- {track.steps.map((step, index) => {
153
- const isCompleted = progress.completedStepIds.includes(step.id);
154
- const stepProgress = isCompleted ? 100 : 0;
142
+ {/* Step-by-step breakdown */}
143
+ <Card>
144
+ <CardHeader>
145
+ <CardTitle className="flex items-center gap-2">
146
+ <span>📋</span>
147
+ <span>Step Details</span>
148
+ </CardTitle>
149
+ </CardHeader>
150
+ <CardContent>
151
+ <div className="space-y-3">
152
+ {track.steps.map((step, index) => {
153
+ const isCompleted = progress.completedStepIds.includes(step.id);
154
+ const stepProgress = isCompleted ? 100 : 0;
155
155
 
156
- return (
157
- <div key={step.id} className="space-y-1">
158
- <div className="flex items-center justify-between text-sm">
159
- <span
160
- className={
161
- isCompleted ? 'text-green-500' : 'text-foreground'
162
- }
163
- >
164
- {index + 1}. {step.title}
165
- </span>
166
- <span
167
- className={
168
- isCompleted ? 'text-green-500' : 'text-muted-foreground'
169
- }
170
- >
171
- {isCompleted ? '✓' : 'Pending'}
172
- </span>
173
- </div>
174
- <Progress value={stepProgress} className="h-1" />
175
- </div>
176
- );
177
- })}
178
- </div>
179
- </CardContent>
180
- </Card>
181
- </div>
182
- );
156
+ return (
157
+ <div key={step.id} className="space-y-1">
158
+ <div className="flex items-center justify-between text-sm">
159
+ <span
160
+ className={
161
+ isCompleted ? 'text-green-500' : 'text-foreground'
162
+ }
163
+ >
164
+ {index + 1}. {step.title}
165
+ </span>
166
+ <span
167
+ className={
168
+ isCompleted ? 'text-green-500' : 'text-muted-foreground'
169
+ }
170
+ >
171
+ {isCompleted ? '✓' : 'Pending'}
172
+ </span>
173
+ </div>
174
+ <Progress value={stepProgress} className="h-1" />
175
+ </div>
176
+ );
177
+ })}
178
+ </div>
179
+ </CardContent>
180
+ </Card>
181
+ </div>
182
+ );
183
183
  }
184
184
 
185
185
  // Re-export with correct name
@@ -1,92 +1,92 @@
1
1
  'use client';
2
2
 
3
- import { useState } from 'react';
3
+ import type { LearningViewProps } from '@contractspec/example.learning-journey-ui-shared';
4
4
  import { Progress } from '@contractspec/lib.ui-kit-web/ui/progress';
5
+ import { useState } from 'react';
5
6
  import { StepChecklist } from '../components/StepChecklist';
6
- import type { LearningViewProps } from '@contractspec/example.learning-journey-ui-shared';
7
7
 
8
8
  export function Steps({ track, progress, onStepComplete }: LearningViewProps) {
9
- const [expandedStepId, setExpandedStepId] = useState<string | null>(() => {
10
- // Auto-expand first incomplete step
11
- const firstIncomplete = track.steps.find(
12
- (s) => !progress.completedStepIds.includes(s.id)
13
- );
14
- return firstIncomplete?.id ?? null;
15
- });
9
+ const [expandedStepId, setExpandedStepId] = useState<string | null>(() => {
10
+ // Auto-expand first incomplete step
11
+ const firstIncomplete = track.steps.find(
12
+ (s) => !progress.completedStepIds.includes(s.id)
13
+ );
14
+ return firstIncomplete?.id ?? null;
15
+ });
16
16
 
17
- const completedSteps = progress.completedStepIds.length;
18
- const totalSteps = track.steps.length;
19
- const percentComplete =
20
- totalSteps > 0 ? (completedSteps / totalSteps) * 100 : 0;
17
+ const completedSteps = progress.completedStepIds.length;
18
+ const totalSteps = track.steps.length;
19
+ const percentComplete =
20
+ totalSteps > 0 ? (completedSteps / totalSteps) * 100 : 0;
21
21
 
22
- const currentStepIndex = track.steps.findIndex(
23
- (s) => !progress.completedStepIds.includes(s.id)
24
- );
22
+ const currentStepIndex = track.steps.findIndex(
23
+ (s) => !progress.completedStepIds.includes(s.id)
24
+ );
25
25
 
26
- return (
27
- <div className="space-y-6">
28
- {/* Progress Header */}
29
- <div className="space-y-2">
30
- <div className="flex items-center justify-between">
31
- <h2 className="text-xl font-bold">Complete Each Step</h2>
32
- <span className="text-muted-foreground text-sm">
33
- {completedSteps} / {totalSteps} completed
34
- </span>
35
- </div>
36
- <Progress value={percentComplete} className="h-2" />
37
- </div>
26
+ return (
27
+ <div className="space-y-6">
28
+ {/* Progress Header */}
29
+ <div className="space-y-2">
30
+ <div className="flex items-center justify-between">
31
+ <h2 className="font-bold text-xl">Complete Each Step</h2>
32
+ <span className="text-muted-foreground text-sm">
33
+ {completedSteps} / {totalSteps} completed
34
+ </span>
35
+ </div>
36
+ <Progress value={percentComplete} className="h-2" />
37
+ </div>
38
38
 
39
- {/* Steps List */}
40
- <div className="space-y-3">
41
- {track.steps.map((step, index) => {
42
- const isCompleted = progress.completedStepIds.includes(step.id);
43
- const isCurrent = index === currentStepIndex;
39
+ {/* Steps List */}
40
+ <div className="space-y-3">
41
+ {track.steps.map((step, index) => {
42
+ const isCompleted = progress.completedStepIds.includes(step.id);
43
+ const isCurrent = index === currentStepIndex;
44
44
 
45
- return (
46
- <StepChecklist
47
- key={step.id}
48
- step={step}
49
- stepNumber={index + 1}
50
- isCompleted={isCompleted}
51
- isCurrent={isCurrent}
52
- isExpanded={expandedStepId === step.id}
53
- onToggle={() =>
54
- setExpandedStepId(expandedStepId === step.id ? null : step.id)
55
- }
56
- onComplete={() => {
57
- onStepComplete?.(step.id);
58
- // Auto-expand next step
59
- const nextStep = track.steps[index + 1];
60
- if (
61
- nextStep &&
62
- !progress.completedStepIds.includes(nextStep.id)
63
- ) {
64
- setExpandedStepId(nextStep.id);
65
- }
66
- }}
67
- />
68
- );
69
- })}
70
- </div>
45
+ return (
46
+ <StepChecklist
47
+ key={step.id}
48
+ step={step}
49
+ stepNumber={index + 1}
50
+ isCompleted={isCompleted}
51
+ isCurrent={isCurrent}
52
+ isExpanded={expandedStepId === step.id}
53
+ onToggle={() =>
54
+ setExpandedStepId(expandedStepId === step.id ? null : step.id)
55
+ }
56
+ onComplete={() => {
57
+ onStepComplete?.(step.id);
58
+ // Auto-expand next step
59
+ const nextStep = track.steps[index + 1];
60
+ if (
61
+ nextStep &&
62
+ !progress.completedStepIds.includes(nextStep.id)
63
+ ) {
64
+ setExpandedStepId(nextStep.id);
65
+ }
66
+ }}
67
+ />
68
+ );
69
+ })}
70
+ </div>
71
71
 
72
- {/* Completion rewards hint */}
73
- {track.completionRewards && percentComplete < 100 && (
74
- <div className="rounded-lg border border-blue-500/30 bg-blue-500/5 p-4">
75
- <p className="text-sm">
76
- 🎁 Complete all steps to unlock:
77
- {track.completionRewards.xpBonus && (
78
- <span className="ml-2 font-semibold text-blue-500">
79
- +{track.completionRewards.xpBonus} XP bonus
80
- </span>
81
- )}
82
- {track.completionRewards.badgeKey && (
83
- <span className="ml-2 font-semibold text-amber-500">
84
- + "{track.completionRewards.badgeKey}" badge
85
- </span>
86
- )}
87
- </p>
88
- </div>
89
- )}
90
- </div>
91
- );
72
+ {/* Completion rewards hint */}
73
+ {track.completionRewards && percentComplete < 100 && (
74
+ <div className="rounded-lg border border-blue-500/30 bg-blue-500/5 p-4">
75
+ <p className="text-sm">
76
+ 🎁 Complete all steps to unlock:
77
+ {track.completionRewards.xpBonus && (
78
+ <span className="ml-2 font-semibold text-blue-500">
79
+ +{track.completionRewards.xpBonus} XP bonus
80
+ </span>
81
+ )}
82
+ {track.completionRewards.badgeKey && (
83
+ <span className="ml-2 font-semibold text-amber-500">
84
+ + "{track.completionRewards.badgeKey}" badge
85
+ </span>
86
+ )}
87
+ </p>
88
+ </div>
89
+ )}
90
+ </div>
91
+ );
92
92
  }